from jinja2 import Template from moto.core.responses import BaseResponse from moto.ec2.models import ec2_backend class ElasticBlockStore(BaseResponse): def attach_volume(self): volume_id = self.querystring.get('VolumeId')[0] instance_id = self.querystring.get('InstanceId')[0] device_path = self.querystring.get('Device')[0] attachment = ec2_backend.attach_volume(volume_id, instance_id, device_path) if not attachment: return "", dict(status=404) template = Template(ATTACHED_VOLUME_RESPONSE) return template.render(attachment=attachment) def copy_snapshot(self): raise NotImplementedError('ElasticBlockStore.copy_snapshot is not yet implemented') def create_snapshot(self): description = None if 'Description' in self.querystring: description = self.querystring.get('Description')[0] volume_id = self.querystring.get('VolumeId')[0] snapshot = ec2_backend.create_snapshot(volume_id, description) template = Template(CREATE_SNAPSHOT_RESPONSE) return template.render(snapshot=snapshot) def create_volume(self): size = self.querystring.get('Size')[0] zone = self.querystring.get('AvailabilityZone')[0] volume = ec2_backend.create_volume(size, zone) template = Template(CREATE_VOLUME_RESPONSE) return template.render(volume=volume) def delete_snapshot(self): snapshot_id = self.querystring.get('SnapshotId')[0] success = ec2_backend.delete_snapshot(snapshot_id) if not success: # Snapshot doesn't exist return "Snapshot with id {0} does not exist".format(snapshot_id), dict(status=404) return DELETE_SNAPSHOT_RESPONSE def delete_volume(self): volume_id = self.querystring.get('VolumeId')[0] success = ec2_backend.delete_volume(volume_id) if not success: # Volume doesn't exist return "Volume with id {0} does not exist".format(volume_id), dict(status=404) return DELETE_VOLUME_RESPONSE def describe_snapshot_attribute(self): raise NotImplementedError('ElasticBlockStore.describe_snapshot_attribute is not yet implemented') def describe_snapshots(self): snapshots = ec2_backend.describe_snapshots() template = Template(DESCRIBE_SNAPSHOTS_RESPONSE) return template.render(snapshots=snapshots) def describe_volumes(self): volumes = ec2_backend.describe_volumes() template = Template(DESCRIBE_VOLUMES_RESPONSE) return template.render(volumes=volumes) def describe_volume_attribute(self): raise NotImplementedError('ElasticBlockStore.describe_volume_attribute is not yet implemented') def describe_volume_status(self): raise NotImplementedError('ElasticBlockStore.describe_volume_status is not yet implemented') def detach_volume(self): volume_id = self.querystring.get('VolumeId')[0] instance_id = self.querystring.get('InstanceId')[0] device_path = self.querystring.get('Device')[0] attachment = ec2_backend.detach_volume(volume_id, instance_id, device_path) if not attachment: # Volume wasn't attached return "Volume {0} can not be detached from {1} because it is not attached".format(volume_id, instance_id), dict(status=404) template = Template(DETATCH_VOLUME_RESPONSE) return template.render(attachment=attachment) def enable_volume_io(self): raise NotImplementedError('ElasticBlockStore.enable_volume_io is not yet implemented') def import_volume(self): raise NotImplementedError('ElasticBlockStore.import_volume is not yet implemented') def modify_snapshot_attribute(self): raise NotImplementedError('ElasticBlockStore.modify_snapshot_attribute is not yet implemented') def modify_volume_attribute(self): raise NotImplementedError('ElasticBlockStore.modify_volume_attribute is not yet implemented') def reset_snapshot_attribute(self): raise NotImplementedError('ElasticBlockStore.reset_snapshot_attribute is not yet implemented') CREATE_VOLUME_RESPONSE = """ 59dbff89-35bd-4eac-99ed-be587EXAMPLE {{ volume.id }} {{ volume.size }} {{ volume.zone.name }} creating YYYY-MM-DDTHH:MM:SS.000Z standard """ DESCRIBE_VOLUMES_RESPONSE = """ 59dbff89-35bd-4eac-99ed-be587EXAMPLE {% for volume in volumes %} {{ volume.id }} {{ volume.size }} {{ volume.zone.name }} {{ volume.status }} YYYY-MM-DDTHH:MM:SS.SSSZ {% if volume.attachment %} {{ volume.id }} {{ volume.attachment.instance.id }} {{ volume.attachment.device }} attached YYYY-MM-DDTHH:MM:SS.SSSZ false {% endif %} standard {% endfor %} """ DELETE_VOLUME_RESPONSE = """ 59dbff89-35bd-4eac-99ed-be587EXAMPLE true """ ATTACHED_VOLUME_RESPONSE = """ 59dbff89-35bd-4eac-99ed-be587EXAMPLE {{ attachment.volume.id }} {{ attachment.instance.id }} {{ attachment.device }} attaching YYYY-MM-DDTHH:MM:SS.000Z """ DETATCH_VOLUME_RESPONSE = """ 59dbff89-35bd-4eac-99ed-be587EXAMPLE {{ attachment.volume.id }} {{ attachment.instance.id }} {{ attachment.device }} detaching YYYY-MM-DDTHH:MM:SS.000Z """ CREATE_SNAPSHOT_RESPONSE = """ 59dbff89-35bd-4eac-99ed-be587EXAMPLE {{ snapshot.id }} {{ snapshot.volume.id }} pending YYYY-MM-DDTHH:MM:SS.000Z 60% 111122223333 {{ snapshot.volume.size }} {{ snapshot.description }} """ DESCRIBE_SNAPSHOTS_RESPONSE = """ 59dbff89-35bd-4eac-99ed-be587EXAMPLE {% for snapshot in snapshots %} {{ snapshot.id }} {{ snapshot.volume.id }} pending YYYY-MM-DDTHH:MM:SS.SSSZ 30% 111122223333 {{ snapshot.volume.size }} {{ snapshot.description }} {% endfor %} """ DELETE_SNAPSHOT_RESPONSE = """ 59dbff89-35bd-4eac-99ed-be587EXAMPLE true """