Merge lp:~hazmat/pyjuju/local-origin-passthrough into lp:pyjuju
- local-origin-passthrough
- Merge into trunk
Proposed by
Kapil Thangavelu
Status: | Superseded | ||||
---|---|---|---|---|---|
Proposed branch: | lp:~hazmat/pyjuju/local-origin-passthrough | ||||
Merge into: | lp:pyjuju | ||||
Diff against target: |
790 lines (+383/-39) 24 files modified
docs/source/provider-configuration-ec2.rst (+9/-3) juju/lib/lxc/data/juju-create (+3/-3) juju/providers/common/cloudinit.py (+78/-2) juju/providers/common/launch.py (+9/-2) juju/providers/common/tests/data/cloud_init_bootstrap (+0/-2) juju/providers/common/tests/data/cloud_init_bootstrap_zookeepers (+0/-2) juju/providers/common/tests/data/cloud_init_branch_trunk (+17/-0) juju/providers/common/tests/data/cloud_init_normal (+0/-2) juju/providers/common/tests/data/cloud_init_ppa (+15/-0) juju/providers/common/tests/test_cloudinit.py (+109/-3) juju/providers/ec2/tests/common.py (+1/-0) juju/providers/ec2/tests/data/bootstrap_cloud_init (+0/-2) juju/providers/ec2/tests/data/launch_cloud_init (+0/-2) juju/providers/ec2/tests/data/launch_cloud_init_branch (+20/-0) juju/providers/ec2/tests/data/launch_cloud_init_ppa (+15/-0) juju/providers/ec2/tests/test_bootstrap.py (+1/-0) juju/providers/ec2/tests/test_launch.py (+60/-2) juju/providers/local/agent.py (+5/-3) juju/providers/local/tests/test_agent.py (+1/-0) juju/providers/orchestra/tests/common.py (+3/-1) juju/providers/orchestra/tests/data/bootstrap_user_data (+0/-2) juju/providers/orchestra/tests/data/launch_user_data (+0/-2) juju/state/relation.py (+19/-3) juju/state/tests/test_relation.py (+18/-3) |
||||
To merge this branch: | bzr merge lp:~hazmat/pyjuju/local-origin-passthrough | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Juju Engineering | Pending | ||
Review via email: mp+77644@code.launchpad.net |
This proposal has been superseded by a proposal from 2011-09-30.
Commit message
Description of the change
Local provider should respect juju-origin
Minor fixes to pass juju origin to the machine agent, and to juju-create
to utilize jujuorigin for lp branch names.
To post a comment you must log in.
- 411. By Kapil Thangavelu
-
use default origin util func if none specified
- 412. By Kapil Thangavelu
-
Merged unit-relation-
with-addr into local-origin- passthrough. - 413. By Kapil Thangavelu
-
fix some local provider problems
- 414. By Kapil Thangavelu
-
unit container deploy pulls origin from environment
- 415. By Kapil Thangavelu
-
log master container customization for foresenic analysis, various sundry fixes for juju-origin in a container
- 416. By Kapil Thangavelu
-
add python-yaml dep for branch installs, and switch address map s/lxc/local
- 417. By Kapil Thangavelu
-
fix up customize log test
- 418. By Kapil Thangavelu
-
merge pipeline, resolve conflict
Unmerged revisions
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'docs/source/provider-configuration-ec2.rst' |
2 | --- docs/source/provider-configuration-ec2.rst 2011-09-15 17:41:55 +0000 |
3 | +++ docs/source/provider-configuration-ec2.rst 2011-09-30 05:02:23 +0000 |
4 | @@ -24,9 +24,15 @@ |
5 | An S3 bucket unique to the environment, where some runtime metadata and |
6 | charms are stored. |
7 | |
8 | - juju-branch: |
9 | - Allow a juju bzr branch to be utilized for all machines within an |
10 | - environment. |
11 | + juju-origin: |
12 | + Defines where juju should be obtained for installing in |
13 | + machines. Can be set to a "lp:..." branch url, to "ppa" for |
14 | + getting packages from the official juju PPA, or to "distro" |
15 | + for using packages from the official Ubuntu repositories. |
16 | + |
17 | + If this option is not set, juju will attempt to detect the |
18 | + correct origin based on its run location and the installed |
19 | + juju package. |
20 | |
21 | default-instance-type: |
22 | The instance type to be used for machines launched within the juju |
23 | |
24 | === modified file 'juju/lib/lxc/data/juju-create' |
25 | --- juju/lib/lxc/data/juju-create 2011-09-30 01:57:00 +0000 |
26 | +++ juju/lib/lxc/data/juju-create 2011-09-30 05:02:23 +0000 |
27 | @@ -69,7 +69,7 @@ |
28 | |
29 | if [ $JUJU_ORIGIN = "ppa" ]; then |
30 | echo "Using juju PPA for container" |
31 | - elif [ $JUJU_ORIGIN = "branch" ]; then |
32 | + elif [[ $JUJU_ORIGIN == lp:* ]]; then |
33 | echo "Using juju Branch $JUJU_SOURCE" |
34 | elif [ $JUJU_ORIGIN = "distro" ]; then |
35 | echo "Using juju distribution packages" |
36 | @@ -87,10 +87,10 @@ |
37 | echo y | apt-add-repository ppa:juju/pkgs |
38 | apt-get update |
39 | apt-get install --force-yes -y juju python-txzookeeper |
40 | - elif [ $JUJU_ORIGIN = "branch" ]; then |
41 | + elif [[ $JUJU_ORIGIN = lp:* ]]; then |
42 | apt-get install --force-yes -y python-txzookeeper |
43 | mkdir /usr/lib/juju |
44 | - bzr branch $JUJU_SOURCE /usr/lib/juju/juju |
45 | + bzr branch $JUJU_ORIGIN /usr/lib/juju/juju |
46 | bash -c "cd /usr/lib/juju/juju && sudo python setup.py develop" |
47 | elif [ $JUJU_ORIGIN = "distro" ]; then |
48 | apt-get install --force-yes -y juju python-txzookeeper |
49 | |
50 | === modified file 'juju/providers/common/cloudinit.py' |
51 | --- juju/providers/common/cloudinit.py 2011-09-23 20:35:02 +0000 |
52 | +++ juju/providers/common/cloudinit.py 2011-09-30 05:02:23 +0000 |
53 | @@ -1,3 +1,5 @@ |
54 | +from subprocess import Popen, PIPE |
55 | + |
56 | from juju.errors import CloudInitError |
57 | from juju.providers.common.utils import format_cloud_init |
58 | from juju.state.auth import make_identity |
59 | @@ -54,6 +56,80 @@ |
60 | % zookeeper_hosts] |
61 | |
62 | |
63 | +def _get_apt_cache_policy(): |
64 | + return Popen(["apt-cache", "policy", "juju"], stdout=PIPE).\ |
65 | + communicate()[0] |
66 | + |
67 | + |
68 | +def _parse_apt_cache_policy(data): |
69 | + """Flatten apt-cache policy output to generate (key, value) pairs.""" |
70 | + |
71 | + # Need to parse in two different phases, so set up iterator now |
72 | + data = iter(data.split("\n")) |
73 | + |
74 | + # Parse preamble |
75 | + for row in data: |
76 | + split = row.split(":", 1) |
77 | + if len(split) != 2: |
78 | + yield None, None |
79 | + k, v = split[0].strip(), split[1].strip() |
80 | + yield k, v |
81 | + if k == "Version table": |
82 | + break |
83 | + |
84 | + # Parse version table into tag, priorities |
85 | + tag = None |
86 | + for row in data: |
87 | + row = row.strip() |
88 | + if row.startswith("***"): |
89 | + tag = row |
90 | + elif tag: |
91 | + yield tag, row |
92 | + |
93 | + |
94 | +def parse_juju_origin(data): |
95 | + """Parse output of apt-cache to determine how juju was installed.""" |
96 | + parse = _parse_apt_cache_policy(data) |
97 | + k, _ = parse.next() |
98 | + if k != "juju": |
99 | + # Sanity check: no record at all, the only possibility is that |
100 | + # this being run as a branch |
101 | + return "branch", "lp:juju" |
102 | + |
103 | + version = None |
104 | + for k, v in parse: |
105 | + if k == "Installed": |
106 | + if v == "(none)": |
107 | + return "branch", "lp:juju" |
108 | + version = v |
109 | + if k == "Version table": |
110 | + break |
111 | + |
112 | + for tag, priority in parse: |
113 | + if (version in tag and |
114 | + "http://ppa.launchpad.net/juju/pkgs/" in priority): |
115 | + return "ppa", None |
116 | + |
117 | + return "distro", None |
118 | + |
119 | + |
120 | +def _get_default_origin(): |
121 | + """Select the best fit for running juju on cloudinit. |
122 | + |
123 | + Used if not otherwise specified by juju-origin. |
124 | + """ |
125 | + import juju |
126 | + if not juju.__file__.startswith("/usr/"): |
127 | + return "lp:juju" |
128 | + origin, source = parse_juju_origin(_get_apt_cache_policy()) |
129 | + if origin == "branch": |
130 | + return source |
131 | + elif origin == "ppa": |
132 | + return _PPA |
133 | + else: |
134 | + return _DISTRO |
135 | + |
136 | + |
137 | class CloudInit(object): |
138 | """Encapsulates juju-specific machine initialisation. |
139 | |
140 | @@ -65,7 +141,7 @@ |
141 | self._machine_id = None |
142 | self._instance_id = None |
143 | self._provider_type = None |
144 | - self._source = _PPA |
145 | + self._source = _get_default_origin() |
146 | self._ssh_keys = [] |
147 | self._provision = False |
148 | self._zookeeper = False |
149 | @@ -103,7 +179,7 @@ |
150 | or fewer than one options, are specified. |
151 | |
152 | Note that you don't need to call this method; the juju source |
153 | - defaults to the juju PPA. |
154 | + defaults to what is returned by `get_default_origin`. |
155 | """ |
156 | if len(filter(None, (branch, ppa, distro))) != 1: |
157 | raise CloudInitError("Please specify one source") |
158 | |
159 | === modified file 'juju/providers/common/launch.py' |
160 | --- juju/providers/common/launch.py 2011-09-22 13:23:00 +0000 |
161 | +++ juju/providers/common/launch.py 2011-09-30 05:02:23 +0000 |
162 | @@ -76,8 +76,15 @@ |
163 | cloud_init.add_ssh_key(get_user_authorized_keys(config)) |
164 | cloud_init.set_machine_id(machine_id) |
165 | cloud_init.set_zookeeper_machines(zookeepers) |
166 | - if config.get("juju-branch"): |
167 | - cloud_init.set_juju_source(config["juju-branch"]) |
168 | + origin = config.get("juju-origin") |
169 | + if origin: |
170 | + if origin.startswith("lp:"): |
171 | + cloud_init.set_juju_source(branch=origin) |
172 | + elif origin == "ppa": |
173 | + cloud_init.set_juju_source(ppa=True) |
174 | + else: |
175 | + # Ignore other values, just use the distro for sanity |
176 | + cloud_init.set_juju_source(distro=True) |
177 | if self._master: |
178 | cloud_init.enable_bootstrap() |
179 | cloud_init.set_zookeeper_secret(config["admin-secret"]) |
180 | |
181 | === modified file 'juju/providers/common/tests/data/cloud_init_bootstrap' |
182 | --- juju/providers/common/tests/data/cloud_init_bootstrap 2011-09-23 20:35:02 +0000 |
183 | +++ juju/providers/common/tests/data/cloud_init_bootstrap 2011-09-30 05:02:23 +0000 |
184 | @@ -1,8 +1,6 @@ |
185 | #cloud-config |
186 | apt-update: true |
187 | apt-upgrade: true |
188 | -apt_sources: |
189 | -- {source: 'ppa:juju/pkgs'} |
190 | machine-data: {juju-provider-type: dummy, juju-zookeeper-hosts: 'localhost:2181', |
191 | machine-id: passport} |
192 | output: {all: '| tee -a /var/log/cloud-init-output.log'} |
193 | |
194 | === modified file 'juju/providers/common/tests/data/cloud_init_bootstrap_zookeepers' |
195 | --- juju/providers/common/tests/data/cloud_init_bootstrap_zookeepers 2011-09-23 20:35:02 +0000 |
196 | +++ juju/providers/common/tests/data/cloud_init_bootstrap_zookeepers 2011-09-30 05:02:23 +0000 |
197 | @@ -1,8 +1,6 @@ |
198 | #cloud-config |
199 | apt-update: true |
200 | apt-upgrade: true |
201 | -apt_sources: |
202 | -- {source: 'ppa:juju/pkgs'} |
203 | machine-data: {juju-provider-type: dummy, juju-zookeeper-hosts: 'cotswold:2181,longleat:2181,localhost:2181', |
204 | machine-id: passport} |
205 | output: {all: '| tee -a /var/log/cloud-init-output.log'} |
206 | |
207 | === added file 'juju/providers/common/tests/data/cloud_init_branch_trunk' |
208 | --- juju/providers/common/tests/data/cloud_init_branch_trunk 1970-01-01 00:00:00 +0000 |
209 | +++ juju/providers/common/tests/data/cloud_init_branch_trunk 2011-09-30 05:02:23 +0000 |
210 | @@ -0,0 +1,17 @@ |
211 | +#cloud-config |
212 | +apt-update: true |
213 | +apt-upgrade: true |
214 | +apt_sources: |
215 | +- {source: 'ppa:juju/pkgs'} |
216 | +machine-data: {juju-provider-type: dummy, juju-zookeeper-hosts: 'cotswold:2181,longleat:2181', |
217 | + machine-id: passport} |
218 | +output: {all: '| tee -a /var/log/cloud-init-output.log'} |
219 | +packages: [bzr, byobu, tmux, python-setuptools, python-twisted, python-argparse, python-txaws, |
220 | + python-zookeeper] |
221 | +runcmd: [sudo apt-get install -y python-txzookeeper, sudo mkdir -p /usr/lib/juju, |
222 | + 'cd /usr/lib/juju && sudo /usr/bin/bzr co lp:juju juju', |
223 | + cd /usr/lib/juju/juju && sudo python setup.py develop, sudo mkdir -p /var/lib/juju, |
224 | + sudo mkdir -p /var/log/juju, 'JUJU_MACHINE_ID=passport JUJU_ZOOKEEPER=cotswold:2181,longleat:2181 |
225 | + python -m juju.agents.machine -n --logfile=/var/log/juju/machine-agent.log |
226 | + --pidfile=/var/run/juju/machine-agent.pid'] |
227 | +ssh_authorized_keys: [chubb] |
228 | |
229 | === modified file 'juju/providers/common/tests/data/cloud_init_normal' |
230 | --- juju/providers/common/tests/data/cloud_init_normal 2011-09-15 19:29:57 +0000 |
231 | +++ juju/providers/common/tests/data/cloud_init_normal 2011-09-30 05:02:23 +0000 |
232 | @@ -1,8 +1,6 @@ |
233 | #cloud-config |
234 | apt-update: true |
235 | apt-upgrade: true |
236 | -apt_sources: |
237 | -- {source: 'ppa:juju/pkgs'} |
238 | machine-data: {juju-provider-type: dummy, juju-zookeeper-hosts: 'cotswold:2181,longleat:2181', |
239 | machine-id: passport} |
240 | output: {all: '| tee -a /var/log/cloud-init-output.log'} |
241 | |
242 | === added file 'juju/providers/common/tests/data/cloud_init_ppa' |
243 | --- juju/providers/common/tests/data/cloud_init_ppa 1970-01-01 00:00:00 +0000 |
244 | +++ juju/providers/common/tests/data/cloud_init_ppa 2011-09-30 05:02:23 +0000 |
245 | @@ -0,0 +1,15 @@ |
246 | +#cloud-config |
247 | +apt-update: true |
248 | +apt-upgrade: true |
249 | +apt_sources: |
250 | +- {'source': 'ppa:juju/pkgs'} |
251 | +machine-data: {juju-provider-type: dummy, juju-zookeeper-hosts: 'cotswold:2181,longleat:2181', |
252 | + machine-id: passport} |
253 | +output: {all: '| tee -a /var/log/cloud-init-output.log'} |
254 | +packages: [bzr, byobu, tmux, python-setuptools, python-twisted, python-argparse, python-txaws, |
255 | + python-zookeeper] |
256 | +runcmd: [sudo apt-get -y install juju, sudo mkdir -p /var/lib/juju, sudo mkdir |
257 | + -p /var/log/juju, 'JUJU_MACHINE_ID=passport JUJU_ZOOKEEPER=cotswold:2181,longleat:2181 |
258 | + python -m juju.agents.machine -n --logfile=/var/log/juju/machine-agent.log |
259 | + --pidfile=/var/run/juju/machine-agent.pid'] |
260 | +ssh_authorized_keys: [chubb] |
261 | |
262 | === modified file 'juju/providers/common/tests/test_cloudinit.py' |
263 | --- juju/providers/common/tests/test_cloudinit.py 2011-09-22 13:23:00 +0000 |
264 | +++ juju/providers/common/tests/test_cloudinit.py 2011-09-30 05:02:23 +0000 |
265 | @@ -1,12 +1,14 @@ |
266 | import os |
267 | +import stat |
268 | |
269 | import yaml |
270 | |
271 | from juju.errors import CloudInitError |
272 | from juju.lib.testing import TestCase |
273 | -from juju.providers.common.cloudinit import CloudInit |
274 | +from juju.providers.common.cloudinit import CloudInit, parse_juju_origin |
275 | from juju.providers.dummy import DummyMachine |
276 | |
277 | + |
278 | DATA_DIR = os.path.join(os.path.abspath(os.path.dirname(__file__)), "data") |
279 | |
280 | |
281 | @@ -30,6 +32,7 @@ |
282 | cloud_init.set_provider_type("dummy") |
283 | cloud_init.set_instance_id_accessor("token") |
284 | cloud_init.set_zookeeper_secret("seekrit") |
285 | + cloud_init.set_juju_source(distro=True) |
286 | if with_zookeepers: |
287 | cloud_init.set_zookeeper_machines([ |
288 | DummyMachine("blah", "blah", "cotswold"), |
289 | @@ -74,12 +77,34 @@ |
290 | self.assertEquals(str(error), "Please specify one source") |
291 | |
292 | def test_render_normal(self): |
293 | - self.assert_render(self.construct_normal(), "cloud_init_normal") |
294 | + path = os.environ.get("PATH", "") |
295 | + alt_apt_cache_path = self.makeDir() |
296 | + filename = os.path.join(alt_apt_cache_path, "apt-cache") |
297 | + with open(filename, "w") as f: |
298 | + f.write( |
299 | + "#!/bin/bash\n" |
300 | + "cat <<EOF\n" |
301 | + "juju:\n" |
302 | + " Installed: good-magic-1.0\n" |
303 | + " Candidate: good-magic-1.0\n" |
304 | + " Version table:\n" |
305 | + " *** good-magic-1.0\n" |
306 | + " 500 http://us.archive.ubuntu.com/ubuntu/ " |
307 | + "natty/main amd64 Packages\n" |
308 | + " 100 /var/lib/dpkg/status\n" |
309 | + "EOF\n") |
310 | + os.chmod(filename, stat.S_IEXEC | stat.S_IREAD) |
311 | + updated_path = alt_apt_cache_path + ":" + path |
312 | + self.change_environment(PATH=updated_path) |
313 | + import juju |
314 | + self.patch(juju, "__file__", |
315 | + "/usr/lib/pymodules/python2.7/juju/__init__.pyc") |
316 | + self.assert_render(self.construct_normal(), "cloud_init_distro") |
317 | |
318 | def test_render_ppa_source(self): |
319 | cloud_init = self.construct_normal() |
320 | cloud_init.set_juju_source(ppa=True) |
321 | - self.assert_render(cloud_init, "cloud_init_normal") |
322 | + self.assert_render(cloud_init, "cloud_init_ppa") |
323 | |
324 | def test_render_distro_source(self): |
325 | cloud_init = self.construct_normal() |
326 | @@ -91,9 +116,90 @@ |
327 | cloud_init.set_juju_source(branch="lp:blah/juju/blah-blah") |
328 | self.assert_render(cloud_init, "cloud_init_branch") |
329 | |
330 | + def test_render_branch_source_if_not_installed(self): |
331 | + import juju |
332 | + self.patch(juju, "__file__", "/not/installed/under/usr") |
333 | + cloud_init = self.construct_normal() |
334 | + self.assert_render(cloud_init, "cloud_init_branch_trunk") |
335 | + |
336 | def test_render_bootstrap(self): |
337 | self.assert_render(self.construct_bootstrap(), "cloud_init_bootstrap") |
338 | |
339 | def test_render_bootstrap_with_zookeepers(self): |
340 | self.assert_render( |
341 | self.construct_bootstrap(True), "cloud_init_bootstrap_zookeepers") |
342 | + |
343 | + |
344 | +class ParseJujuOriginTest(TestCase): |
345 | + |
346 | + def test_distro_installed(self): |
347 | + data = ( |
348 | + "juju:\n" |
349 | + " Installed: good-magic-1.0\n" |
350 | + " Candidate: good-magic-1.0\n" |
351 | + " Version table:\n" |
352 | + " *** good-magic-1.0 0\n" |
353 | + " 500 http://us.archive.ubuntu.com/ubuntu/ " |
354 | + "natty/main amd64 Packages\n" |
355 | + " 100 /var/lib/dpkg/status\n") |
356 | + |
357 | + origin, source = parse_juju_origin(data) |
358 | + self.assertEqual(origin, "distro") |
359 | + self.assertEqual(source, None) |
360 | + |
361 | + def test_multiple_versions_available(self): |
362 | + data = ( |
363 | + "juju:\n" |
364 | + " Installed: 0.5+bzr366-1juju1~natty1\n" |
365 | + " Candidate: 0.5+bzr366-1juju1~natty1\n" |
366 | + " Version table:\n" |
367 | + " *** bad-magic-0.5 0\n" |
368 | + " 500 http://us.archive.ubuntu.com/ubuntu/ " |
369 | + "natty/main amd64 Packages\n" |
370 | + " 100 /var/lib/dpkg/status\n" |
371 | + " *** 0.5+bzr366-1juju1~natty1 0\n" |
372 | + " 500 http://ppa.launchpad.net/juju/pkgs/ubuntu/ " |
373 | + "natty/main amd64 Packages\n" |
374 | + " *** 0.5+bzr356-1juju1~natty1 0\n" |
375 | + " 500 http://ppa.launchpad.net/juju/pkgs/ubuntu/ " |
376 | + "natty/main amd64 Packages\n") |
377 | + |
378 | + origin, source = parse_juju_origin(data) |
379 | + self.assertEqual(origin, "ppa") |
380 | + self.assertEqual(source, None) |
381 | + |
382 | + def test_distro_not_installed(self): |
383 | + data = ( |
384 | + "juju:\n" |
385 | + " Installed: (none)\n" |
386 | + " Candidate: good-magic-1.0\n" |
387 | + " Version table:\n" |
388 | + " *** good-magic-1.0 0\n" |
389 | + " 500 http://us.archive.ubuntu.com/ubuntu/ " |
390 | + "natty/main amd64 Packages\n" |
391 | + " 100 /var/lib/dpkg/status\n") |
392 | + |
393 | + origin, source = parse_juju_origin(data) |
394 | + self.assertEqual(origin, "branch") |
395 | + self.assertEqual(source, "lp:juju") |
396 | + |
397 | + def test_ppa_installed(self): |
398 | + data = ( |
399 | + "juju:\n" |
400 | + " Installed: 0.5+bzr356-1juju1~natty1\n" |
401 | + " Candidate: 0.5+bzr356-1juju1~natty1\n" |
402 | + " Version table:\n" |
403 | + " *** 0.5+bzr356-1juju1~natty1 0\n" |
404 | + " 500 http://ppa.launchpad.net/juju/pkgs/ubuntu/ " |
405 | + "natty/main amd64 Packages\n" |
406 | + " 100 /var/lib/dpkg/status\n") |
407 | + |
408 | + origin, source = parse_juju_origin(data) |
409 | + self.assertEqual(origin, "ppa") |
410 | + self.assertEqual(source, None) |
411 | + |
412 | + def test_juju_package_is_unknown(self): |
413 | + data = "N: Unable to locate package juju" |
414 | + origin, source = parse_juju_origin(data) |
415 | + self.assertEqual(origin, "branch") |
416 | + self.assertEqual(source, "lp:juju") |
417 | |
418 | === modified file 'juju/providers/ec2/tests/common.py' |
419 | --- juju/providers/ec2/tests/common.py 2011-09-22 13:23:00 +0000 |
420 | +++ juju/providers/ec2/tests/common.py 2011-09-30 05:02:23 +0000 |
421 | @@ -22,6 +22,7 @@ |
422 | |
423 | def get_config(self): |
424 | return {"type": "ec2", |
425 | + "juju-origin": "distro", |
426 | "admin-secret": "magic-beans", |
427 | "access-key": "0f62e973d5f8", |
428 | "secret-key": "3e5a7c653f59", |
429 | |
430 | === modified file 'juju/providers/ec2/tests/data/bootstrap_cloud_init' |
431 | --- juju/providers/ec2/tests/data/bootstrap_cloud_init 2011-09-23 20:35:02 +0000 |
432 | +++ juju/providers/ec2/tests/data/bootstrap_cloud_init 2011-09-30 05:02:23 +0000 |
433 | @@ -1,8 +1,6 @@ |
434 | #cloud-config |
435 | apt-update: true |
436 | apt-upgrade: true |
437 | -apt_sources: |
438 | -- {source: 'ppa:juju/pkgs'} |
439 | machine-data: {juju-provider-type: ec2, juju-zookeeper-hosts: 'localhost:2181', |
440 | machine-id: '0'} |
441 | output: {all: '| tee -a /var/log/cloud-init-output.log'} |
442 | |
443 | === modified file 'juju/providers/ec2/tests/data/launch_cloud_init' |
444 | --- juju/providers/ec2/tests/data/launch_cloud_init 2011-09-15 19:29:57 +0000 |
445 | +++ juju/providers/ec2/tests/data/launch_cloud_init 2011-09-30 05:02:23 +0000 |
446 | @@ -1,8 +1,6 @@ |
447 | #cloud-config |
448 | apt-update: true |
449 | apt-upgrade: true |
450 | -apt_sources: |
451 | -- {source: 'ppa:juju/pkgs'} |
452 | machine-data: {juju-provider-type: ec2, juju-zookeeper-hosts: 'es.example.internal:2181', |
453 | machine-id: '1'} |
454 | output: {all: '| tee -a /var/log/cloud-init-output.log'} |
455 | |
456 | === added file 'juju/providers/ec2/tests/data/launch_cloud_init_branch' |
457 | --- juju/providers/ec2/tests/data/launch_cloud_init_branch 1970-01-01 00:00:00 +0000 |
458 | +++ juju/providers/ec2/tests/data/launch_cloud_init_branch 2011-09-30 05:02:23 +0000 |
459 | @@ -0,0 +1,20 @@ |
460 | +#cloud-config |
461 | +apt-update: true |
462 | +apt-upgrade: true |
463 | +apt_sources: |
464 | +- {source: 'ppa:juju/pkgs'} |
465 | +machine-data: {juju-provider-type: ec2, juju-zookeeper-hosts: 'es.example.internal:2181', |
466 | + machine-id: '1'} |
467 | +output: {all: '| tee -a /var/log/cloud-init-output.log'} |
468 | +packages: [bzr, byobu, tmux, python-setuptools, python-twisted, python-argparse, python-txaws, |
469 | + python-zookeeper] |
470 | +runcmd: [sudo apt-get install -y python-txzookeeper, |
471 | + sudo mkdir -p /usr/lib/juju, |
472 | + 'cd /usr/lib/juju && sudo /usr/bin/bzr co lp:~wizard/juju-juicebar juju', |
473 | + cd /usr/lib/juju/juju && sudo python setup.py develop, |
474 | + sudo mkdir -p /var/lib/juju, |
475 | + sudo mkdir -p /var/log/juju, |
476 | + 'JUJU_MACHINE_ID=1 JUJU_ZOOKEEPER=es.example.internal:2181 |
477 | + python -m juju.agents.machine -n --logfile=/var/log/juju/machine-agent.log |
478 | + --pidfile=/var/run/juju/machine-agent.pid'] |
479 | +ssh_authorized_keys: [zebra] |
480 | |
481 | === added file 'juju/providers/ec2/tests/data/launch_cloud_init_ppa' |
482 | --- juju/providers/ec2/tests/data/launch_cloud_init_ppa 1970-01-01 00:00:00 +0000 |
483 | +++ juju/providers/ec2/tests/data/launch_cloud_init_ppa 2011-09-30 05:02:23 +0000 |
484 | @@ -0,0 +1,15 @@ |
485 | +#cloud-config |
486 | +apt-update: true |
487 | +apt-upgrade: true |
488 | +apt_sources: |
489 | +- {source: 'ppa:juju/pkgs'} |
490 | +machine-data: {juju-provider-type: ec2, juju-zookeeper-hosts: 'es.example.internal:2181', |
491 | + machine-id: '1'} |
492 | +output: {all: '| tee -a /var/log/cloud-init-output.log'} |
493 | +packages: [bzr, byobu, tmux, python-setuptools, python-twisted, python-argparse, python-txaws, |
494 | + python-zookeeper] |
495 | +runcmd: [sudo apt-get -y install juju, sudo mkdir -p /var/lib/juju, sudo mkdir |
496 | + -p /var/log/juju, 'JUJU_MACHINE_ID=1 JUJU_ZOOKEEPER=es.example.internal:2181 |
497 | + python -m juju.agents.machine -n --logfile=/var/log/juju/machine-agent.log |
498 | + --pidfile=/var/run/juju/machine-agent.pid'] |
499 | +ssh_authorized_keys: [zebra] |
500 | |
501 | === modified file 'juju/providers/ec2/tests/test_bootstrap.py' |
502 | --- juju/providers/ec2/tests/test_bootstrap.py 2011-09-22 13:23:00 +0000 |
503 | +++ juju/providers/ec2/tests/test_bootstrap.py 2011-09-30 05:02:23 +0000 |
504 | @@ -13,6 +13,7 @@ |
505 | |
506 | from .common import EC2TestMixin, EC2MachineLaunchMixin |
507 | |
508 | + |
509 | DATA_DIR = os.path.join(os.path.abspath(os.path.dirname(__file__)), "data") |
510 | |
511 | |
512 | |
513 | === modified file 'juju/providers/ec2/tests/test_launch.py' |
514 | --- juju/providers/ec2/tests/test_launch.py 2011-09-16 00:36:31 +0000 |
515 | +++ juju/providers/ec2/tests/test_launch.py 2011-09-30 05:02:23 +0000 |
516 | @@ -21,10 +21,11 @@ |
517 | class EC2MachineLaunchTest(EC2TestMixin, EC2MachineLaunchMixin, TestCase): |
518 | |
519 | def _mock_launch(self, instance, expect_ami="ami-default", |
520 | - expect_instance_type="m1.small"): |
521 | + expect_instance_type="m1.small", |
522 | + cloud_init="launch_cloud_init"): |
523 | |
524 | def verify_user_data(data): |
525 | - expect_path = os.path.join(DATA_DIR, "launch_cloud_init") |
526 | + expect_path = os.path.join(DATA_DIR, cloud_init) |
527 | with open(expect_path) as f: |
528 | expect_cloud_init = yaml.load(f.read()) |
529 | self.assertEquals(yaml.load(data), expect_cloud_init) |
530 | @@ -75,6 +76,63 @@ |
531 | return d |
532 | |
533 | @inlineCallbacks |
534 | + def test_provider_launch_using_branch(self): |
535 | + """Can use a juju branch to launch a machine""" |
536 | + self.ec2.describe_security_groups() |
537 | + self.mocker.result(succeed([])) |
538 | + self._mock_create_group() |
539 | + self._mock_create_machine_group("1") |
540 | + self._mock_launch_utils(region="us-east-1") |
541 | + self._mock_get_zookeeper_hosts() |
542 | + self._mock_launch( |
543 | + self.get_instance("i-foobar"), |
544 | + cloud_init="launch_cloud_init_branch") |
545 | + self.mocker.replay() |
546 | + |
547 | + provider = self.get_provider() |
548 | + provider.config["juju-origin"] = "lp:~wizard/juju-juicebar" |
549 | + machines = yield provider.start_machine({"machine-id": "1"}) |
550 | + self.assert_machine(machines[0], "i-foobar", "") |
551 | + |
552 | + @inlineCallbacks |
553 | + def test_provider_launch_using_ppa(self): |
554 | + """Can use the juju ppa to launch a machine""" |
555 | + self.ec2.describe_security_groups() |
556 | + self.mocker.result(succeed([])) |
557 | + self._mock_create_group() |
558 | + self._mock_create_machine_group("1") |
559 | + self._mock_launch_utils(region="us-east-1") |
560 | + self._mock_get_zookeeper_hosts() |
561 | + self._mock_launch( |
562 | + self.get_instance("i-foobar"), |
563 | + cloud_init="launch_cloud_init_ppa") |
564 | + self.mocker.replay() |
565 | + |
566 | + provider = self.get_provider() |
567 | + provider.config["juju-origin"] = "ppa" |
568 | + machines = yield provider.start_machine({"machine-id": "1"}) |
569 | + self.assert_machine(machines[0], "i-foobar", "") |
570 | + |
571 | + @inlineCallbacks |
572 | + def test_provider_launch_using_explicit_distro(self): |
573 | + """Can set juju-origin explicitly to `distro`""" |
574 | + self.ec2.describe_security_groups() |
575 | + self.mocker.result(succeed([])) |
576 | + self._mock_create_group() |
577 | + self._mock_create_machine_group("1") |
578 | + self._mock_launch_utils(region="us-east-1") |
579 | + self._mock_get_zookeeper_hosts() |
580 | + self._mock_launch( |
581 | + self.get_instance("i-foobar"), |
582 | + cloud_init="launch_cloud_init") |
583 | + self.mocker.replay() |
584 | + |
585 | + provider = self.get_provider() |
586 | + provider.config["juju-origin"] = "distro" |
587 | + machines = yield provider.start_machine({"machine-id": "1"}) |
588 | + self.assert_machine(machines[0], "i-foobar", "") |
589 | + |
590 | + @inlineCallbacks |
591 | def test_provider_launch_existing_security_group(self): |
592 | """Verify that the launch works if the env security group exists""" |
593 | instance = Instance("i-foobar", "running", dns_name="x1.example.com") |
594 | |
595 | === modified file 'juju/providers/local/agent.py' |
596 | --- juju/providers/local/agent.py 2011-09-27 16:51:50 +0000 |
597 | +++ juju/providers/local/agent.py 2011-09-30 05:02:23 +0000 |
598 | @@ -15,8 +15,7 @@ |
599 | def __init__( |
600 | self, pid_file, zookeeper_hosts=None, machine_id="0", |
601 | log_file=None, juju_directory="/var/lib/juju", |
602 | - juju_unit_namespace="", |
603 | - public_key=None): |
604 | + juju_unit_namespace="", public_key=None, juju_origin="ppa"): |
605 | """ |
606 | :param pid_file: Path to file used to store process id. |
607 | :param machine_id: machine id for the local machine. |
608 | @@ -37,6 +36,7 @@ |
609 | self._juju_unit_namespace = juju_unit_namespace |
610 | self._log_file = log_file |
611 | self._public_key = public_key |
612 | + self._juju_origin = juju_origin |
613 | |
614 | @inlineCallbacks |
615 | def start(self): |
616 | @@ -51,6 +51,7 @@ |
617 | # to the command. |
618 | args = ["sudo", |
619 | "JUJU_ZOOKEEPER=%s" % self._zookeeper_hosts, |
620 | + "JUJU_ORIGIN=%s" % self._juju_origin, |
621 | "JUJU_MACHINE_ID=%s" % self._machine_id, |
622 | "JUJU_HOME=%s" % self._juju_directory, |
623 | "JUJU_UNIT_NS=%s" % self._juju_unit_namespace, |
624 | @@ -60,7 +61,8 @@ |
625 | "--logfile", self._log_file] |
626 | |
627 | if self._public_key: |
628 | - args.insert(1, "JUJU_PUBLIC_KEY=%s" % pipes.quote(self._public_key)) |
629 | + args.insert( |
630 | + 1, "JUJU_PUBLIC_KEY=%s" % pipes.quote(self._public_key)) |
631 | |
632 | yield deferToThread(subprocess.check_call, args) |
633 | |
634 | |
635 | === modified file 'juju/providers/local/tests/test_agent.py' |
636 | --- juju/providers/local/tests/test_agent.py 2011-09-27 16:51:50 +0000 |
637 | +++ juju/providers/local/tests/test_agent.py 2011-09-30 05:02:23 +0000 |
638 | @@ -47,6 +47,7 @@ |
639 | dict(JUJU_ZOOKEEPER=get_test_zookeeper_address(), |
640 | JUJU_MACHINE_ID="0", |
641 | JUJU_HOME=juju_directory, |
642 | + JUJU_ORIGIN="ppa", |
643 | JUJU_UNIT_NS="ns1")) |
644 | |
645 | @inlineCallbacks |
646 | |
647 | === modified file 'juju/providers/orchestra/tests/common.py' |
648 | --- juju/providers/orchestra/tests/common.py 2011-09-22 13:23:00 +0000 |
649 | +++ juju/providers/orchestra/tests/common.py 2011-09-30 05:02:23 +0000 |
650 | @@ -13,7 +13,9 @@ |
651 | |
652 | DATA_DIR = os.path.join(os.path.abspath(os.path.dirname(__file__)), "data") |
653 | |
654 | -CONFIG = {"orchestra-server": "somewhe.re", |
655 | +CONFIG = {"type": "orchestra", |
656 | + "juju-origin": "distro", |
657 | + "orchestra-server": "somewhe.re", |
658 | "orchestra-user": "user", |
659 | "orchestra-pass": "pass", |
660 | "acquired-mgmt-class": "acquired", |
661 | |
662 | === modified file 'juju/providers/orchestra/tests/data/bootstrap_user_data' |
663 | --- juju/providers/orchestra/tests/data/bootstrap_user_data 2011-09-23 20:35:02 +0000 |
664 | +++ juju/providers/orchestra/tests/data/bootstrap_user_data 2011-09-30 05:02:23 +0000 |
665 | @@ -1,8 +1,6 @@ |
666 | #cloud-config |
667 | apt-update: true |
668 | apt-upgrade: true |
669 | -apt_sources: |
670 | -- {source: 'ppa:juju/pkgs'} |
671 | machine-data: {juju-provider-type: orchestra, juju-zookeeper-hosts: 'localhost:2181', |
672 | machine-id: '0'} |
673 | output: {all: '| tee -a /var/log/cloud-init-output.log'} |
674 | |
675 | === modified file 'juju/providers/orchestra/tests/data/launch_user_data' |
676 | --- juju/providers/orchestra/tests/data/launch_user_data 2011-09-16 14:07:03 +0000 |
677 | +++ juju/providers/orchestra/tests/data/launch_user_data 2011-09-30 05:02:23 +0000 |
678 | @@ -1,8 +1,6 @@ |
679 | #cloud-config |
680 | apt-update: true |
681 | apt-upgrade: true |
682 | -apt_sources: |
683 | -- {source: 'ppa:juju/pkgs'} |
684 | machine-data: {juju-provider-type: orchestra, juju-zookeeper-hosts: 'jennifer:2181', |
685 | machine-id: '42'} |
686 | output: {all: '| tee -a /var/log/cloud-init-output.log'} |
687 | |
688 | === modified file 'juju/state/relation.py' |
689 | --- juju/state/relation.py 2011-09-15 18:50:23 +0000 |
690 | +++ juju/state/relation.py 2011-09-30 05:02:23 +0000 |
691 | @@ -218,6 +218,10 @@ |
692 | def add_unit_state(self, unit_state): |
693 | """Add a unit to the service relation. |
694 | |
695 | + This api is intended for use by the unit agent, as it |
696 | + also creates an ephemeral presence node, denoting the |
697 | + active existance of the unit in the relation. |
698 | + |
699 | returns a unit relation state. |
700 | """ |
701 | settings_path = "/relations/%s/settings/%s" % ( |
702 | @@ -225,11 +229,23 @@ |
703 | |
704 | # We create settings node first, so that presence node events |
705 | # have a chance to inspect state. |
706 | + |
707 | + # Prepopulate the relation node with the node's private address. |
708 | + private_address = yield unit_state.get_private_address() |
709 | try: |
710 | - yield self._client.create(settings_path) |
711 | + yield self._client.create( |
712 | + settings_path, |
713 | + yaml.safe_dump({"private-address": private_address})) |
714 | except zookeeper.NodeExistsException: |
715 | - # previous persistent settings are not an error. |
716 | - pass |
717 | + # previous persistent settings are not an error, but |
718 | + # update the unit address |
719 | + def update_address(content, stat): |
720 | + unit_map = yaml.load(content) |
721 | + if not unit_map: |
722 | + unit_map = {} |
723 | + unit_map["private-address"] = private_address |
724 | + return yaml.safe_dump(unit_map) |
725 | + yield retry_change(self._client, settings_path, update_address) |
726 | |
727 | # Update the unit name -> id mapping on the relation node |
728 | def update_unit_mapping(content, stat): |
729 | |
730 | === modified file 'juju/state/tests/test_relation.py' |
731 | --- juju/state/tests/test_relation.py 2011-09-28 10:38:16 +0000 |
732 | +++ juju/state/tests/test_relation.py 2011-09-30 05:02:23 +0000 |
733 | @@ -577,6 +577,8 @@ |
734 | self.client.exists_and_watch(settings_path)[1].addCallback( |
735 | lambda result: append_event("settings", result)) |
736 | |
737 | + yield unit_state.set_private_address("foobar.local") |
738 | + |
739 | # add the unit agent |
740 | yield self.service1_relation.add_unit_state(unit_state) |
741 | |
742 | @@ -597,6 +599,10 @@ |
743 | unit_map, |
744 | {unit_state.internal_id: unit_state.unit_name}) |
745 | |
746 | + content, stat = yield self.client.get(settings_path) |
747 | + self.assertEqual( |
748 | + yaml.load(content), {"private-address": "foobar.local"}) |
749 | + |
750 | @inlineCallbacks |
751 | def test_presence_node_is_ephemeral(self): |
752 | """ |
753 | @@ -648,17 +654,26 @@ |
754 | |
755 | @inlineCallbacks |
756 | def test_add_unit_state_with_preexisting_settings(self): |
757 | - """A unit coming backup retains its existing settings.""" |
758 | + """A unit coming backup retains its existing settings. |
759 | + |
760 | + With the exception of the unit address, which is always |
761 | + kept current on subsequent joinings. |
762 | + """ |
763 | unit_state = yield self.service_state1.add_unit_state() |
764 | settings_path = "/relations/%s/settings/%s" % ( |
765 | self.relation_state.internal_id, |
766 | unit_state.internal_id) |
767 | |
768 | - data = {"hello": "world"} |
769 | + data = {"hello": "world", "private-address": "foobar.local"} |
770 | yield self.client.create(settings_path, yaml.dump(data)) |
771 | + |
772 | + yield unit_state.set_private_address("northwest.local") |
773 | yield self.service1_relation.add_unit_state(unit_state) |
774 | |
775 | node_data, stat = yield self.client.get(settings_path) |
776 | + |
777 | + # The unit address has been updated to current |
778 | + data["private-address"] = "northwest.local" |
779 | self.assertEqual(node_data, yaml.dump(data)) |
780 | |
781 | data, stat = yield self.client.get( |
782 | @@ -731,7 +746,7 @@ |
783 | unit_relation = states["unit_relation"] |
784 | |
785 | data = yield unit_relation.get_data() |
786 | - self.assertEqual(data, "") |
787 | + self.assertEqual(yaml.load(data), {"private-address": None}) |
788 | |
789 | unit_relation_path = self.get_unit_settings_path(states) |
790 | self.client.set(unit_relation_path, yaml.dump(dict(hello="world"))) |