$OpenBSD: patch-lib_ansible_module_utils_facts_py,v 1.14 2017/01/17 19:23:41 jasper Exp $

- Enable VMM detection
  9547d6b422c8cc6c9a4f0fe6188ad2e4f218b475

- Simplify processor fact resolution
  c17dad0def2fa86733c07610189e94486e056203

- Swap distribution_version and distribution_release values
  4c0188a27bf9dff6c70134817048672a00c8eae7

- Implement DMI facts
  88970bcfb24864c5773c8d913c45db3e7355a74d

--- lib/ansible/module_utils/facts.py.orig	Mon Jan 16 17:48:29 2017
+++ lib/ansible/module_utils/facts.py	Tue Jan 17 20:22:04 2017
@@ -750,12 +750,13 @@ class Distribution(object):
             self.facts['distribution_version'] = '%s.%s' % (data.group(1), data.group(2))
 
     def get_distribution_OpenBSD(self):
+        self.facts['distribution_version'] = platform.release()
         rc, out, err = self.module.run_command("/sbin/sysctl -n kern.version")
         match = re.match('OpenBSD\s[0-9]+.[0-9]+-(\S+)\s.*', out)
         if match:
-            self.facts['distribution_version'] = match.groups()[0]
+            self.facts['distribution_release'] = match.groups()[0]
         else:
-            self.facts['distribution_version'] = 'release'
+            self.facts['distribution_release'] = 'release'
 
     def get_distribution_DragonFly(self):
         pass
@@ -1568,7 +1569,8 @@ class OpenBSDHardware(Hardware):
     - processor_cores
     - processor_count
     - processor_speed
-    - devices
+
+    In addition, it also defines number of DMI facts and device facts.
     """
     platform = 'OpenBSD'
 
@@ -1578,6 +1580,7 @@ class OpenBSDHardware(Hardware):
         self.get_processor_facts()
         self.get_device_facts()
         self.get_mount_facts()
+        self.get_dmi_facts()
         return self.facts
 
     def get_sysctl(self):
@@ -1647,6 +1650,25 @@ class OpenBSDHardware(Hardware):
         devices.extend(self.sysctl['hw.disknames'].split(','))
         self.facts['devices'] = devices
 
+    def get_dmi_facts(self):
+        # We don't use dmidecode(1) here because:
+        # - it would add dependency on an external package
+        # - dmidecode(1) can only be ran as root
+        # So instead we rely on sysctl(8) to provide us the information on a
+        # best-effort basis. As a bonus we also get facts on non-amd64/i386
+        # platforms this way.
+        sysctl_to_dmi = {
+            'hw.product':  'product_name',
+            'hw.version':  'product_version',
+            'hw.uuid':     'product_uuid',
+            'hw.serialno': 'product_serial',
+            'hw.vendor':   'system_vendor',
+        }
+
+        for mib in sysctl_to_dmi:
+            if mib in self.sysctl:
+                self.facts[sysctl_to_dmi[mib]] = self.sysctl[mib]
+
 class FreeBSDHardware(Hardware):
     """
     FreeBSD-specific subclass of Hardware.  Defines memory and CPU facts:
@@ -3192,6 +3214,7 @@ class OpenBSDVirtual(Virtual):
     - virtualization_role
     """
     platform = 'OpenBSD'
+    DMESG_BOOT = '/var/run/dmesg.boot'
 
     def populate(self):
         self.get_virtual_facts()
@@ -3232,6 +3255,18 @@ class OpenBSDVirtual(Virtual):
                         if out.rstrip() == 'QEMU':
                             self.facts['virtualization_type'] = 'kvm'
                             self.facts['virtualization_role'] = 'guest'
+                        if out.rstrip() == 'OpenBSD':
+                            self.facts['virtualization_type'] = 'vmm'
+                            self.facts['virtualization_role'] = 'guest'
+
+        # Check the dmesg if vmm(4) attached, indicating the host is
+        # capable of virtualization.
+        dmesg_boot = get_file_content(OpenBSDVirtual.DMESG_BOOT)
+        for line in dmesg_boot.splitlines():
+            match = re.match('^vmm0 at mainbus0: (SVM/RVI|VMX/EPT)$', line)
+            if match:
+                self.facts['virtualization_type'] = 'vmm'
+                self.facts['virtualization_role'] = 'host'
 
 class HPUXVirtual(Virtual):
     """
