基于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

posted @ 2020-01-15 20:07  GeminiMp  阅读(125)  评论(0编辑  收藏  举报