Openstack builder should use existing floating IPs before allocating them
Rather than always creating a new floating IP, search the provided pool for an unallocated address and use this instead. Only allocate a temporary address if there is no spare address in the pool. Closes #4215
This commit is contained in:
parent
7e92b07735
commit
08ef89f032
|
@ -5,6 +5,7 @@ import (
|
|||
|
||||
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/floatingips"
|
||||
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
|
||||
"github.com/gophercloud/gophercloud/pagination"
|
||||
"github.com/mitchellh/multistep"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
)
|
||||
|
@ -36,20 +37,55 @@ func (s *StepAllocateIp) Run(state multistep.StateBag) multistep.StepAction {
|
|||
if s.FloatingIp != "" {
|
||||
instanceIp.IP = s.FloatingIp
|
||||
} else if s.FloatingIpPool != "" {
|
||||
ui.Say(fmt.Sprintf("Creating floating IP..."))
|
||||
ui.Message(fmt.Sprintf("Pool: %s", s.FloatingIpPool))
|
||||
newIp, err := floatingips.Create(client, floatingips.CreateOpts{
|
||||
Pool: s.FloatingIpPool,
|
||||
}).Extract()
|
||||
// If we have a free floating IP in the pool, use it first
|
||||
// rather than creating one
|
||||
ui.Say(fmt.Sprintf("Searching for unassociated floating IP in pool %s", s.FloatingIpPool))
|
||||
pager := floatingips.List(client)
|
||||
err := pager.EachPage(func(page pagination.Page) (bool, error) {
|
||||
candidates, err := floatingips.ExtractFloatingIPs(page)
|
||||
|
||||
if err != nil {
|
||||
return false, err // stop and throw error out
|
||||
}
|
||||
|
||||
for _, candidate := range candidates {
|
||||
if candidate.Pool != s.FloatingIpPool || candidate.InstanceID != "" {
|
||||
continue // move to next in list
|
||||
}
|
||||
|
||||
// In correct pool and able to be allocated
|
||||
instanceIp.IP = candidate.IP
|
||||
ui.Message(fmt.Sprintf("Selected floating IP: %s", instanceIp.IP))
|
||||
state.Put("floatingip_istemp", false)
|
||||
return false, nil // stop iterating over pages
|
||||
}
|
||||
return true, nil // try the next page
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Error creating floating ip from pool '%s'", s.FloatingIpPool)
|
||||
err := fmt.Errorf("Error searching for floating ip from pool '%s'", s.FloatingIpPool)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
instanceIp = *newIp
|
||||
ui.Message(fmt.Sprintf("Created floating IP: %s", instanceIp.IP))
|
||||
if instanceIp.IP == "" {
|
||||
ui.Say(fmt.Sprintf("Creating floating IP..."))
|
||||
ui.Message(fmt.Sprintf("Pool: %s", s.FloatingIpPool))
|
||||
newIp, err := floatingips.Create(client, floatingips.CreateOpts{
|
||||
Pool: s.FloatingIpPool,
|
||||
}).Extract()
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Error creating floating ip from pool '%s'", s.FloatingIpPool)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
instanceIp = *newIp
|
||||
ui.Message(fmt.Sprintf("Created floating IP: %s", instanceIp.IP))
|
||||
state.Put("floatingip_istemp", true)
|
||||
}
|
||||
}
|
||||
|
||||
if instanceIp.IP != "" {
|
||||
|
@ -80,6 +116,11 @@ func (s *StepAllocateIp) Cleanup(state multistep.StateBag) {
|
|||
ui := state.Get("ui").(packer.Ui)
|
||||
instanceIp := state.Get("access_ip").(*floatingips.FloatingIP)
|
||||
|
||||
// Don't delete pool addresses we didn't allocate
|
||||
if state.Get("floatingip_istemp") == false {
|
||||
return
|
||||
}
|
||||
|
||||
// We need the v2 compute client
|
||||
client, err := config.computeV2Client()
|
||||
if err != nil {
|
||||
|
|
Loading…
Reference in New Issue