~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/gopkg.in/amz.v3/ec2/ec2test/volume_attachments.go

  • Committer: Nicholas Skaggs
  • Date: 2016-10-24 20:56:05 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161024205605-z8lta0uvuhtxwzwl
Initi with beta15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// goamz - Go packages to interact with the Amazon Web Services.
 
3
//
 
4
//   https://wiki.ubuntu.com/goamz
 
5
//
 
6
// Copyright (c) 2011 Canonical Ltd.
 
7
//
 
8
// This file contains code handling AWS API around Volume Attachments.
 
9
 
 
10
package ec2test
 
11
 
 
12
import (
 
13
        "encoding/xml"
 
14
        "net/http"
 
15
        "time"
 
16
 
 
17
        "gopkg.in/amz.v3/ec2"
 
18
)
 
19
 
 
20
type volumeAttachment struct {
 
21
        ec2.VolumeAttachment
 
22
}
 
23
 
 
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")
 
27
        }
 
28
        if req.Form.Get("InstanceId") == "" {
 
29
                fatalf(400, "MissingParameter", "missing instance id")
 
30
        }
 
31
        if req.Form.Get("Device") == "" {
 
32
                fatalf(400, "MissingParameter", "missing device")
 
33
        }
 
34
        ec2VolAttachment := srv.parseVolumeAttachment(req)
 
35
 
 
36
        if _, ok := srv.volumeAttachments[ec2VolAttachment.VolumeId]; ok {
 
37
                fatalf(400, "VolumeInUse", "Volume %s is already attached", ec2VolAttachment.VolumeId)
 
38
        }
 
39
        v := srv.volume(ec2VolAttachment.VolumeId)
 
40
 
 
41
        srv.mu.Lock()
 
42
        defer srv.mu.Unlock()
 
43
        va := &volumeAttachment{ec2VolAttachment}
 
44
        va.Status = "attached"
 
45
        v.Status = "in-use"
 
46
        srv.volumeAttachments[va.VolumeId] = va
 
47
        var resp struct {
 
48
                XMLName xml.Name
 
49
                ec2.VolumeAttachmentResp
 
50
        }
 
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)
 
58
        return resp
 
59
}
 
60
 
 
61
func (srv *Server) parseVolumeAttachment(req *http.Request) ec2.VolumeAttachment {
 
62
        attachment := ec2.VolumeAttachment{}
 
63
        var vol *volume
 
64
        var inst *Instance
 
65
        for attr, vals := range req.Form {
 
66
                switch attr {
 
67
                case "AWSAccessKeyId", "Action", "Signature", "SignatureMethod", "SignatureVersion",
 
68
                        "Version", "Timestamp":
 
69
                        continue
 
70
                case "VolumeId":
 
71
                        v := vals[0]
 
72
                        // Check volume id validity.
 
73
                        vol = srv.volume(v)
 
74
                        if vol.Status != "available" {
 
75
                                fatalf(400, " IncorrectState", "cannot attach volume that is not available", v)
 
76
                        }
 
77
                        attachment.VolumeId = v
 
78
                case "InstanceId":
 
79
                        v := vals[0]
 
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)
 
84
                        }
 
85
                        attachment.InstanceId = v
 
86
                case "Device":
 
87
                        attachment.Device = vals[0]
 
88
                default:
 
89
                        fatalf(400, "InvalidParameterValue", "unknown field %s: %s", attr, vals[0])
 
90
                }
 
91
        }
 
92
        if vol.AvailZone != inst.availZone {
 
93
                fatalf(
 
94
                        400,
 
95
                        "InvalidVolume.ZoneMismatch",
 
96
                        "volume availability zone %q must match instance zone %q", vol.AvailZone, inst.availZone,
 
97
                )
 
98
        }
 
99
        return attachment
 
100
}
 
101
 
 
102
func (srv *Server) volumeAttachment(id string) *volumeAttachment {
 
103
        if id == "" {
 
104
                fatalf(400, "MissingParameter", "missing volumeId")
 
105
        }
 
106
        srv.mu.Lock()
 
107
        defer srv.mu.Unlock()
 
108
        v, found := srv.volumeAttachments[id]
 
109
        if !found {
 
110
                fatalf(400, "InvalidAttachment.NotFound", "Volume attachment for volume %s not found", id)
 
111
        }
 
112
        return v
 
113
}
 
114
 
 
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.
 
120
        v := srv.volume(vId)
 
121
 
 
122
        srv.mu.Lock()
 
123
        defer srv.mu.Unlock()
 
124
        delete(srv.volumeAttachments, vId)
 
125
        v.Status = "available"
 
126
        var resp struct {
 
127
                XMLName xml.Name
 
128
                ec2.VolumeAttachmentResp
 
129
        }
 
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"
 
136
        return resp
 
137
}