97 lines
3.2 KiB
Python
97 lines
3.2 KiB
Python
|
import os
|
||
|
import platform
|
||
|
|
||
|
|
||
|
def get_platform():
|
||
|
'''
|
||
|
:rtype: NativeString
|
||
|
:returns: Name of the platform the module is running on
|
||
|
'''
|
||
|
return platform.system()
|
||
|
|
||
|
|
||
|
def get_distribution():
|
||
|
'''
|
||
|
:rtype: NativeString or None
|
||
|
:returns: Name of the distribution the module is running on
|
||
|
'''
|
||
|
distribution = None
|
||
|
additional_linux = ('alpine', 'arch', 'devuan')
|
||
|
supported_dists = platform._supported_dists + additional_linux
|
||
|
|
||
|
if platform.system() == 'Linux':
|
||
|
try:
|
||
|
distribution = platform.linux_distribution(supported_dists=supported_dists)[0].capitalize()
|
||
|
if not distribution and os.path.isfile('/etc/system-release'):
|
||
|
distribution = platform.linux_distribution(supported_dists=['system'])[0].capitalize()
|
||
|
if 'Amazon' in distribution:
|
||
|
distribution = 'Amazon'
|
||
|
else:
|
||
|
distribution = 'OtherLinux'
|
||
|
except:
|
||
|
# FIXME: MethodMissing, I assume?
|
||
|
distribution = platform.dist()[0].capitalize()
|
||
|
return distribution
|
||
|
|
||
|
|
||
|
def get_distribution_version():
|
||
|
'''
|
||
|
:rtype: NativeString or None
|
||
|
:returns: A string representation of the version of the distribution
|
||
|
'''
|
||
|
distribution_version = None
|
||
|
if platform.system() == 'Linux':
|
||
|
try:
|
||
|
distribution_version = platform.linux_distribution()[1]
|
||
|
if not distribution_version and os.path.isfile('/etc/system-release'):
|
||
|
distribution_version = platform.linux_distribution(supported_dists=['system'])[1]
|
||
|
except Exception:
|
||
|
# FIXME: MethodMissing, I assume?
|
||
|
distribution_version = platform.dist()[1]
|
||
|
return distribution_version
|
||
|
|
||
|
|
||
|
def get_all_subclasses(cls):
|
||
|
'''
|
||
|
used by modules like Hardware or Network fact classes to recursively retrieve all
|
||
|
subclasses of a given class not only the direct sub classes.
|
||
|
'''
|
||
|
# Retrieve direct subclasses
|
||
|
subclasses = cls.__subclasses__()
|
||
|
to_visit = list(subclasses)
|
||
|
# Then visit all subclasses
|
||
|
while to_visit:
|
||
|
for sc in to_visit:
|
||
|
# The current class is now visited, so remove it from list
|
||
|
to_visit.remove(sc)
|
||
|
# Appending all subclasses to visit and keep a reference of available class
|
||
|
for ssc in sc.__subclasses__():
|
||
|
subclasses.append(ssc)
|
||
|
to_visit.append(ssc)
|
||
|
return subclasses
|
||
|
|
||
|
|
||
|
def load_platform_subclass(cls, *args, **kwargs):
|
||
|
'''
|
||
|
used by modules like User to have different implementations based on detected platform. See User
|
||
|
module for an example.
|
||
|
'''
|
||
|
|
||
|
this_platform = get_platform()
|
||
|
distribution = get_distribution()
|
||
|
subclass = None
|
||
|
|
||
|
# get the most specific superclass for this platform
|
||
|
if distribution is not None:
|
||
|
for sc in get_all_subclasses(cls):
|
||
|
if sc.distribution is not None and sc.distribution == distribution and sc.platform == this_platform:
|
||
|
subclass = sc
|
||
|
if subclass is None:
|
||
|
for sc in get_all_subclasses(cls):
|
||
|
if sc.platform == this_platform and sc.distribution is None:
|
||
|
subclass = sc
|
||
|
if subclass is None:
|
||
|
subclass = cls
|
||
|
|
||
|
return super(cls, subclass).__new__(subclass)
|