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
1=== modified file 'hooks/nova_cc_hooks.py'
2--- hooks/nova_cc_hooks.py 2013-11-08 05:41:39 +0000
3+++ hooks/nova_cc_hooks.py 2013-12-17 11:22:30 +0000
4@@ -291,6 +291,11 @@
5 ssh_compute_add(key)
6 relation_set(known_hosts=ssh_known_hosts_b64(),
7 authorized_keys=ssh_authorized_keys_b64())
8+ if relation_get('nova_ssh_public_key'):
9+ key = relation_get('nova_ssh_public_key')
10+ ssh_compute_add(key, user='nova')
11+ relation_set(nova_known_hosts=ssh_known_hosts_b64(user='nova'),
12+ nova_authorized_keys=ssh_authorized_keys_b64(user='nova'))
13
14
15 @hooks.hook('cloud-compute-relation-departed')
16
17=== modified file 'hooks/nova_cc_utils.py'
18--- hooks/nova_cc_utils.py 2013-10-28 19:03:14 +0000
19+++ hooks/nova_cc_utils.py 2013-12-17 11:22:30 +0000
20@@ -334,8 +334,10 @@
21 return b64encode(_in.read())
22
23
24-def ssh_directory_for_unit():
25+def ssh_directory_for_unit(user=None):
26 remote_service = remote_unit().split('/')[0]
27+ if user:
28+ remote_service = "{}_{}".format(remote_service, user)
29 _dir = os.path.join(NOVA_SSH_DIR, remote_service)
30 for d in [NOVA_SSH_DIR, _dir]:
31 if not os.path.isdir(d):
32@@ -347,26 +349,26 @@
33 return _dir
34
35
36-def known_hosts():
37- return os.path.join(ssh_directory_for_unit(), 'known_hosts')
38-
39-
40-def authorized_keys():
41- return os.path.join(ssh_directory_for_unit(), 'authorized_keys')
42-
43-
44-def ssh_known_host_key(host):
45- cmd = ['ssh-keygen', '-f', known_hosts(), '-H', '-F', host]
46+def known_hosts(user=None):
47+ return os.path.join(ssh_directory_for_unit(user), 'known_hosts')
48+
49+
50+def authorized_keys(user=None):
51+ return os.path.join(ssh_directory_for_unit(user), 'authorized_keys')
52+
53+
54+def ssh_known_host_key(host, user=None):
55+ cmd = ['ssh-keygen', '-f', known_hosts(user), '-H', '-F', host]
56 return subprocess.check_output(cmd).strip()
57
58
59-def remove_known_host(host):
60+def remove_known_host(host, user=None):
61 log('Removing SSH known host entry for compute host at %s' % host)
62- cmd = ['ssh-kegen', '-f', known_hosts(), '-R', host]
63+ cmd = ['ssh-keygen', '-f', known_hosts(user), '-R', host]
64 subprocess.check_call(cmd)
65
66
67-def add_known_host(host):
68+def add_known_host(host, user=None):
69 '''Add variations of host to a known hosts file.'''
70 cmd = ['ssh-keyscan', '-H', '-t', 'rsa', host]
71 try:
72@@ -375,30 +377,30 @@
73 log('Could not obtain SSH host key from %s' % host, level=ERROR)
74 raise e
75
76- current_key = ssh_known_host_key(host)
77+ current_key = ssh_known_host_key(host, user)
78 if current_key:
79 if remote_key == current_key:
80 log('Known host key for compute host %s up to date.' % host)
81 return
82 else:
83- remove_known_host(host)
84+ remove_known_host(host, user)
85
86 log('Adding SSH host key to known hosts for compute node at %s.' % host)
87- with open(known_hosts(), 'a') as out:
88+ with open(known_hosts(user), 'a') as out:
89 out.write(remote_key + '\n')
90
91
92-def ssh_authorized_key_exists(public_key):
93- with open(authorized_keys()) as keys:
94+def ssh_authorized_key_exists(public_key, user=None):
95+ with open(authorized_keys(user)) as keys:
96 return (' %s ' % public_key) in keys.read()
97
98
99-def add_authorized_key(public_key):
100- with open(authorized_keys(), 'a') as keys:
101+def add_authorized_key(public_key, user=None):
102+ with open(authorized_keys(user), 'a') as keys:
103 keys.write(public_key + '\n')
104
105
106-def ssh_compute_add(public_key):
107+def ssh_compute_add(public_key, user=None):
108 # If remote compute node hands us a hostname, ensure we have a
109 # known hosts entry for its IP, hostname and FQDN.
110 private_address = relation_get('private-address')
111@@ -413,31 +415,31 @@
112 hosts.append(hn.split('.')[0])
113
114 for host in list(set(hosts)):
115- if not ssh_known_host_key(host):
116- add_known_host(host)
117+ if not ssh_known_host_key(host, user):
118+ add_known_host(host, user)
119
120- if not ssh_authorized_key_exists(public_key):
121+ if not ssh_authorized_key_exists(public_key, user):
122 log('Saving SSH authorized key for compute host at %s.' %
123 private_address)
124- add_authorized_key(public_key)
125-
126-
127-def ssh_known_hosts_b64():
128- with open(known_hosts()) as hosts:
129+ add_authorized_key(public_key, user)
130+
131+
132+def ssh_known_hosts_b64(user=None):
133+ with open(known_hosts(user)) as hosts:
134 return b64encode(hosts.read())
135
136
137-def ssh_authorized_keys_b64():
138- with open(authorized_keys()) as keys:
139+def ssh_authorized_keys_b64(user=None):
140+ with open(authorized_keys(user)) as keys:
141 return b64encode(keys.read())
142
143
144-def ssh_compute_remove(public_key):
145- if not (os.path.isfile(authorized_keys()) or
146- os.path.isfile(known_hosts())):
147+def ssh_compute_remove(public_key, user=None):
148+ if not (os.path.isfile(authorized_keys(user)) or
149+ os.path.isfile(known_hosts(user))):
150 return
151
152- with open(authorized_keys()) as _keys:
153+ with open(authorized_keys(user)) as _keys:
154 keys = [k.strip() for k in _keys.readlines()]
155
156 if public_key not in keys:
157@@ -445,7 +447,7 @@
158
159 [keys.remove(key) for key in keys if key == public_key]
160
161- with open(authorized_keys(), 'w') as _keys:
162+ with open(authorized_keys(user), 'w') as _keys:
163 _keys.write('\n'.join(keys))
164
165
166
167=== modified file 'unit_tests/test_nova_cc_utils.py'
168--- unit_tests/test_nova_cc_utils.py 2013-11-08 05:41:39 +0000
169+++ unit_tests/test_nova_cc_utils.py 2013-12-17 11:22:30 +0000
170@@ -303,7 +303,7 @@
171 host_key.return_value = 'fookey_old'
172 with patch_open() as (_open, _file):
173 utils.add_known_host('foohost')
174- rm.assert_called_with('foohost')
175+ rm.assert_called_with('foohost', None)
176
177 @patch.object(utils, 'known_hosts')
178 @patch.object(utils, 'remove_known_host')
179@@ -336,11 +336,17 @@
180 def test_known_hosts(self, ssh_dir):
181 ssh_dir.return_value = '/tmp/foo'
182 self.assertEquals(utils.known_hosts(), '/tmp/foo/known_hosts')
183+ ssh_dir.assert_called_with(None)
184+ self.assertEquals(utils.known_hosts('bar'), '/tmp/foo/known_hosts')
185+ ssh_dir.assert_called_with('bar')
186
187 @patch.object(utils, 'ssh_directory_for_unit')
188 def test_authorized_keys(self, ssh_dir):
189 ssh_dir.return_value = '/tmp/foo'
190 self.assertEquals(utils.authorized_keys(), '/tmp/foo/authorized_keys')
191+ ssh_dir.assert_called_with(None)
192+ self.assertEquals(utils.authorized_keys('bar'), '/tmp/foo/authorized_keys')
193+ ssh_dir.assert_called_with('bar')
194
195 @patch.object(utils, 'known_hosts')
196 @patch('subprocess.check_call')
197@@ -348,7 +354,7 @@
198 known_hosts.return_value = '/tmp/known_hosts'
199 utils.remove_known_host('foo')
200 check_call.assert_called_with([
201- 'ssh-kegen', '-f', known_hosts(), '-R', 'foo'])
202+ 'ssh-keygen', '-f', known_hosts(), '-R', 'foo'])
203
204 @patch.object(utils, 'authorized_keys')
205 def test_ssh_authorized_key_exists(self, keys):
206@@ -424,3 +430,27 @@
207 'quantum_service': 'quantum'})
208 self.assertEquals(
209 endpoints, utils.determine_endpoints('http://foohost.com'))
210+
211+ @patch.object(utils, 'known_hosts')
212+ @patch('subprocess.check_output')
213+ def test_ssh_known_host_key(self, _check_output, _known_hosts):
214+ _known_hosts.return_value = '/foo/known_hosts'
215+ utils.ssh_known_host_key('test')
216+ _check_output.assert_called_with(
217+ ['ssh-keygen', '-f', '/foo/known_hosts',
218+ '-H', '-F', 'test'])
219+ _known_hosts.assert_called_with(None)
220+ utils.ssh_known_host_key('test', 'bar')
221+ _known_hosts.assert_called_with('bar')
222+
223+ @patch.object(utils, 'known_hosts')
224+ @patch('subprocess.check_call')
225+ def test_remove_known_host(self, _check_call, _known_hosts):
226+ _known_hosts.return_value = '/foo/known_hosts'
227+ utils.remove_known_host('test')
228+ _check_call.assert_called_with(
229+ ['ssh-keygen', '-f', '/foo/known_hosts',
230+ '-R', 'test'])
231+ _known_hosts.assert_called_with(None)
232+ utils.remove_known_host('test', 'bar')
233+ _known_hosts.assert_called_with('bar')

Subscribers

People subscribed via source and target branches

to all changes: