cmdb采集数据的版本

时间:2021-10-03 03:12:38

 

在局部配置文件中配置MODE=‘ agent‘,或者MODE=‘ssh’,或者MODE=‘’saltstack ‘,  实现只需要修改这个配置,就会使用对应的方案进行采集数据

 

第一种版本:

启动文件中直接判断

start.py

from lib.config.config import settings
import subprocess

from src.plugins import board,disk,memory
if __name__ == __main__:
    mode = settings.MODE

    if mode == agent:
        res = subprocess.getoutput(ifconfig)
        ip = res[30:50]
        print(ip)

    elif mode == ssh:
        import paramiko

        # 创建SSH对象
        ssh = paramiko.SSHClient()
        # 允许连接不在know_hosts文件中的主机
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        # 连接服务器
        ssh.connect(hostname=c1.salt.com, port=22, username=root, password=123)
        # 执行命令
        stdin, stdout, stderr = ssh.exec_command(ifconfig)
        # 获取命令结果
        result = stdout.read()
        print(result)
        # 关闭连接
        ssh.close()
    else:
        import salt.client

        local = salt.client.LocalClient()
        result = local.cmd(c2.salt.com, cmd.run, [ifconfig])
        print(result)

如果采集不同的信息,还需要一次次的修改命令并且启动文件不能写业务逻辑代码

存在的问题:

1. 面向过程的写法, 代码不容易扩展, 后续不好维护

2. 不符合软件设计的原则 ()
高内聚低耦合
a. 这是一个代码的设计思想
b. 在写函数或者类的时候, 代码中尽量不要多一行和次函数或者 类无关的代码

原则:
def getUserInfo():
### 获取用户信息的函数

getOrderDetail()
pass

def getOrderDetail():
### 获取订单详情的代码

 

 

改进的方法:???

面向对象的思想??

在src文件夹中创文件夹plugins,将所需要采集的信息如ip,cpu,内存等信息分成一个个py文件各个写入自己的类??

 

board.py 收集服务器ip的文件

from lib.config.config import settings
import subprocess

class Board():
    def process(self):
        # return "board info"


        if settings.MODE == agent:
            res = subprocess.getoutput(ifconfig)
            print(res[30:50])
        elif settings.MODE == ssh:
            import paramiko

            # 创建SSH对象
            ssh = paramiko.SSHClient()
            # 允许连接不在know_hosts文件中的主机
            ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
            # 连接服务器
            ssh.connect(hostname=c1.salt.com, port=22, username=root, password=123)
            # 执行命令
            stdin, stdout, stderr = ssh.exec_command(ifconfig)
            # 获取命令结果
            result = stdout.read()
            print(result)
            # 关闭连接
            ssh.close()
        else:
            import salt.client

            local = salt.client.LocalClient()
            result = local.cmd(c2.salt.com, cmd.run, [ifconfig])

        return  "boaed_info"

disk.py 

from lib.config.config import settings
import subprocess
class Disk():
    def process(self):
        # return "disk info"

        if settings.MODE == agent:
            res = subprocess.getoutput(df -h)
            print(res[30:50])
        elif settings.MODE == ssh:
            import paramiko

            # 创建SSH对象
            ssh = paramiko.SSHClient()
            # 允许连接不在know_hosts文件中的主机
            ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
            # 连接服务器
            ssh.connect(hostname=c1.salt.com, port=22, username=root, password=123)
            # 执行命令
            stdin, stdout, stderr = ssh.exec_command(df -h)
            # 获取命令结果
            result = stdout.read()
            print(result)
            # 关闭连接
            ssh.close()
        else:
            import salt.client

            local = salt.client.LocalClient()
            result = local.cmd(c2.salt.com, cmd.run, [df -h])

        return "disk_info"

 

memory.py

class Memory():
    def process(self):
        # return ‘memory info‘

        if settings.MODE == agent:
            res = subprocess.getoutput(cat memory)
            print(res[30:50])
        elif settings.MODE == ssh:
            import paramiko

            # 创建SSH对象
            ssh = paramiko.SSHClient()
            # 允许连接不在know_hosts文件中的主机
            ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
            # 连接服务器
            ssh.connect(hostname=c1.salt.com, port=22, username=root, password=123)
            # 执行命令
            stdin, stdout, stderr = ssh.exec_command(cat memory)
            # 获取命令结果
            result = stdout.read()
            print(result)
            # 关闭连接
            ssh.close()
        else:
            import salt.client

            local = salt.client.LocalClient()
            result = local.cmd(c2.salt.com, cmd.run, [cat memory])

        return "memory_info"

 

然后在start.py文件中调用

from src.plugins import board,disk,memory
if __name__ == __main__:
    
    print(board.Board.process())
    print(disk.Disk.process())
    print(memory.Memory.process())
存在的问题: 
不是特别的方便

 

 

 

版本2:

解决的方法:

参考django的中间件


实现可插拔式的采集

在custom_settings局部文件中写人

PLUGINS_DICT = {

    board: src.plugins.board.Board,
    disk: src.plugins.disk.Disk,
    memory: src.plugins.memory.Memory,


}

在src文件夹中plugins文件夹中创一个__init__.py文件来管理插拔信息

 

__init__.py

from lib.config.config import settings

import importlib


#管理插件信息的类
class PluginsManger(object):

    def __init__(self):
        self.plugins_dict = settings.PLUGINS_DICT

    #读取配置文件中的pluginsdict, 并执行对应模块中的process方法
    def execute(self):
        response = {}
        for k,v in self.plugins_dict.items():
            ‘‘‘
          k:  board,...
          v:  src.plugins.board.Board   字符串
           ‘‘‘
            #1.导入模块路径
            moudle_path,class_name = v.rsplit(., 1)
            #2.导入这个路径

            moudle_name = importlib.import_module(moudle_path)

            #3.导入对应的类
            classobj = getattr(moudle_name, class_name)

            #4.执行类下面对应的process方法

            res = classobj().process()
            response[k] = res
        return response

 

start.py

from src.plugins import PluginsManger

if __name__ == __main__:
    res = PluginsManger().execute()
    print(res)
存在的问题:
代码过于冗余

解决的方法:

a. 写一个父类, 此父类有一个公共方法, 执行对应的代码

b. 就是以下这种方法








版本3:

??将采集数据的代码(也就是board,cpu,disk,memory中相同的代码)放入到__init__.py 中新创的函数__cmd_run中,然后将命令cmd当成传入,传入的方式就是在调用excute函数中执行调用process函数,然后在每个board,cpu,disk,memory类中process方法获取到这个函数,然后调用传入cmd,然后再抽离将每个方案采集数据的形式都分成一个个函数,再传入cmd

然后每个方案采集数据都不同,ssh需要传入username,password,port,host,   saltstack需要传入host,   agent什么都不需要传,所以在start文件调用PluginsManger类的时候需要传入host,然后将其变成对象属性,而ssh需要传入很多参数,就在custom_settings中传入,再将其变成对象的属性??

 

custom_settings.py

MODE = agent


SSH_USERNAME = root

SSH_PASSWORD = 123

SHH_PORT = 22

PLUGINS_DICT = {

    board: src.plugins.board.Board,
    disk: src.plugins.disk.Disk,
    memory: src.plugins.memory.Memory,


}

 

 

__init__.py

from lib.config.config import settings

import importlib
import subprocess

#管理插件信息的类
class PluginsManger(object):

    def __init__(self, hostname=None):
        self.plugins_dict = settings.PLUGINS_DICT
        self.hostname = hostname

        if settings.mode == ssh:
            self.port = settings.SSH_PORT
            self.username = settings.SSH_USERNAME
            self.pwd = settings.SSH_PASSWORD

    #读取配置文件中的pluginsdict, 并执行对应模块中的process方法
    def execute(self):
        response = {}
        for k,v in self.plugins_dict.items():
            ‘‘‘
          k:  board,...
          v:  src.plugins.board.Board   字符串
           ‘‘‘
            #1.导入模块路径
            moudle_path,class_name = v.rsplit(., 1)
            #2.导入这个路径

            moudle_name = importlib.import_module(moudle_path)

            #3.导入对应的类
            classobj = getattr(moudle_name, class_name)

            #4.执行类下面对应的process方法

            res = classobj().process(self.__cmd_run)
            response[k] = res
        return response


    def __cmd_run(self,cmd):
        if settings.MODE == agent:
           return self.cmd_agent(cmd)
        elif settings.MODE == ssh:
            return self.cmd_ssh(cmd)
        else:
            return self.cmd_salt(cmd)

    def cmd_agent(self,cmd):
        res = subprocess.getoutput(cmd)
        return res

    def cmd_ssh(self, cmd):
        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.pwd)
        # 执行命令
        stdin, stdout, stderr = ssh.exec_command(cmd)
        # 获取命令结果
        result = stdout.read()

        # 关闭连接
        ssh.close()
        return result

    def cmd_salt(self,cmd):
        command = "salt %s cmd.run %s" %(self.hostname,cmd)
        res = subprocess.getoutput(command)
        return res

 

board.py

class Board():
    def process(self, command_func):
        res = command_func(ifconfig)
        data = self.parse_output(res)
        return data

    def parse_output(self, res):
        pass

 

cpu.py

class Cpu():
    def process(self,command_func):
        command_func()

 

disk.py

class Disk():
    def process(self, command_func):
       command_func(df -h)

 

