Don't instantiate tasks

In practice they are just typed functions with attributes, having a reference to an object is just confusing.
So: Task.run() is now a classmethod
This commit is contained in:
Anders Ingemann 2014-01-05 15:57:11 +01:00
parent 039a35a344
commit 0092e1c2c2
39 changed files with 237 additions and 123 deletions

View file

@ -5,8 +5,13 @@ class Task(object):
predecessors = []
successors = []
def __str__(self):
return '{module}.{task}'.format(module=self.__module__, task=self.__class__.__name__)
class __metaclass__(type):
def __repr__(cls):
return '{module}.{task}'.format(module=cls.__module__, task=cls.__name__)
def __repr__(self):
return self.__str__()
def __str__(cls):
return repr(cls)
@classmethod
def run(cls, info):
pass

View file

@ -18,17 +18,16 @@ class TaskList(object):
def run(self, info={}, dry_run=False):
task_list = self.create_list()
log.debug('Tasklist:\n\t{list}'.format(list='\n\t'.join(repr(task) for task in task_list)))
log.debug('Tasklist:\n\t{list}'.format(list='\n\t'.join(map(repr, task_list))))
for task_type in task_list:
task = task_type()
for task in task_list:
if hasattr(task, 'description'):
log.info(task.description)
else:
log.info('Running {task}'.format(task=task))
if not dry_run:
task.run(info)
self.tasks_completed.append(task_type)
self.tasks_completed.append(task)
def create_list(self):
from common.phases import order
@ -47,7 +46,7 @@ class TaskList(object):
for component in components:
if len(component) > 1:
cycles_found += 1
log.debug('Cycle: {list}\n'.format(list=', '.join(repr(task) for task in component)))
log.debug('Cycle: {list}\n'.format(list=', '.join(map(repr, component))))
if cycles_found > 0:
msg = ('{0} cycles were found in the tasklist, '
'consult the logfile for more information.'.format(cycles_found))

View file

