commit
4543db567c
5 changed files with 116 additions and 21 deletions
|
|
@ -1,17 +1,17 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
from collections import defaultdict
|
||||
import boto
|
||||
import copy
|
||||
from datetime import datetime
|
||||
import itertools
|
||||
import re
|
||||
import six
|
||||
|
||||
import boto
|
||||
from collections import defaultdict
|
||||
from datetime import datetime
|
||||
from boto.ec2.instance import Instance as BotoInstance, Reservation
|
||||
from boto.ec2.blockdevicemapping import BlockDeviceMapping, BlockDeviceType
|
||||
from boto.ec2.spotinstancerequest import SpotInstanceRequest as BotoSpotRequest
|
||||
from boto.ec2.launchspecification import LaunchSpecification
|
||||
import six
|
||||
|
||||
from moto.core import BaseBackend
|
||||
from moto.core.models import Model
|
||||
|
|
@ -97,6 +97,9 @@ from .utils import (
|
|||
)
|
||||
|
||||
|
||||
def utc_date_and_time():
|
||||
return datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ')
|
||||
|
||||
def validate_resource_ids(resource_ids):
|
||||
for resource_id in resource_ids:
|
||||
if not is_valid_resource_id(resource_id):
|
||||
|
|
@ -309,14 +312,17 @@ class Instance(BotoInstance, TaggedEC2Resource):
|
|||
in_ec2_classic = not bool(self.subnet_id)
|
||||
self.key_name = kwargs.get("key_name")
|
||||
self.source_dest_check = "true"
|
||||
self.launch_time = datetime.utcnow().isoformat()
|
||||
self.launch_time = utc_date_and_time()
|
||||
associate_public_ip = kwargs.get("associate_public_ip", False)
|
||||
if in_ec2_classic:
|
||||
# If we are in EC2-Classic, autoassign a public IP
|
||||
associate_public_ip = True
|
||||
|
||||
self.block_device_mapping = BlockDeviceMapping()
|
||||
self.block_device_mapping['/dev/sda1'] = BlockDeviceType(volume_id=random_volume_id())
|
||||
# Default have an instance with root volume should you not wish to override with attach volume cmd.
|
||||
# However this is a ghost volume and wont show up in get_all_volumes or snapshot-able.
|
||||
self.block_device_mapping['/dev/sda1'] = BlockDeviceType(volume_id=random_volume_id(), status='attached',
|
||||
attach_time=utc_date_and_time())
|
||||
|
||||
amis = self.ec2_backend.describe_images(filters={'image-id': image_id})
|
||||
ami = amis[0] if amis else None
|
||||
|
|
@ -343,6 +349,10 @@ class Instance(BotoInstance, TaggedEC2Resource):
|
|||
private_ip=kwargs.get("private_ip"),
|
||||
associate_public_ip=associate_public_ip)
|
||||
|
||||
@property
|
||||
def get_block_device_mapping(self):
|
||||
return self.block_device_mapping.items()
|
||||
|
||||
@property
|
||||
def private_ip(self):
|
||||
return self.nics[0].private_ip_address
|
||||
|
|
@ -1349,6 +1359,7 @@ class SecurityGroupIngress(object):
|
|||
class VolumeAttachment(object):
|
||||
def __init__(self, volume, instance, device):
|
||||
self.volume = volume
|
||||
self.attach_time = utc_date_and_time()
|
||||
self.instance = instance
|
||||
self.device = device
|
||||
|
||||
|
|
@ -1373,6 +1384,7 @@ class Volume(TaggedEC2Resource):
|
|||
self.id = volume_id
|
||||
self.size = size
|
||||
self.zone = zone
|
||||
self.create_time = utc_date_and_time()
|
||||
self.attachment = None
|
||||
self.ec2_backend = ec2_backend
|
||||
|
||||
|
|
@ -1404,6 +1416,7 @@ class Snapshot(TaggedEC2Resource):
|
|||
self.id = snapshot_id
|
||||
self.volume = volume
|
||||
self.description = description
|
||||
self.start_time = utc_date_and_time()
|
||||
self.create_volume_permission_groups = set()
|
||||
self.ec2_backend = ec2_backend
|
||||
|
||||
|
|
@ -1444,6 +1457,13 @@ class EBSBackend(object):
|
|||
return False
|
||||
|
||||
volume.attachment = VolumeAttachment(volume, instance, device_path)
|
||||
# Modify instance to capture mount of block device.
|
||||
bdt = BlockDeviceType(volume_id=volume_id, status=volume.status, size=volume.size,
|
||||
attach_time=utc_date_and_time())
|
||||
try:
|
||||
instance.block_device_mapping[device_path] = bdt
|
||||
except:
|
||||
instance.block_device_mapping.setdefault(device_path, bdt)
|
||||
return volume.attachment
|
||||
|
||||
def detach_volume(self, volume_id, instance_id, device_path):
|
||||
|
|
|
|||
|
|
@ -42,12 +42,22 @@ class ElasticBlockStore(BaseResponse):
|
|||
return DELETE_VOLUME_RESPONSE
|
||||
|
||||
def describe_snapshots(self):
|
||||
# querystring for multiple snapshotids results in SnapshotId.1, SnapshotId.2 etc
|
||||
snapshot_ids = ','.join([','.join(s[1]) for s in self.querystring.items() if 'SnapshotId' in s[0]])
|
||||
snapshots = self.ec2_backend.describe_snapshots()
|
||||
# Describe snapshots to handle filter on snapshot_ids
|
||||
snapshots = [s for s in snapshots if s.id in snapshot_ids] if snapshot_ids else snapshots
|
||||
# snapshots = self.ec2_backend.describe_snapshots()
|
||||
template = self.response_template(DESCRIBE_SNAPSHOTS_RESPONSE)
|
||||
return template.render(snapshots=snapshots)
|
||||
|
||||
def describe_volumes(self):
|
||||
# querystring for multiple volumeids results in VolumeId.1, VolumeId.2 etc
|
||||
volume_ids = ','.join([','.join(v[1]) for v in self.querystring.items() if 'VolumeId' in v[0]])
|
||||
volumes = self.ec2_backend.describe_volumes()
|
||||
# Describe volumes to handle filter on volume_ids
|
||||
volumes = [v for v in volumes if v.id in volume_ids] if volume_ids else volumes
|
||||
# volumes = self.ec2_backend.describe_volumes()
|
||||
template = self.response_template(DESCRIBE_VOLUMES_RESPONSE)
|
||||
return template.render(volumes=volumes)
|
||||
|
||||
|
|
@ -103,7 +113,7 @@ CREATE_VOLUME_RESPONSE = """<CreateVolumeResponse xmlns="http://ec2.amazonaws.co
|
|||
<snapshotId/>
|
||||
<availabilityZone>{{ volume.zone.name }}</availabilityZone>
|
||||
<status>creating</status>
|
||||
<createTime>2013-10-04T17:38:53.000Z</createTime>
|
||||
<createTime>{{ volume.create_time}}</createTime>
|
||||
<volumeType>standard</volumeType>
|
||||
</CreateVolumeResponse>"""
|
||||
|
||||
|
|
@ -117,7 +127,7 @@ DESCRIBE_VOLUMES_RESPONSE = """<DescribeVolumesResponse xmlns="http://ec2.amazon
|
|||
<snapshotId/>
|
||||
<availabilityZone>{{ volume.zone.name }}</availabilityZone>
|
||||
<status>{{ volume.status }}</status>
|
||||
<createTime>2013-10-04T17:38:53.000Z</createTime>
|
||||
<createTime>{{ volume.create_time}}</createTime>
|
||||
<attachmentSet>
|
||||
{% if volume.attachment %}
|
||||
<item>
|
||||
|
|
@ -125,7 +135,7 @@ DESCRIBE_VOLUMES_RESPONSE = """<DescribeVolumesResponse xmlns="http://ec2.amazon
|
|||
<instanceId>{{ volume.attachment.instance.id }}</instanceId>
|
||||
<device>{{ volume.attachment.device }}</device>
|
||||
<status>attached</status>
|
||||
<attachTime>2013-10-04T17:38:53.000Z</attachTime>
|
||||
<attachTime>{{volume.attachment.attach_time}}</attachTime>
|
||||
<deleteOnTermination>false</deleteOnTermination>
|
||||
</item>
|
||||
{% endif %}
|
||||
|
|
@ -157,7 +167,7 @@ ATTACHED_VOLUME_RESPONSE = """<AttachVolumeResponse xmlns="http://ec2.amazonaws.
|
|||
<instanceId>{{ attachment.instance.id }}</instanceId>
|
||||
<device>{{ attachment.device }}</device>
|
||||
<status>attaching</status>
|
||||
<attachTime>2013-10-04T17:38:53.000Z</attachTime>
|
||||
<attachTime>{{attachment.attach_time}}</attachTime>
|
||||
</AttachVolumeResponse>"""
|
||||
|
||||
DETATCH_VOLUME_RESPONSE = """<DetachVolumeResponse xmlns="http://ec2.amazonaws.com/doc/2012-12-01/">
|
||||
|
|
@ -174,7 +184,7 @@ CREATE_SNAPSHOT_RESPONSE = """<CreateSnapshotResponse xmlns="http://ec2.amazonaw
|
|||
<snapshotId>{{ snapshot.id }}</snapshotId>
|
||||
<volumeId>{{ snapshot.volume.id }}</volumeId>
|
||||
<status>pending</status>
|
||||
<startTime>2013-10-04T17:38:53.000Z</startTime>
|
||||
<startTime>{{ snapshot.start_time}}</startTime>
|
||||
<progress>60%</progress>
|
||||
<ownerId>111122223333</ownerId>
|
||||
<volumeSize>{{ snapshot.volume.size }}</volumeSize>
|
||||
|
|
@ -189,7 +199,7 @@ DESCRIBE_SNAPSHOTS_RESPONSE = """<DescribeSnapshotsResponse xmlns="http://ec2.am
|
|||
<snapshotId>{{ snapshot.id }}</snapshotId>
|
||||
<volumeId>{{ snapshot.volume.id }}</volumeId>
|
||||
<status>pending</status>
|
||||
<startTime>2013-10-04T17:38:53.000Z</startTime>
|
||||
<startTime>{{ snapshot.start_time}}</startTime>
|
||||
<progress>30%</progress>
|
||||
<ownerId>111122223333</ownerId>
|
||||
<volumeSize>{{ snapshot.volume.size }}</volumeSize>
|
||||
|
|
|
|||
|
|
@ -206,7 +206,7 @@ EC2_RUN_INSTANCES = """<RunInstancesResponse xmlns="http://ec2.amazonaws.com/doc
|
|||
<instanceType>{{ instance.instance_type }}</instanceType>
|
||||
<launchTime>{{ instance.launch_time }}</launchTime>
|
||||
<placement>
|
||||
<availabilityZone>us-east-1b</availabilityZone>
|
||||
<availabilityZone>{{ instance.placement}}</availabilityZone>
|
||||
<groupName/>
|
||||
<tenancy>default</tenancy>
|
||||
</placement>
|
||||
|
|
@ -331,7 +331,7 @@ EC2_DESCRIBE_INSTANCES = """<DescribeInstancesResponse xmlns='http://ec2.amazona
|
|||
<instanceType>{{ instance.instance_type }}</instanceType>
|
||||
<launchTime>{{ instance.launch_time }}</launchTime>
|
||||
<placement>
|
||||
<availabilityZone>us-west-2a</availabilityZone>
|
||||
<availabilityZone>{{ instance.placement }}</availabilityZone>
|
||||
<groupName/>
|
||||
<tenancy>default</tenancy>
|
||||
</placement>
|
||||
|
|
@ -369,15 +369,18 @@ EC2_DESCRIBE_INSTANCES = """<DescribeInstancesResponse xmlns='http://ec2.amazona
|
|||
<rootDeviceType>ebs</rootDeviceType>
|
||||
<rootDeviceName>/dev/sda1</rootDeviceName>
|
||||
<blockDeviceMapping>
|
||||
{% for device_name,deviceobject in instance.get_block_device_mapping %}
|
||||
<item>
|
||||
<deviceName>/dev/sda1</deviceName>
|
||||
<deviceName>{{ device_name }}</deviceName>
|
||||
<ebs>
|
||||
<volumeId>{{ instance.block_device_mapping['/dev/sda1'].volume_id }}</volumeId>
|
||||
<status>attached</status>
|
||||
<attachTime>2015-01-01T00:00:00.000Z</attachTime>
|
||||
<deleteOnTermination>true</deleteOnTermination>
|
||||
<volumeId>{{ deviceobject.volume_id }}</volumeId>
|
||||
<status>{{ deviceobject.status }}</status>
|
||||
<attachTime>{{ deviceobject.attach_time }}</attachTime>
|
||||
<deleteOnTermination>{{ deviceobject.delete_on_termination }}</deleteOnTermination>
|
||||
<size>{{deviceobject.size}}</size>
|
||||
</ebs>
|
||||
</item>
|
||||
{% endfor %}
|
||||
</blockDeviceMapping>
|
||||
<virtualizationType>{{ instance.virtualization_type }}</virtualizationType>
|
||||
<clientToken>ABCDE1234567890123</clientToken>
|
||||
|
|
@ -547,7 +550,7 @@ EC2_INSTANCE_STATUS = """<?xml version="1.0" encoding="UTF-8"?>
|
|||
{% for instance in instances %}
|
||||
<item>
|
||||
<instanceId>{{ instance.id }}</instanceId>
|
||||
<availabilityZone>us-east-1d</availabilityZone>
|
||||
<availabilityZone>{{ instance.placement }}</availabilityZone>
|
||||
<instanceState>
|
||||
<code>{{ instance.state_code }}</code>
|
||||
<name>{{ instance.state }}</name>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue