2
// goamz - Go packages to interact with the Amazon Web Services.
4
// https://wiki.ubuntu.com/goamz
6
// Copyright (c) 2011 Canonical Ltd.
8
// This file contains code handling AWS API around Volume Attachments.
20
type volumeAttachment struct {
24
func (srv *Server) attachVolume(w http.ResponseWriter, req *http.Request, reqId string) interface{} {
25
if req.Form.Get("VolumeId") == "" {
26
fatalf(400, "MissingParameter", "missing volume id")
28
if req.Form.Get("InstanceId") == "" {
29
fatalf(400, "MissingParameter", "missing instance id")
31
if req.Form.Get("Device") == "" {
32
fatalf(400, "MissingParameter", "missing device")
34
ec2VolAttachment := srv.parseVolumeAttachment(req)
36
if _, ok := srv.volumeAttachments[ec2VolAttachment.VolumeId]; ok {
37
fatalf(400, "VolumeInUse", "Volume %s is already attached", ec2VolAttachment.VolumeId)
39
v := srv.volume(ec2VolAttachment.VolumeId)
43
va := &volumeAttachment{ec2VolAttachment}
44
va.Status = "attached"
46
srv.volumeAttachments[va.VolumeId] = va
49
ec2.VolumeAttachmentResp
51
resp.XMLName = xml.Name{defaultXMLName, "AttachVolumeResponse"}
52
resp.RequestId = reqId
53
resp.VolumeId = va.VolumeId
54
resp.InstanceId = va.InstanceId
55
resp.Device = va.Device
56
resp.Status = va.Status
57
resp.AttachTime = time.Now().Format(time.RFC3339)
61
func (srv *Server) parseVolumeAttachment(req *http.Request) ec2.VolumeAttachment {
62
attachment := ec2.VolumeAttachment{}
65
for attr, vals := range req.Form {
67
case "AWSAccessKeyId", "Action", "Signature", "SignatureMethod", "SignatureVersion",
68
"Version", "Timestamp":
72
// Check volume id validity.
74
if vol.Status != "available" {
75
fatalf(400, " IncorrectState", "cannot attach volume that is not available", v)
77
attachment.VolumeId = v
80
// Check instance id validity.
81
inst = srv.instance(v)
82
if inst.state != Running {
83
fatalf(400, "IncorrectInstanceState", "cannot attach volume to instance %s as it is not running", v)
85
attachment.InstanceId = v
87
attachment.Device = vals[0]
89
fatalf(400, "InvalidParameterValue", "unknown field %s: %s", attr, vals[0])
92
if vol.AvailZone != inst.availZone {
95
"InvalidVolume.ZoneMismatch",
96
"volume availability zone %q must match instance zone %q", vol.AvailZone, inst.availZone,
102
func (srv *Server) volumeAttachment(id string) *volumeAttachment {
104
fatalf(400, "MissingParameter", "missing volumeId")
107
defer srv.mu.Unlock()
108
v, found := srv.volumeAttachments[id]
110
fatalf(400, "InvalidAttachment.NotFound", "Volume attachment for volume %s not found", id)
115
func (srv *Server) detachVolume(w http.ResponseWriter, req *http.Request, reqId string) interface{} {
116
vId := req.Form.Get("VolumeId")
117
// Get attachment first so if not found, the expected error is returned.
118
va := srv.volumeAttachment(vId)
119
// Validate volume exists.
123
defer srv.mu.Unlock()
124
delete(srv.volumeAttachments, vId)
125
v.Status = "available"
128
ec2.VolumeAttachmentResp
130
resp.XMLName = xml.Name{defaultXMLName, "DetachVolumeResponse"}
131
resp.RequestId = reqId
132
resp.VolumeId = va.VolumeId
133
resp.InstanceId = va.InstanceId
134
resp.Device = va.Device
135
resp.Status = "detaching"