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

Proposed by Corey Bryant
Status: Merged
Merged at revision: 107
Proposed branch: lp:~corey.bryant/charms/trusty/glance/git
Merge into: lp:~openstack-charmers-archive/charms/trusty/glance/next
Diff against target: 1485 lines (+849/-152) (has conflicts)
23 files modified
.bzrignore (+1/-0)
Makefile (+4/-2)
README.md (+82/-0)
actions.yaml (+2/-0)
actions/git_reinstall.py (+45/-0)
config.yaml (+16/-0)
hooks/charmhelpers/contrib/openstack/templates/git.upstart (+17/-0)
hooks/charmhelpers/contrib/openstack/templates/section-zeromq (+14/-0)
hooks/charmhelpers/contrib/openstack/utils.py (+126/-60)
hooks/glance_relations.py (+20/-11)
hooks/glance_utils.py (+133/-7)
tests/10-basic-precise-essex (+0/-9)
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/17-basic-trusty-juno (+11/-0)
tests/18-basic-trusty-juno-git (+12/-0)
tests/basic_deployment.py (+27/-4)
unit_tests/__init__.py (+1/-0)
unit_tests/test_actions_git_reinstall.py (+96/-0)
unit_tests/test_glance_relations.py (+92/-18)
unit_tests/test_glance_utils.py (+141/-8)
Conflict adding file hooks/charmhelpers/contrib/openstack/templates/git.upstart.  Moved existing file to hooks/charmhelpers/contrib/openstack/templates/git.upstart.moved.
Conflict adding file hooks/charmhelpers/contrib/openstack/templates/section-zeromq.  Moved existing file to hooks/charmhelpers/contrib/openstack/templates/section-zeromq.moved.
Text conflict in hooks/charmhelpers/contrib/openstack/utils.py
To merge this branch: bzr merge lp:~corey.bryant/charms/trusty/glance/git
Reviewer Review Type Date Requested Status
James Page Needs Fixing
Review via email: mp+254645@code.launchpad.net
To post a comment you must log in.
103. By Corey Bryant

Deploy from source

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_lint_check #3081 glance-next for corey.bryant mp254645
    LINT OK: passed

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

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_unit_test #2869 glance-next for corey.bryant mp254645
    UNIT OK: passed

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

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_amulet_test #2899 glance-next for corey.bryant mp254645
    AMULET OK: passed

Build: http://10.245.162.77:8080/job/charm_amulet_test/2899/

104. By Corey Bryant

Pass list of config_files to git.upstart template

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_lint_check #3165 glance-next for corey.bryant mp254645
    LINT OK: passed

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

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_unit_test #2953 glance-next for corey.bryant mp254645
    UNIT FAIL: unit-test failed

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

Full unit test output: http://paste.ubuntu.com/10775162/
Build: http://10.245.162.77:8080/job/charm_unit_test/2953/

105. By Corey Bryant

Unit test updates for config file template change

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_lint_check #3167 glance-next for corey.bryant mp254645
    LINT OK: passed

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

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_unit_test #2955 glance-next for corey.bryant mp254645
    UNIT OK: passed

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

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_amulet_test #2957 glance-next for corey.bryant mp254645
    AMULET OK: passed

Build: http://10.245.162.77:8080/job/charm_amulet_test/2957/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_amulet_test #2959 glance-next for corey.bryant mp254645
    AMULET OK: passed

Build: http://10.245.162.77:8080/job/charm_amulet_test/2959/

Revision history for this message
James Page (james-page) :
review: Needs Fixing
106. By Corey Bryant

Get http_proxy from AMULET_HTTP_PROXY env var

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_lint_check #3281 glance-next for corey.bryant mp254645
    LINT OK: passed

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

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_unit_test #3069 glance-next for corey.bryant mp254645
    UNIT OK: passed

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

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_amulet_test #3098 glance-next for corey.bryant mp254645
    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/10815589/
Build: http://10.245.162.77:8080/job/charm_amulet_test/3098/

Revision history for this message
Ryan Beisner (1chb1n) wrote :

Hi Corey - just a few inline comments re: possibly non-existent os env var, for the scenarios where amulet tests might be run outside of our test infrastructure.

Revision history for this message
Corey Bryant (corey.bryant) wrote :

Hi Ryan, thanks for the comments. I think it should be ok as is since os.environ.get() returns None for a non-existing key.

Revision history for this message
Ryan Beisner (1chb1n) wrote :

Oh, sweet! I've only ever used os.environ['SOMETHING']. Good to know, learn something every day!

Revision history for this message
Corey Bryant (corey.bryant) wrote :

Oh yeah, I think the .get() gets you the None behavior

107. By Corey Bryant

Bulk copy files to /etc/glance

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_lint_check #3299 glance-next for corey.bryant mp254645
    LINT OK: passed

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

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_unit_test #3087 glance-next for corey.bryant mp254645
    UNIT OK: passed

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

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_amulet_test #3116 glance-next for corey.bryant mp254645
    AMULET OK: passed

Build: http://10.245.162.77:8080/job/charm_amulet_test/3116/

108. By Corey Bryant

Turn DEBUG on by default for amulet tests

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_lint_check #3303 glance-next for corey.bryant mp254645
    LINT OK: passed

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

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_unit_test #3091 glance-next for corey.bryant mp254645
    UNIT OK: passed

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

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_amulet_test #3122 glance-next for corey.bryant mp254645
    AMULET OK: passed

Build: http://10.245.162.77:8080/job/charm_amulet_test/3122/

109. By Corey Bryant

Run config-changed hook after git-reinstall action installs from source

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_lint_check #3315 glance-next for corey.bryant mp254645
    LINT OK: passed

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

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_unit_test #3103 glance-next for corey.bryant mp254645
    UNIT OK: passed

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

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_amulet_test #3136 glance-next for corey.bryant mp254645
    AMULET OK: passed

Build: http://10.245.162.77:8080/job/charm_amulet_test/3136/

110. By Corey Bryant

Fixup test_git_reinstall_exception()

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_lint_check #3394 glance-next for corey.bryant mp254645
    LINT OK: passed

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

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_unit_test #3182 glance-next for corey.bryant mp254645
    UNIT OK: passed

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

111. By Corey Bryant

Sync charm-helpers

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_lint_check #3402 glance-next for corey.bryant mp254645
    LINT OK: passed

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

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_unit_test #3190 glance-next for corey.bryant mp254645
    UNIT OK: passed

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

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_amulet_test #3184 glance-next for corey.bryant mp254645
    AMULET OK: passed

Build: http://10.245.162.77:8080/job/charm_amulet_test/3184/

112. By Corey Bryant

Move config_changed into try block

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_lint_check #3408 glance-next for corey.bryant mp254645
    LINT OK: passed

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

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_unit_test #3196 glance-next for corey.bryant mp254645
    UNIT OK: passed

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

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_amulet_test #3195 glance-next for corey.bryant mp254645
    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/10827819/
Build: http://10.245.162.77:8080/job/charm_amulet_test/3195/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_amulet_test #3201 glance-next for corey.bryant mp254645
    AMULET OK: passed

Build: http://10.245.162.77:8080/job/charm_amulet_test/3201/

113. By Corey Bryant

Sync charm-helpers

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_lint_check #3450 glance-next for corey.bryant mp254645
    LINT OK: passed

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

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_unit_test #3238 glance-next for corey.bryant mp254645
    UNIT OK: passed

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

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_amulet_test #3248 glance-next for corey.bryant mp254645
    AMULET OK: passed

