File: //etc/one-context.d/loc-10-network.d/netcfg-networkd
#!/usr/bin/env bash
# -------------------------------------------------------------------------- #
# Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
#
# network module implementation
#
is_network_supported()
{
command -v networkctl >/dev/null
return $?
}
configure_network()
{
gen_resolvconf
gen_network_configuration
}
stop_network()
{
systemctl stop systemd-networkd.service
}
start_network()
{
systemctl start systemd-networkd.service
# Dummy query waits until networkd is running
networkctl list &>/dev/null || :
}
reload_network()
{
# TODO: for newer systemd-networkd use
# networkctl reload && networkctl reconfigure ethX
# and fallback to service restart only if needed
systemctl restart systemd-networkd.service
# Dummy query waits until networkd is running
networkctl list &>/dev/null || :
}
#
# helper functions
#
# TODO: remove global variables and get rid off exports
#
# to satisfy shellcheck SC2154:
export os_id
export ip
export network
export mask
export cidr
export ip6
export ip6_prefix_length
export ip6_ula
export mac
export dev
export mtu
export gateway
export ip6_gateway
export method
export ip6_method
export metric
export ip6_metric
export dns
export search_domains
export external
export detach
export all_nameservers
export all_search_domains
gen_iface_conf()
{
cat <<EOT
[Network]
Address=${ip}/${cidr}
EOT
if [ -n "$dns" ]; then
for _domain in $dns; do
echo "DNS=${_domain}"
done
fi
if [ -n "$search_domains" ]; then
for _search_domain in $search_domains; do
echo "Domains=${_search_domain}"
done
fi
echo "[Route]"
if [ -n "$gateway" ]; then
echo "Gateway=${gateway}"
if [ -n "$metric" ]; then
echo "Metric=${metric}"
fi
fi
# Add static routes
if [ -n "${static_routes}" ]; then
IFS=',' read -r -a routes <<< "$static_routes"
for route in "${routes[@]}"
do
rsplit=( ${route} )
dst="${rsplit[0]}"
gw="${rsplit[2]}"
echo "[Route]"
echo "Destination=$dst"
echo "Gateway=$gw"
done
fi
# Add ONEGATE Proxy static route ip route replace 169.254.16.9 dev eth0
if missing_onegate_proxy_route; then
echo "[Route]"
echo "Destination=${onegate_host}"
echo "Scope=link"
unset onegate_proxy_route_missing
fi
echo ""
}
gen_dhcp_conf()
{
case "${dhcp_conf}" in
ipv4)
cat <<EOT
[Network]
DHCP=ipv4
EOT
;;
ipv4+auto)
cat <<EOT
[Network]
DHCP=ipv4
IPv6AcceptRA=yes
[IPv6AcceptRA]
DHCPv6Client=no
EOT
;;
ipv6)
cat <<EOT
[Network]
DHCP=ipv6
IPv6AcceptRA=yes
EOT
;;
both)
cat <<EOT
[Network]
DHCP=yes
IPv6AcceptRA=yes
EOT
;;
auto)
cat <<EOT
[Network]
DHCP=no
IPv6AcceptRA=yes
[IPv6AcceptRA]
DHCPv6Client=no
EOT
;;
esac
cat <<EOT
[Network]
IPv6PrivacyExtensions=no
EOT
echo ""
}
gen_alias_conf()
{
cat <<EOT
[Address]
Address=${ip}/${cidr}
EOT
echo ""
}
gen_iface6_conf()
{
cat <<EOT
[Network]
Address=${ip6}/${ip6_prefix_length:-64}
EOT
echo "IPv6AcceptRA=false"
if [ -n "$dns" ]; then
for _domain in $dns; do
echo "DNS=${_domain}"
done
fi
if [ -n "$search_domains" ]; then
for _search_domain in $search_domains; do
echo "Domains=${_search_domain}"
done
fi
cat <<EOT
[Route]
EOT
if [ -n "$ip6_gateway" ]; then
echo "Gateway=${ip6_gateway}"
if [ -n "$ip6_metric" ]; then
echo "Metric=${ip6_metric}"
fi
fi
if [ -n "$ip6_ula" ]; then
cat <<EOT
[Network]
Address=${ip6_ula}/64
EOT
fi
echo ""
}
gen_alias6_conf()
{
cat <<EOT
[Address]
Address=${ip6}/${ip6_prefix_length:-64}
EOT
echo ""
}
gen_ipv6_disable()
{
cat <<EOT
[Network]
LinkLocalAddressing=no
IPv6AcceptRA=no
EOT
echo ""
}
# arg: <interface>
is_networkd_iface_managed()
(
_managed=$(LANG=C networkctl list -al --no-pager --no-legend | \
awk -v dev="$1" '{if ($2 == dev) print $NF;}' | \
tr '[:upper:]' '[:lower:]')
case "${_managed}" in
''|unmanaged)
return 1
;;
esac
return 0
)
gen_network_configuration()
{
_context_interfaces=$(get_context_interfaces)
_networkd_version=$(networkctl --version | head -1 | awk '{print $2}')
if [ -n "$_networkd_version" ]; then
# put some dummy low version if not detected
_networkd_version="100"
fi
for _iface in $_context_interfaces; do
setup_iface_vars "$_iface"
skip_interface && continue
# NOTE: This is needed to workaround issue with the networkd metrics.
#
# When attaching new NIC from the same vnet on a running system then
# the networkd will assign some metric to the prefix route of the first
# NIC but leave out metric for the same prefix route of the new NIC.
#
# What happens is that outgoing packets on this subnet will now always
# use the second NIC even while the incoming packets were targeted for
# the IP on the first NIC - the result is a broken connection.
#
# This occurs at least with systemd/networkd version 248, which is on
# Cent OS 8 for example.
if [ $_networkd_version -le 250 ]; then
if is_networkd_iface_managed "${dev}" ; then
# networkctl up/down is not on ubuntu <21.04
networkctl down "$dev" 2>/dev/null || true
# this is still necessary to really unconfigure the interface
ip addr flush "$dev"
fi
fi
{
cat <<EOT
# Generated by one-context
[Match]
Name=${dev}
EOT
if [ -n "${mtu}" ]; then
cat <<EOT
[Link]
MTUBytes=${mtu}
## Supported since Debian 10, Ubuntu 18.04, CentOS 8
# [Network]
# IPv6MTUBytes=${mtu}
EOT
fi
dhcp_conf=''
case "${method}" in
''|static)
[ -n "${ip}" ] && gen_iface_conf
;;
dhcp)
dhcp_conf='ipv4'
;;
esac
case "${ip6_method}" in
''|static)
[ -n "${ip6}" ] && gen_iface6_conf
;;
auto)
if [ -n "${dhcp_conf}" ] ; then
dhcp_conf='ipv4+auto'
else
dhcp_conf='auto'
fi
;;
dhcp)
if [ -n "${dhcp_conf}" ] ; then
dhcp_conf='both'
else
dhcp_conf='ipv6'
fi
;;
disable)
gen_ipv6_disable
;;
esac
[ -n "${dhcp_conf}" ] && gen_dhcp_conf
_aliases=$(get_interface_alias "$_iface")
for _nic_alias in $_aliases ; do
setup_ipadr_vars "$_nic_alias"
setup_ip6adr_vars "$_nic_alias"
setup_alias_vars "$_nic_alias"
if [ -z "${detach}" ]; then
if ! is_true "${external}" ; then
[ -n "${ip}" ] && gen_alias_conf
[ -n "${ip6}" ] && gen_alias6_conf
fi
fi
done
} > "/etc/systemd/network/${dev}.network"
done
}