[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[virt-tools-list] [RFC] virt-what as a reusable library



All:

I am working on a project which would like to know if the current machine is a guest, and if so what type of guest it is. This functionality is currently available in virt-what[1]. The current implementation is a bash shell which invokes a C libary. Our project would be interested in seeing this functionality provided as a library (C or python is preferred). I sample python patch (probably not the best) is attached.

Would other folks see value in a library such as this? I am concerned that if projects each take different takes on this functionality by copying the code we are likely to diverge with un-desirable results.

-- bk

[1] http://people.redhat.com/~rjones/virt-what/
>From b8207f73a5cea4a7ec36f0d8e332828d900ee406 Mon Sep 17 00:00:00 2001
From: Bryan Kearney <bkearney redhat com>
Date: Thu, 11 Nov 2010 09:51:22 -0500
Subject: [PATCH] Move the logic for detecting the hypervisor type into a python library. This should allow other tools to make use of the same logic. The binary (now python instead of bash) just calls into the library

---
 .gitignore     |    1 +
 Makefile.am    |    2 +
 README         |    2 +
 configure.ac   |    3 +
 virt-what.in   |  172 ++++++++++------------------------------------------
 virt_detect.py |  184 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 225 insertions(+), 139 deletions(-)
 create mode 100644 virt_detect.py

diff --git a/.gitignore b/.gitignore
index 72dc52e..35e5ae6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,3 +20,4 @@ virt-what
 virt-what-cpuid-helper
 virt-what.1
 virt-what.txt
+py-compile
diff --git a/Makefile.am b/Makefile.am
index 5f76d8f..605684d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -26,6 +26,8 @@ libexec_PROGRAMS = virt-what-cpuid-helper
 
 man_MANS = virt-what.1
 
+python_PYTHON = virt_detect.py
+
 virt-what.1: virt-what.pod
 	pod2man -c "Virtualization Support" --release "$(PACKAGE)-$(VERSION)" \
 	  $< > $@
diff --git a/README b/README
index a363ddb..c46ebff 100644
--- a/README
+++ b/README
@@ -7,6 +7,8 @@ sort of virtualization you are running inside.
 
 Build:
 
+  aclocal
+  autoconf
   ./configure
   make
 
diff --git a/configure.ac b/configure.ac
index 137e1f4..0ff5cdc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -23,6 +23,9 @@ AC_PROG_CC_STDC
 AC_PROG_INSTALL
 AC_PROG_CPP
 
+dnl Python library
+AM_PATH_PYTHON
+
 AC_C_PROTOTYPES
 test "x$U" != "x" && AC_MSG_ERROR([Compiler not ANSI compliant])
 
diff --git a/virt-what.in b/virt-what.in
index 96c18b4..e6d9f92 100644
--- a/virt-what.in
+++ b/virt-what.in
@@ -1,152 +1,46 @@
-#!/bin/bash -
-# @configure_input@
-# Copyright (C) 2008-2010 Red Hat Inc.
+#!/usr/bin/python
 #
-# This program 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 2 of the License, or
-# (at your option) any later version.
+# Copyright (c) 2010 Red Hat, Inc.
 #
-# This program 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.
+# Authors: Pradeep Kilambi
 #
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-# 'virt-what' tries to detect the type of virtualization being
-# used (or none at all if we're running on bare-metal).  It prints
-# out one of more lines each being a 'fact' about the virtualization.
+# This software is licensed to you under the GNU General Public License,
+# version 2 (GPLv2). There is NO WARRANTY for this software, express or
+# implied, including the implied warranties of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
+# along with this software; if not, see
+# http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
 #
-# Please see also the manual page virt-what(1).
-# This script should be run as root.
+# Red Hat trademarks are not licensed under GPLv2. No permission is
+# granted to use or replicate Red Hat trademarks that are incorporated
+# in this software or its documentation.
 #
-# The following resources were useful in writing this script:
-# . http://www.dmo.ca/blog/20080530151107
-
 VERSION="@VERSION@"
 
-function fail {
-    echo "virt-what: $1"
-    exit 1
-}
-
-function usage {
-    echo "virt-what [options]"
-    echo "Options:"
-    echo "  --help          Display this help"
-    echo "  --version       Display version and exit"
-    exit 0
-}
-
-# Handle the command line arguments, if any.
-
-TEMP=`getopt -o v --long help --long version -n 'virt-what' -- "$@"`
-if [ $? != 0 ]; then exit 1; fi
-eval set -- "$TEMP"
-
-while true; do
-    case "$1" in
-	--help) usage ;;
-	-v|--version) echo $VERSION; exit 0 ;;
-	--) shift; break ;;
-	*) fail "internal error" ;;
-    esac
-done
-
-# Check we're running as root.
-
-uid=`id -u`
-if [ "$uid" != 0 ]; then
-    fail "this script must be run as root"
-fi
-
-# Add /sbin and /usr/sbin to the path so we can find system
-# binaries like dmicode.
-# Add /usr/libexec to the path so we can find the helper binary.
-prefix= prefix@
-exec_prefix= exec_prefix@
-PATH= libexecdir@:/sbin:/usr/sbin:$PATH
-
-# Many fullvirt hypervisors give an indication through CPUID.  Use the
-# helper program to get this information.
-
-cpuid=`virt-what-cpuid-helper`
-
-# Check for various products in the BIOS information.
-
-dmi=`dmidecode 2>&1`
-
-# Check for VMware.
-# cpuid check added by Chetan Loke.
-
-if [ "$cpuid" = "VMwareVMware" ]; then
-    echo vmware
-elif echo "$dmi" | grep -q 'Manufacturer: VMware'; then
-    echo vmware
-fi
-
-# Check for VirtualPC.
-
-if echo "$dmi" | grep -q 'Manufacturer: Microsoft Corporation'; then
-    echo virtualpc
-fi
-
-# Check for VirtualBox.
-# Added by Laurent Léonard.
-if echo "$dmi" | grep -q 'Manufacturer: innotek GmbH'; then
-    echo virtualbox
-fi
-
-# Check for OpenVZ / Virtuozzo.
-# Added by Evgeniy Sokolov.
-# /proc/vz - always exists if OpenVZ kernel is running (inside and outside
-# container)
-# /proc/bc - exists on node, but not inside container.
-
-if [ -d /proc/vz -a ! -d /proc/bc ]; then
-    echo openvz
-fi
+import os
+import sys
+from optparse import OptionParser
+from virt_detect import VirtDetect
 
