mirror of
https://github.com/RobbieHan/sandboxMP.git
synced 2026-02-10 22:24:56 +08:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9d0bd95b69 | ||
|
|
4fbdc88743 |
@@ -1,6 +1,11 @@
|
|||||||
from django.db import models
|
import os
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
# Create your models here.
|
from django.db import models
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
|
from django.dispatch import receiver
|
||||||
|
|
||||||
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
class AbstractMode(models.Model):
|
class AbstractMode(models.Model):
|
||||||
@@ -20,3 +25,94 @@ class Code(AbstractMode):
|
|||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = '字典'
|
verbose_name = '字典'
|
||||||
verbose_name_plural = verbose_name
|
verbose_name_plural = verbose_name
|
||||||
|
|
||||||
|
|
||||||
|
class TimeAbstract(models.Model):
|
||||||
|
add_time = models.DateTimeField(auto_now_add=True, verbose_name="添加时间")
|
||||||
|
modify_time = models.DateTimeField(auto_now=True, verbose_name="更新时间")
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
abstract = True
|
||||||
|
|
||||||
|
|
||||||
|
class ConnectionAbstract(models.Model):
|
||||||
|
auth_method_choices = (
|
||||||
|
('private_key', '密钥认证'),
|
||||||
|
('password', '密码认证')
|
||||||
|
)
|
||||||
|
hostname = models.CharField(max_length=50, verbose_name='设备地址(IP或域名)')
|
||||||
|
port = models.IntegerField(default=22, verbose_name='SSH端口')
|
||||||
|
username = models.CharField(max_length=15, blank=True, default='', verbose_name='SSH用户名')
|
||||||
|
password = models.CharField(max_length=80, blank=True, default='', verbose_name='SSH密码')
|
||||||
|
private_key = models.CharField(max_length=100, blank=True, default='', verbose_name='密钥路径')
|
||||||
|
auth_type = models.CharField(max_length=30, choices=auth_method_choices, default='')
|
||||||
|
status = models.CharField(max_length=10, blank=True, default='')
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
abstract = True
|
||||||
|
|
||||||
|
|
||||||
|
class DeviceAbstract(models.Model):
|
||||||
|
sys_hostname = models.CharField(max_length=50, blank=True, default='', verbose_name='主机名')
|
||||||
|
mac_address = models.CharField(max_length=50, blank=True, default='', verbose_name='MAC地址')
|
||||||
|
sn_number = models.CharField(max_length=50, blank=True, default='', verbose_name='SN号码')
|
||||||
|
os_type = models.CharField(max_length=50, blank=True, default='', verbose_name='系统类型')
|
||||||
|
device_type = models.CharField(max_length=50, blank=True, default='', verbose_name='设备类型')
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
abstract = True
|
||||||
|
|
||||||
|
|
||||||
|
class DeviceScanInfo(ConnectionAbstract, DeviceAbstract, TimeAbstract):
|
||||||
|
error_message = models.CharField(max_length=80, blank=True, default='', verbose_name='错误信息')
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = '扫描信息'
|
||||||
|
verbose_name_plural = verbose_name
|
||||||
|
|
||||||
|
|
||||||
|
class ConnectionInfo(ConnectionAbstract, TimeAbstract):
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = 'SSH连接信息'
|
||||||
|
verbose_name_plural = verbose_name
|
||||||
|
|
||||||
|
|
||||||
|
class Cabinet(models.Model):
|
||||||
|
number = models.CharField(max_length=50, verbose_name='机柜编号')
|
||||||
|
position = models.CharField(max_length=80, verbose_name='机柜位置')
|
||||||
|
desc = models.TextField(blank=True, default='', verbose_name='备注信息')
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = '机柜信息'
|
||||||
|
verbose_name_plural = verbose_name
|
||||||
|
|
||||||
|
|
||||||
|
class DeviceInfo(AbstractMode, DeviceAbstract, TimeAbstract):
|
||||||
|
hostname = models.CharField(max_length=50, verbose_name='设备地址(IP或域名)')
|
||||||
|
network_type = models.IntegerField(blank=True, null=True, verbose_name='网络类型')
|
||||||
|
service_type = models.IntegerField(blank=True, null=True, verbose_name='服务类型')
|
||||||
|
operation_type = models.IntegerField(blank=True, null=True, verbose_name='业务类型')
|
||||||
|
leader = models.IntegerField(blank=True, null=True, verbose_name='责任人')
|
||||||
|
dev_cabinet = models.IntegerField(blank=True, null=True, verbose_name='机柜信息')
|
||||||
|
dev_connection = models.IntegerField(blank=True, null=True, verbose_name='连接信息')
|
||||||
|
buyDate = models.DateField(default=datetime.now, verbose_name="购买日期")
|
||||||
|
warrantyDate = models.DateField(default=datetime.now, verbose_name="到保日期")
|
||||||
|
desc = models.TextField(blank=True, default='', verbose_name='备注信息')
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = '设备信息'
|
||||||
|
verbose_name_plural = verbose_name
|
||||||
|
|
||||||
|
|
||||||
|
class DeviceFile(TimeAbstract):
|
||||||
|
device = models.ForeignKey('DeviceInfo', blank=True, null=True, on_delete=models.SET_NULL, verbose_name='设备')
|
||||||
|
file_content = models.FileField(upload_to="asset_file/%Y/%m", null=True, blank=True, verbose_name="资产文件")
|
||||||
|
upload_user = models.CharField(max_length=20, verbose_name="上传人")
|
||||||
|
|
||||||
|
|
||||||
|
@receiver(models.signals.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)
|
||||||
|
|||||||
@@ -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
|
from . import views_code, views_scan
|
||||||
|
|
||||||
app_name = 'cmdb'
|
app_name = 'cmdb'
|
||||||
|
|
||||||
@@ -12,4 +12,6 @@ urlpatterns = [
|
|||||||
path('portal/code/list/', views_code.CodeListView.as_view(), name='portal-code-list'),
|
path('portal/code/list/', views_code.CodeListView.as_view(), name='portal-code-list'),
|
||||||
path('portal/code/update/', views_code.CodeUpdateView.as_view(), name='portal-code-update'),
|
path('portal/code/update/', views_code.CodeUpdateView.as_view(), name='portal-code-update'),
|
||||||
path('portal/code/delete/', views_code.CodeDeleteView.as_view(), name='portal-code-delete'),
|
path('portal/code/delete/', views_code.CodeDeleteView.as_view(), name='portal-code-delete'),
|
||||||
|
|
||||||
|
path('portal/scan_config/', views_scan.ScanConfigView.as_view(), name='portal-scan_config'),
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ class CodeView(LoginRequiredMixin, BreadcrumbMixin, TemplateView):
|
|||||||
template_name = 'cmdb/code.html'
|
template_name = 'cmdb/code.html'
|
||||||
|
|
||||||
def get_context_data(self):
|
def get_context_data(self):
|
||||||
context = dict(code_parent=Code.objects.filter(parent=None))
|
self.kwargs['code_parent'] = Code.objects.filter(parent=None)
|
||||||
return context
|
return super().get_context_data(**self.kwargs)
|
||||||
|
|
||||||
|
|
||||||
class CodeCreateView(SandboxCreateView):
|
class CodeCreateView(SandboxCreateView):
|
||||||
|
|||||||
54
apps/cmdb/views_scan.py
Normal file
54
apps/cmdb/views_scan.py
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
# @Time : 2018/12/29 19:25
|
||||||
|
# @Author : RobbieHan
|
||||||
|
# @File : views_scan.py
|
||||||
|
|
||||||
|
import ast
|
||||||
|
import logging
|
||||||
|
from ruamel import yaml
|
||||||
|
|
||||||
|
from django.views.generic import View
|
||||||
|
from django.http import JsonResponse
|
||||||
|
from django.shortcuts import render
|
||||||
|
|
||||||
|
|
||||||
|
from system.mixin import LoginRequiredMixin
|
||||||
|
from custom import BreadcrumbMixin
|
||||||
|
from utils.sandbox_utils import ConfigFileMixin
|
||||||
|
from system.models import Menu
|
||||||
|
|
||||||
|
error_logger = logging.getLogger('sandbox_error')
|
||||||
|
|
||||||
|
|
||||||
|
class ScanConfigView(LoginRequiredMixin, BreadcrumbMixin, ConfigFileMixin, View):
|
||||||
|
|
||||||
|
def get(self, request):
|
||||||
|
menu = Menu.get_menu_by_request_url(request.path_info)
|
||||||
|
template_name = 'cmdb/scan_config.html'
|
||||||
|
context = self.get_conf_content()
|
||||||
|
context.update(menu)
|
||||||
|
return render(request, template_name, context)
|
||||||
|
|
||||||
|
def post(self, request):
|
||||||
|
ret = dict(result=False)
|
||||||
|
config = dict()
|
||||||
|
hosts = request.POST
|
||||||
|
try:
|
||||||
|
config['net_address'] = ast.literal_eval(hosts['net_address'])
|
||||||
|
config['ssh_username'] = hosts['ssh_username']
|
||||||
|
config['ssh_port'] = hosts['ssh_port']
|
||||||
|
config['ssh_password'] = hosts['ssh_password']
|
||||||
|
config['ssh_private_key'] = hosts['ssh_private_key']
|
||||||
|
config['commands'] = ast.literal_eval(hosts['commands'])
|
||||||
|
config['auth_type'] = hosts['auth_type']
|
||||||
|
config['scan_type'] = hosts['scan_type']
|
||||||
|
config['email'] = hosts['email']
|
||||||
|
config['send_email'] = hosts['send_email']
|
||||||
|
data = dict(hosts=config)
|
||||||
|
config_file = self.get_config_file()
|
||||||
|
with open(config_file, 'w', encoding='utf-8') as f:
|
||||||
|
yaml.dump(data, f, Dumper=yaml.RoundTripDumper, indent=4)
|
||||||
|
ret['result'] = True
|
||||||
|
except Exception as e:
|
||||||
|
error_logger.error(e)
|
||||||
|
|
||||||
|
return JsonResponse(ret)
|
||||||
3
apps/utils/__init__.py
Normal file
3
apps/utils/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# @Time : 2018/12/29 16:26
|
||||||
|
# @Author : RobbieHan
|
||||||
|
# @File : __init__.py.py
|
||||||
74
apps/utils/sandbox_utils.py
Normal file
74
apps/utils/sandbox_utils.py
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
# @Time : 2018/12/29 19:22
|
||||||
|
# @Author : RobbieHan
|
||||||
|
# @File : sandbox_utils.py
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
|
import yaml
|
||||||
|
import logging
|
||||||
|
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'sandboxMP.settings')
|
||||||
|
error_logger = logging.getLogger('sandbox_error')
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigFileMixin:
|
||||||
|
config_file = None
|
||||||
|
|
||||||
|
def get_config_file(self):
|
||||||
|
"""
|
||||||
|
Return 'config_file' that will be used to look up the scan hosts IP,
|
||||||
|
network, range of IP, or other config settings.
|
||||||
|
This method is called by the default implementation of get_hosts(),
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.config_file is None:
|
||||||
|
config_file = os.path.join(os.path.join(settings.BASE_DIR, 'config'), 'scanhosts.yml')
|
||||||
|
if os.path.exists(config_file):
|
||||||
|
return config_file
|
||||||
|
else:
|
||||||
|
msg = ' %(cls)s is missing a config file. Define %(cls)s.config_file, ' \
|
||||||
|
'or override %(cls)s.get_config_file().' % {'cls': self.__class__.__name__}
|
||||||
|
error_logger.error(msg)
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
|
return self.config_file
|
||||||
|
|
||||||
|
def get_conf_content(self, *key):
|
||||||
|
"""
|
||||||
|
Get the configuration content from config file .
|
||||||
|
Example ssh_password, commands, email which is in the config file.
|
||||||
|
"""
|
||||||
|
_config = self.get_config_file()
|
||||||
|
with open(_config) as f:
|
||||||
|
content = yaml.load(f)
|
||||||
|
if key is not None:
|
||||||
|
try:
|
||||||
|
num = 0
|
||||||
|
while num < len(key):
|
||||||
|
content = content[key[num]]
|
||||||
|
num += 1
|
||||||
|
except Exception as e:
|
||||||
|
msg = '%(exc)s is not in %(config)s.' % {
|
||||||
|
'exc': e,
|
||||||
|
'config': _config
|
||||||
|
}
|
||||||
|
error_logger.error(msg)
|
||||||
|
raise ValueError(msg)
|
||||||
|
return content
|
||||||
|
|
||||||
|
def get_commands(self):
|
||||||
|
"""
|
||||||
|
Get the commands from config file.
|
||||||
|
"""
|
||||||
|
key = ['hosts', 'commands']
|
||||||
|
return self.get_conf_content(*key)
|
||||||
|
|
||||||
|
def get_net_address(self):
|
||||||
|
"""
|
||||||
|
Return the hosts that will be used to scan.
|
||||||
|
Subclasses can override this to return any hosts.
|
||||||
|
"""
|
||||||
|
key = ['hosts', 'net_address']
|
||||||
|
return self.get_conf_content(*key)
|
||||||
18
config/scanhosts.yml
Normal file
18
config/scanhosts.yml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
hosts:
|
||||||
|
net_address:
|
||||||
|
- '172.16.3.0/24'
|
||||||
|
- '172.16.2.100-105'
|
||||||
|
ssh_username: 'root'
|
||||||
|
ssh_port: '22'
|
||||||
|
ssh_password: '1234@abcd.com'
|
||||||
|
ssh_private_key: '/root/.ssh/id_rsa'
|
||||||
|
commands:
|
||||||
|
sys_hostname: 'hostname'
|
||||||
|
mac_address: 'cat /sys/class/net/[^tsbvl]*/address'
|
||||||
|
sn_number: 'dmidecode -s system-serial-number'
|
||||||
|
os_type: 'cat /etc/redhat-release'
|
||||||
|
device_type: 'echo `dmidecode -s system-manufacturer && dmidecode -s system-product-name`'
|
||||||
|
email: 'robbie_han@outlook.com'
|
||||||
|
send_email: 'false'
|
||||||
|
scan_type: 'basic_scan'
|
||||||
|
auth_type: 'private_key'
|
||||||
176
templates/cmdb/scan_config.html
Normal file
176
templates/cmdb/scan_config.html
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
{% extends "base-left.html" %}
|
||||||
|
{% load staticfiles %}
|
||||||
|
|
||||||
|
{% block css %}
|
||||||
|
<link rel="stylesheet" href="{% static 'js/plugins/layer/skin/layer.css' %}">
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<!-- Main content -->
|
||||||
|
<section class="content">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-8">
|
||||||
|
<!-- Horizontal Form -->
|
||||||
|
<div class="box box-default">
|
||||||
|
<div class="box-header with-border">
|
||||||
|
<h3 class="box-title">扫面参数配置</h3>
|
||||||
|
</div>
|
||||||
|
<!-- /.box-header -->
|
||||||
|
<!-- form start -->
|
||||||
|
<form class="form-horizontal" id="addForm" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
<div class="box-body">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-2 control-label">扫描网段</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<input class="form-control" id="net_address" name="net_address" value="{{ hosts.net_address }}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-2 control-label">登陆用户</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<input class="form-control" id="ssh_username" name="ssh_username" value="{{ hosts.ssh_username }}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-2 control-label">SSH端口</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<input class="form-control" id="ssh_port" name="ssh_port" value="{{ hosts.ssh_port }}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-2 control-label">登陆密码</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<input class="form-control" type="password" id="ssh_password" name="ssh_password" value="{{ hosts.ssh_password }}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-2 control-label">密钥路径</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<input class="form-control" id="ssh_private_key" name="ssh_private_key" value="{{ hosts.ssh_private_key }}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-2 control-label">运行命令</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<textarea class="form-control" rows="5" id="commands" name="commands" readonly>{{ hosts.commands }}</textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-2 control-label">认证方式</label>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<select class="form-control" name="auth_type">
|
||||||
|
<option value="password" {% ifequal hosts.auth_type 'password' %}selected="selected"{% endifequal %}>密码认证</option>
|
||||||
|
<option value="private_key" {% ifequal hosts.auth_type 'private_key' %}selected="selected"{% endifequal %}>私钥认证</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<label class="col-sm-2 control-label">扫描方式</label>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<select class="form-control" name="scan_type">
|
||||||
|
<option value="basic_scan" {% ifequal hosts.scan_type 'basic_scan' %}selected="selected"{% endifequal %}>基础扫描</option>
|
||||||
|
<option value="enhanced_scan" {% ifequal hosts.scan_type 'enhanced_scan' %}selected="selected"{% endifequal %}>加强扫描</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-2 control-label">收件邮箱</label>
|
||||||
|
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<input class="form-control" id="email" name="email" value="{{ hosts.email }}">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="form-group has-feedback">
|
||||||
|
<label class="col-sm-2 control-label">发送邮件</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<label class="control-label">
|
||||||
|
<input type="radio" class="minimal" name="send_email" value="true" {% ifequal hosts.send_email 'true' %}checked{% endifequal %}>是
|
||||||
|
</label>
|
||||||
|
<label class="control-label">
|
||||||
|
<input type="radio" class="minimal" name="send_email" value="false" {% ifequal hosts.send_email 'false' %}checked{% endifequal %}>否
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- /.box-body -->
|
||||||
|
<div class="box-footer">
|
||||||
|
<span class="pull-right">
|
||||||
|
<button type="button" id="btnCancel" class="btn btn-default">取消</button>
|
||||||
|
<button type="button" id="btnSave" class="btn btn-info">保存</button>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<!-- /.box-footer -->
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<div class="box box-default">
|
||||||
|
<div class="box-header with-border">
|
||||||
|
<h3 class="box-title">参数配置说明</h3>
|
||||||
|
</div><!-- /.box-header -->
|
||||||
|
<div class="box-body">
|
||||||
|
<a class="product-title"><strong>扫描网段</strong><span class="label label-danger pull-right">必填参数</span></a>
|
||||||
|
<p><small>网络扫描地址列表,列表中可以包含一个或多个网段,也可以是一个或多个地址区间,例如['192.168.100.0/24', '192.168.100.10-20']</small></p>
|
||||||
|
<a class="product-title"><strong>登陆用户</strong><span class="label label-danger pull-right">必填参数</span></a>
|
||||||
|
<p><small>系统登陆测试使用的用户名,默认root。</small></p>
|
||||||
|
<a class="product-title"><strong>登陆密码</strong><span class="label label-danger pull-right">可选参数</span></a>
|
||||||
|
<p><small>系统登陆测试使用的密码,如过认证方式为密码认证,必须填写密码信息。</small></p>
|
||||||
|
<a class="product-title"><strong>密钥路径</strong><span class="label label-primary pull-right">可选参数</span></a>
|
||||||
|
<p><small>系统登陆测试使用的密钥存放路径,如过认证方式为私钥认证,必须填写密钥路径。</small></p>
|
||||||
|
<a class="product-title"><strong>运行命令</strong><span class="label label-default pull-right">预定义参数</span></a>
|
||||||
|
<p><small>登陆系统后运行的基本命令,用来获取系统基本信息,当扫描方式为加强扫描时,才会执行运行命令,运行命令为预定义,禁止修改。</small></p>
|
||||||
|
<a class="product-title"><strong>认证方式</strong><span class="label label-primary pull-right">可选参数</span></a>
|
||||||
|
<p><small>系统登陆认证方式,包括密码认证和私钥认证两种方式,当扫描方式为加强扫描时,需要设定认证方式。</small></p>
|
||||||
|
<a class="product-title"><strong>扫描方式</strong><span class="label label-primary pull-right">可选参数</span></a>
|
||||||
|
<p><small>系统扫描方式,包括基本扫描和加强扫描,当设置为加强扫描时会登陆系统执行运行命令获取系统信息。</small></p>
|
||||||
|
<a class="product-title"><strong>收件邮箱</strong><span class="label label-primary pull-right">可选参数</span></a>
|
||||||
|
<p><small>用于接收扫描结果邮件,可以通过发送邮件选项设置是否发送通知邮件。</small></p>
|
||||||
|
</div><!-- /.box-body -->
|
||||||
|
</div><!-- /.box -->
|
||||||
|
</div>
|
||||||
|
<!-- /.box -->
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- /.content -->
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block javascripts %}
|
||||||
|
<script src="{% static 'js/plugins/layer/layer.js' %}"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
// 菜单选中高亮
|
||||||
|
$(function () {
|
||||||
|
$('#CMDB-PORTAL').addClass('active');
|
||||||
|
$('#CMDB-PORTAL-SCAN_CONFIG').addClass('active');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#btnSave").click(function () {
|
||||||
|
var hosts = $("#addForm").serialize();
|
||||||
|
$.ajax({
|
||||||
|
type: $("#addForm").attr('method'),
|
||||||
|
url: "{% url 'cmdb:portal-scan_config' %}",
|
||||||
|
cache: false,
|
||||||
|
data: hosts,
|
||||||
|
success: function (msg) {
|
||||||
|
if (msg.result) {
|
||||||
|
layer.alert('数据保存成功!', {icon: 1});
|
||||||
|
} else {
|
||||||
|
layer.alert('数据保存失败', {icon: 5});
|
||||||
|
//$('errorMessage').html(msg.message)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/*点取消刷新新页面*/
|
||||||
|
$("#btnCancel").click(function () {
|
||||||
|
window.location.reload();
|
||||||
|
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
||||||
Reference in New Issue
Block a user