diff --git a/bareon/drivers/data/bootstrap.py b/bareon/drivers/data/bootstrap.py index 5b1d8a1..319d4d0 100644 --- a/bareon/drivers/data/bootstrap.py +++ b/bareon/drivers/data/bootstrap.py @@ -22,3 +22,4 @@ class BootstrapBuildImage(nailgun.NailgunBuildImage): def __init__(self, data): super(BootstrapBuildImage, self).__init__(data) self.bootstrap_scheme = base.DictWrapperObject(data['bootstrap']) + self.output = data['output'] diff --git a/bareon/drivers/deploy/nailgun.py b/bareon/drivers/deploy/nailgun.py index d27350e..eb7c626 100644 --- a/bareon/drivers/deploy/nailgun.py +++ b/bareon/drivers/deploy/nailgun.py @@ -518,12 +518,12 @@ class Manager(BaseDeployDriver): chroot, os.path.join(c_dir, os.path.basename(rootfs.uri)), rootfs.compress_format) self.dump_mkbootstrap_meta(metadata, c_dir, bs_scheme) - arch_file = bu.make_targz(c_dir, self.driver.data['output']) - LOG.debug('Output archive file : {0}'.format(arch_file)) + output = bu.save_bs_container(self.driver.output, c_dir, + bs_scheme.container.format) LOG.info('--- Building bootstrap image END (do_mkbootstrap) ---') - return arch_file + return output except Exception as exc: - LOG.error('Failed to bootstrap image: %s', exc) + LOG.error('Failed to build bootstrap image: %s', exc) raise finally: LOG.info('Cleanup chroot') diff --git a/bareon/errors.py b/bareon/errors.py index 16289ec..22edbb1 100644 --- a/bareon/errors.py +++ b/bareon/errors.py @@ -190,3 +190,11 @@ class EmptyCustomFlow(BaseError): class NonexistingFlow(BaseError): pass + + +class WrongOutputContainer(BaseError): + pass + + +class BootstrapFileAlreadyExists(BaseError): + pass diff --git a/bareon/utils/build.py b/bareon/utils/build.py index 5447c31..b04a12e 100644 --- a/bareon/utils/build.py +++ b/bareon/utils/build.py @@ -817,3 +817,37 @@ def dump_runtime_uuid(uuid, config): LOG.debug('Save runtime_uuid:%s to file: %s', uuid, config) with open(config, 'wt') as f: yaml.safe_dump(data, stream=f, encoding='utf-8') + + +def save_bs_container(output, input_dir, format="tar.gz"): + """Copy files from dir to archive or another directory + + :param output: + :param input_dir: + :param format: + :return: + """ + + if format == 'directory': + utils.makedirs_if_not_exists(output) + bs_files = os.listdir(input_dir) + LOG.debug("Output folder: %s\ntry to copy bootstrap files: %s", + output, bs_files) + for bs_file in bs_files: + abs_bs_file = os.path.join(input_dir, bs_file) + if (os.path.isfile(abs_bs_file)): + if os.path.isfile(os.path.join(output, bs_file)): + raise errors.BootstrapFileAlreadyExists( + "File: {0} already exists in: {1}" + .format(bs_file, output)) + shutil.copy(abs_bs_file, output) + os.chmod(os.path.join(output, bs_file), 0o755) + return output + elif format == 'tar.gz': + LOG.debug("Try to make output archive file: %s", output) + output = make_targz(input_dir, output_name=output) + return output + else: + raise errors.WrongOutputContainer( + "Unsupported bootstrap container format {0}." + .format(format)) diff --git a/contrib/fuel_bootstrap/fuel_bootstrap_cli/fuel_bootstrap/commands/build.py b/contrib/fuel_bootstrap/fuel_bootstrap_cli/fuel_bootstrap/commands/build.py index b78c9de..e4accc6 100644 --- a/contrib/fuel_bootstrap/fuel_bootstrap_cli/fuel_bootstrap/commands/build.py +++ b/contrib/fuel_bootstrap/fuel_bootstrap_cli/fuel_bootstrap/commands/build.py @@ -155,9 +155,7 @@ class BuildCommand(command.Command): '--output-dir', type=str, metavar='DIR', - help="Which directory should contain built image. /tmp/" - " is used by default.", - default="/tmp/" + help="Directory to store built image." ) parser.add_argument( '--image-build-dir', @@ -176,6 +174,13 @@ class BuildCommand(command.Command): help="Notify WebUI with result of command", action='store_true' ) + parser.add_argument( + '--no-compress', + help="Do not compress bootstrap image to tar.gz. Bootstrap" + " files will be stored in output dir. NOTE: Not compressed" + " images are not supported by fuel-bootstrap.", + action='store_true' + ) return parser def take_action(self, parsed_args): diff --git a/contrib/fuel_bootstrap/fuel_bootstrap_cli/fuel_bootstrap/consts.py b/contrib/fuel_bootstrap/fuel_bootstrap_cli/fuel_bootstrap/consts.py index 382975b..86ea858 100644 --- a/contrib/fuel_bootstrap/fuel_bootstrap_cli/fuel_bootstrap/consts.py +++ b/contrib/fuel_bootstrap/fuel_bootstrap_cli/fuel_bootstrap/consts.py @@ -20,7 +20,8 @@ # TODO(asvechnikov): add possibility to specify custom config file CONFIG_FILE = "/etc/fuel-bootstrap-cli/fuel_bootstrap_cli.yaml" METADATA_FILE = "metadata.yaml" -CONTAINER_FORMAT = "tar.gz" +COMPRESSED_CONTAINER_FORMAT = "tar.gz" +UNCOMPRESSED_CONTAINER_FORMAT = "directory" ROOTFS = {'name': 'rootfs', 'mask': 'rootfs', 'compress_format': 'xz', diff --git a/contrib/fuel_bootstrap/fuel_bootstrap_cli/fuel_bootstrap/utils/data.py b/contrib/fuel_bootstrap/fuel_bootstrap_cli/fuel_bootstrap/utils/data.py index 6234188..563848b 100644 --- a/contrib/fuel_bootstrap/fuel_bootstrap_cli/fuel_bootstrap/utils/data.py +++ b/contrib/fuel_bootstrap/fuel_bootstrap_cli/fuel_bootstrap/utils/data.py @@ -32,7 +32,9 @@ class BootstrapDataBuilder(object): def __init__(self, data): self.uuid = six.text_type(uuid.uuid4()) - self.container_format = consts.CONTAINER_FORMAT + self.container_format = consts.COMPRESSED_CONTAINER_FORMAT + if data.get('no_compress'): + self.container_format = consts.UNCOMPRESSED_CONTAINER_FORMAT self.ubuntu_release = \ data.get('ubuntu_release') or \ @@ -63,9 +65,10 @@ class BootstrapDataBuilder(object): self.extend_kopts = data.get('extend_kopts') self.kernel_flavor = data.get('kernel_flavor') - file_name = "{0}.{1}".format(self.uuid, self.container_format) - output_dir = data.get('output_dir', CONF.output_dir) - self.output = os.path.join(output_dir, file_name) + self.output = data.get('output_dir') or CONF.output_dir + if not data.get('no_compress'): + file_name = "{0}.{1}".format(self.uuid, self.container_format) + self.output = os.path.join(self.output, file_name) def build(self): return {