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

Commit

Permalink
Merge pull request #475 from feiskyer/neutronports
Browse files Browse the repository at this point in the history
[rfr] Allow to specify hostid when creating/updating a port
  • Loading branch information
Jamie Hannaford committed May 13, 2016
2 parents 74d0736 + 0765099 commit adc2065
Show file tree
Hide file tree
Showing 9 changed files with 767 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package portsbinding
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
// +build acceptance networking portsbinding

package portsbinding

import (
"testing"

base "github.com/rackspace/gophercloud/acceptance/openstack/networking/v2"
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/portsbinding"
"github.com/rackspace/gophercloud/openstack/networking/v2/networks"
"github.com/rackspace/gophercloud/openstack/networking/v2/ports"
"github.com/rackspace/gophercloud/openstack/networking/v2/subnets"
"github.com/rackspace/gophercloud/pagination"
th "github.com/rackspace/gophercloud/testhelper"
)

func TestPortBinding(t *testing.T) {
base.Setup(t)
defer base.Teardown()

// Setup network
t.Log("Setting up network")
networkID, err := createNetwork()
th.AssertNoErr(t, err)
defer networks.Delete(base.Client, networkID)

// Setup subnet
t.Logf("Setting up subnet on network %s", networkID)
subnetID, err := createSubnet(networkID)
th.AssertNoErr(t, err)
defer subnets.Delete(base.Client, subnetID)

// Create port
t.Logf("Create port based on subnet %s", subnetID)
hostID := "localhost"
portID := createPort(t, networkID, subnetID, hostID)

// Get port
if portID == "" {
t.Fatalf("In order to retrieve a port, the portID must be set")
}
p, err := portsbinding.Get(base.Client, portID).Extract()
th.AssertNoErr(t, err)
th.AssertEquals(t, p.ID, portID)
th.AssertEquals(t, p.HostID, hostID)

// Update port
newHostID := "openstack"
updateOpts := portsbinding.UpdateOpts{
HostID: newHostID,
}
p, err = portsbinding.Update(base.Client, portID, updateOpts).Extract()

th.AssertNoErr(t, err)
th.AssertEquals(t, p.HostID, newHostID)

// List ports
t.Logf("Listing all ports")
listPorts(t)

// Delete port
res := ports.Delete(base.Client, portID)
th.AssertNoErr(t, res.Err)
}

func listPorts(t *testing.T) {
count := 0
pager := ports.List(base.Client, ports.ListOpts{})
err := pager.EachPage(func(page pagination.Page) (bool, error) {
count++
t.Logf("--- Page ---")

portList, err := portsbinding.ExtractPorts(page)
th.AssertNoErr(t, err)

for _, p := range portList {
t.Logf("Port: ID [%s] Name [%s] HostID [%s] VNICType [%s] VIFType [%s]",
p.ID, p.Name, p.HostID, p.VNICType, p.VIFType)
}

return true, nil
})

th.CheckNoErr(t, err)

if count == 0 {
t.Logf("No pages were iterated over when listing ports")
}
}

func createPort(t *testing.T, networkID, subnetID, hostID string) string {
enable := false
opts := portsbinding.CreateOpts{
CreateOptsBuilder: ports.CreateOpts{
NetworkID: networkID,
Name: "my_port",
AdminStateUp: &enable,
FixedIPs: []ports.IP{{SubnetID: subnetID}},
},
HostID: hostID,
}

p, err := portsbinding.Create(base.Client, opts).Extract()
th.AssertNoErr(t, err)
th.AssertEquals(t, p.NetworkID, networkID)
th.AssertEquals(t, p.Name, "my_port")
th.AssertEquals(t, p.AdminStateUp, false)

return p.ID
}

func createNetwork() (string, error) {
res, err := networks.Create(base.Client, networks.CreateOpts{Name: "tmp_network", AdminStateUp: networks.Up}).Extract()
return res.ID, err
}

func createSubnet(networkID string) (string, error) {
s, err := subnets.Create(base.Client, subnets.CreateOpts{
NetworkID: networkID,
CIDR: "192.168.199.0/24",
IPVersion: subnets.IPv4,
Name: "my_subnet",
EnableDHCP: subnets.Down,
AllocationPools: []subnets.AllocationPool{
{Start: "192.168.199.2", End: "192.168.199.200"},
},
}).Extract()
return s.ID, err
}
3 changes: 3 additions & 0 deletions openstack/networking/v2/extensions/portsbinding/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Package portsbinding provides information and interaction with the port
// binding extension for the OpenStack Networking service.
package portsbinding
206 changes: 206 additions & 0 deletions openstack/networking/v2/extensions/portsbinding/fixtures.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
package portsbinding

import (
"fmt"
"net/http"
"testing"

fake "github.com/rackspace/gophercloud/openstack/networking/v2/common"
th "github.com/rackspace/gophercloud/testhelper"
)

func HandleListSuccessfully(t *testing.T) {
th.Mux.HandleFunc("/v2.0/ports", func(w http.ResponseWriter, r *http.Request) {
th.TestMethod(t, r, "GET")
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)

w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)

fmt.Fprintf(w, `
{
"ports": [
{
"status": "ACTIVE",
"binding:host_id": "devstack",
"name": "",
"admin_state_up": true,
"network_id": "70c1db1f-b701-45bd-96e0-a313ee3430b3",
"tenant_id": "",
"device_owner": "network:router_gateway",
"mac_address": "fa:16:3e:58:42:ed",
"fixed_ips": [
{
"subnet_id": "008ba151-0b8c-4a67-98b5-0d2b87666062",
"ip_address": "172.24.4.2"
}
],
"id": "d80b1a3b-4fc1-49f3-952e-1e2ab7081d8b",
"security_groups": [],
"device_id": "9ae135f4-b6e0-4dad-9e91-3c223e385824",
"binding:vnic_type": "normal"
}
]
}
`)
})
}

