Merge lp:~cprov/charms/trusty/adt-cloud-service/gunicorn-app into lp:~canonical-ci-engineering/charms/trusty/adt-cloud-service/trunk

Proposed by Celso Providelo
Status: Merged
Approved by: Celso Providelo
Approved revision: 8
Merged at revision: 2
Proposed branch: lp:~cprov/charms/trusty/adt-cloud-service/gunicorn-app
Merge into: lp:~canonical-ci-engineering/charms/trusty/adt-cloud-service/trunk
Diff against target: 272 lines (+83/-59)
8 files modified
README (+3/-2)
adt.conf (+0/-17)
config.yaml (+3/-4)
hooks/actions.py (+63/-11)
hooks/services.py (+5/-2)
hooks/wsgi-relation-joined (+3/-0)
metadata.yaml (+6/-2)
templates/upstart.conf (+0/-21)
To merge this branch: bzr merge lp:~cprov/charms/trusty/adt-cloud-service/gunicorn-app
Reviewer Review Type Date Requested Status
Joe Talbott (community) Approve
Review via email: mp+252855@code.launchpad.net

Commit message

Restoring upstart template capabilities and running web_app with gunicorn from the venv (py3 support).

Description of the change

Restoring upstart template capabilities and running web_app with gunicorn from the venv (py3 support).

Also providing website relation for HA | Apache

To post a comment you must log in.
Revision history for this message
Joe Talbott (joetalbott) wrote :

