don't put extension params in 'CreateOpts' if unset; working rackspace acceptance test
diff --git a/acceptance/rackspace/compute/v2/bootfromvolume_test.go b/acceptance/rackspace/compute/v2/bootfromvolume_test.go
index 7e500e8..591a137 100644
--- a/acceptance/rackspace/compute/v2/bootfromvolume_test.go
+++ b/acceptance/rackspace/compute/v2/bootfromvolume_test.go
@@ -5,7 +5,9 @@
import (
"testing"
- "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume"
+ 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"
)
@@ -24,15 +26,19 @@
name := tools.RandomString("Gophercloud-", 8)
t.Logf("Creating server [%s].", name)
- bd := bootfromvolume.BlockDevice{
+ bd := osBFV.BlockDevice{
UUID: options.imageID,
SourceType: "image",
+ VolumeSize: 10,
}
- server, err := bootfromvolume.Create(client, bootfromvolume.CreateOptsExt{
+ server, err := bootfromvolume.Create(client, servers.CreateOpts{
Name: name,
+ FlavorRef: "performance1-1",
BlockDevice: bd,
}).Extract()
th.AssertNoErr(t, err)
- //defer deleteServer(t, client, server)
+ t.Logf("Created server: %+v\n", server)
+ defer deleteServer(t, client, server)
+ t.Logf("Deleting server [%s]...", name)
}
diff --git a/openstack/compute/v2/extensions/bootfromvolume/requests.go b/openstack/compute/v2/extensions/bootfromvolume/requests.go
index d5b361b..e8ce739 100644
--- a/openstack/compute/v2/extensions/bootfromvolume/requests.go
+++ b/openstack/compute/v2/extensions/bootfromvolume/requests.go
@@ -15,36 +15,46 @@
// volume.
type BlockDevice struct {
// BootIndex [optional] is the boot index. It defaults to 0.
- BootIndex int
+ 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
+ DeleteOnTermination bool `json:"delete_on_termination"`
// DestinationType [optional] is the type that gets created. Possible values are "volume"
// and "local".
- DestinationType string
+ DestinationType string `json:"destination_type"`
// SourceType [optional] must be one of: "volume", "snapshot", "image".
- SourceType string
+ SourceType string `json:"source_type"`
// UUID [optional] is the unique identifier for the volume, snapshot, or image (see above)
- UUID string
+ UUID string `json:"uuid"`
// VolumeSize [optional] is the size of the volume to create (in gigabytes).
- VolumeSize int
+ 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
+ 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
+ }
+
+ var blockDevice BlockDevice
+ if opts.BlockDevice == blockDevice {
+ return base, nil
+ }
+
if opts.BlockDevice.SourceType != "volume" &&
opts.BlockDevice.SourceType != "image" &&
opts.BlockDevice.SourceType != "snapshot" &&
@@ -52,11 +62,6 @@
return nil, errors.New("SourceType must be one of: volume, image, snapshot, [blank].")
}
- base, err := opts.CreateOptsBuilder.ToServerCreateMap()
- if err != nil {
- return nil, err
- }
-
serverMap := base["server"].(map[string]interface{})
bd := make(map[string]interface{})
@@ -77,8 +82,8 @@
}
// 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
+func Create(client *gophercloud.ServiceClient, opts servers.CreateOptsBuilder) CreateResult {
+ var res CreateResult
reqBody, err := opts.ToServerCreateMap()
if err != nil {
@@ -90,7 +95,8 @@
MoreHeaders: client.AuthenticatedHeaders(),
ReqBody: reqBody,
Results: &res.Body,
- OkCodes: []int{200},
+ OkCodes: []int{200, 202},
+ DumpReqJson: true,
})
return res
}
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/diskconfig/requests.go b/openstack/compute/v2/extensions/diskconfig/requests.go
index cc390f7..7407e0d 100644
--- a/openstack/compute/v2/extensions/diskconfig/requests.go
+++ b/openstack/compute/v2/extensions/diskconfig/requests.go
@@ -41,7 +41,7 @@
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.
@@ -51,6 +51,10 @@
return nil, err
}
+ if string(opts.DiskConfig) == "" {
+ return base, nil
+ }
+
serverMap := base["server"].(map[string]interface{})
serverMap["OS-DCF:diskConfig"] = string(opts.DiskConfig)
diff --git a/rackspace/compute/v2/bootfromvolume/delegate.go b/rackspace/compute/v2/bootfromvolume/delegate.go
new file mode 100644
index 0000000..636ced6
--- /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) osBFV.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..a564982
--- /dev/null
+++ b/rackspace/compute/v2/bootfromvolume/delegate_test.go
@@ -0,0 +1 @@
+package bootfromvolume
diff --git a/rackspace/compute/v2/servers/requests.go b/rackspace/compute/v2/servers/requests.go
index 357b174..4f40e83 100644
--- a/rackspace/compute/v2/servers/requests.go
+++ b/rackspace/compute/v2/servers/requests.go
@@ -89,7 +89,10 @@
serverMap := res["server"].(map[string]interface{})
serverMap["key_name"] = opts.KeyPair
- serverMap["block_device_mapping_v2"] = opts.BlockDevice
+ var bd bootfromvolume.BlockDevice
+ if opts.BlockDevice != bd {
+ serverMap["block_device_mapping_v2"] = []bootfromvolume.BlockDevice{opts.BlockDevice}
+ }
return res, nil
}