Networking Acceptance Test Cleanup (#79)
diff --git a/acceptance/clients/clients.go b/acceptance/clients/clients.go
index 9efa901..86871aa 100644
--- a/acceptance/clients/clients.go
+++ b/acceptance/clients/clients.go
@@ -29,6 +29,9 @@
// NetworkName is the name of a network to launch the instance on.
NetworkName string
+
+ // ExternalNetworkID is the network ID of the external network.
+ ExternalNetworkID string
}
// AcceptanceTestChoicesFromEnv populates a ComputeChoices struct from environment variables.
@@ -39,6 +42,7 @@
flavorIDResize := os.Getenv("OS_FLAVOR_ID_RESIZE")
networkName := os.Getenv("OS_NETWORK_NAME")
floatingIPPoolName := os.Getenv("OS_POOL_NAME")
+ externalNetworkID := os.Getenv("OS_EXTGW_ID")
missing := make([]string, 0, 3)
if imageID == "" {
@@ -53,6 +57,9 @@
if floatingIPPoolName == "" {
missing = append(missing, "OS_POOL_NAME")
}
+ if externalNetworkID == "" {
+ missing = append(missing, "OS_EXTGW_ID")
+ }
if networkName == "" {
networkName = "private"
}
@@ -74,7 +81,7 @@
return nil, fmt.Errorf(text)
}
- return &AcceptanceTestChoices{ImageID: imageID, FlavorID: flavorID, FlavorIDResize: flavorIDResize, FloatingIPPoolName: floatingIPPoolName, NetworkName: networkName}, nil
+ return &AcceptanceTestChoices{ImageID: imageID, FlavorID: flavorID, FlavorIDResize: flavorIDResize, FloatingIPPoolName: floatingIPPoolName, NetworkName: networkName, ExternalNetworkID: externalNetworkID}, nil
}
// NewBlockStorageV1Client returns a *ServiceClient for making calls
@@ -225,3 +232,22 @@
return openstack.NewIdentityV3(client, gophercloud.EndpointOpts{})
}
+
+// NewNetworkV2Client returns a *ServiceClient for making calls to the
+// OpenStack Networking v2 API. An error will be returned if authentication
+// or client creation was not possible.
+func NewNetworkV2Client() (*gophercloud.ServiceClient, error) {
+ ao, err := openstack.AuthOptionsFromEnv()
+ if err != nil {
+ return nil, err
+ }
+
+ client, err := openstack.AuthenticatedClient(ao)
+ if err != nil {
+ return nil, err
+ }
+
+ return openstack.NewNetworkV2(client, gophercloud.EndpointOpts{
+ Region: os.Getenv("OS_REGION_NAME"),
+ })
+}
diff --git a/acceptance/openstack/networking/v2/apiversion_test.go b/acceptance/openstack/networking/v2/apiversion_test.go
index 22827d6..409550c 100644
--- a/acceptance/openstack/networking/v2/apiversion_test.go
+++ b/acceptance/openstack/networking/v2/apiversion_test.go
@@ -5,47 +5,48 @@
import (
"testing"
+ "github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/openstack/networking/v2/apiversions"
- "github.com/gophercloud/gophercloud/pagination"
- th "github.com/gophercloud/gophercloud/testhelper"
)
-func TestListAPIVersions(t *testing.T) {
- Setup(t)
- defer Teardown()
+func TestAPIVersionsList(t *testing.T) {
+ client, err := clients.NewNetworkV2Client()
+ if err != nil {
+ t.Fatalf("Unable to create a network client: %v", err)
+ }
- pager := apiversions.ListVersions(Client)
- err := pager.EachPage(func(page pagination.Page) (bool, error) {
- t.Logf("--- Page ---")
+ allPages, err := apiversions.ListVersions(client).AllPages()
+ if err != nil {
+ t.Fatalf("Unable to list api versions: %v", err)
+ }
- versions, err := apiversions.ExtractAPIVersions(page)
- th.AssertNoErr(t, err)
+ allAPIVersions, err := apiversions.ExtractAPIVersions(allPages)
+ if err != nil {
+ t.Fatalf("Unable to extract api versions: %v", err)
+ }
- for _, v := range versions {
- t.Logf("API Version: ID [%s] Status [%s]", v.ID, v.Status)
- }
-
- return true, nil
- })
- th.CheckNoErr(t, err)
+ for _, apiVersion := range allAPIVersions {
+ PrintAPIVersion(t, &apiVersion)
+ }
}
-func TestListAPIResources(t *testing.T) {
- Setup(t)
- defer Teardown()
+func TestAPIResourcesList(t *testing.T) {
+ client, err := clients.NewNetworkV2Client()
+ if err != nil {
+ t.Fatalf("Unable to create a network client: %v", err)
+ }
- pager := apiversions.ListVersionResources(Client, "v2.0")
- err := pager.EachPage(func(page pagination.Page) (bool, error) {
- t.Logf("--- Page ---")
+ allPages, err := apiversions.ListVersionResources(client, "v2.0").AllPages()
+ if err != nil {
+ t.Fatalf("Unable to list api version reosources: %v", err)
+ }
- vrs, err := apiversions.ExtractVersionResources(page)
- th.AssertNoErr(t, err)
+ allVersionResources, err := apiversions.ExtractVersionResources(allPages)
+ if err != nil {
+ t.Fatalf("Unable to extract version resources: %v", err)
+ }
- for _, vr := range vrs {
- t.Logf("Network: Name [%s] Collection [%s]", vr.Name, vr.Collection)
- }
-
- return true, nil
- })
- th.CheckNoErr(t, err)
+ for _, versionResource := range allVersionResources {
+ PrintVersionResource(t, &versionResource)
+ }
}
diff --git a/acceptance/openstack/networking/v2/common.go b/acceptance/openstack/networking/v2/common.go
deleted file mode 100644
index b48855b..0000000
--- a/acceptance/openstack/networking/v2/common.go
+++ /dev/null
@@ -1,39 +0,0 @@
-package v2
-
-import (
- "os"
- "testing"
-
- "github.com/gophercloud/gophercloud"
- "github.com/gophercloud/gophercloud/openstack"
- th "github.com/gophercloud/gophercloud/testhelper"
-)
-
-var Client *gophercloud.ServiceClient
-
-func NewClient() (*gophercloud.ServiceClient, error) {
- opts, err := openstack.AuthOptionsFromEnv()
- if err != nil {
- return nil, err
- }
-
- provider, err := openstack.AuthenticatedClient(opts)
- if err != nil {
- return nil, err
- }
-
- return openstack.NewNetworkV2(provider, gophercloud.EndpointOpts{
- Name: "neutron",
- Region: os.Getenv("OS_REGION_NAME"),
- })
-}
-
-func Setup(t *testing.T) {
- client, err := NewClient()
- th.AssertNoErr(t, err)
- Client = client
-}
-
-func Teardown() {
- Client = nil
-}
diff --git a/acceptance/openstack/networking/v2/extension_test.go b/acceptance/openstack/networking/v2/extension_test.go
index e125034..baade1e 100644
--- a/acceptance/openstack/networking/v2/extension_test.go
+++ b/acceptance/openstack/networking/v2/extension_test.go
@@ -1,45 +1,46 @@
-// +build acceptance networking
+// +build acceptance networking extensions
package v2
import (
"testing"
- "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions"
- "github.com/gophercloud/gophercloud/pagination"
- th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/acceptance/clients"
+ "github.com/gophercloud/gophercloud/acceptance/openstack"
+ "github.com/gophercloud/gophercloud/openstack/common/extensions"
)
-func TestListExts(t *testing.T) {
- Setup(t)
- defer Teardown()
+func TestExtensionsList(t *testing.T) {
+ client, err := clients.NewNetworkV2Client()
+ if err != nil {
+ t.Fatalf("Unable to create a network client: %v", err)
+ }
- pager := extensions.List(Client)
- err := pager.EachPage(func(page pagination.Page) (bool, error) {
- t.Logf("--- Page ---")
+ allPages, err := extensions.List(client).AllPages()
+ if err != nil {
+ t.Fatalf("Unable to list extensions: %v", err)
+ }
- exts, err := extensions.ExtractExtensions(page)
- th.AssertNoErr(t, err)
+ allExtensions, err := extensions.ExtractExtensions(allPages)
+ if err != nil {
+ t.Fatalf("Unable to extract extensions: %v", err)
+ }
- for _, ext := range exts {
- t.Logf("Extension: Name [%s] Description [%s]", ext.Name, ext.Description)
- }
-
- return true, nil
- })
- th.CheckNoErr(t, err)
+ for _, extension := range allExtensions {
+ openstack.PrintExtension(t, &extension)
+ }
}
-func TestGetExt(t *testing.T) {
- Setup(t)
- defer Teardown()
+func TestExtensionGet(t *testing.T) {
+ client, err := clients.NewNetworkV2Client()
+ if err != nil {
+ t.Fatalf("Unable to create a network client: %v", err)
+ }
- ext, err := extensions.Get(Client, "service-type").Extract()
- th.AssertNoErr(t, err)
+ extension, err := extensions.Get(client, "router").Extract()
+ if err != nil {
+ t.Fatalf("Unable to get extension port-security: %v", err)
+ }
- th.AssertEquals(t, ext.Updated, "2013-01-20T00:00:00-00:00")
- th.AssertEquals(t, ext.Name, "Neutron Service Type Management")
- th.AssertEquals(t, ext.Namespace, "http://docs.openstack.org/ext/neutron/service-type/api/v1.0")
- th.AssertEquals(t, ext.Alias, "service-type")
- th.AssertEquals(t, ext.Description, "API for retrieving service providers for Neutron advanced services")
+ openstack.PrintExtension(t, extension)
}
diff --git a/acceptance/openstack/networking/v2/extensions/extensions.go b/acceptance/openstack/networking/v2/extensions/extensions.go
new file mode 100644
index 0000000..f18e430
--- /dev/null
+++ b/acceptance/openstack/networking/v2/extensions/extensions.go
@@ -0,0 +1,180 @@
+package extensions
+
+import (
+ "testing"
+
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/acceptance/tools"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/external"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/provider"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
+)
+
+// CreateExternalNetwork will create an external network. An error will be
+// returned if the creation failed.
+func CreateExternalNetwork(t *testing.T, client *gophercloud.ServiceClient) (*networks.Network, error) {
+ networkName := tools.RandomString("TESTACC-", 8)
+
+ t.Logf("Attempting to create external network: %s", networkName)
+
+ adminStateUp := true
+ isExternal := true
+ createOpts := external.CreateOpts{
+ External: &isExternal,
+ }
+
+ createOpts.Name = networkName
+ createOpts.AdminStateUp = &adminStateUp
+
+ network, err := networks.Create(client, createOpts).Extract()
+ if err != nil {
+ return network, err
+ }
+
+ t.Logf("Created external network: %s", networkName)
+
+ return network, nil
+}
+
+// CreatePortWithSecurityGroup will create a port with a security group
+// attached. An error will be returned if the port could not be created.
+func CreatePortWithSecurityGroup(t *testing.T, client *gophercloud.ServiceClient, networkID, subnetID, secGroupID string) (*ports.Port, error) {
+ portName := tools.RandomString("TESTACC-", 8)
+ iFalse := false
+
+ t.Logf("Attempting to create port: %s", portName)
+
+ createOpts := ports.CreateOpts{
+ NetworkID: networkID,
+ Name: portName,
+ AdminStateUp: &iFalse,
+ FixedIPs: []ports.IP{ports.IP{SubnetID: subnetID}},
+ SecurityGroups: []string{secGroupID},
+ }
+
+ port, err := ports.Create(client, createOpts).Extract()
+ if err != nil {
+ return port, err
+ }
+
+ t.Logf("Successfully created port: %s", portName)
+
+ return port, nil
+}
+
+// CreateSecurityGroup will create a security group with a random name.
+// An error will be returned if one was failed to be created.
+func CreateSecurityGroup(t *testing.T, client *gophercloud.ServiceClient) (*groups.SecGroup, error) {
+ secGroupName := tools.RandomString("TESTACC-", 8)
+
+ t.Logf("Attempting to create security group: %s", secGroupName)
+
+ createOpts := groups.CreateOpts{
+ Name: secGroupName,
+ }
+
+ secGroup, err := groups.Create(client, createOpts).Extract()
+ if err != nil {
+ return secGroup, err
+ }
+
+ t.Logf("Created security group: %s", secGroup.ID)
+
+ return secGroup, nil
+}
+
+// CreateSecurityGroupRule will create a security group rule with a random name
+// and random port between 80 and 99.
+// An error will be returned if one was failed to be created.
+func CreateSecurityGroupRule(t *testing.T, client *gophercloud.ServiceClient, secGroupID string) (*rules.SecGroupRule, error) {
+ t.Logf("Attempting to create security group rule in group: %s", secGroupID)
+
+ fromPort := tools.RandomInt(80, 89)
+ toPort := tools.RandomInt(90, 99)
+
+ createOpts := rules.CreateOpts{
+ Direction: "ingress",
+ EtherType: "IPv4",
+ SecGroupID: secGroupID,
+ PortRangeMin: fromPort,
+ PortRangeMax: toPort,
+ Protocol: rules.ProtocolTCP,
+ }
+
+ rule, err := rules.Create(client, createOpts).Extract()
+ if err != nil {
+ return rule, err
+ }
+
+ t.Logf("Created security group rule: %s", rule.ID)
+
+ return rule, nil
+}
+
+// DeleteSecurityGroup will delete a security group of a specified ID.
+// A fatal error will occur if the deletion failed. This works best as a
+// deferred function
+func DeleteSecurityGroup(t *testing.T, client *gophercloud.ServiceClient, secGroupID string) {
+ t.Logf("Attempting to delete security group: %s", secGroupID)
+
+ err := groups.Delete(client, secGroupID).ExtractErr()
+ if err != nil {
+ t.Fatalf("Unable to delete security group: %v", err)
+ }
+}
+
+// DeleteSecurityGroupRule will delete a security group rule of a specified ID.
+// A fatal error will occur if the deletion failed. This works best as a
+// deferred function
+func DeleteSecurityGroupRule(t *testing.T, client *gophercloud.ServiceClient, ruleID string) {
+ t.Logf("Attempting to delete security group rule: %s", ruleID)
+
+ err := rules.Delete(client, ruleID).ExtractErr()
+ if err != nil {
+ t.Fatalf("Unable to delete security group rule: %v", err)
+ }
+}
+
+// PrintNetworkExtAttrs prints a network and all of its extra attributes.
+func PrintNetworkExtAttrs(t *testing.T, network *provider.NetworkExtAttrs) {
+ t.Logf("ID: %s", network.ID)
+ t.Logf("Name: %s", network.Name)
+ t.Logf("AdminStateUp: %t", network.AdminStateUp)
+ t.Logf("Status: %s", network.Status)
+ t.Logf("Subnets: %s", network.Subnets)
+ t.Logf("TenantID: %s", network.TenantID)
+ t.Logf("Shared: %t", network.Shared)
+ t.Logf("NetworkType: %s", network.NetworkType)
+ t.Logf("PhysicalNetwork: %s", network.PhysicalNetwork)
+ t.Logf("SegmentationID: %d", network.SegmentationID)
+}
+
+// PrintSecurityGroup will print a security group and all of its attributes.
+func PrintSecurityGroup(t *testing.T, secGroup *groups.SecGroup) {
+ t.Logf("ID: %s", secGroup.ID)
+ t.Logf("Name: %s", secGroup.Name)
+ t.Logf("Description: %s", secGroup.Description)
+ t.Logf("TenantID: %s", secGroup.TenantID)
+ t.Logf("Rules:")
+
+ for _, rule := range secGroup.Rules {
+ PrintSecurityGroupRule(t, &rule)
+ }
+}
+
+// PrintSecurityGroupRule will print a security group rule and all of its attributes.
+func PrintSecurityGroupRule(t *testing.T, rule *rules.SecGroupRule) {
+ t.Logf("ID: %s", rule.ID)
+ t.Logf("Direction: %s", rule.Direction)
+ t.Logf("EtherType: %s", rule.EtherType)
+ t.Logf("SecGroupID: %s", rule.SecGroupID)
+ t.Logf("PortRangeMin: %d", rule.PortRangeMin)
+ t.Logf("PortRangeMax: %d", rule.PortRangeMax)
+ t.Logf("Protocol: %s", rule.Protocol)
+ t.Logf("RemoteGroupID: %s", rule.RemoteGroupID)
+ t.Logf("RemoteIPPrefix: %s", rule.RemoteIPPrefix)
+ t.Logf("TenantID: %s", rule.TenantID)
+}
diff --git a/acceptance/openstack/networking/v2/extensions/fwaas/firewall_test.go b/acceptance/openstack/networking/v2/extensions/fwaas/firewall_test.go
index ef1fb1a..976eb79 100644
--- a/acceptance/openstack/networking/v2/extensions/fwaas/firewall_test.go
+++ b/acceptance/openstack/networking/v2/extensions/fwaas/firewall_test.go
@@ -4,113 +4,76 @@
import (
"testing"
- "time"
- "github.com/gophercloud/gophercloud"
- base "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2"
+ "github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/fwaas/firewalls"
- "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/fwaas/policies"
- "github.com/gophercloud/gophercloud/pagination"
- th "github.com/gophercloud/gophercloud/testhelper"
)
-func firewallSetup(t *testing.T) string {
- base.Setup(t)
- return createPolicy(t, &policies.CreateOpts{})
-}
+func TestFirewallList(t *testing.T) {
+ client, err := clients.NewNetworkV2Client()
+ if err != nil {
+ t.Fatalf("Unable to create a network client: %v", err)
+ }
-func firewallTeardown(t *testing.T, policyID string) {
- defer base.Teardown()
- deletePolicy(t, policyID)
-}
+ allPages, err := firewalls.List(client, nil).AllPages()
+ if err != nil {
+ t.Fatalf("Unable to list firewalls: %v", err)
+ }
-func TestFirewall(t *testing.T) {
- policyID := firewallSetup(t)
- defer firewallTeardown(t, policyID)
+ allFirewalls, err := firewalls.ExtractFirewalls(allPages)
+ if err != nil {
+ t.Fatalf("Unable to extract firewalls: %v", err)
+ }
- firewallID := createFirewall(t, &firewalls.CreateOpts{
- Name: "gophercloud test",
- Description: "acceptance test",
- PolicyID: policyID,
- })
-
- waitForFirewallToBeActive(t, firewallID)
-
- listFirewalls(t)
-
- updateFirewall(t, firewallID, &firewalls.UpdateOpts{
- Description: "acceptance test updated",
- })
-
- waitForFirewallToBeActive(t, firewallID)
-
- deleteFirewall(t, firewallID)
-
- waitForFirewallToBeDeleted(t, firewallID)
-}
-
-func createFirewall(t *testing.T, opts *firewalls.CreateOpts) string {
- f, err := firewalls.Create(base.Client, *opts).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Created firewall: %#v", opts)
- return f.ID
-}
-
-func listFirewalls(t *testing.T) {
- err := firewalls.List(base.Client, firewalls.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
- firewallList, err := firewalls.ExtractFirewalls(page)
- if err != nil {
- t.Errorf("Failed to extract firewalls: %v", err)
- return false, err
- }
-
- for _, r := range firewallList {
- t.Logf("Listing firewalls: ID [%s]", r.ID)
- }
-
- return true, nil
- })
- th.AssertNoErr(t, err)
-}
-
-func updateFirewall(t *testing.T, firewallID string, opts *firewalls.UpdateOpts) {
- f, err := firewalls.Update(base.Client, firewallID, *opts).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Updated firewall ID [%s]", f.ID)
-}
-
-func getFirewall(t *testing.T, firewallID string) *firewalls.Firewall {
- f, err := firewalls.Get(base.Client, firewallID).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Getting firewall ID [%s]", f.ID)
- return f
-}
-
-func deleteFirewall(t *testing.T, firewallID string) {
- res := firewalls.Delete(base.Client, firewallID)
- th.AssertNoErr(t, res.Err)
- t.Logf("Deleted firewall %s", firewallID)
-}
-
-func waitForFirewallToBeActive(t *testing.T, firewallID string) {
- for i := 0; i < 10; i++ {
- fw := getFirewall(t, firewallID)
- if fw.Status == "ACTIVE" {
- break
- }
- time.Sleep(time.Second)
+ for _, firewall := range allFirewalls {
+ PrintFirewall(t, &firewall)
}
}
-func waitForFirewallToBeDeleted(t *testing.T, firewallID string) {
- for i := 0; i < 10; i++ {
- err := firewalls.Get(base.Client, firewallID).Err
- if err != nil {
- httpStatus := err.(*gophercloud.UnexpectedResponseCodeError)
- if httpStatus.Actual == 404 {
- return
- }
- }
- time.Sleep(time.Second)
+func TestFirewallCRUD(t *testing.T) {
+ client, err := clients.NewNetworkV2Client()
+ if err != nil {
+ t.Fatalf("Unable to create a network client: %v", err)
}
+
+ rule, err := CreateRule(t, client)
+ if err != nil {
+ t.Fatalf("Unable to create rule: %v", err)
+ }
+ defer DeleteRule(t, client, rule.ID)
+
+ PrintRule(t, rule)
+
+ policy, err := CreatePolicy(t, client, rule.ID)
+ if err != nil {
+ t.Fatalf("Unable to create policy: %v", err)
+ }
+ defer DeletePolicy(t, client, policy.ID)
+
+ PrintPolicy(t, policy)
+
+ firewall, err := CreateFirewall(t, client, policy.ID)
+ if err != nil {
+ t.Fatalf("Unable to create firewall: %v", err)
+ }
+ defer DeleteFirewall(t, client, firewall.ID)
+
+ PrintFirewall(t, firewall)
+
+ updateOpts := firewalls.UpdateOpts{
+ PolicyID: policy.ID,
+ Description: "Some firewall description",
+ }
+
+ _, err = firewalls.Update(client, firewall.ID, updateOpts).Extract()
+ if err != nil {
+ t.Fatalf("Unable to update firewall: %v", err)
+ }
+
+ newFirewall, err := firewalls.Get(client, firewall.ID).Extract()
+ if err != nil {
+ t.Fatalf("Unable to get firewall: %v", err)
+ }
+
+ PrintFirewall(t, newFirewall)
}
diff --git a/acceptance/openstack/networking/v2/extensions/fwaas/fwaas.go b/acceptance/openstack/networking/v2/extensions/fwaas/fwaas.go
new file mode 100644
index 0000000..64ce402
--- /dev/null
+++ b/acceptance/openstack/networking/v2/extensions/fwaas/fwaas.go
@@ -0,0 +1,210 @@
+package fwaas
+
+import (
+ "fmt"
+ "strconv"
+ "testing"
+
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/acceptance/tools"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/fwaas/firewalls"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/fwaas/policies"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/fwaas/rules"
+)
+
+// CreateFirewall will create a Firewaill with a random name and a specified
+// policy ID. An error will be returned if the firewall could not be created.
+func CreateFirewall(t *testing.T, client *gophercloud.ServiceClient, policyID string) (*firewalls.Firewall, error) {
+ firewallName := tools.RandomString("TESTACC-", 8)
+
+ t.Logf("Attempting to create firewall %s", firewallName)
+
+ createOpts := firewalls.CreateOpts{
+ Name: firewallName,
+ PolicyID: policyID,
+ }
+
+ firewall, err := firewalls.Create(client, createOpts).Extract()
+ if err != nil {
+ return firewall, err
+ }
+
+ t.Logf("Waiting for firewall to become active.")
+ if err := WaitForFirewallState(client, firewall.ID, "ACTIVE", 60); err != nil {
+ return firewall, err
+ }
+
+ t.Logf("Successfully created firewall %s", firewallName)
+
+ return firewall, nil
+}
+
+// CreatePolicy will create a Firewall Policy with a random name and given
+// rule. An error will be returned if the rule could not be created.
+func CreatePolicy(t *testing.T, client *gophercloud.ServiceClient, ruleID string) (*policies.Policy, error) {
+ policyName := tools.RandomString("TESTACC-", 8)
+
+ t.Logf("Attempting to create policy %s", policyName)
+
+ createOpts := policies.CreateOpts{
+ Name: policyName,
+ Rules: []string{
+ ruleID,
+ },
+ }
+
+ policy, err := policies.Create(client, createOpts).Extract()
+ if err != nil {
+ return policy, err
+ }
+
+ t.Logf("Successfully created policy %s", policyName)
+
+ return policy, nil
+}
+
+// CreateRule will create a Firewall Rule with a random source address and
+//source port, destination address and port. An error will be returned if
+// the rule could not be created.
+func CreateRule(t *testing.T, client *gophercloud.ServiceClient) (*rules.Rule, error) {
+ ruleName := tools.RandomString("TESTACC-", 8)
+ sourceAddress := fmt.Sprintf("192.168.1.%d", tools.RandomInt(1, 100))
+ sourcePort := strconv.Itoa(tools.RandomInt(1, 100))
+ destinationAddress := fmt.Sprintf("192.168.2.%d", tools.RandomInt(1, 100))
+ destinationPort := strconv.Itoa(tools.RandomInt(1, 100))
+
+ t.Logf("Attempting to create rule %s with source %s:%s and destination %s:%s",
+ ruleName, sourceAddress, sourcePort, destinationAddress, destinationPort)
+
+ createOpts := rules.CreateOpts{
+ Name: ruleName,
+ Protocol: "tcp",
+ Action: "allow",
+ SourceIPAddress: sourceAddress,
+ SourcePort: sourcePort,
+ DestinationIPAddress: destinationAddress,
+ DestinationPort: destinationPort,
+ }
+
+ rule, err := rules.Create(client, createOpts).Extract()
+ if err != nil {
+ return rule, err
+ }
+
+ t.Logf("Rule %s successfully created", ruleName)
+
+ return rule, nil
+}
+
+// DeleteFirewall will delete a firewall with a specified ID. A fatal error
+// will occur if the delete was not successful. This works best when used as
+// a deferred function.
+func DeleteFirewall(t *testing.T, client *gophercloud.ServiceClient, firewallID string) {
+ t.Logf("Attempting to delete firewall: %s", firewallID)
+
+ err := firewalls.Delete(client, firewallID).ExtractErr()
+ if err != nil {
+ t.Fatalf("Unable to delete firewall %s: %v", firewallID, err)
+ }
+
+ t.Logf("Waiting for firewall to delete.")
+ if err := WaitForFirewallState(client, firewallID, "DELETED", 60); err != nil {
+ t.Logf("Unable to delete firewall: %s", firewallID)
+ }
+
+ t.Logf("Firewall deleted: %s", firewallID)
+}
+
+// DeletePolicy will delete a policy with a specified ID. A fatal error will
+// occur if the delete was not successful. This works best when used as a
+// deferred function.
+func DeletePolicy(t *testing.T, client *gophercloud.ServiceClient, policyID string) {
+ t.Logf("Attempting to delete policy: %s", policyID)
+
+ err := policies.Delete(client, policyID).ExtractErr()
+ if err != nil {
+ t.Fatalf("Unable to delete policy %s: %v", policyID, err)
+ }
+
+ t.Logf("Deleted policy: %s", policyID)
+}
+
+// DeleteRule will delete a rule with a specified ID. A fatal error will occur
+// if the delete was not successful. This works best when used as a deferred
+// function.
+func DeleteRule(t *testing.T, client *gophercloud.ServiceClient, ruleID string) {
+ t.Logf("Attempting to delete rule: %s", ruleID)
+
+ err := rules.Delete(client, ruleID).ExtractErr()
+ if err != nil {
+ t.Fatalf("Unable to delete rule %s: %v", ruleID, err)
+ }
+
+ t.Logf("Deleted rule: %s", ruleID)
+}
+
+// PrintFirewall will print a firewall and all of its attributes.
+func PrintFirewall(t *testing.T, firewall *firewalls.Firewall) {
+ t.Logf("ID: %s", firewall.ID)
+ t.Logf("Name: %s", firewall.Name)
+ t.Logf("Description: %s", firewall.Description)
+ t.Logf("AdminStateUp: %t", firewall.AdminStateUp)
+ t.Logf("Status: %s", firewall.Status)
+ t.Logf("PolicyID: %s", firewall.PolicyID)
+ t.Logf("TenantID: %s", firewall.TenantID)
+}
+
+// PrintPolicy will print a policy and all of its attributes.
+func PrintPolicy(t *testing.T, policy *policies.Policy) {
+ t.Logf("ID: %s", policy.ID)
+ t.Logf("Name: %s", policy.Name)
+ t.Logf("Description: %s", policy.Description)
+ t.Logf("TenantID: %s", policy.TenantID)
+ t.Logf("Audited: %t", policy.Audited)
+ t.Logf("Shared: %t", policy.Shared)
+ t.Logf("Rules:")
+
+ for _, rule := range policy.Rules {
+ t.Logf("Rule ID: %s", rule)
+ }
+}
+
+// PrintRule will print a rule and all of its attributes.
+func PrintRule(t *testing.T, rule *rules.Rule) {
+ t.Logf("ID: %s", rule.ID)
+ t.Logf("Name: %s", rule.Name)
+ t.Logf("Description: %s", rule.Description)
+ t.Logf("Protocol: %s", rule.Protocol)
+ t.Logf("Action: %s", rule.Action)
+ t.Logf("IPVersion: %d", rule.IPVersion)
+ t.Logf("SourceIPAddress: %s", rule.SourceIPAddress)
+ t.Logf("DestinationIPAddress: %s", rule.DestinationIPAddress)
+ t.Logf("Shared: %t", rule.Shared)
+ t.Logf("Enabled: %t", rule.Enabled)
+ t.Logf("PolicyID: %s", rule.PolicyID)
+ t.Logf("Position: %d", rule.Position)
+ t.Logf("TenantID: %s", rule.TenantID)
+}
+
+// WaitForFirewallState will wait until a firewall reaches a given state.
+func WaitForFirewallState(client *gophercloud.ServiceClient, firewallID, status string, secs int) error {
+ return gophercloud.WaitFor(secs, func() (bool, error) {
+ current, err := firewalls.Get(client, firewallID).Extract()
+ if err != nil {
+ if httpStatus, ok := err.(gophercloud.ErrDefault404); ok {
+ if httpStatus.Actual == 404 {
+ if status == "DELETED" {
+ return true, nil
+ }
+ }
+ }
+ return false, err
+ }
+
+ if current.Status == status {
+ return true, nil
+ }
+
+ return false, nil
+ })
+}
diff --git a/acceptance/openstack/networking/v2/extensions/fwaas/policy_test.go b/acceptance/openstack/networking/v2/extensions/fwaas/policy_test.go
index 84bae52..9003e54 100644
--- a/acceptance/openstack/networking/v2/extensions/fwaas/policy_test.go
+++ b/acceptance/openstack/networking/v2/extensions/fwaas/policy_test.go
@@ -5,103 +5,66 @@
import (
"testing"
- base "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2"
+ "github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/fwaas/policies"
- "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/fwaas/rules"
- "github.com/gophercloud/gophercloud/pagination"
- th "github.com/gophercloud/gophercloud/testhelper"
)
-func firewallPolicySetup(t *testing.T) string {
- base.Setup(t)
- return createRule(t, &rules.CreateOpts{
- Protocol: "tcp",
- Action: "allow",
- })
+func TestPolicyList(t *testing.T) {
+ client, err := clients.NewNetworkV2Client()
+ if err != nil {
+ t.Fatalf("Unable to create a network client: %v", err)
+ }
+
+ allPages, err := policies.List(client, nil).AllPages()
+ if err != nil {
+ t.Fatalf("Unable to list policies: %v", err)
+ }
+
+ allPolicies, err := policies.ExtractPolicies(allPages)
+ if err != nil {
+ t.Fatalf("Unable to extract policies: %v", err)
+ }
+
+ for _, policy := range allPolicies {
+ PrintPolicy(t, &policy)
+ }
}
-func firewallPolicyTeardown(t *testing.T, ruleID string) {
- defer base.Teardown()
- deleteRule(t, ruleID)
-}
+func TestPolicyCRUD(t *testing.T) {
+ client, err := clients.NewNetworkV2Client()
+ if err != nil {
+ t.Fatalf("Unable to create a network client: %v", err)
+ }
-func TestFirewallPolicy(t *testing.T) {
- ruleID := firewallPolicySetup(t)
- defer firewallPolicyTeardown(t, ruleID)
+ rule, err := CreateRule(t, client)
+ if err != nil {
+ t.Fatalf("Unable to create rule: %v", err)
+ }
+ defer DeleteRule(t, client, rule.ID)
- policyID := createPolicy(t, &policies.CreateOpts{
- Name: "gophercloud test",
- Description: "acceptance test",
- Rules: []string{
- ruleID,
- },
- })
+ PrintRule(t, rule)
- listPolicies(t)
+ policy, err := CreatePolicy(t, client, rule.ID)
+ if err != nil {
+ t.Fatalf("Unable to create policy: %v", err)
+ }
+ defer DeletePolicy(t, client, policy.ID)
- updatePolicy(t, policyID, &policies.UpdateOpts{
- Description: "acceptance test updated",
- })
+ PrintPolicy(t, policy)
- getPolicy(t, policyID)
+ updateOpts := policies.UpdateOpts{
+ Description: "Some policy description",
+ }
- removeRuleFromPolicy(t, policyID, ruleID)
+ _, err = policies.Update(client, policy.ID, updateOpts).Extract()
+ if err != nil {
+ t.Fatalf("Unable to update policy: %v", err)
+ }
- addRuleToPolicy(t, policyID, ruleID)
+ newPolicy, err := policies.Get(client, policy.ID).Extract()
+ if err != nil {
+ t.Fatalf("Unable to get policy: %v", err)
+ }
- deletePolicy(t, policyID)
-}
-
-func createPolicy(t *testing.T, opts *policies.CreateOpts) string {
- p, err := policies.Create(base.Client, *opts).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Created policy: %#v", opts)
- return p.ID
-}
-
-func listPolicies(t *testing.T) {
- err := policies.List(base.Client, policies.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
- policyList, err := policies.ExtractPolicies(page)
- if err != nil {
- t.Errorf("Failed to extract policies: %v", err)
- return false, err
- }
-
- for _, p := range policyList {
- t.Logf("Listing policies: ID [%s]", p.ID)
- }
-
- return true, nil
- })
- th.AssertNoErr(t, err)
-}
-
-func updatePolicy(t *testing.T, policyID string, opts *policies.UpdateOpts) {
- p, err := policies.Update(base.Client, policyID, *opts).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Updated policy ID [%s]", p.ID)
-}
-
-func removeRuleFromPolicy(t *testing.T, policyID string, ruleID string) {
- err := policies.RemoveRule(base.Client, policyID, ruleID)
- th.AssertNoErr(t, err)
- t.Logf("Removed rule [%s] from policy ID [%s]", ruleID, policyID)
-}
-
-func addRuleToPolicy(t *testing.T, policyID string, ruleID string) {
- err := policies.InsertRule(base.Client, policyID, ruleID, "", "")
- th.AssertNoErr(t, err)
- t.Logf("Inserted rule [%s] into policy ID [%s]", ruleID, policyID)
-}
-
-func getPolicy(t *testing.T, policyID string) {
- p, err := policies.Get(base.Client, policyID).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Getting policy ID [%s]", p.ID)
-}
-
-func deletePolicy(t *testing.T, policyID string) {
- res := policies.Delete(base.Client, policyID)
- th.AssertNoErr(t, res.Err)
- t.Logf("Deleted policy %s", policyID)
+ PrintPolicy(t, newPolicy)
}
diff --git a/acceptance/openstack/networking/v2/extensions/fwaas/rule_test.go b/acceptance/openstack/networking/v2/extensions/fwaas/rule_test.go
index aa11ec6..c8e67dc 100644
--- a/acceptance/openstack/networking/v2/extensions/fwaas/rule_test.go
+++ b/acceptance/openstack/networking/v2/extensions/fwaas/rule_test.go
@@ -5,80 +5,59 @@
import (
"testing"
- base "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2"
+ "github.com/gophercloud/gophercloud/acceptance/clients"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/fwaas/rules"
- "github.com/gophercloud/gophercloud/pagination"
- th "github.com/gophercloud/gophercloud/testhelper"
)
-func TestFirewallRules(t *testing.T) {
- base.Setup(t)
- defer base.Teardown()
+func TestRuleList(t *testing.T) {
+ client, err := clients.NewNetworkV2Client()
+ if err != nil {
+ t.Fatalf("Unable to create a network client: %v", err)
+ }
- ruleID := createRule(t, &rules.CreateOpts{
- Name: "gophercloud_test",
- Description: "acceptance test",
- Protocol: "tcp",
- Action: "allow",
- DestinationIPAddress: "192.168.0.0/24",
- DestinationPort: "22",
- })
+ allPages, err := rules.List(client, nil).AllPages()
+ if err != nil {
+ t.Fatalf("Unable to list rules: %v", err)
+ }
- listRules(t)
+ allRules, err := rules.ExtractRules(allPages)
+ if err != nil {
+ t.Fatalf("Unable to extract rules: %v", err)
+ }
- destinationIPAddress := "192.168.1.0/24"
- destinationPort := ""
- sourcePort := "1234"
-
- updateRule(t, ruleID, &rules.UpdateOpts{
- DestinationIPAddress: &destinationIPAddress,
- DestinationPort: &destinationPort,
- SourcePort: &sourcePort,
- })
-
- getRule(t, ruleID)
-
- deleteRule(t, ruleID)
+ for _, rule := range allRules {
+ PrintRule(t, &rule)
+ }
}
-func createRule(t *testing.T, opts *rules.CreateOpts) string {
- r, err := rules.Create(base.Client, *opts).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Created rule: %#v", opts)
- return r.ID
-}
+func TestRuleCRUD(t *testing.T) {
+ client, err := clients.NewNetworkV2Client()
+ if err != nil {
+ t.Fatalf("Unable to create a network client: %v", err)
+ }
-func listRules(t *testing.T) {
- err := rules.List(base.Client, rules.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
- ruleList, err := rules.ExtractRules(page)
- if err != nil {
- t.Errorf("Failed to extract rules: %v", err)
- return false, err
- }
+ rule, err := CreateRule(t, client)
+ if err != nil {
+ t.Fatalf("Unable to create rule: %v", err)
+ }
+ defer DeleteRule(t, client, rule.ID)
- for _, r := range ruleList {
- t.Logf("Listing rules: ID [%s]", r.ID)
- }
+ PrintRule(t, rule)
- return true, nil
- })
- th.AssertNoErr(t, err)
-}
+ ruleDescription := "Some rule description"
+ updateOpts := rules.UpdateOpts{
+ Description: &ruleDescription,
+ }
-func updateRule(t *testing.T, ruleID string, opts *rules.UpdateOpts) {
- r, err := rules.Update(base.Client, ruleID, *opts).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Updated rule ID [%s]", r.ID)
-}
+ _, err = rules.Update(client, rule.ID, updateOpts).Extract()
+ if err != nil {
+ t.Fatalf("Unable to update rule: %v", err)
+ }
-func getRule(t *testing.T, ruleID string) {
- r, err := rules.Get(base.Client, ruleID).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Getting rule ID [%s]", r.ID)
-}
+ newRule, err := rules.Get(client, rule.ID).Extract()
+ if err != nil {
+ t.Fatalf("Unable to get rule: %v", err)
+ }
-func deleteRule(t *testing.T, ruleID string) {
- res := rules.Delete(base.Client, ruleID)
- th.AssertNoErr(t, res.Err)
- t.Logf("Deleted rule %s", ruleID)
+ PrintRule(t, newRule)
}
diff --git a/acceptance/openstack/networking/v2/extensions/layer3/floatingips_test.go b/acceptance/openstack/networking/v2/extensions/layer3/floatingips_test.go
new file mode 100644
index 0000000..cac8983
--- /dev/null
+++ b/acceptance/openstack/networking/v2/extensions/layer3/floatingips_test.go
@@ -0,0 +1,99 @@
+// +build acceptance networking layer3 floatingips
+
+package layer3
+
+import (
+ "testing"
+
+ "github.com/gophercloud/gophercloud/acceptance/clients"
+ networking "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers"
+)
+
+func TestLayer3FloatingIPsList(t *testing.T) {
+ client, err := clients.NewNetworkV2Client()
+ if err != nil {
+ t.Fatalf("Unable to create a compute client: %v", err)
+ }
+
+ listOpts := floatingips.ListOpts{}
+ allPages, err := floatingips.List(client, listOpts).AllPages()
+ if err != nil {
+ t.Fatalf("Unable to list floating IPs: %v", err)
+ }
+
+ allFIPs, err := floatingips.ExtractFloatingIPs(allPages)
+ if err != nil {
+ t.Fatalf("Unable to extract floating IPs: %v", err)
+ }
+
+ for _, fip := range allFIPs {
+ PrintFloatingIP(t, &fip)
+ }
+}
+
+func TestLayer3FloatingIPsCreateDelete(t *testing.T) {
+ client, err := clients.NewNetworkV2Client()
+ if err != nil {
+ t.Fatalf("Unable to create a compute client: %v", err)
+ }
+
+ choices, err := clients.AcceptanceTestChoicesFromEnv()
+ if err != nil {
+ t.Fatalf("Unable to get choices: %v", err)
+ }
+
+ subnet, err := networking.CreateSubnet(t, client, choices.ExternalNetworkID)
+ if err != nil {
+ t.Fatalf("Unable to create subnet: %v", err)
+ }
+ defer networking.DeleteSubnet(t, client, subnet.ID)
+
+ router, err := CreateExternalRouter(t, client)
+ if err != nil {
+ t.Fatalf("Unable to create router: %v", err)
+ }
+ defer DeleteRouter(t, client, router.ID)
+
+ aiOpts := routers.AddInterfaceOpts{
+ SubnetID: subnet.ID,
+ }
+
+ iface, err := routers.AddInterface(client, router.ID, aiOpts).Extract()
+ if err != nil {
+ t.Fatalf("Unable to add interface to router: %v", err)
+ }
+
+ PrintRouter(t, router)
+ PrintRouterInterface(t, iface)
+
+ port, err := networking.CreatePort(t, client, choices.ExternalNetworkID, subnet.ID)
+ if err != nil {
+ t.Fatalf("Unable to create port: %v", err)
+ }
+ defer networking.DeletePort(t, client, port.ID)
+
+ fip, err := CreateFloatingIP(t, client, choices.ExternalNetworkID, port.ID)
+ if err != nil {
+ t.Fatalf("Unable to create floating IP: %v", err)
+ }
+
+ newFip, err := floatingips.Get(client, fip.ID).Extract()
+ if err != nil {
+ t.Fatalf("Unable to get floating ip: %v", err)
+ }
+
+ PrintFloatingIP(t, newFip)
+
+ DeleteFloatingIP(t, client, fip.ID)
+
+ riOpts := routers.RemoveInterfaceOpts{
+ SubnetID: subnet.ID,
+ }
+
+ _, err = routers.RemoveInterface(client, router.ID, riOpts).Extract()
+ if err != nil {
+ t.Fatalf("Failed to remove interface from router: %v", err)
+ }
+}
diff --git a/acceptance/openstack/networking/v2/extensions/layer3/layer3.go b/acceptance/openstack/networking/v2/extensions/layer3/layer3.go
new file mode 100644
index 0000000..5c6031e
--- /dev/null
+++ b/acceptance/openstack/networking/v2/extensions/layer3/layer3.go
@@ -0,0 +1,157 @@
+package layer3
+
+import (
+ "testing"
+
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/acceptance/clients"
+ "github.com/gophercloud/gophercloud/acceptance/tools"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers"
+)
+
+// CreateFloatingIP creates a floating IP on a given network and port. An error
+// will be returned if the creation failed.
+func CreateFloatingIP(t *testing.T, client *gophercloud.ServiceClient, networkID, portID string) (*floatingips.FloatingIP, error) {
+ t.Logf("Attempting to create floating IP on port: %s", portID)
+
+ createOpts := &floatingips.CreateOpts{
+ FloatingNetworkID: networkID,
+ PortID: portID,
+ }
+
+ floatingIP, err := floatingips.Create(client, createOpts).Extract()
+ if err != nil {
+ return floatingIP, err
+ }
+
+ t.Logf("Created floating IP.")
+
+ return floatingIP, err
+}
+
+// CreateExternalRouter creates a router on the external network. This requires
+// the OS_EXTGW_ID environment variable to be set. An error is returned if the
+// creation failed.
+func CreateExternalRouter(t *testing.T, client *gophercloud.ServiceClient) (*routers.Router, error) {
+ var router *routers.Router
+ choices, err := clients.AcceptanceTestChoicesFromEnv()
+ if err != nil {
+ return router, err
+ }
+
+ routerName := tools.RandomString("TESTACC-", 8)
+
+ t.Logf("Attempting to create router: %s", routerName)
+
+ adminStateUp := true
+ gatewayInfo := routers.GatewayInfo{
+ NetworkID: choices.ExternalNetworkID,
+ }
+
+ createOpts := routers.CreateOpts{
+ Name: routerName,
+ AdminStateUp: &adminStateUp,
+ GatewayInfo: &gatewayInfo,
+ }
+
+ router, err = routers.Create(client, createOpts).Extract()
+ if err != nil {
+ return router, err
+ }
+
+ t.Logf("Created router: %s", routerName)
+
+ return router, nil
+}
+
+// CreateRouter creates a router on a specified Network ID. An error will be
+// returned if the creation failed.
+func CreateRouter(t *testing.T, client *gophercloud.ServiceClient, networkID string) (*routers.Router, error) {
+ routerName := tools.RandomString("TESTACC-", 8)
+
+ t.Logf("Attempting to create router: %s", routerName)
+
+ adminStateUp := true
+ gatewayInfo := routers.GatewayInfo{
+ NetworkID: networkID,
+ }
+
+ createOpts := routers.CreateOpts{
+ Name: routerName,
+ AdminStateUp: &adminStateUp,
+ GatewayInfo: &gatewayInfo,
+ }
+
+ router, err := routers.Create(client, createOpts).Extract()
+ if err != nil {
+ return router, err
+ }
+
+ t.Logf("Created router: %s", routerName)
+
+ return router, nil
+}
+
+// DeleteRouter deletes a router of a specified ID. A fatal error will occur
+// if the deletion failed. This works best when used as a deferred function.
+func DeleteRouter(t *testing.T, client *gophercloud.ServiceClient, routerID string) {
+ t.Logf("Attempting to delete router: %s", routerID)
+
+ err := routers.Delete(client, routerID).ExtractErr()
+ if err != nil {
+ t.Fatalf("Error deleting router: %v", err)
+ }
+
+ t.Logf("Deleted router: %s", routerID)
+}
+
+// DeleteFloatingIP deletes a floatingIP of a specified ID. A fatal error will
+// occur if the deletion failed. This works best when used as a deferred
+// function.
+func DeleteFloatingIP(t *testing.T, client *gophercloud.ServiceClient, floatingIPID string) {
+ t.Logf("Attempting to delete floating IP: %s", floatingIPID)
+
+ err := floatingips.Delete(client, floatingIPID).ExtractErr()
+ if err != nil {
+ t.Fatalf("Failed to delete floating IP: %v", err)
+ }
+
+ t.Logf("Deleted floating IP: %s", floatingIPID)
+}
+
+// PrintFloatingIP prints a floating IP and all of its attributes.
+func PrintFloatingIP(t *testing.T, fip *floatingips.FloatingIP) {
+ t.Logf("ID: %s", fip.ID)
+ t.Logf("FloatingNetworkID: %s", fip.FloatingNetworkID)
+ t.Logf("FloatingIP: %s", fip.FloatingIP)
+ t.Logf("PortID: %s", fip.PortID)
+ t.Logf("FixedIP: %s", fip.FixedIP)
+ t.Logf("TenantID: %s", fip.TenantID)
+ t.Logf("Status: %s", fip.Status)
+}
+
+// PrintRouterInterface prints a router interface and all of its attributes.
+func PrintRouterInterface(t *testing.T, routerInterface *routers.InterfaceInfo) {
+ t.Logf("ID: %s", routerInterface.ID)
+ t.Logf("SubnetID: %s", routerInterface.SubnetID)
+ t.Logf("PortID: %s", routerInterface.PortID)
+ t.Logf("TenantID: %s", routerInterface.TenantID)
+}
+
+// PrintRouter prints a router and all of its attributes.
+func PrintRouter(t *testing.T, router *routers.Router) {
+ t.Logf("ID: %s", router.ID)
+ t.Logf("Status: %s", router.Status)
+ t.Logf("GatewayInfo: %s", router.GatewayInfo)
+ t.Logf("AdminStateUp: %t", router.AdminStateUp)
+ t.Logf("Distributed: %t", router.Distributed)
+ t.Logf("Name: %s", router.Name)
+ t.Logf("TenantID: %s", router.TenantID)
+ t.Logf("Routes:")
+
+ for _, route := range router.Routes {
+ t.Logf("\tNextHop: %s", route.NextHop)
+ t.Logf("\tDestinationCIDR: %s", route.DestinationCIDR)
+ }
+}
diff --git a/acceptance/openstack/networking/v2/extensions/layer3/routers_test.go b/acceptance/openstack/networking/v2/extensions/layer3/routers_test.go
new file mode 100644
index 0000000..67688ec
--- /dev/null
+++ b/acceptance/openstack/networking/v2/extensions/layer3/routers_test.go
@@ -0,0 +1,113 @@
+// +build acceptance networking layer3 router
+
+package layer3
+
+import (
+ "testing"
+
+ "github.com/gophercloud/gophercloud/acceptance/clients"
+ networking "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2"
+ "github.com/gophercloud/gophercloud/acceptance/tools"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers"
+)
+
+func TestLayer3RouterList(t *testing.T) {
+ client, err := clients.NewNetworkV2Client()
+ if err != nil {
+ t.Fatalf("Unable to create a network client: %v", err)
+ }
+
+ listOpts := routers.ListOpts{}
+ allPages, err := routers.List(client, listOpts).AllPages()
+ if err != nil {
+ t.Fatalf("Unable to list routers: %v", err)
+ }
+
+ allRouters, err := routers.ExtractRouters(allPages)
+ if err != nil {
+ t.Fatalf("Unable to extract routers: %v", err)
+ }
+
+ for _, router := range allRouters {
+ PrintRouter(t, &router)
+ }
+}
+
+func TestLayer3RouterCreateDelete(t *testing.T) {
+ client, err := clients.NewNetworkV2Client()
+ if err != nil {
+ t.Fatalf("Unable to create a network client: %v", err)
+ }
+
+ router, err := CreateExternalRouter(t, client)
+ if err != nil {
+ t.Fatalf("Unable to create router: %v", err)
+ }
+ defer DeleteRouter(t, client, router.ID)
+
+ PrintRouter(t, router)
+
+ newName := tools.RandomString("TESTACC-", 8)
+ updateOpts := routers.UpdateOpts{
+ Name: newName,
+ }
+
+ _, err = routers.Update(client, router.ID, updateOpts).Extract()
+ if err != nil {
+ t.Fatalf("Unable to update router: %v", err)
+ }
+
+ newRouter, err := routers.Get(client, router.ID).Extract()
+ if err != nil {
+ t.Fatalf("Unable to get router: %v", err)
+ }
+
+ PrintRouter(t, newRouter)
+}
+
+func TestLayer3RouterInterface(t *testing.T) {
+ client, err := clients.NewNetworkV2Client()
+ if err != nil {
+ t.Fatalf("Unable to create a compute client: %v", err)
+ }
+
+ choices, err := clients.AcceptanceTestChoicesFromEnv()
+ if err != nil {
+ t.Fatalf("Unable to get choices: %v", err)
+ }
+
+ subnet, err := networking.CreateSubnet(t, client, choices.ExternalNetworkID)
+ if err != nil {
+ t.Fatalf("Unable to create subnet: %v", err)
+ }
+ defer networking.DeleteSubnet(t, client, subnet.ID)
+
+ networking.PrintSubnet(t, subnet)
+
+ router, err := CreateExternalRouter(t, client)
+ if err != nil {
+ t.Fatalf("Unable to create router: %v", err)
+ }
+ defer DeleteRouter(t, client, router.ID)
+
+ aiOpts := routers.AddInterfaceOpts{
+ SubnetID: subnet.ID,
+ }
+
+ iface, err := routers.AddInterface(client, router.ID, aiOpts).Extract()
+ if err != nil {
+ t.Fatalf("Failed to add interface to router: %v", err)
+ }
+
+ PrintRouter(t, router)
+ PrintRouterInterface(t, iface)
+
+ riOpts := routers.RemoveInterfaceOpts{
+ SubnetID: subnet.ID,
+ }
+
+ _, err = routers.RemoveInterface(client, router.ID, riOpts).Extract()
+ if err != nil {
+ t.Fatalf("Failed to remove interface from router: %v", err)
+ }
+}
diff --git a/acceptance/openstack/networking/v2/extensions/layer3_test.go b/acceptance/openstack/networking/v2/extensions/layer3_test.go
deleted file mode 100644
index 7d9dba3..0000000
--- a/acceptance/openstack/networking/v2/extensions/layer3_test.go
+++ /dev/null
@@ -1,300 +0,0 @@
-// +build acceptance networking layer3ext
-
-package extensions
-
-import (
- "testing"
-
- base "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2"
- "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/external"
- "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips"
- "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers"
- "github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
- "github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
- "github.com/gophercloud/gophercloud/openstack/networking/v2/subnets"
- "github.com/gophercloud/gophercloud/pagination"
- th "github.com/gophercloud/gophercloud/testhelper"
-)
-
-const (
- cidr1 = "10.0.0.1/24"
- cidr2 = "20.0.0.1/24"
-)
-
-func TestAll(t *testing.T) {
- base.Setup(t)
- defer base.Teardown()
-
- testRouter(t)
- testFloatingIP(t)
-}
-
-func testRouter(t *testing.T) {
- // Setup: Create network
- networkID := createNetwork(t)
-
- // Create router
- routerID := createRouter(t, networkID)
-
- // Lists routers
- listRouters(t)
-
- // Update router
- updateRouter(t, routerID)
-
- // Get router
- getRouter(t, routerID)
-
- // Create new subnet. Note: this subnet will be deleted when networkID is deleted
- subnetID := createSubnet(t, networkID, cidr2)
-
- // Add interface
- addInterface(t, routerID, subnetID)
-
- // Remove interface
- removeInterface(t, routerID, subnetID)
-
- // Delete router
- deleteRouter(t, routerID)
-
- // Cleanup
- deleteNetwork(t, networkID)
-}
-
-func testFloatingIP(t *testing.T) {
- // Setup external network
- extNetworkID := createNetwork(t)
-
- // Setup internal network, subnet and port
- intNetworkID, subnetID, portID := createInternalTopology(t)
-
- // Now the important part: we need to allow the external network to talk to
- // the internal subnet. For this we need a router that has an interface to
- // the internal subnet.
- routerID := bridgeIntSubnetWithExtNetwork(t, extNetworkID, subnetID)
-
- // Create floating IP
- ipID := createFloatingIP(t, extNetworkID, portID)
-
- // Get floating IP
- getFloatingIP(t, ipID)
-
- // Update floating IP
- updateFloatingIP(t, ipID, portID)
-
- // Delete floating IP
- deleteFloatingIP(t, ipID)
-
- // Remove the internal subnet interface
- removeInterface(t, routerID, subnetID)
-
- // Delete router and external network
- deleteRouter(t, routerID)
- deleteNetwork(t, extNetworkID)
-
- // Delete internal port and network
- deletePort(t, portID)
- deleteNetwork(t, intNetworkID)
-}
-
-func createNetwork(t *testing.T) string {
- t.Logf("Creating a network")
-
- asu := true
- opts := external.CreateOpts{
- Parent: networks.CreateOpts{Name: "sample_network", AdminStateUp: &asu},
- External: true,
- }
- n, err := networks.Create(base.Client, opts).Extract()
-
- th.AssertNoErr(t, err)
-
- if n.ID == "" {
- t.Fatalf("No ID returned when creating a network")
- }
-
- createSubnet(t, n.ID, cidr1)
-
- t.Logf("Network created: ID [%s]", n.ID)
-
- return n.ID
-}
-
-func deleteNetwork(t *testing.T, networkID string) {
- t.Logf("Deleting network %s", networkID)
- networks.Delete(base.Client, networkID)
-}
-
-func deletePort(t *testing.T, portID string) {
- t.Logf("Deleting port %s", portID)
- ports.Delete(base.Client, portID)
-}
-
-func createInternalTopology(t *testing.T) (string, string, string) {
- t.Logf("Creating an internal network (for port)")
- opts := networks.CreateOpts{Name: "internal_network"}
- n, err := networks.Create(base.Client, opts).Extract()
- th.AssertNoErr(t, err)
-
- // A subnet is also needed
- subnetID := createSubnet(t, n.ID, cidr2)
-
- t.Logf("Creating an internal port on network %s", n.ID)
- p, err := ports.Create(base.Client, ports.CreateOpts{
- NetworkID: n.ID,
- Name: "fixed_internal_port",
- }).Extract()
- th.AssertNoErr(t, err)
-
- return n.ID, subnetID, p.ID
-}
-
-func bridgeIntSubnetWithExtNetwork(t *testing.T, networkID, subnetID string) string {
- // Create router with external gateway info
- routerID := createRouter(t, networkID)
-
- // Add interface for internal subnet
- addInterface(t, routerID, subnetID)
-
- return routerID
-}
-
-func createSubnet(t *testing.T, networkID, cidr string) string {
- t.Logf("Creating a subnet for network %s", networkID)
-
- iFalse := false
- s, err := subnets.Create(base.Client, subnets.CreateOpts{
- NetworkID: networkID,
- CIDR: cidr,
- IPVersion: subnets.IPv4,
- Name: "my_subnet",
- EnableDHCP: &iFalse,
- }).Extract()
-
- th.AssertNoErr(t, err)
-
- t.Logf("Subnet created: ID [%s]", s.ID)
-
- return s.ID
-}
-
-func createRouter(t *testing.T, networkID string) string {
- t.Logf("Creating a router for network %s", networkID)
-
- asu := false
- gwi := routers.GatewayInfo{NetworkID: networkID}
- r, err := routers.Create(base.Client, routers.CreateOpts{
- Name: "foo_router",
- AdminStateUp: &asu,
- GatewayInfo: &gwi,
- }).Extract()
-
- th.AssertNoErr(t, err)
-
- if r.ID == "" {
- t.Fatalf("No ID returned when creating a router")
- }
-
- t.Logf("Router created: ID [%s]", r.ID)
-
- return r.ID
-}
-
-func listRouters(t *testing.T) {
- pager := routers.List(base.Client, routers.ListOpts{})
-
- err := pager.EachPage(func(page pagination.Page) (bool, error) {
- routerList, err := routers.ExtractRouters(page)
- th.AssertNoErr(t, err)
-
- for _, r := range routerList {
- t.Logf("Listing router: ID [%s] Name [%s] Status [%s] GatewayInfo [%#v]",
- r.ID, r.Name, r.Status, r.GatewayInfo)
- }
-
- return true, nil
- })
-
- th.AssertNoErr(t, err)
-}
-
-func updateRouter(t *testing.T, routerID string) {
- _, err := routers.Update(base.Client, routerID, routers.UpdateOpts{
- Name: "another_name",
- }).Extract()
-
- th.AssertNoErr(t, err)
-}
-
-func getRouter(t *testing.T, routerID string) {
- r, err := routers.Get(base.Client, routerID).Extract()
-
- th.AssertNoErr(t, err)
-
- t.Logf("Getting router: ID [%s] Name [%s] Status [%s]", r.ID, r.Name, r.Status)
-}
-
-func addInterface(t *testing.T, routerID, subnetID string) {
- ir, err := routers.AddInterface(base.Client, routerID, routers.InterfaceOpts{SubnetID: subnetID}).Extract()
-
- th.AssertNoErr(t, err)
-
- t.Logf("Interface added to router %s: SubnetID [%s] PortID [%s]", routerID, ir.SubnetID, ir.PortID)
-}
-
-func removeInterface(t *testing.T, routerID, subnetID string) {
- ir, err := routers.RemoveInterface(base.Client, routerID, routers.InterfaceOpts{SubnetID: subnetID}).Extract()
-
- th.AssertNoErr(t, err)
-
- t.Logf("Interface %s removed from %s", ir.ID, routerID)
-}
-
-func deleteRouter(t *testing.T, routerID string) {
- t.Logf("Deleting router %s", routerID)
-
- res := routers.Delete(base.Client, routerID)
-
- th.AssertNoErr(t, res.Err)
-}
-
-func createFloatingIP(t *testing.T, networkID, portID string) string {
- t.Logf("Creating floating IP on network [%s] with port [%s]", networkID, portID)
-
- opts := floatingips.CreateOpts{
- FloatingNetworkID: networkID,
- PortID: portID,
- }
-
- ip, err := floatingips.Create(base.Client, opts).Extract()
-
- th.AssertNoErr(t, err)
-
- t.Logf("Floating IP created: ID [%s] Status [%s] Fixed (internal) IP: [%s] Floating (external) IP: [%s]",
- ip.ID, ip.Status, ip.FixedIP, ip.FloatingIP)
-
- return ip.ID
-}
-
-func getFloatingIP(t *testing.T, ipID string) {
- ip, err := floatingips.Get(base.Client, ipID).Extract()
- th.AssertNoErr(t, err)
-
- t.Logf("Getting floating IP: ID [%s] Status [%s]", ip.ID, ip.Status)
-}
-
-func updateFloatingIP(t *testing.T, ipID, portID string) {
- t.Logf("Disassociate all ports from IP %s", ipID)
- _, err := floatingips.Update(base.Client, ipID, floatingips.UpdateOpts{PortID: ""}).Extract()
- th.AssertNoErr(t, err)
-
- t.Logf("Re-associate the port %s", portID)
- _, err = floatingips.Update(base.Client, ipID, floatingips.UpdateOpts{PortID: portID}).Extract()
- th.AssertNoErr(t, err)
-}
-
-func deleteFloatingIP(t *testing.T, ipID string) {
- t.Logf("Deleting IP %s", ipID)
- res := floatingips.Delete(base.Client, ipID)
- th.AssertNoErr(t, res.Err)
-}
diff --git a/acceptance/openstack/networking/v2/extensions/lbaas/common.go b/acceptance/openstack/networking/v2/extensions/lbaas/common.go
deleted file mode 100644
index 760ee5b..0000000
--- a/acceptance/openstack/networking/v2/extensions/lbaas/common.go
+++ /dev/null
@@ -1,80 +0,0 @@
-package lbaas
-
-import (
- "testing"
-
- "github.com/gophercloud/gophercloud"
- base "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2"
- "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/monitors"
- "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/pools"
- "github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
- "github.com/gophercloud/gophercloud/openstack/networking/v2/subnets"
- th "github.com/gophercloud/gophercloud/testhelper"
-)
-
-func SetupTopology(t *testing.T) (string, string) {
- // create network
- n, err := networks.Create(base.Client, networks.CreateOpts{Name: "tmp_network"}).Extract()
- th.AssertNoErr(t, err)
-
- t.Logf("Created network %s", n.ID)
-
- // create subnet
- s, err := subnets.Create(base.Client, subnets.CreateOpts{
- NetworkID: n.ID,
- CIDR: "192.168.199.0/24",
- IPVersion: gophercloud.IPv4,
- Name: "tmp_subnet",
- }).Extract()
- th.AssertNoErr(t, err)
-
- t.Logf("Created subnet %s", s.ID)
-
- return n.ID, s.ID
-}
-
-func DeleteTopology(t *testing.T, networkID string) {
- res := networks.Delete(base.Client, networkID)
- th.AssertNoErr(t, res.Err)
- t.Logf("Deleted network %s", networkID)
-}
-
-func CreatePool(t *testing.T, subnetID string) string {
- p, err := pools.Create(base.Client, pools.CreateOpts{
- LBMethod: pools.LBMethodRoundRobin,
- Protocol: "HTTP",
- Name: "tmp_pool",
- SubnetID: subnetID,
- Provider: "haproxy",
- }).Extract()
-
- th.AssertNoErr(t, err)
-
- t.Logf("Created pool %s", p.ID)
-
- return p.ID
-}
-
-func DeletePool(t *testing.T, poolID string) {
- res := pools.Delete(base.Client, poolID)
- th.AssertNoErr(t, res.Err)
- t.Logf("Deleted pool %s", poolID)
-}
-
-func CreateMonitor(t *testing.T) string {
- m, err := monitors.Create(base.Client, monitors.CreateOpts{
- Delay: 10,
- Timeout: 10,
- MaxRetries: 3,
- Type: monitors.TypeHTTP,
- ExpectedCodes: "200",
- URLPath: "/login",
- HTTPMethod: "GET",
- }).Extract()
-
- th.AssertNoErr(t, err)
-
- t.Logf("Created monitor ID [%s]", m.ID)
-
- return m.ID
-}
diff --git a/acceptance/openstack/networking/v2/extensions/lbaas/lbaas.go b/acceptance/openstack/networking/v2/extensions/lbaas/lbaas.go
new file mode 100644
index 0000000..32bfcd4
--- /dev/null
+++ b/acceptance/openstack/networking/v2/extensions/lbaas/lbaas.go
@@ -0,0 +1,220 @@
+package lbaas
+
+import (
+ "fmt"
+ "testing"
+
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/acceptance/tools"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/members"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/monitors"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/pools"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/vips"
+)
+
+// CreateMember will create a load balancer member in a specified pool on a
+// random port. An error will be returned if the member could not be created.
+func CreateMember(t *testing.T, client *gophercloud.ServiceClient, poolID string) (*members.Member, error) {
+ protocolPort := tools.RandomInt(100, 1000)
+ address := tools.RandomInt(2, 200)
+ t.Logf("Attempting to create member in port %d", protocolPort)
+
+ createOpts := members.CreateOpts{
+ PoolID: poolID,
+ ProtocolPort: protocolPort,
+ Address: fmt.Sprintf("192.168.1.%d", address),
+ }
+
+ member, err := members.Create(client, createOpts).Extract()
+ if err != nil {
+ return member, err
+ }
+
+ t.Logf("Successfully created member %s")
+
+ return member, nil
+}
+
+// CreateMonitor will create a monitor with a random name for a specific pool.
+// An error will be returned if the monitor could not be created.
+func CreateMonitor(t *testing.T, client *gophercloud.ServiceClient) (*monitors.Monitor, error) {
+ t.Logf("Attempting to create monitor.")
+
+ createOpts := monitors.CreateOpts{
+ Type: monitors.TypePING,
+ Delay: 90,
+ Timeout: 60,
+ MaxRetries: 10,
+ AdminStateUp: gophercloud.Enabled,
+ }
+
+ monitor, err := monitors.Create(client, createOpts).Extract()
+ if err != nil {
+ return monitor, err
+ }
+
+ t.Logf("Successfully created monitor")
+
+ return monitor, nil
+}
+
+// CreatePool will create a pool with a random name. An error will be returned
+// if the pool could not be deleted.
+func CreatePool(t *testing.T, client *gophercloud.ServiceClient, subnetID string) (*pools.Pool, error) {
+ poolName := tools.RandomString("TESTACCT-", 8)
+
+ t.Logf("Attempting to create pool %s", poolName)
+
+ createOpts := pools.CreateOpts{
+ Name: poolName,
+ SubnetID: subnetID,
+ Protocol: pools.ProtocolTCP,
+ LBMethod: pools.LBMethodRoundRobin,
+ }
+
+ pool, err := pools.Create(client, createOpts).Extract()
+ if err != nil {
+ return pool, err
+ }
+
+ t.Logf("Successfully created pool %s", poolName)
+
+ return pool, nil
+}
+
+// CreateVIP will create a vip with a random name and a random port in a
+// specified subnet and pool. An error will be returned if the vip could
+// not be created.
+func CreateVIP(t *testing.T, client *gophercloud.ServiceClient, subnetID, poolID string) (*vips.VirtualIP, error) {
+ vipName := tools.RandomString("TESTACCT-", 8)
+ vipPort := tools.RandomInt(100, 10000)
+
+ t.Logf("Attempting to create VIP %s", vipName)
+
+ createOpts := vips.CreateOpts{
+ Name: vipName,
+ SubnetID: subnetID,
+ PoolID: poolID,
+ Protocol: "TCP",
+ ProtocolPort: vipPort,
+ }
+
+ vip, err := vips.Create(client, createOpts).Extract()
+ if err != nil {
+ return vip, err
+ }
+
+ t.Logf("Successfully created vip %s", vipName)
+
+ return vip, nil
+}
+
+// DeleteMember will delete a specified member. A fatal error will occur if
+// the member could not be deleted. This works best when used as a deferred
+// function.
+func DeleteMember(t *testing.T, client *gophercloud.ServiceClient, memberID string) {
+ t.Logf("Attempting to delete member %s", memberID)
+
+ if err := members.Delete(client, memberID).ExtractErr(); err != nil {
+ t.Fatalf("Unable to delete member: %v", err)
+ }
+
+ t.Logf("Successfully deleted member %s", memberID)
+}
+
+// DeleteMonitor will delete a specified monitor. A fatal error will occur if
+// the monitor could not be deleted. This works best when used as a deferred
+// function.
+func DeleteMonitor(t *testing.T, client *gophercloud.ServiceClient, monitorID string) {
+ t.Logf("Attempting to delete monitor %s", monitorID)
+
+ if err := monitors.Delete(client, monitorID).ExtractErr(); err != nil {
+ t.Fatalf("Unable to delete monitor: %v", err)
+ }
+
+ t.Logf("Successfully deleted monitor %s", monitorID)
+}
+
+// DeletePool will delete a specified pool. A fatal error will occur if the
+// pool could not be deleted. This works best when used as a deferred function.
+func DeletePool(t *testing.T, client *gophercloud.ServiceClient, poolID string) {
+ t.Logf("Attempting to delete pool %s", poolID)
+
+ if err := pools.Delete(client, poolID).ExtractErr(); err != nil {
+ t.Fatalf("Unable to delete pool: %v", err)
+ }
+
+ t.Logf("Successfully deleted pool %s", poolID)
+}
+
+// DeleteVIP will delete a specified vip. A fatal error will occur if the vip
+// could not be deleted. This works best when used as a deferred function.
+func DeleteVIP(t *testing.T, client *gophercloud.ServiceClient, vipID string) {
+ t.Logf("Attempting to delete vip %s", vipID)
+
+ if err := vips.Delete(client, vipID).ExtractErr(); err != nil {
+ t.Fatalf("Unable to delete vip: %v", err)
+ }
+
+ t.Logf("Successfully deleted vip %s", vipID)
+}
+
+// PrintMember will print a member and all of its attributes.
+func PrintMember(t *testing.T, member *members.Member) {
+ t.Logf("ID: %s", member.ID)
+ t.Logf("TenantID: %s", member.TenantID)
+ t.Logf("Status: %s", member.Status)
+ t.Logf("Weight: %d", member.Weight)
+ t.Logf("AdminStateUp: %t", member.AdminStateUp)
+ t.Logf("PoolID: %s", member.PoolID)
+ t.Logf("Address: %s", member.Address)
+ t.Logf("ProtocolPort: %s", member.ProtocolPort)
+}
+
+// PrintMonitor will print a monitor and all of its attributes.
+func PrintMonitor(t *testing.T, monitor *monitors.Monitor) {
+ t.Logf("ID: %s", monitor.ID)
+ t.Logf("Name: %s", monitor.Name)
+ t.Logf("TenantID: %s", monitor.TenantID)
+ t.Logf("Status: %s", monitor.Status)
+ t.Logf("Type: %s", monitor.Type)
+ t.Logf("Delay: %d", monitor.Delay)
+ t.Logf("Timeout: %d", monitor.Timeout)
+ t.Logf("MaxRetries: %d", monitor.MaxRetries)
+ t.Logf("HTTPMethod: %s", monitor.HTTPMethod)
+ t.Logf("URLPath: %s", monitor.URLPath)
+ t.Logf("ExpectedCodes: %s", monitor.ExpectedCodes)
+ t.Logf("AdminStateUp: %t", monitor.AdminStateUp)
+}
+
+// PrintPool will print a pool and all of its attributes.
+func PrintPool(t *testing.T, pool *pools.Pool) {
+ t.Logf("ID: %s", pool.ID)
+ t.Logf("Name: %s", pool.Name)
+ t.Logf("TenantID: %s", pool.TenantID)
+ t.Logf("Status: %s", pool.Status)
+ t.Logf("LBMethod: %s", pool.LBMethod)
+ t.Logf("Description: %s", pool.Description)
+ t.Logf("SubnetID: %s", pool.SubnetID)
+ t.Logf("AdminStateUp: %t", pool.AdminStateUp)
+ t.Logf("MonitorIDs: %s", pool.MonitorIDs)
+ t.Logf("MemberIDs: %s", pool.MemberIDs)
+}
+
+// PrintVIP will print a vip and all of its attributes.
+func PrintVIP(t *testing.T, vip *vips.VirtualIP) {
+ t.Logf("ID: %s", vip.ID)
+ t.Logf("Name: %s", vip.Name)
+ t.Logf("TenantID: %s", vip.TenantID)
+ t.Logf("Status: %s", vip.Status)
+ t.Logf("Description: %s", vip.Description)
+ t.Logf("SubnetID: %s", vip.SubnetID)
+ t.Logf("Address: %s", vip.Address)
+ t.Logf("Protocol: %s", vip.Protocol)
+ t.Logf("ProtocolPort: %d", vip.ProtocolPort)
+ t.Logf("PoolID: %s", vip.PoolID)
+ t.Logf("PortID: %s", vip.PortID)
+ t.Logf("Persistence: %s", vip.Persistence)
+ t.Logf("ConnLimit: %d", vip.ConnLimit)
+ t.Logf("AdminStateUp: %t", vip.AdminStateUp)
+}
diff --git a/acceptance/openstack/networking/v2/extensions/lbaas/member_test.go b/acceptance/openstack/networking/v2/extensions/lbaas/member_test.go
deleted file mode 100644
index dce3bbb..0000000
--- a/acceptance/openstack/networking/v2/extensions/lbaas/member_test.go
+++ /dev/null
@@ -1,95 +0,0 @@
-// +build acceptance networking lbaas lbaasmember
-
-package lbaas
-
-import (
- "testing"
-
- base "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2"
- "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/members"
- "github.com/gophercloud/gophercloud/pagination"
- th "github.com/gophercloud/gophercloud/testhelper"
-)
-
-func TestMembers(t *testing.T) {
- base.Setup(t)
- defer base.Teardown()
-
- // setup
- networkID, subnetID := SetupTopology(t)
- poolID := CreatePool(t, subnetID)
-
- // create member
- memberID := createMember(t, poolID)
-
- // list members
- listMembers(t)
-
- // update member
- updateMember(t, memberID)
-
- // get member
- getMember(t, memberID)
-
- // delete member
- deleteMember(t, memberID)
-
- // teardown
- DeletePool(t, poolID)
- DeleteTopology(t, networkID)
-}
-
-func createMember(t *testing.T, poolID string) string {
- m, err := members.Create(base.Client, members.CreateOpts{
- Address: "192.168.199.1",
- ProtocolPort: 8080,
- PoolID: poolID,
- }).Extract()
-
- th.AssertNoErr(t, err)
-
- t.Logf("Created member: ID [%s] Status [%s] Weight [%d] Address [%s] Port [%d]",
- m.ID, m.Status, m.Weight, m.Address, m.ProtocolPort)
-
- return m.ID
-}
-
-func listMembers(t *testing.T) {
- err := members.List(base.Client, members.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
- memberList, err := members.ExtractMembers(page)
- if err != nil {
- t.Errorf("Failed to extract members: %v", err)
- return false, err
- }
-
- for _, m := range memberList {
- t.Logf("Listing member: ID [%s] Status [%s]", m.ID, m.Status)
- }
-
- return true, nil
- })
-
- th.AssertNoErr(t, err)
-}
-
-func updateMember(t *testing.T, memberID string) {
- m, err := members.Update(base.Client, memberID, members.UpdateOpts{AdminStateUp: true}).Extract()
-
- th.AssertNoErr(t, err)
-
- t.Logf("Updated member ID [%s]", m.ID)
-}
-
-func getMember(t *testing.T, memberID string) {
- m, err := members.Get(base.Client, memberID).Extract()
-
- th.AssertNoErr(t, err)
-
- t.Logf("Getting member ID [%s]", m.ID)
-}
-
-func deleteMember(t *testing.T, memberID string) {
- res := members.Delete(base.Client, memberID)
- th.AssertNoErr(t, res.Err)
- t.Logf("Deleted member %s", memberID)
-}
diff --git a/acceptance/openstack/networking/v2/extensions/lbaas/members_test.go b/acceptance/openstack/networking/v2/extensions/lbaas/members_test.go
new file mode 100644
index 0000000..004036e
--- /dev/null
+++ b/acceptance/openstack/networking/v2/extensions/lbaas/members_test.go
@@ -0,0 +1,82 @@
+// +build acceptance networking lbaas member
+
+package lbaas
+
+import (
+ "testing"
+
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/acceptance/clients"
+ networking "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/members"
+)
+
+func TestMembersList(t *testing.T) {
+ client, err := clients.NewNetworkV2Client()
+ if err != nil {
+ t.Fatalf("Unable to create a network client: %v", err)
+ }
+
+ allPages, err := members.List(client, members.ListOpts{}).AllPages()
+ if err != nil {
+ t.Fatalf("Unable to list members: %v", err)
+ }
+
+ allMembers, err := members.ExtractMembers(allPages)
+ if err != nil {
+ t.Fatalf("Unable to extract members: %v", err)
+ }
+
+ for _, member := range allMembers {
+ PrintMember(t, &member)
+ }
+}
+
+func TestMembersCRUD(t *testing.T) {
+ client, err := clients.NewNetworkV2Client()
+ if err != nil {
+ t.Fatalf("Unable to create a network client: %v", err)
+ }
+
+ network, err := networking.CreateNetwork(t, client)
+ if err != nil {
+ t.Fatalf("Unable to create network: %v", err)
+ }
+ defer networking.DeleteNetwork(t, client, network.ID)
+
+ subnet, err := networking.CreateSubnet(t, client, network.ID)
+ if err != nil {
+ t.Fatalf("Unable to create subnet: %v", err)
+ }
+ defer networking.DeleteSubnet(t, client, subnet.ID)
+
+ pool, err := CreatePool(t, client, subnet.ID)
+ if err != nil {
+ t.Fatalf("Unable to create pool: %v", err)
+ }
+ defer DeletePool(t, client, pool.ID)
+
+ member, err := CreateMember(t, client, pool.ID)
+ if err != nil {
+ t.Fatalf("Unable to create member: %v", err)
+ }
+ defer DeleteMember(t, client, member.ID)
+
+ PrintMember(t, member)
+
+ updateOpts := members.UpdateOpts{
+ AdminStateUp: gophercloud.Enabled,
+ }
+
+ _, err = members.Update(client, member.ID, updateOpts).Extract()
+ if err != nil {
+ t.Fatalf("Unable to update member: %v")
+ }
+
+ newMember, err := members.Get(client, member.ID).Extract()
+ if err != nil {
+ t.Fatalf("Unable to get member: %v")
+ }
+
+ PrintMember(t, newMember)
+}
diff --git a/acceptance/openstack/networking/v2/extensions/lbaas/monitor_test.go b/acceptance/openstack/networking/v2/extensions/lbaas/monitor_test.go
deleted file mode 100644
index e8e7192..0000000
--- a/acceptance/openstack/networking/v2/extensions/lbaas/monitor_test.go
+++ /dev/null
@@ -1,77 +0,0 @@
-// +build acceptance networking lbaas lbaasmonitor
-
-package lbaas
-
-import (
- "testing"
-
- base "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2"
- "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/monitors"
- "github.com/gophercloud/gophercloud/pagination"
- th "github.com/gophercloud/gophercloud/testhelper"
-)
-
-func TestMonitors(t *testing.T) {
- base.Setup(t)
- defer base.Teardown()
-
- // create monitor
- monitorID := CreateMonitor(t)
-
- // list monitors
- listMonitors(t)
-
- // update monitor
- updateMonitor(t, monitorID)
-
- // get monitor
- getMonitor(t, monitorID)
-
- // delete monitor
- deleteMonitor(t, monitorID)
-}
-
-func listMonitors(t *testing.T) {
- err := monitors.List(base.Client, monitors.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
- monitorList, err := monitors.ExtractMonitors(page)
- if err != nil {
- t.Errorf("Failed to extract monitors: %v", err)
- return false, err
- }
-
- for _, m := range monitorList {
- t.Logf("Listing monitor: ID [%s] Type [%s] Delay [%ds] Timeout [%d] Retries [%d] Status [%s]",
- m.ID, m.Type, m.Delay, m.Timeout, m.MaxRetries, m.Status)
- }
-
- return true, nil
- })
-
- th.AssertNoErr(t, err)
-}
-
-func updateMonitor(t *testing.T, monitorID string) {
- opts := monitors.UpdateOpts{Delay: 10, Timeout: 10, MaxRetries: 3}
- m, err := monitors.Update(base.Client, monitorID, opts).Extract()
-
- th.AssertNoErr(t, err)
-
- t.Logf("Updated monitor ID [%s]", m.ID)
-}
-
-func getMonitor(t *testing.T, monitorID string) {
- m, err := monitors.Get(base.Client, monitorID).Extract()
-
- th.AssertNoErr(t, err)
-
- t.Logf("Getting monitor ID [%s]: URL path [%s] HTTP Method [%s] Accepted codes [%s]",
- m.ID, m.URLPath, m.HTTPMethod, m.ExpectedCodes)
-}
-
-func deleteMonitor(t *testing.T, monitorID string) {
- res := monitors.Delete(base.Client, monitorID)
-
- th.AssertNoErr(t, res.Err)
-
- t.Logf("Deleted monitor %s", monitorID)
-}
diff --git a/acceptance/openstack/networking/v2/extensions/lbaas/monitors_test.go b/acceptance/openstack/networking/v2/extensions/lbaas/monitors_test.go
new file mode 100644
index 0000000..e9a7dbb
--- /dev/null
+++ b/acceptance/openstack/networking/v2/extensions/lbaas/monitors_test.go
@@ -0,0 +1,62 @@
+// +build acceptance networking lbaas monitors
+
+package lbaas
+
+import (
+ "testing"
+
+ "github.com/gophercloud/gophercloud/acceptance/clients"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/monitors"
+)
+
+func TestMonitorsList(t *testing.T) {
+ client, err := clients.NewNetworkV2Client()
+ if err != nil {
+ t.Fatalf("Unable to create a network client: %v", err)
+ }
+
+ allPages, err := monitors.List(client, monitors.ListOpts{}).AllPages()
+ if err != nil {
+ t.Fatalf("Unable to list monitors: %v", err)
+ }
+
+ allMonitors, err := monitors.ExtractMonitors(allPages)
+ if err != nil {
+ t.Fatalf("Unable to extract monitors: %v", err)
+ }
+
+ for _, monitor := range allMonitors {
+ PrintMonitor(t, &monitor)
+ }
+}
+
+func TestMonitorsCRUD(t *testing.T) {
+ client, err := clients.NewNetworkV2Client()
+ if err != nil {
+ t.Fatalf("Unable to create a network client: %v", err)
+ }
+
+ monitor, err := CreateMonitor(t, client)
+ if err != nil {
+ t.Fatalf("Unable to create monitor: %v", err)
+ }
+ defer DeleteMonitor(t, client, monitor.ID)
+
+ PrintMonitor(t, monitor)
+
+ updateOpts := monitors.UpdateOpts{
+ Delay: 999,
+ }
+
+ _, err = monitors.Update(client, monitor.ID, updateOpts).Extract()
+ if err != nil {
+ t.Fatalf("Unable to update monitor: %v")
+ }
+
+ newMonitor, err := monitors.Get(client, monitor.ID).Extract()
+ if err != nil {
+ t.Fatalf("Unable to get monitor: %v")
+ }
+
+ PrintMonitor(t, newMonitor)
+}
diff --git a/acceptance/openstack/networking/v2/extensions/lbaas/pool_test.go b/acceptance/openstack/networking/v2/extensions/lbaas/pool_test.go
deleted file mode 100644
index 6151217..0000000
--- a/acceptance/openstack/networking/v2/extensions/lbaas/pool_test.go
+++ /dev/null
@@ -1,98 +0,0 @@
-// +build acceptance networking lbaas lbaaspool
-
-package lbaas
-
-import (
- "testing"
-
- base "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2"
- "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/pools"
- "github.com/gophercloud/gophercloud/pagination"
- th "github.com/gophercloud/gophercloud/testhelper"
-)
-
-func TestPools(t *testing.T) {
- base.Setup(t)
- defer base.Teardown()
-
- // setup
- networkID, subnetID := SetupTopology(t)
-
- // create pool
- poolID := CreatePool(t, subnetID)
-
- // list pools
- listPools(t)
-
- // update pool
- updatePool(t, poolID)
-
- // get pool
- getPool(t, poolID)
-
- // create monitor
- monitorID := CreateMonitor(t)
-
- // associate health monitor
- associateMonitor(t, poolID, monitorID)
-
- // disassociate health monitor
- disassociateMonitor(t, poolID, monitorID)
-
- // delete pool
- DeletePool(t, poolID)
-
- // teardown
- DeleteTopology(t, networkID)
-}
-
-func listPools(t *testing.T) {
- err := pools.List(base.Client, pools.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
- poolList, err := pools.ExtractPools(page)
- if err != nil {
- t.Errorf("Failed to extract pools: %v", err)
- return false, err
- }
-
- for _, p := range poolList {
- t.Logf("Listing pool: ID [%s] Name [%s] Status [%s] LB algorithm [%s] Provider [%s]", p.ID, p.Name, p.Status, p.LBMethod, p.Provider)
- }
-
- return true, nil
- })
-
- th.AssertNoErr(t, err)
-}
-
-func updatePool(t *testing.T, poolID string) {
- opts := pools.UpdateOpts{Name: "SuperPool", LBMethod: pools.LBMethodLeastConnections}
- p, err := pools.Update(base.Client, poolID, opts).Extract()
-
- th.AssertNoErr(t, err)
-
- t.Logf("Updated pool ID [%s]", p.ID)
-}
-
-func getPool(t *testing.T, poolID string) {
- p, err := pools.Get(base.Client, poolID).Extract()
-
- th.AssertNoErr(t, err)
-
- t.Logf("Getting pool ID [%s]", p.ID)
-}
-
-func associateMonitor(t *testing.T, poolID, monitorID string) {
- res := pools.AssociateMonitor(base.Client, poolID, monitorID)
-
- th.AssertNoErr(t, res.Err)
-
- t.Logf("Associated pool %s with monitor %s", poolID, monitorID)
-}
-
-func disassociateMonitor(t *testing.T, poolID, monitorID string) {
- res := pools.DisassociateMonitor(base.Client, poolID, monitorID)
-
- th.AssertNoErr(t, res.Err)
-
- t.Logf("Disassociated pool %s with monitor %s", poolID, monitorID)
-}
diff --git a/acceptance/openstack/networking/v2/extensions/lbaas/pools_test.go b/acceptance/openstack/networking/v2/extensions/lbaas/pools_test.go
new file mode 100644
index 0000000..8af4d19
--- /dev/null
+++ b/acceptance/openstack/networking/v2/extensions/lbaas/pools_test.go
@@ -0,0 +1,117 @@
+// +build acceptance networking lbaas pool
+
+package lbaas
+
+import (
+ "testing"
+
+ "github.com/gophercloud/gophercloud/acceptance/clients"
+ networking "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/pools"
+)
+
+func TestPoolsList(t *testing.T) {
+ client, err := clients.NewNetworkV2Client()
+ if err != nil {
+ t.Fatalf("Unable to create a network client: %v", err)
+ }
+
+ allPages, err := pools.List(client, pools.ListOpts{}).AllPages()
+ if err != nil {
+ t.Fatalf("Unable to list pools: %v", err)
+ }
+
+ allPools, err := pools.ExtractPools(allPages)
+ if err != nil {
+ t.Fatalf("Unable to extract pools: %v", err)
+ }
+
+ for _, pool := range allPools {
+ PrintPool(t, &pool)
+ }
+}
+
+func TestPoolsCRUD(t *testing.T) {
+ client, err := clients.NewNetworkV2Client()
+ if err != nil {
+ t.Fatalf("Unable to create a network client: %v", err)
+ }
+
+ network, err := networking.CreateNetwork(t, client)
+ if err != nil {
+ t.Fatalf("Unable to create network: %v", err)
+ }
+ defer networking.DeleteNetwork(t, client, network.ID)
+
+ subnet, err := networking.CreateSubnet(t, client, network.ID)
+ if err != nil {
+ t.Fatalf("Unable to create subnet: %v", err)
+ }
+ defer networking.DeleteSubnet(t, client, subnet.ID)
+
+ pool, err := CreatePool(t, client, subnet.ID)
+ if err != nil {
+ t.Fatalf("Unable to create pool: %v", err)
+ }
+ defer DeletePool(t, client, pool.ID)
+
+ PrintPool(t, pool)
+
+ updateOpts := pools.UpdateOpts{
+ LBMethod: pools.LBMethodLeastConnections,
+ }
+
+ _, err = pools.Update(client, pool.ID, updateOpts).Extract()
+ if err != nil {
+ t.Fatalf("Unable to update pool: %v")
+ }
+
+ newPool, err := pools.Get(client, pool.ID).Extract()
+ if err != nil {
+ t.Fatalf("Unable to get pool: %v")
+ }
+
+ PrintPool(t, newPool)
+}
+
+func TestPoolsMonitors(t *testing.T) {
+ client, err := clients.NewNetworkV2Client()
+ if err != nil {
+ t.Fatalf("Unable to create a network client: %v", err)
+ }
+
+ network, err := networking.CreateNetwork(t, client)
+ if err != nil {
+ t.Fatalf("Unable to create network: %v", err)
+ }
+ defer networking.DeleteNetwork(t, client, network.ID)
+
+ subnet, err := networking.CreateSubnet(t, client, network.ID)
+ if err != nil {
+ t.Fatalf("Unable to create subnet: %v", err)
+ }
+ defer networking.DeleteSubnet(t, client, subnet.ID)
+
+ pool, err := CreatePool(t, client, subnet.ID)
+ if err != nil {
+ t.Fatalf("Unable to create pool: %v", err)
+ }
+ defer DeletePool(t, client, pool.ID)
+
+ monitor, err := CreateMonitor(t, client)
+ if err != nil {
+ t.Fatalf("Unable to create monitor: %v", err)
+ }
+ defer DeleteMonitor(t, client, monitor.ID)
+
+ t.Logf("Associating monitor %s with pool %s", monitor.ID, pool.ID)
+ if res := pools.AssociateMonitor(client, pool.ID, monitor.ID); res.Err != nil {
+ t.Fatalf("Unable to associate monitor to pool")
+ }
+
+ t.Logf("Disassociating monitor %s with pool %s", monitor.ID, pool.ID)
+ if res := pools.DisassociateMonitor(client, pool.ID, monitor.ID); res.Err != nil {
+ t.Fatalf("Unable to disassociate monitor from pool")
+ }
+
+}
diff --git a/acceptance/openstack/networking/v2/extensions/lbaas/vip_test.go b/acceptance/openstack/networking/v2/extensions/lbaas/vip_test.go
deleted file mode 100644
index d38e9c1..0000000
--- a/acceptance/openstack/networking/v2/extensions/lbaas/vip_test.go
+++ /dev/null
@@ -1,101 +0,0 @@
-// +build acceptance networking lbaas lbaasvip
-
-package lbaas
-
-import (
- "testing"
-
- base "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2"
- "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/vips"
- "github.com/gophercloud/gophercloud/pagination"
- th "github.com/gophercloud/gophercloud/testhelper"
-)
-
-func TestVIPs(t *testing.T) {
- base.Setup(t)
- defer base.Teardown()
-
- // setup
- networkID, subnetID := SetupTopology(t)
- poolID := CreatePool(t, subnetID)
-
- // create VIP
- VIPID := createVIP(t, subnetID, poolID)
-
- // list VIPs
- listVIPs(t)
-
- // update VIP
- updateVIP(t, VIPID)
-
- // get VIP
- getVIP(t, VIPID)
-
- // delete VIP
- deleteVIP(t, VIPID)
-
- // teardown
- DeletePool(t, poolID)
- DeleteTopology(t, networkID)
-}
-
-func createVIP(t *testing.T, subnetID, poolID string) string {
- p, err := vips.Create(base.Client, vips.CreateOpts{
- Protocol: "HTTP",
- Name: "New_VIP",
- AdminStateUp: vips.Up,
- SubnetID: subnetID,
- PoolID: poolID,
- ProtocolPort: 80,
- }).Extract()
-
- th.AssertNoErr(t, err)
-
- t.Logf("Created pool %s", p.ID)
-
- return p.ID
-}
-
-func listVIPs(t *testing.T) {
- err := vips.List(base.Client, vips.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
- vipList, err := vips.ExtractVIPs(page)
- if err != nil {
- t.Errorf("Failed to extract VIPs: %v", err)
- return false, err
- }
-
- for _, vip := range vipList {
- t.Logf("Listing VIP: ID [%s] Name [%s] Address [%s] Port [%s] Connection Limit [%d]",
- vip.ID, vip.Name, vip.Address, vip.ProtocolPort, vip.ConnLimit)
- }
-
- return true, nil
- })
-
- th.AssertNoErr(t, err)
-}
-
-func updateVIP(t *testing.T, VIPID string) {
- i1000 := 1000
- _, err := vips.Update(base.Client, VIPID, vips.UpdateOpts{ConnLimit: &i1000}).Extract()
-
- th.AssertNoErr(t, err)
-
- t.Logf("Updated VIP ID [%s]", VIPID)
-}
-
-func getVIP(t *testing.T, VIPID string) {
- vip, err := vips.Get(base.Client, VIPID).Extract()
-
- th.AssertNoErr(t, err)
-
- t.Logf("Getting VIP ID [%s]: Status [%s]", vip.ID, vip.Status)
-}
-
-func deleteVIP(t *testing.T, VIPID string) {
- res := vips.Delete(base.Client, VIPID)
-
- th.AssertNoErr(t, res.Err)
-
- t.Logf("Deleted VIP %s", VIPID)
-}
diff --git a/acceptance/openstack/networking/v2/extensions/lbaas/vips_test.go b/acceptance/openstack/networking/v2/extensions/lbaas/vips_test.go
new file mode 100644
index 0000000..1f61b36
--- /dev/null
+++ b/acceptance/openstack/networking/v2/extensions/lbaas/vips_test.go
@@ -0,0 +1,82 @@
+// +build acceptance networking lbaas vip
+
+package lbaas
+
+import (
+ "testing"
+
+ "github.com/gophercloud/gophercloud/acceptance/clients"
+ networking "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/vips"
+)
+
+func TestVIPsList(t *testing.T) {
+ client, err := clients.NewNetworkV2Client()
+ if err != nil {
+ t.Fatalf("Unable to create a network client: %v", err)
+ }
+
+ allPages, err := vips.List(client, vips.ListOpts{}).AllPages()
+ if err != nil {
+ t.Fatalf("Unable to list vips: %v", err)
+ }
+
+ allVIPs, err := vips.ExtractVIPs(allPages)
+ if err != nil {
+ t.Fatalf("Unable to extract vips: %v", err)
+ }
+
+ for _, vip := range allVIPs {
+ PrintVIP(t, &vip)
+ }
+}
+
+func TestVIPsCRUD(t *testing.T) {
+ client, err := clients.NewNetworkV2Client()
+ if err != nil {
+ t.Fatalf("Unable to create a network client: %v", err)
+ }
+
+ network, err := networking.CreateNetwork(t, client)
+ if err != nil {
+ t.Fatalf("Unable to create network: %v", err)
+ }
+ defer networking.DeleteNetwork(t, client, network.ID)
+
+ subnet, err := networking.CreateSubnet(t, client, network.ID)
+ if err != nil {
+ t.Fatalf("Unable to create subnet: %v", err)
+ }
+ defer networking.DeleteSubnet(t, client, subnet.ID)
+
+ pool, err := CreatePool(t, client, subnet.ID)
+ if err != nil {
+ t.Fatalf("Unable to create pool: %v", err)
+ }
+ defer DeletePool(t, client, pool.ID)
+
+ vip, err := CreateVIP(t, client, subnet.ID, pool.ID)
+ if err != nil {
+ t.Fatalf("Unable to create vip: %v", err)
+ }
+ defer DeleteVIP(t, client, vip.ID)
+
+ PrintVIP(t, vip)
+
+ connLimit := 100
+ updateOpts := vips.UpdateOpts{
+ ConnLimit: &connLimit,
+ }
+
+ _, err = vips.Update(client, vip.ID, updateOpts).Extract()
+ if err != nil {
+ t.Fatalf("Unable to update vip: %v")
+ }
+
+ newVIP, err := vips.Get(client, vip.ID).Extract()
+ if err != nil {
+ t.Fatalf("Unable to get vip: %v")
+ }
+
+ PrintVIP(t, newVIP)
+}
diff --git a/acceptance/openstack/networking/v2/extensions/lbaas_v2/lbaas_v2.go b/acceptance/openstack/networking/v2/extensions/lbaas_v2/lbaas_v2.go
new file mode 100644
index 0000000..d2e7195
--- /dev/null
+++ b/acceptance/openstack/networking/v2/extensions/lbaas_v2/lbaas_v2.go
@@ -0,0 +1,392 @@
+package lbaas_v2
+
+import (
+ "fmt"
+ "strings"
+ "testing"
+
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/acceptance/tools"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/listeners"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/loadbalancers"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/monitors"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/pools"
+)
+
+const loadbalancerActiveTimeoutSeconds = 300
+const loadbalancerDeleteTimeoutSeconds = 300
+
+// CreateListener will create a listener for a given load balancer on a random
+// port with a random name. An error will be returned if the listener could not
+// be created.
+func CreateListener(t *testing.T, client *gophercloud.ServiceClient, lb *loadbalancers.LoadBalancer) (*listeners.Listener, error) {
+ listenerName := tools.RandomString("TESTACCT-", 8)
+ listenerPort := tools.RandomInt(1, 100)
+
+ t.Logf("Attempting to create listener %s on port %d", listenerName, listenerPort)
+
+ createOpts := listeners.CreateOpts{
+ Name: listenerName,
+ LoadbalancerID: lb.ID,
+ Protocol: "TCP",
+ ProtocolPort: listenerPort,
+ }
+
+ listener, err := listeners.Create(client, createOpts).Extract()
+ if err != nil {
+ return listener, err
+ }
+
+ t.Logf("Successfully created listener %s", listenerName)
+
+ if err := WaitForLoadBalancerState(client, lb.ID, "ACTIVE", loadbalancerActiveTimeoutSeconds); err != nil {
+ return listener, fmt.Errorf("Timed out waiting for loadbalancer to become active")
+ }
+
+ return listener, nil
+}
+
+// CreateLoadBalancer will create a load balancer with a random name on a given
+// subnet. An error will be returned if the loadbalancer could not be created.
+func CreateLoadBalancer(t *testing.T, client *gophercloud.ServiceClient, subnetID string) (*loadbalancers.LoadBalancer, error) {
+ lbName := tools.RandomString("TESTACCT-", 8)
+
+ t.Logf("Attempting to create loadbalancer %s on subnet %s", lbName, subnetID)
+
+ createOpts := loadbalancers.CreateOpts{
+ Name: lbName,
+ VipSubnetID: subnetID,
+ AdminStateUp: gophercloud.Enabled,
+ }
+
+ lb, err := loadbalancers.Create(client, createOpts).Extract()
+ if err != nil {
+ return lb, err
+ }
+
+ t.Logf("Successfully created loadbalancer %s on subnet %s", lbName, subnetID)
+ t.Logf("Waiting for loadbalancer %s to become active", lbName)
+
+ if err := WaitForLoadBalancerState(client, lb.ID, "ACTIVE", loadbalancerActiveTimeoutSeconds); err != nil {
+ return lb, err
+ }
+
+ t.Logf("LoadBalancer %s is active", lbName)
+
+ return lb, nil
+}
+
+// CreateMember will create a member with a random name, port, address, and
+// weight. An error will be returned if the member could not be created.
+func CreateMember(t *testing.T, client *gophercloud.ServiceClient, lb *loadbalancers.LoadBalancer, pool *pools.Pool, subnetID, subnetCIDR string) (*pools.Member, error) {
+ memberName := tools.RandomString("TESTACCT-", 8)
+ memberPort := tools.RandomInt(100, 1000)
+ memberWeight := tools.RandomInt(1, 10)
+
+ cidrParts := strings.Split(subnetCIDR, "/")
+ subnetParts := strings.Split(cidrParts[0], ".")
+ memberAddress := fmt.Sprintf("%s.%s.%s.%d", subnetParts[0], subnetParts[1], subnetParts[2], tools.RandomInt(10, 100))
+
+ t.Logf("Attempting to create member %s", memberName)
+
+ createOpts := pools.CreateMemberOpts{
+ Name: memberName,
+ ProtocolPort: memberPort,
+ Weight: memberWeight,
+ Address: memberAddress,
+ SubnetID: subnetID,
+ }
+
+ t.Logf("Member create opts: %#v", createOpts)
+
+ member, err := pools.CreateMember(client, pool.ID, createOpts).Extract()
+ if err != nil {
+ return member, err
+ }
+
+ t.Logf("Successfully created member %s", memberName)
+
+ if err := WaitForLoadBalancerState(client, lb.ID, "ACTIVE", loadbalancerActiveTimeoutSeconds); err != nil {
+ return member, fmt.Errorf("Timed out waiting for loadbalancer to become active")
+ }
+
+ return member, nil
+}
+
+// CreateMonitor will create a monitor with a random name for a specific pool.
+// An error will be returned if the monitor could not be created.
+func CreateMonitor(t *testing.T, client *gophercloud.ServiceClient, lb *loadbalancers.LoadBalancer, pool *pools.Pool) (*monitors.Monitor, error) {
+ monitorName := tools.RandomString("TESTACCT-", 8)
+
+ t.Logf("Attempting to create monitor %s", monitorName)
+
+ createOpts := monitors.CreateOpts{
+ PoolID: pool.ID,
+ Name: monitorName,
+ Delay: 10,
+ Timeout: 5,
+ MaxRetries: 5,
+ Type: "PING",
+ }
+
+ monitor, err := monitors.Create(client, createOpts).Extract()
+ if err != nil {
+ return monitor, err
+ }
+
+ t.Logf("Successfully created monitor: %s", monitorName)
+
+ if err := WaitForLoadBalancerState(client, lb.ID, "ACTIVE", loadbalancerActiveTimeoutSeconds); err != nil {
+ return monitor, fmt.Errorf("Timed out waiting for loadbalancer to become active")
+ }
+
+ return monitor, nil
+}
+
+// CreatePool will create a pool with a random name with a specified listener
+// and loadbalancer. An error will be returned if the pool could not be
+// created.
+func CreatePool(t *testing.T, client *gophercloud.ServiceClient, lb *loadbalancers.LoadBalancer) (*pools.Pool, error) {
+ poolName := tools.RandomString("TESTACCT-", 8)
+
+ t.Logf("Attempting to create pool %s", poolName)
+
+ createOpts := pools.CreateOpts{
+ Name: poolName,
+ Protocol: pools.ProtocolTCP,
+ LoadbalancerID: lb.ID,
+ LBMethod: pools.LBMethodLeastConnections,
+ }
+
+ pool, err := pools.Create(client, createOpts).Extract()
+ if err != nil {
+ return pool, err
+ }
+
+ t.Logf("Successfully created pool %s", poolName)
+
+ if err := WaitForLoadBalancerState(client, lb.ID, "ACTIVE", loadbalancerActiveTimeoutSeconds); err != nil {
+ return pool, fmt.Errorf("Timed out waiting for loadbalancer to become active")
+ }
+
+ return pool, nil
+}
+
+// DeleteListener will delete a specified listener. A fatal error will occur if
+// the listener could not be deleted. This works best when used as a deferred
+// function.
+func DeleteListener(t *testing.T, client *gophercloud.ServiceClient, lbID, listenerID string) {
+ t.Logf("Attempting to delete listener %s", listenerID)
+
+ if err := listeners.Delete(client, listenerID).ExtractErr(); err != nil {
+ t.Fatalf("Unable to delete listener: %v", err)
+ }
+
+ if err := WaitForLoadBalancerState(client, lbID, "ACTIVE", loadbalancerActiveTimeoutSeconds); err != nil {
+ t.Fatalf("Timed out waiting for loadbalancer to become active")
+ }
+
+ t.Logf("Successfully deleted listener %s", listenerID)
+}
+
+// DeleteMember will delete a specified member. A fatal error will occur if the
+// member could not be deleted. This works best when used as a deferred
+// function.
+func DeleteMember(t *testing.T, client *gophercloud.ServiceClient, lbID, poolID, memberID string) {
+ t.Logf("Attempting to delete member %s", memberID)
+
+ if err := pools.DeleteMember(client, poolID, memberID).ExtractErr(); err != nil {
+ t.Fatalf("Unable to delete member: %s", memberID)
+ }
+
+ if err := WaitForLoadBalancerState(client, lbID, "ACTIVE", loadbalancerActiveTimeoutSeconds); err != nil {
+ t.Fatalf("Timed out waiting for loadbalancer to become active")
+ }
+
+ t.Logf("Successfully deleted member %s", memberID)
+}
+
+// DeleteLoadBalancer will delete a specified loadbalancer. A fatal error will
+// occur if the loadbalancer could not be deleted. This works best when used
+// as a deferred function.
+func DeleteLoadBalancer(t *testing.T, client *gophercloud.ServiceClient, lbID string) {
+ t.Logf("Attempting to delete loadbalancer %s", lbID)
+
+ if err := loadbalancers.Delete(client, lbID).ExtractErr(); err != nil {
+ t.Fatalf("Unable to delete loadbalancer: %v", err)
+ }
+
+ t.Logf("Waiting for loadbalancer %s to delete", lbID)
+
+ if err := WaitForLoadBalancerState(client, lbID, "DELETED", loadbalancerActiveTimeoutSeconds); err != nil {
+ t.Fatalf("Loadbalancer did not delete in time.")
+ }
+
+ t.Logf("Successfully deleted loadbalancer %s", lbID)
+}
+
+// DeleteMonitor will delete a specified monitor. A fatal error will occur if
+// the monitor could not be deleted. This works best when used as a deferred
+// function.
+func DeleteMonitor(t *testing.T, client *gophercloud.ServiceClient, lbID, monitorID string) {
+ t.Logf("Attempting to delete monitor %s", monitorID)
+
+ if err := monitors.Delete(client, monitorID).ExtractErr(); err != nil {
+ t.Fatalf("Unable to delete monitor: %v", err)
+ }
+
+ if err := WaitForLoadBalancerState(client, lbID, "ACTIVE", loadbalancerActiveTimeoutSeconds); err != nil {
+ t.Fatalf("Timed out waiting for loadbalancer to become active")
+ }
+
+ t.Logf("Successfully deleted monitor %s", monitorID)
+}
+
+// DeletePool will delete a specified pool. A fatal error will occur if the
+// pool could not be deleted. This works best when used as a deferred function.
+func DeletePool(t *testing.T, client *gophercloud.ServiceClient, lbID, poolID string) {
+ t.Logf("Attempting to delete pool %s", poolID)
+
+ if err := pools.Delete(client, poolID).ExtractErr(); err != nil {
+ t.Fatalf("Unable to delete pool: %v", err)
+ }
+
+ if err := WaitForLoadBalancerState(client, lbID, "ACTIVE", loadbalancerActiveTimeoutSeconds); err != nil {
+ t.Fatalf("Timed out waiting for loadbalancer to become active")
+ }
+
+ t.Logf("Successfully deleted pool %s", poolID)
+}
+
+// PrintListener will print a listener and all of its attributes.
+func PrintListener(t *testing.T, listener *listeners.Listener) {
+ t.Logf("ID: %s", listener.ID)
+ t.Logf("TenantID: %s", listener.TenantID)
+ t.Logf("Name: %s", listener.Name)
+ t.Logf("Description: %s", listener.Description)
+ t.Logf("Protocol: %s", listener.Protocol)
+ t.Logf("DefaultPoolID: %s", listener.DefaultPoolID)
+ t.Logf("ConnLimit: %d", listener.ConnLimit)
+ t.Logf("SniContainerRefs: %s", listener.SniContainerRefs)
+ t.Logf("DefaultTlsContainerRef: %s", listener.DefaultTlsContainerRef)
+ t.Logf("AdminStateUp: %t", listener.AdminStateUp)
+
+ t.Logf("Pools:")
+ for _, pool := range listener.Pools {
+ t.Logf("\t%#v", pool)
+ }
+
+ t.Logf("LoadBalancers")
+ for _, lb := range listener.Loadbalancers {
+ t.Logf("\t%#v", lb)
+ }
+}
+
+// PrintLoadBalancer will print a load balancer and all of its attributes.
+func PrintLoadBalancer(t *testing.T, lb *loadbalancers.LoadBalancer) {
+ t.Logf("ID: %s", lb.ID)
+ t.Logf("Name: %s", lb.Name)
+ t.Logf("TenantID: %s", lb.TenantID)
+ t.Logf("Description: %s", lb.Description)
+ t.Logf("ProvisioningStatus: %s", lb.ProvisioningStatus)
+ t.Logf("VipAddress: %s", lb.VipAddress)
+ t.Logf("VipPortID: %s", lb.VipPortID)
+ t.Logf("VipSubnetID: %s", lb.VipSubnetID)
+ t.Logf("OperatingStatus: %s", lb.OperatingStatus)
+ t.Logf("Flavor: %s", lb.Flavor)
+ t.Logf("Provider: %s", lb.Provider)
+ t.Logf("AdminStateUp: %t", lb.AdminStateUp)
+
+ t.Logf("Listeners")
+ for _, listener := range lb.Listeners {
+ t.Logf("\t%#v", listener)
+ }
+}
+
+// PrintMember will print a member and all of its attributes.
+func PrintMember(t *testing.T, member *pools.Member) {
+ t.Logf("ID: %s", member.ID)
+ t.Logf("Name: %s", member.Name)
+ t.Logf("TenantID: %s", member.TenantID)
+ t.Logf("Weight: %d", member.Weight)
+ t.Logf("SubnetID: %s", member.SubnetID)
+ t.Logf("PoolID: %s", member.PoolID)
+ t.Logf("Address: %s", member.Address)
+ t.Logf("ProtocolPort: %d", member.ProtocolPort)
+ t.Logf("AdminStateUp: %t", member.AdminStateUp)
+}
+
+// PrintMonitor will print a monitor and all of its attributes.
+func PrintMonitor(t *testing.T, monitor *monitors.Monitor) {
+ t.Logf("ID: %s", monitor.ID)
+ t.Logf("Name: %s", monitor.Name)
+ t.Logf("TenantID: %s", monitor.TenantID)
+ t.Logf("Type: %s", monitor.Type)
+ t.Logf("Delay: %d", monitor.Delay)
+ t.Logf("Timeout: %d", monitor.Timeout)
+ t.Logf("MaxRetries: %d", monitor.MaxRetries)
+ t.Logf("HTTPMethod: %s", monitor.HTTPMethod)
+ t.Logf("URLPath: %s", monitor.URLPath)
+ t.Logf("ExpectedCodes: %s", monitor.ExpectedCodes)
+ t.Logf("AdminStateUp: %t", monitor.AdminStateUp)
+ t.Logf("Status: %s", monitor.Status)
+
+ t.Logf("Pools")
+ for _, pool := range monitor.Pools {
+ t.Logf("\t%#v", pool)
+ }
+}
+
+// PrintPool will print a pool and all of its attributes.
+func PrintPool(t *testing.T, pool *pools.Pool) {
+ t.Logf("ID: %s", pool.ID)
+ t.Logf("Name: %s", pool.Name)
+ t.Logf("TenantID: %s", pool.TenantID)
+ t.Logf("Description: %s", pool.Description)
+ t.Logf("LBMethod: %s", pool.LBMethod)
+ t.Logf("Protocol: %s", pool.Protocol)
+ t.Logf("MonitorID: %s", pool.MonitorID)
+ t.Logf("SubnetID: %s", pool.SubnetID)
+ t.Logf("AdminStateUp: %t", pool.AdminStateUp)
+ t.Logf("Persistence: %s", pool.Persistence)
+ t.Logf("Provider: %s", pool.Provider)
+ t.Logf("Monitor: %#v", pool.Monitor)
+
+ t.Logf("Listeners")
+ for _, listener := range pool.Listeners {
+ t.Logf("\t%#v", listener)
+ }
+
+ t.Logf("Members")
+ for _, member := range pool.Members {
+ t.Logf("\t%#v", member)
+ }
+
+ t.Logf("Loadbalancers")
+ for _, lb := range pool.Loadbalancers {
+ t.Logf("\t%#v", lb)
+ }
+}
+
+// WaitForLoadBalancerState will wait until a loadbalancer reaches a given state.
+func WaitForLoadBalancerState(client *gophercloud.ServiceClient, lbID, status string, secs int) error {
+ return gophercloud.WaitFor(secs, func() (bool, error) {
+ current, err := loadbalancers.Get(client, lbID).Extract()
+ if err != nil {
+ if httpStatus, ok := err.(gophercloud.ErrDefault404); ok {
+ if httpStatus.Actual == 404 {
+ if status == "DELETED" {
+ return true, nil
+ }
+ }
+ }
+ return false, err
+ }
+
+ if current.ProvisioningStatus == status {
+ return true, nil
+ }
+
+ return false, nil
+ })
+}
diff --git a/acceptance/openstack/networking/v2/extensions/lbaas_v2/listeners_test.go b/acceptance/openstack/networking/v2/extensions/lbaas_v2/listeners_test.go
new file mode 100644
index 0000000..ac2681e
--- /dev/null
+++ b/acceptance/openstack/networking/v2/extensions/lbaas_v2/listeners_test.go
@@ -0,0 +1,31 @@
+// +build acceptance networking lbaas_v2 listeners
+
+package lbaas_v2
+
+import (
+ "testing"
+
+ "github.com/gophercloud/gophercloud/acceptance/clients"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/listeners"
+)
+
+func TestListenersList(t *testing.T) {
+ client, err := clients.NewNetworkV2Client()
+ if err != nil {
+ t.Fatalf("Unable to create a network client: %v", err)
+ }
+
+ allPages, err := listeners.List(client, nil).AllPages()
+ if err != nil {
+ t.Fatalf("Unable to list listeners: %v", err)
+ }
+
+ allListeners, err := listeners.ExtractListeners(allPages)
+ if err != nil {
+ t.Fatalf("Unable to extract listeners: %v", err)
+ }
+
+ for _, listener := range allListeners {
+ PrintListener(t, &listener)
+ }
+}
diff --git a/acceptance/openstack/networking/v2/extensions/lbaas_v2/loadbalancer_test.go b/acceptance/openstack/networking/v2/extensions/lbaas_v2/loadbalancer_test.go
deleted file mode 100644
index 051b7eb..0000000
--- a/acceptance/openstack/networking/v2/extensions/lbaas_v2/loadbalancer_test.go
+++ /dev/null
@@ -1,493 +0,0 @@
-// +build acceptance networking lbaas_v2 lbaasloadbalancer
-
-package lbaas_v2
-
-import (
- "testing"
- "time"
-
- "github.com/gophercloud/gophercloud"
- base "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2"
- "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/listeners"
- "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/loadbalancers"
- "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/monitors"
- "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/pools"
- "github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
- "github.com/gophercloud/gophercloud/openstack/networking/v2/subnets"
- "github.com/gophercloud/gophercloud/pagination"
- th "github.com/gophercloud/gophercloud/testhelper"
-)
-
-// Note: when creating a new Loadbalancer (VM), it can take some time before it is ready for use,
-// this timeout is used for waiting until the Loadbalancer provisioning status goes to ACTIVE state.
-const loadbalancerActiveTimeoutSeconds = 120
-const loadbalancerDeleteTimeoutSeconds = 10
-
-func setupTopology(t *testing.T) (string, string) {
- // create network
- n, err := networks.Create(base.Client, networks.CreateOpts{Name: "tmp_network"}).Extract()
- th.AssertNoErr(t, err)
-
- t.Logf("Created network, ID %s", n.ID)
-
- // create subnet
- s, err := subnets.Create(base.Client, subnets.CreateOpts{
- NetworkID: n.ID,
- CIDR: "192.168.199.0/24",
- IPVersion: subnets.IPv4,
- Name: "tmp_subnet",
- }).Extract()
- th.AssertNoErr(t, err)
-
- t.Logf("Created subnet, ID %s", s.ID)
-
- return n.ID, s.ID
-}
-
-func deleteTopology(t *testing.T, networkID string) {
- res := networks.Delete(base.Client, networkID)
- th.AssertNoErr(t, res.Err)
- t.Logf("deleted network, ID %s", networkID)
-}
-
-func TestLoadbalancers(t *testing.T) {
- base.Setup(t)
- defer base.Teardown()
-
- // setup network topology
- networkID, subnetID := setupTopology(t)
-
- // create Loadbalancer
- loadbalancerID := createLoadbalancer(t, subnetID)
-
- // list Loadbalancers
- listLoadbalancers(t)
-
- // get Loadbalancer and wait until ACTIVE
- getLoadbalancerWaitActive(t, loadbalancerID)
-
- // update Loadbalancer
- updateLoadbalancer(t, loadbalancerID)
-
- // get Loadbalancer and wait until ACTIVE
- getLoadbalancerWaitActive(t, loadbalancerID)
-
- // create listener
- listenerID := createListener(t, listeners.ProtocolHTTP, 80, loadbalancerID)
-
- // list listeners
- listListeners(t)
-
- // get Loadbalancer and wait until ACTIVE
- getLoadbalancerWaitActive(t, loadbalancerID)
-
- // update listener
- updateListener(t, listenerID)
-
- // get listener
- getListener(t, listenerID)
-
- // get Loadbalancer and wait until ACTIVE
- getLoadbalancerWaitActive(t, loadbalancerID)
-
- // create pool
- poolID := createPool(t, pools.ProtocolHTTP, listenerID, pools.LBMethodRoundRobin)
-
- // list pools
- listPools(t)
-
- // get Loadbalancer and wait until ACTIVE
- getLoadbalancerWaitActive(t, loadbalancerID)
-
- // update pool
- updatePool(t, poolID)
-
- // get pool
- getPool(t, poolID)
-
- // get Loadbalancer and wait until ACTIVE
- getLoadbalancerWaitActive(t, loadbalancerID)
-
- // create member
- memberID := createMember(t, subnetID, poolID, "1.2.3.4", 80, 5)
-
- // list members
- listMembers(t, poolID)
-
- // get Loadbalancer and wait until ACTIVE
- getLoadbalancerWaitActive(t, loadbalancerID)
-
- // update member
- updateMember(t, poolID, memberID)
-
- // get member
- getMember(t, poolID, memberID)
-
- // get Loadbalancer and wait until ACTIVE
- getLoadbalancerWaitActive(t, loadbalancerID)
-
- // create monitor
- monitorID := createMonitor(t, poolID, monitors.TypePING, 10, 10, 3)
-
- // list monitors
- listMonitors(t)
-
- // get Loadbalancer and wait until ACTIVE
- getLoadbalancerWaitActive(t, loadbalancerID)
-
- // update monitor
- updateMonitor(t, monitorID)
-
- // get monitor
- getMonitor(t, monitorID)
-
- // get loadbalancer statuses tree
- rawStatusTree, err := loadbalancers.GetStatuses(base.Client, loadbalancerID).ExtractStatuses()
- if err == nil {
- // verify statuses tree ID's of relevant objects
- if rawStatusTree.Loadbalancer.ID != loadbalancerID {
- t.Errorf("Loadbalancer ID did not match")
- }
- if rawStatusTree.Loadbalancer.Listeners[0].ID != listenerID {
- t.Errorf("Listner ID did not match")
- }
- if rawStatusTree.Loadbalancer.Listeners[0].Pools[0].ID != poolID {
- t.Errorf("Pool ID did not match")
- }
- if rawStatusTree.Loadbalancer.Listeners[0].Pools[0].Members[0].ID != memberID {
- t.Errorf("Member ID did not match")
- }
- if rawStatusTree.Loadbalancer.Listeners[0].Pools[0].Monitor.ID != monitorID {
- t.Errorf("Monitor ID did not match")
- }
- } else {
- t.Errorf("Failed to extract Loadbalancer statuses tree: %v", err)
- }
-
- getLoadbalancerWaitActive(t, loadbalancerID)
- deleteMonitor(t, monitorID)
- getLoadbalancerWaitActive(t, loadbalancerID)
- deleteMember(t, poolID, memberID)
- getLoadbalancerWaitActive(t, loadbalancerID)
- deletePool(t, poolID)
- getLoadbalancerWaitActive(t, loadbalancerID)
- deleteListener(t, listenerID)
- getLoadbalancerWaitActive(t, loadbalancerID)
- deleteLoadbalancer(t, loadbalancerID)
- getLoadbalancerWaitDeleted(t, loadbalancerID)
- deleteTopology(t, networkID)
-}
-
-func createLoadbalancer(t *testing.T, subnetID string) string {
- lb, err := loadbalancers.Create(base.Client, loadbalancers.CreateOpts{
- VipSubnetID: subnetID,
- Name: "tmp_loadbalancer",
- AdminStateUp: loadbalancers.Up,
- }).Extract()
-
- th.AssertNoErr(t, err)
- t.Logf("Created Loadbalancer, ID %s", lb.ID)
-
- return lb.ID
-}
-
-func deleteLoadbalancer(t *testing.T, loadbalancerID string) {
- res := loadbalancers.Delete(base.Client, loadbalancerID)
- th.AssertNoErr(t, res.Err)
- t.Logf("deleted Loadbalancer, ID %s", loadbalancerID)
-}
-
-func listLoadbalancers(t *testing.T) {
- err := loadbalancers.List(base.Client, loadbalancers.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
- loadbalancerList, err := loadbalancers.ExtractLoadbalancers(page)
- if err != nil {
- t.Errorf("Failed to extract Loadbalancers: %v", err)
- return false, err
- }
-
- for _, loadbalancer := range loadbalancerList {
- t.Logf("Listing Loadbalancer: ID [%s] Name [%s] Address [%s]",
- loadbalancer.ID, loadbalancer.Name, loadbalancer.VipAddress)
- }
-
- return true, nil
- })
-
- th.AssertNoErr(t, err)
-}
-
-func getLoadbalancerWaitDeleted(t *testing.T, loadbalancerID string) {
- start := time.Now().Second()
- for {
- time.Sleep(1 * time.Second)
-
- if time.Now().Second()-start >= loadbalancerDeleteTimeoutSeconds {
- t.Errorf("Loadbalancer failed to delete")
- return
- }
-
- _, err := loadbalancers.Get(base.Client, loadbalancerID).Extract()
- if err != nil {
- if errData, ok := err.(*(gophercloud.UnexpectedResponseCodeError)); ok {
- if errData.Actual == 404 {
- return
- }
- } else {
- th.AssertNoErr(t, err)
- }
- }
- }
-}
-
-func getLoadbalancerWaitActive(t *testing.T, loadbalancerID string) {
- start := time.Now().Second()
- for {
- time.Sleep(1 * time.Second)
-
- if time.Now().Second()-start >= loadbalancerActiveTimeoutSeconds {
- t.Errorf("Loadbalancer failed to go into ACTIVE provisioning status")
- return
- }
-
- loadbalancer, err := loadbalancers.Get(base.Client, loadbalancerID).Extract()
- th.AssertNoErr(t, err)
- if loadbalancer.ProvisioningStatus == "ACTIVE" {
- t.Logf("Retrieved Loadbalancer, ID [%s]: OperatingStatus [%s]", loadbalancer.ID, loadbalancer.ProvisioningStatus)
- return
- }
- }
-}
-
-func updateLoadbalancer(t *testing.T, loadbalancerID string) {
- _, err := loadbalancers.Update(base.Client, loadbalancerID, loadbalancers.UpdateOpts{Name: "tmp_newName"}).Extract()
-
- th.AssertNoErr(t, err)
-
- t.Logf("Updated Loadbalancer ID [%s]", loadbalancerID)
-}
-
-func listListeners(t *testing.T) {
- err := listeners.List(base.Client, listeners.ListOpts{Name: "tmp_listener"}).EachPage(func(page pagination.Page) (bool, error) {
- listenerList, err := listeners.ExtractListeners(page)
- if err != nil {
- t.Errorf("Failed to extract Listeners: %v", err)
- return false, err
- }
-
- for _, listener := range listenerList {
- t.Logf("Listing Listener: ID [%s] Name [%s] Loadbalancers [%s]",
- listener.ID, listener.Name, listener.Loadbalancers)
- }
-
- return true, nil
- })
-
- th.AssertNoErr(t, err)
-}
-
-func createListener(t *testing.T, protocol listeners.Protocol, protocolPort int, loadbalancerID string) string {
- l, err := listeners.Create(base.Client, listeners.CreateOpts{
- Protocol: protocol,
- ProtocolPort: protocolPort,
- LoadbalancerID: loadbalancerID,
- Name: "tmp_listener",
- }).Extract()
-
- th.AssertNoErr(t, err)
- t.Logf("Created Listener, ID %s", l.ID)
-
- return l.ID
-}
-
-func deleteListener(t *testing.T, listenerID string) {
- res := listeners.Delete(base.Client, listenerID)
- th.AssertNoErr(t, res.Err)
- t.Logf("Deleted Loadbalancer, ID %s", listenerID)
-}
-
-func getListener(t *testing.T, listenerID string) {
- listener, err := listeners.Get(base.Client, listenerID).Extract()
-
- th.AssertNoErr(t, err)
-
- t.Logf("Getting Listener, ID [%s]: ", listener.ID)
-}
-
-func updateListener(t *testing.T, listenerID string) {
- _, err := listeners.Update(base.Client, listenerID, listeners.UpdateOpts{Name: "tmp_newName"}).Extract()
-
- th.AssertNoErr(t, err)
-
- t.Logf("Updated Listener, ID [%s]", listenerID)
-}
-
-func listPools(t *testing.T) {
- err := pools.List(base.Client, pools.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
- poolsList, err := pools.ExtractPools(page)
- if err != nil {
- t.Errorf("Failed to extract Pools: %v", err)
- return false, err
- }
-
- for _, pool := range poolsList {
- t.Logf("Listing Pool: ID [%s] Name [%s] Listeners [%s] LBMethod [%s]",
- pool.ID, pool.Name, pool.Listeners, pool.LBMethod)
- }
-
- return true, nil
- })
-
- th.AssertNoErr(t, err)
-}
-
-func createPool(t *testing.T, protocol pools.Protocol, listenerID string, lbMethod pools.LBMethod) string {
- p, err := pools.Create(base.Client, pools.CreateOpts{
- LBMethod: lbMethod,
- Protocol: protocol,
- Name: "tmp_pool",
- ListenerID: listenerID,
- }).Extract()
-
- th.AssertNoErr(t, err)
-
- t.Logf("Created Pool, ID %s", p.ID)
-
- return p.ID
-}
-
-func deletePool(t *testing.T, poolID string) {
- res := pools.Delete(base.Client, poolID)
- th.AssertNoErr(t, res.Err)
- t.Logf("Deleted Pool, ID %s", poolID)
-}
-
-func getPool(t *testing.T, poolID string) {
- pool, err := pools.Get(base.Client, poolID).Extract()
-
- th.AssertNoErr(t, err)
-
- t.Logf("Getting Pool, ID [%s]: ", pool.ID)
-}
-
-func updatePool(t *testing.T, poolID string) {
- _, err := pools.Update(base.Client, poolID, pools.UpdateOpts{Name: "tmp_newName"}).Extract()
-
- th.AssertNoErr(t, err)
-
- t.Logf("Updated Pool, ID [%s]", poolID)
-}
-
-func createMember(t *testing.T, subnetID string, poolID string, address string, protocolPort int, weight int) string {
- m, err := pools.CreateAssociateMember(base.Client, poolID, pools.MemberCreateOpts{
- SubnetID: subnetID,
- Address: address,
- ProtocolPort: protocolPort,
- Weight: weight,
- Name: "tmp_member",
- }).ExtractMember()
-
- th.AssertNoErr(t, err)
-
- t.Logf("Created Member, ID %s", m.ID)
-
- return m.ID
-}
-
-func deleteMember(t *testing.T, poolID string, memberID string) {
- res := pools.DeleteMember(base.Client, poolID, memberID)
- th.AssertNoErr(t, res.Err)
- t.Logf("Deleted Member, ID %s", memberID)
-}
-
-func listMembers(t *testing.T, poolID string) {
- err := pools.ListAssociateMembers(base.Client, poolID, pools.MemberListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
- membersList, err := pools.ExtractMembers(page)
- if err != nil {
- t.Errorf("Failed to extract Members: %v", err)
- return false, err
- }
-
- for _, member := range membersList {
- t.Logf("Listing Member: ID [%s] Name [%s] Pool ID [%s] Weight [%s]",
- member.ID, member.Name, member.PoolID, member.Weight)
- }
-
- return true, nil
- })
-
- th.AssertNoErr(t, err)
-}
-
-func getMember(t *testing.T, poolID string, memberID string) {
- member, err := pools.GetAssociateMember(base.Client, poolID, memberID).ExtractMember()
-
- th.AssertNoErr(t, err)
-
- t.Logf("Getting Member, ID [%s]: ", member.ID)
-}
-
-func updateMember(t *testing.T, poolID string, memberID string) {
- _, err := pools.UpdateAssociateMember(base.Client, poolID, memberID, pools.MemberUpdateOpts{Name: "tmp_newName"}).Extract()
-
- th.AssertNoErr(t, err)
-
- t.Logf("Updated Member, ID [%s], in Pool, ID [%s]", memberID, poolID)
-}
-
-func createMonitor(t *testing.T, poolID string, checkType string, delay int, timeout int, maxRetries int) string {
- m, err := monitors.Create(base.Client, monitors.CreateOpts{
- PoolID: poolID,
- Name: "tmp_monitor",
- Delay: delay,
- Timeout: timeout,
- MaxRetries: maxRetries,
- Type: checkType,
- }).Extract()
-
- th.AssertNoErr(t, err)
-
- t.Logf("Created Monitor, ID [%s]", m.ID)
-
- return m.ID
-}
-
-func deleteMonitor(t *testing.T, monitorID string) {
- res := monitors.Delete(base.Client, monitorID)
- th.AssertNoErr(t, res.Err)
- t.Logf("Deleted Monitor, ID %s", monitorID)
-}
-
-func listMonitors(t *testing.T) {
- err := monitors.List(base.Client, monitors.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
- monitorsList, err := monitors.ExtractMonitors(page)
- if err != nil {
- t.Errorf("Failed to extract Monitors: %v", err)
- return false, err
- }
-
- for _, monitor := range monitorsList {
- t.Logf("Listing Monitors: ID [%s] Type [%s] HTTPMethod [%s] URLPath [%s]",
- monitor.ID, monitor.Type, monitor.HTTPMethod, monitor.URLPath)
- }
-
- return true, nil
- })
-
- th.AssertNoErr(t, err)
-}
-
-func getMonitor(t *testing.T, monitorID string) {
- monitor, err := monitors.Get(base.Client, monitorID).Extract()
-
- th.AssertNoErr(t, err)
-
- t.Logf("Getting Monitor, ID [%s]: ", monitor.ID)
-}
-
-func updateMonitor(t *testing.T, monitorID string) {
- _, err := monitors.Update(base.Client, monitorID, monitors.UpdateOpts{MaxRetries: 10}).Extract()
-
- th.AssertNoErr(t, err)
-
- t.Logf("Updated Monitor, ID [%s]", monitorID)
-}
diff --git a/acceptance/openstack/networking/v2/extensions/lbaas_v2/loadbalancers_test.go b/acceptance/openstack/networking/v2/extensions/lbaas_v2/loadbalancers_test.go
new file mode 100644
index 0000000..7cd49ed
--- /dev/null
+++ b/acceptance/openstack/networking/v2/extensions/lbaas_v2/loadbalancers_test.go
@@ -0,0 +1,178 @@
+// +build acceptance networking lbaas_v2 loadbalancers
+
+package lbaas_v2
+
+import (
+ "testing"
+
+ "github.com/gophercloud/gophercloud/acceptance/clients"
+ networking "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2"
+ "github.com/gophercloud/gophercloud/acceptance/tools"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/listeners"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/loadbalancers"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/monitors"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/pools"
+)
+
+func TestLoadbalancersList(t *testing.T) {
+ client, err := clients.NewNetworkV2Client()
+ if err != nil {
+ t.Fatalf("Unable to create a network client: %v", err)
+ }
+
+ allPages, err := loadbalancers.List(client, nil).AllPages()
+ if err != nil {
+ t.Fatalf("Unable to list loadbalancers: %v", err)
+ }
+
+ allLoadbalancers, err := loadbalancers.ExtractLoadBalancers(allPages)
+ if err != nil {
+ t.Fatalf("Unable to extract loadbalancers: %v", err)
+ }
+
+ for _, lb := range allLoadbalancers {
+ PrintLoadBalancer(t, &lb)
+ }
+}
+
+func TestLoadbalancersCRUD(t *testing.T) {
+ client, err := clients.NewNetworkV2Client()
+ if err != nil {
+ t.Fatalf("Unable to create a network client: %v", err)
+ }
+
+ network, err := networking.CreateNetwork(t, client)
+ if err != nil {
+ t.Fatalf("Unable to create network: %v", err)
+ }
+ defer networking.DeleteNetwork(t, client, network.ID)
+
+ subnet, err := networking.CreateSubnet(t, client, network.ID)
+ if err != nil {
+ t.Fatalf("Unable to create subnet: %v", err)
+ }
+ defer networking.DeleteSubnet(t, client, subnet.ID)
+
+ lb, err := CreateLoadBalancer(t, client, subnet.ID)
+ if err != nil {
+ t.Fatalf("Unable to create loadbalancer: %v", err)
+ }
+ defer DeleteLoadBalancer(t, client, lb.ID)
+
+ newLB, err := loadbalancers.Get(client, lb.ID).Extract()
+ if err != nil {
+ t.Fatalf("Unable to get loadbalancer: %v", err)
+ }
+
+ PrintLoadBalancer(t, newLB)
+
+ // Because of the time it takes to create a loadbalancer,
+ // this test will include some other resources.
+
+ // Listener
+ listener, err := CreateListener(t, client, lb)
+ if err != nil {
+ t.Fatalf("Unable to create listener: %v", err)
+ }
+ defer DeleteListener(t, client, lb.ID, listener.ID)
+
+ updateListenerOpts := listeners.UpdateOpts{
+ Description: "Some listener description",
+ }
+ _, err = listeners.Update(client, listener.ID, updateListenerOpts).Extract()
+ if err != nil {
+ t.Fatalf("Unable to update listener")
+ }
+
+ if err := WaitForLoadBalancerState(client, lb.ID, "ACTIVE", loadbalancerActiveTimeoutSeconds); err != nil {
+ t.Fatalf("Timed out waiting for loadbalancer to become active")
+ }
+
+ newListener, err := listeners.Get(client, listener.ID).Extract()
+ if err != nil {
+ t.Fatalf("Unable to get listener")
+ }
+
+ PrintListener(t, newListener)
+
+ // Pool
+ pool, err := CreatePool(t, client, lb)
+ if err != nil {
+ t.Fatalf("Unable to create pool: %v", err)
+ }
+ defer DeletePool(t, client, lb.ID, pool.ID)
+
+ updatePoolOpts := pools.UpdateOpts{
+ Description: "Some pool description",
+ }
+ _, err = pools.Update(client, pool.ID, updatePoolOpts).Extract()
+ if err != nil {
+ t.Fatalf("Unable to update pool")
+ }
+
+ if err := WaitForLoadBalancerState(client, lb.ID, "ACTIVE", loadbalancerActiveTimeoutSeconds); err != nil {
+ t.Fatalf("Timed out waiting for loadbalancer to become active")
+ }
+
+ newPool, err := pools.Get(client, pool.ID).Extract()
+ if err != nil {
+ t.Fatalf("Unable to get pool")
+ }
+
+ PrintPool(t, newPool)
+
+ // Member
+ member, err := CreateMember(t, client, lb, newPool, subnet.ID, subnet.CIDR)
+ if err != nil {
+ t.Fatalf("Unable to create member: %v", err)
+ }
+ defer DeleteMember(t, client, lb.ID, pool.ID, member.ID)
+
+ newWeight := tools.RandomInt(11, 100)
+ updateMemberOpts := pools.UpdateMemberOpts{
+ Weight: newWeight,
+ }
+ _, err = pools.UpdateMember(client, pool.ID, member.ID, updateMemberOpts).Extract()
+ if err != nil {
+ t.Fatalf("Unable to update pool")
+ }
+
+ if err := WaitForLoadBalancerState(client, lb.ID, "ACTIVE", loadbalancerActiveTimeoutSeconds); err != nil {
+ t.Fatalf("Timed out waiting for loadbalancer to become active")
+ }
+
+ newMember, err := pools.GetMember(client, pool.ID, member.ID).Extract()
+ if err != nil {
+ t.Fatalf("Unable to get member")
+ }
+
+ PrintMember(t, newMember)
+
+ // Monitor
+ monitor, err := CreateMonitor(t, client, lb, newPool)
+ if err != nil {
+ t.Fatalf("Unable to create monitor: %v", err)
+ }
+ defer DeleteMonitor(t, client, lb.ID, monitor.ID)
+
+ newDelay := tools.RandomInt(20, 30)
+ updateMonitorOpts := monitors.UpdateOpts{
+ Delay: newDelay,
+ }
+ _, err = monitors.Update(client, monitor.ID, updateMonitorOpts).Extract()
+ if err != nil {
+ t.Fatalf("Unable to update monitor")
+ }
+
+ if err := WaitForLoadBalancerState(client, lb.ID, "ACTIVE", loadbalancerActiveTimeoutSeconds); err != nil {
+ t.Fatalf("Timed out waiting for loadbalancer to become active")
+ }
+
+ newMonitor, err := monitors.Get(client, monitor.ID).Extract()
+ if err != nil {
+ t.Fatalf("Unable to get monitor")
+ }
+
+ PrintMonitor(t, newMonitor)
+
+}
diff --git a/acceptance/openstack/networking/v2/extensions/lbaas_v2/monitors_test.go b/acceptance/openstack/networking/v2/extensions/lbaas_v2/monitors_test.go
new file mode 100644
index 0000000..2e587d9
--- /dev/null
+++ b/acceptance/openstack/networking/v2/extensions/lbaas_v2/monitors_test.go
@@ -0,0 +1,31 @@
+// +build acceptance networking lbaas_v2 monitors
+
+package lbaas_v2
+
+import (
+ "testing"
+
+ "github.com/gophercloud/gophercloud/acceptance/clients"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/monitors"
+)
+
+func TestMonitorsList(t *testing.T) {
+ client, err := clients.NewNetworkV2Client()
+ if err != nil {
+ t.Fatalf("Unable to create a network client: %v", err)
+ }
+
+ allPages, err := monitors.List(client, nil).AllPages()
+ if err != nil {
+ t.Fatalf("Unable to list monitors: %v", err)
+ }
+
+ allMonitors, err := monitors.ExtractMonitors(allPages)
+ if err != nil {
+ t.Fatalf("Unable to extract monitors: %v", err)
+ }
+
+ for _, monitor := range allMonitors {
+ PrintMonitor(t, &monitor)
+ }
+}
diff --git a/acceptance/openstack/networking/v2/extensions/lbaas_v2/pools_test.go b/acceptance/openstack/networking/v2/extensions/lbaas_v2/pools_test.go
new file mode 100644
index 0000000..42ba5a2
--- /dev/null
+++ b/acceptance/openstack/networking/v2/extensions/lbaas_v2/pools_test.go
@@ -0,0 +1,31 @@
+// +build acceptance networking lbaas_v2 pools
+
+package lbaas_v2
+
+import (
+ "testing"
+
+ "github.com/gophercloud/gophercloud/acceptance/clients"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/pools"
+)
+
+func TestPoolsList(t *testing.T) {
+ client, err := clients.NewNetworkV2Client()
+ if err != nil {
+ t.Fatalf("Unable to create a network client: %v", err)
+ }
+
+ allPages, err := pools.List(client, nil).AllPages()
+ if err != nil {
+ t.Fatalf("Unable to list pools: %v", err)
+ }
+
+ allPools, err := pools.ExtractPools(allPages)
+ if err != nil {
+ t.Fatalf("Unable to extract pools: %v", err)
+ }
+
+ for _, pool := range allPools {
+ PrintPool(t, &pool)
+ }
+}
diff --git a/acceptance/openstack/networking/v2/extensions/portsbinding/portsbinding.go b/acceptance/openstack/networking/v2/extensions/portsbinding/portsbinding.go
new file mode 100644
index 0000000..b52cd80
--- /dev/null
+++ b/acceptance/openstack/networking/v2/extensions/portsbinding/portsbinding.go
@@ -0,0 +1,57 @@
+package portsbinding
+
+import (
+ "testing"
+
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/acceptance/tools"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/portsbinding"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
+)
+
+// CreatePortsbinding will create a port on the specified subnet. An error will be
+// returned if the port could not be created.
+func CreatePortsbinding(t *testing.T, client *gophercloud.ServiceClient, networkID, subnetID, hostID string) (*portsbinding.Port, error) {
+ portName := tools.RandomString("TESTACC-", 8)
+ iFalse := false
+
+ t.Logf("Attempting to create port: %s", portName)
+
+ createOpts := portsbinding.CreateOpts{
+ CreateOptsBuilder: ports.CreateOpts{
+ NetworkID: networkID,
+ Name: portName,
+ AdminStateUp: &iFalse,
+ FixedIPs: []ports.IP{ports.IP{SubnetID: subnetID}},
+ },
+ HostID: hostID,
+ }
+
+ port, err := portsbinding.Create(client, createOpts).Extract()
+ if err != nil {
+ return port, err
+ }
+
+ t.Logf("Successfully created port: %s", portName)
+
+ return port, nil
+}
+
+// PrintPortsbinging will print a port and all of its attributes.
+func PrintPortsbinding(t *testing.T, port *portsbinding.Port) {
+ t.Logf("ID: %s", port.ID)
+ t.Logf("NetworkID: %s", port.NetworkID)
+ t.Logf("Name: %s", port.Name)
+ t.Logf("AdminStateUp: %t", port.AdminStateUp)
+ t.Logf("Status: %s", port.Status)
+ t.Logf("MACAddress: %s", port.MACAddress)
+ t.Logf("FixedIPs: %s", port.FixedIPs)
+ t.Logf("TenantID: %s", port.TenantID)
+ t.Logf("DeviceOwner: %s", port.DeviceOwner)
+ t.Logf("SecurityGroups: %s", port.SecurityGroups)
+ t.Logf("DeviceID: %s", port.DeviceID)
+ t.Logf("DeviceOwner: %s", port.DeviceOwner)
+ t.Logf("AllowedAddressPairs: %s", port.AllowedAddressPairs)
+ t.Logf("HostID: %s", port.HostID)
+ t.Logf("VNICType: %s", port.VNICType)
+}
diff --git a/acceptance/openstack/networking/v2/extensions/portsbinding/portsbinding_test.go b/acceptance/openstack/networking/v2/extensions/portsbinding/portsbinding_test.go
index b703e3b..2f2f618 100644
--- a/acceptance/openstack/networking/v2/extensions/portsbinding/portsbinding_test.go
+++ b/acceptance/openstack/networking/v2/extensions/portsbinding/portsbinding_test.go
@@ -1,129 +1,58 @@
-// +build acceptance networking portsbinding
+// +build acceptance networking
package portsbinding
import (
"testing"
- base "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2"
+ "github.com/gophercloud/gophercloud/acceptance/clients"
+ networking "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2"
+ "github.com/gophercloud/gophercloud/acceptance/tools"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/portsbinding"
- "github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
"github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
- "github.com/gophercloud/gophercloud/openstack/networking/v2/subnets"
- "github.com/gophercloud/gophercloud/pagination"
- th "github.com/gophercloud/gophercloud/testhelper"
)
-func TestPortBinding(t *testing.T) {
- base.Setup(t)
- defer base.Teardown()
+func TestPortsbindingCRUD(t *testing.T) {
+ client, err := clients.NewNetworkV2Client()
+ if err != nil {
+ t.Fatalf("Unable to create a network client: %v", err)
+ }
- // Setup network
- t.Log("Setting up network")
- networkID, err := createNetwork()
- th.AssertNoErr(t, err)
- defer networks.Delete(base.Client, networkID)
+ // Create Network
+ network, err := networking.CreateNetwork(t, client)
+ if err != nil {
+ t.Fatalf("Unable to create network: %v", err)
+ }
+ defer networking.DeleteNetwork(t, client, network.ID)
- // 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 Subnet
+ subnet, err := networking.CreateSubnet(t, client, network.ID)
+ if err != nil {
+ t.Fatalf("Unable to create subnet: %v", err)
+ }
+ defer networking.DeleteSubnet(t, client, subnet.ID)
+
+ // Define a host
+ hostID := "localhost"
// 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")
+ port, err := CreatePortsbinding(t, client, network.ID, subnet.ID, hostID)
+ if err != nil {
+ t.Fatalf("Unable to create port: %v", err)
}
- p, err := portsbinding.Get(base.Client, portID).Extract()
- th.AssertNoErr(t, err)
- th.AssertEquals(t, p.ID, portID)
- th.AssertEquals(t, p.HostID, hostID)
+ defer networking.DeletePort(t, client, port.ID)
+
+ PrintPortsbinding(t, port)
// Update port
- newHostID := "openstack"
- updateOpts := portsbinding.UpdateOpts{
- HostID: newHostID,
+ newPortName := tools.RandomString("TESTACC-", 8)
+ updateOpts := ports.UpdateOpts{
+ Name: newPortName,
}
- 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,
+ newPort, err := portsbinding.Update(client, port.ID, updateOpts).Extract()
+ if err != nil {
+ t.Fatalf("Could not update port: %v", err)
}
- 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
+ PrintPortsbinding(t, newPort)
}
diff --git a/acceptance/openstack/networking/v2/extensions/provider_test.go b/acceptance/openstack/networking/v2/extensions/provider_test.go
index 55acbc9..8136581 100644
--- a/acceptance/openstack/networking/v2/extensions/provider_test.go
+++ b/acceptance/openstack/networking/v2/extensions/provider_test.go
@@ -1,68 +1,34 @@
-// +build acceptance networking
+// +build acceptance networking provider
package extensions
import (
- "strconv"
"testing"
- base "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2"
+ "github.com/gophercloud/gophercloud/acceptance/clients"
+ networking "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/provider"
"github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
- "github.com/gophercloud/gophercloud/pagination"
- th "github.com/gophercloud/gophercloud/testhelper"
)
-func TestNetworkCRUDOperations(t *testing.T) {
- base.Setup(t)
- defer base.Teardown()
+func TestNetworksProviderCRUD(t *testing.T) {
+ client, err := clients.NewNetworkV2Client()
+ if err != nil {
+ t.Fatalf("Unable to create a network client: %v", err)
+ }
// Create a network
- n, err := networks.Create(base.Client, networks.CreateOpts{Name: "sample_network", AdminStateUp: networks.Up}).Extract()
- th.AssertNoErr(t, err)
- th.AssertEquals(t, n.Name, "sample_network")
- th.AssertEquals(t, n.AdminStateUp, true)
- networkID := n.ID
-
- // List networks
- pager := networks.List(base.Client, networks.ListOpts{Limit: 2})
- err = pager.EachPage(func(page pagination.Page) (bool, error) {
- t.Logf("--- Page ---")
-
- networkList, err := networks.ExtractNetworks(page)
- th.AssertNoErr(t, err)
-
- for _, n := range networkList {
- t.Logf("Network: ID [%s] Name [%s] Status [%s] Is shared? [%s]",
- n.ID, n.Name, n.Status, strconv.FormatBool(n.Shared))
- }
-
- return true, nil
- })
- th.CheckNoErr(t, err)
-
- // Get a network
- if networkID == "" {
- t.Fatalf("In order to retrieve a network, the NetworkID must be set")
+ network, err := networking.CreateNetwork(t, client)
+ if err != nil {
+ t.Fatalf("Unable to create network: %v", err)
}
- n, err = networks.Get(base.Client, networkID).Extract()
- th.AssertNoErr(t, err)
- th.AssertEquals(t, n.Status, "ACTIVE")
- th.AssertDeepEquals(t, n.Subnets, []string{})
- th.AssertEquals(t, n.Name, "sample_network")
- th.AssertEquals(t, n.AdminStateUp, true)
- th.AssertEquals(t, n.Shared, false)
- th.AssertEquals(t, n.ID, networkID)
+ defer networking.DeleteNetwork(t, client, network.ID)
- // Update network
- n, err = networks.Update(base.Client, networkID, networks.UpdateOpts{Name: "new_network_name"}).Extract()
- th.AssertNoErr(t, err)
- th.AssertEquals(t, n.Name, "new_network_name")
+ getResult := networks.Get(client, network.ID)
+ newNetwork, err := provider.ExtractGet(getResult)
+ if err != nil {
+ t.Fatalf("Unable to extract network: %v", err)
+ }
- // Delete network
- res := networks.Delete(base.Client, networkID)
- th.AssertNoErr(t, res.Err)
-}
-
-func TestCreateMultipleNetworks(t *testing.T) {
- //networks.CreateMany()
+ PrintNetworkExtAttrs(t, newNetwork)
}
diff --git a/acceptance/openstack/networking/v2/extensions/security_test.go b/acceptance/openstack/networking/v2/extensions/security_test.go
index fe02ada..88003e7 100644
--- a/acceptance/openstack/networking/v2/extensions/security_test.go
+++ b/acceptance/openstack/networking/v2/extensions/security_test.go
@@ -5,167 +5,89 @@
import (
"testing"
- base "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2"
+ "github.com/gophercloud/gophercloud/acceptance/clients"
+ networking "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups"
- "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules"
- "github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
- "github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
- "github.com/gophercloud/gophercloud/pagination"
- th "github.com/gophercloud/gophercloud/testhelper"
)
-func TestSecurityGroups(t *testing.T) {
- base.Setup(t)
- defer base.Teardown()
-
- // create security group
- groupID := createSecGroup(t)
-
- // delete security group
- defer deleteSecGroup(t, groupID)
-
- // list security group
- listSecGroups(t)
-
- // get security group
- getSecGroup(t, groupID)
-
- // create port with security group
- networkID, portID := createPort(t, groupID)
-
- // teardown
- defer deleteNetwork(t, networkID)
-
- // delete port
- defer deletePort(t, portID)
-}
-
-func TestSecurityGroupRules(t *testing.T) {
- base.Setup(t)
- defer base.Teardown()
-
- // create security group
- groupID := createSecGroup(t)
-
- defer deleteSecGroup(t, groupID)
-
- // create security group rule
- ruleID := createSecRule(t, groupID)
-
- // delete security group rule
- defer deleteSecRule(t, ruleID)
-
- // list security group rule
- listSecRules(t)
-
- // get security group rule
- getSecRule(t, ruleID)
-}
-
-func createSecGroup(t *testing.T) string {
- sg, err := groups.Create(base.Client, groups.CreateOpts{
- Name: "new-webservers",
- Description: "security group for webservers",
- }).Extract()
-
- th.AssertNoErr(t, err)
-
- t.Logf("Created security group %s", sg.ID)
-
- return sg.ID
-}
-
-func listSecGroups(t *testing.T) {
- err := groups.List(base.Client, groups.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
- list, err := groups.ExtractGroups(page)
- if err != nil {
- t.Errorf("Failed to extract secgroups: %v", err)
- return false, err
- }
-
- for _, sg := range list {
- t.Logf("Listing security group: ID [%s] Name [%s]", sg.ID, sg.Name)
- }
-
- return true, nil
- })
-
- th.AssertNoErr(t, err)
-}
-
-func getSecGroup(t *testing.T, id string) {
- sg, err := groups.Get(base.Client, id).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Getting security group: ID [%s] Name [%s] Description [%s]", sg.ID, sg.Name, sg.Description)
-}
-
-func createPort(t *testing.T, groupID string) (string, string) {
- n, err := networks.Create(base.Client, networks.CreateOpts{Name: "tmp_network"}).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Created network %s", n.ID)
-
- opts := ports.CreateOpts{
- NetworkID: n.ID,
- Name: "my_port",
- SecurityGroups: []string{groupID},
+func TestSecurityGroupsList(t *testing.T) {
+ client, err := clients.NewNetworkV2Client()
+ if err != nil {
+ t.Fatalf("Unable to create a network client: %v", err)
}
- p, err := ports.Create(base.Client, opts).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Created port %s with security group %s", p.ID, groupID)
- return n.ID, p.ID
+ listOpts := groups.ListOpts{}
+ allPages, err := groups.List(client, listOpts).AllPages()
+ if err != nil {
+ t.Fatalf("Unable to list groups: %v", err)
+ }
+
+ allGroups, err := groups.ExtractGroups(allPages)
+ if err != nil {
+ t.Fatalf("Unable to extract groups: %v", err)
+ }
+
+ for _, group := range allGroups {
+ PrintSecurityGroup(t, &group)
+ }
}
-func deleteSecGroup(t *testing.T, groupID string) {
- res := groups.Delete(base.Client, groupID)
- th.AssertNoErr(t, res.Err)
- t.Logf("Deleted security group %s", groupID)
+func TestSecurityGroupsCreateDelete(t *testing.T) {
+ client, err := clients.NewNetworkV2Client()
+ if err != nil {
+ t.Fatalf("Unable to create a network client: %v", err)
+ }
+
+ group, err := CreateSecurityGroup(t, client)
+ if err != nil {
+ t.Fatalf("Unable to create security group: %v", err)
+ }
+ defer DeleteSecurityGroup(t, client, group.ID)
+
+ rule, err := CreateSecurityGroupRule(t, client, group.ID)
+ if err != nil {
+ t.Fatalf("Unable to create security group rule: %v", err)
+ }
+ defer DeleteSecurityGroupRule(t, client, rule.ID)
+
+ PrintSecurityGroup(t, group)
}
-func createSecRule(t *testing.T, groupID string) string {
- r, err := rules.Create(base.Client, rules.CreateOpts{
- Direction: "ingress",
- PortRangeMin: 80,
- EtherType: "IPv4",
- PortRangeMax: 80,
- Protocol: "tcp",
- SecGroupID: groupID,
- }).Extract()
+func TestSecurityGroupsPort(t *testing.T) {
+ client, err := clients.NewNetworkV2Client()
+ if err != nil {
+ t.Fatalf("Unable to create a network client: %v", err)
+ }
- th.AssertNoErr(t, err)
+ network, err := networking.CreateNetwork(t, client)
+ if err != nil {
+ t.Fatalf("Unable to create network: %v", err)
+ }
+ defer networking.DeleteNetwork(t, client, network.ID)
- t.Logf("Created security group rule %s", r.ID)
+ subnet, err := networking.CreateSubnet(t, client, network.ID)
+ if err != nil {
+ t.Fatalf("Unable to create subnet: %v", err)
+ }
+ defer networking.DeleteSubnet(t, client, subnet.ID)
- return r.ID
-}
+ group, err := CreateSecurityGroup(t, client)
+ if err != nil {
+ t.Fatalf("Unable to create security group: %v", err)
+ }
+ defer DeleteSecurityGroup(t, client, group.ID)
-func listSecRules(t *testing.T) {
- err := rules.List(base.Client, rules.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
- list, err := rules.ExtractRules(page)
- if err != nil {
- t.Errorf("Failed to extract sec rules: %v", err)
- return false, err
- }
+ rule, err := CreateSecurityGroupRule(t, client, group.ID)
+ if err != nil {
+ t.Fatalf("Unable to create security group rule: %v", err)
+ }
+ defer DeleteSecurityGroupRule(t, client, rule.ID)
- for _, r := range list {
- t.Logf("Listing security rule: ID [%s]", r.ID)
- }
+ port, err := CreatePortWithSecurityGroup(t, client, network.ID, subnet.ID, group.ID)
+ if err != nil {
+ t.Fatalf("Unable to create port: %v", err)
+ }
+ defer networking.DeletePort(t, client, port.ID)
- return true, nil
- })
-
- th.AssertNoErr(t, err)
-}
-
-func getSecRule(t *testing.T, id string) {
- r, err := rules.Get(base.Client, id).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Getting security rule: ID [%s] Direction [%s] EtherType [%s] Protocol [%s]",
- r.ID, r.Direction, r.EtherType, r.Protocol)
-}
-
-func deleteSecRule(t *testing.T, id string) {
- res := rules.Delete(base.Client, id)
- th.AssertNoErr(t, res.Err)
- t.Logf("Deleted security rule %s", id)
+ networking.PrintPort(t, port)
}
diff --git a/acceptance/openstack/networking/v2/network_test.go b/acceptance/openstack/networking/v2/network_test.go
deleted file mode 100644
index 1926999..0000000
--- a/acceptance/openstack/networking/v2/network_test.go
+++ /dev/null
@@ -1,68 +0,0 @@
-// +build acceptance networking
-
-package v2
-
-import (
- "strconv"
- "testing"
-
- "github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
- "github.com/gophercloud/gophercloud/pagination"
- th "github.com/gophercloud/gophercloud/testhelper"
-)
-
-func TestNetworkCRUDOperations(t *testing.T) {
- Setup(t)
- defer Teardown()
-
- // Create a network
- n, err := networks.Create(Client, networks.CreateOpts{Name: "sample_network", AdminStateUp: networks.Up}).Extract()
- th.AssertNoErr(t, err)
- defer networks.Delete(Client, n.ID)
- th.AssertEquals(t, n.Name, "sample_network")
- th.AssertEquals(t, n.AdminStateUp, true)
- networkID := n.ID
-
- // List networks
- pager := networks.List(Client, networks.ListOpts{Limit: 2})
- err = pager.EachPage(func(page pagination.Page) (bool, error) {
- t.Logf("--- Page ---")
-
- networkList, err := networks.ExtractNetworks(page)
- th.AssertNoErr(t, err)
-
- for _, n := range networkList {
- t.Logf("Network: ID [%s] Name [%s] Status [%s] Is shared? [%s]",
- n.ID, n.Name, n.Status, strconv.FormatBool(n.Shared))
- }
-
- return true, nil
- })
- th.CheckNoErr(t, err)
-
- // Get a network
- if networkID == "" {
- t.Fatalf("In order to retrieve a network, the NetworkID must be set")
- }
- n, err = networks.Get(Client, networkID).Extract()
- th.AssertNoErr(t, err)
- th.AssertEquals(t, n.Status, "ACTIVE")
- th.AssertDeepEquals(t, n.Subnets, []string{})
- th.AssertEquals(t, n.Name, "sample_network")
- th.AssertEquals(t, n.AdminStateUp, true)
- th.AssertEquals(t, n.Shared, false)
- th.AssertEquals(t, n.ID, networkID)
-
- // Update network
- n, err = networks.Update(Client, networkID, networks.UpdateOpts{Name: "new_network_name"}).Extract()
- th.AssertNoErr(t, err)
- th.AssertEquals(t, n.Name, "new_network_name")
-
- // Delete network
- res := networks.Delete(Client, networkID)
- th.AssertNoErr(t, res.Err)
-}
-
-func TestCreateMultipleNetworks(t *testing.T) {
- //networks.CreateMany()
-}
diff --git a/acceptance/openstack/networking/v2/networking.go b/acceptance/openstack/networking/v2/networking.go
new file mode 100644
index 0000000..86c3545
--- /dev/null
+++ b/acceptance/openstack/networking/v2/networking.go
@@ -0,0 +1,182 @@
+package v2
+
+import (
+ "fmt"
+ "testing"
+
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/acceptance/tools"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/apiversions"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/subnets"
+)
+
+// CreateNetwork will create basic network. An error will be returned if the
+// network could not be created.
+func CreateNetwork(t *testing.T, client *gophercloud.ServiceClient) (*networks.Network, error) {
+ networkName := tools.RandomString("TESTACC-", 8)
+ createOpts := networks.CreateOpts{
+ Name: networkName,
+ AdminStateUp: gophercloud.Enabled,
+ }
+
+ t.Logf("Attempting to create network: %s", networkName)
+
+ network, err := networks.Create(client, createOpts).Extract()
+ if err != nil {
+ return network, err
+ }
+
+ t.Logf("Successfully created network.")
+ return network, nil
+}
+
+// CreatePort will create a port on the specified subnet. An error will be
+// returned if the port could not be created.
+func CreatePort(t *testing.T, client *gophercloud.ServiceClient, networkID, subnetID string) (*ports.Port, error) {
+ portName := tools.RandomString("TESTACC-", 8)
+
+ t.Logf("Attempting to create port: %s", portName)
+
+ createOpts := ports.CreateOpts{
+ NetworkID: networkID,
+ Name: portName,
+ AdminStateUp: gophercloud.Disabled,
+ FixedIPs: []ports.IP{ports.IP{SubnetID: subnetID}},
+ }
+
+ port, err := ports.Create(client, createOpts).Extract()
+ if err != nil {
+ return port, err
+ }
+
+ t.Logf("Successfully created port: %s", portName)
+
+ return port, nil
+}
+
+// CreateSubnet will create a subnet on the specified Network ID. An error
+// will be returned if the subnet could not be created.
+func CreateSubnet(t *testing.T, client *gophercloud.ServiceClient, networkID string) (*subnets.Subnet, error) {
+ subnetName := tools.RandomString("TESTACC-", 8)
+ subnetOctet := tools.RandomInt(1, 250)
+ subnetCIDR := fmt.Sprintf("192.168.%d.0/24", subnetOctet)
+ subnetGateway := fmt.Sprintf("192.168.%d.1", subnetOctet)
+ iFalse := false
+ createOpts := subnets.CreateOpts{
+ NetworkID: networkID,
+ CIDR: subnetCIDR,
+ IPVersion: 4,
+ Name: subnetName,
+ EnableDHCP: &iFalse,
+ GatewayIP: &subnetGateway,
+ }
+
+ t.Logf("Attempting to create subnet: %s", subnetName)
+
+ subnet, err := subnets.Create(client, createOpts).Extract()
+ if err != nil {
+ return subnet, err
+ }
+
+ t.Logf("Successfully created subnet.")
+ return subnet, nil
+}
+
+// DeleteNetwork will delete a network with a specified ID. A fatal error will
+// occur if the delete was not successful. This works best when used as a
+// deferred function.
+func DeleteNetwork(t *testing.T, client *gophercloud.ServiceClient, networkID string) {
+ t.Logf("Attempting to delete network: %s", networkID)
+
+ err := networks.Delete(client, networkID).ExtractErr()
+ if err != nil {
+ t.Fatalf("Unable to delete network %s: %v", networkID, err)
+ }
+
+ t.Logf("Deleted network: %s", networkID)
+}
+
+// DeletePort will delete a port with a specified ID. A fatal error will
+// occur if the delete was not successful. This works best when used as a
+// deferred function.
+func DeletePort(t *testing.T, client *gophercloud.ServiceClient, portID string) {
+ t.Logf("Attempting to delete port: %s", portID)
+
+ err := ports.Delete(client, portID).ExtractErr()
+ if err != nil {
+ t.Fatalf("Unable to delete port %s: %v", portID, err)
+ }
+
+ t.Logf("Deleted port: %s", portID)
+}
+
+// DeleteSubnet will delete a subnet with a specified ID. A fatal error will
+// occur if the delete was not successful. This works best when used as a
+// deferred function.
+func DeleteSubnet(t *testing.T, client *gophercloud.ServiceClient, subnetID string) {
+ t.Logf("Attempting to delete subnet: %s", subnetID)
+
+ err := subnets.Delete(client, subnetID).ExtractErr()
+ if err != nil {
+ t.Fatalf("Unable to delete subnet %s: %v", subnetID, err)
+ }
+
+ t.Logf("Deleted subnet: %s", subnetID)
+}
+
+// PrintAPIVersion will print an API version and all of its attributes.
+func PrintAPIVersion(t *testing.T, apiVersion *apiversions.APIVersion) {
+ t.Logf("ID: %s", apiVersion.ID)
+ t.Logf("Status: %s", apiVersion.Status)
+}
+
+// PrintNetwork will print a network and all of its attributes.
+func PrintNetwork(t *testing.T, network *networks.Network) {
+ t.Logf("ID: %s", network.ID)
+ t.Logf("Name: %s", network.Name)
+ t.Logf("AdminStateUp: %t", network.AdminStateUp)
+ t.Logf("Status: %s", network.Status)
+ t.Logf("TenantID: %s", network.TenantID)
+ t.Logf("Shared: %t", network.Shared)
+ t.Logf("Subnets: %s", network.Subnets)
+}
+
+// PrintPort will print a port and all of its attributes.
+func PrintPort(t *testing.T, port *ports.Port) {
+ t.Logf("ID: %s", port.ID)
+ t.Logf("NetworkID: %s", port.NetworkID)
+ t.Logf("Name: %s", port.Name)
+ t.Logf("AdminStateUp: %t", port.AdminStateUp)
+ t.Logf("Status: %s", port.Status)
+ t.Logf("MACAddress: %s", port.MACAddress)
+ t.Logf("FixedIPs: %s", port.FixedIPs)
+ t.Logf("TenantID: %s", port.TenantID)
+ t.Logf("DeviceOwner: %s", port.DeviceOwner)
+ t.Logf("SecurityGroups: %s", port.SecurityGroups)
+ t.Logf("DeviceID: %s", port.DeviceID)
+ t.Logf("DeviceOwner: %s", port.DeviceOwner)
+ t.Logf("AllowedAddressPairs: %s", port.AllowedAddressPairs)
+}
+
+// PrintSubnet will print a subnet and all of its attributes.
+func PrintSubnet(t *testing.T, subnet *subnets.Subnet) {
+ t.Logf("ID: %s", subnet.ID)
+ t.Logf("NetworkID: %s", subnet.NetworkID)
+ t.Logf("Name: %s", subnet.Name)
+ t.Logf("IPVersion: %d", subnet.IPVersion)
+ t.Logf("CIDR: %s", subnet.CIDR)
+ t.Logf("GatewayIP: %s", subnet.GatewayIP)
+ t.Logf("DNSNameservers: %s", subnet.DNSNameservers)
+ t.Logf("AllocationPools: %s", subnet.AllocationPools)
+ t.Logf("HostRoutes: %s", subnet.HostRoutes)
+ t.Logf("EnableDHCP: %t", subnet.EnableDHCP)
+ t.Logf("TenantID: %s", subnet.TenantID)
+}
+
+// PrintVersionResource will print an API version resource and all of its attributes.
+func PrintVersionResource(t *testing.T, versionResource *apiversions.APIVersionResource) {
+ t.Logf("Name: %s", versionResource.Name)
+ t.Logf("Collection: %s", versionResource.Collection)
+}
diff --git a/acceptance/openstack/networking/v2/networks_test.go b/acceptance/openstack/networking/v2/networks_test.go
new file mode 100644
index 0000000..a095079
--- /dev/null
+++ b/acceptance/openstack/networking/v2/networks_test.go
@@ -0,0 +1,65 @@
+// +build acceptance networking
+
+package v2
+
+import (
+ "testing"
+
+ "github.com/gophercloud/gophercloud/acceptance/clients"
+ "github.com/gophercloud/gophercloud/acceptance/tools"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
+)
+
+func TestNetworksList(t *testing.T) {
+ client, err := clients.NewNetworkV2Client()
+ if err != nil {
+ t.Fatalf("Unable to create a network client: %v", err)
+ }
+
+ allPages, err := networks.List(client, nil).AllPages()
+ if err != nil {
+ t.Fatalf("Unable to list networks: %v", err)
+ }
+
+ allNetworks, err := networks.ExtractNetworks(allPages)
+ if err != nil {
+ t.Fatalf("Unable to extract networks: %v", err)
+ }
+
+ for _, network := range allNetworks {
+ PrintNetwork(t, &network)
+ }
+}
+
+func TestNetworksCRUD(t *testing.T) {
+ client, err := clients.NewNetworkV2Client()
+ if err != nil {
+ t.Fatalf("Unable to create a network client: %v", err)
+ }
+
+ // Create a network
+ network, err := CreateNetwork(t, client)
+ if err != nil {
+ t.Fatalf("Unable to create network: %v", err)
+ }
+ defer DeleteNetwork(t, client, network.ID)
+
+ PrintNetwork(t, network)
+
+ newName := tools.RandomString("TESTACC-", 8)
+ updateOpts := &networks.UpdateOpts{
+ Name: newName,
+ }
+
+ _, err = networks.Update(client, network.ID, updateOpts).Extract()
+ if err != nil {
+ t.Fatalf("Unable to update network: %v", err)
+ }
+
+ newNetwork, err := networks.Get(client, network.ID).Extract()
+ if err != nil {
+ t.Fatalf("Unable to retrieve network: %v", err)
+ }
+
+ PrintNetwork(t, newNetwork)
+}
diff --git a/acceptance/openstack/networking/v2/port_test.go b/acceptance/openstack/networking/v2/port_test.go
deleted file mode 100644
index 2ef3408..0000000
--- a/acceptance/openstack/networking/v2/port_test.go
+++ /dev/null
@@ -1,130 +0,0 @@
-// +build acceptance networking
-
-package v2
-
-import (
- "testing"
-
- "github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
- "github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
- "github.com/gophercloud/gophercloud/openstack/networking/v2/subnets"
- "github.com/gophercloud/gophercloud/pagination"
- th "github.com/gophercloud/gophercloud/testhelper"
-)
-
-func TestPortCRUD(t *testing.T) {
- Setup(t)
- defer Teardown()
-
- // Setup network
- t.Log("Setting up network")
- networkID, err := createNetwork()
- th.AssertNoErr(t, err)
- defer networks.Delete(Client, networkID)
-
- // Setup subnet
- t.Logf("Setting up subnet on network %s", networkID)
- subnetID, err := createSubnet(networkID)
- th.AssertNoErr(t, err)
- defer subnets.Delete(Client, subnetID)
-
- // Create port
- t.Logf("Create port based on subnet %s", subnetID)
- portID := createPort(t, networkID, subnetID)
-
- // List ports
- t.Logf("Listing all ports")
- listPorts(t)
-
- // Get port
- if portID == "" {
- t.Fatalf("In order to retrieve a port, the portID must be set")
- }
- p, err := ports.Get(Client, portID).Extract()
- th.AssertNoErr(t, err)
- th.AssertEquals(t, p.ID, portID)
-
- // Update port
- 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)
-}
-
-func createPort(t *testing.T, networkID, subnetID string) string {
- enable := false
- opts := ports.CreateOpts{
- NetworkID: networkID,
- Name: "my_port",
- AdminStateUp: &enable,
- FixedIPs: []ports.IP{ports.IP{SubnetID: subnetID}},
- }
- p, err := ports.Create(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 listPorts(t *testing.T) {
- count := 0
- pager := ports.List(Client, ports.ListOpts{})
- err := pager.EachPage(func(page pagination.Page) (bool, error) {
- count++
- t.Logf("--- Page ---")
-
- portList, err := ports.ExtractPorts(page)
- 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] Allowed Address Pairs [%#v]",
- p.ID, p.Name, p.Status, p.MACAddress, p.FixedIPs, p.SecurityGroups, p.AllowedAddressPairs)
- }
-
- return true, nil
- })
-
- th.CheckNoErr(t, err)
-
- if count == 0 {
- t.Logf("No pages were iterated over when listing ports")
- }
-}
-
-func createNetwork() (string, error) {
- res, err := networks.Create(Client, networks.CreateOpts{Name: "tmp_network", AdminStateUp: networks.Up}).Extract()
- return res.ID, err
-}
-
-func createSubnet(networkID string) (string, error) {
- s, err := subnets.Create(Client, subnets.CreateOpts{
- NetworkID: networkID,
- CIDR: "192.168.199.0/24",
- 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
-}
-
-func TestPortBatchCreate(t *testing.T) {
- // todo
-}
diff --git a/acceptance/openstack/networking/v2/ports_test.go b/acceptance/openstack/networking/v2/ports_test.go
new file mode 100644
index 0000000..b3b9ecb
--- /dev/null
+++ b/acceptance/openstack/networking/v2/ports_test.go
@@ -0,0 +1,74 @@
+// +build acceptance networking
+
+package v2
+
+import (
+ "testing"
+
+ "github.com/gophercloud/gophercloud/acceptance/clients"
+ "github.com/gophercloud/gophercloud/acceptance/tools"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
+)
+
+func TestPortsList(t *testing.T) {
+ client, err := clients.NewNetworkV2Client()
+ if err != nil {
+ t.Fatalf("Unable to create a network client: %v", err)
+ }
+
+ allPages, err := ports.List(client, nil).AllPages()
+ if err != nil {
+ t.Fatalf("Unable to list ports: %v", err)
+ }
+
+ allPorts, err := ports.ExtractPorts(allPages)
+ if err != nil {
+ t.Fatalf("Unable to extract ports: %v", err)
+ }
+
+ for _, port := range allPorts {
+ PrintPort(t, &port)
+ }
+}
+
+func TestPortsCRUD(t *testing.T) {
+ client, err := clients.NewNetworkV2Client()
+ if err != nil {
+ t.Fatalf("Unable to create a network client: %v", err)
+ }
+
+ // Create Network
+ network, err := CreateNetwork(t, client)
+ if err != nil {
+ t.Fatalf("Unable to create network: %v", err)
+ }
+ defer DeleteNetwork(t, client, network.ID)
+
+ // Create Subnet
+ subnet, err := CreateSubnet(t, client, network.ID)
+ if err != nil {
+ t.Fatalf("Unable to create subnet: %v", err)
+ }
+ defer DeleteSubnet(t, client, subnet.ID)
+
+ // Create port
+ port, err := CreatePort(t, client, network.ID, subnet.ID)
+ if err != nil {
+ t.Fatalf("Unable to create port: %v", err)
+ }
+ defer DeletePort(t, client, port.ID)
+
+ PrintPort(t, port)
+
+ // Update port
+ newPortName := tools.RandomString("TESTACC-", 8)
+ updateOpts := ports.UpdateOpts{
+ Name: newPortName,
+ }
+ newPort, err := ports.Update(client, port.ID, updateOpts).Extract()
+ if err != nil {
+ t.Fatalf("Could not update port: %v", err)
+ }
+
+ PrintPort(t, newPort)
+}
diff --git a/acceptance/openstack/networking/v2/subnet_test.go b/acceptance/openstack/networking/v2/subnet_test.go
deleted file mode 100644
index c9efd5c..0000000
--- a/acceptance/openstack/networking/v2/subnet_test.go
+++ /dev/null
@@ -1,141 +0,0 @@
-// +build acceptance networking
-
-package v2
-
-import (
- "testing"
-
- "github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
- "github.com/gophercloud/gophercloud/openstack/networking/v2/subnets"
- "github.com/gophercloud/gophercloud/pagination"
- th "github.com/gophercloud/gophercloud/testhelper"
-)
-
-func TestSubnetList(t *testing.T) {
- Setup(t)
- defer Teardown()
-
- pager := subnets.List(Client, subnets.ListOpts{Limit: 2})
- err := pager.EachPage(func(page pagination.Page) (bool, error) {
- t.Logf("--- Page ---")
-
- subnetList, err := subnets.ExtractSubnets(page)
- th.AssertNoErr(t, err)
-
- for _, s := range subnetList {
- t.Logf("Subnet: ID [%s] Name [%s] IP Version [%d] CIDR [%s] GatewayIP [%s]",
- s.ID, s.Name, s.IPVersion, s.CIDR, s.GatewayIP)
- }
-
- return true, nil
- })
- th.CheckNoErr(t, err)
-}
-
-func TestSubnetCRUD(t *testing.T) {
- Setup(t)
- defer Teardown()
-
- // Setup network
- t.Log("Setting up network")
- n, err := networks.Create(Client, networks.CreateOpts{Name: "tmp_network", AdminStateUp: networks.Up}).Extract()
- th.AssertNoErr(t, err)
- networkID := n.ID
- defer networks.Delete(Client, networkID)
-
- // Create subnet
- t.Log("Create subnet")
- enable := false
- opts := subnets.CreateOpts{
- NetworkID: networkID,
- CIDR: "192.168.199.0/24",
- IPVersion: subnets.IPv4,
- Name: "my_subnet",
- EnableDHCP: &enable,
- }
- s, err := subnets.Create(Client, opts).Extract()
- th.AssertNoErr(t, err)
-
- th.AssertEquals(t, s.NetworkID, networkID)
- th.AssertEquals(t, s.CIDR, "192.168.199.0/24")
- th.AssertEquals(t, s.IPVersion, 4)
- th.AssertEquals(t, s.Name, "my_subnet")
- th.AssertEquals(t, s.EnableDHCP, false)
- th.AssertEquals(t, s.GatewayIP, "192.168.199.1")
- subnetID := s.ID
-
- // Get subnet
- t.Log("Getting subnet")
- s, err = subnets.Get(Client, subnetID).Extract()
- th.AssertNoErr(t, err)
- th.AssertEquals(t, s.ID, subnetID)
-
- // Update subnet
- t.Log("Update subnet")
- s, err = subnets.Update(Client, subnetID, subnets.UpdateOpts{Name: "new_subnet_name"}).Extract()
- th.AssertNoErr(t, err)
- th.AssertEquals(t, s.Name, "new_subnet_name")
-
- // Delete subnet
- t.Log("Delete subnet")
- res := subnets.Delete(Client, subnetID)
- th.AssertNoErr(t, res.Err)
-
- // Create subnet with no gateway
- t.Log("Create subnet with no gateway")
- opts = subnets.CreateOpts{
- NetworkID: networkID,
- CIDR: "192.168.199.0/24",
- IPVersion: subnets.IPv4,
- Name: "my_subnet",
- EnableDHCP: &enable,
- NoGateway: true,
- }
- s, err = subnets.Create(Client, opts).Extract()
- th.AssertNoErr(t, err)
-
- th.AssertEquals(t, s.NetworkID, networkID)
- th.AssertEquals(t, s.CIDR, "192.168.199.0/24")
- th.AssertEquals(t, s.IPVersion, 4)
- th.AssertEquals(t, s.Name, "my_subnet")
- th.AssertEquals(t, s.EnableDHCP, false)
- th.AssertEquals(t, s.GatewayIP, "")
- subnetID = s.ID
-
- // Get subnet
- t.Log("Getting subnet with no gateway")
- s, err = subnets.Get(Client, subnetID).Extract()
- th.AssertNoErr(t, err)
- th.AssertEquals(t, s.ID, subnetID)
-
- // Update subnet
- t.Log("Update subnet with no gateway")
- s, err = subnets.Update(Client, subnetID, subnets.UpdateOpts{Name: "new_subnet_name"}).Extract()
- th.AssertNoErr(t, err)
- th.AssertEquals(t, s.Name, "new_subnet_name")
-
- // Delete subnet
- t.Log("Delete subnet with no gateway")
- res = subnets.Delete(Client, subnetID)
- th.AssertNoErr(t, res.Err)
-
- // Create subnet with invalid gateway configuration
- t.Log("Create subnet with invalid gateway configuration")
- opts = subnets.CreateOpts{
- NetworkID: networkID,
- CIDR: "192.168.199.0/24",
- IPVersion: subnets.IPv4,
- Name: "my_subnet",
- EnableDHCP: &enable,
- NoGateway: true,
- GatewayIP: "192.168.199.1",
- }
- _, err = subnets.Create(Client, opts).Extract()
- if err == nil {
- t.Fatalf("Expected an error, got none")
- }
-}
-
-func TestBatchCreate(t *testing.T) {
- // todo
-}
diff --git a/acceptance/openstack/networking/v2/subnets_test.go b/acceptance/openstack/networking/v2/subnets_test.go
new file mode 100644
index 0000000..49c970a
--- /dev/null
+++ b/acceptance/openstack/networking/v2/subnets_test.go
@@ -0,0 +1,73 @@
+// +build acceptance networking
+
+package v2
+
+import (
+ "testing"
+
+ "github.com/gophercloud/gophercloud/acceptance/clients"
+ "github.com/gophercloud/gophercloud/acceptance/tools"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/subnets"
+)
+
+func TestSubnetsList(t *testing.T) {
+ client, err := clients.NewNetworkV2Client()
+ if err != nil {
+ t.Fatalf("Unable to create a network client: %v", err)
+ }
+
+ allPages, err := subnets.List(client, nil).AllPages()
+ if err != nil {
+ t.Fatalf("Unable to list subnets: %v", err)
+ }
+
+ allSubnets, err := subnets.ExtractSubnets(allPages)
+ if err != nil {
+ t.Fatalf("Unable to extract subnets: %v", err)
+ }
+
+ for _, subnet := range allSubnets {
+ PrintSubnet(t, &subnet)
+ }
+}
+
+func TestSubnetCRUD(t *testing.T) {
+ client, err := clients.NewNetworkV2Client()
+ if err != nil {
+ t.Fatalf("Unable to create a network client: %v", err)
+ }
+
+ // Create Network
+ network, err := CreateNetwork(t, client)
+ if err != nil {
+ t.Fatalf("Unable to create network: %v", err)
+ }
+ defer DeleteNetwork(t, client, network.ID)
+
+ // Create Subnet
+ subnet, err := CreateSubnet(t, client, network.ID)
+ if err != nil {
+ t.Fatalf("Unable to create subnet: %v", err)
+ }
+ defer DeleteSubnet(t, client, subnet.ID)
+
+ PrintSubnet(t, subnet)
+
+ // Update Subnet
+ newSubnetName := tools.RandomString("TESTACC-", 8)
+ updateOpts := subnets.UpdateOpts{
+ Name: newSubnetName,
+ }
+ _, err = subnets.Update(client, subnet.ID, updateOpts).Extract()
+ if err != nil {
+ t.Fatalf("Unable to update subnet: %v", err)
+ }
+
+ // Get subnet
+ newSubnet, err := subnets.Get(client, subnet.ID).Extract()
+ if err != nil {
+ t.Fatalf("Unable to get subnet: %v", err)
+ }
+
+ PrintSubnet(t, newSubnet)
+}
diff --git a/script/acceptancetest_environments/keystonev3-lbaasv2.sh b/script/acceptancetest_environments/keystonev3-lbaasv2.sh
new file mode 100644
index 0000000..69efca9
--- /dev/null
+++ b/script/acceptancetest_environments/keystonev3-lbaasv2.sh
@@ -0,0 +1,204 @@
+#!/bin/bash
+#
+# This script is useful for creating a devstack environment to run gophercloud
+# acceptance tests on.
+#
+# To run, simply execute this script within a virtual machine.
+#
+# The following OpenStack versions are installed:
+# * OpenStack Mitaka
+# * Keystone v3
+# * Glance v1 and v2
+# * Nova v2 and v2.1
+# * Cinder v1 and v2
+# * Trove v1
+# * Swift v1
+# * Neutron v2
+# * Neutron LBaaS v2.0
+# * Neutron FWaaS v2.0
+#
+# Go 1.6 is also installed.
+
+set -e
+
+cd
+sudo apt-get update
+sudo apt-get install -y git make mercurial
+
+sudo wget -O /usr/local/bin/gimme https://raw.githubusercontent.com/travis-ci/gimme/master/gimme
+sudo chmod +x /usr/local/bin/gimme
+gimme 1.6 >> .bashrc
+
+mkdir ~/go
+eval "$(/usr/local/bin/gimme 1.6)"
+echo 'export GOPATH=$HOME/go' >> .bashrc
+export GOPATH=$HOME/go
+
+export PATH=$PATH:$HOME/terraform:$HOME/go/bin
+echo 'export PATH=$PATH:$HOME/terraform:$HOME/go/bin' >> .bashrc
+source .bashrc
+
+git clone https://git.openstack.org/openstack-dev/devstack -b stable/mitaka
+cd devstack
+cat >local.conf <<EOF
+[[local|localrc]]
+# OpenStack version
+OPENSTACK_VERSION="mitaka"
+
+# devstack password
+DEVSTACK_PASSWORD="password"
+
+# Configure passwords and the Swift Hash
+MYSQL_PASSWORD=\$DEVSTACK_PASSWORD
+RABBIT_PASSWORD=\$DEVSTACK_PASSWORD
+SERVICE_TOKEN=\$DEVSTACK_PASSWORD
+ADMIN_PASSWORD=\$DEVSTACK_PASSWORD
+SERVICE_PASSWORD=\$DEVSTACK_PASSWORD
+SWIFT_HASH=\$DEVSTACK_PASSWORD
+
+# Configure the stable OpenStack branches used by DevStack
+# For stable branches see
+# http://git.openstack.org/cgit/openstack-dev/devstack/refs/
+CINDER_BRANCH=stable/\$OPENSTACK_VERSION
+CEILOMETER_BRANCH=stable/\$OPENSTACK_VERSION
+GLANCE_BRANCH=stable/\$OPENSTACK_VERSION
+HEAT_BRANCH=stable/\$OPENSTACK_VERSION
+HORIZON_BRANCH=stable/\$OPENSTACK_VERSION
+KEYSTONE_BRANCH=stable/\$OPENSTACK_VERSION
+NEUTRON_BRANCH=stable/\$OPENSTACK_VERSION
+NOVA_BRANCH=stable/\$OPENSTACK_VERSION
+SWIFT_BRANCH=stable/\$OPENSTACK_VERSION
+ZAQAR_BRANCH=stable/\$OPENSTACK_VERSION
+
+# Enable Swift
+enable_service s-proxy
+enable_service s-object
+enable_service s-container
+enable_service s-account
+
+# Disable Nova Network and enable Neutron
+disable_service n-net
+enable_service q-svc
+enable_service q-agt
+enable_service q-dhcp
+enable_service q-l3
+enable_service q-meta
+enable_service q-flavors
+
+# Disable Neutron metering
+disable_service q-metering
+
+# Enable LBaaS V1
+#enable_service q-lbaas
+
+# Enable FWaaS
+enable_service q-fwaas
+
+# Enable LBaaS v2
+enable_plugin neutron-lbaas https://git.openstack.org/openstack/neutron-lbaas stable/\$OPENSTACK_VERSION
+#enable_plugin octavia https://git.openstack.org/openstack/octavia stable/\$OPENSTACK_VERSION
+enable_plugin octavia https://git.openstack.org/openstack/octavia
+enable_service q-lbaasv2
+enable_service octavia
+enable_service o-cw
+enable_service o-hm
+enable_service o-hk
+enable_service o-api
+
+# Octavia
+OCTAVIA_AUTH_VERSION=3
+
+# Enable Trove
+#enable_plugin trove git://git.openstack.org/openstack/trove.git stable/\$OPENSTACK_VERSION
+#enable_service trove,tr-api,tr-tmgr,tr-cond
+
+# Disable Temptest
+disable_service tempest
+
+# Disable Horizon
+disable_service horizon
+
+# Disable Keystone v2
+ENABLE_IDENTITY_V2=False
+
+# Enable SSL/tls
+#enable_service tls-proxy
+#USE_SSL=True
+
+# Enable Ceilometer
+#enable_service ceilometer-acompute
+#enable_service ceilometer-acentral
+#enable_service ceilometer-anotification
+#enable_service ceilometer-collector
+#enable_service ceilometer-alarm-evaluator
+#enable_service ceilometer-alarm-notifier
+#enable_service ceilometer-api
+
+# Enable Zaqar
+#enable_plugin zaqar https://github.com/openstack/zaqar
+#enable_service zaqar-server
+
+# Automatically download and register a VM image that Heat can launch
+# For more information on Heat and DevStack see
+# http://docs.openstack.org/developer/heat/getting_started/on_devstack.html
+#IMAGE_URLS+=",http://cloud.fedoraproject.org/fedora-20.x86_64.qcow2"
+#IMAGE_URLS+=",https://cloud-images.ubuntu.com/trusty/current/trusty-server-cloudimg-amd64-disk1.img"
+
+# Logging
+LOGDAYS=1
+LOGFILE=/opt/stack/logs/stack.sh.log
+LOGDIR=/opt/stack/logs
+
+[[post-config|\$OCTAVIA_CONF]]
+[default]
+debug = true
+verbose = true
+[keystone_authtoken]
+auth_uri = http://localhost:5000/v3
+auth_url = http://localhost:35357/v3
+user_domain_id = default
+project_name = default
+auth_type = password
+[keystone_authtoken_v3]
+admin_user_domain = default
+admin_project_domain = default
+[[post-config|\$NEUTRON_CONF]]
+[service_auth]
+auth_version = 3
+auth_uri = http://localhost:5000/v3
+auth_url = http://localhost:35357/v3
+admin_user_domain = default
+admin_project_domain = default
+[[post-config|\$NEUTRON_LBAAS_CONF]]
+[service_auth]
+auth_version = 3
+auth_uri = http://localhost:5000/v3
+auth_url = http://localhost:35357/v3
+admin_user_domain = default
+admin_project_domain = default
+EOF
+./stack.sh
+
+# Patch openrc
+cat >> openrc <<EOF
+if [ "\$OS_IDENTITY_API_VERSION" = "3" ]; then
+ export OS_USER_DOMAIN_ID=\${OS_USER_DOMAIN_ID:-"default"}
+ export OS_PROJECT_DOMAIN_ID=\${OS_PROJECT_DOMAIN_ID:-"default"}
+fi
+EOF
+
+# Prep the testing environment by creating the required testing resources and environment variables
+source openrc admin
+wget http://download.cirros-cloud.net/0.3.4/cirros-0.3.4-x86_64-disk.img
+glance image-create --name CirrOS --disk-format qcow2 --container-format bare < cirros-0.3.4-x86_64-disk.img
+nova flavor-create m1.tform 99 512 5 1 --ephemeral 10
+_NETWORK_ID=$(nova net-list | grep private | awk -F\| '{print $2}' | tr -d ' ')
+_EXTGW_ID=$(nova net-list | grep public | awk -F\| '{print $2}' | tr -d ' ')
+_IMAGE_ID=$(nova image-list | grep CirrOS | awk -F\| '{print $2}' | tr -d ' ' | head -1)
+echo export OS_IMAGE_NAME="cirros-0.3.4-x86_64-uec" >> openrc
+echo export OS_IMAGE_ID="$_IMAGE_ID" >> openrc
+echo export OS_NETWORK_ID=$_NETWORK_ID >> openrc
+echo export OS_EXTGW_ID=$_EXTGW_ID >> openrc
+echo export OS_POOL_NAME="public" >> openrc
+echo export OS_FLAVOR_ID=99 >> openrc
+source openrc demo