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 (存放测试文件的目录)

start.py

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)

setting.py

### 自定义的配置


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

settings.py

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三种模式")

basic.py

###采集服务器基本的信息,包含<平台、系统版本、主机名>等
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方法导入srcplugin下的类对象获得数据,具体做法是在for循环中执行类对象.process,并且传入_cmd_run函数以及debug参数,这里需要注意一下,内部函数_cmd_run是一个内存地址,它以实参的方式传入每个plugin插件下的py文件(eg:basic.py),basic.py中以形参()执行了_cmd_run并把取得的数据存入response中,并且返回。
posted @ 2019-06-25 21:11  不会玩python  阅读(18)  评论(0编辑  收藏  举报