-# Check for UML.
-# Added by Laurent Léonard.
-if grep -q 'UML' /proc/cpuinfo; then
-    echo uml
-fi
+# quick check to see if you are a super-user.
+if os.getuid() != 0:
+    sys.stderr.write('ERROR: must be root to execute\n')
+    sys.exit(8)
 
-# Check for Xen.
+# Parse out any arguments
+args = sys.argv[1:]
 
-if [ "$cpuid" = "XenVMMXenVMM" ]; then
-    echo xen; echo xen-hvm
-    is_xen=1
-elif [ -f /proc/xen/capabilities ]; then
-    echo xen
-    if grep -q "control_d" /proc/xen/capabilities; then
-        echo xen-dom0
-    else
-        echo xen-domU
-    fi
-    is_xen=1
-elif [ -d /proc/xen ]; then
-    # This directory can be present when Xen paravirt drivers are
-    # installed, even on baremetal.  Don't confuse people by
-    # printing anything.
-    :
-fi
+parser = OptionParser("usage: virt-what [OPTIONS]")
+parser.add_option("-v", "--version", action="store_true",
+    dest="show_version",default=False, help="show the version and exit")
+(options, args) = parser.parse_args(args)
 
-# Check for QEMU/KVM.
+if (options.show_version):
+    print VERSION
+    sys.exit(0)
 
-if [ ! "$is_xen" ]; then
-    # Disable this test if we know this is Xen already, because Xen
-    # uses QEMU for its device model.
+vd = VirtDetect()
+types = vd.hypervisor_types()
 
