summaryrefslogtreecommitdiff
path: root/cloudinit/config
diff options
context:
space:
mode:
authorHarm Weites <harm@weites.com>2013-12-06 21:25:04 +0000
committerHarm Weites <harm@weites.com>2013-12-06 21:25:04 +0000
commit53f1938a1c33b4d9e333101d1d614803373a6bc5 (patch)
tree2b5821cd905fb9034e6cb1edac6e70c7285b175b /cloudinit/config
parentee9fbafae1abfd7ba3f4bece11f722519116ca81 (diff)
downloadvyos-cloud-init-53f1938a1c33b4d9e333101d1d614803373a6bc5.tar.gz
vyos-cloud-init-53f1938a1c33b4d9e333101d1d614803373a6bc5.zip
new: FreeBSD module to support cloud-init on the FBSD10 platform. In its
current form its still missing some modules though. Supported: -SSH-keys -growpart -growfs -adduser -powerstate
Diffstat (limited to 'cloudinit/config')
-rw-r--r--cloudinit/config/cc_growpart.py40
-rw-r--r--cloudinit/config/cc_power_state_change.py32
-rw-r--r--cloudinit/config/cc_resizefs.py7
3 files changed, 69 insertions, 10 deletions
diff --git a/cloudinit/config/cc_growpart.py b/cloudinit/config/cc_growpart.py
index 0dd92a46..81de4c37 100644
--- a/cloudinit/config/cc_growpart.py
+++ b/cloudinit/config/cc_growpart.py
@@ -22,6 +22,7 @@ import os
import os.path
import re
import stat
+import sys
from cloudinit import log as logging
from cloudinit.settings import PER_ALWAYS
@@ -137,6 +138,35 @@ class ResizeGrowPart(object):
return (before, get_size(partdev))
+class ResizeGpart(object):
+ def available(self):
+ if not os.path.exists('/usr/local/sbin/gpart'):
+ return False
+ return True
+
+ def resize(self, diskdev, partnum, partdev):
+ """
+ GPT disks store metadata at the beginning (primary) and at the
+ end (secondary) of the disk. When launching an image with a
+ larger disk compared to the original image, the secondary copy
+ is lost. Thus, the metadata will be marked CORRUPT, and need to
+ be recovered.
+ """
+ try:
+ util.subp(["gpart", "recover", diskdev])
+ except util.ProcessExecutionError as e:
+ if e.exit_code != 0:
+ util.logexc(LOG, "Failed: gpart recover %s", diskdev)
+ raise ResizeFailedException(e)
+
+ before = get_size(partdev)
+ try:
+ util.subp(["gpart", "resize", "-i", partnum, diskdev])
+ except util.ProcessExecutionError as e:
+ util.logexc(LOG, "Failed: gpart resize -i %s %s", partnum, diskdev)
+ raise ResizeFailedException(e)
+
+ return (before, get_size(partdev))
def get_size(filename):
fd = os.open(filename, os.O_RDONLY)
@@ -156,6 +186,12 @@ def device_part_info(devpath):
bname = os.path.basename(rpath)
syspath = "/sys/class/block/%s" % bname
+ # FreeBSD doesn't know of sysfs so just get everything we need from
+ # the device, like /dev/vtbd0p2.
+ if sys.platform.startswith('freebsd'):
+ m = re.search('^(/dev/.+)p([0-9])$', devpath)
+ return (m.group(1), m.group(2))
+
if not os.path.exists(syspath):
raise ValueError("%s had no syspath (%s)" % (devpath, syspath))
@@ -206,7 +242,7 @@ def resize_devices(resizer, devices):
"stat of '%s' failed: %s" % (blockdev, e),))
continue
- if not stat.S_ISBLK(statret.st_mode):
+ if not stat.S_ISBLK(statret.st_mode) and not stat.S_ISCHR(statret.st_mode):
info.append((devent, RESIZE.SKIPPED,
"device '%s' not a block device" % blockdev,))
continue
@@ -281,4 +317,4 @@ def handle(_name, cfg, _cloud, log, _args):
# LP: 1212444 FIXME re-order and favor ResizeParted
#RESIZERS = (('growpart', ResizeGrowPart),)
-RESIZERS = (('growpart', ResizeGrowPart), ('parted', ResizeParted))
+RESIZERS = (('growpart', ResizeGrowPart), ('parted', ResizeParted), ('gpart', ResizeGpart))
diff --git a/cloudinit/config/cc_power_state_change.py b/cloudinit/config/cc_power_state_change.py
index e3150808..46ce5ba5 100644
--- a/cloudinit/config/cc_power_state_change.py
+++ b/cloudinit/config/cc_power_state_change.py
@@ -23,12 +23,34 @@ import errno
import os
import re
import subprocess
+import sys
import time
frequency = PER_INSTANCE
EXIT_FAIL = 254
+#
+# Returns the cmdline for the given process id.
+#
+
+def givecmdline(pid):
+ # Check if this pid still exists by sending it the harmless 0 signal.
+ try:
+ os.kill(pid, 0)
+ except OSError:
+ return None
+ else:
+ # Example output from procstat -c 16357
+ # PID COMM ARGS
+ # 1 init /bin/init --
+ if sys.platform.startswith('freebsd'):
+ (output, _err) = util.subp(['procstat', '-c', str(pid)])
+ line = output.splitlines()[1]
+ m = re.search('\d+ (\w|\.|-)+\s+(/\w.+)', line)
+ return m.group(2)
+ else:
+ return util.load_file("/proc/%s/cmdline" % pid)
def handle(_name, cfg, _cloud, log, _args):
@@ -42,8 +64,8 @@ def handle(_name, cfg, _cloud, log, _args):
return
mypid = os.getpid()
- cmdline = util.load_file("/proc/%s/cmdline" % mypid)
+ cmdline = givecmdline(mypid)
if not cmdline:
log.warn("power_state: failed to get cmdline of current process")
return
@@ -119,8 +141,6 @@ def run_after_pid_gone(pid, pidcmdline, timeout, log, func, args):
msg = None
end_time = time.time() + timeout
- cmdline_f = "/proc/%s/cmdline" % pid
-
def fatal(msg):
if log:
log.warn(msg)
@@ -134,16 +154,14 @@ def run_after_pid_gone(pid, pidcmdline, timeout, log, func, args):
break
try:
- cmdline = ""
- with open(cmdline_f) as fp:
- cmdline = fp.read()
+ cmdline = givecmdline(pid)
if cmdline != pidcmdline:
msg = "cmdline changed for %s [now: %s]" % (pid, cmdline)
break
except IOError as ioerr:
if ioerr.errno in known_errnos:
- msg = "pidfile '%s' gone [%d]" % (cmdline_f, ioerr.errno)
+ msg = "pidfile gone [%d]" % ioerr.errno
else:
fatal("IOError during wait: %s" % ioerr)
break
diff --git a/cloudinit/config/cc_resizefs.py b/cloudinit/config/cc_resizefs.py
index 56040fdd..95bc7a4e 100644
--- a/cloudinit/config/cc_resizefs.py
+++ b/cloudinit/config/cc_resizefs.py
@@ -39,6 +39,10 @@ def _resize_ext(mount_point, devpth): # pylint: disable=W0613
def _resize_xfs(mount_point, devpth): # pylint: disable=W0613
return ('xfs_growfs', devpth)
+
+def _resize_ufs(mount_point, devpth): # pylint: disable=W0613
+ return ('growfs', devpth)
+
# Do not use a dictionary as these commands should be able to be used
# for multiple filesystem types if possible, e.g. one command for
# ext2, ext3 and ext4.
@@ -46,6 +50,7 @@ RESIZE_FS_PREFIXES_CMDS = [
('btrfs', _resize_btrfs),
('ext', _resize_ext),
('xfs', _resize_xfs),
+ ('ufs', _resize_ufs),
]
NOBLOCK = "noblock"
@@ -91,7 +96,7 @@ def handle(name, cfg, _cloud, log, args):
raise exc
return
- if not stat.S_ISBLK(statret.st_mode):
+ if not stat.S_ISBLK(statret.st_mode) and not stat.S_ISCHR(statret.st_mode):
if util.is_container():
log.debug("device '%s' not a block device in container."
" cannot resize: %s" % (devpth, info))