View Javadoc
1   /*
2    * Copyright 2019-2023 The OSHI Project Contributors
3    * SPDX-License-Identifier: MIT
4    */
5   package oshi.demo;
6   
7   import java.util.HashMap;
8   import java.util.List;
9   import java.util.Locale;
10  import java.util.Map;
11  import java.util.Properties;
12  
13  import oshi.SystemInfo;
14  import oshi.annotation.SuppressForbidden;
15  import oshi.hardware.HardwareAbstractionLayer;
16  import oshi.hardware.NetworkIF;
17  import oshi.util.FileUtil;
18  
19  /**
20   * Uses OSHI to attempt to identify whether the user is on a Virtual Machine
21   */
22  public class DetectVM {
23  
24      private static final String OSHI_VM_MAC_ADDR_PROPERTIES = "oshi.vmmacaddr.properties";
25      private static final Properties vmMacAddressProps = FileUtil
26              .readPropertiesFromFilename(OSHI_VM_MAC_ADDR_PROPERTIES);
27  
28      // Constant for CPU vendor string
29      private static final Map<String, String> vmVendor = new HashMap<>();
30      static {
31          vmVendor.put("bhyve bhyve", "bhyve");
32          vmVendor.put("KVMKVMKVM", "KVM");
33          vmVendor.put("TCGTCGTCGTCG", "QEMU");
34          vmVendor.put("Microsoft Hv", "Microsoft Hyper-V or Windows Virtual PC");
35          vmVendor.put("lrpepyh vr", "Parallels");// (endianness mismatch of "prl hyperv ")
36          vmVendor.put("VMwareVMware", "VMware");
37          vmVendor.put("XenVMMXenVMM", "Xen HVM");
38          vmVendor.put("ACRNACRNACRN", "Project ACRN");
39          vmVendor.put("QNXQVMBSQG", "QNX Hypervisor");
40      }
41  
42      private static final String[] vmModelArray = new String[] { "Linux KVM", "Linux lguest", "OpenVZ", "Qemu",
43              "Microsoft Virtual PC", "VMWare", "linux-vserver", "Xen", "FreeBSD Jail", "VirtualBox", "Parallels",
44              "Linux Containers", "LXC" };
45  
46      /**
47       * The main method, executing the {@link #identifyVM} method.
48       *
49       * @param args Arguments, ignored.
50       */
51      @SuppressForbidden(reason = "Using System.out in a demo class")
52      public static void main(String[] args) {
53          String vmString = identifyVM();
54  
55          if (vmString.isEmpty()) {
56              System.out.println("You do not appear to be on a Virtual Machine.");
57          } else {
58              System.out.println("You appear to be on a VM: " + vmString);
59          }
60      }
61  
62      /**
63       * The function attempts to identify which Virtual Machine (VM) based on common VM signatures in MAC address and
64       * computer model.
65       *
66       * @return A string indicating the machine's virtualization info if it can be determined, or an emptry string
67       *         otherwise.
68       */
69      public static String identifyVM() {
70          SystemInfo si = new SystemInfo();
71          HardwareAbstractionLayer hw = si.getHardware();
72          // Check CPU Vendor
73          String vendor = hw.getProcessor().getProcessorIdentifier().getVendor().trim();
74          if (vmVendor.containsKey(vendor)) {
75              return vmVendor.get(vendor);
76          }
77  
78          // Try well known MAC addresses
79          List<NetworkIF> nifs = hw.getNetworkIFs();
80          for (NetworkIF nif : nifs) {
81              String mac = nif.getMacaddr().toUpperCase(Locale.ROOT);
82              String oui = mac.length() > 7 ? mac.substring(0, 8) : mac;
83              if (vmMacAddressProps.containsKey(oui)) {
84                  return vmMacAddressProps.getProperty(oui);
85              }
86          }
87  
88          // Try well known models
89          String model = hw.getComputerSystem().getModel();
90          for (String vm : vmModelArray) {
91              if (model.contains(vm)) {
92                  return vm;
93              }
94          }
95          String manufacturer = hw.getComputerSystem().getManufacturer();
96          if ("Microsoft Corporation".equals(manufacturer) && "Virtual Machine".equals(model)) {
97              return "Microsoft Hyper-V";
98          }
99  
100         // Couldn't find VM, return empty string
101         return "";
102     }
103 }