diff --git a/.github/workflows/21-pr-check-format.yml b/.github/workflows/21-pr-check-format.yml index 9fb9063e2cb..afe4f25208b 100644 --- a/.github/workflows/21-pr-check-format.yml +++ b/.github/workflows/21-pr-check-format.yml @@ -13,11 +13,11 @@ defaults: shell: sh -ex {0} jobs: - check_format: + check_linters: strategy: fail-fast: false matrix: - env: [ruff, mypy, pylint, black, isort] + env: [check_format] name: Check ${{ matrix.env }} runs-on: ubuntu-latest env: @@ -30,6 +30,7 @@ jobs: run: | sudo DEBIAN_FRONTEND=noninteractive apt-get -qy update sudo DEBIAN_FRONTEND=noninteractive apt-get -qy install tox + sudo snap install shfmt - name: Print version run: python3 --version @@ -39,20 +40,12 @@ jobs: # matrix env: not to be confused w/environment variables or testenv TOXENV: ${{ matrix.env }} run: tox - schema-format: - strategy: - fail-fast: false - name: Check json format - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - name: Test format + - name: Formatting check failed + if: failure() run: | - tools/check_json_format.sh cloudinit/config/schemas/schema-cloud-config-v1.json - tools/check_json_format.sh cloudinit/config/schemas/schema-network-config-v1.json - tools/check_json_format.sh cloudinit/config/schemas/versions.schema.cloud-config.json + echo "[31mResolve formatting errors with `tox -e do_format` (requires shfmt to format shell).\e[0m" + echo "[31mFor mypy and pylint failures see the warnings above.\e[0m" doc: strategy: diff --git a/Makefile b/Makefile index a425420c9d8..7e2ef07211e 100644 --- a/Makefile +++ b/Makefile @@ -9,40 +9,18 @@ distro ?= redhat GENERATOR_F=./systemd/cloud-init-generator DS_IDENTIFY=./tools/ds-identify -BENCHMARK=./tools/benchmark.sh all: check check: test -style-check: lint - -lint: - @$(CWD)/tools/run-lint - unittest: clean_pyc $(PYTHON) -m pytest -v tests/unittests cloudinit render-template: $(PYTHON) ./tools/render-template --variant=$(VARIANT) $(FILE) $(subst .tmpl,,$(FILE)) -# from systemd-generator(7) regarding generators: -# "We do recommend C code however, since generators are executed -# synchronously and hence delay the entire boot if they are slow." -# -# Our generator is a shell script. Make it easy to measure the -# generator. This should be monitored for performance regressions -benchmark-generator: FILE=$(GENERATOR_F).tmpl -benchmark-generator: VARIANT="benchmark" -benchmark-generator: export ITER=$(NUM_ITER) -benchmark-generator: render-template - $(BENCHMARK) $(GENERATOR_F) - -benchmark-ds-identify: export ITER=$(NUM_ITER) -benchmark-ds-identify: - $(BENCHMARK) $(DS_IDENTIFY) - ci-deps-ubuntu: @$(PYTHON) $(CWD)/tools/read-dependencies --distro ubuntu --test-distro @@ -103,13 +81,6 @@ deb-src: doc: tox -e doc -fmt: - tox -e do_format && tox -e check_format - -fmt-tip: - tox -e do_format_tip && tox -e check_format_tip - - -.PHONY: all check test lint clean rpm srpm deb deb-src clean_pyc -.PHONY: unittest style-check render-template benchmark-generator +.PHONY: all check test clean rpm srpm deb deb-src clean_pyc +.PHONY: unittest render-template .PHONY: clean_pytest clean_packaging clean_release doc diff --git a/tools/Z99-cloud-locale-test.sh b/tools/Z99-cloud-locale-test.sh index e051fa7369a..9ba7716532f 100644 --- a/tools/Z99-cloud-locale-test.sh +++ b/tools/Z99-cloud-locale-test.sh @@ -6,12 +6,12 @@ # (c) 2012, Canonical Group, Ltd. # # This file is part of cloud-init. See LICENSE file for license information. - + # Purpose: Detect invalid locale settings and inform the user # of how to fix them. locale_warn() { - command -v local >/dev/null && local _local="local" || + command -v local > /dev/null && local _local="local" || typeset _local="typeset" $_local bad_names="" bad_lcs="" key="" val="" var="" vars="" bad_kv="" @@ -27,13 +27,14 @@ locale_warn() { # locale: Cannot set LC_SOMETHING to default locale while read -r w1 w2 w3 w4 remain; do case "$w1" in - locale:) bad_names="${bad_names} ${w4}";; + locale:) bad_names="${bad_names} ${w4}" ;; *) key=${w1%%=*} val=${w1#*=} val=${val#\"} val=${val%\"} - vars="${vars} $key=$val";; + vars="${vars} $key=$val" + ;; esac done for bad in $bad_names; do @@ -93,7 +94,7 @@ locale_warn() { printf "_____________________________________________________________________\n\n" # only show the message once - : > ~/.cloud-locale-test.skip 2>/dev/null || : + : > ~/.cloud-locale-test.skip 2> /dev/null || : } [ -f ~/.cloud-locale-test.skip -o -f /var/lib/cloud/instance/locale-check.skip ] || diff --git a/tools/Z99-cloudinit-warnings.sh b/tools/Z99-cloudinit-warnings.sh index 560902350ca..297fbee8380 100644 --- a/tools/Z99-cloudinit-warnings.sh +++ b/tools/Z99-cloudinit-warnings.sh @@ -4,7 +4,7 @@ # Purpose: show user warnings on login. cloud_init_warnings() { - command -v local >/dev/null && local _local="local" || + command -v local > /dev/null && local _local="local" || typeset _local="typeset" $_local warning="" idir="/var/lib/cloud/instance" n=0 $_local warndir="$idir/warnings" @@ -16,7 +16,7 @@ cloud_init_warnings() { for warning in "$warndir"/*; do [ -f "$warning" ] || continue cat "$warning" - n=$((n+1)) + n=$((n + 1)) done [ $n -eq 0 ] && return 0 echo "" diff --git a/tools/benchmark.sh b/tools/benchmark.sh deleted file mode 100755 index c382f374472..00000000000 --- a/tools/benchmark.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/bash - -BIN="$@" -chmod +x "$BIN" - -time for _ in $(seq 1 $ITER); do - "$BIN"; -done diff --git a/tools/build-on-freebsd b/tools/build-on-freebsd index d7b3e354062..c5cc6e23662 100755 --- a/tools/build-on-freebsd +++ b/tools/build-on-freebsd @@ -8,7 +8,10 @@ set -eux -fail() { echo "FAILED:" "$@" 1>&2; exit 1; } +fail() { + echo "FAILED:" "$@" 1>&2 + exit 1 +} PYTHON="${PYTHON:-python3}" if [ ! $(which ${PYTHON}) ]; then diff --git a/tools/build-on-netbsd b/tools/build-on-netbsd index b743d591b6e..25db86f66ec 100755 --- a/tools/build-on-netbsd +++ b/tools/build-on-netbsd @@ -1,6 +1,9 @@ #!/bin/sh -fail() { echo "FAILED:" "$@" 1>&2; exit 1; } +fail() { + echo "FAILED:" "$@" 1>&2 + exit 1 +} PYTHON="${PYTHON:-python3}" if [ ! $(which ${PYTHON}) ]; then diff --git a/tools/build-on-openbsd b/tools/build-on-openbsd index 94c66dd1744..47c6677e8a2 100755 --- a/tools/build-on-openbsd +++ b/tools/build-on-openbsd @@ -1,9 +1,12 @@ #!/bin/sh -fail() { echo "FAILED:" "$@" 1>&2; exit 1; } +fail() { + echo "FAILED:" "$@" 1>&2 + exit 1 +} PYTHON=${PYTHON:-python3} -if ! command -v ${PYTHON} >/dev/null 2>&1; then +if ! command -v ${PYTHON} > /dev/null 2>&1; then echo "Please install python first." exit 1 fi @@ -27,10 +30,10 @@ pkgs=" wget " -[ -f $depschecked ] || echo "Installing the following packages: $pkgs"; output=$(pkg_add -zI $pkgs 2>&1) - +[ -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 +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" diff --git a/tools/check_json_format.sh b/tools/check_json_format.sh deleted file mode 100755 index 62f7d6cd74e..00000000000 --- a/tools/check_json_format.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh -# -# Run python's json.tool and check for changes -# -# requires python 3.9 for --indent -# -file=$1 -before=$(cat "$file") && - python3 -m json.tool --indent 2 "$file" "$file" && - after=$(cat "$file") && - test "$before" = "$after" diff --git a/tools/cloud-init-hotplugd b/tools/cloud-init-hotplugd index eb811d69b10..4df5dd55693 100755 --- a/tools/cloud-init-hotplugd +++ b/tools/cloud-init-hotplugd @@ -14,9 +14,9 @@ PIPE="/run/cloud-init/share/hook-hotplug-cmd" [ -p $PIPE ] || mkfifo -m700 $PIPE while true; do - # shellcheck disable=SC2162 - if read args < $PIPE; then - # shellcheck disable=SC2086 - /usr/bin/cloud-init devel hotplug-hook $args - fi + # shellcheck disable=SC2162 + if read args < $PIPE; then + # shellcheck disable=SC2086 + /usr/bin/cloud-init devel hotplug-hook $args + fi done diff --git a/tools/cloud-init-per b/tools/cloud-init-per index fcd1ea796df..07adf40890f 100755 --- a/tools/cloud-init-per +++ b/tools/cloud-init-per @@ -5,7 +5,7 @@ DATA_PRE="/var/lib/cloud/sem/bootper" INST_PRE="/var/lib/cloud/instance/sem/bootper" Usage() { - cat <&2; } -fail() { [ $# -eq 0 ] || error "$@"; exit 1; } +fail() { + [ $# -eq 0 ] || error "$@" + exit 1 +} # support the old 'cloud-init-run-module freq name "execute" cmd arg1' # if < 3 arguments, it will fail below on usage. if [ "${0##*/}" = "cloud-init-run-module" ]; then - if [ $# -le 2 -o "$3" = "execute" ]; then - error "Warning: ${0##*/} is deprecated. Please use cloud-init-per." - freq=$1; name=$2; - [ $# -le 2 ] || shift 3; - set -- "$freq" "$name" "$@" - else - fail "legacy cloud-init-run-module only supported with module 'execute'" - fi + if [ $# -le 2 -o "$3" = "execute" ]; then + error "Warning: ${0##*/} is deprecated. Please use cloud-init-per." + freq=$1 + name=$2 + [ $# -le 2 ] || shift 3 + set -- "$freq" "$name" "$@" + else + fail "legacy cloud-init-run-module only supported with module 'execute'" + fi fi -[ "$1" = "-h" -o "$1" = "--help" ] && { Usage ; exit 0; } -[ $# -ge 3 ] || { Usage 1>&2; exit 1; } +[ "$1" = "-h" -o "$1" = "--help" ] && { + Usage + exit 0 +} +[ $# -ge 3 ] || { + Usage 1>&2 + exit 1 +} freq=$1 name=$(echo $2 | sed 's/-/_/g') -shift 2; +shift 2 [ "${name#*/}" = "${name}" ] || fail "name cannot contain a /" [ "$(id -u)" = "0" ] || fail "must be root" case "$freq" in - once|always) sem="${DATA_PRE}.$name.$freq";; - instance) sem="${INST_PRE}.$name.$freq";; - *) Usage 1>&2; fail "invalid frequency: $freq";; + once | always) sem="${DATA_PRE}.$name.$freq" ;; + instance) sem="${INST_PRE}.$name.$freq" ;; + *) + Usage 1>&2 + fail "invalid frequency: $freq" + ;; esac [ -d "${sem%/*}" ] || mkdir -p "${sem%/*}" || - fail "failed to make directory for ${sem}" + fail "failed to make directory for ${sem}" # Rename legacy sem files with dashes in their names. Do not overwrite existing # sem files to prevent clobbering those which may have been created from calls @@ -63,5 +76,5 @@ sem_legacy=$(echo $sem | sed 's/_/-/g') "$@" ret=$? printf "%s\t%s\n" "$ret" "$(date +%s)" > "$sem" || - fail "failed to write to $sem" + fail "failed to write to $sem" exit $ret diff --git a/tools/ds-identify b/tools/ds-identify index d0117e83c47..82f6b036bab 100755 --- a/tools/ds-identify +++ b/tools/ds-identify @@ -143,7 +143,7 @@ DI_EC2_STRICT_ID_DEFAULT="true" _IS_IBM_CLOUD="" error() { - set -- "ERROR:" "$@"; + set -- "ERROR:" "$@" debug 0 "$@" stderr "$@" } @@ -166,7 +166,7 @@ debug() { if [ "$_DI_LOGGED" != "$DI_LOG" ]; then # first time here, open file descriptor for append case "$DI_LOG" in - stderr) :;; + stderr) : ;; ?*/*) if [ ! -d "${DI_LOG%/*}" ]; then mkdir -p "${DI_LOG%/*}" || { @@ -174,12 +174,13 @@ debug() { DI_LOG="stderr" } fi + ;; esac if [ "$DI_LOG" = "stderr" ]; then exec 3>&2 else - ( exec 3>>"$DI_LOG" ) && exec 3>>"$DI_LOG" || { - stderr "ERROR: failed writing to $DI_LOG. logging to stderr."; + (exec 3>> "$DI_LOG") && exec 3>> "$DI_LOG" || { + stderr "ERROR: failed writing to $DI_LOG. logging to stderr." exec 3>&2 DI_LOG="stderr" } @@ -191,71 +192,77 @@ debug() { get_kenv_field() { local sys_field="$1" kenv_field="" val="" - command -v kenv >/dev/null 2>&1 || { + command -v kenv > /dev/null 2>&1 || { warn "No kenv program. Cannot read $sys_field." return 1 } case "$sys_field" in - board_asset_tag) kenv_field="smbios.planar.tag";; - board_vendor) kenv_field='smbios.planar.maker';; - board_name) kenv_field='smbios.planar.product';; - board_serial) kenv_field='smbios.planar.serial';; - board_version) kenv_field='smbios.planar.version';; - bios_date) kenv_field='smbios.bios.reldate';; - bios_vendor) kenv_field='smbios.bios.vendor';; - bios_version) kenv_field='smbios.bios.version';; - chassis_asset_tag) kenv_field='smbios.chassis.tag';; - chassis_vendor) kenv_field='smbios.chassis.maker';; - chassis_serial) kenv_field='smbios.chassis.serial';; - chassis_version) kenv_field='smbios.chassis.version';; - sys_vendor) kenv_field='smbios.system.maker';; - product_name) kenv_field='smbios.system.product';; - product_serial) kenv_field='smbios.system.serial';; - product_uuid) kenv_field='smbios.system.uuid';; - *) error "Unknown field $sys_field. Cannot call kenv." - return 1;; + board_asset_tag) kenv_field="smbios.planar.tag" ;; + board_vendor) kenv_field='smbios.planar.maker' ;; + board_name) kenv_field='smbios.planar.product' ;; + board_serial) kenv_field='smbios.planar.serial' ;; + board_version) kenv_field='smbios.planar.version' ;; + bios_date) kenv_field='smbios.bios.reldate' ;; + bios_vendor) kenv_field='smbios.bios.vendor' ;; + bios_version) kenv_field='smbios.bios.version' ;; + chassis_asset_tag) kenv_field='smbios.chassis.tag' ;; + chassis_vendor) kenv_field='smbios.chassis.maker' ;; + chassis_serial) kenv_field='smbios.chassis.serial' ;; + chassis_version) kenv_field='smbios.chassis.version' ;; + sys_vendor) kenv_field='smbios.system.maker' ;; + product_name) kenv_field='smbios.system.product' ;; + product_serial) kenv_field='smbios.system.serial' ;; + product_uuid) kenv_field='smbios.system.uuid' ;; + *) + error "Unknown field $sys_field. Cannot call kenv." + return 1 + ;; esac - val=$(kenv -q "$kenv_field" 2>/dev/null) || return 1 + val=$(kenv -q "$kenv_field" 2> /dev/null) || return 1 _RET="$val" } get_sysctl_field() { local sys_field="$1" sysctl_field="" val="" - command -v sysctl >/dev/null 2>&1 || { + command -v sysctl > /dev/null 2>&1 || { warn "No sysctl program. Cannot read $sys_field." return 1 } case "$sys_field" in - chassis_vendor) sysctl_field='hw.vendor';; - chassis_serial) sysctl_field='hw.type';; - chassis_version) sysctl_field='hw.uuid';; - sys_vendor) sysctl_field='hw.vendor';; - product_name) sysctl_field='hw.product';; - product_serial) sysctl_field='hw.uuid';; - product_uuid) sysctl_field='hw.uuid';; - *) error "Unknown field $sys_field. Cannot call sysctl." - return 1;; + chassis_vendor) sysctl_field='hw.vendor' ;; + chassis_serial) sysctl_field='hw.type' ;; + chassis_version) sysctl_field='hw.uuid' ;; + sys_vendor) sysctl_field='hw.vendor' ;; + product_name) sysctl_field='hw.product' ;; + product_serial) sysctl_field='hw.uuid' ;; + product_uuid) sysctl_field='hw.uuid' ;; + *) + error "Unknown field $sys_field. Cannot call sysctl." + return 1 + ;; esac - val=$(sysctl -nq "$sysctl_field" 2>/dev/null) || return 1 + val=$(sysctl -nq "$sysctl_field" 2> /dev/null) || return 1 _RET="$val" } dmi_decode() { local sys_field="$1" dmi_field="" val="" - command -v dmidecode >/dev/null 2>&1 || { + command -v dmidecode > /dev/null 2>&1 || { warn "No dmidecode program. Cannot read $sys_field." return 1 } case "$sys_field" in - sys_vendor) dmi_field="system-manufacturer";; - product_name) dmi_field="system-product-name";; - product_uuid) dmi_field="system-uuid";; - product_serial) dmi_field="system-serial-number";; - chassis_asset_tag) dmi_field="chassis-asset-tag";; - *) error "Unknown field $sys_field. Cannot call dmidecode." - return 1;; + sys_vendor) dmi_field="system-manufacturer" ;; + product_name) dmi_field="system-product-name" ;; + product_uuid) dmi_field="system-uuid" ;; + product_serial) dmi_field="system-serial-number" ;; + chassis_asset_tag) dmi_field="chassis-asset-tag" ;; + *) + error "Unknown field $sys_field. Cannot call dmidecode." + return 1 + ;; esac - val=$(dmidecode --quiet "--string=$dmi_field" 2>/dev/null) || return 1 + val=$(dmidecode --quiet "--string=$dmi_field" 2> /dev/null) || return 1 _RET="$val" } @@ -295,7 +302,7 @@ ensure_sane_path() { local t for t in /sbin /usr/sbin /bin /usr/bin; do case ":$PATH:" in - *:$t:*|*:$t/:*) continue;; + *:$t:* | *:$t/:*) continue ;; esac PATH="${PATH:+${PATH}:}$t" done @@ -341,20 +348,28 @@ read_fs_info_linux() { # empty lines in "$@" below. # shellcheck disable=2086 - { IFS="$CR"; set -- $DI_BLKID_EXPORT_OUT; IFS="$oifs"; } + { + IFS="$CR" + set -- $DI_BLKID_EXPORT_OUT + IFS="$oifs" + } for line in "$@"; do case "${line}" in DEVNAME=*) [ -n "$dev" -a "$ftype" = "iso9660" ] && isodevs="${isodevs},${dev}=$label" - ftype=""; dev=""; label=""; - dev=${line#DEVNAME=};; - LABEL=*|LABEL_FATBOOT=*) - label="${line#*=}"; - labels="${labels}${label}${delim}";; - TYPE=*) ftype=${line#TYPE=};; - UUID=*) uuids="${uuids}${line#UUID=}$delim";; + ftype="" + dev="" + label="" + dev=${line#DEVNAME=} + ;; + LABEL=* | LABEL_FATBOOT=*) + label="${line#*=}" + labels="${labels}${label}${delim}" + ;; + TYPE=*) ftype=${line#TYPE=} ;; + UUID=*) uuids="${uuids}${line#UUID=}$delim" ;; esac done [ -n "$dev" -a "$ftype" = "iso9660" ] && @@ -395,7 +410,11 @@ read_fs_info_freebsd() { # iso9660/cidata N/A vtbd2 # shellcheck disable=2086 - { IFS="$CR"; set -- $DI_GEOM_LABEL_STATUS_OUT; IFS="$oifs"; } + { + IFS="$CR" + set -- $DI_GEOM_LABEL_STATUS_OUT + IFS="$oifs" + } for line in "$@"; do # shellcheck disable=2086 @@ -451,16 +470,16 @@ detect_virt() { fi debug 2 "detected $virt via ds-identify" fi - elif command -v virt-what >/dev/null 2>&1; then + elif command -v virt-what > /dev/null 2>&1; then # Map virt-what's names to those systemd-detect-virt that # don't match up. out=$(virt-what 2>&1 | head -n 1) && { case "$out" in - ibm_systemz-zvm) virt="zvm" ;; - hyperv) virt="microsoft" ;; - virtualbox) virt="oracle" ;; - xen-domU) virt="xen" ;; - *) virt="$out" + ibm_systemz-zvm) virt="zvm" ;; + hyperv) virt="microsoft" ;; + virtualbox) virt="oracle" ;; + xen-domU) virt="xen" ;; + *) virt="$out" ;; esac } elif [ "$DI_UNAME_KERNEL_NAME" = "FreeBSD" -o "$DI_UNAME_KERNEL_NAME" = "Dragonfly" ]; then @@ -480,15 +499,15 @@ detect_virt() { # parallels | parallels # bhyve | bhyve # vm-other | generic - out=$(sysctl -qn kern.vm_guest 2>/dev/null) && { + out=$(sysctl -qn kern.vm_guest 2> /dev/null) && { case "$out" in hv) virt="microsoft" ;; vbox) virt="oracle" ;; - generic) virt="vm-other";; - *) virt="$out" + generic) virt="vm-other" ;; + *) virt="$out" ;; esac } - out=$(sysctl -qn security.jail.jailed 2>/dev/null) && { + out=$(sysctl -qn security.jail.jailed 2> /dev/null) && { if [ "$out" = "1" ]; then virt="jail" fi @@ -505,8 +524,8 @@ read_virt() { is_container() { case "${DI_VIRT}" in - container-other|lxc|lxc-libvirt|systemd-nspawn|docker|rkt|jail) return 0;; - *) return 1;; + container-other | lxc | lxc-libvirt | systemd-nspawn | docker | rkt | jail) return 0 ;; + *) return 1 ;; esac } @@ -524,7 +543,7 @@ read_kernel_cmdline() { cmdline=$x fi elif [ -f "$fpath" ]; then - read cmdline <"$fpath" + read cmdline < "$fpath" else cmdline="${UNAVAILABLE}:no-cmdline" fi @@ -609,7 +628,11 @@ parse_yaml_array() { val=${val#"["} val=${val%"]"} # shellcheck disable=2086 - { IFS=","; set -- $val; IFS="$oifs"; } + { + IFS="," + set -- $val + IFS="$oifs" + } for tok in "$@"; do trim "$tok" unquote "$_RET" @@ -655,9 +678,13 @@ read_pid1_product_name() { local oifs="$IFS" out="" tok="" key="" val="" product_name="${UNAVAILABLE}" cached "${DI_PID_1_PRODUCT_NAME}" && return [ -r "${PATH_PROC_1_ENVIRON}" ] || return - out=$(tr '\0' '\n' <"${PATH_PROC_1_ENVIRON}") + out=$(tr '\0' '\n' < "${PATH_PROC_1_ENVIRON}") # shellcheck disable=2086 - { IFS="$CR"; set -- $out; IFS="$oifs"; } + { + IFS="$CR" + set -- $out + IFS="$oifs" + } for tok in "$@"; do key=${tok%%=*} [ "$key" != "$tok" ] || continue @@ -671,7 +698,7 @@ dmi_chassis_asset_tag_matches() { is_container && return 1 # shellcheck disable=2254 case "${DI_DMI_CHASSIS_ASSET_TAG}" in - $1) return 0;; + $1) return 0 ;; esac return 1 } @@ -680,7 +707,7 @@ dmi_product_name_matches() { is_container && return 1 # shellcheck disable=2254 case "${DI_DMI_PRODUCT_NAME}" in - $1) return 0;; + $1) return 0 ;; esac return 1 } @@ -689,7 +716,7 @@ dmi_product_serial_matches() { is_container && return 1 # shellcheck disable=2254 case "${DI_DMI_PRODUCT_SERIAL}" in - $1) return 0;; + $1) return 0 ;; esac return 1 } @@ -701,7 +728,7 @@ dmi_sys_vendor_is() { has_fs_with_uuid() { case ",${DI_FS_UUIDS}," in - *,$1,*) return 0;; + *,$1,*) return 0 ;; esac return 1 } @@ -712,7 +739,7 @@ has_fs_with_label() { local label="" for label in "$@"; do case ",${DI_FS_LABELS}," in - *,$label,*) return 0;; + *,$label,*) return 0 ;; esac done return 1 @@ -768,16 +795,25 @@ probe_floppy() { local fpath=/dev/floppy [ -b "$fpath" ] || - { STATE_FLOPPY_PROBED=1; return 1; } + { + STATE_FLOPPY_PROBED=1 + return 1 + } # Use "-b" option as Busybox modprobe doesn't support long-option - modprobe -b floppy >/dev/null 2>&1 || - { STATE_FLOPPY_PROBED=1; return 1; } + modprobe -b floppy > /dev/null 2>&1 || + { + STATE_FLOPPY_PROBED=1 + return 1 + } # Some Linux distros/non-Linux OSes may not have udev if command -v udevadm; then udevadm settle "--exit-if-exists=$fpath" || - { STATE_FLOPPY_PROBED=1; return 1; } + { + STATE_FLOPPY_PROBED=1 + return 1 + } fi [ -b "$fpath" ] @@ -827,7 +863,11 @@ check_config() { files="$*" fi # shellcheck disable=2086 - { set +f; set -- $files; set -f; } + { + set +f + set -- $files + set -f + } if [ "$1" = "$files" -a ! -f "$1" ]; then return 1 fi @@ -846,11 +886,11 @@ check_config() { # key: [ some_value ] # key : [ "some value" ] # key\t:\t[\tsome_value\t]\t - # + # # The syntax warned about is not valid posix shell, and we are not # attempting to access an index of arrays. Silence it. # shellcheck disable=1087 - out=$(grep "$key[\"\']*[[:space:]]*:" "$@" 2>/dev/null) + out=$(grep "$key[\"\']*[[:space:]]*:" "$@" 2> /dev/null) IFS=${CR} for line in $out; do # drop '# comment' @@ -869,8 +909,8 @@ check_config() { continue fi fi - ret=${line#*: }; - found=$((found+1)) + ret=${line#*: } + found=$((found + 1)) done IFS="$oifs" if [ $found -ne 0 ]; then @@ -959,15 +999,17 @@ dscheck_LXD() { return ${DS_NOT_FOUND} fi # Temporarily enable globbing to walk virtio_ports_path. - set +f; set -- "${virtio_ports_path}/"*; set -f; + set +f + set -- "${virtio_ports_path}/"* + set -f for port_dir in "$@"; do local name_file="${port_dir}/name" port_name [ ! -f "${name_file}" ] && continue - read port_name < "${name_file}" || \ - warn "unable to read file: $name_file" + read port_name < "${name_file}" || + warn "unable to read file: $name_file" # Check for both current and legacy LXD serial names - if [ "${port_name}" = "com.canonical.lxd" ] || \ - [ "${port_name}" = "org.linuxcontainers.lxd" ]; then + if [ "${port_name}" = "com.canonical.lxd" ] || + [ "${port_name}" = "org.linuxcontainers.lxd" ]; then return ${DS_FOUND} fi done @@ -977,7 +1019,7 @@ dscheck_LXD() { dscheck_NoCloud() { local fslabel="cidata CIDATA" d="" case " ${DI_DMI_PRODUCT_SERIAL} " in - *\ ds=nocloud*) return ${DS_FOUND};; + *\ ds=nocloud*) return ${DS_FOUND} ;; esac for d in nocloud nocloud-net; do @@ -1012,7 +1054,9 @@ check_configdrive_v2() { local d="" local vlc_config_drive_path="${PATH_VAR_LIB_CLOUD}/seed/config_drive" for d in /config-drive $vlc_config_drive_path; do - set +f; set -- "$d/openstack/"2???-??-??/meta_data.json; set -f; + set +f + set -- "$d/openstack/"2???-??-??/meta_data.json + set -f [ -f "$1" ] && return ${DS_FOUND} done # at least one cloud (softlayer) seeds config drive with only 'latest'. @@ -1081,13 +1125,15 @@ vmware_guest_customization() { local ppath="plugins/vmsvc/libdeployPkgPlugin.so" for pkg in vmware-tools open-vm-tools; do if [ -f "$pre/$pkg/$ppath" -o -f "${pre}64/$pkg/$ppath" ]; then - found="$pkg"; break; + found="$pkg" + break fi # search in multiarch dir - if [ -f "$pre/$x86/$pkg/$ppath" ] || \ - [ -f "$pre/$aarch/$pkg/$ppath" ] || \ - [ -f "$pre/$i386/$pkg/$ppath" ]; then - found="$pkg"; break; + if [ -f "$pre/$x86/$pkg/$ppath" ] || + [ -f "$pre/$aarch/$pkg/$ppath" ] || + [ -f "$pre/$i386/$pkg/$ppath" ]; then + found="$pkg" + break fi done [ -n "$found" ] || return 1 @@ -1098,8 +1144,8 @@ vmware_guest_customization() { if check_config "$key" && get_value "$key" "$_RET"; then debug 2 "${_RET_fname} set $key to $_RET" case "$_RET" in - 0|false|False) return 0;; - *) return 1;; + 0 | false | False) return 0 ;; + *) return 1 ;; esac fi @@ -1107,11 +1153,11 @@ vmware_guest_customization() { } vmware_has_rpctool() { - command -v vmware-rpctool >/dev/null 2>&1 + command -v vmware-rpctool > /dev/null 2>&1 } vmware_rpctool_guestinfo() { - vmware-rpctool "info-get guestinfo.${1}" 2>/dev/null | grep "[[:alnum:]]" + vmware-rpctool "info-get guestinfo.${1}" 2> /dev/null | grep "[[:alnum:]]" } vmware_rpctool_guestinfo_err() { @@ -1119,11 +1165,11 @@ vmware_rpctool_guestinfo_err() { } vmware_has_vmtoolsd() { - command -v vmtoolsd >/dev/null 2>&1 + command -v vmtoolsd > /dev/null 2>&1 } vmware_vmtoolsd_guestinfo() { - vmtoolsd --cmd "info-get guestinfo.${1}" 2>/dev/null | grep "[[:alnum:]]" + vmtoolsd --cmd "info-get guestinfo.${1}" 2> /dev/null | grep "[[:alnum:]]" } vmware_vmtoolsd_guestinfo_err() { @@ -1167,9 +1213,11 @@ ovf_vmware_transport_guestinfo() { return 1 fi case "$out" in - "/dev/null 2>&1; then + if { vmware_guestinfo_metadata || + vmware_guestinfo_userdata || + vmware_guestinfo_vendordata; } > /dev/null 2>&1; then return "${DS_FOUND}" fi @@ -1710,7 +1783,7 @@ WSL_run_cmd() { shift # Using the '/u' flag to enforce Unicode (UTF-16 LE), thus we need to decode it afterwards. # It's more reliable than the default ANSI Code Pages for anything above the ASCII range. - _RET=$(/init "$exepath" /u /c "$@" 2>/dev/null | iconv --from-code UTF-16LE --to-code UTF-8) + _RET=$(/init "$exepath" /u /c "$@" 2> /dev/null | iconv --from-code UTF-16LE --to-code UTF-8) } WSL_profile_dir() { @@ -1724,8 +1797,8 @@ WSL_profile_dir() { # Here WSL's `/init` is used to start the Windows cmd.exe # to output the Windows user profile directory path, which is # held by the environment variable %USERPROFILE%. - # See https://wsl.dev/technical-documentation/interop/ for more information on how /init - # is used to launch Windows binaries. + # See https://wsl.dev/technical-documentation/interop/ for more information on how /init + # is used to launch Windows binaries. WSL_run_cmd "$cmdexe" "echo.%USERPROFILE%" profiledir="${_RET%%[[:cntrl:]]}" if [ -n "$profiledir" ]; then @@ -1867,7 +1940,7 @@ write_result() { pre=" " fi for line in "$@"; do - echo "${pre}$line"; + echo "${pre}$line" done } > "$runcfg" ret=$? @@ -1909,8 +1982,8 @@ found() { fi # if None is not already in the list, then add it last. case " $list " in - *\ None,\ *|*\ None\ ) :;; - *) list=${list:+${list}, None};; + *\ None,\ * | *\ None\ ) : ;; + *) list=${list:+${list}, None} ;; esac write_result "datasource_list: [ $list ]" "$@" return @@ -1919,8 +1992,14 @@ found() { trim() { # trim all whitespace from the string, assign output to _RET local tmp="" cur="$*" - until tmp="${cur#[[:space:]]}"; [ "$tmp" = "$cur" ]; do cur="$tmp"; done - until tmp="${cur%[[:space:]]}"; [ "$tmp" = "$cur" ]; do cur="$tmp"; done + until + tmp="${cur#[[:space:]]}" + [ "$tmp" = "$cur" ] + do cur="$tmp"; done + until + tmp="${cur%[[:space:]]}" + [ "$tmp" = "$cur" ] + do cur="$tmp"; done _RET="$tmp" } @@ -1929,8 +2008,10 @@ unquote() { local quote='"' tick="'" local val="$1" case "$val" in - ${quote}*${quote}|${tick}*${tick}) - val=${val#?}; val=${val%?};; + ${quote}*${quote} | ${tick}*${tick}) + val=${val#?} + val=${val%?} + ;; esac _RET="$val" } @@ -1964,8 +2045,8 @@ _read_config() { fi case "$key" in - datasource) _rc_dsname="$val";; - policy) _rc_policy="$val";; + datasource) _rc_dsname="$val" ;; + policy) _rc_policy="$val" ;; esac done if [ "$keyname" = "_unset" ]; then @@ -2003,10 +2084,10 @@ parse_policy() { local def="" case "$DI_UNAME_MACHINE" in # these have dmi data - i?86|x86_64) def=${DI_DEFAULT_POLICY};; + i?86 | x86_64) def=${DI_DEFAULT_POLICY} ;; # aarch64 has dmi, but not currently used (LP: #1663304) - aarch64) def=${DI_DEFAULT_POLICY_NO_DMI};; - *) def=${DI_DEFAULT_POLICY_NO_DMI};; + aarch64) def=${DI_DEFAULT_POLICY_NO_DMI} ;; + *) def=${DI_DEFAULT_POLICY_NO_DMI} ;; esac local policy="$1" local _def_mode="" _def_report="" _def_found="" _def_maybe="" @@ -2019,23 +2100,30 @@ parse_policy() { local mode="" report="" found="" maybe="" notfound="" local oifs="$IFS" tok="" val="" # shellcheck disable=2086 - { IFS=","; set -- $policy; IFS="$oifs"; } + { + IFS="," + set -- $policy + IFS="$oifs" + } for tok in "$@"; do val=${tok#*=} case "$tok" in - "${DI_ENABLED}"|"${DI_DISABLED}"|search|report) mode=$tok;; - found=all|found=first) found=$val;; - maybe=all|maybe=none) maybe=$val;; - notfound="${DI_ENABLED}"|notfound="${DI_DISABLED}") notfound=$val;; + "${DI_ENABLED}" | "${DI_DISABLED}" | search | report) mode=$tok ;; + found=all | found=first) found=$val ;; + maybe=all | maybe=none) maybe=$val ;; + notfound="${DI_ENABLED}" | notfound="${DI_DISABLED}") notfound=$val ;; found=*) - parse_warn found "$val" "${_def_found}" - found=${_def_found};; + parse_warn found "$val" "${_def_found}" + found=${_def_found} + ;; maybe=*) - parse_warn maybe "$val" "${_def_maybe}" - maybe=${_def_maybe};; + parse_warn maybe "$val" "${_def_maybe}" + maybe=${_def_maybe} + ;; notfound=*) - parse_warn notfound "$val" "${_def_notfound}" - notfound=${_def_notfound};; + parse_warn notfound "$val" "${_def_notfound}" + notfound=${_def_notfound} + ;; esac done report=${report:-${_def_report:-false}} @@ -2064,17 +2152,17 @@ read_config() { # discard anything after the first delimiter val=${val%%;*} case "$key" in - ds) _rc_dsname="$val";; - ci.ds) _rc_dsname="$val";; - ci.datasource) _rc_dsname="$val";; - ci.di.policy) _rc_policy="$val";; + ds) _rc_dsname="$val" ;; + ci.ds) _rc_dsname="$val" ;; + ci.datasource) _rc_dsname="$val" ;; + ci.di.policy) _rc_policy="$val" ;; esac done local _rc_mode _rc_report _rc_found _rc_maybe _rc_notfound parse_policy "${_rc_policy}" debug 1 "policy loaded: mode=${_rc_mode} report=${_rc_report}" \ - "found=${_rc_found} maybe=${_rc_maybe} notfound=${_rc_notfound}" + "found=${_rc_found} maybe=${_rc_maybe} notfound=${_rc_notfound}" DI_MODE=${_rc_mode} DI_ON_FOUND=${_rc_found} DI_ON_MAYBE=${_rc_maybe} @@ -2084,7 +2172,6 @@ read_config() { return $ret } - manual_clean_and_existing() { [ -f "${PATH_VAR_LIB_CLOUD}/instance/manual-clean" ] } @@ -2115,7 +2202,7 @@ set_run_path() { # testing only - NOT use for production code, it is NOT supported get_environment() { if [ -f "$PATH_DI_ENV" ]; then - debug 0 "WARN: loading environment file [${PATH_DI_ENV}]"; + debug 0 "WARN: loading environment file [${PATH_DI_ENV}]" # shellcheck source=/dev/null . "$PATH_DI_ENV" fi @@ -2146,8 +2233,9 @@ _main() { ;; "${DI_ENABLED}") debug 1 "mode=$DI_ENABLED. returning $ret_en" - return $ret_en;; - search|report) :;; + return $ret_en + ;; + search | report) : ;; esac if [ -n "${DI_DSNAME}" ]; then @@ -2165,7 +2253,7 @@ _main() { # shellcheck disable=2086 set -- $DI_DSLIST # if there is only a single entry in $DI_DSLIST - if [ $# -eq 1 ] || [ $# -eq 2 -a "$2" = "None" ] ; then + if [ $# -eq 1 ] || [ $# -eq 2 -a "$2" = "None" ]; then debug 1 "single entry in datasource_list ($DI_DSLIST) use that." if [ $# -eq 1 ]; then write_result "datasource_list: [ $1 ]" @@ -2180,7 +2268,7 @@ _main() { for ds in ${DI_DSLIST}; do dscheck_fn="dscheck_${ds}" debug 2 "Checking for datasource '$ds' via '$dscheck_fn'" - if ! type "$dscheck_fn" >/dev/null 2>&1; then + if ! type "$dscheck_fn" > /dev/null 2>&1; then warn "No check method '$dscheck_fn' for datasource '$ds'" continue fi @@ -2189,14 +2277,16 @@ _main() { ret="$?" case "$ret" in "${DS_FOUND}") - debug 1 "check for '$ds' returned found"; + debug 1 "check for '$ds' returned found" exfound_cfg="${exfound_cfg:+${exfound_cfg}${CR}}${_RET_excfg}" - found="${found} $ds";; + found="${found} $ds" + ;; "${DS_MAYBE}") - debug 1 "check for '$ds' returned maybe"; + debug 1 "check for '$ds' returned maybe" exmaybe_cfg="${exmaybe_cfg:+${exmaybe_cfg}${CR}}${_RET_excfg}" - maybe="${maybe} $ds";; - *) debug 2 "check for '$ds' returned not-found[$ret]";; + maybe="${maybe} $ds" + ;; + *) debug 2 "check for '$ds' returned not-found[$ret]" ;; esac done @@ -2233,17 +2323,21 @@ _main() { case "$DI_MODE:$DI_ON_NOTFOUND" in report:"${DI_DISABLED}") msg="$basemsg Would disable cloud-init [$ret_dis]" - ret=$ret_en;; + ret=$ret_en + ;; report:"${DI_ENABLED}") msg="$basemsg Would enable cloud-init [$ret_en]" - ret=$ret_en;; + ret=$ret_en + ;; search:"${DI_DISABLED}") msg="$basemsg Disabled cloud-init [$ret_dis]" - ret=$ret_dis;; + ret=$ret_dis + ;; search:"${DI_ENABLED}") msg="$basemsg Enabled cloud-init [$ret_en]" - ret=$ret_en;; - *) error "Unexpected result";; + ret=$ret_en + ;; + *) error "Unexpected result" ;; esac debug 1 "$msg" return "$ret" @@ -2262,7 +2356,7 @@ main() { if read ret < "$PATH_RUN_DI_RESULT"; then if [ "$ret" = "0" ] || [ "$ret" = "1" ] || [ "$ret" = "2" ]; then debug 2 "used cached result $ret. pass --force to re-run." - return "$ret"; + return "$ret" fi debug 1 "previous run returned unexpected '$ret'. Re-running." else @@ -2284,11 +2378,12 @@ noop() { get_environment case "${DI_MAIN}" in # builtin DI_MAIN implementations - main|print_info|noop) "${DI_MAIN}" "$@";; + main | print_info | noop) "${DI_MAIN}" "$@" ;; # side-load an alternate implementation # testing only - NOT use for production code, it is NOT supported *) - debug 0 "WARN: side-loading alternate implementation: [${DI_MAIN}]"; - exec "${DI_MAIN}" "$@";; + debug 0 "WARN: side-loading alternate implementation: [${DI_MAIN}]" + exec "${DI_MAIN}" "$@" + ;; esac diff --git a/tools/hook-hotplug b/tools/hook-hotplug index f142d4b9548..485cff19ec5 100755 --- a/tools/hook-hotplug +++ b/tools/hook-hotplug @@ -25,7 +25,7 @@ if ! should_run; then fi # open cloud-init's hotplug-hook fifo rw -exec 3<>$fifo +exec 3<> $fifo env_params=" --subsystem=${SUBSYSTEM} handle --devpath=${DEVPATH} --udevaction=${ACTION}" # write params to cloud-init's hotplug-hook fifo echo "${env_params}" >&3 diff --git a/tools/make-tarball b/tools/make-tarball index 48442d0b080..11dddc26f52 100755 --- a/tools/make-tarball +++ b/tools/make-tarball @@ -8,7 +8,7 @@ cleanup() { trap cleanup EXIT Usage() { - cat <&2; exit 1; } + eval set -- "${getopt_out}" || { + Usage 1>&2 + exit 1 +} long_opt="" orig_opt="" version="" while [ $# -ne 0 ]; do - cur=$1; next=$2 + cur=$1 + next=$2 case "$cur" in - -h|--help) Usage; exit 0;; - -o|--output) output=$next; shift;; - --version) version=$next; shift;; - --long) long_opt="--long";; - --orig-tarball) orig_opt=".orig";; - --) shift; break;; + -h | --help) + Usage + exit 0 + ;; + -o | --output) + output=$next + shift + ;; + --version) + version=$next + shift + ;; + --long) long_opt="--long" ;; + --orig-tarball) orig_opt=".orig" ;; + --) + shift + break + ;; esac - shift; + shift done rev=${1:-HEAD} diff --git a/tools/motd-hook b/tools/motd-hook deleted file mode 100755 index 73d9792c1ab..00000000000 --- a/tools/motd-hook +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/sh -# Copyright (C) 2010 Canonical Ltd. -# -# Authors: Scott Moser -# -# This file is part of cloud-init. See LICENSE file for license information. - -# 92-ec2-upgrade-available - update-motd script - -# Determining if updates are available is possibly slow. -# a cronjob runs occasioinally and updates a file with information -# on the latest available release (if newer than current) - -BUILD_FILE=/var/lib/cloud/data/available.build - -[ -s "${BUILD_FILE}" ] || exit 0 - -read suite build_name name serial other < "${BUILD_FILE}" - -cat <&2; } -fail() { [ $# -eq 0 ] || error "$@"; exit 1; } -errorrc() { local r=$?; error "$@" "ret=$r"; return $r; } +fail() { + [ $# -eq 0 ] || error "$@" + exit 1 +} +errorrc() { + local r=$? + error "$@" "ret=$r" + return $r +} Usage() { - cat <&2; [ $# -eq 0 ] || error "$@"; return 1; } +bad_Usage() { + Usage 1>&2 + [ $# -eq 0 ] || error "$@" + return 1 +} cleanup() { if [ -n "$CONTAINER" ]; then if [ "$KEEP" = "true" ]; then @@ -60,12 +71,12 @@ cleanup() { } debug() { - local level=${1}; shift; + local level=${1} + shift [ "${level}" -gt "${VERBOSITY}" ] && return error "${@}" } - inside_as() { # inside_as(container_name, user, cmd[, args]) # executes cmd with args inside container as user in users home dir. @@ -80,7 +91,7 @@ inside_as() { stuffed=${stuffed# -- } b64=$(printf "%s\n" "$stuffed" | base64 --wrap=0) inside "$name" su "$user" -c \ - 'cd; eval set -- "$(echo '"$b64"' | base64 --decode)" && exec "$@"'; + 'cd; eval set -- "$(echo '"$b64"' | base64 --decode)" && exec "$@"' } inside_as_cd() { @@ -95,21 +106,22 @@ inside() { $LXC exec "$name" -- "$@" } -inject_cloud_init(){ +inject_cloud_init() { # take current cloud-init git dir and put it inside $name at # ~$user/cloud-init. local name="$1" user="$2" dirty="$3" local dname="cloud-init" gitdir="" commitish="" gitdir=$(git rev-parse --git-dir) || { - errorrc "Failed to get git dir in $PWD"; + errorrc "Failed to get git dir in $PWD" return } local t=${gitdir%/*} case "$t" in - */worktrees) + */worktrees) if [ -f "${t%worktrees}/config" ]; then gitdir="${t%worktrees}" fi + ;; esac # attempt to get branch name. @@ -182,7 +194,10 @@ get_os_info_in() { # prep the container (install very basic dependencies) [ -n "${OS_VERSION:-}" -a -n "${OS_NAME:-}" ] && return 0 data=$(run_self_inside "$name" os_info) || - { errorrc "Failed to get os-info in container $name"; return; } + { + errorrc "Failed to get os-info in container $name" + return + } eval "$data" && [ -n "${OS_VERSION:-}" -a -n "${OS_NAME:-}" ] || return debug 1 "determined $name is $OS_NAME/$OS_VERSION" } @@ -204,33 +219,42 @@ get_os_info() { local pname="" pname=$(sh -c '. /etc/os-release; echo $PRETTY_NAME') case "$pname" in - *buster*) OS_VERSION=10;; - *sid*) OS_VERSION="sid";; + *buster*) OS_VERSION=10 ;; + *sid*) OS_VERSION="sid" ;; esac fi elif [ -f /etc/centos-release ]; then local line="" read line < /etc/centos-release case "$line" in - CentOS\ *\ 6.*) OS_VERSION="6"; OS_NAME="centos";; + CentOS\ *\ 6.*) + OS_VERSION="6" + OS_NAME="centos" + ;; esac fi [ -n "${OS_NAME:-}" -a -n "${OS_VERSION:-}" ] || - { error "Unable to determine OS_NAME/OS_VERSION"; return 1; } + { + error "Unable to determine OS_NAME/OS_VERSION" + return 1 + } } yum_install() { local n=0 max=10 ret bcmd="yum install --downloadonly --assumeyes --setopt=keepcache=1" - while n=$((n+1)); do - error ":: running $bcmd $* [$n/$max]" - $bcmd "$@" - ret=$? - [ $ret -eq 0 ] && break - [ $n -ge $max ] && { error "gave up on $bcmd"; exit $ret; } - nap=$((n*5)) - error ":: failed [$ret] ($n/$max). sleeping $nap." - sleep $nap + while n=$((n + 1)); do + error ":: running $bcmd $* [$n/$max]" + $bcmd "$@" + ret=$? + [ $ret -eq 0 ] && break + [ $n -ge $max ] && { + error "gave up on $bcmd" + exit $ret + } + nap=$((n * 5)) + error ":: failed [$ret] ($n/$max). sleeping $nap." + sleep $nap done error ":: running yum install --cacheonly --assumeyes $*" yum install --cacheonly --assumeyes "$@" @@ -251,11 +275,13 @@ apt_install() { install_packages() { get_os_info || return case "$OS_NAME" in - centos|rocky*|fedora) yum_install "$@";; - opensuse*) zypper_install "$@";; - debian|ubuntu) apt_install "$@" -y;; - *) error "Do not know how to install packages on ${OS_NAME}"; - return 1;; + centos | rocky* | fedora) yum_install "$@" ;; + opensuse*) zypper_install "$@" ;; + debian | ubuntu) apt_install "$@" -y ;; + *) + error "Do not know how to install packages on ${OS_NAME}" + return 1 + ;; esac } @@ -270,7 +296,8 @@ prep() { local py3pkg="python3" case "$OS_NAME" in opensuse) - py3pkg="python3-base";; + py3pkg="python3-base" + ;; esac pairs="$pairs python3:$py3pkg" @@ -278,7 +305,7 @@ prep() { for pair in $pairs; do pkg=${pair#*:} cmd=${pair%%:*} - command -v "$cmd" >/dev/null 2>&1 || needed="${needed} $pkg" + command -v "$cmd" > /dev/null 2>&1 || needed="${needed} $pkg" done needed=${needed# } if [ -z "$needed" ]; then @@ -302,15 +329,16 @@ is_done_cloudinit() { is_done_systemd() { local s="" num="$1" - s=$(systemctl is-system-running 2>&1); + s=$(systemctl is-system-running 2>&1) _RET="$? $s" case "$s" in - initializing|starting) return 1;; + initializing | starting) return 1 ;; *[Ff]ailed*connect*bus*) # warn if not the first run. [ "$num" -lt 5 ] || - error "Failed to connect to systemd bus [${_RET%% *}]"; - return 1;; + error "Failed to connect to systemd bus [${_RET%% *}]" + return 1 + ;; esac return 0 } @@ -323,20 +351,20 @@ is_done_other() { wait_inside() { local name="$1" max="${2:-${WAIT_MAX}}" debug=${3:-0} - local i=0 check="is_done_other"; + local i=0 check="is_done_other" if [ -e /run/systemd ]; then check=is_done_systemd elif [ -x /usr/bin/cloud-init ]; then check=is_done_cloudinit fi [ "$debug" != "0" ] && debug 1 "check=$check" - while ! $check $i && i=$((i+1)); do + while ! $check $i && i=$((i + 1)); do [ "$i" -ge "$max" ] && exit 1 [ "$debug" = "0" ] || echo -n . sleep 1 done if [ "$debug" != "0" ]; then - read up _ /dev/null && system_up=true && break + inside "$name" true 2> /dev/null && system_up=true && break done - [ $system_up == true ] || { errorrc "exec command inside $name failed."; return; } + [ $system_up == true ] || { + errorrc "exec command inside $name failed." + return + } get_os_info_in "$name" [ "$OS_NAME" = "debian" ] && wtime=300 && debug 1 "on debian we wait for ${wtime}s" debug 1 "waiting for boot of $name" run_self_inside "$name" wait_inside "$name" "$wtime" "$VERBOSITY" || - { errorrc "wait inside $name failed."; return; } + { + errorrc "wait inside $name failed." + return + } if [ -n "${http_proxy-}" ]; then if [ "$OS_NAME" = "centos" -o "$OS_NAME" = "fedora" ]; then @@ -364,21 +398,21 @@ wait_for_boot() { inside "$name" sh -c "sed -i --regexp-extended '/^#baseurl=/s/#// ; /^(mirrorlist|metalink)=/s/^/#/' /etc/yum.repos.d/*.repo" inside "$name" sh -c "sed -i 's/download\.fedoraproject\.org/dl.fedoraproject.org/g' /etc/yum.repos.d/*.repo" inside "$name" sh -c "sed -i 's/download\.example/dl.fedoraproject.org/g' /etc/yum.repos.d/*.repo" - if [ "$OS_NAME" = "centos" ]; then - CENTOS_REPO="/etc/yum.repos.d/centos.repo" - inside "$name" sh -c "grep -q baseurl $CENTOS_REPO" - if [ $? -eq 1 ]; then - # CentOS 9 does not provide baseurl definitions - inside "$name" sh -c "sed -i '/\[baseos\]/a baseurl=https://mirror.stream.centos.org/9-stream/BaseOS/x86_64/os' ${CENTOS_REPO}" - inside "$name" sh -c "sed -i '/\[appstream\]/a baseurl=https://mirror.stream.centos.org/9-stream/AppStream/x86_64/os' ${CENTOS_REPO}" - inside "$name" sh -c "sed -i '/\[crb\]/a baseurl=https://mirror.stream.centos.org/9-stream/CRB/x86_64/os' ${CENTOS_REPO}" + if [ "$OS_NAME" = "centos" ]; then + CENTOS_REPO="/etc/yum.repos.d/centos.repo" + inside "$name" sh -c "grep -q baseurl $CENTOS_REPO" + if [ $? -eq 1 ]; then + # CentOS 9 does not provide baseurl definitions + inside "$name" sh -c "sed -i '/\[baseos\]/a baseurl=https://mirror.stream.centos.org/9-stream/BaseOS/x86_64/os' ${CENTOS_REPO}" + inside "$name" sh -c "sed -i '/\[appstream\]/a baseurl=https://mirror.stream.centos.org/9-stream/AppStream/x86_64/os' ${CENTOS_REPO}" + inside "$name" sh -c "sed -i '/\[crb\]/a baseurl=https://mirror.stream.centos.org/9-stream/CRB/x86_64/os' ${CENTOS_REPO}" CENTOS_EXTRAS_REPO="/etc/yum.repos.d/centos-addons.repo" - inside "$name" sh -c "sed -i '/\[extras-common\]/a baseurl=https://mirror.stream.centos.org/SIGs/9-stream/extras/x86_64/extras-common' ${CENTOS_EXTRAS_REPO}" - inside "$name" sh -c "dnf install -y 'dnf-command(config-manager)'" - inside "$name" sh -c "dnf config-manager --set-enabled crb" - inside "$name" sh -c "dnf config-manager --set-disabled epel-cisco-openh264" || true + inside "$name" sh -c "sed -i '/\[extras-common\]/a baseurl=https://mirror.stream.centos.org/SIGs/9-stream/extras/x86_64/extras-common' ${CENTOS_EXTRAS_REPO}" + inside "$name" sh -c "dnf install -y 'dnf-command(config-manager)'" + inside "$name" sh -c "dnf config-manager --set-enabled crb" + inside "$name" sh -c "dnf config-manager --set-disabled epel-cisco-openh264" || true fi - fi + fi else debug 1 "do not know how to configure proxy on $OS_NAME" fi @@ -391,7 +425,7 @@ start_instance() { launch_flags=() [ "$use_vm" == true ] && launch_flags+=(--vm) $LXC launch "$src" "$name" "${launch_flags[@]}" || { - errorrc "Failed to start container '$name' from '$src'"; + errorrc "Failed to start container '$name' from '$src'" return } CONTAINER=$name @@ -407,13 +441,13 @@ run_self_inside() { # run_self_inside(container, args) local name="$1" shift - inside "$name" bash -s "$@" <"$0" + inside "$name" bash -s "$@" < "$0" } run_self_inside_as_cd() { local name="$1" user="$2" dir="$3" shift 3 - inside_as_cd "$name" "$user" "$dir" bash -s "$@" <"$0" + inside_as_cd "$name" "$user" "$dir" bash -s "$@" < "$0" } main() { @@ -423,7 +457,10 @@ main() { getopt_out=$(getopt --name "${0##*/}" \ --options "${short_opts}" --long "${long_opts}" -- "$@") && eval set -- "${getopt_out}" || - { bad_Usage; return; } + { + bad_Usage + return + } local cur="" next="" local package=false srcpackage=false unittest="" name="" @@ -431,31 +468,50 @@ main() { local use_vm=false while [ $# -ne 0 ]; do - cur="${1:-}"; next="${2:-}"; + cur="${1:-}" + next="${2:-}" case "$cur" in - -a|--artifacts) artifact_d="$next";; - --dirty) dirty=true;; - -h|--help) Usage ; exit 0;; - -k|--keep) KEEP=true;; - -n|--name) name="$next"; shift;; - -p|--package) package=true;; - -s|--source-package) srcpackage=true;; - -u|--unittest) unittest=1;; - -v|--verbose) VERBOSITY=$((VERBOSITY+1));; - --vm) use_vm=true;; - --wait-max) WAIT_MAX="$next"; shift;; - --commitish) COMMITISH="$next"; shift;; - --) shift; break;; + -a | --artifacts) artifact_d="$next" ;; + --dirty) dirty=true ;; + -h | --help) + Usage + exit 0 + ;; + -k | --keep) KEEP=true ;; + -n | --name) + name="$next" + shift + ;; + -p | --package) package=true ;; + -s | --source-package) srcpackage=true ;; + -u | --unittest) unittest=1 ;; + -v | --verbose) VERBOSITY=$((VERBOSITY + 1)) ;; + --vm) use_vm=true ;; + --wait-max) + WAIT_MAX="$next" + shift + ;; + --commitish) + COMMITISH="$next" + shift + ;; + --) + shift + break + ;; esac - shift; + shift done COMMITISH=${COMMITISH:-HEAD} - [ $# -eq 1 ] || { bad_Usage "Expected 1 arg, got $# ($*)"; return; } + [ $# -eq 1 ] || { + bad_Usage "Expected 1 arg, got $# ($*)" + return + } local img_ref_in="$1" case "${img_ref_in}" in - *:*) img_ref="${img_ref_in}";; - *) img_ref="images:${img_ref_in}";; + *:*) img_ref="${img_ref_in}" ;; + *) img_ref="images:${img_ref_in}" ;; esac # program starts here @@ -476,18 +532,30 @@ main() { trap cleanup EXIT start_instance "$img_ref" "$name" "$use_vm" || - { errorrc "Failed to start container for $img_ref"; return; } + { + errorrc "Failed to start container for $img_ref" + return + } get_os_info_in "$name" || - { errorrc "failed to get os_info in $name"; return; } + { + errorrc "failed to get os_info in $name" + return + } # prep the container (install very basic dependencies) run_self_inside "$name" prep || - { errorrc "Failed to prep container $name"; return; } + { + errorrc "Failed to prep container $name" + return + } # add the user inside "$name" useradd "$user" --create-home "--home-dir=$home" || - { errorrc "Failed to add user '$user' in '$name'"; return 1; } + { + errorrc "Failed to add user '$user' in '$name'" + return 1 + } debug 1 "inserting cloud-init" inject_cloud_init "$name" "$user" "$dirty" || { @@ -501,36 +569,38 @@ main() { return } - local errors=( ) + local errors=() inside_as_cd "$name" "$user" "$cdir" git status || { errorrc "git checkout failed." - errors[${#errors[@]}]="git checkout"; + errors[${#errors[@]}]="git checkout" } if [ -n "$unittest" ]; then debug 1 "running unit tests." run_self_inside_as_cd "$name" "$user" "$cdir" pytest \ tests/unittests cloudinit/ || { - errorrc "pytest failed."; - errors[${#errors[@]}]="pytest" - } + errorrc "pytest failed." + errors[${#errors[@]}]="pytest" + } fi local build_pkg="" build_srcpkg="" pkg_ext="" distflag="" case "$OS_NAME" in - centos|rocky*|fedora) distflag="--distro=redhat";; - opensuse*) distflag="--distro=suse";; + centos | rocky* | fedora) distflag="--distro=redhat" ;; + opensuse*) distflag="--distro=suse" ;; esac case "$OS_NAME" in - debian|ubuntu) - build_pkg="./packages/bddeb -d" + debian | ubuntu) + build_pkg="./packages/bddeb -d" build_srcpkg="./packages/bddeb -S -d" - pkg_ext=".deb";; - centos|opensuse*|rocky*|fedora) + pkg_ext=".deb" + ;; + centos | opensuse* | rocky* | fedora) build_pkg="./packages/brpm $distflag" build_srcpkg="./packages/brpm $distflag --srpm" - pkg_ext=".rpm";; + pkg_ext=".rpm" + ;; esac if [ "$srcpackage" = "true" ]; then [ -n "$build_srcpkg" ] || { @@ -540,7 +610,7 @@ main() { debug 1 "building source package with $build_srcpkg." # shellcheck disable=SC2086 inside_as_cd "$name" "$user" "$cdir" python3 $build_srcpkg || { - errorrc "failed: $build_srcpkg"; + errorrc "failed: $build_srcpkg" errors[${#errors[@]}]="source package" } fi @@ -553,7 +623,7 @@ main() { debug 1 "building binary package with $build_pkg." # shellcheck disable=SC2086 inside_as_cd "$name" "$user" "$cdir" python3 $build_pkg || { - errorrc "failed: $build_pkg"; + errorrc "failed: $build_pkg" errors[${#errors[@]}]="binary package" } fi @@ -588,6 +658,10 @@ main() { } case "${1:-}" in - prep|os_info|wait_inside|pytest) _n=$1; shift; "$_n" "$@";; - *) main "$@";; + prep | os_info | wait_inside | pytest) + _n=$1 + shift + "$_n" "$@" + ;; + *) main "$@" ;; esac diff --git a/tools/run-lint b/tools/run-lint deleted file mode 100755 index 2bd0ab17ac9..00000000000 --- a/tools/run-lint +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -# This file runs flake8 for compatibility's sake. As soon as we move off python 3.6, this should be changed to use ruff. - -CR=" -" -pycheck_dirs=( "cloudinit/" "tests/" "tools/" "setup.py" ) - -set -f -if [ $# -eq 0 ]; then - files=( "${pycheck_dirs[@]}" ) -else - files=( "$@" ) -fi - -if [ -z "$PYTHON" ]; then - PYTHON="python3" -fi -cmd=( "$PYTHON" -m "flake8" "${files[@]}" ) - -echo "Running: " "${cmd[@]}" 1>&2 -exec "${cmd[@]}" diff --git a/tools/tox-venv b/tools/tox-venv deleted file mode 100755 index c22f6faca4d..00000000000 --- a/tools/tox-venv +++ /dev/null @@ -1,183 +0,0 @@ -#!/bin/sh -# https://gist.github.com/smoser/2d4100a6a5d230ca937f - -CR=' -' -error() { echo "$@" 1>&2; } -fail() { [ $# -eq 0 ] || error "$@"; exit 1; } -get_env_dirs() { - # read 'tox --showconfig'. return list of - # envname:dir - local key="" equal="" val="" curenv="" out="" - while read key equal val; do - case "$key" in - "[testenv:"*) - curenv=${key#*:}; - curenv=${curenv%%"]"*}; - continue;; - esac - if [ "${key#*=}" != "$key" ]; then - # older tox shows key=value or key= value - # newer tox shows: key = value - key=${key%%=*} - val=${equal} - fi - [ "$key" = "envdir" ] || [ "$key" = "env_dir" ] || continue - out="${out:+${out}${CR}}${curenv}:$val" - done - echo "$out" -} - -load_config() { - local tox_ini="$1" out="" envs="" - if [ "$tox_ini" = "${CACHED_ENVS_INI}" ]; then - _RET="$CACHED_ENVS" - return - fi - out=$(tox -c "$tox_ini" --showconfig) || return 1 - envs=$(echo "$out" | get_env_dirs) || return 1 - CACHED_ENVS="$envs" - CACHED_ENVS_INI="$tox_ini" - _RET="$envs" -} - -list_environments() { - local tox_ini="$1" prefix=" " out="" envs="" oifs="$IFS" - load_config "$tox_ini" || return 1 - envs="${_RET}" - IFS="$CR" - for d in ${envs}; do - env=${d%%:*} - dir=${d#*:} - [ -f "$dir/bin/activate" ] && s="*" || s="" - echo "${prefix}$env$s"; - done - IFS="$oifs" -} - -get_command() { - local tox_ini="$1" env="$2" out="" - shift 2 - out=$( - sed -e ':x; /\\$/ { N; s/\\\n[ ]*//; tx };' "${tox_ini}" | - gawk ' - $1 ~ /^\[testenv.*\]/ { - name=$1; - sub("\\[", "", name); sub(".*:", "", name); - sub("].*", "", name); - curenv=name; }; - $1 == "basepython" && (name == "testenv" || name == n) { python=$3 } - $1 == "commands" && (name == "testenv" || name == n) { - sub("commands = ", ""); cmd = $0; }; - END { - sub("{envpython}", python, cmd); - sub("{toxinidir}", toxinidir, cmd); - if (inargs == "") replacement = "\\1" - else replacement = inargs - cmd = gensub(/{posargs:?([^}]*)}/, replacement, "global", cmd) - print(cmd); - }' n="$env" toxinidir="$(dirname $tox_ini)" inargs="$*") - if [ -z "$out" ]; then - error "Failed to find command for $env in $tox_ini" - return 1 - fi - echo "$out" -} - -get_env_dir() { - local tox_ini="$1" env="$2" oifs="$IFS" t="" d="" envs="" - if [ "${TOX_VENV_SHORTCUT:-1}" != "0" ]; then - local stox_d="${tox_ini%/*}/.tox/${env}" - if [ -e "${stox_d}/bin/activate" ]; then - _RET="${stox_d}" - return - fi - fi - load_config "$tox_ini" && envs="$_RET" || return 1 - IFS="$CR" - for t in $envs; do - [ "$env" = "${t%%:*}" ] && d="${t#*:}" && break - done - IFS=${oifs} - [ -n "$d" ] || return 1 - _RET="$d" -} - -Usage() { - local tox_ini="$1" - cat <&2; exit 1; } -[ "$1" = "-h" -o "$1" = "--help" ] && { Usage "$tox_ini"; exit 0; } - -[ -f "$tox_ini" ] || fail "$tox_ini: did not find tox.ini" - -if [ "$1" = "-l" -o "$1" = "--list" ]; then - list_environments "$tox_ini" - exit -fi - -nocreate="false" -if [ "$1" = "--no-create" ]; then - nocreate="true" - shift -fi - -env="$1" -shift -[ "$1" = "--" ] && shift -get_env_dir "$tox_ini" "$env" && activate="$_RET/bin/activate" || activate="" - -if [ -z "$activate" -o ! -f "$activate" ]; then - if $nocreate; then - fail "tox env '$env' did not exist, and no-create specified" - elif [ -n "$activate" ]; then - error "attempting to create $env:" - error " tox -c $tox_ini --recreate --notest -e $env" - tox -c "$tox_ini" --recreate --notest -e "$env" || - fail "failed creation of env $env" - else - error "$env: not a valid tox environment?" - error "found tox_ini=$tox_ini" - error "try one of:" - list_environments "$tox_ini" 1>&2 - fail - fi -fi -. "$activate" - -[ $# -eq 0 ] && set -- cmd -if [ "$1" = "cmd" -o "$1" = "-" ]; then - shift - out=$(get_command "$tox_ini" "$env" "$@") || exit - eval set -- "$out" -fi -echo "inside tox:$env running: $*" 1>&2 -debian_chroot="tox:$env" exec "$@" diff --git a/tools/uncloud-init b/tools/uncloud-init index 7900ab73229..68dfa3a6b14 100755 --- a/tools/uncloud-init +++ b/tools/uncloud-init @@ -14,122 +14,156 @@ MARK=/var/lib/cloud/sem/uncloud-init.once ROOT_RW="" doexec() { - if [ -n "$ROOT_RW" ]; then - mkdir -p "${MARK%/*}"; - date > "${MARK}"; - fi - cleanup; - log "invoking /sbin/init $*" - exec /sbin/init "$@"; + if [ -n "$ROOT_RW" ]; then + mkdir -p "${MARK%/*}" + date > "${MARK}" + fi + cleanup + log "invoking /sbin/init $*" + exec /sbin/init "$@" } log() { echo "::${0##*/}:" "$@"; } cleanup() { - [ -z "${UMOUNT}" ] || { umount "${UMOUNT}" && unset UMOUNT; } - [ -z "${RMDIR}" ] || { rm -Rf "${RMDIR}" && unset RMDIR; } - [ -z "${ROOT_RW}" ] || { mount -o remount,ro / ; unset ROOT_RW; } + [ -z "${UMOUNT}" ] || { umount "${UMOUNT}" && unset UMOUNT; } + [ -z "${RMDIR}" ] || { rm -Rf "${RMDIR}" && unset RMDIR; } + [ -z "${ROOT_RW}" ] || { + mount -o remount,ro / + unset ROOT_RW + } } updateFrom() { - local dev=$1 fmt=$2 - local mp=""; - - [ "${fmt}" = "tar" -o "${fmt}" = "mnt" ] || - { log FAIL "unknown format ${fmt}"; return 1; } - - log INFO "updating from ${dev} format ${fmt}" - [ ! -e "${dev}" -a -e "/dev/${dev}" ] && dev="/dev/${dev}" - [ -e "${dev}" ] || { echo "no file $dev"; return 2; } - - mp=$(mktemp -d "${TEMPDIR:-/tmp}/update.XXXXXX") && - RMDIR="${mp}" || - { log FAIL "failed to mktemp"; return 1; } - - if [ "$fmt" = "tar" ]; then - dd "if=${dev}" | ( tar -C "${mp}" -xf - ) || - { log FAIL "failed to extract ${dev}"; return 1; } - elif [ "$fmt" = "mnt" ]; then - mount -o ro "${dev}" "${mp}" && UMOUNT=${mp} || - { log FAIL "failed mount ${mp}"; return 1; } - else - log FAIL "unknown format ${fmt}"; return 1; - fi - - if [ -d "${mp}/updates" ]; then - rsync -av "${mp}/updates/" "/" || - { log FAIL "failed rsync updates/ /"; return 1; } - fi - if [ -f "${mp}/updates.tar" ]; then - tar -C / -xvf "${mp}/updates.tar" || - { log FAIL "failed tar -C / -xvf ${mp}/updates.tar"; return 1; } - fi - script="${mp}/updates.script" - if [ -f "${script}" -a -x "${script}" ]; then - MP_DIR=${mp} "${mp}/updates.script" || - { log FAIL "failed to run updates.script"; return 1; } - fi + local dev=$1 fmt=$2 + local mp="" + + [ "${fmt}" = "tar" -o "${fmt}" = "mnt" ] || + { + log FAIL "unknown format ${fmt}" + return 1 + } + + log INFO "updating from ${dev} format ${fmt}" + [ ! -e "${dev}" -a -e "/dev/${dev}" ] && dev="/dev/${dev}" + [ -e "${dev}" ] || { + echo "no file $dev" + return 2 + } + + mp=$(mktemp -d "${TEMPDIR:-/tmp}/update.XXXXXX") && + RMDIR="${mp}" || + { + log FAIL "failed to mktemp" + return 1 + } + + if [ "$fmt" = "tar" ]; then + dd "if=${dev}" | (tar -C "${mp}" -xf -) || + { + log FAIL "failed to extract ${dev}" + return 1 + } + elif [ "$fmt" = "mnt" ]; then + mount -o ro "${dev}" "${mp}" && UMOUNT=${mp} || + { + log FAIL "failed mount ${mp}" + return 1 + } + else + log FAIL "unknown format ${fmt}" + return 1 + fi + + if [ -d "${mp}/updates" ]; then + rsync -av "${mp}/updates/" "/" || + { + log FAIL "failed rsync updates/ /" + return 1 + } + fi + if [ -f "${mp}/updates.tar" ]; then + tar -C / -xvf "${mp}/updates.tar" || + { + log FAIL "failed tar -C / -xvf ${mp}/updates.tar" + return 1 + } + fi + script="${mp}/updates.script" + if [ -f "${script}" -a -x "${script}" ]; then + MP_DIR=${mp} "${mp}/updates.script" || + { + log FAIL "failed to run updates.script" + return 1 + } + fi } -fail() { { [ $# -eq 0 ] && log "FAILING" ; } || log "$@"; exit 1; } +fail() { + { [ $# -eq 0 ] && log "FAILING"; } || log "$@" + exit 1 +} -[ -s "$MARK" ] && { log "already updated" ; doexec "$@"; } +[ -s "$MARK" ] && { + log "already updated" + doexec "$@" +} mount -o remount,rw / || fail "failed to mount rw" ROOT_RW=1 if [ ! -e /proc/cmdline ]; then - mount -t proc /proc /proc - read cmdline < /proc/cmdline - umount /proc + mount -t proc /proc /proc + read cmdline < /proc/cmdline + umount /proc else - read cmdline < /proc/cmdline + read cmdline < /proc/cmdline fi ubuntu_pass="" for x in ${cmdline}; do - case "$x" in - ${KEY}=*) - val=${x#${KEY}=} - dev=${val%:*} - [ "${dev}" = "${val}" ] && fmt="" || fmt=${val#${dev}:} - log "update from ${dev},${fmt}" - updateFrom "${dev}" "${fmt}" || fail "update failed" - log "end update ${dev},${fmt}" - ;; - ubuntu-pass=*|ubuntu_pass=*) ubuntu_pass=${x#*=};; - helpmount) helpmount=1;; - root=*) rootspec=${x#root=};; - esac + case "$x" in + ${KEY}=*) + val=${x#${KEY}=} + dev=${val%:*} + [ "${dev}" = "${val}" ] && fmt="" || fmt=${val#${dev}:} + log "update from ${dev},${fmt}" + updateFrom "${dev}" "${fmt}" || fail "update failed" + log "end update ${dev},${fmt}" + ;; + ubuntu-pass=* | ubuntu_pass=*) ubuntu_pass=${x#*=} ;; + helpmount) helpmount=1 ;; + root=*) rootspec=${x#root=} ;; + esac done if [ "${ubuntu_pass}" = "R" -o "${ubuntu_pass}" = "random" ]; then - ubuntu_pass=$(python -c 'import string, random; + ubuntu_pass=$(python -c 'import string, random; random.seed(); print "".join(random.sample(string.letters+string.digits, 8))') - log "setting ubuntu pass = ${ubuntu_pass}" - printf "\n===\nubuntu_pass = %s\n===\n" "${ubuntu_pass}" >/dev/ttyS0 + log "setting ubuntu pass = ${ubuntu_pass}" + printf "\n===\nubuntu_pass = %s\n===\n" "${ubuntu_pass}" > /dev/ttyS0 fi [ -z "${ubuntu_pass}" ] || - printf "ubuntu:%s\n" "${ubuntu_pass}" > /root/ubuntu-user-pass + printf "ubuntu:%s\n" "${ubuntu_pass}" > /root/ubuntu-user-pass if [ -e /root/ubuntu-user-pass ]; then - log "changing ubuntu user's password!" - chpasswd < /root/ubuntu-user-pass || - log "FAIL: failed changing pass" + log "changing ubuntu user's password!" + chpasswd < /root/ubuntu-user-pass || + log "FAIL: failed changing pass" fi cp /etc/init/tty2.conf /etc/init/ttyS0.conf && - sed -i s,tty2,ttyS0,g /etc/init/ttyS0.conf 2>/dev/null && - log "enabled console on ttyS0" + sed -i s,tty2,ttyS0,g /etc/init/ttyS0.conf 2> /dev/null && + log "enabled console on ttyS0" pa=PasswordAuthentication -sed -i "s,${pa} no,${pa} yes," /etc/ssh/sshd_config 2>/dev/null && - log "enabled passwd auth in ssh" || - log "failed to enable passwd ssh" +sed -i "s,${pa} no,${pa} yes," /etc/ssh/sshd_config 2> /dev/null && + log "enabled passwd auth in ssh" || + log "failed to enable passwd ssh" grep -q vga16fb /etc/modprobe.d/blacklist.conf || { - echo "blacklist vga16fb" >> /etc/modprobe.d/blacklist.conf && - log "blacklisted vga16fb" + echo "blacklist vga16fb" >> /etc/modprobe.d/blacklist.conf && + log "blacklisted vga16fb" } #lstr="${rootspec}" diff --git a/tools/write-ssh-key-fingerprints b/tools/write-ssh-key-fingerprints index 9409257dba0..55711d1da24 100755 --- a/tools/write-ssh-key-fingerprints +++ b/tools/write-ssh-key-fingerprints @@ -1,7 +1,6 @@ #!/bin/sh # This file is part of cloud-init. See LICENSE file for license information. - do_syslog() { log_message=$1 @@ -17,7 +16,6 @@ do_syslog() { logger $logger_opts "$log_message" } - # Redirect stderr to stdout exec 2>&1 diff --git a/tools/xkvm b/tools/xkvm deleted file mode 100755 index b030dc43f05..00000000000 --- a/tools/xkvm +++ /dev/null @@ -1,707 +0,0 @@ -#!/bin/bash -# This file is part of cloud-init. -# See LICENSE file for copyright and license info. - -set -f - -VERBOSITY=0 -KVM_PID="" -DRY_RUN=false -TEMP_D="" -DEF_BRIDGE="virbr0" -TAPDEVS=( ) -# OVS_CLEANUP gets populated with bridge:devname pairs used with ovs -OVS_CLEANUP=( ) -MAC_PREFIX="52:54:00:12:34" -# allow this to be set externally. -_QEMU_SUPPORTS_FILE_LOCKING="${_QEMU_SUPPORTS_FILE_LOCKING}" -KVM="kvm" -declare -A KVM_DEVOPTS - -error() { echo "$@" 1>&2; } -fail() { [ $# -eq 0 ] || error "$@"; exit 1; } - -bad_Usage() { Usage 1>&2; [ $# -eq 0 ] || error "$@"; exit 1; } -randmac() { - # return random mac addr within final 3 tokens - local random="" - random=$(printf "%02x:%02x:%02x" \ - "$((${RANDOM}%256))" "$((${RANDOM}%256))" "$((${RANDOM}%256))") - padmac "$random" -} - -cleanup() { - [ -z "${TEMP_D}" -o ! -d "${TEMP_D}" ] || rm -Rf "${TEMP_D}" - [ -z "${KVM_PID}" ] || kill "$KVM_PID" - if [ ${#TAPDEVS[@]} -ne 0 ]; then - local name item - for item in "${TAPDEVS[@]}"; do - [ "${item}" = "skip" ] && continue - debug 1 "removing" "$item" - name="${item%:*}" - if $DRY_RUN; then - error ip tuntap del mode tap "$name" - else - ip tuntap del mode tap "$name" - fi - [ $? -eq 0 ] || error "failed removal of $name" - done - if [ ${#OVS_CLEANUP[@]} -ne 0 ]; then - # with linux bridges, there seems to be no harm in just deleting - # the device (not detaching from the bridge). However, with - # ovs, you have to remove them from the bridge, or later it - # will refuse to add the same name. - error "cleaning up ovs ports: ${OVS_CLEANUP[@]}" - if ${DRY_RUN}; then - error sudo "$0" tap-control ovs-cleanup "${OVS_CLEANUP[@]}" - else - sudo "$0" tap-control ovs-cleanup "${OVS_CLEANUP[@]}" - fi - fi - fi -} - -debug() { - local level=${1}; shift; - [ "${level}" -gt "${VERBOSITY}" ] && return - error "${@}" -} - -Usage() { - cat <&1) && - out=$(echo "$out" | sed -e "s,[^.]*[.],," -e 's,=.*,,') && - KVM_DEVOPTS[$model]="$out" || - { error "bad device model $model?"; exit 1; } - fi - opts=( ${KVM_DEVOPTS[$model]} ) - for opt in "${opts[@]}"; do - [ "$input" = "$opt" ] && return 0 - done - return 1 -} - -qemu_supports_file_locking() { - # hackily check if qemu has file.locking in -drive params (LP: #1716028) - if [ -z "$_QEMU_SUPPORTS_FILE_LOCKING" ]; then - # The only way we could find to check presence of file.locking is - # qmp (query-qmp-schema). Simply checking if the virtio-blk driver - # supports 'share-rw' is expected to be equivalent and simpler. - isdevopt virtio-blk share-rw && - _QEMU_SUPPORTS_FILE_LOCKING=true || - _QEMU_SUPPORTS_FILE_LOCKING=false - debug 1 "qemu supports file locking = ${_QEMU_SUPPORTS_FILE_LOCKING}" - fi - [ "$_QEMU_SUPPORTS_FILE_LOCKING" = "true" ] - return -} - -padmac() { - # return a full mac, given a subset. - # assume whatever is input is the last portion to be - # returned, and fill it out with entries from MAC_PREFIX - local mac="$1" num="$2" prefix="${3:-$MAC_PREFIX}" itoks="" ptoks="" - # if input is empty set to :$num - [ -n "$mac" ] || mac=$(printf "%02x" "$num") || return - itoks=( ${mac//:/ } ) - ptoks=( ${prefix//:/ } ) - rtoks=( ) - for r in ${ptoks[@]:0:6-${#itoks[@]}} ${itoks[@]}; do - rtoks[${#rtoks[@]}]="0x$r" - done - _RET=$(printf "%02x:%02x:%02x:%02x:%02x:%02x" "${rtoks[@]}") -} - -make_nics_Usage() { - cat <: for each tap created - # type is one of "ovs" or "brctl" - local short_opts="v" - local long_opts="--verbose" - local getopt_out="" - getopt_out=$(getopt --name "${0##*/} make-nics" \ - --options "${short_opts}" --long "${long_opts}" -- "$@") && - eval set -- "${getopt_out}" || { make_nics_Usage 1>&2; return 1; } - - local cur="" next="" - while [ $# -ne 0 ]; do - cur=${1}; next=${2}; - case "$cur" in - -v|--verbose) VERBOSITY=$((${VERBOSITY}+1));; - --) shift; break;; - esac - shift; - done - - [ $# -ne 0 ] || { - make_nics_Usage 1>&2; error "must give bridge"; - return 1; - } - - local owner="" ovsbrs="" tap="" tapnum="0" brtype="" bridge="" - [ "$(id -u)" = "0" ] || { error "must be root for make-nics"; return 1; } - owner="${SUDO_USER:-root}" - ovsbrs="" - if command -v ovs-vsctl >/dev/null 2>&1; then - out=$(ovs-vsctl list-br) - out=$(echo "$out" | sed "s/\n/,/") - ovsbrs=",$out," - fi - for bridge in "$@"; do - [ "$bridge" = "user" ] && echo skip && continue - [ "${ovsbrs#*,${bridge},}" != "$ovsbrs" ] && - btype="ovs" || btype="brctl" - tapnum=0; - while [ -e /sys/class/net/tapvm$tapnum ]; do tapnum=$(($tapnum+1)); done - tap="tapvm$tapnum" - debug 1 "creating $tap:$btype on $bridge" 1>&2 - ip tuntap add mode tap user "$owner" "$tap" || - { error "failed to create tap '$tap' for '$owner'"; return 1; } - ip link set "$tap" up 1>&2 || { - error "failed to bring up $tap"; - ip tuntap del mode tap "$tap"; - return 1; - } - if [ "$btype" = "ovs" ]; then - ovs-vsctl add-port "$bridge" "$tap" 1>&2 || { - error "failed: ovs-vsctl add-port $bridge $tap"; - ovs-vsctl del-port "$bridge" "$tap" - return 1; - } - else - ip link set "$tap" master "$bridge" 1>&2 || { - error "failed to add tap '$tap' to '$bridge'" - ip tuntap del mode tap "$tap"; - return 1 - } - fi - echo "$tap:$btype" - done -} - -ovs_cleanup() { - [ "$(id -u)" = "0" ] || - { error "must be root for ovs-cleanup"; return 1; } - local item="" errors=0 - # TODO: if get owner (SUDO_USERNAME) and if that isn't - # the owner, then do not delete. - for item in "$@"; do - name=${item#*:} - bridge=${item%:*} - ovs-vsctl del-port "$bridge" "$name" || errors=$((errors+1)) - done - return $errors -} - -quote_cmd() { - local quote='"' x="" vline="" - for x in "$@"; do - if [ "${x#* }" != "${x}" ]; then - if [ "${x#*$quote}" = "${x}" ]; then - x="\"$x\"" - else - x="'$x'" - fi - fi - vline="${vline} $x" - done - echo "$vline" -} - -get_bios_opts() { - # get_bios_opts(bios, uefi, nvram) - # bios is a explicit bios to boot. - # uefi is boolean indicating uefi - # nvram is optional and indicates that ovmf vars should be copied - # to that file if it does not exist. if it exists, use it. - local bios="$1" uefi="${2:-false}" nvram="$3" - local ovmf_dir="/usr/share/OVMF" - local bios_opts="" pflash_common="if=pflash,format=raw" - unset _RET - _RET=( ) - if [ -n "$bios" ]; then - _RET=( -drive "${pflash_common},file=$bios" ) - return 0 - elif ! $uefi; then - return 0 - fi - - # ovmf in older releases (14.04) shipped only a single file - # /usr/share/ovmf/OVMF.fd - # newer ovmf ships split files - # /usr/share/OVMF/OVMF_CODE.fd - # /usr/share/OVMF/OVMF_VARS.fd - # with single file, pass only one file and read-write - # with split, pass code as readonly and vars as read-write - local joined="/usr/share/ovmf/OVMF.fd" - local code="/usr/share/OVMF/OVMF_CODE.fd" - local vars="/usr/share/OVMF/OVMF_VARS.fd" - local split="" nvram_src="" - if [ -e "$code" -o -e "$vars" ]; then - split=true - nvram_src="$vars" - elif [ -e "$joined" ]; then - split=false - nvram_src="$joined" - elif [ -n "$nvram" -a -e "$nvram" ]; then - error "WARN: nvram given, but did not find expected ovmf files." - error " assuming this is code and vars (OVMF.fd)" - split=false - else - error "uefi support requires ovmf bios: apt-get install -qy ovmf" - return 1 - fi - - if [ -n "$nvram" ]; then - if [ ! -f "$nvram" ]; then - cp "$nvram_src" "$nvram" || - { error "failed copy $nvram_src to $nvram"; return 1; } - debug 1 "copied $nvram_src to $nvram" - fi - else - debug 1 "uefi without --uefi-nvram storage." \ - "nvram settings likely will not persist." - nvram="${nvram_src}" - fi - - if [ ! -w "$nvram" ]; then - debug 1 "nvram file ${nvram} is readonly" - nvram_ro="readonly" - fi - - if $split; then - # to ensure bootability firmware must be first, then variables - _RET=( -drive "${pflash_common},file=$code,readonly" ) - fi - _RET=( "${_RET[@]}" - -drive "${pflash_common},file=$nvram${nvram_ro:+,${nvram_ro}}" ) -} - -main() { - local short_opts="hd:n:v" - local long_opts="bios:,help,dowait,disk:,dry-run,kvm:,no-dowait,netdev:,uefi,uefi-nvram:,verbose" - local getopt_out="" - getopt_out=$(getopt --name "${0##*/}" \ - --options "${short_opts}" --long "${long_opts}" -- "$@") && - eval set -- "${getopt_out}" || { bad_Usage; return 1; } - - local bridge="$DEF_BRIDGE" oifs="$IFS" - local netdevs="" need_tap="" ret="" p="" i="" pt="" cur="" conn="" - local kvm="" kvmcmd="" archopts="" - local def_disk_driver=${DEF_DISK_DRIVER:-"virtio-blk"} - local def_netmodel=${DEF_NETMODEL:-"virtio-net-pci"} - local bios="" uefi=false uefi_nvram="" - - archopts=( ) - kvmcmd=( ) - netdevs=( ) - addargs=( ) - diskdevs=( ) - diskargs=( ) - - # dowait: run qemu-system with a '&' and then 'wait' on the pid. - # the reason to do this or not do this has to do with interactivity - # if detached with &, then user input will not go to xkvm. - # if *not* detached, then signal handling is blocked until - # the foreground subprocess returns. which means we can't handle - # a sigterm and kill the qemu-system process. - # We default to dowait=false if input and output are a terminal - local dowait="" - [ -t 0 -a -t 1 ] && dowait=false || dowait=true - while [ $# -ne 0 ]; do - cur=${1}; next=${2}; - case "$cur" in - -h|--help) Usage; exit 0;; - -d|--disk) - diskdevs[${#diskdevs[@]}]="$next"; shift;; - --dry-run) DRY_RUN=true;; - --kvm) kvm="$next"; shift;; - -n|--netdev) - netdevs[${#netdevs[@]}]=$next; shift;; - -v|--verbose) VERBOSITY=$((${VERBOSITY}+1));; - --dowait) dowait=true;; - --no-dowait) dowait=false;; - --bios) bios="$next"; shift;; - --uefi) uefi=true;; - --uefi-nvram) uefi=true; uefi_nvram="$next"; shift;; - --) shift; break;; - esac - shift; - done - - [ ${#netdevs[@]} -eq 0 ] && netdevs=( "${DEF_BRIDGE}" ) - pt=( "$@" ) - - local kvm_pkg="" virtio_scsi_bus="virtio-scsi-pci" virtio_rng_device="virtio-rng-pci" - [ -n "$kvm" ] && kvm_pkg="none" - case $(uname -m) in - i?86) - [ -n "$kvm" ] || - { kvm="qemu-system-i386"; kvm_pkg="qemu-system-x86"; } - ;; - x86_64) - [ -n "$kvm" ] || - { kvm="qemu-system-x86_64"; kvm_pkg="qemu-system-x86"; } - ;; - s390x) - [ -n "$kvm" ] || - { kvm="qemu-system-s390x"; kvm_pkg="qemu-system-misc"; } - def_netmodel=${DEF_NETMODEL:-"virtio-net-ccw"} - # disable virtio-scsi-bus - virtio_scsi_bus="virtio-scsi-ccw" - virtio_blk_bus="virtio-blk-ccw" - virtio_rng_device="virtio-rng-ccw" - ;; - ppc64*) - [ -n "$kvm" ] || - { kvm="qemu-system-ppc64"; kvm_pkg="qemu-system-ppc"; } - def_netmodel="virtio-net-pci" - # virtio seems functional on in 14.10, but might want scsi here - #def_diskif="scsi" - archopts=( "${archopts[@]}" -machine pseries,usb=off ) - archopts=( "${archopts[@]}" -device spapr-vscsi ) - ;; - *) kvm=qemu-system-$(uname -m);; - esac - KVM="$kvm" - kvmcmd=( $kvm -enable-kvm ) - - local bios_opts="" - if [ -n "$bios" ] && $uefi; then - error "--uefi (or --uefi-nvram) is incompatible with --bios" - return 1 - fi - get_bios_opts "$bios" "$uefi" "$uefi_nvram" || - { error "failed to get bios opts"; return 1; } - bios_opts=( "${_RET[@]}" ) - - local out="" fmt="" bus="" unit="" index="" serial="" driver="" devopts="" - local busorindex="" driveopts="" cur="" val="" file="" wwn="" - for((i=0;i<${#diskdevs[@]};i++)); do - cur=${diskdevs[$i]} - IFS=","; set -- $cur; IFS="$oifs" - driver="" - id=$(printf "disk%02d" "$i") - file="" - fmt="" - bus="" - unit="" - index="" - serial="" - wwn="" - for tok in "$@"; do - [ "${tok#*=}" = "${tok}" -a -f "${tok}" -a -z "$file" ] && file="$tok" - val=${tok#*=} - case "$tok" in - driver=*) driver=$val;; - if=virtio) driver=virtio-blk;; - if=scsi) driver=scsi-hd;; - if=pflash) driver=;; - if=sd|if=mtd|floppy) fail "do not know what to do with $tok on $cur";; - id=*) id=$val;; - file=*) file=$val;; - fmt=*|format=*) fmt=$val;; - serial=*) serial=$val;; - wwn=*) wwn=$val;; - bus=*) bus=$val;; - unit=*) unit=$val;; - index=*) index=$val;; - esac - done - [ -z "$file" ] && fail "did not read a file from $cur" - if [ -f "$file" -a -z "$fmt" ]; then - out=$(LANG=C qemu-img info "$file") && - fmt=$(echo "$out" | awk '$0 ~ /^file format:/ { print $3 }') || - { error "failed to determine format of $file"; return 1; } - elif [ -z "$fmt" ]; then - fmt=raw - fi - if [ -z "$driver" ]; then - driver="$def_disk_driver" - fi - if [ -z "$serial" ]; then - # use filename as serial if not provided a wwn - if [ -n "$wwn" ]; then - serial="$wwn" - else - serial="${file##*/}" - fi - fi - - # make sure we add either bus= or index= - if [ -n "$bus" -o "$unit" ] && [ -n "$index" ]; then - fail "bus and index cant be specified together: $cur" - elif [ -z "$bus" -a -z "$unit" -a -z "$index" ]; then - index=$i - elif [ -n "$bus" -a -z "$unit" ]; then - unit=$i - fi - - busorindex="${bus:+bus=$bus,unit=$unit}${index:+index=${index}}" - diskopts="file=${file},id=$id,if=none,format=$fmt,$busorindex" - devopts="$driver,drive=$id${serial:+,serial=${serial}}" - for tok in "$@"; do - case "$tok" in - id=*|if=*|driver=*|$file|file=*) continue;; - fmt=*|format=*) continue;; - serial=*|bus=*|unit=*|index=*) continue;; - file.locking=*) - qemu_supports_file_locking || { - debug 2 "qemu has no file locking." \ - "Dropping '$tok' from: $cur" - continue - };; - esac - isdevopt "$driver" "$tok" && devopts="${devopts},$tok" || - diskopts="${diskopts},${tok}" - done - case $driver in - virtio-blk-ccw) - # disable scsi when using virtio-blk-ccw - devopts="${devopts},scsi=off";; - esac - diskargs=( "${diskargs[@]}" -drive "$diskopts" -device "$devopts" ) - done - - local mnics_vflag="" - for((i=0;i<${VERBOSITY}-1;i++)); do mnics_vflag="${mnics_vflag}v"; done - [ -n "$mnics_vflag" ] && mnics_vflag="-${mnics_vflag}" - - # now go through and split out options - # -device virtio-net-pci,netdev=virtnet0,mac=52:54:31:15:63:02 - # -netdev type=tap,id=virtnet0,vhost=on,script=/etc/kvm/kvm-ifup.br0,downscript=no - local netopts="" devopts="" id="" need_taps=0 model="" - local device_args netdev_args - device_args=( ) - netdev_args=( ) - connections=( ) - for((i=0;i<${#netdevs[@]};i++)); do - id=$(printf "net%02d" "$i") - netopts=""; - devopts="" - # mac=auto is 'unspecified' (let qemu assign one) - mac="auto" - #vhost="off" - - IFS=","; set -- ${netdevs[$i]}; IFS="$oifs" - bridge=$1; shift; - if [ "$bridge" = "user" ]; then - netopts="type=user" - ntype="user" - connections[$i]="user" - else - need_taps=1 - ntype="tap" - netopts="type=tap" - connections[$i]="$bridge" - fi - netopts="${netopts},id=$id" - [ "$ntype" = "tap" ] && netopts="${netopts},script=no,downscript=no" - - model="${def_netmodel}" - for tok in "$@"; do - [ "${tok#model=}" = "${tok}" ] && continue - case "${tok#model=}" in - virtio) model=virtio-net-pci;; - *) model=${tok#model=};; - esac - done - - for tok in "$@"; do - case "$tok" in - mac=*) mac="${tok#mac=}"; continue;; - macaddr=*) mac=${tok#macaddr=}; continue;; - model=*) continue;; - esac - - isdevopt "$model" "$tok" && devopts="${devopts},$tok" || - netopts="${netopts},${tok}" - done - devopts=${devopts#,} - netopts=${netopts#,} - - if [ "$mac" != "auto" ]; then - [ "$mac" = "random" ] && randmac && mac="$_RET" - padmac "$mac" "$i" - devopts="${devopts:+${devopts},}mac=$_RET" - fi - devopts="$model,netdev=$id${devopts:+,${devopts}}" - #netopts="${netopts},vhost=${vhost}" - - device_args[$i]="$devopts" - netdev_args[$i]="$netopts" - done - - trap cleanup EXIT - - reqs=( "$kvm" ) - pkgs=( "$kvm_pkg" ) - for((i=0;i<${#reqs[@]};i++)); do - req=${reqs[$i]} - pkg=${pkgs[$i]} - [ "$pkg" = "none" ] && continue - command -v "$req" >/dev/null || { - missing="${missing:+${missing} }${req}" - missing_pkgs="${missing_pkgs:+${missing_pkgs} }$pkg" - } - done - if [ -n "$missing" ]; then - local reply cmd="" - cmd=( sudo apt-get --quiet install ${missing_pkgs} ) - error "missing prereqs: $missing"; - error "install them now with the following?: ${cmd[*]}" - read reply && [ "$reply" = "y" -o "$reply" = "Y" ] || - { error "run: apt-get install ${missing_pkgs}"; return 1; } - "${cmd[@]}" || { error "failed to install packages"; return 1; } - fi - - if [ $need_taps -ne 0 ]; then - local missing="" missing_pkgs="" reqs="" req="" pkgs="" pkg="" - for i in "${connections[@]}"; do - [ "$i" = "user" -o -e "/sys/class/net/$i" ] || - missing="${missing} $i" - done - [ -z "$missing" ] || { - error "cannot create connection on: ${missing# }." - error "bridges do not exist."; - return 1; - } - error "creating tap devices: ${connections[*]}" - if $DRY_RUN; then - error "sudo $0 tap-control make-nics" \ - $mnics_vflag "${connections[@]}" - taps="" - for((i=0;i<${#connections[@]};i++)); do - if [ "${connections[$i]}" = "user" ]; then - taps="${taps} skip" - else - taps="${taps} dryruntap$i:brctl" - fi - done - else - taps=$(sudo "$0" tap-control make-nics \ - ${mnics_vflag} "${connections[@]}") || - { error "$failed to make-nics ${connections[*]}"; return 1; } - fi - TAPDEVS=( ${taps} ) - for((i=0;i<${#TAPDEVS[@]};i++)); do - cur=${TAPDEVS[$i]} - [ "${cur#*:}" = "ovs" ] || continue - conn=${connections[$i]} - OVS_CLEANUP[${#OVS_CLEANUP[@]}]="${conn}:${cur%:*}" - done - - debug 2 "tapdevs='${TAPDEVS[@]}'" - [ ${#OVS_CLEANUP[@]} -eq 0 ] || error "OVS_CLEANUP='${OVS_CLEANUP[*]}'" - - for((i=0;i<${#TAPDEVS[@]};i++)); do - cur=${TAPDEVS[$i]} - [ "$cur" = "skip" ] && continue - netdev_args[$i]="${netdev_args[$i]},ifname=${cur%:*}"; - done - fi - - netargs=() - for((i=0;i<${#device_args[@]};i++)); do - netargs=( "${netargs[@]}" -device "${device_args[$i]}" - -netdev "${netdev_args[$i]}") - done - - local bus_devices - if [ -n "${virtio_scsi_bus}" ]; then - bus_devices=( -device "$virtio_scsi_bus,id=virtio-scsi-xkvm" ) - fi - local rng_devices - rng_devices=( -object "rng-random,filename=/dev/urandom,id=objrng0" - -device "$virtio_rng_device,rng=objrng0,id=rng0" ) - cmd=( "${kvmcmd[@]}" "${archopts[@]}" - "${bios_opts[@]}" - "${bus_devices[@]}" - "${rng_devices[@]}" - "${netargs[@]}" - "${diskargs[@]}" "${pt[@]}" ) - local pcmd=$(quote_cmd "${cmd[@]}") - error "$pcmd" - ${DRY_RUN} && return 0 - - if $dowait; then - "${cmd[@]}" & - KVM_PID=$! - debug 1 "kvm pid=$KVM_PID. my pid=$$" - wait - ret=$? - KVM_PID="" - else - "${cmd[@]}" - ret=$? - fi - return $ret -} - - -if [ "$1" = "tap-control" ]; then - shift - mode=$1 - shift || fail "must give mode to tap-control" - case "$mode" in - make-nics) make_nics "$@";; - ovs-cleanup) ovs_cleanup "$@";; - *) fail "tap mode must be either make-nics or ovs-cleanup";; - esac -else - main "$@" -fi diff --git a/tox.ini b/tox.ini index d4c750463bb..58e1207caf8 100644 --- a/tox.ini +++ b/tox.ini @@ -94,27 +94,40 @@ deps = -r{toxinidir}/integration-requirements.txt {[testenv]deps} {[pinned_versions]deps} +allowlist_externals = + shfmt + sh commands = {envpython} -m ruff check {posargs:.} {envpython} -m pylint {posargs:cloudinit/ tests/ tools/} {envpython} -m black --check {posargs:.} {envpython} -m isort --check-only --diff {posargs:.} {envpython} -m mypy {posargs:cloudinit/ tests/ tools/} + sh -c "{envpython} -m json.tool --indent 2 {[files]schema} | diff -q - {[files]schema} > /dev/null" + sh -c "{envpython} -m json.tool --indent 2 {[files]version} | diff -q - {[files]version} > /dev/null" + sh -c "{envpython} -m json.tool --indent 2 {[files]network_v1} | diff -q - {[files]network_v1} > /dev/null" + sh -c "{envpython} -m json.tool --indent 2 {[files]network_v2} | diff -q - {[files]network_v2} > /dev/null" + shfmt --list --case-indent --indent=4 --space-redirects --diff {posargs:./tools/} [testenv:check_format_tip] deps = -r{toxinidir}/integration-requirements.txt {[testenv]deps} {[latest_versions]deps} +allowlist_externals = + shfmt commands = {envpython} -m ruff check {posargs:.} {envpython} -m pylint {posargs:.} {envpython} -m black --check {posargs:.} {envpython} -m isort --check-only --diff {posargs:.} {envpython} -m mypy {posargs:cloudinit/ tests/ tools/} + shfmt --list --case-indent --indent=4 --space-redirects --diff {posargs:./tools/} [testenv:do_format] deps = {[pinned_versions]deps} +allowlist_externals = + shfmt commands = {envpython} -m isort . {envpython} -m black . @@ -122,9 +135,12 @@ commands = {envpython} -m json.tool --indent 2 {[files]version} {[files]version} {envpython} -m json.tool --indent 2 {[files]network_v1} {[files]network_v1} {envpython} -m json.tool --indent 2 {[files]network_v2} {[files]network_v2} + shfmt --list --case-indent --indent=4 --space-redirects -w {posargs:./tools/} [testenv:do_format_tip] deps = {[latest_versions]deps} +allowlist_externals = + sh commands = {envpython} -m isort . {envpython} -m black . @@ -132,6 +148,7 @@ commands = {envpython} -m json.tool --indent 2 {[files]version} {[files]version} {envpython} -m json.tool --indent 2 {[files]network_v1} {[files]network_v1} {envpython} -m json.tool --indent 2 {[files]network_v2} {[files]network_v2} + shfmt --list --case-indent --indent=4 --space-redirects -w {posargs:./tools/} [testenv:py3] commands = {envpython} -m pytest -vv --cov=cloudinit --cov-branch {posargs:tests/unittests}