Merge lp:~peter-sabaini/charms/trusty/ceph-osd/ceph-osd-multijournal-next into lp:~openstack-charmers-archive/charms/trusty/ceph-osd/next
- Trusty Tahr (14.04)
- ceph-osd-multijournal-next
- Merge into next
Status: | Rejected |
---|---|
Rejected by: | James Page |
Proposed branch: | lp:~peter-sabaini/charms/trusty/ceph-osd/ceph-osd-multijournal-next |
Merge into: | lp:~openstack-charmers-archive/charms/trusty/ceph-osd/next |
Diff against target: |
207 lines (+84/-19) (has conflicts) 2 files modified
hooks/ceph.py (+39/-7) hooks/ceph_hooks.py (+45/-12) Text conflict in hooks/ceph.py |
To merge this branch: | bzr merge lp:~peter-sabaini/charms/trusty/ceph-osd/ceph-osd-multijournal-next |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
James Page | Needs Fixing | ||
Chris Holcombe (community) | Approve | ||
Review via email: mp+281149@code.launchpad.net |
Commit message
Description of the change
* Handle multiple journals
* Select least-used journal disk instead of blind RR
* Add safeguard for OSD journals
* Avoid zapping journals repeatedly, add check for journal partition type
* Check that journal devices don't overlap with data devices
uosci-testing-bot (uosci-testing-bot) wrote : | # |
uosci-testing-bot (uosci-testing-bot) wrote : | # |
charm_lint_check #15770 ceph-osd-next for peter-sabaini mp281149
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: pastebin not avail., cmd error
Build: http://
uosci-testing-bot (uosci-testing-bot) wrote : | # |
charm_amulet_test #8384 ceph-osd-next for peter-sabaini mp281149
AMULET OK: passed
Build: http://
uosci-testing-bot (uosci-testing-bot) wrote : | # |
charm_lint_check #16579 ceph-osd-next for peter-sabaini mp281149
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://
Build: http://
uosci-testing-bot (uosci-testing-bot) wrote : | # |
charm_unit_test #15488 ceph-osd-next for peter-sabaini mp281149
UNIT OK: passed
uosci-testing-bot (uosci-testing-bot) wrote : | # |
charm_amulet_test #8504 ceph-osd-next for peter-sabaini mp281149
AMULET OK: passed
Build: http://
Chris Holcombe (xfactor973) : | # |
Chris Holcombe (xfactor973) wrote : | # |
If you could just change that write over to being atomic I think this is good to go. I've love to deploy it to aws to test it.
Peter Sabaini (peter-sabaini) wrote : | # |
Thanks for the review and the suggestion around the atomic write, will update!
Chris MacNaughton (chris.macnaughton) wrote : | # |
Hey Peter, this looks great and I look forward to t hat change! If we want to get this landed for the 16.01 feature freeze, we need that change in soon!
Thanks again!
- 56. By Peter Sabaini
-
Make writing the zapfile safer
Peter Sabaini (peter-sabaini) wrote : | # |
Heya Chris+Chris, hope that was what you were looking for?
uosci-testing-bot (uosci-testing-bot) wrote : | # |
charm_lint_check #17945 ceph-osd-next for peter-sabaini mp281149
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://
Build: http://
uosci-testing-bot (uosci-testing-bot) wrote : | # |
charm_unit_test #16770 ceph-osd-next for peter-sabaini mp281149
UNIT OK: passed
Chris Holcombe (xfactor973) wrote : | # |
Yes that's perfect. Thanks!
Chris Holcombe (xfactor973) wrote : | # |
Peter Sabaini - If you could rebase and take care of that merge conflict we can land this :)
James Page (james-page) wrote : | # |
Note that the lint on the python code also needs resolving:
hooks/ceph_
hooks/ceph_
hooks/ceph_
hooks/ceph_
hooks/ceph_
hooks/ceph_
hooks/ceph_
hooks/ceph_
hooks/ceph.
hooks/ceph.
hooks/ceph.
hooks/ceph.
hooks/ceph.
hooks/ceph.
hooks/ceph.
hooks/ceph.
hooks/ceph.
hooks/ceph.
Peter - do you have time to make these changes?
uosci-testing-bot (uosci-testing-bot) wrote : | # |
charm_unit_test #17028 ceph-osd-next for peter-sabaini mp281149
UNIT OK: passed
uosci-testing-bot (uosci-testing-bot) wrote : | # |
charm_lint_check #18277 ceph-osd-next for peter-sabaini mp281149
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://
Build: http://
uosci-testing-bot (uosci-testing-bot) wrote : | # |
charm_amulet_test #9094 ceph-osd-next for peter-sabaini mp281149
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://
Build: http://
James Page (james-page) wrote : | # |
In the interests of getting this landed ASAP:
https:/
Unmerged revisions
Preview Diff
1 | === modified file 'hooks/ceph.py' | |||
2 | --- hooks/ceph.py 2016-01-12 14:16:54 +0000 | |||
3 | +++ hooks/ceph.py 2016-01-22 15:57:27 +0000 | |||
4 | @@ -22,9 +22,13 @@ | |||
5 | 22 | ) | 22 | ) |
6 | 23 | from charmhelpers.core.hookenv import ( | 23 | from charmhelpers.core.hookenv import ( |
7 | 24 | log, | 24 | log, |
8 | 25 | <<<<<<< TREE | ||
9 | 25 | ERROR, | 26 | ERROR, |
10 | 26 | WARNING, | 27 | WARNING, |
11 | 27 | cached, | 28 | cached, |
12 | 29 | ======= | ||
13 | 30 | ERROR, WARNING, DEBUG, | ||
14 | 31 | >>>>>>> MERGE-SOURCE | ||
15 | 28 | status_set, | 32 | status_set, |
16 | 29 | ) | 33 | ) |
17 | 30 | from charmhelpers.fetch import ( | 34 | from charmhelpers.fetch import ( |
18 | @@ -170,16 +174,20 @@ | |||
19 | 170 | 'btrfs' | 174 | 'btrfs' |
20 | 171 | ] | 175 | ] |
21 | 172 | 176 | ||
22 | 177 | CEPH_PARTITIONS = [ | ||
23 | 178 | '4FBD7E29-9D25-41B8-AFD0-062C0CEFF05D', # ceph osd data | ||
24 | 179 | '45B0969E-9B03-4F30-B4C6-B4B80CEFF106', # ceph osd journal | ||
25 | 180 | ] | ||
26 | 173 | 181 | ||
27 | 174 | def is_osd_disk(dev): | 182 | def is_osd_disk(dev): |
28 | 175 | try: | 183 | try: |
29 | 176 | info = subprocess.check_output(['sgdisk', '-i', '1', dev]) | 184 | info = subprocess.check_output(['sgdisk', '-i', '1', dev]) |
30 | 177 | info = info.split("\n") # IGNORE:E1103 | 185 | info = info.split("\n") # IGNORE:E1103 |
31 | 178 | for line in info: | 186 | for line in info: |
36 | 179 | if line.startswith( | 187 | for ptype in CEPH_PARTITIONS: |
37 | 180 | 'Partition GUID code: 4FBD7E29-9D25-41B8-AFD0-062C0CEFF05D' | 188 | sig = 'Partition GUID code: {}'.format(ptype) |
38 | 181 | ): | 189 | if line.startswith(sig): |
39 | 182 | return True | 190 | return True |
40 | 183 | except subprocess.CalledProcessError: | 191 | except subprocess.CalledProcessError: |
41 | 184 | pass | 192 | pass |
42 | 185 | return False | 193 | return False |
43 | @@ -394,6 +402,28 @@ | |||
44 | 394 | with open(init_marker, 'w'): | 402 | with open(init_marker, 'w'): |
45 | 395 | pass | 403 | pass |
46 | 396 | 404 | ||
47 | 405 | def maybe_zap_journal(journal_dev): | ||
48 | 406 | if (is_osd_disk(journal_dev)): | ||
49 | 407 | log('Looks like {} is already an OSD data or journal, skipping.'.format( | ||
50 | 408 | journal_dev)) | ||
51 | 409 | return | ||
52 | 410 | zap_disk(journal_dev) | ||
53 | 411 | log("Zapped journal device {}".format(journal_dev)) | ||
54 | 412 | |||
55 | 413 | def get_partitions(dev): | ||
56 | 414 | cmd = ['partx', '--raw', '--noheadings', dev] | ||
57 | 415 | try: | ||
58 | 416 | out = subprocess.check_output(cmd).splitlines() | ||
59 | 417 | log("get partitions: {}".format(out), level=DEBUG) | ||
60 | 418 | return out | ||
61 | 419 | except subprocess.CalledProcessError as e: | ||
62 | 420 | log("Can't get info for {0}: {1}".format(dev, e.output)) | ||
63 | 421 | return [] | ||
64 | 422 | |||
65 | 423 | def find_least_used_journal(journal_devices): | ||
66 | 424 | usages = map(lambda a: (len(get_partitions(a)), a), journal_devices) | ||
67 | 425 | least = min(usages, key=lambda t: t[0]) | ||
68 | 426 | return least[1] | ||
69 | 397 | 427 | ||
70 | 398 | def osdize(dev, osd_format, osd_journal, reformat_osd=False, | 428 | def osdize(dev, osd_format, osd_journal, reformat_osd=False, |
71 | 399 | ignore_errors=False): | 429 | ignore_errors=False): |
72 | @@ -414,7 +444,7 @@ | |||
73 | 414 | return | 444 | return |
74 | 415 | 445 | ||
75 | 416 | if (is_osd_disk(dev) and not reformat_osd): | 446 | if (is_osd_disk(dev) and not reformat_osd): |
77 | 417 | log('Looks like {} is already an OSD, skipping.'.format(dev)) | 447 | log('Looks like {} is already an OSD data or journal, skipping.'.format(dev)) |
78 | 418 | return | 448 | return |
79 | 419 | 449 | ||
80 | 420 | if is_device_mounted(dev): | 450 | if is_device_mounted(dev): |
81 | @@ -431,8 +461,9 @@ | |||
82 | 431 | if reformat_osd: | 461 | if reformat_osd: |
83 | 432 | cmd.append('--zap-disk') | 462 | cmd.append('--zap-disk') |
84 | 433 | cmd.append(dev) | 463 | cmd.append(dev) |
87 | 434 | if osd_journal and os.path.exists(osd_journal): | 464 | if osd_journal: |
88 | 435 | cmd.append(osd_journal) | 465 | least_used = find_least_used_journal(osd_journal) |
89 | 466 | cmd.append(least_used) | ||
90 | 436 | else: | 467 | else: |
91 | 437 | # Just provide the device - no other options | 468 | # Just provide the device - no other options |
92 | 438 | # for older versions of ceph | 469 | # for older versions of ceph |
93 | @@ -441,6 +472,7 @@ | |||
94 | 441 | zap_disk(dev) | 472 | zap_disk(dev) |
95 | 442 | 473 | ||
96 | 443 | try: | 474 | try: |
97 | 475 | log("osdize cmd: {}".format(cmd)) | ||
98 | 444 | subprocess.check_call(cmd) | 476 | subprocess.check_call(cmd) |
99 | 445 | except subprocess.CalledProcessError as e: | 477 | except subprocess.CalledProcessError as e: |
100 | 446 | if ignore_errors: | 478 | if ignore_errors: |
101 | 447 | 479 | ||
102 | === modified file 'hooks/ceph_hooks.py' | |||
103 | --- hooks/ceph_hooks.py 2016-01-18 10:17:06 +0000 | |||
104 | +++ hooks/ceph_hooks.py 2016-01-22 15:57:27 +0000 | |||
105 | @@ -11,11 +11,13 @@ | |||
106 | 11 | import os | 11 | import os |
107 | 12 | import shutil | 12 | import shutil |
108 | 13 | import sys | 13 | import sys |
109 | 14 | import tempfile | ||
110 | 14 | 15 | ||
111 | 15 | import ceph | 16 | import ceph |
112 | 16 | from charmhelpers.core.hookenv import ( | 17 | from charmhelpers.core.hookenv import ( |
113 | 17 | log, | 18 | log, |
114 | 18 | ERROR, | 19 | ERROR, |
115 | 20 | DEBUG, | ||
116 | 19 | config, | 21 | config, |
117 | 20 | relation_ids, | 22 | relation_ids, |
118 | 21 | related_units, | 23 | related_units, |
119 | @@ -105,6 +107,30 @@ | |||
120 | 105 | 107 | ||
121 | 106 | JOURNAL_ZAPPED = '/var/lib/ceph/journal_zapped' | 108 | JOURNAL_ZAPPED = '/var/lib/ceph/journal_zapped' |
122 | 107 | 109 | ||
123 | 110 | def read_zapped_journals(): | ||
124 | 111 | if os.path.exists(JOURNAL_ZAPPED): | ||
125 | 112 | with open(JOURNAL_ZAPPED) as zapfile: | ||
126 | 113 | zapped = set( | ||
127 | 114 | filter(None, | ||
128 | 115 | [l.strip() for l in zapfile.readlines()])) | ||
129 | 116 | log("read zapped: {}".format(zapped), level=DEBUG) | ||
130 | 117 | return zapped | ||
131 | 118 | return set() | ||
132 | 119 | |||
133 | 120 | def write_zapped_journals(journal_devs): | ||
134 | 121 | tmpfh, tmpfile = tempfile.mkstemp() | ||
135 | 122 | with os.fdopen(tmpfh, 'wb') as zapfile: | ||
136 | 123 | log("write zapped: {}".format(journal_devs), | ||
137 | 124 | level=DEBUG) | ||
138 | 125 | zapfile.write('\n'.join(sorted(list(journal_devs)))) | ||
139 | 126 | os.rename(tmpfile, JOURNAL_ZAPPED) | ||
140 | 127 | |||
141 | 128 | def check_overlap(journaldevs, datadevs): | ||
142 | 129 | if not journaldevs.isdisjoint(datadevs): | ||
143 | 130 | msg = "Journal/data devices mustn't overlap; journal: {0}, data: {1}".format( | ||
144 | 131 | journaldevs, datadevs) | ||
145 | 132 | log(msg, level=ERROR) | ||
146 | 133 | raise ValueError(msg) | ||
147 | 108 | 134 | ||
148 | 109 | @hooks.hook('config-changed') | 135 | @hooks.hook('config-changed') |
149 | 110 | def config_changed(): | 136 | def config_changed(): |
150 | @@ -123,20 +149,24 @@ | |||
151 | 123 | e_mountpoint = config('ephemeral-unmount') | 149 | e_mountpoint = config('ephemeral-unmount') |
152 | 124 | if (e_mountpoint and ceph.filesystem_mounted(e_mountpoint)): | 150 | if (e_mountpoint and ceph.filesystem_mounted(e_mountpoint)): |
153 | 125 | umount(e_mountpoint) | 151 | umount(e_mountpoint) |
154 | 152 | prepare_disks_and_activate() | ||
155 | 126 | 153 | ||
162 | 127 | osd_journal = config('osd-journal') | 154 | def prepare_disks_and_activate(): |
163 | 128 | if (osd_journal and not os.path.exists(JOURNAL_ZAPPED) and | 155 | osd_journal = get_journal_devices() |
164 | 129 | os.path.exists(osd_journal)): | 156 | check_overlap(osd_journal, set(get_devices())) |
165 | 130 | ceph.zap_disk(osd_journal) | 157 | log("got journal devs: {}".format(osd_journal), level=DEBUG) |
166 | 131 | with open(JOURNAL_ZAPPED, 'w') as zapped: | 158 | already_zapped = read_zapped_journals() |
167 | 132 | zapped.write('DONE') | 159 | non_zapped = osd_journal - already_zapped |
168 | 160 | for journ in non_zapped: | ||
169 | 161 | ceph.maybe_zap_journal(journ) | ||
170 | 162 | write_zapped_journals(osd_journal) | ||
171 | 133 | 163 | ||
172 | 134 | if ceph.is_bootstrapped(): | 164 | if ceph.is_bootstrapped(): |
173 | 135 | log('ceph bootstrapped, rescanning disks') | 165 | log('ceph bootstrapped, rescanning disks') |
174 | 136 | emit_cephconf() | 166 | emit_cephconf() |
175 | 137 | for dev in get_devices(): | 167 | for dev in get_devices(): |
176 | 138 | ceph.osdize(dev, config('osd-format'), | 168 | ceph.osdize(dev, config('osd-format'), |
178 | 139 | config('osd-journal'), config('osd-reformat'), | 169 | osd_journal, config('osd-reformat'), |
179 | 140 | config('ignore-device-errors')) | 170 | config('ignore-device-errors')) |
180 | 141 | ceph.start_osds(get_devices()) | 171 | ceph.start_osds(get_devices()) |
181 | 142 | 172 | ||
182 | @@ -186,6 +216,13 @@ | |||
183 | 186 | else: | 216 | else: |
184 | 187 | return [] | 217 | return [] |
185 | 188 | 218 | ||
186 | 219 | def get_journal_devices(): | ||
187 | 220 | osd_journal = config('osd-journal') | ||
188 | 221 | if not osd_journal: | ||
189 | 222 | return set() | ||
190 | 223 | osd_journal = [l.strip() for l in config('osd-journal').split(' ')] | ||
191 | 224 | osd_journal = set(filter(os.path.exists, osd_journal)) | ||
192 | 225 | return osd_journal | ||
193 | 189 | 226 | ||
194 | 190 | @hooks.hook('mon-relation-changed', | 227 | @hooks.hook('mon-relation-changed', |
195 | 191 | 'mon-relation-departed') | 228 | 'mon-relation-departed') |
196 | @@ -195,11 +232,7 @@ | |||
197 | 195 | log('mon has provided conf- scanning disks') | 232 | log('mon has provided conf- scanning disks') |
198 | 196 | emit_cephconf() | 233 | emit_cephconf() |
199 | 197 | ceph.import_osd_bootstrap_key(bootstrap_key) | 234 | ceph.import_osd_bootstrap_key(bootstrap_key) |
205 | 198 | for dev in get_devices(): | 235 | prepare_disks_and_activate() |
201 | 199 | ceph.osdize(dev, config('osd-format'), | ||
202 | 200 | config('osd-journal'), config('osd-reformat'), | ||
203 | 201 | config('ignore-device-errors')) | ||
204 | 202 | ceph.start_osds(get_devices()) | ||
206 | 203 | else: | 236 | else: |
207 | 204 | log('mon cluster has not yet provided conf') | 237 | log('mon cluster has not yet provided conf') |
208 | 205 | 238 |
charm_unit_test #14718 ceph-osd-next for peter-sabaini mp281149
UNIT OK: passed
Build: http:// 10.245. 162.77: 8080/job/ charm_unit_ test/14718/