summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2020-10-07 10:24:24 +0300
committerLars Wirzenius <liw@liw.fi>2020-10-07 11:14:00 +0300
commiteb6b53f818f7bf73ce8b37c16264df4884094c1e (patch)
tree4aa574f6c2b9a3b8f64c0522f45a50d92725425c
parent458538055bf09428d706c7bd7b17c8a0d63d44ad (diff)
downloadvmdb2-eb6b53f818f7bf73ce8b37c16264df4884094c1e.tar.gz
feat: add new plugin to resize rootfs upon boot
-rw-r--r--NEWS3
-rw-r--r--pc.vmdb10
-rw-r--r--vmdb/plugins/resize.mdwn24
-rw-r--r--vmdb/plugins/resize_plugin.py116
-rw-r--r--without-tests1
5 files changed, 152 insertions, 2 deletions
diff --git a/NEWS b/NEWS
index 4747448..62b6ff8 100644
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,9 @@ Version 0.19+git, not yet released
* All use of the Python `cliapp` library has been dropped from vmdb2 now.
+* New step `resize-rootfs` adds a systemd service to resize the root
+ file system to fit the actual drive on boot.
+
Version 0.19, released 2020-09-16
-----------------------------------------------------------------------------
diff --git a/pc.vmdb b/pc.vmdb
index f6d44e0..906d9b1 100644
--- a/pc.vmdb
+++ b/pc.vmdb
@@ -11,7 +11,7 @@ steps:
- mkpart: primary
device: "{{ output }}"
start: 0%
- end: 100%
+ end: 50%
tag: /
- kpartx: "{{ output }}"
@@ -40,10 +40,16 @@ steps:
- chroot: /
shell: |
echo pc > /etc/hostname
- apt -y install python
+ apt -y install python parted
- fstab: /
+ - chroot: /
+ shell: |
+ sed -i 's,^root:[^:]*:,root::,' /etc/passwd
+
+ - resize-rootfs: /
+
- grub: bios
tag: /
quiet: false
diff --git a/vmdb/plugins/resize.mdwn b/vmdb/plugins/resize.mdwn
new file mode 100644
index 0000000..4097f1e
--- /dev/null
+++ b/vmdb/plugins/resize.mdwn
@@ -0,0 +1,24 @@
+Step: rezize-rootfs
+-----------------------------------------------------------------------------
+
+Configure the system on the image so that it automatically resizes
+itself to fill the actual disk, upon first boot. For this to work, the
+root file system MUST be the last partition on the image.
+
+Also, the image MUST have the `parted` package installed for the
+`partprobe` command.
+
+Step keys:
+
+* `resize-rootfs` &mdash; REQUIRED; value MUST be the tag for the root
+ filesystem.
+
+This is based on reading the changes by Peter Lawler to the
+[image-specs](https://salsa.debian.org/raspi-team/image-specs.git)
+repository to do the same thing.
+
+Example:
+
+~~~yaml
+- resize-rootfs: root
+~~~
diff --git a/vmdb/plugins/resize_plugin.py b/vmdb/plugins/resize_plugin.py
new file mode 100644
index 0000000..d3efbad
--- /dev/null
+++ b/vmdb/plugins/resize_plugin.py
@@ -0,0 +1,116 @@
+# Copyright 2020 Lars Wirzenius, Peter Lawler
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# =*= License: GPL-3+ =*=
+
+
+import os
+
+import vmdb
+
+
+SCRIPT = """\
+#!/bin/sh
+
+rootpart="$(findmnt -n -o SOURCE /)"
+rootdev="/dev/$(lsblk -no pkname "$rootpart")"
+partno="$(lsblk -n --list "$rootpart" | wc -l)"
+
+flock $rootdev sfdisk -f $rootdev -N "$partno" <<EOF
+,+
+EOF
+
+sleep 5
+
+udevadm settle
+
+sleep 5
+
+flock $rootdev partprobe $rootdev
+
+mount -o remount,rw $rootpart
+
+resize2fs -f $rootpart
+
+exit 0
+"""
+
+SERVICE = """\
+[Unit]
+Description=resize root file system
+Before=local-fs-pre.target
+DefaultDependencies=no
+
+[Service]
+Type=oneshot
+TimeoutSec=infinity
+ExecStart=/usr/sbin/resize-rootfs
+ExecStart=/bin/systemctl --no-reload disable %n
+
+[Install]
+RequiredBy=local-fs-pre.target
+"""
+
+
+class ResizeRootfsPlugin(vmdb.Plugin):
+ def enable(self):
+ self.app.step_runners.add(ResizeRootfsStepRunner())
+
+
+class ResizeRootfsStepRunner(vmdb.StepRunnerInterface):
+ def get_key_spec(self):
+ return {"resize-rootfs": str}
+
+ def run(self, values, settings, state):
+ tag = values["resize-rootfs"]
+ root = state.tags.get_builder_mount_point(tag)
+
+ partprobe = self.relative(root, "/sbin/parted")
+ if not os.path.exists(partprobe):
+ raise Exception("partprobe is not installed on image, can't resize")
+
+ script_path = "/usr/sbin/resize-rootfs"
+ service_path = "/etc/systemd/system/resize-rootfs.service"
+ requires_path = "/etc/systemd/system/systemd-remount-fs.service.requires/"
+
+ # Install the script that actually does the resizing.
+ self.install(SCRIPT, root, script_path, 0o755)
+
+ # Install the systemd service file to invoke the script at boot.
+ self.install(SERVICE, root, service_path, 0o644)
+
+ # Tell systemd to run the script at the right time. This corresponds to
+ # "systemctl enable".
+ self.mkdir(root, "etc/systemd/system/systemd-remount-fs.service.requires")
+ self.symlink(root, service_path, requires_path)
+
+ def relative(self, root, pathname):
+ return os.path.join(root, "./" + pathname)
+
+ def install(self, content, root, filename, mode):
+ filename = self.relative(root, filename)
+ with open(filename, "w") as f:
+ f.write(content)
+ os.chmod(filename, mode)
+
+ def mkdir(self, root, pathname):
+ pathname = self.relative(root, pathname)
+ os.makedirs(pathname, exist_ok=True)
+
+ def symlink(self, root, linkto, linkname):
+ linkname = self.relative(root, linkname)
+ basename = os.path.basename(linkto)
+ linkname = os.path.join(linkname, basename)
+ os.symlink(linkto, linkname)
diff --git a/without-tests b/without-tests
index 8821505..49079d0 100644
--- a/without-tests
+++ b/without-tests
@@ -22,6 +22,7 @@ vmdb/plugins/mklabel_plugin.py
vmdb/plugins/mkpart_plugin.py
vmdb/plugins/mount_plugin.py
vmdb/plugins/qemudebootstrap_plugin.py
+vmdb/plugins/resize_plugin.py
vmdb/plugins/shell_plugin.py
vmdb/plugins/unpack_rootfs_plugin.py
vmdb/plugins/vgcreate_plugin.py