Repository: ansible/ansible

Issue:
Solaris prtdiag hangs during gather facts
This seems to be a known issue with solaris 10. way to fix is to restart picl before running prtdiag. 

Could add something like the below to setup: 
    def get_virtual_facts(self):
        module.run_command("svcadm restart svc:/system/picl:default")
        rc, out, err = module.run_command("/usr/sbin/prtdiag")

python debug output:

-bash-3.00# python -m pdb setup

> /tmp/.ansible/tmp/ansible-1382106487.8-10732644317884/setup(21)<module>()
> -> import os
> (Pdb) continue

^C{"msg": "Traceback (most recent call last):\n  File \"setup\", line 3089, in run_command\n    out, err = cmd.communicate(input=data)\n  File \"/opt/csw/lib/python2.6/subprocess.py\", line 691, in communicate\n    return self._communicate(inpu
t)\n  File \"/opt/csw/lib/python2.6/subprocess.py\", line 1211, in _communicate\n    rlist, wlist, xlist = select.select(read_set, write_set, [])\nKeyboardInterrupt\n", "failed": true, "cmd": "/usr/sbin/prtdiag", "rc": 257}
The program exited via sys.exit(). Exit status:  1



Discussion:
Sorry, closed the wrong bug

I've seen prtdiag hang, though when using puppet's facter, and indeed restarting picl temporarily fixes the issue. I'm not sure I'm comfortable with the idea of restarting it on every box every time setup is run when it's usually only an issue on a few boxes. If you're going to try to work around the issue in code maybe there's a way to catch the exception on the boxes that do fail on prtdiag and restart picl only then.

It does not throw an exception it just hangs, I waited for 30 minutes today
before I killed it.  Could just time the prtdiag and if it takes longer
than 5 seconds throw an warning to manually restart picl on that box. That
is, if automatically restarting it is not wanted in the setup module.

John

On Fri, Oct 18, 2013 at 3:11 PM, Romeo Theriault
notifications@github.comwrote:

> I've seen prtdiag hang, though when using puppet's facter, and indeed
> restarting picl temporarily fixes the issue. I'm not sure I'm comfortable
> with the idea of restarting it on every box every time setup is run when
> it's usually only an issue on a few boxes. If you're going to try to work
> around the issue in code maybe there's a way to catch the exception on the
> boxes that do fail on prtdiag and restart picl only then.
> 
> —
> Reply to this email directly or view it on GitHubhttps://github.com/ansible/ansible/issues/4583#issuecomment-26621932
> .

## 

-John

Sounds like the solution might be to not call it in the facts if it is unreliable, though you could also execute it in a subprocess (painful) and kill it if a timeout is exceeded.

I think I'd rather remove it, if that seems reasonable?

I would like to see the warning to restart picl rather than removal of the prtdiag info

Hi,

all prtdiag is giving is the 'BIOS Configuration:'. Is this truly needed?

rc, out, err = module.run_command("/usr/sbin/prtdiag")
        for line in out.split('\n'):
            if 'VMware' in line:
                self.facts['virtualization_type'] = 'vmware'
                self.facts['virtualization_role'] = 'guest'
            if 'Parallels' in line:
                self.facts['virtualization_type'] = 'parallels'
                self.facts['virtualization_role'] = 'guest'
            if 'VirtualBox' in line:
                self.facts['virtualization_type'] = 'virtualbox'
                self.facts['virtualization_role'] = 'guest'
            if 'HVM domU' in line:
                self.facts['virtualization_type'] = 'xen'
                self.facts['virtualization_role'] = 'guest'

There maybe other ways to get this information. prtconf may work but it may
also rely on the picl service.

On Sat, Oct 19, 2013 at 1:34 PM, brettheath notifications@github.comwrote:

> I would like to see the warning to restart picl rather than removal of the
> prtdiag info
> 
> —
> Reply to this email directly or view it on GitHubhttps://github.com/ansible/ansible/issues/4583#issuecomment-26654781
> .

## 

-John

I was looking at it from the SPARC perspective, and prtdiag has a lot of useful info, but I'll bet you could glean just about all of it from other commands.

from the setup module the only thing prtdiag is use for is virtualization_type/role. Any idea what other commands or files may contain that info? I been seaching with no luck.

Is it possible that prtdiag behaves differently when there is a pseudo-tty, rather than no tty ?

A lot of Ansible 'hangs' are related to the fact that commands run with a pseudo-tty, and so it may issue a prompt to the user, rather than be silent.

@dagwieers , I don't believe it behaves differently in this case. When I've seen prtdiag hang with 'facter' in the past it would also hang when I ran it manually in a terminal.

Can anyone confirm if this is still an issue?


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
@@ -3249,24 +3249,13 @@ def populate(self):
         return self.facts
 
     def get_virtual_facts(self):
-        rc, out, err = self.module.run_command("/usr/sbin/prtdiag")
-        for line in out.split('\n'):
-            if 'VMware' in line:
-                self.facts['virtualization_type'] = 'vmware'
-                self.facts['virtualization_role'] = 'guest'
-            if 'Parallels' in line:
-                self.facts['virtualization_type'] = 'parallels'
-                self.facts['virtualization_role'] = 'guest'
-            if 'VirtualBox' in line:
-                self.facts['virtualization_type'] = 'virtualbox'
-                self.facts['virtualization_role'] = 'guest'
-            if 'HVM domU' in line:
-                self.facts['virtualization_type'] = 'xen'
-                self.facts['virtualization_role'] = 'guest'
+
         # Check if it's a zone
