Merge lp:~james-page/charms/precise/nova-cloud-controller/resize-fixes into lp:~charmers/charms/precise/nova-cloud-controller/trunk

Proposed by James Page
Status: Merged
Merged at revision: 61
Proposed branch: lp:~james-page/charms/precise/nova-cloud-controller/resize-fixes
Merge into: lp:~charmers/charms/precise/nova-cloud-controller/trunk
Diff against target: 233 lines (+76/-39)
3 files modified
hooks/nova_cc_hooks.py (+5/-0)
hooks/nova_cc_utils.py (+39/-37)
unit_tests/test_nova_cc_utils.py (+32/-2)
To merge this branch: bzr merge lp:~james-page/charms/precise/nova-cloud-controller/resize-fixes
Reviewer Review Type Date Requested Status
Adam Gandelman (community) Approve
Jonathan Davies (community) Approve
Marco Ceppi (community) Abstain
Review via email: mp+199267@code.launchpad.net

Description of the change

Add feature to support resizing of instances; this required SSH access for the nova user between compute hosts.

To post a comment you must log in.
Revision history for this message
Marco Ceppi (marcoceppi) wrote :

Deferring to openstack-charmers

review: Abstain
Revision history for this message
Jonathan Davies (jpds) wrote :

+1 I need this for instance migration.

review: Approve
Revision history for this message
Adam Gandelman (gandelman-a) wrote :

