diff --git a/bootstrapvz/base/bootstrapinfo.py b/bootstrapvz/base/bootstrapinfo.py index 17474d7..3ec08ed 100644 --- a/bootstrapvz/base/bootstrapinfo.py +++ b/bootstrapvz/base/bootstrapinfo.py @@ -68,12 +68,24 @@ class BootstrapInformation(object): # Add a dictionary that can be accessed via info._pluginname for the provider and every plugin # Information specific to the module can be added to that 'namespace', this avoids clutter. providername = manifest.modules['provider'].__name__.split('.')[-1] - setattr(self, '_' + providername, DictClass()) + setattr(self, '_' + providername, {}) for plugin in manifest.modules['plugins']: pluginname = plugin.__name__.split('.')[-1] - setattr(self, '_' + pluginname, DictClass()) + setattr(self, '_' + pluginname, {}) def __create_manifest_vars(self, manifest, additional_vars={}): + class DictClass(dict): + """Tiny extension of dict to allow setting and getting keys via attributes + """ + def __getattr__(self, name): + return self[name] + + def __setattr__(self, name, value): + self[name] = value + + def __delattr__(self, name): + del self[name] + def set_manifest_vars(obj, data): """Runs through the manifest and creates DictClasses for every key @@ -109,16 +121,3 @@ class BootstrapInformation(object): # They are added last so that they may override previous variables set_manifest_vars(manifest_vars, additional_vars) return manifest_vars - - -class DictClass(dict): - """Tiny extension of dict to allow setting and getting keys via attributes - """ - def __getattr__(self, name): - return self[name] - - def __setattr__(self, name, value): - self[name] = value - - def __delattr__(self, name): - del self[name] diff --git a/bootstrapvz/plugins/minimize_size/tasks.py b/bootstrapvz/plugins/minimize_size/tasks.py index fe0da9c..ef7ff97 100644 --- a/bootstrapvz/plugins/minimize_size/tasks.py +++ b/bootstrapvz/plugins/minimize_size/tasks.py @@ -18,10 +18,10 @@ class AddFolderMounts(Task): @classmethod def run(cls, info): - info._minimize_size.foldermounts = os.path.join(info.workspace, 'minimize_size') - os.mkdir(info._minimize_size.foldermounts) + info._minimize_size['foldermounts'] = os.path.join(info.workspace, 'minimize_size') + os.mkdir(info._minimize_size['foldermounts']) for folder in folders: - temp_path = os.path.join(info._minimize_size.foldermounts, folder.replace('/', '_')) + temp_path = os.path.join(info._minimize_size['foldermounts'], folder.replace('/', '_')) os.mkdir(temp_path) full_path = os.path.join(info.root, folder) @@ -37,14 +37,14 @@ class RemoveFolderMounts(Task): def run(cls, info): import shutil for folder in folders: - temp_path = os.path.join(info._minimize_size.foldermounts, folder.replace('/', '_')) + temp_path = os.path.join(info._minimize_size['foldermounts'], folder.replace('/', '_')) full_path = os.path.join(info.root, folder) info.volume.partition_map.root.remove_mount(full_path) shutil.rmtree(temp_path) - os.rmdir(info._minimize_size.foldermounts) - del info._minimize_size.foldermounts + os.rmdir(info._minimize_size['foldermounts']) + del info._minimize_size['foldermounts'] class AddRequiredCommands(Task): diff --git a/bootstrapvz/plugins/prebootstrapped/tasks.py b/bootstrapvz/plugins/prebootstrapped/tasks.py index 41d79ae..55b3252 100644 --- a/bootstrapvz/plugins/prebootstrapped/tasks.py +++ b/bootstrapvz/plugins/prebootstrapped/tasks.py @@ -34,9 +34,9 @@ class CreateFromSnapshot(Task): @classmethod def run(cls, info): snapshot = info.manifest.plugins['prebootstrapped']['snapshot'] - ebs_volume = info._ec2.connection.create_volume(info.volume.size.get_qty_in('GiB'), - info._ec2.host['availabilityZone'], - snapshot=snapshot) + ebs_volume = info._ec2['connection'].create_volume(info.volume.size.get_qty_in('GiB'), + info._ec2['host']['availabilityZone'], + snapshot=snapshot) while ebs_volume.volume_state() != 'available': time.sleep(5) ebs_volume.update() diff --git a/bootstrapvz/plugins/vagrant/tasks.py b/bootstrapvz/plugins/vagrant/tasks.py index 742c98c..6ed57d8 100644 --- a/bootstrapvz/plugins/vagrant/tasks.py +++ b/bootstrapvz/plugins/vagrant/tasks.py @@ -21,8 +21,8 @@ class CheckBoxPath(Task): from bootstrapvz.common.exceptions import TaskError msg = 'The vagrant box `{name}\' already exists at `{path}\''.format(name=box_name, path=box_path) raise TaskError(msg) - info._vagrant.box_name = box_name - info._vagrant.box_path = box_path + info._vagrant['box_name'] = box_name + info._vagrant['box_path'] = box_path class CreateVagrantBoxDir(Task): @@ -32,8 +32,8 @@ class CreateVagrantBoxDir(Task): @classmethod def run(cls, info): - info._vagrant.folder = os.path.join(info.workspace, 'vagrant') - os.mkdir(info._vagrant.folder) + info._vagrant['folder'] = os.path.join(info.workspace, 'vagrant') + os.mkdir(info._vagrant['folder']) class AddPackages(Task): @@ -137,7 +137,7 @@ class PackageBox(Task): @classmethod def run(cls, info): vagrantfile_source = os.path.join(assets, 'Vagrantfile') - vagrantfile = os.path.join(info._vagrant.folder, 'Vagrantfile') + vagrantfile = os.path.join(info._vagrant['folder'], 'Vagrantfile') shutil.copy(vagrantfile_source, vagrantfile) import random @@ -146,26 +146,26 @@ class PackageBox(Task): sed_i(vagrantfile, '\\[MAC_ADDRESS\\]', mac_address) metadata_source = os.path.join(assets, 'metadata.json') - metadata = os.path.join(info._vagrant.folder, 'metadata.json') + metadata = os.path.join(info._vagrant['folder'], 'metadata.json') shutil.copy(metadata_source, metadata) from bootstrapvz.common.tools import log_check_call disk_name = 'box-disk1.{ext}'.format(ext=info.volume.extension) - disk_link = os.path.join(info._vagrant.folder, disk_name) + disk_link = os.path.join(info._vagrant['folder'], disk_name) log_check_call(['ln', '-s', info.volume.image_path, disk_link]) - ovf_path = os.path.join(info._vagrant.folder, 'box.ovf') + ovf_path = os.path.join(info._vagrant['folder'], 'box.ovf') cls.write_ovf(info, ovf_path, mac_address, disk_name) - box_files = os.listdir(info._vagrant.folder) + box_files = os.listdir(info._vagrant['folder']) log_check_call(['tar', '--create', '--gzip', '--dereference', - '--file', info._vagrant.box_path, - '--directory', info._vagrant.folder] + '--file', info._vagrant['box_path'], + '--directory', info._vagrant['folder']] + box_files ) import logging logging.getLogger(__name__).info('The vagrant box has been placed at {box_path}' - .format(box_path=info._vagrant.box_path)) + .format(box_path=info._vagrant['box_path'])) @classmethod def write_ovf(cls, info, destination, mac_address, disk_name): @@ -207,16 +207,16 @@ class PackageBox(Task): attr(disk, 'ovf:uuid', volume_uuid) [system] = root.findall('./ovf:VirtualSystem', namespaces) - attr(system, 'ovf:id', info._vagrant.box_name) + attr(system, 'ovf:id', info._vagrant['box_name']) [sysid] = system.findall('./ovf:VirtualHardwareSection/ovf:System/' 'vssd:VirtualSystemIdentifier', namespaces) - sysid.text = info._vagrant.box_name + sysid.text = info._vagrant['box_name'] [machine] = system.findall('./vbox:Machine', namespaces) import uuid attr(machine, 'ovf:uuid', uuid.uuid4()) - attr(machine, 'ovf:name', info._vagrant.box_name) + attr(machine, 'ovf:name', info._vagrant['box_name']) from datetime import datetime attr(machine, 'ovf:lastStateChange', datetime.now().strftime('%Y-%m-%dT%H:%M:%SZ')) [nic] = machine.findall('./ovf:Hardware/ovf:Network/ovf:Adapter', namespaces) @@ -237,5 +237,5 @@ class RemoveVagrantBoxDir(Task): @classmethod def run(cls, info): - shutil.rmtree(info._vagrant.folder) - del info._vagrant.folder + shutil.rmtree(info._vagrant['folder']) + del info._vagrant['folder'] diff --git a/bootstrapvz/providers/ec2/tasks/ami.py b/bootstrapvz/providers/ec2/tasks/ami.py index f5607c0..5994b21 100644 --- a/bootstrapvz/providers/ec2/tasks/ami.py +++ b/bootstrapvz/providers/ec2/tasks/ami.py @@ -21,13 +21,13 @@ class AMIName(Task): ami_name = info.manifest.image['name'].format(**info.manifest_vars) ami_description = info.manifest.image['description'].format(**info.manifest_vars) - images = info._ec2.connection.get_all_images() + images = info._ec2['connection'].get_all_images() for image in images: if ami_name == image.name: msg = 'An image by the name {ami_name} already exists.'.format(ami_name=ami_name) raise TaskError(msg) - info._ec2.ami_name = ami_name - info._ec2.ami_description = ami_description + info._ec2['ami_name'] = ami_name + info._ec2['ami_description'] = ami_description class BundleImage(Task): @@ -37,7 +37,7 @@ class BundleImage(Task): @classmethod def run(cls, info): bundle_name = 'bundle-{id}'.format(id=info.run_id) - info._ec2.bundle_path = os.path.join(info.workspace, bundle_name) + info._ec2['bundle_path'] = os.path.join(info.workspace, bundle_name) arch = {'i386': 'i386', 'amd64': 'x86_64'}.get(info.manifest.system['architecture']) log_check_call(['euca-bundle-image', '--image', info.volume.image_path, @@ -46,8 +46,8 @@ class BundleImage(Task): '--privatekey', info.credentials['private-key'], '--cert', info.credentials['certificate'], '--ec2cert', cert_ec2, - '--destination', info._ec2.bundle_path, - '--prefix', info._ec2.ami_name]) + '--destination', info._ec2['bundle_path'], + '--prefix', info._ec2['ami_name']]) class UploadImage(Task): @@ -57,21 +57,21 @@ class UploadImage(Task): @classmethod def run(cls, info): - manifest_file = os.path.join(info._ec2.bundle_path, info._ec2.ami_name + '.manifest.xml') - if info._ec2.host['region'] == 'us-east-1': + manifest_file = os.path.join(info._ec2['bundle_path'], info._ec2['ami_name'] + '.manifest.xml') + if info._ec2['host']['region'] == 'us-east-1': s3_url = 'https://s3.amazonaws.com/' - elif info._ec2.host['region'] == 'cn-north-1': + elif info._ec2['host']['region'] == 'cn-north-1': s3_url = 'https://s3.cn-north-1.amazonaws.com.cn' else: - s3_url = 'https://s3-{region}.amazonaws.com/'.format(region=info._ec2.host['region']) - info._ec2.manifest_location = info.manifest.image['bucket'] + '/' + info._ec2.ami_name + '.manifest.xml' + s3_url = 'https://s3-{region}.amazonaws.com/'.format(region=info._ec2['host']['region']) + info._ec2['manifest_location'] = info.manifest.image['bucket'] + '/' + info._ec2['ami_name'] + '.manifest.xml' log_check_call(['euca-upload-bundle', '--bucket', info.manifest.image['bucket'], '--manifest', manifest_file, '--access-key', info.credentials['access-key'], '--secret-key', info.credentials['secret-key'], '--url', s3_url, - '--region', info._ec2.host['region'], + '--region', info._ec2['host']['region'], '--ec2cert', cert_ec2]) @@ -83,8 +83,8 @@ class RemoveBundle(Task): @classmethod def run(cls, info): from shutil import rmtree - rmtree(info._ec2.bundle_path) - del info._ec2.bundle_path + rmtree(info._ec2['bundle_path']) + del info._ec2['bundle_path'] class RegisterAMI(Task): @@ -94,13 +94,13 @@ class RegisterAMI(Task): @classmethod def run(cls, info): - registration_params = {'name': info._ec2.ami_name, - 'description': info._ec2.ami_description} + registration_params = {'name': info._ec2['ami_name'], + 'description': info._ec2['ami_description']} registration_params['architecture'] = {'i386': 'i386', 'amd64': 'x86_64'}.get(info.manifest.system['architecture']) if info.manifest.volume['backing'] == 's3': - registration_params['image_location'] = info._ec2.manifest_location + registration_params['image_location'] = info._ec2['manifest_location'] else: root_dev_name = {'pvm': '/dev/sda', 'hvm': '/dev/xvda'}.get(info.manifest.data['virtualization']) @@ -108,7 +108,7 @@ class RegisterAMI(Task): from boto.ec2.blockdevicemapping import BlockDeviceType from boto.ec2.blockdevicemapping import BlockDeviceMapping - block_device = BlockDeviceType(snapshot_id=info._ec2.snapshot.id, delete_on_termination=True, + block_device = BlockDeviceType(snapshot_id=info._ec2['snapshot'].id, delete_on_termination=True, size=info.volume.size.get_qty_in('GiB')) registration_params['block_device_map'] = BlockDeviceMapping() registration_params['block_device_map'][root_dev_name] = block_device @@ -119,7 +119,7 @@ class RegisterAMI(Task): registration_params['virtualization_type'] = 'paravirtual' akis_path = os.path.join(os.path.dirname(__file__), 'ami-akis.json') from bootstrapvz.common.tools import config_get - registration_params['kernel_id'] = config_get(akis_path, [info._ec2.host['region'], + registration_params['kernel_id'] = config_get(akis_path, [info._ec2['host']['region'], info.manifest.system['architecture']]) - info._ec2.image = info._ec2.connection.register_image(**registration_params) + info._ec2['image'] = info._ec2['connection'].register_image(**registration_params) diff --git a/bootstrapvz/providers/ec2/tasks/connection.py b/bootstrapvz/providers/ec2/tasks/connection.py index e470b51..f17c7a4 100644 --- a/bootstrapvz/providers/ec2/tasks/connection.py +++ b/bootstrapvz/providers/ec2/tasks/connection.py @@ -41,6 +41,6 @@ class Connect(Task): @classmethod def run(cls, info): from boto.ec2 import connect_to_region - info._ec2.connection = connect_to_region(info._ec2.host['region'], - aws_access_key_id=info.credentials['access-key'], - aws_secret_access_key=info.credentials['secret-key']) + info._ec2['connection'] = connect_to_region(info._ec2['host']['region'], + aws_access_key_id=info.credentials['access-key'], + aws_secret_access_key=info.credentials['secret-key']) diff --git a/bootstrapvz/providers/ec2/tasks/ebs.py b/bootstrapvz/providers/ec2/tasks/ebs.py index 680cae0..ff627d5 100644 --- a/bootstrapvz/providers/ec2/tasks/ebs.py +++ b/bootstrapvz/providers/ec2/tasks/ebs.py @@ -8,7 +8,7 @@ class Create(Task): @classmethod def run(cls, info): - info.volume.create(info._ec2.connection, info._ec2.host['availabilityZone']) + info.volume.create(info._ec2['connection'], info._ec2['host']['availabilityZone']) class Attach(Task): @@ -18,7 +18,7 @@ class Attach(Task): @classmethod def run(cls, info): - info.volume.attach(info._ec2.host['instanceId']) + info.volume.attach(info._ec2['host']['instanceId']) class Snapshot(Task): @@ -27,4 +27,4 @@ class Snapshot(Task): @classmethod def run(cls, info): - info._ec2.snapshot = info.volume.snapshot() + info._ec2['snapshot'] = info.volume.snapshot() diff --git a/bootstrapvz/providers/ec2/tasks/host.py b/bootstrapvz/providers/ec2/tasks/host.py index 1fe8662..0f8d414 100644 --- a/bootstrapvz/providers/ec2/tasks/host.py +++ b/bootstrapvz/providers/ec2/tasks/host.py @@ -25,4 +25,4 @@ class GetInfo(Task): import json metadata_url = 'http://169.254.169.254/latest/dynamic/instance-identity/document' response = urllib2.urlopen(url=metadata_url, timeout=5) - info._ec2.host = json.load(response) + info._ec2['host'] = json.load(response)