@ -9,7 +9,8 @@ class AddDefaultSources(Task):
description = 'Adding default release sources'
phase = phases.preparation
def run(self, info):
@classmethod
def run(cls, info):
if info.source_lists.target_exists('{system.release}'):
import logging
msg = ('{system.release} target already exists').format(**info.manifest_vars)
@ -25,7 +26,8 @@ class WriteSources(Task):
description = 'Writing aptitude sources to disk'
phase = phases.package_installation
def run(self, info):
@classmethod
def run(cls, info):
for name, sources in info.source_lists.sources.iteritems():
if name == 'main':
list_path = os.path.join(info.root, 'etc/apt/sources.list')
@ -40,7 +42,8 @@ class DisableDaemonAutostart(Task):
description = 'Disabling daemon autostart'
phase = phases.package_installation
def run(self, info):
@classmethod
def run(cls, info):
rc_policy_path = os.path.join(info.root, 'usr/sbin/policy-rc.d')
with open(rc_policy_path, 'w') as rc_policy:
rc_policy.write(('#!/bin/sh\n'
@ -57,7 +60,8 @@ class AptUpdate(Task):
phase = phases.package_installation
predecessors = [locale.GenerateLocale, WriteSources]
def run(self, info):
@classmethod
def run(cls, info):
log_check_call(['/usr/sbin/chroot', info.root,
'/usr/bin/apt-get', 'update'])
@ -67,7 +71,8 @@ class AptUpgrade(Task):
phase = phases.package_installation
predecessors = [AptUpdate, DisableDaemonAutostart]
def run(self, info):
@classmethod
def run(cls, info):
from subprocess import CalledProcessError
try:
log_check_call(['/usr/sbin/chroot', info.root,
@ -93,7 +98,8 @@ class PurgeUnusedPackages(Task):
description = 'Removing unused packages'
phase = phases.system_cleaning
def run(self, info):
@classmethod
def run(cls, info):
log_check_call(['/usr/sbin/chroot', info.root,
'/usr/bin/apt-get', 'autoremove',
'--purge'])
@ -103,7 +109,8 @@ class AptClean(Task):
description = 'Clearing the aptitude cache'
phase = phases.system_cleaning
def run(self, info):
@classmethod
def run(cls, info):
log_check_call(['/usr/sbin/chroot', info.root,
'/usr/bin/apt-get', 'clean'])
@ -117,5 +124,6 @@ class EnableDaemonAutostart(Task):
description = 'Re-enabling daemon autostart after installation'
phase = phases.system_cleaning
def run(self, info):
@classmethod
def run(cls, info):
os.remove(os.path.join(info.root, 'usr/sbin/policy-rc.d'))

View file

@ -8,7 +8,8 @@ class BlackListModules(Task):
description = 'Blacklisting kernel modules'
phase = phases.system_modification
def run(self, info):
@classmethod
def run(cls, info):
blacklist_path = os.path.join(info.root, 'etc/modprobe.d/blacklist.conf')
with open(blacklist_path, 'a') as blacklist:
blacklist.write(('# disable pc speaker\n'
@ -19,7 +20,8 @@ class DisableGetTTYs(Task):
description = 'Disabling getty processes'
phase = phases.system_modification
def run(self, info):
@classmethod
def run(cls, info):
from common.tools import sed_i
inittab_path = os.path.join(info.root, 'etc/inittab')
tty1 = '1:2345:respawn:/sbin/getty 38400 tty1'
@ -35,7 +37,8 @@ class AddGrubPackage(Task):
phase = phases.preparation
predecessors = [apt.AddDefaultSources]
def run(self, info):
@classmethod
def run(cls, info):
info.packages.add('grub-pc')
@ -44,7 +47,8 @@ class InstallGrub(Task):
phase = phases.system_modification
predecessors = [apt.AptUpgrade]
def run(self, info):
@classmethod
def run(cls, info):
from common.fs.loopbackvolume import LoopbackVolume
from common.tools import log_check_call
@ -107,7 +111,8 @@ class AddExtlinuxPackage(Task):
phase = phases.preparation
predecessors = [apt.AddDefaultSources]
def run(self, info):
@classmethod
def run(cls, info):
info.packages.add('extlinux')
@ -116,7 +121,8 @@ class InstallExtLinux(Task):
phase = phases.system_modification
predecessors = [apt.AptUpgrade]
def run(self, info):
@classmethod
def run(cls, info):
from common.tools import log_check_call
log_check_call(['/usr/sbin/chroot', info.root,
'/usr/bin/extlinux',

View file

@ -21,7 +21,8 @@ class MakeTarball(Task):
description = 'Creating bootstrap tarball'
phase = phases.os_installation
def run(self, info):
@classmethod
def run(cls, info):
from hashlib import sha1
import os.path
executable, options, arguments = get_bootstrap_args(info)
@ -45,7 +46,8 @@ class Bootstrap(Task):
phase = phases.os_installation
predecessors = [MakeTarball]
def run(self, info):
@classmethod
def run(cls, info):
executable, options, arguments = get_bootstrap_args(info)
if hasattr(info, 'tarball'):
options.extend(['--unpack-tarball=' + info.tarball])

View file

@ -8,7 +8,8 @@ class ClearMOTD(Task):
description = 'Clearing the MOTD'
phase = phases.system_cleaning
def run(self, info):
@classmethod
def run(cls, info):
with open('/var/run/motd', 'w'):
pass
@ -17,7 +18,8 @@ class ShredHostkeys(Task):
description = 'Securely deleting ssh hostkeys'
phase = phases.system_cleaning
def run(self, info):
@classmethod
def run(cls, info):
ssh_hostkeys = ['ssh_host_dsa_key',
'ssh_host_rsa_key']
if info.manifest.system['release'] != 'squeeze':
@ -34,7 +36,8 @@ class CleanTMP(Task):
description = 'Removing temporary files'
phase = phases.system_cleaning
def run(self, info):
@classmethod
def run(cls, info):
tmp = os.path.join(info.root, 'tmp')
for tmp_file in [os.path.join(tmp, f) for f in os.listdir(tmp)]:
if os.path.isfile(tmp_file):

View file

@ -7,6 +7,7 @@ class TriggerRollback(Task):
description = 'Triggering a rollback by throwing an exception'
def run(self, info):
@classmethod
def run(cls, info):
from common.exceptions import TaskError
raise TaskError('Trigger rollback')

View file

@ -10,7 +10,8 @@ class Format(Task):
description = 'Formatting the volume'
phase = phases.volume_preparation
def run(self, info):
@classmethod
def run(cls, info):
for partition in info.volume.partition_map.partitions:
partition.format()
@ -20,7 +21,8 @@ class TuneVolumeFS(Task):
phase = phases.volume_preparation
predecessors = [Format]
def run(self, info):
@classmethod
def run(cls, info):
import re
# Disable the time based filesystem check
for partition in info.volume.partition_map.partitions:
@ -33,7 +35,8 @@ class AddXFSProgs(Task):
phase = phases.preparation
predecessors = [apt.AddDefaultSources]
def run(self, info):
@classmethod
def run(cls, info):
info.packages.add('xfsprogs')
@ -41,7 +44,8 @@ class CreateMountDir(Task):
description = 'Creating mountpoint for the root partition'
phase = phases.volume_mounting
def run(self, info):
@classmethod
def run(cls, info):
import os
info.root = os.path.join(info.workspace, 'root')
os.makedirs(info.root)
@ -52,7 +56,8 @@ class MountRoot(Task):
phase = phases.volume_mounting
predecessors = [CreateMountDir]
def run(self, info):
@classmethod
def run(cls, info):
info.volume.partition_map.root.mount(info.root)
@ -61,7 +66,8 @@ class CreateBootMountDir(Task):
phase = phases.volume_mounting
predecessors = [MountRoot]
def run(self, info):
@classmethod
def run(cls, info):
import os.path
os.makedirs(os.path.join(info.root, 'boot'))
@ -71,7 +77,8 @@ class MountBoot(Task):
phase = phases.volume_mounting
predecessors = [CreateBootMountDir]
def run(self, info):
@classmethod
def run(cls, info):
p_map = info.volume.partition_map
p_map.root.add_mount(p_map.boot, 'boot')
@ -81,7 +88,8 @@ class MountSpecials(Task):
phase = phases.os_installation
predecessors = [Bootstrap]
def run(self, info):
@classmethod
def run(cls, info):
root = info.volume.partition_map.root
root.add_mount('/dev', 'dev', ['--bind'])
root.add_mount('none', 'proc', ['--types', 'proc'])
@ -94,7 +102,8 @@ class UnmountRoot(Task):
phase = phases.volume_unmounting
successors = [volume.Detach]
def run(self, info):
@classmethod
def run(cls, info):
info.volume.partition_map.root.unmount()
@ -103,7 +112,8 @@ class DeleteMountDir(Task):
phase = phases.volume_unmounting
predecessors = [UnmountRoot]
def run(self, info):
@classmethod
def run(cls, info):
import os
os.rmdir(info.root)
del info.root
@ -113,7 +123,8 @@ class FStab(Task):
description = 'Adding partitions to the fstab'
phase = phases.system_modification
def run(self, info):
@classmethod
def run(cls, info):
import os.path
p_map = info.volume.partition_map
mount_points = [{'path': '/',

View file

@ -7,7 +7,8 @@ class HostDependencies(Task):
description = 'Determining required host dependencies'
phase = phases.preparation
def run(self, info):
@classmethod
def run(cls, info):
info.host_dependencies.add('debootstrap')
from common.fs.loopbackvolume import LoopbackVolume
@ -27,7 +28,8 @@ class CheckHostDependencies(Task):
phase = phases.preparation
predecessors = [HostDependencies]
def run(self, info):
@classmethod
def run(cls, info):
from common.tools import log_check_call
from subprocess import CalledProcessError
for package in info.host_dependencies:

View file

@ -10,7 +10,8 @@ class InstallInitScripts(Task):
description = 'Installing startup scripts'
phase = phases.system_modification
def run(self, info):
@classmethod
def run(cls, info):
import stat
rwxr_xr_x = (stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR |
stat.S_IRGRP | stat.S_IXGRP |
@ -31,7 +32,8 @@ class AddExpandRoot(Task):
phase = phases.system_modification
successors = [InstallInitScripts]
def run(self, info):
@classmethod
def run(cls, info):
init_scripts_dir = os.path.join(assets, 'init.d')
info.initd['install']['expand-root'] = os.path.join(init_scripts_dir, 'expand-root')
@ -41,7 +43,8 @@ class AddSSHKeyGeneration(Task):
phase = phases.system_modification
successors = [InstallInitScripts]
def run(self, info):
@classmethod
def run(cls, info):
init_scripts_dir = os.path.join(assets, 'init.d')
install = info.initd['install']
from subprocess import CalledProcessError
@ -63,7 +66,8 @@ class RemoveHWClock(Task):
phase = phases.system_modification
successors = [InstallInitScripts]
def run(self, info):
@classmethod
def run(cls, info):
info.initd['disable'].append('hwclock.sh')
if info.manifest.system['release'] == 'squeeze':
info.initd['disable'].append('hwclockfirst.sh')
@ -74,7 +78,8 @@ class AdjustExpandRootScript(Task):
phase = phases.system_modification
predecessors = [InstallInitScripts]
def run(self, info):
@classmethod
def run(cls, info):
if 'expand-root' not in info.initd['install']:
raise TaskError('The expand-root script was not installed')

View file

@ -7,7 +7,8 @@ class LocaleBootstrapPackage(Task):
description = 'Adding locale package to bootstrap installation'
phase = phases.preparation
def run(self, info):
@classmethod
def run(cls, info):
# We could bootstrap without locales, but things just suck without them
# eg. error messages when running apt
info.include_packages.add('locales')
@ -17,7 +18,8 @@ class GenerateLocale(Task):
description = 'Generating the selected locale'
phase = phases.package_installation
def run(self, info):
@classmethod
def run(cls, info):
from common.tools import sed_i
from common.tools import log_check_call
locale_gen = os.path.join(info.root, 'etc/locale.gen')
@ -38,7 +40,8 @@ class SetTimezone(Task):
description = 'Setting the selected timezone'
phase = phases.system_modification
def run(self, info):
@classmethod
def run(cls, info):
from shutil import copy
tz_path = os.path.join(info.root, 'etc/timezone')
timezone = info.manifest.system['timezone']

View file

@ -8,7 +8,8 @@ class Create(Task):
phase = phases.volume_creation
successors = [volume.Attach]
def run(self, info):
@classmethod
def run(cls, info):
import os.path
image_path = os.path.join(info.workspace, 'volume.{ext}'.format(ext=info.volume.extension))
info.volume.create(image_path)
@ -18,7 +19,8 @@ class MoveImage(Task):
description = 'Moving volume image'
phase = phases.image_registration
def run(self, info):
@classmethod
def run(cls, info):
image_name = info.manifest.image['name'].format(**info.manifest_vars)
filename = '{image_name}.{ext}'.format(image_name=image_name, ext=info.volume.extension)

View file

@ -7,7 +7,8 @@ class RemoveDNSInfo(Task):
description = 'Removing resolv.conf'
phase = phases.system_modification
def run(self, info):
@classmethod
def run(cls, info):
from os import remove
remove(os.path.join(info.root, 'etc/resolv.conf'))
@ -16,7 +17,8 @@ class RemoveHostname(Task):
description = 'Removing the hostname file'
phase = phases.system_modification
def run(self, info):
@classmethod
def run(cls, info):
from os import remove
remove(os.path.join(info.root, 'etc/hostname'))
@ -25,7 +27,8 @@ class ConfigureNetworkIF(Task):
description = 'Configuring network interfaces'
phase = phases.system_modification
def run(self, info):
@classmethod
def run(cls, info):
interfaces_path = os.path.join(info.root, 'etc/network/interfaces')
if_config = {'squeeze': ('auto lo\n'
'iface lo inet loopback\n'

View file

@ -8,7 +8,8 @@ class InstallRemotePackages(Task):
phase = phases.package_installation
predecessors = [apt.AptUpgrade]
def run(self, info):
@classmethod
def run(cls, info):
if len(info.packages.remote) == 0:
return
import os
@ -59,7 +60,8 @@ class InstallLocalPackages(Task):
predecessors = [apt.AptUpgrade]
successors = [InstallRemotePackages]
def run(self, info):
@classmethod
def run(cls, info):
if len(info.packages.local) == 0:
return
from shutil import copy

View file

@ -8,7 +8,8 @@ class PartitionVolume(Task):
description = 'Partitioning the volume'
phase = phases.volume_preparation
def run(self, info):
@classmethod
def run(cls, info):
info.volume.partition_map.create(info.volume)
@ -18,7 +19,8 @@ class MapPartitions(Task):
predecessors = [PartitionVolume]
successors = [filesystem.Format]
def run(self, info):
@classmethod
def run(cls, info):
info.volume.partition_map.map(info.volume)
@ -28,5 +30,6 @@ class UnmapPartitions(Task):
predecessors = [filesystem.UnmountRoot]
successors = [volume.Detach]
def run(self, info):
@classmethod
def run(cls, info):
info.volume.partition_map.unmap(info.volume)

View file

@ -7,7 +7,8 @@ class EnableShadowConfig(Task):
description = 'Enabling shadowconfig'
phase = phases.system_modification
def run(self, info):
@classmethod
def run(cls, info):
from common.tools import log_check_call
log_check_call(['/usr/sbin/chroot', info.root, '/sbin/shadowconfig', 'on'])
@ -16,7 +17,8 @@ class DisableSSHPasswordAuthentication(Task):
description = 'Disabling SSH password authentication'
phase = phases.system_modification
def run(self, info):
@classmethod
def run(cls, info):
from common.tools import sed_i
sshd_config_path = os.path.join(info.root, 'etc/ssh/sshd_config')
sed_i(sshd_config_path, '^#PasswordAuthentication yes', 'PasswordAuthentication no')
@ -26,7 +28,8 @@ class DisableSSHDNSLookup(Task):
description = 'Disabling sshd remote host name lookup'
phase = phases.system_modification
def run(self, info):
@classmethod
def run(cls, info):
sshd_config_path = os.path.join(info.root, 'etc/ssh/sshd_config')
with open(sshd_config_path, 'a') as sshd_config:
sshd_config.write('UseDNS no')

View file

@ -7,7 +7,8 @@ class Attach(Task):
description = 'Attaching the volume'
phase = phases.volume_creation
def run(self, info):
@classmethod
def run(cls, info):
info.volume.attach()
@ -15,7 +16,8 @@ class Detach(Task):
description = 'Detaching the volume'
phase = phases.volume_unmounting
def run(self, info):
@classmethod
def run(cls, info):
info.volume.detach()
@ -24,5 +26,6 @@ class Delete(Task):
phase = phases.cleaning
successors = [workspace.DeleteWorkspace]
def run(self, info):
@classmethod
def run(cls, info):
info.volume.delete()

View file

@ -6,7 +6,8 @@ class CreateWorkspace(Task):
description = 'Creating workspace'
phase = phases.preparation
def run(self, info):
@classmethod
def run(cls, info):
import os
os.makedirs(info.workspace)
@ -15,6 +16,7 @@ class DeleteWorkspace(Task):
description = 'Deleting workspace'
phase = phases.cleaning
def run(self, info):
@classmethod
def run(cls, info):
import os
os.rmdir(info.workspace)

View file

@ -10,7 +10,8 @@ class AddSudoPackage(Task):
phase = phases.preparation
predecessors = [apt.AddDefaultSources]
def run(self, info):
@classmethod
def run(cls, info):
info.packages.add('sudo')
@ -18,7 +19,8 @@ class CreateAdminUser(Task):
description = 'Creating the admin user'
phase = phases.system_modification
def run(self, info):
@classmethod
def run(cls, info):
from common.tools import log_check_call
log_check_call(['/usr/sbin/chroot', info.root,
'/usr/sbin/useradd',
@ -30,7 +32,8 @@ class PasswordlessSudo(Task):
description = 'Allowing the admin user to use sudo without a password'
phase = phases.system_modification
def run(self, info):
@classmethod
def run(cls, info):
sudo_admin_path = os.path.join(info.root, 'etc/sudoers.d/99_admin')
username = info.manifest.plugins['admin_user']['username']
with open(sudo_admin_path, 'w') as sudo_admin:
@ -45,7 +48,8 @@ class AdminUserCredentials(Task):
phase = phases.system_modification
predecessors = [InstallInitScripts]
def run(self, info):
@classmethod
def run(cls, info):
from common.tools import sed_i
getcreds_path = os.path.join(info.root, 'etc/init.d/ec2-get-credentials')
username = info.manifest.plugins['admin_user']['username']
@ -56,7 +60,8 @@ class DisableRootLogin(Task):
description = 'Disabling SSH login for root'
phase = phases.system_modification
def run(self, info):
@classmethod
def run(cls, info):
from subprocess import CalledProcessError
from common.tools import log_check_call
try:

View file

@ -6,7 +6,8 @@ class WriteMetadata(Task):
description = 'Writing bootstrap metadata to file'
phase = phases.cleaning
def run(self, info):
@classmethod
def run(cls, info):
metadata_path = info.manifest.plugins['build_metadata']['path']
with open(metadata_path, 'w') as metadata:
metadata.write(('AMI_ID={ami_id}\n'

View file

@ -9,7 +9,8 @@ class AddBackports(Task):
description = 'Adding backports to the apt sources'
phase = phases.preparation
def run(self, info):
@classmethod
def run(cls, info):
if info.source_lists.target_exists('{system.release}-backports'):
import logging
msg = ('{system.release}-backports target already exists').format(**info.manifest_vars)
@ -24,7 +25,8 @@ class AddCloudInitPackages(Task):
phase = phases.preparation
predecessors = [apt.AddDefaultSources, AddBackports]
def run(self, info):
@classmethod
def run(cls, info):
target = None
if info.manifest.system['release'] in ['wheezy', 'stable']:
target = '{system.release}-backports'
@ -36,7 +38,8 @@ class SetUsername(Task):
description = 'Setting username in cloud.cfg'
phase = phases.system_modification
def run(self, info):
@classmethod
def run(cls, info):
from common.tools import sed_i
cloud_cfg = os.path.join(info.root, 'etc/cloud/cloud.cfg')
username = info.manifest.plugins['cloud_init']['username']
@ -51,7 +54,8 @@ class SetMetadataSource(Task):
description = 'Setting metadata source'
phase = phases.system_modification
def run(self, info):
@classmethod
def run(cls, info):
if 'metadata_sources' in info.manifest.plugins['cloud_init']:
sources = info.manifest.plugins['cloud_init']['metadata_sources']
else:
@ -71,7 +75,8 @@ class DisableModules(Task):
description = 'Setting cloud.cfg modules'
phase = phases.system_modification
def run(self, info):
@classmethod
def run(cls, info):
import re
patterns = ""
for pattern in info.manifest.plugins['cloud_init']['disable_modules']:

View file

@ -6,7 +6,8 @@ class ImageExecuteCommand(Task):
description = 'Execute command in the image'
phase = phases.system_modification
def run(self, info):
@classmethod
def run(cls, info):
from common.tools import log_check_call
for user_cmd in info.manifest.plugins['image_commands']['commands']:

View file

@ -12,7 +12,8 @@ class AddFolderMounts(Task):
phase = phases.os_installation
predecessors = [bootstrap.Bootstrap]
def run(self, info):
@classmethod
def run(cls, info):
info.minimize_size_folder = os.path.join(info.workspace, 'minimize_size')
os.mkdir(info.minimize_size_folder)
for folder in folders:
@ -28,7 +29,8 @@ class RemoveFolderMounts(Task):
phase = phases.system_cleaning
successors = [apt.AptClean]
def run(self, info):
@classmethod
def run(cls, info):
import shutil
for folder in folders:
temp_path = os.path.join(info.minimize_size_folder, folder.replace('/', '_'))

View file

@ -11,7 +11,8 @@ class OpenNebulaContext(Task):
phase = phases.system_modification
predecessors = [GenerateLocale]
def run(self, info):
@classmethod
def run(cls, info):
import stat
rwxr_xr_x = (stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR |
stat.S_IRGRP | stat.S_IXGRP |

View file

@ -17,7 +17,8 @@ class Snapshot(Task):
phase = phases.package_installation
predecessors = [packages.InstallRemotePackages, guest_additions.InstallGuestAdditions]
def run(self, info):
@classmethod
def run(cls, info):
def mk_snapshot():
return info.volume.snapshot()
snapshot = remount(info.volume, mk_snapshot)
@ -30,7 +31,8 @@ class CreateFromSnapshot(Task):
phase = phases.volume_creation
successors = [ebs.Attach]
def run(self, info):
@classmethod
def run(cls, info):
volume_size = int(info.volume.partition_map.get_total_size() / 1024)
snapshot = info.manifest.plugins['prebootstrapped']['snapshot']
ebs_volume = info.connection.create_volume(volume_size,
@ -49,7 +51,8 @@ class CopyImage(Task):
phase = phases.package_installation
predecessors = [packages.InstallRemotePackages, guest_additions.InstallGuestAdditions]
def run(self, info):
@classmethod
def run(cls, info):
loopback_backup_name = 'volume-{id}.{ext}.backup'.format(id=info.run_id, ext=info.volume.extension)
destination = os.path.join(info.manifest.bootstrapper['workspace'], loopback_backup_name)
@ -65,7 +68,8 @@ class CreateFromImage(Task):
phase = phases.volume_creation
successors = [volume.Attach]
def run(self, info):
@classmethod
def run(cls, info):
info.volume.image_path = os.path.join(info.workspace, 'volume.{ext}'.format(ext=info.volume.extension))
loopback_backup_path = info.manifest.plugins['prebootstrapped']['image']
copyfile(loopback_backup_path, info.volume.image_path)

View file

@ -6,7 +6,8 @@ class SetRootPassword(Task):
description = 'Setting the root password'
phase = phases.system_modification
def run(self, info):
@classmethod
def run(cls, info):
from common.tools import log_check_call
log_check_call(['/usr/sbin/chroot', info.root, '/usr/sbin/chpasswd'],
'root:' + info.manifest.plugins['root_password']['password'])

View file

@ -8,7 +8,8 @@ class AddUnattendedUpgradesPackage(Task):
phase = phases.preparation
predecessors = [apt.AddDefaultSources]
def run(self, info):
@classmethod
def run(cls, info):
info.packages.add('unattended-upgrades')
@ -16,7 +17,8 @@ class EnablePeriodicUpgrades(Task):
description = 'Writing the periodic upgrades apt config file'
phase = phases.system_modification
def run(self, info):
@classmethod
def run(cls, info):
import os.path
periodic_path = os.path.join(info.root, 'etc/apt/apt.conf.d/02periodic')
update_interval = info.manifest.plugins['unattended_upgrades']['update_interval']

View file

@ -14,7 +14,8 @@ class CreateVagrantBoxDir(Task):
phase = phases.preparation
predecessors = [workspace.CreateWorkspace]
def run(self, info):
@classmethod
def run(cls, info):
info.vagrant_folder = os.path.join(info.workspace, 'vagrant')
os.mkdir(info.vagrant_folder)
@ -24,7 +25,8 @@ class AddPackages(Task):
phase = phases.preparation
predecessors = [apt.AddDefaultSources]
def run(self, info):
@classmethod
def run(cls, info):
info.packages.add('openssh-server')
@ -33,7 +35,8 @@ class AddInsecurePublicKey(Task):
phase = phases.system_modification
predecessors = [CreateAdminUser]
def run(self, info):
@classmethod
def run(cls, info):
ssh_dir = os.path.join(info.root, 'home/vagrant/.ssh')
os.mkdir(ssh_dir)
@ -50,7 +53,8 @@ class PackageBox(Task):
description = 'Packaging the volume as a vagrant box'
phase = phases.image_registration
def run(self, info):
@classmethod
def run(cls, info):
box_basename = info.manifest.image['name'].format(**info.manifest_vars)
box_name = '{name}.box'.format(name=box_basename)
box_path = os.path.join(info.manifest.bootstrapper['workspace'], box_name)
@ -74,7 +78,7 @@ class PackageBox(Task):
log_check_call(['ln', '-s', info.volume.image_path, disk_link])
ovf_path = os.path.join(info.vagrant_folder, 'box.ovf')
self.write_ovf(info, ovf_path, box_name, mac_address, disk_name)
cls.write_ovf(info, ovf_path, box_name, mac_address, disk_name)
box_files = os.listdir(info.vagrant_folder)
log_check_call(['tar', '--create', '--gzip', '--dereference',
@ -86,7 +90,7 @@ class PackageBox(Task):
logging.getLogger(__name__).info('The vagrant box has been placed at {box_path}'
.format(box_path=box_path))
def write_ovf(self, info, destination, box_name, mac_address, disk_name):
def write_ovf(info, destination, box_name, mac_address, disk_name):
namespaces = {'ovf': 'http://schemas.dmtf.org/ovf/envelope/1',
'rasd': 'http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData',
'vssd': 'http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData',
@ -153,6 +157,7 @@ class RemoveVagrantBoxDir(Task):
phase = phases.cleaning
successors = [workspace.DeleteWorkspace]
def run(self, info):
@classmethod
def run(cls, info):
shutil.rmtree(info.vagrant_folder)
del info.vagrant_folder

View file

@ -16,7 +16,8 @@ class AMIName(Task):
phase = phases.preparation
predecessors = [Connect]
def run(self, info):
@classmethod
def run(cls, info):
ami_name = info.manifest.image['name'].format(**info.manifest_vars)
ami_description = info.manifest.image['description'].format(**info.manifest_vars)
@ -33,7 +34,8 @@ class BundleImage(Task):
description = 'Bundling the image'
phase = phases.image_registration
def run(self, info):
@classmethod
def run(cls, info):
bundle_name = 'bundle-{id}'.format(id=info.run_id)
info.bundle_path = os.path.join(info.workspace, bundle_name)
log_check_call(['/usr/bin/euca-bundle-image',
@ -51,7 +53,8 @@ class UploadImage(Task):
phase = phases.image_registration
predecessors = [BundleImage]
def run(self, info):
@classmethod
def run(cls, info):
manifest_file = os.path.join(info.bundle_path, info.ami_name + '.manifest.xml')
if info.host['region'] == 'us-east-1':
s3_url = 'https://s3.amazonaws.com/'
@ -72,7 +75,8 @@ class RemoveBundle(Task):
phase = phases.cleaning
successors = [workspace.DeleteWorkspace]
def run(self, info):
@classmethod
def run(cls, info):
from shutil import rmtree
rmtree(info.bundle_path)
del info.bundle_path
@ -140,7 +144,8 @@ class RegisterAMI(Task):
}
}
def run(self, info):
@classmethod
def run(cls, info):
registration_params = {'name': info.ami_name,
'description': info.ami_description}
registration_params['architecture'] = {'i386': 'i386',
@ -169,7 +174,7 @@ class RegisterAMI(Task):
registration_params['virtualization_type'] = 'hvm'
else:
registration_params['virtualization_type'] = 'paravirtual'
registration_params['kernel_id'] = (self.kernel_mapping
registration_params['kernel_id'] = (cls.kernel_mapping
.get(info.host['region'])
.get(grub_boot_device)
.get(info.manifest.system['architecture']))

View file

@ -8,7 +8,8 @@ class ConfigurePVGrub(Task):
description = 'Creating grub config files for PVGrub'
phase = phases.system_modification
def run(self, info):
@classmethod
def run(cls, info):
import stat
rwxr_xr_x = (stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR |
stat.S_IRGRP | stat.S_IXGRP |

View file

@ -7,13 +7,15 @@ class GetCredentials(Task):
description = 'Getting AWS credentials'
phase = phases.preparation
def run(self, info):
@classmethod
def run(cls, info):
keys = ['access-key', 'secret-key']
if info.manifest.volume['backing'] == 's3':
keys.extend(['certificate', 'private-key', 'user-id'])
info.credentials = self.get_credentials(info.manifest, keys)
info.credentials = cls.get_credentials(info.manifest, keys)
def get_credentials(self, manifest, keys):
@classmethod
def get_credentials(cls, manifest, keys):
from os import getenv
creds = {}
if all(key in manifest.data['credentials'] for key in keys):
@ -36,7 +38,8 @@ class Connect(Task):
phase = phases.preparation
predecessors = [GetCredentials, host.GetInfo]
def run(self, info):
@classmethod
def run(cls, info):
from boto.ec2 import connect_to_region
info.connection = connect_to_region(info.host['region'],
aws_access_key_id=info.credentials['access-key'],

View file

@ -6,7 +6,8 @@ class Create(Task):
description = 'Creating the EBS volume'
phase = phases.volume_creation
def run(self, info):
@classmethod
def run(cls, info):
info.volume.create(info.connection, info.host['availabilityZone'])
@ -15,7 +16,8 @@ class Attach(Task):
phase = phases.volume_creation
predecessors = [Create]
def run(self, info):
@classmethod
def run(cls, info):
info.volume.attach(info.host['instanceId'])
@ -23,5 +25,6 @@ class Snapshot(Task):
description = 'Creating a snapshot of the EBS volume'
phase = phases.image_registration
def run(self, info):
@classmethod
def run(cls, info):
info.snapshot = info.volume.snapshot()

View file

@ -6,7 +6,8 @@ class S3FStab(Task):
description = 'Adding the S3 root partition to the fstab'
phase = phases.system_modification
def run(self, info):
@classmethod
def run(cls, info):
import os.path
root = info.volume.partition_map.root

View file

@ -8,7 +8,8 @@ class HostDependencies(Task):
phase = phases.preparation
successors = [host.CheckHostDependencies]
def run(self, info):
@classmethod
def run(cls, info):
if info.manifest.volume['backing'] == 's3':
info.host_dependencies.add('euca2ools')
@ -17,7 +18,8 @@ class GetInfo(Task):
description = 'Retrieving instance metadata'
phase = phases.preparation
def run(self, info):
@classmethod
def run(cls, info):
import urllib2
import json
metadata_url = 'http://169.254.169.254/latest/dynamic/instance-identity/document'

View file

@ -10,7 +10,8 @@ class AddEC2InitScripts(Task):
phase = phases.system_modification
successors = [initd.InstallInitScripts]
def run(self, info):
@classmethod
def run(cls, info):
init_scripts = {'ec2-get-credentials': 'ec2-get-credentials',
'ec2-run-user-data': 'ec2-run-user-data'}

View file

@ -8,7 +8,8 @@ class EnableDHCPCDDNS(Task):
description = 'Configuring the DHCP client to set the nameservers'
phase = phases.system_modification
def run(self, info):
@classmethod
def run(cls, info):
# The dhcp client that ships with debian sets the DNS servers per default.
# For dhcpcd we need to configure it to do that.
from common.tools import sed_i
@ -21,7 +22,8 @@ class AddBuildEssentialPackage(Task):
phase = phases.preparation
predecessors = [apt.AddDefaultSources]
def run(self, info):
@classmethod
def run(cls, info):
info.packages.add('build-essential')
@ -29,7 +31,8 @@ class InstallEnhancedNetworking(Task):
description = 'Installing network drivers for SR-IOV support'
phase = phases.package_installation
def run(self, info):
@classmethod
def run(cls, info):
drivers_url = 'http://downloads.sourceforge.net/project/e1000/ixgbevf stable/2.11.3/ixgbevf-2.11.3.tar.gz'
archive = os.path.join(info.root, 'tmp', 'ixgbevf-2.11.3.tar.gz')

View file

@ -8,7 +8,8 @@ class DefaultPackages(Task):
phase = phases.preparation
predecessors = [apt.AddDefaultSources]
def run(self, info):
@classmethod
def run(cls, info):
info.packages.add('openssh-server')
info.packages.add('file') # Needed for the init scripts
info.packages.add('dhcpcd') # isc-dhcp-client doesn't work properly with ec2

View file

@ -8,7 +8,8 @@ class CheckGuestAdditionsPath(Task):
description = 'Checking whether the VirtualBox Guest Additions image exists'
phase = phases.preparation
def run(self, info):
@classmethod
def run(cls, info):
import os.path
guest_additions_path = info.manifest.bootstrapper['guest_additions']
if not os.path.exists(guest_additions_path):
@ -21,7 +22,8 @@ class AddGuestAdditionsPackages(Task):
phase = phases.package_installation
successors = [InstallRemotePackages]
def run(self, info):
@classmethod
def run(cls, info):
info.packages.add('bzip2')
info.packages.add('build-essential')
info.packages.add('dkms')
@ -38,7 +40,8 @@ class InstallGuestAdditions(Task):
phase = phases.package_installation
predecessors = [InstallRemotePackages]
def run(self, info):
@classmethod
def run(cls, info):
import os
guest_additions_path = info.manifest.bootstrapper['guest_additions']
mount_dir = 'mnt/guest_additions'

View file

@ -8,7 +8,8 @@ class DefaultPackages(Task):
phase = phases.preparation
predecessors = [apt.AddDefaultSources]
def run(self, info):
@classmethod
def run(cls, info):
kernels = {'amd64': 'linux-image-amd64',
'i386': 'linux-image-686', }
info.packages.add(kernels.get(info.manifest.system['architecture']))