-        if os.path.exists("/usr/bin/zonename"):
-            rc, out, err = self.module.run_command("/usr/bin/zonename")
-            if out.rstrip() != "global":
+
+        zonename = self.module.get_bin_path('zonename')
+        if zonename:
+            rc, out, err = self.module.run_command(zonename)
+            if rc == 0 and out.rstrip() != "global":
                 self.facts['container'] = 'zone'
         # Check if it's a branded zone (i.e. Solaris 8/9 zone)
         if os.path.isdir('/.SUNWnative'):
@@ -3274,16 +3263,25 @@ def get_virtual_facts(self):
         # If it's a zone check if we can detect if our global zone is itself virtualized.
         # Relies on the "guest tools" (e.g. vmware tools) to be installed
         if 'container' in self.facts and self.facts['container'] == 'zone':
-            rc, out, err = self.module.run_command("/usr/sbin/modinfo")
-            for line in out.split('\n'):
-                if 'VMware' in line:
-                    self.facts['virtualization_type'] = 'vmware'
-                    self.facts['virtualization_role'] = 'guest'
-                if 'VirtualBox' in line:
-                    self.facts['virtualization_type'] = 'virtualbox'
-                    self.facts['virtualization_role'] = 'guest'
+            modinfo = self.module.get_bin_path('modinfo')
+            if modinfo:
+                rc, out, err = self.module.run_command(modinfo)
+                if rc == 0:
+                    for line in out.split('\n'):
+                        if 'VMware' in line:
+                            self.facts['virtualization_type'] = 'vmware'
+                            self.facts['virtualization_role'] = 'guest'
+                        if 'VirtualBox' in line:
+                            self.facts['virtualization_type'] = 'virtualbox'
+                            self.facts['virtualization_role'] = 'guest'
+
+        if os.path.exists('/proc/vz'):
+            self.facts['virtualization_type'] = 'virtuozzo'
+            self.facts['virtualization_role'] = 'guest'
+
         # Detect domaining on Sparc hardware
-        if os.path.exists("/usr/sbin/virtinfo"):
+        virtinfo = self.module.get_bin_path('virtinfo')
+        if virtinfo:
             # The output of virtinfo is different whether we are on a machine with logical
             # domains ('LDoms') on a T-series or domains ('Domains') on a M-series. Try LDoms first.
             rc, out, err = self.module.run_command("/usr/sbin/virtinfo -p")
@@ -3291,21 +3289,40 @@ def get_virtual_facts(self):
             #   DOMAINROLE|impl=LDoms|control=false|io=false|service=false|root=false
             # The output may also be not formatted and the returncode is set to 0 regardless of the error condition:
             #   virtinfo can only be run from the global zone
-            try:
+            if rc == 0:
+                try:
+                    for line in out.split('\n'):
+                        fields = line.split('|')
+                        if( fields[0] == 'DOMAINROLE' and fields[1] == 'impl=LDoms' ):
+                            self.facts['virtualization_type'] = 'ldom'
+                            self.facts['virtualization_role'] = 'guest'
+                            hostfeatures = []
+                            for field in fields[2:]:
+                                arg = field.split('=')
+                                if( arg[1] == 'true' ):
+                                    hostfeatures.append(arg[0])
+                            if( len(hostfeatures) > 0 ):
+                                self.facts['virtualization_role'] = 'host (' + ','.join(hostfeatures) + ')'
+                except ValueError:
+                    pass
+
+        else:
+            smbios = self.module.get_bin_path('smbios')
+            rc, out, err = self.module.run_command(smbios)
+            if rc == 0:
                 for line in out.split('\n'):
-                    fields = line.split('|')
-                    if( fields[0] == 'DOMAINROLE' and fields[1] == 'impl=LDoms' ):
-                        self.facts['virtualization_type'] = 'ldom'
+                    if 'VMware' in line:
+                        self.facts['virtualization_type'] = 'vmware'
+                        self.facts['virtualization_role'] = 'guest'
+                    elif 'Parallels' in line:
+                        self.facts['virtualization_type'] = 'parallels'
+                        self.facts['virtualization_role'] = 'guest'
+                    elif 'VirtualBox' in line:
+                        self.facts['virtualization_type'] = 'virtualbox'
+                        self.facts['virtualization_role'] = 'guest'
+                    elif 'HVM domU' in line:
+                        self.facts['virtualization_type'] = 'xen'
                         self.facts['virtualization_role'] = 'guest'
-                        hostfeatures = []
-                        for field in fields[2:]:
-                            arg = field.split('=')
-                            if( arg[1] == 'true' ):
-                                hostfeatures.append(arg[0])
-                        if( len(hostfeatures) > 0 ):
-                            self.facts['virtualization_role'] = 'host (' + ','.join(hostfeatures) + ')'
-            except ValueError:
-                pass
 
 class Ohai(Facts):
     """


Test patch: