diff --git a/api/v1alpha5/conversion.go b/api/v1alpha5/conversion.go index 3f41962b92..9318a93d5c 100644 --- a/api/v1alpha5/conversion.go +++ b/api/v1alpha5/conversion.go @@ -437,3 +437,21 @@ func Convert_v1alpha5_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus( func Convert_v1alpha7_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(in *infrav1.OpenStackMachineSpec, out *OpenStackMachineSpec, s conversion.Scope) error { return autoConvert_v1alpha7_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(in, out, s) } + +func Convert_v1alpha7_RootVolume_To_v1alpha5_RootVolume(in *infrav1.RootVolume, out *RootVolume, s conversion.Scope) error { + // UseMachineAZ = false cannot be represented in v1alpha5 + return autoConvert_v1alpha7_RootVolume_To_v1alpha5_RootVolume(in, out, s) +} + +func Convert_v1alpha5_RootVolume_To_v1alpha7_RootVolume(in *RootVolume, out *infrav1.RootVolume, s conversion.Scope) error { + if err := autoConvert_v1alpha5_RootVolume_To_v1alpha7_RootVolume(in, out, s); err != nil { + return err + } + + // UseMachineAZ was the default behaviour in v1alpha5 when AvailabilityZone was not specified, but in v1alpha7 the default is to use no AZ. + if in.AvailabilityZone == "" { + out.UseMachineAZ = true + } + + return nil +} diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go index 52681a9c65..255c0ddb76 100644 --- a/api/v1alpha5/zz_generated.conversion.go +++ b/api/v1alpha5/zz_generated.conversion.go @@ -244,16 +244,6 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*RootVolume)(nil), (*v1alpha7.RootVolume)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha5_RootVolume_To_v1alpha7_RootVolume(a.(*RootVolume), b.(*v1alpha7.RootVolume), scope) - }); err != nil { - return err - } - if err := s.AddGeneratedConversionFunc((*v1alpha7.RootVolume)(nil), (*RootVolume)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_RootVolume_To_v1alpha5_RootVolume(a.(*v1alpha7.RootVolume), b.(*RootVolume), scope) - }); err != nil { - return err - } if err := s.AddGeneratedConversionFunc((*Router)(nil), (*v1alpha7.Router)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1alpha5_Router_To_v1alpha7_Router(a.(*Router), b.(*v1alpha7.Router), scope) }); err != nil { @@ -339,6 +329,11 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*RootVolume)(nil), (*v1alpha7.RootVolume)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha5_RootVolume_To_v1alpha7_RootVolume(a.(*RootVolume), b.(*v1alpha7.RootVolume), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*SecurityGroupFilter)(nil), (*v1alpha7.SecurityGroupFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1alpha5_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(a.(*SecurityGroupFilter), b.(*v1alpha7.SecurityGroupFilter), scope) }); err != nil { @@ -399,6 +394,11 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*v1alpha7.RootVolume)(nil), (*RootVolume)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_RootVolume_To_v1alpha5_RootVolume(a.(*v1alpha7.RootVolume), b.(*RootVolume), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*v1alpha7.SecurityGroupFilter)(nil), (*SecurityGroupParam)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1alpha7_SecurityGroupFilter_To_v1alpha5_SecurityGroupParam(a.(*v1alpha7.SecurityGroupFilter), b.(*SecurityGroupParam), scope) }); err != nil { @@ -1093,7 +1093,15 @@ func autoConvert_v1alpha5_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec( out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags)) out.ServerMetadata = *(*map[string]string)(unsafe.Pointer(&in.ServerMetadata)) out.ConfigDrive = (*bool)(unsafe.Pointer(in.ConfigDrive)) - out.RootVolume = (*v1alpha7.RootVolume)(unsafe.Pointer(in.RootVolume)) + if in.RootVolume != nil { + in, out := &in.RootVolume, &out.RootVolume + *out = new(v1alpha7.RootVolume) + if err := Convert_v1alpha5_RootVolume_To_v1alpha7_RootVolume(*in, *out, s); err != nil { + return err + } + } else { + out.RootVolume = nil + } out.ServerGroupID = in.ServerGroupID out.IdentityRef = (*v1alpha7.OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef)) return nil @@ -1134,7 +1142,15 @@ func autoConvert_v1alpha7_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec( out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags)) out.ServerMetadata = *(*map[string]string)(unsafe.Pointer(&in.ServerMetadata)) out.ConfigDrive = (*bool)(unsafe.Pointer(in.ConfigDrive)) - out.RootVolume = (*RootVolume)(unsafe.Pointer(in.RootVolume)) + if in.RootVolume != nil { + in, out := &in.RootVolume, &out.RootVolume + *out = new(RootVolume) + if err := Convert_v1alpha7_RootVolume_To_v1alpha5_RootVolume(*in, *out, s); err != nil { + return err + } + } else { + out.RootVolume = nil + } // WARNING: in.AdditionalBlockDevices requires manual conversion: does not exist in peer-type out.ServerGroupID = in.ServerGroupID out.IdentityRef = (*OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef)) @@ -1355,23 +1371,14 @@ func autoConvert_v1alpha5_RootVolume_To_v1alpha7_RootVolume(in *RootVolume, out return nil } -// Convert_v1alpha5_RootVolume_To_v1alpha7_RootVolume is an autogenerated conversion function. -func Convert_v1alpha5_RootVolume_To_v1alpha7_RootVolume(in *RootVolume, out *v1alpha7.RootVolume, s conversion.Scope) error { - return autoConvert_v1alpha5_RootVolume_To_v1alpha7_RootVolume(in, out, s) -} - func autoConvert_v1alpha7_RootVolume_To_v1alpha5_RootVolume(in *v1alpha7.RootVolume, out *RootVolume, s conversion.Scope) error { out.Size = in.Size out.VolumeType = in.VolumeType out.AvailabilityZone = in.AvailabilityZone + // WARNING: in.UseMachineAZ requires manual conversion: does not exist in peer-type return nil } -// Convert_v1alpha7_RootVolume_To_v1alpha5_RootVolume is an autogenerated conversion function. -func Convert_v1alpha7_RootVolume_To_v1alpha5_RootVolume(in *v1alpha7.RootVolume, out *RootVolume, s conversion.Scope) error { - return autoConvert_v1alpha7_RootVolume_To_v1alpha5_RootVolume(in, out, s) -} - func autoConvert_v1alpha5_Router_To_v1alpha7_Router(in *Router, out *v1alpha7.Router, s conversion.Scope) error { out.Name = in.Name out.ID = in.ID diff --git a/api/v1alpha6/conversion.go b/api/v1alpha6/conversion.go index ae8e343ea8..7df099d28f 100644 --- a/api/v1alpha6/conversion.go +++ b/api/v1alpha6/conversion.go @@ -61,6 +61,11 @@ func restorev1alpha7MachineSpec(previous *infrav1.OpenStackMachineSpec, dst *inf // We restore the whole Ports since they are anyway immutable. dst.Ports = previous.Ports dst.AdditionalBlockDevices = previous.AdditionalBlockDevices + + if previous.RootVolume != nil && dst.RootVolume != nil { + // UseMachineAZ = false cannot be represented in v1alpha6 + dst.RootVolume.UseMachineAZ = previous.RootVolume.UseMachineAZ + } } func restorev1alpha7Bastion(previous **infrav1.Bastion, dst **infrav1.Bastion) { @@ -659,3 +664,21 @@ func Convert_v1alpha6_OpenStackClusterStatus_To_v1alpha7_OpenStackClusterStatus( func Convert_v1alpha7_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(in *infrav1.OpenStackMachineSpec, out *OpenStackMachineSpec, s apiconversion.Scope) error { return autoConvert_v1alpha7_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(in, out, s) } + +func Convert_v1alpha7_RootVolume_To_v1alpha6_RootVolume(in *infrav1.RootVolume, out *RootVolume, s apiconversion.Scope) error { + // UseMachineAZ = false cannot be represented in v1alpha6 + return autoConvert_v1alpha7_RootVolume_To_v1alpha6_RootVolume(in, out, s) +} + +func Convert_v1alpha6_RootVolume_To_v1alpha7_RootVolume(in *RootVolume, out *infrav1.RootVolume, s apiconversion.Scope) error { + if err := autoConvert_v1alpha6_RootVolume_To_v1alpha7_RootVolume(in, out, s); err != nil { + return err + } + + // UseMachineAZ was the default behaviour in v1alpha6 when AvailabilityZone was not specified, but in v1alpha7 the default is to use no AZ. + if in.AvailabilityZone == "" { + out.UseMachineAZ = true + } + + return nil +} diff --git a/api/v1alpha6/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go index 6bfa0129c3..dc200b91c1 100644 --- a/api/v1alpha6/zz_generated.conversion.go +++ b/api/v1alpha6/zz_generated.conversion.go @@ -254,16 +254,6 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*RootVolume)(nil), (*v1alpha7.RootVolume)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha6_RootVolume_To_v1alpha7_RootVolume(a.(*RootVolume), b.(*v1alpha7.RootVolume), scope) - }); err != nil { - return err - } - if err := s.AddGeneratedConversionFunc((*v1alpha7.RootVolume)(nil), (*RootVolume)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_RootVolume_To_v1alpha6_RootVolume(a.(*v1alpha7.RootVolume), b.(*RootVolume), scope) - }); err != nil { - return err - } if err := s.AddGeneratedConversionFunc((*Router)(nil), (*v1alpha7.Router)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1alpha6_Router_To_v1alpha7_Router(a.(*Router), b.(*v1alpha7.Router), scope) }); err != nil { @@ -359,6 +349,11 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*RootVolume)(nil), (*v1alpha7.RootVolume)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha6_RootVolume_To_v1alpha7_RootVolume(a.(*RootVolume), b.(*v1alpha7.RootVolume), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*SecurityGroupFilter)(nil), (*v1alpha7.SecurityGroupFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1alpha6_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(a.(*SecurityGroupFilter), b.(*v1alpha7.SecurityGroupFilter), scope) }); err != nil { @@ -409,6 +404,11 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*v1alpha7.RootVolume)(nil), (*RootVolume)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_RootVolume_To_v1alpha6_RootVolume(a.(*v1alpha7.RootVolume), b.(*RootVolume), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*v1alpha7.SecurityGroupFilter)(nil), (*SecurityGroupParam)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1alpha7_SecurityGroupFilter_To_v1alpha6_SecurityGroupParam(a.(*v1alpha7.SecurityGroupFilter), b.(*SecurityGroupParam), scope) }); err != nil { @@ -1116,7 +1116,15 @@ func autoConvert_v1alpha6_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec( out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags)) out.ServerMetadata = *(*map[string]string)(unsafe.Pointer(&in.ServerMetadata)) out.ConfigDrive = (*bool)(unsafe.Pointer(in.ConfigDrive)) - out.RootVolume = (*v1alpha7.RootVolume)(unsafe.Pointer(in.RootVolume)) + if in.RootVolume != nil { + in, out := &in.RootVolume, &out.RootVolume + *out = new(v1alpha7.RootVolume) + if err := Convert_v1alpha6_RootVolume_To_v1alpha7_RootVolume(*in, *out, s); err != nil { + return err + } + } else { + out.RootVolume = nil + } out.ServerGroupID = in.ServerGroupID out.IdentityRef = (*v1alpha7.OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef)) return nil @@ -1157,7 +1165,15 @@ func autoConvert_v1alpha7_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec( out.Tags = *(*[]string)(unsafe.Pointer(&in.Tags)) out.ServerMetadata = *(*map[string]string)(unsafe.Pointer(&in.ServerMetadata)) out.ConfigDrive = (*bool)(unsafe.Pointer(in.ConfigDrive)) - out.RootVolume = (*RootVolume)(unsafe.Pointer(in.RootVolume)) + if in.RootVolume != nil { + in, out := &in.RootVolume, &out.RootVolume + *out = new(RootVolume) + if err := Convert_v1alpha7_RootVolume_To_v1alpha6_RootVolume(*in, *out, s); err != nil { + return err + } + } else { + out.RootVolume = nil + } // WARNING: in.AdditionalBlockDevices requires manual conversion: does not exist in peer-type out.ServerGroupID = in.ServerGroupID out.IdentityRef = (*OpenStackIdentityReference)(unsafe.Pointer(in.IdentityRef)) @@ -1379,23 +1395,14 @@ func autoConvert_v1alpha6_RootVolume_To_v1alpha7_RootVolume(in *RootVolume, out return nil } -// Convert_v1alpha6_RootVolume_To_v1alpha7_RootVolume is an autogenerated conversion function. -func Convert_v1alpha6_RootVolume_To_v1alpha7_RootVolume(in *RootVolume, out *v1alpha7.RootVolume, s conversion.Scope) error { - return autoConvert_v1alpha6_RootVolume_To_v1alpha7_RootVolume(in, out, s) -} - func autoConvert_v1alpha7_RootVolume_To_v1alpha6_RootVolume(in *v1alpha7.RootVolume, out *RootVolume, s conversion.Scope) error { out.Size = in.Size out.VolumeType = in.VolumeType out.AvailabilityZone = in.AvailabilityZone + // WARNING: in.UseMachineAZ requires manual conversion: does not exist in peer-type return nil } -// Convert_v1alpha7_RootVolume_To_v1alpha6_RootVolume is an autogenerated conversion function. -func Convert_v1alpha7_RootVolume_To_v1alpha6_RootVolume(in *v1alpha7.RootVolume, out *RootVolume, s conversion.Scope) error { - return autoConvert_v1alpha7_RootVolume_To_v1alpha6_RootVolume(in, out, s) -} - func autoConvert_v1alpha6_Router_To_v1alpha7_Router(in *Router, out *v1alpha7.Router, s conversion.Scope) error { out.Name = in.Name out.ID = in.ID diff --git a/api/v1alpha7/types.go b/api/v1alpha7/types.go index 3ef5305ff2..04930698a1 100644 --- a/api/v1alpha7/types.go +++ b/api/v1alpha7/types.go @@ -158,9 +158,22 @@ type BastionStatus struct { } type RootVolume struct { - Size int `json:"diskSize,omitempty"` - VolumeType string `json:"volumeType,omitempty"` + // Size specifies the root volume size in GB. + // +required + Size int `json:"diskSize,omitempty"` + + // VolumeType specifies the Cinder Volume Type to use for the root volume + VolumeType string `json:"volumeType,omitempty"` + + // AvailabilityZone specifies the Cinder Availability Zone to use for the root volume. + // Leave empty to allow Cinder to schedule the volume without an availability zone. AvailabilityZone string `json:"availabilityZone,omitempty"` + + // UseMachineAZ specifies that the root volume should be created in a cinder + // availability zone with the same name as the nova availability zone of the server, + // if any. + // It is an error to specify both AvailabilityZone and UseMachineAZ. + UseMachineAZ bool `json:"useMachineAZ,omitempty"` } // BlockDeviceStorage is the storage type of a block device to create and @@ -195,6 +208,13 @@ type BlockDeviceVolume struct { // further information. // +optional AvailabilityZone string `json:"availabilityZone,omitempty"` + + // UseMachineAZ specifies that the root volume should be created in a cinder + // availability zone with the same name as the nova availability zone of the server, + // if any. + // It is an error to specify both AvailabilityZone and UseMachineAZ. + // +optional + UseMachineAZ bool `json:"useMachineAZ,omitempty"` } // AdditionalBlockDevice is a block device to attach to the server. diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml index a5114ac6a2..f22d041b86 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml @@ -3818,6 +3818,14 @@ spec: volume type that is configured in the OpenStack cloud will be used. type: string + useMachineAZ: + description: UseMachineAZ specifies that the + root volume should be created in a cinder + availability zone with the same name as the + nova availability zone of the server, if any. + It is an error to specify both AvailabilityZone + and UseMachineAZ. + type: boolean type: object required: - type @@ -4084,10 +4092,24 @@ spec: description: The volume metadata to boot from properties: availabilityZone: + description: AvailabilityZone specifies the Cinder Availability + Zone to use for the root volume. Leave empty to allow + Cinder to schedule the volume without an availability + zone. type: string diskSize: + description: Size specifies the root volume size in GB. type: integer + useMachineAZ: + description: UseMachineAZ specifies that the root volume + should be created in a cinder availability zone with + the same name as the nova availability zone of the server, + if any. It is an error to specify both AvailabilityZone + and UseMachineAZ. + type: boolean volumeType: + description: VolumeType specifies the Cinder Volume Type + to use for the root volume type: string type: object securityGroups: diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml index 815a3a83fc..58d6a0808a 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml @@ -1664,6 +1664,15 @@ spec: configured in the OpenStack cloud will be used. type: string + useMachineAZ: + description: UseMachineAZ specifies + that the root volume should be created + in a cinder availability zone with + the same name as the nova availability + zone of the server, if any. It is + an error to specify both AvailabilityZone + and UseMachineAZ. + type: boolean type: object required: - type @@ -1940,10 +1949,25 @@ spec: description: The volume metadata to boot from properties: availabilityZone: + description: AvailabilityZone specifies the Cinder + Availability Zone to use for the root volume. + Leave empty to allow Cinder to schedule the + volume without an availability zone. type: string diskSize: + description: Size specifies the root volume size + in GB. type: integer + useMachineAZ: + description: UseMachineAZ specifies that the root + volume should be created in a cinder availability + zone with the same name as the nova availability + zone of the server, if any. It is an error to + specify both AvailabilityZone and UseMachineAZ. + type: boolean volumeType: + description: VolumeType specifies the Cinder Volume + Type to use for the root volume type: string type: object securityGroups: diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml index e5171cd868..b1d771596e 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml @@ -1204,6 +1204,13 @@ spec: If omitted, the default Cinder volume type that is configured in the OpenStack cloud will be used. type: string + useMachineAZ: + description: UseMachineAZ specifies that the root volume + should be created in a cinder availability zone with + the same name as the nova availability zone of the + server, if any. It is an error to specify both AvailabilityZone + and UseMachineAZ. + type: boolean type: object required: - type @@ -1460,10 +1467,22 @@ spec: description: The volume metadata to boot from properties: availabilityZone: + description: AvailabilityZone specifies the Cinder Availability + Zone to use for the root volume. Leave empty to allow Cinder + to schedule the volume without an availability zone. type: string diskSize: + description: Size specifies the root volume size in GB. type: integer + useMachineAZ: + description: UseMachineAZ specifies that the root volume should + be created in a cinder availability zone with the same name + as the nova availability zone of the server, if any. It is an + error to specify both AvailabilityZone and UseMachineAZ. + type: boolean volumeType: + description: VolumeType specifies the Cinder Volume Type to use + for the root volume type: string type: object securityGroups: diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml index bc88d84fa2..023a9f8142 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml @@ -1006,6 +1006,14 @@ spec: volume type that is configured in the OpenStack cloud will be used. type: string + useMachineAZ: + description: UseMachineAZ specifies that the + root volume should be created in a cinder + availability zone with the same name as the + nova availability zone of the server, if any. + It is an error to specify both AvailabilityZone + and UseMachineAZ. + type: boolean type: object required: - type @@ -1272,10 +1280,24 @@ spec: description: The volume metadata to boot from properties: availabilityZone: + description: AvailabilityZone specifies the Cinder Availability + Zone to use for the root volume. Leave empty to allow + Cinder to schedule the volume without an availability + zone. type: string diskSize: + description: Size specifies the root volume size in GB. type: integer + useMachineAZ: + description: UseMachineAZ specifies that the root volume + should be created in a cinder availability zone with + the same name as the nova availability zone of the server, + if any. It is an error to specify both AvailabilityZone + and UseMachineAZ. + type: boolean volumeType: + description: VolumeType specifies the Cinder Volume Type + to use for the root volume type: string type: object securityGroups: diff --git a/docs/book/src/clusteropenstack/configuration.md b/docs/book/src/clusteropenstack/configuration.md index 332f9833ff..3748b69180 100644 --- a/docs/book/src/clusteropenstack/configuration.md +++ b/docs/book/src/clusteropenstack/configuration.md @@ -564,12 +564,17 @@ For example in `OpenStackMachineTemplate` set `spec.rootVolume.diskSize` to some diskSize: volumeType: availabilityZone: + useMachineAZ: ... ``` If `volumeType` is not specified, cinder will use the default volume type. -If `availabilityZone` is not specified, the volume will be created in the cinder availability zone specified in the MachineSpec's `failureDomain`. This same value is also used as the nova availability zone when creating the server. Note that this will fail if cinder and nova do not have matching availability zones. In this case, cinder `availabilityZone` **must** be specified explicitly on `rootVolume`. +If `availabilityZone` is not specified, cinder will schedule the volume to any host. +You can set `useMachineAZ=true` to instead default the volume availability zone to the value of the MachineSpec's `failureDomain`. +This value is also used as the nova availability zone when creating the server. +Note that this will fail if cinder and nova do not have matching availability zones. +The `availabilityZone` and `useMachineAZ` parameters are mutually exclusive. ## Timeout settings diff --git a/docs/book/src/topics/crd-changes/v1alpha6-to-v1alpha7.md b/docs/book/src/topics/crd-changes/v1alpha6-to-v1alpha7.md index 25937afa52..7d9e11a890 100644 --- a/docs/book/src/topics/crd-changes/v1alpha6-to-v1alpha7.md +++ b/docs/book/src/topics/crd-changes/v1alpha6-to-v1alpha7.md @@ -214,7 +214,9 @@ profile: TrustedVF: true ``` -#### Creation of additionalBlockDevices +#### Changes to volumes + +##### Creation of additionalBlockDevices We now have the ability for a machine to have additional block devices to be attached. @@ -256,6 +258,20 @@ additionalBlockDevices Adding more than one ephemeral disk to an instance is possible but you should use it at your own risks, it has been known to cause some issues in some environments. +##### Changes to volume availability zone defaults + +We previously defaulted to using the AZ of the underlying server instance in the absence of a specified volume AZ. +This behaviour has now changed and the volume AZ will remain unset if a volume AZ is not specified. +You can opt-in to the previous behavior by setting `useMachineAZ` for any volumes that you wish to default to the server instance's AZ for. + +Here is an example of a root volume configured to use the server instance's AZ: + +```yaml +rootVolume: + diskSize: 10 + useMachineAZ: true +``` + ### `OpenStackCluster` #### Change to externalRouterIPs.subnet diff --git a/pkg/cloud/services/compute/instance.go b/pkg/cloud/services/compute/instance.go index 3ee0bae2dd..51555a46e5 100644 --- a/pkg/cloud/services/compute/instance.go +++ b/pkg/cloud/services/compute/instance.go @@ -439,12 +439,15 @@ func (s *Service) waitForVolume(volumeID string, timeout time.Duration, retryInt // It returns an error if the volume creation failed or if the expected volume is different from the one that already exists. func (s *Service) getOrCreateVolumeBuilder(eventObject runtime.Object, instanceSpec *InstanceSpec, blockDevice infrav1.AdditionalBlockDevice, imageID string, description string) (*volumes.Volume, error) { var volumeType string - availabilityZone := instanceSpec.FailureDomain + var availabilityZone string if blockDevice.Storage.Volume != nil { if blockDevice.Storage.Volume.AvailabilityZone != "" { availabilityZone = blockDevice.Storage.Volume.AvailabilityZone + } else if blockDevice.Storage.Volume.UseMachineAZ { + availabilityZone = instanceSpec.FailureDomain } + volumeType = blockDevice.Storage.Volume.Type } @@ -475,6 +478,7 @@ func (s *Service) getBlockDevices(eventObject runtime.Object, instanceSpec *Inst Volume: &infrav1.BlockDeviceVolume{ AvailabilityZone: instanceSpec.RootVolume.AvailabilityZone, Type: instanceSpec.RootVolume.VolumeType, + UseMachineAZ: instanceSpec.RootVolume.UseMachineAZ, }, }, }