Merge lp:~hopem/charms/trusty/cinder/lp1493931 into lp:~openstack-charmers-archive/charms/trusty/cinder/next

Proposed by Edward Hope-Morley on 2015-09-10
Status: Superseded
Proposed branch: lp:~hopem/charms/trusty/cinder/lp1493931
Merge into: lp:~openstack-charmers-archive/charms/trusty/cinder/next
Diff against target: 292 lines (+252/-2)
3 files modified
hooks/cinder_contexts.py (+45/-1)
hooks/cinder_utils.py (+1/-1)
unit_tests/test_cinder_contexts.py (+206/-0)
To merge this branch: bzr merge lp:~hopem/charms/trusty/cinder/lp1493931
Reviewer Review Type Date Requested Status
James Page 2015-09-10 Resubmit on 2015-09-11
Review via email: mp+270658@code.launchpad.net

This proposal supersedes a proposal from 2015-09-09.

This proposal has been superseded by a proposal from 2015-09-11.

To post a comment you must log in.
James Page (james-page) wrote : Posted in a previous version of this proposal

Hi Ed

I think we need to add features to backend subordinates so that the sub can determine and flag that its stateful/stateless; that was we don't need to update the cinder charm every time we add a new backend that is stateless.

I would suggest a default assumption of 'stateful', meaning that we would just need to update the cinder-ceph charm for now to set this new flag.

I would suggest something like:

   relation_get('stateful') or True

for the cinder charm, with the cinder-ceph charm setting this on its relation to cinder:

   relation_set('stateful', True)

review: Needs Fixing
Edward Hope-Morley (hopem) wrote : Posted in a previous version of this proposal

Fair dos i'll get that done.

charm_lint_check #9701 cinder-next for hopem mp270658
    LINT FAIL: lint-test failed

LINT Results (max last 2 lines):
make: *** [lint] Error 1
ERROR:root:Make target returned non-zero.

Full lint test output: http://paste.ubuntu.com/12328230/
Build: http://10.245.162.77:8080/job/charm_lint_check/9701/

charm_unit_test #8944 cinder-next for hopem mp270658
    UNIT OK: passed

Build: http://10.245.162.77:8080/job/charm_unit_test/8944/

charm_amulet_test #6332 cinder-next for hopem mp270658
    AMULET FAIL: amulet-test failed

AMULET Results (max last 2 lines):
make: *** [functional_test] Error 1
ERROR:root:Make target returned non-zero.

Full amulet test output: http://paste.ubuntu.com/12328604/
Build: http://10.245.162.77:8080/job/charm_amulet_test/6332/

James Page (james-page) :
review: Resubmit
128. By Edward Hope-Morley on 2015-09-11

fixed unit test lint errors

Ryan Beisner (1chb1n) wrote :

Amulet fail #6332 appears to have been a (new?) juju bug. I've not filed one yet, but after walking through the logs of the various stages, here are observances:

http://paste.ubuntu.com/12366632/

