mirror of
https://github.com/RobbieHan/sandboxMP.git
synced 2026-02-11 22:54:55 +08:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b58be33aac | ||
|
|
f1dde180fb |
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
|
|
||||||
from .models import Code, DeviceInfo
|
from .models import Code, DeviceInfo, ConnectionInfo
|
||||||
|
|
||||||
|
|
||||||
class CodeCreateForm(forms.ModelForm):
|
class CodeCreateForm(forms.ModelForm):
|
||||||
@@ -72,4 +72,28 @@ class DeviceUpdateForm(DeviceCreateForm):
|
|||||||
if self.instance:
|
if self.instance:
|
||||||
matching_device = DeviceInfo.objects.exclude(pk=self.instance.pk)
|
matching_device = DeviceInfo.objects.exclude(pk=self.instance.pk)
|
||||||
if matching_device.filter(hostname=hostname).exists():
|
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('认证类型为[密钥]时,必须设置密钥信息!')
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ class AbstractMode(models.Model):
|
|||||||
class Code(AbstractMode):
|
class Code(AbstractMode):
|
||||||
key = models.CharField(max_length=80, verbose_name='键')
|
key = models.CharField(max_length=80, verbose_name='键')
|
||||||
value = 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:
|
class Meta:
|
||||||
verbose_name = '字典'
|
verbose_name = '字典'
|
||||||
|
|||||||
@@ -1,13 +1,39 @@
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
from django.dispatch import receiver
|
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)
|
@receiver(post_delete, sender=DeviceFile)
|
||||||
def auto_delete_file(sender, instance, **kwargs):
|
def auto_delete_file(sender, instance, **kwargs):
|
||||||
if instance.file_content:
|
if instance.file_content:
|
||||||
if os.path.isfile(instance.file_content.path):
|
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
|
||||||
|
|||||||
@@ -32,5 +32,5 @@ urlpatterns = [
|
|||||||
path('eam/device/update/', views_eam.DeviceUpdateView.as_view(), name='eam-device-update'),
|
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/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/delete/', views_eam.DeviceDeleteView.as_view(), name='eam-device-delete'),
|
||||||
|
path('eam/device/device2connection/', views_eam.Device2ConnectionView.as_view(), name='eam-device-device2connection'),
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -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.contrib.auth import get_user_model
|
||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
|
from django.http import JsonResponse
|
||||||
|
from django.shortcuts import render
|
||||||
|
|
||||||
from system.mixin import LoginRequiredMixin
|
from system.mixin import LoginRequiredMixin
|
||||||
from custom import (BreadcrumbMixin, SandboxDeleteView,
|
from custom import (BreadcrumbMixin, SandboxDeleteView,
|
||||||
SandboxListView, SandboxUpdateView, SandboxCreateView)
|
SandboxListView, SandboxUpdateView, SandboxCreateView)
|
||||||
from .models import Cabinet, DeviceInfo, Code
|
from .models import Cabinet, DeviceInfo, Code, ConnectionInfo
|
||||||
from .forms import DeviceCreateForm, DeviceUpdateForm
|
from .forms import DeviceCreateForm, DeviceUpdateForm, ConnectionInfoForm
|
||||||
|
|
||||||
User = get_user_model()
|
User = get_user_model()
|
||||||
|
|
||||||
@@ -118,3 +122,39 @@ class DeviceUpdateView(SandboxUpdateView):
|
|||||||
|
|
||||||
class DeviceDeleteView(SandboxDeleteView):
|
class DeviceDeleteView(SandboxDeleteView):
|
||||||
model = DeviceInfo
|
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
18
apps/utils/db_utils.py
Normal 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
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<label class="col-sm-2 control-label">描述信息</label>
|
<label class="col-sm-2 control-label">描述信息</label>
|
||||||
<div class="col-sm-3">
|
<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>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -325,5 +325,19 @@
|
|||||||
oDataTable.ajax.reload();
|
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>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
108
templates/cmdb/deviceinfo2connection.html
Normal file
108
templates/cmdb/deviceinfo2connection.html
Normal 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 %}
|
||||||
Reference in New Issue
Block a user