1""" 2Run-time utilities 3""" 4# 5# Copyright (C) 2014 SUSE LLC 6 7 8import logging 9import os 10import re 11 12import salt.utils.files 13from salt.exceptions import CommandExecutionError 14 15log = logging.getLogger(__name__) 16 17 18def _verify_run(out, cmd=None): 19 """ 20 Crash to the log if command execution was not successful. 21 """ 22 if out.get("retcode", 0) and out["stderr"]: 23 if cmd: 24 log.debug("Command: '%s'", cmd) 25 26 log.debug("Return code: %s", out.get("retcode")) 27 log.debug("Error output:\n%s", out.get("stderr", "N/A")) 28 29 raise CommandExecutionError(out["stderr"]) 30 31 32def _get_mounts(fs_type=None): 33 """ 34 List mounted filesystems. 35 """ 36 mounts = {} 37 with salt.utils.files.fopen("/proc/mounts") as fhr: 38 for line in fhr.readlines(): 39 line = salt.utils.stringutils.to_unicode(line) 40 device, mntpnt, fstype, options, fs_freq, fs_passno = line.strip().split( 41 " " 42 ) 43 if fs_type and fstype != fs_type: 44 continue 45 if mounts.get(device) is None: 46 mounts[device] = [] 47 48 data = {"mount_point": mntpnt, "options": options.split(",")} 49 if not fs_type: 50 data["type"] = fstype 51 mounts[device].append(data) 52 return mounts 53 54 55# TODO: Due to "blkid -o export" strongly differs from system to system, this must go away in favor of _blkid() below! 56def _blkid_output(out, fs_type=None): 57 """ 58 Parse blkid output. 59 """ 60 flt = lambda data: [el for el in data if el.strip()] 61 data = {} 62 for dev_meta in flt(out.split("\n\n")): 63 dev = {} 64 for items in flt(dev_meta.strip().split("\n")): 65 key, val = items.split("=", 1) 66 dev[key.lower()] = val 67 if fs_type and dev.get("type", "") == fs_type or not fs_type: 68 if "type" in dev and fs_type: 69 dev.pop("type") 70 data[dev.pop("devname")] = dev 71 72 if fs_type: 73 mounts = _get_mounts(fs_type) 74 for device in mounts: 75 if data.get(device): 76 data[device]["mounts"] = mounts[device] 77 78 return data 79 80 81def _blkid(fs_type=None): 82 """ 83 Return available media devices. 84 85 :param fs_type: Filter only devices that are formatted by that file system. 86 """ 87 flt = lambda data: [el for el in data if el.strip()] 88 data = dict() 89 for dev_meta in flt( 90 os.popen("blkid -o full").read().split(os.linesep) 91 ): # No __salt__ around at this point. 92 dev_meta = dev_meta.strip() 93 if not dev_meta: 94 continue 95 device = dev_meta.split(" ") 96 dev_name = device.pop(0)[:-1] 97 data[dev_name] = dict() 98 for k_set in device: 99 ks_key, ks_value = [elm.replace('"', "") for elm in k_set.split("=")] 100 data[dev_name][ks_key.lower()] = ks_value 101 102 if fs_type: 103 mounts = _get_mounts(fs_type) 104 for device in mounts: 105 if data.get(device): 106 data[device]["mounts"] = mounts[device] 107 108 return data 109 110 111def _is_device(path): 112 """ 113 Return True if path is a physical device. 114 """ 115 out = __salt__["cmd.run_all"]("file -i {}".format(path)) 116 _verify_run(out) 117 118 # Always [device, mime, charset]. See (file --help) 119 return re.split(r"\s+", out["stdout"])[1][:-1] == "inode/blockdevice" 120