基于Djnago配置文件用于我们自己的项目
目录
目录结构
[root@百度云-106 app]# tree -L 2 autoclient/
autoclient/:
├── bin
│ └── start.py # 启动文件
├── conf
│ ├── cert # 保存一些固定信息
│ ├── config.py # 用户可自定义的配置
├── files
│ ├── board.out # 一些示例文件
│ ├── cpuinfo.out
│ ├── disk.out
│ ├── memory.out
│ └── nic.out
├── lib
│ └── conf # 程序默认的一些配置
├── scripts # 测试脚本的文件夹
│ ├── s1.py
│ └── test.py
└── src
├── client.py # 一些公共都需要的方法
├── plugins # 执行任务的一些脚本文件夹
└── script.py # 程序启动的核心文件
10 directories, 12 files
conf/config.py
'''
自定制的配置
'''
import os
BASEDIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# 可配置 客户端脚本采集的方式:
# agent | ssh | salt
MODE = "agent"
# 上线应改为False
DEBUG = True
# 配置连接的用户名、密码
SSH_USER = "root"
SSH_PORT = 22
SSH_PWD = "123"
# 后台收集数据的接口
API_URL = "http://127.0.0.1:8000/api/"
# 配置采集的插件,可插拔式
PULGINS_DICT = {
# "basic": "src.plugins.basic.Basic",
"cpu": "src.plugins.cpu.Cpu",
# "disk": "src.plugins.disk.Disk",
}
lib/conf/global_settings.py
'''
默认的配置
'''
EMAIL_PORT = 25
lib/conf/conf.py
from conf import config # 自定制的配置
from . import global_settings # 高级的配置
class Settings():
def __init__(self):
self.get_global_settings()
self.get_config()
def get_global_settings(self):
# 整合高级配置
for key in dir(global_settings):
if key.isupper():
v = getattr(global_settings, key)
setattr(self, key, v)
def get_config(self):
# 整合自定制配置
for key in dir(config):
if key.isupper():
v = getattr(config, key)
setattr(self, key, v)
settings = Settings()
bin/start.py
from src import plugins, script
if __name__ == '__main__':
script.run()
src/script.py
from src import client
from lib.conf.conf import settings
def run():
if settings.MODE == "agent":
obj = client.Agent()
else:
obj = client.SSH()
obj.collectAndPost()
src/client.py
import os
import requests
from lib.conf.conf import settings
from src.plugins import PluginsManager
from concurrent.futures import ThreadPoolExecutor
class Base():
def post_data(self, res):
requests.post(settings.API_URL, json=res)
# 收集数据并发送
class Agent(Base):
def collectAndPost(self):
server_info = PluginsManager().collect()
'''
处理唯一标识的问题:
以hostname or ip 作为唯一标识,将新采集到post过来的新数据以这个唯一标识作为where条件去数据库中查询
如果没有就表示新增
'''
hostname = server_info["cpu"]["data"]["hostname"]
# 读取文件中的主机名
res = open(os.path.join(settings.BASEDIR, 'conf/cert'), 'r', encoding='utf-8').read()
if not res.strip():
# 如果没有内容,说明是第一次采集,将采集到的hostname写入到文件中
with open(os.path.join(settings.BASEDIR, 'conf/cert'), 'w', encoding='utf-8') as f:
f.write(hostname)
else:
# 第二次采集的时候,永远以第一次文件中采集到的主机名为唯一标识
server_info["cpu"]["data"]["hostname"] = res
# post 到api端
self.post_data(server_info)
class SSH(Base):
def get_hostname(self):
res = requests.get(settings.API_URL)
return res
def run(self, host):
res = PluginsManager(hostname=host).collect()
# post 到api端
self.post_data(res)
def collectAndPost(self):
hostname = self.get_hostname()
p = ThreadPoolExecutor(100)
for host in hostname:
p.submit(self.run, host)
src/plugins/__init__
.py
import subprocess
import importlib
import paramiko
import traceback
from lib.conf.conf import settings
### 管理采集的插件
class PluginsManager():
def __init__(self, hostname=None):
self.hostname = hostname
self.plugins_items = settings.PULGINS_DICT
self.debug = settings.DEBUG
if settings.MODE == "ssh":
self.ssh_user = settings.SSH_USER
self.ssh_port = settings.SSH_PORT
self.ssh_pwd = settings.SSH_PWD
# 核心的采集方法
def collect(self):
response = {}
for key, v in self.plugins_items.items():
ret = {"status": None, "data": None}
try:
module_path, class_name = v.rsplit('.', 1)
m = importlib.import_module(module_path)
cls = getattr(m, class_name)
res = cls().execute(self.command_func, self.debug)
ret["status"] = 10000
ret["data"] = res
except Exception as e:
ret["status"] = 10001
# ret["data"] = str(e)
ret["data"] = "[%s] 采集 [%s] 有误,错误信息:%s" % (
self.hostname if self.hostname else "Agent",
key,
str(traceback.format_exc())
)
response[key] = ret
return response
def command_func(self, cmd):
if settings.MODE == "agent":
self.cmd_agent(cmd)
elif settings.MODE == "ssh":
self.cmd_ssh(cmd)
elif settings.MODE == "salt":
self.cmd_salt(cmd)
else:
print('只支持 agent|ssh|salt 三种模式')
def cmd_agent(self, cmd):
res = subprocess.getoutput(cmd)
return res
# 客户端 获取IP信息。
# ip = "192.168.32.130"
# res = requests.post("http://127.0.0.1:8000/api/", json=ip)
# print(res.text)
def cmd_ssh(self, cmd):
# 使用ssh类方法,使用paramiko模块来采集
# 创建SSH对象
ssh = paramiko.SSHClient()
# 允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接服务器
ssh.connect(hostname=self.hostname,
port=self.ssh_port,
username=self.ssh_user,
password=self.ssh_pwd)
# 执行命令
# stdin:输入的内容
# stdout:输出的内容
# stderr:错误的内容
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