memory.py

class Memory():
    def process(self,command_func):
        command_func(cat memory)

 

cmdb采集数据的版本

cmdb采集数据的版本cmdb采集数据的版本
from src.plugins import PluginsManger

if __name__ == __main__:


    res = PluginsManger().execute()
    print(res)
start.py cmdb采集数据的版本cmdb采集数据的版本
MODE = agent


SSH_USERNAME = root

SSH_PASSWORD = 123

SHH_PORT = 22

PLUGINS_DICT = {

    board: src.plugins.board.Board,
    disk: src.plugins.disk.Disk,
    memory: src.plugins.memory.Memory,


}
custom_settings cmdb采集数据的版本cmdb采集数据的版本
from conf import custom_settings
from . import global_settings


class Settings():
    def __init__(self):
        ### 全局设置
        for key in dir(global_settings):
            if key.isupper():
                v = getattr(global_settings, key)  # 第一个是对象,第二个key
                setattr(self, key,
                        v)  # self代表的是当前的对象settings,key就是配置文件的大写的配置,v 就是self.配置的值,所以这样就可以通过settings这个对象点的方式获取到值

    ### 自定制配置
        for key in dir(custom_settings):
            if key.isupper():
                v = getattr(custom_settings, key)  # 第一个是对象,第二个key
                setattr(self, key,
                        v)  # self代表的是当前的对象settings,key就是配置文件的大写的配置,v 就是self.配置的值,所以这样就可以通过settings这个对象点的方式获取到值

settings = Settings()
config.py cmdb采集数据的版本cmdb采集数据的版本
EMAIL_USER = test
global_settings.py cmdb采集数据的版本cmdb采集数据的版本
from lib.config.config import settings

import importlib
import subprocess

#管理插件信息的类
class PluginsManger(object):

    def __init__(self, hostname=None):
        self.plugins_dict = settings.PLUGINS_DICT
        self.hostname = hostname

        if settings.mode == ssh:
            self.port = settings.SSH_PORT
            self.username = settings.SSH_USERNAME
            self.pwd = settings.SSH_PASSWORD

    #读取配置文件中的pluginsdict, 并执行对应模块中的process方法
    def execute(self):
        response = {}
        for k,v in self.plugins_dict.items():
            ‘‘‘
          k:  board,...
          v:  src.plugins.board.Board   字符串
           ‘‘‘
            #1.导入模块路径
            moudle_path,class_name = v.rsplit(., 1)
            #2.导入这个路径

            moudle_name = importlib.import_module(moudle_path)

            #3.导入对应的类
            classobj = getattr(moudle_name, class_name)

            #4.执行类下面对应的process方法

            res = classobj().process(self.__cmd_run)
            response[k] = res
        return response


    def __cmd_run(self,cmd):
        if settings.MODE == agent:
           return self.cmd_agent(cmd)
        elif settings.MODE == ssh:
            return self.cmd_ssh(cmd)
        else:
            return self.cmd_salt(cmd)

    def cmd_agent(self,cmd):
        res = subprocess.getoutput(cmd)
        return res

    def cmd_ssh(self, cmd):
        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.pwd)
        # 执行命令
        stdin, stdout, stderr = ssh.exec_command(cmd)
        # 获取命令结果
        result = stdout.read()

        # 关闭连接
        ssh.close()
        return result

    def cmd_salt(self,cmd):
        command = "salt %s cmd.run %s" %(self.hostname,cmd)
        res = subprocess.getoutput(command)
        return res
__init__.py cmdb采集数据的版本cmdb采集数据的版本
class Board():
    def process(self, command_func):
        res = command_func(ifconfig)
        data = self.parse_output(res)
        return data

    def parse_output(self, res):
        pass
board.py cmdb采集数据的版本cmdb采集数据的版本
class Cpu():
    def process(self,command_func):
        command_func()
cpu.py cmdb采集数据的版本cmdb采集数据的版本
class Disk():
    def process(self, command_func):
       command_func(df -h)
disk.py cmdb采集数据的版本cmdb采集数据的版本
class Memory():
    def process(self,command_func):
        command_func(cat memory)
memory.py cmdb采集数据的版本cmdb采集数据的版本
USER = root
port = 23
s1.py cmdb采集数据的版本cmdb采集数据的版本
import s1


print(dir(s1))
# [‘USER‘, ‘__builtins__‘, ‘__cached__‘, ‘__doc__‘, ‘__file__‘, ‘__loader__‘, ‘__name__‘, ‘__package__‘, ‘__spec__‘, ‘port‘]

print(s1)
print(s1.USER)

for key in dir(s1):
    if key.isupper():  # 我们只要大写的,因为配置文件里面规定大写,小写就排除掉
        print(key)
s2.py