summaryrefslogtreecommitdiff
path: root/cloudinit/util.py
diff options
context:
space:
mode:
Diffstat (limited to 'cloudinit/util.py')
-rw-r--r--cloudinit/util.py124
1 files changed, 120 insertions, 4 deletions
diff --git a/cloudinit/util.py b/cloudinit/util.py
index e5c6f4ea..709d5cca 100644
--- a/cloudinit/util.py
+++ b/cloudinit/util.py
@@ -404,10 +404,9 @@ def get_cfg_option_list(yobj, key, default=None):
return []
val = yobj[key]
if isinstance(val, (list)):
- # Should we ensure they are all strings??
- cval = [str(v) for v in val]
+ cval = [v for v in val]
return cval
- if not isinstance(val, (str, basestring)):
+ if not isinstance(val, (basestring)):
val = str(val)
return [val]
@@ -1519,7 +1518,7 @@ def get_proc_env(pid):
fn = os.path.join("/proc/", str(pid), "environ")
try:
contents = load_file(fn)
- toks = contents.split("\0")
+ toks = contents.split("\x00")
for tok in toks:
if tok == "":
continue
@@ -1541,3 +1540,120 @@ def keyval_str_to_dict(kvstring):
val = True
ret[key] = val
return ret
+
+
+def is_partition(device):
+ if device.startswith("/dev/"):
+ device = device[5:]
+
+ return os.path.isfile("/sys/class/block/%s/partition" % device)
+
+
+def expand_package_list(version_fmt, pkgs):
+ # we will accept tuples, lists of tuples, or just plain lists
+ if not isinstance(pkgs, list):
+ pkgs = [pkgs]
+
+ pkglist = []
+ for pkg in pkgs:
+ if isinstance(pkg, basestring):
+ pkglist.append(pkg)
+ continue
+
+ if isinstance(pkg, (tuple, list)):
+ if len(pkg) < 1 or len(pkg) > 2:
+ raise RuntimeError("Invalid package & version tuple.")
+
+ if len(pkg) == 2 and pkg[1]:
+ pkglist.append(version_fmt % tuple(pkg))
+ continue
+
+ pkglist.append(pkg[0])
+
+ else:
+ raise RuntimeError("Invalid package type.")
+
+ return pkglist
+
+
+def get_mount_info(path, log=LOG):
+ # Use /proc/$$/mountinfo to find the device where path is mounted.
+ # This is done because with a btrfs filesystem using os.stat(path)
+ # does not return the ID of the device.
+ #
+ # Here, / has a device of 18 (decimal).
+ #
+ # $ stat /
+ # File: '/'
+ # Size: 234 Blocks: 0 IO Block: 4096 directory
+ # Device: 12h/18d Inode: 256 Links: 1
+ # Access: (0755/drwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root)
+ # Access: 2013-01-13 07:31:04.358011255 +0000
+ # Modify: 2013-01-13 18:48:25.930011255 +0000
+ # Change: 2013-01-13 18:48:25.930011255 +0000
+ # Birth: -
+ #
+ # Find where / is mounted:
+ #
+ # $ mount | grep ' / '
+ # /dev/vda1 on / type btrfs (rw,subvol=@,compress=lzo)
+ #
+ # And the device ID for /dev/vda1 is not 18:
+ #
+ # $ ls -l /dev/vda1
+ # brw-rw---- 1 root disk 253, 1 Jan 13 08:29 /dev/vda1
+ #
+ # So use /proc/$$/mountinfo to find the device underlying the
+ # input path.
+ path_elements = [e for e in path.split('/') if e]
+ devpth = None
+ fs_type = None
+ match_mount_point = None
+ match_mount_point_elements = None
+ mountinfo_path = '/proc/%s/mountinfo' % os.getpid()
+ for line in load_file(mountinfo_path).splitlines():
+ parts = line.split()
+
+ mount_point = parts[4]
+ mount_point_elements = [e for e in mount_point.split('/') if e]
+
+ # Ignore mounts deeper than the path in question.
+ if len(mount_point_elements) > len(path_elements):
+ continue
+
+ # Ignore mounts where the common path is not the same.
+ l = min(len(mount_point_elements), len(path_elements))
+ if mount_point_elements[0:l] != path_elements[0:l]:
+ continue
+
+ # Ignore mount points higher than an already seen mount
+ # point.
+ if (match_mount_point_elements is not None and
+ len(match_mount_point_elements) > len(mount_point_elements)):
+ continue
+
+ # Find the '-' which terminates a list of optional columns to
+ # find the filesystem type and the path to the device. See
+ # man 5 proc for the format of this file.
+ try:
+ i = parts.index('-')
+ except ValueError:
+ log.debug("Did not find column named '-' in %s",
+ mountinfo_path)
+ return None
+
+ # Get the path to the device.
+ try:
+ fs_type = parts[i + 1]
+ devpth = parts[i + 2]
+ except IndexError:
+ log.debug("Too few columns in %s after '-' column", mountinfo_path)
+ return None
+
+ match_mount_point = mount_point
+ match_mount_point_elements = mount_point_elements
+
+ if devpth and fs_type and match_mount_point:
+ return (devpth, fs_type, match_mount_point)
+ else:
+ return None