From a7f29e52efdf2a047306fa3d064040c97678d82d Mon Sep 17 00:00:00 2001 From: Chris Holcombe Date: Mon, 30 Jan 2017 13:11:48 -0800 Subject: [PATCH] Use libblkid instead of CLI This patch changes the get_block_uuid function around to use libblkid instead of scraping the cli. Closes-Bug: 1660240 Change-Id: Ieebf5714bceb9d41c70fc1dd0cfd17c903c3a107 --- ceph/__init__.py | 54 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 12 deletions(-) diff --git a/ceph/__init__.py b/ceph/__init__.py index db3772b..375b19e 100644 --- a/ceph/__init__.py +++ b/ceph/__init__.py @@ -11,6 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from _ctypes import POINTER, byref import ctypes import collections import json @@ -309,22 +310,52 @@ def set_hdd_read_ahead(dev_name, read_ahead_sectors=256): def get_block_uuid(block_dev): """ - This queries blkid to get the uuid for a block device. + This queries blkid to get the uuid for a block device. Note: This function + needs to be called with root priv. It will raise an error otherwise. :param block_dev: Name of the block device to query. - :return: The UUID of the device or None on Error. + :return: The UUID of the device or None on Error. Raises OSError """ try: - block_info = subprocess.check_output( - ['blkid', '-o', 'export', block_dev]) - for tag in block_info.split('\n'): - parts = tag.split('=') - if parts[0] == 'UUID': - return parts[1] - return None - except subprocess.CalledProcessError as err: - log('get_block_uuid failed with error: {}'.format(err.output), + blkid = ctypes.cdll.LoadLibrary("libblkid.so") + # Header signature + # extern int blkid_probe_lookup_value(blkid_probe pr, const char *name, + # const char **data, size_t *len); + blkid.blkid_new_probe_from_filename.argtypes = [ctypes.c_char_p] + blkid.blkid_probe_lookup_value.argtypes = [ctypes.c_void_p, + ctypes.c_char_p, + POINTER(ctypes.c_char_p), + POINTER(ctypes.c_ulong)] + except OSError as err: + log('get_block_uuid loading libblkid.so failed with error: {}'.format( + os.strerror(err.errno)), level=ERROR) + raise err + if not os.path.exists(block_dev): return None + probe = blkid.blkid_new_probe_from_filename(ctypes.c_char_p(block_dev)) + if probe < 0: + log('get_block_uuid new_probe_from_filename failed: {}'.format( + os.strerror(probe)), + level=ERROR) + raise OSError(probe, os.strerror(probe)) + result = blkid.blkid_do_probe(probe) + if result != 0: + log('get_block_uuid do_probe failed with error: {}'.format( + os.strerror(result)), + level=ERROR) + raise OSError(result, os.strerror(result)) + uuid = ctypes.c_char_p() + result = blkid.blkid_probe_lookup_value(probe, + ctypes.c_char_p( + 'UUID'.encode('ascii')), + byref(uuid), None) + if result < 0: + log('get_block_uuid lookup_value failed with error: {}'.format( + os.strerror(result)), + level=ERROR) + raise OSError(result, os.strerror(result)) + blkid.blkid_free_probe(probe) + return ctypes.string_at(uuid).decode('ascii') def check_max_sectors(save_settings_dict, @@ -1615,7 +1646,6 @@ def list_pools(service): log("rados lspools failed with error: {}".format(err.output)) raise - # A dict of valid ceph upgrade paths. Mapping is old -> new UPGRADE_PATHS = { 'firefly': 'hammer',