Merge lp:~gnuoy/charms/precise/nova-cloud-controller/cell-support into lp:~openstack-charmers-archive/charms/trusty/nova-cloud-controller/next

Proposed by Liam Young
Status: Merged
Merged at revision: 115
Proposed branch: lp:~gnuoy/charms/precise/nova-cloud-controller/cell-support
Merge into: lp:~openstack-charmers-archive/charms/trusty/nova-cloud-controller/next
Diff against target: 334 lines (+164/-5)
8 files modified
config.yaml (+8/-0)
hooks/nova_cc_context.py (+18/-0)
hooks/nova_cc_hooks.py (+37/-2)
hooks/nova_cc_utils.py (+2/-0)
metadata.yaml (+2/-0)
templates/icehouse/nova.conf (+4/-1)
templates/parts/cell (+6/-0)
unit_tests/test_nova_cc_hooks.py (+87/-2)
To merge this branch: bzr merge lp:~gnuoy/charms/precise/nova-cloud-controller/cell-support
Reviewer Review Type Date Requested Status
OpenStack Charmers Pending
Review via email: mp+236454@code.launchpad.net

Description of the change

Add support for nova cells

To post a comment you must log in.
104. By Liam Young

Remove duplicate LogLevelContext definition

105. By Liam Young

Explicitly set nova url for cells to use

106. By Liam Young

