2021-07-21 11:22:34 +00:00
|
|
|
#!/bin/sh -e
|
2014-02-13 14:38:35 +00:00
|
|
|
#
|
2021-07-21 11:22:34 +00:00
|
|
|
# 2021 Dennis Camera (cdist at dtnr.ch)
|
2014-02-13 14:38:35 +00:00
|
|
|
#
|
|
|
|
# This file is part of cdist.
|
|
|
|
#
|
|
|
|
# cdist is free software: you can redistribute it and/or modify
|
|
|
|
# it under the terms of the GNU General Public License as published by
|
|
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
|
|
# (at your option) any later version.
|
|
|
|
#
|
|
|
|
# cdist is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
|
# along with cdist. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
#
|
2021-07-21 11:22:34 +00:00
|
|
|
# This explorer tries to determine what type of machine the target to be
|
|
|
|
# configured is (container, virtual machine, bare-metal).
|
|
|
|
#
|
|
|
|
# It will print one line for each layer it can detect.
|
|
|
|
# The format of all lines is: TYPE[ VERB VENDOR]
|
|
|
|
#
|
|
|
|
# VERB does not have a special meaning, it is just for better readability.
|
|
|
|
#
|
|
|
|
# e.g.
|
2021-07-31 17:29:41 +00:00
|
|
|
# container
|
2021-07-21 11:22:34 +00:00
|
|
|
# container on lxc
|
|
|
|
# virtual by kvm-spapr
|
|
|
|
#
|
2021-07-31 17:29:41 +00:00
|
|
|
# The third word of each line (except the first) can be composed of different
|
|
|
|
# parts concatenated with a `-' (minus) character, with each component being
|
|
|
|
# a specification of the previous, e.g.:
|
2021-07-21 11:22:34 +00:00
|
|
|
# - lxc-libvirt (LXC container, managed by libvirt)
|
|
|
|
# - lpar-s390 / lpar-power (LPAR running on IBM S/390 or POWER, respectively)
|
|
|
|
# - xen-hvm / xen-pv (Xen HVM vs para-virtualization)
|
|
|
|
#
|
2021-07-31 17:29:41 +00:00
|
|
|
# If this explorer cannot collect enough information about virtualization it
|
|
|
|
# will fall back to 'physical'.
|
2021-07-21 11:22:34 +00:00
|
|
|
#
|
|
|
|
|
|
|
|
# Add /sbin and /usr/sbin to the path so we can find system
|
|
|
|
# binaries like dmidecode.
|
|
|
|
PATH=$(getconf PATH 2>/dev/null) || PATH='/usr/bin:/bin'
|
|
|
|
PATH="/sbin:/usr/sbin:${PATH}"
|
|
|
|
export PATH
|
|
|
|
|
|
|
|
arch=$(uname -m | sed -e 's/i.86/i386/' -e 's/arm.*/arm/')
|
|
|
|
uname_s=$(uname -s)
|
|
|
|
|
|
|
|
|
|
|
|
is_command() { command -v "$1" >/dev/null 2>&1; }
|
|
|
|
|
2021-07-31 20:01:28 +00:00
|
|
|
files_same() {
|
|
|
|
# shellcheck disable=SC2012
|
|
|
|
LC_ALL=C df -P "$1" "$2" 2>/dev/null | {
|
|
|
|
read -r _ # skip header line
|
|
|
|
read -r fs1 _ _ _ _ mp1
|
|
|
|
read -r fs2 _ _ _ _ mp2
|
|
|
|
test "${fs1}" = "${fs2}" -a "${mp1}" = "${mp2}" || return 1
|
|
|
|
} &&
|
|
|
|
ls -1Ldi "$1" "$2" 2>/dev/null | {
|
|
|
|
read -r ino1 _
|
|
|
|
read -r ino2 _
|
|
|
|
test "${ino1}" = "${ino2}" || return 1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-21 11:22:34 +00:00
|
|
|
is_oneof() (
|
|
|
|
x=$1; shift
|
|
|
|
for y
|
|
|
|
do
|
|
|
|
test "${x}" = "${y}" || continue
|
|
|
|
return 0
|
|
|
|
done
|
|
|
|
return 1
|
|
|
|
)
|
|
|
|
|
|
|
|
tolower() { LC_ALL=C tr '[:upper:]' '[:lower:]'; }
|
|
|
|
|
|
|
|
# shellcheck disable=SC2086
|
|
|
|
glob_exists() { set -- $1; test -e "$1"; }
|
|
|
|
|
|
|
|
get_dmi_field() {
|
|
|
|
if is_oneof "${uname_s}" NetBSD
|
|
|
|
then
|
|
|
|
case $1
|
|
|
|
in
|
|
|
|
(system-manufacturer) _mib=machdep.dmi.system-vendor ;;
|
|
|
|
(system-product-name) _mib=machdep.dmi.system-product ;;
|
|
|
|
(system-version|system-uuid) _mib=machdep.dmi.$1 ;;
|
|
|
|
(bios-vendor|bios-version) _mib=machdep.dmi.$1 ;;
|
|
|
|
(biod-release-date) _mib=machdep.dmi.bios-date ;;
|
|
|
|
(*) _mib= ;;
|
|
|
|
esac
|
|
|
|
|
|
|
|
test -n "${_mib}" && get_sysctl "${_mib}" | grep -e . && return
|
|
|
|
fi
|
|
|
|
|
|
|
|
if is_command dmidecode
|
|
|
|
then
|
|
|
|
dmidecode -s "$1"
|
|
|
|
elif test -d "${dmi_sysfs-}"
|
|
|
|
then
|
|
|
|
case $1
|
|
|
|
in
|
|
|
|
(system-manufacturer) _filename=sys_vendor ;;
|
|
|
|
(system-product-name) _filename=product_name ;;
|
|
|
|
(*) _filename=$(echo "$1" | tr - _) ;;
|
|
|
|
esac
|
|
|
|
if test -r "${dmi_sysfs-}/${_filename}"
|
|
|
|
then
|
|
|
|
cat "${dmi_sysfs}/${_filename}"
|
|
|
|
fi
|
|
|
|
unset _filename
|
|
|
|
elif test "${uname_s}" = OpenBSD
|
|
|
|
then
|
|
|
|
# NOTE: something similar to system-manufacutrer and system-product-name
|
|
|
|
# is available on OpenBSD in sysctl
|
|
|
|
case $1
|
|
|
|
in
|
|
|
|
(system-manufacturer) _mib=hw.vendor ;;
|
|
|
|
(system-product-name) _mib=hw.product ;;
|
|
|
|
(*) _mib= ;;
|
|
|
|
esac
|
|
|
|
|
|
|
|
test -n "${_mib}" && get_sysctl "${_mib}" | grep -e . && return
|
|
|
|
fi
|
|
|
|
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
|
|
|
has_cpuinfo() { test -e /proc/cpuinfo; }
|
|
|
|
|
|
|
|
get_sysctl() {
|
|
|
|
is_command sysctl && sysctl -n "$1" 2>/dev/null
|
|
|
|
}
|
|
|
|
|
2021-07-31 17:29:41 +00:00
|
|
|
detected_layer() {
|
|
|
|
test -n "${_toplayer:-}" || echo "${_toplayer:=${1:?}}"
|
|
|
|
}
|
|
|
|
|
2021-07-21 11:22:34 +00:00
|
|
|
|
2021-07-31 20:01:28 +00:00
|
|
|
# Check for chroot
|
|
|
|
|
|
|
|
has_chroot_systemd() {
|
|
|
|
is_command systemd-detect-virt && systemd-detect-virt --help | grep -q -e '^ -r'
|
|
|
|
}
|
|
|
|
|
|
|
|
check_chroot_systemd() {
|
|
|
|
systemd-detect-virt -r
|
|
|
|
}
|
|
|
|
|
|
|
|
has_chroot_debian_ischroot() {
|
|
|
|
is_command ischroot
|
|
|
|
}
|
|
|
|
|
|
|
|
check_chroot_debian_ischroot() {
|
|
|
|
ischroot --default-false
|
|
|
|
}
|
|
|
|
|
|
|
|
has_chroot_procfs() {
|
|
|
|
test -d /proc/
|
|
|
|
}
|
|
|
|
|
2021-08-01 21:09:02 +00:00
|
|
|
check_chroot_procfs() (
|
|
|
|
is_chroot=false # default
|
2021-08-01 14:40:20 +00:00
|
|
|
if test -e /proc/1/root && ! files_same /proc/1/root /
|
2021-08-01 21:09:02 +00:00
|
|
|
then
|
|
|
|
is_chroot=true
|
|
|
|
fi
|
|
|
|
if test -e /proc/1/mountinfo -a -e /proc/self/mountinfo
|
|
|
|
then
|
|
|
|
has_mountinfo=true
|
|
|
|
cmp -s /proc/1/mountinfo /proc/self/mountinfo || is_chroot=true
|
|
|
|
fi
|
|
|
|
|
|
|
|
if ${is_chroot}
|
2021-08-01 14:40:20 +00:00
|
|
|
then
|
|
|
|
# try to determine where the chroot has been mounted
|
2021-08-01 21:09:02 +00:00
|
|
|
rootdev=$(LC_ALL=C df -P / | awk 'NR==2{print $1}')
|
|
|
|
|
|
|
|
if test -e "${rootdev}"
|
|
|
|
then
|
|
|
|
# escape chroot to determine where the device containing the
|
|
|
|
# chroot's / is mounted
|
|
|
|
rootdevmnt=$(LC_ALL=C chroot /proc/1/root df -P "${rootdev}" | awk 'NR==2{print $6}')
|
|
|
|
|
|
|
|
# shellcheck disable=SC2012
|
|
|
|
root_ino=$(ls -1di / | awk '{print $1}')
|
|
|
|
|
|
|
|
# escape chroot and find mount point by inode
|
|
|
|
chroot /proc/1/root find "${rootdevmnt}" -xdev -type d -inum "${root_ino}"
|
|
|
|
elif ${has_mountinfo}
|
|
|
|
then
|
|
|
|
while read -r mntid _ _ _ cmntpnt _
|
|
|
|
do
|
|
|
|
read -r _ _ _ _ hmntpnt _ <<-EOF
|
|
|
|
$(grep -e "^$((mntid)) " /proc/1/mountinfo)
|
|
|
|
EOF
|
|
|
|
printf '%s\n' "${hmntpnt%${cmntpnt}}"
|
|
|
|
done </proc/self/mountinfo \
|
|
|
|
| sort -u \
|
|
|
|
| head -n 1 # just take the first...
|
|
|
|
fi
|
|
|
|
|
2021-08-01 14:40:20 +00:00
|
|
|
return 0
|
2021-08-01 21:09:02 +00:00
|
|
|
else
|
|
|
|
return 1
|
2021-08-01 14:40:20 +00:00
|
|
|
fi
|
2021-08-01 21:09:02 +00:00
|
|
|
)
|
2021-07-31 20:01:28 +00:00
|
|
|
|
2021-07-21 11:22:34 +00:00
|
|
|
# Check for container
|
|
|
|
|
2021-07-31 19:29:24 +00:00
|
|
|
has_ct_systemd() {
|
|
|
|
is_command systemd-detect-virt && systemd-detect-virt --help | grep -q -e '^ -c'
|
|
|
|
}
|
|
|
|
|
|
|
|
check_ct_systemd() (
|
|
|
|
_ctengine=$(systemd-detect-virt -c 2>/dev/null) &&
|
|
|
|
case ${_ctengine}
|
|
|
|
in
|
|
|
|
(''|'none')
|
|
|
|
return 1 ;;
|
|
|
|
('container-other')
|
|
|
|
return 0 ;;
|
|
|
|
('systemd-nspawn')
|
|
|
|
echo systemd_nspawn ;;
|
|
|
|
(*)
|
|
|
|
echo "${_ctengine}" ;;
|
|
|
|
esac
|
|
|
|
)
|
|
|
|
|
2021-07-21 11:22:34 +00:00
|
|
|
has_ct_pid_1() {
|
|
|
|
test -r /run/systemd/container -o -r /proc/1/environ
|
|
|
|
}
|
|
|
|
|
|
|
|
translate_container_name() {
|
|
|
|
case $1
|
|
|
|
in
|
|
|
|
('lxc')
|
|
|
|
echo lxc ;;
|
|
|
|
('lxc-libvirt')
|
|
|
|
echo lxc-libvirt ;;
|
|
|
|
('podman')
|
|
|
|
echo podman ;;
|
|
|
|
('systemd-nspawn')
|
|
|
|
echo systemd_nspawn ;;
|
|
|
|
(*)
|
|
|
|
return 1 ;;
|
|
|
|
esac
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
|
|
|
check_ct_pid_1() {
|
|
|
|
if test -r /run/systemd/container
|
|
|
|
then
|
|
|
|
translate_container_name "$(head -n1 /run/systemd/container)" \
|
|
|
|
&& return 0
|
|
|
|
fi
|
|
|
|
|
|
|
|
if test -r /proc/1/environ
|
|
|
|
then
|
|
|
|
translate_container_name "$(
|
|
|
|
LC_ALL=C tr '\000' '\n' </proc/1/environ \
|
|
|
|
| sed -n -e 's/^container=//p')" \
|
|
|
|
&& return 0
|
|
|
|
fi
|
|
|
|
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
|
|
|
has_ct_cgroup() {
|
|
|
|
test -r /proc/self/cgroup
|
|
|
|
}
|
|
|
|
|
|
|
|
check_ct_cgroup() {
|
|
|
|
if grep -q -e ':/docker/' /proc/self/cgroup
|
|
|
|
then
|
|
|
|
echo docker
|
|
|
|
elif grep -q -e ':/lxc/.*\.libvirt-lxc$' /proc/self/cgroup
|
|
|
|
then
|
|
|
|
echo libvirt-lxc
|
|
|
|
elif grep -q -F '/libpod-' /proc/self/cgroup
|
|
|
|
then
|
|
|
|
echo podman
|
|
|
|
else
|
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
check_ct_files() {
|
|
|
|
if test -e /.dockerenv -o -e /run/.dockerenv -o -e /.dockerinit
|
|
|
|
then
|
|
|
|
echo docker
|
|
|
|
elif test -f /run/.containerenv
|
|
|
|
then
|
|
|
|
# https://github.com/containers/podman/issues/3586#issuecomment-661918679
|
|
|
|
echo podman
|
|
|
|
elif test -d /proc/vz -a ! -d /proc/bc -a -f /proc/user_beancounters \
|
|
|
|
|| test -d /.cpt_hardlink_dir_*/
|
|
|
|
then
|
|
|
|
# Virtuozzo / OpenVZ
|
|
|
|
#
|
|
|
|
# /proc/vz: always exists if OpenVZ kernel is running
|
|
|
|
# /proc/bc: exists only on node (not inside container)
|
|
|
|
# /proc/user_beancounters - exists inside container
|
|
|
|
#
|
|
|
|
# /.cpt_hardlink_dir_*/ may be (?) created by vzctl:
|
|
|
|
# https://github.com/kolyshkin/vzctl/commit/09e974f
|
|
|
|
|
|
|
|
echo openvz
|
|
|
|
elif grep -qie 'Microsoft\|WSL' /proc/sys/kernel/osrelease /proc/version 2>/dev/null
|
|
|
|
then
|
|
|
|
# https://github.com/Microsoft/WSL/issues/423#issuecomment-221627364
|
|
|
|
echo wsl
|
|
|
|
elif test -d /var/.cagefs
|
|
|
|
then
|
|
|
|
# https://docs.cloudlinux.com/cloudlinux_os_components/#cagefs
|
|
|
|
# CageFS is not "really" a container, but it isn't a chroot either.
|
|
|
|
echo cagefs
|
|
|
|
elif test -e /proc/self/status && grep -q -e '^VxID: [0-9]\{1,\}' /proc/self/status
|
|
|
|
then
|
|
|
|
# Linux-VServer
|
|
|
|
if grep -q -x -F 'VxID: 0' /proc/self/status
|
|
|
|
then
|
|
|
|
# host
|
|
|
|
return 1
|
|
|
|
else
|
|
|
|
# guest
|
|
|
|
echo linux_vserver
|
|
|
|
fi
|
|
|
|
else
|
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
check_ct_os_specific() (
|
|
|
|
if jailed=$(get_sysctl security.jail.jailed) && test "${jailed}" = 1
|
|
|
|
then
|
|
|
|
# FreeBSD jail
|
|
|
|
echo jail
|
|
|
|
return 0
|
|
|
|
fi
|
|
|
|
|
|
|
|
if is_command zonename && test "$(zonename)" != global
|
|
|
|
then
|
|
|
|
# Solaris zone
|
|
|
|
echo zone
|
|
|
|
return 0
|
|
|
|
fi
|
|
|
|
|
|
|
|
return 1
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# Check for hypervisor
|
|
|
|
|
|
|
|
guess_hypervisor_from_cpu_model() {
|
|
|
|
case $1
|
|
|
|
in
|
|
|
|
(*\ KVM\ *)
|
|
|
|
echo kvm ;;
|
|
|
|
(*\ QEMU\ *|QEMU\ *)
|
|
|
|
echo qemu ;;
|
|
|
|
(*)
|
|
|
|
return 1 ;;
|
|
|
|
esac
|
|
|
|
}
|
|
|
|
|
2021-07-31 19:29:24 +00:00
|
|
|
has_vm_systemd() {
|
|
|
|
is_command systemd-detect-virt && systemd-detect-virt --help | grep -q -e '^ -v'
|
|
|
|
}
|
|
|
|
|
|
|
|
check_vm_systemd() (
|
|
|
|
_hypervisor=$(systemd-detect-virt -v 2>/dev/null) &&
|
|
|
|
case ${_hypervisor}
|
|
|
|
in
|
|
|
|
(''|'none')
|
|
|
|
return 1 ;;
|
|
|
|
('amazon')
|
|
|
|
echo aws ;;
|
|
|
|
('bochs')
|
|
|
|
echo kvm ;;
|
|
|
|
('microsoft')
|
|
|
|
# assumption
|
|
|
|
echo hyperv ;;
|
|
|
|
('oracle')
|
|
|
|
echo virtualbox ;;
|
|
|
|
('vm-other')
|
|
|
|
return 0 ;;
|
|
|
|
(*)
|
|
|
|
echo "${_hypervisor}" ;;
|
|
|
|
esac
|
|
|
|
)
|
|
|
|
|
2021-07-21 11:22:34 +00:00
|
|
|
has_vm_cpuinfo() { has_cpuinfo; }
|
|
|
|
|
|
|
|
check_vm_cpuinfo() {
|
|
|
|
if grep -q -F 'User Mode Linux' /proc/cpuinfo \
|
|
|
|
|| grep -q -F 'UML' /proc/cpuinfo
|
|
|
|
then
|
|
|
|
# User Mode Linux
|
|
|
|
echo uml
|
|
|
|
elif grep -q -e '^vendor_id.*: PowerVM Lx86' /proc/cpuinfo
|
|
|
|
then
|
|
|
|
# IBM PowerVM Lx86 (Linux/x86 emulator)
|
|
|
|
echo powervm_lx86
|
|
|
|
elif grep -q -e '^vendor_id.*: IBM/S390' /proc/cpuinfo
|
|
|
|
then
|
|
|
|
# IBM SystemZ (S/390)
|
|
|
|
if test -f /proc/sysinfo
|
|
|
|
then
|
|
|
|
if grep -q -e '^VM[0-9]* Control Program: KVM/Linux' /proc/sysinfo
|
|
|
|
then
|
|
|
|
echo kvm-s390
|
|
|
|
return 0
|
|
|
|
elif grep -q -e '^VM[0-9]* Control Program: z/VM' /proc/sysinfo
|
|
|
|
then
|
|
|
|
echo zvm
|
|
|
|
return 0
|
|
|
|
elif grep -q -e '^LPAR ' /proc/sysinfo
|
|
|
|
then
|
|
|
|
echo zvm-lpar
|
|
|
|
return 0
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
return 1
|
|
|
|
else
|
|
|
|
if grep -q -e '^model name.*:' /proc/cpuinfo
|
|
|
|
then
|
|
|
|
sed -n -e 's/^model name[^:]*: *//p' /proc/cpuinfo \
|
|
|
|
| while read -r _cpu_model
|
|
|
|
do
|
|
|
|
guess_hypervisor_from_cpu_model "${_cpu_model}"
|
|
|
|
done \
|
|
|
|
| sort \
|
|
|
|
| uniq -c \
|
|
|
|
| awk '
|
|
|
|
{ if ($1 > most_c) { most_c = $1; most_s = $2 } }
|
|
|
|
END {
|
|
|
|
if (most_s) print most_s
|
|
|
|
exit !most_s
|
|
|
|
}' \
|
|
|
|
&& return 0
|
|
|
|
fi
|
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
check_vm_arch_specific() {
|
|
|
|
case ${arch}
|
|
|
|
in
|
|
|
|
(ppc64|ppc64le)
|
|
|
|
# Check PPC64 LPAR, KVM
|
|
|
|
|
|
|
|
# example /proc/cpuinfo line indicating 'not baremetal'
|
|
|
|
# platform : pSeries
|
|
|
|
#
|
|
|
|
# example /proc/ppc64/lparcfg systemtype line
|
|
|
|
# system_type=IBM pSeries (emulated by qemu)
|
|
|
|
|
|
|
|
if has_cpuinfo && grep -q -e 'platform.**pSeries' /proc/cpuinfo
|
|
|
|
then
|
|
|
|
if test -e /proc/ppc64/lparcfg
|
|
|
|
then
|
|
|
|
# Assume LPAR, now detect shared or dedicated
|
|
|
|
if grep -q -x -F 'shared_processor_mode=1' /proc/ppc64/lparcfg
|
|
|
|
then
|
|
|
|
echo powervm-shared
|
|
|
|
return 0
|
|
|
|
else
|
|
|
|
echo powervm-dedicated
|
|
|
|
return 0
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
;;
|
|
|
|
(sparc*)
|
|
|
|
# Check for SPARC LDoms
|
|
|
|
|
|
|
|
if test -e /dev/mdesc
|
|
|
|
then
|
|
|
|
if test -d /sys/class/vlds/ctrl -a -d /sys/class/vlds/sp
|
|
|
|
then
|
|
|
|
# control LDom
|
|
|
|
return 1
|
|
|
|
else
|
|
|
|
# guest LDom
|
|
|
|
echo ldom-sparc
|
|
|
|
fi
|
|
|
|
|
|
|
|
# MDPROP=/usr/lib/ldoms/mdprop.py
|
|
|
|
# if test -x "${MDPROP}"
|
|
|
|
# then
|
|
|
|
# if test -n "$("${MDPROP}" -v iodevice device-type=pciex)"
|
|
|
|
# then
|
|
|
|
# echo ldoms-root
|
|
|
|
# echo ldoms-io
|
|
|
|
# elif test -n "$("${MDPROP}" -v iov-device vf-id=0)"
|
|
|
|
# then
|
|
|
|
# echo ldoms-io
|
|
|
|
# fi
|
|
|
|
# fi
|
|
|
|
return 0
|
|
|
|
fi
|
|
|
|
;;
|
|
|
|
(i?86|x86*|amd64|i86pc)
|
|
|
|
# VMM CPUID flag denotes that this system is running under a VMM
|
|
|
|
if is_oneof "${uname_s}" Darwin
|
|
|
|
then
|
|
|
|
get_sysctl machdep.cpu.features | tr ' ' '\n' | grep -qixF VMM \
|
|
|
|
&& return 0
|
|
|
|
fi
|
|
|
|
if has_cpuinfo \
|
|
|
|
&& grep -q -i -e '^flags.*:.*\(hypervisor\|vmm\)' /proc/cpuinfo
|
|
|
|
then
|
|
|
|
return 0
|
|
|
|
fi
|
|
|
|
;;
|
|
|
|
(ia64)
|
|
|
|
if test -d /sys/bus/xen -a ! -d /sys/bus/xen-backend
|
|
|
|
then
|
|
|
|
# PV-on-HVM drivers installed in a Xen guest
|
|
|
|
echo xen-hvm
|
|
|
|
return 0
|
|
|
|
fi
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
|
|
|
has_vm_dmi() {
|
|
|
|
# Check for various products in SMBIOS/DMI.
|
|
|
|
# Note that DMI doesn't exist on all architectures (only x86 and some ARM).
|
|
|
|
# On other architectures the $dmi variable will be empty.
|
|
|
|
|
|
|
|
if test -d /sys/class/dmi/id/
|
|
|
|
then
|
|
|
|
dmi_sysfs=/sys/class/dmi/id
|
|
|
|
elif test -d /sys/devices/virtual/dmi/id/
|
|
|
|
then
|
|
|
|
dmi_sysfs=/sys/devices/virtual/dmi/id
|
|
|
|
fi
|
|
|
|
|
|
|
|
# shellcheck disable=SC2015
|
|
|
|
{
|
|
|
|
is_command dmidecode \
|
|
|
|
&& (
|
|
|
|
# dmidecode needs to exit 0 and not print the No SMBIOS/DMI line
|
|
|
|
dmi_out=$(dmidecode 2>&1) \
|
|
|
|
&& ! printf '%s\n' "${dmi_out}" \
|
|
|
|
| grep -qF 'No SMBIOS nor DMI entry point found, sorry.'
|
|
|
|
) \
|
|
|
|
|| test -d "${dmi_sysfs}"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
check_vm_dmi() {
|
|
|
|
case $(get_dmi_field system-product-name)
|
|
|
|
in
|
|
|
|
(*.metal)
|
|
|
|
if test "$(get_dmi_field system-manufacturer)" = 'Amazon EC2'
|
|
|
|
then
|
|
|
|
# AWS EC2 bare metal -> no virtualisation
|
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
;;
|
|
|
|
('BHYVE')
|
|
|
|
echo bhyve
|
|
|
|
return 0
|
|
|
|
;;
|
|
|
|
('Google Compute Engine')
|
|
|
|
echo gce
|
|
|
|
return 0
|
|
|
|
;;
|
|
|
|
('RHEV Hypervisor')
|
|
|
|
# Red Hat Enterprise Virtualization
|
|
|
|
echo rhev
|
|
|
|
return 0
|
|
|
|
;;
|
|
|
|
('KVM'|'Bochs'|'KVM Virtual Machine')
|
|
|
|
echo kvm
|
|
|
|
return 0
|
|
|
|
;;
|
|
|
|
('Parallels Virtual Platform')
|
|
|
|
echo parallels
|
|
|
|
return 0
|
|
|
|
;;
|
|
|
|
('VirtualBox')
|
|
|
|
echo virtualbox
|
|
|
|
return 0
|
|
|
|
;;
|
|
|
|
('VMware Virtual Platform')
|
|
|
|
echo vmware
|
|
|
|
return 0
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
|
|
|
|
case $(get_dmi_field system-manufacturer)
|
|
|
|
in
|
|
|
|
('Alibaba'*)
|
|
|
|
case $(get_dmi_field system-product-name)
|
|
|
|
in
|
|
|
|
('Alibaba Cloud ECS')
|
|
|
|
echo alibaba-ecs
|
|
|
|
;;
|
|
|
|
(*)
|
|
|
|
echo alibaba
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
return 0
|
|
|
|
;;
|
|
|
|
('Amazon EC2')
|
|
|
|
# AWS on bare-metal or KVM
|
|
|
|
echo aws-ec2
|
|
|
|
return 0
|
|
|
|
;;
|
|
|
|
('innotek GmbH'|'Oracle Corporation')
|
|
|
|
echo virtualbox
|
|
|
|
return 0
|
|
|
|
;;
|
|
|
|
('Joyent')
|
|
|
|
if test "$(get_dmi_field system-product-name)" = 'SmartDC HVM'
|
|
|
|
then
|
|
|
|
# SmartOS KVM
|
|
|
|
echo kvm-smartdc_hvm
|
|
|
|
return 0
|
|
|
|
fi
|
|
|
|
;;
|
|
|
|
('Microsoft Corporation'*)
|
|
|
|
if test "$(get_dmi_field system-product-name)" = 'Virtual Machine'
|
|
|
|
then
|
|
|
|
if test -e /proc/irq/7/hyperv \
|
|
|
|
|| expr "$(get_dmi_field bios-version)" : 'VRTUAL.*' >/dev/null
|
|
|
|
then
|
|
|
|
echo hyperv
|
|
|
|
return 0
|
|
|
|
fi
|
|
|
|
|
|
|
|
case $(get_dmi_field system-version)
|
|
|
|
in
|
|
|
|
(VPC[0-9]*|VS2005*|*[Vv]irtual*[Pp][Cc]*)
|
|
|
|
echo virtualpc
|
|
|
|
return 0
|
|
|
|
;;
|
|
|
|
(*)
|
|
|
|
echo hyperv
|
|
|
|
return 0
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
fi
|
|
|
|
;;
|
|
|
|
('Nutanix')
|
|
|
|
# Nutanix AHV. Similar to KVM.
|
|
|
|
if test "$(get_dmi_field system-product-name)" = 'AHV'
|
|
|
|
then
|
|
|
|
echo nutanix_ahv
|
|
|
|
return 0
|
|
|
|
fi
|
|
|
|
;;
|
|
|
|
('oVirt')
|
|
|
|
echo ovirt
|
|
|
|
return 0
|
|
|
|
;;
|
|
|
|
('Parallels Software International Inc.')
|
|
|
|
echo parallels
|
|
|
|
return 0
|
|
|
|
;;
|
|
|
|
('QEMU')
|
|
|
|
echo qemu
|
|
|
|
return 0
|
|
|
|
;;
|
|
|
|
('VMware, Inc.')
|
|
|
|
echo vmware
|
|
|
|
return 0
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
|
|
|
|
case $(get_dmi_field bios-vendor)
|
|
|
|
in
|
|
|
|
('Amazon EC2')
|
|
|
|
# AWS on bare-metal or KVM
|
|
|
|
echo aws-ec2
|
|
|
|
return 0
|
|
|
|
;;
|
|
|
|
('BHYVE')
|
|
|
|
echo bhyve
|
|
|
|
return 0
|
|
|
|
;;
|
|
|
|
('innotek GmbH')
|
|
|
|
echo virtualbox
|
|
|
|
return 0
|
|
|
|
;;
|
|
|
|
('Parallels Software International Inc.')
|
|
|
|
echo parallels
|
|
|
|
return 0
|
|
|
|
;;
|
|
|
|
('Xen')
|
|
|
|
if get_dmi_field bios-version | grep -q -e '\([0-9]\{1,\}\.\)\{2\}amazon'
|
|
|
|
then
|
|
|
|
# AWS on Xen
|
|
|
|
echo aws-xen
|
|
|
|
return 0
|
|
|
|
fi
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
|
|
|
check_vm_hyp_specific() {
|
|
|
|
if is_command vmware-checkvm && vmware-checkvm >/dev/null
|
|
|
|
then
|
|
|
|
# vmware-checkvm is provided by VMware's open-vm-tools
|
|
|
|
echo vmware
|
|
|
|
return 0
|
|
|
|
elif test -d /proc/xen
|
|
|
|
then
|
|
|
|
test -r /proc/xen/capabilities &&
|
|
|
|
if grep -q -F 'control_d' /proc/xen/capabilities 2>/dev/null
|
|
|
|
then
|
|
|
|
# Xen dom0
|
|
|
|
return 1
|
|
|
|
else
|
|
|
|
# Xen domU
|
|
|
|
echo xen
|
|
|
|
return 0
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
|
|
|
has_vm_dt() {
|
|
|
|
# OpenFirmware/Das U-Boot device-tree
|
|
|
|
test -d /proc/device-tree
|
|
|
|
}
|
|
|
|
|
|
|
|
check_vm_dt() {
|
|
|
|
case ${arch}
|
|
|
|
in
|
|
|
|
(arm|aarch64)
|
|
|
|
if test -r /proc/device-tree/hypervisor/compatible
|
|
|
|
then
|
|
|
|
if grep -q -F 'xen' /proc/device-tree/hypervisor/compatible
|
|
|
|
then
|
|
|
|
echo xen
|
|
|
|
return 0
|
|
|
|
elif grep -q -F 'vmware' /proc/device-tree/hypervisor/compatible
|
|
|
|
then
|
|
|
|
# e.g. VMware ESXi on ARM
|
|
|
|
echo vmware
|
|
|
|
return 0
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
if glob_exists /proc/device-tree/fw-cfg@*/compatible
|
|
|
|
then
|
|
|
|
# qemu,fw-cfg-mmio
|
|
|
|
sed -e 's/,.*$//' /proc/device-tree/fw-cfg@*/compatible | head -n1
|
|
|
|
return 0
|
|
|
|
fi
|
|
|
|
if grep -q -F 'dummy-virt' /proc/device-tree/compatible
|
|
|
|
then
|
|
|
|
echo lkvm
|
|
|
|
return 0
|
|
|
|
fi
|
|
|
|
;;
|
|
|
|
(ppc64*)
|
|
|
|
if test -d /proc/device-tree/hypervisor \
|
|
|
|
&& grep -qF 'linux,kvm' /proc/device-tree/hypervisor/compatible
|
|
|
|
then
|
|
|
|
# We are running as a spapr KVM guest on ppc64
|
|
|
|
echo kvm-spapr
|
|
|
|
return 0
|
|
|
|
fi
|
|
|
|
if test -r /proc/device-tree/ibm,partition-name \
|
|
|
|
&& test -r /proc/device-tree/hmc-managed\? \
|
|
|
|
&& test -r /proc/device-tree/chosen/qemu,graphic-width
|
|
|
|
then
|
|
|
|
echo powervm
|
|
|
|
fi
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
|
|
|
has_vm_sys_hypervisor() {
|
|
|
|
test -d /sys/hypervisor/
|
|
|
|
}
|
|
|
|
|
|
|
|
check_vm_sys_hypervisor() {
|
|
|
|
test -r /sys/hypervisor/type &&
|
|
|
|
case $(head -n1 /sys/hypervisor/type)
|
|
|
|
in
|
|
|
|
(xen)
|
|
|
|
# Ordinary kernel with pv_ops. There does not seem to be
|
|
|
|
# enough information at present to tell whether this is dom0
|
|
|
|
# or domU.
|
|
|
|
echo xen
|
|
|
|
return 0
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
|
|
|
check_vm_os_specific() {
|
|
|
|
_hyp_generic=false
|
|
|
|
|
|
|
|
case ${uname_s}
|
|
|
|
in
|
|
|
|
(Darwin)
|
|
|
|
if hv_vmm_present=$(get_sysctl kern.hv_vmm_present) \
|
|
|
|
&& test "${hv_vmm_present}" -ne 0
|
|
|
|
then
|
|
|
|
_hyp_generic=true
|
|
|
|
fi
|
|
|
|
;;
|
|
|
|
(FreeBSD)
|
|
|
|
# FreeBSD does not have /proc/cpuinfo even when procfs is used.
|
|
|
|
# Instead there is a sysctl kern.vm_guest.
|
|
|
|
# Which is 'none' if physical, else the virtualisation.
|
|
|
|
vm_guest=$(get_sysctl kern.vm_guest | tolower) &&
|
|
|
|
case ${vm_guest}
|
|
|
|
in
|
|
|
|
(none) ;;
|
|
|
|
(generic) _hyp_generic=true ;;
|
|
|
|
(*)
|
|
|
|
# kernel could detect hypervisor
|
|
|
|
case ${vm_guest}
|
|
|
|
in
|
|
|
|
(hv) echo hyperv ;;
|
|
|
|
(vbox) echo virtualbox ;;
|
|
|
|
(*) echo "${vm_guest}" ;;
|
|
|
|
esac
|
|
|
|
return 0
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
;;
|
|
|
|
(NetBSD)
|
|
|
|
machdep_hv=$(get_sysctl machdep.hypervisor | tolower) &&
|
|
|
|
case ${machdep_hv}
|
|
|
|
in
|
|
|
|
(none) ;;
|
|
|
|
(generic) _hyp_generic=true ;;
|
|
|
|
(*)
|
|
|
|
# kernel could detect hypervisor
|
|
|
|
case ${machdep_hv}
|
|
|
|
in
|
|
|
|
(hyper-v) echo hyperv ;;
|
|
|
|
(xenhvm*) echo xen-hvm ;;
|
|
|
|
(xenpv*) echo xen-pv ;;
|
|
|
|
(xen*) echo xen ;;
|
|
|
|
(*) echo "${machdep_hv}" ;;
|
|
|
|
esac
|
|
|
|
return 0
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
;;
|
|
|
|
(OpenBSD)
|
|
|
|
if is_command hostctl && glob_exists /dev/pvbus[0-9]*
|
|
|
|
then
|
|
|
|
for _pvbus in /dev/pvbus[0-9]*
|
|
|
|
do
|
|
|
|
_h_out=$(hostctl -f "${_pvbus}" -t 2>/dev/null) || continue
|
|
|
|
case $(expr "${_h_out}" : '[^:]*: *\(.*\)$')
|
|
|
|
in
|
|
|
|
(KVM) echo kvm ;;
|
|
|
|
(Hyper-V) echo hyperv ;;
|
|
|
|
(VMware) echo vmware ;;
|
|
|
|
(Xen) echo xen ;;
|
|
|
|
(bhyve) echo bhyve ;;
|
|
|
|
(OpenBSD) echo openbsd_vmm ;;
|
|
|
|
esac
|
|
|
|
return 0
|
|
|
|
done
|
|
|
|
fi
|
|
|
|
;;
|
|
|
|
(SunOS)
|
|
|
|
diag_conf=$(prtdiag | sed -n -e 's/.*Configuration: *//p' -e '/^$/q')
|
|
|
|
# NOTE: Don't use -e or -F in Solaris grep
|
|
|
|
if printf '%s\n' "${diag_conf}" | grep -q -i QEMU
|
|
|
|
then
|
|
|
|
echo qemu
|
|
|
|
return 0
|
|
|
|
elif printf '%s\n' "${diag_conf}" | grep -q -i VMware
|
|
|
|
then
|
|
|
|
echo vmware
|
|
|
|
return 0
|
|
|
|
fi
|
|
|
|
;;
|
|
|
|
(Linux)
|
|
|
|
if is_command dmesg
|
|
|
|
then
|
|
|
|
while read -r line
|
|
|
|
do
|
|
|
|
case ${line}
|
|
|
|
in
|
|
|
|
('Booting paravirtualized kernel on ')
|
|
|
|
case $(expr "${line}" : '.* kernel on \(.*\)')
|
|
|
|
in
|
|
|
|
('Xen')
|
|
|
|
echo xen-pv; return 0 ;;
|
|
|
|
('bare hardware')
|
|
|
|
return 1 ;;
|
|
|
|
esac
|
|
|
|
;;
|
|
|
|
('Hypervisor detected')
|
|
|
|
case $(expr "${line}" : '.*: *\(.*\)')
|
|
|
|
in
|
|
|
|
('ACRN')
|
|
|
|
echo acrn ;;
|
|
|
|
('Jailhouse')
|
|
|
|
echo jailhouse ;;
|
|
|
|
('KVM')
|
|
|
|
echo kvm ;;
|
|
|
|
('Microsoft Hyper-V')
|
|
|
|
echo hyperv ;;
|
|
|
|
('VMware')
|
|
|
|
echo vmware ;;
|
|
|
|
('Xen HVM')
|
|
|
|
echo xen-hvm ;;
|
|
|
|
('Xen PV')
|
|
|
|
echo xen-pv ;;
|
|
|
|
esac
|
|
|
|
return 0
|
|
|
|
;;
|
|
|
|
(lpar:*' under hypervisor')
|
|
|
|
return 0 ;;
|
|
|
|
esac
|
|
|
|
done <<-EOF
|
|
|
|
$(dmesg 2>/dev/null | awk '
|
|
|
|
/Booting paravirtualized kernel on /
|
|
|
|
/Hypervisor detected: /
|
|
|
|
/lpar: .* under hypervisor/
|
|
|
|
')
|
|
|
|
EOF
|
|
|
|
fi
|
|
|
|
esac
|
|
|
|
|
|
|
|
# Try to guess hypervisor based on CPU model (sysctl hw.model if available)
|
|
|
|
if cpu_model=$(get_sysctl hw.model)
|
|
|
|
then
|
|
|
|
guess_hypervisor_from_cpu_model "${cpu_model}" && return 0
|
|
|
|
fi
|
|
|
|
|
|
|
|
if ${_hyp_generic}
|
|
|
|
then
|
|
|
|
# cannot say which hypervisor, but one was detected
|
|
|
|
return 0
|
|
|
|
else
|
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
run_stage() {
|
|
|
|
if type "has_$1_$2" >/dev/null 2>&1
|
|
|
|
then
|
|
|
|
"has_$1_$2"
|
|
|
|
else
|
|
|
|
true
|
|
|
|
fi \
|
|
|
|
&& "check_$1_$2"
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-07-31 20:01:28 +00:00
|
|
|
# Execute chroot stages
|
|
|
|
|
|
|
|
for stage in \
|
|
|
|
procfs debian_ischroot systemd
|
|
|
|
do
|
2021-08-01 14:40:20 +00:00
|
|
|
chrootpnt=$(run_stage chroot ${stage}) || continue
|
|
|
|
is_chrooted=true
|
2021-07-31 20:01:28 +00:00
|
|
|
detected_layer 'chroot'
|
2021-08-01 14:40:20 +00:00
|
|
|
if test -n "${chrootpnt}"
|
|
|
|
then
|
|
|
|
echo chroot at "${chrootpnt}"
|
|
|
|
break
|
|
|
|
fi
|
2021-07-31 20:01:28 +00:00
|
|
|
done
|
2021-08-01 14:40:20 +00:00
|
|
|
if ${is_chrooted:-false} && test -z "${chrootpnt}"
|
|
|
|
then
|
|
|
|
# could determine chroot, but not its mount point
|
|
|
|
echo chroot
|
|
|
|
fi
|
2021-07-31 20:01:28 +00:00
|
|
|
|
|
|
|
|
2021-07-21 11:22:34 +00:00
|
|
|
# Execute container stages
|
|
|
|
|
|
|
|
for stage in \
|
2021-07-31 19:29:24 +00:00
|
|
|
systemd pid_1 cgroup files os_specific
|
2021-07-21 11:22:34 +00:00
|
|
|
do
|
|
|
|
ctengine=$(run_stage ct ${stage}) || continue
|
2021-07-31 17:29:41 +00:00
|
|
|
detected_layer 'container'
|
2021-07-21 11:22:34 +00:00
|
|
|
is_contained=true
|
|
|
|
if test -n "${ctengine}"
|
|
|
|
then
|
|
|
|
echo container on "${ctengine}"
|
|
|
|
break
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
if ${is_contained:-false} && test -z "${ctengine}"
|
|
|
|
then
|
|
|
|
# none of the stages could determine the specific container engine, but
|
|
|
|
# we are running in some container.
|
|
|
|
echo container
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
# Execute virtual machine / hypervisor stages
|
2014-02-13 14:38:35 +00:00
|
|
|
|
2021-07-21 11:22:34 +00:00
|
|
|
for stage in \
|
2021-07-31 19:29:24 +00:00
|
|
|
systemd os_specific hyp_specific sys_hypervisor dt dmi cpuinfo arch_specific
|
2021-07-21 11:22:34 +00:00
|
|
|
do
|
|
|
|
hypervisor=$(run_stage vm ${stage}) || continue
|
2021-07-31 17:29:41 +00:00
|
|
|
detected_layer 'virtual machine'
|
2021-07-21 11:22:34 +00:00
|
|
|
is_virtual=true
|
|
|
|
if test -n "${hypervisor}"
|
|
|
|
then
|
|
|
|
echo virtual by "${hypervisor}"
|
|
|
|
break
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
if ${is_virtual:-false} && test -z "${hypervisor}"
|
|
|
|
then
|
|
|
|
# none of the stages could determine the specific hypervisor, but
|
|
|
|
# we are virtual.
|
|
|
|
echo virtual
|
|
|
|
fi
|
2021-07-31 17:29:41 +00:00
|
|
|
|
|
|
|
|
|
|
|
# Fallback
|
|
|
|
|
|
|
|
detected_layer physical
|