Refactor block-device base functions.

As part of the final steps, refactor the bits belonging
to block device and functions. This is a partial refactor
from I3600c6a3d663c697b59d91bd3fbb5e408af345e4

Change-Id: I7aa4fe0466e44846d8fa3194575d446fe4b5b2e6
Co-Authored-By: Andreas Florath <andreas@florath.net>
This commit is contained in:
Yolanda Robla 2017-05-01 12:17:21 +02:00 committed by yolanda.robla
parent 02d4f667ff
commit e21935626b
3 changed files with 50 additions and 19 deletions

View File

@ -114,6 +114,30 @@ class BlockDevice(object):
else: else:
v['label'] = "cloudimg-rootfs" 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 @staticmethod
def _load_json(file_name): def _load_json(file_name):
if os.path.exists(file_name): if os.path.exists(file_name):
@ -156,6 +180,7 @@ class BlockDevice(object):
json.dump(state, fd) json.dump(state, fd)
def create_graph(self, config, default_config): def create_graph(self, config, default_config):
logger.debug("Create graph [%s]" % config)
# This is the directed graph of nodes: each parse method must # This is the directed graph of nodes: each parse method must
# add the appropriate nodes and edges. # add the appropriate nodes and edges.
dg = Digraph() dg = Digraph()
@ -205,6 +230,9 @@ class BlockDevice(object):
with open(self.params['config'], "rt") as config_fd: with open(self.params['config'], "rt") as config_fd:
self.config = yaml.safe_load(config_fd) self.config = yaml.safe_load(config_fd)
logger.debug("Config before merge [%s]" % self.config) 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() self._merge_into_config()
logger.debug("Final config [%s]" % self.config) logger.debug("Final config [%s]" % self.config)
# Write the final config # Write the final config
@ -241,27 +269,32 @@ class BlockDevice(object):
logger.info("create() called") logger.info("create() called")
logger.debug("Using config [%s]" % self.config) logger.debug("Using config [%s]" % self.config)
result = {} self.state = {}
rollback = [] rollback = []
try: try:
self.create(result, rollback) self.create(self.state, rollback)
except BlockDeviceSetupException as bdse: except BlockDeviceSetupException as bdse:
logger.error("exception [%s]" % bdse) logger.error("exception [%s]" % bdse)
for rollback_cb in reversed(rollback): for rollback_cb in reversed(rollback):
rollback_cb() rollback_cb()
sys.exit(1) sys.exit(1)
self.write_state(result) self.write_state(self.state)
logger.info("create() finished") logger.info("create() finished")
return 0 return 0
def cmd_umount(self): def cmd_umount(self):
"""Unmounts the blockdevice and cleanup resources""" """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) dg, call_order = self.create_graph(self.config, self.params)
reverse_order = reversed(call_order) reverse_order = reversed(call_order)
if dg is None: if dg is None:
return 0 return 0
for node in reverse_order: for node in reverse_order:
@ -276,8 +309,6 @@ class BlockDevice(object):
dg, call_order = self.create_graph(self.config, self.params) dg, call_order = self.create_graph(self.config, self.params)
reverse_order = reversed(call_order) reverse_order = reversed(call_order)
if dg is None:
return 0
for node in reverse_order: for node in reverse_order:
node.cleanup(self.state) node.cleanup(self.state)
@ -293,8 +324,6 @@ class BlockDevice(object):
dg, call_order = self.create_graph(self.config, self.params) dg, call_order = self.create_graph(self.config, self.params)
reverse_order = reversed(call_order) reverse_order = reversed(call_order)
if dg is None:
return 0
for node in reverse_order: for node in reverse_order:
node.delete(self.state) node.delete(self.state)

View File

@ -417,17 +417,12 @@ if [[ $IMAGE_ELEMENT =~ vm ]]; then
done done
fi 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 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. # there is the need to handle the old environment variables.
echo "image-size: ${DIB_IMAGE_SIZE}KiB" >> ${DIB_BLOCK_DEVICE_PARAMS_YAML} 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 # re-run dib-block-device init because some value might
# change based on the new set parameters. # change based on the new set parameters.
dib-block-device --phase=init \ dib-block-device --phase=init \
@ -460,7 +455,16 @@ if echo "$FS_TYPE" | grep -q "^ext"; then
fi fi
mkdir $TMP_BUILD_DIR/mnt mkdir $TMP_BUILD_DIR/mnt
sudo mount ${IMAGE_BLOCK_DEVICE} $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 mount_proc_dev_sys
run_d_in_target finalise run_d_in_target finalise
finalise_base finalise_base

View File

@ -50,10 +50,8 @@ function trap_cleanup() {
} }
function cleanup () { function cleanup () {
DIB_BLOCK_DEVICE_SCRIPT=$(which dib-block-device) dib-block-device --phase=umount \
sudo -E ${DIB_BLOCK_DEVICE_SCRIPT} \ --params="${DIB_BLOCK_DEVICE_PARAMS_YAML}"
--phase=umount \
--build-dir="${TMP_BUILD_DIR}"
unmount_image unmount_image
cleanup_build_dir cleanup_build_dir
cleanup_image_dir cleanup_image_dir