Merged next in

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'config.yaml'
2--- config.yaml 2014-10-06 21:01:49 +0000
3+++ config.yaml 2014-10-07 11:37:42 +0000
4@@ -243,6 +243,14 @@
5 default: 'en-us'
6 description: |
7 Console keymap
8+ debug:
9+ default: False
10+ type: boolean
11+ description: Enable debug logging
12+ verbose:
13+ default: False
14+ type: boolean
15+ description: Enable verbose logging
16 worker-multiplier:
17 type: int
18 default: 2
19
20=== added symlink 'hooks/cell-relation-broken'
21=== target is u'nova_cc_hooks.py'
22=== added symlink 'hooks/cell-relation-changed'
23=== target is u'nova_cc_hooks.py'
24=== added symlink 'hooks/cell-relation-joined'
25=== target is u'nova_cc_hooks.py'
26=== modified file 'hooks/nova_cc_context.py'
27--- hooks/nova_cc_context.py 2014-09-30 06:48:02 +0000
28+++ hooks/nova_cc_context.py 2014-10-07 11:37:42 +0000
29@@ -41,6 +41,24 @@
30 return super(ApacheSSLContext, self).__call__()
31
32
33+class NovaCellContext(context.OSContextGenerator):
34+ interfaces = ['nova-cell']
35+
36+ def __call__(self):
37+ log('Generating template context for cell')
38+ ctxt = {}
39+ for rid in relation_ids('cell'):
40+ for unit in related_units(rid):
41+ rdata = relation_get(rid=rid, unit=unit)
42+ ctxt = {
43+ 'cell_type': rdata.get('cell_type'),
44+ 'cell_name': rdata.get('cell_name'),
45+ }
46+ if context.context_complete(ctxt):
47+ return ctxt
48+ return {}
49+
50+
51 class NeutronAPIContext(context.OSContextGenerator):
52
53 def __call__(self):
54
55=== modified file 'hooks/nova_cc_hooks.py'
56--- hooks/nova_cc_hooks.py 2014-10-02 09:22:36 +0000
57+++ hooks/nova_cc_hooks.py 2014-10-07 11:37:42 +0000
58@@ -51,7 +51,8 @@
59 )
60
61 from nova_cc_context import (
62- NeutronAPIContext
63+ NeutronAPIContext,
64+ NovaCellContext,
65 )
66
67 from charmhelpers.contrib.peerstorage import (
68@@ -188,6 +189,8 @@
69 CONFIGS.write(QUANTUM_CONF)
70 if network_manager() == 'neutron':
71 CONFIGS.write(NEUTRON_CONF)
72+ [nova_cell_relation_joined(rid=rid)
73+ for rid in relation_ids('cell')]
74
75
76 def conditional_neutron_migration():
77@@ -289,7 +292,10 @@
78 migrate_nova_database()
79 log('Triggering remote cloud-compute restarts.')
80 [compute_joined(rid=rid, remote_restart=True)
81- for rid in relation_ids('cloud-compute')]
82+ for rid in relation_ids('cloud-compute')]
83+ log('Triggering remote cell restarts.')
84+ [nova_cell_relation_joined(rid=rid, remote_restart=True)
85+ for rid in relation_ids('cell')]
86 conditional_neutron_migration()
87
88
89@@ -714,6 +720,8 @@
90 active=config('service-guard'))
91 def relation_broken():
92 CONFIGS.write_all()
93+ [nova_cell_relation_joined(rid=rid)
94+ for rid in relation_ids('cell')]
95
96
97 def configure_https():
98@@ -772,6 +780,31 @@
99 compute_changed(r_id, unit)
100
101
102+# remote_restart is defaulted to true as nova-cells may have started the
103+# nova-cell process before the db migration was run so it will need a
104+# kick
105+@hooks.hook('cell-relation-joined')
106+def nova_cell_relation_joined(rid=None, remote_restart=True):
107+ rel_settings = {
108+ 'nova_url': canonical_url(CONFIGS, INTERNAL) + ":8774/v2"
109+ }
110+ if remote_restart:
111+ rel_settings['restart_trigger'] = str(uuid.uuid4())
112+ relation_set(relation_id=rid, **rel_settings)
113+
114+
115+@hooks.hook('cell-relation-changed')
116+def nova_cell_relation_changed():
117+ CONFIGS.write(NOVA_CONF)
118+
119+
120+def get_cell_type():
121+ cell_info = NovaCellContext()()
122+ if 'cell_type' in cell_info:
123+ return cell_info['cell_type']
124+ return None
125+
126+
127 @hooks.hook('neutron-api-relation-joined')
128 def neutron_api_relation_joined(rid=None, remote_restart=False):
129 with open('/etc/init/neutron-server.override', 'wb') as out:
130@@ -785,6 +818,8 @@
131 rel_settings = {
132 'nova_url': canonical_url(CONFIGS, INTERNAL) + ":8774/v2"
133 }
134+ if get_cell_type():
135+ rel_settings['cell_type'] = get_cell_type()
136 if remote_restart:
137 rel_settings['restart_trigger'] = str(uuid.uuid4())
138 relation_set(relation_id=rid, **rel_settings)
139
140=== modified file 'hooks/nova_cc_utils.py'
141--- hooks/nova_cc_utils.py 2014-10-03 07:43:40 +0000
142+++ hooks/nova_cc_utils.py 2014-10-07 11:37:42 +0000
143@@ -115,7 +115,9 @@
144 interface='nova-vmware',
145 service='nova',
146 config_file=NOVA_CONF),
147+ nova_cc_context.NovaCellContext(),
148 context.SyslogContext(),
149+ context.LogLevelContext(),
150 nova_cc_context.HAProxyContext(),
151 nova_cc_context.IdentityServiceContext(),
152 nova_cc_context.VolumeServiceContext(),
153
154=== modified file 'metadata.yaml'
155--- metadata.yaml 2014-05-15 07:25:56 +0000
156+++ metadata.yaml 2014-10-07 11:37:42 +0000
157@@ -32,6 +32,8 @@
158 interface: quantum
159 neutron-api:
160 interface: neutron-api
161+ cell:
162+ interface: nova-cell
163 ha:
164 interface: hacluster
165 scope: container
166
167=== modified file 'templates/icehouse/nova.conf'
168--- templates/icehouse/nova.conf 2014-09-25 04:01:20 +0000
169+++ templates/icehouse/nova.conf 2014-10-07 11:37:42 +0000
170@@ -4,6 +4,8 @@
171 # Configuration file maintained by Juju. Local changes may be overwritten.
172 ###############################################################################
173 [DEFAULT]
174+verbose={{ verbose }}
175+debug={{ debug }}
176 dhcpbridge_flagfile=/etc/nova/nova.conf
177 dhcpbridge=/usr/bin/nova-dhcpbridge
178 logdir=/var/log/nova
179@@ -14,7 +16,6 @@
180 libvirt_use_virtio_for_bridges=True
181 connection_type=libvirt
182 root_helper=sudo nova-rootwrap /etc/nova/rootwrap.conf
183-verbose=True
184 ec2_private_dns_show_ip=True
185 api_paste_config=/etc/nova/api-paste.ini
186 volumes_path=/var/lib/nova/volumes
187@@ -145,5 +146,7 @@
188 [osapi_v3]
189 enabled=True
190
191+{% include "parts/cell" %}
192+
193 [conductor]
194 workers = {{ workers }}
195
196=== added file 'templates/parts/cell'
197--- templates/parts/cell 1970-01-01 00:00:00 +0000
198+++ templates/parts/cell 2014-10-07 11:37:42 +0000
199@@ -0,0 +1,6 @@
200+{% if cell_type -%}
201+[cells]
202+enable=True
203+name={{ cell_name }}
204+cell_type={{ cell_type }}
205+{% endif -%}
206
207=== modified file 'unit_tests/test_nova_cc_hooks.py'
208--- unit_tests/test_nova_cc_hooks.py 2014-10-02 09:22:36 +0000
209+++ unit_tests/test_nova_cc_hooks.py 2014-10-07 11:37:42 +0000
210@@ -35,6 +35,7 @@
211 'determine_ports',
212 'disable_services',
213 'enable_services',
214+ 'NovaCellContext',
215 'open_port',
216 'is_relation_made',
217 'local_unit',
218@@ -55,6 +56,7 @@
219 'network_manager',
220 'volume_service',
221 'unit_get',
222+ 'uuid',
223 'eligible_leader',
224 'keystone_ca_cert_b64',
225 'neutron_plugin',
226@@ -371,17 +373,99 @@
227 self.assertTrue(configs.write_all.called)
228 self.migrate_nova_database.assert_called_with()
229
230+ @patch.object(hooks, 'nova_cell_relation_joined')
231+ @patch.object(hooks, 'compute_joined')
232+ @patch.object(hooks, 'CONFIGS')
233+ def test_db_changed_remote_restarts(self, configs, comp_joined,
234+ cell_joined):
235+ def _relation_ids(rel):
236+ relid = {
237+ 'cloud-compute': ['nova-compute/0'],
238+ 'cell': ['nova-cell-api/0'],
239+ 'neutron-api': ['neutron-api/0'],
240+ }
241+ return relid[rel]
242+ self.relation_ids.side_effect = _relation_ids
243+ allowed_units = 'nova-cloud-controller/0'
244+ self.test_relation.set({
245+ 'nova_allowed_units': allowed_units,
246+ })
247+ self.local_unit.return_value = 'nova-cloud-controller/0'
248+ self._shared_db_test(configs)
249+ comp_joined.assert_called_with(remote_restart=True,
250+ rid='nova-compute/0')
251+ cell_joined.assert_called_with(remote_restart=True,
252+ rid='nova-cell-api/0')
253+ self.migrate_nova_database.assert_called_with()
254+
255+ @patch.object(hooks, 'nova_cell_relation_joined')
256+ @patch.object(hooks, 'CONFIGS')
257+ def test_amqp_relation_broken(self, configs, cell_joined):
258+ configs.write = MagicMock()
259+ self.relation_ids.return_value = ['nova-cell-api/0']
260+ hooks.relation_broken()
261+ self.assertTrue(configs.write_all.called)
262+ cell_joined.assert_called_with(rid='nova-cell-api/0')
263+
264+ @patch.object(hooks, 'nova_cell_relation_joined')
265+ @patch.object(hooks, 'CONFIGS')
266+ def test_amqp_changed_api_rel(self, configs, cell_joined):
267+ configs.complete_contexts = MagicMock()
268+ configs.complete_contexts.return_value = ['amqp']
269+ configs.write = MagicMock()
270+ self.is_relation_made.return_value = True
271+ hooks.amqp_changed()
272+ self.assertEquals(configs.write.call_args_list,
273+ [call('/etc/nova/nova.conf')])
274+
275+ @patch.object(hooks, 'nova_cell_relation_joined')
276+ @patch.object(hooks, 'CONFIGS')
277+ def test_amqp_changed_noapi_rel(self, configs, cell_joined):
278+ configs.complete_contexts = MagicMock()
279+ configs.complete_contexts.return_value = ['amqp']
280+ configs.write = MagicMock()
281+ self.relation_ids.return_value = ['nova-cell-api/0']
282+ self.is_relation_made.return_value = False
283+ self.network_manager.return_value = 'neutron'
284+ hooks.amqp_changed()
285+ self.assertEquals(configs.write.call_args_list,
286+ [call('/etc/nova/nova.conf'),
287+ call('/etc/neutron/neutron.conf')])
288+ cell_joined.assert_called_with(rid='nova-cell-api/0')
289+
290+ def test_nova_cell_relation_joined(self):
291+ self.uuid.uuid4.return_value = 'bob'
292+ hooks.nova_cell_relation_joined(rid='rid',
293+ remote_restart=True)
294+ self.relation_set.assert_called_with(restart_trigger='bob',
295+ relation_id='rid')
296+
297+ @patch.object(hooks, 'CONFIGS')
298+ def test_nova_cell_relation_changed(self, configs):
299+ hooks.nova_cell_relation_changed()
300+ configs.write.assert_called_with('/etc/nova/nova.conf')
301+
302+ def test_get_cell_type(self):
303+ self.NovaCellContext().return_value = {
304+ 'cell_type': 'parent',
305+ 'cell_name': 'api',
306+ }
307+ self.assertEquals(hooks.get_cell_type(), 'parent')
308+
309 @patch.object(os, 'rename')
310 @patch.object(os.path, 'isfile')
311 @patch.object(hooks, 'CONFIGS')
312- def test_neutron_api_relation_joined(self, configs, isfile, rename):
313+ @patch.object(hooks, 'get_cell_type')
314+ def test_neutron_api_relation_joined(self, get_cell_type, configs, isfile,
315+ rename):
316 neutron_conf = '/etc/neutron/neutron.conf'
317 nova_url = 'http://novaurl:8774/v2'
318 isfile.return_value = True
319 self.service_running.return_value = True
320 _identity_joined = self.patch('identity_joined')
321- self.relation_ids.side_effect = ['relid']
322+ self.relation_ids.return_value = ['relid']
323 self.canonical_url.return_value = 'http://novaurl'
324+ get_cell_type.return_value = 'parent'
325 self.uuid.uuid4.return_value = 'bob'
326 with patch_open() as (_open, _file):
327 hooks.neutron_api_relation_joined(remote_restart=True)
328@@ -389,6 +473,7 @@
329 rename.assert_called_with(neutron_conf, neutron_conf + '_unused')
330 self.assertTrue(_identity_joined.called)
331 self.relation_set.assert_called_with(relation_id=None,
332+ cell_type='parent',
333 nova_url=nova_url,
334 restart_trigger='bob')
335

Subscribers

People subscribed via source and target branches