65 - CMDB-1-traceback&多线程&开放封闭原则&类的抽象方法
相关知识点
1.错误堆栈信息traceback
#!/usr/bin/python # -*- coding:utf-8 -*- import traceback def f1(): result = 123 int('asdf') return result def run(): try: ret = f1() print(ret) except Exception as e: msg = traceback.format_exc() print msg run()
logger.info(msg)
logger.info('777end')
# result_info = '报错信息为:' + str(msg) ####如果没有报错,即msg为空的时候,这个语句会不执行
2.多线程---python3的线程池
#!/usr/bin/python # -*- coding:utf-8 -*- import time from concurrent.futures import ThreadPoolExecutor def task(host): """ 采集资产 :return: """ time.sleep(2) print(host) # 创建了一个线程池,线程池中最多放20个线程(20个我去采集资产) pool = ThreadPoolExecutor(20) for i in range(1,101): hostname = "c%s.com" %(i,) # 去线程池中申请一个线程去执行task函数 pool.submit(task,hostname)
CMDB设计三种模式
1.agent模式

#!/usr/bin/python # -*- coding:utf-8 -*- import requests import json def agent(): """ 获取当前服务器的资产信息并提交给api :return: """ # 1. 获取资产信息:硬盘、网卡、内存...(linux或win的判断) import subprocess disk = subprocess.getoutput('dir') info = {'hostname':'c1','memory':disk} # 2. 日志处理(堆栈信息) # 3. 唯一标记问题 # 如果只是物理机:sn做唯一标记 # 物理+虚拟机:1. 系统+调用openstack api ;2.主机名做唯一标记 url = "http://127.0.0.1:8000/api/asset/" r1 = requests.post( url=url, data=json.dumps(info).encode('utf-8'), # data={'k1':'v1','k2':'v2'} # hostname=c1&memory=xxxxx ) print(r1.text)

2.salt模式
3.ssh模式
#!/usr/bin/python # -*- coding:utf-8 -*- import requests import json def task(host): # 每一台主机,调用ssh或salt接口远程连接上主机并执行命令 获取结果。(线程池的方式进行采集) info = {'hostname': host, 'disk': '....'} # 通过requests发送POST请求将资产数据提交到api url = "http://127.0.0.1:8000/api/asset/" r1 = requests.post( url=url, data=json.dumps(info).encode('utf-8'), ) print(r1.text) def ssh(): # 1. 获取未采集服务器列表 r1 = requests.get(url="http://127.0.0.1:8000/api/asset/") # print(r1.content, r1.text, r1.json() ) host_list = r1.json() from concurrent.futures import ThreadPoolExecutor pool = ThreadPoolExecutor(10) for host in host_list: pool.submit(task,host) ssh()

代码架构设计
1.插件模式(开放封闭原则)

