2 Commits
v2.16 ... v2.18

Author SHA1 Message Date
RobbieHan
b58be33aac change_compare 2019-02-12 21:21:00 +08:00
RobbieHan
f1dde180fb device2connection 2019-02-12 16:37:24 +08:00
9 changed files with 241 additions and 11 deletions

View File

@@ -4,7 +4,7 @@
from django import forms
from .models import Code, DeviceInfo
from .models import Code, DeviceInfo, ConnectionInfo
class CodeCreateForm(forms.ModelForm):
@@ -72,4 +72,28 @@ class DeviceUpdateForm(DeviceCreateForm):
if self.instance:
matching_device = DeviceInfo.objects.exclude(pk=self.instance.pk)
if matching_device.filter(hostname=hostname).exists():
raise forms.ValidationError('设备地址:{}已存在'.format(hostname))
raise forms.ValidationError('设备地址:{}已存在'.format(hostname))
class ConnectionInfoForm(forms.ModelForm):
class Meta:
model = ConnectionInfo
fields = '__all__'
error_messages = {
'port': {'required': '端口不能为空'},
}
def clean(self):
cleaned_data = self.cleaned_data
username = cleaned_data.get('username')
password = cleaned_data.get('password')
private_key = cleaned_data.get('private_key')
auth_type = cleaned_data.get('auth_type')
if len(username) == 0:
raise forms.ValidationError('用户名不能为空!')
if auth_type == 'password' and len(password) == 0:
raise forms.ValidationError('认证类型为[密码]时,必须设置密码信息!')
if auth_type == 'private_key' and len(private_key) == 0:
raise forms.ValidationError('认证类型为[密钥]时,必须设置密钥信息!')

View File

@@ -20,7 +20,7 @@ class AbstractMode(models.Model):
class Code(AbstractMode):
key = models.CharField(max_length=80, verbose_name='')
value = models.CharField(max_length=80, verbose_name='')
desc = models.BooleanField(default=True, verbose_name='备注')
desc = models.CharField(max_length=100, blank=True, default='', verbose_name='备注')
class Meta:
verbose_name = '字典'

View File

@@ -1,13 +1,39 @@
import os
from django.dispatch import receiver
from django.db.models.signals import post_delete
from django.db.models.signals import post_delete, post_save
from .models import DeviceFile
from .models import DeviceFile, DeviceInfo
from utils.db_utils import MongodbDriver
@receiver(post_delete, sender=DeviceFile)
def auto_delete_file(sender, instance, **kwargs):
if instance.file_content:
if os.path.isfile(instance.file_content.path):
os.remove(instance.file_content.path)
os.remove(instance.file_content.path)
@receiver(post_save, sender=DeviceInfo)
def auto_compare_diff(sender, instance, **kwargs):
record = instance.history.latest()
prev_record = record.prev_record
ope_type = {'~': 'update', '+': 'create', '-': 'delete'}
compare_result = {
'id': record.id,
'changed_by': record.changed_by.name,
'history_type': ope_type[record.history_type],
'history_date': record.history_date
}
changes = {}
if prev_record is not None:
delta = record.diff_against(prev_record)
for change in delta.changes:
changes[change.field] = [change.old, change.new]
compare_result['changes'] = changes
if compare_result['changes'] or compare_result['history_type'] == 'create':
try:
mongo = MongodbDriver(collection='change_compare')
mongo.insert(compare_result)
except Exception as e:
pass

View File

@@ -32,5 +32,5 @@ urlpatterns = [
path('eam/device/update/', views_eam.DeviceUpdateView.as_view(), name='eam-device-update'),
path('eam/device/list/', views_eam.DeviceListView.as_view(), name='eam-device-list'),
path('eam/device/delete/', views_eam.DeviceDeleteView.as_view(), name='eam-device-delete'),
path('eam/device/device2connection/', views_eam.Device2ConnectionView.as_view(), name='eam-device-device2connection'),
]

View File

@@ -1,12 +1,16 @@
from django.views.generic import TemplateView
import re
from django.views.generic import TemplateView, View
from django.contrib.auth import get_user_model
from django.shortcuts import get_object_or_404
from django.http import JsonResponse
from django.shortcuts import render
from system.mixin import LoginRequiredMixin
from custom import (BreadcrumbMixin, SandboxDeleteView,
SandboxListView, SandboxUpdateView, SandboxCreateView)
from .models import Cabinet, DeviceInfo, Code
from .forms import DeviceCreateForm, DeviceUpdateForm
from .models import Cabinet, DeviceInfo, Code, ConnectionInfo
from .forms import DeviceCreateForm, DeviceUpdateForm, ConnectionInfoForm
User = get_user_model()
@@ -118,3 +122,39 @@ class DeviceUpdateView(SandboxUpdateView):
class DeviceDeleteView(SandboxDeleteView):
model = DeviceInfo
class Device2ConnectionView(LoginRequiredMixin, View):
def get(self, request):
ret = dict()
if 'id' in request.GET and request.GET['id']:
device = get_object_or_404(DeviceInfo, pk=int(request.GET['id']))
ret['device'] = device
dev_connection = device.dev_connection
if dev_connection:
connection_info = get_object_or_404(
ConnectionInfo, pk=int(dev_connection)
)
ret['connection_info'] = connection_info
return render(request, 'cmdb/deviceinfo2connection.html', ret)
def post(self, request):
res = dict(result=False)
con_info = ConnectionInfo()
if 'id' in request.POST and request.POST['id']:
con_info = get_object_or_404(ConnectionInfo, pk=request.POST['id'])
form = ConnectionInfoForm(request.POST, instance=con_info)
if form.is_valid():
instance = form.save()
con_id = getattr(instance, 'id')
device = get_object_or_404(DeviceInfo, hostname=request.POST['hostname'])
device.dev_connection = con_id
device.save()
res['result'] = True
else:
pattern = '<li>.*?<ul class=.*?><li>(.*?)</li>'
form_errors = str(form.errors)
errors = re.findall(pattern, form_errors)
res['error'] = errors[0]
return JsonResponse(res)

