File: requests.go

package info (click to toggle)
golang-github-rackspace-gophercloud 1.0.0%2Bgit20161013.1012.e00690e8-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 5,148 kB
  • ctags: 6,414
  • sloc: sh: 16; makefile: 6
file content (120 lines) | stat: -rw-r--r-- 3,802 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package bootfromvolume

import (
	"errors"
	"strconv"

	"github.com/rackspace/gophercloud"
	"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
)

// SourceType represents the type of medium being used to create the volume.
type SourceType string

const (
	Volume   SourceType = "volume"
	Snapshot SourceType = "snapshot"
	Image    SourceType = "image"
	Blank    SourceType = "blank"
)

// BlockDevice is a structure with options for booting a server instance
// from a volume. The volume may be created from an image, snapshot, or another
// volume.
type BlockDevice struct {
	// BootIndex [optional] is the boot index. It defaults to 0.
	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 `json:"delete_on_termination"`

	// DestinationType [optional] is the type that gets created. Possible values are "volume"
	// and "local".
	DestinationType string `json:"destination_type"`

	// GuestFormat [optional] specifies the format of the block device.
	GuestFormat string `json:"guest_format"`

	// SourceType [required] must be one of: "volume", "snapshot", "image".
	SourceType SourceType `json:"source_type"`

	// UUID [required] is the unique identifier for the volume, snapshot, or image (see above)
	UUID string `json:"uuid"`

	// VolumeSize [optional] is the size of the volume to create (in gigabytes).
	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 `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 {
		return nil, errors.New("Required fields UUID and SourceType not set.")
	}

	serverMap := base["server"].(map[string]interface{})

	blockDevice := make([]map[string]interface{}, len(opts.BlockDevice))

	for i, bd := range opts.BlockDevice {
		if string(bd.SourceType) == "" {
			return nil, errors.New("SourceType must be one of: volume, image, snapshot.")
		}

		blockDevice[i] = make(map[string]interface{})

		blockDevice[i]["source_type"] = bd.SourceType
		blockDevice[i]["boot_index"] = strconv.Itoa(bd.BootIndex)
		blockDevice[i]["delete_on_termination"] = strconv.FormatBool(bd.DeleteOnTermination)
		if bd.VolumeSize > 0 {
			blockDevice[i]["volume_size"] = strconv.Itoa(bd.VolumeSize)
		}
		if bd.UUID != "" {
			blockDevice[i]["uuid"] = bd.UUID
		}
		if bd.DestinationType != "" {
			blockDevice[i]["destination_type"] = bd.DestinationType
		}
		if bd.GuestFormat != "" {
			blockDevice[i]["guest_format"] = bd.GuestFormat
		}

	}
	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) servers.CreateResult {
	var res servers.CreateResult

	reqBody, err := opts.ToServerCreateMap()
	if err != nil {
		res.Err = err
		return res
	}

	// Delete imageName and flavorName that come from ToServerCreateMap().
	// As of Liberty, Boot From Volume is failing if they are passed.
	delete(reqBody["server"].(map[string]interface{}), "imageName")
	delete(reqBody["server"].(map[string]interface{}), "flavorName")

	_, res.Err = client.Post(createURL(client), reqBody, &res.Body, &gophercloud.RequestOpts{
		OkCodes: []int{200, 202},
	})
	return res
}