Merge lp:~harlowja/cloud-init/migrator-module into lp:~cloud-init-dev/cloud-init/trunk

Proposed by Joshua Harlow
Status: Merged
Merged at revision: 710
Proposed branch: lp:~harlowja/cloud-init/migrator-module
Merge into: lp:~cloud-init-dev/cloud-init/trunk
Diff against target: 138 lines (+92/-1)
3 files modified
cloudinit/config/cc_migrator.py (+83/-0)
cloudinit/helpers.py (+8/-1)
config/cloud.cfg (+1/-0)
To merge this branch: bzr merge lp:~harlowja/cloud-init/migrator-module
Reviewer Review Type Date Requested Status
Scott Moser Pending
Review via email: mp+133409@code.launchpad.net
To post a comment you must log in.
703. By harlowja <email address hidden>

1. Check the name and not the full path
   when applying the canon routine.
2. Add in a function to migrate legacy
   semaphores to new semaphores.

704. By harlowja <email address hidden>

1. Ensure that the sem_path exists and
   is actually a valid value returned.
2. Adjust variable naming

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added file 'cloudinit/config/cc_migrator.py'
--- cloudinit/config/cc_migrator.py 1970-01-01 00:00:00 +0000
+++ cloudinit/config/cc_migrator.py 2012-11-08 07:22:20 +0000
@@ -0,0 +1,83 @@
1# vi: ts=4 expandtab
2#
3# Copyright (C) 2012 Yahoo! Inc.
4#
5# Author: Joshua Harlow <harlowja@yahoo-inc.com>
6#
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU General Public License version 3, as
9# published by the Free Software Foundation.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program. If not, see <http://www.gnu.org/licenses/>.
18
19import os
20import shutil
21
22from cloudinit import helpers
23from cloudinit import util
24
25from cloudinit.settings import PER_ALWAYS
26
27frequency = PER_ALWAYS
28
29
30def _migrate_canon_sems(cloud):
31 sem_path = cloud.paths.get_ipath('sem')
32 if not sem_path or not os.path.exists(sem_path):
33 return 0
34 am_adjusted = 0
35 for p in os.listdir(sem_path):
36 full_path = os.path.join(sem_path, p)
37 if os.path.isfile(full_path):
38 (name, ext) = os.path.splitext(p)
39 canon_name = helpers.canon_sem_name(name)
40 if canon_name != name:
41 new_path = os.path.join(sem_path, canon_name + ext)
42 shutil.move(full_path, new_path)
43 am_adjusted += 1
44 return am_adjusted
45
46
47def _migrate_legacy_sems(cloud, log):
48 sem_path = cloud.paths.get_ipath('sem')
49 if not sem_path or not os.path.exists(sem_path):
50 return
51 legacy_adjust = {
52 'apt-update-upgrade': [
53 'apt-configure',
54 'package-update-upgrade-install',
55 ],
56 }
57 sem_helper = helpers.FileSemaphores(sem_path)
58 for (mod_name, migrate_to) in legacy_adjust.items():
59 possibles = [mod_name, helpers.canon_sem_name(mod_name)]
60 old_exists = []
61 for p in os.listdir(sem_path):
62 (name, _ext) = os.path.splitext(p)
63 if name in possibles and os.path.isfile(p):
64 old_exists.append(p)
65 for p in old_exists:
66 util.del_file(os.path.join(sem_path, p))
67 (_name, freq) = os.path.splitext(p)
68 for m in migrate_to:
69 log.debug("Migrating %s => %s with the same frequency",
70 p, m)
71 with sem_helper.lock(m, freq):
72 pass
73
74
75def handle(name, cfg, cloud, log, _args):
76 do_migrate = util.get_cfg_option_str(cfg, "migrate", True)
77 if not util.translate_bool(do_migrate):
78 log.debug("Skipping module named %s, migration disabled", name)
79 return
80 sems_moved = _migrate_canon_sems(cloud)
81 log.debug("Migrated %s semaphore files to there canonicalized names",
82 sems_moved)
83 _migrate_legacy_sems(cloud, log)
084
=== modified file 'cloudinit/helpers.py'
--- cloudinit/helpers.py 2012-10-28 02:25:48 +0000
+++ cloudinit/helpers.py 2012-11-08 07:22:20 +0000
@@ -71,12 +71,17 @@
71 return "<%s using file %r>" % (util.obj_name(self), self.fn)71 return "<%s using file %r>" % (util.obj_name(self), self.fn)
7272
7373
74def canon_sem_name(name):
75 return name.replace("-", "_")
76
77
74class FileSemaphores(object):78class FileSemaphores(object):
75 def __init__(self, sem_path):79 def __init__(self, sem_path):
76 self.sem_path = sem_path80 self.sem_path = sem_path
7781
78 @contextlib.contextmanager82 @contextlib.contextmanager
79 def lock(self, name, freq, clear_on_fail=False):83 def lock(self, name, freq, clear_on_fail=False):
84 name = canon_sem_name(name)
80 try:85 try:
81 yield self._acquire(name, freq)86 yield self._acquire(name, freq)
82 except:87 except:
@@ -85,6 +90,7 @@
85 raise90 raise
8691
87 def clear(self, name, freq):92 def clear(self, name, freq):
93 name = canon_sem_name(name)
88 sem_file = self._get_path(name, freq)94 sem_file = self._get_path(name, freq)
89 try:95 try:
90 util.del_file(sem_file)96 util.del_file(sem_file)
@@ -119,6 +125,7 @@
119 def has_run(self, name, freq):125 def has_run(self, name, freq):
120 if not freq or freq == PER_ALWAYS:126 if not freq or freq == PER_ALWAYS:
121 return False127 return False
128 name = canon_sem_name(name)
122 sem_file = self._get_path(name, freq)129 sem_file = self._get_path(name, freq)
123 # This isn't really a good atomic check130 # This isn't really a good atomic check
124 # but it suffices for where and when cloudinit runs131 # but it suffices for where and when cloudinit runs
125132
=== modified file 'config/cloud.cfg'
--- config/cloud.cfg 2012-11-07 15:23:32 +0000
+++ config/cloud.cfg 2012-11-08 07:22:20 +0000
@@ -23,6 +23,7 @@
2323
24# The modules that run in the 'init' stage24# The modules that run in the 'init' stage
25cloud_init_modules:25cloud_init_modules:
26 - migrator
26 - bootcmd27 - bootcmd
27 - write-files28 - write-files
28 - resizefs29 - resizefs