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 (*****)


作业:
在正式环境中定义命令并进行解析



posted @ 2018-10-13 22:17  番茄土豆西红柿  阅读(128)  评论(0)    收藏  举报
TOP