18
apps/utils/db_utils.py Normal file
View File

@@ -0,0 +1,18 @@
import pymongo
class MongodbDriver(object):
def __init__(self, db='device', collection='change_compare'):
self.client = pymongo.MongoClient('127.0.0.1', 27017)
self.db = self.client[db]
self.col = self.db[collection]
def insert(self, content):
return self.col.insert(content)
def find(self, sort_by, **filters,):
data = self.col.find(filters)
if sort_by:
data.sort(sort_by, pymongo.DESCENDING)
return data

View File

@@ -40,7 +40,7 @@
</div>
<label class="col-sm-2 control-label">描述信息</label>
<div class="col-sm-3">
<input class="form-control" id="desc" name="desc" type="text" />
<input class="form-control" id="desc" name="desc" type="text" value="{{ code.desc }}"/>
</div>
</div>

View File

@@ -325,5 +325,19 @@
oDataTable.ajax.reload();
});
function doDevice2Connection(id) {
layer.open({
type: 2,
title: '认证管理',
shadeClose: false,
maxmin: true,
area: ['800px', '400px'],
content: ["{% url 'cmdb:eam-device-device2connection' %}" + '?id=' + id, 'no'],
end: function () {
oDataTable.ajax.reload();
}
});
}
</script>
{% endblock %}

View File

@@ -0,0 +1,108 @@
{% extends 'base-layer.html' %}
{% load staticfiles %}
{% block css %}
<link rel="stylesheet" href="{% static 'plugins/select2/select2.min.css' %}">
<!-- iCheck for checkboxes and radio inputs -->
{% endblock %}
{% block main %}
<div class="box box-danger">
<form class="form-horizontal" id="addForm" method="post">
<input type="hidden" name='id' value="{{ connection_info.id }}" />
<input type="hidden" name='hostname' value="{{ device.hostname }}" />
{% csrf_token %}
<div class="box-body">
<fieldset>
<legend>
<h4>关联设备{{ device.sys_hostname }}({{ device.hostname }})</h4>
</legend>
<div class="form-group has-feedback">
<label class="col-sm-2 control-label">用户名</label>
<div class="col-sm-3">
<input class="form-control" name="username" type="text" value="{{ connection_info.username }}"/>
</div>
<label class="col-sm-2 control-label">认证类型</label>
<div class="col-sm-3">
<select class="form-control select2" style="width:100%;" name="auth_type">
<option value="password" {% ifequal connection_info.auth_type 'password' %}selected="selected"{% endifequal %}>密码</option>
<option value="private_key" {% ifequal connection_info.auth_type 'private_key' %}selected="selected"{% endifequal %}>密钥</option>
</select>
</div>
</div>
<div class="form-group has-feedback">
<label class="col-sm-2 control-label">密码</label>
<div class="col-sm-3">
<input class="form-control" name="password" type="password" value="{{ connection_info.password }}"/>
</div>
<label class="col-sm-2 control-label">密钥</label>
<div class="col-sm-3">
<input class="form-control" name="private_key" type="text" value="{{ connection_info.private_key }}"/>
</div>
</div>
<div class="form-group has-feedback">
<label class="col-sm-2 control-label">端口</label>
<div class="col-sm-3">
<input class="form-control" name="port" type="text" value="{{ connection_info.port }}"/>
</div>
<label class="col-sm-2 control-label">状态</label>
<div class="col-sm-3">
<input class="form-control" name="status" type="text" value="{{ connection_info.status }}" readonly/>
</div>
</div>
</fieldset>
</div>
<div class="box-footer ">
<div class="row span7 text-center ">
<button type="button" id="btnCancel" class="btn btn-default margin-right ">重置</button>
<button type="button" id="btnSave" class="btn btn-info margin-right ">保存</button>
</div>
</div>
</form>
</div>
{% endblock %}
{% block javascripts %}
<script src="{% static 'plugins/select2/select2.full.min.js' %}"></script>
<script type="text/javascript">
$("#btnSave").click(function () {
var data = $("#addForm").serialize();
$.ajax({
type: $("#addForm").attr('method'),
url: "{% url 'cmdb:eam-device-device2connection' %}",
data: data,
cache: false,
success: function (msg) {
if (msg.result) {
layer.alert('数据保存成功!', {icon: 1}, function (index) {
parent.layer.closeAll(); //关闭所有弹窗
});
} else {
layer.alert(msg.error, {icon: 5});
//$('errorMessage').html(msg.message)
}
return;
}
});
});
/*点取消刷新新页面*/
$("#btnCancel").click(function () {
window.location.reload();
});
$(function () {
//Initialize Select2 Elements
$(".select2").select2();
});
</script>
{% endblock %}