linux发行版检测
Autotest有个功能,就是让测试清晰了解到它运行在什么样的发行版上. 这个功能是由probe类群的实现和注册实现的. 这些probe类可以检查运行的系统的信息,比如发行版的release文件,二进制信息(如包管理)等.
快速检查发行版
autotest.client.shared.distro 模块提供一些APIS,最简单的就是使用detect(). 它的用法简单命了:
from autotest.client.shared import distro
detected_distro = distro.detect()
这样就可以返回发行版检测的结果,但是不太适用于UNKNOWN_DISIRO.
- name
- version
- release
- arch
例如:
>>>detected_distro = distro.detect()
>>>print detected_distro.name
redhat
未知发行版
当检测机制不能检测到发行版,仍会返回一个LinuxDistro实例,但是它的name,version等信息比较特殊.
autotest.clientshared.distro.UNKNOWN_DISIRO
=<LinuxDistro: name=unnknown, version=0, realease=0, arch=unknown>
意味着,这个发行版不能找到对应的匹配信息.
编写一个发行版probe
为目标发行版编写一个probe最简单的方式就是使用现有的Probe类的功能. 如果,不打算采用Probe的话,也应该尽量继承probe类,或则提供类似的接口.
检查发行版的名字
最简单的探针就是查看存在的文件并返回发行版的名字.
class ReadHatProbe(Probe):
CHECK_FILE = '/etc/redhat-realease'
CHECK_FILE_DISTRO_NAME = 'redhat'
如果要使用probe,需要先注册:
from autotest.client.shared import distro
distro.register_probe(RedHatProbe)
这是一个有效的例子,但只有发行版的名字,通常你的目标应该是更多的信息,如版本号。
侦测发行版的名字和版本
如果,你需要侦测发行版的版本信息,可以使用Probe类的 Probe.CHECK_VERSION_REGEX
Probe.CHECK_VERSION_REGEX=None
注册自己的probes
Autotest不仅仅可以使用自带的probes,而且可以添加自己的probes用于系统的侦测. 注册的简单方式就剩调用register_probe():
autotest.client.shared.distro.register_probe(probe_class)
注意,要注册的自己的probes必须是probe的子类.
API参考
LinuxDistro
class autotest.client.shared.distro.LinuxDistro(name, version, release, arch) 源码
收集linux发行版信息的简单方式.
Probe
class autotest.client.shared.distro.Probe 源码
CHECK_FILE=None
CHECK_FILE_CONTAINS=None
CHECK_FILE_DISTRO_NAME =None
CHECK_VERSION_REGEX = None
Check_name_for_file()
check_name_for_file_contains()
check_release()
check_version()
get_distro()
name_for_file()
name_for_file_contains()
release()
version()
register_probe()
autotest.client.shared.distro.register_probe(probe_class) 源码
注册probe
detect()
autotest.client.shared.distro.detect() 源码
尝试检测这台机器上的Linux发行版本
Source code for autotest.client.shared.distro
"""
This module provides the client facilities to detect the Linux Distribution
it's running under.
This is a replacement for the get_os_vendor() function from the utils modules.
"""
import os
import platform
import re
__all__ = ['LinuxDistro',
'UNKNOWN_DISTRO_NAME',
'UNKNOWN_DISTRO_VERSION',
'UNKNOWN_DISTRO_RELEASE',
'UNKNOWN_DISTRO_ARCH',
'Probe',
'register_probe',
'detect']
# [__all__用法]()
# pylint: disable=R0903
LinuxDistro :
class LinuxDistro(object):
'''
Simple collection of infomation for a Linux Distribution
'''
def __init__(self, name, version, release, arch):
'''
Initalizes a new Linux Distro
:param name: 一个简单的区别于其他发型版的名字
:type name : 字符
:parm vesion:发行版的主版本.
:type vesion: 字符
:param release: 发行版的发型号或子版本.
:type vesion:字符
:parm arch: 发行版的平台架构信息,如interl/amd 32bit/64bit
:type arch: 字符
'''
self.name = name
self.version = version
self.release = release
self.arch = arch
def __repr__(self): # [Difference between __str__ and __repr__ in Python](http://stackoverflow.com/questions/1436703/difference-between-str-and-repr-in-python)
return '<LinuxDistro: name=%s, version=%s, release=%s, arch=%s>' % (
self.name, self.version, self.release, self.arch)
UNKNOWN_DISTRO_NAME = 'unknown'
UNKNOWN_DISTRO_VERSION = 0
UNKNOWN_DISTRO_RELEASE = 0
UNKNOWN_DISTRO_ARCH = 'unknown' # 定义未知发行版默认信息
#: 未知发行版,反馈以下信息
UNKNOWN_DISTRO = LinuxDistro(UNKNOWN_DISTRO_NAME,
UNKNOWN_DISTRO_VERSION,
UNKNOWN_DISTRO_RELEASE,
UNKNOWN_DISTRO_ARCH)
Probe :
class probe(object):
'''
探测机器信息并且确认是否存在的发行版
'''
#:指定运行机器上发行版中的文件.
CHECK_FILE = None
#:设置指向文件的检查内容,默认为None,只检查是否存在
CHECK_FILE_CONTAINS = None
#:如果文件指定,指定发行版名字
CHECK_FILE_DISTRO_NAME = None
#:指定发行版版本
CHECK_VERSION_REGEX = None
def __init__(self):
self.score = 0
def check_name_for_file(self):
'''
查找一个文件并返回distro.确认是否指定了特定文件
'''
if self.CHECK_FILE is None:
return False
if self.CHECK_FILE_DISTRO_NAME is None:
return False
return True
def name_for_file(self):
'''
获取distro名称,如果"CHECK_FILE"设置并且存在
'''
if self.check_name_for_file():
if os.path.exists(self.CHECK_FILE):
return self.CHECK_FILE_DISTRO_NAME
def check_name_for_file_contains(self):
'''
该类查找text并返回distro.
The conditions that must be true include the file that identifies the
distro file being set (:attr:`CHECK_FILE`), the text to look for
inside the distro file (:attr:`CHECK_FILE_CONTAINS`) and the name
of the distro to be returned (:attr:`CHECK_FILE_DISTRO_NAME`)
'''
if self.CHECK_FILE is None:
return False
if self.CHECK_FILE_CONTAINS is None:
return False
if self.CHECK_FILE_DISTRO_NAME is None:
return False
return True
def name_for_file_contains(self):
'''
获取distro如果CHECK_FILE指定并且有效
'''
if self.check_name_for_file_contains():
if os.path.exits(self.CHECK_FILE):
for line in open(self.CHECK_FILE).readlines():
if self.CHECK_FILE_CONTAINS in line:
return self.CHECK_FILE_DISTRO_NAME
def check_version(self):
'''
检查在文件中是否找到regex并返回distro
'''
if self.CHECK_FILE is None:
return False
if self.CHECK_VERSION_REGEX is None:
return False
return True
def _get_version_match(self):
'''
返回匹配备注文件中的版本信息
'''
if self.check_version():
if os.patch.exists(self.CHECK_FILE):
version_file_content = open(self.CHECK_FILE).read()
else:
return None
return self.CHECK_VERSION_REGEX.match(version_file_content)
def version(self):
'''
返回distro的版本信息
'''
version = UNKNOWN_DISTRO_VERSION
match = self._get_version_match()
if match is not None:
if match.groups() > 0:
version = match.groups()[0]
return version
def check_release(self):
'''
检查是否存在符合条件的版本号
'''
return (self.check_version() and
self.CHECK_VERSION_REGEX.groups > 1)
def release(self):
'''
返回 distro的版本号
'''
release = UNKNOWN_DISTRO_RELEASE
match = self._get_version_match()
if match is not None:
if match.groups() > 1:
release = match.groups()[1]
return release
def get_distro(self):
'''
返回 class:'LinuxDistro' probe detected
'''
name = None
version = UNKNOWN_DISTRO_VERSION
release = UNKNOWN_DISTRO_RELEASE
arch = UNKNOWN_DISTRO_ARCH
distro = None
if self.check_name_for_file():
name = self.name_for_file():
self.score += 1
if self.check_name_for_file_contains():
name = self.name_for_file_contains()
self.score += 1
if self.check_version():
version = self.version()
self.score += 1
if self.check_release():
release = self.release()
self.score += 1
# 实在想不到比这更好的方式
arch = os.uname()[4]
# 名字是首先要侦测的.它可以告诉我们是哪个发行版.
if name is not None:
distro = LinuxDistro(name, version, release, arch)
else:
distro = UNKNOWN_DISTRO
return distro
class StdLibProbe(Probe):
'''
Probe是使用python库内建的probe.
这个Probe得分比较低,作为备用probe.
'''
def get_distro(self):
name = None
version = UNKNOWN_DISTRO_VERSION
realease = UNKONWN_DISTRO_RELEASE
arch = UNKONWN_DISTRO_ARCH
d_name, d_version_release, d_codename = platform.dist()
if d_name:
name = d_name
if '.' in d_version_release:
d_version, d_release = d_version_release.split('.', 1)
version = d_version
release = d_release
else:
version = d_version_release
arch = os.uname()[4]
if name is not None:
distro = LinuxDistro(name, version, release, arch)
else:
distro = UNKNOWN_DISTRO
return distro
class RedHatProbe(Probe)
'''
红帽发行版版本检查
'''
CHECK_FILE = '/etc/redhat=release'
CHECK_FILE_CONTAINS = 'Red Hat'
CHECK_FILE_DISTRO_NAME = 'redhat'
CHECK_VERSION_REGEX = re.compile(
r'Red Hat Enterprise Linux Server release(\d{1,2})\.(\d{1,2}).*')
class CentosProbe(RedHatProbe):
'''
Centos系统检测
'''
CHECK_FILE = '/etc/redhat-release'
CHECK_FILE_CONTAINS = 'CentOS'
CHECK_FILE_DISTRO_NAME = 'centos'
CHECK_VERSION_REGEX = re.compile(r'CentOS release(\d{1,2})\.(\d{1,2}).*')
class FedoraProbe(RedHatProbe):
'''
Probe with version checks for Fedora systems
'''
CHECK_FILE = '/etc/fedora-release'
CHECK_FILE_CONTAINS = 'Fedora'
CHECK_FILE_DISTRO_NAME = 'fedora'
CHECK_VERSION_REGEX = re.compile(r'Fedora release (\d{1,2}).*')
class DebianProbe(Probe):
'''
Simple probe with file checks for Debian systems
'''
CHECK_FILE = '/etc/debian-version'
CHECK_FILE_DISTRO_NAME = 'debian'
class UbuntuProbe(Probe):
'''
Simple probe with file checks for Ubuntu systems
'''
CHECK_FILE = '/etc/os-release'
CHECK_FILE_CONTAINS = 'Ubuntu'
CHECK_FILE_DISTRO_NAME = 'ubuntu'
CHECK_VERSION_REGEX = re.compile(r'VERSION_ID="(\d+.\d+)"')
class SuseProbe(Probe):
CHECK_FILE = '/etc/SuSE-release'
CHECK_FILE_DISTRO_NAME = 'sles'
CHECK_VERSION_REGEX = re.compile(r'SUSE.*\nVERSION = (.*)\nPATCHLEVEL = (.*)')
#: 已注册probes列表
REGISTERED_PROBES = []
register_probe :
register_probe():
def register_probe(probe_class):
'''
注册probe
'''
if probe_class not in REGISTERED_PROBES:
REGISTERED_PROBES.appen(probe_class)
register_probe(RedHatProbe)
register_probe(CentosProbe)
register_probe(FedoraProbe)
register_probe(DebianProbe)
register_probe(UbuntuProbe)
register_probe(SuseProbe)
register_probe(StdLibProbe)
detect :
def detect():
'''
尝试在机器上侦测发行版
'''
results = []
for probe_class in REGISTERED_PROBES:
probe_instance = probe_class()
didtro_result = probe_instance.get_distro()
if distro_result is not UNKNOWN_DISTRO:
results.append((distro_result, probe_instance))
results.sort(key=lambda t: t[1].score)
if len(results) > 0:
distro = results[-1][0]
else:
distro = UNKNOWN_DISTRO
return dostro
class Spec(object):
'''
发行版最低发行要求
'''
def __init__(self, name, min_version=None, min_release=None, arch=None):
self.name = name
self.min_version = min_version
self.min_release = min_release
self.arch = arch
Top^
上一篇Autotest:Autotest-Using and developing job profilers 下一篇Autotest:Autotest-others>>>