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