blob: e8ce7392bccd069ca3bba4bc8ece56a295c92ad6 [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.
Jon Perritt8dd49db2014-10-24 12:39:07 -050018 BootIndex int `json:"boot_index"`
Jon Perrittd9a4bf72014-10-23 23:44:04 -050019
20 // DeleteOnTermination [optional] specifies whether or not to delete the attached volume
21 // when the server is deleted. Defaults to `false`.
Jon Perritt8dd49db2014-10-24 12:39:07 -050022 DeleteOnTermination bool `json:"delete_on_termination"`
Jon Perrittd9a4bf72014-10-23 23:44:04 -050023
24 // DestinationType [optional] is the type that gets created. Possible values are "volume"
25 // and "local".
Jon Perritt8dd49db2014-10-24 12:39:07 -050026 DestinationType string `json:"destination_type"`
Jon Perrittd9a4bf72014-10-23 23:44:04 -050027
28 // SourceType [optional] must be one of: "volume", "snapshot", "image".
Jon Perritt8dd49db2014-10-24 12:39:07 -050029 SourceType string `json:"source_type"`
Jon Perrittd9a4bf72014-10-23 23:44:04 -050030
31 // UUID [optional] is the unique identifier for the volume, snapshot, or image (see above)
Jon Perritt8dd49db2014-10-24 12:39:07 -050032 UUID string `json:"uuid"`
Jon Perrittd9a4bf72014-10-23 23:44:04 -050033
34 // VolumeSize [optional] is the size of the volume to create (in gigabytes).
Jon Perritt8dd49db2014-10-24 12:39:07 -050035 VolumeSize int `json:"volume_size"`
Jon Perrittd9a4bf72014-10-23 23:44:04 -050036}
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 Perritt8dd49db2014-10-24 12:39:07 -050042 BlockDevice BlockDevice `json:"block_device_mapping_v2,omitempty"`
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 Perritt8dd49db2014-10-24 12:39:07 -050048 base, err := opts.CreateOptsBuilder.ToServerCreateMap()
49 if err != nil {
50 return nil, err
51 }
52
53 var blockDevice BlockDevice
54 if opts.BlockDevice == blockDevice {
55 return base, nil
56 }
57
Jon Perrittd9a4bf72014-10-23 23:44:04 -050058 if opts.BlockDevice.SourceType != "volume" &&
59 opts.BlockDevice.SourceType != "image" &&
60 opts.BlockDevice.SourceType != "snapshot" &&
61 opts.BlockDevice.SourceType != "" {
62 return nil, errors.New("SourceType must be one of: volume, image, snapshot, [blank].")
Jon Perritt4149d7c2014-10-23 21:23:46 -050063 }
Jon Perritt654fb0e2014-10-23 20:54:14 -050064
Jon Perritt4149d7c2014-10-23 21:23:46 -050065 serverMap := base["server"].(map[string]interface{})
Jon Perrittd9a4bf72014-10-23 23:44:04 -050066
67 bd := make(map[string]interface{})
68 bd["source_type"] = opts.BlockDevice.SourceType
69 bd["boot_index"] = strconv.Itoa(opts.BlockDevice.BootIndex)
70 bd["delete_on_termination"] = strconv.FormatBool(opts.BlockDevice.DeleteOnTermination)
71 bd["volume_size"] = strconv.Itoa(opts.BlockDevice.VolumeSize)
72 if opts.BlockDevice.UUID != "" {
73 bd["uuid"] = opts.BlockDevice.UUID
74 }
75 if opts.BlockDevice.DestinationType != "" {
76 bd["destination_type"] = opts.BlockDevice.DestinationType
77 }
78
79 serverMap["block_device_mapping_v2"] = []map[string]interface{}{bd}
Jon Perritt654fb0e2014-10-23 20:54:14 -050080
Jon Perritt4149d7c2014-10-23 21:23:46 -050081 return base, nil
Jon Perritt654fb0e2014-10-23 20:54:14 -050082}
Jon Perrittd9a4bf72014-10-23 23:44:04 -050083
84// Create requests the creation of a server from the given block device mapping.
Jon Perritt8dd49db2014-10-24 12:39:07 -050085func Create(client *gophercloud.ServiceClient, opts servers.CreateOptsBuilder) CreateResult {
86 var res CreateResult
Jon Perrittd9a4bf72014-10-23 23:44:04 -050087
88 reqBody, err := opts.ToServerCreateMap()
89 if err != nil {
90 res.Err = err
91 return res
92 }
93
94 _, res.Err = perigee.Request("POST", createURL(client), perigee.Options{
95 MoreHeaders: client.AuthenticatedHeaders(),
96 ReqBody: reqBody,
97 Results: &res.Body,
Jon Perritt8dd49db2014-10-24 12:39:07 -050098 OkCodes: []int{200, 202},
99 DumpReqJson: true,
Jon Perrittd9a4bf72014-10-23 23:44:04 -0500100 })
101 return res
102}