1# Copyright (c) 2009-2012 Mitch Garnaat http://garnaat.org/
2# Copyright (c) 2012 Amazon.com, Inc. or its affiliates.  All Rights Reserved
3#
4# Permission is hereby granted, free of charge, to any person obtaining a
5# copy of this software and associated documentation files (the
6# "Software"), to deal in the Software without restriction, including
7# without limitation the rights to use, copy, modify, merge, publish, dis-
8# tribute, sublicense, and/or sell copies of the Software, and to permit
9# persons to whom the Software is furnished to do so, subject to the fol-
10# lowing conditions:
11#
12# The above copyright notice and this permission notice shall be included
13# in all copies or substantial portions of the Software.
14#
15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
17# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
18# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21# IN THE SOFTWARE.
22#
23
24
25class BlockDeviceType(object):
26    """
27    Represents parameters for a block device.
28    """
29
30    def __init__(self,
31                 connection=None,
32                 ephemeral_name=None,
33                 no_device=False,
34                 volume_id=None,
35                 snapshot_id=None,
36                 status=None,
37                 attach_time=None,
38                 delete_on_termination=False,
39                 size=None,
40                 volume_type=None,
41                 iops=None,
42                 encrypted=None):
43        self.connection = connection
44        self.ephemeral_name = ephemeral_name
45        self.no_device = no_device
46        self.volume_id = volume_id
47        self.snapshot_id = snapshot_id
48        self.status = status
49        self.attach_time = attach_time
50        self.delete_on_termination = delete_on_termination
51        self.size = size
52        self.volume_type = volume_type
53        self.iops = iops
54        self.encrypted = encrypted
55
56    def startElement(self, name, attrs, connection):
57        pass
58
59    def endElement(self, name, value, connection):
60        lname = name.lower()
61        if name == 'volumeId':
62            self.volume_id = value
63        elif lname == 'virtualname':
64            self.ephemeral_name = value
65        elif lname == 'nodevice':
66            self.no_device = (value == 'true')
67        elif lname == 'snapshotid':
68            self.snapshot_id = value
69        elif lname == 'volumesize':
70            self.size = int(value)
71        elif lname == 'status':
72            self.status = value
73        elif lname == 'attachtime':
74            self.attach_time = value
75        elif lname == 'deleteontermination':
76            self.delete_on_termination = (value == 'true')
77        elif lname == 'volumetype':
78            self.volume_type = value
79        elif lname == 'iops':
80            self.iops = int(value)
81        elif lname == 'encrypted':
82            self.encrypted = (value == 'true')
83        else:
84            setattr(self, name, value)
85
86# for backwards compatibility
87EBSBlockDeviceType = BlockDeviceType
88
89
90class BlockDeviceMapping(dict):
91    """
92    Represents a collection of BlockDeviceTypes when creating ec2 instances.
93
94    Example:
95    dev_sda1 = BlockDeviceType()
96    dev_sda1.size = 100   # change root volume to 100GB instead of default
97    bdm = BlockDeviceMapping()
98    bdm['/dev/sda1'] = dev_sda1
99    reservation = image.run(..., block_device_map=bdm, ...)
100    """
101
102    def __init__(self, connection=None):
103        """
104        :type connection: :class:`boto.ec2.EC2Connection`
105        :param connection: Optional connection.
106        """
107        dict.__init__(self)
108        self.connection = connection
109        self.current_name = None
110        self.current_value = None
111
112    def startElement(self, name, attrs, connection):
113        lname = name.lower()
114        if lname in ['ebs', 'virtualname']:
115            self.current_value = BlockDeviceType(self)
116            return self.current_value
117
118    def endElement(self, name, value, connection):
119        lname = name.lower()
120        if lname in ['device', 'devicename']:
121            self.current_name = value
122        elif lname in ['item', 'member']:
123            self[self.current_name] = self.current_value
124
125    def ec2_build_list_params(self, params, prefix=''):
126        pre = '%sBlockDeviceMapping' % prefix
127        return self._build_list_params(params, prefix=pre)
128
129    def autoscale_build_list_params(self, params, prefix=''):
130        pre = '%sBlockDeviceMappings.member' % prefix
131        return self._build_list_params(params, prefix=pre)
132
133    def _build_list_params(self, params, prefix=''):
134        i = 1
135        for dev_name in self:
136            pre = '%s.%d' % (prefix, i)
137            params['%s.DeviceName' % pre] = dev_name
138            block_dev = self[dev_name]
139            if block_dev.ephemeral_name:
140                params['%s.VirtualName' % pre] = block_dev.ephemeral_name
141            else:
142                if block_dev.no_device:
143                    params['%s.NoDevice' % pre] = ''
144                else:
145                    if block_dev.snapshot_id:
146                        params['%s.Ebs.SnapshotId' % pre] = block_dev.snapshot_id
147                    if block_dev.size:
148                        params['%s.Ebs.VolumeSize' % pre] = block_dev.size
149                    if block_dev.delete_on_termination:
150                        params['%s.Ebs.DeleteOnTermination' % pre] = 'true'
151                    else:
152                        params['%s.Ebs.DeleteOnTermination' % pre] = 'false'
153                    if block_dev.volume_type:
154                        params['%s.Ebs.VolumeType' % pre] = block_dev.volume_type
155                    if block_dev.iops is not None:
156                        params['%s.Ebs.Iops' % pre] = block_dev.iops
157                    # The encrypted flag (even if False) cannot be specified for the root EBS
158                    # volume.
159                    if block_dev.encrypted is not None:
160                        if block_dev.encrypted:
161                            params['%s.Ebs.Encrypted' % pre] = 'true'
162                        else:
163                            params['%s.Ebs.Encrypted' % pre] = 'false'
164
165            i += 1
166