mirror of https://github.com/jumpserver/jumpserver
merge with cmdb
commit
3b07198b8a
|
@ -37,6 +37,7 @@ nosetests.xml
|
|||
.mr.developer.cfg
|
||||
.project
|
||||
.pydevproject
|
||||
*.xlsx
|
||||
node_modules
|
||||
logs
|
||||
keys
|
||||
|
|
|
@ -0,0 +1,459 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from ansible.inventory.group import Group
|
||||
from ansible.inventory.host import Host
|
||||
from ansible.inventory import Inventory
|
||||
from ansible.runner import Runner
|
||||
from ansible.playbook import PlayBook
|
||||
|
||||
from ansible import callbacks
|
||||
from ansible import utils
|
||||
from passlib.hash import sha512_crypt
|
||||
|
||||
# from utils import get_rand_pass
|
||||
|
||||
import random
|
||||
import os.path
|
||||
API_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
ANSIBLE_DIR = os.path.join(API_DIR, 'playbooks')
|
||||
|
||||
def get_rand_pass():
|
||||
"""
|
||||
get a reandom password.
|
||||
"""
|
||||
lower = [chr(i) for i in range(97,123)]
|
||||
upper = [chr(i).upper() for i in range(97,123)]
|
||||
digit = [str(i) for i in range(10)]
|
||||
password_pool = []
|
||||
password_pool.extend(lower)
|
||||
password_pool.extend(upper)
|
||||
password_pool.extend(digit)
|
||||
pass_list = [random.choice(password_pool) for i in range(1,14)]
|
||||
pass_list.insert(random.choice(range(1,14)), '@')
|
||||
pass_list.insert(random.choice(range(1,14)), random.choice(digit))
|
||||
password = ''.join(pass_list)
|
||||
return password
|
||||
|
||||
class AnsibleError(StandardError):
|
||||
"""
|
||||
the base AnsibleError which contains error(required),
|
||||
data(optional) and message(optional).
|
||||
存储所有Ansible 异常对象
|
||||
"""
|
||||
def __init__(self, error, data='', message=''):
|
||||
super(AnsibleError, self).__init__(message)
|
||||
self.error = error
|
||||
self.data = data
|
||||
self.message = message
|
||||
|
||||
|
||||
class CommandValueError(AnsibleError):
|
||||
"""
|
||||
indicate the input value has error or invalid.
|
||||
the data specifies the error field of input form.
|
||||
输入不合法 异常对象
|
||||
"""
|
||||
def __init__(self, field, message=''):
|
||||
super(CommandValueError, self).__init__('value:invalid', field, message)
|
||||
|
||||
|
||||
class MyInventory(object):
|
||||
"""
|
||||
this is my ansible inventory object.
|
||||
"""
|
||||
def __init__(self, resource):
|
||||
"""
|
||||
resource的数据格式是一个列表字典,比如
|
||||
{
|
||||
"group1": {
|
||||
"hosts": [{"hostname": "10.10.10.10", "port": "22", "username": "test", "password": "mypass"}, ...],
|
||||
"vars": {"var1": value1, "var2": value2, ...}
|
||||
}
|
||||
}
|
||||
|
||||
如果你只传入1个列表,这默认该列表内的所有主机属于my_group组,比如
|
||||
[{"hostname": "10.10.10.10", "port": "22", "username": "test", "password": "mypass"}, ...]
|
||||
"""
|
||||
self.resource = resource
|
||||
self.inventory = Inventory()
|
||||
self.gen_inventory()
|
||||
|
||||
def add_group(self, hosts, groupname, groupvars=None):
|
||||
"""
|
||||
add hosts to a group
|
||||
"""
|
||||
my_group = Group(name=groupname)
|
||||
|
||||
# if group variables exists, add them to group
|
||||
if groupvars:
|
||||
for key, value in groupvars.iteritems():
|
||||
my_group.set_variable(key, value)
|
||||
|
||||
# add hosts to group
|
||||
for host in hosts:
|
||||
# set connection variables
|
||||
hostname = host.get("hostname")
|
||||
hostport = host.get("port")
|
||||
username = host.get("username")
|
||||
password = host.get("password")
|
||||
my_host = Host(name=hostname, port=hostport)
|
||||
my_host.set_variable('ansible_ssh_host', hostname)
|
||||
my_host.set_variable('ansible_ssh_port', hostport)
|
||||
my_host.set_variable('ansible_ssh_user', username)
|
||||
my_host.set_variable('ansible_ssh_pass', password)
|
||||
# set other variables
|
||||
for key, value in host.iteritems():
|
||||
if key not in ["hostname", "port", "username", "password"]:
|
||||
my_host.set_variable(key, value)
|
||||
# add to group
|
||||
my_group.add_host(my_host)
|
||||
|
||||
self.inventory.add_group(my_group)
|
||||
|
||||
def gen_inventory(self):
|
||||
"""
|
||||
add hosts to inventory.
|
||||
"""
|
||||
if isinstance(self.resource, list):
|
||||
self.add_group(self.resource, 'my_group')
|
||||
elif isinstance(self.resource, dict):
|
||||
for groupname, hosts_and_vars in self.resource.iteritems():
|
||||
self.add_group(hosts_and_vars.get("hosts"), groupname, hosts_and_vars.get("vars"))
|
||||
|
||||
|
||||
class Command(MyInventory):
|
||||
"""
|
||||
this is a command object for parallel execute command.
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(Command, self).__init__(*args, **kwargs)
|
||||
self.results = ''
|
||||
|
||||
def run(self, command, module_name="command", timeout=5, forks=10, group='my_group'):
|
||||
"""
|
||||
run command from andible ad-hoc.
|
||||
command : 必须是一个需要执行的命令字符串, 比如
|
||||
'uname -a'
|
||||
"""
|
||||
if module_name not in ["raw", "command", "shell"]:
|
||||
raise CommandValueError("module_name",
|
||||
"module_name must be of the 'raw, command, shell'")
|
||||
hoc = Runner(module_name=module_name,
|
||||
module_args=command,
|
||||
timeout=timeout,
|
||||
inventory=self.inventory,
|
||||
subset=group,
|
||||
forks=forks
|
||||
)
|
||||
self.results = hoc.run()
|
||||
|
||||
if self.stdout:
|
||||
return {"ok": self.stdout}
|
||||
else:
|
||||
msg = []
|
||||
if self.stderr:
|
||||
msg.append(self.stderr)
|
||||
if self.dark:
|
||||
msg.append(self.dark)
|
||||
return {"failed": msg}
|
||||
|
||||
@property
|
||||
def raw_results(self):
|
||||
"""
|
||||
get the ansible raw results.
|
||||
"""
|
||||
return self.results
|
||||
|
||||
@property
|
||||
def exec_time(self):
|
||||
"""
|
||||
get the command execute time.
|
||||
"""
|
||||
result = {}
|
||||
all = self.results.get("contacted")
|
||||
for key, value in all.iteritems():
|
||||
result[key] = {
|
||||
"start": value.get("start"),
|
||||
"end" : value.get("end"),
|
||||
"delta": value.get("delta"),}
|
||||
return result
|
||||
|
||||
@property
|
||||
def stdout(self):
|
||||
"""
|
||||
get the comamnd standard output.
|
||||
"""
|
||||
result = {}
|
||||
all = self.results.get("contacted")
|
||||
for key, value in all.iteritems():
|
||||
result[key] = value.get("stdout")
|
||||
return result
|
||||
|
||||
@property
|
||||
def stderr(self):
|
||||
"""
|
||||
get the command standard error.
|
||||
"""
|
||||
result = {}
|
||||
all = self.results.get("contacted")
|
||||
for key, value in all.iteritems():
|
||||
result[key] = {
|
||||
"stderr": value.get("stderr"),
|
||||
"warnings": value.get("warnings"),}
|
||||
return result
|
||||
|
||||
@property
|
||||
def dark(self):
|
||||
"""
|
||||
get the dark results.
|
||||
"""
|
||||
return self.results.get("dark")
|
||||
|
||||
|
||||
class Tasks(Command):
|
||||
"""
|
||||
this is a tasks object for include the common command.
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(Tasks, self).__init__(*args, **kwargs)
|
||||
|
||||
def __run(self, module_args, module_name="command", timeout=5, forks=10, group='my_group'):
|
||||
"""
|
||||
run command from andible ad-hoc.
|
||||
command : 必须是一个需要执行的命令字符串, 比如
|
||||
'uname -a'
|
||||
"""
|
||||
hoc = Runner(module_name=module_name,
|
||||
module_args=module_args,
|
||||
timeout=timeout,
|
||||
inventory=self.inventory,
|
||||
subset=group,
|
||||
forks=forks
|
||||
)
|
||||
|
||||
self.results = hoc.run()
|
||||
|
||||
@property
|
||||
def msg(self):
|
||||
"""
|
||||
get the contacted and dark msg
|
||||
"""
|
||||
msg = {}
|
||||
for result in ["contacted", "dark"]:
|
||||
all = self.results.get(result)
|
||||
for key, value in all.iteritems():
|
||||
if value.get("msg"):
|
||||
msg[key] = value.get("msg")
|
||||
return msg
|
||||
|
||||
def push_key(self, user, key_path):
|
||||
"""
|
||||
push the ssh authorized key to target.
|
||||
"""
|
||||
module_args = 'user="%s" key="{{ lookup("file", "%s") }}"' % (user, key_path)
|
||||
self.__run(module_args, "authorized_key")
|
||||
|
||||
return {"status": "failed","msg": self.msg} if self.msg else {"status": "ok"}
|
||||
|
||||
def del_key(self, user, key_path):
|
||||
"""
|
||||
push the ssh authorized key to target.
|
||||
"""
|
||||
module_args = 'user="%s" key="{{ lookup("file", "%s") }}" state="absent"' % (user, key_path)
|
||||
self.__run(module_args, "authorized_key")
|
||||
|
||||
return {"status": "failed","msg": self.msg} if self.msg else {"status": "ok"}
|
||||
|
||||
def add_user(self, username, password):
|
||||
"""
|
||||
add a host user.
|
||||
"""
|
||||
encrypt_pass = sha512_crypt.encrypt(password)
|
||||
module_args = 'name=%s shell=/bin/bash password=%s' % (username, encrypt_pass)
|
||||
self.__run(module_args, "user")
|
||||
|
||||
return {"status": "failed","msg": self.msg} if self.msg else {"status": "ok"}
|
||||
|
||||
def add_multi_user(self, *args):
|
||||
"""
|
||||
add multi user
|
||||
:param args:
|
||||
user
|
||||
:return:
|
||||
"""
|
||||
results = {}
|
||||
users = {}
|
||||
action = results["action_info"] = {}
|
||||
for user in args:
|
||||
users[user] = get_rand_pass()
|
||||
for user, password in users.iteritems():
|
||||
ret = self.add_user(user, password)
|
||||
action[user] = ret
|
||||
results["user_info"] = users
|
||||
|
||||
return results
|
||||
|
||||
def del_user(self, username):
|
||||
"""
|
||||
delete a host user.
|
||||
"""
|
||||
module_args = 'name=%s state=absent remove=yes move_home=yes force=yes' % (username)
|
||||
self.__run(module_args, "user")
|
||||
|
||||
return {"status": "failed","msg": self.msg} if self.msg else {"status": "ok"}
|
||||
|
||||
def add_init_users(self):
|
||||
"""
|
||||
add initail users: SA, DBA, DEV
|
||||
"""
|
||||
results = {}
|
||||
action = results["action_info"] = {}
|
||||
users = {"SA": get_rand_pass(), "DBA": get_rand_pass(), "DEV": get_rand_pass()}
|
||||
for user, password in users.iteritems():
|
||||
ret = self.add_user(user, password)
|
||||
action[user] = ret
|
||||
results["user_info"] = users
|
||||
|
||||
return results
|
||||
|
||||
def del_init_users(self):
|
||||
"""
|
||||
delete initail users: SA, DBA, DEV
|
||||
"""
|
||||
results = {}
|
||||
action = results["action_info"] = {}
|
||||
for user in ["SA", "DBA", "DEV"]:
|
||||
ret = self.del_user(user)
|
||||
action[user] = ret
|
||||
return results
|
||||
|
||||
def get_host_info(self):
|
||||
"""
|
||||
use the setup module get host informations
|
||||
:return:
|
||||
all_ip is list
|
||||
processor_count is int
|
||||
system_dist_version is string
|
||||
system_type is string
|
||||
disk is dict (device_name: device_size}
|
||||
system_dist is string
|
||||
processor_type is string
|
||||
default_ip is string
|
||||
hostname is string
|
||||
product_sn is string
|
||||
memory_total is int (MB)
|
||||
default_mac is string
|
||||
product_name is string
|
||||
"""
|
||||
self.__run('', 'setup')
|
||||
|
||||
result = {}
|
||||
all = self.results.get("contacted")
|
||||
for key, value in all.iteritems():
|
||||
setup =value.get("ansible_facts")
|
||||
# get disk informations
|
||||
disk_all = setup.get("ansible_devices")
|
||||
disk_need = {}
|
||||
for disk_name, disk_info in disk_all.iteritems():
|
||||
if disk_name.startswith('sd') or disk_name.startswith('hd') or disk_name.startswith('vd'):
|
||||
disk_need[disk_name] = disk_info.get("size")
|
||||
|
||||
result[key] = {
|
||||
"other_ip": setup.get("ansible_all_ipv4_addresses"),
|
||||
"hostname": setup.get("ansible_hostname" ),
|
||||
"ip": setup.get("ansible_default_ipv4").get("address"),
|
||||
"mac": setup.get("ansible_default_ipv4").get("macaddress"),
|
||||
"brand": setup.get("ansible_product_name"),
|
||||
"cpu_type": setup.get("ansible_processor"),
|
||||
"cpu_cores": setup.get("ansible_processor_count"),
|
||||
"memory": setup.get("ansible_memtotal_mb"),
|
||||
"disk": disk_need,
|
||||
"system_type": setup.get("ansible_distribution"),
|
||||
"system_version": setup.get("ansible_distribution_version"),
|
||||
"asset_type": setup.get("ansible_system"),
|
||||
"sn": setup.get("ansible_product_serial")
|
||||
}
|
||||
|
||||
return {"status": "failed", "msg": self.msg} if self.msg else {"status": "ok", "result": result}
|
||||
|
||||
|
||||
class CustomAggregateStats(callbacks.AggregateStats):
|
||||
"""
|
||||
Holds stats about per-host activity during playbook runs.
|
||||
"""
|
||||
def __init__(self):
|
||||
super(CustomAggregateStats, self).__init__()
|
||||
self.results = []
|
||||
|
||||
def compute(self, runner_results, setup=False, poll=False,
|
||||
ignore_errors=False):
|
||||
"""
|
||||
Walk through all results and increment stats.
|
||||
"""
|
||||
super(CustomAggregateStats, self).compute(runner_results, setup, poll,
|
||||
ignore_errors)
|
||||
|
||||
self.results.append(runner_results)
|
||||
|
||||
|
||||
def summarize(self, host):
|
||||
"""
|
||||
Return information about a particular host
|
||||
"""
|
||||
summarized_info = super(CustomAggregateStats, self).summarize(host)
|
||||
|
||||
# Adding the info I need
|
||||
summarized_info['result'] = self.results
|
||||
|
||||
return summarized_info
|
||||
|
||||
|
||||
class MyPlaybook(MyInventory):
|
||||
"""
|
||||
this is my playbook object for execute playbook.
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(MyPlaybook, self).__init__(*args, **kwargs)
|
||||
|
||||
|
||||
def run(self, playbook_relational_path, extra_vars=None):
|
||||
"""
|
||||
run ansible playbook,
|
||||
only surport relational path.
|
||||
"""
|
||||
stats = callbacks.AggregateStats()
|
||||
playbook_cb = callbacks.PlaybookCallbacks(verbose=utils.VERBOSITY)
|
||||
runner_cb = callbacks.PlaybookRunnerCallbacks(stats, verbose=utils.VERBOSITY)
|
||||
playbook_path = os.path.join(ANSIBLE_DIR, playbook_relational_path)
|
||||
|
||||
pb = PlayBook(
|
||||
playbook = playbook_path,
|
||||
stats = stats,
|
||||
callbacks = playbook_cb,
|
||||
runner_callbacks = runner_cb,
|
||||
inventory = self.inventory,
|
||||
extra_vars = extra_vars,
|
||||
check=False)
|
||||
|
||||
self.results = pb.run()
|
||||
|
||||
@property
|
||||
def raw_results(self):
|
||||
"""
|
||||
get the raw results after playbook run.
|
||||
"""
|
||||
return self.results
|
||||
|
||||
|
||||
class App(MyPlaybook):
|
||||
"""
|
||||
this is a app object for inclue the common playbook.
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(App, self).__init__(*args, **kwargs)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pass
|
||||
|
||||
|
|
@ -1,5 +1,9 @@
|
|||
# coding: utf-8
|
||||
import xlrd
|
||||
import xlsxwriter
|
||||
from django.db.models import AutoField
|
||||
from jumpserver.api import *
|
||||
from jasset.models import ASSET_STATUS, ASSET_TYPE, ASSET_ENV, IDC, AssetRecord
|
||||
|
||||
|
||||
def group_add_asset(group, asset_id=None, asset_ip=None):
|
||||
|
@ -32,6 +36,21 @@ def db_add_group(**kwargs):
|
|||
group_add_asset(group, asset_id)
|
||||
|
||||
|
||||
def db_update_group(**kwargs):
|
||||
"""
|
||||
add a asset group in database
|
||||
数据库中更新资产
|
||||
"""
|
||||
group_id = kwargs.pop('id')
|
||||
asset_id_list = kwargs.pop('asset_select')
|
||||
group = get_object(AssetGroup, id=group_id)
|
||||
|
||||
for asset_id in asset_id_list:
|
||||
group_add_asset(group, asset_id)
|
||||
|
||||
AssetGroup.objects.filter(id=group_id).update(**kwargs)
|
||||
|
||||
|
||||
def db_asset_add(**kwargs):
|
||||
"""
|
||||
add asset to db
|
||||
|
@ -80,11 +99,12 @@ def db_asset_update(**kwargs):
|
|||
asset_id = kwargs.pop('id')
|
||||
Asset.objects.filter(id=asset_id).update(**kwargs)
|
||||
|
||||
|
||||
#
|
||||
#
|
||||
# def batch_host_edit(host_info, j_user='', j_password=''):
|
||||
# def batch_host_edit(host_alter_dic, j_user='', j_password=''):
|
||||
# """ 批量修改主机函数 """
|
||||
# j_id, j_ip, j_idc, j_port, j_type, j_group, j_dept, j_active, j_comment = host_info
|
||||
# j_id, j_ip, j_idc, j_port, j_type, j_group, j_dept, j_active, j_comment = host_alter_dic
|
||||
# groups, depts = [], []
|
||||
# is_active = {u'是': '1', u'否': '2'}
|
||||
# login_types = {'LDAP': 'L', 'MAP': 'M'}
|
||||
|
@ -156,3 +176,230 @@ def db_asset_update(**kwargs):
|
|||
# else:
|
||||
# return httperror(request, '删除失败, 没有这个IDC!')
|
||||
|
||||
|
||||
def sort_ip_list(ip_list):
|
||||
""" ip地址排序 """
|
||||
ip_list.sort(key=lambda s: map(int, s.split('.')))
|
||||
return ip_list
|
||||
|
||||
|
||||
def get_tuple_name(asset_tuple, value):
|
||||
""""""
|
||||
for t in asset_tuple:
|
||||
if t[0] == value:
|
||||
return t[1]
|
||||
|
||||
return ''
|
||||
|
||||
|
||||
def get_tuple_diff(asset_tuple, field_name, value):
|
||||
""""""
|
||||
old_name = get_tuple_name(asset_tuple, int(value[0])) if value[0] else u''
|
||||
new_name = get_tuple_name(asset_tuple, int(value[1])) if value[1] else u''
|
||||
alert_info = [field_name, old_name, new_name]
|
||||
return alert_info
|
||||
|
||||
|
||||
def asset_diff(before, after):
|
||||
"""
|
||||
asset change before and after
|
||||
"""
|
||||
alter_dic = {}
|
||||
before_dic, after_dic = before, dict(after.iterlists())
|
||||
for k, v in before_dic.items():
|
||||
after_dic_values = after_dic.get(k, [])
|
||||
if k == 'group':
|
||||
after_dic_value = after_dic_values if len(after_dic_values) > 0 else u''
|
||||
uv = v if v is not None else u''
|
||||
else:
|
||||
after_dic_value = after_dic_values[0] if len(after_dic_values) > 0 else u''
|
||||
uv = unicode(v) if v is not None else u''
|
||||
if uv != after_dic_value:
|
||||
alter_dic.update({k: [uv, after_dic_value]})
|
||||
|
||||
for k, v in alter_dic.items():
|
||||
if v == [None, u'']:
|
||||
alter_dic.pop(k)
|
||||
|
||||
return alter_dic
|
||||
|
||||
|
||||
def asset_diff_one(before, after):
|
||||
print before.__dict__, after.__dict__
|
||||
fields = Asset._meta.get_all_field_names()
|
||||
for field in fields:
|
||||
print before.field, after.field
|
||||
|
||||
|
||||
def db_asset_alert(asset, username, alert_dic):
|
||||
"""
|
||||
asset alert info to db
|
||||
"""
|
||||
alert_list = []
|
||||
asset_tuple_dic = {'status': ASSET_STATUS, 'env': ASSET_ENV, 'asset_type': ASSET_TYPE}
|
||||
for field, value in alert_dic.iteritems():
|
||||
print field
|
||||
field_name = Asset._meta.get_field_by_name(field)[0].verbose_name
|
||||
if field == 'idc':
|
||||
old = IDC.objects.filter(id=value[0]) if value[0] else u''
|
||||
new = IDC.objects.filter(id=value[1]) if value[1] else u''
|
||||
old_name = old[0].name if old else u''
|
||||
new_name = new[0].name if new else u''
|
||||
alert_info = [field_name, old_name, new_name]
|
||||
|
||||
elif field in ['status', 'env', 'asset_type']:
|
||||
alert_info = get_tuple_diff(asset_tuple_dic.get(field), field_name, value)
|
||||
|
||||
elif field == 'group':
|
||||
old, new = [], []
|
||||
for group_id in value[0]:
|
||||
group_name = AssetGroup.objects.get(id=int(group_id)).name
|
||||
old.append(group_name)
|
||||
for group_id in value[1]:
|
||||
group_name = AssetGroup.objects.get(id=int(group_id)).name
|
||||
new.append(group_name)
|
||||
if old == new:
|
||||
continue
|
||||
else:
|
||||
alert_info = [field_name, ','.join(old), ','.join(new)]
|
||||
|
||||
elif field == 'use_default_auth':
|
||||
if unicode(value[0]) == 'True' and unicode(value[1]) == 'on' or \
|
||||
unicode(value[0]) == 'False' and unicode(value[1]) == '':
|
||||
continue
|
||||
else:
|
||||
name = asset.username
|
||||
alert_info = [field_name, u'默认', name] if unicode(value[0]) == 'True' else \
|
||||
[field_name, name, u'默认']
|
||||
|
||||
elif field in ['username', 'password']:
|
||||
continue
|
||||
|
||||
elif field == 'is_active':
|
||||
if unicode(value[0]) == 'True' and unicode(value[1]) == '1' or \
|
||||
unicode(value[0]) == 'False' and unicode(value[1]) == '0':
|
||||
continue
|
||||
else:
|
||||
alert_info = [u'是否激活', u'激活', u'禁用'] if unicode(value[0]) == 'True' else \
|
||||
[u'是否激活', u'禁用', u'激活']
|
||||
|
||||
else:
|
||||
alert_info = [field_name, unicode(value[0]), unicode(value[1])]
|
||||
|
||||
if 'alert_info' in dir():
|
||||
alert_list.append(alert_info)
|
||||
|
||||
if alert_list:
|
||||
AssetRecord.objects.create(asset=asset, username=username, content=alert_list)
|
||||
|
||||
|
||||
def write_excel(asset_all):
|
||||
data = []
|
||||
now = datetime.datetime.now().strftime('%Y_%m_%d_%H_%M')
|
||||
file_name = 'cmdb_excel_' + now + '.xlsx'
|
||||
workbook = xlsxwriter.Workbook('static/files/excels/%s' % file_name)
|
||||
worksheet = workbook.add_worksheet(u'CMDB数据')
|
||||
worksheet.set_first_sheet()
|
||||
worksheet.set_column('A:Z', 14)
|
||||
title = [u'主机名', u'IP', u'IDC', u'MAC', u'远控IP', u'CPU', u'内存', u'硬盘', u'操作系统', u'机柜位置',
|
||||
u'所属主机组', u'机器状态', u'备注']
|
||||
for asset in asset_all:
|
||||
group_list = []
|
||||
for p in asset.group.all():
|
||||
group_list.append(p.name)
|
||||
|
||||
group_all = '/'.join(group_list)
|
||||
status = asset.get_status_display()
|
||||
idc_name = asset.idc.name if asset.idc else u''
|
||||
alter_dic = [asset.hostname, asset.ip, idc_name, asset.mac, asset.remote_ip, asset.cpu, asset.memory,
|
||||
asset.disk, (asset.system_type + asset.system_version), asset.cabinet, group_all, status,
|
||||
asset.comment]
|
||||
data.append(alter_dic)
|
||||
format = workbook.add_format()
|
||||
format.set_border(1)
|
||||
format.set_align('center')
|
||||
|
||||
format_title = workbook.add_format()
|
||||
format_title.set_border(1)
|
||||
format_title.set_bg_color('#cccccc')
|
||||
format_title.set_align('center')
|
||||
format_title.set_bold()
|
||||
|
||||
format_ave = workbook.add_format()
|
||||
format_ave.set_border(1)
|
||||
format_ave.set_num_format('0.00')
|
||||
|
||||
worksheet.write_row('A1', title, format_title)
|
||||
i = 2
|
||||
for alter_dic in data:
|
||||
location = 'A' + str(i)
|
||||
worksheet.write_row(location, alter_dic, format)
|
||||
i += 1
|
||||
|
||||
workbook.close()
|
||||
ret = (True, file_name)
|
||||
return ret
|
||||
|
||||
|
||||
def copy_model_instance(obj):
|
||||
initial = dict([(f.name, getattr(obj, f.name))
|
||||
for f in obj._meta.fields
|
||||
if not isinstance(f, AutoField) and \
|
||||
not f in obj._meta.parents.values()])
|
||||
return obj.__class__(**initial)
|
||||
|
||||
|
||||
def ansible_record(asset, ansible_dic, username):
|
||||
alert_dic = {}
|
||||
asset_dic = asset.__dict__
|
||||
for field, value in ansible_dic.items():
|
||||
old = asset_dic.get(field)
|
||||
new = ansible_dic.get(field)
|
||||
if unicode(old) != unicode(new):
|
||||
print old, new, type(old), type(new)
|
||||
setattr(asset, field, value)
|
||||
asset.save()
|
||||
alert_dic[field] = [old, new]
|
||||
|
||||
db_asset_alert(asset, username, alert_dic)
|
||||
|
||||
|
||||
def excel_to_db(excel_file):
|
||||
"""
|
||||
Asset add batch function
|
||||
"""
|
||||
try:
|
||||
data = xlrd.open_workbook(filename=None, file_contents=excel_file.read())
|
||||
except Exception, e:
|
||||
return False
|
||||
|
||||
else:
|
||||
table = data.sheets()[0]
|
||||
rows = table.nrows
|
||||
group_instance = []
|
||||
for row_num in range(1, rows):
|
||||
row = table.row_values(row_num)
|
||||
if row:
|
||||
ip, port, hostname, use_default_auth, username, password, group = row
|
||||
print ip
|
||||
use_default_auth = 1 if use_default_auth == u'默认' else 0
|
||||
if get_object(Asset, ip=ip):
|
||||
continue
|
||||
if ip and port:
|
||||
asset = Asset(ip=ip,
|
||||
port=port,
|
||||
use_default_auth=use_default_auth,
|
||||
username=username,
|
||||
password=password
|
||||
)
|
||||
asset.save()
|
||||
group_list = group.split('/')
|
||||
for group_name in group_list:
|
||||
group = get_object(AssetGroup, name=group_name)
|
||||
if group:
|
||||
group_instance.append(group)
|
||||
if group_instance:
|
||||
print group_instance
|
||||
asset.group = group_instance
|
||||
asset.save()
|
||||
return True
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
# coding:utf-8
|
||||
from django import forms
|
||||
|
||||
from jasset.models import IDC, Asset, AssetGroup
|
||||
|
||||
|
||||
class AssetForm(forms.ModelForm):
|
||||
|
||||
class Meta:
|
||||
model = Asset
|
||||
|
||||
fields = [
|
||||
"ip", "other_ip", "hostname", "port", "group", "username", "password", "use_default_auth",
|
||||
"idc", "mac", "remote_ip", "brand", "cpu", "memory", "disk", "system_type", "system_version",
|
||||
"cabinet", "position", "number", "status", "asset_type", "env", "sn", "is_active", "comment"
|
||||
]
|
||||
|
||||
|
||||
class AssetGroupForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = AssetGroup
|
||||
fields = [
|
||||
"name", "comment"
|
||||
]
|
||||
|
||||
|
||||
class IdcForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = IDC
|
||||
fields = ['name', "bandwidth", "operator", 'linkman', 'phone', 'address', 'network', 'comment']
|
||||
|
||||
|
155
jasset/models.py
155
jasset/models.py
|
@ -1,6 +1,25 @@
|
|||
# coding: utf-8
|
||||
|
||||
import datetime
|
||||
from django.db import models
|
||||
# from juser.models import User, UserGroup
|
||||
from juser.models import User, UserGroup
|
||||
|
||||
ASSET_ENV = (
|
||||
(1, U'生产环境'),
|
||||
(2, U'测试环境')
|
||||
)
|
||||
|
||||
ASSET_STATUS = (
|
||||
(1, u"已使用"),
|
||||
(2, u"未使用"),
|
||||
(3, u"报废")
|
||||
)
|
||||
|
||||
ASSET_TYPE = (
|
||||
(1, u"服务器"),
|
||||
(2, u"网络设备"),
|
||||
(3, u"其他")
|
||||
)
|
||||
|
||||
|
||||
class AssetGroup(models.Model):
|
||||
|
@ -14,86 +33,74 @@ class AssetGroup(models.Model):
|
|||
def __unicode__(self):
|
||||
return self.name
|
||||
|
||||
# def get_asset(self):
|
||||
# return self.asset_set.all()
|
||||
#
|
||||
# def get_asset_info(self, printable=False):
|
||||
# assets = self.get_asset()
|
||||
# ip_comment = {}
|
||||
# for asset in assets:
|
||||
# ip_comment[asset.ip] = asset.comment
|
||||
#
|
||||
# for ip in sorted(ip_comment):
|
||||
# if ip_comment[ip]:
|
||||
# print '%-15s -- %s' % (ip, ip_comment[ip])
|
||||
# else:
|
||||
# print '%-15s' % ip
|
||||
# print ''
|
||||
#
|
||||
# def get_asset_num(self):
|
||||
# return len(self.get_asset())
|
||||
#
|
||||
# def get_user_group(self):
|
||||
# perm_list = self.perm_set.all()
|
||||
# user_group_list = []
|
||||
# for perm in perm_list:
|
||||
# user_group_list.append(perm.user_group)
|
||||
# return user_group_list
|
||||
#
|
||||
# def get_user(self):
|
||||
# user_list = []
|
||||
# user_group_list = self.get_user_group()
|
||||
# for user_group in user_group_list:
|
||||
# user_list.extend(user_group.user_set.all())
|
||||
# return user_list
|
||||
#
|
||||
# def is_permed(self, user=None, user_group=None):
|
||||
# if user:
|
||||
# if user in self.get_user():
|
||||
# return True
|
||||
#
|
||||
# if user_group:
|
||||
# if user_group in self.get_user_group():
|
||||
# return True
|
||||
# return False
|
||||
|
||||
class IDC(models.Model):
|
||||
name = models.CharField(max_length=32, verbose_name=u'机房名称')
|
||||
bandwidth = models.CharField(max_length=32, blank=True, null=True, verbose_name=u'机房带宽')
|
||||
linkman = models.CharField(max_length=16, null=True, verbose_name=u'联系人')
|
||||
phone = models.CharField(max_length=32, verbose_name=u'联系电话')
|
||||
address = models.CharField(max_length=128, blank=True, null=True, verbose_name=u"机房地址")
|
||||
network = models.TextField(blank=True, null=True, verbose_name=u"IP地址段")
|
||||
date_added = models.DateField(auto_now=True, default=datetime.datetime.now(), null=True)
|
||||
operator = models.IntegerField(max_length=32, blank=True, null=True, verbose_name=u"运营商")
|
||||
comment = models.CharField(max_length=128, blank=True, null=True, verbose_name=u"备注")
|
||||
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
|
||||
class Meta:
|
||||
verbose_name = u"IDC机房"
|
||||
verbose_name_plural = verbose_name
|
||||
|
||||
|
||||
class Asset(models.Model):
|
||||
ip = models.GenericIPAddressField(unique=True)
|
||||
port = models.IntegerField()
|
||||
group = models.ManyToManyField(AssetGroup)
|
||||
username = models.CharField(max_length=20, blank=True, null=True)
|
||||
password = models.CharField(max_length=80, blank=True, null=True)
|
||||
use_default_auth = models.BooleanField(default=True)
|
||||
date_added = models.DateTimeField(auto_now_add=True)
|
||||
is_active = models.BooleanField(default=True)
|
||||
comment = models.CharField(max_length=100, blank=True, null=True)
|
||||
"""
|
||||
asset modle
|
||||
"""
|
||||
ip = models.IPAddressField(unique=True, verbose_name=u"主机IP")
|
||||
other_ip = models.CharField(max_length=255, blank=True, null=True, verbose_name=u"其他IP")
|
||||
hostname = models.CharField(max_length=64, blank=True, null=True, verbose_name=u"主机名")
|
||||
port = models.IntegerField(max_length=6, verbose_name=u"端口号")
|
||||
group = models.ManyToManyField(AssetGroup, blank=True, null=True, verbose_name=u"所属主机组")
|
||||
username = models.CharField(max_length=16, blank=True, null=True, verbose_name=u"管理用户名")
|
||||
password = models.CharField(max_length=64, blank=True, null=True, verbose_name=u"密码")
|
||||
use_default_auth = models.BooleanField(default=True, verbose_name=u"使用默认管理账号")
|
||||
idc = models.ForeignKey(IDC, blank=True, null=True, on_delete=models.SET_NULL, verbose_name=u'机房')
|
||||
mac = models.CharField(max_length=20, blank=True, null=True, verbose_name=u"MAC地址")
|
||||
remote_ip = models.CharField(max_length=16, blank=True, null=True, verbose_name=u'远控卡')
|
||||
brand = models.CharField(max_length=64, blank=True, null=True, verbose_name=u'硬件厂商型号')
|
||||
cpu = models.CharField(max_length=64, blank=True, null=True, verbose_name=u'CPU')
|
||||
memory = models.CharField(max_length=128, blank=True, null=True, verbose_name=u'内存')
|
||||
disk = models.CharField(max_length=128, blank=True, null=True, verbose_name=u'硬盘')
|
||||
system_type = models.CharField(max_length=32, blank=True, null=True, verbose_name=u"系统类型")
|
||||
system_version = models.CharField(max_length=8, blank=True, null=True, verbose_name=u"版本号")
|
||||
cabinet = models.CharField(max_length=32, blank=True, null=True, verbose_name=u'机柜号')
|
||||
position = models.IntegerField(max_length=2, blank=True, null=True, verbose_name=u'机器位置')
|
||||
number = models.CharField(max_length=32, blank=True, null=True, verbose_name=u'资产编号')
|
||||
status = models.IntegerField(max_length=2, choices=ASSET_STATUS, blank=True, null=True, default=1, verbose_name=u"机器状态")
|
||||
asset_type = models.IntegerField(max_length=2, choices=ASSET_TYPE, blank=True, null=True, verbose_name=u"主机类型")
|
||||
env = models.IntegerField(max_length=2, choices=ASSET_ENV, blank=True, null=True, verbose_name=u"运行环境")
|
||||
sn = models.CharField(max_length=128, blank=True, null=True, verbose_name=u"SN编号")
|
||||
date_added = models.DateTimeField(auto_now=True, default=datetime.datetime.now(), null=True)
|
||||
is_active = models.BooleanField(default=True, verbose_name=u"是否激活")
|
||||
comment = models.CharField(max_length=128, blank=True, null=True, verbose_name=u"备注")
|
||||
|
||||
def __unicode__(self):
|
||||
return self.ip
|
||||
|
||||
# def get_user(self):
|
||||
# perm_list = []
|
||||
# asset_group_all = self.bis_group.all()
|
||||
# for asset_group in asset_group_all:
|
||||
# perm_list.extend(asset_group.perm_set.all())
|
||||
#
|
||||
# user_group_list = []
|
||||
# for perm in perm_list:
|
||||
# user_group_list.append(perm.user_group)
|
||||
#
|
||||
# user_permed_list = []
|
||||
# for user_group in user_group_list:
|
||||
# user_permed_list.extend(user_group.user_set.all())
|
||||
# user_permed_list = list(set(user_permed_list))
|
||||
# return user_permed_list
|
||||
|
||||
class AssetRecord(models.Model):
|
||||
asset = models.ForeignKey(Asset)
|
||||
username = models.CharField(max_length=30, null=True)
|
||||
alert_time = models.DateTimeField(auto_now_add=True)
|
||||
content = models.TextField(null=True, blank=True)
|
||||
comment = models.TextField(null=True, blank=True)
|
||||
|
||||
|
||||
class AssetAlias(models.Model):
|
||||
pass
|
||||
# user = models.ForeignKey(User)
|
||||
# asset = models.ForeignKey(Asset)
|
||||
# alias = models.CharField(max_length=100, blank=True, null=True)
|
||||
#
|
||||
# def __unicode__(self):
|
||||
# return self.alias
|
||||
user = models.ForeignKey(User)
|
||||
asset = models.ForeignKey(Asset)
|
||||
alias = models.CharField(max_length=100, blank=True, null=True)
|
||||
|
||||
def __unicode__(self):
|
||||
return self.alias
|
||||
|
|
|
@ -4,23 +4,27 @@ from jasset.views import *
|
|||
|
||||
urlpatterns = patterns('',
|
||||
url(r'^asset_add/$', asset_add),
|
||||
# url(r"^host_add_multi/$", host_add_batch),
|
||||
url(r'^group_add/$', group_add),
|
||||
url(r'^group_list/$', group_list),
|
||||
url(r"^asset_add_batch/$", asset_add_batch),
|
||||
url(r'^group_del/$', group_del),
|
||||
url(r'^asset_list/$', asset_list),
|
||||
url(r'^asset_del/$', asset_del),
|
||||
url(r"^asset_detail/$", asset_detail),
|
||||
url(r'^asset_edit/$', asset_edit),
|
||||
url(r'^asset_update/$', asset_update),
|
||||
# url(r'^search/$', host_search),
|
||||
# url(r"^host_detail/$", host_detail),
|
||||
# url(r"^dept_host_ajax/$", dept_host_ajax),
|
||||
# url(r"^show_all_ajax/$", show_all_ajax),
|
||||
# url(r'^group_edit/$', group_edit),
|
||||
# url(r'^group_list/$', group_list),
|
||||
# url(r'^group_detail/$', group_detail),
|
||||
url(r'^group_add/$', group_add),
|
||||
url(r'^group_list/$', group_list),
|
||||
url(r'^group_edit/$', group_edit),
|
||||
url(r'^group_list/$', group_list),
|
||||
url(r'^group_detail/$', group_detail),
|
||||
# url(r'^group_del_host/$', group_del_host),
|
||||
|
||||
# url(r'^host_edit/batch/$', host_edit_batch),
|
||||
url(r'^asset_edit_batch/$', asset_edit_batch),
|
||||
# url(r'^host_edit_common/batch/$', host_edit_common_batch),
|
||||
url(r'^idc_add/$', idc_add),
|
||||
url(r'^idc_list/$', idc_list),
|
||||
url(r'^idc_detail/$', idc_detail),
|
||||
url(r'^idc_edit/$', idc_edit),
|
||||
url(r'^idc_del/$', idc_del),
|
||||
url(r'^upload/$', asset_upload),
|
||||
)
|
396
jasset/views.py
396
jasset/views.py
|
@ -1,13 +1,13 @@
|
|||
# coding:utf-8
|
||||
|
||||
import ast
|
||||
|
||||
from django.db.models import Q
|
||||
from django.template import RequestContext
|
||||
from django.shortcuts import get_object_or_404
|
||||
|
||||
from jasset.asset_api import *
|
||||
from jumpserver.api import *
|
||||
from jasset.forms import AssetForm, IdcForm
|
||||
from jasset.models import Asset, IDC, AssetGroup, ASSET_TYPE, ASSET_STATUS
|
||||
from ansible_api import Tasks
|
||||
|
||||
|
||||
@require_role('admin')
|
||||
|
@ -36,13 +36,69 @@ def group_add(request):
|
|||
|
||||
except ServerError:
|
||||
pass
|
||||
|
||||
else:
|
||||
db_add_group(name=name, comment=comment, asset_select=asset_select)
|
||||
msg = u"主机组 %s 添加成功" % name
|
||||
smg = u"主机组 %s 添加成功" % name
|
||||
|
||||
return my_render('jasset/group_add.html', locals(), request)
|
||||
|
||||
|
||||
@require_role('admin')
|
||||
def group_edit(request):
|
||||
"""
|
||||
Edit asset group
|
||||
编辑资产组
|
||||
"""
|
||||
header_title, path1, path2 = u'编辑主机组', u'资产管理', u'编辑主机组'
|
||||
group_id = request.GET.get('id', '')
|
||||
group = get_object(AssetGroup, id=group_id)
|
||||
|
||||
asset_all = Asset.objects.all()
|
||||
asset_select = Asset.objects.filter(group=group)
|
||||
asset_no_select = [a for a in asset_all if a not in asset_select]
|
||||
|
||||
if request.method == 'POST':
|
||||
name = request.POST.get('name', '')
|
||||
asset_select = request.POST.getlist('asset_select', [])
|
||||
comment = request.POST.get('comment', '')
|
||||
|
||||
try:
|
||||
if not name:
|
||||
emg = u'组名不能为空'
|
||||
raise ServerError(emg)
|
||||
|
||||
if group.name != name:
|
||||
asset_group_test = get_object(AssetGroup, name=name)
|
||||
if asset_group_test:
|
||||
emg = u"该组名 %s 已存在" % name
|
||||
raise ServerError(emg)
|
||||
|
||||
except ServerError:
|
||||
pass
|
||||
|
||||
else:
|
||||
group.asset_set.clear()
|
||||
db_update_group(id=group_id, name=name, comment=comment, asset_select=asset_select)
|
||||
smg = u"主机组 %s 添加成功" % name
|
||||
|
||||
return HttpResponseRedirect('/jasset/group_list')
|
||||
|
||||
return my_render('jasset/group_edit.html', locals(), request)
|
||||
|
||||
|
||||
@require_role('admin')
|
||||
def group_detail(request):
|
||||
""" 主机组详情 """
|
||||
header_title, path1, path2 = u'主机组详情', u'资产管理', u'主机组详情'
|
||||
group_id = request.GET.get('id', '')
|
||||
group = get_object(AssetGroup, id=group_id)
|
||||
asset_all = Asset.objects.filter(group=group).order_by('ip')
|
||||
|
||||
contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(asset_all, request)
|
||||
return my_render('jasset/group_detail.html', locals(), request)
|
||||
|
||||
|
||||
@require_role('admin')
|
||||
def group_list(request):
|
||||
"""
|
||||
|
@ -85,23 +141,13 @@ def asset_add(request):
|
|||
"""
|
||||
header_title, path1, path2 = u'添加资产', u'资产管理', u'添加资产'
|
||||
asset_group_all = AssetGroup.objects.all()
|
||||
af = AssetForm()
|
||||
if request.method == 'POST':
|
||||
ip = request.POST.get('ip')
|
||||
groups = request.POST.getlist('groups')
|
||||
use_default = True if request.POST.getlist('use_default', []) else False
|
||||
is_active = True if request.POST.get('is_active') else False
|
||||
comment = request.POST.get('comment')
|
||||
|
||||
if not use_default:
|
||||
username = request.POST.get('username')
|
||||
password = request.POST.get('password')
|
||||
port = request.POST.get('port')
|
||||
password_encode = password
|
||||
else:
|
||||
username = None
|
||||
port = None
|
||||
password_encode = None
|
||||
|
||||
af_post = AssetForm(request.POST)
|
||||
print af_post
|
||||
ip = request.POST.get('ip', '')
|
||||
is_active = True if request.POST.get('is_active') == '1' else False
|
||||
use_default_auth = request.POST.get('use_default_auth', '')
|
||||
try:
|
||||
if Asset.objects.filter(ip=str(ip)):
|
||||
error = u'该IP %s 已存在!' % ip
|
||||
|
@ -110,34 +156,27 @@ def asset_add(request):
|
|||
except ServerError:
|
||||
pass
|
||||
else:
|
||||
db_asset_add(
|
||||
ip=ip, port=port, use_default=use_default, is_active=is_active, comment=comment,
|
||||
groups=groups, username=username, password=password_encode
|
||||
)
|
||||
if af_post.is_valid():
|
||||
asset_save = af_post.save(commit=False)
|
||||
if not use_default_auth:
|
||||
password = request.POST.get('password', '')
|
||||
password_encode = CRYPTOR.encrypt(password)
|
||||
asset_save.password = password_encode
|
||||
asset_save.is_active = True if is_active else False
|
||||
asset_save.save()
|
||||
af_post.save_m2m()
|
||||
|
||||
msg = u'主机 %s 添加成功' % ip
|
||||
else:
|
||||
esg = u'主机 %s 添加失败' % ip
|
||||
|
||||
return my_render('jasset/asset_add.html', locals(), request)
|
||||
|
||||
|
||||
@require_role(role='user')
|
||||
def asset_list(request):
|
||||
"""
|
||||
list assets
|
||||
列出资产表
|
||||
"""
|
||||
header_title, path1, path2 = u'查看主机', u'资产管理', u'查看主机'
|
||||
keyword = request.GET.get('keyword', '')
|
||||
gid = request.GET.get('gid', '') # asset group id
|
||||
sid = request.GET.get('sid', '')
|
||||
assets_list = Asset.objects.all().order_by('ip')
|
||||
|
||||
if keyword:
|
||||
assets_list = assets_list.filter(Q(ip__contains=keyword) |
|
||||
Q(comment__contains=keyword)).distinct().order_by('ip')
|
||||
|
||||
assets_list, p, assets, page_range, current_page, show_first, show_end = pages(assets_list, request)
|
||||
return my_render('jasset/asset_list.html', locals(), request)
|
||||
@require_role('admin')
|
||||
def asset_add_batch(request):
|
||||
header_title, path1, path2 = u'添加资产', u'资产管理', u'批量添加'
|
||||
return my_render('jasset/asset_add_batch.html', locals(), request)
|
||||
|
||||
|
||||
@require_role('admin')
|
||||
|
@ -149,64 +188,279 @@ def asset_del(request):
|
|||
asset_id = request.GET.get('id', '')
|
||||
if asset_id:
|
||||
Asset.objects.filter(id=asset_id).delete()
|
||||
|
||||
if request.method == 'POST':
|
||||
asset_batch = request.GET.get('arg', '')
|
||||
asset_id_all = str(request.POST.get('asset_id_all', ''))
|
||||
|
||||
if asset_batch:
|
||||
for asset_id in asset_id_all.split(','):
|
||||
asset = get_object(Asset, id=asset_id)
|
||||
asset.delete()
|
||||
|
||||
return HttpResponse(u'删除成功')
|
||||
return Http404
|
||||
|
||||
|
||||
@require_role(role='super')
|
||||
def asset_edit(request):
|
||||
""" 修改主机 """
|
||||
"""
|
||||
edit a asset
|
||||
修改主机
|
||||
"""
|
||||
header_title, path1, path2 = u'修改资产', u'资产管理', u'修改资产'
|
||||
|
||||
asset_id = request.GET.get('id', '')
|
||||
if not asset_id:
|
||||
return HttpResponse('没有该主机')
|
||||
username = request.session.get('username', 'admin')
|
||||
asset = get_object(Asset, id=asset_id)
|
||||
|
||||
asset_old = copy_model_instance(asset)
|
||||
af = AssetForm(instance=asset)
|
||||
if request.method == 'POST':
|
||||
ip = request.POST.get('ip')
|
||||
groups = request.POST.getlist('groups')
|
||||
use_default = True if request.POST.getlist('use_default', []) else False
|
||||
is_active = True if request.POST.get('is_active') else False
|
||||
comment = request.POST.get('comment')
|
||||
|
||||
if not use_default:
|
||||
username = request.POST.get('username')
|
||||
password = request.POST.get('password')
|
||||
port = request.POST.get('port')
|
||||
if password == asset.password:
|
||||
password_encode = password
|
||||
else:
|
||||
password_encode = CRYPTOR.encrypt(password)
|
||||
else:
|
||||
username = None
|
||||
password_encode = None
|
||||
port = 22
|
||||
|
||||
af_post = AssetForm(request.POST, instance=asset)
|
||||
ip = request.POST.get('ip', '')
|
||||
use_default_auth = request.POST.get('use_default_auth')
|
||||
try:
|
||||
asset_test = get_object(Asset, ip=ip)
|
||||
if asset_test and asset_id != str(asset_test.id):
|
||||
if asset_test and asset_id != unicode(asset_test.id):
|
||||
error = u'该IP %s 已存在!' % ip
|
||||
raise ServerError(error)
|
||||
except ServerError:
|
||||
pass
|
||||
else:
|
||||
db_asset_update(id=asset_id, ip=ip, port=port, use_default=use_default,
|
||||
username=username, password=password_encode,
|
||||
is_active=is_active, comment=comment)
|
||||
if af_post.is_valid():
|
||||
af_save = af_post.save(commit=False)
|
||||
if use_default_auth:
|
||||
af_save.username = ''
|
||||
af_save.password = ''
|
||||
af_save.save()
|
||||
af_post.save_m2m()
|
||||
# asset_new = get_object(Asset, id=asset_id)
|
||||
# asset_diff_one(asset_old, asset_new)
|
||||
info = asset_diff(af_post.__dict__.get('initial'), request.POST)
|
||||
db_asset_alert(asset, username, info)
|
||||
|
||||
msg = u'主机 %s 修改成功' % ip
|
||||
else:
|
||||
emg = u'主机 %s 修改失败' % ip
|
||||
return HttpResponseRedirect('/jasset/asset_detail/?id=%s' % asset_id)
|
||||
|
||||
return my_render('jasset/asset_edit.html', locals(), request)
|
||||
|
||||
|
||||
@require_role('user')
|
||||
def asset_list(request):
|
||||
"""
|
||||
asset list view
|
||||
"""
|
||||
idc_all = IDC.objects.filter()
|
||||
asset_group_all = AssetGroup.objects.all()
|
||||
asset_types = ASSET_TYPE
|
||||
asset_status = ASSET_STATUS
|
||||
|
||||
idc_name = request.GET.get('idc', '')
|
||||
group_name = request.GET.get('group', '')
|
||||
asset_type = request.GET.get('asset_type', '')
|
||||
status = request.GET.get('status', '')
|
||||
keyword = request.GET.get('keyword', '')
|
||||
export = request.GET.get("export", False)
|
||||
|
||||
asset_find = Asset.objects.all()
|
||||
if idc_name:
|
||||
asset_find = asset_find.filter(idc__name__contains=idc_name)
|
||||
|
||||
if group_name:
|
||||
asset_find = asset_find.filter(group__name__contains=group_name)
|
||||
|
||||
if asset_type:
|
||||
asset_find = asset_find.filter(asset_type__contains=asset_type)
|
||||
|
||||
if status:
|
||||
asset_find = asset_find.filter(status__contains=status)
|
||||
|
||||
if keyword:
|
||||
asset_find = asset_find.filter(
|
||||
Q(hostname__contains=keyword) |
|
||||
Q(other_ip__contains=keyword) |
|
||||
Q(ip__contains=keyword) |
|
||||
Q(remote_ip__contains=keyword) |
|
||||
Q(comment__contains=keyword) |
|
||||
Q(group__name__contains=keyword) |
|
||||
Q(cpu__contains=keyword) |
|
||||
Q(memory__contains=keyword) |
|
||||
Q(disk__contains=keyword))
|
||||
|
||||
if export:
|
||||
s = write_excel(asset_find)
|
||||
if s[0]:
|
||||
file_name = s[1]
|
||||
smg = 'excel文件已生成,请点击下载!'
|
||||
return my_render('jasset/asset_excel_download.html', locals(), request)
|
||||
assets_list, p, assets, page_range, current_page, show_first, show_end = pages(asset_find, request)
|
||||
return my_render('jasset/asset_list.html', locals(), request)
|
||||
|
||||
|
||||
@require_role('admin')
|
||||
def asset_edit_batch(request):
|
||||
af = AssetForm()
|
||||
asset_group_all = AssetGroup.objects.all()
|
||||
return my_render('jasset/asset_edit_batch.html', locals(), request)
|
||||
|
||||
|
||||
@require_role('admin')
|
||||
def asset_detail(request):
|
||||
""" 主机详情 """
|
||||
"""
|
||||
Asset detail view
|
||||
"""
|
||||
header_title, path1, path2 = u'主机详细信息', u'资产管理', u'主机详情'
|
||||
asset_id = request.GET.get('id', '')
|
||||
asset = get_object(Asset, id=asset_id)
|
||||
asset_record = AssetRecord.objects.filter(asset=asset).order_by('-alert_time')
|
||||
|
||||
return my_render('jasset/asset_detail.html', locals(), request)
|
||||
|
||||
|
||||
@require_role('admin')
|
||||
def asset_update(request):
|
||||
"""
|
||||
Asset update host info via ansible view
|
||||
"""
|
||||
asset_id = request.GET.get('id', '')
|
||||
asset = get_object(Asset, id=asset_id)
|
||||
if not asset:
|
||||
return HttpResponseRedirect('/jasset/asset_detail/?id=%s' % asset_id)
|
||||
name = request.session.get('username', 'admin')
|
||||
if asset.use_default_auth:
|
||||
username = 'root'
|
||||
password = '123456'
|
||||
else:
|
||||
username = asset.username
|
||||
password = asset.password
|
||||
|
||||
resource = [{"hostname": asset.ip, "port": asset.port,
|
||||
"username": username, "password": password}]
|
||||
|
||||
ansible_instance = Tasks(resource)
|
||||
ansible_asset_info = ansible_instance.get_host_info()
|
||||
if ansible_asset_info['status'] == 'ok':
|
||||
asset_info = ansible_asset_info['result'][asset.ip]
|
||||
if asset_info:
|
||||
hostname = asset_info.get('hostname')
|
||||
other_ip = ','.join(asset_info.get('other_ip'))
|
||||
cpu_type = asset_info.get('cpu_type')[1]
|
||||
cpu_cores = asset_info.get('cpu_cores')
|
||||
cpu = cpu_type + ' * ' + unicode(cpu_cores)
|
||||
memory = asset_info.get('memory')
|
||||
disk = asset_info.get('disk')
|
||||
sn = asset_info.get('sn')
|
||||
brand = asset_info.get('brand')
|
||||
system_type = asset_info.get('system_type')
|
||||
system_version = asset_info.get('system_version')
|
||||
|
||||
asset_dic = {"hostname": hostname, "other_ip": other_ip, "cpu": cpu,
|
||||
"memory": memory, "disk": disk, "system_type": system_type,
|
||||
"system_version": system_version, "brand": brand, "sn": sn
|
||||
}
|
||||
|
||||
ansible_record(asset, asset_dic, name)
|
||||
|
||||
return HttpResponseRedirect('/jasset/asset_detail/?id=%s' % asset_id)
|
||||
|
||||
|
||||
@require_role('admin')
|
||||
def idc_add(request):
|
||||
"""
|
||||
IDC add view
|
||||
"""
|
||||
header_title, path1, path2 = u'添加IDC', u'资产管理', u'添加IDC'
|
||||
if request.method == 'POST':
|
||||
idc_form = IdcForm(request.POST)
|
||||
if idc_form.is_valid():
|
||||
idc_name = idc_form.cleaned_data['name']
|
||||
|
||||
if IDC.objects.filter(name=idc_name):
|
||||
emg = u'添加失败, 此IDC %s 已存在!' % idc_name
|
||||
return my_render('jasset/idc_add.html', locals(), request)
|
||||
else:
|
||||
idc_form.save()
|
||||
smg = u'IDC: %s添加成功' % idc_name
|
||||
return HttpResponseRedirect("/jasset/idc_list/")
|
||||
else:
|
||||
idc_form = IdcForm()
|
||||
return render_to_response('jasset/idc_add.html',
|
||||
locals(),
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
|
||||
@require_role('admin')
|
||||
def idc_list(request):
|
||||
"""
|
||||
IDC list view
|
||||
"""
|
||||
header_title, path1, path2 = u'查看IDC', u'资产管理', u'查看IDC'
|
||||
posts = IDC.objects.all()
|
||||
keyword = request.GET.get('keyword', '')
|
||||
if keyword:
|
||||
posts = IDC.objects.filter(Q(name__contains=keyword) | Q(comment__contains=keyword))
|
||||
else:
|
||||
posts = IDC.objects.exclude(name='ALL').order_by('id')
|
||||
contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(posts, request)
|
||||
return render_to_response('jasset/idc_list.html',
|
||||
locals(),
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
|
||||
@require_role('admin')
|
||||
def idc_edit(request):
|
||||
"""
|
||||
IDC edit view
|
||||
"""
|
||||
header_title, path1, path2 = u'编辑IDC', u'资产管理', u'编辑IDC'
|
||||
idc_id = request.GET.get('id', '')
|
||||
idc = get_object(IDC, id=idc_id)
|
||||
if request.method == 'POST':
|
||||
idc_form = IdcForm(request.POST, instance=idc)
|
||||
if idc_form.is_valid():
|
||||
idc_form.save()
|
||||
return HttpResponseRedirect("/jasset/idc_list/")
|
||||
else:
|
||||
idc_form = IdcForm(instance=idc)
|
||||
return my_render('jasset/idc_edit.html', locals(), request)
|
||||
|
||||
|
||||
@require_role('admin')
|
||||
def idc_detail(request):
|
||||
"""
|
||||
IDC detail view
|
||||
"""
|
||||
header_title, path1, path2 = u'IDC详情', u'资产管理', u'IDC详情'
|
||||
idc_id = request.GET.get('id', '')
|
||||
idc = get_object(IDC, id=idc_id)
|
||||
posts = Asset.objects.filter(idc=idc).order_by('ip')
|
||||
contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(posts, request)
|
||||
|
||||
return my_render('jasset/idc_detail.html', locals(), request)
|
||||
|
||||
|
||||
@require_role('admin')
|
||||
def idc_del(request):
|
||||
"""
|
||||
IDC delete view
|
||||
"""
|
||||
uuid = request.GET.get('uuid', '')
|
||||
idc = get_object_or_404(IDC, uuid=uuid)
|
||||
idc.delete()
|
||||
return HttpResponseRedirect('/jasset/idc_list/')
|
||||
|
||||
|
||||
@require_role('admin')
|
||||
def asset_upload(request):
|
||||
"""
|
||||
Upload file view
|
||||
"""
|
||||
if request.method == 'POST':
|
||||
excel_file = request.FILES.get('file_name', '')
|
||||
ret = excel_to_db(excel_file)
|
||||
if ret:
|
||||
smg = u'批量添加成功'
|
||||
else:
|
||||
emg = u'批量添加失败,请检查格式.'
|
||||
return my_render('jasset/asset_add_batch.html', locals(), request)
|
||||
|
|
|
@ -15,8 +15,6 @@ database = jumpserver
|
|||
[websocket]
|
||||
web_socket_host = 127.0.0.1:3000
|
||||
|
||||
|
||||
|
||||
[mail]
|
||||
mail_enable = 1
|
||||
email_host = smtp.exmail.qq.com
|
||||
|
|
|
@ -65,12 +65,12 @@ INSTALLED_APPS = (
|
|||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'django.contrib.humanize',
|
||||
'bootstrapform',
|
||||
'jumpserver',
|
||||
'juser',
|
||||
'jasset',
|
||||
'jperm',
|
||||
'jlog',
|
||||
|
||||
)
|
||||
|
||||
MIDDLEWARE_CLASSES = (
|
||||
|
@ -146,3 +146,5 @@ USE_TZ = False
|
|||
# https://docs.djangoproject.com/en/1.7/howto/static-files/
|
||||
|
||||
STATIC_URL = '/static/'
|
||||
|
||||
BOOTSTRAP_COLUMN_COUNT = 10
|
||||
|
|
|
@ -182,3 +182,132 @@ def asset_which_group(asset, member):
|
|||
names = [members.name for members in member.all()]
|
||||
|
||||
return ','.join(names)
|
||||
#
|
||||
#
|
||||
# @register.filter(name='get_user_asset_group')
|
||||
# def get_user_asset_group(user):
|
||||
# return user.get_asset_group()
|
||||
#
|
||||
#
|
||||
# @register.filter(name='group_asset_list')
|
||||
# def group_asset_list(group):
|
||||
# return group.asset_set.all()
|
||||
#
|
||||
#
|
||||
# @register.filter(name='group_asset_list_count')
|
||||
# def group_asset_list_count(group):
|
||||
# return group.asset_set.all().count()
|
||||
#
|
||||
#
|
||||
# @register.filter(name='time_delta')
|
||||
# def time_delta(time_before):
|
||||
# delta = datetime.datetime.now() - time_before
|
||||
# days = delta.days
|
||||
# if days:
|
||||
# return "%s 天前" % days
|
||||
# else:
|
||||
# hours = delta.seconds/3600
|
||||
# if hours:
|
||||
# return "%s 小时前" % hours
|
||||
# else:
|
||||
# mins = delta.seconds/60
|
||||
# if mins:
|
||||
# return '%s 分钟前' % mins
|
||||
# else:
|
||||
# return '%s 秒前' % delta.seconds
|
||||
#
|
||||
#
|
||||
# @register.filter(name='sudo_cmd_list')
|
||||
# def sudo_cmd_list(cmd_group_id):
|
||||
# cmd_group = CmdGroup.objects.filter(id=cmd_group_id)
|
||||
# if cmd_group:
|
||||
# cmd_group = cmd_group[0]
|
||||
# return cmd_group.cmd.split(',')
|
||||
#
|
||||
#
|
||||
# @register.filter(name='sudo_cmd_count')
|
||||
# def sudo_cmd_count(user_group_id):
|
||||
# user_group = UserGroup.objects.filter(id=user_group_id)
|
||||
# cmds = []
|
||||
# if user_group:
|
||||
# user_group = user_group[0]
|
||||
# cmd_groups = []
|
||||
#
|
||||
# for perm in user_group.sudoperm_set.all():
|
||||
# cmd_groups.extend(perm.cmd_group.all())
|
||||
#
|
||||
# for cmd_group in cmd_groups:
|
||||
# cmds.extend(cmd_group.cmd.split(','))
|
||||
# return len(set(cmds))
|
||||
#
|
||||
# else:
|
||||
# return 0
|
||||
#
|
||||
#
|
||||
# @register.filter(name='sudo_cmd_count')
|
||||
# def sudo_cmd_count(user_group_id):
|
||||
# user_group = UserGroup.objects.filter(id=user_group_id)
|
||||
# cmds = []
|
||||
# if user_group:
|
||||
# user_group = user_group[0]
|
||||
# cmd_groups = []
|
||||
# for perm in user_group.sudoperm_set.all():
|
||||
# cmd_groups.extend(perm.cmd_group.all())
|
||||
#
|
||||
# for cmd_group in cmd_groups:
|
||||
# cmds.extend(cmd_group.cmd.split(','))
|
||||
# return len(set(cmds))
|
||||
# else:
|
||||
# return 0
|
||||
#
|
||||
#
|
||||
# @register.filter(name='sudo_cmd_ids')
|
||||
# def sudo_cmd_ids(user_group_id):
|
||||
# user_group = UserGroup.objects.filter(id=user_group_id)
|
||||
# if user_group:
|
||||
# user_group = user_group[0]
|
||||
# cmd_groups = []
|
||||
# for perm in user_group.sudoperm_set.all():
|
||||
# cmd_groups.extend(perm.cmd_group.all())
|
||||
# cmd_ids = [str(cmd_group.id) for cmd_group in cmd_groups]
|
||||
# return ','.join(cmd_ids)
|
||||
# else:
|
||||
# return '0'
|
||||
#
|
||||
#
|
||||
# @register.filter(name='cmd_group_split')
|
||||
# def cmd_group_split(cmd_group):
|
||||
# return cmd_group.cmd.split(',')
|
||||
|
||||
|
||||
@register.filter(name='str_to_list')
|
||||
def str_to_list(info):
|
||||
"""
|
||||
str to list
|
||||
"""
|
||||
print ast.literal_eval(info), type(ast.literal_eval(info))
|
||||
return ast.literal_eval(info)
|
||||
|
||||
|
||||
@register.filter(name='str_to_dic')
|
||||
def str_to_dic(info):
|
||||
"""
|
||||
str to list
|
||||
"""
|
||||
return ast.literal_eval(info).iteritems()
|
||||
|
||||
|
||||
@register.filter(name='str_to_code')
|
||||
def str_to_code(char_str):
|
||||
if char_str:
|
||||
return char_str
|
||||
else:
|
||||
return u'空'
|
||||
|
||||
|
||||
@register.filter(name='ip_str_to_list')
|
||||
def ip_str_to_list(ip_str):
|
||||
"""
|
||||
ip str to list
|
||||
"""
|
||||
return ip_str.split(',')
|
||||
|
|
|
@ -4562,3 +4562,8 @@ body.skin-3 {
|
|||
.red-fonts {
|
||||
color: #ed5565;
|
||||
}
|
||||
|
||||
.form-group.required .control-label:after {
|
||||
content: " *";
|
||||
color: red;
|
||||
}
|
|
@ -135,3 +135,11 @@ function selectAll(){
|
|||
// })
|
||||
//}
|
||||
|
||||
function getIDall() {
|
||||
var check_array = [];
|
||||
$(".gradeX input:checked").each(function () {
|
||||
var id = $(this).attr("value");
|
||||
check_array.push(id);
|
||||
});
|
||||
return check_array.join(",");
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load mytags %}
|
||||
{% load bootstrap %}
|
||||
{% block content %}
|
||||
{% include 'nav_cat_bar.html' %}
|
||||
<div class="wrapper wrapper-content animated fadeInRight">
|
||||
|
@ -26,7 +27,7 @@
|
|||
<div class="panel-options">
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="active"><a href="/jasset/asset_add/" class="text-center"><i class="fa fa-laptop"></i> 单台添加 </a></li>
|
||||
<li><a href="/jasset/host_add_multi" class="text-center"><i class="fa fa-bar-chart-o"></i> 批量添加 </a></li>
|
||||
<li><a href="/jasset/asset_add_batch" class="text-center"><i class="fa fa-bar-chart-o"></i> 批量添加 </a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
|
@ -38,17 +39,23 @@
|
|||
{% if msg %}
|
||||
<div class="alert alert-success text-center">{{ msg }}</div>
|
||||
{% endif %}
|
||||
|
||||
<form id="assetForm" method="post" class="form-horizontal">
|
||||
<div class="form-group"><label class="col-sm-2 control-label"> IP地址<span class="red-fonts">*</span> </label>
|
||||
<div class="col-sm-8"><input type="text" name="ip" placeholder="IP" class="form-control"></div>
|
||||
</div>
|
||||
{{ af.ip|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{{ af.port|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{{ af.idc|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<label for="j_group" class="col-sm-2 control-label">使用默认</label>
|
||||
<div class="col-sm-1">
|
||||
<label for="j_group" class="col-sm-2 control-label">管理账号<span class="red-fonts"> *</span></label>
|
||||
<div class="col-sm-2">
|
||||
<div class="radio i-checks">
|
||||
<label>
|
||||
<input type="checkbox" checked="" value="1" id="use_default" name="use_default">
|
||||
<input type="checkbox" checked="" id="id_use_default_auth" name="use_default_auth"><span> 使用默认 </span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -73,16 +80,9 @@
|
|||
</div>
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<label for="groups" class="col-sm-2 control-label">所属主机组</label>
|
||||
<div class="col-sm-8">
|
||||
<select id="groups" name="groups" class="form-control m-b" multiple size="10">
|
||||
{% for asset_group in asset_group_all %}
|
||||
<option type="checkbox" value="{{ asset_group.id }}">{{ asset_group.name }} {% if asset_group.comment %} --- {{ asset_group.comment }} {% endif %}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{{ af.group|bootstrap_horizontal }}
|
||||
|
||||
{# {{ af.is_active|bootstrap_horizontal }}#}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group"><label class="col-sm-2 control-label"> 是否激活<span class="red-fonts"> *</span> </label>
|
||||
|
@ -94,11 +94,6 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group"><label class="col-sm-2 control-label"> 备注 </label>
|
||||
<div class="col-sm-8"><input type="text" placeholder="comment" name="comment" class="form-control"></div>
|
||||
</div>
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-4 col-sm-offset-2">
|
||||
|
@ -120,7 +115,18 @@
|
|||
|
||||
{% block self_footer_js %}
|
||||
<script>
|
||||
$('document').ready(function(){
|
||||
$('#id_use_default_auth').click(function(){
|
||||
if ($(this).is(':checked')){
|
||||
$('#admin_account').css('display', 'none')
|
||||
}
|
||||
else {
|
||||
$('#admin_account').css('display', 'block')
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
<<<<<<< HEAD
|
||||
$('document').ready(function(){
|
||||
$('#use_default').click(function(){
|
||||
if ($(this).is(':checked')){
|
||||
|
@ -147,10 +153,36 @@ $('#assetForm').validator({
|
|||
tip: "输入IP",
|
||||
ok: "",
|
||||
msg: {required: "必须填写!"}
|
||||
=======
|
||||
var required_fields = ["id_hostname", "id_ip", "id_port"];
|
||||
required_fields.forEach(function(field) {
|
||||
$('label[for="' + field + '"]').parent().addClass("required");
|
||||
});
|
||||
|
||||
$('#assetForm').validator({
|
||||
timely: 2,
|
||||
theme: "yellow_right_effect",
|
||||
rules: {
|
||||
check_ip: [/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])(\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])){3}$/, 'ip地址不正确'],
|
||||
check_port: [/^\d{1,5}$/, '端口号不正确'],
|
||||
},
|
||||
fields: {
|
||||
"ip": {
|
||||
rule: "required;check_ip",
|
||||
tip: "输入IP",
|
||||
ok: "",
|
||||
msg: {required: "必须填写!"}
|
||||
},
|
||||
"port": {
|
||||
rule: "required;check_port",
|
||||
tip: "输入端口号",
|
||||
ok: "",
|
||||
msg: {required: "必须填写!"}
|
||||
}
|
||||
},
|
||||
valid: function(form) {
|
||||
form.submit();
|
||||
>>>>>>> cmdb
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,166 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load mytags %}
|
||||
{% block content %}
|
||||
{% include 'nav_cat_bar.html' %}
|
||||
<div class="wrapper wrapper-content animated fadeInRight">
|
||||
<div class="row">
|
||||
<div class="col-lg-10">
|
||||
<div class="ibox float-e-margins">
|
||||
<div id="ibox-content" class="ibox-title">
|
||||
<h5> 填写资产基本信息 </h5>
|
||||
<div class="ibox-tools">
|
||||
<a class="collapse-link">
|
||||
<i class="fa fa-chevron-up"></i>
|
||||
</a>
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
|
||||
<i class="fa fa-wrench"></i>
|
||||
</a>
|
||||
<a class="close-link">
|
||||
<i class="fa fa-times"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ibox-content">
|
||||
<div class="panel blank-panel">
|
||||
<div class="panel-options">
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="active"><a href="/jasset/asset_add/" class="text-center"><i class="fa fa-laptop"></i> 单台添加 </a></li>
|
||||
<li><a href="/jasset/host_add_multi" class="text-center"><i class="fa fa-bar-chart-o"></i> 批量添加 </a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div class="tab-content">
|
||||
<div id="tab-1" class="ibox float-e-margins tab-pane active">
|
||||
{% if error %}
|
||||
<div class="alert alert-warning text-center">{{ error }}</div>
|
||||
{% endif %}
|
||||
{% if msg %}
|
||||
<div class="alert alert-success text-center">{{ msg }}</div>
|
||||
{% endif %}
|
||||
<form id="assetForm" method="post" class="form-horizontal">
|
||||
<div class="form-group"><label class="col-sm-2 control-label"> IP地址<span class="red-fonts">*</span> </label>
|
||||
<div class="col-sm-8"><input type="text" name="ip" placeholder="IP" class="form-control"></div>
|
||||
</div>
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label"> 端口号<span class="red-fonts">*</span> </label>
|
||||
<div class="col-sm-8">
|
||||
<input type="text" placeholder="Port" name="port" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<label for="j_group" class="col-sm-2 control-label">管理账号</label>
|
||||
<div class="col-sm-2">
|
||||
<div class="radio i-checks">
|
||||
<label>
|
||||
<input type="checkbox" checked="" value="1" id="use_default_auth" name="use_default_auth"><span> 使用默认 </span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group" id="admin_account" style="display: none">
|
||||
<label class="col-sm-2 control-label"> 管理用户名<span class="red-fonts">*</span> </label>
|
||||
<div class="col-sm-3">
|
||||
<input type="text" placeholder="Username" name="username" class="form-control">
|
||||
</div>
|
||||
|
||||
<label class="col-sm-1 control-label"> 密码<span class="red-fonts">*</span> </label>
|
||||
<div class="col-sm-4">
|
||||
<input type="password" placeholder="Password" name="password" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<label for="groups" class="col-sm-2 control-label">所属主机组</label>
|
||||
<div class="col-sm-8">
|
||||
<select id="groups" name="groups" class="form-control m-b" multiple size="10">
|
||||
{% for asset_group in asset_group_all %}
|
||||
<option type="checkbox" value="{{ asset_group.id }}">{{ asset_group.name }} {% if asset_group.comment %} --- {{ asset_group.comment }} {% endif %}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group"><label class="col-sm-2 control-label"> 是否激活<span class="red-fonts">*</span> </label>
|
||||
<div class="col-sm-8">
|
||||
<div class="radio i-checks">
|
||||
<label> <input type="radio" checked="" value="1" name="is_active">激活 </label>
|
||||
<label> <input type="radio" value="0" name="is_active"> 禁用</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group"><label class="col-sm-2 control-label"> 备注 </label>
|
||||
<div class="col-sm-8"><input type="text" placeholder="comment" name="comment" class="form-control"></div>
|
||||
</div>
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-4 col-sm-offset-2">
|
||||
<button class="btn btn-white" type="reset"> 重置 </button>
|
||||
<button class="btn btn-primary" type="submit"> 提交 </button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block self_footer_js %}
|
||||
<script>
|
||||
|
||||
$('document').ready(function(){
|
||||
$('#use_default_auth').click(function(){
|
||||
if ($(this).is(':checked')){
|
||||
$('#admin_account').css('display', 'none')
|
||||
}
|
||||
else {
|
||||
$('#admin_account').css('display', 'block')
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
$('#assetForm').validator({
|
||||
timely: 2,
|
||||
theme: "yellow_right_effect",
|
||||
rules: {
|
||||
check_ip: [/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])(\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])){3}$/, 'ip地址不正确'],
|
||||
check_port: [/^\d{1,5}$/, '端口号不正确'],
|
||||
},
|
||||
fields: {
|
||||
"ip": {
|
||||
rule: "required;check_ip",
|
||||
tip: "输入IP",
|
||||
ok: "",
|
||||
msg: {required: "必须填写!"}
|
||||
},
|
||||
"port": {
|
||||
rule: "required;check_port",
|
||||
tip: "输入端口号",
|
||||
ok: "",
|
||||
msg: {required: "必须填写!"}
|
||||
}
|
||||
},
|
||||
valid: function(form) {
|
||||
form.submit();
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
|
@ -0,0 +1,65 @@
|
|||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
{% include 'nav_cat_bar.html' %}
|
||||
<style>
|
||||
.file-box{ position:relative;width:340px}
|
||||
.txt{ height:22px; border:1px solid #cdcdcd; width:180px;}
|
||||
.file{ position:absolute; top:0; right:80px; height:24px; filter:alpha(opacity:0);opacity: 0;width:260px }
|
||||
</style>
|
||||
<div class="wrapper wrapper-content animated fadeInRight">
|
||||
<div class="row">
|
||||
<div class="col-lg-10">
|
||||
<div class="ibox float-e-margins">
|
||||
<div id="ibox-content" class="ibox-title">
|
||||
<h5> 填写主机基本信息 </h5>
|
||||
<div class="ibox-tools">
|
||||
<a class="collapse-link">
|
||||
<i class="fa fa-chevron-up"></i>
|
||||
</a>
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
|
||||
<i class="fa fa-wrench"></i>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-user">
|
||||
</ul>
|
||||
<a class="close-link">
|
||||
<i class="fa fa-times"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ibox-content">
|
||||
<div class="panel blank-panel">
|
||||
<div class="panel-options">
|
||||
<ul class="nav nav-tabs">
|
||||
<li><a href="/jasset/asset_add/" class="text-center"><i class="fa fa-laptop"></i> 单台添加 </a></li>
|
||||
<li class="active"><a href="/jasset/asset_add_batch/" class="text-center"><i class="fa fa-bar-chart-o"></i> 批量添加 </a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div id="tab-2" class="ibox float-e-margins tab-pane active">
|
||||
{% if emg %}
|
||||
<div class="alert alert-warning text-center">{{ emg }}</div>
|
||||
{% endif %}
|
||||
{% if smg %}
|
||||
<div class="alert alert-success text-center">{{ smg }}</div>
|
||||
{% endif %}
|
||||
<p>请下载Excel文件, 按照格式填写主机信息, 上传导入. <a href="/static/files/excels/asset.xlsx">点击下载模板</a></p>
|
||||
<form action="/jasset/upload/" method="POST" enctype="multipart/form-data">
|
||||
<div class="file-box">
|
||||
<input id='textfield' />
|
||||
<input type="button" class="btn btn-info btn-sm" name="file_name" value="点击选择文件">
|
||||
<input type="file" name="file_name" class="file" id="fileField" size="28" onchange="document.getElementById('textfield').value=this.value" />
|
||||
<button class="btn btn-primary btn-sm" type="submit">上传文件</button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
|
@ -1,6 +1,6 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load mytags %}
|
||||
|
||||
{% load humanize %}
|
||||
|
||||
{% block content %}
|
||||
{% include 'nav_cat_bar.html' %}
|
||||
|
@ -33,6 +33,28 @@
|
|||
<td class="text-navy">IP</td>
|
||||
<td>{{ asset.ip }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-navy">主机名</td>
|
||||
<td>{{ asset.hostname }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-navy">其他IP</td>
|
||||
<td>
|
||||
<table class="table">
|
||||
{% if asset.other_ip %}
|
||||
{% for ip in asset.other_ip|ip_str_to_list %}
|
||||
<tr>
|
||||
<td>{{ ip }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-navy">远控IP</td>
|
||||
<td>{{ asset.remote_ip }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-navy">端口</td>
|
||||
<td>{{ asset.port }}</td>
|
||||
|
@ -42,12 +64,80 @@
|
|||
<td class="text-navy">主机组</td>
|
||||
<td>
|
||||
<table class="table">
|
||||
{% for asset_group in asset.group.all %}
|
||||
<tr>
|
||||
<td>{{ asset_group.name }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-navy">使用默认管理账号</td>
|
||||
<td>{{ asset.use_default_auth|bool2str }}</td>
|
||||
{# <td>{{ asset.use_default_auth|bool2str }}</td>#}
|
||||
<td>{{ asset.use_default_auth|bool2str }} {% if not asset.use_default_auth %} <span class="text-info">{{ asset.username }}</span> {% endif %}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-navy">机房</td>
|
||||
<td>{{ asset.idc.name }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-navy">硬件厂商型号</td>
|
||||
<td>{{ asset.brand }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-navy">CPU</td>
|
||||
<td>{{ asset.cpu }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-navy">内存</td>
|
||||
<td>{{ asset.memory }}M</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-navy">硬盘</td>
|
||||
<td>
|
||||
<table class="table">
|
||||
{% if asset.disk %}
|
||||
{% for disk, value in asset.disk|str_to_dic %}
|
||||
<tr>
|
||||
<td><span class="text-navy">{{ disk }}</span>     {{ value }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-navy">资产编号</td>
|
||||
<td>{{ asset.number }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-navy">SN</td>
|
||||
<td>{{ asset.sn }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-navy">主机类型</td>
|
||||
<td>{{ asset.get_asset_type_display }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-navy">系统版本</td>
|
||||
<td>{{ asset.system_type }} {{ asset.system_version }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-navy">运行环境</td>
|
||||
<td>{{ asset.get_env_display }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-navy">机器状态</td>
|
||||
<td>{{ asset.get_status_display }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-navy">机柜号</td>
|
||||
<td>{{ asset.cabinet }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-navy">机柜位置</td>
|
||||
<td>{{ asset.position }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-navy">激活</td>
|
||||
|
@ -91,8 +181,8 @@
|
|||
</div>
|
||||
<div class="ibox-content">
|
||||
<div>
|
||||
<div class="text-left">
|
||||
<table class="table">
|
||||
{# <div class="text-left">#}
|
||||
{# <table class="table">#}
|
||||
{# {% if user_permed_list %}#}
|
||||
{# {% for user in user_permed_list %}#}
|
||||
{# <tr>#}
|
||||
|
@ -104,9 +194,49 @@
|
|||
{# {% else %}#}
|
||||
{# <p class="text-center">(暂无)</p>#}
|
||||
{# {% endif %}#}
|
||||
</table>
|
||||
{# </table>#}
|
||||
{# </div>#}
|
||||
</div>
|
||||
</div>
|
||||
<div class="ibox-title">
|
||||
<h5>主机修改记录</h5>
|
||||
<div class="ibox-tools">
|
||||
<a class="collapse-link">
|
||||
<i class="fa fa-chevron-up"></i>
|
||||
</a>
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
|
||||
<i class="fa fa-wrench"></i>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-user">
|
||||
</ul>
|
||||
<a class="close-link">
|
||||
<i class="fa fa-times"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ibox-content ibox-heading">
|
||||
<h3>主机修改记录</h3>
|
||||
<small><i class="fa fa-map-marker"></i> 包含了此主机所有历史修改记录.</small>
|
||||
</div>
|
||||
<div class="ibox-content">
|
||||
<div class="feed-activity-list">
|
||||
{% if asset_record %}
|
||||
{% for r in asset_record %}
|
||||
<div class="feed-element">
|
||||
<div>
|
||||
<small class="pull-right">{{ r.alert_time|naturaltime }}</small>
|
||||
<strong class="text-navy">{{ r.username }}</strong>
|
||||
{% for i in r.content|str_to_list %}
|
||||
<div>{{ i.0 }} 由 <span class="text-success">{{ i.1|str_to_code }}</span> 改为 <span class="text-warning">{{ i.2|str_to_code }}</span></div>
|
||||
{% endfor %}
|
||||
<small class="text-success">{{ r.alert_time }}</small>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<p class="text-center">(暂无)</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load mytags %}
|
||||
{% load bootstrap %}
|
||||
{% block content %}
|
||||
{% include 'nav_cat_bar.html' %}
|
||||
<div class="wrapper wrapper-content animated fadeInRight">
|
||||
|
@ -32,53 +33,86 @@
|
|||
<div class="alert alert-success text-center">{{ msg }}</div>
|
||||
{% endif %}
|
||||
<form id="assetForm" method="post" class="form-horizontal">
|
||||
<div class="form-group"><label class="col-sm-2 control-label"> IP地址<span class="red-fonts">*</span> </label>
|
||||
<div class="col-sm-8"><input type="text" name="ip" value="{{ asset.ip }}" class="form-control"></div>
|
||||
</div>
|
||||
|
||||
{{ af.ip|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{{ af.hostname|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{{ af.other_ip|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{{ af.remote_ip|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{{ af.port|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label"> 端口号<span class="red-fonts">*</span> </label>
|
||||
<div class="col-sm-8">
|
||||
<input type="text" value="{{ asset.port }}" name="port" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<label for="j_group" class="col-sm-2 control-label">使用默认管理账号</label>
|
||||
<div class="col-sm-1">
|
||||
<label for="j_group" class="col-sm-2 control-label">管理账号 <span class="red-fonts">*</span></label>
|
||||
<div class="col-sm-2">
|
||||
<div class="radio i-checks">
|
||||
<label>
|
||||
<input type="checkbox" {% ifequal asset.use_default 1 %} checked="" {% endifequal %} value="1" id="use_default" name="use_default">
|
||||
<input type="checkbox" {% if asset.use_default_auth %} checked="" {% endif %} id="id_use_default_auth" name="use_default_auth"><span> 使用默认 </span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group" id="admin_account" {% ifequal asset.use_default 1 %} style="display: none" {% endifequal %}>
|
||||
<div class="form-group" id="admin_account" {% if asset.use_default_auth %} style="display: none" {% endif %}>
|
||||
<label class="col-sm-2 control-label"> 管理用户名 <span class="red-fonts">*</span> </label>
|
||||
<div class="col-sm-3">
|
||||
<input type="text" {% ifnotequal asset.use_default 1 %} value="{{ asset.username }}" {% endifnotequal %} name="username" class="form-control">
|
||||
<input type="text" value="{{ asset.username }}" name="username" class="form-control">
|
||||
</div>
|
||||
|
||||
<label class="col-sm-1 control-label"> 密码<span class="red-fonts">*</span> </label>
|
||||
<div class="col-sm-4">
|
||||
<input type="password" {% ifnotequal asset.use_default 1 %} value="{{ asset.password }}" {% endifnotequal %} name="password" class="form-control">
|
||||
<input type="password" value="{{ asset.password }}" name="password" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<label for="groups" class="col-sm-2 control-label">所属主机组</label>
|
||||
<div class="col-sm-8">
|
||||
<select id="groups" name="groups" class="form-control m-b" multiple size="10">
|
||||
{% for g in egroup %}
|
||||
<option type="checkbox" value="{{ g.id }}">{{ g.name }} {% if g.comment %} --- {{ g.comment }} {% endif %}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{{ af.group|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{{ af.idc|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{{ af.brand|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{{ af.cpu|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{{ af.memory|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{{ af.disk|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{{ af.number|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{{ af.sn|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{{ af.cabinet|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{{ af.position|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{{ af.asset_type|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{{ af.env|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{{ af.status|bootstrap_horizontal }}
|
||||
|
||||
{# <div class="hr-line-dashed"></div>#}
|
||||
{# {{ af.is_active|bootstrap_horizontal }}#}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group"><label class="col-sm-2 control-label"> 是否激活<span class="red-fonts">*</span> </label>
|
||||
|
@ -96,9 +130,7 @@
|
|||
</div>
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group"><label class="col-sm-2 control-label"> 备注 </label>
|
||||
<div class="col-sm-8"><input type="text" value="{{ asset.comment }}" name="comment" class="form-control"></div>
|
||||
</div>
|
||||
{{ af.comment|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
|
@ -121,9 +153,8 @@
|
|||
|
||||
{% block self_footer_js %}
|
||||
<script>
|
||||
|
||||
$('document').ready(function(){
|
||||
$('#use_default').click(function(){
|
||||
$('#id_use_default_auth').click(function(){
|
||||
if ($(this).is(':checked')){
|
||||
$('#admin_account').css('display', 'none')
|
||||
}
|
||||
|
@ -133,6 +164,11 @@ $('document').ready(function(){
|
|||
})
|
||||
});
|
||||
|
||||
var required_fields = ["id_ip", "id_port"];
|
||||
required_fields.forEach(function(field) {
|
||||
$('label[for="' + field + '"]').parent().addClass("required");
|
||||
});
|
||||
|
||||
$('#assetForm').validator({
|
||||
timely: 2,
|
||||
theme: "yellow_right_effect",
|
||||
|
|
|
@ -0,0 +1,180 @@
|
|||
<html>
|
||||
<head>
|
||||
<link href="/static/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="/static/font-awesome/css/font-awesome.css" rel="stylesheet">
|
||||
<link href="/static/css/plugins/iCheck/custom.css" rel="stylesheet">
|
||||
<link href="/static/css/animate.css" rel="stylesheet">
|
||||
<link href="/static/css/style.css" rel="stylesheet">
|
||||
|
||||
<script src="/static/js/jquery-2.1.1.js"></script>
|
||||
{# <style>#}
|
||||
{# body {background: #ffffff;}#}
|
||||
{# </style>#}
|
||||
</head>
|
||||
|
||||
{% load bootstrap %}
|
||||
{% block content %}
|
||||
|
||||
<body>
|
||||
<div class="wrapper wrapper-content animated fadeInRight">
|
||||
<div class="row">
|
||||
<div class="col-lg-10">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-title">
|
||||
<h5 class="text-center"> 填写修改主机信息. </h5>
|
||||
<div class="ibox-tools">
|
||||
<a class="collapse-link">
|
||||
<i class="fa fa-chevron-up"></i>
|
||||
</a>
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
|
||||
<i class="fa fa-wrench"></i>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-user"></ul>
|
||||
<a class="close-link">
|
||||
<i class="fa fa-times"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ibox-content">
|
||||
<form class="form-horizontal" action="" id="signupForm" method="post" name="horizontal" role="form" autocomplete="off">
|
||||
{% csrf_token %}
|
||||
<input id="ids" style="display: none">
|
||||
{{ af.env|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{{ af.idc|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{{ af.port|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<label for="j_group" class="col-sm-2 control-label">管理账号</label>
|
||||
<div class="col-sm-2">
|
||||
<div class="radio i-checks">
|
||||
<label>
|
||||
<input type="radio" checked="" value="no_action" name="use_default_auth"><span> 不修改 </span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="radio i-checks">
|
||||
<label>
|
||||
<input type="radio" name="use_default_auth"><span> 使用默认 </span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="radio i-checks">
|
||||
<label>
|
||||
<input type="radio" id="id_use_default_auth" name="use_default_auth"><span> 用户名密码 </span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group" id="admin_account" style="display: none">
|
||||
<label class="col-sm-2 control-label"> 管理用户名<span class="red-fonts"> *</span></label>
|
||||
<div class="col-sm-3">
|
||||
<input type="text" placeholder="Username" name="username" class="form-control">
|
||||
</div>
|
||||
|
||||
<label class="col-sm-1 control-label"> 密码<span class="red-fonts">*</span> </label>
|
||||
<div class="col-sm-4">
|
||||
<input type="password" placeholder="Password" name="password" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<label for="groups" class="col-sm-2 control-label">所属主机组</label>
|
||||
|
||||
<div class="col-sm-3">
|
||||
<select id="groups" size="10" class="form-control m-b" multiple>
|
||||
{% for asset_group in asset_group_all %}
|
||||
<option value="{{ asset_group.id }}">{{ asset_group.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-sm-1">
|
||||
<div class="btn-group" style="margin-top: 50px;">
|
||||
<button type="button" class="btn btn-white" onclick="move_right('groups', 'groups_selected')"><i class="fa fa-chevron-right"></i></button>
|
||||
<button type="button" class="btn btn-white" onclick="move_left('groups_selected', 'groups')"><i class="fa fa-chevron-left"></i> </button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-3">
|
||||
<div>
|
||||
<select id="groups_selected" name="project" class="form-control m-b" size="10" multiple>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{{ af.cabinet|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{{ af.comment|bootstrap_horizontal }}
|
||||
<div class="hr-line-dashed"></div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-sm-4 col-sm-offset-5">
|
||||
<button class="btn btn-white" type="submit"> 重置 </button>
|
||||
<button class="btn btn-primary" id="host_edit"> 提交 </button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$('#host_edit').click(function () {
|
||||
var args = {};
|
||||
var match = null;
|
||||
var uuid = decodeURIComponent(location.search.substring(1));
|
||||
var reg = /(?:([^&]+)=([^&]+))/g;
|
||||
while((match = reg.exec(uuid))!==null){
|
||||
args[match[1]] = match[2];
|
||||
}
|
||||
var ids = args['uuid'];
|
||||
$('#uuid').val(ids)
|
||||
});
|
||||
|
||||
$('#id_use_default_auth').click(function(){
|
||||
if ($(this).is(':checked')){
|
||||
$('#admin_account').css('display', 'block')
|
||||
}
|
||||
else {
|
||||
$('#admin_account').css('display', 'none')
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
function move_left(from, to) {
|
||||
$("#"+from+" option").each(function(){
|
||||
if ( $(this).prop("selected") == true ) {
|
||||
$("#"+to).append(this);
|
||||
$(this).attr("selected",'false');
|
||||
}
|
||||
$(this).attr("selected",'true');
|
||||
});
|
||||
}
|
||||
function move_right(from, to) {
|
||||
$("#"+from+" option").each(function(){
|
||||
if ( $(this).prop("selected") == true ) {
|
||||
$("#"+to).append(this);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
function move_all(from, to){
|
||||
$("#"+from).children().each(function(){
|
||||
$("#"+to).append(this);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
{% endblock content %}
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<div class="col-md-12 column">
|
||||
<div class="alert alert-success alert-dismissable">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
|
||||
<h4>
|
||||
</h4> <strong>Nice!</strong> excel文件已生成请点击 <a href="/static/files/excels/{{ file_name }}" target="_blank" class="alert-link">下载</a>
|
||||
</div>
|
||||
</div>
|
|
@ -23,36 +23,93 @@
|
|||
</div>
|
||||
|
||||
<div class="ibox-content">
|
||||
<div>
|
||||
{% if session_role_id > 0 %}
|
||||
<a target="_blank" href="/jasset/asset_add/" class="btn btn-sm btn-primary "> 添加 </a>
|
||||
{% endif %}
|
||||
<form id="search_form" method="get" action="" class="pull-right mail-search">
|
||||
<form id="asset_form">
|
||||
<div class="col-sm-2" style="padding-left: 0px">
|
||||
<label>
|
||||
<select name="idc" class="form-control m-b" onchange="change_info()">
|
||||
<option value="">IDC机房</option>
|
||||
{% for idc in idc_all %}
|
||||
{% ifequal idc.name idc_name %}
|
||||
<option value="{{idc.name}}" selected> {{ idc.name }}</option>
|
||||
{% else %}
|
||||
<option value="{{idc.name}}"> {{ idc.name }}</option>
|
||||
{% endifequal %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
<label>
|
||||
<select name="group" class="form-control m-b" onchange="change_info()">
|
||||
<option value="">主机组</option>
|
||||
{% for asset_group in asset_group_all %}
|
||||
{% ifequal asset_group.name group_name %}
|
||||
<option value="{{ asset_group.name }}" selected> {{ asset_group.name }} </option>
|
||||
{% else %}
|
||||
<option value="{{ asset_group.name }}"> {{ asset_group.name }} </option>
|
||||
{% endifequal %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-2">
|
||||
<label>
|
||||
<select name="asset_type" class="form-control m-b" onchange="change_info()">
|
||||
<option value="">所有类型</option>
|
||||
{% for type in asset_types %}
|
||||
{% ifequal type.0|int2str asset_type %}
|
||||
<option value="{{ type.0 }}" selected> {{ type.1 }}</option>
|
||||
{% else %}
|
||||
<option value="{{ type.0 }}"> {{ type.1 }}</option>
|
||||
{% endifequal %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
<label>
|
||||
<select name="status" class="form-control m-b" onchange="change_info()">
|
||||
<option value="">状态</option>
|
||||
{% for s in asset_status %}
|
||||
{% ifequal s.0|int2str status %}
|
||||
<option value="{{ s.0 }}" selected> {{ s.1 }}</option>
|
||||
{% else %}
|
||||
<option value="{{ s.0 }}"> {{ s.1 }}</option>
|
||||
{% endifequal %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-sm-4">
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control input-sm" id="search_input" name="keyword" placeholder="Search">
|
||||
<input type="text" class="form-control m-b" id="search_input" name="keyword" value="{{ keyword }}" placeholder="Search">
|
||||
<input type="text" style="display: none">
|
||||
<div class="input-group-btn">
|
||||
<button type="submit" class="btn btn-sm btn-primary">
|
||||
<button id='search_btn' href="/jasset/asset_list/?search=true" type="button" class="btn btn-xm btn-primary search-btn" onclick="change_info()">
|
||||
- 搜索 -
|
||||
</button>
|
||||
<button type="button" href="/jasset/asset_list/?export=true" name="export" class="btn btn-xm btn-success search-btn-excel" onclick="return false">
|
||||
- 导出 -
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<form id="contents_form" name="contents_form">
|
||||
<div id="export"></div>
|
||||
<table class="table table-striped table-bordered table-hover " id="editable" name="editable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-center">
|
||||
<input id="checkall" type="checkbox" class="i-checks" name="checkall" value="checkall" data-editable='false' onclick="check_all('contents_form')">
|
||||
<input id="checkall" type="checkbox" class="i-checks" name="checkall" value="checkall" data-editable='false' onclick="check_all('asset_form')">
|
||||
</th>
|
||||
<th class="text-center" name="ip"> IP地址 </th>
|
||||
<th class="text-center"> 端口号 </th>
|
||||
<th class="text-center"> 主机名 </th>
|
||||
<th class="text-center"> IDC </th>
|
||||
<th class="text-center"> 所属主机组 </th>
|
||||
{# <th class="text-center"> 配置信息 </th>#}
|
||||
<th class="text-center"> 操作系统 </th>
|
||||
<th class="text-center"> 使用默认管理 </th>
|
||||
<th class="text-center"> 激活 </th>
|
||||
<th class="text-center" name="comment"> 备注 </th>
|
||||
<th class="text-center"> 操作 </th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
@ -63,15 +120,17 @@
|
|||
<input name="id" value="{{ asset.id }}" type="checkbox" class="i-checks">
|
||||
</td>
|
||||
<td class="text-center"> {{ asset.ip }} </td>
|
||||
<td class="text-center"> {{ asset.port }} </td>
|
||||
<td class="text-center">{{ asset.port }}</td>
|
||||
<td class="text-center"> {{ asset.hostname }} </td>
|
||||
<td class="text-center"> {{ asset.idc.name }} </td>
|
||||
<td class="text-center">{{ asset.group.all|group_str2 }}</td>
|
||||
{# <td class="text-center">{{ asset.cpu }}|{{ asset.memory }}|{{ asset.disk }}</td>#}
|
||||
<td class="text-center">{{ asset.system_type }}{{ asset.system_version }}</td>
|
||||
<td class="text-center"> {{ asset.use_default_auth|bool2str }} </td>
|
||||
<td class="text-center"> {{ asset.is_active|bool2str }} </td>
|
||||
<td class="text-center"> {{ asset.comment }} </td>
|
||||
<td class="text-center" data-editable='false'>
|
||||
<a href="/jasset/asset_detail/?id={{ asset.id }}" class="btn btn-xs btn-primary">详情</a>
|
||||
{% ifnotequal session_role_id 0 %}
|
||||
<a href="/jasset/asset_edit/?id={{ asset.id }}" class="btn btn-xs btn-info">编辑</a>
|
||||
<a href="/jasset/asset_update/?id={{ asset.id }}" class="btn btn-xs btn-info">更新</a>
|
||||
<a value="/jasset/asset_del/?id={{ asset.id }}" class="btn btn-xs btn-danger asset_del">删除</a>
|
||||
{% endifnotequal %}
|
||||
</td>
|
||||
|
@ -81,8 +140,8 @@
|
|||
</table>
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<input type="button" id="del_button" class="btn btn-danger btn-sm" name="del_button" value="删除" onclick="del('contents_form')" />
|
||||
<input type="button" id="alter_button" class="btn btn-warning btn-sm" name="alter_button" value="修改" onclick="alter('contents_form')" />
|
||||
<input type="button" id="asset_del" class="btn btn-danger btn-sm" name="del_button" value="删除"/>
|
||||
<a value="/jasset/asset_edit_batch/" type="button" class="btn btn-sm btn-warning iframe">修改</a>
|
||||
</div>
|
||||
{% include 'paginator.html' %}
|
||||
</div>
|
||||
|
@ -124,60 +183,70 @@
|
|||
})
|
||||
});
|
||||
|
||||
|
||||
function alter(form) {
|
||||
selectData = GetTableDataBox();
|
||||
console.log(selectData[0])
|
||||
if (selectData[1] != 0) {
|
||||
$.ajax({
|
||||
type: "post",
|
||||
url: "/jasset/host_edit/batch/",
|
||||
data: {"editable": selectData[0], "len_table": selectData[1]},
|
||||
success: function (data) {
|
||||
alert("修改成功");
|
||||
window.open("/jasset/host_list/", "_self");
|
||||
error: window.open("/jasset/host_list/", "_self");
|
||||
$(".iframe").on('click', function(){
|
||||
var ids = getIDall();
|
||||
if (ids == ''){
|
||||
alert("请至少选择一行!");
|
||||
return false;
|
||||
}
|
||||
var url= $(this).attr("value") + '?id=' + ids;
|
||||
index = $.layer({
|
||||
type: 2,
|
||||
title: 'JumpServer - 批量修改主机',
|
||||
maxmin: true,
|
||||
shift: 'top',
|
||||
border: [2, 0.3, '#1AB394'],
|
||||
shade: [0.5, '#000000'],
|
||||
shadeClose: true,
|
||||
area : ['800px' , '600px'],
|
||||
iframe: {src: url},
|
||||
close: function(){
|
||||
location.replace(location.href);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function del(form) {
|
||||
var checkboxes = document.getElementById(form);
|
||||
var id_list = {};
|
||||
var j = 0;
|
||||
for (var i = 0; i < checkboxes.elements.length; i++) {
|
||||
if (checkboxes.elements[i].type == "checkbox" && checkboxes.elements[i].checked == true && checkboxes.elements[i].value != "checkall") {
|
||||
id_list[j] = checkboxes.elements[i].value;
|
||||
j++;
|
||||
$('.search-btn-excel').unbind('click').bind('click',function(){
|
||||
var url= $(this).attr("href");
|
||||
console.log(url);
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: url,
|
||||
data: $("#asset_form").serialize(),
|
||||
success: function (data) {
|
||||
$("#export").html(data);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('#asset_del').click(function () {
|
||||
var asset_id_all = getIDall();
|
||||
console.log(asset_id_all);
|
||||
if (asset_id_all == ''){
|
||||
alert("请至少选择一行!");
|
||||
return false;
|
||||
}
|
||||
if (confirm("确定删除")) {
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "/jasset/host_del/multi/",
|
||||
data: {"id_list": id_list, "len_list": j},
|
||||
success: function (data) {
|
||||
window.open("/jasset/host_list/", "_self");
|
||||
type: "post",
|
||||
data: {asset_id_all: asset_id_all},
|
||||
url: "/jasset/asset_del/?arg=batch",
|
||||
success: function () {
|
||||
parent.location.reload();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
{# function host_search(){#}
|
||||
{# $.ajax({#}
|
||||
{# type: "GET",#}
|
||||
{# url: "/jasset/search/",#}
|
||||
{# data: $("#search_form").serialize(),#}
|
||||
{# success: function (data) {#}
|
||||
{# $("#contents_form").html(data);#}
|
||||
{# }#}
|
||||
{# });#}
|
||||
{# }#}
|
||||
|
||||
function change_info(){
|
||||
var args = $("#asset_form").serialize();
|
||||
window.location = "/jasset/asset_list/?" + args
|
||||
}
|
||||
|
||||
$("#search_input").keydown(function(e){
|
||||
if(e.keyCode==13){
|
||||
host_search()
|
||||
change_info()
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -187,7 +256,6 @@
|
|||
$.ajax({
|
||||
type: "GET",
|
||||
url: url,
|
||||
// data: $("#search_form").serialize(),
|
||||
success: function (data) {
|
||||
$("#j_group_" + id).html(data);
|
||||
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
{% for field in af %}
|
||||
<div class="alert alert-warning text-center"> {{ field.errors }}</div>
|
||||
{{ field.label_tag }}: {{ field }}
|
||||
{% endfor %}
|
||||
|
||||
|
||||
{% if af.errors %}
|
||||
<ul>
|
||||
{% for error in af.errors %}
|
||||
<li><strong>{{ error }}</strong></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
|
@ -22,7 +22,7 @@
|
|||
<div class="col-lg-10">
|
||||
<div class="ibox float-e-margins">
|
||||
<div id="ibox-content" class="ibox-title">
|
||||
<h5> 填写资产组基本信息 </h5>
|
||||
<h5> 填写主机组基本信息 </h5>
|
||||
<div class="ibox-tools">
|
||||
<a class="collapse-link">
|
||||
<i class="fa fa-chevron-up"></i>
|
||||
|
@ -30,37 +30,34 @@
|
|||
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
|
||||
<i class="fa fa-wrench"></i>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-user">
|
||||
<li><a href="#">未启用 1</a>
|
||||
</li>
|
||||
<li><a href="#">未启用 2</a>
|
||||
</li>
|
||||
</ul>
|
||||
<a class="close-link">
|
||||
<i class="fa fa-times"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# <select id="assets_total" name="assets" class="form-control m-b" size="12" multiple style="display: none">#}
|
||||
{# {% for asset in assets_all %}#}
|
||||
{# <option value="{{ asset.id }}">{{ asset.ip }}</option>#}
|
||||
{# {% endfor %}#}
|
||||
{# </select>#}
|
||||
{##}
|
||||
{# <select id="asset_select_total" name="j_hosts" class="form-control m-b" size="12" multiple style="display: none">#}
|
||||
{# {% for asset in eposts %}#}
|
||||
{# <option value="{{ asset.id }}">{{ asset.ip }}</option>#}
|
||||
{# {% endfor %}#}
|
||||
{# </select>#}
|
||||
<select id="assets_total" name="assets" class="form-control m-b" size="12" multiple style="display: none">
|
||||
{% for asset in asset_all %}
|
||||
<option value="{{ asset.id }}">{{ asset.ip }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
|
||||
<div class="ibox-content">
|
||||
{% if error %}
|
||||
<div class="alert alert-warning text-center">{{ error }}</div>
|
||||
{% if emg %}
|
||||
<div class="alert alert-warning text-center">{{ emg }}</div>
|
||||
{% endif %}
|
||||
{% if msg %}
|
||||
<div class="alert alert-success text-center">{{ msg }}</div>
|
||||
{% if smg %}
|
||||
<div class="alert alert-success text-center">{{ smg }}</div>
|
||||
{% endif %}
|
||||
<form id="assetForm" method="post" class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label"> 主机组名<span class="red-fonts">*</span></label>
|
||||
<div class="col-sm-8">
|
||||
<input type="text" placeholder="Name" name="name" class="form-control">
|
||||
</div>
|
||||
<div class="form-group"><label class="col-sm-2 control-label"> 主机组名<span class="red-fonts">*</span></label>
|
||||
<div class="col-sm-8" name="group_id" value="{{ post.id }}"><input type="text" value="{{ group.name }}" placeholder="Name" name="name" class="form-control"></div>
|
||||
</div>
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
|
@ -92,7 +89,7 @@
|
|||
<div class="col-sm-1">
|
||||
<div class="btn-group" style="margin-top: 60px;">
|
||||
<button type="button" class="btn btn-white" onclick="move('assets', 'asset_select', 'assets_total', 'asset_select_total' )"><i class="fa fa-chevron-right"></i></button>
|
||||
<button type="button" class="btn btn-white" onclick="move('asset_select', 'assets', 'asset_select_total', 'assets_total')"><i class="fa fa-chevron-left"></i> </button>
|
||||
<button type="button" class="btn btn-white" onclick="move_left('asset_select', 'assets', 'asset_select_total', 'assets_total')"><i class="fa fa-chevron-left"></i> </button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -104,18 +101,15 @@
|
|||
</div>
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label"> 备注 </label>
|
||||
<div class="col-sm-8">
|
||||
<input type="text" placeholder="Comment" name="comment" class="form-control">
|
||||
</div>
|
||||
<div class="form-group"><label class="col-sm-2 control-label"> 备注 </label>
|
||||
<div class="col-sm-8"><input type="text" value="" placeholder="comment" name="comment" class="form-control"></div>
|
||||
</div>
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-4 col-sm-offset-2">
|
||||
<button class="btn btn-white" type="reset"> 重置 </button>
|
||||
<button class="btn btn-primary" type="submit" onclick="on_submit('groups_selected') "> 提交 </button>
|
||||
<div class="col-sm-4 col-sm-offset-5">
|
||||
<button class="btn btn-white" type="submit"> 重置 </button>
|
||||
<button class="btn btn-primary" id="submit_button" type="submit" onclick="on_submit('groups_selected') "> 提交 </button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -159,16 +153,6 @@
|
|||
})
|
||||
}
|
||||
|
||||
// $('#search').keyup(function() {
|
||||
// var $rows = $('#hosts option');
|
||||
// var val = $.trim($(this).val()).replace(/ +/g, ' ').toLowerCase();
|
||||
//
|
||||
// $rows.show().filter(function() {
|
||||
// var text = $(this).text().replace(/\s+/g, ' ').toLowerCase();
|
||||
// return !~text.indexOf(val);
|
||||
// }).hide();
|
||||
// });
|
||||
|
||||
function change_dept(dept_id){
|
||||
$.get('/jasset/dept_host_ajax/',
|
||||
{'id': dept_id},
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
<div class="ibox-content">
|
||||
<div class="">
|
||||
<a target="_blank" href="/jasset/host_add" class="btn btn-sm btn-primary"> 添加主机 </a>
|
||||
<a target="_blank" href="/jasset/asset_add" class="btn btn-sm btn-primary"> 添加主机 </a>
|
||||
<b class="pull-right">提示: 此页面删除只从本主机组中剔除主机 </b>
|
||||
</div>
|
||||
|
||||
|
@ -41,9 +41,8 @@
|
|||
<th class="text-center"><input id="checkall" type="checkbox" class="i-checks" name="checkall" value="checkall" data-editable='false' onclick="check_all('contents_form')"></th>
|
||||
<th class="text-center" name="j_ip"> IP地址 </th>
|
||||
<th class="text-center"> 端口号 </th>
|
||||
<th class="text-center" name="j_type"> 登录方式 </th>
|
||||
<th class="text-center" name="j_idc"> 所属IDC </th>
|
||||
<th class="text-center" id="group_id" value="{{ group.id }}"> 所属业务组 </th>
|
||||
<th class="text-center" id="group_id" value="{{ group.id }}"> 所属主机组 </th>
|
||||
<th class="text-center"> 是否激活 </th>
|
||||
<th class="text-center" name="j_time"> 添加时间 </th>
|
||||
<th class="text-center" name="j_comment"> 备注 </th>
|
||||
|
@ -51,21 +50,20 @@
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for post in contacts.object_list %}
|
||||
{% for asset in contacts.object_list %}
|
||||
<tr class="gradeX">
|
||||
<td class="text-center" name="j_id" value="{{ post.id }}" data-editable='false'><input name="id" value="{{ post.id }}" type="checkbox" class="i-checks"></td>
|
||||
<td class="text-center" name="j_ip"> {{ post.ip }} </td>
|
||||
<td class="text-center" name="j_port"> {{ post.port }} </td>
|
||||
<td class="text-center" name="j_type"> {{ post.login_type|get_login_type }} </td>
|
||||
<td class="text-center" name="j_idc"> {{ post.idc.name }} </td>
|
||||
<td class="text-center" name="j_group">{{ post.bis_group.all | group_str2 }}</td>
|
||||
<td class="text-center" name="j_active"> {{ post.is_active|bool2str }} </td>
|
||||
<td class="text-center"> {{ post.date_added|date:"Y-m-d H:i:s" }} </td>
|
||||
<td class="text-center" name="j_comment"> {{ post.comment }} </td>
|
||||
<td class="text-center" name="j_id" value="{{ asset.id }}" data-editable='false'><input name="id" value="{{ asset.id }}" type="checkbox" class="i-checks"></td>
|
||||
<td class="text-center" name="j_ip"> {{ asset.ip }} </td>
|
||||
<td class="text-center" name="j_port"> {{ asset.port }} </td>
|
||||
<td class="text-center" name="j_idc"> {{ asset.idc.name }} </td>
|
||||
<td class="text-center" name="j_group">{{ asset.bis_group.all | group_str2 }}</td>
|
||||
<td class="text-center" name="j_active"> {{ asset.is_active|bool2str }} </td>
|
||||
<td class="text-center"> {{ asset.date_added|date:"Y-m-d H:i:s" }} </td>
|
||||
<td class="text-center" name="j_comment"> {{ asset.comment }} </td>
|
||||
<td class="text-center" data-editable='false'>
|
||||
<a href="/jasset/host_detail/?id={{ post.id }}" class="iframe btn btn-xs btn-primary">详情</a>
|
||||
<a href="/jasset/host_edit/?id={{ post.id }}" class="btn btn-xs btn-info">编辑</a>
|
||||
<a href="/jasset/group_del_host/?id={{ post.id }}&gid={{ group.id }}" class="btn btn-xs btn-danger">删除</a>
|
||||
<a href="/jasset/host_detail/?id={{ asset.id }}" class="iframe btn btn-xs btn-primary">详情</a>
|
||||
<a href="/jasset/host_edit/?id={{ asset.id }}" class="btn btn-xs btn-info">编辑</a>
|
||||
<a href="/jasset/group_del_host/?id={{ asset.id }}&gid={{ group.id }}" class="btn btn-xs btn-danger">删除</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
@ -165,7 +163,7 @@
|
|||
selectData = GetTableDataBox();
|
||||
if (selectData[1] != 0) {
|
||||
$.ajax({
|
||||
type: "post",
|
||||
type: "asset",
|
||||
url: "/jasset/host_edit/batch/",
|
||||
data: {"editable": selectData[0], "len_table": selectData[1]},
|
||||
success: function (data) {
|
||||
|
|
|
@ -43,13 +43,13 @@
|
|||
</div>
|
||||
|
||||
<select id="assets_total" name="assets" class="form-control m-b" size="12" multiple style="display: none">
|
||||
{% for asset in posts %}
|
||||
{% for asset in asset_all %}
|
||||
<option value="{{ asset.id }}">{{ asset.ip }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
|
||||
<select id="asset_select_total" name="j_hosts" class="form-control m-b" size="12" multiple style="display: none">
|
||||
{% for asset in eposts %}
|
||||
<select id="asset_select_total" name="asset_select" class="form-control m-b" size="12" multiple style="display: none">
|
||||
{% for asset in asset_select %}
|
||||
<option value="{{ asset.id }}">{{ asset.ip }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
|
@ -63,14 +63,7 @@
|
|||
{% endif %}
|
||||
<form id="assetForm" method="post" class="form-horizontal">
|
||||
<div class="form-group"><label class="col-sm-2 control-label"> 主机组名<span class="red-fonts">*</span></label>
|
||||
<div class="col-sm-8" name="group_id" value="{{ post.id }}"><input type="text" value="{{ group.name }}" placeholder="网站" name="j_group" class="form-control"></div>
|
||||
</div>
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<label for="j_dept" class="col-lg-2 control-label">所属部门<span class="red-fonts" style="">*</span></label>
|
||||
<input type="text" name="j_dept" value="{{ group.dept.id }}" style="display: none">
|
||||
<div class="col-sm-8"><input type="text" value="{{ group.dept.name }}" class="form-control" readonly="readonly"></div>
|
||||
<div class="col-sm-8" name="group_id" value="{{ group.id }}"><input type="text" value="{{ group.name }}" placeholder="Name" name="name" class="form-control"></div>
|
||||
</div>
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
|
@ -92,8 +85,8 @@
|
|||
<div class="col-sm-4">
|
||||
<div>
|
||||
<select id="assets" name="assets" class="form-control m-b" size="12" multiple>
|
||||
{% for post in posts %}
|
||||
<option value="{{ post.id }}">{{ post.ip }}</option>
|
||||
{% for asset in asset_no_select %}
|
||||
<option value="{{ asset.id }}">{{ asset.ip }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
@ -108,8 +101,8 @@
|
|||
|
||||
<div class="col-sm-3">
|
||||
<div>
|
||||
<select id="asset_select" name="j_hosts" class="form-control m-b" size="12" multiple>
|
||||
{% for asset in eposts %}
|
||||
<select id="asset_select" name="asset_select" class="form-control m-b" size="12" multiple>
|
||||
{% for asset in asset_select %}
|
||||
<option value="{{ asset.id }}">{{ asset.ip }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
|
@ -119,7 +112,7 @@
|
|||
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group"><label class="col-sm-2 control-label"> 备注 </label>
|
||||
<div class="col-sm-8"><input type="text" value="{{ group.comment }}" placeholder=包括web组所有主机 name="j_comment" class="form-control"></div>
|
||||
<div class="col-sm-8"><input type="text" value="{{ group.comment }}" name="comment" class="form-control"></div>
|
||||
</div>
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
{% load bootstrap %}
|
||||
{% include 'nav_cat_bar.html' %}
|
||||
<div class="wrapper wrapper-content animated fadeInRight">
|
||||
<div class="row">
|
||||
<div class="col-lg-10">
|
||||
<div class="ibox float-e-margins">
|
||||
<div id="ibox-content" class="ibox-title">
|
||||
<h5> 填写IDC基本信息 </h5>
|
||||
<div class="ibox-tools">
|
||||
<a class="collapse-link">
|
||||
<i class="fa fa-chevron-up"></i>
|
||||
</a>
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
|
||||
<i class="fa fa-wrench"></i>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-user">
|
||||
</ul>
|
||||
<a class="close-link">
|
||||
<i class="fa fa-times"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ibox-content">
|
||||
{% if emg %}
|
||||
<div class="alert alert-warning text-center">{{ emg }}</div>
|
||||
{% endif %}
|
||||
{% if smg %}
|
||||
<div class="alert alert-success text-center">{{ smg }}</div>
|
||||
{% endif %}
|
||||
<form id="assetForm" method="post" class="form-horizontal">
|
||||
{{ idc_form.name|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{{ idc_form.bandwidth|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{{ idc_form.operator|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{{ idc_form.linkman|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{{ idc_form.phone|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{{ idc_form.address|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{{ idc_form.network|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{{ idc_form.comment|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-4 col-sm-offset-5">
|
||||
<button class="btn btn-white" type="submit"> 重置 </button>
|
||||
<button class="btn btn-primary" type="sumbit"> 提交 </button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var required_fields = ["id_name"];
|
||||
required_fields.forEach(function(field) {
|
||||
$('label[for="' + field + '"]').parent().addClass("required");
|
||||
});
|
||||
|
||||
$('#assetForm').validator({
|
||||
timely: 2,
|
||||
theme: "yellow_right_effect",
|
||||
fields: {
|
||||
"j_idc": {
|
||||
rule: "required",
|
||||
tip: "输入IDC名",
|
||||
ok: "",
|
||||
msg: {required: "IDC名必须填写!"},
|
||||
data: {'data-ok':"主机名可以使用", 'data-msg-required': '主机名已正确'}
|
||||
}
|
||||
},
|
||||
valid: function(form) {
|
||||
form.submit();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
|
@ -0,0 +1,229 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load mytags %}
|
||||
{% block content %}
|
||||
{% include 'nav_cat_bar.html' %}
|
||||
|
||||
<div class="wrapper wrapper-content animated fadeInRight">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class="ibox float-e-margins" id="all">
|
||||
<div class="ibox-title">
|
||||
<h5> IDC<span class="text-info"> {{ idc.name }} </span>详细信息列表 </h5>
|
||||
<div class="ibox-tools">
|
||||
<a class="collapse-link">
|
||||
<i class="fa fa-chevron-up"></i>
|
||||
</a>
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
|
||||
<i class="fa fa-wrench"></i>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-user">
|
||||
<li><a href="#">未启用 1</a>
|
||||
</li>
|
||||
<li><a href="#">未启用 2</a>
|
||||
</li>
|
||||
</ul>
|
||||
<a class="close-link">
|
||||
<i class="fa fa-times"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ibox-content">
|
||||
{% if emg %}
|
||||
<div class="alert alert-warning text-center">{{ emg }}</div>
|
||||
{% endif %}
|
||||
{% if smg %}
|
||||
<div class="alert alert-success text-center">{{ smg }}</div>
|
||||
{% endif %}
|
||||
<div class="">
|
||||
<a target="_blank" href="/jasset/host_add" class="btn btn-sm btn-primary "> 添加主机 </a>
|
||||
</div>
|
||||
|
||||
<form id="asset_form" name="asset_form">
|
||||
<table class="table table-striped table-bordered table-hover " id="editable" name="editable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-center">
|
||||
<input id="checkall" type="checkbox" class="i-checks" name="checkall" value="checkall" data-editable='false' onclick="check_all('asset_form')">
|
||||
</th>
|
||||
<th class="text-center" name="ip"> IP地址 </th>
|
||||
<th class="text-center"> 主机名 </th>
|
||||
<th class="text-center"> IDC </th>
|
||||
<th class="text-center"> 所属主机组 </th>
|
||||
<th class="text-center"> 配置信息 </th>
|
||||
<th class="text-center"> 使用默认管理 </th>
|
||||
<th class="text-center"> 操作 </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for asset in contact_list %}
|
||||
<tr class="gradeX">
|
||||
<td class="text-center" name="id" value="{{ asset.id }}" data-editable='false'>
|
||||
<input name="id" value="{{ asset.id }}" type="checkbox" class="i-checks">
|
||||
</td>
|
||||
<td class="text-center"> {{ asset.ip }} </td>
|
||||
<td class="text-center"> {{ asset.hostname }} </td>
|
||||
<td class="text-center"> {{ asset.idc.name }} </td>
|
||||
<td class="text-center">{{ asset.group.all|group_str2 }}</td>
|
||||
<td class="text-center">{{ asset.cpu }}|{{ asset.memory }}|{{ asset.disk }}</td>
|
||||
<td class="text-center"> {{ asset.use_default_auth|bool2str }} </td>
|
||||
<td class="text-center" data-editable='false'>
|
||||
<a href="/jasset/asset_detail/?id={{ asset.id }}" class="btn btn-xs btn-primary">详情</a>
|
||||
{% ifnotequal session_role_id 0 %}
|
||||
<a href="/jasset/asset_edit/?id={{ asset.id }}" class="btn btn-xs btn-info">编辑</a>
|
||||
<a value="/jasset/asset_del/?id={{ asset.id }}" class="btn btn-xs btn-danger asset_del">删除</a>
|
||||
{% endifnotequal %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<input type="button" id="asset_del" class="btn btn-danger btn-sm" name="del_button" value="删除" />
|
||||
<a value="/jasset/asset_edit_batch/" type="button" class="btn btn-sm btn-warning iframe">修改</a>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="dataTables_paginate paging_simple_numbers" id="editable_paginate">
|
||||
<ul class="pagination" style="margin-top: 0; float: right">
|
||||
{% if keyword %}
|
||||
{% if contacts.has_previous %}
|
||||
<li class="paginate_button previous" aria-controls="editable" tabindex="0" id="editable_previous">
|
||||
<a href="?keyword={{ keyword }}&page={{ contacts.previous_page_number }}">Previous</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="paginate_button previous disabled" aria-controls="editable" tabindex="0" id="editable_previous">
|
||||
<a href="#">Previous</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% ifequal show_first 1 %}
|
||||
<li class="paginate_button" aria-controls="editable" tabindex="0"><a href="?keyword={{ keyword }}&page=1&id={{ idc.id }}" title="第1页">1...</a></li>
|
||||
{% endifequal %}
|
||||
{% for page in page_range %}
|
||||
{% ifequal current_page page %}
|
||||
<li class="paginate_button active" aria-controls="editable" tabindex="0"><a href="?keyword={{ keyword }}&page={{ page }}&id={{ idc.id }}" title="第{{ page }}页">{{ page }}</a></li>
|
||||
{% else %}
|
||||
<li class="paginate_button" aria-controls="editable" tabindex="0"><a href="?keyword={{ keyword }}&page={{ page }}&id={{ idc.id }}" title="第{{ page }}页">{{ page }}</a></li>
|
||||
{% endifequal %}
|
||||
{% endfor %}
|
||||
{% ifequal show_end 1 %}
|
||||
<li class="paginate_button" aria-controls="editable" tabindex="0"><a href="?keyword={{ keyword }}&page={{ p.num_pages }}&id={{ idc.id }}" title="第{{ page }}页">...{{ p.num_pages }}</a></li>
|
||||
{% endifequal %}
|
||||
{% if contacts.has_next %}
|
||||
<li class="paginate_button next" aria-controls="editable" tabindex="0" id="editable_next">
|
||||
<a href="?keyword={{ keyword }}&page={{ contacts.next_page_number }}&id={{ idc.id }}">Next</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="paginate_button next disabled" aria-controls="editable" tabindex="0" id="editable_next">
|
||||
<a href="#">Next</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{% else %}
|
||||
{% if contacts.has_previous %}
|
||||
<li class="paginate_button previous" aria-controls="editable" tabindex="0" id="editable_previous">
|
||||
<a href="?page={{ contacts.previous_page_number }}&id={{ idc.id }}">Previous</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="paginate_button previous disabled" aria-controls="editable" tabindex="0" id="editable_previous">
|
||||
<a href="#">Previous</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% ifequal show_first 1 %}
|
||||
<li class="paginate_button" aria-controls="editable" tabindex="0"><a href="?page=1&id={{ idc.id }}" title="第1页">1...</a></li>
|
||||
{% endifequal %}
|
||||
{% for page in page_range %}
|
||||
{% ifequal current_page page %}
|
||||
<li class="paginate_button active" aria-controls="editable" tabindex="0"><a href="?page={{ page }}&id={{ idc.id }}" title="第{{ page }}页">{{ page }}</a></li>
|
||||
{% else %}
|
||||
<li class="paginate_button" aria-controls="editable" tabindex="0"><a href="?page={{ page }}&id={{ idc.id }}" title="第{{ page }}页">{{ page }}</a></li>
|
||||
{% endifequal %}
|
||||
{% endfor %}
|
||||
{% ifequal show_end 1 %}
|
||||
<li class="paginate_button" aria-controls="editable" tabindex="0"><a href="?page={{ p.num_pages }}&id={{ idc.id }}" title="第{{ page }}页">...{{ p.num_pages }}</a></li>
|
||||
{% endifequal %}
|
||||
{% if contacts.has_next %}
|
||||
<li class="paginate_button next" aria-controls="editable" tabindex="0" id="editable_next">
|
||||
<a href="?page={{ contacts.next_page_number }}&id={{ idc.id }}">Next</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="paginate_button next disabled" aria-controls="editable" tabindex="0" id="editable_next">
|
||||
<a href="#">Next</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
$('#editable').editableTableWidget();
|
||||
});
|
||||
|
||||
function alter(form) {
|
||||
selectData = GetTableDataBox();
|
||||
if (selectData[1] != 0) {
|
||||
$.ajax({
|
||||
type: "post",
|
||||
url: "/jasset/host_edit/batch/",
|
||||
data: {"editable": selectData[0], "len_table": selectData[1]},
|
||||
success: function (data) {
|
||||
alert("修改成功");
|
||||
window.open("/jasset/host_list/", "_self");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$(".iframe").on('click', function(){
|
||||
var ids = getIDall();
|
||||
if (ids == ''){
|
||||
alert("请至少选择一行!");
|
||||
return false;
|
||||
}
|
||||
var url= $(this).attr("value") + '?id=' + ids;
|
||||
index = $.layer({
|
||||
type: 2,
|
||||
title: 'JumpServer - 批量修改主机',
|
||||
maxmin: true,
|
||||
shift: 'top',
|
||||
border: [2, 0.3, '#1AB394'],
|
||||
shade: [0.5, '#000000'],
|
||||
shadeClose: true,
|
||||
area : ['800px' , '600px'],
|
||||
iframe: {src: url},
|
||||
close: function(){
|
||||
location.replace(location.href);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('#asset_del').click(function () {
|
||||
var asset_id_all = getIDall();
|
||||
console.log(asset_id_all);
|
||||
if (asset_id_all == ''){
|
||||
alert("请至少选择一行!");
|
||||
return false;
|
||||
}
|
||||
if (confirm("确定删除")) {
|
||||
$.ajax({
|
||||
type: "post",
|
||||
data: {asset_id_all: asset_id_all},
|
||||
url: "/jasset/asset_del/?arg=batch",
|
||||
success: function () {
|
||||
parent.location.reload();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
|
@ -0,0 +1,99 @@
|
|||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
{% load bootstrap %}
|
||||
{% include 'nav_cat_bar.html' %}
|
||||
<div class="wrapper wrapper-content animated fadeInRight">
|
||||
<div class="row">
|
||||
<div class="col-lg-10">
|
||||
<div class="ibox float-e-margins">
|
||||
<div id="ibox-content" class="ibox-title">
|
||||
<h5> 填写IDC基本信息 </h5>
|
||||
<div class="ibox-tools">
|
||||
<a class="collapse-link">
|
||||
<i class="fa fa-chevron-up"></i>
|
||||
</a>
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
|
||||
<i class="fa fa-wrench"></i>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-user">
|
||||
<li><a href="#">未启用 1</a>
|
||||
</li>
|
||||
<li><a href="#">未启用 2</a>
|
||||
</li>
|
||||
</ul>
|
||||
<a class="close-link">
|
||||
<i class="fa fa-times"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ibox-content">
|
||||
{% if emg %}
|
||||
<div class="alert alert-warning text-center">{{ emg }}</div>
|
||||
{% endif %}
|
||||
{% if smg %}
|
||||
<div class="alert alert-success text-center">{{ smg }}</div>
|
||||
{% endif %}
|
||||
<form id="assetForm" method="post" class="form-horizontal">
|
||||
{{ idc_form.name|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{{ idc_form.bandwidth|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{{ idc_form.operator|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{{ idc_form.linkman|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{{ idc_form.phone|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{{ idc_form.address|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{{ idc_form.network|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{{ idc_form.comment|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-4 col-sm-offset-5">
|
||||
<button class="btn btn-white" type="submit"> 重置 </button>
|
||||
<button class="btn btn-primary" type="sumbit"> 提交 </button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var required_fields = ["id_name"];
|
||||
required_fields.forEach(function(field) {
|
||||
$('label[for="' + field + '"]').parent().addClass("required");
|
||||
});
|
||||
|
||||
$('#assetForm').validator({
|
||||
timely: 2,
|
||||
theme: "yellow_right_effect",
|
||||
fields: {
|
||||
"j_idc": {
|
||||
rule: "required",
|
||||
tip: "输入IDC名",
|
||||
ok: "",
|
||||
msg: {required: "IDC名必须填写!"},
|
||||
data: {'data-ok':"主机名可以使用", 'data-msg-required': '主机名已正确'}
|
||||
}
|
||||
},
|
||||
valid: function(form) {
|
||||
form.submit();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
|
@ -0,0 +1,115 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load mytags %}
|
||||
{% block content %}
|
||||
{% include 'nav_cat_bar.html' %}
|
||||
|
||||
<div class="wrapper wrapper-content animated fadeInRight">
|
||||
<div class="row">
|
||||
<div class="col-lg-10">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-title">
|
||||
<h5> IDC详细信息列表</h5>
|
||||
<div class="ibox-tools">
|
||||
<a class="collapse-link">
|
||||
<i class="fa fa-chevron-up"></i>
|
||||
</a>
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
|
||||
<i class="fa fa-wrench"></i>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-user">
|
||||
<li><a href="#">未启用 1</a>
|
||||
</li>
|
||||
<li><a href="#">未启用 2</a>
|
||||
</li>
|
||||
</ul>
|
||||
<a class="close-link">
|
||||
<i class="fa fa-times"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ibox-content">
|
||||
<div class="">
|
||||
<a target="_blank" href="/jasset/idc_add" class="btn btn-sm btn-primary "> 添加IDC </a>
|
||||
<form id="search_form" method="get" action="" class="pull-right mail-search">
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control input-sm" id="search_input" name="keyword" placeholder="Search">
|
||||
<input type="text" style="display: none">
|
||||
<div class="input-group-btn">
|
||||
<button id='search_btn' type="submit" class="btn btn-sm btn-primary">
|
||||
Search
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<form id="contents_form" name="contents_form">
|
||||
<table class="table table-striped table-bordered table-hover " id="editable" >
|
||||
<thead>
|
||||
<tr>
|
||||
{% ifequal session_role_id 2 %}
|
||||
<th class="text-center"><input id="checkall" type="checkbox" class="i-checks" name="checkall" value="checkall" data-editable='false' onclick="check_all('contents_form')"></th>
|
||||
{% endifequal %}
|
||||
<th class="text-center"> 机房名 </th>
|
||||
<th class="text-center"> 主机数量 </th>
|
||||
<th class="text-center"> 备注 </th>
|
||||
<th class="text-center"> 操作 </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for post in contacts.object_list %}
|
||||
<tr class="gradeX">
|
||||
<td class="text-center" name="j_id" value="{{ post.id }}" data-editable='false'><input name="id" value="{{ post.id }}" type="checkbox" class="i-checks"></td>
|
||||
<td class="text-center"> {{ post.name }} </td>
|
||||
<td class="text-center"> <a href="/jasset/idc_detail/?id={{ post.id }}">{{ post.asset_set.count }}</a> </td>
|
||||
<td class="text-center"> {{ post.comment }} </td>
|
||||
<td class="text-center">
|
||||
<a href="/jasset/idc_detail/?id={{ post.id }}" class="iframe btn btn-xs btn-primary">详情</a>
|
||||
<a href="/jasset/idc_edit/?id={{ post.id }}" class="btn btn-xs btn-info">编辑</a>
|
||||
<a href="/jasset/idc_del/?id={{ post.id }}" class="btn btn-xs btn-danger">删除</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
{% ifequal session_role_id 2 %}
|
||||
<input type="button" id="del_button" class="btn btn-danger btn-sm" name="del_button" value="删除" onclick="del('contents_form')" />
|
||||
<!--<input type="button" id="alter_button" class="btn btn-warning btn-sm" name="alter_button" value="修改" onclick="alter('contents_form')" />-->
|
||||
{% endifequal %}
|
||||
</div>
|
||||
{% include 'paginator.html' %}
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function del(form) {
|
||||
var checkboxes = document.getElementById(form);
|
||||
var id_list = {};
|
||||
var j = 0;
|
||||
for (var i = 0; i < checkboxes.elements.length; i++) {
|
||||
if (checkboxes.elements[i].type == "checkbox" && checkboxes.elements[i].checked == true && checkboxes.elements[i].value != "checkall") {
|
||||
id_list[j] = checkboxes.elements[i].value;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
if (confirm("确定删除")) {
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "/jasset/idc_del/?id=multi",
|
||||
data: {"id_list": id_list, "len_list": j},
|
||||
success: function (data) {
|
||||
window.open("/jasset/idc_list/", "_self");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
|
@ -21,7 +21,9 @@
|
|||
<li class="group_add"><a href="/jasset/group_add/">添加资产组</a></li>
|
||||
<li class="group_list group_detail group_edit"><a href="/jasset/group_list/">查看资产组</a></li>
|
||||
<li class="asset_add asset_add_multi"><a href="/jasset/asset_add/">添加资产</a></li>
|
||||
<li class="host_list host_detail host_edit"><a href="/jasset/asset_list/">查看资产<span class="label label-info pull-right">{{ host_active_num }}/{{ host_total_num}}</span></a></li>
|
||||
<li class="asset_list asset_detail asset_edit"><a href="/jasset/asset_list/">查看资产<span class="label label-info pull-right">{{ host_active_num }}/{{ host_total_num}}</span></a></li>
|
||||
<li class="idc_add"><a href="/jasset/idc_add/">添加机房</a></li>
|
||||
<li class="idc_list idc_detail idc_edit"><a href="/jasset/idc_list/">查看机房</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li id="jperm">
|
||||
|
|
Loading…
Reference in New Issue