summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Holcombe <xfactor973@gmail.com>2017-04-07 18:01:19 -0700
committerChris Holcombe <xfactor973@gmail.com>2017-04-25 08:29:26 -0700
commit573bad86dc6919737d0b953f894fb7d2bce5ee9e (patch)
treed64fd6f99b142cc535a30ad0a2279ccfdb6987d7
parentb483fa2668e5190ffe803e7d06ab781510c9b317 (diff)
Zap Journals
The is_osd_disk code assumes that the first partition is the osd journal. That might not always be the case. This patch makes that function more general by searching all partitions on a disk. Change-Id: I4239ae498b9b6d2d97551d61d1a4f2981f72b88a
Notes
Notes (review): Code-Review+1: Billy Olsen <billy.olsen@gmail.com> Code-Review+2: Chris MacNaughton <chris.macnaughton@canonical.com> Workflow+1: Chris MacNaughton <chris.macnaughton@canonical.com> Verified+2: Jenkins Submitted-by: Jenkins Submitted-at: Thu, 27 Apr 2017 06:11:29 +0000 Reviewed-on: https://review.openstack.org/454928 Project: openstack/charms.ceph Branch: refs/heads/master
-rw-r--r--ceph/__init__.py89
-rw-r--r--unit_tests/partx_output2
-rw-r--r--unit_tests/test_ceph.py17
3 files changed, 93 insertions, 15 deletions
diff --git a/ceph/__init__.py b/ceph/__init__.py
index c30bfd5..01ae4f7 100644
--- a/ceph/__init__.py
+++ b/ceph/__init__.py
@@ -117,6 +117,42 @@ NETWORK_ADAPTER_SYSCTLS = {
117} 117}
118 118
119 119
120class Partition(object):
121 def __init__(self, name, number, size, start, end, sectors, uuid):
122 """
123 A block device partition
124 :param name: Name of block device
125 :param number: Partition number
126 :param size: Capacity of the device
127 :param start: Starting block
128 :param end: Ending block
129 :param sectors: Number of blocks
130 :param uuid: UUID of the partition
131 """
132 self.name = name,
133 self.number = number
134 self.size = size
135 self.start = start
136 self.end = end
137 self.sectors = sectors
138 self.uuid = uuid
139
140 def __str__(self):
141 return "number: {} start: {} end: {} sectors: {} size: {} " \
142 "name: {} uuid: {}".format(self.number, self.start,
143 self.end,
144 self.sectors, self.size,
145 self.name, self.uuid)
146
147 def __eq__(self, other):
148 if isinstance(other, self.__class__):
149 return self.__dict__ == other.__dict__
150 return False
151
152 def __ne__(self, other):
153 return not self.__eq__(other)
154
155
120def unmounted_disks(): 156def unmounted_disks():
121 """List of unmounted block devices on the current host.""" 157 """List of unmounted block devices on the current host."""
122 disks = [] 158 disks = []
@@ -759,9 +795,12 @@ DISK_FORMATS = [
759] 795]
760 796
761CEPH_PARTITIONS = [ 797CEPH_PARTITIONS = [
798 '89C57F98-2FE5-4DC0-89C1-5EC00CEFF2BE', # ceph encrypted disk in creation
799 '45B0969E-9B03-4F30-B4C6-5EC00CEFF106', # ceph encrypted journal
762 '4FBD7E29-9D25-41B8-AFD0-5EC00CEFF05D', # ceph encrypted osd data 800 '4FBD7E29-9D25-41B8-AFD0-5EC00CEFF05D', # ceph encrypted osd data
763 '4FBD7E29-9D25-41B8-AFD0-062C0CEFF05D', # ceph osd data 801 '4FBD7E29-9D25-41B8-AFD0-062C0CEFF05D', # ceph osd data
764 '45B0969E-9B03-4F30-B4C6-B4B80CEFF106', # ceph osd journal 802 '45B0969E-9B03-4F30-B4C6-B4B80CEFF106', # ceph osd journal
803 '89C57F98-2FE5-4DC0-89C1-F3AD0CEFF2BE', # ceph disk in creation
765] 804]
766 805
767 806
@@ -872,17 +911,48 @@ def replace_osd(dead_osd_number,
872 log('replace_osd failed with error: ' + e.output) 911 log('replace_osd failed with error: ' + e.output)
873 912
874 913
875def is_osd_disk(dev): 914def get_partition_list(dev):
915 """
916 Lists the partitions of a block device
917 :param dev: Path to a block device. ex: /dev/sda
918 :return: :raise: Returns a list of Partition objects.
919 Raises CalledProcessException if lsblk fails
920 """
921 partitions_list = []
876 try: 922 try:
877 info = check_output(['sgdisk', '-i', '1', dev]) 923 partitions = get_partitions(dev)
878 info = info.split("\n") # IGNORE:E1103 924 # For each line of output
879 for line in info: 925 for partition in partitions:
880 for ptype in CEPH_PARTITIONS: 926 parts = partition.split()
881 sig = 'Partition GUID code: {}'.format(ptype) 927 partitions_list.append(
882 if line.startswith(sig): 928 Partition(number=parts[0],
883 return True 929 start=parts[1],
930 end=parts[2],
931 sectors=parts[3],
932 size=parts[4],
933 name=parts[5],
934 uuid=parts[6])
935 )
936 return partitions_list
884 except subprocess.CalledProcessError: 937 except subprocess.CalledProcessError:
885 pass 938 raise
939
940
941def is_osd_disk(dev):
942 partitions = get_partition_list(dev)
943 for partition in partitions:
944 try:
945 info = check_output(['sgdisk', '-i', partition.number, dev])
946 info = info.split("\n") # IGNORE:E1103
947 for line in info:
948 for ptype in CEPH_PARTITIONS:
949 sig = 'Partition GUID code: {}'.format(ptype)
950 if line.startswith(sig):
951 return True
952 except subprocess.CalledProcessError as e:
953 log("sgdisk inspection of partition {} on {} failed with "
954 "error: {}. Skipping".format(partition.minor, dev, e.message),
955 level=ERROR)
886 return False 956 return False
887 957
888 958
@@ -1923,7 +1993,6 @@ def dirs_need_ownership_update(service):
1923 # All child directories had the expected ownership 1993 # All child directories had the expected ownership
1924 return False 1994 return False
1925 1995
1926
1927# A dict of valid ceph upgrade paths. Mapping is old -> new 1996# A dict of valid ceph upgrade paths. Mapping is old -> new
1928UPGRADE_PATHS = { 1997UPGRADE_PATHS = {
1929 'firefly': 'hammer', 1998 'firefly': 'hammer',
diff --git a/unit_tests/partx_output b/unit_tests/partx_output
new file mode 100644
index 0000000..9964245
--- /dev/null
+++ b/unit_tests/partx_output
@@ -0,0 +1,2 @@
11 2099200 8377310 6278111 3G ceph\x20data 6e99ac59-1aa3-4812-abd7-9c886a151dd4
22 2048 2099199 2097152 1G ceph\x20journal 0333f202-256c-4867-a85c-3e3c92abd461
diff --git a/unit_tests/test_ceph.py b/unit_tests/test_ceph.py
index ec9f64a..0fa9f81 100644
--- a/unit_tests/test_ceph.py
+++ b/unit_tests/test_ceph.py
@@ -153,17 +153,17 @@ class CephTestCase(unittest.TestCase):
153 153
154 def test_parse_key_with_caps_existing_key(self): 154 def test_parse_key_with_caps_existing_key(self):
155 expected = "AQCm7aVYQFXXFhAAj0WIeqcag88DKOvY4UKR/g==" 155 expected = "AQCm7aVYQFXXFhAAj0WIeqcag88DKOvY4UKR/g=="
156 with_caps = "[client.osd-upgrade]\n"\ 156 with_caps = "[client.osd-upgrade]\n" \
157 " key = AQCm7aVYQFXXFhAAj0WIeqcag88DKOvY4UKR/g==\n"\ 157 " key = AQCm7aVYQFXXFhAAj0WIeqcag88DKOvY4UKR/g==\n" \
158 " caps mon = \"allow command \"config-key\";" 158 " caps mon = \"allow command \"config-key\";"
159 key = ceph.parse_key(with_caps) 159 key = ceph.parse_key(with_caps)
160 print("key: {}".format(key)) 160 print("key: {}".format(key))
161 self.assertEqual(key, expected) 161 self.assertEqual(key, expected)
162 162
163 def test_parse_key_without_caps(self): 163 def test_parse_key_without_caps(self):
164 expected = "AQCm7aVYQFXXFhAAj0WIeqcag88DKOvY4UKR/g==" 164 expected = "AQCm7aVYQFXXFhAAj0WIeqcag88DKOvY4UKR/g=="
165 without_caps = "[client.osd-upgrade]\n"\ 165 without_caps = "[client.osd-upgrade]\n" \
166 " key = AQCm7aVYQFXXFhAAj0WIeqcag88DKOvY4UKR/g==" 166 " key = AQCm7aVYQFXXFhAAj0WIeqcag88DKOvY4UKR/g=="
167 key = ceph.parse_key(without_caps) 167 key = ceph.parse_key(without_caps)
168 print("key: {}".format(key)) 168 print("key: {}".format(key))
169 self.assertEqual(key, expected) 169 self.assertEqual(key, expected)
@@ -193,6 +193,13 @@ class CephTestCase(unittest.TestCase):
193 devices = ceph.unmounted_disks() 193 devices = ceph.unmounted_disks()
194 self.assertEqual(devices, []) 194 self.assertEqual(devices, [])
195 195
196 @mock.patch.object(ceph, 'check_output')
197 def test_get_partition_list(self, output):
198 with open('unit_tests/partx_output', 'r') as partx_out:
199 output.return_value = partx_out.read()
200 partition_list = ceph.get_partition_list('/dev/xvdb')
201 self.assertEqual(len(partition_list), 2)
202
196 203
197class CephVersionTestCase(unittest.TestCase): 204class CephVersionTestCase(unittest.TestCase):
198 @mock.patch.object(ceph, 'get_os_codename_install_source') 205 @mock.patch.object(ceph, 'get_os_codename_install_source')