diff --git a/diskimage_builder/block_device/blockdevice.py b/diskimage_builder/block_device/blockdevice.py index 571aab3e3..fc7917f3d 100644 --- a/diskimage_builder/block_device/blockdevice.py +++ b/diskimage_builder/block_device/blockdevice.py @@ -114,6 +114,30 @@ class BlockDevice(object): else: v['label'] = "cloudimg-rootfs" + @staticmethod + def _config_tree_to_digraph(tconfig, plugin_manager): + """Converts a possible tree-like config into a complete digraph""" + dconfig = [] + for config_entry in tconfig: + if len(config_entry) != 1: + logger.error("Invalid config entry: more than one key " + "on top level [%s]" % config_entry) + raise BlockDeviceSetupException( + "Top level config must contain exactly one key per entry") + logger.debug("Config entry [%s]" % config_entry) + config_key = config_entry.keys()[0] + config_value = config_entry[config_key] + name = config_value['name'] \ + if 'name' in config_value else None + if config_key not in plugin_manager: + dconfig.append(config_entry) + else: + plugin_manager[config_key].plugin \ + .tree_config.config_tree_to_digraph( + config_key, config_value, dconfig, name, + plugin_manager) + return dconfig + @staticmethod def _load_json(file_name): if os.path.exists(file_name): @@ -156,6 +180,7 @@ class BlockDevice(object): json.dump(state, fd) def create_graph(self, config, default_config): + logger.debug("Create graph [%s]" % config) # This is the directed graph of nodes: each parse method must # add the appropriate nodes and edges. dg = Digraph() @@ -205,6 +230,9 @@ class BlockDevice(object): with open(self.params['config'], "rt") as config_fd: self.config = yaml.safe_load(config_fd) logger.debug("Config before merge [%s]" % self.config) + self.config = self._config_tree_to_digraph(self.config, + self.plugin_manager) + logger.debug("Config before merge [%s]" % self.config) self._merge_into_config() logger.debug("Final config [%s]" % self.config) # Write the final config @@ -241,27 +269,32 @@ class BlockDevice(object): logger.info("create() called") logger.debug("Using config [%s]" % self.config) - result = {} + self.state = {} rollback = [] try: - self.create(result, rollback) + self.create(self.state, rollback) except BlockDeviceSetupException as bdse: logger.error("exception [%s]" % bdse) for rollback_cb in reversed(rollback): rollback_cb() sys.exit(1) - self.write_state(result) + self.write_state(self.state) logger.info("create() finished") return 0 def cmd_umount(self): """Unmounts the blockdevice and cleanup resources""" + if self.state is None: + logger.info("State already cleaned - no way to do anything here") + return 0 + # Deleting must be done in reverse order dg, call_order = self.create_graph(self.config, self.params) reverse_order = reversed(call_order) + if dg is None: return 0 for node in reverse_order: @@ -276,8 +309,6 @@ class BlockDevice(object): dg, call_order = self.create_graph(self.config, self.params) reverse_order = reversed(call_order) - if dg is None: - return 0 for node in reverse_order: node.cleanup(self.state) @@ -293,8 +324,6 @@ class BlockDevice(object): dg, call_order = self.create_graph(self.config, self.params) reverse_order = reversed(call_order) - if dg is None: - return 0 for node in reverse_order: node.delete(self.state) diff --git a/diskimage_builder/lib/disk-image-create b/diskimage_builder/lib/disk-image-create index e559aba51..56e065e9b 100644 --- a/diskimage_builder/lib/disk-image-create +++ b/diskimage_builder/lib/disk-image-create @@ -417,17 +417,12 @@ if [[ $IMAGE_ELEMENT =~ vm ]]; then done fi -# There is the need to get the path of the dib-block-device entry -# point, because when running in a venv, the standard path of -# sudo does not include this. -DIB_BLOCK_DEVICE_SCRIPT=$(which dib-block-device) - if [ -z ${IMAGE_BLOCK_DEVICE} ] ; then - # For compatibility reasons in addition to the YAML configuration + # For compatibily reasons in addition to the YAML configuration # there is the need to handle the old environment variables. echo "image-size: ${DIB_IMAGE_SIZE}KiB" >> ${DIB_BLOCK_DEVICE_PARAMS_YAML} - # After changing the parameters, there is the need to + # After changeing the parameters, there is the need to # re-run dib-block-device init because some value might # change based on the new set parameters. dib-block-device --phase=init \ @@ -460,7 +455,16 @@ if echo "$FS_TYPE" | grep -q "^ext"; then fi mkdir $TMP_BUILD_DIR/mnt sudo mount ${IMAGE_BLOCK_DEVICE} $TMP_BUILD_DIR/mnt -sudo mv -t $TMP_BUILD_DIR/mnt ${TMP_BUILD_DIR}/built/* + +# 'mv' is not usable here - especially when a top level directory +# has the same name as a mount point of a partition. If so, 'mv' +# will complain: +# mv: inter-device move failed: '...' to '...'; \ +# unable to remove target: Device or resource busy +# therefore a 'cp' and 'rm' approach is used. +sudo cp -ra ${TMP_BUILD_DIR}/built/* $TMP_BUILD_DIR/mnt +sudo rm -fr ${TMP_BUILD_DIR}/built/* + mount_proc_dev_sys run_d_in_target finalise finalise_base diff --git a/diskimage_builder/lib/img-functions b/diskimage_builder/lib/img-functions index d1163904e..d790823a2 100644 --- a/diskimage_builder/lib/img-functions +++ b/diskimage_builder/lib/img-functions @@ -50,10 +50,8 @@ function trap_cleanup() { } function cleanup () { - DIB_BLOCK_DEVICE_SCRIPT=$(which dib-block-device) - sudo -E ${DIB_BLOCK_DEVICE_SCRIPT} \ - --phase=umount \ - --build-dir="${TMP_BUILD_DIR}" + dib-block-device --phase=umount \ + --params="${DIB_BLOCK_DEVICE_PARAMS_YAML}" unmount_image cleanup_build_dir cleanup_image_dir