Vendor: add Gophercloud Compute bootfromvolume

Add the Compute service extenstion client library to allow server to be
created with a remote blockstorage root volume.
This commit is contained in:
Andrei Ozerov 2018-05-24 10:00:20 +03:00 committed by Rickard von Essen
parent d38bd6b5f8
commit cfa922a180
5 changed files with 297 additions and 0 deletions

View File

@ -0,0 +1,152 @@
/*
Package bootfromvolume extends a server create request with the ability to
specify block device options. This can be used to boot a server from a block
storage volume as well as specify multiple ephemeral disks upon creation.
It is recommended to refer to the Block Device Mapping documentation to see
all possible ways to configure a server's block devices at creation time:
https://docs.openstack.org/nova/latest/user/block-device-mapping.html
Note that this package implements `block_device_mapping_v2`.
Example of Creating a Server From an Image
This example will boot a server from an image and use a standard ephemeral
disk as the server's root disk. This is virtually no different than creating
a server without using block device mappings.
blockDevices := []bootfromvolume.BlockDevice{
bootfromvolume.BlockDevice{
BootIndex: 0,
DeleteOnTermination: true,
DestinationType: bootfromvolume.DestinationLocal,
SourceType: bootfromvolume.SourceImage,
UUID: "image-uuid",
},
}
serverCreateOpts := servers.CreateOpts{
Name: "server_name",
FlavorRef: "flavor-uuid",
ImageRef: "image-uuid",
}
createOpts := bootfromvolume.CreateOptsExt{
CreateOptsBuilder: serverCreateOpts,
BlockDevice: blockDevices,
}
server, err := bootfromvolume.Create(client, createOpts).Extract()
if err != nil {
panic(err)
}
Example of Creating a Server From a New Volume
This example will create a block storage volume based on the given Image. The
server will use this volume as its root disk.
blockDevices := []bootfromvolume.BlockDevice{
bootfromvolume.BlockDevice{
DeleteOnTermination: true,
DestinationType: bootfromvolume.DestinationVolume,
SourceType: bootfromvolume.SourceImage,
UUID: "image-uuid",
VolumeSize: 2,
},
}
serverCreateOpts := servers.CreateOpts{
Name: "server_name",
FlavorRef: "flavor-uuid",
}
createOpts := bootfromvolume.CreateOptsExt{
CreateOptsBuilder: serverCreateOpts,
BlockDevice: blockDevices,
}
server, err := bootfromvolume.Create(client, createOpts).Extract()
if err != nil {
panic(err)
}
Example of Creating a Server From an Existing Volume
This example will create a server with an existing volume as its root disk.
blockDevices := []bootfromvolume.BlockDevice{
bootfromvolume.BlockDevice{
DeleteOnTermination: true,
DestinationType: bootfromvolume.DestinationVolume,
SourceType: bootfromvolume.SourceVolume,
UUID: "volume-uuid",
},
}
serverCreateOpts := servers.CreateOpts{
Name: "server_name",
FlavorRef: "flavor-uuid",
}
createOpts := bootfromvolume.CreateOptsExt{
CreateOptsBuilder: serverCreateOpts,
BlockDevice: blockDevices,
}
server, err := bootfromvolume.Create(client, createOpts).Extract()
if err != nil {
panic(err)
}
Example of Creating a Server with Multiple Ephemeral Disks
This example will create a server with multiple ephemeral disks. The first
block device will be based off of an existing Image. Each additional
ephemeral disks must have an index of -1.
blockDevices := []bootfromvolume.BlockDevice{
bootfromvolume.BlockDevice{
BootIndex: 0,
DestinationType: bootfromvolume.DestinationLocal,
DeleteOnTermination: true,
SourceType: bootfromvolume.SourceImage,
UUID: "image-uuid",
VolumeSize: 5,
},
bootfromvolume.BlockDevice{
BootIndex: -1,
DestinationType: bootfromvolume.DestinationLocal,
DeleteOnTermination: true,
GuestFormat: "ext4",
SourceType: bootfromvolume.SourceBlank,
VolumeSize: 1,
},
bootfromvolume.BlockDevice{
BootIndex: -1,
DestinationType: bootfromvolume.DestinationLocal,
DeleteOnTermination: true,
GuestFormat: "ext4",
SourceType: bootfromvolume.SourceBlank,
VolumeSize: 1,
},
}
serverCreateOpts := servers.CreateOpts{
Name: "server_name",
FlavorRef: "flavor-uuid",
ImageRef: "image-uuid",
}
createOpts := bootfromvolume.CreateOptsExt{
CreateOptsBuilder: serverCreateOpts,
BlockDevice: blockDevices,
}
server, err := bootfromvolume.Create(client, createOpts).Extract()
if err != nil {
panic(err)
}
*/
package bootfromvolume

