Merge pull request #488 from trumant/allowed_address_pairs
Allowed address pairs support for Neutron Port
diff --git a/acceptance/openstack/networking/v2/port_test.go b/acceptance/openstack/networking/v2/port_test.go
index 03e8e27..91bf5bd 100644
--- a/acceptance/openstack/networking/v2/port_test.go
+++ b/acceptance/openstack/networking/v2/port_test.go
@@ -45,10 +45,20 @@
th.AssertEquals(t, p.ID, portID)
// Update port
- p, err = ports.Update(Client, portID, ports.UpdateOpts{Name: "new_port_name"}).Extract()
+ updateOpts := ports.UpdateOpts{
+ Name: "new_port_name",
+ AllowedAddressPairs: []ports.AddressPair{
+ ports.AddressPair{IPAddress: "192.168.199.201"},
+ },
+ }
+ p, err = ports.Update(Client, portID, updateOpts).Extract()
+
th.AssertNoErr(t, err)
th.AssertEquals(t, p.Name, "new_port_name")
+ updatedPort, err := ports.Get(Client, portID).Extract()
+ th.AssertEquals(t, updatedPort.AllowedAddressPairs[0].IPAddress, "192.168.199.201")
+
// Delete port
res := ports.Delete(Client, portID)
th.AssertNoErr(t, res.Err)
@@ -82,8 +92,8 @@
th.AssertNoErr(t, err)
for _, p := range portList {
- t.Logf("Port: ID [%s] Name [%s] Status [%s] MAC addr [%s] Fixed IPs [%#v] Security groups [%#v]",
- p.ID, p.Name, p.Status, p.MACAddress, p.FixedIPs, p.SecurityGroups)
+ t.Logf("Port: ID [%s] Name [%s] Status [%s] MAC addr [%s] Fixed IPs [%#v] Security groups [%#v] Allowed Address Pairs [%#v]",
+ p.ID, p.Name, p.Status, p.MACAddress, p.FixedIPs, p.SecurityGroups, p.AllowedAddressPairs)
}
return true, nil
@@ -108,6 +118,9 @@
IPVersion: subnets.IPv4,
Name: "my_subnet",
EnableDHCP: subnets.Down,
+ AllocationPools: []subnets.AllocationPool{
+ subnets.AllocationPool{Start: "192.168.199.2", End: "192.168.199.200"},
+ },
}).Extract()
return s.ID, err
}
diff --git a/openstack/networking/v2/ports/requests.go b/openstack/networking/v2/ports/requests.go
index 2caf1ca..e73e10a 100644
--- a/openstack/networking/v2/ports/requests.go
+++ b/openstack/networking/v2/ports/requests.go
@@ -95,15 +95,16 @@
// CreateOpts represents the attributes used when creating a new port.
type CreateOpts struct {
- NetworkID string
- Name string
- AdminStateUp *bool
- MACAddress string
- FixedIPs interface{}
- DeviceID string
- DeviceOwner string
- TenantID string
- SecurityGroups []string
+ NetworkID string
+ Name string
+ AdminStateUp *bool
+ MACAddress string
+ FixedIPs interface{}
+ DeviceID string
+ DeviceOwner string
+ TenantID string
+ SecurityGroups []string
+ AllowedAddressPairs []AddressPair
}
// ToPortCreateMap casts a CreateOpts struct to a map.
@@ -139,6 +140,9 @@
if opts.MACAddress != "" {
p["mac_address"] = opts.MACAddress
}
+ if opts.AllowedAddressPairs != nil {
+ p["allowed_address_pairs"] = opts.AllowedAddressPairs
+ }
return map[string]interface{}{"port": p}, nil
}
@@ -168,12 +172,13 @@
// UpdateOpts represents the attributes used when updating an existing port.
type UpdateOpts struct {
- Name string
- AdminStateUp *bool
- FixedIPs interface{}
- DeviceID string
- DeviceOwner string
- SecurityGroups []string
+ Name string
+ AdminStateUp *bool
+ FixedIPs interface{}
+ DeviceID string
+ DeviceOwner string
+ SecurityGroups []string
+ AllowedAddressPairs []AddressPair
}
// ToPortUpdateMap casts an UpdateOpts struct to a map.
@@ -198,6 +203,9 @@
if opts.Name != "" {
p["name"] = opts.Name
}
+ if opts.AllowedAddressPairs != nil {
+ p["allowed_address_pairs"] = opts.AllowedAddressPairs
+ }
return map[string]interface{}{"port": p}, nil
}
diff --git a/openstack/networking/v2/ports/requests_test.go b/openstack/networking/v2/ports/requests_test.go
index 9e323ef..b442996 100644
--- a/openstack/networking/v2/ports/requests_test.go
+++ b/openstack/networking/v2/ports/requests_test.go
@@ -164,7 +164,13 @@
"ip_address": "10.0.0.2"
}
],
- "security_groups": ["foo"]
+ "security_groups": ["foo"],
+ "allowed_address_pairs": [
+ {
+ "ip_address": "10.0.0.4",
+ "mac_address": "fa:16:3e:c9:cb:f0"
+ }
+ ]
}
}
`)
@@ -177,7 +183,6 @@
"port": {
"status": "DOWN",
"name": "private-port",
- "allowed_address_pairs": [],
"admin_state_up": true,
"network_id": "a87cc70a-3e15-4acf-8205-9b711a3531b7",
"tenant_id": "d6700c0c9ffa4f1cb322cd4a1f3906fa",
@@ -193,6 +198,12 @@
"security_groups": [
"f0ac4394-7e4a-4409-9701-ba8be283dbc3"
],
+ "allowed_address_pairs": [
+ {
+ "ip_address": "10.0.0.4",
+ "mac_address": "fa:16:3e:c9:cb:f0"
+ }
+ ],
"device_id": ""
}
}
@@ -208,6 +219,9 @@
IP{SubnetID: "a0304c3a-4f08-4c43-88af-d796509c97d2", IPAddress: "10.0.0.2"},
},
SecurityGroups: []string{"foo"},
+ AllowedAddressPairs: []AddressPair{
+ AddressPair{IPAddress: "10.0.0.4", MACAddress: "fa:16:3e:c9:cb:f0"},
+ },
}
n, err := Create(fake.ServiceClient(), options).Extract()
th.AssertNoErr(t, err)
@@ -224,6 +238,9 @@
})
th.AssertEquals(t, n.ID, "65c0ee9f-d634-4522-8954-51021b570b0d")
th.AssertDeepEquals(t, n.SecurityGroups, []string{"f0ac4394-7e4a-4409-9701-ba8be283dbc3"})
+ th.AssertDeepEquals(t, n.AllowedAddressPairs, []AddressPair{
+ AddressPair{IPAddress: "10.0.0.4", MACAddress: "fa:16:3e:c9:cb:f0"},
+ })
}
func TestRequiredCreateOpts(t *testing.T) {
@@ -252,6 +269,12 @@
"ip_address": "10.0.0.3"
}
],
+ "allowed_address_pairs": [
+ {
+ "ip_address": "10.0.0.4",
+ "mac_address": "fa:16:3e:c9:cb:f0"
+ }
+ ],
"security_groups": [
"f0ac4394-7e4a-4409-9701-ba8be283dbc3"
]
@@ -278,6 +301,12 @@
"ip_address": "10.0.0.3"
}
],
+ "allowed_address_pairs": [
+ {
+ "ip_address": "10.0.0.4",
+ "mac_address": "fa:16:3e:c9:cb:f0"
+ }
+ ],
"id": "65c0ee9f-d634-4522-8954-51021b570b0d",
"security_groups": [
"f0ac4394-7e4a-4409-9701-ba8be283dbc3"
@@ -294,6 +323,9 @@
IP{SubnetID: "a0304c3a-4f08-4c43-88af-d796509c97d2", IPAddress: "10.0.0.3"},
},
SecurityGroups: []string{"f0ac4394-7e4a-4409-9701-ba8be283dbc3"},
+ AllowedAddressPairs: []AddressPair{
+ AddressPair{IPAddress: "10.0.0.4", MACAddress: "fa:16:3e:c9:cb:f0"},
+ },
}
s, err := Update(fake.ServiceClient(), "65c0ee9f-d634-4522-8954-51021b570b0d", options).Extract()
@@ -303,6 +335,9 @@
th.AssertDeepEquals(t, s.FixedIPs, []IP{
IP{SubnetID: "a0304c3a-4f08-4c43-88af-d796509c97d2", IPAddress: "10.0.0.3"},
})
+ th.AssertDeepEquals(t, s.AllowedAddressPairs, []AddressPair{
+ AddressPair{IPAddress: "10.0.0.4", MACAddress: "fa:16:3e:c9:cb:f0"},
+ })
th.AssertDeepEquals(t, s.SecurityGroups, []string{"f0ac4394-7e4a-4409-9701-ba8be283dbc3"})
}
diff --git a/openstack/networking/v2/ports/results.go b/openstack/networking/v2/ports/results.go
index 2511ff5..1f7eea1 100644
--- a/openstack/networking/v2/ports/results.go
+++ b/openstack/networking/v2/ports/results.go
@@ -19,7 +19,6 @@
var res struct {
Port *Port `json:"port"`
}
-
err := mapstructure.Decode(r.Body, &res)
return res.Port, err
@@ -51,6 +50,11 @@
IPAddress string `mapstructure:"ip_address" json:"ip_address,omitempty"`
}
+type AddressPair struct {
+ IPAddress string `mapstructure:"ip_address" json:"ip_address,omitempty"`
+ MACAddress string `mapstructure:"mac_address" json:"mac_address,omitempty"`
+}
+
// Port represents a Neutron port. See package documentation for a top-level
// description of what this is.
type Port struct {
@@ -78,6 +82,8 @@
SecurityGroups []string `mapstructure:"security_groups" json:"security_groups"`
// Identifies the device (e.g., virtual server) using this port.
DeviceID string `mapstructure:"device_id" json:"device_id"`
+ // Identifies the list of IP addresses the port will recognize/accept
+ AllowedAddressPairs []AddressPair `mapstructure:"allowed_address_pairs" json:"allowed_address_pairs"`
}
// PortPage is the page returned by a pager when traversing over a collection