merge lbaasv2, portsbinding, volumes v2; remove 'rackspace' refs; update docs
diff --git a/acceptance/openstack/blockstorage/v2/extensions/pkg.go b/acceptance/openstack/blockstorage/v2/extensions/pkg.go
new file mode 100644
index 0000000..89d906d
--- /dev/null
+++ b/acceptance/openstack/blockstorage/v2/extensions/pkg.go
@@ -0,0 +1,3 @@
+// The extensions package contains acceptance tests for the Openstack Cinder V2 extensions service.
+
+package extensions
diff --git a/acceptance/openstack/blockstorage/v2/extensions/volumeactions_test.go b/acceptance/openstack/blockstorage/v2/extensions/volumeactions_test.go
new file mode 100644
index 0000000..20a4597
--- /dev/null
+++ b/acceptance/openstack/blockstorage/v2/extensions/volumeactions_test.go
@@ -0,0 +1,149 @@
+// +build acceptance blockstorage
+
+package extensions
+
+import (
+ "os"
+ "testing"
+
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/openstack"
+ "github.com/gophercloud/gophercloud/openstack/blockstorage/v2/extensions/volumeactions"
+ "github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes"
+ th "github.com/gophercloud/gophercloud/testhelper"
+)
+
+func newClient(t *testing.T) (*gophercloud.ServiceClient, error) {
+ ao, err := openstack.AuthOptionsFromEnv()
+ th.AssertNoErr(t, err)
+
+ client, err := openstack.AuthenticatedClient(ao)
+ th.AssertNoErr(t, err)
+
+ return openstack.NewBlockStorageV2(client, gophercloud.EndpointOpts{
+ Region: os.Getenv("OS_REGION_NAME"),
+ })
+}
+
+func TestVolumeAttach(t *testing.T) {
+ client, err := newClient(t)
+ th.AssertNoErr(t, err)
+
+ t.Logf("Creating volume")
+ cv, err := volumes.Create(client, &volumes.CreateOpts{
+ Size: 1,
+ Name: "blockv2-volume",
+ }).Extract()
+ th.AssertNoErr(t, err)
+
+ defer func() {
+ err = volumes.WaitForStatus(client, cv.ID, "available", 60)
+ th.AssertNoErr(t, err)
+
+ t.Logf("Deleting volume")
+ err = volumes.Delete(client, cv.ID).ExtractErr()
+ th.AssertNoErr(t, err)
+ }()
+
+ err = volumes.WaitForStatus(client, cv.ID, "available", 60)
+ th.AssertNoErr(t, err)
+
+ instanceID := os.Getenv("OS_INSTANCE_ID")
+ if instanceID == "" {
+ t.Fatal("Environment variable OS_INSTANCE_ID is required")
+ }
+
+ t.Logf("Attaching volume")
+ err = volumeactions.Attach(client, cv.ID, &volumeactions.AttachOpts{
+ MountPoint: "/mnt",
+ Mode: "rw",
+ InstanceUUID: instanceID,
+ }).ExtractErr()
+ th.AssertNoErr(t, err)
+
+ err = volumes.WaitForStatus(client, cv.ID, "in-use", 60)
+ th.AssertNoErr(t, err)
+
+ t.Logf("Detaching volume")
+ err = volumeactions.Detach(client, cv.ID).ExtractErr()
+ th.AssertNoErr(t, err)
+}
+
+func TestVolumeReserve(t *testing.T) {
+ client, err := newClient(t)
+ th.AssertNoErr(t, err)
+
+ t.Logf("Creating volume")
+ cv, err := volumes.Create(client, &volumes.CreateOpts{
+ Size: 1,
+ Name: "blockv2-volume",
+ }).Extract()
+ th.AssertNoErr(t, err)
+
+ defer func() {
+ err = volumes.WaitForStatus(client, cv.ID, "available", 60)
+ th.AssertNoErr(t, err)
+
+ t.Logf("Deleting volume")
+ err = volumes.Delete(client, cv.ID).ExtractErr()
+ th.AssertNoErr(t, err)
+ }()
+
+ err = volumes.WaitForStatus(client, cv.ID, "available", 60)
+ th.AssertNoErr(t, err)
+
+ t.Logf("Reserving volume")
+ err = volumeactions.Reserve(client, cv.ID).ExtractErr()
+ th.AssertNoErr(t, err)
+
+ err = volumes.WaitForStatus(client, cv.ID, "attaching", 60)
+ th.AssertNoErr(t, err)
+
+ t.Logf("Unreserving volume")
+ err = volumeactions.Unreserve(client, cv.ID).ExtractErr()
+ th.AssertNoErr(t, err)
+
+ err = volumes.WaitForStatus(client, cv.ID, "available", 60)
+ th.AssertNoErr(t, err)
+}
+
+func TestVolumeConns(t *testing.T) {
+ client, err := newClient(t)
+ th.AssertNoErr(t, err)
+
+ t.Logf("Creating volume")
+ cv, err := volumes.Create(client, &volumes.CreateOpts{
+ Size: 1,
+ Name: "blockv2-volume",
+ }).Extract()
+ th.AssertNoErr(t, err)
+
+ defer func() {
+ err = volumes.WaitForStatus(client, cv.ID, "available", 60)
+ th.AssertNoErr(t, err)
+
+ t.Logf("Deleting volume")
+ err = volumes.Delete(client, cv.ID).ExtractErr()
+ th.AssertNoErr(t, err)
+ }()
+
+ err = volumes.WaitForStatus(client, cv.ID, "available", 60)
+ th.AssertNoErr(t, err)
+
+ connOpts := &volumeactions.ConnectorOpts{
+ IP: "127.0.0.1",
+ Host: "stack",
+ Initiator: "iqn.1994-05.com.redhat:17cf566367d2",
+ Multipath: false,
+ Platform: "x86_64",
+ OSType: "linux2",
+ }
+
+ t.Logf("Initializing connection")
+ _, err = volumeactions.InitializeConnection(client, cv.ID, connOpts).Extract()
+ th.AssertNoErr(t, err)
+
+ t.Logf("Terminating connection")
+ err = volumeactions.TerminateConnection(client, cv.ID, connOpts).ExtractErr()
+ th.AssertNoErr(t, err)
+}
diff --git a/acceptance/openstack/blockstorage/v2/pkg.go b/acceptance/openstack/blockstorage/v2/pkg.go
new file mode 100644
index 0000000..31dd0ff
--- /dev/null
+++ b/acceptance/openstack/blockstorage/v2/pkg.go
@@ -0,0 +1,3 @@
+// The v2 package contains acceptance tests for the Openstack Cinder V2 service.
+
+package v2
diff --git a/acceptance/openstack/blockstorage/v2/volumes_test.go b/acceptance/openstack/blockstorage/v2/volumes_test.go
new file mode 100644
index 0000000..9edf31a
--- /dev/null
+++ b/acceptance/openstack/blockstorage/v2/volumes_test.go
@@ -0,0 +1,63 @@
+// +build acceptance blockstorage
+
+package v2
+
+import (
+ "os"
+ "testing"
+
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/openstack"
+ "github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+)
+
+func newClient(t *testing.T) (*gophercloud.ServiceClient, error) {
+ ao, err := openstack.AuthOptionsFromEnv()
+ th.AssertNoErr(t, err)
+
+ client, err := openstack.AuthenticatedClient(ao)
+ th.AssertNoErr(t, err)
+
+ return openstack.NewBlockStorageV2(client, gophercloud.EndpointOpts{
+ Region: os.Getenv("OS_REGION_NAME"),
+ })
+}
+
+func TestVolumes(t *testing.T) {
+ client, err := newClient(t)
+ th.AssertNoErr(t, err)
+
+ cv, err := volumes.Create(client, &volumes.CreateOpts{
+ Size: 1,
+ Name: "blockv2-volume",
+ }).Extract()
+ th.AssertNoErr(t, err)
+ defer func() {
+ err = volumes.WaitForStatus(client, cv.ID, "available", 60)
+ th.AssertNoErr(t, err)
+ err = volumes.Delete(client, cv.ID).ExtractErr()
+ th.AssertNoErr(t, err)
+ }()
+
+ _, err = volumes.Update(client, cv.ID, &volumes.UpdateOpts{
+ Name: "blockv2-updated-volume",
+ }).Extract()
+ th.AssertNoErr(t, err)
+
+ v, err := volumes.Get(client, cv.ID).Extract()
+ th.AssertNoErr(t, err)
+ t.Logf("Got volume: %+v\n", v)
+
+ if v.Name != "blockv2-updated-volume" {
+ t.Errorf("Unable to update volume: Expected name: blockv2-updated-volume\nActual name: %s", v.Name)
+ }
+
+ err = volumes.List(client, &volumes.ListOpts{Name: "blockv2-updated-volume"}).EachPage(func(page pagination.Page) (bool, error) {
+ vols, err := volumes.ExtractVolumes(page)
+ th.CheckEquals(t, 1, len(vols))
+ return true, err
+ })
+ th.AssertNoErr(t, err)
+}