File 0009-Fix-overflowing-journel-partitions.patch of Package ceph.2107

From: Owen Synge <osynge@suse.com>
Date: Wed, 3 Dec 2014 12:32:34 +0100
Subject: [PATCH] Fix overflowing journel partitions.

This fixes #896406. When useing ceph-disk to create a journel parititon
in the next available partition and thier is not enough space ceph-disk
did not provide a clear error message.

Signed-off-by: Owen Synge <osynge@suse.com>
(cherry picked from commit 05a4347f745f9d648acf67e25736d8d70cdc8f80)
---
 src/ceph-disk | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 72 insertions(+), 3 deletions(-)

diff --git a/src/ceph-disk b/src/ceph-disk
index 6264d53..7d0a298 100755
--- a/src/ceph-disk
+++ b/src/ceph-disk
@@ -29,6 +29,7 @@ import stat
 import sys
 import tempfile
 import uuid
+import math
 
 """
 Prepare:
@@ -923,7 +924,7 @@ 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):
+def get_free_partition_index(dev, size='megabytes'):
     """
     Get the next free partition index on a given device.
 
@@ -960,6 +961,71 @@ def get_free_partition_index(dev):
     else:
         return 1
 
+def get_free_partition_space(dev, size='megabytes'):
+    """
+    Attempt to get the free partition space on a given device.
+
+    :param dev: the device to calculate the size
+    :param size: bytes or megabytes
+    :return: size
+
+    Finds total space and removes space for each partition.
+    Better would be to find largest free contiguous space.
+    """
+    def size_str_as_bytes(totalsize_str, tunc = False):
+        output = -1
+        found_size = float(totalsize_str[:-2])
+        if tunc:
+            found_size = math.trunc(found_size)
+        else:
+            found_size = math.ceil(found_size)
+        if totalsize_str[-2:] == "GB":
+            output = int(1024*1024*1024*found_size)
+        if totalsize_str[-2:] == "MB":
+            output = int(1024*1024*found_size)
+        return output
+    try:
+        lines = _check_output(
+            args=[
+                'parted',
+                '--machine',
+                '--',
+                dev,
+                'print',
+                ],
+            )
+    except subprocess.CalledProcessError as e:
+        print 'cannot read partition index; assume it isn\'t present\n (Error: %s)' % e
+        return 1
+
+    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])
+    # We want to truncate the full size to avoid rounding up errors.
+    size_free = size_str_as_bytes(lines[0].split(':')[1], True)
+    del lines[0]
+
+    seen = set()
+    for line in lines:
+        partused = size_str_as_bytes(line.split(':')[3])
+        size_free -= partused
+
+    dividers = {'bytes': 1, 'megabytes': 1024*1024}
+    divider = dividers.get(size, 1024*1024)  # default to megabytes
+    return size_free/divider
+
+
 
 def update_partition(action, dev, description):
      # try to make sure the kernel refreshes the table.  note
@@ -1078,6 +1144,7 @@ def prepare_journal_dev(
 
     # it is a whole disk.  create a partition!
     num = None
+    dev_size = None
     if journal == data:
         # we're sharing the disk between osd data and journal;
         # make journal be partition number 2, so it's pretty
@@ -1086,6 +1153,8 @@ def prepare_journal_dev(
             num=num,
             size=journal_size,
             )
+        # now get dev_size
+        dev_size = get_dev_size(journal)
     else:
         # sgdisk has no way for me to say "whatever is the next
         # free index number" when setting type guids etc, so we
@@ -1099,8 +1168,8 @@ def prepare_journal_dev(
             size=journal_size,
             )
         LOG.warning('OSD will not be hot-swappable if journal is not the same device as the osd data')
-
-    dev_size = get_dev_size(journal)
+        # now get dev_size
+        dev_size = get_free_partition_space(journal)
 
     if journal_size > dev_size:
         LOG.error('refusing to create journal on %s' % journal)
openSUSE Build Service is sponsored by