Skip to content

Commit 25c0a61

Browse files
openstack: Create server groups in the CAPI flow
CAPO doesn't create server groups; it needs the server groups referred to in Machines to be created in the PreProvision hook.
1 parent 5c107e3 commit 25c0a61

File tree

3 files changed

+139
-9
lines changed

3 files changed

+139
-9
lines changed

pkg/infrastructure/openstack/clusterapi/clusterapi.go

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"sigs.k8s.io/controller-runtime/pkg/client"
1111

1212
configv1 "github.com/openshift/api/config/v1"
13+
mapov1alpha1 "github.com/openshift/api/machine/v1alpha1"
1314
"github.com/openshift/installer/pkg/asset/manifests"
1415
"github.com/openshift/installer/pkg/asset/manifests/capiutils"
1516
"github.com/openshift/installer/pkg/infrastructure/clusterapi"
@@ -32,13 +33,16 @@ func (p Provider) Name() string {
3233

3334
var _ clusterapi.PreProvider = Provider{}
3435

35-
// PreProvision tags the VIP ports and creates the security groups that are needed during CAPI provisioning.
36+
// PreProvision tags the VIP ports, and creates the security groups and the
37+
// server groups defined in the Machine manifests.
3638
func (p Provider) PreProvision(ctx context.Context, in clusterapi.PreProvisionInput) error {
3739
var (
38-
infraID = in.InfraID
39-
installConfig = in.InstallConfig
40-
rhcosImage = string(*in.RhcosImage)
41-
manifestsAsset = in.ManifestsAsset
40+
infraID = in.InfraID
41+
installConfig = in.InstallConfig
42+
rhcosImage = string(*in.RhcosImage)
43+
manifestsAsset = in.ManifestsAsset
44+
machineManifests = in.MachineManifests
45+
workersAsset = in.WorkersAsset
4246
)
4347

4448
if err := preprovision.TagVIPPorts(ctx, installConfig, infraID); err != nil {
@@ -71,6 +75,30 @@ func (p Provider) PreProvision(ctx context.Context, in clusterapi.PreProvisionIn
7175
}
7276
}
7377

78+
{
79+
capiMachines := make([]capo.OpenStackMachine, 0, len(machineManifests))
80+
for i := range machineManifests {
81+
if m, ok := machineManifests[i].(*capo.OpenStackMachine); ok {
82+
capiMachines = append(capiMachines, *m)
83+
}
84+
}
85+
86+
var workerSpecs []mapov1alpha1.OpenstackProviderSpec
87+
{
88+
machineSets, err := workersAsset.MachineSets()
89+
if err != nil {
90+
return fmt.Errorf("failed to extract MachineSets from the worker assets: %w", err)
91+
}
92+
workerSpecs = make([]mapov1alpha1.OpenstackProviderSpec, 0, len(machineSets))
93+
for _, machineSet := range machineSets {
94+
workerSpecs = append(workerSpecs, *machineSet.Spec.Template.Spec.ProviderSpec.Value.Object.(*mapov1alpha1.OpenstackProviderSpec))
95+
}
96+
}
97+
if err := preprovision.ServerGroups(ctx, installConfig, capiMachines, workerSpecs); err != nil {
98+
return fmt.Errorf("failed to create server groups: %w", err)
99+
}
100+
}
101+
74102
return nil
75103
}
76104

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
package preprovision
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/servergroups"
8+
"github.com/gophercloud/gophercloud/pagination"
9+
"github.com/sirupsen/logrus"
10+
capo "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
11+
12+
mapov1alpha1 "github.com/openshift/api/machine/v1alpha1"
13+
"github.com/openshift/installer/pkg/asset/installconfig"
14+
tfvars "github.com/openshift/installer/pkg/tfvars/openstack"
15+
"github.com/openshift/installer/pkg/types/openstack"
16+
"github.com/openshift/installer/pkg/types/openstack/defaults"
17+
)
18+
19+
// ServerGroups creates server groups referenced by name in the Machine
20+
// manifests if they don't exist already. The newly created server groups have
21+
// the policy defined in the install-config's machine-pools.
22+
func ServerGroups(_ context.Context, installConfig *installconfig.InstallConfig, capiMachines []capo.OpenStackMachine, mapoWorkerProviderSpecs []mapov1alpha1.OpenstackProviderSpec) error {
23+
logrus.Debugf("Creating the server groups")
24+
computeClient, err := defaults.NewServiceClient("compute", defaults.DefaultClientOpts(installConfig.Config.Platform.OpenStack.Cloud))
25+
if err != nil {
26+
return fmt.Errorf("failed to build an OpenStack client: %w", err)
27+
}
28+
computeClient.Microversion = "2.64"
29+
30+
var masterPolicy, workerPolicy openstack.ServerGroupPolicy
31+
{
32+
if masterMP := installConfig.Config.ControlPlane; masterMP != nil {
33+
masterPolicy = tfvars.GetServerGroupPolicy(masterMP.Platform.OpenStack, installConfig.Config.OpenStack.DefaultMachinePlatform)
34+
} else {
35+
masterPolicy = tfvars.GetServerGroupPolicy(nil, installConfig.Config.OpenStack.DefaultMachinePlatform)
36+
}
37+
38+
if workerMP := installConfig.Config.WorkerMachinePool(); workerMP != nil {
39+
workerPolicy = tfvars.GetServerGroupPolicy(workerMP.Platform.OpenStack, installConfig.Config.OpenStack.DefaultMachinePlatform)
40+
} else {
41+
workerPolicy = tfvars.GetServerGroupPolicy(nil, installConfig.Config.OpenStack.DefaultMachinePlatform)
42+
}
43+
}
44+
45+
// serverGroups is the set of server groups to be created.
46+
serverGroups := make(map[string]openstack.ServerGroupPolicy, len(capiMachines)+len(mapoWorkerProviderSpecs))
47+
for _, machine := range capiMachines {
48+
if _, ok := machine.Labels["cluster.x-k8s.io/control-plane"]; !ok {
49+
logrus.Debugf("Found unexpected machine %q among the CAPI Machine manifests", machine.GetName())
50+
continue
51+
}
52+
if sgParam := machine.Spec.ServerGroup; sgParam != nil && sgParam.Filter != nil && sgParam.Filter.Name != nil {
53+
serverGroupName := *sgParam.Filter.Name
54+
if visitedPolicy, ok := serverGroups[serverGroupName]; ok {
55+
if masterPolicy != visitedPolicy {
56+
return fmt.Errorf("server group %q is referenced with different policies in the install-config machine-pools", serverGroupName)
57+
}
58+
continue
59+
}
60+
serverGroups[serverGroupName] = masterPolicy
61+
}
62+
}
63+
for _, providerSpec := range mapoWorkerProviderSpecs {
64+
if serverGroupName := providerSpec.ServerGroupName; serverGroupName != "" {
65+
if visitedPolicy, ok := serverGroups[serverGroupName]; ok {
66+
if workerPolicy != visitedPolicy {
67+
return fmt.Errorf("server group %q is referenced with different policies in the install-config machine-pools", serverGroupName)
68+
}
69+
continue
70+
}
71+
serverGroups[serverGroupName] = workerPolicy
72+
}
73+
}
74+
75+
// Remove existing server groups from the list of resources to be created.
76+
if err = servergroups.List(computeClient, nil).EachPage(func(p pagination.Page) (bool, error) {
77+
sgs, err := servergroups.ExtractServerGroups(p)
78+
if err != nil {
79+
return false, err
80+
}
81+
82+
for i := range sgs {
83+
delete(serverGroups, sgs[i].Name)
84+
}
85+
return true, nil
86+
}); err != nil {
87+
return fmt.Errorf("failed to list server groups: %w", err)
88+
}
89+
90+
// Create the server groups referenced by name in the Machine manifests, that don't exist already.
91+
for name, policy := range serverGroups {
92+
logrus.Debugf("Creating server group %q with policy %q", name, policy)
93+
if _, err := servergroups.Create(computeClient, servergroups.CreateOpts{
94+
Name: name,
95+
Policy: string(policy),
96+
}).Extract(); err != nil {
97+
return fmt.Errorf("failed to create server group %q: %w", name, err)
98+
}
99+
}
100+
return nil
101+
}

