mirror of
https://github.com/kevingruesser/bootstrap-vz.git
synced 2025-10-10 17:19:51 +00:00
Porting EC2 provider to boto3
This commit is contained in:
parent
b27658652d
commit
89eedae5fc
4 changed files with 65 additions and 43 deletions
|
@ -1,6 +1,5 @@
|
||||||
from bootstrapvz.base.fs.volume import Volume
|
from bootstrapvz.base.fs.volume import Volume
|
||||||
from bootstrapvz.base.fs.exceptions import VolumeError
|
from bootstrapvz.base.fs.exceptions import VolumeError
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
class EBSVolume(Volume):
|
class EBSVolume(Volume):
|
||||||
|
@ -9,21 +8,25 @@ class EBSVolume(Volume):
|
||||||
self.fsm.create(connection=conn, zone=zone)
|
self.fsm.create(connection=conn, zone=zone)
|
||||||
|
|
||||||
def _before_create(self, e):
|
def _before_create(self, e):
|
||||||
conn = e.connection
|
self.conn = e.connection
|
||||||
zone = e.zone
|
zone = e.zone
|
||||||
size = self.size.bytes.get_qty_in('GiB')
|
size = self.size.bytes.get_qty_in('GiB')
|
||||||
self.volume = conn.create_volume(size, zone, volume_type='gp2')
|
self.volume = self.conn.create_volume(Size=size,
|
||||||
while self.volume.volume_state() != 'available':
|
AvailabilityZone=zone,
|
||||||
time.sleep(5)
|
VolumeType='gp2')
|
||||||
self.volume.update()
|
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):
|
def attach(self, instance_id):
|
||||||
self.fsm.attach(instance_id=instance_id)
|
self.fsm.attach(instance_id=instance_id)
|
||||||
|
|
||||||
def _before_attach(self, e):
|
def _before_attach(self, e):
|
||||||
instance_id = e.instance_id
|
|
||||||
import os.path
|
import os.path
|
||||||
import string
|
import string
|
||||||
|
|
||||||
|
self.instance_id = e.instance_id
|
||||||
for letter in string.ascii_lowercase[5:]:
|
for letter in string.ascii_lowercase[5:]:
|
||||||
dev_path = os.path.join('/dev', 'xvd' + letter)
|
dev_path = os.path.join('/dev', 'xvd' + letter)
|
||||||
if not os.path.exists(dev_path):
|
if not os.path.exists(dev_path):
|
||||||
|
@ -34,25 +37,30 @@ class EBSVolume(Volume):
|
||||||
if self.device_path is None:
|
if self.device_path is None:
|
||||||
raise VolumeError('Unable to find a free block device path for mounting the bootstrap volume')
|
raise VolumeError('Unable to find a free block device path for mounting the bootstrap volume')
|
||||||
|
|
||||||
self.volume.attach(instance_id, self.ec2_device_path)
|
self.conn.attach_volume(VolumeId=self.vol_id,
|
||||||
while self.volume.attachment_state() != 'attached':
|
InstanceId=self.instance_id,
|
||||||
time.sleep(2)
|
Device=self.ec2_device_path)
|
||||||
self.volume.update()
|
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):
|
def _before_detach(self, e):
|
||||||
self.volume.detach()
|
self.conn.detach_volume(VolumeId=self.vol_id,
|
||||||
while self.volume.attachment_state() is not None:
|
InstanceId=self.instance_id,
|
||||||
time.sleep(2)
|
Device=self.ec2_device_path)
|
||||||
self.volume.update()
|
waiter = self.conn.get_waiter('volume_available')
|
||||||
|
waiter.wait(VolumeIds=[self.vol_id],
|
||||||
|
Filters=[{'Name': 'status', 'Values': ['available']}])
|
||||||
del self.ec2_device_path
|
del self.ec2_device_path
|
||||||
self.device_path = None
|
self.device_path = None
|
||||||
|
|
||||||
def _before_delete(self, e):
|
def _before_delete(self, e):
|
||||||
self.volume.delete()
|
self.conn.delete_volume(VolumeId=self.vol_id)
|
||||||
|
|
||||||
def snapshot(self):
|
def snapshot(self):
|
||||||
snapshot = self.volume.create_snapshot()
|
snapshot = self.conn.create_snapshot(VolumeId=self.vol_id)
|
||||||
while snapshot.status != 'completed':
|
self.snap_id = snapshot['SnapshotId']
|
||||||
time.sleep(2)
|
waiter = self.conn.get_waiter('snapshot_completed')
|
||||||
snapshot.update()
|
waiter.wait(SnapshotIds=[self.snap_id],
|
||||||
return snapshot
|
Filters=[{'Name': 'status', 'Values': ['completed']}])
|
||||||
|
return self.snap_id
|
||||||
|
|
|
@ -21,9 +21,9 @@ class AMIName(Task):
|
||||||
ami_name = info.manifest.name.format(**info.manifest_vars)
|
ami_name = info.manifest.name.format(**info.manifest_vars)
|
||||||
ami_description = info.manifest.provider['description'].format(**info.manifest_vars)
|
ami_description = info.manifest.provider['description'].format(**info.manifest_vars)
|
||||||
|
|
||||||
images = info._ec2['connection'].get_all_images(owners=['self'])
|
images = info._ec2['connection'].describe_images(Owners=['self'])['Images']
|
||||||
for image in images:
|
for image in images:
|
||||||
if ami_name == image.name:
|
if ami_name == image['Name']:
|
||||||
msg = 'An image by the name {ami_name} already exists.'.format(ami_name=ami_name)
|
msg = 'An image by the name {ami_name} already exists.'.format(ami_name=ami_name)
|
||||||
raise TaskError(msg)
|
raise TaskError(msg)
|
||||||
info._ec2['ami_name'] = ami_name
|
info._ec2['ami_name'] = ami_name
|
||||||
|
@ -93,41 +93,45 @@ class RegisterAMI(Task):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, info):
|
def run(cls, info):
|
||||||
registration_params = {'name': info._ec2['ami_name'],
|
registration_params = {'Name': info._ec2['ami_name'],
|
||||||
'description': info._ec2['ami_description']}
|
'Description': info._ec2['ami_description']}
|
||||||
registration_params['architecture'] = {'i386': 'i386',
|
registration_params['Architecture'] = {'i386': 'i386',
|
||||||
'amd64': 'x86_64'}.get(info.manifest.system['architecture'])
|
'amd64': 'x86_64'}.get(info.manifest.system['architecture'])
|
||||||
|
|
||||||
if info.manifest.volume['backing'] == 's3':
|
if info.manifest.volume['backing'] == 's3':
|
||||||
registration_params['image_location'] = info._ec2['manifest_location']
|
registration_params['ImageLocation'] = info._ec2['manifest_location']
|
||||||
else:
|
else:
|
||||||
root_dev_name = {'pvm': '/dev/sda',
|
root_dev_name = {'pvm': '/dev/sda',
|
||||||
'hvm': '/dev/xvda'}.get(info.manifest.provider['virtualization'])
|
'hvm': '/dev/xvda'}.get(info.manifest.provider['virtualization'])
|
||||||
registration_params['root_device_name'] = root_dev_name
|
registration_params['RootDeviceName'] = root_dev_name
|
||||||
|
|
||||||
from boto.ec2.blockdevicemapping import BlockDeviceType
|
block_device = [{'DeviceName': root_dev_name,
|
||||||
from boto.ec2.blockdevicemapping import BlockDeviceMapping
|
'Ebs': {
|
||||||
block_device = BlockDeviceType(snapshot_id=info._ec2['snapshot'].id, delete_on_termination=True,
|
'SnapshotId': info._ec2['snapshot'],
|
||||||
size=info.volume.size.bytes.get_qty_in('GiB'), volume_type='gp2')
|
'VolumeSize': info.volume.size.bytes.get_qty_in('GiB'),
|
||||||
registration_params['block_device_map'] = BlockDeviceMapping()
|
'VolumeType': 'gp2',
|
||||||
registration_params['block_device_map'][root_dev_name] = block_device
|
'DeleteOnTermination': True}}]
|
||||||
|
registration_params['BlockDeviceMappings'] = block_device
|
||||||
|
|
||||||
if info.manifest.provider['virtualization'] == 'hvm':
|
if info.manifest.provider['virtualization'] == 'hvm':
|
||||||
registration_params['virtualization_type'] = 'hvm'
|
registration_params['VirtualizationType'] = 'hvm'
|
||||||
else:
|
else:
|
||||||
registration_params['virtualization_type'] = 'paravirtual'
|
registration_params['VirtualizationType'] = 'paravirtual'
|
||||||
akis_path = rel_path(__file__, 'ami-akis.yml')
|
akis_path = rel_path(__file__, 'ami-akis.yml')
|
||||||
from bootstrapvz.common.tools import config_get
|
from bootstrapvz.common.tools import config_get
|
||||||
registration_params['kernel_id'] = config_get(akis_path, [info._ec2['region'],
|
registration_params['kernel_id'] = config_get(akis_path,
|
||||||
info.manifest.system['architecture']])
|
[info._ec2['region'],
|
||||||
|
info.manifest.system['architecture']])
|
||||||
|
|
||||||
if info.manifest.provider.get('enhanced_networking', None) == 'simple':
|
if info.manifest.provider.get('enhanced_networking', None) == 'simple':
|
||||||
registration_params['sriov_net_support'] = 'simple'
|
registration_params['SriovNetSupport'] = 'simple'
|
||||||
|
|
||||||
info._ec2['image'] = info._ec2['connection'].register_image(**registration_params)
|
info._ec2['image'] = info._ec2['connection'].register_image(**registration_params)
|
||||||
|
|
||||||
# Setting up tags on the AMI
|
# Setting up tags on the AMI
|
||||||
if 'tags' in info.manifest.data:
|
if 'tags' in info.manifest.data:
|
||||||
raw_tags = info.manifest.data['tags']
|
raw_tags = info.manifest.data['tags']
|
||||||
tags = {k: v.format(**info.manifest_vars) for k, v in raw_tags.items()}
|
formatted_tags = {k: v.format(**info.manifest_vars) for k, v in raw_tags.items()}
|
||||||
info._ec2['connection'].create_tags(info._ec2['image'], tags)
|
tags = [{'Key': k, 'Value': v} for k, v in formatted_tags.items()]
|
||||||
|
info._ec2['connection'].create_tags(Resources=[info._ec2['image']['ImageId']],
|
||||||
|
Tags=tags)
|
||||||
|
|
|
@ -64,7 +64,7 @@ class Connect(Task):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, info):
|
def run(cls, info):
|
||||||
from boto.ec2 import connect_to_region
|
import boto3
|
||||||
connect_args = {
|
connect_args = {
|
||||||
'aws_access_key_id': info.credentials['access-key'],
|
'aws_access_key_id': info.credentials['access-key'],
|
||||||
'aws_secret_access_key': info.credentials['secret-key']
|
'aws_secret_access_key': info.credentials['secret-key']
|
||||||
|
@ -73,4 +73,7 @@ class Connect(Task):
|
||||||
if 'security-token' in info.credentials:
|
if 'security-token' in info.credentials:
|
||||||
connect_args['security_token'] = info.credentials['security-token']
|
connect_args['security_token'] = info.credentials['security-token']
|
||||||
|
|
||||||
info._ec2['connection'] = connect_to_region(info._ec2['region'], **connect_args)
|
info._ec2['connection'] = boto3.Session(info._ec2['region'],
|
||||||
|
info.credentials['access-key'],
|
||||||
|
info.credentials['secret-key'])
|
||||||
|
info._ec2['connection'] = boto3.client('ec2', region_name=info._ec2['region'])
|
||||||
|
|
|
@ -28,3 +28,10 @@ class Snapshot(Task):
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, info):
|
def run(cls, info):
|
||||||
info._ec2['snapshot'] = info.volume.snapshot()
|
info._ec2['snapshot'] = info.volume.snapshot()
|
||||||
|
|
||||||
|
# # Setting up tags on the snapshot
|
||||||
|
# if 'tags' in info.manifest.data:
|
||||||
|
# raw_tags = info.manifest.data['tags']
|
||||||
|
# tags = {k: v.format(**info.manifest_vars) for k, v in raw_tags.items()}
|
||||||
|
# info._ec2['connection'](Resources=[info._ec2['snapshot']],
|
||||||
|
# Tags=[tags])
|
||||||
|
|
Loading…
Add table
Reference in a new issue