Use `type' to check if command available. Fixes #11

This commit is contained in:
Anders Ingemann 2014-02-23 21:51:28 +01:00
parent 739e22e929
commit 5cff8f9b1d
6 changed files with 34 additions and 30 deletions

View file

@ -55,6 +55,6 @@ class BootstrapInformation(object):
self.include_packages = set() self.include_packages = set()
self.exclude_packages = set() self.exclude_packages = set()
self.host_dependencies = set() self.host_dependencies = {}
self.initd = {'install': {}, 'disable': []} self.initd = {'install': {}, 'disable': []}

View file

@ -12,8 +12,8 @@ from common.tasks import security
from common.tasks import locale from common.tasks import locale
base_set = [workspace.CreateWorkspace, base_set = [workspace.CreateWorkspace,
host.HostDependencies, host.AddExternalCommands,
host.CheckHostDependencies, host.CheckExternalCommands,
bootstrap.Bootstrap, bootstrap.Bootstrap,
workspace.DeleteWorkspace, workspace.DeleteWorkspace,
] ]

View file

@ -3,47 +3,49 @@ from common import phases
from common.exceptions import TaskError from common.exceptions import TaskError
class HostDependencies(Task): class AddExternalCommands(Task):
description = 'Determining required host dependencies' description = 'Determining which external commands are required'
phase = phases.preparation phase = phases.preparation
@classmethod @classmethod
def run(cls, info): def run(cls, info):
info.host_dependencies.add('debootstrap') info.host_dependencies['debootstrap'] = 'debootstrap'
from common.fs.loopbackvolume import LoopbackVolume from common.fs.loopbackvolume import LoopbackVolume
if isinstance(info.volume, LoopbackVolume): if isinstance(info.volume, LoopbackVolume):
info.host_dependencies.add('qemu-utils') info.host_dependencies['qemu-img'] = 'qemu-utils'
info.host_dependencies['losetup'] = 'mount'
from common.fs.qemuvolume import QEMUVolume
if isinstance(info.volume, QEMUVolume):
info.host_dependencies['losetup'] = 'qemu-nbd'
if 'xfs' in (p.filesystem for p in info.volume.partition_map.partitions): if 'xfs' in (p.filesystem for p in info.volume.partition_map.partitions):
info.host_dependencies.add('xfsprogs') info.host_dependencies['mkfs.xfs'] = 'xfsprogs'
from base.fs.partitionmaps.none import NoPartitions from base.fs.partitionmaps.none import NoPartitions
if not isinstance(info.volume.partition_map, NoPartitions): if not isinstance(info.volume.partition_map, NoPartitions):
info.host_dependencies.update(['parted', 'kpartx']) info.host_dependencies['parted'] = 'parted'
info.host_dependencies['kpartx'] = 'kpartx'
class CheckHostDependencies(Task): class CheckExternalCommands(Task):
description = 'Checking installed host packages' description = 'Checking availability of external commands'
phase = phases.preparation phase = phases.preparation
predecessors = [HostDependencies] predecessors = [AddExternalCommands]
@classmethod @classmethod
def run(cls, info): def run(cls, info):
from common.tools import log_check_call from common.tools import log_check_call
from subprocess import CalledProcessError from subprocess import CalledProcessError
missing_packages = [] missing_packages = []
for package in info.host_dependencies: for command, package in info.host_dependencies.items():
try: try:
import os.path log_check_call(['type ' + command], shell=True)
if os.path.isfile('/usr/bin/dpkg-query'):
log_check_call(['/usr/bin/dpkg-query', '-s', package])
except CalledProcessError: except CalledProcessError:
missing_packages.append(package) msg = ('The command `{command}\' is not available, '
'it is located in the package `{package}\'.'
.format(command=command, package=package))
missing_packages.append(msg)
if len(missing_packages) > 0: if len(missing_packages) > 0:
pkgs = '\', `'.join(missing_packages) msg = '\n'.join(missing_packages)
if len(missing_packages) > 1:
msg = "The packages `{packages}\' are not installed".format(packages=pkgs)
else:
msg = "The package `{packages}\' is not installed".format(packages=pkgs)
raise TaskError(msg) raise TaskError(msg)

View file

@ -1,14 +1,14 @@
def log_check_call(command, stdin=None, env=None): def log_check_call(command, stdin=None, env=None, shell=False):
status, stdout, stderr = log_call(command, stdin, env) status, stdout, stderr = log_call(command, stdin, env, shell)
if status != 0: if status != 0:
from subprocess import CalledProcessError from subprocess import CalledProcessError
raise CalledProcessError(status, ' '.join(command), '\n'.join(stderr)) raise CalledProcessError(status, ' '.join(command), '\n'.join(stderr))
return stdout return stdout
def log_call(command, stdin=None, env=None): def log_call(command, stdin=None, env=None, shell=False):
import subprocess import subprocess
import select import select
@ -22,6 +22,7 @@ def log_call(command, stdin=None, env=None):
popen_args = {'args': command, popen_args = {'args': command,
'env': env, 'env': env,
'shell': shell,
'stdin': subprocess.PIPE, 'stdin': subprocess.PIPE,
'stdout': subprocess.PIPE, 'stdout': subprocess.PIPE,
'stderr': subprocess.PIPE, } 'stderr': subprocess.PIPE, }

View file

@ -61,7 +61,7 @@ def resolve_tasks(taskset, manifest):
if manifest.volume['partitions']['type'] != 'none': if manifest.volume['partitions']['type'] != 'none':
taskset.update(common.task_sets.partitioning_set) taskset.update(common.task_sets.partitioning_set)
taskset.update([tasks.host.HostDependencies, taskset.update([tasks.host.AddExternalCommands,
tasks.packages.DefaultPackages, tasks.packages.DefaultPackages,
tasks.connection.GetCredentials, tasks.connection.GetCredentials,
tasks.host.GetInfo, tasks.host.GetInfo,

View file

@ -3,15 +3,16 @@ from common import phases
from common.tasks import host from common.tasks import host
class HostDependencies(Task): class AddExternalCommands(Task):
description = 'Adding required host packages for EC2 bootstrapping' description = 'Determining required external commands for EC2 bootstrapping'
phase = phases.preparation phase = phases.preparation
successors = [host.CheckHostDependencies] successors = [host.CheckExternalCommands]
@classmethod @classmethod
def run(cls, info): def run(cls, info):
if info.manifest.volume['backing'] == 's3': if info.manifest.volume['backing'] == 's3':
info.host_dependencies.add('euca2ools') info.host_dependencies['euca-bundle-image'] = 'euca2ools'
info.host_dependencies['euca-upload-bundle'] = 'euca2ools'
class GetInfo(Task): class GetInfo(Task):