diff options
author | Joshua Harlow <harlowja@gmail.com> | 2012-11-10 22:02:19 -0500 |
---|---|---|
committer | Scott Moser <smoser@ubuntu.com> | 2012-11-10 22:02:19 -0500 |
commit | cec15471c0fc7008cad607da222dd3c177e764b6 (patch) | |
tree | 72ccc6fafd7bbaf7d18f0b2f92d0413c7a4cb8ac | |
parent | efa2dfa699bc9222105850641a2820ceda9bfe67 (diff) | |
parent | 196badd4cfa5f9f76be1138fb2d073649af3e031 (diff) | |
download | vyos-cloud-init-cec15471c0fc7008cad607da222dd3c177e764b6.tar.gz vyos-cloud-init-cec15471c0fc7008cad607da222dd3c177e764b6.zip |
Add 'migrator' for handling config name changes and consistency
This migrator module does a few things
* fixes filename markers that were written with a '-' in them to have
an '_' instead
* support renaming modules. Explicitly this handles the name change
of 'apt-update-upgrade' to 'apt-configure' and
'package-update-upgrade-install'
Also, just be more consistent everywhere where writing semaphore/marker
files and use '_' instead of '-' (canon_sem_name).
-rw-r--r-- | cloudinit/config/cc_migrator.py | 83 | ||||
-rw-r--r-- | cloudinit/helpers.py | 9 | ||||
-rw-r--r-- | config/cloud.cfg | 1 |
3 files changed, 92 insertions, 1 deletions
diff --git a/cloudinit/config/cc_migrator.py b/cloudinit/config/cc_migrator.py new file mode 100644 index 00000000..58232fc9 --- /dev/null +++ b/cloudinit/config/cc_migrator.py @@ -0,0 +1,83 @@ +# vi: ts=4 expandtab +# +# Copyright (C) 2012 Yahoo! Inc. +# +# Author: Joshua Harlow <harlowja@yahoo-inc.com> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 3, as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import os +import shutil + +from cloudinit import helpers +from cloudinit import util + +from cloudinit.settings import PER_ALWAYS + +frequency = PER_ALWAYS + + +def _migrate_canon_sems(cloud): + sem_path = cloud.paths.get_ipath('sem') + if not sem_path or not os.path.exists(sem_path): + return 0 + am_adjusted = 0 + for p in os.listdir(sem_path): + full_path = os.path.join(sem_path, p) + if os.path.isfile(full_path): + (name, ext) = os.path.splitext(p) + canon_name = helpers.canon_sem_name(name) + if canon_name != name: + new_path = os.path.join(sem_path, canon_name + ext) + shutil.move(full_path, new_path) + am_adjusted += 1 + return am_adjusted + + +def _migrate_legacy_sems(cloud, log): + sem_path = cloud.paths.get_ipath('sem') + if not sem_path or not os.path.exists(sem_path): + return + legacy_adjust = { + 'apt-update-upgrade': [ + 'apt-configure', + 'package-update-upgrade-install', + ], + } + sem_helper = helpers.FileSemaphores(sem_path) + for (mod_name, migrate_to) in legacy_adjust.items(): + possibles = [mod_name, helpers.canon_sem_name(mod_name)] + old_exists = [] + for p in os.listdir(sem_path): + (name, _ext) = os.path.splitext(p) + if name in possibles and os.path.isfile(p): + old_exists.append(p) + for p in old_exists: + util.del_file(os.path.join(sem_path, p)) + (_name, freq) = os.path.splitext(p) + for m in migrate_to: + log.debug("Migrating %s => %s with the same frequency", + p, m) + with sem_helper.lock(m, freq): + pass + + +def handle(name, cfg, cloud, log, _args): + do_migrate = util.get_cfg_option_str(cfg, "migrate", True) + if not util.translate_bool(do_migrate): + log.debug("Skipping module named %s, migration disabled", name) + return + sems_moved = _migrate_canon_sems(cloud) + log.debug("Migrated %s semaphore files to there canonicalized names", + sems_moved) + _migrate_legacy_sems(cloud, log) diff --git a/cloudinit/helpers.py b/cloudinit/helpers.py index 985ce3e5..d26625a0 100644 --- a/cloudinit/helpers.py +++ b/cloudinit/helpers.py @@ -71,12 +71,17 @@ class FileLock(object): return "<%s using file %r>" % (util.obj_name(self), self.fn) +def canon_sem_name(name): + return name.replace("-", "_") + + class FileSemaphores(object): - def __init__(self, sem_path): + def __init__(self, sem_path): self.sem_path = sem_path @contextlib.contextmanager def lock(self, name, freq, clear_on_fail=False): + name = canon_sem_name(name) try: yield self._acquire(name, freq) except: @@ -85,6 +90,7 @@ class FileSemaphores(object): raise def clear(self, name, freq): + name = canon_sem_name(name) sem_file = self._get_path(name, freq) try: util.del_file(sem_file) @@ -119,6 +125,7 @@ class FileSemaphores(object): def has_run(self, name, freq): if not freq or freq == PER_ALWAYS: return False + name = canon_sem_name(name) sem_file = self._get_path(name, freq) # This isn't really a good atomic check # but it suffices for where and when cloudinit runs diff --git a/config/cloud.cfg b/config/cloud.cfg index 05bb4eef..ad100fff 100644 --- a/config/cloud.cfg +++ b/config/cloud.cfg @@ -23,6 +23,7 @@ preserve_hostname: false # The modules that run in the 'init' stage cloud_init_modules: + - migrator - bootcmd - write-files - resizefs |