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