The branch main has been updated by bapt: URL: https://cgit.FreeBSD.org/src/commit/?id=797dad91ff468a9bd6cd5d4f720eb4bbac1f454a
commit 797dad91ff468a9bd6cd5d4f720eb4bbac1f454a Author: Baptiste Daroussin <[email protected]> AuthorDate: 2026-06-05 10:05:08 +0000 Commit: Baptiste Daroussin <[email protected]> CommitDate: 2026-06-05 11:15:16 +0000 nuageinit: implement mounts support Add support for the 'mounts' cloud-config key which configures mount points by appending entries to /etc/fstab and creating the corresponding directories. --- libexec/nuageinit/nuage.lua | 48 +++++++++++++++++++++++++++++++++++- libexec/nuageinit/nuageinit | 33 +++++++++++++++++++++++++ libexec/nuageinit/nuageinit.7 | 36 +++++++++++++++++++++++++++ libexec/nuageinit/tests/nuageinit.sh | 28 +++++++++++++++++++++ 4 files changed, 144 insertions(+), 1 deletion(-) diff --git a/libexec/nuageinit/nuage.lua b/libexec/nuageinit/nuage.lua index 45e14ef0ce21..34cf8c9fc090 100644 --- a/libexec/nuageinit/nuage.lua +++ b/libexec/nuageinit/nuage.lua @@ -821,6 +821,50 @@ local function addfile(file, defer) return true end +local function add_fstab_entry(root, device, mount_point, fstype, options, dump_freq, passno) + local fstab_path = root .. "/etc/fstab" + local f = io.open(fstab_path, "a") + if not f then + warnmsg("unable to open " .. fstab_path .. " for writing") + return false + end + options = options or "rw" + dump_freq = dump_freq or 0 + passno = passno or 0 + f:write(string.format("%s\t\t%s\t\t%s\t\t%s\t\t%d\t\t%d\n", + device, mount_point, fstype, options, dump_freq, passno)) + f:close() + return true +end + +local function remove_fstab_entry(root, mount_point) + local fstab_path = root .. "/etc/fstab" + local f = io.open(fstab_path, "r") + if not f then + return + end + local lines = {} + for line in f:lines() do + local fields = {} + for field in line:gmatch("%S+") do + table.insert(fields, field) + end + if fields[2] ~= mount_point then + table.insert(lines, line) + end + end + f:close() + local nf = io.open(fstab_path, "w") + if not nf then + warnmsg("unable to open " .. fstab_path .. " for writing") + return + end + for _, line in ipairs(lines) do + nf:write(line .. "\n") + end + nf:close() +end + local n = { shell_escape = shell_escape, warn = warnmsg, @@ -844,7 +888,9 @@ local n = { upgrade_packages = upgrade_packages, addsudo = addsudo, adddoas = adddoas, - addfile = addfile + addfile = addfile, + add_fstab_entry = add_fstab_entry, + remove_fstab_entry = remove_fstab_entry, } return n diff --git a/libexec/nuageinit/nuageinit b/libexec/nuageinit/nuageinit index 9d2f3c6024c4..f56d1207cf01 100755 --- a/libexec/nuageinit/nuageinit +++ b/libexec/nuageinit/nuageinit @@ -531,6 +531,38 @@ local function disable_root(obj) end end +local function mounts(obj) + if obj.mounts == nil then return end + for _, m in ipairs(obj.mounts) do + local device, mount_point, fstype, options, dump_freq, passno + if type(m) == "table" then + if m[1] then + -- List format: [device, mount_point, fstype, options, dump_freq, passno] + device = m[1] + mount_point = m[2] + fstype = m[3] + options = m[4] + dump_freq = tonumber(m[5]) or 0 + passno = tonumber(m[6]) or 0 + else + -- Dict format + device = m.name or m.device or m.spec + mount_point = m.mount_point or m.mountpoint + fstype = m.type or m.filesystem or m.fstype + options = m.options or m.opts + dump_freq = tonumber(m.dump) or 0 + passno = tonumber(m.passno) or tonumber(m.pass_no) or 0 + end + end + if device and mount_point and fstype then + nuage.mkdir_p(root .. mount_point) + nuage.add_fstab_entry(root, device, mount_point, fstype, options, dump_freq, passno) + else + warnmsg("Invalid mount entry, skipping") + end + end +end + local function bootcmd(obj) if obj.bootcmd == nil then return end local f = nil @@ -828,6 +860,7 @@ if line == nil then -- YAML user-data elseif line == "#cloud-config" then local pre_network_calls = { + mounts, bootcmd, sethostname, manage_etc_hosts, diff --git a/libexec/nuageinit/nuageinit.7 b/libexec/nuageinit/nuageinit.7 index 66a72324f414..c2981669acb7 100644 --- a/libexec/nuageinit/nuageinit.7 +++ b/libexec/nuageinit/nuageinit.7 @@ -159,6 +159,42 @@ Defaults to Set to .Ar false to skip this behaviour. +.It Ic mounts +A list of mount points to configure. +Each entry is written to +.Pa /etc/fstab +and the mount point directory is created. +.Pp +Each entry can be specified as a list: +.Bd -literal -offset indent +[ device, mountpoint, fstype ] +.Ed +.Pp +or as an object: +.Bd -literal -offset indent +{ device: "...", mountpoint: "...", type: "...", options: "..." } +.Ed +.Pp +The following keys are recognized: +.Bl -tag -width "options" +.It device (or name, spec) +The device to mount. +.It mountpoint (or mount_point) +The mount point directory. +.It type (or fstype, filesystem) +The filesystem type. +.It options (or opts) +The mount options, defaults to +.Qq rw . +.It dump +The dump frequency for +.Xr dump 8 , +defaults to 0. +.It passno +The pass number for +.Xr fsck 8 , +defaults to 0. +.El .It Ic timezone Sets the system timezone based on the value provided. .Pp diff --git a/libexec/nuageinit/tests/nuageinit.sh b/libexec/nuageinit/tests/nuageinit.sh index ac7086183d86..11d34fcd98ea 100644 --- a/libexec/nuageinit/tests/nuageinit.sh +++ b/libexec/nuageinit/tests/nuageinit.sh @@ -34,6 +34,7 @@ atf_test_case config2_userdata_ssh_deletekeys atf_test_case config2_userdata_disable_root atf_test_case config2_userdata_bootcmd atf_test_case config2_userdata_manage_etc_hosts +atf_test_case config2_userdata_mounts atf_test_case config2_userdata_fqdn_and_hostname atf_test_case config2_userdata_write_files @@ -1113,6 +1114,32 @@ EOF atf_check -o inline:"::1\t\tlocalhost\n127.0.0.1\t\tlocalhost\n" cat etc/hosts } +config2_userdata_mounts_head() +{ + atf_set "require.user" root +} +config2_userdata_mounts_body() +{ + mkdir -p media/nuageinit + setup_test_adduser + printf "{}" > media/nuageinit/meta_data.json + cat > media/nuageinit/user_data <<EOF +#cloud-config +mounts: + - [ /dev/ada1p1, /mnt/data, ufs, rw, 0, 2 ] + - device: tmpfs + mountpoint: /mnt/tmp + fstype: tmpfs + options: "size=256M" +EOF + atf_check -o empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2 + atf_check -o match:"/dev/ada1p1.*/mnt/data.*ufs.*rw.*0.*2" cat etc/fstab + atf_check -o match:"tmpfs.*/mnt/tmp.*tmpfs.*size=256M.*0.*0" cat etc/fstab + test -d mnt/data || atf_fail "/mnt/data directory not created" + test -d mnt/tmp || atf_fail "/mnt/tmp directory not created" + true +} + config2_userdata_fqdn_and_hostname_body() { mkdir -p media/nuageinit @@ -1162,6 +1189,7 @@ atf_init_test_cases() atf_add_test_case config2_userdata_disable_root atf_add_test_case config2_userdata_bootcmd atf_add_test_case config2_userdata_manage_etc_hosts + atf_add_test_case config2_userdata_mounts atf_add_test_case config2_userdata_fqdn_and_hostname atf_add_test_case config2_userdata_write_files }
