summaryrefslogtreecommitdiff
path: root/cloudinit/util.py
diff options
context:
space:
mode:
Diffstat (limited to 'cloudinit/util.py')
-rw-r--r--cloudinit/util.py149
1 files changed, 135 insertions, 14 deletions
diff --git a/cloudinit/util.py b/cloudinit/util.py
index e6489648..c37f0316 100644
--- a/cloudinit/util.py
+++ b/cloudinit/util.py
@@ -32,6 +32,7 @@ import re
import socket
import sys
import time
+import tempfile
import traceback
import urlparse
@@ -515,30 +516,70 @@ def dos2unix(string):
return(string.replace('\r\n', '\n'))
-def islxc():
- # is this host running lxc?
+def is_container():
+ # is this code running in a container of some sort
+
+ for helper in ('running-in-container', 'lxc-is-container'):
+ try:
+ # try to run a helper program. if it returns true
+ # then we're inside a container. otherwise, no
+ sp = subprocess.Popen(helper, stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ sp.communicate(None)
+ return(sp.returncode == 0)
+ except OSError as e:
+ if e.errno != errno.ENOENT:
+ raise
+
+ # this code is largely from the logic in
+ # ubuntu's /etc/init/container-detect.conf
try:
- with open("/proc/1/cgroup") as f:
- if f.read() == "/":
- return True
+ # Detect old-style libvirt
+ # Detect OpenVZ containers
+ pid1env = get_proc_env(1)
+ if "container" in pid1env:
+ return True
+
+ if "LIBVIRT_LXC_UUID" in pid1env:
+ return True
+
except IOError as e:
if e.errno != errno.ENOENT:
- raise
+ pass
+
+ # Detect OpenVZ containers
+ if os.path.isdir("/proc/vz") and not os.path.isdir("/proc/bc"):
+ return True
try:
- # try to run a program named 'lxc-is-container'. if it returns true,
- # then we're inside a container. otherwise, no
- sp = subprocess.Popen(['lxc-is-container'], stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- sp.communicate(None)
- return(sp.returncode == 0)
- except OSError as e:
+ # Detect Vserver containers
+ with open("/proc/self/status") as fp:
+ lines = fp.read().splitlines()
+ for line in lines:
+ if line.startswith("VxID:"):
+ (_key, val) = line.strip().split(":", 1)
+ if val != "0":
+ return True
+ except IOError as e:
if e.errno != errno.ENOENT:
- raise
+ pass
return False
+def get_proc_env(pid):
+ # return the environment in a dict that a given process id was started with
+ env = {}
+ with open("/proc/%s/environ" % pid) as fp:
+ toks = fp.read().split("\0")
+ for tok in toks:
+ if tok == "":
+ continue
+ (name, val) = tok.split("=", 1)
+ env[name] = val
+ return env
+
+
def get_hostname_fqdn(cfg, cloud):
# return the hostname and fqdn from 'cfg'. If not found in cfg,
# then fall back to data from cloud
@@ -630,3 +671,83 @@ def close_stdin():
return
with open(os.devnull) as fp:
os.dup2(fp.fileno(), sys.stdin.fileno())
+
+
+def find_devs_with(criteria):
+ """
+ find devices matching given criteria (via blkid)
+ criteria can be *one* of:
+ TYPE=<filesystem>
+ LABEL=<label>
+ UUID=<uuid>
+ """
+ try:
+ (out, _err) = subp(['blkid', '-t%s' % criteria, '-odevice'])
+ except subprocess.CalledProcessError:
+ return([])
+ return(str(out).splitlines())
+
+
+class mountFailedError(Exception):
+ pass
+
+
+def mount_callback_umount(device, callback, data=None):
+ """
+ mount the device, call method 'callback' passing the directory
+ in which it was mounted, then unmount. Return whatever 'callback'
+ returned. If data != None, also pass data to callback.
+ """
+
+ def _cleanup(umount, tmpd):
+ if umount:
+ try:
+ subp(["umount", '-l', umount])
+ except subprocess.CalledProcessError:
+ raise
+ if tmpd:
+ os.rmdir(tmpd)
+
+ # go through mounts to see if it was already mounted
+ fp = open("/proc/mounts")
+ mounts = fp.readlines()
+ fp.close()
+
+ tmpd = None
+
+ mounted = {}
+ for mpline in mounts:
+ (dev, mp, fstype, _opts, _freq, _passno) = mpline.split()
+ mp = mp.replace("\\040", " ")
+ mounted[dev] = (dev, fstype, mp, False)
+
+ umount = False
+ if device in mounted:
+ mountpoint = "%s/" % mounted[device][2]
+ else:
+ tmpd = tempfile.mkdtemp()
+
+ mountcmd = ["mount", "-o", "ro", device, tmpd]
+
+ try:
+ (_out, _err) = subp(mountcmd)
+ umount = tmpd
+ except subprocess.CalledProcessError as exc:
+ _cleanup(umount, tmpd)
+ raise mountFailedError(exc.output[1])
+
+ mountpoint = "%s/" % tmpd
+
+ try:
+ if data == None:
+ ret = callback(mountpoint)
+ else:
+ ret = callback(mountpoint, data)
+
+ except Exception as exc:
+ _cleanup(umount, tmpd)
+ raise exc
+
+ _cleanup(umount, tmpd)
+
+ return(ret)