Repository: ansible/ansible

Issue:
RHEV virtualization is not detected
<!---
Please do not report issues/requests related to Ansible modules here !!

Report them to the appropriate modules-core or modules-extras project:
  - https://github.com/ansible/ansible-modules-core/issues
  - https://github.com/ansible/ansible-modules-extras/issues

Also verify first that your issue/request is not already reported in GitHub
-->
##### ISSUE TYPE

<!--- Pick one below and delete the rest: -->
- Bug Report
##### COMPONENT NAME

<!--- Name of the plugin/task/feature -->

setup module_util
##### SUMMARY

<!--- Explain the problem briefly -->

The default facts do not cover RHEV virtualization, and while RHEV is using KVM underneath it would be useful for users to make a clear distinction between a RHEV host and a normal KVM host.

I don't know if there is a way to determine if a VM is a RHEV guest, but it probably doesn't matter that much as it does for hosts.



Discussion:
@dagwieers  I see it's there:

https://github.com/ansible/ansible/blob/devel/lib/ansible/module_utils/facts.py#L2923

Also it works for me:

```
[root@10-34-60-84 ~]# cat /sys/devices/virtual/dmi/id/product_name 
RHEV Hypervisor
```

So what's the problem you have?

The problem is that it exists at the FIRST virtualization it finds so i doubt that part of the code ever gets hit as 'kvm' will be positive first.

@machacekondra For a guest, that's fine. But a RHEV host is reported to be a kvm host. Which is not wrong, but doesn't allow us to distinguish a RHEL server with kvm from a RHEV host.

I do not know yet what information (on the RHEV host) would be best to make the distinction in our facts, but we definitely need to make that distinction when managing servers.

Alright, after looking into this, I think the easiest/best way is to detect if a process named **vdsm** is running. The **vdsm** process is absolutely required on any RHEV host in order to manage and monitor the host's storage, memory and networks as well as VM creation.

The installation of the **vdsm** package may not mean it is a RHEV host (since it could be something left over), existence of files on the filesystem poses the same problem.

Another option is to check for the **qemu-kvm-rhev** or **qemu-img-rhev** package, but similarly, the installation of a package does not necessarily indicate that the software is running/active. However I noticed that the vdsm package does create a _/rhev/_ directory

We could test a combination of both, to guarantee that we are not testing for something else that happens to be called vdsm. So I would go for:
- If we have determined that the system is a kvm host
- Test if a vdsm process is running
- Test if /rhev/ exists (part of the vdsm package)
- Conclude we have a rhev host and report it accordingly

So I will propose this as an improvement to our setup logic.

Here's a working implementation:

``` python
if 'kvm' in modules:
    vdsm_found = False

    if HAS_PSUTIL:
        for proc in psutil.process_iter():
            if proc.name() == 'vdsm':
                vdsm_found = True
                break

    # Check whether this KVM host is a RHEV hypervisor
    if vdsm_found and os.path.isdir('/rhev/'):
        self.facts['virtualization_type'] = 'rhev'
    else:
        self.facts['virtualization_type'] = 'kvm'
    self.facts['virtualization_role'] = 'host'
    return
```

The problem is that we require the psutil module in order to find vdsm, and maybe that's asking to much. (We'd be defaulting to a false negative) I could go iterating in _/proc_ myself instead ? :-/

I rewrote it like this now:

``` python
if 'kvm' in modules:

    # Build list of process-names
    proc_list = []
    for f in glob.glob('/proc/[0-9]*/comm'):
        try:
            proc_list.append(open(f).read().rstrip())
        except:
            pass

    # Check whether this KVM host is a RHEV hypervisor
    if 'vdsm' in proc_list and os.path.isdir('/rhev/'):
        self.facts['virtualization_type'] = 'rhev'
    else:
        self.facts['virtualization_type'] = 'kvm'
    self.facts['virtualization_role'] = 'host'
    return
```

Which should be fine.


Resolving patch:
diff --git a/lib/ansible/module_utils/facts.py b/lib/ansible/module_utils/facts.py
--- a/lib/ansible/module_utils/facts.py
+++ b/lib/ansible/module_utils/facts.py
@@ -3119,7 +3119,22 @@ def get_virtual_facts(self):
                 modules.append(data[0])
 
             if 'kvm' in modules:
-                self.facts['virtualization_type'] = 'kvm'
+
+                if os.path.isdir('/rhev/'):
+
+                    # Check whether this is a RHEV hypervisor (is vdsm running ?)
+                    for f in glob.glob('/proc/[0-9]*/comm'):
+                        try:
+                            if open(f).read().rstrip() == 'vdsm':
+                                self.facts['virtualization_type'] = 'RHEV'
+                                break
+                        except:
+                            pass
+                    else:
+                        self.facts['virtualization_type'] = 'kvm'
+
+                else:
+                    self.facts['virtualization_type'] = 'kvm'
                 self.facts['virtualization_role'] = 'host'
                 return
 


Test patch: