mirror of
https://github.com/RobbieHan/sandboxMP.git
synced 2026-02-12 23:24:57 +08:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a36f8d74f6 | ||
|
|
cea6fa7cba |
56
apps/cmdb/tasks.py
Normal file
56
apps/cmdb/tasks.py
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
import time
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from celery import shared_task
|
||||||
|
from celery_once import QueueOnce
|
||||||
|
|
||||||
|
from utils.sandbox_utils import SandboxScan, LoginExecution
|
||||||
|
from .models import DeviceScanInfo
|
||||||
|
|
||||||
|
info_logger = logging.getLogger('sandbox_info')
|
||||||
|
|
||||||
|
|
||||||
|
@shared_task(base=QueueOnce)
|
||||||
|
def scan_execution():
|
||||||
|
scan = SandboxScan()
|
||||||
|
execution = LoginExecution()
|
||||||
|
scan_type = execution.get_scan_type()
|
||||||
|
auth_type = execution.get_auth_type()
|
||||||
|
start_time = time.time()
|
||||||
|
if scan_type == 'basic_scan':
|
||||||
|
hosts = scan.basic_scan()
|
||||||
|
for host in hosts:
|
||||||
|
DeviceScanInfo.objects.update_or_create(
|
||||||
|
hostname=host,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
hosts = scan.os_scan()
|
||||||
|
login_hosts = [host for host in hosts if host['os'] in ['Linux', 'embedded']]
|
||||||
|
nologin_hosts = [host for host in hosts if host not in login_hosts]
|
||||||
|
for host in nologin_hosts:
|
||||||
|
DeviceScanInfo.objects.update_or_create(
|
||||||
|
hostname=host['host'],
|
||||||
|
defaults={
|
||||||
|
'os_type': host['os']
|
||||||
|
}
|
||||||
|
)
|
||||||
|
for host in login_hosts:
|
||||||
|
kwargs = {
|
||||||
|
'hostname': host['host'],
|
||||||
|
'username': execution.get_ssh_username(),
|
||||||
|
'port': execution.get_ssh_port(),
|
||||||
|
'password': execution.get_ssh_password(),
|
||||||
|
'private_key': execution.get_ssh_private_key()
|
||||||
|
}
|
||||||
|
defaults = execution.login_execution(auth_type=auth_type, **kwargs)
|
||||||
|
DeviceScanInfo.objects.update_or_create(
|
||||||
|
hostname=host['host'],
|
||||||
|
defaults=defaults
|
||||||
|
)
|
||||||
|
end_time = time.time()
|
||||||
|
msg = 'Scan task has been completed, execution time: %(time)s, %(num)s hosts are up.' % {
|
||||||
|
'time': end_time - start_time,
|
||||||
|
'num': len(hosts)
|
||||||
|
}
|
||||||
|
info_logger.info(msg)
|
||||||
|
return msg
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
from django.urls import path
|
from django.urls import path
|
||||||
|
|
||||||
from .views import CmdbView
|
from .views import CmdbView
|
||||||
from . import views_code, views_scan
|
from . import views_code, views_scan, views_eam
|
||||||
|
|
||||||
app_name = 'cmdb'
|
app_name = 'cmdb'
|
||||||
|
|
||||||
@@ -19,5 +19,12 @@ urlpatterns = [
|
|||||||
path('portal/device_scan/detail/', views_scan.DeviceScanDetailView.as_view(), name='portal-device_scan-detail'),
|
path('portal/device_scan/detail/', views_scan.DeviceScanDetailView.as_view(), name='portal-device_scan-detail'),
|
||||||
path('portal/device_scan/delete/', views_scan.DeviceScanDeleteView.as_view(), name='portal-device_scan-delete'),
|
path('portal/device_scan/delete/', views_scan.DeviceScanDeleteView.as_view(), name='portal-device_scan-delete'),
|
||||||
path('portal/device_scan/exec/', views_scan.DeviceScanExecView.as_view(), name='portal-device_scan-exec'),
|
path('portal/device_scan/exec/', views_scan.DeviceScanExecView.as_view(), name='portal-device_scan-exec'),
|
||||||
|
path('portal/device_scan/inbound/', views_scan.DeviceScanInboundView.as_view(), name='portal-device_scan-inbound'),
|
||||||
|
|
||||||
|
path('eam/cabinet/', views_eam.CabinetView.as_view(), name='eam-cabinet'),
|
||||||
|
path('eam/cabinet/create/', views_eam.CabinetCreateView.as_view(), name='eam-cabinet-create'),
|
||||||
|
path('eam/cabinet/update/', views_eam.CabinetUpdateView.as_view(), name='eam-cabinet-update'),
|
||||||
|
path('eam/cabinet/list/', views_eam.CabinetListView.as_view(), name='eam-cabinet-list'),
|
||||||
|
path('eam/cabinet/delete/', views_eam.CabinetDeleteView.as_view(), name='eam-cabinet-delete'),
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|||||||
38
apps/cmdb/views_eam.py
Normal file
38
apps/cmdb/views_eam.py
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
from django.views.generic import TemplateView
|
||||||
|
|
||||||
|
from system.mixin import LoginRequiredMixin
|
||||||
|
from custom import (BreadcrumbMixin, SandboxDeleteView,
|
||||||
|
SandboxListView, SandboxUpdateView, SandboxCreateView)
|
||||||
|
from .models import Cabinet
|
||||||
|
|
||||||
|
|
||||||
|
class CabinetView(LoginRequiredMixin, BreadcrumbMixin, TemplateView):
|
||||||
|
template_name = 'cmdb/cabinet.html'
|
||||||
|
|
||||||
|
|
||||||
|
class CabinetCreateView(SandboxCreateView):
|
||||||
|
model = Cabinet
|
||||||
|
fields = '__all__'
|
||||||
|
|
||||||
|
|
||||||
|
class CabinetUpdateView(SandboxUpdateView):
|
||||||
|
model = Cabinet
|
||||||
|
fields = '__all__'
|
||||||
|
|
||||||
|
|
||||||
|
class CabinetListView(SandboxListView):
|
||||||
|
model = Cabinet
|
||||||
|
fields = ['id', 'number', 'position', 'desc']
|
||||||
|
|
||||||
|
def get_filters(self):
|
||||||
|
data = self.request.GET
|
||||||
|
filters = {}
|
||||||
|
if 'number' in data and data['number']:
|
||||||
|
filters['number__icontains'] = data['number']
|
||||||
|
if 'position' in data and data['position']:
|
||||||
|
filters['position__icontains'] = data['position']
|
||||||
|
return filters
|
||||||
|
|
||||||
|
|
||||||
|
class CabinetDeleteView(SandboxDeleteView):
|
||||||
|
model = Cabinet
|
||||||
@@ -10,12 +10,15 @@ from django.views.generic import View, TemplateView
|
|||||||
from django.http import JsonResponse
|
from django.http import JsonResponse
|
||||||
from django.shortcuts import render, get_object_or_404
|
from django.shortcuts import render, get_object_or_404
|
||||||
|
|
||||||
|
from celery_once import AlreadyQueued
|
||||||
|
|
||||||
from system.mixin import LoginRequiredMixin
|
from system.mixin import LoginRequiredMixin
|
||||||
from custom import BreadcrumbMixin, SandboxListView, SandboxDeleteView
|
from custom import BreadcrumbMixin, SandboxListView, SandboxDeleteView
|
||||||
from utils.sandbox_utils import ConfigFileMixin
|
from utils.sandbox_utils import ConfigFileMixin
|
||||||
from system.models import Menu
|
from system.models import Menu
|
||||||
from .models import DeviceScanInfo
|
from .models import (DeviceScanInfo, ConnectionInfo, DeviceInfo,
|
||||||
|
ConnectionAbstract, DeviceAbstract)
|
||||||
|
from .tasks import scan_execution
|
||||||
|
|
||||||
error_logger = logging.getLogger('sandbox_error')
|
error_logger = logging.getLogger('sandbox_error')
|
||||||
|
|
||||||
@@ -81,50 +84,35 @@ class DeviceScanDeleteView(SandboxDeleteView):
|
|||||||
class DeviceScanExecView(LoginRequiredMixin, View):
|
class DeviceScanExecView(LoginRequiredMixin, View):
|
||||||
|
|
||||||
def get(self, request):
|
def get(self, request):
|
||||||
import time
|
ret = dict(status='fail')
|
||||||
from utils.sandbox_utils import SandboxScan, LoginExecution
|
try:
|
||||||
info_logger = logging.getLogger('sandbox_info')
|
scan_execution.delay()
|
||||||
|
ret['status'] = 'success'
|
||||||
|
except AlreadyQueued:
|
||||||
|
ret['status'] = 'already_queued'
|
||||||
|
return JsonResponse(ret)
|
||||||
|
|
||||||
|
|
||||||
|
class DeviceScanInboundView(LoginRequiredMixin, View):
|
||||||
|
def post(self, request):
|
||||||
ret = dict(result=False)
|
ret = dict(result=False)
|
||||||
scan = SandboxScan()
|
login_succeed = list(DeviceScanInfo.objects.filter(status='succeed').values())
|
||||||
execution = LoginExecution()
|
connection_fields = [field.name for field in ConnectionAbstract._meta.fields if field.name is not 'id']
|
||||||
scan_type = execution.get_scan_type()
|
device_fields = [field.name for field in DeviceAbstract._meta.fields if field.name is not 'id']
|
||||||
auth_type = execution.get_auth_type()
|
device_fields.append('hostname')
|
||||||
start_time = time.time()
|
for host in login_succeed:
|
||||||
if scan_type == 'basic_scan':
|
connection_defaults = {key: host[key] for key in host.keys() & connection_fields}
|
||||||
hosts = scan.basic_scan()
|
device_defaults = {key: host[key] for key in host.keys() & device_fields}
|
||||||
for host in hosts:
|
connection_info, _ = ConnectionInfo.objects.update_or_create(
|
||||||
DeviceScanInfo.objects.update_or_create(
|
hostname=host['hostname'],
|
||||||
hostname=host,
|
defaults=connection_defaults
|
||||||
)
|
)
|
||||||
else:
|
connection_id = int(getattr(connection_info, 'id'))
|
||||||
hosts = scan.os_scan()
|
device_defaults['dev_connection'] = connection_id
|
||||||
login_hosts = [host for host in hosts if host['os'] in ['Linux', 'embedded']]
|
device_defaults['changed_by_id'] = request.user.id
|
||||||
nologin_hosts = [host for host in hosts if host not in login_hosts]
|
DeviceInfo.objects.update_or_create(
|
||||||
for host in nologin_hosts:
|
hostname=host['hostname'],
|
||||||
DeviceScanInfo.objects.update_or_create(
|
defaults=device_defaults
|
||||||
hostname=host['host'],
|
)
|
||||||
defaults={
|
|
||||||
'os_type': host['os']
|
|
||||||
}
|
|
||||||
)
|
|
||||||
for host in login_hosts:
|
|
||||||
kwargs = {
|
|
||||||
'hostname': host['host'],
|
|
||||||
'username': execution.get_ssh_username(),
|
|
||||||
'port': execution.get_ssh_port(),
|
|
||||||
'password': execution.get_ssh_password(),
|
|
||||||
'private_key': execution.get_ssh_private_key()
|
|
||||||
}
|
|
||||||
defaults = execution.login_execution(auth_type=auth_type, **kwargs)
|
|
||||||
DeviceScanInfo.objects.update_or_create(
|
|
||||||
hostname=host['host'],
|
|
||||||
defaults=defaults
|
|
||||||
)
|
|
||||||
end_time = time.time()
|
|
||||||
msg = 'Scan task has been completed, execution time: %(time)s, %(num)s hosts are up.' % {
|
|
||||||
'time': end_time - start_time,
|
|
||||||
'num': len(hosts)
|
|
||||||
}
|
|
||||||
info_logger.info(msg)
|
|
||||||
ret['result'] = True
|
ret['result'] = True
|
||||||
return JsonResponse(ret)
|
return JsonResponse(ret)
|
||||||
|
|||||||
@@ -84,9 +84,9 @@ class SandboxMultipleObjectMixin:
|
|||||||
filters = self.get_filters()
|
filters = self.get_filters()
|
||||||
fields = self.get_fields()
|
fields = self.get_fields()
|
||||||
if filters:
|
if filters:
|
||||||
queryset = queryset.filter(**self.filters)
|
queryset = queryset.filter(**filters)
|
||||||
if fields:
|
if fields:
|
||||||
queryset = queryset.values(*self.fields)
|
queryset = queryset.values(*fields)
|
||||||
|
|
||||||
record_filter_count = queryset.count()
|
record_filter_count = queryset.count()
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
from __future__ import absolute_import, unicode_literals
|
||||||
|
|
||||||
|
from .celery import app as celery_app
|
||||||
|
|
||||||
|
__all__ = ('celery_app')
|
||||||
38
sandboxMP/celery.py
Normal file
38
sandboxMP/celery.py
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
from __future__ import absolute_import, unicode_literals
|
||||||
|
import os
|
||||||
|
from celery import Celery
|
||||||
|
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'sandboxMP.settings')
|
||||||
|
|
||||||
|
app = Celery('sandbox')
|
||||||
|
|
||||||
|
app.config_from_object('django.conf:settings')
|
||||||
|
|
||||||
|
app.autodiscover_tasks()
|
||||||
|
|
||||||
|
BROKER_URL = 'redis://localhost:6379/0'
|
||||||
|
|
||||||
|
CELERY_RESULT_BACKEND = 'redis://localhost:6379/1'
|
||||||
|
|
||||||
|
CELERY_TIMEZONE = 'Asia/Shanghai'
|
||||||
|
|
||||||
|
CELERY_ENABLE_UTC = False
|
||||||
|
|
||||||
|
CELERYD_FORCE_EXECV = True
|
||||||
|
|
||||||
|
CELERYD_CONCURRENCY = 5
|
||||||
|
|
||||||
|
CELERY_ACKS_LATE = True
|
||||||
|
|
||||||
|
CELERYD_MAX_TASKS_PER_CHILD = 100
|
||||||
|
|
||||||
|
CELERYD_TASK_TIME_LIMIT = 60 * 5
|
||||||
|
|
||||||
|
|
||||||
|
app.conf.ONCE = {
|
||||||
|
'backend': 'celery_once.backends.Redis',
|
||||||
|
'settings': {
|
||||||
|
'url': 'redis://localhost:6379/2',
|
||||||
|
'default_timeout': 60 * 5
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,6 +13,8 @@ https://docs.djangoproject.com/en/2.1/ref/settings/
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
from .celery import *
|
||||||
|
|
||||||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
|
||||||
|
|||||||
276
templates/cmdb/cabinet.html
Normal file
276
templates/cmdb/cabinet.html
Normal file
@@ -0,0 +1,276 @@
|
|||||||
|
{% extends "base-left.html" %}
|
||||||
|
{% load staticfiles %}
|
||||||
|
|
||||||
|
{% block css %}
|
||||||
|
<link rel="stylesheet" href="{% static 'plugins/datatables/jquery.dataTables.min.css' %}">
|
||||||
|
<link rel="stylesheet" href="{% static 'js/plugins/layer/skin/layer.css' %}">
|
||||||
|
<link rel="stylesheet" href="{% static 'plugins/select2/select2.min.css' %}">
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<!-- Main content -->
|
||||||
|
<section class="content">
|
||||||
|
<div id="devlist">
|
||||||
|
<div class="box box-primary" id="liebiao">
|
||||||
|
<div class="box-header">
|
||||||
|
<div class="btn-group pull-left">
|
||||||
|
<button type="button" id="btnRefresh" class="btn btn-default">
|
||||||
|
<i class="glyphicon glyphicon-repeat"></i>刷新
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="btn-group pull-left"> </div>
|
||||||
|
<div class="btn-group pull-left">
|
||||||
|
<button type="button" id="btnCreate" class="btn btn-default">
|
||||||
|
<i class="glyphicon glyphicon-plus"></i>新增
|
||||||
|
</button>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="btn-group pull-left"> </div>
|
||||||
|
<div class="btn-group pull-left">
|
||||||
|
<button type="button" id="btnDelete" class="btn btn-default">
|
||||||
|
<i class="glyphicon glyphicon-trash"></i>删除
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="pull-right">
|
||||||
|
<form class="form-inline" id="queryForm">
|
||||||
|
<div class="form-group searchArea margin-r-5 margin-top-5">
|
||||||
|
<label>机柜编号:</label>
|
||||||
|
<input type="text" name="number" class="form-control inputText" id="number">
|
||||||
|
</div>
|
||||||
|
<div class="form-group searchArea margin-r-5 margin-top-5">
|
||||||
|
<label>机柜位置:</label>
|
||||||
|
<input type="text" name="position" class="form-control inputText" id="position">
|
||||||
|
</div>
|
||||||
|
<button type="button" id="btnSearch" class="btn btn-default">
|
||||||
|
<i class="glyphicon glyphicon-search"></i>查询
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="box-body">
|
||||||
|
<table id="dtbList" class="display" cellspacing="0" width="100%">
|
||||||
|
<thead>
|
||||||
|
<tr valign="middle">
|
||||||
|
<th><input type="checkbox" id="checkAll"></th>
|
||||||
|
<th>ID</th>
|
||||||
|
<th>机柜编号</th>
|
||||||
|
<th>机柜位置</th>
|
||||||
|
<th>备注信息</th>
|
||||||
|
<th>操作</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<br> <br>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- /.content -->
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block javascripts %}
|
||||||
|
|
||||||
|
<script src="{% static 'plugins/datatables/jquery.dataTables.min.js' %}"></script>
|
||||||
|
<script src="{% static 'plugins/datatables/dataTables.const-1.js' %}"></script>
|
||||||
|
<script src="{% static 'js/plugins/layer/layer.js' %}"></script>
|
||||||
|
<script src="{% static 'plugins/select2/select2.full.min.js' %}"></script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
// 菜单选中高亮
|
||||||
|
$(function () {
|
||||||
|
$('#CMDB-EAM').addClass('active');
|
||||||
|
$('#CMDB-EAM-CABINET').addClass('active');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
// datatables 初始化配置
|
||||||
|
var oDataTable = null;
|
||||||
|
$(function () {
|
||||||
|
oDataTable = initTable();
|
||||||
|
|
||||||
|
function initTable() {
|
||||||
|
var oTable = $('#dtbList').DataTable($.extend(true, {},
|
||||||
|
DATATABLES_CONSTANT.DATA_TABLES.SERVER_SIDE_OPTION,
|
||||||
|
|
||||||
|
{
|
||||||
|
ajax: {
|
||||||
|
"url": "{% url 'cmdb:eam-cabinet-list' %}",
|
||||||
|
"data": function (d) {
|
||||||
|
d.number = $("#number").val();
|
||||||
|
d.position = $("#position").val();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
columns: [
|
||||||
|
DATATABLES_CONSTANT.DATA_TABLES.COLUMN.CHECKBOX,
|
||||||
|
{
|
||||||
|
data: "id",
|
||||||
|
width: "5%",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
data: "number",
|
||||||
|
//width : "20%",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
data: "position",
|
||||||
|
//width : "20%",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
data: "desc",
|
||||||
|
//width : "20%",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
data: "id",
|
||||||
|
width: "10%",
|
||||||
|
bSortable: "false",
|
||||||
|
render: function (data, type, row, meta) {
|
||||||
|
var ret = "";
|
||||||
|
var ret = "<button title='详情-修改' onclick='doUpdate("
|
||||||
|
+ data + ")'><i class='glyphicon glyphicon-pencil'></i></button>";
|
||||||
|
ret = ret + "<button title='删除' onclick='doDelete("
|
||||||
|
+ data + ")'><i class='glyphicon glyphicon-trash'></i></button>";
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
}));
|
||||||
|
return oTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
// 刷新数据
|
||||||
|
$("#btnRefresh").click(function () {
|
||||||
|
oDataTable.ajax.reload();
|
||||||
|
});
|
||||||
|
//新建数据
|
||||||
|
$("#btnCreate").click(function () {
|
||||||
|
layer.open({
|
||||||
|
type: 2,
|
||||||
|
title: '新增',
|
||||||
|
shadeClose: false,
|
||||||
|
maxmin: true,
|
||||||
|
area: ['800px', '400px'],
|
||||||
|
content: "{% url 'cmdb:eam-cabinet-create' %}",
|
||||||
|
end: function () {
|
||||||
|
//关闭时做的事情
|
||||||
|
oDataTable.ajax.reload();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
//修改数据
|
||||||
|
function doUpdate(id) {
|
||||||
|
layer.open({
|
||||||
|
type: 2,
|
||||||
|
title: '编辑',
|
||||||
|
shadeClose: false,
|
||||||
|
maxmin: true,
|
||||||
|
area: ['800px', '400px'],
|
||||||
|
content: ["{% url 'cmdb:eam-cabinet-update' %}" + '?id=' + id, 'no'],
|
||||||
|
end: function () {
|
||||||
|
oDataTable.ajax.reload();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//checkbox全选
|
||||||
|
$("#checkAll").on("click", function () {
|
||||||
|
if ($(this).prop("checked") === true) {
|
||||||
|
$("input[name='checkList']").prop("checked", $(this).prop("checked"));
|
||||||
|
$('#example tbody tr').addClass('selected');
|
||||||
|
} else {
|
||||||
|
$("input[name='checkList']").prop("checked", false);
|
||||||
|
$('#example tbody tr').removeClass('selected');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//批量删除
|
||||||
|
$("#btnDelete").click(function () {
|
||||||
|
if ($("input[name='checkList']:checked").length == 0) {
|
||||||
|
layer.msg("请选择要删除的记录");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var arrId = new Array();
|
||||||
|
$("input[name='checkList']:checked").each(function () {
|
||||||
|
//alert($(this).val());
|
||||||
|
arrId.push($(this).val());
|
||||||
|
});
|
||||||
|
|
||||||
|
sId = arrId.join(',');
|
||||||
|
|
||||||
|
layer.alert('确定删除吗?', {
|
||||||
|
title: '提示'
|
||||||
|
, icon: 3 //0:感叹号 1:对号 2:差号 3:问号 4:小锁 5:哭脸 6:笑脸
|
||||||
|
, time: 0 //不自动关闭
|
||||||
|
, btn: ['YES', 'NO']
|
||||||
|
, yes: function (index) {
|
||||||
|
layer.close(index);
|
||||||
|
$.ajax({
|
||||||
|
type: "POST",
|
||||||
|
url: "{% url 'cmdb:eam-cabinet-delete' %}",
|
||||||
|
data: {"id": sId, csrfmiddlewaretoken: '{{ csrf_token }}'},
|
||||||
|
cache: false,
|
||||||
|
success: function (msg) {
|
||||||
|
if (msg.result) {
|
||||||
|
layer.alert("操作成功", {icon: 1});
|
||||||
|
oDataTable.ajax.reload();
|
||||||
|
} else {
|
||||||
|
//alert(msg.message);
|
||||||
|
layer.alert("操作失败", {icon: 2});
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
//删除单个数据
|
||||||
|
function doDelete(id) {
|
||||||
|
layer.alert('确定删除吗?', {
|
||||||
|
title: '提示'
|
||||||
|
, icon: 3 //0:感叹号 1:对号 2:差号 3:问号 4:小锁 5:哭脸 6:笑脸
|
||||||
|
, time: 0 //不自动关闭
|
||||||
|
, btn: ['YES', 'NO']
|
||||||
|
, yes: function (index) {
|
||||||
|
layer.close(index);
|
||||||
|
$.ajax({
|
||||||
|
type: "POST",
|
||||||
|
url: "{% url 'cmdb:eam-cabinet-delete' %}",
|
||||||
|
data: {"id": id, csrfmiddlewaretoken: '{{ csrf_token }}'},
|
||||||
|
cache: false,
|
||||||
|
success: function (msg) {
|
||||||
|
if (msg.result) {
|
||||||
|
layer.alert('删除成功', {icon: 1});
|
||||||
|
oDataTable.ajax.reload();
|
||||||
|
} else {
|
||||||
|
//alert(msg.message);
|
||||||
|
layer.alert('删除失败', {icon: 2});
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//select2
|
||||||
|
$(function () {
|
||||||
|
//Initialize Select2 Elements
|
||||||
|
$(".select2").select2();
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#btnSearch").click(function(){
|
||||||
|
oDataTable.ajax.reload();
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
||||||
99
templates/cmdb/cabinet_form.html
Normal file
99
templates/cmdb/cabinet_form.html
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
{% 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="{{ cabinet.id }}" />
|
||||||
|
{% csrf_token %}
|
||||||
|
<div class="box-body">
|
||||||
|
<fieldset>
|
||||||
|
<legend>
|
||||||
|
<h4>机柜信息</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="number" type="text" value="{{ cabinet.number }}"/>
|
||||||
|
</div>
|
||||||
|
<label class="col-sm-2 control-label">机柜位置</label>
|
||||||
|
<div class="col-sm-3">
|
||||||
|
<input class="form-control" name="position" type="text" value="{{ cabinet.position }}"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group has-feedback">
|
||||||
|
<label class="col-sm-2 control-label">描述信息</label>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<input class="form-control" id="desc" name="desc" type="text" value="{{ cabinet.desc }}"/>
|
||||||
|
</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">
|
||||||
|
|
||||||
|
function getUrl() {
|
||||||
|
if ($("input[name='id']").val()) {
|
||||||
|
var url = "{% url 'cmdb:eam-cabinet-update' %}";
|
||||||
|
} else {
|
||||||
|
var url = "{% url 'cmdb:eam-cabinet-create' %}";
|
||||||
|
}
|
||||||
|
return url
|
||||||
|
}
|
||||||
|
|
||||||
|
$("#btnSave").click(function () {
|
||||||
|
var data = $("#addForm").serialize();
|
||||||
|
$.ajax({
|
||||||
|
type: $("#addForm").attr('method'),
|
||||||
|
url: getUrl(),
|
||||||
|
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 %}
|
||||||
@@ -279,8 +279,12 @@
|
|||||||
},
|
},
|
||||||
success: function (msg) {
|
success: function (msg) {
|
||||||
layer.closeAll('loading');
|
layer.closeAll('loading');
|
||||||
if (msg.result) {
|
if (msg.status == 'success') {
|
||||||
layer.alert('扫描已完成', {icon: 1});
|
layer.alert('扫描任务已下发', {icon: 1});
|
||||||
|
oDataTable.ajax.reload();
|
||||||
|
}
|
||||||
|
else if (msg.status == 'already_queued') {
|
||||||
|
layer.alert('当前已有扫描任务正在执行', {icon: 4});
|
||||||
oDataTable.ajax.reload();
|
oDataTable.ajax.reload();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -294,5 +298,32 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function doInbound() {
|
||||||
|
layer.alert('确定将扫描结果导入设备管理库吗?', {
|
||||||
|
title: '提示'
|
||||||
|
, icon: 3
|
||||||
|
, time: 0
|
||||||
|
, btn: ['YES', 'NO']
|
||||||
|
, yes: function (index) {
|
||||||
|
layer.close(index);
|
||||||
|
$.ajax({
|
||||||
|
type: "POST",
|
||||||
|
url: "{% url 'cmdb:portal-device_scan-inbound' %}",
|
||||||
|
data: {csrfmiddlewaretoken: '{{ csrf_token }}'},
|
||||||
|
cache: false,
|
||||||
|
success: function (msg) {
|
||||||
|
if (msg.result) {
|
||||||
|
layer.alert('设备已入库', {icon: 1});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//alert(msg.message);
|
||||||
|
layer.alert('设备入库失败', {icon: 2});
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
Reference in New Issue
Block a user