1# This file is part of Ansible
2#
3# Ansible is free software: you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by
5# the Free Software Foundation, either version 3 of the License, or
6# (at your option) any later version.
7#
8# Ansible is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11# GNU General Public License for more details.
12#
13# You should have received a copy of the GNU General Public License
14# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
15
16from __future__ import (absolute_import, division, print_function)
17__metaclass__ = type
18
19import os
20
21from ansible.module_utils.facts.virtual.base import Virtual, VirtualCollector
22
23
24class SunOSVirtual(Virtual):
25    """
26    This is a SunOS-specific subclass of Virtual.  It defines
27    - virtualization_type
28    - virtualization_role
29    - container
30    """
31    platform = 'SunOS'
32
33    def get_virtual_facts(self):
34        virtual_facts = {}
35        host_tech = set()
36        guest_tech = set()
37
38        # Check if it's a zone
39        zonename = self.module.get_bin_path('zonename')
40        if zonename:
41            rc, out, err = self.module.run_command(zonename)
42            if rc == 0:
43                if out.rstrip() == "global":
44                    host_tech.add('zone')
45                else:
46                    guest_tech.add('zone')
47                    virtual_facts['container'] = 'zone'
48
49        # Check if it's a branded zone (i.e. Solaris 8/9 zone)
50        if os.path.isdir('/.SUNWnative'):
51            guest_tech.add('zone')
52            virtual_facts['container'] = 'zone'
53
54        # If it's a zone check if we can detect if our global zone is itself virtualized.
55        # Relies on the "guest tools" (e.g. vmware tools) to be installed
56        if 'container' in virtual_facts and virtual_facts['container'] == 'zone':
57            modinfo = self.module.get_bin_path('modinfo')
58            if modinfo:
59                rc, out, err = self.module.run_command(modinfo)
60                if rc == 0:
61                    for line in out.splitlines():
62                        if 'VMware' in line:
63                            guest_tech.add('vmware')
64                            virtual_facts['virtualization_type'] = 'vmware'
65                            virtual_facts['virtualization_role'] = 'guest'
66                        if 'VirtualBox' in line:
67                            guest_tech.add('virtualbox')
68                            virtual_facts['virtualization_type'] = 'virtualbox'
69                            virtual_facts['virtualization_role'] = 'guest'
70
71        if os.path.exists('/proc/vz'):
72            guest_tech.add('virtuozzo')
73            virtual_facts['virtualization_type'] = 'virtuozzo'
74            virtual_facts['virtualization_role'] = 'guest'
75
76        # Detect domaining on Sparc hardware
77        virtinfo = self.module.get_bin_path('virtinfo')
78        if virtinfo:
79            # The output of virtinfo is different whether we are on a machine with logical
80            # domains ('LDoms') on a T-series or domains ('Domains') on a M-series. Try LDoms first.
81            rc, out, err = self.module.run_command("/usr/sbin/virtinfo -p")
82            # The output contains multiple lines with different keys like this:
83            #   DOMAINROLE|impl=LDoms|control=false|io=false|service=false|root=false
84            # The output may also be not formatted and the returncode is set to 0 regardless of the error condition:
85            #   virtinfo can only be run from the global zone
86            if rc == 0:
87                try:
88                    for line in out.splitlines():
89                        fields = line.split('|')
90                        if fields[0] == 'DOMAINROLE' and fields[1] == 'impl=LDoms':
91                            guest_tech.add('ldom')
92                            virtual_facts['virtualization_type'] = 'ldom'
93                            virtual_facts['virtualization_role'] = 'guest'
94                            hostfeatures = []
95                            for field in fields[2:]:
96                                arg = field.split('=')
97                                if arg[1] == 'true':
98                                    hostfeatures.append(arg[0])
99                            if len(hostfeatures) > 0:
100                                virtual_facts['virtualization_role'] = 'host (' + ','.join(hostfeatures) + ')'
101                except ValueError:
102                    pass
103
104        else:
105            smbios = self.module.get_bin_path('smbios')
106            if not smbios:
107                return
108            rc, out, err = self.module.run_command(smbios)
109            if rc == 0:
110                for line in out.splitlines():
111                    if 'VMware' in line:
112                        guest_tech.add('vmware')
113                        virtual_facts['virtualization_type'] = 'vmware'
114                        virtual_facts['virtualization_role'] = 'guest'
115                    elif 'Parallels' in line:
116                        guest_tech.add('parallels')
117                        virtual_facts['virtualization_type'] = 'parallels'
118                        virtual_facts['virtualization_role'] = 'guest'
119                    elif 'VirtualBox' in line:
120                        guest_tech.add('virtualbox')
121                        virtual_facts['virtualization_type'] = 'virtualbox'
122                        virtual_facts['virtualization_role'] = 'guest'
123                    elif 'HVM domU' in line:
124                        guest_tech.add('xen')
125                        virtual_facts['virtualization_type'] = 'xen'
126                        virtual_facts['virtualization_role'] = 'guest'
127                    elif 'KVM' in line:
128                        guest_tech.add('kvm')
129                        virtual_facts['virtualization_type'] = 'kvm'
130                        virtual_facts['virtualization_role'] = 'guest'
131
132        virtual_facts['virtualization_tech_guest'] = guest_tech
133        virtual_facts['virtualization_tech_host'] = host_tech
134        return virtual_facts
135
136
137class SunOSVirtualCollector(VirtualCollector):
138    _fact_class = SunOSVirtual
139    _platform = 'SunOS'
140