diff --git a/charts/internal/machineclass/templates/machineclass.yaml b/charts/internal/machineclass/templates/machineclass.yaml index c955dd478..fceb0fac9 100644 --- a/charts/internal/machineclass/templates/machineclass.yaml +++ b/charts/internal/machineclass/templates/machineclass.yaml @@ -56,7 +56,7 @@ providerSpec: {{- end }} networkID: {{ $machineClass.networkID }} subnetID: {{ $machineClass.subnetID }} - podNetworkCidr: {{ $machineClass.podNetworkCidr }} + podNetworkCIDRs: {{ $machineClass.podNetworkCIDRs }} {{- if $machineClass.rootDiskSize }} rootDiskSize: {{ $machineClass.rootDiskSize }} {{- end }} diff --git a/charts/internal/machineclass/values.yaml b/charts/internal/machineclass/values.yaml index 4112d71ca..7e8d892d9 100644 --- a/charts/internal/machineclass/values.yaml +++ b/charts/internal/machineclass/values.yaml @@ -18,7 +18,8 @@ machineClasses: imageName: coreos-v1.0 #imageID: 836428cd-5f98-1305-af9d-9825d4dfd0ec networkID: 426428cd-5e88-4005-9fad-9555d4dfd0fb - podNetworkCidr: 100.96.0.0/11 + # podNetworkCIDRs: + # - 100.96.0.0/11 # rootDiskSize: 100 # 100GB # rootDiskType: standard_hdd # serverGroupID: b35e94c1-15a7-4b54-a0f6-8789fasdf79s diff --git a/pkg/apis/openstack/validation/controlplane.go b/pkg/apis/openstack/validation/controlplane.go index 0912c3fd3..a1661e992 100644 --- a/pkg/apis/openstack/validation/controlplane.go +++ b/pkg/apis/openstack/validation/controlplane.go @@ -36,7 +36,7 @@ func ValidateControlPlaneConfig(controlPlaneConfig *api.ControlPlaneConfig, infr allErrs = append(allErrs, featurevalidation.ValidateFeatureGates(controlPlaneConfig.CloudControllerManager.FeatureGates, version, fldPath.Child("cloudControllerManager", "featureGates"))...) } - allErrs = append(allErrs, validateStorage(controlPlaneConfig.Storage, infraConfig.Networks.ShareNetwork, fldPath.Child("storage"))...) + allErrs = append(allErrs, validateStorage(controlPlaneConfig.Storage, infraConfig.Networks, fldPath.Child("storage"))...) return allErrs } @@ -139,13 +139,18 @@ func validateLoadBalancerClassesConstraints(floatingPools []api.FloatingPool, sh return allErrs } -func validateStorage(storage *api.Storage, shareNetwork *api.ShareNetwork, fldPath *field.Path) field.ErrorList { +func validateStorage(storage *api.Storage, networks api.Networks, fldPath *field.Path) field.ErrorList { var allErrs field.ErrorList if storage == nil || storage.CSIManila == nil || !storage.CSIManila.Enabled { return allErrs } - if shareNetwork == nil || !shareNetwork.Enabled { - allErrs = append(allErrs, field.Invalid(fldPath.Child("csiManila", "enabled"), storage.CSIManila.Enabled, "share network must be created if CSI manila driver is enabled")) + // for an existing subnet we do not need to validate the storage since we can only do that in runtime. + if networks.SubnetID != nil { + return allErrs } - return allErrs + if networks.ShareNetwork != nil && networks.ShareNetwork.Enabled { + return allErrs + + } + return append(allErrs, field.Invalid(fldPath.Child("csiManila", "enabled"), storage.CSIManila.Enabled, "share network must be created if CSI manila driver is enabled")) } diff --git a/pkg/controller/controlplane/valuesprovider.go b/pkg/controller/controlplane/valuesprovider.go index b8b1caa81..c620f5976 100644 --- a/pkg/controller/controlplane/valuesprovider.go +++ b/pkg/controller/controlplane/valuesprovider.go @@ -953,10 +953,6 @@ func (vp *valuesProvider) addCSIManilaValues( "clusterID": cp.Namespace, } - infraConfig, err := helper.InfrastructureConfigFromRawExtension(cluster.Shoot.Spec.Provider.InfrastructureConfig) - if err != nil { - return fmt.Errorf("could not decode infrastructure config of controlplane '%s': %w", k8sclient.ObjectKeyFromObject(cp), err) - } infraStatus, err := vp.getInfrastructureStatus(cp) if err != nil { return err diff --git a/pkg/controller/infrastructure/infraflow/delete.go b/pkg/controller/infrastructure/infraflow/delete.go index 42fed96fa..b70a7e458 100644 --- a/pkg/controller/infrastructure/infraflow/delete.go +++ b/pkg/controller/infrastructure/infraflow/delete.go @@ -79,7 +79,9 @@ func (fctx *FlowContext) buildDeleteGraph() *flow.Graph { _ = fctx.AddTask(g, "delete share network", fctx.deleteShareNetwork, - shared.Timeout(defaultTimeout), shared.Dependencies(recoverSubnetID)) + shared.Timeout(defaultTimeout), shared.Dependencies(recoverSubnetID), + shared.DoIf(needToDeleteSubnet), + ) deleteRouterInterface := fctx.AddTask(g, "delete router interface", fctx.deleteRouterInterface, shared.DoIf(needToDeleteSubnet || needToDeleteRouter), diff --git a/pkg/controller/infrastructure/infraflow/reconcile.go b/pkg/controller/infrastructure/infraflow/reconcile.go index 375d0484a..6f8cb3ce9 100644 --- a/pkg/controller/infrastructure/infraflow/reconcile.go +++ b/pkg/controller/infrastructure/infraflow/reconcile.go @@ -476,6 +476,9 @@ func (fctx *FlowContext) ensureSSHKeyPair(ctx context.Context) error { } func (fctx *FlowContext) ensureShareNetwork(ctx context.Context) error { + if fctx.config.Networks.SubnetID != nil { + return fctx.ensureShareNetworkForExistingSubnet(ctx) + } if fctx.config.Networks.ShareNetwork == nil || !fctx.config.Networks.ShareNetwork.Enabled { return fctx.deleteShareNetwork(ctx) } @@ -521,3 +524,34 @@ func (fctx *FlowContext) ensureShareNetwork(ctx context.Context) error { fctx.state.Set(NameShareNetwork, created.Name) return nil } + +// ensureShareNetworkForExistingSubnet ensures the shared network for an existing subnet. Because the subnet may be shared among many different shoots, +// it could be that there is already a sharednetwork associated with a subnet. This function is responsible for detecting the shared network associated with the subnet. +func (fctx *FlowContext) ensureShareNetworkForExistingSubnet(ctx context.Context) error { + networkID := ptr.Deref(fctx.state.Get(IdentifierNetwork), "") + subnetID := ptr.Deref(fctx.state.Get(IdentifierSubnet), "") + current, err := findExisting(fctx.state.Get(IdentifierShareNetwork), + "", + fctx.sharedFilesystem.GetShareNetwork, + func(_ string) ([]*sharenetworks.ShareNetwork, error) { + list, err := fctx.sharedFilesystem.ListShareNetworks(sharenetworks.ListOpts{ + NeutronNetID: networkID, + NeutronSubnetID: subnetID, + }) + if err != nil { + return nil, err + } + return sliceToPtr(list), nil + }) + + if err != nil { + return err + } + + if current != nil { + fctx.state.Set(IdentifierShareNetwork, current.ID) + fctx.state.Set(NameShareNetwork, current.Name) + } + + return nil +} diff --git a/pkg/controller/infrastructure/infraflow/utils.go b/pkg/controller/infrastructure/infraflow/utils.go index 5757d8f16..17ab192ae 100644 --- a/pkg/controller/infrastructure/infraflow/utils.go +++ b/pkg/controller/infrastructure/infraflow/utils.go @@ -83,12 +83,3 @@ func (fctx *FlowContext) defaultSecurityGroupName() string { func (fctx *FlowContext) defaultSharedNetworkName() string { return fctx.infra.Namespace } - -func (fctx *FlowContext) workerCIDR() string { - s := fctx.config.Networks.Worker - if workers := fctx.config.Networks.Workers; workers != "" { - s = workers - } - - return s -} diff --git a/pkg/controller/worker/machines.go b/pkg/controller/worker/machines.go index d24979100..4c36faea4 100644 --- a/pkg/controller/worker/machines.go +++ b/pkg/controller/worker/machines.go @@ -149,7 +149,7 @@ func (w *workerDelegate) generateMachineConfig(ctx context.Context) error { "machineType": pool.MachineType, "keyName": infrastructureStatus.Node.KeyName, "networkID": infrastructureStatus.Networks.ID, - "podNetworkCidr": extensionscontroller.GetPodNetwork(w.cluster), + "podNetworkCIDRs": extensionscontroller.GetPodNetwork(w.cluster), "securityGroups": []string{nodesSecurityGroup.Name}, "tags": utils.MergeStringMaps( NormalizeLabelsForMachineClass(pool.Labels), diff --git a/pkg/internal/infrastructure/infrastucture_test.go b/pkg/internal/infrastructure/infrastucture_test.go index 7a5d83944..71e915af4 100644 --- a/pkg/internal/infrastructure/infrastucture_test.go +++ b/pkg/internal/infrastructure/infrastucture_test.go @@ -7,6 +7,7 @@ import ( "github.com/go-logr/logr" "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/loadbalancers" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers" + "github.com/gophercloud/gophercloud/openstack/networking/v2/subnets" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "go.uber.org/mock/gomock" @@ -21,8 +22,10 @@ var _ = Describe("Infrastructure", func() { nw *mocks.MockNetworking ctx context.Context routerID string + subnetID string defaultWorker = "10.0.0.0/16" router *routers.Router + subnet *subnets.Subnet clusterName = "foo-bar" ) @@ -35,9 +38,14 @@ var _ = Describe("Infrastructure", func() { Context("Route deletion", func() { BeforeEach(func() { routerID = "router" + subnetID = "subnet" router = &routers.Router{ ID: routerID, } + subnet = &subnets.Subnet{ + ID: subnetID, + CIDR: defaultWorker, + } }) type args struct { @@ -48,11 +56,12 @@ var _ = Describe("Infrastructure", func() { prepRoutes := func(routes ...routers.Route) { router.Routes = routes nw.EXPECT().GetRouterByID(routerID).Return(router, nil) + nw.EXPECT().GetSubnetByID(subnetID).Return(subnet, nil) } DescribeTable("#RouteCleanup", func(a args, expErr error) { a.prep() - err := CleanupKubernetesRoutes(ctx, nw, routerID, a.workers) + err := CleanupKubernetesRoutes(ctx, nw, routerID, subnetID) if expErr == nil { Expect(err).To(BeNil()) } else {