-    if grep -q 'QEMU' /proc/cpuinfo; then
-	if [ "$cpuid" = "KVMKVMKVM" ]; then
-	    echo kvm
-	else
-	    echo qemu
-	fi
-    fi
-fi
+for type in types:
+    print type
diff --git a/virt_detect.py b/virt_detect.py
new file mode 100644
index 0000000..7d05752
--- /dev/null
+++ b/virt_detect.py
@@ -0,0 +1,184 @@
+#
+# Module to probe Hardware info from the system
+#
+# Copyright (c) 2010 Red Hat, Inc.
+#
+# Authors: Pradeep Kilambi <pkilambi redhat com>
+#
+# This software is licensed to you under the GNU General Public License,
+# version 2 (GPLv2). There is NO WARRANTY for this software, express or
+# implied, including the implied warranties of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
+# along with this software; if not, see
+# http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+#
+# Red Hat trademarks are not licensed under GPLv2. No permission is
+# granted to use or replicate Red Hat trademarks that are incorporated
+# in this software or its documentation.
+#
+
+import os
+import sys
+import dmidecode
+
+kvm        = "kvm"
+qemu       = "qemu"
+vmware     = "vmware"
+virtualpc  = "virtualpc"
+virtualbox = "virtualbox"
+openvz     = "openvz"
+uml        = "uml"
+xen        = "xen"
+xenhvm     = "xen-hvm"
+xendom0    = "xen-dom0"
+xendomU    = "xen-domU"
+
+
+# The logic was take from virt-what located at
+# http://people.redhat.com/~rjones/virt-what/
+class VirtDetect:
+
+    def __init__(self):
+        self.cpuid = os.popen("/usr/libexec/virt-what-cpuid-helper").read().strip();
+
+        self.dmi = {
+                "bios": dmidecode.bios(),
+                "processor": dmidecode.processor(),
+                "system": dmidecode.system(),
+                "chassis": dmidecode.chassis(),
+            }
+
+    # Check for VMware.
+    # cpuid check added by Chetan Loke.
+    def on_vmware(self):
+        return (self.cpuid == "VMwareVMware") or (self._is_manufacturer("VMware"))
+
+    def on_virtualpc(self):
+        return self._is_manufacturer("Microsoft Corporation")
+
+    # Check for VirtualBox.
+    # Added by Laurent Leonard.
+    def on_virtualbox(self):
+        return self._is_manufacturer("innotek GmbH")
+
+    # Check for UML.
+    # Added by Laurent Leonard.
+    def on_uml(self):
+        return self._grep("/proc/cpuinfo", "UML")
+
+    def on_xen_hvm(self):
+        return (self.cpuid == "XenVMMXenVMM")
+
+    def is_xen_dom0(self):
+        xen = False
+        if (os.path.exists("proc/xen/capablities")):
+            xen = self_grep("proc/xen/capablities", control_d)
+        return xen
+
+    def is_xen_domU(self):
+        xen = False
+        if (os.path.exists("proc/xen/capablities")):
+            xen = not self_grep("proc/xen/capablities", control_d)
+        return xen
+
+    # Check for OpenVZ / Virtuozzo.
+    # Added by Evgeniy Sokolov.
+    # Need to make sure not xen before running this since
+    # Xen uses QEMU for its device model
+    def on_kvm(self):
+        kvm = False
+        if not (self.on_xen_hvm() or self.is_xen_dom0() or self.is_xen_domU()):
+            if self._grep("/proc/cpuinfo", "QEMU"):
+                kvm = (self.cpuid == "KVMKVMKVM")
+        return kvm
+
+    # Need to make sure not xen before running this since
+    # Xen uses QEMU for its device model
+    def on_qemu(self):
+        qemu = False
+        if not (self.on_xen_hvm() or self.is_xen_dom0() or self.is_xen_domU()):
+            if self._grep("/proc/cpuinfo", "QEMU"):
+                qemu = not self.cpuid != "KVMKVMKVM"
+        return qemu
+
+
+
+    # /proc/vz - always exists if OpenVZ kernel is running (inside and outside
+    # container)
+    # /proc/bc - exists on node, but not inside container.
+    def on_openvz(self):
+        return (os.path.exists("/proc/vz")) and not (os.path.exists("/proc/bc"))
+
+    def hypervisor_types(self):
+        types = []
+        is_xen = False;
+        if self.on_vmware(): types.append(vmware)
+        if self.on_virtualpc(): types.append(virtualpc)
+        if self.on_virtualbox(): types.append(virtualbox)
+        if self.on_openvz(): types.append(openvz)
+        if self.on_uml(): types.append(uml)
+        if self.on_xen_hvm(): 
+            types.append(xenhvm)
+            is_xen = True
+        if self.is_xen_dom0(): 
+            types.append(xendom0)
+            is_xen = True
+        if self.is_xen_domU(): 
+            types.append(xendomU)
+            is_xen = True            
+        if self.on_kvm(): types.append(kvm)
+        if self.on_qemu(): types.append(qemu)
+        
+        if is_xen:
+            types.append(xen)
+            
+        return types
+
+    def _is_manufacturer(self, mf):
+        found = False
+        for key, value in self.dmi["processor"].items():
+            if mf == value["data"]["Manufacturer"]["Vendor"]:
+                found = True
+                break
+        if not found:
+            for key, value in self.dmi["bios"].items():
+                if "Vendor" in value["data"]:
+                    if mf == value["data"]["Vendor"]:
+                        found = True
+                        break
+        if not found:
+            for key, value in self.dmi["system"].items():
+                if "Manufacturer" in value["data"]:
+                    if mf == value["data"]["Manufacturer"]:
+                        found = True
+                        break
+        if not found:
+            for key, value in self.dmi["chassis"].items():
+                if "Manufacturer" in value["data"]:
+                    if mf == value["data"]["Manufacturer"]:
+                        found = True
+                        break
+        return found
+
+
+    def _grep(self, fname, data):
+        found = False
+        if (os.path.exists(fname)):
+            for line in open(fname):
+                if data in line:
+                    found = True
+                    break
+        return found
+
+if __name__ == '__main__':
+    g = VirtDetect()
+    print "On VMWare:     %i" % g.on_vmware()
+    print "On VirtualPC:  %i" % g.on_vmware()
+    print "On Virtualbox: %i" % g.on_virtualbox()
+    print "On Openvz:     %i" % g.on_openvz()
+    print "On UML:        %i" % g.on_uml()
+    print "On XenHVM:     %i" % g.on_xen_hvm()
+    print "Is XenDom0:    %i" % g.is_xen_dom0()
+    print "Is XenDomU:    %i" % g.is_xen_domU()
+    print "On Qemu:       %i" % g.on_qemu()
+    print "On KVM:        %i" % g.on_kvm()
-- 
1.7.3.2


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]