from bootstrapvz.base.fs.volume import Volume from bootstrapvz.base.fs.exceptions import VolumeError class EBSVolume(Volume): def create(self, conn, zone, tags=[], encrypted=False, kms_key_id=None): self.fsm.create(connection=conn, zone=zone, tags=tags, encrypted=encrypted, kms_key_id=kms_key_id) def _before_create(self, e): self.conn = e.connection zone = e.zone tags = e.tags size = self.size.bytes.get_qty_in('GiB') params = dict(Size=size, AvailabilityZone=zone, VolumeType='gp2', TagSpecifications=[{'ResourceType': 'volume', 'Tags': tags}], Encrypted=e.encrypted) if e.encrypted and e.kms_key_id: params['KmsKeyId'] = e.kms_key_id self.volume = self.conn.create_volume(**params) self.vol_id = self.volume['VolumeId'] waiter = self.conn.get_waiter('volume_available') waiter.wait(VolumeIds=[self.vol_id], Filters=[{'Name': 'status', 'Values': ['available']}]) def attach(self, instance_id): self.fsm.attach(instance_id=instance_id) def _before_attach(self, e): import os.path import string self.instance_id = e.instance_id for letter in string.ascii_lowercase[5:]: dev_path = os.path.join('/dev', 'xvd' + letter) if not os.path.exists(dev_path): self.device_path = dev_path self.ec2_device_path = os.path.join('/dev', 'sd' + letter) break if self.device_path is None: raise VolumeError('Unable to find a free block device path for mounting the bootstrap volume') self.conn.attach_volume(VolumeId=self.vol_id, InstanceId=self.instance_id, Device=self.ec2_device_path) waiter = self.conn.get_waiter('volume_in_use') waiter.wait(VolumeIds=[self.vol_id], Filters=[{'Name': 'attachment.status', 'Values': ['attached']}]) def _before_detach(self, e): self.conn.detach_volume(VolumeId=self.vol_id, InstanceId=self.instance_id, Device=self.ec2_device_path) waiter = self.conn.get_waiter('volume_available') waiter.wait(VolumeIds=[self.vol_id], Filters=[{'Name': 'status', 'Values': ['available']}]) del self.ec2_device_path self.device_path = None def _before_delete(self, e): self.conn.delete_volume(VolumeId=self.vol_id) def snapshot(self): snapshot = self.conn.create_snapshot(VolumeId=self.vol_id) self.snap_id = snapshot['SnapshotId'] waiter = self.conn.get_waiter('snapshot_completed') waiter.wait(SnapshotIds=[self.snap_id], Filters=[{'Name': 'status', 'Values': ['completed']}], WaiterConfig={'Delay': 15, 'MaxAttempts': 120}) return self.snap_id