2015-09-10 13:33:59 DEBUG juju.service discovery.go:111 failed to find init system "upstart": exec "/sbin/initctl" failed: exit status 1

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'hooks/cinder_contexts.py'
2--- hooks/cinder_contexts.py 2014-11-25 10:19:07 +0000
3+++ hooks/cinder_contexts.py 2015-09-10 11:18:26 +0000
4@@ -3,12 +3,15 @@
5 relation_ids,
6 service_name,
7 related_units,
8- relation_get
9+ relation_get,
10+ log,
11+ WARNING,
12 )
13
14 from charmhelpers.contrib.openstack.context import (
15 OSContextGenerator,
16 ApacheSSLContext as SSLContext,
17+ SubordinateConfigContext,
18 )
19
20 from charmhelpers.contrib.openstack.utils import (
21@@ -110,3 +113,44 @@
22
23 def __call__(self):
24 return {'debug': config('debug'), 'verbose': config('verbose')}
25+
26+
27+class CinderSubordinateConfigContext(SubordinateConfigContext):
28+
29+ def __call__(self):
30+ ctxt = super(CinderSubordinateConfigContext, self).__call__()
31+
32+ # If all backends are stateless we can allow host setting to be set
33+ # across hosts/units to allow for HA volume failover but otherwise we
34+ # have to leave it as unique (LP: #1493931).
35+ rids = []
36+ for interface in self.interfaces:
37+ rids.extend(relation_ids(interface))
38+
39+ stateless = None
40+ any_stateless = False
41+ for rid in rids:
42+ for unit in related_units(rid):
43+ val = relation_get('stateless', rid=rid, unit=unit) or ""
44+ if val.lower() == 'true':
45+ if stateless is None:
46+ stateless = True
47+ else:
48+ stateless = stateless and True
49+ else:
50+ stateless = False
51+
52+ any_stateless = any_stateless or stateless
53+
54+ if stateless:
55+ if 'DEFAULT' in ctxt['sections']:
56+ ctxt['sections']['DEFAULT'].append(('host', service_name()))
57+ else:
58+ ctxt['sections']['DEFAULT'] = [('host', service_name())]
59+
60+ elif any_stateless:
61+ log("One or more stateless backends configured but unable to "
62+ "set host param since there appear to also be stateful "
63+ "backends configured.", level=WARNING)
64+
65+ return ctxt
66
67=== modified file 'hooks/cinder_utils.py'
68--- hooks/cinder_utils.py 2015-08-03 20:18:39 +0000
69+++ hooks/cinder_utils.py 2015-09-10 11:18:26 +0000
70@@ -172,7 +172,7 @@
71 cinder_contexts.CephContext(),
72 cinder_contexts.HAProxyContext(),
73 cinder_contexts.ImageServiceContext(),
74- context.SubordinateConfigContext(
75+ cinder_contexts.CinderSubordinateConfigContext(
76 interface='storage-backend',
77 service='cinder',
78 config_file=CINDER_CONF),
79
80=== modified file 'unit_tests/test_cinder_contexts.py'
81--- unit_tests/test_cinder_contexts.py 2014-10-01 22:07:44 +0000
82+++ unit_tests/test_cinder_contexts.py 2015-09-10 11:18:26 +0000
83@@ -135,3 +135,209 @@
84 'namespace': 'cinder'})
85 self.assertTrue(mock_https.called)
86 mock_unit_get.assert_called_with('private-address')
87+
88+ @patch('%s.relation_get' % (mod_ch_context))
89+ @patch('%s.related_units' % (mod_ch_context))
90+ @patch('%s.relation_ids' % (mod_ch_context))
91+ @patch('%s.log' % (mod_ch_context), lambda *args, **kwargs: None)
92+ def test_subordinate_config_context_stateless(self, mock_rel_ids,
93+ mock_rel_units,
94+ mock_rel_get):
95+ mock_rel_ids.return_value = ['storage-backend:0']
96+ self.relation_ids.return_value = ['storage-backend:0']
97+
98+ mock_rel_units.return_value = ['cinder-ceph/0']
99+ self.related_units.return_value = ['cinder-ceph/0']
100+
101+ self.service_name.return_value = 'cinder'
102+
103+ settings = \
104+ {'backend_name': 'cinder-ceph',
105+ 'private-address': '10.5.8.191',
106+ 'stateless': 'True',
107+ 'subordinate_configuration':
108+ '{"cinder": '
109+ '{"/etc/cinder/cinder.conf": '
110+ '{"sections": '
111+ '{"cinder-ceph": '
112+ '[["volume_backend_name", '
113+ '"cinder-ceph"], '
114+ '["volume_driver", '
115+ '"cinder.volume.drivers.rbd.RBDDriver"], '
116+ '["rbd_pool", '
117+ '"cinder-ceph"], '
118+ '["rbd_user", '
119+ '"cinder-ceph"]]}}}}'}
120+
121+ def fake_rel_get(attribute=None, unit=None, rid=None):
122+ return settings.get(attribute)
123+
124+ mock_rel_get.side_effect = fake_rel_get
125+ self.relation_get.side_effect = fake_rel_get
126+
127+ ctxt = contexts.CinderSubordinateConfigContext(
128+ interface='storage-backend',
129+ service='cinder',
130+ config_file='/etc/cinder/cinder.conf')()
131+
132+ exp = {'sections': {'DEFAULT': [('host', 'cinder')],
133+ u'cinder-ceph': [[u'volume_backend_name', u'cinder-ceph'],
134+ [u'volume_driver',
135+ u'cinder.volume.drivers.rbd.RBDDriver'],
136+ [u'rbd_pool', u'cinder-ceph'],
137+ [u'rbd_user', u'cinder-ceph']]}}
138+
139+ self.assertEquals(ctxt, exp)
140+
141+ @patch('%s.relation_get' % (mod_ch_context))
142+ @patch('%s.related_units' % (mod_ch_context))
143+ @patch('%s.relation_ids' % (mod_ch_context))
144+ @patch('%s.log' % (mod_ch_context), lambda *args, **kwargs: None)
145+ def test_subordinate_config_context_statefull(self, mock_rel_ids,
146+ mock_rel_units,
147+ mock_rel_get):
148+ mock_rel_ids.return_value = ['storage-backend:0']
149+ self.relation_ids.return_value = ['storage-backend:0']
150+
151+ mock_rel_units.return_value = ['cinder-ceph/0']
152+ self.related_units.return_value = ['cinder-ceph/0']
153+
154+ self.service_name.return_value = 'cinder'
155+
156+ settings = \
157+ {'backend_name': 'cinder-ceph',
158+ 'private-address': '10.5.8.191',
159+ 'stateless': 'False',
160+ 'subordinate_configuration':
161+ '{"cinder": '
162+ '{"/etc/cinder/cinder.conf": '
163+ '{"sections": '
164+ '{"cinder-ceph": '
165+ '[["volume_backend_name", '
166+ '"cinder-ceph"], '
167+ '["volume_driver", '
168+ '"cinder.volume.drivers.rbd.RBDDriver"], '
169+ '["rbd_pool", '
170+ '"cinder-ceph"], '
171+ '["rbd_user", '
172+ '"cinder-ceph"]]}}}}'}
173+
174+ def fake_rel_get(attribute=None, unit=None, rid=None):
175+ return settings.get(attribute)
176+
177+ mock_rel_get.side_effect = fake_rel_get
178+ self.relation_get.side_effect = fake_rel_get
179+
180+ ctxt = contexts.CinderSubordinateConfigContext(
181+ interface='storage-backend',
182+ service='cinder',
183+ config_file='/etc/cinder/cinder.conf')()
184+
185+ exp = {'sections':
186+ {u'cinder-ceph': [[u'volume_backend_name',
187+ u'cinder-ceph'],
188+ [u'volume_driver',
189+ u'cinder.volume.drivers.rbd.RBDDriver'],
190+ [u'rbd_pool', u'cinder-ceph'],
191+ [u'rbd_user', u'cinder-ceph']]}}
192+
193+ self.assertEquals(ctxt, exp)
194+
195+ del settings['stateless']
196+
197+ ctxt = contexts.CinderSubordinateConfigContext(
198+ interface='storage-backend',
199+ service='cinder',
200+ config_file='/etc/cinder/cinder.conf')()
201+
202+ exp = {'sections':
203+ {u'cinder-ceph': [[u'volume_backend_name',
204+ u'cinder-ceph'],
205+ [u'volume_driver',
206+ u'cinder.volume.drivers.rbd.RBDDriver'],
207+ [u'rbd_pool', u'cinder-ceph'],
208+ [u'rbd_user', u'cinder-ceph']]}}
209+
210+ self.assertEquals(ctxt, exp)
211+
212+ @patch('%s.relation_get' % (mod_ch_context))
213+ @patch('%s.related_units' % (mod_ch_context))
214+ @patch('%s.relation_ids' % (mod_ch_context))
215+ @patch.object(contexts, 'log', lambda *args, **kwargs: None)
216+ @patch('%s.log' % (mod_ch_context), lambda *args, **kwargs: None)
217+ def test_subordinate_config_context_mixed(self, mock_rel_ids,
218+ mock_rel_units,
219+ mock_rel_get):
220+ mock_rel_ids.return_value = ['storage-backend:0', 'storage-backend:1']
221+ self.relation_ids.return_value = ['storage-backend:0',
222+ 'storage-backend:1']
223+
224+ def fake_rel_units(rid):
225+ if rid == 'storage-backend:0':
226+ return ['cinder-ceph/0']
227+ else:
228+ return ['cinder-other/0']
229+
230+ mock_rel_units.side_effect = fake_rel_units
231+ self.related_units.side_effect = fake_rel_units
232+
233+ self.service_name.return_value = 'cinder'
234+
235+ cinder_ceph_settings = \
236+ {'backend_name': 'cinder-ceph',
237+ 'private-address': '10.5.8.191',
238+ 'stateless': 'True',
239+ 'subordinate_configuration':
240+ '{"cinder": '
241+ '{"/etc/cinder/cinder.conf": '
242+ '{"sections": '
243+ '{"cinder-ceph": '
244+ '[["volume_backend_name", '
245+ '"cinder-ceph"], '
246+ '["volume_driver", '
247+ '"cinder.volume.drivers.rbd.RBDDriver"], '
248+ '["rbd_pool", '
249+ '"cinder-ceph"], '
250+ '["rbd_user", '
251+ '"cinder-ceph"]]}}}}'}
252+
253+ cinder_other_settings = \
254+ {'backend_name': 'cinder-other',
255+ 'private-address': '10.5.8.192',
256+ 'subordinate_configuration':
257+ '{"cinder": '
258+ '{"/etc/cinder/cinder.conf": '
259+ '{"sections": '
260+ '{"cinder-other": '
261+ '[["volume_backend_name", '
262+ '"cinder-other"], '
263+ '["volume_driver", '
264+ '"cinder.volume.drivers.OtherDriver"]]}}}}'}
265+
266+ def fake_rel_get(attribute=None, unit=None, rid=None):
267+ if unit == 'cinder-ceph/0':
268+ return cinder_ceph_settings.get(attribute)
269+ elif unit == 'cinder-other/0':
270+ return cinder_other_settings.get(attribute)
271+
272+ mock_rel_get.side_effect = fake_rel_get
273+ self.relation_get.side_effect = fake_rel_get
274+
275+ ctxt = contexts.CinderSubordinateConfigContext(
276+ interface='storage-backend',
277+ service='cinder',
278+ config_file='/etc/cinder/cinder.conf')()
279+
280+ exp = {'sections':
281+ {u'cinder-ceph': [[u'volume_backend_name',
282+ u'cinder-ceph'],
283+ [u'volume_driver',
284+ u'cinder.volume.drivers.rbd.RBDDriver'],
285+ [u'rbd_pool', u'cinder-ceph'],
286+ [u'rbd_user', u'cinder-ceph']],
287+ u'cinder-other': [[u'volume_backend_name',
288+ u'cinder-other'],
289+ [u'volume_driver',
290+ u'cinder.volume.drivers.OtherDriver']]}}
291+
292+ self.assertEquals(ctxt, exp)

Subscribers

People subscribed via source and target branches