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
This commit is contained in:
Chris Holcombe 2017-01-30 13:11:48 -08:00
parent f11843671b
commit a7f29e52ef
1 changed files with 42 additions and 12 deletions

View File

@ -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',