blob: d5b361b4bcd4d50c994808f9cc073fa69cd87977 [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 Perrittd9a4bf72014-10-23 23:44:04 -05009
10 "github.com/racker/perigee"
Jon Perritt654fb0e2014-10-23 20:54:14 -050011)
12
Jon Perrittd9a4bf72014-10-23 23:44:04 -050013// BlockDevice is a structure with options for booting a server instance
14// from a volume. The volume may be created from an image, snapshot, or another
15// volume.
16type BlockDevice struct {
17 // BootIndex [optional] is the boot index. It defaults to 0.
18 BootIndex int
19
20 // DeleteOnTermination [optional] specifies whether or not to delete the attached volume
21 // when the server is deleted. Defaults to `false`.
22 DeleteOnTermination bool
23
24 // DestinationType [optional] is the type that gets created. Possible values are "volume"
25 // and "local".
26 DestinationType string
27
28 // SourceType [optional] must be one of: "volume", "snapshot", "image".
29 SourceType string
30
31 // UUID [optional] is the unique identifier for the volume, snapshot, or image (see above)
32 UUID string
33
34 // VolumeSize [optional] is the size of the volume to create (in gigabytes).
35 VolumeSize int
36}
37
38// CreateOptsExt is a structure that extends the server `CreateOpts` structure
39// by allowing for a block device mapping.
Jon Perritt654fb0e2014-10-23 20:54:14 -050040type CreateOptsExt struct {
41 servers.CreateOptsBuilder
Jon Perrittd9a4bf72014-10-23 23:44:04 -050042 BlockDevice BlockDevice
Jon Perritt654fb0e2014-10-23 20:54:14 -050043}
44
45// ToServerCreateMap adds the block device mapping option to the base server
46// creation options.
47func (opts CreateOptsExt) ToServerCreateMap() (map[string]interface{}, error) {
Jon Perrittd9a4bf72014-10-23 23:44:04 -050048 if opts.BlockDevice.SourceType != "volume" &&
49 opts.BlockDevice.SourceType != "image" &&
50 opts.BlockDevice.SourceType != "snapshot" &&
51 opts.BlockDevice.SourceType != "" {
52 return nil, errors.New("SourceType must be one of: volume, image, snapshot, [blank].")
Jon Perritt4149d7c2014-10-23 21:23:46 -050053 }
Jon Perritt654fb0e2014-10-23 20:54:14 -050054
Jon Perritt4149d7c2014-10-23 21:23:46 -050055 base, err := opts.CreateOptsBuilder.ToServerCreateMap()
56 if err != nil {
57 return nil, err
58 }
Jon Perritt654fb0e2014-10-23 20:54:14 -050059
Jon Perritt4149d7c2014-10-23 21:23:46 -050060 serverMap := base["server"].(map[string]interface{})
Jon Perrittd9a4bf72014-10-23 23:44:04 -050061
62 bd := make(map[string]interface{})
63 bd["source_type"] = opts.BlockDevice.SourceType
64 bd["boot_index"] = strconv.Itoa(opts.BlockDevice.BootIndex)
65 bd["delete_on_termination"] = strconv.FormatBool(opts.BlockDevice.DeleteOnTermination)
66 bd["volume_size"] = strconv.Itoa(opts.BlockDevice.VolumeSize)
67 if opts.BlockDevice.UUID != "" {
68 bd["uuid"] = opts.BlockDevice.UUID
69 }
70 if opts.BlockDevice.DestinationType != "" {
71 bd["destination_type"] = opts.BlockDevice.DestinationType
72 }
73
74 serverMap["block_device_mapping_v2"] = []map[string]interface{}{bd}
Jon Perritt654fb0e2014-10-23 20:54:14 -050075
Jon Perritt4149d7c2014-10-23 21:23:46 -050076 return base, nil
Jon Perritt654fb0e2014-10-23 20:54:14 -050077}
Jon Perrittd9a4bf72014-10-23 23:44:04 -050078
79// Create requests the creation of a server from the given block device mapping.
80func Create(client *gophercloud.ServiceClient, opts servers.CreateOptsBuilder) servers.CreateResult {
81 var res servers.CreateResult
82
83 reqBody, err := opts.ToServerCreateMap()
84 if err != nil {
85 res.Err = err
86 return res
87 }
88
89 _, res.Err = perigee.Request("POST", createURL(client), perigee.Options{
90 MoreHeaders: client.AuthenticatedHeaders(),
91 ReqBody: reqBody,
92 Results: &res.Body,
93 OkCodes: []int{200},
94 })
95 return res
96}