Skip to content

Commit

Permalink
cluster-api: Create bootstrap FIP
Browse files Browse the repository at this point in the history
This is created in the postprovision step, since we'll attach it once
the bootstrap machine has been created.

Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
  • Loading branch information
stephenfin authored and MaysaMacedo committed Feb 19, 2024
1 parent fa02381 commit 993ec21
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 1 deletion.
23 changes: 23 additions & 0 deletions pkg/infrastructure/openstack/clusterapi/clusterapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/openshift/installer/pkg/asset/manifests/capiutils"
"github.com/openshift/installer/pkg/infrastructure/clusterapi"
"github.com/openshift/installer/pkg/infrastructure/openstack/infraready"
"github.com/openshift/installer/pkg/infrastructure/openstack/postprovision"
"github.com/openshift/installer/pkg/infrastructure/openstack/preprovision"
"github.com/openshift/installer/pkg/rhcos"
"github.com/openshift/installer/pkg/types/openstack"
Expand Down Expand Up @@ -102,3 +103,25 @@ func (p Provider) Ignition(ctx context.Context, in clusterapi.IgnitionInput) ([]

return preprovision.UploadIgnitionAndBuildShim(ctx, installConfig.Config.Platform.OpenStack.Cloud, infraID, installConfig.Config.Proxy, bootstrapIgnData)
}

var _ clusterapi.PostProvider = Provider{}

// PostProvision creates and attaches a Floating IP to the Bootstrap Machine.
func (p Provider) PostProvision(ctx context.Context, in clusterapi.PostProvisionInput) error {
var (
k8sClient = in.Client
infraID = in.InfraID
installConfig = in.InstallConfig
)

ospCluster := &capo.OpenStackCluster{}
key := client.ObjectKey{
Name: infraID,
Namespace: capiutils.Namespace,
}
if err := k8sClient.Get(ctx, key, ospCluster); err != nil {
return fmt.Errorf("failed to get OSPCluster: %w", err)
}

return postprovision.FloatingIPs(ctx, k8sClient, ospCluster, installConfig, infraID)
}
1 change: 0 additions & 1 deletion pkg/infrastructure/openstack/infraready/floatingips.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ func FloatingIPs(cluster *capo.OpenStackCluster, installConfig *installconfig.In
return nil
}


func createPort(client *gophercloud.ServiceClient, role, infraID, networkID, subnetID, fixedIP string) (*ports.Port, error) {
createOpts := ports.CreateOpts{
Name: fmt.Sprintf("%s-%s-port", infraID, role),
Expand Down
120 changes: 120 additions & 0 deletions pkg/infrastructure/openstack/postprovision/floatingips.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package postprovision

import (
"context"
"fmt"

"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/attributestags"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips"
"github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
"github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
capo "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7"
"sigs.k8s.io/controller-runtime/pkg/client"

"github.com/openshift/installer/pkg/asset/installconfig"
"github.com/openshift/installer/pkg/asset/manifests/capiutils"
openstackdefaults "github.com/openshift/installer/pkg/types/openstack/defaults"
)

// FloatingIPs creates and attaches a Floating IP to the Bootstrap Machine.
func FloatingIPs(ctx context.Context, c client.Client, cluster *capo.OpenStackCluster, installConfig *installconfig.InstallConfig, infraID string) error {
bootstrapMachine := &capo.OpenStackMachine{}
key := client.ObjectKey{
Name: capiutils.GenerateBoostrapMachineName(infraID),
Namespace: capiutils.Namespace,
}
if err := c.Get(ctx, key, bootstrapMachine); err != nil {
return fmt.Errorf("failed to get bootstrap Machine: %w", err)
}

networkClient, err := openstackdefaults.NewServiceClient("network", openstackdefaults.DefaultClientOpts(installConfig.Config.Platform.OpenStack.Cloud))
if err != nil {
return err
}

bootstrapPort, err := getPortForInstance(networkClient, *bootstrapMachine.Spec.InstanceID)
if err != nil {
return err
}

network, err := getNetworkByName(networkClient, cluster.Spec.ExternalNetworkID)
if err != nil {
return err
}

_, err = createAndAttachFIP(networkClient, "bootstrap", infraID, network.ID, bootstrapPort.ID)
if err != nil {
return err
}

return nil
}

// Get the first port associated with an instance.
//
// This is used to attach a FIP to the instance.
func getPortForInstance(client *gophercloud.ServiceClient, instanceID string) (*ports.Port, error) {
listOpts := ports.ListOpts{
DeviceID: instanceID,
}
allPages, err := ports.List(client, listOpts).AllPages()
if err != nil {
return nil, fmt.Errorf("failed to list ports: %w", err)
}
allPorts, err := ports.ExtractPorts(allPages)
if err != nil {
return nil, fmt.Errorf("failed to extract ports: %w", err)
}

if len(allPorts) < 1 {
return nil, fmt.Errorf("bootstrap machine has no associated ports")
}

return &allPorts[0], nil
}

// Get a network by name.
func getNetworkByName(client *gophercloud.ServiceClient, name string) (*networks.Network, error) {
listOpts := networks.ListOpts{
Name: name,
}
allPages, err := networks.List(client, listOpts).AllPages()
if err != nil {
return nil, fmt.Errorf("failed to list networks: %w", err)
}
allNetworks, err := networks.ExtractNetworks(allPages)
if err != nil {
return nil, fmt.Errorf("failed to extract networks: %w", err)
}

if len(allNetworks) < 1 {
return nil, fmt.Errorf("found no matches for network %s", name)
} else if len(allNetworks) > 1 {
return nil, fmt.Errorf("found more than one match for network %s", name)
}

return &allNetworks[0], nil
}

// Create a floating IP.
func createAndAttachFIP(client *gophercloud.ServiceClient, role, infraID, networkID, portID string) (*floatingips.FloatingIP, error) {
createOpts := floatingips.CreateOpts{
Description: fmt.Sprintf("%s-%s-fip", infraID, role),
FloatingNetworkID: networkID,
PortID: portID,
}

floatingIP, err := floatingips.Create(client, createOpts).Extract()
if err != nil {
return nil, err
}

tag := fmt.Sprintf("openshiftClusterID=%s", infraID)
err = attributestags.Add(client, "floatingips", floatingIP.ID, tag).ExtractErr()
if err != nil {
return nil, err
}

return floatingIP, err
}

0 comments on commit 993ec21

Please sign in to comment.