|
| 1 | +package vsphere |
| 2 | + |
| 3 | +import ( |
| 4 | + "context" |
| 5 | + _ "embed" |
| 6 | + "fmt" |
| 7 | + "slices" |
| 8 | + "strings" |
| 9 | + |
| 10 | + . "github.com/onsi/ginkgo/v2" |
| 11 | + . "github.com/onsi/gomega" |
| 12 | + configv1 "github.com/openshift/api/config/v1" |
| 13 | + machinev1beta1 "github.com/openshift/api/machine/v1beta1" |
| 14 | + configclient "github.com/openshift/client-go/config/clientset/versioned/typed/config/v1" |
| 15 | + machinesetclient "github.com/openshift/client-go/machine/clientset/versioned/typed/machine/v1beta1" |
| 16 | + "github.com/openshift/machine-api-operator/pkg/controller/vsphere" |
| 17 | + e2eutil "github.com/openshift/machine-api-operator/test/e2e" |
| 18 | + corev1 "k8s.io/api/core/v1" |
| 19 | + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" |
| 20 | + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" |
| 21 | + "k8s.io/client-go/kubernetes" |
| 22 | + "k8s.io/client-go/rest" |
| 23 | + e2e "k8s.io/kubernetes/test/e2e/framework" |
| 24 | +) |
| 25 | + |
| 26 | +func failIfNodeNotInMachineNetwork(nodes corev1.NodeList, machineNetworks []string) { |
| 27 | + |
| 28 | + By("checking if nodes are in the machine network") |
| 29 | + |
| 30 | + for _, node := range nodes.Items { |
| 31 | + for _, address := range node.Status.Addresses { |
| 32 | + if address.Type != "InternalIP" && address.Type != "ExternalIP" { |
| 33 | + continue |
| 34 | + } |
| 35 | + inRange, err := isIpInCidrRange(address.Address, machineNetworks[0]) |
| 36 | + Expect(err).NotTo(HaveOccurred()) |
| 37 | + Expect(inRange).To(BeTrue()) |
| 38 | + } |
| 39 | + } |
| 40 | +} |
| 41 | + |
| 42 | +func failIfIncorrectPortgroupsAttachedToVMs( |
| 43 | + ctx context.Context, |
| 44 | + infra configv1.PlatformSpec, |
| 45 | + nodeList *corev1.NodeList, |
| 46 | + vsphereCreds *corev1.Secret) { |
| 47 | + |
| 48 | + By("checking if VMs have the correct portgroups attached") |
| 49 | + |
| 50 | + for _, failureDomain := range infra.VSphere.FailureDomains { |
| 51 | + nodes, err := getNodesInFailureDomain(infra.VSphere, failureDomain, nodeList) |
| 52 | + fmt.Printf("nodes: %d", len(nodes)) |
| 53 | + Expect(err).NotTo(HaveOccurred()) |
| 54 | + |
| 55 | + vmPortgroupMap, err := GetPortGroupsAttachedToVMsInFailureDomain(ctx, failureDomain, vsphereCreds, infra.VSphere.VCenters) |
| 56 | + if err != nil { |
| 57 | + Expect(err).NotTo(HaveOccurred()) |
| 58 | + } |
| 59 | + |
| 60 | + var nodeProviderIds []string |
| 61 | + for _, node := range nodes { |
| 62 | + providerId := node.Spec.ProviderID |
| 63 | + Expect(len(providerId)).ShouldNot(BeZero()) |
| 64 | + |
| 65 | + parts := strings.Split(providerId, "vsphere://") |
| 66 | + Expect(len(parts)).Should(BeIdenticalTo(2)) |
| 67 | + |
| 68 | + nodeProviderIds = append(nodeProviderIds, parts[1]) |
| 69 | + } |
| 70 | + |
| 71 | + for _, nodeProviderId := range nodeProviderIds { |
| 72 | + attachedPortgroups, exists := vmPortgroupMap[nodeProviderId] |
| 73 | + Expect(exists).To(BeTrue()) |
| 74 | + |
| 75 | + slices.Sort(attachedPortgroups) |
| 76 | + slices.Sort(failureDomain.Topology.Networks) |
| 77 | + if slices.Compare(attachedPortgroups, failureDomain.Topology.Networks) != 0 { |
| 78 | + Expect(fmt.Errorf("portgroups for VM %s does not align with failure domain %s", nodeProviderId, failureDomain.Name)).NotTo(HaveOccurred()) |
| 79 | + } |
| 80 | + } |
| 81 | + } |
| 82 | +} |
| 83 | + |
| 84 | +func failIfNodeNetworkingInconsistentWithMachineNetwork(infra configv1.PlatformSpec, machineNetworks []string) { |
| 85 | + internalNodeNetworking := infra.VSphere.NodeNetworking.Internal |
| 86 | + externalNodeNetworking := infra.VSphere.NodeNetworking.External |
| 87 | + |
| 88 | + By("comparing nodeNetworking slices to the machine network") |
| 89 | + for _, nodeNetworkingSpec := range []configv1.VSpherePlatformNodeNetworkingSpec{internalNodeNetworking, externalNodeNetworking} { |
| 90 | + slices.Sort(nodeNetworkingSpec.NetworkSubnetCIDR) |
| 91 | + Expect(slices.Equal(nodeNetworkingSpec.NetworkSubnetCIDR, machineNetworks)).To(BeTrue()) |
| 92 | + } |
| 93 | +} |
| 94 | + |
| 95 | +func failIfMachinesDoNotHaveAllPortgroups(platformSpec configv1.PlatformSpec, machines *machinev1beta1.MachineList) { |
| 96 | + |
| 97 | + By("checking to see if machines have all portgroups") |
| 98 | + |
| 99 | + for _, failureDomain := range platformSpec.VSphere.FailureDomains { |
| 100 | + machinesInFailureDomain, err := getMachinesInFailureDomain(platformSpec.VSphere, failureDomain, machines) |
| 101 | + Expect(err).NotTo(HaveOccurred()) |
| 102 | + |
| 103 | + for _, machine := range machinesInFailureDomain { |
| 104 | + failIfMachineDoesNotHaveAllPortgroups(machine, failureDomain) |
| 105 | + } |
| 106 | + } |
| 107 | +} |
| 108 | + |
| 109 | +func failIfMachineDoesNotHaveAllPortgroups(machine machinev1beta1.Machine, failureDomain configv1.VSpherePlatformFailureDomainSpec) { |
| 110 | + |
| 111 | + By("checking to see if machine has all portgroups") |
| 112 | + |
| 113 | + spec, err := vsphere.ProviderSpecFromRawExtension(machine.Spec.ProviderSpec.Value) |
| 114 | + Expect(err).NotTo(HaveOccurred()) |
| 115 | + |
| 116 | + expectedPortgroups := failureDomain.Topology.Networks |
| 117 | + var portgroups []string |
| 118 | + |
| 119 | + for _, device := range spec.Network.Devices { |
| 120 | + portgroups = append(portgroups, device.NetworkName) |
| 121 | + } |
| 122 | + |
| 123 | + slices.Sort(expectedPortgroups) |
| 124 | + slices.Sort(portgroups) |
| 125 | + |
| 126 | + Expect(slices.Equal(expectedPortgroups, portgroups)).To(BeTrue()) |
| 127 | +} |
| 128 | + |
| 129 | +var _ = Describe("[sig-cluster-lifecycle][OCPFeatureGate:VSphereMultiNetworks][platform:vsphere] Managed cluster should", func() { |
| 130 | + defer GinkgoRecover() |
| 131 | + ctx := context.Background() |
| 132 | + |
| 133 | + var ( |
| 134 | + cfg *rest.Config |
| 135 | + c *kubernetes.Clientset |
| 136 | + cc *configclient.ConfigV1Client |
| 137 | + |
| 138 | + mc *machinesetclient.MachineV1beta1Client |
| 139 | + err error |
| 140 | + machineNetworks []string |
| 141 | + infra *configv1.Infrastructure |
| 142 | + nodes *corev1.NodeList |
| 143 | + machinePortgroups []string |
| 144 | + vsphereCreds *corev1.Secret |
| 145 | + machines *machinev1beta1.MachineList |
| 146 | + ) |
| 147 | + |
| 148 | + BeforeEach(func() { |
| 149 | + cfg, err = e2e.LoadConfig() |
| 150 | + Expect(err).NotTo(HaveOccurred()) |
| 151 | + c, err = e2e.LoadClientset() |
| 152 | + Expect(err).NotTo(HaveOccurred()) |
| 153 | + mc, err = machinesetclient.NewForConfig(cfg) |
| 154 | + Expect(err).NotTo(HaveOccurred()) |
| 155 | + cc, err = configclient.NewForConfig(cfg) |
| 156 | + Expect(err).NotTo(HaveOccurred()) |
| 157 | + infra, err = cc.Infrastructures().Get(ctx, "cluster", metav1.GetOptions{}) |
| 158 | + Expect(err).NotTo(HaveOccurred()) |
| 159 | + |
| 160 | + vsphereCreds, err = c.CoreV1().Secrets("kube-system").Get(ctx, "vsphere-creds", v1.GetOptions{}) |
| 161 | + Expect(err).NotTo(HaveOccurred()) |
| 162 | + |
| 163 | + Expect(len(infra.Spec.PlatformSpec.VSphere.FailureDomains) >= 1) |
| 164 | + |
| 165 | + for _, machineNetwork := range infra.Spec.PlatformSpec.VSphere.MachineNetworks { |
| 166 | + machineNetworks = append(machineNetworks, string(machineNetwork)) |
| 167 | + } |
| 168 | + |
| 169 | + Expect(len(machineNetworks) >= 1) |
| 170 | + slices.Sort(machineNetworks) |
| 171 | + |
| 172 | + nodes, err = c.CoreV1().Nodes().List(ctx, v1.ListOptions{}) |
| 173 | + Expect(err).NotTo(HaveOccurred()) |
| 174 | + |
| 175 | + machines, err = mc.Machines("openshift-machine-api").List(ctx, v1.ListOptions{}) |
| 176 | + Expect(err).NotTo(HaveOccurred()) |
| 177 | + |
| 178 | + portGroups := make(map[string]any) |
| 179 | + for _, machine := range machines.Items { |
| 180 | + providerSpec, err := vsphere.ProviderSpecFromRawExtension(machine.Spec.ProviderSpec.Value) |
| 181 | + Expect(err).NotTo(HaveOccurred()) |
| 182 | + |
| 183 | + for _, network := range providerSpec.Network.Devices { |
| 184 | + portGroups[network.NetworkName] = network |
| 185 | + } |
| 186 | + } |
| 187 | + |
| 188 | + for k, _ := range portGroups { |
| 189 | + machinePortgroups = append(machinePortgroups, k) |
| 190 | + } |
| 191 | + }) |
| 192 | + |
| 193 | + It("node addresses should be correlated with the machine network", func() { |
| 194 | + By("checking for correlation between node internal/external IPs and the machine network") |
| 195 | + failIfNodeNotInMachineNetwork(*nodes, machineNetworks) |
| 196 | + }) |
| 197 | + |
| 198 | + It("machine network should be correlated with node networking", func() { |
| 199 | + failIfNodeNetworkingInconsistentWithMachineNetwork(infra.Spec.PlatformSpec, machineNetworks) |
| 200 | + }) |
| 201 | + |
| 202 | + It("machines should have all specified portgroup associated with their failure domain", func() { |
| 203 | + failIfMachinesDoNotHaveAllPortgroups(infra.Spec.PlatformSpec, machines) |
| 204 | + }) |
| 205 | + |
| 206 | + It("node VMs should have all specified portgroups attached which are associated with their failure domain", func() { |
| 207 | + failIfIncorrectPortgroupsAttachedToVMs(ctx, infra.Spec.PlatformSpec, nodes, vsphereCreds) |
| 208 | + }) |
| 209 | + |
| 210 | + It("new machines should pass multi network tests", func() { |
| 211 | + machineSets, err := e2eutil.GetMachineSets(cfg) |
| 212 | + Expect(err).NotTo(HaveOccurred()) |
| 213 | + |
| 214 | + Expect(len(machineSets.Items) >= 1) |
| 215 | + |
| 216 | + machineSet := machineSets.Items[0] |
| 217 | + |
| 218 | + // scale up new machine and wait for scale up to complete |
| 219 | + By("scaling up a new machineset which should have multiple NICs") |
| 220 | + err = e2eutil.ScaleMachineSet(cfg, machineSet.Name, int(*machineSet.Spec.Replicas)+1) |
| 221 | + Expect(err).NotTo(HaveOccurred()) |
| 222 | + |
| 223 | + nodes, err = c.CoreV1().Nodes().List(ctx, v1.ListOptions{}) |
| 224 | + Expect(err).NotTo(HaveOccurred()) |
| 225 | + |
| 226 | + machines, err = mc.Machines("openshift-machine-api").List(ctx, v1.ListOptions{}) |
| 227 | + Expect(err).NotTo(HaveOccurred()) |
| 228 | + |
| 229 | + By("determining common port groups among machines") |
| 230 | + portGroups := make(map[string]any) |
| 231 | + for _, machine := range machines.Items { |
| 232 | + providerSpec, err := vsphere.ProviderSpecFromRawExtension(machine.Spec.ProviderSpec.Value) |
| 233 | + Expect(err).NotTo(HaveOccurred()) |
| 234 | + |
| 235 | + for _, network := range providerSpec.Network.Devices { |
| 236 | + portGroups[network.NetworkName] = network |
| 237 | + } |
| 238 | + } |
| 239 | + |
| 240 | + for k, _ := range portGroups { |
| 241 | + machinePortgroups = append(machinePortgroups, k) |
| 242 | + } |
| 243 | + |
| 244 | + failIfNodeNotInMachineNetwork(*nodes, machineNetworks) |
| 245 | + failIfNodeNetworkingInconsistentWithMachineNetwork(infra.Spec.PlatformSpec, machineNetworks) |
| 246 | + failIfMachinesDoNotHaveAllPortgroups(infra.Spec.PlatformSpec, machines) |
| 247 | + failIfIncorrectPortgroupsAttachedToVMs(ctx, infra.Spec.PlatformSpec, nodes, vsphereCreds) |
| 248 | + }) |
| 249 | +}) |
0 commit comments