2016-03-23 09:40:16 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
|
|
import os
|
|
|
|
from kobo.threads import ThreadPool, WorkerThread
|
|
|
|
import shutil
|
|
|
|
from productmd import images
|
2016-04-08 10:48:42 +00:00
|
|
|
import pipes
|
|
|
|
from kobo import shortcuts
|
2016-03-23 09:40:16 +00:00
|
|
|
|
2016-11-18 20:33:03 +00:00
|
|
|
from .base import ConfigGuardedPhase, PhaseLoggerMixin
|
2016-03-23 09:40:16 +00:00
|
|
|
from .. import util
|
|
|
|
from ..paths import translate_path
|
2016-10-06 07:17:09 +00:00
|
|
|
from ..util import get_volid
|
2016-04-11 08:25:10 +00:00
|
|
|
from ..wrappers import kojiwrapper, iso, lorax, scm
|
2016-03-23 09:40:16 +00:00
|
|
|
|
|
|
|
|
2016-11-18 20:33:03 +00:00
|
|
|
class OstreeInstallerPhase(PhaseLoggerMixin, ConfigGuardedPhase):
|
2016-04-05 07:13:01 +00:00
|
|
|
name = 'ostree_installer'
|
2016-03-23 09:40:16 +00:00
|
|
|
|
|
|
|
def __init__(self, compose):
|
2016-04-05 07:13:01 +00:00
|
|
|
super(OstreeInstallerPhase, self).__init__(compose)
|
2016-11-18 20:33:03 +00:00
|
|
|
self.pool = ThreadPool(logger=self.logger)
|
2016-03-23 09:40:16 +00:00
|
|
|
|
|
|
|
def run(self):
|
|
|
|
for variant in self.compose.get_variants():
|
|
|
|
for arch in variant.arches:
|
|
|
|
for conf in util.get_arch_variant_data(self.compose.conf, self.name, arch, variant):
|
2016-04-05 07:13:01 +00:00
|
|
|
self.pool.add(OstreeInstallerThread(self.pool))
|
2016-03-23 09:40:16 +00:00
|
|
|
self.pool.queue_put((self.compose, variant, arch, conf))
|
|
|
|
|
|
|
|
self.pool.start()
|
|
|
|
|
|
|
|
|
2016-04-05 07:13:01 +00:00
|
|
|
class OstreeInstallerThread(WorkerThread):
|
2016-03-23 09:40:16 +00:00
|
|
|
def process(self, item, num):
|
|
|
|
compose, variant, arch, config = item
|
|
|
|
self.num = num
|
2016-06-24 07:44:40 +00:00
|
|
|
failable_arches = config.get('failable', [])
|
|
|
|
self.can_fail = util.can_arch_fail(failable_arches, arch)
|
2016-11-18 20:33:03 +00:00
|
|
|
with util.failable(compose, self.can_fail, variant, arch, 'ostree-installer',
|
|
|
|
logger=self.pool._logger):
|
2016-03-23 09:40:16 +00:00
|
|
|
self.worker(compose, variant, arch, config)
|
|
|
|
|
|
|
|
def worker(self, compose, variant, arch, config):
|
2016-04-05 07:13:01 +00:00
|
|
|
msg = 'Ostree phase for variant %s, arch %s' % (variant.uid, arch)
|
2016-03-23 09:40:16 +00:00
|
|
|
self.pool.log_info('[BEGIN] %s' % msg)
|
2017-03-15 14:54:45 +00:00
|
|
|
self.logdir = compose.paths.log.topdir('%s/%s/ostree_installer-%s' % (arch, variant, self.num))
|
2016-03-23 09:40:16 +00:00
|
|
|
|
2017-01-13 08:57:30 +00:00
|
|
|
source_from_repos = [self._get_source_repo(compose, arch, v)
|
2017-02-22 02:48:05 +00:00
|
|
|
for v in shortcuts.force_list(config['repo_from'])]
|
2017-01-13 08:57:30 +00:00
|
|
|
repos = shortcuts.force_list(config.pop('repo', []))
|
|
|
|
source_repos = source_from_repos + repos
|
2016-04-08 07:29:05 +00:00
|
|
|
output_dir = os.path.join(compose.paths.work.topdir(arch), variant.uid, 'ostree_installer')
|
|
|
|
util.makedirs(os.path.dirname(output_dir))
|
2016-03-23 09:40:16 +00:00
|
|
|
|
2016-04-11 08:25:10 +00:00
|
|
|
self.template_dir = os.path.join(compose.paths.work.topdir(arch), variant.uid, 'lorax_templates')
|
|
|
|
self._clone_templates(config.get('template_repo'), config.get('template_branch'))
|
2016-10-06 07:17:09 +00:00
|
|
|
disc_type = compose.conf['disc_types'].get('ostree', 'ostree')
|
2016-04-11 08:25:10 +00:00
|
|
|
|
2016-10-06 07:17:09 +00:00
|
|
|
volid = get_volid(compose, arch, variant, disc_type=disc_type)
|
2017-03-15 15:17:38 +00:00
|
|
|
task_id = self._run_ostree_cmd(compose, variant, arch, config, source_repos, output_dir, volid)
|
2016-03-23 09:40:16 +00:00
|
|
|
|
2016-04-14 08:56:12 +00:00
|
|
|
filename = compose.get_image_name(arch, variant, disc_type=disc_type)
|
2016-04-08 07:29:05 +00:00
|
|
|
self._copy_image(compose, variant, arch, filename, output_dir)
|
2016-03-23 09:40:16 +00:00
|
|
|
self._add_to_manifest(compose, variant, arch, filename)
|
2017-03-15 15:17:38 +00:00
|
|
|
self.pool.log_info('[DONE ] %s, (task id: %s)' % (msg, task_id))
|
2016-03-23 09:40:16 +00:00
|
|
|
|
2016-05-24 08:03:36 +00:00
|
|
|
def _get_source_repo(self, compose, arch, source):
|
|
|
|
"""
|
|
|
|
If `source` is a URL, return it as-is (possibly replacing $arch with
|
|
|
|
actual arch. Otherwise treat is a a variant name and return path to
|
|
|
|
repo in that variant.
|
|
|
|
"""
|
|
|
|
if '://' in source:
|
|
|
|
return source.replace('$arch', arch)
|
2016-11-09 09:20:55 +00:00
|
|
|
source_variant = compose.all_variants[source]
|
2016-05-24 08:03:36 +00:00
|
|
|
return translate_path(
|
|
|
|
compose, compose.paths.compose.repository(arch, source_variant, create_dir=False))
|
|
|
|
|
2016-04-11 08:25:10 +00:00
|
|
|
def _clone_templates(self, url, branch='master'):
|
|
|
|
if not url:
|
|
|
|
self.template_dir = None
|
|
|
|
return
|
|
|
|
scm.get_dir_from_scm({'scm': 'git', 'repo': url, 'branch': branch, 'dir': '.'},
|
|
|
|
self.template_dir, logger=self.pool._logger)
|
|
|
|
|
2016-03-23 09:40:16 +00:00
|
|
|
def _get_release(self, compose, config):
|
|
|
|
if 'release' in config and config['release'] is None:
|
|
|
|
return compose.image_release
|
|
|
|
return config.get('release', None)
|
|
|
|
|
2016-04-08 07:29:05 +00:00
|
|
|
def _copy_image(self, compose, variant, arch, filename, output_dir):
|
2016-03-23 09:40:16 +00:00
|
|
|
iso_path = compose.paths.compose.iso_path(arch, variant, filename)
|
2016-05-26 07:58:56 +00:00
|
|
|
os_path = compose.paths.compose.os_tree(arch, variant)
|
2016-04-08 07:29:05 +00:00
|
|
|
boot_iso = os.path.join(output_dir, 'images', 'boot.iso')
|
2016-03-23 09:40:16 +00:00
|
|
|
|
2016-04-08 10:48:42 +00:00
|
|
|
shortcuts.run('cp -av %s/* %s/' %
|
2016-05-26 07:58:56 +00:00
|
|
|
(pipes.quote(output_dir), pipes.quote(os_path)))
|
2016-03-23 09:40:16 +00:00
|
|
|
try:
|
|
|
|
os.link(boot_iso, iso_path)
|
|
|
|
except OSError:
|
|
|
|
shutil.copy2(boot_iso, iso_path)
|
|
|
|
|
|
|
|
def _add_to_manifest(self, compose, variant, arch, filename):
|
|
|
|
full_iso_path = compose.paths.compose.iso_path(arch, variant, filename)
|
|
|
|
iso_path = compose.paths.compose.iso_path(arch, variant, filename, relative=True)
|
2016-10-12 11:56:19 +00:00
|
|
|
implant_md5 = iso.get_implanted_md5(full_iso_path)
|
2016-03-23 09:40:16 +00:00
|
|
|
|
|
|
|
img = images.Image(compose.im)
|
|
|
|
img.path = iso_path
|
|
|
|
img.mtime = util.get_mtime(full_iso_path)
|
|
|
|
img.size = util.get_file_size(full_iso_path)
|
|
|
|
img.arch = arch
|
2016-10-06 11:12:34 +00:00
|
|
|
img.type = "dvd-ostree"
|
2016-03-23 09:40:16 +00:00
|
|
|
img.format = "iso"
|
|
|
|
img.disc_number = 1
|
|
|
|
img.disc_count = 1
|
|
|
|
img.bootable = True
|
|
|
|
img.subvariant = variant.name
|
|
|
|
img.implant_md5 = implant_md5
|
2016-06-24 07:44:40 +00:00
|
|
|
setattr(img, 'can_fail', self.can_fail)
|
2016-05-03 14:31:20 +00:00
|
|
|
setattr(img, 'deliverable', 'ostree-installer')
|
2016-03-23 09:40:16 +00:00
|
|
|
try:
|
2016-10-12 11:56:19 +00:00
|
|
|
img.volume_id = iso.get_volume_id(full_iso_path)
|
2016-03-23 09:40:16 +00:00
|
|
|
except RuntimeError:
|
|
|
|
pass
|
|
|
|
compose.im.add(variant.uid, arch, img)
|
|
|
|
|
2016-04-11 08:25:10 +00:00
|
|
|
def _get_templates(self, config, key):
|
|
|
|
"""Retrieve all templates from configuration and make sure the paths
|
|
|
|
are absolute. Raises RuntimeError if template repo is needed but not
|
|
|
|
configured.
|
|
|
|
"""
|
|
|
|
templates = []
|
|
|
|
for template in config.get(key, []):
|
|
|
|
if template[0] != '/':
|
|
|
|
if not self.template_dir:
|
|
|
|
raise RuntimeError('Relative path to template without setting template_repo.')
|
|
|
|
template = os.path.join(self.template_dir, template)
|
|
|
|
templates.append(template)
|
|
|
|
return templates
|
|
|
|
|
2016-10-06 07:17:09 +00:00
|
|
|
def _run_ostree_cmd(self, compose, variant, arch, config, source_repo, output_dir, volid):
|
2016-03-23 09:40:16 +00:00
|
|
|
lorax_wrapper = lorax.LoraxWrapper()
|
|
|
|
cmd = lorax_wrapper.get_lorax_cmd(
|
|
|
|
compose.conf['release_name'],
|
|
|
|
compose.conf["release_version"],
|
|
|
|
self._get_release(compose, config),
|
|
|
|
repo_baseurl=source_repo,
|
2016-04-08 07:29:05 +00:00
|
|
|
output_dir=output_dir,
|
2016-03-23 09:40:16 +00:00
|
|
|
variant=variant.uid,
|
|
|
|
nomacboot=True,
|
2016-10-06 07:17:09 +00:00
|
|
|
volid=volid,
|
2016-03-23 09:40:16 +00:00
|
|
|
buildinstallpackages=config.get('installpkgs'),
|
2016-04-11 08:25:10 +00:00
|
|
|
add_template=self._get_templates(config, 'add_template'),
|
|
|
|
add_arch_template=self._get_templates(config, 'add_arch_template'),
|
2016-03-23 09:40:16 +00:00
|
|
|
add_template_var=config.get('add_template_var'),
|
2016-09-21 11:48:51 +00:00
|
|
|
add_arch_template_var=config.get('add_arch_template_var'),
|
2016-11-17 15:15:03 +00:00
|
|
|
rootfs_size=config.get('rootfs_size'),
|
2016-09-21 11:48:51 +00:00
|
|
|
is_final=compose.supported,
|
2016-11-09 08:00:33 +00:00
|
|
|
log_dir=self.logdir,
|
2016-03-23 09:40:16 +00:00
|
|
|
)
|
|
|
|
|
2016-08-22 14:08:25 +00:00
|
|
|
runroot_channel = compose.conf.get("runroot_channel")
|
2016-03-23 09:40:16 +00:00
|
|
|
runroot_tag = compose.conf["runroot_tag"]
|
|
|
|
|
2016-04-12 10:45:28 +00:00
|
|
|
packages = ['pungi', 'lorax', 'ostree']
|
2016-03-23 09:40:16 +00:00
|
|
|
log_file = os.path.join(self.logdir, 'runroot.log')
|
|
|
|
koji = kojiwrapper.KojiWrapper(compose.conf["koji_profile"])
|
|
|
|
koji_cmd = koji.get_runroot_cmd(runroot_tag, arch, cmd,
|
|
|
|
channel=runroot_channel,
|
|
|
|
use_shell=True, task_id=True,
|
2017-02-23 09:28:49 +00:00
|
|
|
packages=packages, mounts=[compose.topdir],
|
|
|
|
weight=compose.conf['runroot_weights'].get('ostree_installer'))
|
2016-03-23 09:40:16 +00:00
|
|
|
output = koji.run_runroot_cmd(koji_cmd, log_file=log_file)
|
|
|
|
if output["retcode"] != 0:
|
|
|
|
raise RuntimeError("Runroot task failed: %s. See %s for more details."
|
|
|
|
% (output["task_id"], log_file))
|
2017-03-15 15:17:38 +00:00
|
|
|
return output['task_id']
|