Merge lp:~cjwatson/charms/trusty/turnip/code-in-swift into lp:~canonical-launchpad-branches/charms/trusty/turnip/devel

Proposed by Colin Watson
Status: Rejected
Rejected by: Colin Watson
Proposed branch: lp:~cjwatson/charms/trusty/turnip/code-in-swift
Merge into: lp:~canonical-launchpad-branches/charms/trusty/turnip/devel
Diff against target: 170 lines (+111/-4)
2 files modified
config.yaml (+28/-0)
hooks/actions.py (+83/-4)
To merge this branch: bzr merge lp:~cjwatson/charms/trusty/turnip/code-in-swift
Reviewer Review Type Date Requested Status
Launchpad code reviewers Pending
Review via email: mp+262198@code.launchpad.net

Commit message

Add support for fetching turnip payload from Swift.

Description of the change

Add support for fetching turnip payload from Swift.

I haven't actually tested this yet, but it will be a lot easier to do on qastaging than locally! The code is modelled reasonably closely on that in the certification charm (lp:~gnuoy/canonical-is-charms/certification-python), so it should be more or less right.

To post a comment you must log in.
Revision history for this message
Kit Randel (blr) wrote :

LGTM, although would it be worth factoring out the name of the tarball?

82. By Colin Watson

Factor out tarball name.

Revision history for this message
Colin Watson (cjwatson) wrote :

This has long since been superseded by the in-tree charm.

Unmerged revisions

82. By Colin Watson

Factor out tarball name.

81. By Colin Watson

