Merge branch 'iface-type' into 'master'

WIP: Add __interface* and __bridge types

See merge request ungleich-public/cdist!838
This commit is contained in:
ssrq 2021-11-04 00:16:58 +01:00
commit e9f50fa439
50 changed files with 2032 additions and 0 deletions

View File

@ -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 <http://www.gnu.org/licenses/>.
#
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 "$@"

View File

@ -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 <http://www.gnu.org/licenses/>.
#
__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 "$@"

View File

@ -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 <http://www.gnu.org/licenses/>.
#

View File

@ -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 <dennis.camera@ssrq-sds-fds.ch>
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.

View File

@ -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 <http://www.gnu.org/licenses/>.
#
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}"

View File

@ -0,0 +1,3 @@
hotplug
onboot
stp

View File

@ -0,0 +1 @@
manual

View File

@ -0,0 +1 @@
leave

View File

@ -0,0 +1 @@
present

View File

@ -0,0 +1,7 @@
bootproto
comment
gateway
name
onchange
state
type

View File

@ -0,0 +1,3 @@
address
extra-config
port

View File

@ -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 <http://www.gnu.org/licenses/>.
#
#
# Check whether system has networkctl.
#
command -v networkctl 2>/dev/null || true

View File

@ -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 <http://www.gnu.org/licenses/>.
#
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:?}" "$@"

View File

@ -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 <http://www.gnu.org/licenses/>.
#
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:?}" "$@"

View File

@ -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 <http://www.gnu.org/licenses/>.
#
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:?}" "$@"

View File

@ -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 <http://www.gnu.org/licenses/>.
#
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

View File

@ -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 <dennis.camera@ssrq-sds-fds.ch>
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.

View File

@ -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 <http://www.gnu.org/licenses/>.
#
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}"

View File

@ -0,0 +1,2 @@
hotplug
onboot

View File

@ -0,0 +1 @@
dhcp

View File

@ -0,0 +1 @@
leave

View File

@ -0,0 +1 @@
present

View File

@ -0,0 +1,7 @@
bootproto
comment
gateway
name
onchange
state
type

View File

@ -0,0 +1,2 @@
address
extra-config

View File

@ -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 <steven-cdist at armstrong.cc>
Dennis Camera <dennis.camera at ssrq-sds-fds.ch>
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.

View File

@ -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 <http://www.gnu.org/licenses/>.
#
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 -

View File

@ -0,0 +1,2 @@
onboot
hotplug

View File

@ -0,0 +1 @@
leave

View File

@ -0,0 +1 @@
present

View File

@ -0,0 +1 @@
Ethernet

View File

@ -0,0 +1,4 @@
comment
name
onchange
state

View File

@ -0,0 +1,2 @@
bootproto
type

View File

@ -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

View File

@ -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 <dennis.camera@ssrq-sds-fds.ch>
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.

View File

@ -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 <http://www.gnu.org/licenses/>.
#
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

View File

@ -0,0 +1,4 @@
auto
hotplug
no-auto-down
no-scripts

View File

@ -0,0 +1 @@
leave

View File

@ -0,0 +1 @@
present

View File

@ -0,0 +1,5 @@
comment
name
rename
state
onchange

View File

@ -0,0 +1 @@
option

View File

@ -0,0 +1,2 @@
family
method

View File

@ -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 <http://www.gnu.org/licenses/>.
#
#
# Prints the path of networkctl if found on the target system.
#
command -v networkctl 2>/dev/null || true

View File

@ -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 <http://www.gnu.org/licenses/>.
#
#
# 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

View File

@ -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 <dennis.camera at ssrq-sds-fds.ch>
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.

View File

@ -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 <http://www.gnu.org/licenses/>.
#
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

View File

@ -0,0 +1 @@
auto-reload

View File

@ -0,0 +1 @@
present

View File

@ -0,0 +1,3 @@
name
priority
state

View File

@ -0,0 +1,2 @@
match
option