Merge lp:~corey.bryant/charms/trusty/cinder/git into lp:~openstack-charmers-archive/charms/trusty/cinder/next

Proposed by Corey Bryant
Status: Merged
Merged at revision: 86
Proposed branch: lp:~corey.bryant/charms/trusty/cinder/git
Merge into: lp:~openstack-charmers-archive/charms/trusty/cinder/next
Diff against target: 1450 lines (+899/-90)
30 files modified
Makefile (+6/-2)
README.md (+91/-0)
actions.yaml (+2/-0)
actions/git_reinstall.py (+45/-0)
charm-helpers-hooks.yaml (+1/-1)
config.yaml (+16/-0)
hooks/charmhelpers/contrib/openstack/utils.py (+4/-1)
hooks/cinder_hooks.py (+18/-8)
hooks/cinder_utils.py (+181/-4)
templates/git/cinder_sudoers (+4/-0)
templates/git/cinder_tgt.conf (+1/-0)
templates/git/logging.conf (+76/-0)
tests/00-setup (+3/-2)
tests/11-basic-precise-folsom (+0/-11)
tests/12-basic-precise-grizzly (+0/-11)
tests/13-basic-precise-havana (+0/-11)
tests/16-basic-trusty-icehouse-git (+9/-0)
tests/16-basic-vivid-kilo (+0/-9)
tests/17-basic-trusty-juno (+11/-0)
tests/17-basic-trusty-kilo (+0/-11)
tests/18-basic-trusty-juno-git (+12/-0)
tests/19-basic-trusty-kilo (+11/-0)
tests/20-basic-trusty-kilo-git (+12/-0)
tests/21-basic-vivid-kilo (+9/-0)
tests/22-basic-vivid-kilo-git (+9/-0)
tests/basic_deployment.py (+27/-3)
unit_tests/__init__.py (+2/-0)
unit_tests/test_actions_git_reinstall.py (+110/-0)
unit_tests/test_cinder_hooks.py (+74/-10)
unit_tests/test_cinder_utils.py (+165/-6)
To merge this branch: bzr merge lp:~corey.bryant/charms/trusty/cinder/git
Reviewer Review Type Date Requested Status
OpenStack Charmers Pending
Review via email: mp+254951@code.launchpad.net
To post a comment you must log in.
Corey Bryant (corey.bryant) wrote :

The conflicts don't make any sense to me so I'm leaving them as is. I don't think they're an issue.

92. By Corey Bryant on 2015-04-15

Move config_changed into try block

charm_lint_check #3409 cinder-next for corey.bryant mp254951
    LINT OK: passed

Build: http://10.245.162.77:8080/job/charm_lint_check/3409/

charm_unit_test #3197 cinder-next for corey.bryant mp254951
    UNIT OK: passed

Build: http://10.245.162.77:8080/job/charm_unit_test/3197/

charm_amulet_test #3202 cinder-next for corey.bryant mp254951
    AMULET FAIL: amulet-test failed

AMULET Results (max last 2 lines):
make: *** [test] Error 1
ERROR:root:Make target returned non-zero.

Full amulet test output: http://paste.ubuntu.com/10828226/
Build: http://10.245.162.77:8080/job/charm_amulet_test/3202/

Corey Bryant (corey.bryant) wrote :

The only amulet tests that are failing are kilo based tests.

Corey Bryant (corey.bryant) wrote :

> The only amulet tests that are failing are kilo based tests.

And that is expected atm.

93. By Corey Bryant on 2015-04-16

Sync charm-helpers

charm_lint_check #3451 cinder-next for corey.bryant mp254951
    LINT OK: passed

Build: http://10.245.162.77:8080/job/charm_lint_check/3451/

charm_unit_test #3239 cinder-next for corey.bryant mp254951
    UNIT OK: passed

