diff options
-rw-r--r-- | tests/unittests/test_ds_identify.py | 40 | ||||
-rwxr-xr-x | tools/ds-identify | 106 |
2 files changed, 137 insertions, 9 deletions
diff --git a/tests/unittests/test_ds_identify.py b/tests/unittests/test_ds_identify.py index 9314b244..5f8a4a29 100644 --- a/tests/unittests/test_ds_identify.py +++ b/tests/unittests/test_ds_identify.py @@ -20,6 +20,8 @@ UNAME_MYSYS = ("Linux bart 4.4.0-62-generic #83-Ubuntu " UNAME_PPC64EL = ("Linux diamond 4.4.0-83-generic #106-Ubuntu SMP " "Mon Jun 26 17:53:54 UTC 2017 " "ppc64le ppc64le ppc64le GNU/Linux") +UNAME_FREEBSD = ("FreeBSD fbsd12-1 12.1-RELEASE-p10 " + "FreeBSD 12.1-RELEASE-p10 GENERIC amd64") BLKID_EFI_ROOT = """ DEVNAME=/dev/sda1 @@ -80,6 +82,7 @@ MOCK_VIRT_IS_VMWARE = {'name': 'detect_virt', 'RET': 'vmware', 'ret': 0} MOCK_VIRT_IS_VM_OTHER = {'name': 'detect_virt', 'RET': 'vm-other', 'ret': 0} MOCK_VIRT_IS_XEN = {'name': 'detect_virt', 'RET': 'xen', 'ret': 0} MOCK_UNAME_IS_PPC64 = {'name': 'uname', 'out': UNAME_PPC64EL, 'ret': 0} +MOCK_UNAME_IS_FREEBSD = {'name': 'uname', 'out': UNAME_FREEBSD, 'ret': 0} shell_true = 0 shell_false = 1 @@ -257,6 +260,10 @@ class TestDsIdentify(DsIdentifyBase): """EC2: bobrightbox.com in product_serial is not brightbox'""" self._test_ds_not_found('Ec2-brightbox-negative') + def test_freebsd_nocloud(self): + """NoCloud identified on FreeBSD via label by geom.""" + self._test_ds_found('NoCloud-fbsd') + def test_gce_by_product_name(self): """GCE identifies itself with product_name.""" self._test_ds_found('GCE') @@ -725,6 +732,26 @@ def blkid_out(disks=None): return '\n'.join(lines) +def geom_out(disks=None): + """Convert a list of disk dictionaries into geom content. + + geom called with -a (provider) and -s (script-friendly), will produce the + following output: + + gpt/gptboot0 N/A vtbd1p1 + gpt/swap0 N/A vtbd1p2 + iso9660/cidata N/A vtbd2 + """ + if disks is None: + disks = [] + lines = [] + for disk in disks: + lines.append("%s/%s N/A %s" % ( + disk["TYPE"], disk["LABEL"], disk["DEVNAME"])) + lines.append("") + return '\n'.join(lines) + + def _print_run_output(rc, out, err, cfg, files): """A helper to print return of TestDsIdentify. @@ -807,6 +834,19 @@ VALID_CFG = { 'dev/vdb': 'pretend iso content for cidata\n', } }, + 'NoCloud-fbsd': { + 'ds': 'NoCloud', + 'mocks': [ + MOCK_VIRT_IS_KVM, + MOCK_UNAME_IS_FREEBSD, + {'name': 'geom', 'ret': 0, + 'out': geom_out( + [{'DEVNAME': 'vtbd', 'TYPE': 'iso9660', 'LABEL': 'cidata'}])}, + ], + 'files': { + '/dev/vtdb': 'pretend iso content for cidata\n', + } + }, 'NoCloudUpper': { 'ds': 'NoCloud', 'mocks': [ diff --git a/tools/ds-identify b/tools/ds-identify index 4e5700fc..ec9e775e 100755 --- a/tools/ds-identify +++ b/tools/ds-identify @@ -92,7 +92,8 @@ _DI_LOGGED="" # set DI_MAIN='noop' in environment to source this file with no main called. DI_MAIN=${DI_MAIN:-main} -DI_BLKID_OUTPUT="" +DI_BLKID_EXPORT_OUT="" +DI_GEOM_LABEL_STATUS_OUT="" DI_DEFAULT_POLICY="search,found=all,maybe=all,notfound=${DI_DISABLED}" DI_DEFAULT_POLICY_NO_DMI="search,found=all,maybe=all,notfound=${DI_ENABLED}" DI_DMI_CHASSIS_ASSET_TAG="" @@ -231,8 +232,19 @@ ensure_sane_path() { done } -read_fs_info() { - cached "${DI_BLKID_OUTPUT}" && return 0 +blkid_export() { + # call 'blkid -c /dev/null export', set DI_BLKID_EXPORT_OUT + cached "$DI_BLKID_EXPORT_OUT" && return 0 + local out="" ret=0 + out=$(blkid -c /dev/null -o export) && DI_BLKID_EXPORT_OUT="$out" || { + ret=$? + error "failed running [$ret]: blkid -c /dev/null -o export" + DI_BLKID_EXPORT_OUT="$UNAVAILABLE" + } + return $ret +} + +read_fs_info_linux() { # do not rely on links in /dev/disk which might not be present yet. # Note that blkid < 2.22 (centos6, trusty) do not output DEVNAME. # that means that DI_ISO9660_DEVS will not be set. @@ -244,20 +256,23 @@ read_fs_info() { return fi local oifs="$IFS" line="" delim="," - local ret=0 out="" labels="" dev="" label="" ftype="" isodevs="" uuids="" - out=$(blkid -c /dev/null -o export) || { - ret=$? - error "failed running [$ret]: blkid -c /dev/null -o export" + local ret=0 labels="" dev="" label="" ftype="" isodevs="" uuids="" + + blkid_export + ret=$? + [ "$DI_BLKID_EXPORT_OUT" = "$UNAVAILABLE" ] && { DI_FS_LABELS="$UNAVAILABLE:error" DI_ISO9660_DEVS="$UNAVAILABLE:error" + DI_FS_UUIDS="$UNAVAILABLE:error" return $ret } + # 'set --' will collapse multiple consecutive entries in IFS for # whitespace characters (\n, tab, " ") so we cannot rely on getting # empty lines in "$@" below. # shellcheck disable=2086 - { IFS="$CR"; set -- $out; IFS="$oifs"; } + { IFS="$CR"; set -- $DI_BLKID_EXPORT_OUT; IFS="$oifs"; } for line in "$@"; do case "${line}" in @@ -281,6 +296,74 @@ read_fs_info() { DI_ISO9660_DEVS="${isodevs#,}" } +geom_label_status_as() { + # call 'geom label status -as', set DI_GEOM_LABEL_STATUS_OUT + cached "$DI_GEOM_LABEL_STATUS_OUT" && return 0 + local out="" ret=0 + out=$(geom label status -as) && DI_GEOM_LABEL_STATUS_OUT="$out" || { + ret=$? + error "failed running [$ret]: geom label status -as" + DI_GEOM_LABEL_STATUS_OUT="$UNAVAILABLE" + } + return $ret +} + + +read_fs_info_freebsd() { + local oifs="$IFS" line="" delim="," + local ret=0 labels="" dev="" label="" ftype="" isodevs="" + + geom_label_status_as + ret=$? + [ "$DI_GEOM_LABEL_STATUS_OUT" = "$UNAVAILABLE" ] && { + DI_FS_LABELS="$UNAVAILABLE:error" + DI_ISO9660_DEVS="$UNAVAILABLE:error" + return $ret + } + + # The expected output looks like this: + # gpt/gptboot0 N/A vtbd1p1 + # gpt/swap0 N/A vtbd1p2 + # iso9660/cidata N/A vtbd2 + + # shellcheck disable=2086 + { IFS="$CR"; set -- $DI_GEOM_LABEL_STATUS_OUT; IFS="$oifs"; } + + for line in "$@"; do + # shellcheck disable=2086 + set -- $line + provider=$1 + ftype="${provider%/*}" + label="${provider#*/}" + dev=$3 + + [ -n "$dev" -a "$ftype" = "iso9660" ] && + isodevs="${isodevs},${dev}=$label" + + labels="${labels}${label}${delim}" + done + + DI_FS_LABELS="${labels%${delim}}" + DI_ISO9660_DEVS="${isodevs#,}" +} + +read_fs_info() { + # After calling its subfunctions, read_fs_info() will set the following + # variables: + # + # - DI_FS_LABELS + # - DI_ISO9660_DEVS + # - DI_FS_UUIDS + + if [ "$DI_UNAME_KERNEL_NAME" = "FreeBSD" ]; then + read_fs_info_freebsd + return $? + else + read_fs_info_linux + return $? + fi +} + cached() { [ -n "$1" ] && _RET="$1" && return || return 1 } @@ -319,6 +402,11 @@ detect_virt() { *) virt="$out" esac } + out=$(sysctl -qn security.jail.jailed 2>/dev/null) && { + if [ "$out" = "1" ]; then + virt="jail" + fi + } fi _RET="$virt" } @@ -331,7 +419,7 @@ read_virt() { is_container() { case "${DI_VIRT}" in - container-other|lxc|lxc-libvirt|systemd-nspawn|docker|rkt) return 0;; + container-other|lxc|lxc-libvirt|systemd-nspawn|docker|rkt|jail) return 0;; *) return 1;; esac } |