packer-cn/builder/openstack/step_allocate_ip.go

171 lines
5.4 KiB
Go
Raw Normal View History

2014-02-27 03:34:24 -05:00
package openstack
import (
"context"
2014-02-27 03:34:24 -05:00
"fmt"
2015-06-12 00:16:43 -04:00
2016-11-27 19:59:26 -05:00
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips"
"github.com/hashicorp/packer/helper/multistep"
2017-04-04 16:39:01 -04:00
"github.com/hashicorp/packer/packer"
2014-02-27 03:34:24 -05:00
)
type StepAllocateIp struct {
FloatingNetwork string
FloatingIP string
ReuseIPs bool
2014-02-27 03:34:24 -05:00
}
func (s *StepAllocateIp) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
2014-02-27 03:34:24 -05:00
ui := state.Get("ui").(packer.Ui)
2015-06-12 00:16:43 -04:00
config := state.Get("config").(Config)
server := state.Get("server").(*servers.Server)
// We need the v2 compute client
computeClient, err := config.computeV2Client()
2015-06-12 00:16:43 -04:00
if err != nil {
err = fmt.Errorf("Error initializing compute client: %s", err)
state.Put("error", err)
return multistep.ActionHalt
}
2014-02-27 03:34:24 -05:00
// We need the v2 network client
networkClient, err := config.networkV2Client()
if err != nil {
err = fmt.Errorf("Error initializing network client: %s", err)
state.Put("error", err)
return multistep.ActionHalt
}
var instanceIP floatingips.FloatingIP
2015-06-12 10:02:04 -04:00
2014-02-27 03:34:24 -05:00
// This is here in case we error out before putting instanceIp into the
// statebag below, because it is requested by Cleanup()
state.Put("access_ip", &instanceIP)
// Try to use floating IP provided by the user or find a free floating IP.
if s.FloatingIP != "" {
freeFloatingIP, err := CheckFloatingIP(networkClient, s.FloatingIP)
if err != nil {
err := fmt.Errorf("Error using provided floating IP '%s': %s", s.FloatingIP, err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
2014-02-27 03:34:24 -05:00
}
2015-06-12 00:16:43 -04:00
instanceIP = *freeFloatingIP
ui.Message(fmt.Sprintf("Selected floating IP: '%s' (%s)", instanceIP.ID, instanceIP.FloatingIP))
state.Put("floatingip_istemp", false)
} else if s.ReuseIPs {
// If ReuseIPs is set to true and we have a free floating IP, use it rather
// than creating one.
ui.Say(fmt.Sprint("Searching for unassociated floating IP"))
freeFloatingIP, err := FindFreeFloatingIP(networkClient)
if err != nil {
err := fmt.Errorf("Error searching for floating IP: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
instanceIP = *freeFloatingIP
ui.Message(fmt.Sprintf("Selected floating IP: '%s' (%s)", instanceIP.ID, instanceIP.FloatingIP))
state.Put("floatingip_istemp", false)
}
// 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.FloatingNetwork
if floatingNetwork == "" {
ui.Say(fmt.Sprintf("Searching for the external network..."))
externalNetwork, err := FindExternalNetwork(networkClient)
if err != nil {
err := fmt.Errorf("Error searching the external network: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
floatingNetwork = externalNetwork.ID
}
ui.Say(fmt.Sprintf("Creating floating IP..."))
newIP, err := floatingips.Create(networkClient, floatingips.CreateOpts{
FloatingNetworkID: floatingNetwork,
}).Extract()
if err != nil {
err := fmt.Errorf("Error creating floating IP from floating network '%s': %s", floatingNetwork, err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
instanceIP = *newIP
ui.Message(fmt.Sprintf("Created floating IP: '%s' (%s)", instanceIP.ID, instanceIP.FloatingIP))
state.Put("floatingip_istemp", true)
2014-02-27 03:34:24 -05:00
}
// Assoctate a floating IP that was obtained in the previous steps.
if instanceIP.ID != "" {
ui.Say(fmt.Sprintf("Associating floating IP '%s' (%s) with instance port...",
instanceIP.ID, instanceIP.FloatingIP))
portID, err := GetInstancePortID(computeClient, server.ID)
if err != nil {
err := fmt.Errorf("Error getting interfaces of the instance '%s': %s", server.ID, err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
_, err = floatingips.Update(networkClient, instanceIP.ID, floatingips.UpdateOpts{
PortID: &portID,
}).Extract()
2015-06-12 00:16:43 -04:00
if err != nil {
err := fmt.Errorf(
"Error associating floating IP '%s' (%s) with instance port '%s': %s",
instanceIP.ID, instanceIP.FloatingIP, portID, err)
2014-02-27 03:34:24 -05:00
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
2015-06-12 00:16:43 -04:00
ui.Message(fmt.Sprintf(
"Added floating IP '%s' (%s) to instance!", instanceIP.ID, instanceIP.FloatingIP))
2014-02-27 03:34:24 -05:00
}
state.Put("access_ip", &instanceIP)
2014-02-27 03:34:24 -05:00
return multistep.ActionContinue
}
func (s *StepAllocateIp) Cleanup(state multistep.StateBag) {
2015-06-12 00:16:43 -04:00
config := state.Get("config").(Config)
2014-02-27 03:34:24 -05:00
ui := state.Get("ui").(packer.Ui)
instanceIP := state.Get("access_ip").(*floatingips.FloatingIP)
2015-06-12 00:16:43 -04:00
// Don't delete pool addresses we didn't allocate
if state.Get("floatingip_istemp") == false {
return
}
// We need the v2 network client
client, err := config.networkV2Client()
2015-06-12 00:16:43 -04:00
if err != nil {
ui.Error(fmt.Sprintf(
"Error deleting temporary floating IP '%s' (%s)", instanceIP.ID, instanceIP.FloatingIP))
2015-06-12 00:16:43 -04:00
return
}
if instanceIP.ID != "" {
if err := floatingips.Delete(client, instanceIP.ID).ExtractErr(); err != nil {
2015-06-12 00:16:43 -04:00
ui.Error(fmt.Sprintf(
"Error deleting temporary floating IP '%s' (%s)", instanceIP.ID, instanceIP.FloatingIP))
2014-02-27 03:34:24 -05:00
return
}
2015-06-12 00:16:43 -04:00
ui.Say(fmt.Sprintf("Deleted temporary floating IP '%s' (%s)", instanceIP.ID, instanceIP.FloatingIP))
2014-02-27 03:34:24 -05:00
}
}