Merge lp:~louis/charms/precise/nova-cloud-controller/lp1313602-multiline-known-hosts into lp:~openstack-charmers-archive/charms/trusty/nova-cloud-controller/next
- Precise Pangolin (12.04)
- lp1313602-multiline-known-hosts
- Merge into next
Status: | Merged |
---|---|
Merged at revision: | 83 |
Proposed branch: | lp:~louis/charms/precise/nova-cloud-controller/lp1313602-multiline-known-hosts |
Merge into: | lp:~openstack-charmers-archive/charms/trusty/nova-cloud-controller/next |
Diff against target: |
413 lines (+169/-77) 4 files modified
hooks/nova_cc_hooks.py (+44/-14) hooks/nova_cc_utils.py (+59/-45) unit_tests/test_nova_cc_hooks.py (+56/-8) unit_tests/test_nova_cc_utils.py (+10/-10) |
To merge this branch: | bzr merge lp:~louis/charms/precise/nova-cloud-controller/lp1313602-multiline-known-hosts |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
James Page | Needs Fixing | ||
Louis Bouchard | Pending | ||
Review via email: mp+223713@code.launchpad.net |
This proposal supersedes a proposal from 2014-05-06.
Commit message
Description of the change
Send known_hosts and authorized_keys line by line
Only empty lines are not carried over
James Page (james-page) wrote : Posted in a previous version of this proposal | # |
Louis Bouchard (louis) wrote : Posted in a previous version of this proposal | # |
Added call in upgrade-charm hook to action the new code that use multi-line mechanism. Tested that it can be used to recover from a previous failure caused by authorised_
Fixed unit test for previous modifications and adapted them to changes made to support non-relation hook calls (required for upgrade-charm).
Added one unit-test to cover part of the modified code not previously tested.
More test would be needed to cover the non-relation context but out of scope for this bug
James Page (james-page) wrote : | # |
I still see two test errors:
=======
ERROR: test_compute_
-------
Traceback (most recent call last):
File "/home/
call(
NameError: global name 'call' is not defined
=======
ERROR: test_compute_
-------
Traceback (most recent call last):
File "/home/
call(
NameError: global name 'call' is not defined
James Page (james-page) wrote : | # |
Some inline feedback.
Louis Bouchard (louis) : | # |
- 84. By Louis Bouchard
-
Implement changes following Merge Proposal
- Replaced uid by unit
- Rolled back change to compute_departed
- Use rel_settings.get()
James Page (james-page) wrote : | # |
=======
FAIL: test_compute_
-------
Traceback (most recent call last):
File "/home/
rid=None, uid=None)
File "/usr/lib/
raise AssertionError(msg)
AssertionError: Expected call: ssh_compute_
Actual call: ssh_compute_
=======
FAIL: test_compute_
-------
Traceback (most recent call last):
File "/home/
self.
File "/usr/lib/
raise AssertionError(msg)
AssertionError: Expected call: ssh_compute_
Actual call: ssh_compute_
- 85. By Louis Bouchard
-
Fix unit test following uid->unit change in hook
Preview Diff
1 | === modified file 'hooks/nova_cc_hooks.py' |
2 | --- hooks/nova_cc_hooks.py 2014-06-29 07:21:38 +0000 |
3 | +++ hooks/nova_cc_hooks.py 2014-07-16 09:41:59 +0000 |
4 | @@ -19,6 +19,7 @@ |
5 | relation_get, |
6 | relation_ids, |
7 | relation_set, |
8 | + related_units, |
9 | open_port, |
10 | unit_get, |
11 | ) |
12 | @@ -60,8 +61,8 @@ |
13 | save_script_rc, |
14 | ssh_compute_add, |
15 | ssh_compute_remove, |
16 | - ssh_known_hosts_b64, |
17 | - ssh_authorized_keys_b64, |
18 | + ssh_known_hosts_lines, |
19 | + ssh_authorized_keys_lines, |
20 | register_configs, |
21 | restart_map, |
22 | volume_service, |
23 | @@ -364,21 +365,47 @@ |
24 | |
25 | |
26 | @hooks.hook('cloud-compute-relation-changed') |
27 | -def compute_changed(): |
28 | - migration_auth = relation_get('migration_auth_type') |
29 | - if migration_auth == 'ssh': |
30 | - key = relation_get('ssh_public_key') |
31 | +def compute_changed(rid=None, unit=None): |
32 | + rel_settings = relation_get(rid=rid, unit=unit) |
33 | + if 'migration_auth_type' not in rel_settings: |
34 | + return |
35 | + if rel_settings['migration_auth_type'] == 'ssh': |
36 | + key = rel_settings.get('ssh_public_key') |
37 | if not key: |
38 | log('SSH migration set but peer did not publish key.') |
39 | return |
40 | - ssh_compute_add(key) |
41 | - relation_set(known_hosts=ssh_known_hosts_b64(), |
42 | - authorized_keys=ssh_authorized_keys_b64()) |
43 | - if relation_get('nova_ssh_public_key'): |
44 | - key = relation_get('nova_ssh_public_key') |
45 | - ssh_compute_add(key, user='nova') |
46 | - relation_set(nova_known_hosts=ssh_known_hosts_b64(user='nova'), |
47 | - nova_authorized_keys=ssh_authorized_keys_b64(user='nova')) |
48 | + ssh_compute_add(key, rid=rid, unit=unit) |
49 | + index = 0 |
50 | + for line in ssh_known_hosts_lines(unit=unit): |
51 | + relation_set(relation_id=rid, relation_settings= |
52 | + {'known_hosts_{}'.format(index): line}) |
53 | + index += 1 |
54 | + relation_set(relation_id=rid, known_hosts_max_index=index) |
55 | + index = 0 |
56 | + for line in ssh_authorized_keys_lines(unit=unit): |
57 | + relation_set(relation_id=rid, relation_settings= |
58 | + {'authorized_keys_{}'.format(index): line}) |
59 | + index += 1 |
60 | + relation_set(relation_id=rid, authorized_keys_max_index=index) |
61 | + if 'nova_ssh_public_key' not in rel_settings: |
62 | + return |
63 | + if rel_settings['nova_ssh_public_key']: |
64 | + ssh_compute_add(rel_settings['nova_ssh_public_key'], |
65 | + rid=rid, unit=unit, user='nova') |
66 | + index = 0 |
67 | + for line in ssh_known_hosts_lines(unit=unit, user='nova'): |
68 | + relation_set(relation_id=rid, relation_settings= |
69 | + {'{}_known_hosts_{}'.format('nova', index): line}) |
70 | + index += 1 |
71 | + relation_set(relation_id=rid, relation_settings= |
72 | + {'{}_known_hosts_max_index'.format('nova'): index}) |
73 | + index = 0 |
74 | + for line in ssh_authorized_keys_lines(unit=unit, user='nova'): |
75 | + relation_set(relation_id=rid, relation_settings= |
76 | + {'{}_authorized_keys_{}'.format('nova', index): line}) |
77 | + index += 1 |
78 | + relation_set(relation_id=rid, relation_settings= |
79 | + {'{}_authorized_keys_max_index'.format('nova'): index}) |
80 | |
81 | |
82 | @hooks.hook('cloud-compute-relation-departed') |
83 | @@ -514,6 +541,9 @@ |
84 | amqp_joined(relation_id=r_id) |
85 | for r_id in relation_ids('identity-service'): |
86 | identity_joined(rid=r_id) |
87 | + for r_id in relation_ids('cloud-compute'): |
88 | + for unit in related_units(r_id): |
89 | + compute_changed(r_id, unit) |
90 | |
91 | |
92 | @hooks.hook('neutron-api-relation-joined') |
93 | |
94 | === modified file 'hooks/nova_cc_utils.py' |
95 | --- hooks/nova_cc_utils.py 2014-06-24 11:43:28 +0000 |
96 | +++ hooks/nova_cc_utils.py 2014-07-16 09:41:59 +0000 |
97 | @@ -518,8 +518,11 @@ |
98 | return b64encode(_in.read()) |
99 | |
100 | |
101 | -def ssh_directory_for_unit(user=None): |
102 | - remote_service = remote_unit().split('/')[0] |
103 | +def ssh_directory_for_unit(unit=None, user=None): |
104 | + if unit: |
105 | + remote_service = unit.split('/')[0] |
106 | + else: |
107 | + remote_service = remote_unit().split('/')[0] |
108 | if user: |
109 | remote_service = "{}_{}".format(remote_service, user) |
110 | _dir = os.path.join(NOVA_SSH_DIR, remote_service) |
111 | @@ -533,29 +536,29 @@ |
112 | return _dir |
113 | |
114 | |
115 | -def known_hosts(user=None): |
116 | - return os.path.join(ssh_directory_for_unit(user), 'known_hosts') |
117 | - |
118 | - |
119 | -def authorized_keys(user=None): |
120 | - return os.path.join(ssh_directory_for_unit(user), 'authorized_keys') |
121 | - |
122 | - |
123 | -def ssh_known_host_key(host, user=None): |
124 | - cmd = ['ssh-keygen', '-f', known_hosts(user), '-H', '-F', host] |
125 | +def known_hosts(unit=None, user=None): |
126 | + return os.path.join(ssh_directory_for_unit(unit, user), 'known_hosts') |
127 | + |
128 | + |
129 | +def authorized_keys(unit=None, user=None): |
130 | + return os.path.join(ssh_directory_for_unit(unit, user), 'authorized_keys') |
131 | + |
132 | + |
133 | +def ssh_known_host_key(host, unit=None, user=None): |
134 | + cmd = ['ssh-keygen', '-f', known_hosts(unit, user), '-H', '-F', host] |
135 | try: |
136 | return subprocess.check_output(cmd).strip() |
137 | except subprocess.CalledProcessError: |
138 | return None |
139 | |
140 | |
141 | -def remove_known_host(host, user=None): |
142 | +def remove_known_host(host, unit=None, user=None): |
143 | log('Removing SSH known host entry for compute host at %s' % host) |
144 | - cmd = ['ssh-keygen', '-f', known_hosts(user), '-R', host] |
145 | + cmd = ['ssh-keygen', '-f', known_hosts(unit, user), '-R', host] |
146 | subprocess.check_call(cmd) |
147 | |
148 | |
149 | -def add_known_host(host, user=None): |
150 | +def add_known_host(host, unit=None, user=None): |
151 | '''Add variations of host to a known hosts file.''' |
152 | cmd = ['ssh-keyscan', '-H', '-t', 'rsa', host] |
153 | try: |
154 | @@ -564,33 +567,34 @@ |
155 | log('Could not obtain SSH host key from %s' % host, level=ERROR) |
156 | raise e |
157 | |
158 | - current_key = ssh_known_host_key(host, user) |
159 | + current_key = ssh_known_host_key(host, unit, user) |
160 | if current_key: |
161 | if remote_key == current_key: |
162 | log('Known host key for compute host %s up to date.' % host) |
163 | return |
164 | else: |
165 | - remove_known_host(host, user) |
166 | + remove_known_host(host, unit, user) |
167 | |
168 | log('Adding SSH host key to known hosts for compute node at %s.' % host) |
169 | - with open(known_hosts(user), 'a') as out: |
170 | + with open(known_hosts(unit, user), 'a') as out: |
171 | out.write(remote_key + '\n') |
172 | |
173 | |
174 | -def ssh_authorized_key_exists(public_key, user=None): |
175 | - with open(authorized_keys(user)) as keys: |
176 | +def ssh_authorized_key_exists(public_key, unit=None, user=None): |
177 | + with open(authorized_keys(unit, user)) as keys: |
178 | return (' %s ' % public_key) in keys.read() |
179 | |
180 | |
181 | -def add_authorized_key(public_key, user=None): |
182 | - with open(authorized_keys(user), 'a') as keys: |
183 | +def add_authorized_key(public_key, unit=None, user=None): |
184 | + with open(authorized_keys(unit, user), 'a') as keys: |
185 | keys.write(public_key + '\n') |
186 | |
187 | |
188 | -def ssh_compute_add(public_key, user=None): |
189 | +def ssh_compute_add(public_key, rid=None, unit=None, user=None): |
190 | # If remote compute node hands us a hostname, ensure we have a |
191 | # known hosts entry for its IP, hostname and FQDN. |
192 | - private_address = relation_get('private-address') |
193 | + private_address = relation_get(rid=rid, unit=unit, |
194 | + attribute='private-address') |
195 | hosts = [private_address] |
196 | if relation_get('hostname'): |
197 | hosts.append(relation_get('hostname')) |
198 | @@ -604,31 +608,41 @@ |
199 | hosts.append(hn.split('.')[0]) |
200 | |
201 | for host in list(set(hosts)): |
202 | - if not ssh_known_host_key(host, user): |
203 | - add_known_host(host, user) |
204 | + if not ssh_known_host_key(host, unit, user): |
205 | + add_known_host(host, unit, user) |
206 | |
207 | - if not ssh_authorized_key_exists(public_key, user): |
208 | + if not ssh_authorized_key_exists(public_key, unit, user): |
209 | log('Saving SSH authorized key for compute host at %s.' % |
210 | private_address) |
211 | - add_authorized_key(public_key, user) |
212 | - |
213 | - |
214 | -def ssh_known_hosts_b64(user=None): |
215 | - with open(known_hosts(user)) as hosts: |
216 | - return b64encode(hosts.read()) |
217 | - |
218 | - |
219 | -def ssh_authorized_keys_b64(user=None): |
220 | - with open(authorized_keys(user)) as keys: |
221 | - return b64encode(keys.read()) |
222 | - |
223 | - |
224 | -def ssh_compute_remove(public_key, user=None): |
225 | - if not (os.path.isfile(authorized_keys(user)) or |
226 | - os.path.isfile(known_hosts(user))): |
227 | + add_authorized_key(public_key, unit, user) |
228 | + |
229 | + |
230 | +def ssh_known_hosts_lines(unit=None, user=None): |
231 | + known_hosts_list = [] |
232 | + |
233 | + with open(known_hosts(unit, user)) as hosts: |
234 | + for hosts_line in hosts: |
235 | + if hosts_line.rstrip(): |
236 | + known_hosts_list.append(hosts_line.rstrip()) |
237 | + return(known_hosts_list) |
238 | + |
239 | + |
240 | +def ssh_authorized_keys_lines(unit=None, user=None): |
241 | + authorized_keys_list = [] |
242 | + |
243 | + with open(authorized_keys(unit, user)) as keys: |
244 | + for authkey_line in keys: |
245 | + if authkey_line.rstrip(): |
246 | + authorized_keys_list.append(authkey_line.rstrip()) |
247 | + return(authorized_keys_list) |
248 | + |
249 | + |
250 | +def ssh_compute_remove(public_key, unit=None, user=None): |
251 | + if not (os.path.isfile(authorized_keys(unit, user)) or |
252 | + os.path.isfile(known_hosts(unit, user))): |
253 | return |
254 | |
255 | - with open(authorized_keys(user)) as _keys: |
256 | + with open(authorized_keys(unit, user)) as _keys: |
257 | keys = [k.strip() for k in _keys.readlines()] |
258 | |
259 | if public_key not in keys: |
260 | @@ -636,7 +650,7 @@ |
261 | |
262 | [keys.remove(key) for key in keys if key == public_key] |
263 | |
264 | - with open(authorized_keys(user), 'w') as _keys: |
265 | + with open(authorized_keys(unit, user), 'w') as _keys: |
266 | keys = '\n'.join(keys) |
267 | if not keys.endswith('\n'): |
268 | keys += '\n' |
269 | |
270 | === modified file 'unit_tests/test_nova_cc_hooks.py' |
271 | --- unit_tests/test_nova_cc_hooks.py 2014-06-24 11:43:28 +0000 |
272 | +++ unit_tests/test_nova_cc_hooks.py 2014-07-16 09:41:59 +0000 |
273 | @@ -35,8 +35,8 @@ |
274 | 'relation_set', |
275 | 'relation_ids', |
276 | 'ssh_compute_add', |
277 | - 'ssh_known_hosts_b64', |
278 | - 'ssh_authorized_keys_b64', |
279 | + 'ssh_known_hosts_lines', |
280 | + 'ssh_authorized_keys_lines', |
281 | 'save_script_rc', |
282 | 'service_running', |
283 | 'service_stop', |
284 | @@ -100,12 +100,60 @@ |
285 | self.test_relation.set({ |
286 | 'migration_auth_type': 'ssh', 'ssh_public_key': 'fookey', |
287 | 'private-address': '10.0.0.1'}) |
288 | - self.ssh_known_hosts_b64.return_value = 'hosts' |
289 | - self.ssh_authorized_keys_b64.return_value = 'keys' |
290 | - hooks.compute_changed() |
291 | - self.ssh_compute_add.assert_called_with('fookey') |
292 | - self.relation_set.assert_called_with(known_hosts='hosts', |
293 | - authorized_keys='keys') |
294 | + self.ssh_known_hosts_lines.return_value = [ |
295 | + 'k_h_0', 'k_h_1', 'k_h_2'] |
296 | + self.ssh_authorized_keys_lines.return_value = [ |
297 | + 'auth_0', 'auth_1', 'auth_2'] |
298 | + hooks.compute_changed() |
299 | + self.ssh_compute_add.assert_called_with('fookey', rid=None, unit=None) |
300 | + expected_relations = [ |
301 | + call(relation_settings={'authorized_keys_0': 'auth_0'}, |
302 | + relation_id=None), |
303 | + call(relation_settings={'authorized_keys_1': 'auth_1'}, |
304 | + relation_id=None), |
305 | + call(relation_settings={'authorized_keys_2': 'auth_2'}, |
306 | + relation_id=None), |
307 | + call(relation_settings={'known_hosts_0': 'k_h_0'}, |
308 | + relation_id=None), |
309 | + call(relation_settings={'known_hosts_1': 'k_h_1'}, |
310 | + relation_id=None), |
311 | + call(relation_settings={'known_hosts_2': 'k_h_2'}, |
312 | + relation_id=None), |
313 | + call(authorized_keys_max_index=3, relation_id=None), |
314 | + call(known_hosts_max_index=3, relation_id=None)] |
315 | + self.assertEquals(sorted(self.relation_set.call_args_list), |
316 | + sorted(expected_relations)) |
317 | + |
318 | + def test_compute_changed_nova_public_key(self): |
319 | + self.test_relation.set({ |
320 | + 'migration_auth_type': 'sasl', 'nova_ssh_public_key': 'fookey', |
321 | + 'private-address': '10.0.0.1'}) |
322 | + self.ssh_known_hosts_lines.return_value = [ |
323 | + 'k_h_0', 'k_h_1', 'k_h_2'] |
324 | + self.ssh_authorized_keys_lines.return_value = [ |
325 | + 'auth_0', 'auth_1', 'auth_2'] |
326 | + hooks.compute_changed() |
327 | + self.ssh_compute_add.assert_called_with('fookey', user='nova', |
328 | + rid=None, unit=None) |
329 | + expected_relations = [ |
330 | + call(relation_settings={'nova_authorized_keys_0': 'auth_0'}, |
331 | + relation_id=None), |
332 | + call(relation_settings={'nova_authorized_keys_1': 'auth_1'}, |
333 | + relation_id=None), |
334 | + call(relation_settings={'nova_authorized_keys_2': 'auth_2'}, |
335 | + relation_id=None), |
336 | + call(relation_settings={'nova_known_hosts_0': 'k_h_0'}, |
337 | + relation_id=None), |
338 | + call(relation_settings={'nova_known_hosts_1': 'k_h_1'}, |
339 | + relation_id=None), |
340 | + call(relation_settings={'nova_known_hosts_2': 'k_h_2'}, |
341 | + relation_id=None), |
342 | + call(relation_settings={'nova_known_hosts_max_index': 3}, |
343 | + relation_id=None), |
344 | + call(relation_settings={'nova_authorized_keys_max_index': 3}, |
345 | + relation_id=None)] |
346 | + self.assertEquals(sorted(self.relation_set.call_args_list), |
347 | + sorted(expected_relations)) |
348 | |
349 | @patch.object(hooks, '_auth_config') |
350 | def test_compute_joined_neutron(self, auth_config): |
351 | |
352 | === modified file 'unit_tests/test_nova_cc_utils.py' |
353 | --- unit_tests/test_nova_cc_utils.py 2014-06-23 11:07:35 +0000 |
354 | +++ unit_tests/test_nova_cc_utils.py 2014-07-16 09:41:59 +0000 |
355 | @@ -337,8 +337,8 @@ |
356 | check_output.return_value = 'fookey' |
357 | host_key.return_value = 'fookey_old' |
358 | with patch_open() as (_open, _file): |
359 | - utils.add_known_host('foohost') |
360 | - rm.assert_called_with('foohost', None) |
361 | + utils.add_known_host('foohost', None, None) |
362 | + rm.assert_called_with('foohost', None, None) |
363 | |
364 | @patch.object(utils, 'known_hosts') |
365 | @patch.object(utils, 'remove_known_host') |
366 | @@ -371,19 +371,19 @@ |
367 | def test_known_hosts(self, ssh_dir): |
368 | ssh_dir.return_value = '/tmp/foo' |
369 | self.assertEquals(utils.known_hosts(), '/tmp/foo/known_hosts') |
370 | - ssh_dir.assert_called_with(None) |
371 | + ssh_dir.assert_called_with(None, None) |
372 | self.assertEquals(utils.known_hosts('bar'), '/tmp/foo/known_hosts') |
373 | - ssh_dir.assert_called_with('bar') |
374 | + ssh_dir.assert_called_with('bar', None) |
375 | |
376 | @patch.object(utils, 'ssh_directory_for_unit') |
377 | def test_authorized_keys(self, ssh_dir): |
378 | ssh_dir.return_value = '/tmp/foo' |
379 | self.assertEquals(utils.authorized_keys(), '/tmp/foo/authorized_keys') |
380 | - ssh_dir.assert_called_with(None) |
381 | + ssh_dir.assert_called_with(None, None) |
382 | self.assertEquals( |
383 | utils.authorized_keys('bar'), |
384 | '/tmp/foo/authorized_keys') |
385 | - ssh_dir.assert_called_with('bar') |
386 | + ssh_dir.assert_called_with('bar', None) |
387 | |
388 | @patch.object(utils, 'known_hosts') |
389 | @patch('subprocess.check_call') |
390 | @@ -494,9 +494,9 @@ |
391 | _check_output.assert_called_with( |
392 | ['ssh-keygen', '-f', '/foo/known_hosts', |
393 | '-H', '-F', 'test']) |
394 | - _known_hosts.assert_called_with(None) |
395 | + _known_hosts.assert_called_with(None, None) |
396 | utils.ssh_known_host_key('test', 'bar') |
397 | - _known_hosts.assert_called_with('bar') |
398 | + _known_hosts.assert_called_with('bar', None) |
399 | |
400 | @patch.object(utils, 'known_hosts') |
401 | @patch('subprocess.check_call') |
402 | @@ -506,9 +506,9 @@ |
403 | _check_call.assert_called_with( |
404 | ['ssh-keygen', '-f', '/foo/known_hosts', |
405 | '-R', 'test']) |
406 | - _known_hosts.assert_called_with(None) |
407 | + _known_hosts.assert_called_with(None, None) |
408 | utils.remove_known_host('test', 'bar') |
409 | - _known_hosts.assert_called_with('bar') |
410 | + _known_hosts.assert_called_with('bar', None) |
411 | |
412 | @patch('subprocess.check_output') |
413 | def test_migrate_database(self, check_output): |
Hi Louis
The general approach to fixing this looks fine, however the unit tests all need updating:
make test changed_ ssh_migration (unit_tests. test_nova_ cc_hooks. NovaCCHooksTest s) ... ERROR joined_ neutron (unit_tests. test_nova_ cc_hooks. NovaCCHooksTest s) ... ERROR changed_ no_upgrade (unit_tests. test_nova_ cc_hooks. NovaCCHooksTest s) ... ERROR changed_ with_upgrade (unit_tests. test_nova_ cc_hooks. NovaCCHooksTest s) ... ERROR test_nova_ cc_hooks. NovaCCHooksTest s) ... ERROR changed_ missing_ relation_ data (unit_tests. test_nova_ cc_hooks. NovaCCHooksTest s) ... ERROR test_nova_ cc_hooks. NovaCCHooksTest s) ... ERROR joined_ with_postgresql (unit_tests. test_nova_ cc_hooks. NovaCCHooksTest s) ... ERROR test_nova_ cc_hooks. NovaCCHooksTest s) ... ERROR vmware_ joined (unit_tests. test_nova_ cc_hooks. NovaCCHooksTest s) ... ERROR _db_changed (unit_tests. test_nova_ cc_hooks. NovaCCHooksTest s) ... ERROR _neutron_ db_joined (unit_tests. test_nova_ cc_hooks. NovaCCHooksTest s) ... ERROR _neutron_ joined_ with_db (unit_tests. test_nova_ cc_hooks. NovaCCHooksTest s) ... ERROR _nova_db_ changed_ missing_ relation_ data (unit_tests. test_nova_ cc_hooks. NovaCCHooksTest s) ... ERROR _nova_db_ joined (unit_tests. test_nova_ cc_hooks. NovaCCHooksTest s) ... ERROR _nova_joined_ with_db (unit_tests. test_nova_ cc_hooks. NovaCCHooksTest s) ... ERROR known_host_ exists (unit_tests. test_nova_ cc_utils. NovaCCUtilsTest s) ... ok known_host_ exists_ added (unit_tests. test_nova_ cc_utils. NovaCCUtilsTest s) ... ok known_host_ exists_ outdated (unit_tests. test_nova_ cc_utils. NovaCCUtilsTest s) ... ok _keys (unit_tests. test_nova_ cc_utils. NovaCCUtilsTest s) ... ok endpoints_ base (unit_tests. test_nova_ cc_utils. NovaCCUtilsTest s) ... ok endpoints_ nova_volume (unit_tests. test_nova_ cc_utils. NovaCCUtilsTest s) ... ok endpoints_ quantum_ neutron (unit_tests. test_nova_ cc_utils. NovaCCUtilsTest s) ... ok packages_ base (unit_tests. test_nova_ cc_utils. NovaCCUtilsTest s) ... ok packages_ base_grizzly_ beyond (unit_tests. test_nova_ cc_utils. NovaCCUtilsTest s) ... ok packages_ neutron (unit_tests. test_nova_ cc_utils. NovaCCUtilsTest s) ... ok packages_ nova_volume (unit_tests. test_nova_ cc_utils. NovaCCUtilsTest s) ... ok packages_ quantum (unit_tests. test_nova_ cc_utils. NovaCCUtilsTest s) ... ok ports (unit_tests. test_nova_ cc_utils. NovaCCUtilsTest s) ... ok volume_ service_ essex (unit_tests. test_nova_ cc_utils. NovaCCUtilsTest s) ... ok volume_ service_ folsom_ cinder (unit_tests. test_nova_ cc_utils. NovaCCUtilsTest s) ... ok volume_ service_ folsom_ nova_vol (unit_tests. test_nova_ cc_utils. NovaCCUtilsTest s) ... ok volume_ service_ grizzly_ and_beyond (unit_tests. test_nova_ cc_utils. NovaCCUtilsTest s) ... ok test_nova_ cc_utils. NovaCCUtilsTest s) ... ok
Starting tests...
test_compute_
test_compute_
test_config_
test_config_
test_db_changed (unit_tests.
test_db_
test_db_joined (unit_tests.
test_db_
test_install_hook (unit_tests.
test_nova_
test_postgresql
test_postgresql
test_postgresql
test_postgresql
test_postgresql
test_postgresql
test_add_
test_add_
test_add_
test_authorized
test_determine_
test_determine_
test_determine_
test_determine_
test_determine_
test_determine_
test_determine_
test_determine_
test_determine_
test_determine_
test_determine_
test_determine_
test_determine_
test_known_hosts (unit_tests.
Migrate database w...