From 1af899248bd285ceb04d98982e34c6410e216f75 Mon Sep 17 00:00:00 2001 From: Andrei Ozerov Date: Thu, 16 Aug 2018 23:38:41 +0300 Subject: [PATCH] OpenStack builder: allow floating IP network name Add support for the external network reference by it's name apart from ID. Include external network id in a log message of the openstack/step_allocate_ip. --- builder/openstack/networks.go | 37 +++++++++++++++++++++++++++ builder/openstack/step_allocate_ip.go | 20 ++++++++++----- 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/builder/openstack/networks.go b/builder/openstack/networks.go index ac56fa531..8afc31013 100644 --- a/builder/openstack/networks.go +++ b/builder/openstack/networks.go @@ -3,6 +3,7 @@ package openstack import ( "fmt" + "github.com/google/uuid" "github.com/gophercloud/gophercloud" "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/attachinterfaces" "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/external" @@ -112,3 +113,39 @@ func GetInstancePortID(client *gophercloud.ServiceClient, id string) (string, er return interfaces[0].PortID, nil } + +// CheckExternalNetworkRef checks provided network reference and returns a valid +// Networking service ID. +func CheckExternalNetworkRef(client *gophercloud.ServiceClient, networkRef string) (string, error) { + if _, err := uuid.Parse(networkRef); err != nil { + return GetExternalNetworkIDByName(client, networkRef) + } + + return networkRef, nil +} + +// GetExternalNetworkIDByName searches for the external network ID by the provided name. +func GetExternalNetworkIDByName(client *gophercloud.ServiceClient, networkName string) (string, error) { + var externalNetworks []ExternalNetwork + + allPages, err := networks.List(client, networks.ListOpts{ + Name: networkName, + }).AllPages() + if err != nil { + return "", err + } + + if err := networks.ExtractNetworksInto(allPages, &externalNetworks); err != nil { + return "", err + } + + if len(externalNetworks) == 0 { + return "", fmt.Errorf("can't find external network %s", networkName) + } + // Check and return the first external network. + if !externalNetworks[0].External { + return "", fmt.Errorf("network %s is not external", networkName) + } + + return externalNetworks[0].ID, nil +} diff --git a/builder/openstack/step_allocate_ip.go b/builder/openstack/step_allocate_ip.go index 7c864ca7a..ad58ad352 100644 --- a/builder/openstack/step_allocate_ip.go +++ b/builder/openstack/step_allocate_ip.go @@ -75,10 +75,19 @@ func (s *StepAllocateIp) Run(_ context.Context, state multistep.StateBag) multis // Create a new floating IP if it wasn't obtained in the previous step. if instanceIP.ID == "" { - // Search for the external network that can be used for the floating IPs if - // user hasn't provided any. - floatingNetwork := s.FloatingIPNetwork - if floatingNetwork == "" { + var floatingNetwork string + + if s.FloatingIPNetwork != "" { + // Validate provided external network reference and get an ID. + floatingNetwork, err = CheckExternalNetworkRef(networkClient, s.FloatingIPNetwork) + if err != nil { + err := fmt.Errorf("Error using the provided floating_ip_network: %s", err) + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt + } + } else { + // Search for the external network that can be used for the floating IPs. ui.Say(fmt.Sprintf("Searching for the external network...")) externalNetwork, err := FindExternalNetwork(networkClient) if err != nil { @@ -87,11 +96,10 @@ func (s *StepAllocateIp) Run(_ context.Context, state multistep.StateBag) multis ui.Error(err.Error()) return multistep.ActionHalt } - floatingNetwork = externalNetwork.ID } - ui.Say(fmt.Sprintf("Creating floating IP...")) + ui.Say(fmt.Sprintf("Creating floating IP using network %s ...", floatingNetwork)) newIP, err := floatingips.Create(networkClient, floatingips.CreateOpts{ FloatingNetworkID: floatingNetwork, }).Extract()