如下配置文件1
#!/usr/bin/python # -*- coding:utf-8 -*- ENGINE_HANDLERS = { 'agent':'src.engine.agent.AgentHandler', 'ssh':'src.engine.ssh.SSHHandler', 'salt':'src.engine.salt.SaltHandler', } ENGINE = 'salt' # ########### SSH模式 ########### # 私钥地址 SSH_PRIVATE_KEY = '/xxx/xx/xx' SSH_PORT = 22 SSH_USER = 'cmdb' # ############################## 插件 ################################ PLUGIN_DICT = { 'disk':'src.plugins.disk.Disk', 'memory':'src.plugins.memory.Memory', 'network':'src.plugins.network.Network', }
输出结果:
salt模式 {'disk': '硬盘', 'memory': '内存', 'network': '网络'}
如下配置文件2
#!/usr/bin/python # -*- coding:utf-8 -*- ENGINE_HANDLERS = { 'agent':'src.engine.agent.AgentHandler', 'ssh':'src.engine.ssh.SSHHandler', 'salt':'src.engine.salt.SaltHandler', } ENGINE = 'agent' # ########### SSH模式 ########### # 私钥地址 SSH_PRIVATE_KEY = '/xxx/xx/xx' SSH_PORT = 22 SSH_USER = 'cmdb' # ############################## 插件 ################################ PLUGIN_DICT = { # 'disk':'src.plugins.disk.Disk', 'memory':'src.plugins.memory.Memory', 'network':'src.plugins.network.Network', }
输出结果
agent {'memory': '内存', 'network': '网络'}
详细代码参考:https://files.cnblogs.com/files/robinunix/auto_client-1-%E6%8F%92%E4%BB%B6%E7%9A%84%E8%AE%BE%E8%AE%A1.tar.gz
课堂自己笔记
++++++++++++++++++
1.request 提交,django 获取数据(request.post中没有,就去request.body中获取)
2.traceback
3.代码拆分的开放封闭原则(切换功能 和 新增功能的时候都遵循这个原则),按功能目录拆分,engine中的文件是类的编写方式
使用字典定义配置文件,比使用字符串定义配置文件,然后在源码中再做if else判断要更加灵活
4.性能问题考虑多线程,多线程数量考虑线程池
5.csrf token的装饰器
6.程序’可插拔’兼容多种模式
7.设计模式==抽象工厂模式->根据配置文件不同做不同的事情!!!!!!!可扩展性的程序设计!!!!!!!!
简单工厂
抽象方法
抽象工厂
8.代码的潜规则,抽象类 or 抽象方法
java====javapython
java是编译,编译的时候如果没有定义就会报错
python 是解释性语言,所以不会报错,但是执行的时候,在本类中没有,去父类中找就会去报错
在python中约束子类,用下面的方法
基类的作用:
1.约束派生类
2.派生类中的公用方法写到基类中
python
info是个字典
可以从request.body获取
data=json.dumps(info).encode(‘utf-8’) #给request传送的得是字节,自己转换
json = info ##可以直接传字典,但是字典不能包含中文(因为request中自动的吹字节码不是utf-8)
data = info 这样会转换的是=的格式(request完成的),可以从request.post中获取
获取request的返回
r1.content 字节
r1.text 字符串
r1.json 字典,列表类型=====这种的更方便
traceback 记录报错堆栈的完整信息,写错误日志用这个。。。。获取错误的堆栈信息,然后把堆栈信息写入到日志!!!!!!
CMDB和预算相关
开发中遇到的问题及解决方案是什么??
资产信息的唯一标识符用SN,不能用主机名,但是使用OpenStack宿主机虚拟出多个虚拟机,虚拟机和宿主机的SN是一样的
SN: 只处理物理机
物理机 + 虚拟机 :还用主机名,但是发送的是主机名 + 一个文件的内容(新的主机是空的,老的主机是老的主机名,这样主机名变化的时候会传现有主机名 + 文件中的主机名来做diff)
代码拆封如何拆分???
不仅仅是函数的拆分,应该设计成如何可扩展,遵循开放封闭原则,(配置文件开放,源码封闭)
考虑性能采用多线程来解决?那么问题来了,创建多少个线程呢?使用线程池
线程池:先创建20个线程ready,30个任务,20个中的任何一个处理完了,继续处理剩下中的10个中的一个,效果就是同时处理20个
访问django的接口,url后面加反斜杠~~~~~~~~~~
python2 和python3 slat的包不一样,要注意~~~
*args.**kgwargs 或者参数使用默认值
传递self的效果是不用做参数判断了!!!!!!!
实例化的时候,如果自己没有构造方法,则执行父类的构造方法!!!!
找模板,如果公共的templates中没有模板,就会去各个app的templates中去找!!!!
给django rest frame work发送post的数据,request的header需要制定header的conten-type为application/json
课堂笔记
CMDB项目
自动化平台相关:CMDB资产管理
1. 堡垒机
2. 发布
3. 配管系统、装机
4. 私有云/公有云
5. 故障自愈、预测
目标:CMDB
1. Excel做资产管理
2. 监控系统的联动
3. 装机系统需求联动
总结:cmdb资产管理开发。
实现思路:
1. agent模式
2. ssh模式
3. salt模式
兼容以上三种模式的设计且可扩展。
基本架构
- 资产采集
- api
- 管理平台
今日内容:
- 资产采集
内容详细:
1. 创建项目
- 资产采集,自己写脚本。
- auto_client
- agent模式
1. 获取本机资产信息
2. 使用requests将资产信息上报api,入库持久化。
- ssh模式
1. 获取未采集服务器列表
2. 循环列表,为每个服务资产采集(ssh)创建一个线程去执行(线程池)。
3. 获取资产后自动提交。
- salt模式
1. 获取未采集服务器列表
2. 循环列表,为每个服务资产采集(salt接口)创建一个线程去执行(线程池)。
3. 获取资产后自动提交。
- 相关知识点:
- 错误堆栈信息
- POST方式提交数据,django的request.POST可能没有值,去request.body
- 开放封闭原则:
- 开发:配置
- 封闭:源码
- 线程池
- csrf token,取消个别函数的csrf token验证,使用特殊装饰器:
如:
@csrf_exempt # 告诉django该函数不用走csrf验证
def asset(request):
pass
- api,基于django实现。
- auto_server
2. 项目结构设计
a. 项目基础架构:开放封闭+工厂模式
b. 约束:面向对象约束
java
# 接口类型
interface IFoo:
# 在接口中定义了一个方法(方法内部不能写任何代码)
def func(self):pass
# 如果类继承了 某个接口 在类中必须 实现=编写 接口中所有的方法。
class Person(IFoo):
def func(self):
pass
Python
class Base:
def func(self):
raise NotImplementedError()
class Person(Base):
def func(self):pass
obj = Person()
obj.func()
示例:
class BaseHandler(object):
def handler(self):
"""
约束所有的派生类都必须实现handler方法
:return:
"""
raise NotImplementedError('handler must be implemented')
class AgentHandler(BaseHandler):
def handler(self):
"""
处理Agent模式下的资产采集
:return:
"""
print('agent模式')
c. 插件的可扩展性
作业:在正式环境中定义命令并进行解析
客户端遗留的问题:
- 错误信息
- 日志
- 插件:信息 (内存、网卡、硬盘)
d. API相关
1. 写接口,使用cbv; 编写API时,不推荐使用FBV而是用CBV。
2. cbv中遇到希望添加装饰器
import json
from django.shortcuts import render,HttpResponse
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator
from django.views import View
class AssetView(View):
"""
资产相关接口
"""
@method_decorator(x1)
def get(self,requset,*args,**kwargs):
host_list = ['c1.com', 'c2.com', 'c3.com']
return HttpResponse(json.dumps(host_list))
@method_decorator(x2)
def post(self,request,*args,**kwargs):
info = json.loads(request.body.decode('utf-8'))
print(info)
return HttpResponse('收到了')
3. csrf_exempt
import json
from django.shortcuts import render,HttpResponse
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator
from django.views import View
# 方式一
@method_decorator(csrf_exempt,name='dispatch')
class AssetView(View):
"""
资产相关接口
"""
# 方式二
# @method_decorator(csrf_exempt)
# def dispatch(self, request, *args, **kwargs):
# return super().dispatch(request, *args, **kwargs)
def get(self,requset,*args,**kwargs):
host_list = ['c1.com', 'c2.com', 'c3.com']
return HttpResponse(json.dumps(host_list))
def post(self,request,*args,**kwargs):
info = json.loads(request.body.decode('utf-8'))
print(info)
return HttpResponse('收到了')
4. django rest framework
- 自动加 csrf_exempt
- 页面变好看
- 自动反序列化
from rest_framework.views import APIView
from rest_framework.response import Response
class AssetView(APIView):
def get(self, requset, *args, **kwargs):
host_list = ['c1.com', 'c2.com', 'c3.com']
# return HttpResponse(json.dumps(host_list))
return Response(host_list)
def post(self, request, *args, **kwargs):
# info = json.loads(request.body.decode('utf-8'))
# print(info)
print(request.data) # json格式
return HttpResponse('收到了')
注意:注册app
重点:
1. 写代码的思路(*****)
- 开发封闭原则
- 设计模式:工厂模式
2. 客户端开发(****)
3. restful api (*****)
作业:
在正式环境中定义命令并进行解析

浙公网安备 33010602011771号