CMDB可插拔式项目架构(一)
目录分布
----bin
----start.py
----conf
----setting.py (用户自定义部分)
----files
----board.text
----……………
----disk.text
(一些死数据,DEBUG模式下使用)
----lib (用于存放类库文件,常见内外部工具包)
----config
----global_settings.py (默认全局配置)
----settings.py (配置类对象)
----src (源码目录)
----plugins (插件目录,可插拔组件)
----init.py
----basic.py
----cpu.py
----disk.py
----memory.py
----nic.py
----test
—test1 (存放测试文件的目录)
from lib.config.settings import settings
from src.plugins import basic,cpu,disk,memory,nic
from src.plugins import PluginsManager #会自动执行__init__文件
if __name__ == '__main__':
pluginsManagerObj = PluginsManager()
result = pluginsManagerObj.excute()
print(result)
### 自定义的配置
MODE = 'ssh'
DEBUG = True
#可插拔式
PLUGINS_DICT = {
'basic':'src.plugins.basic.Basic',
# 'cpu':'src.plugins.cpu.Cpu',
# 'disk':'src.plugins.disk.Disk',
# 'memory':'src.plugins.memory.Memory',
# 'nic':'src.plugins.nic.Nic'
}
#SSH专用
SSH_USER = 'root'
SSH_PWD = '1'
SSH_PORT = 22
from conf import setting
from . import global_settings
class Settings():
def __init__(self):
### 集成默认配置文件中的配置
for key in dir(global_settings):
if key.isupper():
v = getattr(global_settings, key)
setattr(self, key, v) #把符合条件的key和value绑定到self上
### 集成自定义配置文件中的配置
for key in dir(setting):
if key.isupper():
v = getattr(setting, key)
setattr(self, key, v)
@staticmethod
def hostname(self):
if setting.MODE == 'SSH':
self.hostname = ['mypc'] #TODO:这里写从API服务器获取需要远程链接的用户列表
return self.hostname
settings = Settings()
__init__.py (采集配置文件中的插件)
from lib.config.settings import settings #实例化的settings配置类对象
import importlib
class PluginsManager(object):
def __init__(self,hostname=None):
self.response = {}
self.plugins_dict = settings.PLUGINS_DICT
self.mode =settings.MODE
self.debug = settings.DEBUG
if self.mode == 'ssh':
self.hostname = settings.hostname
self.port = settings.SSH_PORT
self.username = settings.SSH_USER
self.password = settings.SSH_PWD
### 管理配置文件中采集的插件
def excute(self):
#获得setting配置中用户自定义的PLUGINS_DICT,查看有哪些PLUGIN需要遍历。
for k,v in self.plugins_dict.items():
# print(k,v)
module_name,class_name = v.rsplit('.',1) #以最右边的"."作分割符,做次数为1的分割。
### 将一个包以字符串形式导入
module_path = importlib.import_module(module_name)
cls = getattr(module_path,class_name) #获得 src.plugins.basic下的 Basic类对象
collect = cls().process(self._cmd_run,self.debug) #实例化后运行process 进行采集
self.response[k] = collect
return self.response
def _cmd_run(self,cmd):
if self.mode == 'agent':
import subprocess
res = subprocess.getoutput(cmd)
ipinfo = res[10:20] # 省略切割代码
return ipinfo
elif self.mode == 'ssh':
import paramiko
# 创建SSH对象
ssh = paramiko.SSHClient()
# 允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接服务器
ssh.connect(hostname=self.hostname, port=self.port, username=self.username, password=self.username)
# 执行命令
stdin, stdout, stderr = ssh.exec_command(cmd)
# 获取命令结果
result = stdout.read()
# 关闭连接
ssh.close()
return result
elif self.mode == 'salt':
import subprocess
res = subprocess.getoutput("salt '%s' cmd.run 'ifconfig'"%cmd)
return res
else:
raise Exception("当前仅支持模式agent、ssh、salt三种模式")
###采集服务器基本的信息,包含<平台、系统版本、主机名>等
from .Base import Base
class Basic(Base):
def process(self,command_func,debug): #command_func传入Linux 下的cmd命令,debug为是否为调试模式(调试模式就用死数据)
if debug:
output = {
'os_platform':'Linux',
'os_version':'CentOS release 6.6 (Final)\n Kernel \r on an \m',
'hostname':'mypc'
}
else:
output = {
'os_platform':command_func('uname').strip(),
'os_version':command_func('cat /etc/issue').strip().split('\n')[0],
'hostname':command_func('hostname').strip()
}
return output
def parse_response(self,res):
### 具体清洗数据
pass
知识点总结:
该项目模仿Django写了一个可插拔式的数据采集系统,实现了以下几个功能
- 用户自定义配置,用户不定义的就执行默认的
global_setting
代码贴出的为简易版本未提供默认配置,可据此修改完善。 - 可自定义采集内容,如果不需要采集,在配置文件中注释即可。首先在plugins下的
__init__.py
启动文件下定义了一个PluginsManager
对象,把settings
这个配置类对象的中需要的数据用self.attr = settings.strr
的方式传入PluginsManager
对象,然后在把配置文件下的PLUGINS_DICT
解析成字符串后,for
循环读取用户定义的配置,利用importlib
模块下的import_module
方法导入src
–plugin
下的类对象获得数据,具体做法是在for
循环中执行类对象.process
,并且传入_cmd_run
函数以及debug
参数,这里需要注意一下,内部函数_cmd_run
是一个内存地址,它以实参的方式传入每个plugin插件下的py文件(eg:basic.py)
,basic.py
中以形参()
执行了_cmd_run
并把取得的数据存入response中,并且返回。