Merge lp:~openstack-charmers/charms/precise/cinder/multi-backend into lp:~openstack-charmers-archive/charms/precise/cinder/trunk

Proposed by James Page
Status: Merged
Merged at revision: 33
Proposed branch: lp:~openstack-charmers/charms/precise/cinder/multi-backend
Merge into: lp:~openstack-charmers-archive/charms/precise/cinder/trunk
Diff against target: 446 lines (+131/-41)
15 files modified
hooks/charmhelpers/contrib/openstack/context.py (+24/-37)
hooks/charmhelpers/contrib/openstack/templates/ceph.conf (+3/-0)
hooks/charmhelpers/contrib/storage/linux/ceph.py (+6/-2)
hooks/charmhelpers/contrib/storage/linux/utils.py (+2/-1)
hooks/charmhelpers/fetch/__init__.py (+4/-0)
hooks/cinder_contexts.py (+19/-0)
hooks/cinder_hooks.py (+7/-0)
hooks/cinder_utils.py (+7/-1)
metadata.yaml (+3/-0)
templates/cinder.conf (+18/-0)
unit_tests/test_cinder_contexts.py (+22/-0)
unit_tests/test_cinder_hooks.py (+11/-0)
unit_tests/test_cinder_utils.py (+1/-0)
unit_tests/test_cluster_hooks.py (+1/-0)
unit_tests/test_utils.py (+3/-0)
To merge this branch: bzr merge lp:~openstack-charmers/charms/precise/cinder/multi-backend
Reviewer Review Type Date Requested Status
Marco Ceppi (community) Abstain
OpenStack Charmers Pending
OpenStack Charmers Pending
Review via email: mp+207221@code.launchpad.net

This proposal supersedes a proposal from 2014-02-12.

Description of the change

Add support for multiple storage backends using subordinate charms.

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

There appears to be a few conflicts

review: Abstain
36. By James Page

Resync helpers

37. By James Page

