Add the ability to create, delete, list, and get networks, ports and subnets
Partially implements network-v2 Updated to use Session Change-Id: I9c57cbe524712313892868c0fb38eb6f6062d362
This commit is contained in:

committed by
Dean Troyer

parent
4141ca3ed3
commit
c42cbe79a0
252
examples/40-network-v2.go
Normal file
252
examples/40-network-v2.go
Normal file
@@ -0,0 +1,252 @@
|
|||||||
|
// Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
// not use this file except in compliance with the License. You may obtain
|
||||||
|
// a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
// License for the specific language governing permissions and limitations
|
||||||
|
// under the License.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"reflect"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.openstack.org/openstack/golang-client.git/network/v2"
|
||||||
|
"git.openstack.org/openstack/golang-client.git/openstack"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
config := getConfig()
|
||||||
|
|
||||||
|
// Authenticate with a username, password, tenant id.
|
||||||
|
creds := openstack.AuthOpts{
|
||||||
|
AuthUrl: config.Host,
|
||||||
|
Project: config.ProjectName,
|
||||||
|
Username: config.Username,
|
||||||
|
Password: config.Password,
|
||||||
|
}
|
||||||
|
auth, err := openstack.DoAuthRequest(creds)
|
||||||
|
if err != nil {
|
||||||
|
panicString := fmt.Sprint("There was an error authenticating:", err)
|
||||||
|
panic(panicString)
|
||||||
|
}
|
||||||
|
if !auth.GetExpiration().After(time.Now()) {
|
||||||
|
panic("There was an error. The auth token has an invalid expiration.")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the endpoint for the network service.
|
||||||
|
url, err := auth.GetEndpoint("network", "")
|
||||||
|
if url == "" || err != nil {
|
||||||
|
panic("v2 network service url not found during authentication")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make a new client with these creds
|
||||||
|
sess, err := openstack.NewSession(nil, auth, nil)
|
||||||
|
if err != nil {
|
||||||
|
panicString := fmt.Sprint("Error crating new Session:", err)
|
||||||
|
panic(panicString)
|
||||||
|
}
|
||||||
|
|
||||||
|
networkService := network.Service{
|
||||||
|
Session: *sess,
|
||||||
|
Client: *http.DefaultClient,
|
||||||
|
URL: url + "/v2.0", // We're forcing Network v2.0 for now
|
||||||
|
}
|
||||||
|
|
||||||
|
networkName := "OtherNetwork"
|
||||||
|
activeNetwork := CreateNewNetworkVerifyExistsAndActive(networkService, networkName)
|
||||||
|
|
||||||
|
// Create list, get and delete a subnet
|
||||||
|
activeSubnet := CreateSubnetAndVerify(networkService, activeNetwork)
|
||||||
|
activePort := CreatePortAndVerify(networkService, activeSubnet, activeNetwork)
|
||||||
|
DeletePortAndVerify(networkService, activePort)
|
||||||
|
DeleteSubnetAndVerify(networkService, activeSubnet)
|
||||||
|
DeleteNetworkAndVerify(networkService, activeNetwork)
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreatePortAndVerify(networkService network.Service, subnet network.SubnetResponse, activeNetwork network.Response) network.PortResponse {
|
||||||
|
var portToCreate = network.CreatePortParameters{AdminStateUp: false, Name: "testPort", NetworkID: activeNetwork.ID}
|
||||||
|
|
||||||
|
portCreated, err := networkService.CreatePort(portToCreate)
|
||||||
|
if err != nil {
|
||||||
|
panicString := fmt.Sprint("Error in creating port:", err)
|
||||||
|
panic(panicString)
|
||||||
|
}
|
||||||
|
|
||||||
|
foundPorts, err := networkService.Ports()
|
||||||
|
if err != nil {
|
||||||
|
panicString := fmt.Sprint("Error in getting list of subnets:", err)
|
||||||
|
panic(panicString)
|
||||||
|
}
|
||||||
|
|
||||||
|
foundCreatedPort := false
|
||||||
|
for _, portFound := range foundPorts {
|
||||||
|
if reflect.DeepEqual(portCreated, portFound) {
|
||||||
|
foundCreatedPort = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !foundCreatedPort {
|
||||||
|
panic("Cannot find the newly created port.")
|
||||||
|
}
|
||||||
|
|
||||||
|
return portCreated
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeletePortAndVerify(networkService network.Service, port network.PortResponse) {
|
||||||
|
err := networkService.DeletePort(port.ID)
|
||||||
|
if err != nil {
|
||||||
|
panicString := fmt.Sprint("Error in deleting port:", err)
|
||||||
|
panic(panicString)
|
||||||
|
}
|
||||||
|
|
||||||
|
ports, err := networkService.Ports()
|
||||||
|
if err != nil {
|
||||||
|
panicString := fmt.Sprint("There was an error getting a list of ports to verify the port was deleted:", err)
|
||||||
|
panic(panicString)
|
||||||
|
}
|
||||||
|
|
||||||
|
portDeleted := true
|
||||||
|
for _, portFound := range ports {
|
||||||
|
if reflect.DeepEqual(portFound, port) {
|
||||||
|
portDeleted = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !portDeleted {
|
||||||
|
panic("port was not deleted.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateSubnetAndVerify(networkService network.Service, activeNetwork network.Response) network.SubnetResponse {
|
||||||
|
var allocationPools = []network.AllocationPool{network.AllocationPool{Start: "10.1.2.5", End: "10.1.2.15"}}
|
||||||
|
subnetToCreate := network.CreateSubnetParameters{NetworkID: activeNetwork.ID, IPVersion: network.IPV4,
|
||||||
|
CIDR: "10.1.2.1/25", AllocationPools: allocationPools}
|
||||||
|
|
||||||
|
subnetCreated, err := networkService.CreateSubnet(subnetToCreate)
|
||||||
|
if err != nil {
|
||||||
|
panicString := fmt.Sprint("Error in creating subnet:", err)
|
||||||
|
panic(panicString)
|
||||||
|
}
|
||||||
|
|
||||||
|
foundSubnets, err := networkService.Subnets()
|
||||||
|
if err != nil {
|
||||||
|
panicString := fmt.Sprint("Error in getting list of subnets:", err)
|
||||||
|
panic(panicString)
|
||||||
|
}
|
||||||
|
|
||||||
|
foundCreatedSubnet := false
|
||||||
|
for _, subnetFound := range foundSubnets {
|
||||||
|
if reflect.DeepEqual(subnetCreated, subnetFound) {
|
||||||
|
foundCreatedSubnet = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !foundCreatedSubnet {
|
||||||
|
panic("Cannot find the newly created subnet.")
|
||||||
|
}
|
||||||
|
|
||||||
|
return subnetCreated
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeleteSubnetAndVerify(networkService network.Service, subnet network.SubnetResponse) {
|
||||||
|
err := networkService.DeleteSubnet(subnet.ID)
|
||||||
|
if err != nil {
|
||||||
|
panicString := fmt.Sprint("Error in deleting subnet:", err)
|
||||||
|
panic(panicString)
|
||||||
|
}
|
||||||
|
|
||||||
|
subnets, err := networkService.Subnets()
|
||||||
|
if err != nil {
|
||||||
|
panicString := fmt.Sprint("There was an error getting a list of networks to verify the network was deleted:", err)
|
||||||
|
panic(panicString)
|
||||||
|
}
|
||||||
|
|
||||||
|
subnetDeleted := true
|
||||||
|
for _, subnetFound := range subnets {
|
||||||
|
if reflect.DeepEqual(subnetFound, subnet) {
|
||||||
|
subnetDeleted = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !subnetDeleted {
|
||||||
|
panic("subnet was not deleted.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeleteNetworkAndVerify(networkService network.Service, activeNetwork network.Response) {
|
||||||
|
err := networkService.DeleteNetwork(activeNetwork.ID)
|
||||||
|
if err != nil {
|
||||||
|
panicString := fmt.Sprint("Error in deleting 'OtherNetwork'", err)
|
||||||
|
panic(panicString)
|
||||||
|
}
|
||||||
|
|
||||||
|
networks, err := networkService.Networks()
|
||||||
|
if err != nil {
|
||||||
|
panicString := fmt.Sprint("There was an error getting a list of networks to verify the network was deleted:", err)
|
||||||
|
panic(panicString)
|
||||||
|
}
|
||||||
|
|
||||||
|
networkDeleted := true
|
||||||
|
for _, networkFound := range networks {
|
||||||
|
if reflect.DeepEqual(activeNetwork, networkFound) {
|
||||||
|
networkDeleted = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !networkDeleted {
|
||||||
|
panic("network was not deleted.")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
func CreateNewNetworkVerifyExistsAndActive(networkService network.Service, networkName string) network.Response {
|
||||||
|
createdNetwork, err := networkService.CreateNetwork(true, networkName, false)
|
||||||
|
if err != nil {
|
||||||
|
panicString := fmt.Sprint("There was an error creating a network:", err)
|
||||||
|
panic(panicString)
|
||||||
|
}
|
||||||
|
|
||||||
|
networks, err := networkService.Networks()
|
||||||
|
if err != nil {
|
||||||
|
panicString := fmt.Sprint("There was an error getting a list of networks:", err)
|
||||||
|
panic(panicString)
|
||||||
|
}
|
||||||
|
|
||||||
|
foundCreatedNetwork := false
|
||||||
|
for _, networkFound := range networks {
|
||||||
|
if reflect.DeepEqual(createdNetwork, networkFound) {
|
||||||
|
foundCreatedNetwork = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !foundCreatedNetwork {
|
||||||
|
panic("Cannot find network called 'OtherNetwork' when getting a list of networks.")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Might be nice to have some sugar api that can do this easily for a developer...
|
||||||
|
// Keep iterating until active or until more than 5 tries has been exceeded.
|
||||||
|
//numTries := 0
|
||||||
|
//activeNetwork := createdNetwork
|
||||||
|
//for activeNetwork.Status != "ACTIVE" && numTries < 5 {
|
||||||
|
// activeNetwork, _ = networkService.Network(createdNetwork.ID)
|
||||||
|
// numTries++
|
||||||
|
// fmt.Println("Sleeping 50ms on try:" + string(numTries) + " with status currently " + activeNetwork.Status)
|
||||||
|
// sleepDuration, _ := time.ParseDuration("50ms")
|
||||||
|
// time.Sleep(sleepDuration)
|
||||||
|
//}
|
||||||
|
|
||||||
|
//if activeNetwork.Status != "ACTIVE" {
|
||||||
|
// panic("The network is not in the active state and cannot be deleted")
|
||||||
|
//}
|
||||||
|
|
||||||
|
return createdNetwork
|
||||||
|
}
|
94
network/v2/network.go
Normal file
94
network/v2/network.go
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
// Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
// not use this file except in compliance with the License. You may obtain
|
||||||
|
// a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
// License for the specific language governing permissions and limitations
|
||||||
|
// under the License.
|
||||||
|
|
||||||
|
// Package network is used to create, delete, and query, networks, ports and subnets
|
||||||
|
package network
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"git.openstack.org/openstack/golang-client.git/openstack"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Service holds state that is use to make requests and get responses for networks,
|
||||||
|
// ports and subnets
|
||||||
|
type Service struct {
|
||||||
|
Client http.Client
|
||||||
|
Session openstack.Session
|
||||||
|
URL string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Response returns a set of values of the a network response.
|
||||||
|
type Response struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
Subnets []string `json:"subnets"`
|
||||||
|
TenantID string `json:"tenant_id"`
|
||||||
|
RouterExternal bool `json:"router:external"`
|
||||||
|
AdminStateUp bool `json:"admin_state_up"`
|
||||||
|
Shared bool `json:"shared"`
|
||||||
|
PortSecurityEnabled bool `json:"port_security_enabled"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Networks will issue a get query that returns a list of networks
|
||||||
|
func (networkService Service) Networks() ([]Response, error) {
|
||||||
|
reqURL := networkService.URL + "/networks"
|
||||||
|
nwContainer := networksResp{}
|
||||||
|
_, err := networkService.Session.GetJSON(reqURL, nil, nil, &nwContainer)
|
||||||
|
return nwContainer.Networks, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Network will issue a get request for a specific network.
|
||||||
|
func (networkService Service) Network(id string) (Response, error) {
|
||||||
|
reqURL := networkService.URL + "/networks/" + id
|
||||||
|
nwContainer := networkResp{}
|
||||||
|
_, err := networkService.Session.GetJSON(reqURL, nil, nil, &nwContainer)
|
||||||
|
return nwContainer.Network, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateNetwork will send a POST request to create a new network with the specified parameters.
|
||||||
|
func (networkService Service) CreateNetwork(adminStateUp bool, name string, shared bool) (Response, error) {
|
||||||
|
createParameters := createNetworkValuesContainer{createNetworkValues{Name: name, AdminStateUp: adminStateUp, Shared: shared, TenantID: ""}}
|
||||||
|
reqURL := networkService.URL + "/networks"
|
||||||
|
nwContainer := networkResp{}
|
||||||
|
_, err := networkService.Session.PostJSON(reqURL, nil, nil, &createParameters, &nwContainer)
|
||||||
|
return nwContainer.Network, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteNetwork will delete the specified network.
|
||||||
|
func (networkService Service) DeleteNetwork(name string) (err error) {
|
||||||
|
reqURL := networkService.URL + "/networks/" + name
|
||||||
|
_, err = networkService.Session.Delete(reqURL, nil, nil)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
type createNetworkValues struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
AdminStateUp bool `json:"admin_state_up"`
|
||||||
|
Shared bool `json:"shared"`
|
||||||
|
TenantID string `json:"tenant_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type createNetworkValuesContainer struct {
|
||||||
|
Network createNetworkValues `json:"network"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type networksResp struct {
|
||||||
|
Networks []Response `json:"networks"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type networkResp struct {
|
||||||
|
Network Response `json:"network"`
|
||||||
|
}
|
107
network/v2/network_test.go
Normal file
107
network/v2/network_test.go
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
// Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
// not use this file except in compliance with the License. You may obtain
|
||||||
|
// a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
// License for the specific language governing permissions and limitations
|
||||||
|
// under the License.
|
||||||
|
|
||||||
|
package network_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"git.openstack.org/openstack/golang-client.git/network/v2"
|
||||||
|
"git.openstack.org/openstack/golang-client.git/testutil"
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var tokn = "eaaafd18-0fed-4b3a-81b4-663c99ec1cbb"
|
||||||
|
var subnets = []string{"10.3.5.2", "12.34.1.4"}
|
||||||
|
var sampleNetworkResponse = network.Response{
|
||||||
|
ID: "16470140hb",
|
||||||
|
Name: "networkName",
|
||||||
|
Status: "active",
|
||||||
|
Subnets: subnets,
|
||||||
|
TenantID: "tenantID",
|
||||||
|
RouterExternal: true,
|
||||||
|
AdminStateUp: false,
|
||||||
|
Shared: true,
|
||||||
|
PortSecurityEnabled: false}
|
||||||
|
|
||||||
|
func TestGetNetworks(t *testing.T) {
|
||||||
|
mockResponseObject := networksContainer{Networks: []network.Response{sampleNetworkResponse}}
|
||||||
|
apiServer := testUtil.CreateGetJSONTestRequestServerWithMockObject(t, tokn, mockResponseObject, "/networks")
|
||||||
|
defer apiServer.Close()
|
||||||
|
|
||||||
|
networkService := CreateNetworkService(apiServer.URL)
|
||||||
|
networks, err := networkService.Networks()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(networks) != 1 {
|
||||||
|
t.Error(errors.New("Error: Expected 2 networks to be listed"))
|
||||||
|
}
|
||||||
|
testUtil.Equals(t, sampleNetworkResponse, networks[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetNetwork(t *testing.T) {
|
||||||
|
mockResponseObject := networkContainer{Network: sampleNetworkResponse}
|
||||||
|
apiServer := testUtil.CreateGetJSONTestRequestServerWithMockObject(t, tokn, mockResponseObject, "/networks/5270u2tg0")
|
||||||
|
defer apiServer.Close()
|
||||||
|
|
||||||
|
networkService := CreateNetworkService(apiServer.URL)
|
||||||
|
network, err := networkService.Network("5270u2tg0")
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
testUtil.Equals(t, sampleNetworkResponse, network)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDeleteNetwork(t *testing.T) {
|
||||||
|
name := "networkName"
|
||||||
|
apiServer := testUtil.CreateDeleteTestRequestServer(t, tokn, "/networks/"+name)
|
||||||
|
defer apiServer.Close()
|
||||||
|
|
||||||
|
networkService := CreateNetworkService(apiServer.URL)
|
||||||
|
err := networkService.DeleteNetwork(name)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateNetwork(t *testing.T) {
|
||||||
|
mockResponse, _ := json.Marshal(networkContainer{sampleNetworkResponse})
|
||||||
|
apiServer := testUtil.CreatePostJSONTestRequestServer(t, tokn, string(mockResponse), "/networks",
|
||||||
|
`{"network":{"name":"networkName","admin_state_up":false,"shared":true,"tenant_id":"tenantId"}}`)
|
||||||
|
defer apiServer.Close()
|
||||||
|
|
||||||
|
networkService := CreateNetworkService(apiServer.URL)
|
||||||
|
actualNetwork, err := networkService.CreateNetwork(false, "networkName", true)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
testUtil.Equals(t, sampleNetworkResponse, actualNetwork)
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateNetworkService(url string) network.Service {
|
||||||
|
return network.Service{TokenID: tokn, TenantID: "tenantId", Client: *http.DefaultClient, URL: url}
|
||||||
|
}
|
||||||
|
|
||||||
|
type networksContainer struct {
|
||||||
|
Networks []network.Response `json:"networks"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type networkContainer struct {
|
||||||
|
Network network.Response `json:"network"`
|
||||||
|
}
|
109
network/v2/port.go
Normal file
109
network/v2/port.go
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
// Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
// not use this file except in compliance with the License. You may obtain
|
||||||
|
// a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
// License for the specific language governing permissions and limitations
|
||||||
|
// under the License.
|
||||||
|
|
||||||
|
package network
|
||||||
|
|
||||||
|
import (
|
||||||
|
// "git.openstack.org/openstack/golang-client.git/openstack"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PortResponse returns a set of values of the a port response.
|
||||||
|
type PortResponse struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
AdminStateUp bool `json:"admin_state_up"`
|
||||||
|
PortSecurityEnabled bool `json:"port_security_enabled"`
|
||||||
|
DeviceID string `json:"device_id"`
|
||||||
|
DeviceOwner string `json:"device_owner"`
|
||||||
|
NetworkID string `json:"network_id"`
|
||||||
|
TenantID string `json:"tenant_id"`
|
||||||
|
MacAddress string `json:"mac_address"`
|
||||||
|
FixedIPs []FixedIP `json:"fixed_ips"`
|
||||||
|
SecurityGroups []string `json:"security_groups"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreatePortParameters holds a set of values that specify how
|
||||||
|
// to create a new port.
|
||||||
|
type CreatePortParameters struct {
|
||||||
|
AdminStateUp bool `json:"admin_state_up,omitempty"`
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
NetworkID string `json:"network_id"`
|
||||||
|
DeviceID string `json:"device_id,omitempty"`
|
||||||
|
MacAddress string `json:"mac_address,omitempty"`
|
||||||
|
FixedIPs []FixedIP `json:"fixed_ips,omitempty"`
|
||||||
|
SecurityGroups []string `json:"security_groups,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PortResponses is a type for a slice of PortResponses.
|
||||||
|
type PortResponses []PortResponse
|
||||||
|
|
||||||
|
func (a PortResponses) Len() int { return len(a) }
|
||||||
|
func (a PortResponses) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||||
|
func (a PortResponses) Less(i, j int) bool { return a[i].Name < a[j].Name }
|
||||||
|
|
||||||
|
// FixedIP is holds data that specifies a fixed IP.
|
||||||
|
type FixedIP struct {
|
||||||
|
SubnetID string `json:"subnet_id"`
|
||||||
|
IPAddress string `json:"ip_address,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ports issues a GET request that returns the found port responses
|
||||||
|
func (networkService Service) Ports() ([]PortResponse, error) {
|
||||||
|
reqURL := networkService.URL + "/ports"
|
||||||
|
var portResponse = portsResp{}
|
||||||
|
_, err := networkService.Session.GetJSON(reqURL, nil, nil, &portResponse)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return portResponse.Ports, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Port issues a GET request that returns a specific port response.
|
||||||
|
func (networkService Service) Port(id string) (PortResponse, error) {
|
||||||
|
reqURL := networkService.URL + "/ports/" + id
|
||||||
|
portResponse := portResp{}
|
||||||
|
_, err := networkService.Session.GetJSON(reqURL, nil, nil, &portResponse)
|
||||||
|
return portResponse.Port, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeletePort issues a DELETE to the specified port url to delete it.
|
||||||
|
func (networkService Service) DeletePort(id string) error {
|
||||||
|
reqURL := networkService.URL + "/ports/" + id
|
||||||
|
_, err := networkService.Session.Delete(reqURL, nil, nil)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreatePort issues a POST to create the specified port and return a PortResponse.
|
||||||
|
func (networkService Service) CreatePort(parameters CreatePortParameters) (PortResponse, error) {
|
||||||
|
reqURL := networkService.URL + "/ports"
|
||||||
|
parametersContainer := createPortContainer{Port: parameters}
|
||||||
|
portResponse := portResp{}
|
||||||
|
|
||||||
|
_, err := networkService.Session.PostJSON(reqURL, nil, nil, ¶metersContainer, &portResponse)
|
||||||
|
return portResponse.Port, err
|
||||||
|
}
|
||||||
|
|
||||||
|
type portsResp struct {
|
||||||
|
Ports []PortResponse `json:"ports"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type portResp struct {
|
||||||
|
Port PortResponse `json:"port"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type createPortContainer struct {
|
||||||
|
Port CreatePortParameters `json:"port"`
|
||||||
|
}
|
104
network/v2/port_test.go
Normal file
104
network/v2/port_test.go
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
// Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
// not use this file except in compliance with the License. You may obtain
|
||||||
|
// a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
// License for the specific language governing permissions and limitations
|
||||||
|
// under the License.
|
||||||
|
|
||||||
|
package network_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"git.openstack.org/openstack/golang-client.git/network/v2"
|
||||||
|
"git.openstack.org/openstack/golang-client.git/testutil"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var fixedIps = []network.FixedIP{network.FixedIP{SubnetID: "125071206726"}, network.FixedIP{SubnetID: "15615526", IPAddress: "132.145.15.11"}}
|
||||||
|
var samplePortResponse = network.PortResponse{
|
||||||
|
ID: "2490640zbg",
|
||||||
|
Name: "Port14",
|
||||||
|
Status: "active",
|
||||||
|
AdminStateUp: true,
|
||||||
|
PortSecurityEnabled: true,
|
||||||
|
DeviceID: "deviceid",
|
||||||
|
DeviceOwner: "deviceowner",
|
||||||
|
NetworkID: "networkid",
|
||||||
|
TenantID: "tenantid",
|
||||||
|
MacAddress: "macAddress",
|
||||||
|
FixedIPs: fixedIps,
|
||||||
|
SecurityGroups: []string{"sec1", "sec2"}}
|
||||||
|
|
||||||
|
func TestGetPorts(t *testing.T) {
|
||||||
|
mockResponseObject := portsContainer{Ports: []network.PortResponse{samplePortResponse}}
|
||||||
|
apiServer := testUtil.CreateGetJSONTestRequestServerWithMockObject(t, tokn, mockResponseObject, "/ports")
|
||||||
|
defer apiServer.Close()
|
||||||
|
|
||||||
|
networkService := CreateNetworkService(apiServer.URL)
|
||||||
|
ports, err := networkService.Ports()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(ports) != 1 {
|
||||||
|
t.Error(errors.New("Error: Expected 2 networks to be listed"))
|
||||||
|
}
|
||||||
|
testUtil.Equals(t, samplePortResponse, ports[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetPort(t *testing.T) {
|
||||||
|
mockResponseObject := portContainer{Port: samplePortResponse}
|
||||||
|
apiServer := testUtil.CreateGetJSONTestRequestServerWithMockObject(t, tokn, mockResponseObject, "/ports/23507256")
|
||||||
|
defer apiServer.Close()
|
||||||
|
|
||||||
|
networkService := CreateNetworkService(apiServer.URL)
|
||||||
|
port, err := networkService.Port("23507256")
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
testUtil.Equals(t, samplePortResponse, port)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDeletePort(t *testing.T) {
|
||||||
|
portName := "portName"
|
||||||
|
apiServer := testUtil.CreateDeleteTestRequestServer(t, tokn, "/ports/"+portName)
|
||||||
|
defer apiServer.Close()
|
||||||
|
|
||||||
|
networkService := CreateNetworkService(apiServer.URL)
|
||||||
|
err := networkService.DeletePort(portName)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreatePort(t *testing.T) {
|
||||||
|
mockResponse, _ := json.Marshal(portContainer{Port: samplePortResponse})
|
||||||
|
apiServer := testUtil.CreatePostJSONTestRequestServer(t, tokn, string(mockResponse), "/ports",
|
||||||
|
`{"port":{"admin_state_up":true,"name":"name","network_id":"networkid","fixed_ips":[{"subnet_id":"125071206726"},{"subnet_id":"15615526","ip_address":"132.145.15.11"}]}}`)
|
||||||
|
defer apiServer.Close()
|
||||||
|
|
||||||
|
networkService := CreateNetworkService(apiServer.URL)
|
||||||
|
createPortParameters := network.CreatePortParameters{AdminStateUp: true, Name: "name", NetworkID: "networkid", FixedIPs: fixedIps}
|
||||||
|
actualPort, err := networkService.CreatePort(createPortParameters)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
testUtil.Equals(t, samplePortResponse, actualPort)
|
||||||
|
}
|
||||||
|
|
||||||
|
type portsContainer struct {
|
||||||
|
Ports []network.PortResponse `json:"ports"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type portContainer struct {
|
||||||
|
Port network.PortResponse `json:"port"`
|
||||||
|
}
|
106
network/v2/subnet.go
Normal file
106
network/v2/subnet.go
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
// Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
// not use this file except in compliance with the License. You may obtain
|
||||||
|
// a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
// License for the specific language governing permissions and limitations
|
||||||
|
// under the License.
|
||||||
|
|
||||||
|
package network
|
||||||
|
|
||||||
|
import (
|
||||||
|
// "git.openstack.org/openstack/golang-client.git/openstack"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SubnetResponse returns a set of values of the a Subnet response
|
||||||
|
type SubnetResponse struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
NetworkID string `json:"network_id"`
|
||||||
|
TenantID string `json:"tenant_id"`
|
||||||
|
EnableDHCP bool `json:"enable_dhcp"`
|
||||||
|
DNSNameserver []string `json:"dns_nameservers"`
|
||||||
|
AllocationPools []AllocationPool `json:"allocation_pools"`
|
||||||
|
HostRoutes []string `json:"host_routes"`
|
||||||
|
IPVersion IPVersion `json:"ip_version"`
|
||||||
|
GatewayIP string `json:"gateway_ip"`
|
||||||
|
CIDR string `json:"cidr"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateSubnetParameters is a set of values to create a new subnet.
|
||||||
|
type CreateSubnetParameters struct {
|
||||||
|
NetworkID string `json:"network_id"`
|
||||||
|
IPVersion IPVersion `json:"ip_version"`
|
||||||
|
CIDR string `json:"cidr"`
|
||||||
|
AllocationPools []AllocationPool `json:"allocation_pools"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllocationPool is a set of values for an allocation pool of ip addresses.
|
||||||
|
type AllocationPool struct {
|
||||||
|
Start string `json:"start"`
|
||||||
|
End string `json:"end"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPVersion type indicates whether an ip address is IPV4 or IPV6.
|
||||||
|
type IPVersion int
|
||||||
|
|
||||||
|
const (
|
||||||
|
// IPV4 indicates its an ip address version 4.
|
||||||
|
IPV4 IPVersion = 4
|
||||||
|
// IPV6 indicates its an ip address version 6
|
||||||
|
IPV6 IPVersion = 6
|
||||||
|
)
|
||||||
|
|
||||||
|
// Subnets issues a GET request to return all subnets.
|
||||||
|
func (networkService Service) Subnets() ([]SubnetResponse, error) {
|
||||||
|
reqURL := networkService.URL + "/subnets"
|
||||||
|
var subnetResponse = subnetsResp{}
|
||||||
|
_, err := networkService.Session.GetJSON(reqURL, nil, nil, &subnetResponse)
|
||||||
|
return subnetResponse.Subnets, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subnet issues a GET request to a specific url of a subnet and returns a subnet response.
|
||||||
|
func (networkService Service) Subnet(id string) (SubnetResponse, error) {
|
||||||
|
reqURL := networkService.URL + "/subnets/" + id
|
||||||
|
|
||||||
|
subnetResponse := subnetResp{}
|
||||||
|
_, err := networkService.Session.GetJSON(reqURL, nil, nil, &subnetResponse)
|
||||||
|
return subnetResponse.Subnet, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteSubnet issues a DELETE request to remove the subnet.
|
||||||
|
func (networkService Service) DeleteSubnet(id string) error {
|
||||||
|
reqURL := networkService.URL + "/subnets/" + id
|
||||||
|
_, err := networkService.Session.Delete(reqURL, nil, nil)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateSubnet issues a GET request to add a Subnet with the specified parameters
|
||||||
|
// and returns the Subnet created.
|
||||||
|
func (networkService Service) CreateSubnet(parameters CreateSubnetParameters) (SubnetResponse, error) {
|
||||||
|
|
||||||
|
reqURL := networkService.URL + "/subnets"
|
||||||
|
parametersContainer := createSubnetContainer{Subnet: parameters}
|
||||||
|
subnetResponse := subnetResp{}
|
||||||
|
|
||||||
|
_, err := networkService.Session.PostJSON(reqURL, nil, nil, ¶metersContainer, &subnetResponse)
|
||||||
|
return subnetResponse.Subnet, err
|
||||||
|
}
|
||||||
|
|
||||||
|
type subnetResp struct {
|
||||||
|
Subnet SubnetResponse `json:"subnet"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type subnetsResp struct {
|
||||||
|
Subnets []SubnetResponse `json:"subnets"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type createSubnetContainer struct {
|
||||||
|
Subnet CreateSubnetParameters `json:"subnet"`
|
||||||
|
}
|
107
network/v2/subnet_test.go
Normal file
107
network/v2/subnet_test.go
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
// Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
// not use this file except in compliance with the License. You may obtain
|
||||||
|
// a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
// License for the specific language governing permissions and limitations
|
||||||
|
// under the License.
|
||||||
|
|
||||||
|
package network_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"git.openstack.org/openstack/golang-client.git/network/v2"
|
||||||
|
"git.openstack.org/openstack/golang-client.git/testutil"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var allocationPool1 = network.AllocationPool{Start: "13.14.14.15", End: "13.14.14.15"}
|
||||||
|
var allocationPools = []network.AllocationPool{allocationPool1}
|
||||||
|
var sampleSubNetResponse = network.SubnetResponse{
|
||||||
|
ID: "subnet",
|
||||||
|
Name: "name",
|
||||||
|
NetworkID: "networkid",
|
||||||
|
TenantID: "tenantid",
|
||||||
|
EnableDHCP: true,
|
||||||
|
DNSNameserver: []string{"13.14.14.15"},
|
||||||
|
AllocationPools: allocationPools,
|
||||||
|
HostRoutes: []string{"35.15.15.15"},
|
||||||
|
IPVersion: network.IPV4,
|
||||||
|
GatewayIP: "35.15.15.1",
|
||||||
|
CIDR: "35.15.15.3"}
|
||||||
|
|
||||||
|
func TestGetSubnets(t *testing.T) {
|
||||||
|
mockResponseObject := subnetsResp{Subnets: []network.SubnetResponse{sampleSubNetResponse}}
|
||||||
|
apiServer := testUtil.CreateGetJSONTestRequestServerWithMockObject(t, tokn, mockResponseObject, "/subnets")
|
||||||
|
|
||||||
|
defer apiServer.Close()
|
||||||
|
|
||||||
|
networkService := CreateNetworkService(apiServer.URL)
|
||||||
|
subnets, err := networkService.Subnets()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(subnets) != 1 {
|
||||||
|
t.Error(errors.New("Error: Expected 1 subnet to be listed"))
|
||||||
|
}
|
||||||
|
testUtil.Equals(t, sampleSubNetResponse, subnets[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetSubnet(t *testing.T) {
|
||||||
|
mockResponseObject := subnetResp{Subnet: sampleSubNetResponse}
|
||||||
|
apiServer := testUtil.CreateGetJSONTestRequestServerWithMockObject(t, tokn, mockResponseObject, "/subnets/5270u2tg0")
|
||||||
|
defer apiServer.Close()
|
||||||
|
|
||||||
|
networkService := CreateNetworkService(apiServer.URL)
|
||||||
|
subnet, err := networkService.Subnet("5270u2tg0")
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
testUtil.Equals(t, sampleSubNetResponse, subnet)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDeleteSubnet(t *testing.T) {
|
||||||
|
name := "subnetName"
|
||||||
|
apiServer := testUtil.CreateDeleteTestRequestServer(t, tokn, "/subnets/"+name)
|
||||||
|
defer apiServer.Close()
|
||||||
|
|
||||||
|
networkService := CreateNetworkService(apiServer.URL)
|
||||||
|
err := networkService.DeleteSubnet(name)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateSubnet(t *testing.T) {
|
||||||
|
mockResponse, err := json.Marshal(subnetResp{Subnet: sampleSubNetResponse})
|
||||||
|
|
||||||
|
apiServer := testUtil.CreatePostJSONTestRequestServer(t, tokn, string(mockResponse), "/subnets",
|
||||||
|
`{"subnet":{"network_id":"subnetid","ip_version":4,"cidr":"12.14.76.87","allocation_pools":[{"start":"13.14.14.15","end":"13.14.14.15"}]}}`)
|
||||||
|
defer apiServer.Close()
|
||||||
|
|
||||||
|
networkService := CreateNetworkService(apiServer.URL)
|
||||||
|
createSubnetParameters := network.CreateSubnetParameters{NetworkID: "subnetid", AllocationPools: allocationPools, CIDR: "12.14.76.87", IPVersion: 4}
|
||||||
|
actualPort, err := networkService.CreateSubnet(createSubnetParameters)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
testUtil.Equals(t, sampleSubNetResponse, actualPort)
|
||||||
|
}
|
||||||
|
|
||||||
|
type subnetsResp struct {
|
||||||
|
Subnets []network.SubnetResponse `json:"subnets"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type subnetResp struct {
|
||||||
|
Subnet network.SubnetResponse `json:"subnet"`
|
||||||
|
}
|
@@ -16,6 +16,7 @@
|
|||||||
package testUtil
|
package testUtil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -101,6 +102,22 @@ func CreateGetJSONTestRequestServer(t *testing.T, expectedAuthTokenValue string,
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreateGetJSONTestRequestServerWithMockObject a http.Server that can be used to test PostJson requests. Specify the token,
|
||||||
|
// response object which will be marshaled to a json payload and the expected ending url.
|
||||||
|
func CreateGetJSONTestRequestServerWithMockObject(t *testing.T, token string, mockResponseObject interface{}, urlEndsWith string) *httptest.Server {
|
||||||
|
mockResponse, err := json.Marshal(mockResponseObject)
|
||||||
|
if err != nil {
|
||||||
|
t.Error("Test failed to marshal mockResponseObject:", err)
|
||||||
|
}
|
||||||
|
anon := func(req *http.Request) {
|
||||||
|
reqURL := req.URL.String()
|
||||||
|
if !strings.HasSuffix(reqURL, urlEndsWith) {
|
||||||
|
t.Error(errors.New("Incorrect url created, expected:" + urlEndsWith + " at the end, actual url:" + reqURL))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CreateGetJSONTestRequestServer(t, token, string(mockResponse), anon)
|
||||||
|
}
|
||||||
|
|
||||||
// CreatePostJSONTestRequestServer creates a http.Server that can be used to test PostJson requests. Specify the token,
|
// CreatePostJSONTestRequestServer creates a http.Server that can be used to test PostJson requests. Specify the token,
|
||||||
// response json payload and the url and request body that is expected.
|
// response json payload and the url and request body that is expected.
|
||||||
func CreatePostJSONTestRequestServer(t *testing.T, expectedAuthTokenValue string, outputResponseJSONPayload string, expectedRequestURLEndsWith string, expectedRequestBody string) *httptest.Server {
|
func CreatePostJSONTestRequestServer(t *testing.T, expectedAuthTokenValue string, outputResponseJSONPayload string, expectedRequestURLEndsWith string, expectedRequestBody string) *httptest.Server {
|
||||||
|
Reference in New Issue
Block a user