pkg/tfvars/openstack/openstack.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,13 +125,13 @@ func TFVars(
125125
rootVolumeSize = rootVolume.Size
126126
}
127127

128-
masterServerGroupPolicy := getServerGroupPolicy(mastermpool, defaultmpool, types_openstack.SGPolicySoftAntiAffinity)
128+
masterServerGroupPolicy := GetServerGroupPolicy(mastermpool, defaultmpool)
129129
masterServerGroupName := masterSpecs[0].ServerGroupName
130130
if masterSpecs[0].ServerGroupID != "" {
131131
return nil, fmt.Errorf("the field ServerGroupID is not implemented in the Installer. Please use ServerGroupName for automatic creation of the Control Plane server group")
132132
}
133133

134-
workerServerGroupPolicy := getServerGroupPolicy(workermpool, defaultmpool, types_openstack.SGPolicySoftAntiAffinity)
134+
workerServerGroupPolicy := GetServerGroupPolicy(workermpool, defaultmpool)
135135
var workerServerGroupNames []string
136136
{
137137
for _, workerConfig := range workerSpecs {
@@ -272,12 +272,13 @@ func isOctaviaSupported(serviceCatalog *tokens.ServiceCatalog) (bool, error) {
272272
return true, nil
273273
}
274274

275-
func getServerGroupPolicy(machinePool, defaultMachinePool *types_openstack.MachinePool, defaultPolicy types_openstack.ServerGroupPolicy) types_openstack.ServerGroupPolicy {
275+
// GetServerGroupPolicy returns the server group policy set in the given machine-pool, or in the default one, or falls back to soft-anti-affinity.
276+
func GetServerGroupPolicy(machinePool, defaultMachinePool *types_openstack.MachinePool) types_openstack.ServerGroupPolicy {
276277
if machinePool != nil && machinePool.ServerGroupPolicy.IsSet() {
277278
return machinePool.ServerGroupPolicy
278279
}
279280
if defaultMachinePool != nil && defaultMachinePool.ServerGroupPolicy.IsSet() {
280281
return defaultMachinePool.ServerGroupPolicy
281282
}
282-
return defaultPolicy
283+
return types_openstack.SGPolicySoftAntiAffinity
283284
}

0 commit comments

Comments
 (0)