Merge lp:~adam-stokes/landscape-charm/add-conjure-up into lp:~landscape/landscape-charm/trunk
- add-conjure-up
- Merge into trunk
Proposed by
Adam Stokes
Status: | Superseded |
---|---|
Proposed branch: | lp:~adam-stokes/landscape-charm/add-conjure-up |
Merge into: | lp:~landscape/landscape-charm/trunk |
Diff against target: |
786 lines (+723/-0) (has conflicts) 12 files modified
Makefile (+18/-0) README.md (+28/-0) charm-store (+23/-0) conjure/metadata.json (+5/-0) conjure/steps/01_register-autopilot.sh (+13/-0) conjure/steps/configure-landscape (+210/-0) landscape-dense-maas.yaml (+63/-0) landscape-dense.yaml (+59/-0) landscape-scalable.yaml (+49/-0) landscape-template.jinja2 (+99/-0) render-bundles (+58/-0) update-charm-revisions (+98/-0) Conflict adding file Makefile. Moved existing file to Makefile.moved. Conflict adding file README.md. Moved existing file to README.md.moved. |
To merge this branch: | bzr merge lp:~adam-stokes/landscape-charm/add-conjure-up |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Landscape | Pending | ||
Landscape | Pending | ||
Review via email: mp+295260@code.launchpad.net |
Commit message
Description of the change
This adds the proper metadata to make this bundle conjure-up enabled. Additionally, I've added tags to the bundle to add more context to what this bundle provides.
To post a comment you must log in.
- 25. By Adam Stokes
-
add make render output
- 26. By Adam Stokes
-
merge r24
- 27. By Adam Stokes
-
Add description to bundle metadata
- 28. By Adam Stokes
-
Update processing script
Die properly if the services are in error state.
Unmerged revisions
- 28. By Adam Stokes
-
Update processing script
Die properly if the services are in error state.
- 27. By Adam Stokes
-
Add description to bundle metadata
- 26. By Adam Stokes
-
merge r24
- 25. By Adam Stokes
-
add make render output
- 24. By Adam Stokes
-
Add conjure-up enablement
- 23. By Andreas Hasenack
-
Updated charm revisions
- 22. By Adam Collard
-
Bump us (again) to 16.03 from 15.11 in the bundle [trivial] [r=ack]
- 21. By David Britton
-
don't use machines in 'scalable' case.
- 20. By David Britton
-
check in rendered changes to bundles.
- 19. By David Britton
-
to: needs to be an array in v4 bundles.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === added file 'Makefile' |
2 | --- Makefile 1970-01-01 00:00:00 +0000 |
3 | +++ Makefile 2016-05-19 19:34:40 +0000 |
4 | @@ -0,0 +1,18 @@ |
5 | +compare-charm-store: |
6 | + ./charm-store |
7 | + |
8 | +commit-charm-store: |
9 | + CHARM_STORE_COMMIT=1 ./charm-store |
10 | + |
11 | +clean: |
12 | + @rm -rf build |
13 | + |
14 | +render: |
15 | + @./render-bundles |
16 | + |
17 | +update-charm-revisions: |
18 | + @./update-charm-revisions \ |
19 | + $(EXTRA_UPDATE_ARGUMENTS) \ |
20 | + apache2 postgresql juju-gui haproxy rabbitmq-server nfs |
21 | + |
22 | +.PHONY: clean render commit-charm-store update-charm-revisions compare-charm-store |
23 | |
24 | === renamed file 'Makefile' => 'Makefile.moved' |
25 | === added file 'README.md' |
26 | --- README.md 1970-01-01 00:00:00 +0000 |
27 | +++ README.md 2016-05-19 19:34:40 +0000 |
28 | @@ -0,0 +1,28 @@ |
29 | +Overview |
30 | +======== |
31 | + |
32 | +This branch contains the necessary config and instructions for using |
33 | +juju-deployer/juju-quickstart to deploy the landscape charm. |
34 | + |
35 | +Deployment should be straightforward. |
36 | + |
37 | +Dense Deployment - MAAS |
38 | +======================= |
39 | +For MAAS where LXCs can be addressed externally, you can deploy to a single |
40 | +machine while at the same time making the service scalable in the future: |
41 | + |
42 | + juju quickstart u/landscape/landscape-dense-maas/ |
43 | + |
44 | +Dense Deployment - Other |
45 | +======================== |
46 | +For other substrates, use the plain dense deployment which allows your |
47 | +landscape server to be fully reachable, but will not allow easy scaling |
48 | +should load increase. |
49 | + |
50 | + juju quickstart u/landscape/landscape-dense/ |
51 | + |
52 | +Scalable Deployment |
53 | +=================== |
54 | +For a truly scalable deployment, the following stanza should be used. |
55 | + |
56 | + juju quickstart u/landscape/landscape-scalable |
57 | |
58 | === renamed file 'README.md' => 'README.md.moved' |
59 | === added file 'charm-store' |
60 | --- charm-store 1970-01-01 00:00:00 +0000 |
61 | +++ charm-store 2016-05-19 19:34:40 +0000 |
62 | @@ -0,0 +1,23 @@ |
63 | +#!/bin/bash -e |
64 | + |
65 | +COMMIT=${CHARM_STORE_COMMIT:-} |
66 | + |
67 | +for i in *.yaml; do |
68 | + revno=$(bzr revno) |
69 | + target=$(basename $i .yaml) |
70 | + if [ -e build/$target ]; then |
71 | + echo "build/$target exists, please remove before continuing (make clean)" |
72 | + exit 1 |
73 | + fi |
74 | + mkdir -p build |
75 | + bzr co lp:~landscape/charms/bundles/$target/bundle build/$target |
76 | + cp $target.yaml build/$target/bundle.yaml |
77 | + cp README.md build/$target/README.md |
78 | + if [ "$COMMIT" == "" ]; then |
79 | + echo "Diff from Charm Store: $target" |
80 | + (cd build/$target && bzr diff) || /bin/true |
81 | + else |
82 | + echo "Committing to Charm Store: $target" |
83 | + (cd build/$target && bzr commit -m "$COMMIT (stable: r$revno)") |
84 | + fi |
85 | +done |
86 | |
87 | === added directory 'conjure' |
88 | === added file 'conjure/metadata.json' |
89 | --- conjure/metadata.json 1970-01-01 00:00:00 +0000 |
90 | +++ conjure/metadata.json 2016-05-19 19:34:40 +0000 |
91 | @@ -0,0 +1,5 @@ |
92 | +{ |
93 | + "friendly-name": "OpenStack Autopilot", |
94 | + "description": "The Canonical Distribution - Enterprise OpenStack Install and Management.", |
95 | + "cloud_whitelist": ["maas", "localhost"] |
96 | +} |
97 | |
98 | === added directory 'conjure/steps' |
99 | === added file 'conjure/steps/01_register-autopilot.sh' |
100 | --- conjure/steps/01_register-autopilot.sh 1970-01-01 00:00:00 +0000 |
101 | +++ conjure/steps/01_register-autopilot.sh 2016-05-19 19:34:40 +0000 |
102 | @@ -0,0 +1,13 @@ |
103 | +#!/bin/bash |
104 | +# |
105 | +# Title: Registering against Landscape |
106 | +# Description: registers an admin user to login with |
107 | + |
108 | +. /usr/share/conjure-up/hooklib/common.sh |
109 | + |
110 | +landscape_exec=$SCRIPTPATH/configure-landscape |
111 | +while ! `$landscape_exec --admin-email "root@example.com" --admin-name "administrator" --system-email "root@example.com" --maas-host "$MAAS_SERVER" --maas-apikey "$MAAS_OAUTH"`; do sleep 5; done |
112 | + |
113 | +result_message="Access Autopilot: http://$hostname/account/standalone/openstack l: root@example.com p: ubuntu123" |
114 | + |
115 | +exposeResult "$result_message" 0 "true" |
116 | |
117 | === added file 'conjure/steps/configure-landscape' |
118 | --- conjure/steps/configure-landscape 1970-01-01 00:00:00 +0000 |
119 | +++ conjure/steps/configure-landscape 2016-05-19 19:34:40 +0000 |
120 | @@ -0,0 +1,210 @@ |
121 | +#!/usr/bin/env python3 |
122 | +# -*- mode: python; -*- |
123 | +# |
124 | +# Copyright 2014 Canonical, Ltd. |
125 | +# |
126 | +# This program is free software: you can redistribute it and/or modify |
127 | +# it under the terms of the GNU General Public License as published by |
128 | +# the Free Software Foundation, either version 3 of the License, or |
129 | +# (at your option) any later version. |
130 | +# |
131 | +# This package is distributed in the hope that it will be useful, |
132 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
133 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
134 | +# GNU General Public License for more details. |
135 | +# |
136 | +# You should have received a copy of the GNU General Public License |
137 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
138 | + |
139 | +import sys |
140 | +import argparse # noqa |
141 | +import requests # noqa |
142 | +from requests.exceptions import ConnectionError # noqa |
143 | +from requests.packages.urllib3.exceptions import InsecureRequestWarning # noqa |
144 | +import time # noqa |
145 | +import yaml # noqa |
146 | +from urllib.parse import quote, urlparse, urlunparse # noqa |
147 | +import hmac # noqa |
148 | +from hashlib import sha256 # noqa |
149 | +from base64 import b64encode # noqa |
150 | +import logging # noqa |
151 | +from subprocess import check_output # noqa |
152 | + |
153 | +MAGIC_OK_STRING = 'New user - Landscape' |
154 | +LATEST_VERSION = "2011-08-01" |
155 | + |
156 | +log = logging.getLogger('openstack') |
157 | + |
158 | +# Disable the insecure request warning |
159 | +requests.packages.urllib3.disable_warnings(InsecureRequestWarning) |
160 | + |
161 | + |
162 | +def parse(url): |
163 | + """ |
164 | + Split the given URL into the host, port, and path. |
165 | + |
166 | + @type url: C{str} |
167 | + @param url: An URL to parse. |
168 | + """ |
169 | + lowurl = url.lower() |
170 | + if not lowurl.startswith(("http://", "https://")): |
171 | + raise SyntaxError( |
172 | + "URL must start with 'http://' or 'https://': %s" % (url,)) |
173 | + url = url.strip() |
174 | + parsed = urlparse(url) |
175 | + path = urlunparse(("", "") + parsed[2:]) |
176 | + host = parsed[1] |
177 | + |
178 | + if ":" in host: |
179 | + host, port = host.split(":") |
180 | + try: |
181 | + port = int(port) |
182 | + except ValueError: |
183 | + port = None |
184 | + else: |
185 | + port = None |
186 | + |
187 | + return str(host), port, str(path) |
188 | + |
189 | + |
190 | +def run_query(access_key, secret_key, action, params, uri, |
191 | + version=LATEST_VERSION): |
192 | + """Make a low-level query against the Landscape API. |
193 | + |
194 | + @param access_key: The user access key. |
195 | + @param secret_key: The user secret key. |
196 | + @param action: The type of methods to call. For example, "GetComputers". |
197 | + @param params: A dictionary of the parameters to pass to the action. |
198 | + @param uri: The root URI of the API service. For example, |
199 | + "https://landscape.canonical.com/". |
200 | + """ |
201 | + timestamp = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()) |
202 | + params.update({"access_key_id": access_key, |
203 | + "action": action, |
204 | + "signature_version": "2", |
205 | + "signature_method": "HmacSHA256", |
206 | + "timestamp": timestamp, |
207 | + "version": version}) |
208 | + |
209 | + for key, value in params.items(): |
210 | + if isinstance(key, str): |
211 | + params.pop(key) |
212 | + key = key.encode('utf-8') |
213 | + if isinstance(value, str): |
214 | + value = value.encode("utf-8") |
215 | + params[key] = value |
216 | + |
217 | + method = "POST" |
218 | + host, port, path = parse(uri) |
219 | + if port is not None: |
220 | + signed_host = "%s:%d" % (host, port) |
221 | + else: |
222 | + signed_host = host |
223 | + if not path: |
224 | + path = "/" |
225 | + uri = "%s/" % uri |
226 | + signed_params = "&".join( |
227 | + "%s=%s" % (quote(key, safe="~"), quote(value, safe="~")) |
228 | + for key, value in sorted(params.items())) |
229 | + to_sign = "%s\n%s\n%s\n%s" % (method, signed_host, path, signed_params) |
230 | + to_sign = to_sign.encode('utf-8') |
231 | + secret_key = secret_key.encode('utf-8') |
232 | + digest = hmac.new(secret_key, to_sign, sha256).digest() |
233 | + signature = b64encode(digest) |
234 | + signed_params += "&signature=%s" % quote(signature) |
235 | + params['signature'] = signature |
236 | + r = requests.post(uri, data=params, verify=False) |
237 | + |
238 | + # if we can't talk to landscape correctly, the install should fail. |
239 | + assert r.status_code == 200 |
240 | + |
241 | + return r |
242 | + |
243 | + |
244 | +def get_landscape_host(): |
245 | + """ Assuming landscape has been deployed in landscape-dense-maas form, |
246 | + find the "dns-name" of the landscape web server. """ |
247 | + out = check_output('juju status --format yaml', shell=True) |
248 | + juju = yaml.load(out.decode('utf8')) |
249 | + |
250 | + try: |
251 | + services = juju['services'] |
252 | + haproxy = services['haproxy']['units']['haproxy/0'] |
253 | + public_address = haproxy['public-address'] |
254 | + return public_address |
255 | + except KeyError: |
256 | + sys.exit(1) |
257 | + # raise Exception("Landscape not found!") |
258 | + |
259 | + |
260 | +# Landscape isn't actually up when juju-deployer exits; the relations take a |
261 | +# while to set up and deployer doesn't wait until they're finished (it has |
262 | +# no way to, viz. LP #1254766), so we wait until everything is ok. |
263 | +def wait_for_landscape(host): |
264 | + while True: |
265 | + try: |
266 | + # Landscape generates a self signed cert for each install. |
267 | + r = requests.get('http://%s/' % host, verify=False) |
268 | + if MAGIC_OK_STRING in r.text: |
269 | + # now do an API call to make sure the API is up (it gives 503 |
270 | + # for a while) |
271 | + r = requests.get('http://%s/api/' % host, verify=False) |
272 | + if r.status_code == 200: |
273 | + log.debug("got status code {} for landscape " |
274 | + " api".format(r)) |
275 | + break |
276 | + except ConnectionError: |
277 | + log.debug("connection error waiting for landscape") |
278 | + pass |
279 | + time.sleep(10) |
280 | + |
281 | + |
282 | +def register_new_user(host, **kwargs): |
283 | + """ Register a new user. Takes kwargs admin_email admin_name, and |
284 | + system_email. """ |
285 | + kwargs['root_url'] = 'https://%s/' % host |
286 | + kwargs['admin_password'] = "ubuntu123" |
287 | + |
288 | + res = run_query('anonymous', |
289 | + 'anonymous', |
290 | + 'BootstrapLDS', |
291 | + kwargs, |
292 | + 'https://{}/api/'.format(host)) |
293 | + return res.json() |
294 | + |
295 | + |
296 | +def register_maas(host, key, secret, maas_host, maas_apikey): |
297 | + data = { |
298 | + 'endpoint': 'http://{}/MAAS'.format(maas_host), |
299 | + 'credentials': maas_apikey |
300 | + } |
301 | + |
302 | + run_query(key, secret, 'RegisterMAASRegionController', data, |
303 | + 'https://{}/api/'.format(host)) |
304 | + |
305 | + |
306 | +def main(): |
307 | + parser = argparse.ArgumentParser() |
308 | + |
309 | + parser.add_argument("--admin-email", help="the admin (login) e-mail") |
310 | + parser.add_argument("--admin-name", help="administrator's full name") |
311 | + parser.add_argument("--system-email", help="landscape's email address") |
312 | + parser.add_argument("--maas-host", help="the host of the MAAS instance") |
313 | + parser.add_argument("--maas-apikey", |
314 | + help="the apikey of the MAAS instance") |
315 | + |
316 | + args = parser.parse_args() |
317 | + log.debug(args) |
318 | + host = get_landscape_host() |
319 | + wait_for_landscape(host) |
320 | + auth = register_new_user(host, admin_email=args.admin_email, |
321 | + admin_name=args.admin_name, |
322 | + system_email=args.system_email) |
323 | + |
324 | + register_maas(host, auth['LANDSCAPE_API_KEY'], |
325 | + auth['LANDSCAPE_API_SECRET'], args.maas_host, |
326 | + args.maas_apikey) |
327 | + print(host) |
328 | + |
329 | +if __name__ == '__main__': |
330 | + main() |
331 | |
332 | === added file 'landscape-dense-maas.yaml' |
333 | --- landscape-dense-maas.yaml 1970-01-01 00:00:00 +0000 |
334 | +++ landscape-dense-maas.yaml 2016-05-19 19:34:40 +0000 |
335 | @@ -0,0 +1,63 @@ |
336 | +series: trusty |
337 | +services: |
338 | + rabbitmq-server: |
339 | + charm: cs:trusty/rabbitmq-server-43 |
340 | + to: |
341 | + - lxc:0 |
342 | + num_units: 1 |
343 | + annotations: |
344 | + "gui-x": "600" |
345 | + "gui-y": "370" |
346 | + postgresql: |
347 | + charm: cs:trusty/postgresql-40 |
348 | + constraints: mem=2048 |
349 | + to: |
350 | + - lxc:0 |
351 | + num_units: 1 |
352 | + options: |
353 | + extra_packages: python-apt postgresql-contrib postgresql-.*-debversion postgresql-plpython-.* |
354 | + max_connections: 500 |
355 | + max_prepared_transactions: 500 |
356 | + annotations: |
357 | + "gui-x": "600" |
358 | + "gui-y": "120" |
359 | + haproxy: |
360 | + charm: cs:trusty/haproxy-16 |
361 | + to: |
362 | + - lxc:0 |
363 | + expose: True |
364 | + num_units: 1 |
365 | + options: |
366 | + enable_monitoring: True |
367 | + monitoring_allowed_cidr: "0.0.0.0/0" |
368 | + monitoring_password: "haproxy" |
369 | + default_timeouts: "queue 60000, connect 5000, client 120000, server 120000" |
370 | + # Don't deploy default haproxy service on port 80 |
371 | + services: "" |
372 | + source: backports |
373 | + ssl_cert: SELFSIGNED |
374 | + annotations: |
375 | + "gui-x": "1200" |
376 | + "gui-y": "120" |
377 | + landscape-server: |
378 | + charm: cs:trusty/landscape-server |
379 | + constraints: mem=2048 |
380 | + to: |
381 | + - lxc:0 |
382 | + num_units: 1 |
383 | + options: |
384 | + source: deb http://ppa.launchpad.net/landscape/16.03/ubuntu trusty main |
385 | + key: 4652B4E6 |
386 | + annotations: |
387 | + "gui-x": "950" |
388 | + "gui-y": "120" |
389 | +machines: |
390 | + "0": {} |
391 | +relations: |
392 | + - [landscape-server, rabbitmq-server] |
393 | + - [landscape-server, haproxy] |
394 | + - ["landscape-server:db", "postgresql:db-admin"] |
395 | +tags: |
396 | + - conjure-openstack |
397 | + - autopilot |
398 | + - landscape |
399 | |
400 | === added file 'landscape-dense.yaml' |
401 | --- landscape-dense.yaml 1970-01-01 00:00:00 +0000 |
402 | +++ landscape-dense.yaml 2016-05-19 19:34:40 +0000 |
403 | @@ -0,0 +1,59 @@ |
404 | +series: trusty |
405 | +services: |
406 | + rabbitmq-server: |
407 | + charm: cs:trusty/rabbitmq-server-43 |
408 | + to: |
409 | + - lxc:0 |
410 | + num_units: 1 |
411 | + annotations: |
412 | + "gui-x": "600" |
413 | + "gui-y": "370" |
414 | + postgresql: |
415 | + charm: cs:trusty/postgresql-40 |
416 | + constraints: mem=2048 |
417 | + to: |
418 | + - lxc:0 |
419 | + num_units: 1 |
420 | + options: |
421 | + extra_packages: python-apt postgresql-contrib postgresql-.*-debversion postgresql-plpython-.* |
422 | + max_connections: 500 |
423 | + max_prepared_transactions: 500 |
424 | + annotations: |
425 | + "gui-x": "600" |
426 | + "gui-y": "120" |
427 | + haproxy: |
428 | + charm: cs:trusty/haproxy-16 |
429 | + to: |
430 | + - 0 |
431 | + expose: True |
432 | + num_units: 1 |
433 | + options: |
434 | + enable_monitoring: True |
435 | + monitoring_allowed_cidr: "0.0.0.0/0" |
436 | + monitoring_password: "haproxy" |
437 | + default_timeouts: "queue 60000, connect 5000, client 120000, server 120000" |
438 | + # Don't deploy default haproxy service on port 80 |
439 | + services: "" |
440 | + source: backports |
441 | + ssl_cert: SELFSIGNED |
442 | + annotations: |
443 | + "gui-x": "1200" |
444 | + "gui-y": "120" |
445 | + landscape-server: |
446 | + charm: cs:trusty/landscape-server |
447 | + constraints: mem=2048 |
448 | + to: |
449 | + - lxc:0 |
450 | + num_units: 1 |
451 | + options: |
452 | + source: deb http://ppa.launchpad.net/landscape/16.03/ubuntu trusty main |
453 | + key: 4652B4E6 |
454 | + annotations: |
455 | + "gui-x": "950" |
456 | + "gui-y": "120" |
457 | +machines: |
458 | + "0": {} |
459 | +relations: |
460 | + - [landscape-server, rabbitmq-server] |
461 | + - [landscape-server, haproxy] |
462 | + - ["landscape-server:db", "postgresql:db-admin"] |
463 | |
464 | === added file 'landscape-scalable.yaml' |
465 | --- landscape-scalable.yaml 1970-01-01 00:00:00 +0000 |
466 | +++ landscape-scalable.yaml 2016-05-19 19:34:40 +0000 |
467 | @@ -0,0 +1,49 @@ |
468 | +series: trusty |
469 | +services: |
470 | + rabbitmq-server: |
471 | + charm: cs:trusty/rabbitmq-server-43 |
472 | + num_units: 1 |
473 | + annotations: |
474 | + "gui-x": "600" |
475 | + "gui-y": "370" |
476 | + postgresql: |
477 | + charm: cs:trusty/postgresql-40 |
478 | + constraints: mem=2048 |
479 | + num_units: 1 |
480 | + options: |
481 | + extra_packages: python-apt postgresql-contrib postgresql-.*-debversion postgresql-plpython-.* |
482 | + max_connections: 500 |
483 | + max_prepared_transactions: 500 |
484 | + annotations: |
485 | + "gui-x": "600" |
486 | + "gui-y": "120" |
487 | + haproxy: |
488 | + charm: cs:trusty/haproxy-16 |
489 | + expose: True |
490 | + num_units: 1 |
491 | + options: |
492 | + enable_monitoring: True |
493 | + monitoring_allowed_cidr: "0.0.0.0/0" |
494 | + monitoring_password: "haproxy" |
495 | + default_timeouts: "queue 60000, connect 5000, client 120000, server 120000" |
496 | + # Don't deploy default haproxy service on port 80 |
497 | + services: "" |
498 | + source: backports |
499 | + ssl_cert: SELFSIGNED |
500 | + annotations: |
501 | + "gui-x": "1200" |
502 | + "gui-y": "120" |
503 | + landscape-server: |
504 | + charm: cs:trusty/landscape-server |
505 | + constraints: mem=2048 |
506 | + num_units: 1 |
507 | + options: |
508 | + source: deb http://ppa.launchpad.net/landscape/16.03/ubuntu trusty main |
509 | + key: 4652B4E6 |
510 | + annotations: |
511 | + "gui-x": "950" |
512 | + "gui-y": "120" |
513 | +relations: |
514 | + - [landscape-server, rabbitmq-server] |
515 | + - [landscape-server, haproxy] |
516 | + - ["landscape-server:db", "postgresql:db-admin"] |
517 | |
518 | === added file 'landscape-template.jinja2' |
519 | --- landscape-template.jinja2 1970-01-01 00:00:00 +0000 |
520 | +++ landscape-template.jinja2 2016-05-19 19:34:40 +0000 |
521 | @@ -0,0 +1,99 @@ |
522 | +series: trusty |
523 | +services: |
524 | + rabbitmq-server: |
525 | + charm: cs:trusty/rabbitmq-server-44 |
526 | + {% if rabbitmq["to"] %} |
527 | + to: |
528 | + - {{ rabbitmq["to"] }} |
529 | + {% endif %} |
530 | + num_units: 1 |
531 | + annotations: |
532 | + "gui-x": "600" |
533 | + "gui-y": "370" |
534 | + postgresql: |
535 | + charm: cs:trusty/postgresql-41 |
536 | + {% if postgresql["memory"] %} |
537 | + constraints: mem={{ postgresql["memory"] }} |
538 | + {% endif %} |
539 | + {% if postgresql["to"] %} |
540 | + to: |
541 | + - {{ postgresql["to"] }} |
542 | + {% endif %} |
543 | + num_units: 1 |
544 | + options: |
545 | + extra_packages: python-apt postgresql-contrib postgresql-.*-debversion postgresql-plpython-.* |
546 | + max_connections: {{ postgresql.max_connections }} |
547 | + max_prepared_transactions: {{ postgresql.max_connections }} |
548 | + {% if postgresql.manual_tuning %} |
549 | + performance_tuning: manual |
550 | + {% endif %} |
551 | + {% if postgresql.shared_buffers %} |
552 | + shared_buffers: {{ postgresql.shared_buffers }} |
553 | + {% endif %} |
554 | + {% if postgresql.checkpoint_segments %} |
555 | + checkpoint_segments: {{ postgresql.checkpoint_segments }} |
556 | + {% endif %} |
557 | + {% if postgresql.maintenance_work_mem %} |
558 | + maintenance_work_mem: {{ postgresql.maintenance_work_mem }} |
559 | + {% endif %} |
560 | + {% if postgresql.work_mem %} |
561 | + work_mem: {{ postgresql.work_mem }} |
562 | + {% endif %} |
563 | + {% if postgresql.effective_cache_size %} |
564 | + effective_cache_size: {{ postgresql.effective_cache_size }} |
565 | + {% endif %} |
566 | + annotations: |
567 | + "gui-x": "600" |
568 | + "gui-y": "120" |
569 | + haproxy: |
570 | + charm: cs:trusty/haproxy-19 |
571 | + {% if haproxy["to"] %} |
572 | + to: |
573 | + - {{ haproxy["to"] }} |
574 | + {% endif %} |
575 | + expose: True |
576 | + num_units: 1 |
577 | + options: |
578 | + enable_monitoring: True |
579 | + monitoring_allowed_cidr: "0.0.0.0/0" |
580 | + monitoring_password: "haproxy" |
581 | + default_timeouts: "queue 60000, connect 5000, client 120000, server 120000" |
582 | + # Don't deploy default haproxy service on port 80 |
583 | + services: "" |
584 | + source: backports |
585 | + ssl_cert: SELFSIGNED |
586 | + annotations: |
587 | + "gui-x": "1200" |
588 | + "gui-y": "120" |
589 | + landscape-server: |
590 | + {% if landscape["branch"] %} |
591 | + branch: {{ landscape["branch"] }} |
592 | + {% else %} |
593 | + charm: cs:trusty/landscape-server |
594 | + {% endif %} |
595 | + {% if landscape["memory"] %} |
596 | + constraints: mem={{ landscape["memory"] }} |
597 | + {% endif %} |
598 | + {% if landscape["to"] %} |
599 | + to: |
600 | + - {{ landscape["to"] }} |
601 | + {% endif %} |
602 | + num_units: 1 |
603 | + options: |
604 | + source: {{ landscape["source"] }} |
605 | + key: {{ landscape["key"] }} |
606 | + {% if landscape["ssl-cert"] %} |
607 | + ssl-cert: {{ landscape["ssl-cert"] }} |
608 | + ssl-key: {{ landscape["ssl-key"] }} |
609 | + {% endif %} |
610 | + annotations: |
611 | + "gui-x": "950" |
612 | + "gui-y": "120" |
613 | +{% if landscape["to"] %} |
614 | +machines: |
615 | + "0": {} |
616 | +{% endif %} |
617 | +relations: |
618 | + - [landscape-server, rabbitmq-server] |
619 | + - [landscape-server, haproxy] |
620 | + - ["landscape-server:db", "postgresql:db-admin"] |
621 | |
622 | === added file 'render-bundles' |
623 | --- render-bundles 1970-01-01 00:00:00 +0000 |
624 | +++ render-bundles 2016-05-19 19:34:40 +0000 |
625 | @@ -0,0 +1,58 @@ |
626 | +#!/usr/bin/python3 |
627 | + |
628 | +import os |
629 | + |
630 | +from jinja2 import FileSystemLoader, Environment |
631 | + |
632 | +DEFAULTS = { |
633 | + "rabbitmq": {}, |
634 | + "postgresql": { |
635 | + "max_connections": 500, |
636 | + "max_prepared_transactions": 500, |
637 | + "memory": 2048}, |
638 | + "haproxy": {}, |
639 | + "landscape": { |
640 | + "memory": 2048, |
641 | + "source": "deb http://ppa.launchpad.net/landscape/16.03/ubuntu trusty main", |
642 | + "key": "4652B4E6"} |
643 | +} |
644 | + |
645 | +FLAVORS = [ |
646 | + # scalable |
647 | + {"name": "scalable"}, |
648 | + |
649 | + # dense |
650 | + {"name": "dense", |
651 | + "rabbitmq": { |
652 | + "to": "lxc:0"}, |
653 | + "postgresql": { |
654 | + "to": "lxc:0"}, |
655 | + "haproxy": { |
656 | + "to": "0"}, |
657 | + "landscape": { |
658 | + "to": "lxc:0"}}, |
659 | + |
660 | + # dense-maas |
661 | + {"name": "dense-maas", |
662 | + "rabbitmq": { |
663 | + "to": "lxc:0"}, |
664 | + "postgresql": { |
665 | + "to": "lxc:0"}, |
666 | + "haproxy": { |
667 | + "to": "lxc:0"}, |
668 | + "landscape": { |
669 | + "to": "lxc:0"}}, |
670 | +] |
671 | + |
672 | +if __name__ == "__main__": |
673 | + environment = Environment( |
674 | + loader=FileSystemLoader("."), trim_blocks=True, lstrip_blocks=True, |
675 | + keep_trailing_newline=True) |
676 | + template = environment.get_template("landscape-template.jinja2") |
677 | + for flavor in FLAVORS: |
678 | + with open("landscape-%s.yaml" % flavor["name"], "w") as fd: |
679 | + context = DEFAULTS.copy() |
680 | + context["name"] = flavor["name"] |
681 | + for key in DEFAULTS.keys(): |
682 | + context[key].update(flavor.get(key, {})) |
683 | + fd.write(template.render(context)) |
684 | |
685 | === added file 'update-charm-revisions' |
686 | --- update-charm-revisions 1970-01-01 00:00:00 +0000 |
687 | +++ update-charm-revisions 2016-05-19 19:34:40 +0000 |
688 | @@ -0,0 +1,98 @@ |
689 | +#!/usr/bin/python3 |
690 | + |
691 | +import argparse |
692 | +import fileinput |
693 | +import re |
694 | +import sys |
695 | +from urllib.request import urlopen |
696 | +from yaml import load |
697 | +from glob import glob |
698 | + |
699 | + |
700 | +class Charm(object): |
701 | + |
702 | + def __init__(self, charm_name, series): |
703 | + """Create a charm object. |
704 | + @param charm_name: name of charm |
705 | + """ |
706 | + reference = "cs:{}/{}".format(series, charm_name) |
707 | + base_url = "https://store.juju.ubuntu.com/charm-info?charms=" |
708 | + url = "{}{}".format(base_url, reference) |
709 | + response = urlopen(url) |
710 | + self.charm_data = load(response)[reference] |
711 | + self.name = charm_name |
712 | + if "errors" in self.charm_data: |
713 | + raise IOError("{}: {}".format( |
714 | + charm_name, self.charm_data["errors"])) |
715 | + self.revision = self.charm_data["revision"] |
716 | + self.store_url = "cs:{}/{}-{}".format(series, self.name, self.revision) |
717 | + |
718 | + |
719 | +def _get_charm(charm_name, series): |
720 | + """ |
721 | + Small wrapper to try to get the series charm you specify. Falls back |
722 | + to precise if you specified something else |
723 | + """ |
724 | + try: |
725 | + return Charm(charm_name, series) |
726 | + except IOError as e: |
727 | + if series != "precise": |
728 | + try: |
729 | + return Charm(charm_name, series="precise") |
730 | + except IOError as precise_e: |
731 | + raise IOError( |
732 | + "%s: not found? (even tried precise): {}, {}".format( |
733 | + charm_name, e, precise_e)) |
734 | + raise |
735 | + |
736 | + |
737 | +def replace_in_config(filename, charms, series): |
738 | + """ |
739 | + Iterate over each charm, replacing all occurences of old charm store |
740 | + urls with new versions. Intent is to leave file in a state that can |
741 | + be tested and checked in if successful. |
742 | + |
743 | + Look for lines like: |
744 | + charm: cs:trusty/juju-gui-83 |
745 | + |
746 | + Or: |
747 | + series: trusty |
748 | + """ |
749 | + for line in fileinput.input(filename, inplace=1): |
750 | + pattern = "^(\s*)series:\s.*$" |
751 | + line = re.sub(pattern, r"\1series: %s" % series, line) |
752 | + for charm in charms: |
753 | + pattern = "cs:[^/]+/{}-[0-9]+".format(charm.name) |
754 | + line = re.sub(pattern, charm.store_url, line) |
755 | + sys.stdout.write(line) |
756 | + |
757 | + print("# Config written, use `bzr diff %s` to see any changes" % filename) |
758 | + |
759 | + |
760 | +def get_options(): |
761 | + """Parse and return command line options.""" |
762 | + description = "Put new charmstore descriptors into a deployer file." |
763 | + parser = argparse.ArgumentParser(description=description) |
764 | + parser.add_argument("charms", help="List charms to update", nargs='*') |
765 | + parser.add_argument("--series", help="Charm series", default="trusty") |
766 | + return parser.parse_args() |
767 | + |
768 | + |
769 | +def main(): |
770 | + options = get_options() |
771 | + charms = [] |
772 | + if len(options.charms): |
773 | + print("# Latest upstream versions of charms ({}):".format( |
774 | + options.series)) |
775 | + for charm_name in options.charms: |
776 | + charm = _get_charm(charm_name, series=options.series) |
777 | + print("# {}: {}".format(charm_name, charm.revision)) |
778 | + charms.append(charm) |
779 | + |
780 | + for filename in glob("*.jinja2"): |
781 | + replace_in_config(filename, charms, series=options.series) |
782 | + |
783 | + sys.exit(0) |
784 | + |
785 | +if __name__ == "__main__": |
786 | + main() |