2014-03-23 23:12:07 +01:00
|
|
|
from bootstrapvz.base import Task
|
|
|
|
from .. import phases
|
|
|
|
from ..exceptions import TaskError
|
2014-02-23 22:03:13 +01:00
|
|
|
import host
|
2013-07-07 21:35:31 +02:00
|
|
|
import logging
|
2014-04-26 13:49:47 -03:00
|
|
|
import os.path
|
2013-07-07 21:35:31 +02:00
|
|
|
log = logging.getLogger(__name__)
|
2013-06-27 23:26:29 +02:00
|
|
|
|
|
|
|
|
2014-02-23 22:03:13 +01:00
|
|
|
class AddRequiredCommands(Task):
|
2014-04-08 22:04:29 +02:00
|
|
|
description = 'Adding commands required for bootstrapping Debian'
|
2014-02-23 22:03:13 +01:00
|
|
|
phase = phases.preparation
|
|
|
|
successors = [host.CheckExternalCommands]
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def run(cls, info):
|
|
|
|
info.host_dependencies['debootstrap'] = 'debootstrap'
|
|
|
|
|
|
|
|
|
2013-06-27 23:26:29 +02:00
|
|
|
def get_bootstrap_args(info):
|
2014-02-23 22:16:10 +01:00
|
|
|
executable = ['debootstrap']
|
2014-11-19 21:57:24 +00:00
|
|
|
arch = info.manifest.system.get('userspace_architecture', info.manifest.system.get('architecture'))
|
|
|
|
options = ['--arch=' + arch]
|
2015-12-09 19:00:06 +01:00
|
|
|
if 'variant' in info.manifest.bootstrapper:
|
|
|
|
options.append('--variant=' + info.manifest.bootstrapper['variant'])
|
2013-12-29 16:09:47 +01:00
|
|
|
if len(info.include_packages) > 0:
|
|
|
|
options.append('--include=' + ','.join(info.include_packages))
|
|
|
|
if len(info.exclude_packages) > 0:
|
|
|
|
options.append('--exclude=' + ','.join(info.exclude_packages))
|
2013-12-29 22:50:35 +01:00
|
|
|
mirror = info.manifest.bootstrapper.get('mirror', info.apt_mirror)
|
|
|
|
arguments = [info.manifest.system['release'], info.root, mirror]
|
2013-06-27 23:26:29 +02:00
|
|
|
return executable, options, arguments
|
|
|
|
|
|
|
|
|
2014-04-26 13:49:47 -03:00
|
|
|
def get_tarball_filename(info):
|
|
|
|
from hashlib import sha1
|
|
|
|
executable, options, arguments = get_bootstrap_args(info)
|
|
|
|
# Filter info.root which points at /target/volume-id, we won't ever hit anything with that in there.
|
|
|
|
hash_args = [arg for arg in arguments if arg != info.root]
|
|
|
|
tarball_id = sha1(repr(frozenset(options + hash_args))).hexdigest()[0:8]
|
2014-05-03 22:24:13 +02:00
|
|
|
tarball_filename = 'debootstrap-' + tarball_id + '.tar'
|
2014-04-26 13:49:47 -03:00
|
|
|
return os.path.join(info.manifest.bootstrapper['workspace'], tarball_filename)
|
|
|
|
|
|
|
|
|
2013-06-27 23:26:29 +02:00
|
|
|
class MakeTarball(Task):
|
|
|
|
description = 'Creating bootstrap tarball'
|
|
|
|
phase = phases.os_installation
|
|
|
|
|
2014-01-05 15:57:11 +01:00
|
|
|
@classmethod
|
|
|
|
def run(cls, info):
|
2013-06-27 23:26:29 +02:00
|
|
|
executable, options, arguments = get_bootstrap_args(info)
|
2015-12-10 23:01:25 +01:00
|
|
|
tarball = get_tarball_filename(info)
|
|
|
|
if os.path.isfile(tarball):
|
2014-04-26 13:49:47 -03:00
|
|
|
log.debug('Found matching tarball, skipping creation')
|
2013-07-07 21:35:31 +02:00
|
|
|
else:
|
2014-03-23 23:12:07 +01:00
|
|
|
from ..tools import log_call
|
2015-12-10 23:01:25 +01:00
|
|
|
status, out, err = log_call(executable + options + ['--make-tarball=' + tarball] + arguments)
|
2015-12-09 19:00:06 +01:00
|
|
|
if status not in [0, 1]: # variant=minbase exits with 0
|
|
|
|
msg = 'debootstrap exited with status {status}, it should exit with status 0 or 1'.format(status=status)
|
2013-07-07 21:59:50 +02:00
|
|
|
raise TaskError(msg)
|
2013-06-27 23:26:29 +02:00
|
|
|
|
|
|
|
|
|
|
|
class Bootstrap(Task):
|
|
|
|
description = 'Installing Debian'
|
|
|
|
phase = phases.os_installation
|
2013-11-21 15:54:42 +01:00
|
|
|
predecessors = [MakeTarball]
|
2013-06-27 23:26:29 +02:00
|
|
|
|
2014-01-05 15:57:11 +01:00
|
|
|
@classmethod
|
|
|
|
def run(cls, info):
|
2013-06-27 23:26:29 +02:00
|
|
|
executable, options, arguments = get_bootstrap_args(info)
|
2015-12-10 23:01:25 +01:00
|
|
|
tarball = get_tarball_filename(info)
|
|
|
|
if os.path.isfile(tarball):
|
2014-04-26 13:49:47 -03:00
|
|
|
if not info.manifest.bootstrapper.get('tarball', False):
|
|
|
|
# Only shows this message if it hasn't tried to create the tarball
|
|
|
|
log.debug('Found matching tarball, skipping download')
|
2015-12-10 23:01:25 +01:00
|
|
|
options.extend(['--unpack-tarball=' + tarball])
|
2013-06-27 23:29:41 +02:00
|
|
|
|
2015-12-11 00:48:14 +01:00
|
|
|
if info.bootstrap_script is not None:
|
|
|
|
# Optional bootstrapping script to modify the bootstrapping process
|
|
|
|
arguments.append(info.bootstrap_script)
|
|
|
|
|
2015-12-12 23:53:13 +01:00
|
|
|
try:
|
|
|
|
from ..tools import log_check_call
|
|
|
|
log_check_call(executable + options + arguments)
|
|
|
|
except KeyboardInterrupt:
|
|
|
|
# Sometimes ../root/sys and ../root/proc are still mounted when
|
|
|
|
# quitting debootstrap prematurely. This break the cleanup process,
|
|
|
|
# so we unmount manually (ignore the exit code, the dirs may not be mounted).
|
|
|
|
from ..tools import log_call
|
|
|
|
log_call(['umount', os.path.join(info.root, 'sys')])
|
|
|
|
log_call(['umount', os.path.join(info.root, 'proc')])
|
|
|
|
raise
|
2014-05-04 21:50:32 +05:30
|
|
|
|
|
|
|
|
|
|
|
class IncludePackagesInBootstrap(Task):
|
|
|
|
description = 'Add packages in the bootstrap phase'
|
|
|
|
phase = phases.preparation
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def run(cls, info):
|
2014-05-05 00:00:48 +05:30
|
|
|
info.include_packages.update(
|
|
|
|
set(info.manifest.bootstrapper['include_packages'])
|
|
|
|
)
|
2014-05-04 21:50:32 +05:30
|
|
|
|
|
|
|
|
|
|
|
class ExcludePackagesInBootstrap(Task):
|
|
|
|
description = 'Remove packages from bootstrap phase'
|
|
|
|
phase = phases.preparation
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def run(cls, info):
|
2014-05-05 00:00:48 +05:30
|
|
|
info.exclude_packages.update(
|
|
|
|
set(info.manifest.bootstrapper['exclude_packages'])
|
|
|
|
)
|