个人博客地址
继上篇zabbix-api,决定简单写一个页面来完成zabbix-api的批量操作
使用django完成
目录如下

这个简陋的页面长这样,登录

长这样,主页,展示groups

长这样,展示groups中的所有agent类host

长这样,展示host中筛选过的items

最后添加items页面长这样,可以多选key,批量添加

代码部分
自己日常工作用,页面不重要,重要的是功能,因为写页面太tm耗时了
下面贴下代码
urls.py
from django.contrib import admin
from django.urls import path
from DarkZabbix import views
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.zabbix),
path('login.html/', views.login),
path('zabbix.html/', views.zabbix),
path('zabbix_host.html/', views.zabbix_host),
path('zabbix_items.html/', views.zabbix_items),
path('additems.html/', views.add_items),
path('keylist.html/', views.key_list),
path('delitem.html/', views.del_items),
]
templates里只用两个html页面,一个用于登录,一个用于展示和操作
login.html
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>登录title>
<style>
.input{width: 300px; height: 20px;margin-top: 10px;}
style>
head>
<body style="background-color: royalblue;">
<div style="position: absolute;top: 50%;left: 50%;transform: translate(-50%,-50%);">
<form action="/login.html/" method="POST">
{% csrf_token %}
<h1 style="text-align: center; color: seashell;">Dark-zabbixh1>
<input class="input" name="username" type="text" placeholder=username>
<br>
<input class="input" name="passwd" type="password" placeholder=passwd>
<br>
<button style="width: 300px;height: 30px; margin-top: 10px;" >登录button>
<span>{{error}}span>
form>
div>
body>
html>
zabbix.html
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>indextitle>
<link href="/static/index.css" rel='stylesheet' type="text/css">
<script src="/static/jquery-3.6.0.js">script>
<script src="/static/jquery.cookie.js">script>
<script src="/static/index.js">script>
head>
<body>
{% csrf_token %}
<div class="hidden block">div>
<div class="top">
<div class="top-left">
DarkZabbix
div>
<div class="top-right">
<div>用户:{{request.user}}div>
div>
div>
<div class="left">
{%for hostgroup in groupli%}
<a class="leftmenu astyle" id={{hostgroup.groupid}} href="#">{{hostgroup.name}}a>
{%endfor%}
div>
<div class="right">
div>
body>
html>
statics里放登录用的证书和jquery文件,还有自定义的js css文件
index.js 里存放页面操作函数
token = $.cookie('csrftoken')
$(function(){
hostshow()
itemshow()
additems()
command()
delitem()
})
function hostshow(){
$('.leftmenu').click(function(){
var hostid = $(this).attr('id')
$.ajax({
url:'/zabbix_host.html/',
data:{'id':hostid},
type:'POST',
headers:{'X-CSRFToken':token},
success:function(host_li){
$('.right').empty()
$('.right').append(host_li)
}
})
})
}
function itemshow(){
$('.right').on('click','.host',function(){
var hostid = $(this).attr('hostid')
var hostname = $(this).text()
var interfaceid = $(this).attr('interfaceid')
$.ajax({
url:'/zabbix_items.html/',
data:{'hostid':hostid,'interfaceid':interfaceid,'hostname':hostname},
type:'POST',
headers:{'X-CSRFToken':token},
success:function(items){
$('.right').empty()
$('.right').append(items)
}
})
})
}
function additems(){
$('.right').on('click','.additem',function(){
var hostid = $(this).attr('hostid')
var interfaceid = $(this).attr('interfaceid')
addlable=''+
'提交'
$.ajax({
url:'/keylist.html/',
data:{'hostid':hostid},
type:'POST',
headers:{'X-CSRFToken':token},
success:function(ret){
$('.right').empty()
var lab = ret + addlable
$('.right').append(lab)
}
})
})
}
function command(){
$('.right').on('click','.command',function(){
var data = $('.itemname').val()
var key_ = $('select').val()
var hostid = $(this).attr('hostid')
var interfaceid = $(this).attr('interfaceid')
console.log(data,key_)
$.ajax({
url:'/additems.html/',
data:{'hostid':hostid,'interfaceid':interfaceid,'data':data,'key_':JSON.stringify(key_)},
type:'POST',
headers:{'X-CSRFToken':token},
success:function(ret){
$('.right').empty()
$('.right').append(ret)
}
})
}
)
}
function delitem(){
$('.right').on('click','.del',function(){
itemid = $(this).attr('itemid')
$.ajax({
url:'/delitem.html/',
data:{'itemid':itemid},
type:'POST',
headers:{'X-CSRFToken':token},
success:function(ret){
$("."+itemid).remove()
var htm = $('.right').html()
$('.right').empty()
$('.right').append(htm)
}
})
}
)
}
jquery.cook,js 官网下载文件,用于django的CSRF,防止跨站

/*!
* jQuery Cookie Plugin v1.4.1
* https://github.com/carhartl/jquery-cookie
*
* Copyright 2006, 2014 Klaus Hartl
* Released under the MIT license
*/
(function (factory) {
if (typeof define === 'function' && define.amd) {
// AMD (Register as an anonymous module)
define(['jquery'], factory);
} else if (typeof exports === 'object') {
// Node/CommonJS
module.exports = factory(require('jquery'));
} else {
// Browser globals
factory(jQuery);
}
}(function ($) {
var pluses = /\+/g;
function encode(s) {
return config.raw ? s : encodeURIComponent(s);
}
function decode(s) {
return config.raw ? s : decodeURIComponent(s);
}
function stringifyCookieValue(value) {
return encode(config.json ? JSON.stringify(value) : String(value));
}
function parseCookieValue(s) {
if (s.indexOf('"') === 0) {
// This is a quoted cookie as according to RFC2068, unescape...
s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
}
try {
// Replace server-side written pluses with spaces.
// If we can't decode the cookie, ignore it, it's unusable.
// If we can't parse the cookie, ignore it, it's unusable.
s = decodeURIComponent(s.replace(pluses, ' '));
return config.json ? JSON.parse(s) : s;
} catch(e) {}
}
function read(s, converter) {
var value = config.raw ? s : parseCookieValue(s);
return $.isFunction(converter) ? converter(value) : value;
}
var config = $.cookie = function (key, value, options) {
// Write
if (arguments.length > 1 && !$.isFunction(value)) {
options = $.extend({}, config.defaults, options);
if (typeof options.expires === 'number') {
var days = options.expires, t = options.expires = new Date();
t.setMilliseconds(t.getMilliseconds() + days * 864e+5);
}
return (document.cookie = [
encode(key), '=', stringifyCookieValue(value),
options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
options.path ? '; path=' + options.path : '',
options.domain ? '; domain=' + options.domain : '',
options.secure ? '; secure' : ''
].join(''));
}
// Read
var result = key ? undefined : {},
// To prevent the for loop in the first place assign an empty array
// in case there are no cookies at all. Also prevents odd result when
// calling $.cookie().
cookies = document.cookie ? document.cookie.split('; ') : [],
i = 0,
l = cookies.length;
for (; i < l; i++) {
var parts = cookies[i].split('='),
name = decode(parts.shift()),
cookie = parts.join('=');
if (key === name) {
// If second argument (value) is a function it's a converter...
result = read(cookie, value);
break;
}
// Prevent storing a cookie that we couldn't decode.
if (!key && (cookie = read(cookie)) !== undefined) {
result[name] = cookie;
}
}
return result;
};
config.defaults = {};
$.removeCookie = function (key, options) {
// Must not alter options, thus extending a fresh object...
$.cookie(key, '', $.extend({}, options, { expires: -1 }));
return !$.cookie(key);
};
}));
View Code
index.css 页面简单渲染
*{margin: 0;padding: 0; }
.top{
background-color: rgb(83, 83, 236);
height: 52px;
}
.top-left{
width: 300px;height: 53px;
float: left;
text-align: center;line-height: 48px;
color: seashell;
}
.top-right{height: 53px;
float: right;
text-align: center;line-height: 48px;
color: seashell;
margin-right: 60px;
}
.left{background-color: whitesmoke;
position: absolute;left: 0;top: 48px;bottom: 0; z-index: 99;
width: 300px;
border-right:1px solid black;
z-index: 99;
overflow: auto;
}
.right{
background-color: whitesmoke;
position: absolute;left: 301px;top: 48px;bottom: 0;right: 0; z-index: 99;
overflow: scroll;
z-index: 99;
overflow: auto;
}
a:hover{
background-color: cornflowerblue;
}
.astyle{
display: block;padding: 10px;
}
.block{
position: absolute;top: 0;bottom: 0;right: 0;left: 0;
background-color: black ;opacity: 0.2;z-index: 100;
}
.currsor:hover{
cursor: pointer;
}
.hidden{
display: none;
}
.pitch{
background-color:black;color: white;
}
.unpitch{
background-color: white;color: black;
}
.page{
margin-left: 10px;
}
textarea{
width: 453px;
margin-top: 20px;
margin-left: 10px;
}
.select{
margin-top: 20px;
margin-left: 10px;
display: block;
}
.command{
margin-top: 20px;
margin-left: 10px;
display: block;
}
table.gridtable {
font-family: verdana,arial,sans-serif;
font-size:11px;
width: 100%;
color:#333333;
border-width: 1px;
border-color: #666666;
border-collapse: collapse;
}
table.gridtable th {
border-width: 1px;
padding: 8px;
border-style: solid;
border-color: #666666;
background-color: #dedede;
}
.change{
width: 70px;
}
table.gridtable td {
border-width: 1px;
padding: 8px;
border-style: solid;
border-color: #666666;
background-color: #ffffff;
}
models.py 定义数据库,在这里除了登录用不上
from django.db import models
Create your models here.
class login(models.Model):
username = models.CharField(max_length=64)
passwd = models.CharField(max_length=64)
def __str__(self):
return self.username
zbauth.py 定义zabbix-api的登录和一系列操作
import requests
class ZabbixOperates:
def __init__(self):
self.zabbix_url = 'https://ex.zabbix.com/api_jsonrpc.php'
self.user="user"
self.pwd="passwd"
self.verify_file,self.ssl_pem,self.ssl_key='/home/user.pem','/home/uer.pem','/home/user.key'
self.head={"Content-Type":"application/json"}
self.token = self.get_token()
def get_token(self):
data = {
"jsonrpc":"2.0",
"method":"user.login",
"params":{
"user":self.user,
"password":self.pwd
},
"id":1
}
res = requests.post(self.zabbix_url,headers=self.head,json=data,verify=self.verify_file,cert=(self.ssl_pem,self.ssl_key))
return res.json()['result']
def reuqest(self,data):
res = requests.post(self.zabbix_url,json=data,verify=self.verify_file,cert=(self.ssl_pem,self.ssl_key))
return(res.json())
def show(self,value,filter=None):
if 'error' in value:
return(value['error'])
def operate(self,data):
return self.reuqest(data)
def get_host(self,groupid=None):
data={
"jsonrpc": "2.0",
"method":"host.get",
"params": {
"groupids": groupid,
"output": [
"hostid",
"host",
"interfaceid",
],
"selectInterfaces": [
"interfaceid"
],
"filter":{"type":"1"}
},
"id":1,
"auth":self.token
}
return self.reuqest(data)
def get_group(self):
data={
"jsonrpc": "2.0",
"method": "hostgroup.get",
"params": {
"output": ["name"],
},
"auth": self.token,
"id": 1
}
return self.reuqest(data)
def get_item(self,hostid,key):
data = {
"jsonrpc": "2.0",
"method": "item.get",
"params": {
"output": [
'itemid',
'name',
'key_'
],
"hostids": hostid,
"search": {
"key_": key
},
"sortfield": "name"
},
"auth": self.token,
"id": 1
}
return self.reuqest(data)
def create_item(self,*value):
hostid,interfaceid,name,key,units=value
data={
"jsonrpc": "2.0",
"method": "item.create",
"params": {
"name": name,
"key_": key,
"hostid": hostid,
"type": 0,
"value_type": 0,
"interfaceid": interfaceid,
"delay": '20s',
'history': '90d',
'trends': '365d',
'units': units,
'lifetime': '30d',
},
"auth": self.token,
"id": 3
}
return self.reuqest(data)
def del_items(self,itemid):
data = {
"jsonrpc": "2.0",
"method": "item.delete",
"params": [
itemid
],
"auth": self.token,
"id": 1
}
return self.reuqest(data)
views.py 存放后端数据处理函数
from django.shortcuts import render,redirect,HttpResponse
from django.views.decorators.csrf import csrf_exempt
from DarkZabbix import models
from functools import wraps
from DarkZabbix.zbauth import ZabbixOperates
import json
Create your views here.
op = ZabbixOperates()
def auth(func):
@wraps(func)
def check_login(res,*args,**kwargs):
try:
res.session['name']
return func(res,*args,**kwargs)
except:
return render(res,'login.html')
return check_login
def deny_get(func):
@wraps(func)
def deny(res,*args,**kwatgs):
if res.method == 'GET':
return HttpResponse('已记录此次访问Ip地址')
else:
return func(res,*args,**kwatgs)
return deny
def login(res):
if res.method == 'GET':
return render(res,'login.html')
elif res.method == 'POST':
username = res.POST.get('username')
passwd = res.POST.get('passwd')
if models.login.objects.filter(username=username,passwd=passwd):
res.session.set_expiry(3600)
res.session['name']=username
return redirect('/zabbix.html')
else:
error = '用户名或密码错误'
return render(res,'login.html',{'error':error})
@auth
def zabbix(res):
groupli = op.get_group()['result']
return render(res,'zabbix.html',{'groupli':groupli})
@auth
@deny_get
def zabbix_host(res):
group_id = res.POST.get('id')
hostli = op.get_host(groupid=group_id)['result']
lab=''
for host in hostli:
lab+='%s'%(host['hostid'],host['interfaces'][0]['interfaceid'],host['host'])
return HttpResponse(lab)
@auth
@deny_get
def zabbix_items(res):
host_id,interface_id,hostname = res.POST.get('hostid'),res.POST.get('interfaceid'),res.POST.get('hostname')
lab='%s 添加itemnamekeyoperate'%(hostname,host_id,interface_id)
items = op.get_item(host_id,'ping')['result']
for item in items:
lab+='%s%s删除'%(item['itemid'],item['name'],item['key_'],item['itemid'])
lab+=''
return HttpResponse(lab)
@auth
@deny_get
def key_list(res):
import re
key_list=['ping_pkloss[*]','ping_restime[*]']
host_id = res.POST.get('hostid')
items = op.get_item(host_id,'ping')['result']
for item in items:
key_ = item['key_']
try:
host = re.findall('\[.*\]',key_)[0]
key_= key_.replace(host,'[*]')
except:
pass
if key_ not in key_list:
key_list.append(key_)
labli=['%s'%x for x in key_list]
lab = 'key: '+''.join(labli)+''
return HttpResponse(lab)
@auth
@deny_get
def add_items(res):
hostid,interfaceid,itemname,key_list = res.POST.get('hostid'),res.POST.get('interfaceid'),res.POST.get('data'),res.POST.get('key_')
key_list = json.loads(key_list)
if not key_list:
return HttpResponse('缺少必选项或格式错误')
items = itemname.split('\n')
for item in items:
name = item
item = item.strip()
_,host = item.split('-')
for key_ in key_list:
key_ = key_.replace('*',host)
type_ = 'restime' if 'restime' in key_ else 'pkloss'
unit = 'ms' if type_ =='restime' else '%'
ret = op.create_item(hostid,interfaceid,name+type_,key_,unit)
if op.show(ret):
return HttpResponse(json.dumps(op.show(ret)))
lab='操作成功'
return HttpResponse(lab)
@auth
@deny_get
def del_items(res):
itemid = res.POST.get('itemid')
ret = op.del_items(itemid)
if op.show(ret):
return HttpResponse(json.show(op.show(ret)))
lab='操作成功'
return HttpResponse(lab)
ending……
Original: https://www.cnblogs.com/darkchen/p/16295461.html
Author: 奔波的驱魔人
Title: 一个简陋的批量操作zabbix监控项页面
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/715271/
转载文章受原作者版权保护。转载请注明原作者出处!