diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go index 1f0f43c79e..994ddb9fc7 100644 --- a/api/v1alpha5/zz_generated.conversion.go +++ b/api/v1alpha5/zz_generated.conversion.go @@ -731,6 +731,7 @@ func autoConvert_v1alpha7_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec( if err := Convert_v1alpha7_SubnetFilter_To_v1alpha5_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil { return err } + // WARNING: in.Subnets requires manual conversion: does not exist in peer-type // WARNING: in.NetworkMTU requires manual conversion: does not exist in peer-type out.DNSNameservers = *(*[]string)(unsafe.Pointer(&in.DNSNameservers)) if in.ExternalRouterIPs != nil { diff --git a/api/v1alpha6/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go index 09cd655cc1..d422626085 100644 --- a/api/v1alpha6/zz_generated.conversion.go +++ b/api/v1alpha6/zz_generated.conversion.go @@ -754,6 +754,7 @@ func autoConvert_v1alpha7_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec( if err := Convert_v1alpha7_SubnetFilter_To_v1alpha6_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil { return err } + // WARNING: in.Subnets requires manual conversion: does not exist in peer-type // WARNING: in.NetworkMTU requires manual conversion: does not exist in peer-type out.DNSNameservers = *(*[]string)(unsafe.Pointer(&in.DNSNameservers)) if in.ExternalRouterIPs != nil { diff --git a/api/v1alpha7/openstackcluster_types.go b/api/v1alpha7/openstackcluster_types.go index b4826685b0..7f865231aa 100644 --- a/api/v1alpha7/openstackcluster_types.go +++ b/api/v1alpha7/openstackcluster_types.go @@ -48,8 +48,13 @@ type OpenStackClusterSpec struct { Network NetworkFilter `json:"network,omitempty"` // If NodeCIDR cannot be set this can be used to detect an existing subnet. + // + // Deprecated: Use subnets instead. subnet will be silently ignored if subnets is set. Subnet SubnetFilter `json:"subnet,omitempty"` + // If NodeCIDR cannot be set this can be used to detect existing IPv4 and/or IPv6 subnets. + Subnets []SubnetFilter `json:"subnets,omitempty"` + // NetworkMTU sets the maximum transmission unit (MTU) value to address fragmentation for the private network ID. // This value will be used only if the Cluster actuator creates the network. // If leaved empty, the network will have the default MTU defined in Openstack network service. diff --git a/api/v1alpha7/zz_generated.deepcopy.go b/api/v1alpha7/zz_generated.deepcopy.go index 1d81a83410..05274cfe14 100644 --- a/api/v1alpha7/zz_generated.deepcopy.go +++ b/api/v1alpha7/zz_generated.deepcopy.go @@ -352,6 +352,11 @@ func (in *OpenStackClusterSpec) DeepCopyInto(out *OpenStackClusterSpec) { } out.Network = in.Network out.Subnet = in.Subnet + if in.Subnets != nil { + in, out := &in.Subnets, &out.Subnets + *out = make([]SubnetFilter, len(*in)) + copy(*out, *in) + } if in.DNSNameservers != nil { in, out := &in.DNSNameservers, &out.DNSNameservers *out = make([]string, len(*in)) 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 ac700b690a..b410f718cb 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml @@ -4328,8 +4328,9 @@ spec: type: string type: object subnet: - description: If NodeCIDR cannot be set this can be used to detect - an existing subnet. + description: "If NodeCIDR cannot be set this can be used to detect + an existing subnet. \n Deprecated: Use subnets instead. subnet will + be silently ignored if subnets is set." properties: cidr: type: string @@ -4358,6 +4359,39 @@ spec: tagsAny: type: string type: object + subnets: + description: If NodeCIDR cannot be set this can be used to detect + existing IPv4 and/or IPv6 subnets. + items: + properties: + cidr: + type: string + description: + type: string + gateway_ip: + type: string + id: + type: string + ipVersion: + type: integer + ipv6AddressMode: + type: string + ipv6RaMode: + type: string + name: + type: string + notTags: + type: string + notTagsAny: + type: string + projectId: + type: string + tags: + type: string + tagsAny: + type: string + type: object + type: array tags: description: Tags for all resources in cluster items: 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 281b48f8df..74d97c194c 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml @@ -2195,8 +2195,9 @@ spec: type: string type: object subnet: - description: If NodeCIDR cannot be set this can be used to - detect an existing subnet. + description: "If NodeCIDR cannot be set this can be used to + detect an existing subnet. \n Deprecated: Use subnets instead. + subnet will be silently ignored if subnets is set." properties: cidr: type: string @@ -2225,6 +2226,39 @@ spec: tagsAny: type: string type: object + subnets: + description: If NodeCIDR cannot be set this can be used to + detect existing IPv4 and/or IPv6 subnets. + items: + properties: + cidr: + type: string + description: + type: string + gateway_ip: + type: string + id: + type: string + ipVersion: + type: integer + ipv6AddressMode: + type: string + ipv6RaMode: + type: string + name: + type: string + notTags: + type: string + notTagsAny: + type: string + projectId: + type: string + tags: + type: string + tagsAny: + type: string + type: object + type: array tags: description: Tags for all resources in cluster items: diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go index e6d3025cba..8e4bed3a90 100644 --- a/controllers/openstackcluster_controller.go +++ b/controllers/openstackcluster_controller.go @@ -461,26 +461,26 @@ func reconcileNetworkComponents(scope scope.Scope, cluster *clusterv1.Cluster, o openStackCluster.Status.Network.Name = networkList[0].Name openStackCluster.Status.Network.Tags = networkList[0].Tags - subnet, err := networkingService.GetNetworkSubnetByFilter(openStackCluster.Status.Network.ID, &openStackCluster.Spec.Subnet) - if err != nil { - err = fmt.Errorf("failed to find subnet: %w", err) + var filteredSubnets []infrav1.Subnet + for _, subnet := range openStackCluster.Spec.Subnets { + filteredSubnet, err := networkingService.GetNetworkSubnetByFilter(openStackCluster.Status.Network.ID, &subnet) + if err != nil { + err = fmt.Errorf("failed to find subnet: %w", err) + // Set the cluster to failed if subnet filter is invalid + if errors.Is(err, networking.ErrFilterMatch) { + handleUpdateOSCError(openStackCluster, err) + } - // Set the cluster to failed if subnet filter is invalid - if errors.Is(err, networking.ErrFilterMatch) { - handleUpdateOSCError(openStackCluster, err) + return err } - - return err - } - - openStackCluster.Status.Network.Subnets = []infrav1.Subnet{ - { - ID: subnet.ID, - Name: subnet.Name, - CIDR: subnet.CIDR, - Tags: subnet.Tags, - }, + filteredSubnets = append(filteredSubnets, infrav1.Subnet{ + ID: filteredSubnet.ID, + Name: filteredSubnet.Name, + CIDR: filteredSubnet.CIDR, + Tags: filteredSubnet.Tags, + }) } + openStackCluster.Status.Network.Subnets = filteredSubnets } else { err := networkingService.ReconcileNetwork(openStackCluster, clusterName) if err != nil {