Skip to content
This repository was archived by the owner on Aug 1, 2023. It is now read-only.

Commit adc2065

Browse files
author
Jamie Hannaford
committed
Merge pull request #475 from feiskyer/neutronports
[rfr] Allow to specify hostid when creating/updating a port
2 parents 74d0736 + 0765099 commit adc2065

File tree

9 files changed

+767
-0
lines changed

9 files changed

+767
-0
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package portsbinding
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
// +build acceptance networking portsbinding
2+
3+
package portsbinding
4+
5+
import (
6+
"testing"
7+
8+
base "github.com/rackspace/gophercloud/acceptance/openstack/networking/v2"
9+
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/portsbinding"
10+
"github.com/rackspace/gophercloud/openstack/networking/v2/networks"
11+
"github.com/rackspace/gophercloud/openstack/networking/v2/ports"
12+
"github.com/rackspace/gophercloud/openstack/networking/v2/subnets"
13+
"github.com/rackspace/gophercloud/pagination"
14+
th "github.com/rackspace/gophercloud/testhelper"
15+
)
16+
17+
func TestPortBinding(t *testing.T) {
18+
base.Setup(t)
19+
defer base.Teardown()
20+
21+
// Setup network
22+
t.Log("Setting up network")
23+
networkID, err := createNetwork()
24+
th.AssertNoErr(t, err)
25+
defer networks.Delete(base.Client, networkID)
26+
27+
// Setup subnet
28+
t.Logf("Setting up subnet on network %s", networkID)
29+
subnetID, err := createSubnet(networkID)
30+
th.AssertNoErr(t, err)
31+
defer subnets.Delete(base.Client, subnetID)
32+
33+
// Create port
34+
t.Logf("Create port based on subnet %s", subnetID)
35+
hostID := "localhost"
36+
portID := createPort(t, networkID, subnetID, hostID)
37+
38+
// Get port
39+
if portID == "" {
40+
t.Fatalf("In order to retrieve a port, the portID must be set")
41+
}
42+
p, err := portsbinding.Get(base.Client, portID).Extract()
43+
th.AssertNoErr(t, err)
44+
th.AssertEquals(t, p.ID, portID)
45+
th.AssertEquals(t, p.HostID, hostID)
46+
47+
// Update port
48+
newHostID := "openstack"
49+
updateOpts := portsbinding.UpdateOpts{
50+
HostID: newHostID,
51+
}
52+
p, err = portsbinding.Update(base.Client, portID, updateOpts).Extract()
53+
54+
th.AssertNoErr(t, err)
55+
th.AssertEquals(t, p.HostID, newHostID)
56+
57+
// List ports
58+
t.Logf("Listing all ports")
59+
listPorts(t)
60+
61+
// Delete port
62+
res := ports.Delete(base.Client, portID)
63+
th.AssertNoErr(t, res.Err)
64+
}
65+
66+
func listPorts(t *testing.T) {
67+
count := 0
68+
pager := ports.List(base.Client, ports.ListOpts{})
69+
err := pager.EachPage(func(page pagination.Page) (bool, error) {
70+
count++
71+
t.Logf("--- Page ---")
72+
73+
portList, err := portsbinding.ExtractPorts(page)
74+
th.AssertNoErr(t, err)
75+
76+
for _, p := range portList {
77+
t.Logf("Port: ID [%s] Name [%s] HostID [%s] VNICType [%s] VIFType [%s]",
78+
p.ID, p.Name, p.HostID, p.VNICType, p.VIFType)
79+
}
80+
81+
return true, nil
82+
})
83+
84+
th.CheckNoErr(t, err)
85+
86+
if count == 0 {
87+
t.Logf("No pages were iterated over when listing ports")
88+
}
89+
}
90+
91+
func createPort(t *testing.T, networkID, subnetID, hostID string) string {
92+
enable := false
93+
opts := portsbinding.CreateOpts{
94+
CreateOptsBuilder: ports.CreateOpts{
95+
NetworkID: networkID,
96+
Name: "my_port",
97+
AdminStateUp: &enable,
98+
FixedIPs: []ports.IP{{SubnetID: subnetID}},
99+
},
100+
HostID: hostID,
101+
}
102+
103+
p, err := portsbinding.Create(base.Client, opts).Extract()
104+
th.AssertNoErr(t, err)
105+
th.AssertEquals(t, p.NetworkID, networkID)
106+
th.AssertEquals(t, p.Name, "my_port")
107+
th.AssertEquals(t, p.AdminStateUp, false)
108+
109+
return p.ID
110+
}
111+
112+
func createNetwork() (string, error) {
113+
res, err := networks.Create(base.Client, networks.CreateOpts{Name: "tmp_network", AdminStateUp: networks.Up}).Extract()
114+
return res.ID, err
115+
}
116+
117+
func createSubnet(networkID string) (string, error) {
118+
s, err := subnets.Create(base.Client, subnets.CreateOpts{
119+
NetworkID: networkID,
120+
CIDR: "192.168.199.0/24",
121+
IPVersion: subnets.IPv4,
122+
Name: "my_subnet",
123+
EnableDHCP: subnets.Down,
124+
AllocationPools: []subnets.AllocationPool{
125+
{Start: "192.168.199.2", End: "192.168.199.200"},
126+
},
127+
}).Extract()
128+
return s.ID, err
129+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// Package portsbinding provides information and interaction with the port
2+
// binding extension for the OpenStack Networking service.
3+
package portsbinding
Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
package portsbinding
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
"testing"
7+
8+
fake "github.com/rackspace/gophercloud/openstack/networking/v2/common"
9+
th "github.com/rackspace/gophercloud/testhelper"
10+
)
11+
12+
func HandleListSuccessfully(t *testing.T) {
13+
th.Mux.HandleFunc("/v2.0/ports", func(w http.ResponseWriter, r *http.Request) {
14+
th.TestMethod(t, r, "GET")
15+
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
16+
17+
w.Header().Add("Content-Type", "application/json")
18+
w.WriteHeader(http.StatusOK)
19+
20+
fmt.Fprintf(w, `
21+
{
22+
"ports": [
23+
{
24+
"status": "ACTIVE",
25+
"binding:host_id": "devstack",
26+
"name": "",
27+
"admin_state_up": true,
28+
"network_id": "70c1db1f-b701-45bd-96e0-a313ee3430b3",
29+
"tenant_id": "",
30+
"device_owner": "network:router_gateway",
31+
"mac_address": "fa:16:3e:58:42:ed",
32+
"fixed_ips": [
33+
{
34+
"subnet_id": "008ba151-0b8c-4a67-98b5-0d2b87666062",
35+
"ip_address": "172.24.4.2"
36+
}
37+
],
38+
"id": "d80b1a3b-4fc1-49f3-952e-1e2ab7081d8b",
39+
"security_groups": [],
40+
"device_id": "9ae135f4-b6e0-4dad-9e91-3c223e385824",
41+
"binding:vnic_type": "normal"
42+
}
43+
]
44+
}
45+
`)
46+
})
47+
}
48+
49+
func HandleGet(t *testing.T) {
50+
th.Mux.HandleFunc("/v2.0/ports/46d4bfb9-b26e-41f3-bd2e-e6dcc1ccedb2", func(w http.ResponseWriter, r *http.Request) {
51+
th.TestMethod(t, r, "GET")
52+
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
53+
54+
w.Header().Add("Content-Type", "application/json")
55+
w.WriteHeader(http.StatusOK)
56+
57+
fmt.Fprintf(w, `
58+
{
59+
"port": {
60+
"status": "ACTIVE",
61+
"binding:host_id": "devstack",
62+
"name": "",
63+
"allowed_address_pairs": [],
64+
"admin_state_up": true,
65+
"network_id": "a87cc70a-3e15-4acf-8205-9b711a3531b7",
66+
"tenant_id": "7e02058126cc4950b75f9970368ba177",
67+
"extra_dhcp_opts": [],
68+
"binding:vif_details": {
69+
"port_filter": true,
70+
"ovs_hybrid_plug": true
71+
},
72+
"binding:vif_type": "ovs",
73+
"device_owner": "network:router_interface",
74+
"port_security_enabled": false,
75+
"mac_address": "fa:16:3e:23:fd:d7",
76+
"binding:profile": {},
77+
"binding:vnic_type": "normal",
78+
"fixed_ips": [
79+
{
80+
"subnet_id": "a0304c3a-4f08-4c43-88af-d796509c97d2",
81+
"ip_address": "10.0.0.1"
82+
}
83+
],
84+
"id": "46d4bfb9-b26e-41f3-bd2e-e6dcc1ccedb2",
85+
"security_groups": [],
86+
"device_id": "5e3898d7-11be-483e-9732-b2f5eccd2b2e"
87+
}
88+
}
89+
`)
90+
})
91+
}
92+
93+
func HandleCreate(t *testing.T) {
94+
th.Mux.HandleFunc("/v2.0/ports", func(w http.ResponseWriter, r *http.Request) {
95+
th.TestMethod(t, r, "POST")
96+
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
97+
th.TestHeader(t, r, "Content-Type", "application/json")
98+
th.TestHeader(t, r, "Accept", "application/json")
99+
th.TestJSONRequest(t, r, `
100+
{
101+
"port": {
102+
"network_id": "a87cc70a-3e15-4acf-8205-9b711a3531b7",
103+
"name": "private-port",
104+
"admin_state_up": true,
105+
"fixed_ips": [
106+
{
107+
"subnet_id": "a0304c3a-4f08-4c43-88af-d796509c97d2",
108+
"ip_address": "10.0.0.2"
109+
}
110+
],
111+
"security_groups": ["foo"],
112+
"binding:host_id": "HOST1",
113+
"binding:vnic_type": "normal"
114+
}
115+
}
116+
`)
117+
118+
w.Header().Add("Content-Type", "application/json")
119+
w.WriteHeader(http.StatusCreated)
120+
121+
fmt.Fprintf(w, `
122+
{
123+
"port": {
124+
"status": "DOWN",
125+
"name": "private-port",
126+
"allowed_address_pairs": [],
127+
"admin_state_up": true,
128+
"network_id": "a87cc70a-3e15-4acf-8205-9b711a3531b7",
129+
"tenant_id": "d6700c0c9ffa4f1cb322cd4a1f3906fa",
130+
"device_owner": "",
131+
"mac_address": "fa:16:3e:c9:cb:f0",
132+
"fixed_ips": [
133+
{
134+
"subnet_id": "a0304c3a-4f08-4c43-88af-d796509c97d2",
135+
"ip_address": "10.0.0.2"
136+
}
137+
],
138+
"binding:host_id": "HOST1",
139+
"binding:vnic_type": "normal",
140+
"id": "65c0ee9f-d634-4522-8954-51021b570b0d",
141+
"security_groups": [
142+
"f0ac4394-7e4a-4409-9701-ba8be283dbc3"
143+
],
144+
"device_id": ""
145+
}
146+
}
147+
`)
148+
})
149+
}
150+
151+
func HandleUpdate(t *testing.T) {
152+
th.Mux.HandleFunc("/v2.0/ports/65c0ee9f-d634-4522-8954-51021b570b0d", func(w http.ResponseWriter, r *http.Request) {
153+
th.TestMethod(t, r, "PUT")
154+
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
155+
th.TestHeader(t, r, "Content-Type", "application/json")
156+
th.TestHeader(t, r, "Accept", "application/json")
157+
th.TestJSONRequest(t, r, `
158+
{
159+
"port": {
160+
"name": "new_port_name",
161+
"fixed_ips": [
162+
{
163+
"subnet_id": "a0304c3a-4f08-4c43-88af-d796509c97d2",
164+
"ip_address": "10.0.0.3"
165+
}
166+
],
167+
"security_groups": [
168+
"f0ac4394-7e4a-4409-9701-ba8be283dbc3"
169+
],
170+
"binding:host_id": "HOST1",
171+
"binding:vnic_type": "normal"
172+
}
173+
}
174+
`)
175+
176+
w.Header().Add("Content-Type", "application/json")
177+
w.WriteHeader(http.StatusOK)
178+
179+
fmt.Fprintf(w, `
180+
{
181+
"port": {
182+
"status": "DOWN",
183+
"name": "new_port_name",
184+
"admin_state_up": true,
185+
"network_id": "a87cc70a-3e15-4acf-8205-9b711a3531b7",
186+
"tenant_id": "d6700c0c9ffa4f1cb322cd4a1f3906fa",
187+
"device_owner": "",
188+
"mac_address": "fa:16:3e:c9:cb:f0",
189+
"fixed_ips": [
190+
{
191+
"subnet_id": "a0304c3a-4f08-4c43-88af-d796509c97d2",
192+
"ip_address": "10.0.0.3"
193+
}
194+
],
195+
"id": "65c0ee9f-d634-4522-8954-51021b570b0d",
196+
"security_groups": [
197+
"f0ac4394-7e4a-4409-9701-ba8be283dbc3"
198+
],
199+
"device_id": "",
200+
"binding:host_id": "HOST1",
201+
"binding:vnic_type": "normal"
202+
}
203+
}
204+
`)
205+
})
206+
}

0 commit comments

Comments
 (0)