View File

@ -0,0 +1,120 @@
package bootfromvolume
import (
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
)
type (
// DestinationType represents the type of medium being used as the
// destination of the bootable device.
DestinationType string
// SourceType represents the type of medium being used as the source of the
// bootable device.
SourceType string
)
const (
// DestinationLocal DestinationType is for using an ephemeral disk as the
// destination.
DestinationLocal DestinationType = "local"
// DestinationVolume DestinationType is for using a volume as the destination.
DestinationVolume DestinationType = "volume"
// SourceBlank SourceType is for a "blank" or empty source.
SourceBlank SourceType = "blank"
// SourceImage SourceType is for using images as the source of a block device.
SourceImage SourceType = "image"
// SourceSnapshot SourceType is for using a volume snapshot as the source of
// a block device.
SourceSnapshot SourceType = "snapshot"
// SourceVolume SourceType is for using a volume as the source of block
// device.
SourceVolume SourceType = "volume"
)
// BlockDevice is a structure with options for creating block devices in a
// server. The block device may be created from an image, snapshot, new volume,
// or existing volume. The destination may be a new volume, existing volume
// which will be attached to the instance, ephemeral disk, or boot device.
type BlockDevice struct {
// SourceType must be one of: "volume", "snapshot", "image", or "blank".
SourceType SourceType `json:"source_type" required:"true"`
// UUID is the unique identifier for the existing volume, snapshot, or
// image (see above).
UUID string `json:"uuid,omitempty"`
// BootIndex is the boot index. It defaults to 0.
BootIndex int `json:"boot_index"`
// DeleteOnTermination specifies whether or not to delete the attached volume
// when the server is deleted. Defaults to `false`.
DeleteOnTermination bool `json:"delete_on_termination"`
// DestinationType is the type that gets created. Possible values are "volume"
// and "local".
DestinationType DestinationType `json:"destination_type,omitempty"`
// GuestFormat specifies the format of the block device.
GuestFormat string `json:"guest_format,omitempty"`
// VolumeSize is the size of the volume to create (in gigabytes). This can be
// omitted for existing volumes.
VolumeSize int `json:"volume_size,omitempty"`
}
// 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 {
err := gophercloud.ErrMissingInput{}
err.Argument = "bootfromvolume.CreateOptsExt.BlockDevice"
return nil, err
}
serverMap := base["server"].(map[string]interface{})
blockDevice := make([]map[string]interface{}, len(opts.BlockDevice))
for i, bd := range opts.BlockDevice {
b, err := gophercloud.BuildRequestBody(bd, "")
if err != nil {
return nil, err
}
blockDevice[i] = b
}
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) (r servers.CreateResult) {
b, err := opts.ToServerCreateMap()
if err != nil {
r.Err = err
return
}
_, r.Err = client.Post(createURL(client), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200, 202},
})
return
}

View File

@ -0,0 +1,12 @@
package bootfromvolume
import (
os "github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
)
// CreateResult temporarily contains the response from a Create call.
// It embeds the standard servers.CreateResults type and so can be used the
// same way as a standard server request result.
type CreateResult struct {
os.CreateResult
}

View File

@ -0,0 +1,7 @@
package bootfromvolume
import "github.com/gophercloud/gophercloud"
func createURL(c *gophercloud.ServiceClient) string {
return c.ServiceURL("os-volumes_boot")
}

6
vendor/vendor.json vendored
View File

@ -755,6 +755,12 @@
"revision": "95a28eb606def6aaaed082b6b82d3244b0552184",
"revisionTime": "2017-06-23T01:44:30Z"
},
{
"checksumSHA1": "kCHEEeRVZeR1LhbvNP+WyvB8z2s=",
"path": "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/bootfromvolume",
"revision": "282f25e4025de0a42015d2e2b5faef1d920aad3c",
"revisionTime": "2018-05-15T01:47:05Z"
},
{
"checksumSHA1": "e7AW3YDVYJPKUjpqsB4AL9RRlTw=",
"path": "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/floatingips",