10
10
from lib.juju import Juju
12
from base64 import b64encode
12
from base64 import b64encode, b64decode
13
13
from configobj import ConfigObj, ConfigObjError
14
from contextlib import closing
14
15
from copy import deepcopy
27
27
from subprocess import check_call, check_output, CalledProcessError, call
30
SSL_CERT_LOCATION = "/etc/ssl/certs/landscape_server_ca.crt"
30
33
def _get_installed_version(name):
31
34
"""Returns the version string of name using dpkg-query or returns None"""
95
98
services=yaml.safe_dump(_get_services_haproxy()))
101
def notify_vhost_config_relation(relation_id=None):
103
Notify the vhost-config relation.
105
This will mark it "ready to proceed". If relation_id is specified
106
use that as the relation context, otherwise look up and notify all
107
vhost-config relations.
110
with open("%s/config/vhostssl.tmpl" % ROOT, 'r') as handle:
112
"port": "443", "template": b64encode(handle.read())})
113
with open("%s/config/vhost.tmpl" % ROOT, 'r') as handle:
115
"port": "80", "template": b64encode(handle.read())})
117
relation_ids = [relation_id]
118
if relation_id is None:
119
relation_ids = juju.relation_ids("vhost-config")
120
for relation_id in relation_ids:
121
juju.relation_set(relation_id=relation_id, vhosts=yaml.dump(vhosts))
98
124
def db_admin_relation_joined():
150
176
"password": password},
151
177
"schema": {"store_user": admin, "store_password": admin_password}})
154
# Name as lock so we don't try to reuse it as a database connection
155
lock = util.connect_exclusive(host, admin, admin_password)
156
except psycopg2.Error:
157
# Another unit is performing database configuration.
161
util.create_user(user, password, host, admin, admin_password)
162
_create_maintenance_user(password, host, admin, admin_password)
163
check_call("setup-landscape-server")
165
juju.juju_log("Landscape database initialized!")
179
with closing(util.connect_exclusive(host, admin, admin_password)):
180
util.create_user(user, password, host, admin, admin_password)
181
_create_maintenance_user(password, host, admin, admin_password)
182
check_call("setup-landscape-server")
183
juju.juju_log("Landscape database initialized!")
185
notify_vhost_config_relation()
169
188
# Handle remove-relation db-admin. This call will fail because
338
def vhost_config_relation_changed():
339
"""Relate to apache to configure a vhost.
341
This hook will supply vhost configuration as well as read simple data
342
out of apache (servername, certificate). This data is necessary for
343
informing clients of the correct URL and cert to use when connecting
346
notify_vhost_config_relation(os.environ.get("JUJU_RELATION_ID", None))
348
config_obj = _get_config_obj(LANDSCAPE_SERVICE_CONF)
350
section = config_obj["stores"]
351
database = section["main"]
352
host = section["host"]
353
user = section["user"]
354
password = section["password"]
356
juju.juju_log("Database not ready yet, deferring call")
359
relids = juju.relation_ids("vhost-config")
362
apache2_unit = juju.relation_list(relid)[0]
363
apache_servername = juju.relation_get(
364
"servername", unit_name=apache2_unit, relation_id=relid)
366
apache_servername = juju.relation_get("servername")
368
if not apache_servername:
369
juju.juju_log("Waiting for data from apache, deferring")
371
apache_url = "https://%s/" % apache_servername
374
juju.juju_log("Waiting for database to become available, deferring.")
377
with closing(util.connect_exclusive(host, user, password)):
378
juju.juju_log("Updating Landscape root_url: %s" % apache_url)
379
util.change_root_url(database, user, password, host, apache_url)
381
# This data may or may not be present, dependeing on if cert is self
382
# signed from apache.
383
ssl_cert = juju.relation_get(
384
"ssl_cert", unit_name=apache2_unit, relation_id=relid)
386
juju.juju_log("Writing new SSL cert: %s" % SSL_CERT_LOCATION)
387
with open(SSL_CERT_LOCATION, 'w') as f:
388
f.write(str(b64decode(ssl_cert)))
390
if os.path.exists(SSL_CERT_LOCATION):
391
os.remove(SSL_CERT_LOCATION)
393
# only starts services again if is_db_up and _is_amqp_up
319
397
def config_changed():
320
398
"""Update and restart services based on config setting changes.
369
447
def _setup_apache():
371
Setup apache2 to serve static landscape content
449
Setup apache2 to serve static landscape content, removing everything else.
451
N.B. As of Trusty, sites must be named with '.conf' at the end.
452
Precise and Trusty can then both use a2ensite/a2dissite with 'file.conf'.
373
454
public = juju.unit_get("public-address")
374
455
_a2enmods(["rewrite", "proxy_http", "ssl", "headers", "expires"])
375
_a2dissite("default")
456
sites_available = os.listdir(os.path.dirname(LANDSCAPE_APACHE_SITE))
457
for site in sites_available:
376
459
shutil.copy("%s/hooks/conf/landscape-http" % ROOT, LANDSCAPE_APACHE_SITE)
377
460
_replace_in_file(LANDSCAPE_APACHE_SITE, r"@hostname@", public)
378
_a2ensite("landscape")
461
_a2ensite("landscape.conf")
379
462
_service("apache2", "restart")
671
754
"errorfiles": deepcopy(ERROR_FILES)},
673
"port": "8090", "httpchk": "HEAD /index.html HTTP/1.0",
674
"errorfiles": deepcopy(ERROR_FILES)},
756
"port": "8090", "httpchk": "HEAD /index.html HTTP/1.0"
676
"port": "8070", "httpchk": "HEAD /ping HTTP/1.0",
677
"errorfiles": deepcopy(ERROR_FILES)},
759
"port": "8070", "httpchk": "HEAD /ping HTTP/1.0"
678
761
"combo-loader": {
680
"httpchk": "HEAD /?yui/scrollview/scrollview-min.js HTTP/1.0",
681
"errorfiles": deepcopy(ERROR_FILES)},
682
"async-frontend": {"port": "9090"},
763
"httpchk": "HEAD /?yui/scrollview/scrollview-min.js HTTP/1.0"
767
"service_options": ["timeout client 300000",
768
"timeout server 300000"]},
683
769
"apiserver": {"port": "9080"},
684
770
"package-upload": {"port": "9100"},
685
771
"package-search": {"port": "9090"}}
721
807
LANDSCAPE_DEFAULT_FILE = "/etc/default/landscape-server"
722
LANDSCAPE_APACHE_SITE = "/etc/apache2/sites-available/landscape"
808
LANDSCAPE_APACHE_SITE = "/etc/apache2/sites-available/landscape.conf"
723
809
LANDSCAPE_LICENSE_DEST = "/etc/landscape/license.txt"
724
810
LANDSCAPE_SERVICE_CONF = "/etc/landscape/service.conf"
725
811
LANDSCAPE_MAINTENANCE = "/opt/canonical/landscape/maintenance.txt"
735
821
"data-relation-changed": data_relation_changed,
736
822
"db-admin-relation-joined": db_admin_relation_joined,
737
823
"db-admin-relation-changed": db_admin_relation_changed,
738
"website-relation-joined": website_relation_joined}
824
"website-relation-joined": website_relation_joined,
825
"vhost-config-relation-changed": vhost_config_relation_changed}
739
826
hook = os.path.basename(sys.argv[0])
740
827
# If the hook is unsupported, let it raise a KeyError and exit with error.