Merge lp:~smoser/cloud-init/opennebula into lp:~vlastimil-holer/cloud-init/opennebula

Proposed by Scott Moser
Status: Merged
Approved by: Vlastimil Holer
Approved revision: 694
Merged at revision: 693
Proposed branch: lp:~smoser/cloud-init/opennebula
Merge into: lp:~vlastimil-holer/cloud-init/opennebula
Diff against target: 177 lines (+46/-24)
3 files modified
cloudinit/sources/DataSourceOpenNebula.py (+25/-23)
cloudinit/sources/__init__.py (+7/-0)
tests/unittests/test_datasource/test_opennebula.py (+14/-1)
To merge this branch: bzr merge lp:~smoser/cloud-init/opennebula
Reviewer Review Type Date Requested Status
Vlastimil Holer Approve
Review via email: mp+184844@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Vlastimil Holer (vlastimil-holer) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'cloudinit/sources/DataSourceOpenNebula.py'
2--- cloudinit/sources/DataSourceOpenNebula.py 2013-09-10 16:35:19 +0000
3+++ cloudinit/sources/DataSourceOpenNebula.py 2013-09-10 18:23:38 +0000
4@@ -23,9 +23,9 @@
5 # along with this program. If not, see <http://www.gnu.org/licenses/>.
6
7 import os
8+import pwd
9 import re
10-import string
11-import subprocess
12+import string # pylint: disable=W0402
13
14 from cloudinit import log as logging
15 from cloudinit import sources
16@@ -58,7 +58,7 @@
17
18 # decide parseuser for context.sh shell reader
19 parseuser = DEFAULT_PARSEUSER
20- if self.ds_cfg.get('parseuser'):
21+ if 'parseuser' in self.ds_cfg:
22 parseuser = self.ds_cfg.get('parseuser')
23
24 candidates = [self.seed_dir]
25@@ -260,13 +260,21 @@
26 return combined
27
28
29-def parse_shell_config(content, keylist=None, bash=None, asuser=None):
30+def switch_user_cmd(user):
31+ return ['sudo', '-u', user]
32+
33+
34+def parse_shell_config(content, keylist=None, bash=None, asuser=None,
35+ switch_user_cb=None):
36
37 if isinstance(bash, str):
38 bash = [bash]
39 elif bash is None:
40 bash = ['bash', '-e']
41
42+ if switch_user_cb is None:
43+ switch_user_cb = switch_user_cmd
44+
45 # allvars expands to all existing variables by using '${!x*}' notation
46 # where x is lower or upper case letters or '_'
47 allvars = ["${!%s*}" % x for x in string.letters + "_"]
48@@ -302,23 +310,17 @@
49 bcmd = ('unset IFS\n' +
50 setup +
51 varprinter(allvars) +
52- '{\n%s\n\n} > /dev/null\n' % content +
53+ '{\n%s\n\n:\n} > /dev/null\n' % content +
54 'unset IFS\n' +
55 varprinter(keylist) + "\n")
56
57 cmd = []
58 if asuser is not None:
59- cmd = ['sudo', '-u', asuser]
60+ cmd = switch_user_cb(asuser)
61
62 cmd.extend(bash)
63
64- sp = subprocess.Popen(cmd, stdin=subprocess.PIPE,
65- stdout=subprocess.PIPE,
66- stderr=subprocess.PIPE)
67- (output, error) = sp.communicate(input=bcmd)
68-
69- if sp.returncode != 0:
70- raise Exception("Process returned %d" % sp.returncode)
71+ (output, _error) = util.subp(cmd, data=bcmd)
72
73 # exclude vars in bash that change on their own or that we used
74 excluded = ("RANDOM", "LINENO", "_", "__v")
75@@ -329,7 +331,7 @@
76
77 # go through output. First _start_ is for 'preset', second for 'target'.
78 # Add to target only things were changed and not in volitile
79- for line in output.split("\0"):
80+ for line in output.split("\x00"):
81 try:
82 (key, val) = line.split("=", 1)
83 if target is preset:
84@@ -367,21 +369,21 @@
85 results = {'userdata': None, 'metadata': {}}
86
87 if "context.sh" in found:
88+ if asuser is not None:
89+ try:
90+ pwd.getpwnam(asuser)
91+ except KeyError as e:
92+ raise BrokenContextDiskDir("configured user '%s' "
93+ "does not exist", asuser)
94 try:
95 with open(os.path.join(source_dir, 'context.sh'), 'r') as f:
96 content = f.read().strip()
97- f.close()
98
99- # don't pass empty context script
100- # to shell parser
101- non_empty = re.match(r'.*?^\s*([^# ]+)', content,
102- re.MULTILINE | re.DOTALL)
103- if non_empty:
104- context = parse_shell_config(content, asuser=asuser)
105+ context = parse_shell_config(content, asuser=asuser)
106+ except util.ProcessExecutionError as e:
107+ raise BrokenContextDiskDir("Error processing context.sh: %s" % (e))
108 except IOError as e:
109 raise NonContextDiskDir("Error reading context.sh: %s" % (e))
110- except Exception as e:
111- raise BrokenContextDiskDir("Error processing context.sh: %s" % (e))
112 else:
113 raise NonContextDiskDir("Missing context.sh")
114
115
116=== modified file 'cloudinit/sources/__init__.py'
117--- cloudinit/sources/__init__.py 2013-09-09 22:46:37 +0000
118+++ cloudinit/sources/__init__.py 2013-09-10 18:23:38 +0000
119@@ -53,9 +53,16 @@
120 self.userdata = None
121 self.metadata = None
122 self.userdata_raw = None
123+
124+ # find the datasource config name.
125+ # remove 'DataSource' from classname on front, and remove 'Net' on end.
126+ # Both Foo and FooNet sources expect config in cfg['sources']['Foo']
127 name = type_utils.obj_name(self)
128 if name.startswith(DS_PREFIX):
129 name = name[len(DS_PREFIX):]
130+ if name.endswith('Net'):
131+ name = name[0:-3]
132+
133 self.ds_cfg = util.get_cfg_by_path(self.sys_cfg,
134 ("datasource", name), {})
135 if not ud_proc:
136
137=== modified file 'tests/unittests/test_datasource/test_opennebula.py'
138--- tests/unittests/test_datasource/test_opennebula.py 2013-09-10 16:35:19 +0000
139+++ tests/unittests/test_datasource/test_opennebula.py 2013-09-10 18:23:38 +0000
140@@ -37,6 +37,7 @@
141
142
143 class TestOpenNebulaDataSource(MockerTestCase):
144+ parsed_user = None
145
146 def setUp(self):
147 super(TestOpenNebulaDataSource, self).setUp()
148@@ -48,6 +49,18 @@
149 self.seed_dir = os.path.join(self.paths.seed_dir, "opennebula")
150 self.sys_cfg = {'datasource': {'OpenNebula': {'dsmode': 'local'}}}
151
152+ # we don't want 'sudo' called in tests. so we patch switch_user_cmd
153+ def my_switch_user_cmd(user):
154+ self.parsed_user = user
155+ return []
156+
157+ self.switch_user_cmd_real = ds.switch_user_cmd
158+ ds.switch_user_cmd = my_switch_user_cmd
159+
160+ def tearDown(self):
161+ ds.switch_user_cmd = self.switch_user_cmd_real
162+ super(TestOpenNebulaDataSource, self).tearDown()
163+
164 def test_get_data_non_contextdisk(self):
165 try:
166 # dont' try to lookup for CDs
167@@ -96,9 +109,9 @@
168 util.find_devs_with = orig_find_devs_with
169
170 def test_get_data(self):
171+ orig_find_devs_with = util.find_devs_with
172 try:
173 # dont' try to lookup for CDs
174- orig_find_devs_with = util.find_devs_with
175 util.find_devs_with = lambda n: []
176 populate_context_dir(self.seed_dir, {'KEY1': 'val1'})
177 dsrc = self.ds(sys_cfg=self.sys_cfg, distro=None, paths=self.paths)

Subscribers

People subscribed via source and target branches