Add support for fetching turnip payload from Swift.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'config.yaml'
--- config.yaml 2015-05-22 15:42:11 +0000
+++ config.yaml 2015-06-18 13:52:10 +0000
@@ -37,6 +37,10 @@
37 type: string37 type: string
38 default: '19417'38 default: '19417'
39 description: API port.39 description: API port.
40 code_src:
41 type: string
42 default: 'local'
43 description: Code source: 'local' or 'swift'.
40 revision:44 revision:
41 type: string45 type: string
42 default: '1'46 default: '1'
@@ -120,6 +124,30 @@
120 description: |124 description: |
121 Hosts that should be allowed to rsync logs. Note that this relies on125 Hosts that should be allowed to rsync logs. Note that this relies on
122 basenode.126 basenode.
127 swift_username:
128 type: string
129 default: ""
130 description: Username to use when accessing Swift.
131 swift_password:
132 type: string
133 default: ""
134 description: Password to use when accessing Swift.
135 swift_auth_url:
136 type: string
137 default: ""
138 description: URL for authenticating against Keystone.
139 swift_region_name:
140 type: string
141 default: ""
142 description: Swift region.
143 swift_tenant_name:
144 type: string
145 default: ""
146 description: Entity that owns resources.
147 swift_container_name:
148 type: string
149 default: ""
150 description: Container to put objects in.
123151
124 # apt configuration used by charmhelpers.152 # apt configuration used by charmhelpers.
125 install_sources:153 install_sources:
126154
=== modified file 'hooks/actions.py'
--- hooks/actions.py 2015-05-22 15:42:11 +0000
+++ hooks/actions.py 2015-06-18 13:52:10 +0000
@@ -1,5 +1,6 @@
1import base641import base64
2import grp2import grp
3import hashlib
3import os4import os
4import pwd5import pwd
5import shutil6import shutil
@@ -39,6 +40,7 @@
39LOGS_DIR = os.path.join(BASE_DIR, 'logs')40LOGS_DIR = os.path.join(BASE_DIR, 'logs')
40DATA_DIR = os.path.join(BASE_DIR, 'data')41DATA_DIR = os.path.join(BASE_DIR, 'data')
41KEY_DIR = os.path.join(BASE_DIR, 'keys')42KEY_DIR = os.path.join(BASE_DIR, 'keys')
43CODE_TARBALL = 'turnip.tar.gz'
4244
43CODE_USER = config['code_user']45CODE_USER = config['code_user']
44CODE_GROUP = config['code_group']46CODE_GROUP = config['code_group']
@@ -87,16 +89,90 @@
87 host.add_user_to_group(USER, CGIT_GROUP)89 host.add_user_to_group(USER, CGIT_GROUP)
8890
8991
92def get_swift_creds(config):
93 return {
94 'user': config['swift_username'],
95 'project': config['swift_tenant_name'],
96 'password': config['swift_password'],
97 'authurl': config['swift_auth_url'],
98 'region': config['swift_region_name'],
99 }
100
101
102def swift_base_cmd(**swift_creds):
103 return [
104 'swift',
105 '--os-username=' + swift_creds['user'],
106 '--os-tenant-name=' + swift_creds['project'],
107 '--os-password=' + swift_creds['password'],
108 '--os-auth-url=' + swift_creds['authurl'],
109 '--os-region-name=' + swift_creds['region'],
110 ]
111
112
113def swift_get_etag(name, container=None, **swift_creds):
114 cmd = swift_base_cmd(**swift_creds) + ['stat', container, name]
115 file_stat = subprocess.check_output(cmd).splitlines()
116 for line in file_stat:
117 words = line.split()
118 if words[0] == 'ETag:':
119 return words[1]
120
121
122def swift_fetch(source, target, container=None, **swift_creds):
123 cmd = swift_base_cmd(**swift_creds) + [
124 'download', '--output=' + target, container, source]
125 subprocess.check_call(cmd)
126
127
128def md5sum(filename):
129 md5 = hashlib.md5()
130 with open(filename, 'rb') as f:
131 for chunk in iter(lambda: f.read(128 * md5.block_size), b''):
132 md5.update(chunk)
133 return md5.hexdigest()
134
135
90def unpack_source(service_name):136def unpack_source(service_name):
91 hookenv.log('Deploying source...')137 hookenv.log('Deploying source...')
92138
93 make_srv_location()139 make_srv_location()
94140
95 # Copy source archive141 # Copy source archive
96 archive_path = os.path.join(BASE_DIR, 'turnip.tar.gz')142 archive_path = os.path.join(BASE_DIR, CODE_TARBALL)
143 if os.path.exists(archive_path):
144 archive_md5sum = md5sum(archive_path)
145 else:
146 archive_md5sum = None
97147
98 with open(os.path.join(CHARM_FILES_DIR, 'turnip.tar.gz')) as file:148 if config['code_src'] == 'swift':
99 host.write_file(archive_path, file.read(), perms=0o644)149 swift_creds = get_swift_creds(config)
150 swift_container = config['swift_container_name']
151 swift_etag = swift_get_etag(
152 CODE_TARBALL, container=swift_container, **swift_creds)
153 if swift_etag is None:
154 raise Exception(
155 'code_src == swift, but %s not found in Swift' % CODE_TARBALL)
156 if archive_md5sum is not None and swift_etag == archive_md5sum:
157 hookenv.log(
158 'Skipping code deployment: checksum of %s matches checksum '
159 'of file in Swift' % archive_path)
160 return
161 swift_fetch(
162 CODE_TARBALL, archive_path, container=swift_container,
163 **swift_creds)
164 elif config['code_src'] == 'local':
165 charm_path = os.path.join(CHARM_FILES_DIR, CODE_TARBALL)
166 if archive_md5sum is not None and md5sum(charm_path) == archive_md5sum:
167 hookenv.log(
168 'Skipping code deployment: checksum of %s matches checksum '
169 'of %s' % (archive_path, charm_path))
170 return
171 with open(charm_path) as file:
172 host.write_file(archive_path, file.read(), perms=0o644)
173 else:
174 raise Exception(
175 "Unsupported code_src value: '%s'" % config['code_src'])
100176
101 # Unpack source177 # Unpack source
102 archive.extract_tarfile(archive_path, CODE_DIR)178 archive.extract_tarfile(archive_path, CODE_DIR)
@@ -109,7 +185,10 @@
109def install_packages(service_name):185def install_packages(service_name):
110 hookenv.log('Installing system packages...')186 hookenv.log('Installing system packages...')
111 fetch.configure_sources(update=True)187 fetch.configure_sources(update=True)
112 fetch.apt_install(REQUIRED_PACKAGES, fatal=True)188 packages = list(REQUIRED_PACKAGES)
189 if config['code_src'] == 'swift':
190 packages.append('python-swiftclient')
191 fetch.apt_install(packages, fatal=True)
113192
114193
115def install_python_packages(service_name):194def install_python_packages(service_name):

Subscribers

People subscribed via source and target branches

to all changes: