diff --git a/cdist/conf/type/__bridge/files/backends/ifcfg/manifest b/cdist/conf/type/__bridge/files/backends/ifcfg/manifest new file mode 100755 index 00000000..6f863c14 --- /dev/null +++ b/cdist/conf/type/__bridge/files/backends/ifcfg/manifest @@ -0,0 +1,108 @@ +#!/bin/sh -e +# -*- mode: sh; indent-tabs-mode: t -*- +# +# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.ch) +# +# This file is part of cdist. +# +# cdist 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. +# +# cdist 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 cdist. If not, see . +# + +os=$(cat "${__global:?}/explorer/os") + +case $os +in + (centos|redhat|scientific) + systype=redhat + ;; + (suse) + systype=suse + set -- "$@" --extra-config BRIDGE=yes + ;; + (*) + printf "Your operating system (%s) is currently not supported by %s's ifcfg backend.\n" "${os}" "${__type##*/}" >&2 + printf "Please contribute an implementation for it if you can.\n" >&2 + exit 1 + ;; +esac + +bridge_ports= # space-separated list +bridge_stp='off' + +cd "${__object:?}/parameter" +for param in * +do + case ${param} + in + (bootproto) + bootproto=$(cat "${__object:?}/parameter/bootproto") + set -- "$@" --bootproto "${bootproto}" + ;; + (hotplug) + echo '--hotplug is not (yet) supported by the ifcfg backend.' >&2 + exit 1 + ;; + (port) + case ${systype} + in + (redhat) + # TOOD + ;; + (suse) + bridge_ports=$( + while read -r _port + do + test -z "$(echo "${_port}" | tr -d 'A-Za-z0-9')" || { + printf 'Invalid bridge port name: %s\n' "${_port}" >&2 + exit 1 + } + printf ' %s' "${_port}" + done <"${__object:?}/parameter/port" + ) + bridge_ports=${bridge_ports# } + ;; + esac + ;; + (stp) + bridge_stp='on' + ;; + (onboot) + # boolean parameters + set -- "$@" --"${param}" + ;; + (*) + set -- "$@" --"${param}" "$(cat "${__object:?}/parameter/${param}")" + ;; + esac +done + +# Set bridge ports +set -- "$@" --extra-config "BRIDGE_PORTS='${bridge_ports}'" + +# Set boolean options +case $systype +in + (redhat) + set -- "$@" --extra-config "STP=${bridge_stp}" + test "${bridge_stp}" = 'on' || set -- "$@" --extra-config DELAY=0 + ;; + (suse) + set -- "$@" --extra-config "BRIDGE_STP=${bridge_stp}" + test "${bridge_stp}" = 'on' \ + || set -- "$@" --extra-config BRIDGE_FORWARDDELAY=0 + ;; +esac + +# Instantiate backend type +__interface_ifcfg "${__object_id:?}" --type Bridge "$@" diff --git a/cdist/conf/type/__bridge/files/backends/ifupdown.d/manifest b/cdist/conf/type/__bridge/files/backends/ifupdown.d/manifest new file mode 100755 index 00000000..f29b883a --- /dev/null +++ b/cdist/conf/type/__bridge/files/backends/ifupdown.d/manifest @@ -0,0 +1,98 @@ +#!/bin/sh -e +# -*- mode: sh; indent-tabs-mode: t -*- +# +# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.ch) +# +# This file is part of cdist. +# +# cdist 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. +# +# cdist 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 cdist. If not, see . +# + +__package_apt bridge-utils +export require=__package_apt/bridge-utils + +bridge_ports='none' # space-separated list +bridge_stp='off' +enable_hotplug=no + +cd "${__object:?}/parameter" +for param in * +do + case ${param} + in + (bootproto) + bootproto=$(cat "${__object:?}/parameter/bootproto") + set -- "$@" --bootproto "${bootproto}" + + case ${bootproto} + in + (manual) + # if set to manual, there is nothing to wait for… + set -- "$@" --extra-config 'bridge_maxwait 0' + ;; + esac + ;; + (hotplug) + # N.B.: This option must be equal for all configured bridges, + # or cdist will error. + # This is a limitation of the bridge-utils package. + enable_hotplug=yes + ;; + (port) + bridge_ports=$( + while read -r _port + do + test -z "$(echo "${_port}" | tr -d 'A-Za-z0-9')" || { + printf 'Invalid bridge port name: %s\n' "${_port}" >&2 + exit 1 + } + + printf ' %s' "${_port}" + done <"${__object:?}/parameter/port" + ) + bridge_ports=${bridge_ports# } + ;; + (stp) + bridge_stp='on' + ;; + (onboot) + # boolean parameters + set -- "$@" --"${param}" + ;; + (*) + set -- "$@" --"${param}" "$(cat "${__object:?}/parameter/${param}")" + ;; + esac +done + + +# Set bridge ports +set -- "$@" --extra-config "bridge_ports ${bridge_ports}" + +# Set boolean options +set -- "$@" --extra-config "bridge_stp ${bridge_stp}" +test "${bridge_stp}" = 'on' || set -- "$@" --extra-config 'bridge_fd 0' + +__key_value /etc/default/bridge-utils:BRIDGE_HOTPLUG --state present \ + --file /etc/default/bridge-utils --key BRIDGE_HOTPLUG \ + --delimiter = --exact_delimiter \ + --value "${enable_hotplug}" + + +# Instantiate backend type +if test -s "${__object:?}/stdin" +then + exec <"${__object:?}/stdin" +fi +__interface "${__object_id:?}" --type ifupdown.d "$@" diff --git a/cdist/conf/type/__bridge/gencode-remote b/cdist/conf/type/__bridge/gencode-remote new file mode 100755 index 00000000..77ad9d25 --- /dev/null +++ b/cdist/conf/type/__bridge/gencode-remote @@ -0,0 +1,20 @@ +#!/bin/sh -e +# +# 2020 Dennis Camera (dennis.camera@ssrq-sds-fds.ch) +# +# This file is part of cdist. +# +# cdist 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. +# +# cdist 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 cdist. If not, see . +# + diff --git a/cdist/conf/type/__bridge/man.rst b/cdist/conf/type/__bridge/man.rst new file mode 100644 index 00000000..bffe088b --- /dev/null +++ b/cdist/conf/type/__bridge/man.rst @@ -0,0 +1,106 @@ +cdist-type__bridge(7) +===================== + +NAME +---- +cdist-type__bridge - Manage network bridges + + +DESCRIPTION +----------- +This cdist type allows you to manage virtual Ethernet bridges on the target. +It acts as a wrapper around cdist-type__interface(7) to provide more convenient +access to bridge-specific parameters. +Only TCP/IP is supported. For other protocol stacks, use the specific types for +your OS. + + +REQUIRED PARAMETERS +------------------- +port + A port (interface) to be part of the bridge. + This parameter can be used multiple times, to add more than one port to the + bridge. + The ports should not be defined as __interfaces. + + +OPTIONAL PARAMETERS +------------------- +address + The IP address (in CIDR notation) to assign to the network interface. + Can be repeated to assign multiple IP addresses. +bootproto + The boot protocol to use. + + Acceptable values are ``dhcp``, ``static``, ``manual``. + Defaults to ``manual``. +comment + A comment to be stored in the configuration file. +extra-config + Other options to be passed to the implementation type verbatim. + Using this option makes the configuration non-portable to other backends. + If this option is used extensively, it is recommended to use the respective + backend type directly. +gateway + The default gateway to assign to this interface (optional). +name + The name of the logical network device to configure. + Defaults to ``__object_id``. +onchange + The action to perform if the interface configuration has changed. + + Available options are: + + leave (default) + Do nothing. + up + Bring the interface up if it is down. + down + Bring the interface down if it is up. + refresh + Refresh the interface (down && up). +state + ``present`` or ``absent``, defaults to ``present``. +type + The backend to use to store the interface configuration. + Default is to auto detect. + + +BOOLEAN PARAMETERS +------------------ +onboot + Bring the interface up on boot. + Otherwise, it has to be manually brought up using OS utilities + (e.g. ifup\ (8)). +hotplug + | Allow hotplugging the ports on this bridge. + | N.B.: Some backends might not support this. +stp + Enable the Spanning Tree Protocol (STP) on this bridge. + + +EXAMPLES +-------- + +.. code-block:: sh + + # Create a bridge br0 comprised of eth0 and eth1 that is brought up on boot. + __bridge br0 --onboot --port eth0 --port eth1 + + +SEE ALSO +-------- +:strong:`cdist-type__interface`\ (7) + + +AUTHORS +------- +Dennis Camera + + +COPYING +------- +Copyright \(C) 2020 Dennis Camera. 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. diff --git a/cdist/conf/type/__bridge/manifest b/cdist/conf/type/__bridge/manifest new file mode 100755 index 00000000..755a09bc --- /dev/null +++ b/cdist/conf/type/__bridge/manifest @@ -0,0 +1,54 @@ +#!/bin/sh -e +# +# 2020 Dennis Camera (dennis.camera@ssrq-sds-fds.ch) +# +# This file is part of cdist. +# +# cdist 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. +# +# cdist 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 cdist. If not, see . +# + + +os=$(cat "${__global:?}/explorer/os") + +case $os +in + (debian) + os_major=$(grep -o '^[0-9][0-9]*' "${__global:?}/explorer/os_version") + test "${os_major}" -ge 7 \ + || die 'Debian versions older than 7 (wheezy) are not supported' + + impl_type=ifupdown.d + ;; + (devuan) + impl_type=ifupdown.d + ;; + (centos|redhat|scientific|suse) + impl_type=ifcfg + ;; + (*) + printf "Your operating system (%s) is currently not supported by this type (%s)\n" "${os}" "${__type##*/}" >&2 + printf "Please contribute an implementation for it if you can.\n" >&2 + exit 1 + ;; +esac + +# Hand over to backend-specific implementation +manifest_file="${__type:?}/files/backends/${impl_type}/manifest" +test -x "${manifest_file}" || { + printf 'Unknown type: %s\n' "${impl_type}" >&2 + exit 1 +} + +# Run backend-specific script +exec "${manifest_file}" diff --git a/cdist/conf/type/__bridge/parameter/boolean b/cdist/conf/type/__bridge/parameter/boolean new file mode 100644 index 00000000..0d323712 --- /dev/null +++ b/cdist/conf/type/__bridge/parameter/boolean @@ -0,0 +1,3 @@ +hotplug +onboot +stp diff --git a/cdist/conf/type/__bridge/parameter/default/bootproto b/cdist/conf/type/__bridge/parameter/default/bootproto new file mode 100644 index 00000000..2905494b --- /dev/null +++ b/cdist/conf/type/__bridge/parameter/default/bootproto @@ -0,0 +1 @@ +manual diff --git a/cdist/conf/type/__bridge/parameter/default/onchange b/cdist/conf/type/__bridge/parameter/default/onchange new file mode 100644 index 00000000..e8f9c907 --- /dev/null +++ b/cdist/conf/type/__bridge/parameter/default/onchange @@ -0,0 +1 @@ +leave diff --git a/cdist/conf/type/__bridge/parameter/default/state b/cdist/conf/type/__bridge/parameter/default/state new file mode 100644 index 00000000..e7f6134f --- /dev/null +++ b/cdist/conf/type/__bridge/parameter/default/state @@ -0,0 +1 @@ +present diff --git a/cdist/conf/type/__bridge/parameter/optional b/cdist/conf/type/__bridge/parameter/optional new file mode 100644 index 00000000..16ae6fba --- /dev/null +++ b/cdist/conf/type/__bridge/parameter/optional @@ -0,0 +1,7 @@ +bootproto +comment +gateway +name +onchange +state +type diff --git a/cdist/conf/type/__bridge/parameter/optional_multiple b/cdist/conf/type/__bridge/parameter/optional_multiple new file mode 100644 index 00000000..d54585d1 --- /dev/null +++ b/cdist/conf/type/__bridge/parameter/optional_multiple @@ -0,0 +1,3 @@ +address +extra-config +port diff --git a/cdist/conf/type/__interface/explorer/has_networkctl b/cdist/conf/type/__interface/explorer/has_networkctl new file mode 100755 index 00000000..dd247ae8 --- /dev/null +++ b/cdist/conf/type/__interface/explorer/has_networkctl @@ -0,0 +1,24 @@ +#!/bin/sh -e +# +# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.ch) +# +# This file is part of cdist. +# +# cdist 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. +# +# cdist 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 cdist. If not, see . +# +# +# Check whether system has networkctl. +# + +command -v networkctl 2>/dev/null || true diff --git a/cdist/conf/type/__interface/files/backends/ifcfg/manifest b/cdist/conf/type/__interface/files/backends/ifcfg/manifest new file mode 100755 index 00000000..a4b6dbdf --- /dev/null +++ b/cdist/conf/type/__interface/files/backends/ifcfg/manifest @@ -0,0 +1,105 @@ +#!/bin/sh -e +# -*- mode: sh; indent-tabs-mode: t -*- +# +# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.ch) +# +# This file is part of cdist. +# +# cdist 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. +# +# cdist 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 cdist. If not, see . +# + +opt_format() { + printf '%s="%s"\n' "${1:?'option name missing'}" "${2:?'option value missing'}" +} + +opt_from_param() { + # Only first line will be read. + opt_format \ + "${1:?'option name missing'}" \ + "$(head -n 1 "${__object:?}/parameter/${2:?'parameter name missing'}")" +} + + +set -- --state "$(cat "${__object:?}/parameter/state")" --family inet + +# Boolean flags +if test -f "${__object:?}/parameter/onboot" +then + set -- "$@" --onboot +fi +if test -f "${__object:?}/parameter/hotplug" +then + set -- "$@" --hotplug +fi + + +if test -f "${__object:?}/parameter/name" +then + set -- "$@" --name "$(cat "${__object:?}/parameter/name")" +fi + + +# Generate appropriate parameters based on bootproto +bootproto=$(cat "${__object:?}/parameter/bootproto") +case $bootproto +in + (dhcp) + set -- "$@" --bootproto dhcp + ;; + (static) + set -- "$@" --bootproto static + + if test -s "${__object:?}/parameter/address" + then + while read -r _addr + do + set -- "$@" --address "${_addr}" + done <"${__object:?}/parameter/address" + unset _addr + fi + + if test -s "${__object:?}/parameter/gateway" + then + set -- "$@" --option "$(opt_from_param GATEWAY gateway)" + fi + ;; + (manual) + set -- "$@" --bootproto none + ;; + (*) + exit 1 + ;; +esac + +if test -s "${__object:?}/parameter/comment" +then + set -- "$@" --comment "$(cat "${__object:?}/parameter/comment")" +fi + +if test -s "${__object:?}/parameter/onchange" +then + set -- "$@" --onchange "$(cat "${__object:?}/parameter/onchange")" +fi + +if test -s "${__object:?}/parameter/extra-config" +then + while read -r _opt + do + set -- "$@" --option "${_opt}" + done <"${__object:?}/parameter/extra-config" + unset _opt +fi + +# Instantiate backend type +__interface_ifcfg "${__object_id:?}" "$@" diff --git a/cdist/conf/type/__interface/files/backends/ifupdown.d/manifest b/cdist/conf/type/__interface/files/backends/ifupdown.d/manifest new file mode 100755 index 00000000..bbdca8bb --- /dev/null +++ b/cdist/conf/type/__interface/files/backends/ifupdown.d/manifest @@ -0,0 +1,109 @@ +#!/bin/sh -e +# -*- mode: sh; indent-tabs-mode: t -*- +# +# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.ch) +# +# This file is part of cdist. +# +# cdist 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. +# +# cdist 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 cdist. If not, see . +# + +opt_format() { + printf '%s %s\n' "${1:?'option name missing'}" "${2:?'option value missing'}" +} + +opt_from_param() { + # Only first line will be read. + opt_format \ + "${1:?'option name missing'}" \ + "$(head -n 1 "${__object:?}/parameter/${2:?'parameter name missing'}")" +} + + +set -- --state "$(cat "${__object:?}/parameter/state")" --family inet + +# Boolean flags +if test -f "${__object:?}/parameter/onboot" +then + set -- "$@" --auto +fi +if test -f "${__object:?}/parameter/hotplug" +then + set -- "$@" --hotplug +fi + + +if test -f "${__object:?}/parameter/name" +then + set -- "$@" --name "$(cat "${__object:?}/parameter/name")" +fi + + +# Generate appropriate parameters based on bootproto +bootproto=$(cat "${__object:?}/parameter/bootproto") +case $bootproto +in + (dhcp) + set -- "$@" --method dhcp + ;; + (static) + set -- "$@" --method static + + if test -s "${__object:?}/parameter/address" + then + while read -r _value + do + set -- "$@" --option "$(opt_format address "${_value}")" + done <"${__object:?}/parameter/address" + unset _value + fi + + if test -s "${__object:?}/parameter/gateway" + then + set -- "$@" --option "$(opt_from_param gateway gateway)" + fi + ;; + (manual) + set -- "$@" --method manual + ;; + (*) + exit 1 + ;; +esac + +if test -s "${__object:?}/parameter/comment" +then + set -- "$@" --comment "$(cat "${__object:?}/parameter/comment")" +fi + +if test -s "${__object:?}/parameter/onchange" +then + set -- "$@" --onchange "$(cat "${__object:?}/parameter/onchange")" +fi + +if test -s "${__object:?}/parameter/extra-config" +then + while read -r _opt + do + set -- "$@" --option "${_opt}" + done <"${__object:?}/parameter/extra-config" + unset _opt +fi + +# Instantiate backend type +if test -s "${__object:?}/stdin" +then + exec <"${__object:?}/stdin" +fi +__interface_ifupdown.d "${__object_id:?}" "$@" diff --git a/cdist/conf/type/__interface/files/backends/systemd/manifest b/cdist/conf/type/__interface/files/backends/systemd/manifest new file mode 100755 index 00000000..2e86ee4e --- /dev/null +++ b/cdist/conf/type/__interface/files/backends/systemd/manifest @@ -0,0 +1,117 @@ +#!/bin/sh -e +# -*- mode: sh; indent-tabs-mode: t -*- +# +# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.ch) +# +# This file is part of cdist. +# +# cdist 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. +# +# cdist 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 cdist. If not, see . +# + +opt_format() { + printf '%s=%s\n' "${1:?'option name missing'}" "${2:?'option value missing'}" +} + +opt_from_param() { + # Only first line will be read. + opt_format \ + "${1:?'option name missing'}" \ + "$(head -n 1 "${__object:?}/parameter/${2:?'parameter name missing'}")" +} + + +set -- --state "$(cat "${__object:?}/parameter/state")" + +# Boolean flags +test -f "${__object:?}/parameter/onboot" || { + echo "WARNING: ${__type##*/}: The systemd backend only supports --onboot." >&2 +} +test -f "${__object:?}/parameter/hotplug" || { + echo "WARNING: ${__type##*/}: The systemd backend only supports --hotplug." >&2 +} + + +if test -f "${__object:?}/parameter/name" +then + set -- "$@" --name "$(cat "${__object:?}/parameter/name")" +fi + + +# Generate appropriate parameters based on bootproto +bootproto=$(cat "${__object:?}/parameter/bootproto") +case $bootproto +in + (dhcp*) + if test "${bootproto}" = dhcp + then + set -- "$@" --option "$(opt_format Network.DHCP yes)" + # TODO: Implement IPv6 support + # else + # set -- "$@" --option "$(opt_format Network.DHCP "${bootproto}")" + fi + ;; + (static) + set -- "$@" --option 'Network.DHCP=false' + + if test -s "${__object:?}/parameter/address" + then + while read -r _value + do + set -- "$@" --option "$(opt_format Network.Address "${_value}")" + done <"${__object:?}/parameter/address" + unset _value + fi + + if test -s "${__object:?}/parameter/gateway" + then + set -- "$@" --option "$(opt_from_param Network.Gateway gateway)" + fi + ;; + (manual) + set -- "$@" --option 'Network.DHCP=false' + ;; + (*) + exit 1 + ;; +esac + +if test -s "${__object:?}/parameter/comment" +then + set -- "$@" --option "$(opt_from_param Network.Description comment)" +fi + +case $(cat "${__object:?}/parameter/onchange") +in + (leave) + ;; + (refresh) + set -- "$@" --auto-reload + ;; + (*) + echo 'The --onchange parameter for type systemd only accepts "leave" or "refresh".' >&2 + echo 'systemd-networkd automatically reconfigures all interfaces.' >&2 + exit 1 +esac + +if test -s "${__object:?}/parameter/extra-config" +then + while read -r _opt + do + set -- "$@" --option "${_opt}" + done <"${__object:?}/parameter/extra-config" + unset _opt +fi + +# Instantiate backend type +__systemd_networkd_network "${__object_id:?}" "$@" diff --git a/cdist/conf/type/__interface/files/backends/uci/manifest b/cdist/conf/type/__interface/files/backends/uci/manifest new file mode 100755 index 00000000..21c1bd7e --- /dev/null +++ b/cdist/conf/type/__interface/files/backends/uci/manifest @@ -0,0 +1,132 @@ +#!/bin/sh -e +# -*- mode: sh; indent-tabs-mode: t -*- +# +# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.ch) +# +# This file is part of cdist. +# +# cdist 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. +# +# cdist 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 cdist. If not, see . +# + +opt_format() { + printf "%s='%s'\\n" "${1:?'option name missing'}" "${2:?'option value missing'}" +} + +opt_from_param() { + # Only first line will be read. + opt_format \ + "${1:?'option name missing'}" \ + "$(head -n 1 "${__object:?}/parameter/${2:?'parameter name missing'}")" +} + +onchange_action=$(cat "${__object:?}/parameter/onchange") +state=$(cat "${__object:?}/parameter/state") + +obj_name="network.${__object_id:?}" + +onchange_action() { + case $onchange_action + in + (refresh) + printf "ifup '%s'\n" "${__object_id:?}" + ;; + (up) + # shellcheck disable=SC2016 + echo 'isifup()(up=0; . /usr/share/libubox/jshn.sh && json_load "$(ifstatus "$1")" && json_get_var up up; return $((!up)))' + printf "isifup '%s' || ifup '%s'\n" "${__object_id:?}" "${__object_id:?}" + ;; + (down) + printf "ifdown '%s'\n" "${__object_id:?}" + ;; + (leave) + # ignore + ;; + (*) + printf 'Invalid --onchange: %s\n' "${onchange_action}" >&2 + exit 1 + ;; + esac +} + + +set -- --state "${state}" --transaction "${obj_name}" + +if test -s "${__object:?}/parameter/comment" +then + set -- "$@" --option "$(opt_from_param _comment comment)" +fi + +if test -f "${__object:?}/parameter/name" +then + set -- "$@" --option "$(opt_from_param ifname name)" +else + set -- "$@" --option "$(opt_format ifname "${__object_id:?}")" +fi + +set -- "$@" --option "$(opt_format auto "$( + ! test -f "${__object:?}/parameter/onboot"; echo $?)")" +set -- "$@" --option "$(opt_format force_link "$( + test -f "${__object:?}/parameter/hotplug"; echo $?)")" + +# Generate appropriate parameters based on bootproto +bootproto=$(cat "${__object:?}/parameter/bootproto") +case $bootproto +in + (dhcp) + set -- "$@" --option "$(opt_format proto dhcp)" + ;; + (static) + set -- "$@" --option "$(opt_format proto static)" + + if test -s "${__object:?}/parameter/address" + then + while read -r _value + do + set -- "$@" --option "$(opt_format ipaddr "${_value}")" + done <"${__object:?}/parameter/address" + unset _value + fi + + if test -s "${__object:?}/parameter/gateway" + then + set -- "$@" --option "$(opt_from_param gateway gateway)" + fi + ;; + (manual) + set -- "$@" --option "$(opt_format proto static)" + ;; + (*) + exit 1 + ;; +esac + +if test -s "${__object:?}/parameter/extra-config" +then + while read -r _opt + do + set -- "$@" --option "${_opt}" + done <"${__object:?}/parameter/extra-config" + unset _opt +fi + +# Instantiate backend type +__uci_section "${obj_name}" --type network.interface "$@" + +if test -s "${__object:?}/parameter/onchange" +then + require=__uci_commit/"${obj_name}" \ + __check_messages "interface_${__object_id:?}_onchange" \ + --pattern "^__uci_commit/network.${__object_id:?}:" \ + --execute "$(onchange_action)" +fi diff --git a/cdist/conf/type/__interface/man.rst b/cdist/conf/type/__interface/man.rst new file mode 100644 index 00000000..de71c438 --- /dev/null +++ b/cdist/conf/type/__interface/man.rst @@ -0,0 +1,90 @@ +cdist-type__interface(7) +======================== + +NAME +---- +cdist-type__interface - Manage network interfaces + + +DESCRIPTION +----------- +This cdist type allows you to manage network interfaces on the target. +It dispatches the actual work to the interface management system specific types. +Only TCP/IP is supported. For other protocol stacks, use the specific types for +your OS. + + +REQUIRED PARAMETERS +------------------- +None. + + +OPTIONAL PARAMETERS +------------------- +address + The IP address (in CIDR notation) to assign to the network interface. + Can be repeated to assign multiple IP addresses. +bootproto + The boot protocol to use. + Acceptable values are ``dhcp``, ``static``, ``manual``. + Defaults to ``dhcp``. +comment + A comment to be stored in the configuration file. +extra-config + Other options to be passed to the implementation type verbatim. + Using this option makes the configuration non-portable to other backends. + If this option is used extensively, it is recommended to use the respective + backend type directly. +gateway + The default gateway to assign to this interface (optional). +name + The name of the physical or logical network device to configure. + Defaults to ``__object_id``. +onchange + The action to perform if the interface configuration has changed. + + Available options are: + + leave (default) + Do nothing. + up + Bring the interface up if it is down. + down + Bring the interface down if it is up. + refresh + Refresh the interface (down && up). +state + ``present`` or ``absent``, defaults to ``present``. +type + The backend to use to store the interface configuration. + Default is to auto detect. + + +BOOLEAN PARAMETERS +------------------ +onboot + Whether to bring the interface up on boot +hotplug + Allow/disallow hotplug support for this interface + + +EXAMPLES +-------- + +.. code-block:: sh + + # TODO + __interface + + +AUTHORS +------- +Dennis Camera + + +COPYING +------- +Copyright \(C) 2020 Dennis Camera. 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. diff --git a/cdist/conf/type/__interface/manifest b/cdist/conf/type/__interface/manifest new file mode 100755 index 00000000..73727a2a --- /dev/null +++ b/cdist/conf/type/__interface/manifest @@ -0,0 +1,94 @@ +#!/bin/sh -e +# -*- mode: sh; indent-tabs-mode: t -*- +# +# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.ch) +# +# This file is part of cdist. +# +# cdist 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. +# +# cdist 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 cdist. If not, see . +# + +die() { echo "$*" >&2; exit 1; } +dief() { + #shellcheck disable=SC2059 + die "$(printf "$@")" +} +invalid_param() { die "$@"; } +invalid_paramf() { dief "$@"; } + + +os=$(cat "${__global:?}/explorer/os") + +# Check parameters +bootproto=$(cat "${__object:?}/parameter/bootproto") +case $bootproto +in + (dhcp) + # Check parameters + ! test -f "${__object:?}/parameter/address" \ + || invalid_param '--address is invalid for --bootproto dhcp' + ! test -f "${__object:?}/parameter/gateway" \ + || invalid_param '--gateway is invalid for --bootproto dhcp' + ;; + (static) + # TODO + ;; + (manual) + # TODO + ;; + (*) + invalid_paramf 'Unknown --bootproto: %s\n' "${bootproto}" + ;; +esac + +if test -f "${__object:?}/parameter/type" +then + impl_type=$(cat "${__object:?}/parameter/type") +else + # Guess the type based on the operating system + case $os + in + (debian) + os_major=$(grep -o '^[0-9][0-9]*' "${__global:?}/explorer/os_version") + test "${os_major}" -ge 7 \ + || die 'Debian versions older than 7 (wheezy) are not supported' + + impl_type=ifupdown.d + ;; + (devuan) + impl_type=ifupdown.d + ;; + (centos|redhat|scientific|suse) + impl_type=ifcfg + ;; + (openwrt) + impl_type=uci + ;; + (*) + if test -s "${__object:?}/explorer/has_networkctl" + then + impl_type=systemd + else + dief "Don't know how to manage interfaces on: %s\n" "${os}" + fi + ;; + esac +fi + +# Hand over to backend-specific implementation +manifest_file="${__type:?}/files/backends/${impl_type}/manifest" +test -x "${manifest_file}" || dief 'Unknown type: %s\n' "${impl_type}" + +# Run backend-specific script +exec "${manifest_file}" diff --git a/cdist/conf/type/__interface/parameter/boolean b/cdist/conf/type/__interface/parameter/boolean new file mode 100644 index 00000000..2b6d0a3b --- /dev/null +++ b/cdist/conf/type/__interface/parameter/boolean @@ -0,0 +1,2 @@ +hotplug +onboot diff --git a/cdist/conf/type/__interface/parameter/default/bootproto b/cdist/conf/type/__interface/parameter/default/bootproto new file mode 100644 index 00000000..72ab18f1 --- /dev/null +++ b/cdist/conf/type/__interface/parameter/default/bootproto @@ -0,0 +1 @@ +dhcp diff --git a/cdist/conf/type/__interface/parameter/default/onchange b/cdist/conf/type/__interface/parameter/default/onchange new file mode 100644 index 00000000..e8f9c907 --- /dev/null +++ b/cdist/conf/type/__interface/parameter/default/onchange @@ -0,0 +1 @@ +leave diff --git a/cdist/conf/type/__interface/parameter/default/state b/cdist/conf/type/__interface/parameter/default/state new file mode 100644 index 00000000..e7f6134f --- /dev/null +++ b/cdist/conf/type/__interface/parameter/default/state @@ -0,0 +1 @@ +present diff --git a/cdist/conf/type/__interface/parameter/optional b/cdist/conf/type/__interface/parameter/optional new file mode 100644 index 00000000..16ae6fba --- /dev/null +++ b/cdist/conf/type/__interface/parameter/optional @@ -0,0 +1,7 @@ +bootproto +comment +gateway +name +onchange +state +type diff --git a/cdist/conf/type/__interface/parameter/optional_multiple b/cdist/conf/type/__interface/parameter/optional_multiple new file mode 100644 index 00000000..5bb11f03 --- /dev/null +++ b/cdist/conf/type/__interface/parameter/optional_multiple @@ -0,0 +1,2 @@ +address +extra-config diff --git a/cdist/conf/type/__interface_ifcfg/man.rst b/cdist/conf/type/__interface_ifcfg/man.rst new file mode 100644 index 00000000..54fc76b7 --- /dev/null +++ b/cdist/conf/type/__interface_ifcfg/man.rst @@ -0,0 +1,72 @@ +cdist-type__interface_ifcfg(7) +=============================== + +NAME +---- +cdist-type__interface_ifcfg - Manage network interfaces using ifcfg network +scripts. + + +DESCRIPTION +----------- +This type allows to configure network interfaces using the ifcfg network scripts +on RedHat and SuSE distributions. + + +REQUIRED PARAMETERS +------------------- +bootproto + ... +type + The type of the interface, e.g. ``Ethernet``, ``Bridge``, ``Dummy``, + ``Loopback``. + Defaults to ``Ethernet``. + + +OPTIONAL PARAMETERS +------------------- +address + +comment + If supplied, the value will be inserted at the top of the configuration file + as a comment. +option + ... + Can be used multiple times. + + +BOOLEAN PARAMETERS +------------------ +onboot + +hotplug + + + +EXAMPLES +-------- + +.. code-block:: sh + + # TODO + __interface_ifcfg ... + + +SEE ALSO +-------- +:strong:`cdist-type__interface`\ (7) + + +AUTHORS +------- +Steven Armstrong +Dennis Camera + + +COPYING +------- +Copyright \(C) 2014--2020 Steven Armstrong and Dennis Camera. + +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. diff --git a/cdist/conf/type/__interface_ifcfg/manifest b/cdist/conf/type/__interface_ifcfg/manifest new file mode 100755 index 00000000..a0bc0c16 --- /dev/null +++ b/cdist/conf/type/__interface_ifcfg/manifest @@ -0,0 +1,257 @@ +#!/bin/sh -e +# +# 2014 Steven Armstrong (steven-cdist at armstrong.cc) +# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.ch) +# +# This file is part of cdist. +# +# cdist 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. +# +# cdist 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 cdist. If not, see . +# + +yesno() { test $? -eq 0 && echo yes || echo no; } +opt_format() { + printf '%s="%s"\n' "${1:?'option name missing'}" "${2:?'option value missing'}" +} +prefix2subnet() { + python3 -c 'for addr in __import__("sys").argv[1:]: print(__import__("ipaddress").ip_network(addr, strict=False).netmask)' "$@" +} +param2var() { + echo "${1:?'param name missing'}" | tr '[:lower:]-' '[:upper:]_' +} +ipversion() { + python3 -c 'for addr in __import__("sys").argv[1:]: print(__import__("ipaddress").ip_address(addr).version)' "$@" +} + +os=$(cat "${__global:?}/explorer/os") + +case $os +in + (centos|redhat|scientific) + NETWORK_SCRIPTS_DIR='/etc/sysconfig/network-scripts' + systype=redhat + ;; + (suse) + NETWORK_SCRIPTS_DIR='/etc/sysconfig/network' + systype=suse + ;; + (*) + printf "Your operating system (%s) is currently not supported by this type (%s)\n" "${os}" "${__type##*/}" >&2 + printf "Please contribute an implementation for it if you can.\n" >&2 + exit 1 + ;; +esac + +if test -s "${__object:?}/parameter/name" +then + name=$(cat "${__object:?}/parameter/name") +else + name=${__object_id:?} +fi +state_should=$(cat "${__object:?}/parameter/state") +bootproto=$(cat "${__object:?}/parameter/bootproto") +onchange=$(cat "${__object:?}/parameter/onchange") +iftype=$(cat "${__object:?}/parameter/type") + +ifcfg_file="${NETWORK_SCRIPTS_DIR:?}/ifcfg-${__object_id:?}" + + +onchange_action() { + case $onchange + in + (refresh) + printf "ifdown '%s' || true ; ifup '%s'\n" "${name}" "${name}" + ;; + (up) + printf "ifup '%s'\n" "${name}" + ;; + (down) + printf "ifdown '%s' || true\n" "${name}" + ;; + (leave) + # ignore + ;; + (*) + printf 'Invalid --onchange: %s\n' "${onchange}" >&2 + exit 1 + ;; + esac +} + + +{ + cat <<-EOF + # Created by cdist ${__type##*/} + # Do not change. Changes will be overwritten. + # + + EOF + + if test -f "${__object:?}/parameter/comment" + then + awk '{ print "# " $0 }' <"${__object:?}/parameter/comment" + echo + fi + + opt_format DEVICE "${name}" + opt_format NM_CONTROLLED no + + case $systype + in + (redhat) + opt_format TYPE "${iftype}" + + for _param in onboot hotplug + do + _key=$(param2var "${_param}") + opt_format "${_key}" "$(test -f "${__object}/parameter/${_param}" | yesno)" + done + unset _param _key + ;; + (suse) + iftype=$(echo "${iftype}" | tr '[:upper:]' '[:lower:]') + if test "${iftype}" = 'loopback' -o "${iftype}" = 'dummy' + then + # Only use INTERFACETYPE for lo/dummy. + # cf. /usr/share/YaST2/modules/NetworkInterfaces.rb + opt_format INTERFACETYPE "${iftype}" + fi + + _startmode=manual + + if test -f "${__object:?}/parameter/onboot" + then + _startmode=auto + fi + if test -f "${__object:?}/parameter/hotplug" + then + _startmode=ifplugd + fi + + opt_format STARTMODE "${_startmode}" + ;; + esac + + ignored_parameters= + + # manually_handled_parameters are handled in their own code block, not by + # the generic accumulator + manually_handled_parameters='bootproto comment extra-config hotplug name onboot onchange state' + + case $bootproto + in + (dhcp) + opt_format BOOTPROTO dhcp + ignored_parameters='address broadcast gateway' + ;; + (static|none) + opt_format BOOTPROTO none + ;; + (*) + printf 'Invalid --bootproto: %s\n' "${bootproto}" >&2 + exit 1 + ;; + esac + + _bonding_opts= + + for _param in "${__object:?}"/parameter/* + do + _key=$(param2var "${_param}") + + echo "${ignored_parameters}" | grep -q -w "${_param}" && continue + echo "${manually_handled_parameters}" | grep -q -w "${_param}" && continue + + case $_param + in + (bond-master) + opt_format SLAVE yes + opt_format MASTER "$(cat "${__object:?}/parameter/${_param}")" + ;; + (bond-*) + _key=$(echo "${_param#bond-}" | tr '-' '_') + _value=$(cat "${__object:?}/parameter/${_param}") + + if test "${_key}" = 'arp_ip_target' + then + _value=$(echo "${_value}" | awk -v RS= -v FS='\n' -v OFS=',' '$1=$1') + fi + + _bonding_opts="${_bonding_opts} $(opt_format "${_key}" "${_value}")" + ;; + (*) + case $_param + in + (address) + n=0 + case $systype + in + (redhat) + # the fucked-up config + while read -r _addr + do + if test "$(ipversion "${_addr}")" -eq 6 + then + if ! ${_ipv6_enabled:-false} + then + opt_format IPV6INIT yes + opt_format IPV6ADDR "${_addr}" + _ipv6_enabled=true + else + _ipv6_sec="${_ipv6_sec} ${_addr}" + fi + else + opt_format "IPADDR${n}" "${_addr%%/*}" + opt_format "NETMASK${n}" "$(prefix2subnet "${_addr##*/}")" + : $((n+=1)) + fi + done + + if test -n "${_ipv6_sec}" + then + opt_format IPV6ADDR_SECONDARIES "${_ipv6_sec# }" + fi + unset _ipv6_enabled _ipv6_sec + ;; + (suse) + # the sane config + while read -r _addr + do + opt_format "IPADDR${n}" "${_addr}" + : $((n+=1)) + done + ;; + esac <"${__object:?}/parameter/address" + unset n _addr + ;; + (*) + opt_format "${_key}" "$(cat "${__object:?}/parameter/${_param}")" + ;; + esac + ;; + esac + done + + if test -n "${_bonding_opts}" + then + # strip leading space + opt_format BONDING_OPTS "${_bonding_opts# }" + fi + + if test -f "${__object:?}/parameter/extra-config" + then + cat "${__object:?}/parameter/extra-config" + fi +} | __file "${ifcfg_file}" \ + --state "${state_should}" --owner root --group root --mode 0644 \ + --onchange "$(onchange_action)" --source - diff --git a/cdist/conf/type/__interface_ifcfg/parameter/boolean b/cdist/conf/type/__interface_ifcfg/parameter/boolean new file mode 100644 index 00000000..14b5e789 --- /dev/null +++ b/cdist/conf/type/__interface_ifcfg/parameter/boolean @@ -0,0 +1,2 @@ +onboot +hotplug diff --git a/cdist/conf/type/__interface_ifcfg/parameter/default/onchange b/cdist/conf/type/__interface_ifcfg/parameter/default/onchange new file mode 100644 index 00000000..e8f9c907 --- /dev/null +++ b/cdist/conf/type/__interface_ifcfg/parameter/default/onchange @@ -0,0 +1 @@ +leave diff --git a/cdist/conf/type/__interface_ifcfg/parameter/default/state b/cdist/conf/type/__interface_ifcfg/parameter/default/state new file mode 100644 index 00000000..e7f6134f --- /dev/null +++ b/cdist/conf/type/__interface_ifcfg/parameter/default/state @@ -0,0 +1 @@ +present diff --git a/cdist/conf/type/__interface_ifcfg/parameter/default/type b/cdist/conf/type/__interface_ifcfg/parameter/default/type new file mode 100644 index 00000000..8942065e --- /dev/null +++ b/cdist/conf/type/__interface_ifcfg/parameter/default/type @@ -0,0 +1 @@ +Ethernet diff --git a/cdist/conf/type/__interface_ifcfg/parameter/optional b/cdist/conf/type/__interface_ifcfg/parameter/optional new file mode 100644 index 00000000..f8e8477d --- /dev/null +++ b/cdist/conf/type/__interface_ifcfg/parameter/optional @@ -0,0 +1,4 @@ +comment +name +onchange +state diff --git a/cdist/conf/type/__interface_ifcfg/parameter/required b/cdist/conf/type/__interface_ifcfg/parameter/required new file mode 100644 index 00000000..8df5eed7 --- /dev/null +++ b/cdist/conf/type/__interface_ifcfg/parameter/required @@ -0,0 +1,2 @@ +bootproto +type diff --git a/cdist/conf/type/__interface_ifupdown.d/files/interfaces b/cdist/conf/type/__interface_ifupdown.d/files/interfaces new file mode 100644 index 00000000..084df231 --- /dev/null +++ b/cdist/conf/type/__interface_ifupdown.d/files/interfaces @@ -0,0 +1,11 @@ +# Managed by cdist +# Changes will be overwritten. + +# This file describes the network interfaces available on your system +# and how to activate them. For more information, see interfaces(5). + +source /etc/network/interfaces.d/* + +# The loopback network interface +auto lo +iface lo inet loopback diff --git a/cdist/conf/type/__interface_ifupdown.d/man.rst b/cdist/conf/type/__interface_ifupdown.d/man.rst new file mode 100644 index 00000000..205c6d64 --- /dev/null +++ b/cdist/conf/type/__interface_ifupdown.d/man.rst @@ -0,0 +1,114 @@ +cdist-type__interface_ifupdown.d(7) +=================================== + +NAME +---- +cdist-type__interface_ifupdown.d - Manage network interfaces using ifupdown +using the interfaces.d directory + + +DESCRIPTION +----------- +This space intentionally left blank. + +NOTE: Only interfaces declared by cdist are removed when using --state absent. + Moreover, the interface declaration is identified by the object_id, + not by the interface's IP address or the like. + +REQUIRED PARAMETERS +------------------- +family + The name of the address family that the interface uses. + Available options are: 'inet', 'ipx', 'inet6', 'can'. +method + The name of the method used to configure the interface. + Available options depend on the address family and are, for + inet: + 'loopback', 'static', 'manual', 'dhcp', 'bootp', 'tunnel', 'ppp', + 'wvdial', and 'ip4ll'. + ipx: + 'static', and 'dynamic'. + inet6: + 'auto', 'loopback', 'static', 'manual', 'dhcp', 'v4tunnel', '6to4'. + can: + 'static'. + + +OPTIONAL PARAMETERS +------------------- +name + The name of the logical interface to configure (usually equivalent to the + physical interface). + Defaults to __object_id. +comment + If supplied, the value will be inserted at the top of the configuration file + as a comment. + If comment is '-', what was written to stdin is used as the comment. +rename + If supplied, the given interface renaming spefication will be added to the + config file. + This option can e.g. be used to generate predictable interface names based + on the interface's MAC address. +state + Either present or absent. Defaults to present. +option + Option that is added to the generated interface configuration verbatim. + Can be used multiple times so add more than one option. +onchange + The action to perform if the interface configuration has changed. + Available options are: + leave (default) + Do nothing. + up + Bring the interface up if it is down. + down + Bring the interface down if it is up. + refresh + Refresh the interface (down && up). + + +BOOLEAN PARAMETERS +------------------ +auto + If supplied, the interface will be marked "auto" and brought up during boot. +hotplug + Allow hotplug support for this interface. + The interface will be brought up when udev detects it, this can be during + boot or later. +no-auto-down + If supplied, the interface will not be brought down by the command + "ifdown -a". +no-scripts + If supplied, scripts in '/etc/network/if-*.d/' will not be run when this + interface is brought up or down. + + +EXAMPLES +-------- + +.. code-block:: sh + + # Configure interface eth0 to use DHCP. + __interface_ifupdown.d eth0 --family inet --method dhcp + + # Rename interface with MAC 00:11:22:33:44:55 to eth1 and use DHCP. + __interface_ifupdown.d eth1 --rename mac/00:11:22:33:44:55=eth1 \ + --family inet --method dhcp + + +SEE ALSO +-------- +:strong:`interfaces`\ (5) + + +AUTHORS +------- +Dennis Camera + + +COPYING +------- +Copyright \(C) 2020 Dennis Camera. 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. diff --git a/cdist/conf/type/__interface_ifupdown.d/manifest b/cdist/conf/type/__interface_ifupdown.d/manifest new file mode 100755 index 00000000..d37bc30b --- /dev/null +++ b/cdist/conf/type/__interface_ifupdown.d/manifest @@ -0,0 +1,184 @@ +#!/bin/sh -e +# +# 2020-2021 Dennis Camera (dennis.camera@ssrq-sds-fds.ch) +# +# This file is part of cdist. +# +# cdist 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. +# +# cdist 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 cdist. If not, see . +# + +INTERFACES_FILE=/etc/network/interfaces +INTERFACES_D_PATH=/etc/network/interfaces.d + +os=$(cat "${__global}/explorer/os") + +if test -s "${__object}/parameter/name" +then + name=$(cat "${__object}/parameter/name") +else + name=$__object_id +fi +onchange_action=$(cat "${__object}/parameter/onchange") +state=$(cat "${__object}/parameter/state") + +# NOTE: No file ending is used not to break the source-directory stanza +# (if used and at least for normal interface names) +iface_file="${INTERFACES_D_PATH}/${__object_id}" + +onchange_action() { + case $onchange_action + in + (refresh) + printf "ifdown --force '%s' ; ifup '%s'\n" "${name}" "${name}" + ;; + (up) + printf "ifup '%s'\n" "${name}" + ;; + (down) + printf "ifdown --force '%s'\n" "${name}" + ;; + (leave) + # ignore + ;; + (*) + printf 'Invalid --onchange: %s\n' "${onchange_action}" >&2 + exit 1 + ;; + esac +} + + +case $os +in + (debian) + os_major=$(grep -o '^[0-9][0-9]*' "${__global}/explorer/os_version") + if test "${os_major}" -lt 7 + then + # Old versions do not support "source" + printf 'Debian versions older than 7 (wheezy) are not supported by this type (%s)\n' "${__type##*/}" >&2 + exit 1 + fi + + if test "${state}" = 'present' + then + __package ifupdown --state present + export require=__package/ifupdown + fi + ;; + (devuan) + if test "${state}" = 'present' + then + __package ifupdown --state present + export require=__package/ifupdown + fi + ;; + (*) + printf 'Your operating system (%s) is currently not supported by this type (%s)\n' "$os" "${__type##*/}" >&2 + printf "Please contribute an implementation for it if you can.\n" >&2 + exit 1 + ;; +esac + +case $state +in + (present) + if test "${IFUPDOWND_LEAVE_EXISTING_CONFIG:-0}" -eq 0 + then + # The /etc/network/interfaces file is overwritten with a basic example. + __file "${INTERFACES_FILE}" --state present --owner root --mode 0644 \ + --source "${__type}/files/interfaces" + export require="__file${INTERFACES_FILE}" + else + # If state is present and IFUPDOWND_LEAVE_EXISTING_CONFIG is set, + # ensure that the interfaces.d directory is sourced in the main + # interfaces file, being as minimally invasive as possible. + __line "${INTERFACES_FILE}:source_interfaces.d" --state present \ + --file "${INTERFACES_FILE}" \ + --before '^#?[:blank:]*(auto|no-auto-down|no-scripts|allow-|iface|mapping|rename|source|source-directory)|^#[[:blank:]]*The .* interface$' \ + --line "source ${INTERFACES_D_PATH}/*" + export require="__line${INTERFACES_FILE}:source_interfaces.d" + fi + + __directory "${INTERFACES_D_PATH}" --state pre-exists \ + --owner root --mode 0755 + export require="__directory/${INTERFACES_D_PATH}" + + # Construct interface config file + ( + cat <<-EOF + # Managed by cdist (${__type##*/}) + # Do not change. Changes will be overwritten. + + EOF + + if test -s "${__object}/parameter/comment" + then + # Prefix lines with # and append trailing empty line. + # shellcheck disable=SC2016 + { + if test "$(cat "${__object}/parameter/comment")" = '-' + then + cat "${__object}/stdin" + else + cat "${__object}/parameter/comment" + fi + } | sed -e 's/^/# /;$G' + fi + + # Put together rename line + if test -s "${__object}/parameter/rename" + then + printf 'rename %s\n' "$(cat "${__object}/parameter/rename")" + fi + + # Put together the "allow" lines (these are the line(s) usually + # preceeding the iface line in the config). + if test -f "${__object}/parameter/auto" + then + printf 'auto %s\n' "${name}" + fi + if test -f "${__object}/parameter/hotplug" + then + printf 'allow-hotplug %s\n' "${name}" + fi + if test -f "${__object}/parameter/no-auto-down" + then + printf 'no-auto-down %s\n' "${name}" + fi + if test -f "${__object}/parameter/no-scripts" + then + printf 'no-scripts %s\n' "${name}" + fi + + addrfam=$(cat "${__object}/parameter/family") + method=$(cat "${__object}/parameter/method") + printf 'iface %s %s %s\n' "${name}" "${addrfam}" "${method}" + + while read -r _opt + do + printf '\t%s\n' "${_opt}" + done <"${__object}/parameter/option" + unset _opt + ) | __file "${iface_file}" --state present --owner root --mode 0644 \ + --onchange "$(onchange_action)" --source - + ;; + (absent) + __file "${iface_file}" --state absent \ + --onchange "$(onchange_action)" + ;; + (*) + printf 'Invalid --state: %s\n' "${state}" >&2 + exit 1 + ;; +esac diff --git a/cdist/conf/type/__interface_ifupdown.d/parameter/boolean b/cdist/conf/type/__interface_ifupdown.d/parameter/boolean new file mode 100644 index 00000000..211dcf33 --- /dev/null +++ b/cdist/conf/type/__interface_ifupdown.d/parameter/boolean @@ -0,0 +1,4 @@ +auto +hotplug +no-auto-down +no-scripts diff --git a/cdist/conf/type/__interface_ifupdown.d/parameter/default/onchange b/cdist/conf/type/__interface_ifupdown.d/parameter/default/onchange new file mode 100644 index 00000000..e8f9c907 --- /dev/null +++ b/cdist/conf/type/__interface_ifupdown.d/parameter/default/onchange @@ -0,0 +1 @@ +leave diff --git a/cdist/conf/type/__interface_ifupdown.d/parameter/default/state b/cdist/conf/type/__interface_ifupdown.d/parameter/default/state new file mode 100644 index 00000000..e7f6134f --- /dev/null +++ b/cdist/conf/type/__interface_ifupdown.d/parameter/default/state @@ -0,0 +1 @@ +present diff --git a/cdist/conf/type/__interface_ifupdown.d/parameter/optional b/cdist/conf/type/__interface_ifupdown.d/parameter/optional new file mode 100644 index 00000000..70b22b74 --- /dev/null +++ b/cdist/conf/type/__interface_ifupdown.d/parameter/optional @@ -0,0 +1,5 @@ +comment +name +rename +state +onchange diff --git a/cdist/conf/type/__interface_ifupdown.d/parameter/optional_multiple b/cdist/conf/type/__interface_ifupdown.d/parameter/optional_multiple new file mode 100644 index 00000000..01925a15 --- /dev/null +++ b/cdist/conf/type/__interface_ifupdown.d/parameter/optional_multiple @@ -0,0 +1 @@ +option diff --git a/cdist/conf/type/__interface_ifupdown.d/parameter/required b/cdist/conf/type/__interface_ifupdown.d/parameter/required new file mode 100644 index 00000000..32c70451 --- /dev/null +++ b/cdist/conf/type/__interface_ifupdown.d/parameter/required @@ -0,0 +1,2 @@ +family +method diff --git a/cdist/conf/type/__systemd_networkd_network/explorer/networkctl_bin b/cdist/conf/type/__systemd_networkd_network/explorer/networkctl_bin new file mode 100755 index 00000000..e2cf8409 --- /dev/null +++ b/cdist/conf/type/__systemd_networkd_network/explorer/networkctl_bin @@ -0,0 +1,24 @@ +#!/bin/sh -e +# +# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.ch) +# +# This file is part of cdist. +# +# cdist 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. +# +# cdist 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 cdist. If not, see . +# +# +# Prints the path of networkctl if found on the target system. +# + +command -v networkctl 2>/dev/null || true diff --git a/cdist/conf/type/__systemd_networkd_network/explorer/state b/cdist/conf/type/__systemd_networkd_network/explorer/state new file mode 100755 index 00000000..6c225e4e --- /dev/null +++ b/cdist/conf/type/__systemd_networkd_network/explorer/state @@ -0,0 +1,60 @@ +#!/bin/sh -e +# +# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.ch) +# +# This file is part of cdist. +# +# cdist 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. +# +# cdist 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 cdist. If not, see . +# +# +# Check whether a configuration for the interface already exists with the same +# name already exists. +# The output will be "exists" followed by the config file path on the next line, +# or "absent" +# In case networkctl cannot be found, the output will be "error". +# + +networkctl_bin=$("${__type_explorer:?}/networkctl_bin") + +test -x "${networkctl_bin}" || { echo error; exit 0; } + +if test -f "${__object:?}/parameter/name" +then + name=$(cat "${__object:?}/parameter/name") +else + name=${__object_id:?} +fi + +if "${networkctl_bin}" --no-pager --no-legend list "${name}" >/dev/null 2>&1 +then + echo exists + + "${networkctl_bin}" --no-pager --no-legend status "${name}" \ + | awk -F ': ' -v ifname="${name}" ' + BEGIN { + # header line + getline + # · N: en... + if (index($2, ifname) != 1 || substr($2, length(ifname) + 1) !~ /^[[:blank:]]*$/) + exit + } + !$0 { exit } # skip journal lines + /^[[:blank:]]*Network File:/ { + sub(/[[:blank:]]*$/, "", $2) + print $2 + }' \ + | grep -ixvF 'n/a' || true # networkctl prints "n/a" if iface is unmanaged +else + echo absent +fi diff --git a/cdist/conf/type/__systemd_networkd_network/man.rst b/cdist/conf/type/__systemd_networkd_network/man.rst new file mode 100644 index 00000000..3cc999fe --- /dev/null +++ b/cdist/conf/type/__systemd_networkd_network/man.rst @@ -0,0 +1,69 @@ +cdist-type__systemd_networkd_network(7) +======================================= + +NAME +---- +cdist-type__systemd_networkd_network - Manage network configuration using +systemd-networkd. + + +DESCRIPTION +----------- +This space intentionally left blank. + + +REQUIRED PARAMETERS +------------------- +None. + + +OPTIONAL PARAMETERS +------------------- +match + Match directives can be used to filter the interfaces to which this + configuration applies. This paramter can be used multiple times. + The value will be copied to the [Match] section of the config file verbatim. + Defaults to: "Name={interface name}" +name + The name of the interface to configure. +option + ... +priority + The "priority" of this configuration. It is used as a prefix to the + configuration file name. + Defaults to 10. +state + Either ``present`` or ``absent``. Defaults to ``present``. + + +BOOLEAN PARAMETERS +------------------ +auto-reload + Automatically apply new config after changes have been written. + + +EXAMPLES +-------- + +.. code-block:: sh + + # TODO + __systemd_networkd_network + + +SEE ALSO +-------- +:strong:`systemd.network`\ (5) + + +AUTHORS +------- +Dennis Camera + + +COPYING +------- +Copyright \(C) 2020 Dennis Camera. 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. diff --git a/cdist/conf/type/__systemd_networkd_network/manifest b/cdist/conf/type/__systemd_networkd_network/manifest new file mode 100755 index 00000000..ab4da92e --- /dev/null +++ b/cdist/conf/type/__systemd_networkd_network/manifest @@ -0,0 +1,121 @@ +#!/bin/sh -e +# +# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.ch) +# +# This file is part of cdist. +# +# cdist 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. +# +# cdist 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 cdist. If not, see . +# + +CONFIG_FILE_PATH='/etc/systemd/network' + +networkctl_bin=$(cat "${__object:?}/explorer/networkctl_bin") + +test -n "${networkctl_bin}" || { + printf 'This system is not supported by this type (%s).' "${__type##*/}" >&2 + printf ' The networkctl tool could not be found.\n' >&2 + exit 1 +} + +{ + # shellcheck disable=SC2034 + read -r state_is + read -r config_is || true +} <"${__object:?}/explorer/state" + +if test -f "${__object:?}/parameter/name" +then + name=$(cat "${__object:?}/parameter/name") +else + name=${__object_id:?} +fi + +priority=$(cat "${__object:?}/parameter/priority") +state_should=$(cat "${__object:?}/parameter/state") + +config_file=$(printf '%s/%02u-%s.network' "${CONFIG_FILE_PATH}" "${priority}" "${__object_id:?}") + +if test -f "${__object:?}/parameter/auto-reload" +then + reload_cmd="${networkctl_bin} reload" +else + reload_cmd= +fi + +gen_conf() { + echo '[Match]' + + if test -s "${__object:?}/parameter/match" + then + cat "${__object:?}/parameter/match" + else + # By default match against the interface name + printf 'Name=%s\n' "${name}" + fi + + { + grep -e '^Network\.' "${__object:?}/parameter/option" + + grep -v -e '^\(Match\|Network\)\.' "${__object:?}/parameter/option" \ + | sort -t . -k 1 + } | while read -r _option + do + _section=${_option%%.*} + + if test "${_cur_section}" != "${_section}" + then + # new section + printf '\n[%s]\n' "${_section}" + _cur_section=$_section + fi + + echo "${_option#*.}" + done +} + + +if test -n "${config_is}" -a "${config_is}" != "${config_file}" +then + # Check if only the priority has changed! + # We cannot in all cases delete the old config file as it might be a default + # config. + if test "$(dirname "${config_file}")" = "$(dirname "${config_is}")" \ + && test "$(basename "${config_is}" | sed -e 's/^[0-9]*//')" \ + = "$(basename "${config_file}" | sed -e 's/^[0-9]*//')" + then + # Remove old config, but do not reload, yet. + # reload will be done after new config file has been written… + require="__file${config_file}" __file "${config_is}" --state absent + fi +fi + + +case $state_should +in + (present) + __directory "${CONFIG_FILE_PATH}" --state pre-exists + export require=__directory"${CONFIG_FILE_PATH}" + + gen_conf | __file "${config_file}" --state "${state_should}" \ + --owner 0 --mode 0644 --source - \ + --onchange "${reload_cmd}" + ;; + (absent) + __file "${config_file}" --state absent \ + --onchange "${reload_cmd}" + ;; + (*) + printf 'Invalid --state: %s\n' "${state_should}" + ;; +esac diff --git a/cdist/conf/type/__systemd_networkd_network/parameter/boolean b/cdist/conf/type/__systemd_networkd_network/parameter/boolean new file mode 100644 index 00000000..ae36618d --- /dev/null +++ b/cdist/conf/type/__systemd_networkd_network/parameter/boolean @@ -0,0 +1 @@ +auto-reload diff --git a/cdist/conf/type/__systemd_networkd_network/parameter/default/priority b/cdist/conf/type/__systemd_networkd_network/parameter/default/priority new file mode 100644 index 00000000..f599e28b --- /dev/null +++ b/cdist/conf/type/__systemd_networkd_network/parameter/default/priority @@ -0,0 +1 @@ +10 diff --git a/cdist/conf/type/__systemd_networkd_network/parameter/default/state b/cdist/conf/type/__systemd_networkd_network/parameter/default/state new file mode 100644 index 00000000..e7f6134f --- /dev/null +++ b/cdist/conf/type/__systemd_networkd_network/parameter/default/state @@ -0,0 +1 @@ +present diff --git a/cdist/conf/type/__systemd_networkd_network/parameter/optional b/cdist/conf/type/__systemd_networkd_network/parameter/optional new file mode 100644 index 00000000..685217c5 --- /dev/null +++ b/cdist/conf/type/__systemd_networkd_network/parameter/optional @@ -0,0 +1,3 @@ +name +priority +state diff --git a/cdist/conf/type/__systemd_networkd_network/parameter/optional_multiple b/cdist/conf/type/__systemd_networkd_network/parameter/optional_multiple new file mode 100644 index 00000000..ec20610b --- /dev/null +++ b/cdist/conf/type/__systemd_networkd_network/parameter/optional_multiple @@ -0,0 +1,2 @@ +match +option