Merge lp:~corey.bryant/charms/trusty/cinder/remove-missing into lp:~openstack-charmers-archive/charms/trusty/cinder/next

Proposed by Corey Bryant
Status: Merged
Merged at revision: 56
Proposed branch: lp:~corey.bryant/charms/trusty/cinder/remove-missing
Merge into: lp:~openstack-charmers-archive/charms/trusty/cinder/next
Diff against target: 251 lines (+62/-16)
5 files modified
config.yaml (+12/-2)
hooks/cinder_hooks.py (+2/-1)
hooks/cinder_utils.py (+19/-2)
unit_tests/test_cinder_hooks.py (+3/-2)
unit_tests/test_cinder_utils.py (+26/-9)
To merge this branch: bzr merge lp:~corey.bryant/charms/trusty/cinder/remove-missing
Reviewer Review Type Date Requested Status
James Page Needs Fixing
OpenStack Charmers Pending
Review via email: mp+237439@code.launchpad.net

Description of the change

OIL has hit failures where physical volumes (from a previous deployment) are missing from the volume group on the current deployment, and vgextend fails. This patch fixes that by adding an option that requests that missing physical volumes be removed from the volume group.

To post a comment you must log in.
Revision history for this message
James Page (james-page) :
review: Needs Fixing
Revision history for this message
James Page (james-page) wrote :

Marking WIP - set back to 'Needs review' when ready for re-review.

Revision history for this message
James Page (james-page) wrote :

======================================================================
FAIL: It writes out all config
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/mock.py", line 1210, in patched
    return func(*args, **keywargs)
  File "/home/jamespage/src/charms/landing/cinder/unit_tests/test_cinder_hooks.py", line 118, in test_config_changed
    False)
  File "/usr/lib/python2.7/dist-packages/mock.py", line 844, in assert_called_with
    raise AssertionError(msg)
AssertionError: Expected call: configure_lvm_storage(['sdb'], 'cinder-volumes', False)
Actual call: configure_lvm_storage(['sdb'], 'cinder-volumes', False, False)

======================================================================
FAIL: It writes out all config
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/mock.py", line 1210, in patched
    return func(*args, **keywargs)
  File "/home/jamespage/src/charms/landing/cinder/unit_tests/test_cinder_hooks.py", line 133, in test_config_changed_block_devices
    True)
  File "/usr/lib/python2.7/dist-packages/mock.py", line 844, in assert_called_with
    raise AssertionError(msg)
AssertionError: Expected call: configure_lvm_storage(['sdb', '/dev/sdc', 'sde'], 'cinder-new', True)
Actual call: configure_lvm_storage(['sdb', '/dev/sdc', 'sde'], 'cinder-new', True, False)

review: Needs Fixing
Revision history for this message
James Page (james-page) wrote :

