create map from 'CreateOptsBuilder'; rackspace boot from volume; untested acceptance test
diff --git a/openstack/compute/v2/extensions/bootfromvolume/requests.go b/openstack/compute/v2/extensions/bootfromvolume/requests.go
index bbef496..d5b361b 100644
--- a/openstack/compute/v2/extensions/bootfromvolume/requests.go
+++ b/openstack/compute/v2/extensions/bootfromvolume/requests.go
@@ -2,24 +2,54 @@
 
 import (
 	"errors"
+	"strconv"
 
+	"github.com/rackspace/gophercloud"
 	"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
+
+	"github.com/racker/perigee"
 )
 
+// 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
+
+	// DeleteOnTermination [optional] specifies whether or not to delete the attached volume
+	// when the server is deleted. Defaults to `false`.
+	DeleteOnTermination bool
+
+	// DestinationType [optional] is the type that gets created. Possible values are "volume"
+	// and "local".
+	DestinationType string
+
+	// SourceType [optional] must be one of: "volume", "snapshot", "image".
+	SourceType string
+
+	// UUID [optional] is the unique identifier for the volume, snapshot, or image (see above)
+	UUID string
+
+	// VolumeSize [optional] is the size of the volume to create (in gigabytes).
+	VolumeSize int
+}
+
+// CreateOptsExt is a structure that extends the server `CreateOpts` structure
+// by allowing for a block device mapping.
 type CreateOptsExt struct {
 	servers.CreateOptsBuilder
-	BDM BlockDeviceMapping
+	BlockDevice BlockDevice
 }
 
 // ToServerCreateMap adds the block device mapping option to the base server
 // creation options.
 func (opts CreateOptsExt) ToServerCreateMap() (map[string]interface{}, error) {
-	if opts.BDM.SourceType != "volume" && opts.BDM.SourceType != "image" && opts.BDM.SourceType != "snapshot" {
-		return nil, errors.New("SourceType must be one of: volume, image, snapshot.")
-	}
-
-	if opts.BDM.UUID == "" {
-		return nil, errors.New("Required field UUID not set.")
+	if opts.BlockDevice.SourceType != "volume" &&
+		opts.BlockDevice.SourceType != "image" &&
+		opts.BlockDevice.SourceType != "snapshot" &&
+		opts.BlockDevice.SourceType != "" {
+		return nil, errors.New("SourceType must be one of: volume, image, snapshot, [blank].")
 	}
 
 	base, err := opts.CreateOptsBuilder.ToServerCreateMap()
@@ -28,7 +58,39 @@
 	}
 
 	serverMap := base["server"].(map[string]interface{})
-	serverMap["block_device_mapping_v2"] = opts.BDM
+
+	bd := make(map[string]interface{})
+	bd["source_type"] = opts.BlockDevice.SourceType
+	bd["boot_index"] = strconv.Itoa(opts.BlockDevice.BootIndex)
+	bd["delete_on_termination"] = strconv.FormatBool(opts.BlockDevice.DeleteOnTermination)
+	bd["volume_size"] = strconv.Itoa(opts.BlockDevice.VolumeSize)
+	if opts.BlockDevice.UUID != "" {
+		bd["uuid"] = opts.BlockDevice.UUID
+	}
+	if opts.BlockDevice.DestinationType != "" {
+		bd["destination_type"] = opts.BlockDevice.DestinationType
+	}
+
+	serverMap["block_device_mapping_v2"] = []map[string]interface{}{bd}
 
 	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},
+	})
+	return res
+}
diff --git a/openstack/compute/v2/extensions/bootfromvolume/requests_test.go b/openstack/compute/v2/extensions/bootfromvolume/requests_test.go
index a564982..bad6c03 100644
--- a/openstack/compute/v2/extensions/bootfromvolume/requests_test.go
+++ b/openstack/compute/v2/extensions/bootfromvolume/requests_test.go
@@ -1 +1,49 @@
 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{
+			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
deleted file mode 100644
index 9d33728..0000000
--- a/openstack/compute/v2/extensions/bootfromvolume/results.go
+++ /dev/null
@@ -1,10 +0,0 @@
-package bootfromvolume
-
-type BlockDeviceMapping struct {
-	BootIndex           int    `json:"boot_index"`
-	DeleteOnTermination bool   `json:"delete_on_termination"`
-	DestinationType     string `json:"destination_type"`
-	SourceType          string `json:"source_type"`
-	UUID                string `json:"uuid"`
-	VolumeSize          int    `json:"volume_size"`
-}
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))
+}