Build: http://10.245.162.77:8080/job/charm_amulet_test/3248/

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.bzrignore'
2--- .bzrignore 2014-07-02 08:09:03 +0000
3+++ .bzrignore 2015-04-16 14:42:02 +0000
4@@ -1,2 +1,3 @@
5 .coverage
6 bin
7+tags
8
9=== modified file 'Makefile'
10--- Makefile 2014-10-08 20:18:38 +0000
11+++ Makefile 2015-04-16 14:42:02 +0000
12@@ -3,7 +3,7 @@
13
14 lint:
15 @echo "Running flake8 tests: "
16- @flake8 --exclude hooks/charmhelpers hooks unit_tests tests
17+ @flake8 --exclude hooks/charmhelpers actions hooks unit_tests tests
18 @echo "OK"
19 @echo "Running charm proof: "
20 @charm proof
21@@ -27,7 +27,9 @@
22 # raise_status() messages to stderr:
23 # https://bugs.launchpad.net/amulet/+bug/1320357
24 @juju test -v -p AMULET_HTTP_PROXY --timeout 900 \
25- 00-setup 14-basic-precise-icehouse 15-basic-trusty-icehouse
26+ 00-setup 14-basic-precise-icehouse 15-basic-trusty-icehouse \
27+ 16-basic-trusty-icehouse-git 17-basic-trusty-juno \
28+ 18-basic-trusty-juno-git
29
30 publish: lint unit_test
31 bzr push lp:charms/glance
32
33=== modified file 'README.md'
34--- README.md 2013-09-26 10:22:09 +0000
35+++ README.md 2015-04-16 14:42:02 +0000
36@@ -81,6 +81,88 @@
37 Note that Glance in this configuration must be used with either Ceph or
38 Swift providing backing image storage.
39
40+Deploying from source
41+---------------------
42+
43+The minimum openstack-origin-git config required to deploy from source is:
44+
45+ openstack-origin-git:
46+ "repositories:
47+ - {name: requirements,
48+ repository: 'git://git.openstack.org/openstack/requirements',
49+ branch: stable/juno}
50+ - {name: glance,
51+ repository: 'git://git.openstack.org/openstack/glance',
52+ branch: stable/juno}"
53+
54+Note that there are only two 'name' values the charm knows about: 'requirements'
55+and 'glance'. These repositories must correspond to these 'name' values.
56+Additionally, the requirements repository must be specified first and the
57+glance repository must be specified last. All other repostories are installed
58+in the order in which they are specified.
59+
60+The following is a full list of current tip repos (may not be up-to-date):
61+
62+ openstack-origin-git:
63+ "repositories:
64+ - {name: requirements,
65+ repository: 'git://git.openstack.org/openstack/requirements',
66+ branch: master}
67+ - {name: oslo-concurrency,
68+ repository: 'git://git.openstack.org/openstack/oslo.concurrency',
69+ branch: master}
70+ - {name: oslo-config,
71+ repository: 'git://git.openstack.org/openstack/oslo.config',
72+ branch: master}
73+ - {name: oslo-db,
74+ repository: 'git://git.openstack.org/openstack/oslo.db',
75+ branch: master}
76+ - {name: oslo-i18n,
77+ repository: 'git://git.openstack.org/openstack/oslo.i18n',
78+ branch: master}
79+ - {name: oslo-messaging,
80+ repository: 'git://git.openstack.org/openstack/oslo.messaging',
81+ branch: master}
82+ - {name: oslo-serialization,
83+ repository: 'git://git.openstack.org/openstack/oslo.serialization',
84+ branch: master}
85+ - {name: oslo-utils,
86+ repository: 'git://git.openstack.org/openstack/oslo.utils',
87+ branch: master}
88+ - {name: oslo-vmware,
89+ repository: 'git://git.openstack.org/openstack/oslo.vmware',
90+ branch: master}
91+ - {name: osprofiler,
92+ repository: 'git://git.openstack.org/stackforge/osprofiler',
93+ branch: master}
94+ - {name: pbr,
95+ repository: 'git://git.openstack.org/openstack-dev/pbr',
96+ branch: master}
97+ - {name: python-keystoneclient,
98+ repository: 'git://git.openstack.org/openstack/python-keystoneclient',
99+ branch: master}
100+ - {name: python-swiftclient,
101+ repository: 'git://git.openstack.org/openstack/python-swiftclient',
102+ branch: master}
103+ - {name: sqlalchemy-migrate,
104+ repository: 'git://git.openstack.org/stackforge/sqlalchemy-migrate',
105+ branch: master}
106+ - {name: stevedore,
107+ repository: 'git://git.openstack.org/openstack/stevedore',
108+ branch: master}
109+ - {name: wsme,
110+ repository: 'git://git.openstack.org/stackforge/wsme',
111+ branch: master}
112+ - {name: keystonemiddleware,
113+ repository: 'git://git.openstack.org/openstack/keystonemiddleware',
114+ branch: master}
115+ - {name: glance-store,
116+ repository: 'git://git.openstack.org/openstack/glance_store',
117+ branch: master}
118+ - {name: glance,
119+ repository: 'git://git.openstack.org/openstack/glance',
120+ branch: master}"
121+
122 Contact Information
123 -------------------
124
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:42:02 +0000
130@@ -0,0 +1,2 @@
131+git-reinstall:
132+ description: Reinstall glance 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:42:02 +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 glance_utils import (
157+ git_install,
158+)
159+
160+from glance_relations 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 'config.yaml'
187--- config.yaml 2015-02-19 00:38:40 +0000
188+++ config.yaml 2015-04-16 14:42:02 +0000
189@@ -14,6 +14,22 @@
190 Note that updating this setting to a source that is known to
191 provide a later version of OpenStack will trigger a software
192 upgrade.
193+
194+ Note that when openstack-origin-git is specified, openstack
195+ specific packages will be installed from source rather than
196+ from the openstack-origin repository.
197+ openstack-origin-git:
198+ default:
199+ type: string
200+ description: |
201+ Specifies a YAML-formatted dictionary listing the git
202+ repositories and branches from which to install OpenStack and
203+ its dependencies.
204+
205+ Note that the installed config files will be determined based on
206+ the OpenStack release of the openstack-origin option.
207+
208+ For more details see README.md.
209 database-user:
210 default: glance
211 type: string
212
213=== added file 'hooks/charmhelpers/contrib/openstack/templates/git.upstart'
214--- hooks/charmhelpers/contrib/openstack/templates/git.upstart 1970-01-01 00:00:00 +0000
215+++ hooks/charmhelpers/contrib/openstack/templates/git.upstart 2015-04-16 14:42:02 +0000
216@@ -0,0 +1,17 @@
217+description "{{ service_description }}"
218+author "Juju {{ service_name }} Charm <juju@localhost>"
219+
220+start on runlevel [2345]
221+stop on runlevel [!2345]
222+
223+respawn
224+
225+exec start-stop-daemon --start --chuid {{ user_name }} \
226+ --chdir {{ start_dir }} --name {{ process_name }} \
227+ --exec {{ executable_name }} -- \
228+ {% for config_file in config_files -%}
229+ --config-file={{ config_file }} \
230+ {% endfor -%}
231+ {% if log_file -%}
232+ --log-file={{ log_file }}
233+ {% endif -%}
234
235=== renamed file 'hooks/charmhelpers/contrib/openstack/templates/git.upstart' => 'hooks/charmhelpers/contrib/openstack/templates/git.upstart.moved'
236=== added file 'hooks/charmhelpers/contrib/openstack/templates/section-zeromq'
237--- hooks/charmhelpers/contrib/openstack/templates/section-zeromq 1970-01-01 00:00:00 +0000
238+++ hooks/charmhelpers/contrib/openstack/templates/section-zeromq 2015-04-16 14:42:02 +0000
239@@ -0,0 +1,14 @@
240+{% if zmq_host -%}
241+# ZeroMQ configuration (restart-nonce: {{ zmq_nonce }})
242+rpc_backend = zmq
243+rpc_zmq_host = {{ zmq_host }}
244+{% if zmq_redis_address -%}
245+rpc_zmq_matchmaker = redis
246+matchmaker_heartbeat_freq = 15
247+matchmaker_heartbeat_ttl = 30
248+[matchmaker_redis]
249+host = {{ zmq_redis_address }}
250+{% else -%}
251+rpc_zmq_matchmaker = ring
252+{% endif -%}
253+{% endif -%}
254
255=== renamed file 'hooks/charmhelpers/contrib/openstack/templates/section-zeromq' => 'hooks/charmhelpers/contrib/openstack/templates/section-zeromq.moved'
256=== modified file 'hooks/charmhelpers/contrib/openstack/utils.py'
257--- hooks/charmhelpers/contrib/openstack/utils.py 2015-04-16 10:26:34 +0000
258+++ hooks/charmhelpers/contrib/openstack/utils.py 2015-04-16 14:42:02 +0000
259@@ -521,66 +521,132 @@
260 if not projects_yaml:
261 return
262
263- projects = yaml.load(projects_yaml)
264- _git_validate_projects_yaml(projects, core_project)
265-
266- if 'http_proxy' in projects.keys():
267- os.environ['http_proxy'] = projects['http_proxy']
268-
269- if 'https_proxy' in projects.keys():
270- os.environ['https_proxy'] = projects['https_proxy']
271-
272- if 'directory' in projects.keys():
273- parent_dir = projects['directory']
274-
275- for p in projects['repositories']:
276- repo = p['repository']
277- branch = p['branch']
278- if p['name'] == 'requirements':
279- repo_dir = _git_clone_and_install_single(repo, branch, parent_dir,
280- update_requirements=False)
281- requirements_dir = repo_dir
282- else:
283- repo_dir = _git_clone_and_install_single(repo, branch, parent_dir,
284- update_requirements=True)
285-
286-
287-def _git_validate_projects_yaml(projects, core_project):
288- """
289- Validate the projects yaml.
290- """
291- _git_ensure_key_exists('repositories', projects)
292-
293- for project in projects['repositories']:
294- _git_ensure_key_exists('name', project.keys())
295- _git_ensure_key_exists('repository', project.keys())
296- _git_ensure_key_exists('branch', project.keys())
297-
298- if projects['repositories'][0]['name'] != 'requirements':
299- error_out('{} git repo must be specified first'.format('requirements'))
300-
301- if projects['repositories'][-1]['name'] != core_project:
302- error_out('{} git repo must be specified last'.format(core_project))
303-
304-
305-def _git_ensure_key_exists(key, keys):
306- """
307- Ensure that key exists in keys.
308- """
309- if key not in keys:
310- error_out('openstack-origin-git key \'{}\' is missing'.format(key))
311-
312-
313-def _git_clone_and_install_single(repo, branch, parent_dir, update_requirements):
314- """
315- Clone and install a single git repository.
316- """
317- dest_dir = os.path.join(parent_dir, os.path.basename(repo))
318-
319- if not os.path.exists(parent_dir):
320- juju_log('Directory already exists at {}. '
321- 'No need to create directory.'.format(parent_dir))
322- os.mkdir(parent_dir)
323+<<<<<<< TREE
324+ projects = yaml.load(projects_yaml)
325+ _git_validate_projects_yaml(projects, core_project)
326+
327+ if 'http_proxy' in projects.keys():
328+ os.environ['http_proxy'] = projects['http_proxy']
329+
330+ if 'https_proxy' in projects.keys():
331+ os.environ['https_proxy'] = projects['https_proxy']
332+
333+ if 'directory' in projects.keys():
334+ parent_dir = projects['directory']
335+
336+ for p in projects['repositories']:
337+ repo = p['repository']
338+ branch = p['branch']
339+ if p['name'] == 'requirements':
340+ repo_dir = _git_clone_and_install_single(repo, branch, parent_dir,
341+ update_requirements=False)
342+ requirements_dir = repo_dir
343+ else:
344+ repo_dir = _git_clone_and_install_single(repo, branch, parent_dir,
345+ update_requirements=True)
346+
347+
348+def _git_validate_projects_yaml(projects, core_project):
349+ """
350+ Validate the projects yaml.
351+ """
352+ _git_ensure_key_exists('repositories', projects)
353+
354+ for project in projects['repositories']:
355+ _git_ensure_key_exists('name', project.keys())
356+ _git_ensure_key_exists('repository', project.keys())
357+ _git_ensure_key_exists('branch', project.keys())
358+
359+ if projects['repositories'][0]['name'] != 'requirements':
360+ error_out('{} git repo must be specified first'.format('requirements'))
361+
362+ if projects['repositories'][-1]['name'] != core_project:
363+ error_out('{} git repo must be specified last'.format(core_project))
364+
365+
366+def _git_ensure_key_exists(key, keys):
367+ """
368+ Ensure that key exists in keys.
369+ """
370+ if key not in keys:
371+ error_out('openstack-origin-git key \'{}\' is missing'.format(key))
372+
373+
374+def _git_clone_and_install_single(repo, branch, parent_dir, update_requirements):
375+ """
376+ Clone and install a single git repository.
377+ """
378+ dest_dir = os.path.join(parent_dir, os.path.basename(repo))
379+
380+ if not os.path.exists(parent_dir):
381+ juju_log('Directory already exists at {}. '
382+ 'No need to create directory.'.format(parent_dir))
383+ os.mkdir(parent_dir)
384+=======
385+ projects = yaml.load(projects_yaml)
386+ _git_validate_projects_yaml(projects, core_project)
387+
388+ old_environ = dict(os.environ)
389+
390+ if 'http_proxy' in projects.keys():
391+ os.environ['http_proxy'] = projects['http_proxy']
392+ if 'https_proxy' in projects.keys():
393+ os.environ['https_proxy'] = projects['https_proxy']
394+
395+ if 'directory' in projects.keys():
396+ parent_dir = projects['directory']
397+
398+ for p in projects['repositories']:
399+ repo = p['repository']
400+ branch = p['branch']
401+ if p['name'] == 'requirements':
402+ repo_dir = _git_clone_and_install_single(repo, branch, parent_dir,
403+ update_requirements=False)
404+ requirements_dir = repo_dir
405+ else:
406+ repo_dir = _git_clone_and_install_single(repo, branch, parent_dir,
407+ update_requirements=True)
408+
409+ os.environ = old_environ
410+
411+
412+def _git_validate_projects_yaml(projects, core_project):
413+ """
414+ Validate the projects yaml.
415+ """
416+ _git_ensure_key_exists('repositories', projects)
417+
418+ for project in projects['repositories']:
419+ _git_ensure_key_exists('name', project.keys())
420+ _git_ensure_key_exists('repository', project.keys())
421+ _git_ensure_key_exists('branch', project.keys())
422+
423+ if projects['repositories'][0]['name'] != 'requirements':
424+ error_out('{} git repo must be specified first'.format('requirements'))
425+
426+ if projects['repositories'][-1]['name'] != core_project:
427+ error_out('{} git repo must be specified last'.format(core_project))
428+
429+
430+def _git_ensure_key_exists(key, keys):
431+ """
432+ Ensure that key exists in keys.
433+ """
434+ if key not in keys:
435+ error_out('openstack-origin-git key \'{}\' is missing'.format(key))
436+
437+
438+def _git_clone_and_install_single(repo, branch, parent_dir, update_requirements):
439+ """
440+ Clone and install a single git repository.
441+ """
442+ dest_dir = os.path.join(parent_dir, os.path.basename(repo))
443+
444+ if not os.path.exists(parent_dir):
445+ juju_log('Directory already exists at {}. '
446+ 'No need to create directory.'.format(parent_dir))
447+ os.mkdir(parent_dir)
448+>>>>>>> MERGE-SOURCE
449
450 if not os.path.exists(dest_dir):
451 juju_log('Cloning git repo: {}, branch: {}'.format(repo, branch))
452
453=== modified file 'hooks/glance_relations.py'
454--- hooks/glance_relations.py 2015-03-30 17:26:30 +0000
455+++ hooks/glance_relations.py 2015-04-16 14:42:02 +0000
456@@ -8,12 +8,13 @@
457
458 from glance_utils import (
459 do_openstack_upgrade,
460+ git_install,
461 migrate_database,
462 register_configs,
463 restart_map,
464 services,
465 CLUSTER_RES,
466- PACKAGES,
467+ determine_packages,
468 SERVICES,
469 CHARM,
470 GLANCE_REGISTRY_CONF,
471@@ -55,11 +56,13 @@
472 get_hacluster_config
473 )
474 from charmhelpers.contrib.openstack.utils import (
475+ config_value_changed,
476 configure_installation_source,
477- get_os_codename_package,
478+ git_install_requested,
479+ lsb_release,
480 openstack_upgrade_available,
481- lsb_release,
482- sync_db_with_multi_ipv6_addresses
483+ os_release,
484+ sync_db_with_multi_ipv6_addresses,
485 )
486 from charmhelpers.contrib.storage.linux.ceph import (
487 ensure_ceph_keyring,
488@@ -103,7 +106,9 @@
489 configure_installation_source(src)
490
491 apt_update(fatal=True)
492- apt_install(PACKAGES, fatal=True)
493+ apt_install(determine_packages(), fatal=True)
494+
495+ git_install(config('openstack-origin-git'))
496
497 for service in SERVICES:
498 service_stop(service)
499@@ -143,7 +148,7 @@
500 @hooks.hook('shared-db-relation-changed')
501 @restart_on_change(restart_map())
502 def db_changed():
503- rel = get_os_codename_package("glance-common")
504+ rel = os_release('glance-common')
505
506 if 'shared-db' not in CONFIGS.complete_contexts():
507 juju_log('shared-db relation incomplete. Peer not ready?')
508@@ -176,7 +181,7 @@
509 @hooks.hook('pgsql-db-relation-changed')
510 @restart_on_change(restart_map())
511 def pgsql_db_changed():
512- rel = get_os_codename_package("glance-common")
513+ rel = os_release('glance-common')
514
515 if 'pgsql-db' not in CONFIGS.complete_contexts():
516 juju_log('pgsql-db relation incomplete. Peer not ready?')
517@@ -320,9 +325,13 @@
518 sync_db_with_multi_ipv6_addresses(config('database'),
519 config('database-user'))
520
521- if openstack_upgrade_available('glance-common'):
522- juju_log('Upgrading OpenStack release')
523- do_openstack_upgrade(CONFIGS)
524+ if git_install_requested():
525+ if config_value_changed('openstack-origin-git'):
526+ git_install(config('openstack-origin-git'))
527+ else:
528+ if openstack_upgrade_available('glance-common'):
529+ juju_log('Upgrading OpenStack release')
530+ do_openstack_upgrade(CONFIGS)
531
532 open_port(9292)
533 configure_https()
534@@ -366,7 +375,7 @@
535 @hooks.hook('upgrade-charm')
536 @restart_on_change(restart_map(), stopstart=True)
537 def upgrade_charm():
538- apt_install(filter_installed_packages(PACKAGES), fatal=True)
539+ apt_install(filter_installed_packages(determine_packages()), fatal=True)
540 configure_https()
541 update_nrpe_config()
542 CONFIGS.write_all()
543
544=== modified file 'hooks/glance_utils.py'
545--- hooks/glance_utils.py 2015-02-20 10:33:48 +0000
546+++ hooks/glance_utils.py 2015-04-16 14:42:02 +0000
547@@ -1,6 +1,7 @@
548 #!/usr/bin/python
549
550 import os
551+import shutil
552 import subprocess
553
554 import glance_contexts
555@@ -14,21 +15,27 @@
556 add_source)
557
558 from charmhelpers.core.hookenv import (
559+ charm_dir,
560 config,
561 log,
562 relation_ids,
563 service_name)
564
565 from charmhelpers.core.host import (
566+ adduser,
567+ add_group,
568+ add_user_to_group,
569 mkdir,
570 service_stop,
571 service_start,
572- lsb_release
573+ service_restart,
574+ lsb_release,
575+ write_file,
576 )
577
578 from charmhelpers.contrib.openstack import (
579 templating,
580- context, )
581+ context,)
582
583 from charmhelpers.contrib.hahelpers.cluster import (
584 eligible_leader,
585@@ -37,8 +44,14 @@
586 from charmhelpers.contrib.openstack.alternatives import install_alternative
587 from charmhelpers.contrib.openstack.utils import (
588 get_os_codename_install_source,
589- get_os_codename_package,
590- configure_installation_source)
591+ git_install_requested,
592+ git_clone_and_install,
593+ git_src_dir,
594+ configure_installation_source,
595+ os_release,
596+)
597+
598+from charmhelpers.core.templating import render
599
600 CLUSTER_RES = "grp_glance_vips"
601
602@@ -46,8 +59,27 @@
603 "apache2", "glance", "python-mysqldb", "python-swiftclient",
604 "python-psycopg2", "python-keystone", "python-six", "uuid", "haproxy", ]
605
606+BASE_GIT_PACKAGES = [
607+ 'libxml2-dev',
608+ 'libxslt1-dev',
609+ 'python-dev',
610+ 'python-pip',
611+ 'python-setuptools',
612+ 'zlib1g-dev',
613+]
614+
615 SERVICES = [
616- "glance-api", "glance-registry", ]
617+ "glance-api",
618+ "glance-registry",
619+]
620+
621+# ubuntu packages that should not be installed when deploying from git
622+GIT_PACKAGE_BLACKLIST = [
623+ 'glance',
624+ 'python-swiftclient',
625+ 'python-keystone',
626+]
627+
628
629 CHARM = "glance"
630
631@@ -140,7 +172,7 @@
632 # Register config files with their respective contexts.
633 # Regstration of some configs may not be required depending on
634 # existing of certain relations.
635- release = get_os_codename_package('glance-common', fatal=False) or 'essex'
636+ release = os_release('glance-common')
637 configs = templating.OSConfigRenderer(templates_dir=TEMPLATES,
638 openstack_release=release)
639
640@@ -177,6 +209,18 @@
641 return configs
642
643
644+def determine_packages():
645+ packages = [] + PACKAGES
646+
647+ if git_install_requested():
648+ packages.extend(BASE_GIT_PACKAGES)
649+ # don't include packages that will be installed from git
650+ for p in GIT_PACKAGE_BLACKLIST:
651+ packages.remove(p)
652+
653+ return list(set(packages))
654+
655+
656 def migrate_database():
657 '''Runs glance-manage to initialize a new database
658 or migrate existing
659@@ -205,7 +249,7 @@
660 ]
661 apt_update()
662 apt_upgrade(options=dpkg_opts, fatal=True, dist=True)
663- apt_install(PACKAGES, fatal=True)
664+ apt_install(determine_packages(), fatal=True)
665
666 # set CONFIGS to load templates from new release and regenerate config
667 configs.set_release(openstack_release=new_os_rel)
668@@ -256,3 +300,85 @@
669 ' main')
670 apt_update()
671 apt_install('haproxy/trusty-backports', fatal=True)
672+
673+
674+def git_install(projects_yaml):
675+ """Perform setup, and install git repos specified in yaml parameter."""
676+ if git_install_requested():
677+ git_pre_install()
678+ git_clone_and_install(projects_yaml, core_project='glance')
679+ git_post_install(projects_yaml)
680+
681+
682+def git_pre_install():
683+ """Perform glance pre-install setup."""
684+ dirs = [
685+ '/var/lib/glance',
686+ '/var/lib/glance/images',
687+ '/var/lib/glance/image-cache',
688+ '/var/lib/glance/image-cache/incomplete',
689+ '/var/lib/glance/image-cache/invalid',
690+ '/var/lib/glance/image-cache/queue',
691+ '/var/log/glance',
692+ ]
693+
694+ logs = [
695+ '/var/log/glance/glance-api.log',
696+ '/var/log/glance/glance-registry.log',
697+ ]
698+
699+ adduser('glance', shell='/bin/bash', system_user=True)
700+ add_group('glance', system_group=True)
701+ add_user_to_group('glance', 'glance')
702+
703+ for d in dirs:
704+ mkdir(d, owner='glance', group='glance', perms=0700, force=False)
705+
706+ for l in logs:
707+ write_file(l, '', owner='glance', group='glance', perms=0600)
708+
709+
710+def git_post_install(projects_yaml):
711+ """Perform glance post-install setup."""
712+ src_etc = os.path.join(git_src_dir(projects_yaml, 'glance'), 'etc')
713+ configs = {
714+ 'src': src_etc,
715+ 'dest': '/etc/glance',
716+ }
717+
718+ if os.path.exists(configs['dest']):
719+ shutil.rmtree(configs['dest'])
720+ shutil.copytree(configs['src'], configs['dest'])
721+
722+ glance_api_context = {
723+ 'service_description': 'Glance API server',
724+ 'service_name': 'Glance',
725+ 'user_name': 'glance',
726+ 'start_dir': '/var/lib/glance',
727+ 'process_name': 'glance-api',
728+ 'executable_name': '/usr/local/bin/glance-api',
729+ 'config_files': ['/etc/glance/glance-api.conf'],
730+ 'log_file': '/var/log/glance/api.log',
731+ }
732+
733+ glance_registry_context = {
734+ 'service_description': 'Glance registry server',
735+ 'service_name': 'Glance',
736+ 'user_name': 'glance',
737+ 'start_dir': '/var/lib/glance',
738+ 'process_name': 'glance-registry',
739+ 'executable_name': '/usr/local/bin/glance-registry',
740+ 'config_files': ['/etc/glance/glance-registry.conf'],
741+ 'log_file': '/var/log/glance/registry.log',
742+ }
743+
744+ # NOTE(coreycb): Needs systemd support
745+ templates_dir = 'hooks/charmhelpers/contrib/openstack/templates'
746+ templates_dir = os.path.join(charm_dir(), templates_dir)
747+ render('git.upstart', '/etc/init/glance-api.conf',
748+ glance_api_context, perms=0o644, templates_dir=templates_dir)
749+ render('git.upstart', '/etc/init/glance-registry.conf',
750+ glance_registry_context, perms=0o644, templates_dir=templates_dir)
751+
752+ service_restart('glance-api')
753+ service_restart('glance-registry')
754
755=== removed file 'tests/10-basic-precise-essex'
756--- tests/10-basic-precise-essex 2014-07-11 14:11:03 +0000
757+++ tests/10-basic-precise-essex 1970-01-01 00:00:00 +0000
758@@ -1,9 +0,0 @@
759-#!/usr/bin/python
760-
761-"""Amulet tests on a basic glance deployment on precise-essex."""
762-
763-from basic_deployment import GlanceBasicDeployment
764-
765-if __name__ == '__main__':
766- deployment = GlanceBasicDeployment(series='precise')
767- deployment.run_tests()
768
769=== removed file 'tests/11-basic-precise-folsom'
770--- tests/11-basic-precise-folsom 2014-07-11 14:11:03 +0000
771+++ tests/11-basic-precise-folsom 1970-01-01 00:00:00 +0000
772@@ -1,11 +0,0 @@
773-#!/usr/bin/python
774-
775-"""Amulet tests on a basic glance deployment on precise-folsom."""
776-
777-from basic_deployment import GlanceBasicDeployment
778-
779-if __name__ == '__main__':
780- deployment = GlanceBasicDeployment(series='precise',
781- openstack='cloud:precise-folsom',
782- source='cloud:precise-updates/folsom')
783- deployment.run_tests()
784
785=== removed file 'tests/12-basic-precise-grizzly'
786--- tests/12-basic-precise-grizzly 2014-07-11 14:11:03 +0000
787+++ tests/12-basic-precise-grizzly 1970-01-01 00:00:00 +0000
788@@ -1,11 +0,0 @@
789-#!/usr/bin/python
790-
791-"""Amulet tests on a basic glance deployment on precise-grizzly."""
792-
793-from basic_deployment import GlanceBasicDeployment
794-
795-if __name__ == '__main__':
796- deployment = GlanceBasicDeployment(series='precise',
797- openstack='cloud:precise-grizzly',
798- source='cloud:precise-updates/grizzly')
799- deployment.run_tests()
800
801=== removed file 'tests/13-basic-precise-havana'
802--- tests/13-basic-precise-havana 2014-07-11 14:11:03 +0000
803+++ tests/13-basic-precise-havana 1970-01-01 00:00:00 +0000
804@@ -1,11 +0,0 @@
805-#!/usr/bin/python
806-
807-"""Amulet tests on a basic glance deployment on precise-havana."""
808-
809-from basic_deployment import GlanceBasicDeployment
810-
811-if __name__ == '__main__':
812- deployment = GlanceBasicDeployment(series='precise',
813- openstack='cloud:precise-havana',
814- source='cloud:precise-updates/havana')
815- deployment.run_tests()
816
817=== added file 'tests/16-basic-trusty-icehouse-git'
818--- tests/16-basic-trusty-icehouse-git 1970-01-01 00:00:00 +0000
819+++ tests/16-basic-trusty-icehouse-git 2015-04-16 14:42:02 +0000
820@@ -0,0 +1,9 @@
821+#!/usr/bin/python
822+
823+"""Amulet tests on a basic Glance git deployment on trusty-icehouse."""
824+
825+from basic_deployment import GlanceBasicDeployment
826+
827+if __name__ == '__main__':
828+ deployment = GlanceBasicDeployment(series='trusty', git=True)
829+ deployment.run_tests()
830
831=== added file 'tests/17-basic-trusty-juno'
832--- tests/17-basic-trusty-juno 1970-01-01 00:00:00 +0000
833+++ tests/17-basic-trusty-juno 2015-04-16 14:42:02 +0000
834@@ -0,0 +1,11 @@
835+#!/usr/bin/python
836+
837+"""Amulet tests on a basic Glance deployment on trusty-juno."""
838+
839+from basic_deployment import GlanceBasicDeployment
840+
841+if __name__ == '__main__':
842+ deployment = GlanceBasicDeployment(series='trusty',
843+ openstack='cloud:trusty-juno',
844+ source='cloud:trusty-updates/juno')
845+ deployment.run_tests()
846
847=== added file 'tests/18-basic-trusty-juno-git'
848--- tests/18-basic-trusty-juno-git 1970-01-01 00:00:00 +0000
849+++ tests/18-basic-trusty-juno-git 2015-04-16 14:42:02 +0000
850@@ -0,0 +1,12 @@
851+#!/usr/bin/python
852+
853+"""Amulet tests on a basic Glance git deployment on trusty-juno."""
854+
855+from basic_deployment import GlanceBasicDeployment
856+
857+if __name__ == '__main__':
858+ deployment = GlanceBasicDeployment(series='trusty',
859+ openstack='cloud:trusty-juno',
860+ source='cloud:trusty-updates/juno',
861+ git=True)
862+ deployment.run_tests()
863
864=== modified file 'tests/basic_deployment.py'
865--- tests/basic_deployment.py 2015-03-26 16:24:45 +0000
866+++ tests/basic_deployment.py 2015-04-16 14:42:02 +0000
867@@ -1,6 +1,8 @@
868 #!/usr/bin/python
869
870 import amulet
871+import os
872+import yaml
873
874 from charmhelpers.contrib.openstack.amulet.deployment import (
875 OpenStackAmuletDeployment
876@@ -13,7 +15,7 @@
877 )
878
879 # Use DEBUG to turn on debug logging
880-u = OpenStackAmuletUtils(ERROR)
881+u = OpenStackAmuletUtils(DEBUG)
882
883 class GlanceBasicDeployment(OpenStackAmuletDeployment):
884 '''Amulet tests on a basic file-backed glance deployment. Verify relations,
885@@ -23,9 +25,11 @@
886 # * Add tests with different storage back ends
887 # * Resolve Essex->Havana juju set charm bug
888
889- def __init__(self, series=None, openstack=None, source=None, stable=False):
890+ def __init__(self, series=None, openstack=None, source=None, git=False,
891+ stable=False):
892 '''Deploy the entire test environment.'''
893 super(GlanceBasicDeployment, self).__init__(series, openstack, source, stable)
894+ self.git = git
895 self._add_services()
896 self._add_relations()
897 self._configure_services()
898@@ -55,11 +59,30 @@
899
900 def _configure_services(self):
901 '''Configure all of the services.'''
902+ glance_config = {}
903+ if self.git:
904+ branch = 'stable/' + self._get_openstack_release_string()
905+ amulet_http_proxy = os.environ.get('AMULET_HTTP_PROXY')
906+ openstack_origin_git = {
907+ 'repositories': [
908+ {'name': 'requirements',
909+ 'repository': 'git://git.openstack.org/openstack/requirements',
910+ 'branch': branch},
911+ {'name': 'glance',
912+ 'repository': 'git://git.openstack.org/openstack/glance',
913+ 'branch': branch},
914+ ],
915+ 'directory': '/mnt/openstack-git',
916+ 'http_proxy': amulet_http_proxy,
917+ 'https_proxy': amulet_http_proxy,
918+ }
919+ glance_config['openstack-origin-git'] = yaml.dump(openstack_origin_git)
920+
921 keystone_config = {'admin-password': 'openstack',
922 'admin-token': 'ubuntutesting'}
923-
924 mysql_config = {'dataset-size': '50%'}
925- configs = {'keystone': keystone_config,
926+ configs = {'glance': glance_config,
927+ 'keystone': keystone_config,
928 'mysql': mysql_config}
929 super(GlanceBasicDeployment, self)._configure_services(configs)
930
931
932=== added directory 'trusty'
933=== modified file 'unit_tests/__init__.py'
934--- unit_tests/__init__.py 2013-08-09 18:45:02 +0000
935+++ unit_tests/__init__.py 2015-04-16 14:42:02 +0000
936@@ -1,3 +1,4 @@
937 import sys
938
939+sys.path.append('actions/')
940 sys.path.append('hooks/')
941
942=== added file 'unit_tests/test_actions_git_reinstall.py'
943--- unit_tests/test_actions_git_reinstall.py 1970-01-01 00:00:00 +0000
944+++ unit_tests/test_actions_git_reinstall.py 2015-04-16 14:42:02 +0000
945@@ -0,0 +1,96 @@
946+from mock import patch
947+import os
948+
949+os.environ['JUJU_UNIT_NAME'] = 'glance'
950+
951+with patch('glance_utils.register_configs') as register_configs:
952+ import git_reinstall
953+
954+from test_utils import (
955+ CharmTestCase
956+)
957+
958+TO_PATCH = [
959+ 'config',
960+]
961+
962+
963+openstack_origin_git = \
964+ """repositories:
965+ - {name: requirements,
966+ repository: 'git://git.openstack.org/openstack/requirements',
967+ branch: stable/juno}
968+ - {name: glance,
969+ repository: 'git://git.openstack.org/openstack/glance',
970+ branch: stable/juno}"""
971+
972+
973+class TestGlanceActions(CharmTestCase):
974+
975+ def setUp(self):
976+ super(TestGlanceActions, self).setUp(git_reinstall, TO_PATCH)
977+ self.config.side_effect = self.test_config.get
978+
979+ @patch.object(git_reinstall, 'action_set')
980+ @patch.object(git_reinstall, 'action_fail')
981+ @patch.object(git_reinstall, 'git_install')
982+ @patch.object(git_reinstall, 'config_changed')
983+ @patch('charmhelpers.contrib.openstack.utils.config')
984+ def test_git_reinstall(self, _config, config_changed, git_install,
985+ action_fail, action_set):
986+ _config.return_value = openstack_origin_git
987+ self.test_config.set('openstack-origin-git', openstack_origin_git)
988+
989+ git_reinstall.git_reinstall()
990+
991+ git_install.assert_called_with(openstack_origin_git)
992+ self.assertTrue(git_install.called)
993+ self.assertTrue(config_changed.called)
994+ self.assertFalse(action_set.called)
995+ self.assertFalse(action_fail.called)
996+
997+ @patch.object(git_reinstall, 'action_set')
998+ @patch.object(git_reinstall, 'action_fail')
999+ @patch.object(git_reinstall, 'git_install')
1000+ @patch.object(git_reinstall, 'config_changed')
1001+ @patch('charmhelpers.contrib.openstack.utils.config')
1002+ def test_git_reinstall_not_configured(self, _config, config_changed,
1003+ git_install, action_fail,
1004+ action_set):
1005+ _config.return_value = None
1006+
1007+ git_reinstall.git_reinstall()
1008+
1009+ msg = 'openstack-origin-git is not configured'
1010+ action_fail.assert_called_with(msg)
1011+ self.assertFalse(git_install.called)
1012+ self.assertFalse(action_set.called)
1013+
1014+ @patch.object(git_reinstall, 'action_set')
1015+ @patch.object(git_reinstall, 'action_fail')
1016+ @patch.object(git_reinstall, 'git_install')
1017+ @patch.object(git_reinstall, 'config_changed')
1018+ @patch('traceback.format_exc')
1019+ @patch('charmhelpers.contrib.openstack.utils.config')
1020+ def test_git_reinstall_exception(self, _config, format_exc,
1021+ config_changed, git_install, action_fail,
1022+ action_set):
1023+ _config.return_value = openstack_origin_git
1024+ e = OSError('something bad happened')
1025+ git_install.side_effect = e
1026+ traceback = (
1027+ "Traceback (most recent call last):\n"
1028+ " File \"actions/git_reinstall.py\", line 37, in git_reinstall\n"
1029+ " git_install(config(\'openstack-origin-git\'))\n"
1030+ " File \"/usr/lib/python2.7/dist-packages/mock.py\", line 964, in __call__\n" # noqa
1031+ " return _mock_self._mock_call(*args, **kwargs)\n"
1032+ " File \"/usr/lib/python2.7/dist-packages/mock.py\", line 1019, in _mock_call\n" # noqa
1033+ " raise effect\n"
1034+ "OSError: something bad happened\n")
1035+ format_exc.return_value = traceback
1036+
1037+ git_reinstall.git_reinstall()
1038+
1039+ msg = 'git-reinstall resulted in an unexpected error'
1040+ action_fail.assert_called_with(msg)
1041+ action_set.assert_called_with({'traceback': traceback})
1042
1043=== modified file 'unit_tests/test_glance_relations.py'
1044--- unit_tests/test_glance_relations.py 2015-03-30 17:26:30 +0000
1045+++ unit_tests/test_glance_relations.py 2015-04-16 14:42:02 +0000
1046@@ -1,6 +1,7 @@
1047 from mock import call, patch, MagicMock
1048 import json
1049 import os
1050+import yaml
1051
1052 from test_utils import CharmTestCase
1053
1054@@ -42,7 +43,7 @@
1055 'service_stop',
1056 # charmhelpers.contrib.openstack.utils
1057 'configure_installation_source',
1058- 'get_os_codename_package',
1059+ 'os_release',
1060 'openstack_upgrade_available',
1061 # charmhelpers.contrib.hahelpers.cluster_utils
1062 'eligible_leader',
1063@@ -53,6 +54,7 @@
1064 'migrate_database',
1065 'ensure_ceph_keyring',
1066 'ceph_config_file',
1067+ 'git_install',
1068 'update_nrpe_config',
1069 # other
1070 'call',
1071@@ -75,23 +77,26 @@
1072 super(GlanceRelationTests, self).setUp(relations, TO_PATCH)
1073 self.config.side_effect = self.test_config.get
1074
1075- def test_install_hook(self):
1076+ @patch.object(utils, 'git_install_requested')
1077+ def test_install_hook(self, git_requested):
1078+ git_requested.return_value = False
1079 repo = 'cloud:precise-grizzly'
1080 self.test_config.set('openstack-origin', repo)
1081 self.service_stop.return_value = True
1082 relations.install_hook()
1083 self.configure_installation_source.assert_called_with(repo)
1084 self.apt_update.assert_called_with(fatal=True)
1085- self.apt_install.assert_called_with(['apache2', 'glance',
1086- 'python-mysqldb',
1087- 'python-swiftclient',
1088- 'python-psycopg2',
1089+ self.apt_install.assert_called_with(['haproxy', 'python-six', 'uuid',
1090+ 'python-mysqldb', 'apache2',
1091+ 'python-psycopg2', 'glance',
1092 'python-keystone',
1093- 'python-six',
1094- 'uuid', 'haproxy'], fatal=True)
1095+ 'python-swiftclient'], fatal=True)
1096 self.assertTrue(self.execd_preinstall.called)
1097+ self.git_install.assert_called_with(None)
1098
1099- def test_install_hook_precise_distro(self):
1100+ @patch.object(utils, 'git_install_requested')
1101+ def test_install_hook_precise_distro(self, git_requested):
1102+ git_requested.return_value = False
1103 self.test_config.set('openstack-origin', 'distro')
1104 self.lsb_release.return_value = {'DISTRIB_RELEASE': 12.04,
1105 'DISTRIB_CODENAME': 'precise'}
1106@@ -101,6 +106,37 @@
1107 "cloud:precise-folsom"
1108 )
1109
1110+ @patch.object(utils, 'git_install_requested')
1111+ def test_install_hook_git(self, git_requested):
1112+ git_requested.return_value = True
1113+ repo = 'cloud:trusty-juno'
1114+ openstack_origin_git = {
1115+ 'repositories': [
1116+ {'name': 'requirements',
1117+ 'repository': 'git://git.openstack.org/openstack/requirements', # noqa
1118+ 'branch': 'stable/juno'},
1119+ {'name': 'glance',
1120+ 'repository': 'git://git.openstack.org/openstack/glance',
1121+ 'branch': 'stable/juno'}
1122+ ],
1123+ 'directory': '/mnt/openstack-git',
1124+ }
1125+ projects_yaml = yaml.dump(openstack_origin_git)
1126+ self.test_config.set('openstack-origin', repo)
1127+ self.test_config.set('openstack-origin-git', projects_yaml)
1128+ relations.install_hook()
1129+ self.assertTrue(self.execd_preinstall.called)
1130+ self.configure_installation_source.assert_called_with(repo)
1131+ self.apt_update.assert_called_with(fatal=True)
1132+ self.apt_install.assert_called_with(['haproxy', 'python-setuptools',
1133+ 'python-six', 'uuid',
1134+ 'python-mysqldb', 'python-pip',
1135+ 'apache2', 'libxslt1-dev',
1136+ 'python-psycopg2', 'zlib1g-dev',
1137+ 'python-dev', 'libxml2-dev'],
1138+ fatal=True)
1139+ self.git_install.assert_called_with(projects_yaml)
1140+
1141 def test_db_joined(self):
1142 self.unit_get.return_value = 'glance.foohost.com'
1143 self.is_relation_made.return_value = False
1144@@ -217,7 +253,7 @@
1145
1146 @patch.object(relations, 'CONFIGS')
1147 def test_db_changed_with_essex_not_setting_version_control(self, configs):
1148- self.get_os_codename_package.return_value = "essex"
1149+ self.os_release.return_value = "essex"
1150 self.call.return_value = 0
1151 self._shared_db_test(configs, 'glance/0')
1152 self.assertEquals([call('/etc/glance/glance-registry.conf')],
1153@@ -230,7 +266,7 @@
1154 @patch.object(relations, 'CONFIGS')
1155 def test_postgresql_db_changed_with_essex_not_setting_version_control(
1156 self, configs):
1157- self.get_os_codename_package.return_value = "essex"
1158+ self.os_release.return_value = "essex"
1159 self.call.return_value = 0
1160 self._postgresql_db_test(configs)
1161 self.assertEquals([call('/etc/glance/glance-registry.conf')],
1162@@ -242,7 +278,7 @@
1163
1164 @patch.object(relations, 'CONFIGS')
1165 def test_db_changed_with_essex_setting_version_control(self, configs):
1166- self.get_os_codename_package.return_value = "essex"
1167+ self.os_release.return_value = "essex"
1168 self.call.return_value = 1
1169 self._shared_db_test(configs, 'glance/0')
1170 self.assertEquals([call('/etc/glance/glance-registry.conf')],
1171@@ -258,7 +294,7 @@
1172 @patch.object(relations, 'CONFIGS')
1173 def test_postgresql_db_changed_with_essex_setting_version_control(
1174 self, configs):
1175- self.get_os_codename_package.return_value = "essex"
1176+ self.os_release.return_value = "essex"
1177 self.call.return_value = 1
1178 self._postgresql_db_test(configs)
1179 self.assertEquals([call('/etc/glance/glance-registry.conf')],
1180@@ -442,8 +478,12 @@
1181 @patch.object(relations, 'configure_https')
1182 @patch.object(relations, 'object_store_joined')
1183 @patch.object(relations, 'CONFIGS')
1184- def test_keystone_changed_with_object_store_relation(
1185- self, configs, object_store_joined, configure_https):
1186+ @patch.object(utils, 'git_install_requested')
1187+ def test_keystone_changed_with_object_store_relation(self, git_requested,
1188+ configs,
1189+ object_store_joined,
1190+ configure_https):
1191+ git_requested.return_value = False
1192 configs.complete_contexts = MagicMock()
1193 configs.complete_contexts.return_value = ['identity-service']
1194 configs.write = MagicMock()
1195@@ -458,14 +498,20 @@
1196 self.assertTrue(configure_https.called)
1197
1198 @patch.object(relations, 'configure_https')
1199- def test_config_changed_no_openstack_upgrade(self, configure_https):
1200+ @patch.object(relations, 'git_install_requested')
1201+ def test_config_changed_no_openstack_upgrade(self, git_requested,
1202+ configure_https):
1203+ git_requested.return_value = False
1204 self.openstack_upgrade_available.return_value = False
1205 relations.config_changed()
1206 self.open_port.assert_called_with(9292)
1207 self.assertTrue(configure_https.called)
1208
1209 @patch.object(relations, 'configure_https')
1210- def test_config_changed_with_openstack_upgrade(self, configure_https):
1211+ @patch.object(relations, 'git_install_requested')
1212+ def test_config_changed_with_openstack_upgrade(self, git_requested,
1213+ configure_https):
1214+ git_requested.return_value = False
1215 self.openstack_upgrade_available.return_value = True
1216 relations.config_changed()
1217 self.juju_log.assert_called_with(
1218@@ -474,6 +520,32 @@
1219 self.assertTrue(self.do_openstack_upgrade.called)
1220 self.assertTrue(configure_https.called)
1221
1222+ @patch.object(relations, 'configure_https')
1223+ @patch.object(relations, 'git_install_requested')
1224+ @patch.object(relations, 'config_value_changed')
1225+ def test_config_changed_git_updated(self, config_val_changed,
1226+ git_requested, configure_https):
1227+ git_requested.return_value = True
1228+ repo = 'cloud:trusty-juno'
1229+ openstack_origin_git = {
1230+ 'repositories': [
1231+ {'name': 'requirements',
1232+ 'repository': 'git://git.openstack.org/openstack/requirements', # noqa
1233+ 'branch': 'stable/juno'},
1234+ {'name': 'glance',
1235+ 'repository': 'git://git.openstack.org/openstack/glance',
1236+ 'branch': 'stable/juno'}
1237+ ],
1238+ 'directory': '/mnt/openstack-git',
1239+ }
1240+ projects_yaml = yaml.dump(openstack_origin_git)
1241+ self.test_config.set('openstack-origin', repo)
1242+ self.test_config.set('openstack-origin-git', projects_yaml)
1243+ relations.config_changed()
1244+ self.git_install.assert_called_with(projects_yaml)
1245+ self.assertFalse(self.do_openstack_upgrade.called)
1246+ self.assertTrue(configure_https.called)
1247+
1248 @patch.object(relations, 'CONFIGS')
1249 def test_cluster_changed(self, configs):
1250 self.test_config.set('prefer-ipv6', False)
1251@@ -500,7 +572,9 @@
1252 configs.write.call_args_list)
1253
1254 @patch.object(relations, 'CONFIGS')
1255- def test_upgrade_charm(self, configs):
1256+ @patch.object(utils, 'git_install_requested')
1257+ def test_upgrade_charm(self, git_requested, configs):
1258+ git_requested.return_value = False
1259 self.filter_installed_packages.return_value = ['test']
1260 relations.upgrade_charm()
1261 self.apt_install.assert_called_with(['test'], fatal=True)
1262
1263=== modified file 'unit_tests/test_glance_utils.py'
1264--- unit_tests/test_glance_utils.py 2015-01-06 15:09:51 +0000
1265+++ unit_tests/test_glance_utils.py 2015-04-16 14:42:02 +0000
1266@@ -14,7 +14,6 @@
1267 'config',
1268 'log',
1269 'relation_ids',
1270- 'get_os_codename_package',
1271 'get_os_codename_install_source',
1272 'configure_installation_source',
1273 'eligible_leader',
1274@@ -23,6 +22,7 @@
1275 'apt_upgrade',
1276 'apt_install',
1277 'mkdir',
1278+ 'os_release',
1279 'service_start',
1280 'service_stop',
1281 'service_name',
1282@@ -34,6 +34,15 @@
1283 '--option', 'Dpkg::Options::=--force-confdef',
1284 ]
1285
1286+openstack_origin_git = \
1287+ """repositories:
1288+ - {name: requirements,
1289+ repository: 'git://git.openstack.org/openstack/requirements',
1290+ branch: stable/juno}
1291+ - {name: glance,
1292+ repository: 'git://git.openstack.org/openstack/glance',
1293+ branch: stable/juno}"""
1294+
1295
1296 class TestGlanceUtils(CharmTestCase):
1297
1298@@ -50,7 +59,7 @@
1299 @patch('os.path.exists')
1300 def test_register_configs_apache(self, exists):
1301 exists.return_value = False
1302- self.get_os_codename_package.return_value = 'grizzly'
1303+ self.os_release.return_value = 'grizzly'
1304 self.relation_ids.return_value = False
1305 configs = utils.register_configs()
1306 calls = []
1307@@ -69,7 +78,7 @@
1308 @patch('os.path.exists')
1309 def test_register_configs_apache24(self, exists):
1310 exists.return_value = True
1311- self.get_os_codename_package.return_value = 'grizzly'
1312+ self.os_release.return_value = 'grizzly'
1313 self.relation_ids.return_value = False
1314 configs = utils.register_configs()
1315 calls = []
1316@@ -88,7 +97,7 @@
1317 @patch('os.path.exists')
1318 def test_register_configs_ceph(self, exists):
1319 exists.return_value = True
1320- self.get_os_codename_package.return_value = 'grizzly'
1321+ self.os_release.return_value = 'grizzly'
1322 self.relation_ids.return_value = ['ceph:0']
1323 self.service_name.return_value = 'glance'
1324 configs = utils.register_configs()
1325@@ -121,8 +130,26 @@
1326 ])
1327 self.assertEquals(ex_map, utils.restart_map())
1328
1329+ @patch('charmhelpers.contrib.openstack.utils.config')
1330+ def test_determine_packages(self, _config):
1331+ _config.return_value = None
1332+ result = utils.determine_packages()
1333+ ex = utils.PACKAGES
1334+ self.assertEquals(set(ex), set(result))
1335+
1336+ @patch('charmhelpers.contrib.openstack.utils.config')
1337+ def test_determine_packages_git(self, _config):
1338+ _config.return_value = openstack_origin_git
1339+ result = utils.determine_packages()
1340+ ex = utils.PACKAGES + utils.BASE_GIT_PACKAGES
1341+ for p in utils.GIT_PACKAGE_BLACKLIST:
1342+ ex.remove(p)
1343+ self.assertEquals(set(ex), set(result))
1344+
1345 @patch.object(utils, 'migrate_database')
1346- def test_openstack_upgrade_leader(self, migrate):
1347+ @patch.object(utils, 'git_install_requested')
1348+ def test_openstack_upgrade_leader(self, git_requested, migrate):
1349+ git_requested.return_value = True
1350 self.config.side_effect = None
1351 self.config.return_value = 'cloud:precise-havana'
1352 self.eligible_leader.return_value = True
1353@@ -130,14 +157,17 @@
1354 configs = MagicMock()
1355 utils.do_openstack_upgrade(configs)
1356 self.assertTrue(configs.write_all.called)
1357- self.apt_install.assert_called_with(utils.PACKAGES, fatal=True)
1358+ self.apt_install.assert_called_with(utils.determine_packages(),
1359+ fatal=True)
1360 self.apt_upgrade.assert_called_with(options=DPKG_OPTS,
1361 fatal=True, dist=True)
1362 configs.set_release.assert_called_with(openstack_release='havana')
1363 self.assertTrue(migrate.called)
1364
1365 @patch.object(utils, 'migrate_database')
1366- def test_openstack_upgrade_not_leader(self, migrate):
1367+ @patch.object(utils, 'git_install_requested')
1368+ def test_openstack_upgrade_not_leader(self, git_requested, migrate):
1369+ git_requested.return_value = True
1370 self.config.side_effect = None
1371 self.config.return_value = 'cloud:precise-havana'
1372 self.eligible_leader.return_value = False
1373@@ -145,8 +175,111 @@
1374 configs = MagicMock()
1375 utils.do_openstack_upgrade(configs)
1376 self.assertTrue(configs.write_all.called)
1377- self.apt_install.assert_called_with(utils.PACKAGES, fatal=True)
1378+ self.apt_install.assert_called_with(utils.determine_packages(),
1379+ fatal=True)
1380 self.apt_upgrade.assert_called_with(options=DPKG_OPTS,
1381 fatal=True, dist=True)
1382 configs.set_release.assert_called_with(openstack_release='havana')
1383 self.assertFalse(migrate.called)
1384+
1385+ @patch.object(utils, 'git_install_requested')
1386+ @patch.object(utils, 'git_clone_and_install')
1387+ @patch.object(utils, 'git_post_install')
1388+ @patch.object(utils, 'git_pre_install')
1389+ def test_git_install(self, git_pre, git_post, git_clone_and_install,
1390+ git_requested):
1391+ projects_yaml = openstack_origin_git
1392+ git_requested.return_value = True
1393+ utils.git_install(projects_yaml)
1394+ self.assertTrue(git_pre.called)
1395+ git_clone_and_install.assert_called_with(openstack_origin_git,
1396+ core_project='glance')
1397+ self.assertTrue(git_post.called)
1398+
1399+ @patch.object(utils, 'mkdir')
1400+ @patch.object(utils, 'write_file')
1401+ @patch.object(utils, 'add_user_to_group')
1402+ @patch.object(utils, 'add_group')
1403+ @patch.object(utils, 'adduser')
1404+ def test_git_pre_install(self, adduser, add_group, add_user_to_group,
1405+ write_file, mkdir):
1406+ utils.git_pre_install()
1407+ adduser.assert_called_with('glance', shell='/bin/bash',
1408+ system_user=True)
1409+ add_group.assert_called_with('glance', system_group=True)
1410+ add_user_to_group.assert_called_with('glance', 'glance')
1411+ expected = [
1412+ call('/var/lib/glance', owner='glance',
1413+ group='glance', perms=0700, force=False),
1414+ call('/var/lib/glance/images', owner='glance',
1415+ group='glance', perms=0700, force=False),
1416+ call('/var/lib/glance/image-cache', owner='glance',
1417+ group='glance', perms=0700, force=False),
1418+ call('/var/lib/glance/image-cache/incomplete', owner='glance',
1419+ group='glance', perms=0700, force=False),
1420+ call('/var/lib/glance/image-cache/invalid', owner='glance',
1421+ group='glance', perms=0700, force=False),
1422+ call('/var/lib/glance/image-cache/queue', owner='glance',
1423+ group='glance', perms=0700, force=False),
1424+ call('/var/log/glance', owner='glance',
1425+ group='glance', perms=0700, force=False),
1426+ ]
1427+ self.assertEquals(mkdir.call_args_list, expected)
1428+ expected = [
1429+ call('/var/log/glance/glance-api.log', '', owner='glance',
1430+ group='glance', perms=0600),
1431+ call('/var/log/glance/glance-registry.log', '', owner='glance',
1432+ group='glance', perms=0600),
1433+ ]
1434+ self.assertEquals(write_file.call_args_list, expected)
1435+
1436+ @patch.object(utils, 'git_src_dir')
1437+ @patch.object(utils, 'service_restart')
1438+ @patch.object(utils, 'render')
1439+ @patch('os.path.join')
1440+ @patch('os.path.exists')
1441+ @patch('shutil.copytree')
1442+ @patch('shutil.rmtree')
1443+ def test_git_post_install(self, rmtree, copytree, exists, join, render,
1444+ service_restart, git_src_dir):
1445+ projects_yaml = openstack_origin_git
1446+ join.return_value = 'joined-string'
1447+ utils.git_post_install(projects_yaml)
1448+ expected = [
1449+ call('joined-string', '/etc/glance'),
1450+ ]
1451+ copytree.assert_has_calls(expected)
1452+ glance_api_context = {
1453+ 'service_description': 'Glance API server',
1454+ 'service_name': 'Glance',
1455+ 'user_name': 'glance',
1456+ 'start_dir': '/var/lib/glance',
1457+ 'process_name': 'glance-api',
1458+ 'executable_name': '/usr/local/bin/glance-api',
1459+ 'config_files': ['/etc/glance/glance-api.conf'],
1460+ 'log_file': '/var/log/glance/api.log',
1461+ }
1462+ glance_registry_context = {
1463+ 'service_description': 'Glance registry server',
1464+ 'service_name': 'Glance',
1465+ 'user_name': 'glance',
1466+ 'start_dir': '/var/lib/glance',
1467+ 'process_name': 'glance-registry',
1468+ 'executable_name': '/usr/local/bin/glance-registry',
1469+ 'config_files': ['/etc/glance/glance-registry.conf'],
1470+ 'log_file': '/var/log/glance/registry.log',
1471+ }
1472+ expected = [
1473+ call('git.upstart', '/etc/init/glance-api.conf',
1474+ glance_api_context, perms=0o644,
1475+ templates_dir='joined-string'),
1476+ call('git.upstart', '/etc/init/glance-registry.conf',
1477+ glance_registry_context, perms=0o644,
1478+ templates_dir='joined-string'),
1479+ ]
1480+ self.assertEquals(render.call_args_list, expected)
1481+ expected = [
1482+ call('glance-api'),
1483+ call('glance-registry'),
1484+ ]
1485+ self.assertEquals(service_restart.call_args_list, expected)

Subscribers

People subscribed via source and target branches