diff --git a/board/common/rootfs/libexec/infix/init.d/05-product b/board/common/rootfs/libexec/infix/init.d/05-product new file mode 100755 index 00000000..ce46d5fd --- /dev/null +++ b/board/common/rootfs/libexec/infix/init.d/05-product @@ -0,0 +1,22 @@ +#!/bin/sh +# Find and install any product specific files in /etc before bootstrap +ident=$(basename "$0") + +PREFIXD=/usr/share/product +PRODUCT=$(jq -r '."product-name" | ascii_downcase' /run/system.json) + +note() +{ + logger -k -p user.notice -t "$ident" "$1" +} + +DIR="$PREFIXD/$PRODUCT" +if [ -z "$PRODUCT" ] || [ ! -d "$DIR" ]; then + note "No vendor/product specific directory found, using built-in defaults." + exit 0 +fi + +note "Using vendor/product specific defaults." +for dir in "$DIR"/*; do + [ -d "$dir" ] && cp -a "$dir" / +done diff --git a/board/common/rootfs/usr/share/product/.empty b/board/common/rootfs/usr/share/product/.empty new file mode 100644 index 00000000..e69de29b diff --git a/src/confd/README.md b/src/confd/README.md index 02951ac8..94ddc022 100644 --- a/src/confd/README.md +++ b/src/confd/README.md @@ -6,6 +6,31 @@ between sysrepo and netopeer2 (NETCONF) and the UNIX system under it all. +Factory & Failure Config +------------------------ + +Infix supports both static and dynamically generated factory-config. At +boot the dynamic is always generated to `/run/confd/factory-config.gen`, +which is installed to `/etc/factory-config.cfg` and used by default, if +that file does not already exist. The same applies to the failure mode +configuration. + +The following describes how a vendor/product specific config is found +and installed into `/etc/factory-config.cfg` before the dynamic one is +installed. + + 1. `/etc/factory-config.cfg`: built into the image, e.g., r2s + 2. `/usr/share/product//etc/factory-config.cfg`, where the + `` is determined from the VPD, which is available after + `probe` has run, in `/run/system.json` as `"product-name"`. The + lower case version of the string is used + +In the second option a script running just after `probe` will in fact +`cp` the complete product specific directory to `/`, meaning any file +and directory that is writable at runtime can be overloaded with device +specific versions. + + Origin & References ------------------- diff --git a/src/confd/bin/bootstrap b/src/confd/bin/bootstrap index aebdcc75..7ab39d04 100755 --- a/src/confd/bin/bootstrap +++ b/src/confd/bin/bootstrap @@ -4,8 +4,8 @@ ######################################################################## # The system factory-config and failure-config are derived from default # settings snippets, from /usr/share/confd/factory.d, and some generated -# snippets, e.g., device unique password, hostname (based on base MAC -# address), and number of interfaces. +# snippets, e.g., hostname (based on base MAC address) and number of +# interfaces. # # The resulting factory-config is used to create the syrepo db (below) # {factory} datastore. Hence, the factory-config file must match the @@ -127,6 +127,8 @@ failure() collate "$FAILURE_GEN" "$FAILURE_CFG" "$FAILURE_D" } +# Both factory-config and failure-config are generated every boot +# regardless if there is a static /etc/factory-config.cfg or not. factory "$FACTORY_GEN" failure "$FAILURE_GEN" @@ -143,24 +145,18 @@ else fi rc=$? -sysrepoctl -z $INIT_DATA -rc=$? -sudo -u root -g wheel sysrepocfg -f json -I"$INIT_DATA" -d running -rc=$? - - -#rm $INIT_DATA - -# On first boot, install factory-config as startup-config. -chgrp wheel /cfg -chmod g+w /cfg -if [ ! -f "$STARTUP_CFG" ]; then - sysrepocfg -f json -X"$STARTUP_CFG" +chgrp wheel "$CFG_PATH_" +chmod g+w "$CFG_PATH_" +if ! sysrepoctl -z "$INIT_DATA"; then + rc=$? + logger -sik -p user.error "Failed loading factory-default datastore" +else + # Clear running-config so we can load/create startup in the next step + temp=$(mktemp) + echo "{}" > "$temp" + sysrepocfg -f json -I"$temp" -d running + rc=$? + rm "$temp" fi -# Clear running-config so we can load startup in the next step -temp=$(mktemp) -echo "{}" > $temp -sysrepocfg -f json -I$temp -d running - exit $rc diff --git a/src/confd/bin/load b/src/confd/bin/load index 1de60e88..df19130b 100755 --- a/src/confd/bin/load +++ b/src/confd/bin/load @@ -7,7 +7,6 @@ # sysrepocfg returns OK. This to be able to detect and trigger the Infix # Fail Secure Mode at boot. # -set -e banner_append() { @@ -19,6 +18,14 @@ banner_append() return 0 } +# Ensure correct ownership and permissions, in particular after factory reset +# Created by the system, writable by any user in the admin group. +perms() +{ + chown root:wheel "$1" + chmod 0660 "$1" +} + note() { logger -s -I $$ -p user.notice -t load "$*" @@ -45,8 +52,21 @@ else fi if [ ! -f "$fn" ]; then - err "No such file, $fn, aborting!" - exit 1 + case "$config" in + startup-config) + note "startup-config missing, initializing running datastore from factory-config" + sysrepocfg -C factory-default + rc=$? + note "saving factory-config to $STARTUP_CFG ..." + sysrepocfg -f json -X"$STARTUP_CFG" + perms "$STARTUP_CFG" + exit $rc + ;; + *) + err "No such file, $fn, aborting!" + exit 1 + ;; + esac fi note "Loading $config ..." @@ -82,8 +102,5 @@ note "Loaded $fn successfully." if [ "$config" = "failure-config" ]; then banner_append "ERROR: Corrupt startup-config, system has reverted to default login credentials" else - # Ensure correct ownership and permissions, in particular after factory reset - # Created by the system, writable by any user in the admin group. - chown root:wheel "$fn" - chmod 0660 "$fn" + perms "$fn" fi