mirror of
https://github.com/systemd/systemd.git
synced 2025-03-31 14:50:15 +03:00
Merge pull request #1190 from poettering/rework-virt
basic: rework virtualization detection API
This commit is contained in:
commit
da323858ef
@ -4817,7 +4817,7 @@ int shall_restore_state(void) {
|
||||
int proc_cmdline(char **ret) {
|
||||
assert(ret);
|
||||
|
||||
if (detect_container(NULL) > 0)
|
||||
if (detect_container() > 0)
|
||||
return get_process_cmdline(1, 0, false, ret);
|
||||
else
|
||||
return read_one_line_file("/proc/cmdline", ret);
|
||||
|
411
src/basic/virt.c
411
src/basic/virt.c
@ -28,25 +28,24 @@
|
||||
#include "virt.h"
|
||||
#include "fileio.h"
|
||||
|
||||
static int detect_vm_cpuid(const char **_id) {
|
||||
static int detect_vm_cpuid(void) {
|
||||
|
||||
/* Both CPUID and DMI are x86 specific interfaces... */
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
|
||||
static const char cpuid_vendor_table[] =
|
||||
"XenVMMXenVMM\0" "xen\0"
|
||||
"KVMKVMKVM\0" "kvm\0"
|
||||
static const struct {
|
||||
const char *cpuid;
|
||||
int id;
|
||||
} cpuid_vendor_table[] = {
|
||||
{ "XenVMMXenVMM", VIRTUALIZATION_XEN },
|
||||
{ "KVMKVMKVM", VIRTUALIZATION_KVM },
|
||||
/* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
|
||||
"VMwareVMware\0" "vmware\0"
|
||||
{ "VMwareVMware", VIRTUALIZATION_VMWARE },
|
||||
/* http://msdn.microsoft.com/en-us/library/ff542428.aspx */
|
||||
"Microsoft Hv\0" "microsoft\0";
|
||||
{ "Microsoft Hv", VIRTUALIZATION_MICROSOFT },
|
||||
};
|
||||
|
||||
uint32_t eax, ecx;
|
||||
union {
|
||||
uint32_t sig32[3];
|
||||
char text[13];
|
||||
} sig = {};
|
||||
const char *j, *k;
|
||||
bool hypervisor;
|
||||
|
||||
/* http://lwn.net/Articles/301888/ */
|
||||
@ -74,6 +73,11 @@ static int detect_vm_cpuid(const char **_id) {
|
||||
hypervisor = !!(ecx & 0x80000000U);
|
||||
|
||||
if (hypervisor) {
|
||||
union {
|
||||
uint32_t sig32[3];
|
||||
char text[13];
|
||||
} sig = {};
|
||||
unsigned j;
|
||||
|
||||
/* There is a hypervisor, see what it is */
|
||||
eax = 0x40000000U;
|
||||
@ -88,57 +92,54 @@ static int detect_vm_cpuid(const char **_id) {
|
||||
: "0" (eax)
|
||||
);
|
||||
|
||||
NULSTR_FOREACH_PAIR(j, k, cpuid_vendor_table)
|
||||
if (streq(sig.text, j)) {
|
||||
*_id = k;
|
||||
return 1;
|
||||
}
|
||||
for (j = 0; j < ELEMENTSOF(cpuid_vendor_table); j ++)
|
||||
if (streq(sig.text, cpuid_vendor_table[j].cpuid))
|
||||
return cpuid_vendor_table[j].id;
|
||||
|
||||
*_id = "other";
|
||||
return 0;
|
||||
return VIRTUALIZATION_VM_OTHER;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
return VIRTUALIZATION_NONE;
|
||||
}
|
||||
|
||||
static int detect_vm_devicetree(const char **_id) {
|
||||
static int detect_vm_device_tree(void) {
|
||||
#if defined(__arm__) || defined(__aarch64__) || defined(__powerpc__) || defined(__powerpc64__)
|
||||
_cleanup_free_ char *hvtype = NULL;
|
||||
int r;
|
||||
|
||||
r = read_one_line_file("/proc/device-tree/hypervisor/compatible", &hvtype);
|
||||
if (r >= 0) {
|
||||
if (streq(hvtype, "linux,kvm")) {
|
||||
*_id = "kvm";
|
||||
return 1;
|
||||
} else if (strstr(hvtype, "xen")) {
|
||||
*_id = "xen";
|
||||
return 1;
|
||||
}
|
||||
} else if (r == -ENOENT) {
|
||||
if (r == -ENOENT) {
|
||||
_cleanup_closedir_ DIR *dir = NULL;
|
||||
struct dirent *dent;
|
||||
|
||||
dir = opendir("/proc/device-tree");
|
||||
if (!dir) {
|
||||
if (errno == ENOENT)
|
||||
return 0;
|
||||
return VIRTUALIZATION_NONE;
|
||||
return -errno;
|
||||
}
|
||||
|
||||
FOREACH_DIRENT(dent, dir, return -errno) {
|
||||
if (strstr(dent->d_name, "fw-cfg")) {
|
||||
*_id = "qemu";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
FOREACH_DIRENT(dent, dir, return -errno)
|
||||
if (strstr(dent->d_name, "fw-cfg"))
|
||||
return VIRTUALIZATION_QEMU;
|
||||
|
||||
return VIRTUALIZATION_NONE;
|
||||
} else if (r < 0)
|
||||
return r;
|
||||
|
||||
if (streq(hvtype, "linux,kvm"))
|
||||
return VIRTUALIZATION_KVM;
|
||||
else if (strstr(hvtype, "xen"))
|
||||
return VIRTUALIZATION_XEN;
|
||||
else
|
||||
return VIRTUALIZATION_VM_OTHER;
|
||||
#else
|
||||
return VIRTUALIZATION_NONE;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int detect_vm_dmi(const char **_id) {
|
||||
static int detect_vm_dmi(void) {
|
||||
|
||||
/* Both CPUID and DMI are x86 specific interfaces... */
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
@ -149,188 +150,195 @@ static int detect_vm_dmi(const char **_id) {
|
||||
"/sys/class/dmi/id/bios_vendor"
|
||||
};
|
||||
|
||||
static const char dmi_vendor_table[] =
|
||||
"QEMU\0" "qemu\0"
|
||||
static const struct {
|
||||
const char *vendor;
|
||||
int id;
|
||||
} dmi_vendor_table[] = {
|
||||
{ "QEMU", VIRTUALIZATION_QEMU },
|
||||
/* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
|
||||
"VMware\0" "vmware\0"
|
||||
"VMW\0" "vmware\0"
|
||||
"innotek GmbH\0" "oracle\0"
|
||||
"Xen\0" "xen\0"
|
||||
"Bochs\0" "bochs\0"
|
||||
"Parallels\0" "parallels\0";
|
||||
{ "VMware", VIRTUALIZATION_VMWARE },
|
||||
{ "VMW", VIRTUALIZATION_VMWARE },
|
||||
{ "innotek GmbH", VIRTUALIZATION_ORACLE },
|
||||
{ "Xen", VIRTUALIZATION_XEN },
|
||||
{ "Bochs", VIRTUALIZATION_BOCHS },
|
||||
{ "Parallels", VIRTUALIZATION_PARALLELS },
|
||||
};
|
||||
unsigned i;
|
||||
int r;
|
||||
|
||||
for (i = 0; i < ELEMENTSOF(dmi_vendors); i++) {
|
||||
_cleanup_free_ char *s = NULL;
|
||||
const char *j, *k;
|
||||
int r;
|
||||
unsigned j;
|
||||
|
||||
r = read_one_line_file(dmi_vendors[i], &s);
|
||||
if (r < 0) {
|
||||
if (r != -ENOENT)
|
||||
return r;
|
||||
if (r == -ENOENT)
|
||||
continue;
|
||||
|
||||
continue;
|
||||
return r;
|
||||
}
|
||||
|
||||
NULSTR_FOREACH_PAIR(j, k, dmi_vendor_table)
|
||||
if (startswith(s, j)) {
|
||||
*_id = k;
|
||||
return 1;
|
||||
}
|
||||
for (j = 0; j < ELEMENTSOF(dmi_vendor_table); j++)
|
||||
if (startswith(s, dmi_vendor_table[j].vendor))
|
||||
return dmi_vendor_table[j].id;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
return VIRTUALIZATION_NONE;
|
||||
}
|
||||
|
||||
/* Returns a short identifier for the various VM implementations */
|
||||
int detect_vm(const char **id) {
|
||||
_cleanup_free_ char *domcap = NULL, *cpuinfo_contents = NULL;
|
||||
static thread_local int cached_found = -1;
|
||||
static thread_local const char *cached_id = NULL;
|
||||
const char *_id = NULL, *_id_cpuid = NULL;
|
||||
static int detect_vm_xen(void) {
|
||||
_cleanup_free_ char *domcap = NULL;
|
||||
char *cap, *i;
|
||||
int r;
|
||||
|
||||
if (_likely_(cached_found >= 0)) {
|
||||
|
||||
if (id)
|
||||
*id = cached_id;
|
||||
|
||||
return cached_found;
|
||||
}
|
||||
|
||||
/* Try xen capabilities file first, if not found try high-level hypervisor sysfs file:
|
||||
*
|
||||
* https://bugs.freedesktop.org/show_bug.cgi?id=77271 */
|
||||
r = read_one_line_file("/proc/xen/capabilities", &domcap);
|
||||
if (r >= 0) {
|
||||
char *cap, *i = domcap;
|
||||
if (r == -ENOENT)
|
||||
return VIRTUALIZATION_NONE;
|
||||
|
||||
while ((cap = strsep(&i, ",")))
|
||||
if (streq(cap, "control_d"))
|
||||
break;
|
||||
i = domcap;
|
||||
while ((cap = strsep(&i, ",")))
|
||||
if (streq(cap, "control_d"))
|
||||
break;
|
||||
|
||||
if (!cap) {
|
||||
_id = "xen";
|
||||
r = 1;
|
||||
}
|
||||
return cap ? VIRTUALIZATION_NONE : VIRTUALIZATION_XEN;
|
||||
}
|
||||
|
||||
goto finish;
|
||||
static int detect_vm_hypervisor(void) {
|
||||
_cleanup_free_ char *hvtype = NULL;
|
||||
int r;
|
||||
|
||||
} else if (r == -ENOENT) {
|
||||
_cleanup_free_ char *hvtype = NULL;
|
||||
|
||||
r = read_one_line_file("/sys/hypervisor/type", &hvtype);
|
||||
if (r >= 0) {
|
||||
if (streq(hvtype, "xen")) {
|
||||
_id = "xen";
|
||||
r = 1;
|
||||
goto finish;
|
||||
}
|
||||
} else if (r != -ENOENT)
|
||||
return r;
|
||||
} else
|
||||
r = read_one_line_file("/sys/hypervisor/type", &hvtype);
|
||||
if (r == -ENOENT)
|
||||
return VIRTUALIZATION_NONE;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* this will set _id to "other" and return 0 for unknown hypervisors */
|
||||
r = detect_vm_cpuid(&_id);
|
||||
if (streq(hvtype, "xen"))
|
||||
return VIRTUALIZATION_XEN;
|
||||
else
|
||||
return VIRTUALIZATION_VM_OTHER;
|
||||
}
|
||||
|
||||
/* finish when found a known hypervisor other than kvm */
|
||||
if (r < 0 || (r > 0 && !streq(_id, "kvm")))
|
||||
goto finish;
|
||||
|
||||
_id_cpuid = _id;
|
||||
|
||||
r = detect_vm_dmi(&_id);
|
||||
|
||||
/* kvm with and without Virtualbox */
|
||||
/* Parallels exports KVMKVMKVM leaf */
|
||||
if (streq_ptr(_id_cpuid, "kvm")) {
|
||||
if (r > 0 && (streq(_id, "oracle") || streq(_id, "parallels")))
|
||||
goto finish;
|
||||
|
||||
_id = _id_cpuid;
|
||||
r = 1;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
/* information from dmi */
|
||||
if (r != 0)
|
||||
goto finish;
|
||||
|
||||
r = detect_vm_devicetree(&_id);
|
||||
if (r != 0)
|
||||
goto finish;
|
||||
|
||||
if (_id) {
|
||||
/* "other" */
|
||||
r = 1;
|
||||
goto finish;
|
||||
}
|
||||
static int detect_vm_uml(void) {
|
||||
_cleanup_free_ char *cpuinfo_contents = NULL;
|
||||
int r;
|
||||
|
||||
/* Detect User-Mode Linux by reading /proc/cpuinfo */
|
||||
r = read_full_file("/proc/cpuinfo", &cpuinfo_contents, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (strstr(cpuinfo_contents, "\nvendor_id\t: User Mode Linux\n")) {
|
||||
_id = "uml";
|
||||
r = 1;
|
||||
goto finish;
|
||||
}
|
||||
if (strstr(cpuinfo_contents, "\nvendor_id\t: User Mode Linux\n"))
|
||||
return VIRTUALIZATION_UML;
|
||||
|
||||
return VIRTUALIZATION_NONE;
|
||||
}
|
||||
|
||||
static int detect_vm_zvm(void) {
|
||||
|
||||
#if defined(__s390__)
|
||||
{
|
||||
_cleanup_free_ char *t = NULL;
|
||||
_cleanup_free_ char *t = NULL;
|
||||
int r;
|
||||
|
||||
r = get_status_field("/proc/sysinfo", "VM00 Control Program:", &t);
|
||||
if (r >= 0) {
|
||||
if (streq(t, "z/VM"))
|
||||
_id = "zvm";
|
||||
else
|
||||
_id = "kvm";
|
||||
r = 1;
|
||||
r = get_status_field("/proc/sysinfo", "VM00 Control Program:", &t);
|
||||
if (r == -ENOENT)
|
||||
return VIRTUALIZATION_NONE;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
if (streq(t, "z/VM"))
|
||||
return VIRTUALIZATION_ZVM;
|
||||
else
|
||||
return VIRTUALIZATION_KVM;
|
||||
#else
|
||||
return VIRTUALIZATION_NONE;
|
||||
#endif
|
||||
}
|
||||
|
||||
r = 0;
|
||||
/* Returns a short identifier for the various VM implementations */
|
||||
int detect_vm(void) {
|
||||
static thread_local int cached_found = _VIRTUALIZATION_INVALID;
|
||||
int r;
|
||||
|
||||
if (cached_found >= 0)
|
||||
return cached_found;
|
||||
|
||||
/* Try xen capabilities file first, if not found try
|
||||
* high-level hypervisor sysfs file:
|
||||
*
|
||||
* https://bugs.freedesktop.org/show_bug.cgi?id=77271 */
|
||||
|
||||
r = detect_vm_xen();
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r != VIRTUALIZATION_NONE)
|
||||
goto finish;
|
||||
|
||||
r = detect_vm_dmi();
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r != VIRTUALIZATION_NONE)
|
||||
goto finish;
|
||||
|
||||
r = detect_vm_cpuid();
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r != VIRTUALIZATION_NONE)
|
||||
goto finish;
|
||||
|
||||
r = detect_vm_hypervisor();
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r != VIRTUALIZATION_NONE)
|
||||
goto finish;
|
||||
|
||||
r = detect_vm_device_tree();
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r != VIRTUALIZATION_NONE)
|
||||
goto finish;
|
||||
|
||||
r = detect_vm_uml();
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r != VIRTUALIZATION_NONE)
|
||||
goto finish;
|
||||
|
||||
r = detect_vm_zvm();
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
finish:
|
||||
cached_found = r;
|
||||
|
||||
cached_id = _id;
|
||||
if (id)
|
||||
*id = _id;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int detect_container(const char **id) {
|
||||
int detect_container(void) {
|
||||
|
||||
static thread_local int cached_found = -1;
|
||||
static thread_local const char *cached_id = NULL;
|
||||
static const struct {
|
||||
const char *value;
|
||||
int id;
|
||||
} value_table[] = {
|
||||
{ "lxc", VIRTUALIZATION_LXC },
|
||||
{ "lxc-libvirt", VIRTUALIZATION_LXC_LIBVIRT },
|
||||
{ "systemd-nspawn", VIRTUALIZATION_SYSTEMD_NSPAWN },
|
||||
{ "docker", VIRTUALIZATION_DOCKER },
|
||||
};
|
||||
|
||||
static thread_local int cached_found = _VIRTUALIZATION_INVALID;
|
||||
_cleanup_free_ char *m = NULL;
|
||||
const char *_id = NULL, *e = NULL;
|
||||
const char *e = NULL;
|
||||
unsigned j;
|
||||
int r;
|
||||
|
||||
if (_likely_(cached_found >= 0)) {
|
||||
|
||||
if (id)
|
||||
*id = cached_id;
|
||||
|
||||
if (cached_found >= 0)
|
||||
return cached_found;
|
||||
}
|
||||
|
||||
/* /proc/vz exists in container and outside of the container,
|
||||
* /proc/bc only outside of the container. */
|
||||
if (access("/proc/vz", F_OK) >= 0 &&
|
||||
access("/proc/bc", F_OK) < 0) {
|
||||
_id = "openvz";
|
||||
r = 1;
|
||||
r = VIRTUALIZATION_OPENVZ;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
@ -340,7 +348,7 @@ int detect_container(const char **id) {
|
||||
|
||||
e = getenv("container");
|
||||
if (isempty(e)) {
|
||||
r = 0;
|
||||
r = VIRTUALIZATION_NONE;
|
||||
goto finish;
|
||||
}
|
||||
} else {
|
||||
@ -369,7 +377,7 @@ int detect_container(const char **id) {
|
||||
* as /proc/1/environ is only readable
|
||||
* with privileges. */
|
||||
|
||||
r = 0;
|
||||
r = VIRTUALIZATION_NONE;
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
@ -379,46 +387,49 @@ int detect_container(const char **id) {
|
||||
e = m;
|
||||
}
|
||||
|
||||
/* We only recognize a selected few here, since we want to
|
||||
* enforce a redacted namespace */
|
||||
if (streq(e, "lxc"))
|
||||
_id ="lxc";
|
||||
else if (streq(e, "lxc-libvirt"))
|
||||
_id = "lxc-libvirt";
|
||||
else if (streq(e, "systemd-nspawn"))
|
||||
_id = "systemd-nspawn";
|
||||
else if (streq(e, "docker"))
|
||||
_id = "docker";
|
||||
else
|
||||
_id = "other";
|
||||
for (j = 0; j < ELEMENTSOF(value_table); j++)
|
||||
if (streq(e, value_table[j].value)) {
|
||||
r = value_table[j].id;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = 1;
|
||||
r = VIRTUALIZATION_NONE;
|
||||
|
||||
finish:
|
||||
cached_found = r;
|
||||
|
||||
cached_id = _id;
|
||||
if (id)
|
||||
*id = _id;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Returns a short identifier for the various VM/container implementations */
|
||||
int detect_virtualization(const char **id) {
|
||||
int detect_virtualization(void) {
|
||||
int r;
|
||||
|
||||
r = detect_container(id);
|
||||
if (r < 0)
|
||||
r = detect_container();
|
||||
if (r != 0)
|
||||
return r;
|
||||
if (r > 0)
|
||||
return VIRTUALIZATION_CONTAINER;
|
||||
|
||||
r = detect_vm(id);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0)
|
||||
return VIRTUALIZATION_VM;
|
||||
|
||||
return VIRTUALIZATION_NONE;
|
||||
return detect_vm();
|
||||
}
|
||||
|
||||
static const char *const virtualization_table[_VIRTUALIZATION_MAX] = {
|
||||
[VIRTUALIZATION_NONE] = "none",
|
||||
[VIRTUALIZATION_KVM] = "kvm",
|
||||
[VIRTUALIZATION_QEMU] = "qemu",
|
||||
[VIRTUALIZATION_BOCHS] = "bochs",
|
||||
[VIRTUALIZATION_XEN] = "xen",
|
||||
[VIRTUALIZATION_UML] = "uml",
|
||||
[VIRTUALIZATION_VMWARE] = "vmware",
|
||||
[VIRTUALIZATION_ORACLE] = "oracle",
|
||||
[VIRTUALIZATION_MICROSOFT] = "microsoft",
|
||||
[VIRTUALIZATION_ZVM] = "zvm",
|
||||
[VIRTUALIZATION_PARALLELS] = "parallels",
|
||||
[VIRTUALIZATION_VM_OTHER] = "vm-other",
|
||||
|
||||
[VIRTUALIZATION_SYSTEMD_NSPAWN] = "systemd-nspawn",
|
||||
[VIRTUALIZATION_LXC_LIBVIRT] = "lxc-libvirt",
|
||||
[VIRTUALIZATION_LXC] = "lxc",
|
||||
[VIRTUALIZATION_OPENVZ] = "openvz",
|
||||
[VIRTUALIZATION_DOCKER] = "docker",
|
||||
[VIRTUALIZATION_CONTAINER_OTHER] = "container-other",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(virtualization, int);
|
||||
|
@ -21,15 +21,51 @@
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
int detect_vm(const char **id);
|
||||
int detect_container(const char **id);
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "macro.h"
|
||||
|
||||
enum {
|
||||
VIRTUALIZATION_NONE = 0,
|
||||
VIRTUALIZATION_VM,
|
||||
VIRTUALIZATION_CONTAINER,
|
||||
|
||||
VIRTUALIZATION_VM_FIRST,
|
||||
VIRTUALIZATION_KVM = VIRTUALIZATION_VM_FIRST,
|
||||
VIRTUALIZATION_QEMU,
|
||||
VIRTUALIZATION_BOCHS,
|
||||
VIRTUALIZATION_XEN,
|
||||
VIRTUALIZATION_UML,
|
||||
VIRTUALIZATION_VMWARE,
|
||||
VIRTUALIZATION_ORACLE,
|
||||
VIRTUALIZATION_MICROSOFT,
|
||||
VIRTUALIZATION_ZVM,
|
||||
VIRTUALIZATION_PARALLELS,
|
||||
VIRTUALIZATION_VM_OTHER,
|
||||
VIRTUALIZATION_VM_LAST = VIRTUALIZATION_VM_OTHER,
|
||||
|
||||
VIRTUALIZATION_CONTAINER_FIRST,
|
||||
VIRTUALIZATION_SYSTEMD_NSPAWN = VIRTUALIZATION_CONTAINER_FIRST,
|
||||
VIRTUALIZATION_LXC_LIBVIRT,
|
||||
VIRTUALIZATION_LXC,
|
||||
VIRTUALIZATION_OPENVZ,
|
||||
VIRTUALIZATION_DOCKER,
|
||||
VIRTUALIZATION_CONTAINER_OTHER,
|
||||
VIRTUALIZATION_CONTAINER_LAST = VIRTUALIZATION_CONTAINER_OTHER,
|
||||
|
||||
_VIRTUALIZATION_MAX,
|
||||
_VIRTUALIZATION_INVALID = -1
|
||||
};
|
||||
|
||||
int detect_virtualization(const char **id);
|
||||
static inline bool VIRTUALIZATION_IS_VM(int x) {
|
||||
return x >= VIRTUALIZATION_VM_FIRST && x <= VIRTUALIZATION_VM_LAST;
|
||||
}
|
||||
|
||||
static inline bool VIRTUALIZATION_IS_CONTAINER(int x) {
|
||||
return x >= VIRTUALIZATION_CONTAINER_FIRST && x <= VIRTUALIZATION_CONTAINER_LAST;
|
||||
}
|
||||
|
||||
int detect_vm(void);
|
||||
int detect_container(void);
|
||||
int detect_virtualization(void);
|
||||
|
||||
const char *virtualization_to_string(int v) _const_;
|
||||
int virtualization_from_string(const char *s) _pure_;
|
||||
|
@ -81,14 +81,10 @@ static int property_get_virtualization(
|
||||
void *userdata,
|
||||
sd_bus_error *error) {
|
||||
|
||||
const char *id = NULL;
|
||||
|
||||
assert(bus);
|
||||
assert(reply);
|
||||
|
||||
detect_virtualization(&id);
|
||||
|
||||
return sd_bus_message_append(reply, "s", id);
|
||||
return sd_bus_message_append(reply, "s", virtualization_to_string(detect_virtualization()));
|
||||
}
|
||||
|
||||
static int property_get_architecture(
|
||||
|
@ -1137,7 +1137,7 @@ void job_shutdown_magic(Job *j) {
|
||||
/* In case messages on console has been disabled on boot */
|
||||
j->unit->manager->no_console_output = false;
|
||||
|
||||
if (detect_container(NULL) > 0)
|
||||
if (detect_container() > 0)
|
||||
return;
|
||||
|
||||
asynchronous_sync();
|
||||
|
@ -35,7 +35,7 @@ int locale_setup(char ***environment) {
|
||||
char *variables[_VARIABLE_LC_MAX] = {};
|
||||
int r = 0, i;
|
||||
|
||||
if (detect_container(NULL) <= 0) {
|
||||
if (detect_container() <= 0) {
|
||||
r = parse_env_file("/proc/cmdline", WHITESPACE,
|
||||
"locale.LANG", &variables[VARIABLE_LANG],
|
||||
"locale.LANGUAGE", &variables[VARIABLE_LANGUAGE],
|
||||
|
@ -108,7 +108,7 @@ static int generate_machine_id(char id[34], const char *root) {
|
||||
unsigned char *p;
|
||||
sd_id128_t buf;
|
||||
char *q;
|
||||
const char *vm_id, *dbus_machine_id;
|
||||
const char *dbus_machine_id;
|
||||
|
||||
assert(id);
|
||||
|
||||
@ -133,8 +133,8 @@ static int generate_machine_id(char id[34], const char *root) {
|
||||
/* If that didn't work, see if we are running in a container,
|
||||
* and a machine ID was passed in via $container_uuid the way
|
||||
* libvirt/LXC does it */
|
||||
r = detect_container(NULL);
|
||||
if (r > 0) {
|
||||
|
||||
if (detect_container() > 0) {
|
||||
_cleanup_free_ char *e = NULL;
|
||||
|
||||
r = getenv_for_pid(1, "container_uuid", &e);
|
||||
@ -146,26 +146,24 @@ static int generate_machine_id(char id[34], const char *root) {
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
} else if (detect_vm() == VIRTUALIZATION_KVM) {
|
||||
|
||||
/* If we are not running in a container, see if we are
|
||||
* running in qemu/kvm and a machine ID was passed in
|
||||
* via -uuid on the qemu/kvm command line */
|
||||
|
||||
r = detect_vm(&vm_id);
|
||||
if (r > 0 && streq(vm_id, "kvm")) {
|
||||
char uuid[36];
|
||||
char uuid[36];
|
||||
|
||||
fd = open("/sys/class/dmi/id/product_uuid", O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
|
||||
if (fd >= 0) {
|
||||
r = loop_read_exact(fd, uuid, 36, false);
|
||||
safe_close(fd);
|
||||
fd = open("/sys/class/dmi/id/product_uuid", O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
|
||||
if (fd >= 0) {
|
||||
r = loop_read_exact(fd, uuid, 36, false);
|
||||
safe_close(fd);
|
||||
|
||||
if (r >= 0) {
|
||||
r = shorten_uuid(id, uuid);
|
||||
if (r >= 0) {
|
||||
r = shorten_uuid(id, uuid);
|
||||
if (r >= 0) {
|
||||
log_info("Initializing machine ID from KVM UUID.");
|
||||
return 0;
|
||||
}
|
||||
log_info("Initializing machine ID from KVM UUID.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -374,7 +374,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value) {
|
||||
/* Note that log_parse_environment() handles 'debug'
|
||||
* too, and sets the log level to LOG_DEBUG. */
|
||||
|
||||
if (detect_container(NULL) > 0)
|
||||
if (detect_container() > 0)
|
||||
log_set_target(LOG_TARGET_CONSOLE);
|
||||
|
||||
} else if (!in_initrd() && !value) {
|
||||
@ -1297,7 +1297,7 @@ int main(int argc, char *argv[]) {
|
||||
if (getpid() == 1)
|
||||
umask(0);
|
||||
|
||||
if (getpid() == 1 && detect_container(NULL) <= 0) {
|
||||
if (getpid() == 1 && detect_container() <= 0) {
|
||||
|
||||
/* Running outside of a container as PID 1 */
|
||||
arg_running_as = MANAGER_SYSTEM;
|
||||
@ -1551,14 +1551,14 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
if (arg_running_as == MANAGER_SYSTEM) {
|
||||
const char *virtualization = NULL;
|
||||
int v;
|
||||
|
||||
log_info(PACKAGE_STRING " running in %ssystem mode. (" SYSTEMD_FEATURES ")",
|
||||
arg_action == ACTION_TEST ? "test " : "" );
|
||||
|
||||
detect_virtualization(&virtualization);
|
||||
if (virtualization)
|
||||
log_info("Detected virtualization %s.", virtualization);
|
||||
v = detect_virtualization();
|
||||
if (v > 0)
|
||||
log_info("Detected virtualization %s.", virtualization_to_string(v));
|
||||
|
||||
write_container_id();
|
||||
|
||||
@ -2046,7 +2046,7 @@ finish:
|
||||
/* Avoid the creation of new processes forked by the
|
||||
* kernel; at this point, we will not listen to the
|
||||
* signals anyway */
|
||||
if (detect_container(NULL) <= 0)
|
||||
if (detect_container() <= 0)
|
||||
(void) cg_uninstall_release_agent(SYSTEMD_CGROUP_CONTROLLER);
|
||||
|
||||
execve(SYSTEMD_SHUTDOWN_BINARY_PATH, (char **) command_line, env_block);
|
||||
|
@ -554,7 +554,7 @@ int manager_new(ManagerRunningAs running_as, bool test_run, Manager **_m) {
|
||||
return -ENOMEM;
|
||||
|
||||
#ifdef ENABLE_EFI
|
||||
if (running_as == MANAGER_SYSTEM && detect_container(NULL) <= 0)
|
||||
if (running_as == MANAGER_SYSTEM && detect_container() <= 0)
|
||||
boot_timestamps(&m->userspace_timestamp, &m->firmware_timestamp, &m->loader_timestamp);
|
||||
#endif
|
||||
|
||||
@ -2156,7 +2156,7 @@ void manager_send_unit_plymouth(Manager *m, Unit *u) {
|
||||
if (m->running_as != MANAGER_SYSTEM)
|
||||
return;
|
||||
|
||||
if (detect_container(NULL) > 0)
|
||||
if (detect_container() > 0)
|
||||
return;
|
||||
|
||||
if (u->type != UNIT_SERVICE &&
|
||||
@ -2613,7 +2613,7 @@ static void manager_notify_finished(Manager *m) {
|
||||
if (m->test_run)
|
||||
return;
|
||||
|
||||
if (m->running_as == MANAGER_SYSTEM && detect_container(NULL) <= 0) {
|
||||
if (m->running_as == MANAGER_SYSTEM && detect_container() <= 0) {
|
||||
|
||||
/* Note that m->kernel_usec.monotonic is always at 0,
|
||||
* and m->firmware_usec.monotonic and
|
||||
|
@ -164,7 +164,7 @@ static int mount_one(const MountPoint *p, bool relabel) {
|
||||
return 0;
|
||||
|
||||
/* Skip securityfs in a container */
|
||||
if (!(p->mode & MNT_IN_CONTAINER) && detect_container(NULL) > 0)
|
||||
if (!(p->mode & MNT_IN_CONTAINER) && detect_container() > 0)
|
||||
return 0;
|
||||
|
||||
/* The access mode here doesn't really matter too much, since
|
||||
@ -385,7 +385,7 @@ int mount_setup(bool loaded_policy) {
|
||||
* nspawn and the container tools work out of the box. If
|
||||
* specific setups need other settings they can reset the
|
||||
* propagation mode to private if needed. */
|
||||
if (detect_container(NULL) <= 0)
|
||||
if (detect_container() <= 0)
|
||||
if (mount(NULL, "/", NULL, MS_REC|MS_SHARED, NULL) < 0)
|
||||
log_warning_errno(errno, "Failed to set up the root directory for shared mount propagation: %m");
|
||||
|
||||
|
@ -202,7 +202,7 @@ int main(int argc, char *argv[]) {
|
||||
log_info("Sending SIGKILL to remaining processes...");
|
||||
broadcast_signal(SIGKILL, true, false);
|
||||
|
||||
in_container = detect_container(NULL) > 0;
|
||||
in_container = detect_container() > 0;
|
||||
|
||||
need_umount = !in_container;
|
||||
need_swapoff = !in_container;
|
||||
|
@ -215,7 +215,7 @@ static int swap_add_default_dependencies(Swap *s) {
|
||||
if (UNIT(s)->manager->running_as != MANAGER_SYSTEM)
|
||||
return 0;
|
||||
|
||||
if (detect_container(NULL) > 0)
|
||||
if (detect_container() > 0)
|
||||
return 0;
|
||||
|
||||
return unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true);
|
||||
@ -824,7 +824,7 @@ static int swap_start(Unit *u) {
|
||||
|
||||
assert(s->state == SWAP_DEAD || s->state == SWAP_FAILED);
|
||||
|
||||
if (detect_container(NULL) > 0)
|
||||
if (detect_container() > 0)
|
||||
return -EPERM;
|
||||
|
||||
/* If there's a job for another swap unit for the same node
|
||||
@ -857,7 +857,7 @@ static int swap_stop(Unit *u) {
|
||||
s->state == SWAP_ACTIVATING_DONE ||
|
||||
s->state == SWAP_ACTIVE);
|
||||
|
||||
if (detect_container(NULL) > 0)
|
||||
if (detect_container() > 0)
|
||||
return -EPERM;
|
||||
|
||||
swap_enter_deactivating(s);
|
||||
@ -1404,7 +1404,7 @@ static bool swap_supported(void) {
|
||||
if (supported < 0)
|
||||
supported =
|
||||
access("/proc/swaps", F_OK) >= 0 &&
|
||||
detect_container(NULL) <= 0;
|
||||
detect_container() <= 0;
|
||||
|
||||
return supported;
|
||||
}
|
||||
|
@ -368,7 +368,7 @@ static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_e
|
||||
read-only mount anything as that brings no real
|
||||
benefits, but might confuse the host, as we remount
|
||||
the superblock here, not the bind mound. */
|
||||
if (detect_container(NULL) <= 0) {
|
||||
if (detect_container() <= 0) {
|
||||
/* We always try to remount directories
|
||||
* read-only first, before we go on and umount
|
||||
* them.
|
||||
|
@ -3510,7 +3510,7 @@ int unit_kill_context(
|
||||
* them.*/
|
||||
|
||||
if (cg_unified() > 0 ||
|
||||
(detect_container(NULL) == 0 && !unit_cgroup_delegate(u)))
|
||||
(detect_container() == 0 && !unit_cgroup_delegate(u)))
|
||||
wait_for_exit = true;
|
||||
|
||||
if (c->send_sighup && k != KILL_KILL) {
|
||||
|
@ -108,9 +108,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
const char *id = NULL;
|
||||
int retval = EXIT_SUCCESS;
|
||||
int r;
|
||||
int retval = EXIT_SUCCESS, r;
|
||||
|
||||
/* This is mostly intended to be used for scripts which want
|
||||
* to detect whether we are being run in a virtualized
|
||||
@ -125,42 +123,39 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
switch (arg_mode) {
|
||||
|
||||
case ANY_VIRTUALIZATION: {
|
||||
int v;
|
||||
|
||||
v = detect_virtualization(&id);
|
||||
if (v < 0) {
|
||||
log_error_errno(v, "Failed to check for virtualization: %m");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
retval = v != VIRTUALIZATION_NONE ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
case ONLY_CONTAINER:
|
||||
r = detect_container(&id);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to check for container: %m");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
retval = r > 0 ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
break;
|
||||
|
||||
case ONLY_VM:
|
||||
r = detect_vm(&id);
|
||||
r = detect_vm();
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to check for vm: %m");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
retval = r > 0 ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
break;
|
||||
|
||||
case ONLY_CONTAINER:
|
||||
r = detect_container();
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to check for container: %m");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case ANY_VIRTUALIZATION:
|
||||
default:
|
||||
r = detect_virtualization();
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to check for virtualization: %m");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (!arg_quiet)
|
||||
puts(id ? id : "none");
|
||||
puts(virtualization_to_string(r));
|
||||
|
||||
retval = r != VIRTUALIZATION_NONE ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ static int add_swap(
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (detect_container(NULL) > 0) {
|
||||
if (detect_container() > 0) {
|
||||
log_info("Running in a container, ignoring fstab swap entry for %s.", what);
|
||||
return 0;
|
||||
}
|
||||
|
@ -142,7 +142,7 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
umask(0022);
|
||||
|
||||
if (detect_container(NULL) > 0) {
|
||||
if (detect_container() > 0) {
|
||||
_cleanup_free_ char *container_ttys = NULL;
|
||||
|
||||
log_debug("Automatically adding console shell.");
|
||||
|
@ -460,7 +460,7 @@ static int add_boot(const char *what) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (detect_container(NULL) > 0) {
|
||||
if (detect_container() > 0) {
|
||||
log_debug("In a container, ignoring /boot.");
|
||||
return 0;
|
||||
}
|
||||
@ -992,7 +992,7 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
umask(0022);
|
||||
|
||||
if (detect_container(NULL) > 0) {
|
||||
if (detect_container() > 0) {
|
||||
log_debug("In a container, exiting.");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -155,11 +155,11 @@ static const char* fallback_chassis(void) {
|
||||
unsigned t;
|
||||
int v;
|
||||
|
||||
v = detect_virtualization(NULL);
|
||||
v = detect_virtualization();
|
||||
|
||||
if (v == VIRTUALIZATION_VM)
|
||||
if (VIRTUALIZATION_IS_VM(v))
|
||||
return "vm";
|
||||
if (v == VIRTUALIZATION_CONTAINER)
|
||||
if (VIRTUALIZATION_IS_CONTAINER(v))
|
||||
return "container";
|
||||
|
||||
r = read_one_line_file("/sys/firmware/acpi/pm_profile", &type);
|
||||
|
@ -66,7 +66,7 @@ int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_i
|
||||
const char *name = NULL;
|
||||
uint64_t id;
|
||||
|
||||
if (detect_container(NULL) <= 0) {
|
||||
if (detect_container() <= 0) {
|
||||
/* not in a container, udev will be around */
|
||||
_cleanup_udev_unref_ struct udev *udev;
|
||||
char ifindex_str[2 + DECIMAL_STR_MAX(int)];
|
||||
|
@ -357,18 +357,6 @@ static int test_hangcheck(sd_event_source *s, uint64_t usec, void *userdata) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int detect_vm(const char **id) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int detect_container(const char **id) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int detect_virtualization(const char **id) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void test_client_solicit_cb(sd_dhcp6_client *client, int event,
|
||||
void *userdata) {
|
||||
sd_event *e = userdata;
|
||||
|
@ -96,7 +96,7 @@ static void print_overridden_variables(void) {
|
||||
LocaleVariable j;
|
||||
bool print_warning = true;
|
||||
|
||||
if (detect_container(NULL) > 0 || arg_host)
|
||||
if (detect_container() > 0 || arg_host)
|
||||
return;
|
||||
|
||||
r = parse_env_file("/proc/cmdline", WHITESPACE,
|
||||
|
@ -2152,7 +2152,7 @@ int link_add(Manager *m, sd_netlink_message *message, Link **ret) {
|
||||
|
||||
log_link_debug(link, "Link %d added", link->ifindex);
|
||||
|
||||
if (detect_container(NULL) <= 0) {
|
||||
if (detect_container() <= 0) {
|
||||
/* not in a container, udev will be around */
|
||||
sprintf(ifindex_str, "n%d", link->ifindex);
|
||||
device = udev_device_new_from_device_id(m->udev, ifindex_str);
|
||||
|
@ -241,7 +241,7 @@ static int manager_connect_udev(Manager *m) {
|
||||
/* udev does not initialize devices inside containers,
|
||||
* so we rely on them being already initialized before
|
||||
* entering the container */
|
||||
if (detect_container(NULL) > 0)
|
||||
if (detect_container() > 0)
|
||||
return 0;
|
||||
|
||||
m->udev = udev_new();
|
||||
|
@ -125,13 +125,12 @@ static int condition_test_kernel_command_line(Condition *c) {
|
||||
|
||||
static int condition_test_virtualization(Condition *c) {
|
||||
int b, v;
|
||||
const char *id;
|
||||
|
||||
assert(c);
|
||||
assert(c->parameter);
|
||||
assert(c->type == CONDITION_VIRTUALIZATION);
|
||||
|
||||
v = detect_virtualization(&id);
|
||||
v = detect_virtualization();
|
||||
if (v < 0)
|
||||
return v;
|
||||
|
||||
@ -145,14 +144,14 @@ static int condition_test_virtualization(Condition *c) {
|
||||
return true;
|
||||
|
||||
/* Then, compare categorization */
|
||||
if (v == VIRTUALIZATION_VM && streq(c->parameter, "vm"))
|
||||
if (VIRTUALIZATION_IS_VM(v) && streq(c->parameter, "vm"))
|
||||
return true;
|
||||
|
||||
if (v == VIRTUALIZATION_CONTAINER && streq(c->parameter, "container"))
|
||||
if (VIRTUALIZATION_IS_CONTAINER(v) && streq(c->parameter, "container"))
|
||||
return true;
|
||||
|
||||
/* Finally compare id */
|
||||
return v > 0 && streq(c->parameter, id);
|
||||
return v != VIRTUALIZATION_NONE && streq(c->parameter, virtualization_to_string(v));
|
||||
}
|
||||
|
||||
static int condition_test_architecture(Condition *c) {
|
||||
|
@ -101,7 +101,7 @@ int efi_reboot_to_firmware_supported(void) {
|
||||
uint64_t b;
|
||||
_cleanup_free_ void *v = NULL;
|
||||
|
||||
if (!is_efi_boot() || detect_container(NULL) > 0)
|
||||
if (!is_efi_boot() || detect_container() > 0)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
r = efi_get_variable(EFI_VENDOR_GLOBAL, "OsIndicationsSupported", NULL, &v, &s);
|
||||
|
@ -25,18 +25,18 @@
|
||||
#include "log.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
const char *id = NULL;
|
||||
int a, v;
|
||||
|
||||
v = detect_virtualization(&id);
|
||||
v = detect_virtualization();
|
||||
if (v == -EPERM || v == -EACCES)
|
||||
return EXIT_TEST_SKIP;
|
||||
|
||||
assert_se(v >= 0);
|
||||
|
||||
log_info("virtualization=%s id=%s",
|
||||
v == VIRTUALIZATION_CONTAINER ? "container" : v == VIRTUALIZATION_VM ? "vm" : "n/a",
|
||||
strna(id));
|
||||
VIRTUALIZATION_IS_CONTAINER(v) ? "container" :
|
||||
VIRTUALIZATION_IS_VM(v) ? "vm" : "n/a",
|
||||
virtualization_to_string(v));
|
||||
|
||||
a = uname_architecture();
|
||||
assert_se(a >= 0);
|
||||
|
@ -85,7 +85,7 @@ static void test_get_process_comm(void) {
|
||||
assert_se(r >= 0 || r == -EACCES);
|
||||
log_info("self strlen(environ): '%zu'", strlen(env));
|
||||
|
||||
if (!detect_container(NULL))
|
||||
if (!detect_container())
|
||||
assert_se(get_ctty_devnr(1, &h) == -ENXIO);
|
||||
|
||||
getenv_for_pid(1, "PATH", &i);
|
||||
|
@ -293,7 +293,7 @@ int main(int argc, char **argv) {
|
||||
log_warning_errno(r, "Failed to read /etc/vconsole.conf: %m");
|
||||
|
||||
/* Let the kernel command line override /etc/vconsole.conf */
|
||||
if (detect_container(NULL) <= 0) {
|
||||
if (detect_container() <= 0) {
|
||||
r = parse_env_file("/proc/cmdline", WHITESPACE,
|
||||
"vconsole.keymap", &vc_keymap,
|
||||
"vconsole.keymap.toggle", &vc_keymap_toggle,
|
||||
|
Loading…
x
Reference in New Issue
Block a user