Merge lp:~adam-stokes/landscape-charm/add-conjure-up into lp:~landscape/landscape-charm/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
Reviewer Review Type Date Requested Status
Landscape Pending
Landscape Pending
Review via email: mp+295260@code.launchpad.net

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()

Subscribers

People subscribed via source and target branches