Fix #7171: select instance network on which to assign floating ip

Add config parameter instance_floating_ip_net to control
floating ip assignment for a multi-homed instances.  This ensures
the floating ip can be correctly assigned to the instance port
that is connected to the preferred network for floating ip assignment.

This avoids the default first-returned selection method which may
choose a network to which floating ip's can't be assigned,
e.g. because that network is not reachable from the floating ip
network.
This commit is contained in:
John-Paul Robinson 2019-07-17 17:00:28 -05:00
parent 6b1a407e2a
commit 5fe9f3980d
4 changed files with 20 additions and 3 deletions

View File

@ -129,6 +129,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
FloatingIPNetwork: b.config.FloatingIPNetwork,
FloatingIP: b.config.FloatingIP,
ReuseIPs: b.config.ReuseIPs,
InstanceFloatingIPNet: b.config.InstanceFloatingIPNet,
},
&communicator.StepConnect{
Config: &b.config.RunConfig.Comm,

View File

@ -2,6 +2,7 @@ package openstack
import (
"fmt"
"log"
"github.com/google/uuid"
"github.com/gophercloud/gophercloud"
@ -66,7 +67,10 @@ func FindFreeFloatingIP(client *gophercloud.ServiceClient) (*floatingips.Floatin
// GetInstancePortID returns internal port of the instance that can be used for
// the association of a floating IP.
// It will return an ID of a first port if there are many.
func GetInstancePortID(client *gophercloud.ServiceClient, id string) (string, error) {
func GetInstancePortID(client *gophercloud.ServiceClient, id string, instance_float_net string) (string, error) {
selected_interface := 0
interfacesPage, err := attachinterfaces.List(client, id).AllPages()
if err != nil {
return "", err
@ -79,7 +83,17 @@ func GetInstancePortID(client *gophercloud.ServiceClient, id string) (string, er
return "", fmt.Errorf("instance '%s' has no interfaces", id)
}
return interfaces[0].PortID, nil
for i := 0; i < len(interfaces); i++ {
log.Printf("Instance interface: %v: %+v\n", i, interfaces[i])
if interfaces[i].NetID == instance_float_net {
log.Printf("Found preferred interface: %v\n", i)
selected_interface = i
log.Printf("Using interface value: %v", selected_interface)
}
}
return interfaces[selected_interface].PortID, nil
}
// CheckFloatingIPNetwork checks provided network reference and returns a valid

View File

@ -28,6 +28,7 @@ type RunConfig struct {
ReuseIPs bool `mapstructure:"reuse_ips"`
SecurityGroups []string `mapstructure:"security_groups"`
Networks []string `mapstructure:"networks"`
InstanceFloatingIPNet string `mapstructure:"instance_floating_ip_net"`
Ports []string `mapstructure:"ports"`
UserData string `mapstructure:"user_data"`
UserDataFile string `mapstructure:"user_data_file"`

View File

@ -14,6 +14,7 @@ type StepAllocateIp struct {
FloatingIPNetwork string
FloatingIP string
ReuseIPs bool
InstanceFloatingIPNet string
}
func (s *StepAllocateIp) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
@ -114,7 +115,7 @@ func (s *StepAllocateIp) Run(ctx context.Context, state multistep.StateBag) mult
ui.Say(fmt.Sprintf("Associating floating IP '%s' (%s) with instance port...",
instanceIP.ID, instanceIP.FloatingIP))
portID, err := GetInstancePortID(computeClient, server.ID)
portID, err := GetInstancePortID(computeClient, server.ID, s.InstanceFloatingIPNet)
if err != nil {
err := fmt.Errorf("Error getting interfaces of the instance '%s': %s", server.ID, err)
state.Put("error", err)