func HandleGet(t *testing.T) {
th.Mux.HandleFunc("/v2.0/ports/46d4bfb9-b26e-41f3-bd2e-e6dcc1ccedb2", func(w http.ResponseWriter, r *http.Request) {
th.TestMethod(t, r, "GET")
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)

w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)

fmt.Fprintf(w, `
{
"port": {
"status": "ACTIVE",
"binding:host_id": "devstack",
"name": "",
"allowed_address_pairs": [],
"admin_state_up": true,
"network_id": "a87cc70a-3e15-4acf-8205-9b711a3531b7",
"tenant_id": "7e02058126cc4950b75f9970368ba177",
"extra_dhcp_opts": [],
"binding:vif_details": {
"port_filter": true,
"ovs_hybrid_plug": true
},
"binding:vif_type": "ovs",
"device_owner": "network:router_interface",
"port_security_enabled": false,
"mac_address": "fa:16:3e:23:fd:d7",
"binding:profile": {},
"binding:vnic_type": "normal",
"fixed_ips": [
{
"subnet_id": "a0304c3a-4f08-4c43-88af-d796509c97d2",
"ip_address": "10.0.0.1"
}
],
"id": "46d4bfb9-b26e-41f3-bd2e-e6dcc1ccedb2",
"security_groups": [],
"device_id": "5e3898d7-11be-483e-9732-b2f5eccd2b2e"
}
}
`)
})
}

func HandleCreate(t *testing.T) {
th.Mux.HandleFunc("/v2.0/ports", func(w http.ResponseWriter, r *http.Request) {
th.TestMethod(t, r, "POST")
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
th.TestHeader(t, r, "Content-Type", "application/json")
th.TestHeader(t, r, "Accept", "application/json")
th.TestJSONRequest(t, r, `
{
"port": {
"network_id": "a87cc70a-3e15-4acf-8205-9b711a3531b7",
"name": "private-port",
"admin_state_up": true,
"fixed_ips": [
{
"subnet_id": "a0304c3a-4f08-4c43-88af-d796509c97d2",
"ip_address": "10.0.0.2"
}
],
"security_groups": ["foo"],
"binding:host_id": "HOST1",
"binding:vnic_type": "normal"
}
}
`)

w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)

fmt.Fprintf(w, `
{
"port": {
"status": "DOWN",
"name": "private-port",
"allowed_address_pairs": [],
"admin_state_up": true,
"network_id": "a87cc70a-3e15-4acf-8205-9b711a3531b7",
"tenant_id": "d6700c0c9ffa4f1cb322cd4a1f3906fa",
"device_owner": "",
"mac_address": "fa:16:3e:c9:cb:f0",
"fixed_ips": [
{
"subnet_id": "a0304c3a-4f08-4c43-88af-d796509c97d2",
"ip_address": "10.0.0.2"
}
],
"binding:host_id": "HOST1",
"binding:vnic_type": "normal",
"id": "65c0ee9f-d634-4522-8954-51021b570b0d",
"security_groups": [
"f0ac4394-7e4a-4409-9701-ba8be283dbc3"
],
"device_id": ""
}
}
`)
})
}

func HandleUpdate(t *testing.T) {
th.Mux.HandleFunc("/v2.0/ports/65c0ee9f-d634-4522-8954-51021b570b0d", func(w http.ResponseWriter, r *http.Request) {
th.TestMethod(t, r, "PUT")
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
th.TestHeader(t, r, "Content-Type", "application/json")
th.TestHeader(t, r, "Accept", "application/json")
th.TestJSONRequest(t, r, `
{
"port": {
"name": "new_port_name",
"fixed_ips": [
{
"subnet_id": "a0304c3a-4f08-4c43-88af-d796509c97d2",
"ip_address": "10.0.0.3"
}
],
"security_groups": [
"f0ac4394-7e4a-4409-9701-ba8be283dbc3"
],
"binding:host_id": "HOST1",
"binding:vnic_type": "normal"
}
}
`)

w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)

fmt.Fprintf(w, `
{
"port": {
"status": "DOWN",
"name": "new_port_name",
"admin_state_up": true,
"network_id": "a87cc70a-3e15-4acf-8205-9b711a3531b7",
"tenant_id": "d6700c0c9ffa4f1cb322cd4a1f3906fa",
"device_owner": "",
"mac_address": "fa:16:3e:c9:cb:f0",
"fixed_ips": [
{
"subnet_id": "a0304c3a-4f08-4c43-88af-d796509c97d2",
"ip_address": "10.0.0.3"
}
],
"id": "65c0ee9f-d634-4522-8954-51021b570b0d",
"security_groups": [
"f0ac4394-7e4a-4409-9701-ba8be283dbc3"
],
"device_id": "",
"binding:host_id": "HOST1",
"binding:vnic_type": "normal"
}
}
`)
})
}
Loading

0 comments on commit adc2065

Please sign in to comment.