Merge pull request #262 from jamiehannaford/godoc-touch-up

[wip] Godocs touch up
diff --git a/acceptance/openstack/blockstorage/v1/volumes_test.go b/acceptance/openstack/blockstorage/v1/volumes_test.go
index f84f5cb..6739a99 100644
--- a/acceptance/openstack/blockstorage/v1/volumes_test.go
+++ b/acceptance/openstack/blockstorage/v1/volumes_test.go
@@ -3,7 +3,6 @@
 package v1
 
 import (
-	"fmt"
 	"os"
 	"testing"
 
@@ -68,7 +67,7 @@
 		t.Error(err)
 		return
 	}
-	fmt.Printf("Got volume: %+v\n", v)
+	t.Logf("Got volume: %+v\n", v)
 
 	if v.Name != "gophercloud-updated-volume" {
 		t.Errorf("Unable to update volume: Expected name: gophercloud-updated-volume\nActual name: %s", v.Name)
diff --git a/acceptance/openstack/compute/v2/bootfromvolume_test.go b/acceptance/openstack/compute/v2/bootfromvolume_test.go
new file mode 100644
index 0000000..d08abe6
--- /dev/null
+++ b/acceptance/openstack/compute/v2/bootfromvolume_test.go
@@ -0,0 +1,50 @@
+// +build acceptance
+
+package v2
+
+import (
+	"testing"
+
+	"github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume"
+	"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
+	th "github.com/rackspace/gophercloud/testhelper"
+	"github.com/smashwilson/gophercloud/acceptance/tools"
+)
+
+func TestBootFromVolume(t *testing.T) {
+	client, err := newClient()
+	th.AssertNoErr(t, err)
+
+	if testing.Short() {
+		t.Skip("Skipping test that requires server creation in short mode.")
+	}
+
+	choices, err := ComputeChoicesFromEnv()
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	name := tools.RandomString("Gophercloud-", 8)
+	t.Logf("Creating server [%s].", name)
+
+	bd := []bootfromvolume.BlockDevice{
+		bootfromvolume.BlockDevice{
+			UUID:       choices.ImageID,
+			SourceType: bootfromvolume.Image,
+			VolumeSize: 10,
+		},
+	}
+
+	serverCreateOpts := servers.CreateOpts{
+		Name:      name,
+		FlavorRef: "3",
+	}
+	server, err := bootfromvolume.Create(client, bootfromvolume.CreateOptsExt{
+		serverCreateOpts,
+		bd,
+	}).Extract()
+	th.AssertNoErr(t, err)
+	t.Logf("Created server: %+v\n", server)
+	//defer deleteServer(t, client, server)
+	t.Logf("Deleting server [%s]...", name)
+}
diff --git a/acceptance/openstack/compute/v2/flavors_test.go b/acceptance/openstack/compute/v2/flavors_test.go
index cf547f2..9f51b12 100644
--- a/acceptance/openstack/compute/v2/flavors_test.go
+++ b/acceptance/openstack/compute/v2/flavors_test.go
@@ -17,7 +17,7 @@
 
 	t.Logf("ID\tRegion\tName\tStatus\tCreated")
 
-	pager := flavors.List(client, nil)
+	pager := flavors.ListDetail(client, nil)
 	count, pages := 0, 0
 	pager.EachPage(func(page pagination.Page) (bool, error) {
 		t.Logf("---")
diff --git a/acceptance/openstack/compute/v2/servers_test.go b/acceptance/openstack/compute/v2/servers_test.go
index 6bdc9e9..e223c18 100644
--- a/acceptance/openstack/compute/v2/servers_test.go
+++ b/acceptance/openstack/compute/v2/servers_test.go
@@ -3,7 +3,6 @@
 package v2
 
 import (
-	"fmt"
 	"os"
 	"testing"
 
@@ -42,7 +41,7 @@
 		return true, nil
 	})
 
-	fmt.Printf("--------\n%d servers listed on %d pages.\n", count, pages)
+	t.Logf("--------\n%d servers listed on %d pages.\n", count, pages)
 }
 
 func networkingClient() (*gophercloud.ServiceClient, error) {
@@ -63,7 +62,7 @@
 }
 
 func createServer(t *testing.T, client *gophercloud.ServiceClient, choices *ComputeChoices) (*servers.Server, error) {
-	if testing.Short(){
+	if testing.Short() {
 		t.Skip("Skipping test that requires server creation in short mode.")
 	}
 
@@ -319,7 +318,10 @@
 
 	t.Logf("Attempting to resize server [%s]", server.ID)
 
-	if res := servers.Resize(client, server.ID, choices.FlavorIDResize); res.Err != nil {
+	opts := &servers.ResizeOpts{
+		FlavorRef: choices.FlavorIDResize,
+	}
+	if res := servers.Resize(client, server.ID, opts); res.Err != nil {
 		t.Fatal(res.Err)
 	}
 
diff --git a/acceptance/rackspace/compute/v2/bootfromvolume_test.go b/acceptance/rackspace/compute/v2/bootfromvolume_test.go
new file mode 100644
index 0000000..010bf42
--- /dev/null
+++ b/acceptance/rackspace/compute/v2/bootfromvolume_test.go
@@ -0,0 +1,46 @@
+// +build acceptance
+
+package v2
+
+import (
+	"testing"
+
+	osBFV "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume"
+	"github.com/rackspace/gophercloud/rackspace/compute/v2/bootfromvolume"
+	"github.com/rackspace/gophercloud/rackspace/compute/v2/servers"
+	th "github.com/rackspace/gophercloud/testhelper"
+	"github.com/smashwilson/gophercloud/acceptance/tools"
+)
+
+func TestBootFromVolume(t *testing.T) {
+	client, err := newClient()
+	th.AssertNoErr(t, err)
+
+	if testing.Short() {
+		t.Skip("Skipping test that requires server creation in short mode.")
+	}
+
+	options, err := optionsFromEnv()
+	th.AssertNoErr(t, err)
+
+	name := tools.RandomString("Gophercloud-", 8)
+	t.Logf("Creating server [%s].", name)
+
+	bd := []osBFV.BlockDevice{
+		osBFV.BlockDevice{
+			UUID:       options.imageID,
+			SourceType: osBFV.Image,
+			VolumeSize: 10,
+		},
+	}
+
+	server, err := bootfromvolume.Create(client, servers.CreateOpts{
+		Name:        name,
+		FlavorRef:   "performance1-1",
+		BlockDevice: bd,
+	}).Extract()
+	th.AssertNoErr(t, err)
+	t.Logf("Created server: %+v\n", server)
+	//defer deleteServer(t, client, server)
+	t.Logf("Deleting server [%s]...", name)
+}
diff --git a/acceptance/rackspace/compute/v2/flavors_test.go b/acceptance/rackspace/compute/v2/flavors_test.go
index 248ab91..4618ecc 100644
--- a/acceptance/rackspace/compute/v2/flavors_test.go
+++ b/acceptance/rackspace/compute/v2/flavors_test.go
@@ -15,7 +15,7 @@
 	th.AssertNoErr(t, err)
 
 	count := 0
-	err = flavors.List(client, nil).EachPage(func(page pagination.Page) (bool, error) {
+	err = flavors.ListDetail(client, nil).EachPage(func(page pagination.Page) (bool, error) {
 		count++
 		t.Logf("-- Page %0d --", count)
 
diff --git a/acceptance/rackspace/compute/v2/servers_test.go b/acceptance/rackspace/compute/v2/servers_test.go
index af4bbe0..5359450 100644
--- a/acceptance/rackspace/compute/v2/servers_test.go
+++ b/acceptance/rackspace/compute/v2/servers_test.go
@@ -38,14 +38,20 @@
 	th.AssertNoErr(t, err)
 
 	name := tools.RandomString("Gophercloud-", 8)
-	t.Logf("Creating server [%s].", name)
-	s, err := servers.Create(client, &servers.CreateOpts{
+
+	opts := &servers.CreateOpts{
 		Name:       name,
 		ImageRef:   options.imageID,
 		FlavorRef:  options.flavorID,
-		KeyPair:    keyName,
 		DiskConfig: diskconfig.Manual,
-	}).Extract()
+	}
+
+	if keyName != "" {
+		opts.KeyPair = keyName
+	}
+
+	t.Logf("Creating server [%s].", name)
+	s, err := servers.Create(client, opts).Extract()
 	th.AssertNoErr(t, err)
 	t.Logf("Creating server.")
 
diff --git a/acceptance/rackspace/compute/v2/virtualinterfaces_test.go b/acceptance/rackspace/compute/v2/virtualinterfaces_test.go
index 446d3a3..39475e1 100644
--- a/acceptance/rackspace/compute/v2/virtualinterfaces_test.go
+++ b/acceptance/rackspace/compute/v2/virtualinterfaces_test.go
@@ -3,51 +3,51 @@
 package v2
 
 import (
-  "testing"
+	"testing"
 
-  "github.com/rackspace/gophercloud/pagination"
-  "github.com/rackspace/gophercloud/rackspace/compute/v2/networks"
-  "github.com/rackspace/gophercloud/rackspace/compute/v2/virtualinterfaces"
-  th "github.com/rackspace/gophercloud/testhelper"
+	"github.com/rackspace/gophercloud/pagination"
+	"github.com/rackspace/gophercloud/rackspace/compute/v2/networks"
+	"github.com/rackspace/gophercloud/rackspace/compute/v2/virtualinterfaces"
+	th "github.com/rackspace/gophercloud/testhelper"
 )
 
 func TestVirtualInterfaces(t *testing.T) {
-  client, err := newClient()
-  th.AssertNoErr(t, err)
+	client, err := newClient()
+	th.AssertNoErr(t, err)
 
-  // Create a server
-  server := createServer(t, client)
-  t.Logf("Created Server: %v\n", server)
-  defer deleteServer(t, client, server)
-  serverID := server.ID
+	// Create a server
+	server := createServer(t, client, "")
+	t.Logf("Created Server: %v\n", server)
+	defer deleteServer(t, client, server)
+	serverID := server.ID
 
-  // Create a network
-  n, err := networks.Create(client, networks.CreateOpts{Label: "sample_network", CIDR: "172.20.0.0/24"}).Extract()
-  th.AssertNoErr(t, err)
-  t.Logf("Created Network: %v\n", n)
-  defer networks.Delete(client, n.ID)
-  networkID := n.ID
+	// Create a network
+	n, err := networks.Create(client, networks.CreateOpts{Label: "sample_network", CIDR: "172.20.0.0/24"}).Extract()
+	th.AssertNoErr(t, err)
+	t.Logf("Created Network: %v\n", n)
+	defer networks.Delete(client, n.ID)
+	networkID := n.ID
 
-  // Create a virtual interface
-  vi, err := virtualinterfaces.Create(client, serverID, networkID).Extract()
-  th.AssertNoErr(t, err)
-  t.Logf("Created virtual interface: %+v\n", vi)
-  defer virtualinterfaces.Delete(client, serverID, vi.ID)
+	// Create a virtual interface
+	vi, err := virtualinterfaces.Create(client, serverID, networkID).Extract()
+	th.AssertNoErr(t, err)
+	t.Logf("Created virtual interface: %+v\n", vi)
+	defer virtualinterfaces.Delete(client, serverID, vi.ID)
 
-  // List virtual interfaces
-  pager := virtualinterfaces.List(client, serverID)
-  err = pager.EachPage(func(page pagination.Page) (bool, error) {
-    t.Logf("--- Page ---")
+	// List virtual interfaces
+	pager := virtualinterfaces.List(client, serverID)
+	err = pager.EachPage(func(page pagination.Page) (bool, error) {
+		t.Logf("--- Page ---")
 
-    virtualinterfacesList, err := virtualinterfaces.ExtractVirtualInterfaces(page)
-    th.AssertNoErr(t, err)
+		virtualinterfacesList, err := virtualinterfaces.ExtractVirtualInterfaces(page)
+		th.AssertNoErr(t, err)
 
-    for _, vi := range virtualinterfacesList {
-      t.Logf("Virtual Interface: ID [%s] MAC Address [%s] IP Addresses [%v]",
-        vi.ID, vi.MACAddress, vi.IPAddresses)
-    }
+		for _, vi := range virtualinterfacesList {
+			t.Logf("Virtual Interface: ID [%s] MAC Address [%s] IP Addresses [%v]",
+				vi.ID, vi.MACAddress, vi.IPAddresses)
+		}
 
-    return true, nil
-  })
-  th.CheckNoErr(t, err)
+		return true, nil
+	})
+	th.CheckNoErr(t, err)
 }
diff --git a/openstack/compute/v2/extensions/bootfromvolume/requests.go b/openstack/compute/v2/extensions/bootfromvolume/requests.go
new file mode 100644
index 0000000..5a976d1
--- /dev/null
+++ b/openstack/compute/v2/extensions/bootfromvolume/requests.go
@@ -0,0 +1,111 @@
+package bootfromvolume
+
+import (
+	"errors"
+	"strconv"
+
+	"github.com/rackspace/gophercloud"
+	"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
+
+	"github.com/racker/perigee"
+)
+
+// SourceType represents the type of medium being used to create the volume.
+type SourceType string
+
+const (
+	Volume   SourceType = "volume"
+	Snapshot SourceType = "snapshot"
+	Image    SourceType = "image"
+)
+
+// BlockDevice is a structure with options for booting a server instance
+// from a volume. The volume may be created from an image, snapshot, or another
+// volume.
+type BlockDevice struct {
+	// BootIndex [optional] is the boot index. It defaults to 0.
+	BootIndex int `json:"boot_index"`
+
+	// DeleteOnTermination [optional] specifies whether or not to delete the attached volume
+	// when the server is deleted. Defaults to `false`.
+	DeleteOnTermination bool `json:"delete_on_termination"`
+
+	// DestinationType [optional] is the type that gets created. Possible values are "volume"
+	// and "local".
+	DestinationType string `json:"destination_type"`
+
+	// SourceType [required] must be one of: "volume", "snapshot", "image".
+	SourceType SourceType `json:"source_type"`
+
+	// UUID [required] is the unique identifier for the volume, snapshot, or image (see above)
+	UUID string `json:"uuid"`
+
+	// VolumeSize [optional] is the size of the volume to create (in gigabytes).
+	VolumeSize int `json:"volume_size"`
+}
+
+// CreateOptsExt is a structure that extends the server `CreateOpts` structure
+// by allowing for a block device mapping.
+type CreateOptsExt struct {
+	servers.CreateOptsBuilder
+	BlockDevice []BlockDevice `json:"block_device_mapping_v2,omitempty"`
+}
+
+// ToServerCreateMap adds the block device mapping option to the base server
+// creation options.
+func (opts CreateOptsExt) ToServerCreateMap() (map[string]interface{}, error) {
+	base, err := opts.CreateOptsBuilder.ToServerCreateMap()
+	if err != nil {
+		return nil, err
+	}
+
+	if len(opts.BlockDevice) == 0 {
+		return nil, errors.New("Required fields UUID and SourceType not set.")
+	}
+
+	serverMap := base["server"].(map[string]interface{})
+
+	blockDevice := make([]map[string]interface{}, len(opts.BlockDevice))
+
+	for i, bd := range opts.BlockDevice {
+		if string(bd.SourceType) == "" {
+			return nil, errors.New("SourceType must be one of: volume, image, snapshot.")
+		}
+
+		blockDevice[i] = make(map[string]interface{})
+
+		blockDevice[i]["source_type"] = bd.SourceType
+		blockDevice[i]["boot_index"] = strconv.Itoa(bd.BootIndex)
+		blockDevice[i]["delete_on_termination"] = strconv.FormatBool(bd.DeleteOnTermination)
+		blockDevice[i]["volume_size"] = strconv.Itoa(bd.VolumeSize)
+		if bd.UUID != "" {
+			blockDevice[i]["uuid"] = bd.UUID
+		}
+		if bd.DestinationType != "" {
+			blockDevice[i]["destination_type"] = bd.DestinationType
+		}
+
+	}
+	serverMap["block_device_mapping_v2"] = blockDevice
+
+	return base, nil
+}
+
+// Create requests the creation of a server from the given block device mapping.
+func Create(client *gophercloud.ServiceClient, opts servers.CreateOptsBuilder) servers.CreateResult {
+	var res servers.CreateResult
+
+	reqBody, err := opts.ToServerCreateMap()
+	if err != nil {
+		res.Err = err
+		return res
+	}
+
+	_, res.Err = perigee.Request("POST", createURL(client), perigee.Options{
+		MoreHeaders: client.AuthenticatedHeaders(),
+		ReqBody:     reqBody,
+		Results:     &res.Body,
+		OkCodes:     []int{200, 202},
+	})
+	return res
+}
diff --git a/openstack/compute/v2/extensions/bootfromvolume/requests_test.go b/openstack/compute/v2/extensions/bootfromvolume/requests_test.go
new file mode 100644
index 0000000..5bf9137
--- /dev/null
+++ b/openstack/compute/v2/extensions/bootfromvolume/requests_test.go
@@ -0,0 +1,51 @@
+package bootfromvolume
+
+import (
+	"testing"
+
+	"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
+	th "github.com/rackspace/gophercloud/testhelper"
+)
+
+func TestCreateOpts(t *testing.T) {
+	base := servers.CreateOpts{
+		Name:      "createdserver",
+		ImageRef:  "asdfasdfasdf",
+		FlavorRef: "performance1-1",
+	}
+
+	ext := CreateOptsExt{
+		CreateOptsBuilder: base,
+		BlockDevice: []BlockDevice{
+			BlockDevice{
+				UUID:            "123456",
+				SourceType:      Image,
+				DestinationType: "volume",
+				VolumeSize:      10,
+			},
+		},
+	}
+
+	expected := `
+    {
+      "server": {
+        "name": "createdserver",
+        "imageRef": "asdfasdfasdf",
+        "flavorRef": "performance1-1",
+        "block_device_mapping_v2":[
+          {
+            "uuid":"123456",
+            "source_type":"image",
+            "destination_type":"volume",
+            "boot_index": "0",
+            "delete_on_termination": "false",
+            "volume_size": "10"
+          }
+        ]
+      }
+    }
+  `
+	actual, err := ext.ToServerCreateMap()
+	th.AssertNoErr(t, err)
+	th.CheckJSONEquals(t, expected, actual)
+}
diff --git a/openstack/compute/v2/extensions/bootfromvolume/results.go b/openstack/compute/v2/extensions/bootfromvolume/results.go
new file mode 100644
index 0000000..f60329f
--- /dev/null
+++ b/openstack/compute/v2/extensions/bootfromvolume/results.go
@@ -0,0 +1,10 @@
+package bootfromvolume
+
+import (
+	os "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
+)
+
+// CreateResult temporarily contains the response from a Create call.
+type CreateResult struct {
+	os.CreateResult
+}
diff --git a/openstack/compute/v2/extensions/bootfromvolume/urls.go b/openstack/compute/v2/extensions/bootfromvolume/urls.go
new file mode 100644
index 0000000..0cffe25
--- /dev/null
+++ b/openstack/compute/v2/extensions/bootfromvolume/urls.go
@@ -0,0 +1,7 @@
+package bootfromvolume
+
+import "github.com/rackspace/gophercloud"
+
+func createURL(c *gophercloud.ServiceClient) string {
+	return c.ServiceURL("os-volumes_boot")
+}
diff --git a/openstack/compute/v2/extensions/bootfromvolume/urls_test.go b/openstack/compute/v2/extensions/bootfromvolume/urls_test.go
new file mode 100644
index 0000000..6ee6477
--- /dev/null
+++ b/openstack/compute/v2/extensions/bootfromvolume/urls_test.go
@@ -0,0 +1,16 @@
+package bootfromvolume
+
+import (
+	"testing"
+
+	th "github.com/rackspace/gophercloud/testhelper"
+	"github.com/rackspace/gophercloud/testhelper/client"
+)
+
+func TestCreateURL(t *testing.T) {
+	th.SetupHTTP()
+	defer th.TeardownHTTP()
+	c := client.ServiceClient()
+
+	th.CheckEquals(t, c.Endpoint+"os-volumes_boot", createURL(c))
+}
diff --git a/openstack/compute/v2/extensions/diskconfig/requests.go b/openstack/compute/v2/extensions/diskconfig/requests.go
index 06a922a..7407e0d 100644
--- a/openstack/compute/v2/extensions/diskconfig/requests.go
+++ b/openstack/compute/v2/extensions/diskconfig/requests.go
@@ -41,17 +41,24 @@
 	servers.CreateOptsBuilder
 
 	// DiskConfig [optional] controls how the created server's disk is partitioned.
-	DiskConfig DiskConfig
+	DiskConfig DiskConfig `json:"OS-DCF:diskConfig,omitempty"`
 }
 
 // ToServerCreateMap adds the diskconfig option to the base server creation options.
-func (opts CreateOptsExt) ToServerCreateMap() map[string]interface{} {
-	base := opts.CreateOptsBuilder.ToServerCreateMap()
+func (opts CreateOptsExt) ToServerCreateMap() (map[string]interface{}, error) {
+	base, err := opts.CreateOptsBuilder.ToServerCreateMap()
+	if err != nil {
+		return nil, err
+	}
+
+	if string(opts.DiskConfig) == "" {
+		return base, nil
+	}
 
 	serverMap := base["server"].(map[string]interface{})
 	serverMap["OS-DCF:diskConfig"] = string(opts.DiskConfig)
 
-	return base
+	return base, nil
 }
 
 // RebuildOptsExt adds a DiskConfig option to the base RebuildOpts.
diff --git a/openstack/compute/v2/extensions/diskconfig/requests_test.go b/openstack/compute/v2/extensions/diskconfig/requests_test.go
index 1f4f626..e3c26d4 100644
--- a/openstack/compute/v2/extensions/diskconfig/requests_test.go
+++ b/openstack/compute/v2/extensions/diskconfig/requests_test.go
@@ -29,7 +29,9 @@
 			}
 		}
 	`
-	th.CheckJSONEquals(t, expected, ext.ToServerCreateMap())
+	actual, err := ext.ToServerCreateMap()
+	th.AssertNoErr(t, err)
+	th.CheckJSONEquals(t, expected, actual)
 }
 
 func TestRebuildOpts(t *testing.T) {
diff --git a/openstack/compute/v2/flavors/requests.go b/openstack/compute/v2/flavors/requests.go
index 95eb7f9..065a2ec 100644
--- a/openstack/compute/v2/flavors/requests.go
+++ b/openstack/compute/v2/flavors/requests.go
@@ -41,10 +41,10 @@
 	return q.String(), nil
 }
 
-// List instructs OpenStack to provide a list of flavors.
+// ListDetail instructs OpenStack to provide a list of flavors.
 // You may provide criteria by which List curtails its results for easier processing.
 // See ListOpts for more details.
-func List(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
+func ListDetail(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
 	url := listURL(client)
 	if opts != nil {
 		query, err := opts.ToFlavorListQuery()
diff --git a/openstack/compute/v2/flavors/requests_test.go b/openstack/compute/v2/flavors/requests_test.go
index bc9b82e..fbd7c33 100644
--- a/openstack/compute/v2/flavors/requests_test.go
+++ b/openstack/compute/v2/flavors/requests_test.go
@@ -60,7 +60,7 @@
 	})
 
 	pages := 0
-	err := List(fake.ServiceClient(), &ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
+	err := ListDetail(fake.ServiceClient(), nil).EachPage(func(page pagination.Page) (bool, error) {
 		pages++
 
 		actual, err := ExtractFlavors(page)
diff --git a/openstack/compute/v2/servers/requests.go b/openstack/compute/v2/servers/requests.go
index c6eca11..544f816 100644
--- a/openstack/compute/v2/servers/requests.go
+++ b/openstack/compute/v2/servers/requests.go
@@ -79,7 +79,7 @@
 // CreateOptsBuilder describes struct types that can be accepted by the Create call.
 // The CreateOpts struct in this package does.
 type CreateOptsBuilder interface {
-	ToServerCreateMap() map[string]interface{}
+	ToServerCreateMap() (map[string]interface{}, error)
 }
 
 // Network is used within CreateOpts to control a new server's network attachments.
@@ -134,7 +134,7 @@
 }
 
 // ToServerCreateMap assembles a request body based on the contents of a CreateOpts.
-func (opts CreateOpts) ToServerCreateMap() map[string]interface{} {
+func (opts CreateOpts) ToServerCreateMap() (map[string]interface{}, error) {
 	server := make(map[string]interface{})
 
 	server["name"] = opts.Name
@@ -183,19 +183,26 @@
 		server["networks"] = networks
 	}
 
-	return map[string]interface{}{"server": server}
+	return map[string]interface{}{"server": server}, nil
 }
 
 // Create requests a server to be provisioned to the user in the current tenant.
 func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
-	var result CreateResult
-	_, result.Err = perigee.Request("POST", listURL(client), perigee.Options{
-		Results:     &result.Body,
-		ReqBody:     opts.ToServerCreateMap(),
+	var res CreateResult
+
+	reqBody, err := opts.ToServerCreateMap()
+	if err != nil {
+		res.Err = err
+		return res
+	}
+
+	_, res.Err = perigee.Request("POST", listURL(client), perigee.Options{
+		Results:     &res.Body,
+		ReqBody:     reqBody,
 		MoreHeaders: client.AuthenticatedHeaders(),
 		OkCodes:     []int{202},
 	})
-	return result
+	return res
 }
 
 // Delete requests that a server previously provisioned be removed from your account.
diff --git a/openstack/objectstorage/v1/objects/requests.go b/openstack/objectstorage/v1/objects/requests.go
index 1b6cb5c..0ad0315 100644
--- a/openstack/objectstorage/v1/objects/requests.go
+++ b/openstack/objectstorage/v1/objects/requests.go
@@ -49,7 +49,6 @@
 	if opts != nil {
 		full, query, err := opts.ToObjectListParams()
 		if err != nil {
-			fmt.Printf("Error building query string: %v", err)
 			return pagination.Pager{Err: err}
 		}
 		url += query
diff --git a/pagination/linked.go b/pagination/linked.go
index 447d4b1..461fa49 100644
--- a/pagination/linked.go
+++ b/pagination/linked.go
@@ -39,8 +39,6 @@
 			return "", nil
 		}
 
-		fmt.Printf("key = %#v, path = %#v, value = %#v\n", key, path, value)
-
 		if len(path) > 0 {
 			submap, ok = value.(map[string]interface{})
 			if !ok {
diff --git a/rackspace/compute/v2/bootfromvolume/delegate.go b/rackspace/compute/v2/bootfromvolume/delegate.go
new file mode 100644
index 0000000..2580459
--- /dev/null
+++ b/rackspace/compute/v2/bootfromvolume/delegate.go
@@ -0,0 +1,12 @@
+package bootfromvolume
+
+import (
+	"github.com/rackspace/gophercloud"
+	osBFV "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume"
+	osServers "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
+)
+
+// Create requests the creation of a server from the given block device mapping.
+func Create(client *gophercloud.ServiceClient, opts osServers.CreateOptsBuilder) osServers.CreateResult {
+	return osBFV.Create(client, opts)
+}
diff --git a/rackspace/compute/v2/bootfromvolume/delegate_test.go b/rackspace/compute/v2/bootfromvolume/delegate_test.go
new file mode 100644
index 0000000..0b53527
--- /dev/null
+++ b/rackspace/compute/v2/bootfromvolume/delegate_test.go
@@ -0,0 +1,52 @@
+package bootfromvolume
+
+import (
+	"testing"
+
+	osBFV "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume"
+	"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
+	th "github.com/rackspace/gophercloud/testhelper"
+)
+
+func TestCreateOpts(t *testing.T) {
+	base := servers.CreateOpts{
+		Name:      "createdserver",
+		ImageRef:  "asdfasdfasdf",
+		FlavorRef: "performance1-1",
+	}
+
+	ext := osBFV.CreateOptsExt{
+		CreateOptsBuilder: base,
+		BlockDevice: []osBFV.BlockDevice{
+			osBFV.BlockDevice{
+				UUID:            "123456",
+				SourceType:      osBFV.Image,
+				DestinationType: "volume",
+				VolumeSize:      10,
+			},
+		},
+	}
+
+	expected := `
+    {
+      "server": {
+        "name": "createdserver",
+        "imageRef": "asdfasdfasdf",
+        "flavorRef": "performance1-1",
+        "block_device_mapping_v2":[
+          {
+            "uuid":"123456",
+            "source_type":"image",
+            "destination_type":"volume",
+            "boot_index": "0",
+            "delete_on_termination": "false",
+            "volume_size": "10"
+          }
+        ]
+      }
+    }
+  `
+	actual, err := ext.ToServerCreateMap()
+	th.AssertNoErr(t, err)
+	th.CheckJSONEquals(t, expected, actual)
+}
diff --git a/rackspace/compute/v2/flavors/delegate.go b/rackspace/compute/v2/flavors/delegate.go
index 2cf31b5..6bfc20c 100644
--- a/rackspace/compute/v2/flavors/delegate.go
+++ b/rackspace/compute/v2/flavors/delegate.go
@@ -30,9 +30,9 @@
 	return q.String(), nil
 }
 
-// List enumerates the server images available to your account.
-func List(client *gophercloud.ServiceClient, opts os.ListOptsBuilder) pagination.Pager {
-	return os.List(client, opts)
+// ListDetail enumerates the server images available to your account.
+func ListDetail(client *gophercloud.ServiceClient, opts os.ListOptsBuilder) pagination.Pager {
+	return os.ListDetail(client, opts)
 }
 
 // Get returns details about a single flavor, identity by ID.
diff --git a/rackspace/compute/v2/flavors/delegate_test.go b/rackspace/compute/v2/flavors/delegate_test.go
index b2a2ea2..204081d 100644
--- a/rackspace/compute/v2/flavors/delegate_test.go
+++ b/rackspace/compute/v2/flavors/delegate_test.go
@@ -32,7 +32,7 @@
 	})
 
 	count := 0
-	err := List(client.ServiceClient(), nil).EachPage(func(page pagination.Page) (bool, error) {
+	err := ListDetail(client.ServiceClient(), nil).EachPage(func(page pagination.Page) (bool, error) {
 		actual, err := ExtractFlavors(page)
 		th.AssertNoErr(t, err)
 		th.CheckDeepEquals(t, ExpectedFlavorSlice, actual)
diff --git a/rackspace/compute/v2/servers/requests.go b/rackspace/compute/v2/servers/requests.go
index b83a893..884b9cb 100644
--- a/rackspace/compute/v2/servers/requests.go
+++ b/rackspace/compute/v2/servers/requests.go
@@ -1,6 +1,7 @@
 package servers
 
 import (
+	"github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume"
 	"github.com/rackspace/gophercloud/openstack/compute/v2/extensions/diskconfig"
 	os "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
 )
@@ -51,11 +52,15 @@
 	// DiskConfig [optional] controls how the created server's disk is partitioned. See the "diskconfig"
 	// extension in OpenStack compute v2.
 	DiskConfig diskconfig.DiskConfig
+
+	// BlockDevice [optional] will create the server from a volume, which is created from an image,
+	// a snapshot, or an another volume.
+	BlockDevice []bootfromvolume.BlockDevice
 }
 
 // ToServerCreateMap constructs a request body using all of the OpenStack extensions that are
 // active on Rackspace.
-func (opts CreateOpts) ToServerCreateMap() map[string]interface{} {
+func (opts CreateOpts) ToServerCreateMap() (map[string]interface{}, error) {
 	base := os.CreateOpts{
 		Name:             opts.Name,
 		ImageRef:         opts.ImageRef,
@@ -74,14 +79,29 @@
 		DiskConfig:        opts.DiskConfig,
 	}
 
-	result := drive.ToServerCreateMap()
+	res, err := drive.ToServerCreateMap()
+	if err != nil {
+		return nil, err
+	}
+
+	if len(opts.BlockDevice) != 0 {
+		bfv := bootfromvolume.CreateOptsExt{
+			CreateOptsBuilder: drive,
+			BlockDevice:       opts.BlockDevice,
+		}
+
+		res, err = bfv.ToServerCreateMap()
+		if err != nil {
+			return nil, err
+		}
+	}
 
 	// key_name doesn't actually come from the extension (or at least isn't documented there) so
 	// we need to add it manually.
-	serverMap := result["server"].(map[string]interface{})
+	serverMap := res["server"].(map[string]interface{})
 	serverMap["key_name"] = opts.KeyPair
 
-	return result
+	return res, nil
 }
 
 // RebuildOpts represents all of the configuration options used in a server rebuild operation that
diff --git a/rackspace/compute/v2/servers/requests_test.go b/rackspace/compute/v2/servers/requests_test.go
index ac7058f..3c0f806 100644
--- a/rackspace/compute/v2/servers/requests_test.go
+++ b/rackspace/compute/v2/servers/requests_test.go
@@ -27,7 +27,9 @@
 		}
 	}
 	`
-	th.CheckJSONEquals(t, expected, opts.ToServerCreateMap())
+	actual, err := opts.ToServerCreateMap()
+	th.AssertNoErr(t, err)
+	th.CheckJSONEquals(t, expected, actual)
 }
 
 func TestRebuildOpts(t *testing.T) {
diff --git a/script/acceptancetest b/script/acceptancetest
index 49039fd..f9c89f4 100755
--- a/script/acceptancetest
+++ b/script/acceptancetest
@@ -2,4 +2,4 @@
 #
 # Run the acceptance tests.
 
-exec go test -v -p=1 -tags 'acceptance fixtures' ./acceptance/... $@
+exec go test -p=1 -tags 'acceptance fixtures' github.com/rackspace/gophercloud/acceptance/... $@
diff --git a/testhelper/convenience.go b/testhelper/convenience.go
index adb77e5..cf33e1a 100644
--- a/testhelper/convenience.go
+++ b/testhelper/convenience.go
@@ -259,14 +259,19 @@
 // isJSONEquals is a utility function that implements JSON comparison for AssertJSONEquals and
 // CheckJSONEquals.
 func isJSONEquals(t *testing.T, expectedJSON string, actual interface{}) bool {
-	var parsedExpected interface{}
+	var parsedExpected, parsedActual interface{}
 	err := json.Unmarshal([]byte(expectedJSON), &parsedExpected)
 	if err != nil {
 		t.Errorf("Unable to parse expected value as JSON: %v", err)
 		return false
 	}
 
-	if !reflect.DeepEqual(parsedExpected, actual) {
+	jsonActual, err := json.Marshal(actual)
+	AssertNoErr(t, err)
+	err = json.Unmarshal(jsonActual, &parsedActual)
+	AssertNoErr(t, err)
+
+	if !reflect.DeepEqual(parsedExpected, parsedActual) {
 		prettyExpected, err := json.MarshalIndent(parsedExpected, "", "  ")
 		if err != nil {
 			t.Logf("Unable to pretty-print expected JSON: %v\n%s", err, expectedJSON)