@ -87,7 +87,8 @@ class Facts(object):
_I386RE = re . compile ( r ' i([3456]86|86pc) ' )
# For the most part, we assume that platform.dist() will tell the truth.
# This is the fallback to handle unknowns or exceptions
OSDIST_LIST = ( ( ' /etc/redhat-release ' , ' RedHat ' ) ,
OSDIST_LIST = ( ( ' /etc/oracle-release ' , ' Oracle Linux ' ) ,
( ' /etc/redhat-release ' , ' RedHat ' ) ,
( ' /etc/vmware-release ' , ' VMwareESX ' ) ,
( ' /etc/openwrt_release ' , ' OpenWrt ' ) ,
( ' /etc/system-release ' , ' OtherLinux ' ) ,
@ -170,9 +171,14 @@ class Facts(object):
if self . facts [ ' system ' ] == ' Linux ' :
self . get_distribution_facts ( )
elif self . facts [ ' system ' ] == ' AIX ' :
try :
rc , out , err = module . run_command ( " /usr/sbin/bootinfo -p " )
data = out . split ( ' \n ' )
self . facts [ ' architecture ' ] = data [ 0 ]
except :
self . facts [ ' architecture ' ] = ' Not Available '
elif self . facts [ ' system ' ] == ' OpenBSD ' :
self . facts [ ' architecture ' ] = platform . uname ( ) [ 5 ]
def get_local_facts ( self ) :
@ -229,8 +235,8 @@ class Facts(object):
RedHat = ' RedHat ' , Fedora = ' RedHat ' , CentOS = ' RedHat ' , Scientific = ' RedHat ' ,
SLC = ' RedHat ' , Ascendos = ' RedHat ' , CloudLinux = ' RedHat ' , PSBM = ' RedHat ' ,
OracleLinux = ' RedHat ' , OVS = ' RedHat ' , OEL = ' RedHat ' , Amazon = ' RedHat ' ,
XenServer = ' RedHat ' , Ubuntu = ' Debian ' , Debian = ' Debian ' , SLES = ' Suse ' ,
SLED = ' Suse ' , OpenSu SE = ' Suse ' , SuSE = ' Suse ' , Gentoo = ' Gentoo ' , Funtoo = ' Gentoo ' ,
XenServer = ' RedHat ' , Ubuntu = ' Debian ' , Debian = ' Debian ' , Raspbian = ' Debian ' , SLES = ' Suse ' ,
SLED = ' Suse ' , openSU SE = ' Suse ' , SuSE = ' Suse ' , Gentoo = ' Gentoo ' , Funtoo = ' Gentoo ' ,
Archlinux = ' Archlinux ' , Mandriva = ' Mandrake ' , Mandrake = ' Mandrake ' ,
Solaris = ' Solaris ' , Nexenta = ' Solaris ' , OmniOS = ' Solaris ' , OpenIndiana = ' Solaris ' ,
SmartOS = ' Solaris ' , AIX = ' AIX ' , Alpine = ' Alpine ' , MacOSX = ' Darwin ' ,
@ -261,6 +267,10 @@ class Facts(object):
self . facts [ ' distribution ' ] = ' FreeBSD '
self . facts [ ' distribution_release ' ] = platform . release ( )
self . facts [ ' distribution_version ' ] = platform . version ( )
elif self . facts [ ' system ' ] == ' NetBSD ' :
self . facts [ ' distribution ' ] = ' NetBSD '
self . facts [ ' distribution_release ' ] = platform . release ( )
self . facts [ ' distribution_version ' ] = platform . version ( )
elif self . facts [ ' system ' ] == ' OpenBSD ' :
self . facts [ ' distribution ' ] = ' OpenBSD '
self . facts [ ' distribution_release ' ] = platform . release ( )
@ -284,6 +294,13 @@ class Facts(object):
# Once we determine the value is one of these distros
# we trust the values are always correct
break
elif name == ' Oracle Linux ' :
data = get_file_content ( path )
if ' Oracle Linux ' in data :
self . facts [ ' distribution ' ] = name
else :
self . facts [ ' distribution ' ] = data . split ( ) [ 0 ]
break
elif name == ' RedHat ' :
data = get_file_content ( path )
if ' Red Hat ' in data :
@ -354,13 +371,27 @@ class Facts(object):
data = get_file_content ( path )
if ' suse ' in data . lower ( ) :
if path == ' /etc/os-release ' :
release = re . search ( " PRETTY_NAME=[^(]+ \ (?([^)]+?) \ ) " , data )
distdata = get_file_content ( path ) . split ( ' \n ' ) [ 0 ]
self . facts [ ' distribution ' ] = distdata . split ( ' = ' ) [ 1 ]
for line in data . splitlines ( ) :
distribution = re . search ( " ^NAME=(.*) " , line )
if distribution :
self . facts [ ' distribution ' ] = distribution . group ( 1 ) . strip ( ' " ' )
distribution_version = re . search ( ' ^VERSION_ID= " ?([0-9]+ \ .?[0-9]*) " ? ' , line ) # example pattern are 13.04 13.0 13
if distribution_version :
self . facts [ ' distribution_version ' ] = distribution_version . group ( 1 )
if ' open ' in data . lower ( ) :
release = re . search ( " ^PRETTY_NAME=[^(]+ \ (?([^)]+?) \ ) " , line )
if release :
self . facts [ ' distribution_release ' ] = release . groups ( ) [ 0 ]
elif ' enterprise ' in data . lower ( ) :
release = re . search ( ' ^VERSION_ID= " ?[0-9]+ \ .?([0-9]*) " ? ' , line ) # SLES doesn't got funny release names
if release :
release = release . group ( 1 )
else :
release = " 0 " # no minor number, so it is the first release
self . facts [ ' distribution_release ' ] = release
break
elif path == ' /etc/SuSE-release ' :
if ' open ' in data . lower ( ) :
data = data . splitlines ( )
distdata = get_file_content ( path ) . split ( ' \n ' ) [ 0 ]
self . facts [ ' distribution ' ] = distdata . split ( ) [ 0 ]
@ -368,10 +399,21 @@ class Facts(object):
release = re . search ( ' CODENAME *= *([^ \n ]+) ' , line )
if release :
self . facts [ ' distribution_release ' ] = release . groups ( ) [ 0 ] . strip ( )
break
elif ' enterprise ' in data . lower ( ) :
lines = data . splitlines ( )
distribution = lines [ 0 ] . split ( ) [ 0 ]
if " Server " in data :
self . facts [ ' distribution ' ] = " SLES "
elif " Desktop " in data :
self . facts [ ' distribution ' ] = " SLED "
for line in lines :
release = re . search ( ' PATCHLEVEL = ([0-9]+) ' , line ) # SLES doesn't got funny release names
if release :
self . facts [ ' distribution_release ' ] = release . group ( 1 )
self . facts [ ' distribution_version ' ] = self . facts [ ' distribution_version ' ] + ' . ' + release . group ( 1 )
elif name == ' Debian ' :
data = get_file_content ( path )
if ' Debian ' in data :
if ' Debian ' in data or ' Raspbian ' in data :
release = re . search ( " PRETTY_NAME=[^(]+ \ (?([^)]+?) \ ) " , data )
if release :
self . facts [ ' distribution_release ' ] = release . groups ( ) [ 0 ]
@ -403,7 +445,10 @@ class Facts(object):
self . facts [ ' distribution_release ' ] = release . group ( 1 ) . strip ( ' " ' )
else :
self . facts [ ' distribution ' ] = name
machine_id = get_file_content ( " /var/lib/dbus/machine-id " ) or get_file_content ( " /etc/machine-id " )
if machine_id :
machine_id = machine_id . split ( ' \n ' ) [ 0 ]
self . facts [ " machine_id " ] = machine_id
self . facts [ ' os_family ' ] = self . facts [ ' distribution ' ]
if self . facts [ ' distribution ' ] in OS_FAMILY :
self . facts [ ' os_family ' ] = OS_FAMILY [ self . facts [ ' distribution ' ] ]
@ -462,7 +507,7 @@ class Facts(object):
if rc == 0 :
self . facts [ ' lsb ' ] = { }
for line in out . split ( ' \n ' ) :
if len ( line ) < 1 :
if len ( line ) < 1 or ' : ' not in line :
continue
value = line . split ( ' : ' , 1 ) [ 1 ] . strip ( )
if ' LSB Version: ' in line :
@ -635,6 +680,7 @@ class LinuxHardware(Hardware):
self . get_memory_facts ( )
self . get_dmi_facts ( )
self . get_device_facts ( )
self . get_uptime_facts ( )
try :
self . get_mount_facts ( )
except TimeoutError :
@ -855,13 +901,14 @@ class LinuxHardware(Hardware):
size_available = statvfs_result . f_bsize * ( statvfs_result . f_bavail )
except OSError , e :
continue
uuid = ' NA '
lsblkPath = module . get_bin_path ( " lsblk " )
if lsblkPath :
rc , out , err = module . run_command ( " %s -ln --output UUID %s " % ( lsblkPath , fields [ 0 ] ) , use_unsafe_shell = True )
if rc == 0 :
uuid = out . strip ( )
else :
uuid = ' NA '
self . facts [ ' mounts ' ] . append (
{ ' mount ' : fields [ 1 ] ,
@ -973,6 +1020,9 @@ class LinuxHardware(Hardware):
self . facts [ ' devices ' ] [ diskname ] = d
def get_uptime_facts ( self ) :
uptime_seconds_string = get_file_content ( ' /proc/uptime ' ) . split ( ' ' ) [ 0 ]
self . facts [ ' uptime_seconds ' ] = int ( float ( uptime_seconds_string ) )
class SunOSHardware ( Hardware ) :
"""
@ -987,6 +1037,10 @@ class SunOSHardware(Hardware):
def populate ( self ) :
self . get_cpu_facts ( )
self . get_memory_facts ( )
try :
self . get_mount_facts ( )
except TimeoutError :
pass
return self . facts
def get_cpu_facts ( self ) :
@ -1047,6 +1101,17 @@ class SunOSHardware(Hardware):
self . facts [ ' swap_allocated_mb ' ] = allocated / 1024
self . facts [ ' swap_reserved_mb ' ] = reserved / 1024
@timeout ( 10 )
def get_mount_facts ( self ) :
self . facts [ ' mounts ' ] = [ ]
# For a detailed format description see mnttab(4)
# special mount_point fstype options time
fstab = get_file_content ( ' /etc/mnttab ' )
if fstab :
for line in fstab . split ( ' \n ' ) :
fields = line . rstrip ( ' \n ' ) . split ( ' \t ' )
self . facts [ ' mounts ' ] . append ( { ' mount ' : fields [ 1 ] , ' device ' : fields [ 0 ] , ' fstype ' : fields [ 2 ] , ' options ' : fields [ 3 ] , ' time ' : fields [ 4 ] } )
class OpenBSDHardware ( Hardware ) :
"""
OpenBSD - specific subclass of Hardware . Defines memory , CPU and device facts :
@ -1071,6 +1136,7 @@ class OpenBSDHardware(Hardware):
self . get_memory_facts ( )
self . get_processor_facts ( )
self . get_device_facts ( )
self . get_mount_facts ( )
return self . facts
def get_sysctl ( self ) :
@ -1083,6 +1149,19 @@ class OpenBSDHardware(Hardware):
sysctl [ key ] = value . strip ( )
return sysctl
@timeout ( 10 )
def get_mount_facts ( self ) :
self . facts [ ' mounts ' ] = [ ]
fstab = get_file_content ( ' /etc/fstab ' )
if fstab :
for line in fstab . split ( ' \n ' ) :
if line . startswith ( ' # ' ) or line . strip ( ) == ' ' :
continue
fields = re . sub ( r ' \ s+ ' , ' ' , line . rstrip ( ' \n ' ) ) . split ( )
if fields [ 1 ] == ' none ' or fields [ 3 ] == ' xx ' :
continue
self . facts [ ' mounts ' ] . append ( { ' mount ' : fields [ 1 ] , ' device ' : fields [ 0 ] , ' fstype ' : fields [ 2 ] , ' options ' : fields [ 3 ] } )
def get_memory_facts ( self ) :
# Get free memory. vmstat output looks like:
# procs memory page disks traps cpu
@ -2133,7 +2212,40 @@ class AIXNetwork(GenericBsdIfconfigNetwork, Network):
self . parse_inet6_line ( words , current_if , ips )
else :
self . parse_unknown_line ( words , current_if , ips )
uname_path = module . get_bin_path ( ' uname ' )
if uname_path :
rc , out , err = module . run_command ( [ uname_path , ' -W ' ] )
# don't bother with wpars it does not work
# zero means not in wpar
if out . split ( ) [ 0 ] == ' 0 ' :
if current_if [ ' macaddress ' ] == ' unknown ' and re . match ( ' ^en ' , current_if [ ' device ' ] ) :
entstat_path = module . get_bin_path ( ' entstat ' )
if entstat_path :
rc , out , err = module . run_command ( [ entstat_path , current_if [ ' device ' ] ] )
if rc != 0 :
break
for line in out . split ( ' \n ' ) :
if not line :
pass
buff = re . match ( ' ^Hardware Address: (.*) ' , line )
if buff :
current_if [ ' macaddress ' ] = buff . group ( 1 )
buff = re . match ( ' ^Device Type: ' , line )
if buff and re . match ( ' .*Ethernet ' , line ) :
current_if [ ' type ' ] = ' ether '
# device must have mtu attribute in ODM
if ' mtu ' not in current_if :
lsattr_path = module . get_bin_path ( ' lsattr ' )
if lsattr_path :
rc , out , err = module . run_command ( [ lsattr_path , ' -El ' , current_if [ ' device ' ] ] )
if rc != 0 :
break
for line in out . split ( ' \n ' ) :
if line :
words = line . split ( )
if words [ 0 ] == ' mtu ' :
current_if [ ' mtu ' ] = words [ 1 ]
return interfaces , ips
# AIX 'ifconfig -a' does not inform about MTU, so remove current_if['mtu'] here
@ -2360,6 +2472,11 @@ class LinuxVirtual(Virtual):
self . facts [ ' virtualization_role ' ] = ' guest '
return
if sys_vendor == ' oVirt ' :
self . facts [ ' virtualization_type ' ] = ' kvm '
self . facts [ ' virtualization_role ' ] = ' guest '
return
if os . path . exists ( ' /proc/self/status ' ) :
for line in get_file_lines ( ' /proc/self/status ' ) :
if re . match ( ' ^VxID: \ d+ ' , line ) :
@ -2514,6 +2631,30 @@ class SunOSVirtual(Virtual):
if ' VirtualBox ' in line :
self . facts [ ' virtualization_type ' ] = ' virtualbox '
self . facts [ ' virtualization_role ' ] = ' guest '
# Detect domaining on Sparc hardware
if os . path . exists ( " /usr/sbin/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 = module . run_command ( " /usr/sbin/virtinfo -p " )
# The output contains multiple lines with different keys like this:
# DOMAINROLE|impl=LDoms|control=false|io=false|service=false|root=false
# The output may also be not formated and the returncode is set to 0 regardless of the error condition:
# virtinfo can only be run from the global zone
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 , e :
pass
def get_file_content ( path , default = None , strip = True ) :
data = default