在局部配置文件中配置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‘)
from src.plugins import PluginsManger if __name__ == ‘__main__‘: res = PluginsManger().execute() print(res)start.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‘, }custom_settings
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
EMAIL_USER = ‘test‘global_settings.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__init__.py
class Board(): def process(self, command_func): res = command_func(‘ifconfig‘) data = self.parse_output(res) return data def parse_output(self, res): passboard.py
class Cpu(): def process(self,command_func): command_func()cpu.py
class Disk(): def process(self, command_func): command_func(‘df -h‘)disk.py
class Memory(): def process(self,command_func): command_func(‘cat memory‘)memory.py
USER = ‘root‘ port = 23s1.py
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