~npochet/landscape-charm/landscape-charm

« back to all changes in this revision

Viewing changes to hooks/hooks.py

  • Committer: David Britton
  • Date: 2014-06-20 22:04:25 UTC
  • mfrom: (143.2.17 stable)
  • mto: (143.2.22 stable)
  • mto: This revision was merged to the branch mainline in revision 199.
  • Revision ID: dpb@canonical.com-20140620220425-d06570b12htz7vi3
New upstream:
- added vhost-config relation to  configure apache2 (no more base64 blobs needed)
- support latest upstream fixes in landscape project
- Add trusty support to charm (pre-enablement)
- Fix async service timeout
- only install hash-id-database package if necessary

Show diffs side-by-side

added added

removed removed

Lines of Context:
9
9
from lib import util
10
10
from lib.juju import Juju
11
11
 
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
15
16
import cStringIO
16
17
import datetime
17
18
import grp
18
19
import os
19
20
import psutil
20
 
import psycopg2
21
21
import pwd
22
22
import pycurl
23
23
import re
27
27
from subprocess import check_call, check_output, CalledProcessError, call
28
28
 
29
29
 
 
30
SSL_CERT_LOCATION = "/etc/ssl/certs/landscape_server_ca.crt"
 
31
 
 
32
 
30
33
def _get_installed_version(name):
31
34
    """Returns the version string of name using dpkg-query or returns None"""
32
35
    try:
95
98
            services=yaml.safe_dump(_get_services_haproxy()))
96
99
 
97
100
 
 
101
def notify_vhost_config_relation(relation_id=None):
 
102
    """
 
103
    Notify the vhost-config relation.
 
104
 
 
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.
 
108
    """
 
109
    vhosts = []
 
110
    with open("%s/config/vhostssl.tmpl" % ROOT, 'r') as handle:
 
111
        vhosts.append({
 
112
            "port": "443", "template": b64encode(handle.read())})
 
113
    with open("%s/config/vhost.tmpl" % ROOT, 'r') as handle:
 
114
        vhosts.append({
 
115
            "port": "80", "template": b64encode(handle.read())})
 
116
 
 
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))
 
122
 
 
123
 
98
124
def db_admin_relation_joined():
99
125
    pass
100
126
 
150
176
                    "password": password},
151
177
         "schema": {"store_user": admin, "store_password": admin_password}})
152
178
 
153
 
    try:
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.
158
 
        pass
159
 
    else:
160
 
        try:
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")
164
 
        finally:
165
 
            juju.juju_log("Landscape database initialized!")
166
 
            lock.close()
 
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!")
 
184
 
 
185
    notify_vhost_config_relation()
167
186
 
168
187
    try:
169
188
        # Handle remove-relation db-admin.  This call will fail because
316
335
        config_changed()
317
336
 
318
337
 
 
338
def vhost_config_relation_changed():
 
339
    """Relate to apache to configure a vhost.
 
340
 
 
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
 
344
    to the server.
 
345
    """
 
346
    notify_vhost_config_relation(os.environ.get("JUJU_RELATION_ID", None))
 
347
 
 
348
    config_obj = _get_config_obj(LANDSCAPE_SERVICE_CONF)
 
349
    try:
 
350
        section = config_obj["stores"]
 
351
        database = section["main"]
 
352
        host = section["host"]
 
353
        user = section["user"]
 
354
        password = section["password"]
 
355
    except KeyError:
 
356
        juju.juju_log("Database not ready yet, deferring call")
 
357
        sys.exit(0)
 
358
 
 
359
    relids = juju.relation_ids("vhost-config")
 
360
    if relids:
 
361
        relid = relids[0]
 
362
        apache2_unit = juju.relation_list(relid)[0]
 
363
        apache_servername = juju.relation_get(
 
364
            "servername", unit_name=apache2_unit, relation_id=relid)
 
365
    else:
 
366
        apache_servername = juju.relation_get("servername")
 
367
 
 
368
    if not apache_servername:
 
369
        juju.juju_log("Waiting for data from apache, deferring")
 
370
        sys.exit(0)
 
371
    apache_url = "https://%s/" % apache_servername
 
372
 
 
373
    if not _is_db_up():
 
374
        juju.juju_log("Waiting for database to become available, deferring.")
 
375
        sys.exit(0)
 
376
 
 
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)
 
380
 
 
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)
 
385
    if ssl_cert:
 
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)))
 
389
    else:
 
390
        if os.path.exists(SSL_CERT_LOCATION):
 
391
            os.remove(SSL_CERT_LOCATION)
 
392
 
 
393
    # only starts services again if is_db_up and _is_amqp_up
 
394
    config_changed()
 
395
 
 
396
 
319
397
def config_changed():
320
398
    """Update and restart services based on config setting changes.
321
399
 
368
446
 
369
447
def _setup_apache():
370
448
    """
371
 
    Setup apache2 to serve static landscape content
 
449
    Setup apache2 to serve static landscape content, removing everything else.
 
450
 
 
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'.
372
453
    """
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:
 
458
        _a2dissite(site)
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")
380
463
 
381
464
 
670
753
        "port": "8080",
671
754
        "errorfiles": deepcopy(ERROR_FILES)},
672
755
    "msgserver": {
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"
 
757
        },
675
758
    "pingserver": {
676
 
        "port": "8070", "httpchk": "HEAD /ping HTTP/1.0",
677
 
        "errorfiles": deepcopy(ERROR_FILES)},
 
759
        "port": "8070", "httpchk": "HEAD /ping HTTP/1.0"
 
760
        },
678
761
    "combo-loader": {
679
762
        "port": "9070",
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"
 
764
        },
 
765
    "async-frontend": {
 
766
        "port": "9090",
 
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"}}
719
805
    "static": None}
720
806
 
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.
741
828
    hooks[hook]()