blob: c0ba368db75916ffa126f68349f1d3835c64851c [file] [log] [blame]
Jon Perritt654fb0e2014-10-23 20:54:14 -05001package bootfromvolume
2
3import (
Jon Perritt4149d7c2014-10-23 21:23:46 -05004 "errors"
Jon Perrittd9a4bf72014-10-23 23:44:04 -05005 "strconv"
Jon Perritt654fb0e2014-10-23 20:54:14 -05006
Jon Perrittd9a4bf72014-10-23 23:44:04 -05007 "github.com/rackspace/gophercloud"
Jon Perritt4149d7c2014-10-23 21:23:46 -05008 "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
Jon Perritt654fb0e2014-10-23 20:54:14 -05009)
10
Jon Perritt01686cd2014-10-24 14:10:16 -050011// SourceType represents the type of medium being used to create the volume.
12type SourceType string
13
14const (
15 Volume SourceType = "volume"
16 Snapshot SourceType = "snapshot"
17 Image SourceType = "image"
18)
19
Jon Perrittd9a4bf72014-10-23 23:44:04 -050020// BlockDevice is a structure with options for booting a server instance
21// from a volume. The volume may be created from an image, snapshot, or another
22// volume.
23type BlockDevice struct {
24 // BootIndex [optional] is the boot index. It defaults to 0.
Jon Perritt8dd49db2014-10-24 12:39:07 -050025 BootIndex int `json:"boot_index"`
Jon Perrittd9a4bf72014-10-23 23:44:04 -050026
27 // DeleteOnTermination [optional] specifies whether or not to delete the attached volume
28 // when the server is deleted. Defaults to `false`.
Jon Perritt8dd49db2014-10-24 12:39:07 -050029 DeleteOnTermination bool `json:"delete_on_termination"`
Jon Perrittd9a4bf72014-10-23 23:44:04 -050030
31 // DestinationType [optional] is the type that gets created. Possible values are "volume"
32 // and "local".
Jon Perritt8dd49db2014-10-24 12:39:07 -050033 DestinationType string `json:"destination_type"`
Jon Perrittd9a4bf72014-10-23 23:44:04 -050034
Jon Perritt61710222014-10-24 13:01:31 -050035 // SourceType [required] must be one of: "volume", "snapshot", "image".
Jon Perritt01686cd2014-10-24 14:10:16 -050036 SourceType SourceType `json:"source_type"`
Jon Perrittd9a4bf72014-10-23 23:44:04 -050037
Jon Perritt61710222014-10-24 13:01:31 -050038 // UUID [required] is the unique identifier for the volume, snapshot, or image (see above)
Jon Perritt8dd49db2014-10-24 12:39:07 -050039 UUID string `json:"uuid"`
Jon Perrittd9a4bf72014-10-23 23:44:04 -050040
41 // VolumeSize [optional] is the size of the volume to create (in gigabytes).
Jon Perritt8dd49db2014-10-24 12:39:07 -050042 VolumeSize int `json:"volume_size"`
Jon Perrittd9a4bf72014-10-23 23:44:04 -050043}
44
45// CreateOptsExt is a structure that extends the server `CreateOpts` structure
46// by allowing for a block device mapping.
Jon Perritt654fb0e2014-10-23 20:54:14 -050047type CreateOptsExt struct {
48 servers.CreateOptsBuilder
Jon Perritt01686cd2014-10-24 14:10:16 -050049 BlockDevice []BlockDevice `json:"block_device_mapping_v2,omitempty"`
Jon Perritt654fb0e2014-10-23 20:54:14 -050050}
51
52// ToServerCreateMap adds the block device mapping option to the base server
53// creation options.
54func (opts CreateOptsExt) ToServerCreateMap() (map[string]interface{}, error) {
Jon Perritt8dd49db2014-10-24 12:39:07 -050055 base, err := opts.CreateOptsBuilder.ToServerCreateMap()
56 if err != nil {
57 return nil, err
58 }
59
Jon Perritt01686cd2014-10-24 14:10:16 -050060 if len(opts.BlockDevice) == 0 {
61 return nil, errors.New("Required fields UUID and SourceType not set.")
Jon Perritt4149d7c2014-10-23 21:23:46 -050062 }
Jon Perritt654fb0e2014-10-23 20:54:14 -050063
Jon Perritt4149d7c2014-10-23 21:23:46 -050064 serverMap := base["server"].(map[string]interface{})
Jon Perrittd9a4bf72014-10-23 23:44:04 -050065
Jon Perritt01686cd2014-10-24 14:10:16 -050066 blockDevice := make([]map[string]interface{}, len(opts.BlockDevice))
Jon Perrittd9a4bf72014-10-23 23:44:04 -050067
Jon Perritt01686cd2014-10-24 14:10:16 -050068 for i, bd := range opts.BlockDevice {
69 if string(bd.SourceType) == "" {
70 return nil, errors.New("SourceType must be one of: volume, image, snapshot.")
71 }
72
73 blockDevice[i] = make(map[string]interface{})
74
75 blockDevice[i]["source_type"] = bd.SourceType
76 blockDevice[i]["boot_index"] = strconv.Itoa(bd.BootIndex)
77 blockDevice[i]["delete_on_termination"] = strconv.FormatBool(bd.DeleteOnTermination)
78 blockDevice[i]["volume_size"] = strconv.Itoa(bd.VolumeSize)
79 if bd.UUID != "" {
80 blockDevice[i]["uuid"] = bd.UUID
81 }
82 if bd.DestinationType != "" {
83 blockDevice[i]["destination_type"] = bd.DestinationType
84 }
85
86 }
87 serverMap["block_device_mapping_v2"] = blockDevice
Jon Perritt654fb0e2014-10-23 20:54:14 -050088
Jon Perritt4149d7c2014-10-23 21:23:46 -050089 return base, nil
Jon Perritt654fb0e2014-10-23 20:54:14 -050090}
Jon Perrittd9a4bf72014-10-23 23:44:04 -050091
92// Create requests the creation of a server from the given block device mapping.
Jon Perritt01686cd2014-10-24 14:10:16 -050093func Create(client *gophercloud.ServiceClient, opts servers.CreateOptsBuilder) servers.CreateResult {
94 var res servers.CreateResult
Jon Perrittd9a4bf72014-10-23 23:44:04 -050095
96 reqBody, err := opts.ToServerCreateMap()
97 if err != nil {
98 res.Err = err
99 return res
100 }
101
Jamie Hannaford6a3a78f2015-03-24 14:56:12 +0100102 _, res.Err = client.Post(createURL(client), reqBody, &res.Body, &gophercloud.RequestOpts{
103 OkCodes: []int{200, 202},
Jon Perrittd9a4bf72014-10-23 23:44:04 -0500104 })
105 return res
106}