Rebase on trunk, re-sync helpers

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'hooks/charmhelpers/contrib/openstack/context.py'
2--- hooks/charmhelpers/contrib/openstack/context.py 2014-03-13 15:50:49 +0000
3+++ hooks/charmhelpers/contrib/openstack/context.py 2014-03-18 13:08:41 +0000
4@@ -29,6 +29,7 @@
5 determine_apache_port,
6 determine_api_port,
7 https,
8+ is_clustered
9 )
10
11 from charmhelpers.contrib.hahelpers.apache import (
12@@ -240,10 +241,13 @@
13 '''This generates context for /etc/ceph/ceph.conf templates'''
14 if not relation_ids('ceph'):
15 return {}
16+
17 log('Generating template context for ceph')
18+
19 mon_hosts = []
20 auth = None
21 key = None
22+ use_syslog = str(config('use-syslog')).lower()
23 for rid in relation_ids('ceph'):
24 for unit in related_units(rid):
25 mon_hosts.append(relation_get('private-address', rid=rid,
26@@ -255,6 +259,7 @@
27 'mon_hosts': ' '.join(mon_hosts),
28 'auth': auth,
29 'key': key,
30+ 'use_syslog': use_syslog
31 }
32
33 if not os.path.isdir('/etc/ceph'):
34@@ -391,7 +396,7 @@
35 return ctxt
36
37
38-class NeutronContext(object):
39+class NeutronContext(OSContextGenerator):
40 interfaces = []
41
42 @property
43@@ -452,6 +457,22 @@
44
45 return nvp_ctxt
46
47+ def neutron_ctxt(self):
48+ if https():
49+ proto = 'https'
50+ else:
51+ proto = 'http'
52+ if is_clustered():
53+ host = config('vip')
54+ else:
55+ host = unit_get('private-address')
56+ url = '%s://%s:%s' % (proto, host, '9696')
57+ ctxt = {
58+ 'network_manager': self.network_manager,
59+ 'neutron_url': url,
60+ }
61+ return ctxt
62+
63 def __call__(self):
64 self._ensure_packages()
65
66@@ -461,7 +482,7 @@
67 if not self.plugin:
68 return {}
69
70- ctxt = {'network_manager': self.network_manager}
71+ ctxt = self.neutron_ctxt()
72
73 if self.plugin == 'ovs':
74 ctxt.update(self.ovs_ctxt())
75@@ -493,41 +514,7 @@
76 if not config_flags:
77 return {}
78
79- if config_flags.find('==') >= 0:
80- log("config_flags is not in expected format (key=value)",
81- level=ERROR)
82- raise OSContextError
83-
84- # strip the following from each value.
85- post_strippers = ' ,'
86- # we strip any leading/trailing '=' or ' ' from the string then
87- # split on '='.
88- split = config_flags.strip(' =').split('=')
89- limit = len(split)
90- flags = {}
91- for i in xrange(0, limit - 1):
92- current = split[i]
93- next = split[i + 1]
94- vindex = next.rfind(',')
95- if (i == limit - 2) or (vindex < 0):
96- value = next
97- else:
98- value = next[:vindex]
99-
100- if i == 0:
101- key = current
102- else:
103- # if this not the first entry, expect an embedded key.
104- index = current.rfind(',')
105- if index < 0:
106- log("invalid config value(s) at index %s" % (i),
107- level=ERROR)
108- raise OSContextError
109- key = current[index + 1:]
110-
111- # Add to collection.
112- flags[key.strip(post_strippers)] = value.rstrip(post_strippers)
113-
114+ flags = config_flags_parser(config_flags)
115 return {'user_config_flags': flags}
116
117
118
119=== modified file 'hooks/charmhelpers/contrib/openstack/templates/ceph.conf'
120--- hooks/charmhelpers/contrib/openstack/templates/ceph.conf 2013-10-17 21:48:08 +0000
121+++ hooks/charmhelpers/contrib/openstack/templates/ceph.conf 2014-03-18 13:08:41 +0000
122@@ -9,3 +9,6 @@
123 keyring = /etc/ceph/$cluster.$name.keyring
124 mon host = {{ mon_hosts }}
125 {% endif -%}
126+log to syslog = {{ use_syslog }}
127+err to syslog = {{ use_syslog }}
128+clog to syslog = {{ use_syslog }}
129
130=== modified file 'hooks/charmhelpers/contrib/storage/linux/ceph.py'
131--- hooks/charmhelpers/contrib/storage/linux/ceph.py 2013-11-06 03:53:17 +0000
132+++ hooks/charmhelpers/contrib/storage/linux/ceph.py 2014-03-18 13:08:41 +0000
133@@ -49,6 +49,9 @@
134 auth supported = {auth}
135 keyring = {keyring}
136 mon host = {mon_hosts}
137+ log to syslog = {use_syslog}
138+ err to syslog = {use_syslog}
139+ clog to syslog = {use_syslog}
140 """
141
142
143@@ -194,7 +197,7 @@
144 return hosts
145
146
147-def configure(service, key, auth):
148+def configure(service, key, auth, use_syslog):
149 ''' Perform basic configuration of Ceph '''
150 create_keyring(service, key)
151 create_key_file(service, key)
152@@ -202,7 +205,8 @@
153 with open('/etc/ceph/ceph.conf', 'w') as ceph_conf:
154 ceph_conf.write(CEPH_CONF.format(auth=auth,
155 keyring=_keyring_path(service),
156- mon_hosts=",".join(map(str, hosts))))
157+ mon_hosts=",".join(map(str, hosts)),
158+ use_syslog=use_syslog))
159 modprobe('rbd')
160
161
162
163=== modified file 'hooks/charmhelpers/contrib/storage/linux/utils.py'
164--- hooks/charmhelpers/contrib/storage/linux/utils.py 2014-02-18 12:25:01 +0000
165+++ hooks/charmhelpers/contrib/storage/linux/utils.py 2014-03-18 13:08:41 +0000
166@@ -22,4 +22,5 @@
167
168 :param block_device: str: Full path of block device to clean.
169 '''
170- check_call(['sgdisk', '--zap-all', '--mbrtogpt', block_device])
171+ check_call(['sgdisk', '--zap-all', '--clear',
172+ '--mbrtogpt', block_device])
173
174=== modified file 'hooks/charmhelpers/fetch/__init__.py'
175--- hooks/charmhelpers/fetch/__init__.py 2014-02-18 12:25:01 +0000
176+++ hooks/charmhelpers/fetch/__init__.py 2014-03-18 13:08:41 +0000
177@@ -135,6 +135,10 @@
178
179
180 def add_source(source, key=None):
181+ if source is None:
182+ log('Source is not present. Skipping')
183+ return
184+
185 if (source.startswith('ppa:') or
186 source.startswith('http') or
187 source.startswith('deb ') or
188
189=== modified file 'hooks/cinder_contexts.py'
190--- hooks/cinder_contexts.py 2014-03-13 15:50:49 +0000
191+++ hooks/cinder_contexts.py 2014-03-18 13:08:41 +0000
192@@ -2,6 +2,8 @@
193 config,
194 relation_ids,
195 service_name,
196+ related_units,
197+ relation_get,
198 )
199
200 from charmhelpers.contrib.openstack.context import (
201@@ -74,3 +76,20 @@
202 if not service_enabled('cinder-api'):
203 return {}
204 return super(ApacheSSLContext, self).__call__()
205+
206+
207+class StorageBackendContext(OSContextGenerator):
208+ interfaces = ['storage-backend']
209+
210+ def __call__(self):
211+ backends = []
212+ for rid in relation_ids('storage-backend'):
213+ for unit in related_units(rid):
214+ backend_name = relation_get('backend_name',
215+ unit, rid)
216+ if backend_name:
217+ backends.append(backend_name)
218+ if len(backends) > 0:
219+ return {'backends': ",".join(backends)}
220+ else:
221+ return {}
222
223=== modified file 'hooks/cinder_hooks.py'
224--- hooks/cinder_hooks.py 2014-03-13 15:50:49 +0000
225+++ hooks/cinder_hooks.py 2014-03-18 13:08:41 +0000
226@@ -271,6 +271,13 @@
227 amqp_joined(relation_id=rel_id)
228
229
230+@hooks.hook('storage-backend-relation-changed')
231+@hooks.hook('storage-backend-relation-broken')
232+@restart_on_change(restart_map())
233+def storage_backend():
234+ CONFIGS.write(CINDER_CONF)
235+
236+
237 if __name__ == '__main__':
238 try:
239 hooks.execute(sys.argv)
240
241=== modified file 'hooks/cinder_utils.py'
242--- hooks/cinder_utils.py 2014-02-18 12:25:01 +0000
243+++ hooks/cinder_utils.py 2014-03-18 13:08:41 +0000
244@@ -98,6 +98,7 @@
245
246 TEMPLATES = 'templates/'
247
248+
249 def ceph_config_file():
250 return CHARM_CEPH_CONF.format(service_name())
251
252@@ -112,7 +113,12 @@
253 context.SyslogContext(),
254 cinder_contexts.CephContext(),
255 cinder_contexts.HAProxyContext(),
256- cinder_contexts.ImageServiceContext()],
257+ cinder_contexts.ImageServiceContext(),
258+ context.SubordinateConfigContext(
259+ interface='storage-backend',
260+ service='cinder',
261+ config_file=CINDER_CONF),
262+ cinder_contexts.StorageBackendContext()],
263 'services': ['cinder-api', 'cinder-volume',
264 'cinder-scheduler', 'haproxy']
265 }),
266
267=== added symlink 'hooks/storage-backend-relation-broken'
268=== target is u'cinder_hooks.py'
269=== added symlink 'hooks/storage-backend-relation-changed'
270=== target is u'cinder_hooks.py'
271=== added symlink 'hooks/storage-backend-relation-departed'
272=== target is u'cinder_hooks.py'
273=== added symlink 'hooks/storage-backend-relation-joined'
274=== target is u'cinder_hooks.py'
275=== modified file 'metadata.yaml'
276--- metadata.yaml 2013-10-17 21:48:08 +0000
277+++ metadata.yaml 2014-03-18 13:08:41 +0000
278@@ -22,6 +22,9 @@
279 ha:
280 interface: hacluster
281 scope: container
282+ storage-backend:
283+ interface: cinder-backend
284+ scope: container
285 peers:
286 cluster:
287 interface: cinder-ha
288
289=== modified file 'templates/cinder.conf'
290--- templates/cinder.conf 2014-02-03 10:44:24 +0000
291+++ templates/cinder.conf 2014-03-18 13:08:41 +0000
292@@ -50,3 +50,21 @@
293 {% endfor -%}
294 {% endif -%}
295
296+{% if sections and 'DEFAULT' in sections -%}
297+{% for key, value in sections['DEFAULT'] -%}
298+{{ key }} = {{ value }}
299+{% endfor -%}
300+{% endif -%}
301+
302+{% if backends -%}
303+enabled_backends = {{ backends }}
304+{% endif -%}
305+
306+{% for section in sections -%}
307+{% if section != 'DEFAULT' -%}
308+[{{ section }}]
309+{% for key, value in sections[section] -%}
310+{{ key }} = {{ value }}
311+{% endfor -%}
312+{% endif -%}
313+{% endfor -%}
314
315=== modified file 'unit_tests/test_cinder_contexts.py'
316--- unit_tests/test_cinder_contexts.py 2014-03-13 15:50:49 +0000
317+++ unit_tests/test_cinder_contexts.py 2014-03-18 13:08:41 +0000
318@@ -16,10 +16,13 @@
319 'service_name',
320 'determine_apache_port',
321 'determine_api_port',
322+ 'related_units',
323+ 'relation_get'
324 ]
325
326
327 class TestCinderContext(CharmTestCase):
328+
329 def setUp(self):
330 super(TestCinderContext, self).setUp(contexts, TO_PATCH)
331
332@@ -59,6 +62,25 @@
333 service_enabled.return_value = False
334 self.assertEquals(contexts.ApacheSSLContext()(), {})
335
336+ def test_storage_backend_no_backends(self):
337+ self.relation_ids.return_value = []
338+ self.assertEquals(contexts.StorageBackendContext()(), {})
339+
340+ def test_storage_backend_single_backend(self):
341+ self.relation_ids.return_value = ['cinder-ceph:0']
342+ self.related_units.return_value = ['cinder-ceph/0']
343+ self.relation_get.return_value = 'cinder-ceph'
344+ self.assertEquals(contexts.StorageBackendContext()(),
345+ {'backends': 'cinder-ceph'})
346+
347+ def test_storage_backend_multi_backend(self):
348+ self.relation_ids.return_value = ['cinder-ceph:0', 'cinder-vmware:0']
349+ self.related_units.side_effect = [['cinder-ceph/0'],
350+ ['cinder-vmware/0']]
351+ self.relation_get.side_effect = ['cinder-ceph', 'cinder-vmware']
352+ self.assertEquals(contexts.StorageBackendContext()(),
353+ {'backends': 'cinder-ceph,cinder-vmware'})
354+
355 @patch('charmhelpers.contrib.openstack.context.determine_apache_port')
356 @patch('charmhelpers.contrib.openstack.context.determine_api_port')
357 @patch('charmhelpers.contrib.openstack.context.unit_get')
358
359=== modified file 'unit_tests/test_cinder_hooks.py'
360--- unit_tests/test_cinder_hooks.py 2014-02-18 12:25:57 +0000
361+++ unit_tests/test_cinder_hooks.py 2014-03-18 13:08:41 +0000
362@@ -64,6 +64,7 @@
363
364
365 class TestInstallHook(CharmTestCase):
366+
367 def setUp(self):
368 super(TestInstallHook, self).setUp(hooks, TO_PATCH)
369 self.config.side_effect = self.test_config.get_all
370@@ -121,6 +122,7 @@
371
372
373 class TestChangedHooks(CharmTestCase):
374+
375 def setUp(self):
376 super(TestChangedHooks, self).setUp(hooks, TO_PATCH)
377 self.config.side_effect = self.test_config.get_all
378@@ -228,8 +230,17 @@
379 hooks.hooks.execute(['hooks/image-service-relation-broken'])
380 self.assertTrue(self.CONFIGS.write_all.called)
381
382+ def test_storage_backend_changed(self):
383+ hooks.hooks.execute(['hooks/storage-backend-relation-changed'])
384+ self.CONFIGS.write.assert_called_with(utils.CINDER_CONF)
385+
386+ def test_storage_backend_broken(self):
387+ hooks.hooks.execute(['hooks/storage-backend-relation-broken'])
388+ self.CONFIGS.write.assert_called_with(utils.CINDER_CONF)
389+
390
391 class TestJoinedHooks(CharmTestCase):
392+
393 def setUp(self):
394 super(TestJoinedHooks, self).setUp(hooks, TO_PATCH)
395 self.config.side_effect = self.test_config.get_all
396
397=== modified file 'unit_tests/test_cinder_utils.py'
398--- unit_tests/test_cinder_utils.py 2014-02-12 10:55:14 +0000
399+++ unit_tests/test_cinder_utils.py 2014-03-18 13:08:41 +0000
400@@ -51,6 +51,7 @@
401
402
403 class TestCinderUtils(CharmTestCase):
404+
405 def setUp(self):
406 super(TestCinderUtils, self).setUp(cinder_utils, TO_PATCH)
407 self.config.side_effect = self.test_config.get_all
408
409=== modified file 'unit_tests/test_cluster_hooks.py'
410--- unit_tests/test_cluster_hooks.py 2014-03-13 15:50:49 +0000
411+++ unit_tests/test_cluster_hooks.py 2014-03-18 13:08:41 +0000
412@@ -58,6 +58,7 @@
413
414
415 class TestClusterHooks(CharmTestCase):
416+
417 def setUp(self):
418 super(TestClusterHooks, self).setUp(hooks, TO_PATCH)
419 self.config.side_effect = self.test_config.get_all
420
421=== modified file 'unit_tests/test_utils.py'
422--- unit_tests/test_utils.py 2014-01-15 15:30:21 +0000
423+++ unit_tests/test_utils.py 2014-03-18 13:08:41 +0000
424@@ -55,6 +55,7 @@
425
426
427 class CharmTestCase(unittest.TestCase):
428+
429 def setUp(self, obj, patches):
430 super(CharmTestCase, self).setUp()
431 self.patches = patches
432@@ -75,6 +76,7 @@
433
434
435 class TestConfig(object):
436+
437 def __init__(self):
438 self.config = get_default_config()
439
440@@ -94,6 +96,7 @@
441
442
443 class TestRelation(object):
444+
445 def __init__(self, relation_data={}):
446 self.relation_data = relation_data
447

Subscribers

People subscribed via source and target branches

to all changes: