CMDB项目管理

运维自动化项目
  减少人工干预,降低人员成本
  - 资产管理
  - 操作管理

CMDB
  - 运维自动化基础
  - 资产管理,自动化收集,API接口,可视化管理

  装系统,装服务器环境,比特流上传代码,实时监控服务器

一、资产采集方式
  1.CMDB资产采集方式之agent
  - 本地执行命令 v=subprocess.getoutput('ipconfig')
  - 获取关键信息
  - 将数据录入数据库
  - 不能直连数据库,由于安全,写django程序,通过某个url提交数据到views函数,再提交给数据库(API,requests.post)

优点:快
不好:有agent

# 采集数据
import subprocess
import requests
result = subprocess.getoutput('ipconfig')
# result 正则表达式处理

# 整理资产信息
data_dict = {
'nic':{},
'disk':{},
'mem':{},
}
# 发送数据
requests.post('http://www.127.0.0.1:8000/assets.html',data=data_dict)
Agent 代码

  

2.CMDB资产采集方式之ssh

中间有一个采集资产的机器,不能subprocess了
python 有个模块paramiko,主机名+密码+命令即可在机器执行命令,获取结果返回给中间机器,然后给API,再给数据库

优点:无agent
缺点:paramiko慢(ansible,fabric)

代码:

import requests
import paramiko
# 获取今天未采集主机名
requests.get('http://www.127.0.0.1:8000/assets.html')
result = ['c1.com','c2.com']
# ################## 通过paramiko连接远程服务器,执行命令##################
# 创建SSH对象
ssh = paramiko.SSHClient()
# 允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接服务器
ssh.connect(hostname='192.168.14.36', port=22, username='wupeiqi', password='123')

# 执行命令
# stdin, stdout, stderr = ssh.exec_command('ipconfig')
# stdin.write('') # 用于写信息
# 获取命令结果
# result = stdout.read()
# 关闭连接
# ssh.close()
# print(result)

# data_dict = {result}
# ################## 发送数据 ##################
# requests.post('http://www.127.0.0.1:8000/assets.html',data=data_dict)
ssh方式

 


3.CMDB资产采集方式之saltstack(最火)

  基本流程一样,也有中间的采集资产机器

  但不同在于依赖第三方工具,远程发送执行命令的时候比较快(salt.cmd('c1.com','ipconfig'))
  与ssh的区别:不是硬连,维护一个队列。salt-master主动发送命令给队列,salt-slave获取自己命令,将结果放到另一个队列
  master从这个队列取。RPC形式,没有等待。
  优点:快,不用开发部署agent
  缺点:依赖第三方

代码:
# ################## 获取今日未采集主机名 ##################
#result = requests.get('http://www.127.0.0.1:8000/assets.html')
# result = ['c1.com','c2.com']

# ################## 远程服务器执行命令 ##################
# import subprocess
# result = subprocess.getoutput("salt 'c1.com' cmd.run 'ifconfig'") # 本地执行命令,本地通过saltstack去远程拿数据
#
# import salt.client
# local = salt.client.LocalClient()
# result = local.cmd('c2.salt.com', 'cmd.run', ['ifconfig'])

# ################## 发送数据 ##################
# requests.post('http://www.127.0.0.1:8000/assets.html',data=data_dict)
SaltStack方式

  


4.CMDB资产采集方式之puppet(比较老了)

  puppet类似于saltstack,被动接受slava结果

  puppet有个报表功能,slave每一段时间主动连master,执行自定义命令,这个脚本得用ruby写

  优点:自动汇报
  缺点:ruby

总结:写配置文件,兼容前三种方式,根据情况选择。每天采集一次即可。
  - 第一种,agent定时执行脚本,汇报给api(提供数据,收集数据统一管理)
  - 第二种,paramiko从api取哪台机器还没汇报,远程执行命令,拿取数据
  - 第三种,依赖saltstack,队列RPC形式,
  - 第四种,知道即可,每段时间连接master,执行factor命令脚本,汇报结果


二、SaltStack运行

1. 安装saltstack
rpm --import https://repo.saltstack.com/yum/redhat/6/x86_64/latest/SALTSTACK-GPG-KEY.pub

Master: yum install salt-master
Master准备:
a. 配置文件,监听本机IP
vim /etc/salt/master
interface: 本机IP地址
b. 启动master
/etc/init.d/salt-master start


Slave: yum install salt-minion
Slave准备:
a. 配置文件,连接那个master
vim /etc/salt/minion
master: 远程master地址
b. 启动slave
/etc/init.d/salt-minion start

2. 创建关系
查看
Master:salt-key -L
Accepted Keys:
Denied Keys:
Unaccepted Keys:
c1.com
c2.com
c3.com
Rejected Keys:
接受
Master:salt-key -a c1.com
Accepted Keys:
c1.com
c2.com
Denied Keys:
Unaccepted Keys:
c3.com
Rejected Keys:

3. 执行命令
master:
salt 'c1.com' cmd.run 'ifconfig'

python中执行
import salt.client
local = salt.client.LocalClient()
result = local.cmd('c2.salt.com', 'cmd.run', ['ifconfig'])
SaltStack运行

  

三、资产采集插件

python程序目录结构:
  - bin:可执行文件目录
  - conf:配置文件目录
  - lib:公共模块目录
  - log:日志
  - src:业务逻辑

  发送数据:字典嵌套字典的数据,通过requests.post的json可以自动转为字符串,再转为字节,服务器需要先str(body)再loads

四、动态加密方式

  第一种:在headers设置一个随机字符串,服务器获取request.META['HTTP_AUTHKEY']比较

headers={'authkey':'asdasd'}
json.loads(str(request.body,encoding='utf-8'))

  


第二种:将随机字符串md5加密

app_id = 'asdasdasdasd'
m = hashlib.md5()
m.update(bytes(app_id,encoding='utf-8'))
authkey = m.hexdigest()

  


第三种:随机字符串|当前时间 =》加密后的字符串|时间

current_time = time.time()
app_id = 'asdasdasdasd'
app_id_time = "%s|%s" %(app_id,current_time)
m = hashlib.md5()
m.update(bytes(app_id_time,encoding='utf-8'))
authkey = m.hexdigest()
authkey_time = "%s|%s"%(authkey,current_time)

auth_key_time = request.META['HTTP_AUTHKEY']
auth_key,client_ctime = auth_key_time.split('|')
key_time = "%s|%s" %(ck,client_ctime)
m = hashlib.md5()
m.update(bytes(key_time, encoding='utf-8'))
authkey = m.hexdigest()
if authkey!=auth_key:
return HttpResponse('授权失败')

  

第四种:在第三种基础上,通过加密字符串列表和时间限制,来限制

server_current_time = time.time()
auth_list = []
if server_current_time - 10 > float(client_ctime):
return HttpResponse('授权失败')
if auth_key_time in auth_list:
return HttpResponse('授权失败')
auth_list.append(auth_key_time)	#仅当通过三重验证后才加入列表

  




2018/07/25 day 76 CMDB之后台管理

一、配置文件控制生成表格

table_config = [
{
'q':'id',
'title':'ID',
'display':False
},
{
'q': 'cabinet_num',
'title': '机柜号',
'display': True
},
]

q_list.append(i['q'])    # 添加要取的列名
data_list = models.Asset.objects.all().values(*q_list)
data_list = list(data_list)    # 转列表

function initHeaders(table_config) {
var tr = document.createElement('tr');
$.each(table_config,function (k,item) {    # 循环
if(item.display){
var th = document.createElement('th');
th.innerHTML = item.title;    # 赋值    
$(tr).append(th);
}
});
$('#thead_th').append(tr)
}
配置文件

 

  

二、自定义字符串方法实现字符串替换

String.prototype.format = function (kwargs) {
var ret = this.replace(/\{(\w+)\}/g,function(km,m) {
return kwargs[m]
});
return ret
};

  



三、自定义@符号规则

{
'q': None,
'title': '操作',
'display': True,
'text': {'content': '<a href="/asset-detail/{m}">{n}</a>', 'kwargs': {'n': '查看','m':'@id'}}
},

var kwargs = {};
$.each(config.text.kwargs,function (key,value) {
if(value[0]=='@'){    #遇到第一个字符为@时获取数据库的数据
kwargs[key]=item[value.substring(1,value.length)];
}else {
kwargs[key]=value;
}
});
var temp = config.text.content.format(kwargs);
td.innerHTML = temp;
自定义@符号

  



四、双@规则

在前端设置字符串的全局变量
function initGlobalData(global_list) {
$.each(global_list,function (k,v) {
window[k]=v
})
}

views函数中
{
'q': 'device_type_id',
'title': '资产类型',
'display': True,
'text': {'content': '{n}', 'kwargs': {'n': '@@device_type_choices'}}
},
JavaScript判断
if(value.substring(0,2)=='@@'){
var globalName = value.substring(2,value.length);
var currentId = item[config.q];    # 获取数据库对应的id
var t = getTextFromGlobalById(globalName,currentId);# 去全局变量中取id对应的文本
kwargs[key]=t;
}
定义函数
function getTextFromGlobalById(globalName,currentId) {
var ret = null;
$.each(window[globalName],function (k,item) {
if(item[0]==currentId){
ret = item[1];    # 取id对应的文本
return
}
});
return ret
}
双@符号

  


五、自定义属性以及单@规则

{
'q': 'cabinet_num',
'title': '机柜号',
'display': True,
'text': {'content':'{n}','kwargs':{'n':'@cabinet_num'}},
'attrs': {'edit-enable': 'true', 'edit-type': 'input'}
},

$.each(config.attrs,function (kk,vv) {
td.setAttribute(kk,vv);
});

  


单@规则:

{
'q': 'manager__name',
'title': '管理人组',
'display': True,
'text': {'content': '{n}', 'kwargs': {'n': '@manager__name'}},
'attrs': {'name': 'manager_id', 'origin': '@manager_id', 'edit-enable': 'true', 'edit-type': 'select',
'global-name': 'manager_choices'}
},

  



origin:用于生成select框时的赋值(ID数字),origin的@在initBody函数内会转换为item的值,这样生成select框时有值可赋。
    而对于input,则不赋值,只用于比较新生成的值new-val
name:用于保存新编辑的值,字典的key
global-name:用于生成输入框时从全局变量取对应的字典来循环。



  总结:

posted @ 2018-07-27 21:23  心平万物顺  阅读(539)  评论(0编辑  收藏  举报