Merge lp:~louis/charms/precise/nova-cloud-controller/lp1313602-multiline-known-hosts into lp:~openstack-charmers-archive/charms/precise/nova-cloud-controller/trunk
- Precise Pangolin (12.04)
- lp1313602-multiline-known-hosts
- Merge into trunk
Status: | Superseded |
---|---|
Proposed branch: | lp:~louis/charms/precise/nova-cloud-controller/lp1313602-multiline-known-hosts |
Merge into: | lp:~openstack-charmers-archive/charms/precise/nova-cloud-controller/trunk |
Diff against target: |
420 lines (+171/-79) 4 files modified
hooks/nova_cc_hooks.py (+46/-16) 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 |
---|---|---|---|
Louis Bouchard (community) | Needs Resubmitting | ||
James Page | Needs Fixing | ||
Review via email: mp+218442@code.launchpad.net |
This proposal has been superseded by a proposal from 2014-06-19.
Commit message
Description of the change
Send known_hosts and authorized_keys line by line
Only empty lines are not carried over
- 77. By Louis Bouchard
-
Adapt unit tests to changes made by previous commit
Tests now cover multi-line known_hosts & authorized_keys
- 78. By Louis Bouchard
-
Add new test_compute_
changed_ nova_public_ key unit test Test the compute_changed hook when 'enable-resize' is
used by nova-compute - 79. By Louis Bouchard
-
Modify hook funcions & util to work in non-relation hooks
Some hook functions did not work when invoked from non-relation
hooks (compute_changed in particular). Modified all utils
hook functions to honour relation-id & unit-id when required - 80. By Louis Bouchard
-
Modified relation_get mechanism in compute_changed
Get all relations in one call in use dictionary
- 81. By Louis Bouchard
-
Add missing rel_settings test
- 82. By Louis Bouchard
-
Fix unit_test to honour calls with unit & relation ids
- 83. By Louis Bouchard
-
More PEP8 cleanup
Louis Bouchard (louis) wrote : | # |
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
- 84. By Louis Bouchard
-
Implement changes following Merge Proposal
- Replaced uid by unit
- Rolled back change to compute_departed
- Use rel_settings.get() - 85. By Louis Bouchard
-
Fix unit test following uid->unit change in hook
Unmerged revisions
Preview Diff
1 | === modified file 'hooks/nova_cc_hooks.py' |
2 | --- hooks/nova_cc_hooks.py 2014-04-11 16:41:42 +0000 |
3 | +++ hooks/nova_cc_hooks.py 2014-05-27 14:01:55 +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 | @@ -54,8 +55,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 | @@ -339,26 +340,52 @@ |
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, uid=None): |
32 | + rel_settings = relation_get(rid=rid, unit=uid) |
33 | + if 'migration_auth_type' not in rel_settings: |
34 | + return |
35 | + if rel_settings['migration_auth_type'] == 'ssh': |
36 | + key = rel_settings['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, uid=uid) |
49 | + index = 0 |
50 | + for line in ssh_known_hosts_lines(uid=uid): |
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(uid=uid): |
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, uid=uid, user='nova') |
66 | + index = 0 |
67 | + for line in ssh_known_hosts_lines(uid=uid, 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(uid=uid, 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 | -def compute_departed(): |
84 | - ssh_compute_remove(public_key=relation_get('ssh_public_key')) |
85 | +def compute_departed(uid=None): |
86 | + ssh_compute_remove(uid=uid, public_key=relation_get('ssh_public_key')) |
87 | |
88 | |
89 | @hooks.hook('neutron-network-service-relation-joined', |
90 | @@ -498,6 +525,9 @@ |
91 | amqp_joined(relation_id=r_id) |
92 | for r_id in relation_ids('identity-service'): |
93 | identity_joined(rid=r_id) |
94 | + for r_id in relation_ids('cloud-compute'): |
95 | + for unit in related_units(r_id): |
96 | + compute_changed(r_id, unit) |
97 | |
98 | |
99 | def main(): |
100 | |
101 | === modified file 'hooks/nova_cc_utils.py' |
102 | --- hooks/nova_cc_utils.py 2014-05-21 10:03:01 +0000 |
103 | +++ hooks/nova_cc_utils.py 2014-05-27 14:01:55 +0000 |
104 | @@ -509,8 +509,11 @@ |
105 | return b64encode(_in.read()) |
106 | |
107 | |
108 | -def ssh_directory_for_unit(user=None): |
109 | - remote_service = remote_unit().split('/')[0] |
110 | +def ssh_directory_for_unit(remunit=None, user=None): |
111 | + if remunit: |
112 | + remote_service = remunit.split('/')[0] |
113 | + else: |
114 | + remote_service = remote_unit().split('/')[0] |
115 | if user: |
116 | remote_service = "{}_{}".format(remote_service, user) |
117 | _dir = os.path.join(NOVA_SSH_DIR, remote_service) |
118 | @@ -524,29 +527,29 @@ |
119 | return _dir |
120 | |
121 | |
122 | -def known_hosts(user=None): |
123 | - return os.path.join(ssh_directory_for_unit(user), 'known_hosts') |
124 | - |
125 | - |
126 | -def authorized_keys(user=None): |
127 | - return os.path.join(ssh_directory_for_unit(user), 'authorized_keys') |
128 | - |
129 | - |
130 | -def ssh_known_host_key(host, user=None): |
131 | - cmd = ['ssh-keygen', '-f', known_hosts(user), '-H', '-F', host] |
132 | +def known_hosts(unit=None, user=None): |
133 | + return os.path.join(ssh_directory_for_unit(unit, user), 'known_hosts') |
134 | + |
135 | + |
136 | +def authorized_keys(unit=None, user=None): |
137 | + return os.path.join(ssh_directory_for_unit(unit, user), 'authorized_keys') |
138 | + |
139 | + |
140 | +def ssh_known_host_key(host, uid=None, user=None): |
141 | + cmd = ['ssh-keygen', '-f', known_hosts(uid, user), '-H', '-F', host] |
142 | try: |
143 | return subprocess.check_output(cmd).strip() |
144 | except subprocess.CalledProcessError: |
145 | return None |
146 | |
147 | |
148 | -def remove_known_host(host, user=None): |
149 | +def remove_known_host(host, uid=None, user=None): |
150 | log('Removing SSH known host entry for compute host at %s' % host) |
151 | - cmd = ['ssh-keygen', '-f', known_hosts(user), '-R', host] |
152 | + cmd = ['ssh-keygen', '-f', known_hosts(uid, user), '-R', host] |
153 | subprocess.check_call(cmd) |
154 | |
155 | |
156 | -def add_known_host(host, user=None): |
157 | +def add_known_host(host, uid=None, user=None): |
158 | '''Add variations of host to a known hosts file.''' |
159 | cmd = ['ssh-keyscan', '-H', '-t', 'rsa', host] |
160 | try: |
161 | @@ -555,33 +558,34 @@ |
162 | log('Could not obtain SSH host key from %s' % host, level=ERROR) |
163 | raise e |
164 | |
165 | - current_key = ssh_known_host_key(host, user) |
166 | + current_key = ssh_known_host_key(host, uid, user) |
167 | if current_key: |
168 | if remote_key == current_key: |
169 | log('Known host key for compute host %s up to date.' % host) |
170 | return |
171 | else: |
172 | - remove_known_host(host, user) |
173 | + remove_known_host(host, uid, user) |
174 | |
175 | log('Adding SSH host key to known hosts for compute node at %s.' % host) |
176 | - with open(known_hosts(user), 'a') as out: |
177 | + with open(known_hosts(uid, user), 'a') as out: |
178 | out.write(remote_key + '\n') |
179 | |
180 | |
181 | -def ssh_authorized_key_exists(public_key, user=None): |
182 | - with open(authorized_keys(user)) as keys: |
183 | +def ssh_authorized_key_exists(public_key, uid=None, user=None): |
184 | + with open(authorized_keys(uid, user)) as keys: |
185 | return (' %s ' % public_key) in keys.read() |
186 | |
187 | |
188 | -def add_authorized_key(public_key, user=None): |
189 | - with open(authorized_keys(user), 'a') as keys: |
190 | +def add_authorized_key(public_key, uid=None, user=None): |
191 | + with open(authorized_keys(uid, user), 'a') as keys: |
192 | keys.write(public_key + '\n') |
193 | |
194 | |
195 | -def ssh_compute_add(public_key, user=None): |
196 | +def ssh_compute_add(public_key, rid=None, uid=None, user=None): |
197 | # If remote compute node hands us a hostname, ensure we have a |
198 | # known hosts entry for its IP, hostname and FQDN. |
199 | - private_address = relation_get('private-address') |
200 | + private_address = relation_get(rid=rid, unit=uid, |
201 | + attribute='private-address') |
202 | hosts = [private_address] |
203 | |
204 | if not is_ip(private_address): |
205 | @@ -593,31 +597,41 @@ |
206 | hosts.append(hn.split('.')[0]) |
207 | |
208 | for host in list(set(hosts)): |
209 | - if not ssh_known_host_key(host, user): |
210 | - add_known_host(host, user) |
211 | + if not ssh_known_host_key(host, uid, user): |
212 | + add_known_host(host, uid, user) |
213 | |
214 | - if not ssh_authorized_key_exists(public_key, user): |
215 | + if not ssh_authorized_key_exists(public_key, uid, user): |
216 | log('Saving SSH authorized key for compute host at %s.' % |
217 | private_address) |
218 | - add_authorized_key(public_key, user) |
219 | - |
220 | - |
221 | -def ssh_known_hosts_b64(user=None): |
222 | - with open(known_hosts(user)) as hosts: |
223 | - return b64encode(hosts.read()) |
224 | - |
225 | - |
226 | -def ssh_authorized_keys_b64(user=None): |
227 | - with open(authorized_keys(user)) as keys: |
228 | - return b64encode(keys.read()) |
229 | - |
230 | - |
231 | -def ssh_compute_remove(public_key, user=None): |
232 | - if not (os.path.isfile(authorized_keys(user)) or |
233 | - os.path.isfile(known_hosts(user))): |
234 | + add_authorized_key(public_key, uid, user) |
235 | + |
236 | + |
237 | +def ssh_known_hosts_lines(uid=None, user=None): |
238 | + known_hosts_list = [] |
239 | + |
240 | + with open(known_hosts(uid, user)) as hosts: |
241 | + for hosts_line in hosts: |
242 | + if hosts_line.rstrip(): |
243 | + known_hosts_list.append(hosts_line.rstrip()) |
244 | + return(known_hosts_list) |
245 | + |
246 | + |
247 | +def ssh_authorized_keys_lines(uid=None, user=None): |
248 | + authorized_keys_list = [] |
249 | + |
250 | + with open(authorized_keys(uid, user)) as keys: |
251 | + for authkey_line in keys: |
252 | + if authkey_line.rstrip(): |
253 | + authorized_keys_list.append(authkey_line.rstrip()) |
254 | + return(authorized_keys_list) |
255 | + |
256 | + |
257 | +def ssh_compute_remove(public_key, uid=None, user=None): |
258 | + if not (os.path.isfile(authorized_keys(uid, user)) or |
259 | + os.path.isfile(known_hosts(uid, user))): |
260 | return |
261 | |
262 | - with open(authorized_keys(user)) as _keys: |
263 | + with open(authorized_keys(uid, user)) as _keys: |
264 | keys = [k.strip() for k in _keys.readlines()] |
265 | |
266 | if public_key not in keys: |
267 | @@ -625,7 +639,7 @@ |
268 | |
269 | [keys.remove(key) for key in keys if key == public_key] |
270 | |
271 | - with open(authorized_keys(user), 'w') as _keys: |
272 | + with open(authorized_keys(uid, user), 'w') as _keys: |
273 | keys = '\n'.join(keys) |
274 | if not keys.endswith('\n'): |
275 | keys += '\n' |
276 | |
277 | === modified file 'unit_tests/test_nova_cc_hooks.py' |
278 | --- unit_tests/test_nova_cc_hooks.py 2014-05-21 10:03:01 +0000 |
279 | +++ unit_tests/test_nova_cc_hooks.py 2014-05-27 14:01:55 +0000 |
280 | @@ -35,8 +35,8 @@ |
281 | 'relation_set', |
282 | 'relation_ids', |
283 | 'ssh_compute_add', |
284 | - 'ssh_known_hosts_b64', |
285 | - 'ssh_authorized_keys_b64', |
286 | + 'ssh_known_hosts_lines', |
287 | + 'ssh_authorized_keys_lines', |
288 | 'save_script_rc', |
289 | 'execd_preinstall', |
290 | 'network_manager', |
291 | @@ -98,12 +98,60 @@ |
292 | self.test_relation.set({ |
293 | 'migration_auth_type': 'ssh', 'ssh_public_key': 'fookey', |
294 | 'private-address': '10.0.0.1'}) |
295 | - self.ssh_known_hosts_b64.return_value = 'hosts' |
296 | - self.ssh_authorized_keys_b64.return_value = 'keys' |
297 | - hooks.compute_changed() |
298 | - self.ssh_compute_add.assert_called_with('fookey') |
299 | - self.relation_set.assert_called_with(known_hosts='hosts', |
300 | - authorized_keys='keys') |
301 | + self.ssh_known_hosts_lines.return_value = [ |
302 | + 'k_h_0', 'k_h_1', 'k_h_2'] |
303 | + self.ssh_authorized_keys_lines.return_value = [ |
304 | + 'auth_0', 'auth_1', 'auth_2'] |
305 | + hooks.compute_changed() |
306 | + self.ssh_compute_add.assert_called_with('fookey', rid=None, uid=None) |
307 | + expected_relations = [ |
308 | + call(relation_settings={'authorized_keys_0': 'auth_0'}, |
309 | + relation_id=None), |
310 | + call(relation_settings={'authorized_keys_1': 'auth_1'}, |
311 | + relation_id=None), |
312 | + call(relation_settings={'authorized_keys_2': 'auth_2'}, |
313 | + relation_id=None), |
314 | + call(relation_settings={'known_hosts_0': 'k_h_0'}, |
315 | + relation_id=None), |
316 | + call(relation_settings={'known_hosts_1': 'k_h_1'}, |
317 | + relation_id=None), |
318 | + call(relation_settings={'known_hosts_2': 'k_h_2'}, |
319 | + relation_id=None), |
320 | + call(authorized_keys_max_index=3, relation_id=None), |
321 | + call(known_hosts_max_index=3, relation_id=None)] |
322 | + self.assertEquals(sorted(self.relation_set.call_args_list), |
323 | + sorted(expected_relations)) |
324 | + |
325 | + def test_compute_changed_nova_public_key(self): |
326 | + self.test_relation.set({ |
327 | + 'migration_auth_type': 'sasl', 'nova_ssh_public_key': 'fookey', |
328 | + 'private-address': '10.0.0.1'}) |
329 | + self.ssh_known_hosts_lines.return_value = [ |
330 | + 'k_h_0', 'k_h_1', 'k_h_2'] |
331 | + self.ssh_authorized_keys_lines.return_value = [ |
332 | + 'auth_0', 'auth_1', 'auth_2'] |
333 | + hooks.compute_changed() |
334 | + self.ssh_compute_add.assert_called_with('fookey', user='nova', |
335 | + rid=None, uid=None) |
336 | + expected_relations = [ |
337 | + call(relation_settings={'nova_authorized_keys_0': 'auth_0'}, |
338 | + relation_id=None), |
339 | + call(relation_settings={'nova_authorized_keys_1': 'auth_1'}, |
340 | + relation_id=None), |
341 | + call(relation_settings={'nova_authorized_keys_2': 'auth_2'}, |
342 | + relation_id=None), |
343 | + call(relation_settings={'nova_known_hosts_0': 'k_h_0'}, |
344 | + relation_id=None), |
345 | + call(relation_settings={'nova_known_hosts_1': 'k_h_1'}, |
346 | + relation_id=None), |
347 | + call(relation_settings={'nova_known_hosts_2': 'k_h_2'}, |
348 | + relation_id=None), |
349 | + call(relation_settings={'nova_known_hosts_max_index': 3}, |
350 | + relation_id=None), |
351 | + call(relation_settings={'nova_authorized_keys_max_index': 3}, |
352 | + relation_id=None)] |
353 | + self.assertEquals(sorted(self.relation_set.call_args_list), |
354 | + sorted(expected_relations)) |
355 | |
356 | @patch.object(hooks, '_auth_config') |
357 | def test_compute_joined_neutron(self, auth_config): |
358 | |
359 | === modified file 'unit_tests/test_nova_cc_utils.py' |
360 | --- unit_tests/test_nova_cc_utils.py 2014-05-02 10:06:23 +0000 |
361 | +++ unit_tests/test_nova_cc_utils.py 2014-05-27 14:01:55 +0000 |
362 | @@ -321,8 +321,8 @@ |
363 | check_output.return_value = 'fookey' |
364 | host_key.return_value = 'fookey_old' |
365 | with patch_open() as (_open, _file): |
366 | - utils.add_known_host('foohost') |
367 | - rm.assert_called_with('foohost', None) |
368 | + utils.add_known_host('foohost', None, None) |
369 | + rm.assert_called_with('foohost', None, None) |
370 | |
371 | @patch.object(utils, 'known_hosts') |
372 | @patch.object(utils, 'remove_known_host') |
373 | @@ -355,19 +355,19 @@ |
374 | def test_known_hosts(self, ssh_dir): |
375 | ssh_dir.return_value = '/tmp/foo' |
376 | self.assertEquals(utils.known_hosts(), '/tmp/foo/known_hosts') |
377 | - ssh_dir.assert_called_with(None) |
378 | + ssh_dir.assert_called_with(None, None) |
379 | self.assertEquals(utils.known_hosts('bar'), '/tmp/foo/known_hosts') |
380 | - ssh_dir.assert_called_with('bar') |
381 | + ssh_dir.assert_called_with('bar', None) |
382 | |
383 | @patch.object(utils, 'ssh_directory_for_unit') |
384 | def test_authorized_keys(self, ssh_dir): |
385 | ssh_dir.return_value = '/tmp/foo' |
386 | self.assertEquals(utils.authorized_keys(), '/tmp/foo/authorized_keys') |
387 | - ssh_dir.assert_called_with(None) |
388 | + ssh_dir.assert_called_with(None, None) |
389 | self.assertEquals( |
390 | utils.authorized_keys('bar'), |
391 | '/tmp/foo/authorized_keys') |
392 | - ssh_dir.assert_called_with('bar') |
393 | + ssh_dir.assert_called_with('bar', None) |
394 | |
395 | @patch.object(utils, 'known_hosts') |
396 | @patch('subprocess.check_call') |
397 | @@ -461,9 +461,9 @@ |
398 | _check_output.assert_called_with( |
399 | ['ssh-keygen', '-f', '/foo/known_hosts', |
400 | '-H', '-F', 'test']) |
401 | - _known_hosts.assert_called_with(None) |
402 | + _known_hosts.assert_called_with(None, None) |
403 | utils.ssh_known_host_key('test', 'bar') |
404 | - _known_hosts.assert_called_with('bar') |
405 | + _known_hosts.assert_called_with('bar', None) |
406 | |
407 | @patch.object(utils, 'known_hosts') |
408 | @patch('subprocess.check_call') |
409 | @@ -473,9 +473,9 @@ |
410 | _check_call.assert_called_with( |
411 | ['ssh-keygen', '-f', '/foo/known_hosts', |
412 | '-R', 'test']) |
413 | - _known_hosts.assert_called_with(None) |
414 | + _known_hosts.assert_called_with(None, None) |
415 | utils.remove_known_host('test', 'bar') |
416 | - _known_hosts.assert_called_with('bar') |
417 | + _known_hosts.assert_called_with('bar', None) |
418 | |
419 | @patch('subprocess.check_output') |
420 | 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...