Hmm. I appear not to have access to actually approve the merge?

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'hooks/nova_cc_hooks.py'
--- hooks/nova_cc_hooks.py 2013-11-08 05:41:39 +0000
+++ hooks/nova_cc_hooks.py 2013-12-17 11:22:30 +0000
@@ -291,6 +291,11 @@
291 ssh_compute_add(key)291 ssh_compute_add(key)
292 relation_set(known_hosts=ssh_known_hosts_b64(),292 relation_set(known_hosts=ssh_known_hosts_b64(),
293 authorized_keys=ssh_authorized_keys_b64())293 authorized_keys=ssh_authorized_keys_b64())
294 if relation_get('nova_ssh_public_key'):
295 key = relation_get('nova_ssh_public_key')
296 ssh_compute_add(key, user='nova')
297 relation_set(nova_known_hosts=ssh_known_hosts_b64(user='nova'),
298 nova_authorized_keys=ssh_authorized_keys_b64(user='nova'))
294299
295300
296@hooks.hook('cloud-compute-relation-departed')301@hooks.hook('cloud-compute-relation-departed')
297302
=== modified file 'hooks/nova_cc_utils.py'
--- hooks/nova_cc_utils.py 2013-10-28 19:03:14 +0000
+++ hooks/nova_cc_utils.py 2013-12-17 11:22:30 +0000
@@ -334,8 +334,10 @@
334 return b64encode(_in.read())334 return b64encode(_in.read())
335335
336336
337def ssh_directory_for_unit():337def ssh_directory_for_unit(user=None):
338 remote_service = remote_unit().split('/')[0]338 remote_service = remote_unit().split('/')[0]
339 if user:
340 remote_service = "{}_{}".format(remote_service, user)
339 _dir = os.path.join(NOVA_SSH_DIR, remote_service)341 _dir = os.path.join(NOVA_SSH_DIR, remote_service)
340 for d in [NOVA_SSH_DIR, _dir]:342 for d in [NOVA_SSH_DIR, _dir]:
341 if not os.path.isdir(d):343 if not os.path.isdir(d):
@@ -347,26 +349,26 @@
347 return _dir349 return _dir
348350
349351
350def known_hosts():352def known_hosts(user=None):
351 return os.path.join(ssh_directory_for_unit(), 'known_hosts')353 return os.path.join(ssh_directory_for_unit(user), 'known_hosts')
352354
353355
354def authorized_keys():356def authorized_keys(user=None):
355 return os.path.join(ssh_directory_for_unit(), 'authorized_keys')357 return os.path.join(ssh_directory_for_unit(user), 'authorized_keys')
356358
357359
358def ssh_known_host_key(host):360def ssh_known_host_key(host, user=None):
359 cmd = ['ssh-keygen', '-f', known_hosts(), '-H', '-F', host]361 cmd = ['ssh-keygen', '-f', known_hosts(user), '-H', '-F', host]
360 return subprocess.check_output(cmd).strip()362 return subprocess.check_output(cmd).strip()
361363
362364
363def remove_known_host(host):365def remove_known_host(host, user=None):
364 log('Removing SSH known host entry for compute host at %s' % host)366 log('Removing SSH known host entry for compute host at %s' % host)
365 cmd = ['ssh-kegen', '-f', known_hosts(), '-R', host]367 cmd = ['ssh-keygen', '-f', known_hosts(user), '-R', host]
366 subprocess.check_call(cmd)368 subprocess.check_call(cmd)
367369
368370
369def add_known_host(host):371def add_known_host(host, user=None):
370 '''Add variations of host to a known hosts file.'''372 '''Add variations of host to a known hosts file.'''
371 cmd = ['ssh-keyscan', '-H', '-t', 'rsa', host]373 cmd = ['ssh-keyscan', '-H', '-t', 'rsa', host]
372 try:374 try:
@@ -375,30 +377,30 @@
375 log('Could not obtain SSH host key from %s' % host, level=ERROR)377 log('Could not obtain SSH host key from %s' % host, level=ERROR)
376 raise e378 raise e
377379
378 current_key = ssh_known_host_key(host)380 current_key = ssh_known_host_key(host, user)
379 if current_key:381 if current_key:
380 if remote_key == current_key:382 if remote_key == current_key:
381 log('Known host key for compute host %s up to date.' % host)383 log('Known host key for compute host %s up to date.' % host)
382 return384 return
383 else:385 else:
384 remove_known_host(host)386 remove_known_host(host, user)
385387
386 log('Adding SSH host key to known hosts for compute node at %s.' % host)388 log('Adding SSH host key to known hosts for compute node at %s.' % host)
387 with open(known_hosts(), 'a') as out:389 with open(known_hosts(user), 'a') as out:
388 out.write(remote_key + '\n')390 out.write(remote_key + '\n')
389391
390392
391def ssh_authorized_key_exists(public_key):393def ssh_authorized_key_exists(public_key, user=None):
392 with open(authorized_keys()) as keys:394 with open(authorized_keys(user)) as keys:
393 return (' %s ' % public_key) in keys.read()395 return (' %s ' % public_key) in keys.read()
394396
395397
396def add_authorized_key(public_key):398def add_authorized_key(public_key, user=None):
397 with open(authorized_keys(), 'a') as keys:399 with open(authorized_keys(user), 'a') as keys:
398 keys.write(public_key + '\n')400 keys.write(public_key + '\n')
399401
400402
401def ssh_compute_add(public_key):403def ssh_compute_add(public_key, user=None):
402 # If remote compute node hands us a hostname, ensure we have a404 # If remote compute node hands us a hostname, ensure we have a
403 # known hosts entry for its IP, hostname and FQDN.405 # known hosts entry for its IP, hostname and FQDN.
404 private_address = relation_get('private-address')406 private_address = relation_get('private-address')
@@ -413,31 +415,31 @@
413 hosts.append(hn.split('.')[0])415 hosts.append(hn.split('.')[0])
414416
415 for host in list(set(hosts)):417 for host in list(set(hosts)):
416 if not ssh_known_host_key(host):418 if not ssh_known_host_key(host, user):
417 add_known_host(host)419 add_known_host(host, user)
418420
419 if not ssh_authorized_key_exists(public_key):421 if not ssh_authorized_key_exists(public_key, user):
420 log('Saving SSH authorized key for compute host at %s.' %422 log('Saving SSH authorized key for compute host at %s.' %
421 private_address)423 private_address)
422 add_authorized_key(public_key)424 add_authorized_key(public_key, user)
423425
424426
425def ssh_known_hosts_b64():427def ssh_known_hosts_b64(user=None):
426 with open(known_hosts()) as hosts:428 with open(known_hosts(user)) as hosts:
427 return b64encode(hosts.read())429 return b64encode(hosts.read())
428430
429431
430def ssh_authorized_keys_b64():432def ssh_authorized_keys_b64(user=None):
431 with open(authorized_keys()) as keys:433 with open(authorized_keys(user)) as keys:
432 return b64encode(keys.read())434 return b64encode(keys.read())
433435
434436
435def ssh_compute_remove(public_key):437def ssh_compute_remove(public_key, user=None):
436 if not (os.path.isfile(authorized_keys()) or438 if not (os.path.isfile(authorized_keys(user)) or
437 os.path.isfile(known_hosts())):439 os.path.isfile(known_hosts(user))):
438 return440 return
439441
440 with open(authorized_keys()) as _keys:442 with open(authorized_keys(user)) as _keys:
441 keys = [k.strip() for k in _keys.readlines()]443 keys = [k.strip() for k in _keys.readlines()]
442444
443 if public_key not in keys:445 if public_key not in keys:
@@ -445,7 +447,7 @@
445447
446 [keys.remove(key) for key in keys if key == public_key]448 [keys.remove(key) for key in keys if key == public_key]
447449
448 with open(authorized_keys(), 'w') as _keys:450 with open(authorized_keys(user), 'w') as _keys:
449 _keys.write('\n'.join(keys))451 _keys.write('\n'.join(keys))
450452
451453
452454
=== modified file 'unit_tests/test_nova_cc_utils.py'
--- unit_tests/test_nova_cc_utils.py 2013-11-08 05:41:39 +0000
+++ unit_tests/test_nova_cc_utils.py 2013-12-17 11:22:30 +0000
@@ -303,7 +303,7 @@
303 host_key.return_value = 'fookey_old'303 host_key.return_value = 'fookey_old'
304 with patch_open() as (_open, _file):304 with patch_open() as (_open, _file):
305 utils.add_known_host('foohost')305 utils.add_known_host('foohost')
306 rm.assert_called_with('foohost')306 rm.assert_called_with('foohost', None)
307307
308 @patch.object(utils, 'known_hosts')308 @patch.object(utils, 'known_hosts')
309 @patch.object(utils, 'remove_known_host')309 @patch.object(utils, 'remove_known_host')
@@ -336,11 +336,17 @@
336 def test_known_hosts(self, ssh_dir):336 def test_known_hosts(self, ssh_dir):
337 ssh_dir.return_value = '/tmp/foo'337 ssh_dir.return_value = '/tmp/foo'
338 self.assertEquals(utils.known_hosts(), '/tmp/foo/known_hosts')338 self.assertEquals(utils.known_hosts(), '/tmp/foo/known_hosts')
339 ssh_dir.assert_called_with(None)
340 self.assertEquals(utils.known_hosts('bar'), '/tmp/foo/known_hosts')
341 ssh_dir.assert_called_with('bar')
339342
340 @patch.object(utils, 'ssh_directory_for_unit')343 @patch.object(utils, 'ssh_directory_for_unit')
341 def test_authorized_keys(self, ssh_dir):344 def test_authorized_keys(self, ssh_dir):
342 ssh_dir.return_value = '/tmp/foo'345 ssh_dir.return_value = '/tmp/foo'
343 self.assertEquals(utils.authorized_keys(), '/tmp/foo/authorized_keys')346 self.assertEquals(utils.authorized_keys(), '/tmp/foo/authorized_keys')
347 ssh_dir.assert_called_with(None)
348 self.assertEquals(utils.authorized_keys('bar'), '/tmp/foo/authorized_keys')
349 ssh_dir.assert_called_with('bar')
344350
345 @patch.object(utils, 'known_hosts')351 @patch.object(utils, 'known_hosts')
346 @patch('subprocess.check_call')352 @patch('subprocess.check_call')
@@ -348,7 +354,7 @@
348 known_hosts.return_value = '/tmp/known_hosts'354 known_hosts.return_value = '/tmp/known_hosts'
349 utils.remove_known_host('foo')355 utils.remove_known_host('foo')
350 check_call.assert_called_with([356 check_call.assert_called_with([
351 'ssh-kegen', '-f', known_hosts(), '-R', 'foo'])357 'ssh-keygen', '-f', known_hosts(), '-R', 'foo'])
352358
353 @patch.object(utils, 'authorized_keys')359 @patch.object(utils, 'authorized_keys')
354 def test_ssh_authorized_key_exists(self, keys):360 def test_ssh_authorized_key_exists(self, keys):
@@ -424,3 +430,27 @@
424 'quantum_service': 'quantum'})430 'quantum_service': 'quantum'})
425 self.assertEquals(431 self.assertEquals(
426 endpoints, utils.determine_endpoints('http://foohost.com'))432 endpoints, utils.determine_endpoints('http://foohost.com'))
433
434 @patch.object(utils, 'known_hosts')
435 @patch('subprocess.check_output')
436 def test_ssh_known_host_key(self, _check_output, _known_hosts):
437 _known_hosts.return_value = '/foo/known_hosts'
438 utils.ssh_known_host_key('test')
439 _check_output.assert_called_with(
440 ['ssh-keygen', '-f', '/foo/known_hosts',
441 '-H', '-F', 'test'])
442 _known_hosts.assert_called_with(None)
443 utils.ssh_known_host_key('test', 'bar')
444 _known_hosts.assert_called_with('bar')
445
446 @patch.object(utils, 'known_hosts')
447 @patch('subprocess.check_call')
448 def test_remove_known_host(self, _check_call, _known_hosts):
449 _known_hosts.return_value = '/foo/known_hosts'
450 utils.remove_known_host('test')
451 _check_call.assert_called_with(
452 ['ssh-keygen', '-f', '/foo/known_hosts',
453 '-R', 'test'])
454 _known_hosts.assert_called_with(None)
455 utils.remove_known_host('test', 'bar')
456 _known_hosts.assert_called_with('bar')

Subscribers

People subscribed via source and target branches

to all changes: