github.com/openshift/installer@v1.4.17/pkg/infrastructure/openstack/postprovision/floatingips.go (about) 1 package postprovision 2 3 import ( 4 "context" 5 "fmt" 6 7 "github.com/gophercloud/gophercloud/v2" 8 "github.com/gophercloud/gophercloud/v2/openstack/networking/v2/extensions/attributestags" 9 "github.com/gophercloud/gophercloud/v2/openstack/networking/v2/extensions/layer3/floatingips" 10 "github.com/gophercloud/gophercloud/v2/openstack/networking/v2/ports" 11 "github.com/gophercloud/gophercloud/v2/pagination" 12 capo "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1" 13 "sigs.k8s.io/controller-runtime/pkg/client" 14 15 "github.com/openshift/installer/pkg/asset/installconfig" 16 "github.com/openshift/installer/pkg/asset/manifests/capiutils" 17 openstackdefaults "github.com/openshift/installer/pkg/types/openstack/defaults" 18 ) 19 20 // FloatingIPs creates and attaches a Floating IP to the Bootstrap Machine. 21 func FloatingIPs(ctx context.Context, c client.Client, cluster *capo.OpenStackCluster, installConfig *installconfig.InstallConfig, infraID string) error { 22 if cluster.Status.ExternalNetwork == nil { 23 return nil 24 } 25 bootstrapMachine := &capo.OpenStackMachine{} 26 key := client.ObjectKey{ 27 Name: capiutils.GenerateBoostrapMachineName(infraID), 28 Namespace: capiutils.Namespace, 29 } 30 if err := c.Get(ctx, key, bootstrapMachine); err != nil { 31 return fmt.Errorf("failed to get bootstrap Machine: %w", err) 32 } 33 34 networkClient, err := openstackdefaults.NewServiceClient(ctx, "network", openstackdefaults.DefaultClientOpts(installConfig.Config.Platform.OpenStack.Cloud)) 35 if err != nil { 36 return err 37 } 38 39 bootstrapPort, err := getPortForInstance(ctx, networkClient, *bootstrapMachine.Status.InstanceID, cluster.Status.Network.ID) 40 if err != nil { 41 return err 42 } 43 44 _, err = createAndAttachFIP(ctx, networkClient, "bootstrap", infraID, cluster.Status.ExternalNetwork.ID, bootstrapPort.ID) 45 if err != nil { 46 return err 47 } 48 49 return nil 50 } 51 52 // Return the first port associated with the given instance and existing on the 53 // given network. 54 func getPortForInstance(ctx context.Context, client *gophercloud.ServiceClient, instanceID, networkID string) (*ports.Port, error) { 55 var port *ports.Port 56 if err := ports.List(client, ports.ListOpts{DeviceID: instanceID, NetworkID: networkID}).EachPage(ctx, func(_ context.Context, page pagination.Page) (bool, error) { 57 ports, err := ports.ExtractPorts(page) 58 if err != nil { 59 return false, err 60 } 61 if len(ports) > 0 { 62 port = &ports[0] 63 return false, nil 64 } 65 return true, nil 66 }); err != nil { 67 return nil, fmt.Errorf("failed to list the ports of the bootstrap server: %w", err) 68 } 69 if port == nil { 70 return nil, fmt.Errorf("the bootstrap server has no associated ports") 71 } 72 return port, nil 73 } 74 75 // Create a floating IP. 76 func createAndAttachFIP(ctx context.Context, client *gophercloud.ServiceClient, role, infraID, networkID, portID string) (*floatingips.FloatingIP, error) { 77 createOpts := floatingips.CreateOpts{ 78 Description: fmt.Sprintf("%s-%s-fip", infraID, role), 79 FloatingNetworkID: networkID, 80 PortID: portID, 81 } 82 83 floatingIP, err := floatingips.Create(ctx, client, createOpts).Extract() 84 if err != nil { 85 return nil, err 86 } 87 88 tag := fmt.Sprintf("openshiftClusterID=%s", infraID) 89 err = attributestags.Add(ctx, client, "floatingips", floatingIP.ID, tag).ExtractErr() 90 if err != nil { 91 return nil, err 92 } 93 94 return floatingIP, err 95 }