From 909096713dcef5dc4fdbb22a9971609554688e23 Mon Sep 17 00:00:00 2001 From: Loic Dachary Date: Sun, 8 Mar 2015 15:15:35 +0100 Subject: [PATCH] ceph-disk: more robust parted output parser In some cases, depending on the implementation or the operating system, parted --machine -- /dev/sdh print may contain empty lines. The current parsing code is fragile and highly depends on output details. Replace it with code that basically does the same sanity checks (output not empty, existence of units, existence of the dev entry) but handles the entire output instead of checking line by line. http://tracker.ceph.com/issues/10983 Fixes: #10983 Signed-off-by: Loic Dachary (cherry picked from commit f5acf6bb6a342b05897605703d7d9cb7c09714fd) --- src/ceph-disk | 41 ++++++++++++++++------------------------- 1 file changed, 16 insertions(+), 25 deletions(-) diff --git a/src/ceph-disk b/src/ceph-disk index 6bd02201bd8b7..12d52a2974801 100755 --- a/src/ceph-disk +++ b/src/ceph-disk @@ -919,6 +919,9 @@ def unmount( ########################################### +def extract_parted_partition_numbers(partitions): + numbers_as_strings = re.findall('^\d+', partitions, re.MULTILINE) + return map(int, numbers_as_strings) def get_free_partition_index(dev): """ @@ -943,31 +946,19 @@ def get_free_partition_index(dev): if not lines: raise Error('parted failed to output anything') - lines = str(lines).splitlines(True) - - # work around buggy libreadline(?) library in rhel/centos. - idiot_prefix = '\x1b\x5b\x3f\x31\x30\x33\x34\x68' - if lines[0].startswith(idiot_prefix): - lines[0] = lines[0][8:] - - if lines[0] not in ['CHS;\n', 'CYL;\n', 'BYT;\n']: - raise Error('weird parted units', lines[0]) - del lines[0] - - if not lines[0].startswith('/dev/'): - raise Error('weird parted disk entry', lines[0]) - del lines[0] - - seen = set() - for line in lines: - idx, _ = line.split(':', 1) - idx = int(idx) - seen.add(idx) - - num = 1 - while num in seen: - num += 1 - return num + if ('CHS;' not in lines and + 'CYL;' not in lines and + 'BYT;' not in lines): + raise Error('parted output expected to contain one of ' + + 'CHH; CYL; or BYT; : ' + lines) + if dev not in lines: + raise Error('parted output expected to contain ' + dev + ': ' + lines) + _, partitions = lines.split(dev) + partition_numbers = extract_parted_partition_numbers(partitions) + if partition_numbers: + return max(partition_numbers) + 1 + else: + return 1 def update_partition(action, dev, description): -- 2.39.5