From 3d28e0c5e7950fb60c2d2ee17f24523d0e2adfed Mon Sep 17 00:00:00 2001 From: Jason Hollis <400979+CodeBleu@users.noreply.github.com> Date: Mon, 4 Dec 2023 17:15:51 -0500 Subject: [PATCH] fix(openbsd): services & build tool * Added net/activator for `ifconfig` that is used with OpenBSD * Added sysvinit scripts for OpenBSD * Updated build-on-openbsd tool with additional dependencies and better logic --- cloudinit/net/activators.py | 28 ++++++++++++++++ cloudinit/net/ifconfig.py | 13 ++++++++ setup.py | 6 ++++ sysvinit/openbsd/cloudconfig.tmpl | 39 ++++++++++++++++++++++ sysvinit/openbsd/cloudfinal.tmpl | 37 +++++++++++++++++++++ sysvinit/openbsd/cloudinit.tmpl | 37 +++++++++++++++++++++ sysvinit/openbsd/cloudinitlocal.tmpl | 40 +++++++++++++++++++++++ tools/build-on-openbsd | 49 +++++++++++++++++++++++++--- 8 files changed, 244 insertions(+), 5 deletions(-) create mode 100644 cloudinit/net/ifconfig.py create mode 100755 sysvinit/openbsd/cloudconfig.tmpl create mode 100755 sysvinit/openbsd/cloudfinal.tmpl create mode 100755 sysvinit/openbsd/cloudinit.tmpl create mode 100755 sysvinit/openbsd/cloudinitlocal.tmpl diff --git a/cloudinit/net/activators.py b/cloudinit/net/activators.py index e69da40d371c..e6839f3ec09a 100644 --- a/cloudinit/net/activators.py +++ b/cloudinit/net/activators.py @@ -5,6 +5,7 @@ from cloudinit import subp, util from cloudinit.net.eni import available as eni_available +from cloudinit.net.ifconfig import available as ifconfig_available from cloudinit.net.netplan import available as netplan_available from cloudinit.net.network_manager import available as nm_available from cloudinit.net.network_state import NetworkState @@ -102,6 +103,31 @@ def bring_down_interface(device_name: str) -> bool: return _alter_interface(cmd, device_name) +class IfConfigActivator(NetworkActivator): + @staticmethod + def available(target: Optional[str] = None) -> bool: + """Return true if ifconfig can be used on this system.""" + return ifconfig_available(target=target) + + @staticmethod + def bring_up_interface(device_name: str) -> bool: + """Bring up interface using ifconfig up. + + Return True is successful, otherwise return False + """ + cmd = ["ifconfig", device_name, "up"] + return _alter_interface(cmd, device_name) + + @staticmethod + def bring_down_interface(device_name: str) -> bool: + """Bring up interface using ifconfig down. + + Return True is successful, otherwise return False + """ + cmd = ["ifconfig", device_name, "down"] + return _alter_interface(cmd, device_name) + + class NetworkManagerActivator(NetworkActivator): @staticmethod def available(target=None) -> bool: @@ -217,6 +243,7 @@ def bring_down_interface(device_name: str) -> bool: # version to encompass both seems overkill at this point DEFAULT_PRIORITY = [ "eni", + "ifconfig", "netplan", "network-manager", "networkd", @@ -224,6 +251,7 @@ def bring_down_interface(device_name: str) -> bool: NAME_TO_ACTIVATOR: Dict[str, Type[NetworkActivator]] = { "eni": IfUpDownActivator, + "ifconfig": IfConfigActivator, "netplan": NetplanActivator, "network-manager": NetworkManagerActivator, "networkd": NetworkdActivator, diff --git a/cloudinit/net/ifconfig.py b/cloudinit/net/ifconfig.py new file mode 100644 index 000000000000..88e3d044252b --- /dev/null +++ b/cloudinit/net/ifconfig.py @@ -0,0 +1,13 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +import logging + +from cloudinit import subp + +LOG = logging.getLogger(__name__) + + +def available(target=None): + expected = "ifconfig" + search = ["/sbin"] + return subp.which(expected, search=search, target=target) diff --git a/setup.py b/setup.py index bff183624988..e40d730e5508 100644 --- a/setup.py +++ b/setup.py @@ -132,6 +132,11 @@ def render_tmpl(template, mode=None, is_yaml=False): for f in glob("sysvinit/netbsd/*") if is_f(f) ], + "sysvinit_openbsd": lambda: [ + render_tmpl(f, mode=0o755) + for f in glob("sysvinit/openbsd/*") + if is_f(f) + ], "sysvinit_deb": lambda: [f for f in glob("sysvinit/debian/*") if is_f(f)], "sysvinit_openrc": lambda: [ f for f in glob("sysvinit/gentoo/*") if is_f(f) @@ -156,6 +161,7 @@ def render_tmpl(template, mode=None, is_yaml=False): "sysvinit": "etc/rc.d/init.d", "sysvinit_freebsd": "usr/local/etc/rc.d", "sysvinit_netbsd": "usr/local/etc/rc.d", + "sysvinit_openbsd": "etc/rc.d", "sysvinit_deb": "etc/init.d", "sysvinit_openrc": "etc/init.d", "systemd": pkg_config_read("systemd", "systemdsystemunitdir"), diff --git a/sysvinit/openbsd/cloudconfig.tmpl b/sysvinit/openbsd/cloudconfig.tmpl new file mode 100755 index 000000000000..b0b535ddbad1 --- /dev/null +++ b/sysvinit/openbsd/cloudconfig.tmpl @@ -0,0 +1,39 @@ +## template:jinja +#!/bin/ksh + +# PROVIDE: cloudconfig +# REQUIRE: cloudinit +# BEFORE: sshd + + +daemon="cloud-init" +daemon_execdir="{{prefix}}/bin" +daemon_flags="modules --mode config" +daemon_rtable=0 +daemon_timeout=1 +daemon_user=root + +. /etc/rc.d/rc.subr + +rc_bg="YES" # (undefined or "YES") +rc_usercheck="YES" # (undefined or "NO") + +rc_start() { + if test -e /etc/cloud/cloud-init.disabled; then + echo -n "cloud-init is disabled via cloud-init.disabled file." | logger -t ${daemon} + else + echo -n "Starting..." | logger -t ${daemon} + rc_exec "${daemon_execdir}/${daemon} ${daemon_flags}" + fi +} + +rc_check() { + pgrep -f "${daemon}" >/dev/null +} + +rc_stop() { + echo -n "Stopping..." | logger -t ${daemon} + pkill -f "${daemon}" >/dev/null +} + +rc_cmd "$1" diff --git a/sysvinit/openbsd/cloudfinal.tmpl b/sysvinit/openbsd/cloudfinal.tmpl new file mode 100755 index 000000000000..662a3d7e9705 --- /dev/null +++ b/sysvinit/openbsd/cloudfinal.tmpl @@ -0,0 +1,37 @@ +## template:jinja +#!/bin/ksh + +# PROVIDE: cloudfinal +# REQUIRE: LOGIN cloudconfig + +daemon="cloud-init" +daemon_execdir="{{prefix}}/bin" +daemon_flags="modules --mode final" +daemon_rtable=0 +daemon_timeout=1 +daemon_user=root + +. /etc/rc.d/rc.subr + +rc_bg="YES" # (undefined or "YES") +rc_usercheck="YES" # (undefined or "NO") + +rc_start() { + if test -e /etc/cloud/cloud-init.disabled; then + echo -n "cloud-init is disabled via cloud-init.disabled file." | logger -t ${daemon} + else + echo -n "Starting..." | logger -t ${daemon} + rc_exec "${daemon_execdir}/${daemon} ${daemon_flags}" + fi +} + +rc_check() { + pgrep -f "${daemon}" >/dev/null +} + +rc_stop() { + echo -n "Stopping..." | logger -t ${daemon} + pkill -f "${daemon}" >/dev/null +} + +rc_cmd "$1" diff --git a/sysvinit/openbsd/cloudinit.tmpl b/sysvinit/openbsd/cloudinit.tmpl new file mode 100755 index 000000000000..7b990c0825d2 --- /dev/null +++ b/sysvinit/openbsd/cloudinit.tmpl @@ -0,0 +1,37 @@ +## template:jinja +#!/bin/ksh + +# PROVIDE: cloudinit +# REQUIRE: cloudinitlocal + +daemon="cloud-init" +daemon_execdir="{{prefix}}/bin" +daemon_flags="init" +daemon_rtable=0 +daemon_timeout=1 +daemon_user=root + +. /etc/rc.d/rc.subr + +rc_bg="YES" # (undefined or "YES") +rc_usercheck="YES" # (undefined or "NO") + +rc_start() { + if test -e /etc/cloud/cloud-init.disabled; then + echo -n "cloud-init is disabled via cloud-init.disabled file." | logger -t ${daemon} + else + echo -n "Starting..." | logger -t ${daemon} + rc_exec "${daemon_execdir}/${daemon} ${daemon_flags}" + fi +} + +rc_check() { + pgrep -f "${daemon}" >/dev/null +} + +rc_stop() { + echo -n "Stopping..." | logger -t ${daemon} + pkill -f "${daemon}" >/dev/null +} + +rc_cmd "$1" diff --git a/sysvinit/openbsd/cloudinitlocal.tmpl b/sysvinit/openbsd/cloudinitlocal.tmpl new file mode 100755 index 000000000000..c019b70027d1 --- /dev/null +++ b/sysvinit/openbsd/cloudinitlocal.tmpl @@ -0,0 +1,40 @@ +## template:jinja +#!/bin/ksh + +# PROVIDE: cloudinitlocal +# REQUIRE: NETWORKING + +# After NETWORKING because we don't want staticroute to wipe +# the route set by the DHCP client toward the meta-data server. + +daemon="cloud-init" +daemon_execdir="{{prefix}}/bin" +daemon_flags="init -l" +daemon_rtable=0 +daemon_timeout=1 +daemon_user=root + +. /etc/rc.d/rc.subr + +rc_bg="YES" # (undefined or "YES") +rc_usercheck="YES" + +rc_start() { + if test -e /etc/cloud/cloud-init.disabled; then + echo -n "cloud-init is disabled via cloud-init.disabled file." | logger -t ${daemon} + else + echo -n "Starting..." | logger -t ${daemon} + rc_exec "${daemon_execdir}/${daemon} ${daemon_flags}" + fi +} + +rc_check() { + pgrep -f "${daemon}" >/dev/null +} + +rc_stop() { + echo -n "Stopping..." | logger -t ${daemon} + pkill -f "${daemon}" >/dev/null +} + +rc_cmd "$1" diff --git a/tools/build-on-openbsd b/tools/build-on-openbsd index fd038afa2d5f..48d978fc9bb6 100755 --- a/tools/build-on-openbsd +++ b/tools/build-on-openbsd @@ -2,6 +2,12 @@ fail() { echo "FAILED:" "$@" 1>&2; exit 1; } +PYTHON=${PYTHON:-python3} +if ! command -v ${PYTHON} >/dev/null 2>&1; then + echo "Please install python first." + exit 1 +fi + # Check dependencies: depschecked=/tmp/c-i.dependencieschecked pkgs=" @@ -16,12 +22,45 @@ pkgs=" py3-setuptools py3-yaml sudo-- + wget " -[ -f "$depschecked" ] || pkg_add "${pkgs}" || fail "install packages" -touch $depschecked +[ -f $depschecked ] || echo "Installing the following packages: $pkgs"; output=$(pkg_add -zI $pkgs 2>&1) + + +if echo "$output" | grep -q -e "Can't find" -e "Ambiguous"; then + echo "Failed to find or install one or more packages" + echo "Failed Package(s):" + echo "$output" + exit 1 +else + echo Successfully installed packages + touch $depschecked + + python3 setup.py build + python3 setup.py install -O1 --distro openbsd --skip-build --init-system sysvinit_openbsd -python3 setup.py build -python3 setup.py install -O1 --distro openbsd --skip-build + echo "Installation completed." + RC_LOCAL="/etc/rc.local" + RC_LOCAL_CONTENT=" +/usr/lib/cloud-init/ds-identify +wait -echo "Installation completed." +cloud-init init --local +wait + +cloud-init init +wait + +cloud-init modules --mode config +wait + +cloud-init modules --mode final +" + if ! test -e $RC_LOCAL; then + echo "export PATH=$PATH:/usr/local/sbin:/usr/local/bin" >> $RC_LOCAL + echo "$RC_LOCAL_CONTENT" >> $RC_LOCAL + elif ! grep -Fq "cloud-init" $RC_LOCAL; then + echo "$RC_LOCAL_CONTENT" >> $RC_LOCAL + fi +fi