Probably worth adding a unit test to ensure that switching the config has the desired effect as well.

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-08 10:42:20 +0000
3+++ config.yaml 2014-10-10 20:37:29 +0000
4@@ -27,12 +27,16 @@
5 description: |
6 The block devices on which to create LVM volume group.
7
8- May also be set to None for deployments that will not need local
9+ May be set to None for deployments that will not need local
10 storage (eg, Ceph/RBD-backed volumes).
11
12 This can also be a space delimited list of block devices to attempt
13 to use in the cinder LVM volume group - each block device detected
14 will be added to the available physical volumes in the volume group.
15+
16+ May be set to the path and size of a local file
17+ (/path/to/file.img|$sizeG), which will be created and used as a
18+ loopback device (for testing only). $sizeG defaults to 5G
19 ceph-osd-replication-count:
20 default: 3
21 type: int
22@@ -51,8 +55,14 @@
23 default: "false"
24 type: string
25 description: |
26- If true, charm will attempt to overwrite block devices containin
27+ If true, charm will attempt to overwrite block devices containing
28 previous filesystems or LVM, assuming it is not in use.
29+ remove-missing:
30+ default: False
31+ type: boolean
32+ description: |
33+ If True, charm will attempt to remove missing physical volumes from
34+ volume group, if logical volumes are not allocated on them.
35 database-user:
36 default: cinder
37 type: string
38
39=== modified file 'hooks/cinder_hooks.py'
40--- hooks/cinder_hooks.py 2014-10-01 22:15:34 +0000
41+++ hooks/cinder_hooks.py 2014-10-10 20:37:29 +0000
42@@ -105,7 +105,8 @@
43 block_devices = conf['block-device'].split()
44 configure_lvm_storage(block_devices,
45 conf['volume-group'],
46- conf['overwrite'] in ['true', 'True', True])
47+ conf['overwrite'] in ['true', 'True', True],
48+ conf['remove-missing'])
49
50 if openstack_upgrade_available('cinder-common'):
51 do_openstack_upgrade(configs=CONFIGS)
52
53=== modified file 'hooks/cinder_utils.py'
54--- hooks/cinder_utils.py 2014-10-07 12:27:23 +0000
55+++ hooks/cinder_utils.py 2014-10-10 20:37:29 +0000
56@@ -267,9 +267,19 @@
57 return list(set(_services))
58
59
60+def reduce_lvm_volume_group_missing(volume_group):
61+ '''
62+ Remove all missing physical volumes from the volume group, if there
63+ are no logical volumes allocated on them.
64+
65+ :param volume_group: str: Name of volume group to reduce.
66+ '''
67+ subprocess.check_call(['vgreduce', '--removemissing', volume_group])
68+
69+
70 def extend_lvm_volume_group(volume_group, block_device):
71 '''
72- Extend and LVM volume group onto a given block device.
73+ Extend an LVM volume group onto a given block device.
74
75 Assumes block device has already been initialized as an LVM PV.
76
77@@ -279,13 +289,16 @@
78 subprocess.check_call(['vgextend', volume_group, block_device])
79
80
81-def configure_lvm_storage(block_devices, volume_group, overwrite=False):
82+def configure_lvm_storage(block_devices, volume_group, overwrite=False,
83+ remove_missing=False):
84 ''' Configure LVM storage on the list of block devices provided
85
86 :param block_devices: list: List of whitelisted block devices to detect
87 and use if found
88 :param overwrite: bool: Scrub any existing block data if block device is
89 not already in-use
90+ :param remove_missing: bool: Remove missing physical volumes from volume
91+ group if logical volume not allocated on them
92 '''
93 devices = []
94 for block_device in block_devices:
95@@ -320,6 +333,10 @@
96 create_lvm_volume_group(volume_group, new_devices[0])
97 new_devices.remove(new_devices[0])
98
99+ # Remove missing physical volumes from volume group
100+ if remove_missing:
101+ reduce_lvm_volume_group_missing(volume_group)
102+
103 if len(new_devices) > 0:
104 # Extend the volume group as required
105 for new_device in new_devices:
106
107=== modified file 'unit_tests/test_cinder_hooks.py'
108--- unit_tests/test_cinder_hooks.py 2014-10-08 10:53:24 +0000
109+++ unit_tests/test_cinder_hooks.py 2014-10-10 20:37:29 +0000
110@@ -115,7 +115,7 @@
111 self.assertTrue(conf_https.called)
112 self.configure_lvm_storage.assert_called_with(['sdb'],
113 'cinder-volumes',
114- False)
115+ False, False)
116
117 @patch.object(hooks, 'configure_https')
118 def test_config_changed_block_devices(self, conf_https):
119@@ -124,13 +124,14 @@
120 self.test_config.set('block-device', 'sdb /dev/sdc sde')
121 self.test_config.set('volume-group', 'cinder-new')
122 self.test_config.set('overwrite', 'True')
123+ self.test_config.set('remove-missing', True)
124 hooks.hooks.execute(['hooks/config-changed'])
125 self.assertTrue(self.CONFIGS.write_all.called)
126 self.assertTrue(conf_https.called)
127 self.configure_lvm_storage.assert_called_with(
128 ['sdb', '/dev/sdc', 'sde'],
129 'cinder-new',
130- True)
131+ True, True)
132
133 @patch.object(hooks, 'configure_https')
134 def test_config_changed_upgrade_available(self, conf_https):
135
136=== modified file 'unit_tests/test_cinder_utils.py'
137--- unit_tests/test_cinder_utils.py 2014-04-14 14:41:11 +0000
138+++ unit_tests/test_cinder_utils.py 2014-10-10 20:37:29 +0000
139@@ -211,11 +211,12 @@
140 ('/mnt/loop0', cinder_utils.DEFAULT_LOOPBACK_SIZE))
141
142 @patch.object(cinder_utils, 'clean_storage')
143+ @patch.object(cinder_utils, 'reduce_lvm_volume_group_missing')
144 @patch.object(cinder_utils, 'extend_lvm_volume_group')
145- def test_configure_lvm_storage(self, extend_lvm, clean_storage):
146+ def test_configure_lvm_storage(self, extend_lvm, reduce_lvm, clean_storage):
147 devices = ['/dev/vdb', '/dev/vdc']
148 self.is_lvm_physical_volume.return_value = False
149- cinder_utils.configure_lvm_storage(devices, 'test', True)
150+ cinder_utils.configure_lvm_storage(devices, 'test', True, True)
151 clean_storage.assert_has_calls(
152 [call('/dev/vdb'),
153 call('/dev/vdc')]
154@@ -225,24 +226,29 @@
155 call('/dev/vdc')]
156 )
157 self.create_lvm_volume_group.assert_called_with('test', '/dev/vdb')
158+ reduce_lvm.assert_called_with('test')
159 extend_lvm.assert_called_with('test', '/dev/vdc')
160
161 @patch.object(cinder_utils, 'clean_storage')
162+ @patch.object(cinder_utils, 'reduce_lvm_volume_group_missing')
163 @patch.object(cinder_utils, 'extend_lvm_volume_group')
164- def test_configure_lvm_storage_loopback(self, extend_lvm, clean_storage):
165+ def test_configure_lvm_storage_loopback(self, extend_lvm, reduce_lvm,
166+ clean_storage):
167 devices = ['/mnt/loop0|10']
168 self.ensure_loopback_device.return_value = '/dev/loop0'
169 self.is_lvm_physical_volume.return_value = False
170- cinder_utils.configure_lvm_storage(devices, 'test', True)
171+ cinder_utils.configure_lvm_storage(devices, 'test', True, True)
172 clean_storage.assert_called_with('/dev/loop0')
173 self.ensure_loopback_device.assert_called_with('/mnt/loop0', '10')
174 self.create_lvm_physical_volume.assert_called_with('/dev/loop0')
175 self.create_lvm_volume_group.assert_called_with('test', '/dev/loop0')
176+ reduce_lvm.assert_called_with('test')
177 self.assertFalse(extend_lvm.called)
178
179 @patch.object(cinder_utils, 'clean_storage')
180+ @patch.object(cinder_utils, 'reduce_lvm_volume_group_missing')
181 @patch.object(cinder_utils, 'extend_lvm_volume_group')
182- def test_configure_lvm_storage_existing_vg(self, extend_lvm,
183+ def test_configure_lvm_storage_existing_vg(self, extend_lvm, reduce_lvm,
184 clean_storage):
185 def pv_lookup(device):
186 devices = {
187@@ -260,19 +266,21 @@
188 devices = ['/dev/vdb', '/dev/vdc']
189 self.is_lvm_physical_volume.side_effect = pv_lookup
190 self.list_lvm_volume_group.side_effect = vg_lookup
191- cinder_utils.configure_lvm_storage(devices, 'test', True)
192+ cinder_utils.configure_lvm_storage(devices, 'test', True, True)
193 clean_storage.assert_has_calls(
194 [call('/dev/vdc')]
195 )
196 self.create_lvm_physical_volume.assert_has_calls(
197 [call('/dev/vdc')]
198 )
199+ reduce_lvm.assert_called_with('test')
200 extend_lvm.assert_called_with('test', '/dev/vdc')
201 self.assertFalse(self.create_lvm_volume_group.called)
202
203 @patch.object(cinder_utils, 'clean_storage')
204+ @patch.object(cinder_utils, 'reduce_lvm_volume_group_missing')
205 @patch.object(cinder_utils, 'extend_lvm_volume_group')
206- def test_configure_lvm_storage_different_vg(self, extend_lvm,
207+ def test_configure_lvm_storage_different_vg(self, extend_lvm, reduce_lvm,
208 clean_storage):
209 def pv_lookup(device):
210 devices = {
211@@ -290,15 +298,18 @@
212 devices = ['/dev/vdb', '/dev/vdc']
213 self.is_lvm_physical_volume.side_effect = pv_lookup
214 self.list_lvm_volume_group.side_effect = vg_lookup
215- cinder_utils.configure_lvm_storage(devices, 'test', True)
216+ cinder_utils.configure_lvm_storage(devices, 'test', True, True)
217 clean_storage.assert_called_with('/dev/vdc')
218 self.create_lvm_physical_volume.assert_called_with('/dev/vdc')
219+ reduce_lvm.assert_called_with('test')
220 extend_lvm.assert_called_with('test', '/dev/vdc')
221 self.assertFalse(self.create_lvm_volume_group.called)
222
223 @patch.object(cinder_utils, 'clean_storage')
224+ @patch.object(cinder_utils, 'reduce_lvm_volume_group_missing')
225 @patch.object(cinder_utils, 'extend_lvm_volume_group')
226 def test_configure_lvm_storage_different_vg_ignore(self, extend_lvm,
227+ reduce_lvm,
228 clean_storage):
229 def pv_lookup(device):
230 devices = {
231@@ -316,13 +327,19 @@
232 devices = ['/dev/vdb', '/dev/vdc']
233 self.is_lvm_physical_volume.side_effect = pv_lookup
234 self.list_lvm_volume_group.side_effect = vg_lookup
235- cinder_utils.configure_lvm_storage(devices, 'test', False)
236+ cinder_utils.configure_lvm_storage(devices, 'test', False, False)
237 self.assertFalse(clean_storage.called)
238 self.assertFalse(self.create_lvm_physical_volume.called)
239+ self.assertFalse(reduce_lvm.called)
240 self.assertFalse(extend_lvm.called)
241 self.assertFalse(self.create_lvm_volume_group.called)
242
243 @patch('subprocess.check_call')
244+ def test_reduce_lvm_volume_group_missing(self, _call):
245+ cinder_utils.reduce_lvm_volume_group_missing('test')
246+ _call.assert_called_with(['vgreduce', '--removemissing', 'test'])
247+
248+ @patch('subprocess.check_call')
249 def test_extend_lvm_volume_group(self, _call):
250 cinder_utils.extend_lvm_volume_group('test', '/dev/sdb')
251 _call.assert_called_with(['vgextend', 'test', '/dev/sdb'])

Subscribers

People subscribed via source and target branches