Build: http://10.245.162.77:8080/job/charm_unit_test/3239/

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Makefile'
2--- Makefile 2015-02-19 11:51:46 +0000
3+++ Makefile 2015-04-16 14:41:14 +0000
4@@ -2,7 +2,7 @@
5 PYTHON := /usr/bin/env python
6
7 lint:
8- @flake8 --exclude hooks/charmhelpers hooks unit_tests tests
9+ @flake8 --exclude hooks/charmhelpers actions hooks unit_tests tests
10 @charm proof
11
12 unit_test:
13@@ -14,7 +14,11 @@
14 #NOTE(beisner): can remove -v after bug 1320357 is fixed
15 # https://bugs.launchpad.net/amulet/+bug/1320357
16 @juju test -v -p AMULET_HTTP_PROXY --timeout 900 \
17- 00-setup 14-basic-precise-icehouse 15-basic-trusty-icehouse
18+ 00-setup 14-basic-precise-icehouse 15-basic-trusty-icehouse \
19+ 16-basic-trusty-icehouse-git 17-basic-trusty-juno \
20+ 18-basic-trusty-juno-git 19-basic-trusty-kilo \
21+ 20-basic-trusty-kilo-git 21-basic-vivid-kilo \
22+ 22-basic-vivid-kilo-git
23
24 bin/charm_helpers_sync.py:
25 @mkdir -p bin
26
27=== modified file 'README.md'
28--- README.md 2015-01-08 12:03:18 +0000
29+++ README.md 2015-04-16 14:41:14 +0000
30@@ -117,3 +117,94 @@
31
32 enabled-services: Can be used to separate cinder services between service
33 service units (see previous section)
34+
35+Deploying from source
36+---------------------
37+
38+The minimum openstack-origin-git config required to deploy from source is:
39+
40+ openstack-origin-git:
41+ "repositories:
42+ - {name: requirements,
43+ repository: 'git://git.openstack.org/openstack/requirements',
44+ branch: stable/juno}
45+ - {name: cinder,
46+ repository: 'git://git.openstack.org/openstack/cinder',
47+ branch: stable/juno}"
48+
49+Note that there are only two 'name' values the charm knows about: 'requirements'
50+and 'cinder'. These repositories must correspond to these 'name' values.
51+Additionally, the requirements repository must be specified first and the
52+cinder repository must be specified last. All other repostories are installed
53+in the order in which they are specified.
54+
55+The following is a full list of current tip repos (may not be up-to-date):
56+
57+ openstack-origin-git:
58+ "repositories:
59+ - {name: requirements,
60+ repository: 'git://git.openstack.org/openstack/requirements',
61+ branch: master}
62+ - {name: oslo-concurrency,
63+ repository: 'git://git.openstack.org/openstack/oslo.concurrency',
64+ branch: master}
65+ - {name: oslo-config,
66+ repository: 'git://git.openstack.org/openstack/oslo.config',
67+ branch: master}
68+ - {name: oslo-context,
69+ repository': 'git://git.openstack.org/openstack/oslo.context.git',
70+ branch: master}
71+ - {name: oslo-db,
72+ repository: 'git://git.openstack.org/openstack/oslo.db',
73+ branch: master}
74+ - {name: oslo-i18n,
75+ repository: 'git://git.openstack.org/openstack/oslo.i18n',
76+ branch: master}
77+ - {name: oslo-messaging,
78+ repository: 'git://git.openstack.org/openstack/oslo.messaging.git',
79+ branch: master}
80+ - {name: oslo-serialization,
81+ repository: 'git://git.openstack.org/openstack/oslo.serialization',
82+ branch: master}
83+ - {name: oslo-utils,
84+ repository: 'git://git.openstack.org/openstack/oslo.utils',
85+ branch: master}
86+ - {name: oslo-rootwrap,
87+ repository: 'git://git.openstack.org/openstack/oslo.rootwrap.git',
88+ branch: master}
89+ - {name: oslo-vmware,
90+ repository: 'git://git.openstack.org/openstack/oslo.vmware.git',
91+ branch: master}
92+ - {name: osprofiler,
93+ repository: 'git://git.openstack.org/stackforge/osprofiler.git',
94+ branch: master}
95+ - {name: pbr,
96+ repository: 'git://git.openstack.org/openstack-dev/pbr',
97+ branch: master}
98+ - {name: python-barbicanclient,
99+ repository: 'git://git.openstack.org/openstack/python-barbicanclient.git',
100+ branch: master}
101+ - {name: python-glanceclient,
102+ repository: 'git://git.openstack.org/openstack/python-glanceclient.git',
103+ branch: master}
104+ - {name: python-novaclient,
105+ repository: 'git://git.openstack.org/openstack/python-novaclient.git',
106+ branch: master}
107+ - {name: python-swiftclient:
108+ repository: 'git://git.openstack.org/openstack/python-swiftclient.git',
109+ branch: master}
110+ - {name: sqlalchemy-migrate,
111+ repository: 'git://git.openstack.org/stackforge/sqlalchemy-migrate',
112+ branch: master}
113+ - {name: stevedore,
114+ repository: 'git://git.openstack.org/openstack/stevedore.git',
115+ branch: master}
116+ - {name: taskflow,
117+ repository: 'git://git.openstack.org/openstack/taskflow.git',
118+ branch: master}
119+ - {name: keystonemiddleware,
120+ repository: 'git://git.openstack.org/openstack/keystonemiddleware',
121+ branch: master}
122+ - {name: cinder,
123+ repository: 'git://git.openstack.org/openstack/cinder',
124+ branch: master}"
125
126=== added directory 'actions'
127=== added file 'actions.yaml'
128--- actions.yaml 1970-01-01 00:00:00 +0000
129+++ actions.yaml 2015-04-16 14:41:14 +0000
130@@ -0,0 +1,2 @@
131+git-reinstall:
132+ description: Reinstall cinder from the openstack-origin-git repositories.
133
134=== added symlink 'actions/git-reinstall'
135=== target is u'git_reinstall.py'
136=== added file 'actions/git_reinstall.py'
137--- actions/git_reinstall.py 1970-01-01 00:00:00 +0000
138+++ actions/git_reinstall.py 2015-04-16 14:41:14 +0000
139@@ -0,0 +1,45 @@
140+#!/usr/bin/python
141+import sys
142+import traceback
143+
144+sys.path.append('hooks/')
145+
146+from charmhelpers.contrib.openstack.utils import (
147+ git_install_requested,
148+)
149+
150+from charmhelpers.core.hookenv import (
151+ action_set,
152+ action_fail,
153+ config,
154+)
155+
156+from cinder_utils import (
157+ git_install,
158+)
159+
160+from cinder_hooks import (
161+ config_changed,
162+)
163+
164+
165+def git_reinstall():
166+ """Reinstall from source and restart services.
167+
168+ If the openstack-origin-git config option was used to install openstack
169+ from source git repositories, then this action can be used to reinstall
170+ from updated git repositories, followed by a restart of services."""
171+ if not git_install_requested():
172+ action_fail('openstack-origin-git is not configured')
173+ return
174+
175+ try:
176+ git_install(config('openstack-origin-git'))
177+ config_changed()
178+ except:
179+ action_set({'traceback': traceback.format_exc()})
180+ action_fail('git-reinstall resulted in an unexpected error')
181+
182+
183+if __name__ == '__main__':
184+ git_reinstall()
185
186=== modified file 'charm-helpers-hooks.yaml'
187--- charm-helpers-hooks.yaml 2015-03-18 18:35:28 +0000
188+++ charm-helpers-hooks.yaml 2015-04-16 14:41:14 +0000
189@@ -1,4 +1,4 @@
190-branch: lp:charm-helpers
191+branch: lp:charm-helpers
192 destination: hooks/charmhelpers
193 include:
194 - core
195
196=== modified file 'config.yaml'
197--- config.yaml 2015-03-16 09:38:03 +0000
198+++ config.yaml 2015-04-16 14:41:14 +0000
199@@ -15,6 +15,22 @@
200 the cloud:precise-folsom/updates repository instead, since Cinder
201 was not available in the Ubuntu archive for Precise and is only
202 available via the Ubuntu Cloud Archive.
203+
204+ Note that when openstack-origin-git is specified, openstack
205+ specific packages will be installed from source rather than
206+ from the openstack-origin repository.
207+ openstack-origin-git:
208+ default:
209+ type: string
210+ description: |
211+ Specifies a YAML-formatted dictionary listing the git
212+ repositories and branches from which to install OpenStack and
213+ its dependencies.
214+
215+ Note that the installed config files will be determined based on
216+ the OpenStack release of the openstack-origin option.
217+
218+ For more details see README.md.
219 enabled-services:
220 default: all
221 type: string
222
223=== modified file 'hooks/charmhelpers/contrib/openstack/utils.py'
224--- hooks/charmhelpers/contrib/openstack/utils.py 2015-04-09 04:52:26 +0000
225+++ hooks/charmhelpers/contrib/openstack/utils.py 2015-04-16 14:41:14 +0000
226@@ -524,9 +524,10 @@
227 projects = yaml.load(projects_yaml)
228 _git_validate_projects_yaml(projects, core_project)
229
230+ old_environ = dict(os.environ)
231+
232 if 'http_proxy' in projects.keys():
233 os.environ['http_proxy'] = projects['http_proxy']
234-
235 if 'https_proxy' in projects.keys():
236 os.environ['https_proxy'] = projects['https_proxy']
237
238@@ -544,6 +545,8 @@
239 repo_dir = _git_clone_and_install_single(repo, branch, parent_dir,
240 update_requirements=True)
241
242+ os.environ = old_environ
243+
244
245 def _git_validate_projects_yaml(projects, core_project):
246 """
247
248=== modified file 'hooks/cinder_hooks.py'
249--- hooks/cinder_hooks.py 2015-03-31 08:37:22 +0000
250+++ hooks/cinder_hooks.py 2015-04-16 14:41:14 +0000
251@@ -10,6 +10,7 @@
252 from cinder_utils import (
253 determine_packages,
254 do_openstack_upgrade,
255+ git_install,
256 juju_log,
257 migrate_database,
258 configure_lvm_storage,
259@@ -53,10 +54,12 @@
260 )
261
262 from charmhelpers.contrib.openstack.utils import (
263+ config_value_changed,
264 configure_installation_source,
265+ git_install_requested,
266 openstack_upgrade_available,
267 sync_db_with_multi_ipv6_addresses,
268- get_os_codename_package
269+ os_release,
270 )
271
272 from charmhelpers.contrib.storage.linux.ceph import (
273@@ -101,9 +104,12 @@
274 src == 'distro'):
275 src = 'cloud:precise-folsom'
276 configure_installation_source(src)
277+
278 apt_update()
279 apt_install(determine_packages(), fatal=True)
280
281+ git_install(config('openstack-origin-git'))
282+
283
284 @hooks.hook('config-changed')
285 @restart_on_change(restart_map(), stopstart=True)
286@@ -123,12 +129,16 @@
287 conf['overwrite'] in ['true', 'True', True],
288 conf['remove-missing'])
289
290- if openstack_upgrade_available('cinder-common'):
291- do_openstack_upgrade(configs=CONFIGS)
292- # NOTE(jamespage) tell any storage-backends we just upgraded
293- for rid in relation_ids('storage-backend'):
294- relation_set(relation_id=rid,
295- upgrade_nonce=uuid.uuid4())
296+ if git_install_requested():
297+ if config_value_changed('openstack-origin-git'):
298+ git_install(config('openstack-origin-git'))
299+ else:
300+ if openstack_upgrade_available('cinder-common'):
301+ do_openstack_upgrade(configs=CONFIGS)
302+ # NOTE(jamespage) tell any storage-backends we just upgraded
303+ for rid in relation_ids('storage-backend'):
304+ relation_set(relation_id=rid,
305+ upgrade_nonce=uuid.uuid4())
306
307 CONFIGS.write_all()
308 configure_https()
309@@ -255,7 +265,7 @@
310 'cinder_internal_url': internal_url,
311 'cinder_admin_url': admin_url,
312 }
313- if get_os_codename_package('cinder-common') >= 'icehouse':
314+ if os_release('cinder-common') >= 'icehouse':
315 # NOTE(jamespage) register v2 endpoint as well
316 public_url = '{}:{}/v2/$(tenant_id)s'.format(
317 canonical_url(CONFIGS, PUBLIC),
318
319=== modified file 'hooks/cinder_utils.py'
320--- hooks/cinder_utils.py 2015-04-09 03:10:16 +0000
321+++ hooks/cinder_utils.py 2015-04-16 14:41:14 +0000
322@@ -1,10 +1,12 @@
323 import os
324+import shutil
325 import subprocess
326
327 from collections import OrderedDict
328 from copy import copy
329
330 from charmhelpers.core.hookenv import (
331+ charm_dir,
332 config,
333 relation_ids,
334 log,
335@@ -19,12 +21,17 @@
336 )
337
338 from charmhelpers.core.host import (
339+ adduser,
340+ add_group,
341+ add_user_to_group,
342+ lsb_release,
343+ mkdir,
344 mounts,
345 umount,
346+ service_restart,
347 service_stop,
348 service_start,
349- mkdir,
350- lsb_release
351+ write_file,
352 )
353
354 from charmhelpers.contrib.openstack.alternatives import install_alternative
355@@ -58,10 +65,15 @@
356
357 from charmhelpers.contrib.openstack.utils import (
358 configure_installation_source,
359- get_os_codename_package,
360 get_os_codename_install_source,
361+ git_install_requested,
362+ git_clone_and_install,
363+ git_src_dir,
364+ os_release,
365 )
366
367+from charmhelpers.core.templating import render
368+
369 import cinder_contexts
370
371 COMMON_PACKAGES = [
372@@ -81,6 +93,25 @@
373 VOLUME_PACKAGES = ['cinder-volume']
374 SCHEDULER_PACKAGES = ['cinder-scheduler']
375
376+BASE_GIT_PACKAGES = [
377+ 'libxml2-dev',
378+ 'libxslt1-dev',
379+ 'lvm2',
380+ 'python-dev',
381+ 'python-pip',
382+ 'python-setuptools',
383+ 'zlib1g-dev',
384+]
385+
386+# ubuntu packages that should not be installed when deploying from source
387+GIT_PACKAGE_BLACKLIST = [
388+ 'cinder-api',
389+ 'cinder-common',
390+ 'cinder-scheduler',
391+ 'cinder-volume',
392+ 'python-keystoneclient',
393+]
394+
395 DEFAULT_LOOPBACK_SIZE = '5G'
396
397 # Cluster resource used to determine leadership when hacluster'd
398@@ -166,7 +197,7 @@
399 # if called without anything installed (eg during install hook)
400 # just default to earliest supported release. configs dont get touched
401 # till post-install, anyway.
402- release = get_os_codename_package('cinder-common', fatal=False) or 'folsom'
403+ release = os_release('cinder-common', base='folsom')
404 configs = templating.OSConfigRenderer(templates_dir=TEMPLATES,
405 openstack_release=release)
406
407@@ -218,6 +249,13 @@
408 ('scheduler', SCHEDULER_PACKAGES)]:
409 if service_enabled(s):
410 pkgs += p
411+
412+ if git_install_requested():
413+ pkgs.extend(BASE_GIT_PACKAGES)
414+ # don't include packages that will be installed from git
415+ for p in GIT_PACKAGE_BLACKLIST:
416+ pkgs.remove(p)
417+
418 return pkgs
419
420
421@@ -467,3 +505,142 @@
422 ' main')
423 apt_update()
424 apt_install('haproxy/trusty-backports', fatal=True)
425+
426+
427+def git_install(projects_yaml):
428+ """Perform setup, and install git repos specified in yaml parameter."""
429+ if git_install_requested():
430+ git_pre_install()
431+ git_clone_and_install(projects_yaml, core_project='cinder')
432+ git_post_install(projects_yaml)
433+
434+
435+def git_pre_install():
436+ """Perform cinder pre-install setup."""
437+ dirs = [{'path': '/etc/tgt',
438+ 'owner': 'cinder',
439+ 'group': 'cinder',
440+ 'perms': 0750,
441+ },
442+ {'path': '/var/lib/cinder',
443+ 'owner': 'cinder',
444+ 'group': 'cinder',
445+ 'perms': 0755,
446+ },
447+ {'path': '/var/lib/cinder/volumes',
448+ 'owner': 'cinder',
449+ 'group': 'cinder',
450+ 'perms': 0750,
451+ },
452+ {'path': '/var/lock/cinder',
453+ 'owner': 'cinder',
454+ 'group': 'root',
455+ 'perms': 0750,
456+ },
457+ {'path': '/var/log/cinder',
458+ 'owner': 'cinder',
459+ 'group': 'cinder',
460+ 'perms': 0750,
461+ }]
462+
463+ logs = [
464+ '/var/log/cinder/cinder-api.log',
465+ '/var/log/cinder/cinder-backup.log',
466+ '/var/log/cinder/cinder-scheduler.log',
467+ '/var/log/cinder/cinder-volume.log',
468+ ]
469+
470+ adduser('cinder', shell='/bin/bash', system_user=True)
471+ add_group('cinder', system_group=True)
472+ add_user_to_group('cinder', 'cinder')
473+
474+ for d in dirs:
475+ mkdir(d['path'], owner=d['owner'], group=d['group'], perms=d['perms'],
476+ force=False)
477+
478+ for l in logs:
479+ write_file(l, '', owner='cinder', group='cinder', perms=0600)
480+
481+
482+def git_post_install(projects_yaml):
483+ """Perform cinder post-install setup."""
484+ src_etc = os.path.join(git_src_dir(projects_yaml, 'cinder'), 'etc/cinder')
485+ configs = {
486+ 'src': src_etc,
487+ 'dest': '/etc/cinder',
488+ }
489+
490+ if os.path.exists(configs['dest']):
491+ shutil.rmtree(configs['dest'])
492+ shutil.copytree(configs['src'], configs['dest'])
493+
494+ render('cinder.conf', '/etc/cinder/cinder.conf', {}, owner='cinder',
495+ group='cinder', perms=0o644)
496+ render('git/cinder_tgt.conf', '/etc/tgt/conf.d', {}, owner='cinder',
497+ group='cinder', perms=0o644)
498+ render('git/logging.conf', '/etc/cinder/logging.conf', {}, owner='cinder',
499+ group='cinder', perms=0o644)
500+ render('git/cinder_sudoers', '/etc/sudoers.d/cinder_sudoers', {},
501+ owner='root', group='root', perms=0o440)
502+
503+ os.chmod('/etc/sudoers.d', 0o750)
504+
505+ cinder_api_context = {
506+ 'service_description': 'Cinder API server',
507+ 'service_name': 'Cinder',
508+ 'user_name': 'cinder',
509+ 'start_dir': '/var/lib/cinder',
510+ 'process_name': 'cinder-api',
511+ 'executable_name': '/usr/local/bin/cinder-api',
512+ 'config_files': ['/etc/cinder/cinder.conf'],
513+ 'log_file': '/var/log/cinder/cinder-api.log',
514+ }
515+
516+ cinder_backup_context = {
517+ 'service_description': 'Cinder backup server',
518+ 'service_name': 'Cinder',
519+ 'user_name': 'cinder',
520+ 'start_dir': '/var/lib/cinder',
521+ 'process_name': 'cinder-backup',
522+ 'executable_name': '/usr/local/bin/cinder-backup',
523+ 'config_files': ['/etc/cinder/cinder.conf'],
524+ 'log_file': '/var/log/cinder/cinder-backup.log',
525+ }
526+
527+ cinder_scheduler_context = {
528+ 'service_description': 'Cinder scheduler server',
529+ 'service_name': 'Cinder',
530+ 'user_name': 'cinder',
531+ 'start_dir': '/var/lib/cinder',
532+ 'process_name': 'cinder-scheduler',
533+ 'executable_name': '/usr/local/bin/cinder-scheduler',
534+ 'config_files': ['/etc/cinder/cinder.conf'],
535+ 'log_file': '/var/log/cinder/cinder-scheduler.log',
536+ }
537+
538+ cinder_volume_context = {
539+ 'service_description': 'Cinder volume server',
540+ 'service_name': 'Cinder',
541+ 'user_name': 'cinder',
542+ 'start_dir': '/var/lib/cinder',
543+ 'process_name': 'cinder-volume',
544+ 'executable_name': '/usr/local/bin/cinder-volume',
545+ 'config_files': ['/etc/cinder/cinder.conf'],
546+ 'log_file': '/var/log/cinder/cinder-volume.log',
547+ }
548+
549+ # NOTE(coreycb): Needs systemd support
550+ templates_dir = 'hooks/charmhelpers/contrib/openstack/templates'
551+ templates_dir = os.path.join(charm_dir(), templates_dir)
552+ render('git.upstart', '/etc/init/cinder-api.conf',
553+ cinder_api_context, perms=0o644, templates_dir=templates_dir)
554+ render('git.upstart', '/etc/init/cinder-backup.conf',
555+ cinder_backup_context, perms=0o644, templates_dir=templates_dir)
556+ render('git.upstart', '/etc/init/cinder-scheduler.conf',
557+ cinder_scheduler_context, perms=0o644, templates_dir=templates_dir)
558+ render('git.upstart', '/etc/init/cinder-volume.conf',
559+ cinder_volume_context, perms=0o644, templates_dir=templates_dir)
560+
561+ service_restart('tgtd')
562+
563+ [service_restart(s) for s in services()]
564
565=== added directory 'templates/git'
566=== added file 'templates/git/cinder_sudoers'
567--- templates/git/cinder_sudoers 1970-01-01 00:00:00 +0000
568+++ templates/git/cinder_sudoers 2015-04-16 14:41:14 +0000
569@@ -0,0 +1,4 @@
570+Defaults:cinder !requiretty
571+
572+cinder ALL = (root) NOPASSWD: /usr/local/bin/cinder-rootwrap /etc/cinder/rootwrap.conf *
573+
574
575=== added file 'templates/git/cinder_tgt.conf'
576--- templates/git/cinder_tgt.conf 1970-01-01 00:00:00 +0000
577+++ templates/git/cinder_tgt.conf 2015-04-16 14:41:14 +0000
578@@ -0,0 +1,1 @@
579+include /var/lib/cinder/volumes/*
580
581=== added file 'templates/git/logging.conf'
582--- templates/git/logging.conf 1970-01-01 00:00:00 +0000
583+++ templates/git/logging.conf 2015-04-16 14:41:14 +0000
584@@ -0,0 +1,76 @@
585+[loggers]
586+keys = root, cinder
587+
588+[handlers]
589+keys = stderr, stdout, watchedfile, syslog, null
590+
591+[formatters]
592+keys = legacycinder, default
593+
594+[logger_root]
595+level = WARNING
596+handlers = null
597+
598+[logger_cinder]
599+level = INFO
600+handlers = stderr
601+qualname = cinder
602+
603+[logger_amqplib]
604+level = WARNING
605+handlers = stderr
606+qualname = amqplib
607+
608+[logger_sqlalchemy]
609+level = WARNING
610+handlers = stderr
611+qualname = sqlalchemy
612+# "level = INFO" logs SQL queries.
613+# "level = DEBUG" logs SQL queries and results.
614+# "level = WARNING" logs neither. (Recommended for production systems.)
615+
616+[logger_boto]
617+level = WARNING
618+handlers = stderr
619+qualname = boto
620+
621+[logger_suds]
622+level = INFO
623+handlers = stderr
624+qualname = suds
625+
626+[logger_eventletwsgi]
627+level = WARNING
628+handlers = stderr
629+qualname = eventlet.wsgi.server
630+
631+[handler_stderr]
632+class = StreamHandler
633+args = (sys.stderr,)
634+formatter = legacycinder
635+
636+[handler_stdout]
637+class = StreamHandler
638+args = (sys.stdout,)
639+formatter = legacycinder
640+
641+[handler_watchedfile]
642+class = handlers.WatchedFileHandler
643+args = ('cinder.log',)
644+formatter = legacycinder
645+
646+[handler_syslog]
647+class = handlers.SysLogHandler
648+args = ('/dev/log', handlers.SysLogHandler.LOG_USER)
649+formatter = legacycinder
650+
651+[handler_null]
652+class = cinder.log.NullHandler
653+formatter = default
654+args = ()
655+
656+[formatter_legacycinder]
657+class = cinder.log.LegacyCinderFormatter
658+
659+[formatter_default]
660+format = %(message)s
661
662=== modified file 'tests/00-setup'
663--- tests/00-setup 2014-10-07 18:32:59 +0000
664+++ tests/00-setup 2015-04-16 14:41:14 +0000
665@@ -5,6 +5,7 @@
666 sudo add-apt-repository --yes ppa:juju/stable
667 sudo apt-get update --yes
668 sudo apt-get install --yes python-amulet \
669+ python-cinderclient \
670+ python-glanceclient \
671 python-keystoneclient \
672- python-cinderclient \
673- python-glanceclient
674+ python-novaclient
675
676=== removed file 'tests/11-basic-precise-folsom'
677--- tests/11-basic-precise-folsom 2014-07-31 15:27:14 +0000
678+++ tests/11-basic-precise-folsom 1970-01-01 00:00:00 +0000
679@@ -1,11 +0,0 @@
680-#!/usr/bin/python
681-
682-"""Amulet tests on a basic cinder deployment on precise-folsom."""
683-
684-from basic_deployment import CinderBasicDeployment
685-
686-if __name__ == '__main__':
687- deployment = CinderBasicDeployment(series='precise',
688- openstack='cloud:precise-folsom',
689- source='cloud:precise-updates/folsom')
690- deployment.run_tests()
691
692=== removed file 'tests/12-basic-precise-grizzly'
693--- tests/12-basic-precise-grizzly 2014-07-31 15:27:14 +0000
694+++ tests/12-basic-precise-grizzly 1970-01-01 00:00:00 +0000
695@@ -1,11 +0,0 @@
696-#!/usr/bin/python
697-
698-"""Amulet tests on a basic cinder deployment on precise-grizzly."""
699-
700-from basic_deployment import CinderBasicDeployment
701-
702-if __name__ == '__main__':
703- deployment = CinderBasicDeployment(series='precise',
704- openstack='cloud:precise-grizzly',
705- source='cloud:precise-updates/grizzly')
706- deployment.run_tests()
707
708=== removed file 'tests/13-basic-precise-havana'
709--- tests/13-basic-precise-havana 2014-07-31 15:27:14 +0000
710+++ tests/13-basic-precise-havana 1970-01-01 00:00:00 +0000
711@@ -1,11 +0,0 @@
712-#!/usr/bin/python
713-
714-"""Amulet tests on a basic cinder deployment on precise-havana."""
715-
716-from basic_deployment import CinderBasicDeployment
717-
718-if __name__ == '__main__':
719- deployment = CinderBasicDeployment(series='precise',
720- openstack='cloud:precise-havana',
721- source='cloud:precise-updates/havana')
722- deployment.run_tests()
723
724=== added file 'tests/16-basic-trusty-icehouse-git'
725--- tests/16-basic-trusty-icehouse-git 1970-01-01 00:00:00 +0000
726+++ tests/16-basic-trusty-icehouse-git 2015-04-16 14:41:14 +0000
727@@ -0,0 +1,9 @@
728+#!/usr/bin/python
729+
730+"""Amulet tests on a basic Cinder git deployment on trusty-icehouse."""
731+
732+from basic_deployment import CinderBasicDeployment
733+
734+if __name__ == '__main__':
735+ deployment = CinderBasicDeployment(series='trusty', git=True)
736+ deployment.run_tests()
737
738=== removed file 'tests/16-basic-vivid-kilo'
739--- tests/16-basic-vivid-kilo 2015-04-13 19:33:14 +0000
740+++ tests/16-basic-vivid-kilo 1970-01-01 00:00:00 +0000
741@@ -1,9 +0,0 @@
742-#!/usr/bin/python
743-
744-"""Amulet tests on a basic Cinder deployment on vivid-kilo."""
745-
746-from basic_deployment import CinderBasicDeployment
747-
748-if __name__ == '__main__':
749- deployment = CinderBasicDeployment(series='vivid')
750- deployment.run_tests()
751
752=== added file 'tests/17-basic-trusty-juno'
753--- tests/17-basic-trusty-juno 1970-01-01 00:00:00 +0000
754+++ tests/17-basic-trusty-juno 2015-04-16 14:41:14 +0000
755@@ -0,0 +1,11 @@
756+#!/usr/bin/python
757+
758+"""Amulet tests on a basic Cinder deployment on trusty-juno."""
759+
760+from basic_deployment import CinderBasicDeployment
761+
762+if __name__ == '__main__':
763+ deployment = CinderBasicDeployment(series='trusty',
764+ openstack='cloud:trusty-juno',
765+ source='cloud:trusty-updates/juno')
766+ deployment.run_tests()
767
768=== removed file 'tests/17-basic-trusty-kilo'
769--- tests/17-basic-trusty-kilo 2015-04-13 19:33:14 +0000
770+++ tests/17-basic-trusty-kilo 1970-01-01 00:00:00 +0000
771@@ -1,11 +0,0 @@
772-#!/usr/bin/python
773-
774-"""Amulet tests on a basic cinder deployment on trusty-kilo."""
775-
776-from basic_deployment import CinderBasicDeployment
777-
778-if __name__ == '__main__':
779- deployment = CinderBasicDeployment(series='trusty',
780- openstack='cloud:trusty-kilo',
781- source='cloud:trusty-updates/kilo')
782- deployment.run_tests()
783
784=== added file 'tests/18-basic-trusty-juno-git'
785--- tests/18-basic-trusty-juno-git 1970-01-01 00:00:00 +0000
786+++ tests/18-basic-trusty-juno-git 2015-04-16 14:41:14 +0000
787@@ -0,0 +1,12 @@
788+#!/usr/bin/python
789+
790+"""Amulet tests on a basic Cinder git deployment on trusty-juno."""
791+
792+from basic_deployment import CinderBasicDeployment
793+
794+if __name__ == '__main__':
795+ deployment = CinderBasicDeployment(series='trusty',
796+ openstack='cloud:trusty-juno',
797+ source='cloud:trusty-updates/juno',
798+ git=True)
799+ deployment.run_tests()
800
801=== added file 'tests/19-basic-trusty-kilo'
802--- tests/19-basic-trusty-kilo 1970-01-01 00:00:00 +0000
803+++ tests/19-basic-trusty-kilo 2015-04-16 14:41:14 +0000
804@@ -0,0 +1,11 @@
805+#!/usr/bin/python
806+
807+"""Amulet tests on a basic cinder deployment on trusty-kilo."""
808+
809+from basic_deployment import CinderBasicDeployment
810+
811+if __name__ == '__main__':
812+ deployment = CinderBasicDeployment(series='trusty',
813+ openstack='cloud:trusty-kilo',
814+ source='cloud:trusty-updates/kilo')
815+ deployment.run_tests()
816
817=== added file 'tests/20-basic-trusty-kilo-git'
818--- tests/20-basic-trusty-kilo-git 1970-01-01 00:00:00 +0000
819+++ tests/20-basic-trusty-kilo-git 2015-04-16 14:41:14 +0000
820@@ -0,0 +1,12 @@
821+#!/usr/bin/python
822+
823+"""Amulet tests on a basic cinder git deployment on trusty-kilo."""
824+
825+from basic_deployment import CinderBasicDeployment
826+
827+if __name__ == '__main__':
828+ deployment = CinderBasicDeployment(series='trusty',
829+ openstack='cloud:trusty-kilo',
830+ source='cloud:trusty-updates/kilo',
831+ git=True)
832+ deployment.run_tests()
833
834=== added file 'tests/21-basic-vivid-kilo'
835--- tests/21-basic-vivid-kilo 1970-01-01 00:00:00 +0000
836+++ tests/21-basic-vivid-kilo 2015-04-16 14:41:14 +0000
837@@ -0,0 +1,9 @@
838+#!/usr/bin/python
839+
840+"""Amulet tests on a basic Cinder deployment on vivid-kilo."""
841+
842+from basic_deployment import CinderBasicDeployment
843+
844+if __name__ == '__main__':
845+ deployment = CinderBasicDeployment(series='vivid')
846+ deployment.run_tests()
847
848=== added file 'tests/22-basic-vivid-kilo-git'
849--- tests/22-basic-vivid-kilo-git 1970-01-01 00:00:00 +0000
850+++ tests/22-basic-vivid-kilo-git 2015-04-16 14:41:14 +0000
851@@ -0,0 +1,9 @@
852+#!/usr/bin/python
853+
854+"""Amulet tests on a basic Cinder git deployment on vivid-kilo."""
855+
856+from basic_deployment import CinderBasicDeployment
857+
858+if __name__ == '__main__':
859+ deployment = CinderBasicDeployment(series='vivid', git=True)
860+ deployment.run_tests()
861
862=== modified file 'tests/basic_deployment.py'
863--- tests/basic_deployment.py 2015-04-13 19:39:27 +0000
864+++ tests/basic_deployment.py 2015-04-16 14:41:14 +0000
865@@ -1,8 +1,10 @@
866 #!/usr/bin/python
867
868 import amulet
869+import os
870 import types
871 from time import sleep
872+import yaml
873 import cinderclient.v1.client as cinder_client
874
875 from charmhelpers.contrib.openstack.amulet.deployment import (
876@@ -28,10 +30,12 @@
877 # NOTE(beisner): Features and tests vary across Openstack releases.
878 # https://wiki.openstack.org/wiki/CinderSupportMatrix
879
880- def __init__(self, series=None, openstack=None, source=None, stable=False):
881+ def __init__(self, series=None, openstack=None, source=None, git=False,
882+ stable=False):
883 '''Deploy the entire test environment.'''
884 super(CinderBasicDeployment, self).__init__(series, openstack, source,
885 stable)
886+ self.git = git
887 self._add_services()
888 self._add_relations()
889 self._configure_services()
890@@ -67,11 +71,31 @@
891
892 def _configure_services(self):
893 '''Configure all of the services.'''
894- keystone_config = {'admin-password': 'openstack',
895- 'admin-token': 'ubuntutesting'}
896 cinder_config = {'block-device': 'vdb',
897 'glance-api-version': '2',
898 'overwrite': 'true'}
899+ if self.git:
900+ branch = 'stable/' + self._get_openstack_release_string()
901+ amulet_http_proxy = os.environ.get('AMULET_HTTP_PROXY')
902+ openstack_origin_git = {
903+ 'repositories': [
904+ {'name': 'requirements',
905+ 'repository':
906+ 'git://git.openstack.org/openstack/requirements',
907+ 'branch': branch},
908+ {'name': 'cinder',
909+ 'repository': 'git://git.openstack.org/openstack/cinder',
910+ 'branch': branch},
911+ ],
912+ 'directory': '/mnt/openstack-git',
913+ 'http_proxy': amulet_http_proxy,
914+ 'https_proxy': amulet_http_proxy,
915+ }
916+ cinder_config['openstack-origin-git'] = \
917+ yaml.dump(openstack_origin_git)
918+
919+ keystone_config = {'admin-password': 'openstack',
920+ 'admin-token': 'ubuntutesting'}
921 mysql_config = {'dataset-size': '50%'}
922 configs = {'cinder': cinder_config,
923 'keystone': keystone_config,
924
925=== modified file 'unit_tests/__init__.py'
926--- unit_tests/__init__.py 2013-10-17 21:48:08 +0000
927+++ unit_tests/__init__.py 2015-04-16 14:41:14 +0000
928@@ -1,2 +1,4 @@
929 import sys
930+
931+sys.path.append('actions')
932 sys.path.append('hooks')
933
934=== added file 'unit_tests/test_actions_git_reinstall.py'
935--- unit_tests/test_actions_git_reinstall.py 1970-01-01 00:00:00 +0000
936+++ unit_tests/test_actions_git_reinstall.py 2015-04-16 14:41:14 +0000
937@@ -0,0 +1,110 @@
938+from mock import patch, MagicMock
939+import os
940+
941+os.environ['JUJU_UNIT_NAME'] = 'cinder'
942+
943+from test_utils import RESTART_MAP
944+import cinder_utils as utils
945+
946+# Need to do some early patching to get the module loaded.
947+_restart_map = utils.restart_map
948+_register_configs = utils.register_configs
949+
950+utils.restart_map = MagicMock()
951+utils.restart_map.return_value = RESTART_MAP
952+utils.register_configs = MagicMock()
953+
954+import git_reinstall
955+
956+# Unpatch it now that its loaded.
957+utils.restart_map = _restart_map
958+utils.register_configs = _register_configs
959+
960+
961+from test_utils import (
962+ CharmTestCase
963+)
964+
965+TO_PATCH = [
966+ 'config',
967+]
968+
969+
970+openstack_origin_git = \
971+ """repositories:
972+ - {name: requirements,
973+ repository: 'git://git.openstack.org/openstack/requirements',
974+ branch: stable/juno}
975+ - {name: cinder,
976+ repository: 'git://git.openstack.org/openstack/cinder',
977+ branch: stable/juno}"""
978+
979+
980+class TestCinderActions(CharmTestCase):
981+
982+ def setUp(self):
983+ super(TestCinderActions, self).setUp(git_reinstall, TO_PATCH)
984+ self.config.side_effect = self.test_config.get
985+
986+ @patch.object(git_reinstall, 'action_set')
987+ @patch.object(git_reinstall, 'action_fail')
988+ @patch.object(git_reinstall, 'git_install')
989+ @patch.object(git_reinstall, 'config_changed')
990+ @patch('charmhelpers.contrib.openstack.utils.config')
991+ def test_git_reinstall(self, _config, config_changed, git_install,
992+ action_fail, action_set):
993+ _config.return_value = openstack_origin_git
994+ self.test_config.set('openstack-origin-git', openstack_origin_git)
995+
996+ git_reinstall.git_reinstall()
997+
998+ git_install.assert_called_with(openstack_origin_git)
999+ self.assertTrue(git_install.called)
1000+ self.assertTrue(config_changed.called)
1001+ self.assertFalse(action_set.called)
1002+ self.assertFalse(action_fail.called)
1003+
1004+ @patch.object(git_reinstall, 'action_set')
1005+ @patch.object(git_reinstall, 'action_fail')
1006+ @patch.object(git_reinstall, 'git_install')
1007+ @patch.object(git_reinstall, 'config_changed')
1008+ @patch('charmhelpers.contrib.openstack.utils.config')
1009+ def test_git_reinstall_not_configured(self, _config, config_changed,
1010+ git_install, action_fail,
1011+ action_set):
1012+ _config.return_value = None
1013+
1014+ git_reinstall.git_reinstall()
1015+
1016+ msg = 'openstack-origin-git is not configured'
1017+ action_fail.assert_called_with(msg)
1018+ self.assertFalse(git_install.called)
1019+ self.assertFalse(action_set.called)
1020+
1021+ @patch.object(git_reinstall, 'action_set')
1022+ @patch.object(git_reinstall, 'action_fail')
1023+ @patch.object(git_reinstall, 'git_install')
1024+ @patch.object(git_reinstall, 'config_changed')
1025+ @patch('traceback.format_exc')
1026+ @patch('charmhelpers.contrib.openstack.utils.config')
1027+ def test_git_reinstall_exception(self, _config, format_exc, config_changed,
1028+ git_install, action_fail, action_set):
1029+ _config.return_value = openstack_origin_git
1030+ e = OSError('something bad happened')
1031+ git_install.side_effect = e
1032+ traceback = (
1033+ "Traceback (most recent call last):\n"
1034+ " File \"actions/git_reinstall.py\", line 37, in git_reinstall\n"
1035+ " git_install(config(\'openstack-origin-git\'))\n"
1036+ " File \"/usr/lib/python2.7/dist-packages/mock.py\", line 964, in __call__\n" # noqa
1037+ " return _mock_self._mock_call(*args, **kwargs)\n"
1038+ " File \"/usr/lib/python2.7/dist-packages/mock.py\", line 1019, in _mock_call\n" # noqa
1039+ " raise effect\n"
1040+ "OSError: something bad happened\n")
1041+ format_exc.return_value = traceback
1042+
1043+ git_reinstall.git_reinstall()
1044+
1045+ msg = 'git-reinstall resulted in an unexpected error'
1046+ action_fail.assert_called_with(msg)
1047+ action_set.assert_called_with({'traceback': traceback})
1048
1049=== modified file 'unit_tests/test_cinder_hooks.py'
1050--- unit_tests/test_cinder_hooks.py 2015-03-31 08:37:22 +0000
1051+++ unit_tests/test_cinder_hooks.py 2015-04-16 14:41:14 +0000
1052@@ -4,6 +4,7 @@
1053 patch,
1054 call
1055 )
1056+import yaml
1057
1058 import cinder_utils as utils
1059 from test_utils import (
1060@@ -35,6 +36,7 @@
1061 'determine_packages',
1062 'do_openstack_upgrade',
1063 'ensure_ceph_keyring',
1064+ 'git_install',
1065 'juju_log',
1066 'log',
1067 'lsb_release',
1068@@ -63,7 +65,7 @@
1069 # charmhelpers.contrib.openstack.openstack_utils
1070 'configure_installation_source',
1071 'openstack_upgrade_available',
1072- 'get_os_codename_package',
1073+ 'os_release',
1074 # charmhelpers.contrib.hahelpers.cluster_utils
1075 'canonical_url',
1076 'eligible_leader',
1077@@ -79,17 +81,47 @@
1078
1079 def setUp(self):
1080 super(TestInstallHook, self).setUp(hooks, TO_PATCH)
1081- self.config.side_effect = self.test_config.get_all
1082+ self.config.side_effect = self.test_config.get
1083
1084- def test_install_precise_distro(self):
1085+ @patch.object(utils, 'git_install_requested')
1086+ def test_install_precise_distro(self, git_requested):
1087 'It redirects to cloud archive if setup to install precise+distro'
1088+ git_requested.return_value = False
1089 self.lsb_release.return_value = {'DISTRIB_CODENAME': 'precise'}
1090 hooks.hooks.execute(['hooks/install'])
1091 ca = 'cloud:precise-folsom'
1092 self.configure_installation_source.assert_called_with(ca)
1093
1094- def test_correct_install_packages(self):
1095+ @patch.object(utils, 'git_install_requested')
1096+ def test_install_git(self, git_requested):
1097+ git_requested.return_value = True
1098+ self.determine_packages.return_value = ['foo', 'bar', 'baz']
1099+ repo = 'cloud:trusty-juno'
1100+ openstack_origin_git = {
1101+ 'repositories': [
1102+ {'name': 'requirements',
1103+ 'repository': 'git://git.openstack.org/openstack/requirements', # noqa
1104+ 'branch': 'stable/juno'},
1105+ {'name': 'cinder',
1106+ 'repository': 'git://git.openstack.org/openstack/cinder',
1107+ 'branch': 'stable/juno'}
1108+ ],
1109+ 'directory': '/mnt/openstack-git',
1110+ }
1111+ projects_yaml = yaml.dump(openstack_origin_git)
1112+ self.test_config.set('openstack-origin', repo)
1113+ self.test_config.set('openstack-origin-git', projects_yaml)
1114+ hooks.hooks.execute(['hooks/install'])
1115+ self.assertTrue(self.execd_preinstall.called)
1116+ self.configure_installation_source.assert_called_with(repo)
1117+ self.apt_update.assert_called_with()
1118+ self.apt_install.assert_called_with(['foo', 'bar', 'baz'], fatal=True)
1119+ self.git_install.assert_called_with(projects_yaml)
1120+
1121+ @patch.object(utils, 'git_install_requested')
1122+ def test_correct_install_packages(self, git_requested):
1123 'It installs the correct packages based on what is determined'
1124+ git_requested.return_value = False
1125 self.determine_packages.return_value = ['foo', 'bar', 'baz']
1126 hooks.hooks.execute(['hooks/install'])
1127 self.apt_install.assert_called_with(['foo', 'bar', 'baz'], fatal=True)
1128@@ -99,7 +131,7 @@
1129
1130 def setUp(self):
1131 super(TestChangedHooks, self).setUp(hooks, TO_PATCH)
1132- self.config.side_effect = self.test_config.get_all
1133+ self.config.side_effect = self.test_config.get
1134
1135 @patch.object(hooks, 'amqp_joined')
1136 def test_upgrade_charm_no_amqp(self, _joined):
1137@@ -114,8 +146,10 @@
1138 _joined.assert_called_with(relation_id='amqp:1')
1139
1140 @patch.object(hooks, 'configure_https')
1141- def test_config_changed(self, conf_https):
1142+ @patch.object(hooks, 'git_install_requested')
1143+ def test_config_changed(self, git_requested, conf_https):
1144 'It writes out all config'
1145+ git_requested.return_value = False
1146 self.openstack_upgrade_available.return_value = False
1147 hooks.hooks.execute(['hooks/config-changed'])
1148 self.assertTrue(self.CONFIGS.write_all.called)
1149@@ -125,8 +159,10 @@
1150 False, False)
1151
1152 @patch.object(hooks, 'configure_https')
1153- def test_config_changed_block_devices(self, conf_https):
1154+ @patch.object(hooks, 'git_install_requested')
1155+ def test_config_changed_block_devices(self, git_requested, conf_https):
1156 'It writes out all config'
1157+ git_requested.return_value = False
1158 self.openstack_upgrade_available.return_value = False
1159 self.test_config.set('block-device', 'sdb /dev/sdc sde')
1160 self.test_config.set('volume-group', 'cinder-new')
1161@@ -141,12 +177,40 @@
1162 True, True)
1163
1164 @patch.object(hooks, 'configure_https')
1165- def test_config_changed_upgrade_available(self, conf_https):
1166+ @patch.object(hooks, 'git_install_requested')
1167+ def test_config_changed_upgrade_available(self, git_requested, conf_https):
1168 'It writes out all config with an available OS upgrade'
1169+ git_requested.return_value = False
1170 self.openstack_upgrade_available.return_value = True
1171 hooks.hooks.execute(['hooks/config-changed'])
1172 self.do_openstack_upgrade.assert_called_with(configs=self.CONFIGS)
1173
1174+ @patch.object(hooks, 'configure_https')
1175+ @patch.object(hooks, 'git_install_requested')
1176+ @patch.object(hooks, 'config_value_changed')
1177+ def test_config_changed_git_updated(self, config_val_changed,
1178+ git_requested, conf_https):
1179+ git_requested.return_value = True
1180+ repo = 'cloud:trusty-juno'
1181+ openstack_origin_git = {
1182+ 'repositories': [
1183+ {'name': 'requirements',
1184+ 'repository': 'git://git.openstack.org/openstack/requirements', # noqa
1185+ 'branch': 'stable/juno'},
1186+ {'name': 'cinder',
1187+ 'repository': 'git://git.openstack.org/openstack/',
1188+ 'branch': 'stable/juno'}
1189+ ],
1190+ 'directory': '/mnt/openstack-git',
1191+ }
1192+ projects_yaml = yaml.dump(openstack_origin_git)
1193+ self.test_config.set('openstack-origin', repo)
1194+ self.test_config.set('openstack-origin-git', projects_yaml)
1195+ hooks.hooks.execute(['hooks/config-changed'])
1196+ self.git_install.assert_called_with(projects_yaml)
1197+ self.assertFalse(self.do_openstack_upgrade.called)
1198+ self.assertTrue(conf_https.called)
1199+
1200 def test_db_changed(self):
1201 'It writes out cinder.conf on db changed'
1202 self.relation_get.return_value = 'cinder/0 cinder/1'
1203@@ -341,7 +405,7 @@
1204
1205 def test_identity_service_joined(self):
1206 'It properly requests unclustered endpoint via identity-service'
1207- self.get_os_codename_package.return_value = 'havana'
1208+ self.os_release.return_value = 'havana'
1209 self.unit_get.return_value = 'cindernode1'
1210 self.config.side_effect = self.test_config.get
1211 self.canonical_url.return_value = 'http://cindernode1'
1212@@ -363,7 +427,7 @@
1213
1214 def test_identity_service_joined_icehouse(self):
1215 'It properly requests unclustered endpoint via identity-service'
1216- self.get_os_codename_package.return_value = 'icehouse'
1217+ self.os_release.return_value = 'icehouse'
1218 self.unit_get.return_value = 'cindernode1'
1219 self.config.side_effect = self.test_config.get
1220 self.canonical_url.return_value = 'http://cindernode1'
1221
1222=== modified file 'unit_tests/test_cinder_utils.py'
1223--- unit_tests/test_cinder_utils.py 2014-12-15 10:17:11 +0000
1224+++ unit_tests/test_cinder_utils.py 2015-04-16 14:41:14 +0000
1225@@ -30,7 +30,7 @@
1226 'ensure_loopback_device',
1227 'is_block_device',
1228 'zap_disk',
1229- 'get_os_codename_package',
1230+ 'os_release',
1231 'get_os_codename_install_source',
1232 'configure_installation_source',
1233 'eligible_leader',
1234@@ -68,6 +68,15 @@
1235
1236 """
1237
1238+openstack_origin_git = \
1239+ """repositories:
1240+ - {name: requirements,
1241+ repository: 'git://git.openstack.org/openstack/requirements',
1242+ branch: stable/juno}
1243+ - {name: cinder,
1244+ repository: 'git://git.openstack.org/openstack/cinder',
1245+ branch: stable/juno}"""
1246+
1247
1248 class TestCinderUtils(CharmTestCase):
1249
1250@@ -97,8 +106,10 @@
1251 self.assertFalse(cinder_utils.service_enabled('volume'))
1252
1253 @patch('cinder_utils.service_enabled')
1254- def test_determine_packages_all(self, service_enabled):
1255+ @patch('cinder_utils.git_install_requested')
1256+ def test_determine_packages_all(self, git_requested, service_enabled):
1257 'It determines all packages required when all services enabled'
1258+ git_requested.return_value = False
1259 service_enabled.return_value = True
1260 pkgs = cinder_utils.determine_packages()
1261 self.assertEquals(sorted(pkgs),
1262@@ -108,8 +119,10 @@
1263 cinder_utils.SCHEDULER_PACKAGES))
1264
1265 @patch('cinder_utils.service_enabled')
1266- def test_determine_packages_subset(self, service_enabled):
1267+ @patch('cinder_utils.git_install_requested')
1268+ def test_determine_packages_subset(self, git_requested, service_enabled):
1269 'It determines packages required for a subset of enabled services'
1270+ git_requested.return_value = False
1271 service_enabled.side_effect = self.svc_enabled
1272
1273 self.test_config.set('enabled-services', 'api')
1274@@ -402,7 +415,7 @@
1275 @patch('os.path.exists')
1276 def test_register_configs_apache(self, exists):
1277 exists.return_value = False
1278- self.get_os_codename_package.return_value = 'grizzly'
1279+ self.os_release.return_value = 'grizzly'
1280 self.relation_ids.return_value = False
1281 configs = cinder_utils.register_configs()
1282 calls = []
1283@@ -419,7 +432,7 @@
1284 @patch('os.path.exists')
1285 def test_register_configs_apache24(self, exists):
1286 exists.return_value = True
1287- self.get_os_codename_package.return_value = 'grizzly'
1288+ self.os_release.return_value = 'grizzly'
1289 self.relation_ids.return_value = False
1290 configs = cinder_utils.register_configs()
1291 calls = []
1292@@ -438,7 +451,7 @@
1293 def test_register_configs_ceph(self, exists, isdir):
1294 exists.return_value = True
1295 isdir.return_value = False
1296- self.get_os_codename_package.return_value = 'grizzly'
1297+ self.os_release.return_value = 'grizzly'
1298 self.relation_ids.return_value = ['ceph:0']
1299 self.ceph_config_file.return_value = '/var/lib/charm/cinder/ceph.conf'
1300 configs = cinder_utils.register_configs()
1301@@ -504,3 +517,149 @@
1302 self.apt_install.assert_called_with(['mypackage'], fatal=True)
1303 configs.set_release.assert_called_with(openstack_release='havana')
1304 self.assertFalse(migrate.called)
1305+
1306+ @patch.object(cinder_utils, 'git_install_requested')
1307+ @patch.object(cinder_utils, 'git_clone_and_install')
1308+ @patch.object(cinder_utils, 'git_post_install')
1309+ @patch.object(cinder_utils, 'git_pre_install')
1310+ def test_git_install(self, git_pre, git_post, git_clone_and_install,
1311+ git_requested):
1312+ projects_yaml = openstack_origin_git
1313+ git_requested.return_value = True
1314+ cinder_utils.git_install(projects_yaml)
1315+ self.assertTrue(git_pre.called)
1316+ git_clone_and_install.assert_called_with(openstack_origin_git,
1317+ core_project='cinder')
1318+ self.assertTrue(git_post.called)
1319+
1320+ @patch.object(cinder_utils, 'mkdir')
1321+ @patch.object(cinder_utils, 'write_file')
1322+ @patch.object(cinder_utils, 'add_user_to_group')
1323+ @patch.object(cinder_utils, 'add_group')
1324+ @patch.object(cinder_utils, 'adduser')
1325+ def test_git_pre_install(self, adduser, add_group, add_user_to_group,
1326+ write_file, mkdir):
1327+ cinder_utils.git_pre_install()
1328+ adduser.assert_called_with('cinder', shell='/bin/bash',
1329+ system_user=True)
1330+ add_group.assert_called_with('cinder', system_group=True)
1331+ add_user_to_group.assert_called_with('cinder', 'cinder')
1332+ expected = [
1333+ call('/etc/tgt', owner='cinder', perms=488, force=False,
1334+ group='cinder'),
1335+ call('/var/lib/cinder', owner='cinder', perms=493, force=False,
1336+ group='cinder'),
1337+ call('/var/lib/cinder/volumes', owner='cinder', perms=488,
1338+ force=False, group='cinder'),
1339+ call('/var/lock/cinder', owner='cinder', perms=488, force=False,
1340+ group='root'),
1341+ call('/var/log/cinder', owner='cinder', perms=488, force=False,
1342+ group='cinder'),
1343+ ]
1344+ self.assertEquals(mkdir.call_args_list, expected)
1345+ expected = [
1346+ call('/var/log/cinder/cinder-api.log', '', perms=0600,
1347+ owner='cinder', group='cinder'),
1348+ call('/var/log/cinder/cinder-backup.log', '', perms=0600,
1349+ owner='cinder', group='cinder'),
1350+ call('/var/log/cinder/cinder-scheduler.log', '', perms=0600,
1351+ owner='cinder', group='cinder'),
1352+ call('/var/log/cinder/cinder-volume.log', '', perms=0600,
1353+ owner='cinder', group='cinder'),
1354+ ]
1355+ self.assertEquals(write_file.call_args_list, expected)
1356+
1357+ @patch.object(cinder_utils, 'git_src_dir')
1358+ @patch.object(cinder_utils, 'service_restart')
1359+ @patch.object(cinder_utils, 'render')
1360+ @patch('os.path.join')
1361+ @patch('os.path.exists')
1362+ @patch('shutil.copytree')
1363+ @patch('shutil.rmtree')
1364+ @patch('pwd.getpwnam')
1365+ @patch('grp.getgrnam')
1366+ @patch('os.chown')
1367+ @patch('os.chmod')
1368+ def test_git_post_install(self, chmod, chown, grp, pwd, rmtree, copytree,
1369+ exists, join, render, service_restart,
1370+ git_src_dir):
1371+ projects_yaml = openstack_origin_git
1372+ join.return_value = 'joined-string'
1373+ cinder_utils.git_post_install(projects_yaml)
1374+ expected = [
1375+ call('joined-string', '/etc/cinder'),
1376+ ]
1377+ copytree.assert_has_calls(expected)
1378+
1379+ cinder_api_context = {
1380+ 'service_description': 'Cinder API server',
1381+ 'service_name': 'Cinder',
1382+ 'user_name': 'cinder',
1383+ 'start_dir': '/var/lib/cinder',
1384+ 'process_name': 'cinder-api',
1385+ 'executable_name': '/usr/local/bin/cinder-api',
1386+ 'config_files': ['/etc/cinder/cinder.conf'],
1387+ 'log_file': '/var/log/cinder/cinder-api.log',
1388+ }
1389+
1390+ cinder_backup_context = {
1391+ 'service_description': 'Cinder backup server',
1392+ 'service_name': 'Cinder',
1393+ 'user_name': 'cinder',
1394+ 'start_dir': '/var/lib/cinder',
1395+ 'process_name': 'cinder-backup',
1396+ 'executable_name': '/usr/local/bin/cinder-backup',
1397+ 'config_files': ['/etc/cinder/cinder.conf'],
1398+ 'log_file': '/var/log/cinder/cinder-backup.log',
1399+ }
1400+
1401+ cinder_scheduler_context = {
1402+ 'service_description': 'Cinder scheduler server',
1403+ 'service_name': 'Cinder',
1404+ 'user_name': 'cinder',
1405+ 'start_dir': '/var/lib/cinder',
1406+ 'process_name': 'cinder-scheduler',
1407+ 'executable_name': '/usr/local/bin/cinder-scheduler',
1408+ 'config_files': ['/etc/cinder/cinder.conf'],
1409+ 'log_file': '/var/log/cinder/cinder-scheduler.log',
1410+ }
1411+
1412+ cinder_volume_context = {
1413+ 'service_description': 'Cinder volume server',
1414+ 'service_name': 'Cinder',
1415+ 'user_name': 'cinder',
1416+ 'start_dir': '/var/lib/cinder',
1417+ 'process_name': 'cinder-volume',
1418+ 'executable_name': '/usr/local/bin/cinder-volume',
1419+ 'config_files': ['/etc/cinder/cinder.conf'],
1420+ 'log_file': '/var/log/cinder/cinder-volume.log',
1421+ }
1422+ expected = [
1423+ call('cinder.conf', '/etc/cinder/cinder.conf', {}, owner='cinder',
1424+ group='cinder', perms=0o644),
1425+ call('git/cinder_tgt.conf', '/etc/tgt/conf.d', {}, owner='cinder',
1426+ group='cinder', perms=0o644),
1427+ call('git/logging.conf', '/etc/cinder/logging.conf', {},
1428+ owner='cinder', group='cinder', perms=0o644),
1429+ call('git/cinder_sudoers', '/etc/sudoers.d/cinder_sudoers', {},
1430+ owner='root', group='root', perms=0o440),
1431+ call('git.upstart', '/etc/init/cinder-api.conf',
1432+ cinder_api_context, perms=0o644,
1433+ templates_dir='joined-string'),
1434+ call('git.upstart', '/etc/init/cinder-backup.conf',
1435+ cinder_backup_context, perms=0o644,
1436+ templates_dir='joined-string'),
1437+ call('git.upstart', '/etc/init/cinder-scheduler.conf',
1438+ cinder_scheduler_context, perms=0o644,
1439+ templates_dir='joined-string'),
1440+ call('git.upstart', '/etc/init/cinder-volume.conf',
1441+ cinder_volume_context, perms=0o644,
1442+ templates_dir='joined-string'),
1443+ ]
1444+ self.assertEquals(render.call_args_list, expected)
1445+ expected = [
1446+ call('tgtd'), call('haproxy'), call('apache2'),
1447+ call('cinder-api'), call('cinder-volume'),
1448+ call('cinder-scheduler'),
1449+ ]
1450+ self.assertEquals(service_restart.call_args_list, expected)

Subscribers

People subscribed via source and target branches