1package bootfromvolume
2
3import (
4	"github.com/gophercloud/gophercloud"
5	"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
6)
7
8type (
9	// DestinationType represents the type of medium being used as the
10	// destination of the bootable device.
11	DestinationType string
12
13	// SourceType represents the type of medium being used as the source of the
14	// bootable device.
15	SourceType string
16)
17
18const (
19	// DestinationLocal DestinationType is for using an ephemeral disk as the
20	// destination.
21	DestinationLocal DestinationType = "local"
22
23	// DestinationVolume DestinationType is for using a volume as the destination.
24	DestinationVolume DestinationType = "volume"
25
26	// SourceBlank SourceType is for a "blank" or empty source.
27	SourceBlank SourceType = "blank"
28
29	// SourceImage SourceType is for using images as the source of a block device.
30	SourceImage SourceType = "image"
31
32	// SourceSnapshot SourceType is for using a volume snapshot as the source of
33	// a block device.
34	SourceSnapshot SourceType = "snapshot"
35
36	// SourceVolume SourceType is for using a volume as the source of block
37	// device.
38	SourceVolume SourceType = "volume"
39)
40
41// BlockDevice is a structure with options for creating block devices in a
42// server. The block device may be created from an image, snapshot, new volume,
43// or existing volume. The destination may be a new volume, existing volume
44// which will be attached to the instance, ephemeral disk, or boot device.
45type BlockDevice struct {
46	// SourceType must be one of: "volume", "snapshot", "image", or "blank".
47	SourceType SourceType `json:"source_type" required:"true"`
48
49	// UUID is the unique identifier for the existing volume, snapshot, or
50	// image (see above).
51	UUID string `json:"uuid,omitempty"`
52
53	// BootIndex is the boot index. It defaults to 0.
54	BootIndex int `json:"boot_index"`
55
56	// DeleteOnTermination specifies whether or not to delete the attached volume
57	// when the server is deleted. Defaults to `false`.
58	DeleteOnTermination bool `json:"delete_on_termination"`
59
60	// DestinationType is the type that gets created. Possible values are "volume"
61	// and "local".
62	DestinationType DestinationType `json:"destination_type,omitempty"`
63
64	// GuestFormat specifies the format of the block device.
65	GuestFormat string `json:"guest_format,omitempty"`
66
67	// VolumeSize is the size of the volume to create (in gigabytes). This can be
68	// omitted for existing volumes.
69	VolumeSize int `json:"volume_size,omitempty"`
70
71	// DeviceType specifies the device type of the block devices.
72	// Examples of this are disk, cdrom, floppy, lun, etc.
73	DeviceType string `json:"device_type,omitempty"`
74
75	// DiskBus is the bus type of the block devices.
76	// Examples of this are ide, usb, virtio, scsi, etc.
77	DiskBus string `json:"disk_bus,omitempty"`
78
79	// VolumeType is the volume type of the block device.
80	// This requires Compute API microversion 2.67 or later.
81	VolumeType string `json:"volume_type,omitempty"`
82}
83
84// CreateOptsExt is a structure that extends the server `CreateOpts` structure
85// by allowing for a block device mapping.
86type CreateOptsExt struct {
87	servers.CreateOptsBuilder
88	BlockDevice []BlockDevice `json:"block_device_mapping_v2,omitempty"`
89}
90
91// ToServerCreateMap adds the block device mapping option to the base server
92// creation options.
93func (opts CreateOptsExt) ToServerCreateMap() (map[string]interface{}, error) {
94	base, err := opts.CreateOptsBuilder.ToServerCreateMap()
95	if err != nil {
96		return nil, err
97	}
98
99	if len(opts.BlockDevice) == 0 {
100		err := gophercloud.ErrMissingInput{}
101		err.Argument = "bootfromvolume.CreateOptsExt.BlockDevice"
102		return nil, err
103	}
104
105	serverMap := base["server"].(map[string]interface{})
106
107	blockDevice := make([]map[string]interface{}, len(opts.BlockDevice))
108
109	for i, bd := range opts.BlockDevice {
110		b, err := gophercloud.BuildRequestBody(bd, "")
111		if err != nil {
112			return nil, err
113		}
114		blockDevice[i] = b
115	}
116	serverMap["block_device_mapping_v2"] = blockDevice
117
118	return base, nil
119}
120
121// Create requests the creation of a server from the given block device mapping.
122func Create(client *gophercloud.ServiceClient, opts servers.CreateOptsBuilder) (r servers.CreateResult) {
123	b, err := opts.ToServerCreateMap()
124	if err != nil {
125		r.Err = err
126		return
127	}
128	_, r.Err = client.Post(createURL(client), b, &r.Body, &gophercloud.RequestOpts{
129		OkCodes: []int{200, 202},
130	})
131	return
132}
133