Skip to content
This repository has been archived by the owner on Sep 26, 2021. It is now read-only.

OpenStack driver: define multiple networks and select floating point network #4756

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ before_script:
expire_in: 1 week
tags:
- docker
- privileged

.build_validate: &build_validate
<<: *build_base
Expand Down
33 changes: 19 additions & 14 deletions drivers/openstack/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"
"io/ioutil"
"net/http"
"strings"
"time"

"github.com/docker/machine/libmachine/log"
Expand Down Expand Up @@ -43,12 +44,11 @@ type Client interface {
GetPublicKey(keyPairName string) ([]byte, error)
CreateKeyPair(d *Driver, name string, publicKey string) error
DeleteKeyPair(d *Driver, name string) error
GetNetworkID(d *Driver) (string, error)
GetNetworkIDs(networkNames []string) (string, error)
GetFlavorID(d *Driver) (string, error)
GetImageID(d *Driver) (string, error)
AssignFloatingIP(d *Driver, floatingIP *FloatingIP) error
GetFloatingIPs(d *Driver) ([]FloatingIP, error)
GetFloatingIPPoolID(d *Driver) (string, error)
GetInstancePortID(d *Driver) (string, error)
GetTenantID(d *Driver) (string, error)
}
Expand All @@ -72,11 +72,12 @@ func (c *GenericClient) CreateInstance(d *Driver) (string, error) {
Metadata: d.GetMetadata(),
}
if d.NetworkId != "" {
serverOpts.Networks = []servers.Network{
{
UUID: d.NetworkId,
},
networkIDs := strings.Split(d.NetworkId, ",")
networks := make([]servers.Network, len(networkIDs))
for i, id := range networkIDs {
networks[i] = servers.Network{UUID: id}
}
serverOpts.Networks = networks
}

log.Info("Creating machine...")
Expand Down Expand Up @@ -204,15 +205,19 @@ func (c *GenericClient) GetInstanceIPAddresses(d *Driver) ([]IPAddress, error) {
return addresses, nil
}

func (c *GenericClient) GetNetworkID(d *Driver) (string, error) {
return c.getNetworkID(d, d.NetworkName)
}

func (c *GenericClient) GetFloatingIPPoolID(d *Driver) (string, error) {
return c.getNetworkID(d, d.FloatingIpPool)
func (c *GenericClient) GetNetworkIDs(networkNames []string) (string, error) {
ips := []string{}
for _, name := range networkNames {
id, err := c.getNetworkID(name)
if err != nil {
return "", err
}
ips = append(ips, id)
}
return strings.Join(ips, ","), nil
}

func (c *GenericClient) getNetworkID(d *Driver, networkName string) (string, error) {
func (c *GenericClient) getNetworkID(networkName string) (string, error) {
opts := networks.ListOpts{Name: networkName}
pager := networks.List(c.Network, opts)
networkID := ""
Expand Down Expand Up @@ -454,7 +459,7 @@ func (c *GenericClient) getNeutronNetworkFloatingIPs(d *Driver) ([]FloatingIP, e
func (c *GenericClient) GetInstancePortID(d *Driver) (string, error) {
pager := ports.List(c.Network, ports.ListOpts{
DeviceID: d.MachineId,
NetworkID: d.NetworkId,
NetworkID: d.FloatingIpNetworkId,
})

var portID string
Expand Down
77 changes: 60 additions & 17 deletions drivers/openstack/openstack.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ type Driver struct {
client Client
// ExistingKey keeps track of whether the key was created by us or we used an existing one. If an existing one was used, we shouldn't delete it when the machine is deleted.
ExistingKey bool
// To get right port id, if multiple networks are configured and first one is not the one for floating ip.
FloatingIpNetworkName string
FloatingIpNetworkId string
}

const (
Expand Down Expand Up @@ -164,11 +167,11 @@ func (d *Driver) GetCreateFlags() []mcnflag.Flag {
Usage: "OpenStack keypair to use to SSH to the instance",
Value: "",
},
mcnflag.StringFlag{
mcnflag.StringSliceFlag{
EnvVar: "OS_NETWORK_ID",
Name: "openstack-net-id",
Usage: "OpenStack network id the machine will be connected on",
Value: "",
Value: []string{},
},
mcnflag.StringFlag{
EnvVar: "OS_PRIVATE_KEY_FILE",
Expand All @@ -182,11 +185,11 @@ func (d *Driver) GetCreateFlags() []mcnflag.Flag {
Usage: "File containing an openstack userdata script",
Value: "",
},
mcnflag.StringFlag{
mcnflag.StringSliceFlag{
EnvVar: "OS_NETWORK_NAME",
Name: "openstack-net-name",
Usage: "OpenStack network name the machine will be connected on",
Value: "",
Value: []string{},
},
mcnflag.StringFlag{
EnvVar: "OS_SECURITY_GROUPS",
Expand All @@ -202,7 +205,19 @@ func (d *Driver) GetCreateFlags() []mcnflag.Flag {
mcnflag.StringFlag{
EnvVar: "OS_FLOATINGIP_POOL",
Name: "openstack-floatingip-pool",
Usage: "OpenStack floating IP pool to get an IP from to assign to the instance",
Usage: "OpenStack floating IP pool to get an IP from to assign to the instance.",
Value: "",
},
mcnflag.StringFlag{
EnvVar: "OS_FLOATINGIP_NETWORK_NAME",
Name: "openstack-floatingip-net-name",
Usage: "OpenStack floating IP target network name to get right port for assingin IP.",
Value: "",
},
mcnflag.StringFlag{
EnvVar: "OS_FLOATINGIP_NETWORK_ID",
Name: "openstack-floatingip-net-id",
Usage: "OpenStack floating IP target network id to get right port for assingin IP.",
Value: "",
},
mcnflag.IntFlag{
Expand Down Expand Up @@ -291,13 +306,15 @@ func (d *Driver) SetConfigFromFlags(flags drivers.DriverOptions) error {
d.FlavorName = flags.String("openstack-flavor-name")
d.ImageId = flags.String("openstack-image-id")
d.ImageName = flags.String("openstack-image-name")
d.NetworkId = flags.String("openstack-net-id")
d.NetworkName = flags.String("openstack-net-name")
d.NetworkId = strings.Join(flags.StringSlice("openstack-net-id"), ",")
d.NetworkName = strings.Join(flags.StringSlice("openstack-net-name"), ",")
d.metadata = flags.String("openstack-metadata")
if flags.String("openstack-sec-groups") != "" {
d.SecurityGroups = strings.Split(flags.String("openstack-sec-groups"), ",")
}
d.FloatingIpPool = flags.String("openstack-floatingip-pool")
d.FloatingIpNetworkName = flags.String("openstack-floatingip-net-name")
d.FloatingIpNetworkId = flags.String("openstack-floatingip-net-id")
d.IpVersion = flags.Int("openstack-ip-version")
d.ComputeNetwork = flags.Bool("openstack-nova-network")
d.SSHUser = flags.String("openstack-ssh-user")
Expand Down Expand Up @@ -553,14 +570,17 @@ func (d *Driver) checkConfig() error {
}

if d.NetworkName != "" && d.NetworkId != "" {
return fmt.Errorf(errorExclusiveOptions, "Network name", "Network id")
return fmt.Errorf(errorExclusiveOptions, "Network names", "Network ids")
}
if d.EndpointType != "" && (d.EndpointType != "publicURL" && d.EndpointType != "adminURL" && d.EndpointType != "internalURL") {
return fmt.Errorf(errorWrongEndpointType)
}
if (d.KeyPairName != "" && d.PrivateKeyFile == "") || (d.KeyPairName == "" && d.PrivateKeyFile != "") {
return fmt.Errorf(errorBothOptions, "KeyPairName", "PrivateKeyFile")
}
if d.FloatingIpNetworkName != "" && d.FloatingIpNetworkId != "" {
return fmt.Errorf(errorBothOptions, "FloatingIpNetworkName", "FloatingIpNetworkId")
}
return nil
}

Expand All @@ -570,20 +590,20 @@ func (d *Driver) resolveIds() error {
return err
}

networkID, err := d.client.GetNetworkID(d)
networkIDs, err := d.client.GetNetworkIDs(strings.Split(d.NetworkName, ","))

if err != nil {
return err
}

if networkID == "" {
if networkIDs == "" {
return fmt.Errorf(errorUnknownNetworkName, d.NetworkName)
}

d.NetworkId = networkID
log.Debug("Found network id using its name", map[string]string{
"Name": d.NetworkName,
"ID": d.NetworkId,
d.NetworkId = networkIDs
log.Debug("Found networks using their name", map[string]string{
"Names": d.NetworkName,
"IDs": d.NetworkId,
})
}

Expand Down Expand Up @@ -633,23 +653,46 @@ func (d *Driver) resolveIds() error {
if err := d.initNetwork(); err != nil {
return err
}
f, err := d.client.GetFloatingIPPoolID(d)

networkID, err := d.client.GetNetworkIDs([]string{d.FloatingIpPool})

if err != nil {
return err
}

if f == "" {
if networkID == "" {
return fmt.Errorf(errorUnknownNetworkName, d.FloatingIpPool)
}

d.FloatingIpPoolId = f
d.FloatingIpPoolId = networkID
log.Debug("Found floating IP pool id using its name", map[string]string{
"Name": d.FloatingIpPool,
"ID": d.FloatingIpPoolId,
})
}

if d.FloatingIpNetworkId == "" && !d.ComputeNetwork {
d.FloatingIpNetworkId = strings.Split(d.NetworkId, ",")[0]
log.Debug("Using first network as floating ip network")
} else if d.FloatingIpNetworkName != "" && !d.ComputeNetwork {
if err := d.initNetwork(); err != nil {
return err
}

networkID, err := d.client.GetNetworkIDs([]string{d.FloatingIpNetworkName})

if err != nil {
return err
}

d.FloatingIpNetworkId = networkID

log.Debug("Found floating network for floating ip using its name", map[string]string{
"Name": d.FloatingIpNetworkName,
"ID": d.FloatingIpNetworkId,
})
}

if d.TenantName != "" && d.TenantId == "" {
if err := d.initIdentity(); err != nil {
return err
Expand Down
90 changes: 90 additions & 0 deletions drivers/openstack/openstack_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,93 @@ func TestSetConfigFromFlags(t *testing.T) {
assert.NoError(t, err)
assert.Empty(t, checkFlags.InvalidFlags)
}

func TestSetSingleNetworkId(t *testing.T) {
driver := NewDriver("default", "path")

checkFlags := &drivers.CheckDriverOptions{
FlagsValues: map[string]interface{}{
"openstack-auth-url": "http://url",
"openstack-username": "user",
"openstack-password": "pwd",
"openstack-tenant-id": "ID",
"openstack-flavor-id": "ID",
"openstack-image-id": "ID",
"openstack-net-id": "ID",
},
CreateFlags: driver.GetCreateFlags(),
}

err := driver.SetConfigFromFlags(checkFlags)

assert.NoError(t, err)
assert.Empty(t, checkFlags.InvalidFlags)
}

func TestSetSingleNetworkName(t *testing.T) {
driver := NewDriver("default", "path")

checkFlags := &drivers.CheckDriverOptions{
FlagsValues: map[string]interface{}{
"openstack-auth-url": "http://url",
"openstack-username": "user",
"openstack-password": "pwd",
"openstack-tenant-id": "ID",
"openstack-flavor-id": "ID",
"openstack-image-id": "ID",
"openstack-net-name": "ID",
},
CreateFlags: driver.GetCreateFlags(),
}

err := driver.SetConfigFromFlags(checkFlags)

assert.NoError(t, err)
assert.Empty(t, checkFlags.InvalidFlags)
}

func TestSetMultipleNetworkIds(t *testing.T) {
driver := NewDriver("default", "path")

checkFlags := &drivers.CheckDriverOptions{
FlagsValues: map[string]interface{}{
"openstack-auth-url": "http://url",
"openstack-username": "user",
"openstack-password": "pwd",
"openstack-tenant-id": "ID",
"openstack-flavor-id": "ID",
"openstack-image-id": "ID",
"openstack-net-id": []string{"ID", "ID2"},
"openstack-floatingip-net-id": "ID2",
},
CreateFlags: driver.GetCreateFlags(),
}

err := driver.SetConfigFromFlags(checkFlags)

assert.NoError(t, err)
assert.Empty(t, checkFlags.InvalidFlags)
}

func TestSetMultipleNetworkNames(t *testing.T) {
driver := NewDriver("default", "path")

checkFlags := &drivers.CheckDriverOptions{
FlagsValues: map[string]interface{}{
"openstack-auth-url": "http://url",
"openstack-username": "user",
"openstack-password": "pwd",
"openstack-tenant-id": "ID",
"openstack-flavor-id": "ID",
"openstack-image-id": "ID",
"openstack-net-name": []string{"ID", "ID2"},
"openstack-floatingip-net-name": "ID2",
},
CreateFlags: driver.GetCreateFlags(),
}

err := driver.SetConfigFromFlags(checkFlags)

assert.NoError(t, err)
assert.Empty(t, checkFlags.InvalidFlags)
}