LGTM, Thanks for doing this.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'README'
--- README 2015-03-10 20:17:05 +0000
+++ README 2015-03-13 03:40:39 +0000
@@ -7,7 +7,8 @@
7-------------7-------------
88
9There are only two config options for this charm:9There are only two config options for this charm:
10 * branch: The bzr branch to pull for adt-cloud-service (default:
11 lp:adt-cloud-service)
12 * config-file: A base64 encoded string with the config file to use for10 * config-file: A base64 encoded string with the config file to use for
13 adt-cloud-service.11 adt-cloud-service.
12
13NOTE: This expects the payload code in the form of adt-cloud-service.tgz
14to exist with the snapshot of lp:adt-cloud-service that needs deploying
1415
=== removed file 'adt.conf'
--- adt.conf 2015-03-10 20:17:05 +0000
+++ adt.conf 1970-01-01 00:00:00 +0000
@@ -1,17 +0,0 @@
1# `adt-cloud-worker` configuration file.
2[adt]
3name = foo
4# <arch>.<platform>[ ...]
5tags = i386.nova amd64.nova
6
7[amqp]
8uris = amqp://guest:guest@localhost:5672//
9
10[nova]
11# Matching OS_ env_vars.
12os_username = foo
13os_tenant_name = foo_project
14os_password = <redacted>
15os_auth_url = http://172.20.161.138:5000/v2.0/
16os_region_name = bot-prototype
17extra_args = --net-id=415a0839-eb05-4e7a-907c-413c657f4bf5
180
=== modified file 'config.yaml'
--- config.yaml 2015-03-10 20:17:05 +0000
+++ config.yaml 2015-03-13 03:40:39 +0000
@@ -1,6 +1,5 @@
1options:1options:
2 branch:2 config-file:
3 type: string3 type: string
4 default: "lp:adt-cloud-service"4 description: |
5 description: "Branch to use for adt-cloud-service"5 base64 encoded string with the config file for adt-cloud-worker
6
76
=== added directory 'files'
=== modified file 'hooks/actions.py'
--- hooks/actions.py 2015-03-10 20:17:05 +0000
+++ hooks/actions.py 2015-03-13 03:40:39 +0000
@@ -1,38 +1,90 @@
1import base641import base64
2import os2import os
3import shutil
4import subprocess3import subprocess
54
6from charmhelpers import fetch5from charmhelpers import fetch
7from charmhelpers.core import hookenv6from charmhelpers.core import (
7 hookenv,
8 host,
9)
10from charmhelpers.core.services import helpers
11from charmhelpers.payload.archive import extract_tarfile
812
913
10REQUIRED_PACKAGES = [14REQUIRED_PACKAGES = [
11 'bzr',15 'python-virtualenv', 'python3-dev',
12 # py2 dependencies as a temporary hack-to-production.
13 'python-kombu',
14 'python-configparser',
15 'python-swiftclient',
16]16]
17SERVICE_DIR = '/srv/adt-cloud-service'17SERVICE_DIR = '/srv/adt-cloud-service'
18LOG_DIR = os.path.join(SERVICE_DIR, 'logs')
19WSGI_USER = 'www-data'
20WSGI_GROUP = 'www-data'
1821
19config = hookenv.config()22config = hookenv.config()
2023
24
21def log_start(service_name):25def log_start(service_name):
22 hookenv.log('adt-cloud-service starting')26 hookenv.log('adt-cloud-service starting')
2327
28
24def install_packages(service_name):29def install_packages(service_name):
25 hookenv.log('Installing dependencies...')30 hookenv.log('Installing dependencies...')
31 fetch.add_source('ppa:canonical-ci-engineering/ci-airline-phase-0')
26 fetch.configure_sources(update=True)32 fetch.configure_sources(update=True)
27 fetch.apt_install(REQUIRED_PACKAGES, fatal=True)33 fetch.apt_install(REQUIRED_PACKAGES, fatal=True)
2834
29def get_cloud_service_branch(service_name):35
30 branch = config['branch']36def get_cloud_service_from_tarball(service_name):
31 shutil.rmtree(SERVICE_DIR, ignore_errors=True)37 files_dir = os.path.join(hookenv.charm_dir(), 'files')
32 subprocess.call(['bzr', 'branch', branch, SERVICE_DIR])38 tarball = os.path.join(files_dir, 'adt-cloud-service.tgz')
39 if not os.path.exists(SERVICE_DIR):
40 hookenv.log('Installing the code for the first time from tarball')
41 extract_tarfile(tarball, '/srv/')
42
3343
34def get_config_file(service_name):44def get_config_file(service_name):
35 config_file = config.get('config-file')45 config_file = config.get('config-file')
36 if config_file is not None:46 if config_file is not None:
37 with open(os.path.join(SERVICE_DIR, '.adt-service.conf'), 'w') as f:47 with open(os.path.join(SERVICE_DIR, '.adt-service.conf'), 'w') as f:
38 f.write(base64.b64decode(config_file))48 f.write(base64.b64decode(config_file))
49
50
51def install_python_packages(service_name):
52 env_dir = os.path.join(SERVICE_DIR, 've')
53 if os.path.exists(env_dir):
54 hookenv.log('Service venv already exists, nothing to do ...')
55 return
56
57 hookenv.log('Installing python packages into the venv ...')
58 subprocess.check_call(['virtualenv', '-p', 'python3', env_dir])
59
60 pip_cache = os.path.join(hookenv.charm_dir(), 'files', 'pip-cache')
61 requirements = os.path.join(SERVICE_DIR, 'requirements.txt')
62
63 hookenv.log('Installing from download cache.')
64 subprocess.check_call(['%s/bin/pip' % env_dir,
65 'install',
66 '--no-index',
67 '--find-links={}'.format(pip_cache),
68 '-r', requirements])
69
70 subprocess.check_call(['%s/bin/pip' % env_dir,
71 'install', '--no-deps', '-e', SERVICE_DIR])
72
73def prepare_for_wsgi(service_name):
74 host.adduser(WSGI_USER)
75 host.add_group(WSGI_GROUP)
76 host.add_user_to_group(WSGI_USER, WSGI_GROUP)
77 if not os.path.exists(LOG_DIR):
78 host.mkdir(LOG_DIR, WSGI_USER, WSGI_GROUP, perms=0755)
79
80
81class WebsiteRelation(helpers.RelationContext):
82 name = 'website'
83 interface = 'http'
84
85 def provide_data(self):
86 data = {
87 'hostname': hookenv.unit_private_ip(),
88 'port': 8000,
89 }
90 return data
3991
=== modified file 'hooks/services.py'
--- hooks/services.py 2015-03-10 20:17:05 +0000
+++ hooks/services.py 2015-03-13 03:40:39 +0000
@@ -1,8 +1,8 @@
1#!/usr/bin/python1#!/usr/bin/python
22
3from charmhelpers.core import hookenv3from charmhelpers.core import hookenv
4from charmhelpers.core.services import helpers
4from charmhelpers.core.services.base import ServiceManager5from charmhelpers.core.services.base import ServiceManager
5from charmhelpers.core.services import helpers
66
7import actions7import actions
88
@@ -12,11 +12,14 @@
12 manager = ServiceManager([12 manager = ServiceManager([
13 {13 {
14 'service': 'adt-cloud-service',14 'service': 'adt-cloud-service',
15 'provided_data': [actions.WebsiteRelation()],
15 'required_data': [config],16 'required_data': [config],
16 'data_ready': [17 'data_ready': [
17 actions.install_packages,18 actions.install_packages,
18 actions.get_cloud_service_branch,19 actions.get_cloud_service_from_tarball,
20 actions.install_python_packages,
19 actions.get_config_file,21 actions.get_config_file,
22 actions.prepare_for_wsgi,
20 helpers.render_template(23 helpers.render_template(
21 source='upstart.conf',24 source='upstart.conf',
22 target='/etc/init/adt-cloud-service.conf'),25 target='/etc/init/adt-cloud-service.conf'),
2326
=== added file 'hooks/wsgi-relation-joined'
--- hooks/wsgi-relation-joined 1970-01-01 00:00:00 +0000
+++ hooks/wsgi-relation-joined 2015-03-13 03:40:39 +0000
@@ -0,0 +1,3 @@
1#!/usr/bin/python
2import services
3services.manage()
04
=== modified file 'metadata.yaml'
--- metadata.yaml 2015-03-10 20:17:05 +0000
+++ metadata.yaml 2015-03-13 03:40:39 +0000
@@ -1,5 +1,9 @@
1name: adt-cloud-service1name: adt-cloud-service
2summary: Deploy a service to handle adt jobs dispatched to a rabbit queue2summary: Deploys a web_app to handle adt jobs dispatched to a rabbit queue
3maintainer: Canonical CI Engineering <canonical-ci-engineering@lists.launchpad.net>3maintainer: Canonical CI Engineering <canonical-ci-engineering@lists.launchpad.net>
4description: |4description: |
5 Runs adt-cloud-service from a specified bzr branch5 Runs adt-cloud-service using gunicorn from given code tarball
6provides:
7 website:
8 interface: http
9 optional: true
610
=== added directory 'templates'
=== removed directory 'templates'
=== added file 'templates/upstart.conf'
--- templates/upstart.conf 1970-01-01 00:00:00 +0000
+++ templates/upstart.conf 2015-03-13 03:40:39 +0000
@@ -0,0 +1,28 @@
1description "Starts the adt-cloud-service with gunicorn"
2
3start on (local-filesystems and net-device-up IFACE=eth0)
4stop on runlevel [!12345]
5
6# use sigint so python code just needs to catch KeyboardInterrupt
7kill signal SIGINT
8
9# If the process quits unexpectedly trigger respawn it
10respawn
11# unless it fails 15 times within 5 seconds
12respawn limit 15 5
13
14env SERVICE_DIR=/srv/adt-cloud-service
15
16script
17
18 chdir ${SERVICE_DIR}
19
20 exec sudo -u www-data ./ve/bin/gunicorn \
21 --name=adt-cloud-service \
22 --bind=0.0.0.0 \
23 --log-file=${SERVICE_DIR}/logs/gunicorn.log \
24 --log-level=INFO \
25 --access-logfile=${SERVICE_DIR}/logs/access.log \
26 adt_cloud_service:app
27
28end script
029
=== removed file 'templates/upstart.conf'
--- templates/upstart.conf 2015-03-10 20:17:05 +0000
+++ templates/upstart.conf 1970-01-01 00:00:00 +0000
@@ -1,21 +0,0 @@
1description "Starts a adt-cloud-worker process"
2
3start on (local-filesystems and net-device-up IFACE=eth0)
4stop on runlevel [!12345]
5
6# use sigint so python code just needs to catch KeyboardInterrupt
7kill signal SIGINT
8
9# If the process quits unexpectedly trigger respawn it
10respawn
11# unless it fails 15 times within 5 seconds
12respawn limit 15 5
13
14env SERVICE_DIR=/srv/adt-cloud-worker
15
16script
17 mkdir -p ${SERVICE_DIR}/logs
18 # XXX cprov: respect py3 project choice once we have proper dependencies
19 # available.
20 exec python ${SERVICE_DIR}/adt-cloud-worker.py -c ${SERVICE_DIR}/.adt-service.conf >> ${SERVICE_DIR}/logs/adt-cloud-worker.log 2>&1
21end script

Subscribers

People subscribed via source and target branches