github.com/openshift/installer@v1.4.17/pkg/asset/installconfig/openstack/validvaluesfetcher.go (about) 1 package openstack 2 3 import ( 4 "context" 5 "fmt" 6 7 "github.com/gophercloud/gophercloud/v2/openstack/compute/v2/flavors" 8 "github.com/gophercloud/gophercloud/v2/openstack/networking/v2/extensions/external" 9 "github.com/gophercloud/gophercloud/v2/openstack/networking/v2/extensions/layer3/floatingips" 10 "github.com/gophercloud/gophercloud/v2/openstack/networking/v2/networks" 11 "github.com/gophercloud/utils/v2/openstack/clientconfig" 12 networkutils "github.com/gophercloud/utils/v2/openstack/networking/v2/networks" 13 14 openstackdefaults "github.com/openshift/installer/pkg/types/openstack/defaults" 15 ) 16 17 // getCloudNames gets the valid cloud names. These are read from clouds.yaml. 18 func getCloudNames() ([]string, error) { 19 clouds, err := clientconfig.LoadCloudsYAML() 20 if err != nil { 21 return nil, err 22 } 23 24 cloudNames := []string{} 25 for k := range clouds { 26 cloudNames = append(cloudNames, k) 27 } 28 return cloudNames, nil 29 } 30 31 // getExternalNetworkNames interrogates OpenStack to get the external network 32 // names. 33 func getExternalNetworkNames(ctx context.Context, cloud string) ([]string, error) { 34 conn, err := openstackdefaults.NewServiceClient(ctx, "network", openstackdefaults.DefaultClientOpts(cloud)) 35 if err != nil { 36 return nil, err 37 } 38 39 iTrue := true 40 listOpts := external.ListOptsExt{ 41 ListOptsBuilder: networks.ListOpts{}, 42 External: &iTrue, 43 } 44 45 allPages, err := networks.List(conn, listOpts).AllPages(ctx) 46 if err != nil { 47 return nil, err 48 } 49 50 allNetworks, err := networks.ExtractNetworks(allPages) 51 if err != nil { 52 return nil, err 53 } 54 55 networkNames := make([]string, len(allNetworks)) 56 for x, network := range allNetworks { 57 networkNames[x] = network.Name 58 } 59 60 return networkNames, nil 61 } 62 63 // getFlavorNames gets a list of valid flavor names. 64 func getFlavorNames(ctx context.Context, cloud string) ([]string, error) { 65 conn, err := openstackdefaults.NewServiceClient(ctx, "compute", openstackdefaults.DefaultClientOpts(cloud)) 66 if err != nil { 67 return nil, err 68 } 69 70 listOpts := flavors.ListOpts{} 71 allPages, err := flavors.ListDetail(conn, listOpts).AllPages(ctx) 72 if err != nil { 73 return nil, err 74 } 75 76 allFlavors, err := flavors.ExtractFlavors(allPages) 77 if err != nil { 78 return nil, err 79 } 80 81 if len(allFlavors) == 0 { 82 return nil, fmt.Errorf("no OpenStack flavors were found") 83 } 84 85 flavorNames := make([]string, len(allFlavors)) 86 for i, flavor := range allFlavors { 87 flavorNames[i] = flavor.Name 88 } 89 90 return flavorNames, nil 91 } 92 93 type sortableFloatingIPCollection []floatingips.FloatingIP 94 95 func (fips sortableFloatingIPCollection) Len() int { return len(fips) } 96 func (fips sortableFloatingIPCollection) Less(i, j int) bool { 97 return fips[i].FloatingIP < fips[j].FloatingIP 98 } 99 func (fips sortableFloatingIPCollection) Swap(i, j int) { 100 fips[i], fips[j] = fips[j], fips[i] 101 } 102 103 func (fips sortableFloatingIPCollection) Names() []string { 104 names := make([]string, len(fips)) 105 for i := range fips { 106 names[i] = fips[i].FloatingIP 107 } 108 return names 109 } 110 111 func (fips sortableFloatingIPCollection) Description(index int) string { 112 return fips[index].Description 113 } 114 115 func (fips sortableFloatingIPCollection) Contains(value string) bool { 116 for i := range fips { 117 if value == fips[i].FloatingIP { 118 return true 119 } 120 } 121 return false 122 } 123 124 func getFloatingIPs(ctx context.Context, cloud string, floatingNetworkName string) (sortableFloatingIPCollection, error) { 125 conn, err := openstackdefaults.NewServiceClient(ctx, "network", openstackdefaults.DefaultClientOpts(cloud)) 126 if err != nil { 127 return nil, err 128 } 129 130 // floatingips.ListOpts requires an ID so we must get it from the name 131 floatingNetworkID, err := networkutils.IDFromName(ctx, conn, floatingNetworkName) 132 if err != nil { 133 return nil, err 134 } 135 136 // Only show IPs that belong to the network and are not in use 137 listOpts := floatingips.ListOpts{ 138 FloatingNetworkID: floatingNetworkID, 139 Status: "DOWN", 140 } 141 142 allPages, err := floatingips.List(conn, listOpts).AllPages(ctx) 143 if err != nil { 144 return nil, err 145 } 146 147 allFloatingIPs, err := floatingips.ExtractFloatingIPs(allPages) 148 if err != nil { 149 return nil, err 150 } 151 152 if len(allFloatingIPs) == 0 { 153 return nil, fmt.Errorf("there are no unassigned floating IP addresses available") 154 } 155 156 return allFloatingIPs, nil 157 }