1# Copyright (c) 2006-2010 Mitch Garnaat http://garnaat.org/
2# Copyright (c) 2010, Eucalyptus Systems, Inc.
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"""
24Represents an EC2 Elastic Block Store Snapshot
25"""
26from boto.ec2.ec2object import TaggedEC2Object
27from boto.ec2.zone import Zone
28
29
30class Snapshot(TaggedEC2Object):
31    AttrName = 'createVolumePermission'
32
33    def __init__(self, connection=None):
34        super(Snapshot, self).__init__(connection)
35        self.id = None
36        self.volume_id = None
37        self.status = None
38        self.progress = None
39        self.start_time = None
40        self.owner_id = None
41        self.owner_alias = None
42        self.volume_size = None
43        self.description = None
44        self.encrypted = None
45
46    def __repr__(self):
47        return 'Snapshot:%s' % self.id
48
49    def endElement(self, name, value, connection):
50        if name == 'snapshotId':
51            self.id = value
52        elif name == 'volumeId':
53            self.volume_id = value
54        elif name == 'status':
55            self.status = value
56        elif name == 'startTime':
57            self.start_time = value
58        elif name == 'ownerId':
59            self.owner_id = value
60        elif name == 'ownerAlias':
61            self.owner_alias = value
62        elif name == 'volumeSize':
63            try:
64                self.volume_size = int(value)
65            except:
66                self.volume_size = value
67        elif name == 'description':
68            self.description = value
69        elif name == 'encrypted':
70            self.encrypted = (value.lower() == 'true')
71        else:
72            setattr(self, name, value)
73
74    def _update(self, updated):
75        self.progress = updated.progress
76        self.status = updated.status
77
78    def update(self, validate=False, dry_run=False):
79        """
80        Update the data associated with this snapshot by querying EC2.
81
82        :type validate: bool
83        :param validate: By default, if EC2 returns no data about the
84                         snapshot the update method returns quietly.  If
85                         the validate param is True, however, it will
86                         raise a ValueError exception if no data is
87                         returned from EC2.
88        """
89        rs = self.connection.get_all_snapshots([self.id], dry_run=dry_run)
90        if len(rs) > 0:
91            self._update(rs[0])
92        elif validate:
93            raise ValueError('%s is not a valid Snapshot ID' % self.id)
94        return self.progress
95
96    def delete(self, dry_run=False):
97        return self.connection.delete_snapshot(self.id, dry_run=dry_run)
98
99    def get_permissions(self, dry_run=False):
100        attrs = self.connection.get_snapshot_attribute(
101            self.id,
102            self.AttrName,
103            dry_run=dry_run
104        )
105        return attrs.attrs
106
107    def share(self, user_ids=None, groups=None, dry_run=False):
108        return self.connection.modify_snapshot_attribute(self.id,
109                                                         self.AttrName,
110                                                         'add',
111                                                         user_ids,
112                                                         groups,
113                                                         dry_run=dry_run)
114
115    def unshare(self, user_ids=None, groups=None, dry_run=False):
116        return self.connection.modify_snapshot_attribute(self.id,
117                                                         self.AttrName,
118                                                         'remove',
119                                                         user_ids,
120                                                         groups,
121                                                         dry_run=dry_run)
122
123    def reset_permissions(self, dry_run=False):
124        return self.connection.reset_snapshot_attribute(
125            self.id,
126            self.AttrName,
127            dry_run=dry_run
128        )
129
130    def create_volume(self, zone, size=None, volume_type=None, iops=None,
131                      dry_run=False):
132        """
133        Create a new EBS Volume from this Snapshot
134
135        :type zone: string or :class:`boto.ec2.zone.Zone`
136        :param zone: The availability zone in which the Volume will be created.
137
138        :type size: int
139        :param size: The size of the new volume, in GiB. (optional). Defaults to
140            the size of the snapshot.
141
142        :type volume_type: string
143        :param volume_type: The type of the volume. (optional).  Valid
144            values are: standard | io1 | gp2.
145
146        :type iops: int
147        :param iops: The provisioned IOPs you want to associate with
148            this volume. (optional)
149        """
150        if isinstance(zone, Zone):
151            zone = zone.name
152        return self.connection.create_volume(
153            size,
154            zone,
155            self.id,
156            volume_type,
157            iops,
158            self.encrypted,
159            dry_run=dry_run
160        )
161
162
163class SnapshotAttribute(object):
164    def __init__(self, parent=None):
165        self.snapshot_id = None
166        self.attrs = {}
167
168    def startElement(self, name, attrs, connection):
169        return None
170
171    def endElement(self, name, value, connection):
172        if name == 'createVolumePermission':
173            self.name = 'create_volume_permission'
174        elif name == 'group':
175            if 'groups' in self.attrs:
176                self.attrs['groups'].append(value)
177            else:
178                self.attrs['groups'] = [value]
179        elif name == 'userId':
180            if 'user_ids' in self.attrs:
181                self.attrs['user_ids'].append(value)
182            else:
183                self.attrs['user_ids'] = [value]
184        elif name == 'snapshotId':
185            self.snapshot_id = value
186        else:
187            setattr(self, name, value)
188