Merge pull request #7884 from jprorama/fix-7171

[WIP] Fix #7171: select instance network on which to assign floating ip
This commit is contained in:
Megan Marsh 2019-07-25 11:57:24 -07:00 committed by GitHub
commit 3d22535742
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 49 additions and 26 deletions

View File

@ -126,9 +126,10 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
Wait: b.config.RackconnectWait, Wait: b.config.RackconnectWait,
}, },
&StepAllocateIp{ &StepAllocateIp{
FloatingIPNetwork: b.config.FloatingIPNetwork, FloatingIPNetwork: b.config.FloatingIPNetwork,
FloatingIP: b.config.FloatingIP, FloatingIP: b.config.FloatingIP,
ReuseIPs: b.config.ReuseIPs, ReuseIPs: b.config.ReuseIPs,
InstanceFloatingIPNet: b.config.InstanceFloatingIPNet,
}, },
&communicator.StepConnect{ &communicator.StepConnect{
Config: &b.config.RunConfig.Comm, Config: &b.config.RunConfig.Comm,

View File

@ -2,6 +2,7 @@ package openstack
import ( import (
"fmt" "fmt"
"log"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/gophercloud/gophercloud" "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 // GetInstancePortID returns internal port of the instance that can be used for
// the association of a floating IP. // the association of a floating IP.
// It will return an ID of a first port if there are many. // 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() interfacesPage, err := attachinterfaces.List(client, id).AllPages()
if err != nil { if err != nil {
return "", err return "", err
@ -79,7 +83,16 @@ func GetInstancePortID(client *gophercloud.ServiceClient, id string) (string, er
return "", fmt.Errorf("instance '%s' has no interfaces", id) 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 // CheckFloatingIPNetwork checks provided network reference and returns a valid

View File

@ -17,23 +17,24 @@ type RunConfig struct {
SSHInterface string `mapstructure:"ssh_interface"` SSHInterface string `mapstructure:"ssh_interface"`
SSHIPVersion string `mapstructure:"ssh_ip_version"` SSHIPVersion string `mapstructure:"ssh_ip_version"`
SourceImage string `mapstructure:"source_image"` SourceImage string `mapstructure:"source_image"`
SourceImageName string `mapstructure:"source_image_name"` SourceImageName string `mapstructure:"source_image_name"`
SourceImageFilters ImageFilter `mapstructure:"source_image_filter"` SourceImageFilters ImageFilter `mapstructure:"source_image_filter"`
Flavor string `mapstructure:"flavor"` Flavor string `mapstructure:"flavor"`
AvailabilityZone string `mapstructure:"availability_zone"` AvailabilityZone string `mapstructure:"availability_zone"`
RackconnectWait bool `mapstructure:"rackconnect_wait"` RackconnectWait bool `mapstructure:"rackconnect_wait"`
FloatingIPNetwork string `mapstructure:"floating_ip_network"` FloatingIPNetwork string `mapstructure:"floating_ip_network"`
FloatingIP string `mapstructure:"floating_ip"` FloatingIP string `mapstructure:"floating_ip"`
ReuseIPs bool `mapstructure:"reuse_ips"` ReuseIPs bool `mapstructure:"reuse_ips"`
SecurityGroups []string `mapstructure:"security_groups"` SecurityGroups []string `mapstructure:"security_groups"`
Networks []string `mapstructure:"networks"` Networks []string `mapstructure:"networks"`
Ports []string `mapstructure:"ports"` InstanceFloatingIPNet string `mapstructure:"instance_floating_ip_net"`
UserData string `mapstructure:"user_data"` Ports []string `mapstructure:"ports"`
UserDataFile string `mapstructure:"user_data_file"` UserData string `mapstructure:"user_data"`
InstanceName string `mapstructure:"instance_name"` UserDataFile string `mapstructure:"user_data_file"`
InstanceMetadata map[string]string `mapstructure:"instance_metadata"` InstanceName string `mapstructure:"instance_name"`
ForceDelete bool `mapstructure:"force_delete"` InstanceMetadata map[string]string `mapstructure:"instance_metadata"`
ForceDelete bool `mapstructure:"force_delete"`
ConfigDrive bool `mapstructure:"config_drive"` ConfigDrive bool `mapstructure:"config_drive"`

View File

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

View File

@ -155,6 +155,13 @@ builder.
- `insecure` (boolean) - Whether or not the connection to OpenStack can be - `insecure` (boolean) - Whether or not the connection to OpenStack can be
done over an insecure connection. By default this is false. done over an insecure connection. By default this is false.
- `instance_floating_ip_net` (string) - The ID of the network to which the
instance is attached and which should be used to associate with the floating
IP. This provides control over the floating ip association on multi-homed
instances. The association otherwise depends on a first-returned-interface
policy which could fail if the network to which it is connected is
unreachable from the floating IP network.
- `key` (string) - Client private key file path for SSL client - `key` (string) - Client private key file path for SSL client
authentication. If omitted the `OS_KEY` environment variable can be used. authentication. If omitted the `OS_KEY` environment variable can be used.