Merge branch 'dev' of https://git.coding.net/jumpserver/jumpserver into NormalUserPageLZ
157
connect.py
|
@ -19,10 +19,11 @@ import struct, fcntl, signal, socket, select
|
|||
os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings'
|
||||
if django.get_version() != '1.6':
|
||||
django.setup()
|
||||
from jumpserver.api import ServerError, User, Asset, AssetGroup, get_object, mkdir
|
||||
from jumpserver.api import logger, Log, TtyLog
|
||||
from jumpserver.api import ServerError, User, Asset, AssetGroup, get_object, mkdir, get_asset_info, get_role
|
||||
from jumpserver.api import logger, Log, TtyLog, get_role_key
|
||||
from jperm.perm_api import gen_resource, get_group_asset_perm, get_group_user_perm
|
||||
from jumpserver.settings import LOG_DIR
|
||||
|
||||
from jperm.ansible_api import Command
|
||||
|
||||
login_user = get_object(User, username=getpass.getuser())
|
||||
VIM_FLAG = False
|
||||
|
@ -73,15 +74,15 @@ class Tty(object):
|
|||
A virtual tty class
|
||||
一个虚拟终端类,实现连接ssh和记录日志,基类
|
||||
"""
|
||||
def __init__(self, username, asset_name):
|
||||
self.username = username
|
||||
self.asset_name = asset_name
|
||||
def __init__(self, user, asset, role):
|
||||
self.username = user.username
|
||||
self.asset_name = asset.hostname
|
||||
self.ip = None
|
||||
self.port = 22
|
||||
self.channel = None
|
||||
#self.asset = get_object(Asset, name=asset_name)
|
||||
#self.user = get_object(User, username=username)
|
||||
self.role = None
|
||||
self.asset = asset
|
||||
self.user = user
|
||||
self.role = role
|
||||
self.ssh = None
|
||||
self.connect_info = None
|
||||
self.login_type = 'ssh'
|
||||
|
@ -287,7 +288,10 @@ class Tty(object):
|
|||
# 2. get 映射用户
|
||||
# 3. get 映射用户的账号,密码或者key
|
||||
# self.connect_info = {'user': '', 'asset': '', 'ip': '', 'port': 0, 'role_name': '', 'role_pass': '', 'role_key': ''}
|
||||
self.connect_info = {'user': 'a', 'asset': 'b', 'ip': '127.0.0.1', 'port': 22, 'role_name': 'root', 'role_pass': 'redhat', 'role_key': ''}
|
||||
asset_info = get_asset_info(self.asset)
|
||||
self.connect_info = {'user': self.user, 'asset': self.asset, 'ip': asset_info.get('ip'),
|
||||
'port': int(asset_info.get('port')), 'role_name': self.role.name,
|
||||
'role_pass': self.role.password, 'role_key': self.role.key_path}
|
||||
return self.connect_info
|
||||
|
||||
def get_connection(self):
|
||||
|
@ -301,18 +305,24 @@ class Tty(object):
|
|||
ssh.load_system_host_keys()
|
||||
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
try:
|
||||
if connect_info.get('role_pass'):
|
||||
ssh.connect(connect_info.get('ip'),
|
||||
port=connect_info.get('port'),
|
||||
username=connect_info.get('role_name'),
|
||||
password=connect_info.get('role_pass'),
|
||||
look_for_keys=False)
|
||||
else:
|
||||
ssh.connect(connect_info.get('ip'),
|
||||
port=connect_info.get('port'),
|
||||
username=connect_info.get('role_name'),
|
||||
key_filename=connect_info.get('role_key'),
|
||||
look_for_keys=False)
|
||||
role_key = get_role_key(self.user, self.role)
|
||||
if role_key and os.path.isfile(role_key):
|
||||
try:
|
||||
ssh.connect(connect_info.get('ip'),
|
||||
port=connect_info.get('port'),
|
||||
username=connect_info.get('role_name'),
|
||||
key_filename=role_key,
|
||||
look_for_keys=False)
|
||||
self.ssh = ssh
|
||||
return ssh
|
||||
except paramiko.ssh_exception.AuthenticationException, paramiko.ssh_exception.SSHException:
|
||||
pass
|
||||
|
||||
ssh.connect(connect_info.get('ip'),
|
||||
port=connect_info.get('port'),
|
||||
username=connect_info.get('role_name'),
|
||||
password=connect_info.get('role_pass'),
|
||||
look_for_keys=False)
|
||||
|
||||
except paramiko.ssh_exception.AuthenticationException, paramiko.ssh_exception.SSHException:
|
||||
raise ServerError('认证失败 Authentication Error.')
|
||||
|
@ -458,28 +468,12 @@ class SshTty(Tty):
|
|||
channel.close()
|
||||
ssh.close()
|
||||
|
||||
def execute(self, cmd):
|
||||
"""
|
||||
execute cmd on the asset
|
||||
执行命令
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def print_user_asset_group_info(user):
|
||||
asset_groups = AssetGroup.objects.all()
|
||||
for asset_group in asset_groups:
|
||||
if asset_group.comment:
|
||||
print '[%-2s] %-10s %s' % (asset_group.id, asset_group.name, asset_group.comment)
|
||||
else:
|
||||
print '[%-2s] %-10s' % (asset_group.id, asset_group.name)
|
||||
print
|
||||
|
||||
|
||||
class Nav(object):
|
||||
def __init__(self, user):
|
||||
self.user = user
|
||||
self.search_result = {}
|
||||
self.user_perm = {}
|
||||
|
||||
@staticmethod
|
||||
def print_nav():
|
||||
|
@ -510,7 +504,9 @@ class Nav(object):
|
|||
|
||||
def search(self, str_r=''):
|
||||
gid_pattern = re.compile(r'^g\d+$')
|
||||
user_asset_all = list(Asset.objects.all())
|
||||
if not self.user_perm:
|
||||
self.user_perm = get_group_user_perm(self.user)
|
||||
user_asset_all = self.user_perm.get('asset').keys()
|
||||
user_asset_search = []
|
||||
if str_r:
|
||||
if gid_pattern.match(str_r):
|
||||
|
@ -523,13 +519,15 @@ class Nav(object):
|
|||
user_asset_search = user_asset_all
|
||||
|
||||
self.search_result = dict(zip(range(len(user_asset_search)), user_asset_search))
|
||||
|
||||
print '\033[32m[%-3s] %-15s %-15s %-5s %-5s %s \033[0m' % ('ID', 'AssetName', 'IP', 'Port', 'Role', 'Comment')
|
||||
print '\033[32m[%-3s] %-15s %-15s %-5s %-10s %s \033[0m' % ('ID', 'AssetName', 'IP', 'Port', 'Role', 'Comment')
|
||||
for index, asset in self.search_result.items():
|
||||
asset_info = get_asset_info(asset)
|
||||
role = [str(role.name) for role in self.user_perm.get('asset').get(asset).get('role')]
|
||||
if asset.comment:
|
||||
print '[%-3s] %-15s %-15s %-5s %-5s %s' % (index, 'asset_name'+str(index), asset.ip, asset.port, 'role', asset.comment)
|
||||
print '[%-3s] %-15s %-15s %-5s %-10s %s' % (index, asset.hostname, asset.ip, asset_info.get('port'),
|
||||
role, asset.comment)
|
||||
else:
|
||||
print '[%-3s] %-15s %-15s %-5s %-5s' % (index, 'asset_name'+str(index), asset.ip, asset.port, 'role')
|
||||
print '[%-3s] %-15s %-15s %-5s %-10s' % (index, asset.hostname, asset.ip, asset_info.get('port'), role)
|
||||
print
|
||||
|
||||
@staticmethod
|
||||
|
@ -544,6 +542,50 @@ class Nav(object):
|
|||
print '[%-3s] %-15s' % (asset_group.id, asset_group.name)
|
||||
print
|
||||
|
||||
def exec_cmd(self):
|
||||
self.search()
|
||||
while True:
|
||||
print "请输入主机名、IP或ansile支持的pattern, q退出"
|
||||
try:
|
||||
pattern = raw_input("\033[1;32mPattern>:\033[0m ").strip()
|
||||
if pattern == 'q':
|
||||
break
|
||||
else:
|
||||
if not self.user_perm:
|
||||
self.user_perm = get_group_user_perm(self.user)
|
||||
res = gen_resource(self.user, perm=self.user_perm)
|
||||
cmd = Command(res)
|
||||
logger.debug(res)
|
||||
for inv in cmd.inventory.get_hosts(pattern=pattern):
|
||||
print inv.name
|
||||
confirm_host = raw_input("\033[1;32mIs that [y/n]>:\033[0m ").strip()
|
||||
if confirm_host == 'y':
|
||||
while True:
|
||||
print "请输入执行的命令, 按q退出"
|
||||
command = raw_input("\033[1;32mCmds>:\033[0m ").strip()
|
||||
if command == 'q':
|
||||
break
|
||||
result = cmd.run(module_name='shell', command=command, pattern=pattern)
|
||||
for k, v in result.items():
|
||||
if k == 'ok':
|
||||
for host, output in v.items():
|
||||
color_print("%s => %s" % (host, 'Ok'), 'green')
|
||||
print output
|
||||
print
|
||||
else:
|
||||
for host, output in v.items():
|
||||
color_print("%s => %s" % (host, k), 'red')
|
||||
color_print(output, 'red')
|
||||
print
|
||||
print "=" * 20
|
||||
print
|
||||
else:
|
||||
continue
|
||||
|
||||
except EOFError:
|
||||
print
|
||||
break
|
||||
|
||||
|
||||
def main():
|
||||
"""
|
||||
|
@ -575,14 +617,35 @@ def main():
|
|||
nav.print_asset_group()
|
||||
continue
|
||||
elif option in ['E', 'e']:
|
||||
# exec_cmd_servers(login_name)
|
||||
pass
|
||||
nav.exec_cmd()
|
||||
continue
|
||||
elif option in ['Q', 'q', 'exit']:
|
||||
sys.exit()
|
||||
else:
|
||||
try:
|
||||
asset = nav.search_result[int(option)]
|
||||
ssh_tty = SshTty('a', 'b')
|
||||
roles = get_role(login_user, asset)
|
||||
if len(roles) > 1:
|
||||
role_check = dict(zip(range(len(roles)), roles))
|
||||
print role_check
|
||||
for index, role in role_check.items():
|
||||
print "[%s] %s" % (index, role.name)
|
||||
print "输入角色ID, q退出"
|
||||
try:
|
||||
role_index = raw_input("\033[1;32mID>:\033[0m ").strip()
|
||||
if role_index == 'q':
|
||||
continue
|
||||
else:
|
||||
role = role_check[int(role_index)]
|
||||
except IndexError:
|
||||
color_print('请输入正确ID', 'red')
|
||||
continue
|
||||
elif len(roles) == 1:
|
||||
role = roles[0]
|
||||
else:
|
||||
color_print('没有映射用户', 'red')
|
||||
continue
|
||||
ssh_tty = SshTty(login_user, asset, role)
|
||||
ssh_tty.connect()
|
||||
except (KeyError, ValueError):
|
||||
color_print('请输入正确ID', 'red')
|
||||
|
|
|
@ -238,7 +238,6 @@ def db_asset_alert(asset, username, alert_dic):
|
|||
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''
|
||||
|
@ -386,9 +385,9 @@ def excel_to_db(excel_file):
|
|||
if row:
|
||||
ip, port, hostname, use_default_auth, username, password, group = row
|
||||
use_default_auth = 1 if use_default_auth == u'默认' else 0
|
||||
if get_object(Asset, ip=ip):
|
||||
if get_object(Asset, hostname=hostname):
|
||||
continue
|
||||
if ip and port:
|
||||
if hostname:
|
||||
asset = Asset(ip=ip,
|
||||
port=port,
|
||||
hostname=hostname,
|
||||
|
|
|
@ -28,5 +28,10 @@ class IdcForm(forms.ModelForm):
|
|||
class Meta:
|
||||
model = IDC
|
||||
fields = ['name', "bandwidth", "operator", 'linkman', 'phone', 'address', 'network', 'comment']
|
||||
widgets = {
|
||||
'name': forms.TextInput(attrs={'placeholder': 'Name'}),
|
||||
'network': forms.Textarea(
|
||||
attrs={'placeholder': '192.168.1.0/24\n192.168.2.0/24'})
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ class IDC(models.Model):
|
|||
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, null=True)
|
||||
operator = models.IntegerField(blank=True, null=True, verbose_name=u"运营商")
|
||||
operator = models.CharField(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):
|
||||
|
@ -57,17 +57,17 @@ class Asset(models.Model):
|
|||
"""
|
||||
asset modle
|
||||
"""
|
||||
ip = models.GenericIPAddressField(unique=True, verbose_name=u"主机IP")
|
||||
ip = models.GenericIPAddressField(blank=True, null=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(verbose_name=u"端口号")
|
||||
hostname = models.CharField(unique=True, max_length=128, verbose_name=u"主机名")
|
||||
port = models.IntegerField(blank=True, null=True, verbose_name=u"端口号")
|
||||
group = models.ManyToManyField(AssetGroup, blank=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'远控卡')
|
||||
remote_ip = models.CharField(max_length=16, blank=True, null=True, verbose_name=u'远控卡IP')
|
||||
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'内存')
|
||||
|
|
|
@ -17,13 +17,11 @@ urlpatterns = patterns('',
|
|||
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'^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),
|
||||
|
|
163
jasset/views.py
|
@ -26,13 +26,13 @@ def group_add(request):
|
|||
|
||||
try:
|
||||
if not name:
|
||||
error = u'组名不能为空'
|
||||
raise ServerError(error)
|
||||
emg = u'组名不能为空'
|
||||
raise ServerError(emg)
|
||||
|
||||
asset_group_test = get_object(AssetGroup, name=name)
|
||||
if asset_group_test:
|
||||
error = u"该组名 %s 已存在" % name
|
||||
raise ServerError(error)
|
||||
emg = u"该组名 %s 已存在" % name
|
||||
raise ServerError(emg)
|
||||
|
||||
except ServerError:
|
||||
pass
|
||||
|
@ -87,21 +87,6 @@ def group_edit(request):
|
|||
return my_render('jasset/group_edit.html', locals(), request)
|
||||
|
||||
|
||||
@require_role('admin')
|
||||
def group_detail(request):
|
||||
"""
|
||||
Group detail view
|
||||
主机组详情
|
||||
"""
|
||||
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):
|
||||
"""
|
||||
|
@ -147,13 +132,13 @@ def asset_add(request):
|
|||
af = AssetForm()
|
||||
if request.method == 'POST':
|
||||
af_post = AssetForm(request.POST)
|
||||
print af_post
|
||||
ip = request.POST.get('ip', '')
|
||||
hostname = request.POST.get('hostname', '')
|
||||
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
|
||||
if Asset.objects.filter(hostname=str(hostname)):
|
||||
error = u'该主机名 %s 已存在!' % hostname
|
||||
raise ServerError(error)
|
||||
|
||||
except ServerError:
|
||||
|
@ -165,13 +150,15 @@ def asset_add(request):
|
|||
password = request.POST.get('password', '')
|
||||
password_encode = password
|
||||
asset_save.password = password_encode
|
||||
if not ip:
|
||||
asset_save.ip = hostname
|
||||
asset_save.is_active = True if is_active else False
|
||||
asset_save.save()
|
||||
af_post.save_m2m()
|
||||
|
||||
msg = u'主机 %s 添加成功' % ip
|
||||
msg = u'主机 %s 添加成功' % hostname
|
||||
else:
|
||||
esg = u'主机 %s 添加失败' % ip
|
||||
esg = u'主机 %s 添加失败' % hostname
|
||||
|
||||
return my_render('jasset/asset_add.html', locals(), request)
|
||||
|
||||
|
@ -215,17 +202,21 @@ def asset_edit(request):
|
|||
asset_id = request.GET.get('id', '')
|
||||
username = request.session.get('username', 'admin')
|
||||
asset = get_object(Asset, id=asset_id)
|
||||
asset_old = copy_model_instance(asset)
|
||||
if asset:
|
||||
password_old = asset.password
|
||||
# asset_old = copy_model_instance(asset)
|
||||
af = AssetForm(instance=asset)
|
||||
if request.method == 'POST':
|
||||
af_post = AssetForm(request.POST, instance=asset)
|
||||
ip = request.POST.get('ip', '')
|
||||
use_default_auth = request.POST.get('use_default_auth')
|
||||
hostname = request.POST.get('hostname', '')
|
||||
password = request.POST.get('password', '')
|
||||
use_default_auth = request.POST.get('use_default_auth', '')
|
||||
|
||||
try:
|
||||
asset_test = get_object(Asset, ip=ip)
|
||||
asset_test = get_object(Asset, hostname=hostname)
|
||||
if asset_test and asset_id != unicode(asset_test.id):
|
||||
error = u'该IP %s 已存在!' % ip
|
||||
error = u'该主机名 %s 已存在!' % hostname
|
||||
raise ServerError(error)
|
||||
except ServerError:
|
||||
pass
|
||||
|
@ -235,6 +226,10 @@ def asset_edit(request):
|
|||
if use_default_auth:
|
||||
af_save.username = ''
|
||||
af_save.password = ''
|
||||
else:
|
||||
if password_old != password:
|
||||
password_encode = CRYPTOR.encrypt(password)
|
||||
af_save.password = password_encode
|
||||
af_save.save()
|
||||
af_post.save_m2m()
|
||||
# asset_new = get_object(Asset, id=asset_id)
|
||||
|
@ -266,8 +261,19 @@ def asset_list(request):
|
|||
status = request.GET.get('status', '')
|
||||
keyword = request.GET.get('keyword', '')
|
||||
export = request.GET.get("export", False)
|
||||
group_id = request.GET.get("group_id", '')
|
||||
idc_id = request.GET.get("idc_id", '')
|
||||
if group_id:
|
||||
group = get_object(AssetGroup, id=group_id)
|
||||
if group:
|
||||
asset_find = Asset.objects.filter(group=group)
|
||||
elif idc_id:
|
||||
idc = get_object(IDC, id=idc_id)
|
||||
if idc:
|
||||
asset_find = Asset.objects.filter(idc=idc)
|
||||
else:
|
||||
asset_find = Asset.objects.all()
|
||||
|
||||
asset_find = Asset.objects.all()
|
||||
if idc_name:
|
||||
asset_find = asset_find.filter(idc__name__contains=idc_name)
|
||||
|
||||
|
@ -305,7 +311,82 @@ def asset_list(request):
|
|||
@require_role('admin')
|
||||
def asset_edit_batch(request):
|
||||
af = AssetForm()
|
||||
name = request.session.get('username', 'admin')
|
||||
asset_group_all = AssetGroup.objects.all()
|
||||
|
||||
if request.method == 'POST':
|
||||
env = request.POST.get('env', '')
|
||||
idc_id = request.POST.get('idc', '')
|
||||
port = request.POST.get('port', '')
|
||||
use_default_auth = request.POST.get('use_default_auth', '')
|
||||
username = request.POST.get('username', '')
|
||||
password = request.POST.get('password', '')
|
||||
group = request.POST.getlist('group', [])
|
||||
cabinet = request.POST.get('cabinet', '')
|
||||
comment = request.POST.get('comment', '')
|
||||
asset_id_all = unicode(request.GET.get('asset_id_all', ''))
|
||||
asset_id_all = asset_id_all.split(',')
|
||||
for asset_id in asset_id_all:
|
||||
alert_list = []
|
||||
asset = get_object(Asset, id=asset_id)
|
||||
if asset:
|
||||
if env:
|
||||
if asset.env != env:
|
||||
asset.env = env
|
||||
alert_list.append([u'运行环境', asset.env, env])
|
||||
if idc_id:
|
||||
idc = get_object(IDC, id=idc_id)
|
||||
name_old = asset.idc.name if asset.idc else u''
|
||||
if idc and idc.name != name_old:
|
||||
asset.idc = idc
|
||||
alert_list.append([u'机房', name_old, idc.name])
|
||||
if port:
|
||||
if unicode(asset.port) != port:
|
||||
asset.port = port
|
||||
alert_list.append([u'端口号', asset.port, port])
|
||||
|
||||
if use_default_auth:
|
||||
if use_default_auth == 'default':
|
||||
asset.use_default_auth = 1
|
||||
asset.username = ''
|
||||
asset.password = ''
|
||||
alert_list.append([u'使用默认管理账号', asset.use_default_auth, u'默认'])
|
||||
elif use_default_auth == 'user_passwd':
|
||||
asset.use_default_auth = 0
|
||||
asset.username = username
|
||||
password_encode = CRYPTOR.encrypt(password)
|
||||
asset.password = password_encode
|
||||
alert_list.append([u'使用默认管理账号', asset.use_default_auth, username])
|
||||
if group:
|
||||
group_new, group_old, group_new_name, group_old_name = [], asset.group.all(), [], []
|
||||
for group_id in group:
|
||||
g = get_object(AssetGroup, id=group_id)
|
||||
if g:
|
||||
group_new.append(g)
|
||||
if not set(group_new) < set(group_old):
|
||||
group_instance = list(set(group_new) | set(group_old))
|
||||
for g in group_instance:
|
||||
group_new_name.append(g.name)
|
||||
for g in group_old:
|
||||
group_old_name.append(g.name)
|
||||
asset.group = group_instance
|
||||
alert_list.append([u'主机组', ','.join(group_old_name), ','.join(group_new_name)])
|
||||
if cabinet:
|
||||
if asset.cabinet != cabinet:
|
||||
asset.cabinet = cabinet
|
||||
alert_list.append([u'机柜号', asset.cabinet, cabinet])
|
||||
if comment:
|
||||
if asset.comment != comment:
|
||||
asset.comment = comment
|
||||
alert_list.append([u'备注', asset.comment, comment])
|
||||
asset.save()
|
||||
|
||||
if alert_list:
|
||||
username = unicode(name) + ' - ' + u'批量'
|
||||
print alert_list
|
||||
AssetRecord.objects.create(asset=asset, username=username, content=alert_list)
|
||||
return HttpResponse('ok')
|
||||
|
||||
return my_render('jasset/asset_edit_batch.html', locals(), request)
|
||||
|
||||
|
||||
|
@ -437,29 +518,17 @@ def idc_edit(request):
|
|||
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('id', '')
|
||||
idc = get_object(IDC, id=uuid)
|
||||
if idc:
|
||||
idc.delete()
|
||||
idc_ids = request.GET.get('id', '')
|
||||
idc_id_list = idc_ids.split(',')
|
||||
|
||||
for idc_id in idc_id_list:
|
||||
IDC.objects.filter(id=idc_id).delete()
|
||||
|
||||
return HttpResponseRedirect('/jasset/idc_list/')
|
||||
|
||||
|
||||
|
|
|
@ -79,14 +79,17 @@ class MyInventory(object):
|
|||
for host in hosts:
|
||||
# set connection variables
|
||||
hostname = host.get("hostname")
|
||||
hostip = host.get('ip', hostname)
|
||||
hostport = host.get("port")
|
||||
username = host.get("username")
|
||||
password = host.get("password")
|
||||
ssh_key = host.get("ssh_key")
|
||||
my_host = Host(name=hostname, port=hostport)
|
||||
my_host.set_variable('ansible_ssh_host', hostname)
|
||||
my_host.set_variable('ansible_ssh_host', hostip)
|
||||
my_host.set_variable('ansible_ssh_port', hostport)
|
||||
my_host.set_variable('ansible_ssh_user', username)
|
||||
my_host.set_variable('ansible_ssh_pass', password)
|
||||
my_host.set_variable('ansible_ssh_private_key_file', ssh_key)
|
||||
# set other variables
|
||||
for key, value in host.iteritems():
|
||||
if key not in ["hostname", "port", "username", "password"]:
|
||||
|
@ -107,43 +110,72 @@ class MyInventory(object):
|
|||
self.add_group(hosts_and_vars.get("hosts"), groupname, hosts_and_vars.get("vars"))
|
||||
|
||||
|
||||
class MyRunner(MyInventory):
|
||||
"""
|
||||
This is a General object for parallel execute modules.
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(MyRunner, self).__init__(*args, **kwargs)
|
||||
self.results = {}
|
||||
|
||||
def run(self, module_name, module_args='', timeout=10, forks=10, pattern='',
|
||||
sudo=False, sudo_user='root', sudo_pass=''):
|
||||
"""
|
||||
run module from andible ad-hoc.
|
||||
module_name: ansible module_name
|
||||
module_args: ansible module args
|
||||
"""
|
||||
hoc = Runner(module_name=module_name,
|
||||
module_args=module_args,
|
||||
timeout=timeout,
|
||||
inventory=self.inventory,
|
||||
pattern=pattern,
|
||||
forks=forks,
|
||||
become=sudo,
|
||||
become_method='sudo',
|
||||
become_user=sudo_user,
|
||||
become_pass=sudo_pass
|
||||
)
|
||||
self.results = hoc.run()
|
||||
return self.results
|
||||
|
||||
|
||||
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 = ''
|
||||
self.results = {}
|
||||
|
||||
def run(self, command, module_name="command", timeout=10, forks=10, group='default_group', pattern='*'):
|
||||
def run(self, command, module_name="command", timeout=10, forks=10, pattern='*'):
|
||||
"""
|
||||
run command from andible ad-hoc.
|
||||
command : 必须是一个需要执行的命令字符串, 比如
|
||||
'uname -a'
|
||||
"""
|
||||
data = {}
|
||||
|
||||
if module_name not in ["raw", "command", "shell"]:
|
||||
raise CommandValueError("module_name",
|
||||
"module_name must be of the 'raw, command, shell'")
|
||||
"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,
|
||||
pattern=pattern,
|
||||
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}
|
||||
data['ok'] = self.stdout
|
||||
if self.stderr:
|
||||
data['err'] = self.stderr
|
||||
if self.dark:
|
||||
data['dark'] = self.dark
|
||||
|
||||
return data
|
||||
|
||||
@property
|
||||
def raw_results(self):
|
||||
|
@ -174,7 +206,7 @@ class Command(MyInventory):
|
|||
result = {}
|
||||
all = self.results.get("contacted")
|
||||
for key, value in all.iteritems():
|
||||
result[key] = value.get("stdout")
|
||||
result[key] = value.get("stdout")
|
||||
return result
|
||||
|
||||
@property
|
||||
|
@ -185,7 +217,8 @@ class Command(MyInventory):
|
|||
result = {}
|
||||
all = self.results.get("contacted")
|
||||
for key, value in all.iteritems():
|
||||
result[key] = {
|
||||
if value.get("stderr") or value.get("warnings"):
|
||||
result[key] = {
|
||||
"stderr": value.get("stderr"),
|
||||
"warnings": value.get("warnings"),}
|
||||
return result
|
||||
|
@ -371,7 +404,7 @@ class Tasks(Command):
|
|||
|
||||
result[key] = {
|
||||
"all_ip": setup.get("ansible_all_ipv4_addresses"),
|
||||
"hostname" : setup.get("ansible_hostname" ),
|
||||
"hostname" : setup.get("ansible_hostname"),
|
||||
"default_ip": setup.get("ansible_default_ipv4").get("address"),
|
||||
"default_mac": setup.get("ansible_default_ipv4").get("macaddress"),
|
||||
"product_name": setup.get("ansible_product_name"),
|
||||
|
@ -388,8 +421,6 @@ class Tasks(Command):
|
|||
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.
|
||||
|
@ -408,7 +439,6 @@ class CustomAggregateStats(callbacks.AggregateStats):
|
|||
|
||||
self.results.append(runner_results)
|
||||
|
||||
|
||||
def summarize(self, host):
|
||||
"""
|
||||
Return information about a particular host
|
||||
|
|
|
@ -5,20 +5,6 @@ from jasset.models import Asset, AssetGroup
|
|||
from juser.models import User, UserGroup
|
||||
|
||||
|
||||
class PermLog(models.Model):
|
||||
datetime = models.DateTimeField(auto_now_add=True)
|
||||
action = models.CharField(max_length=100, null=True, blank=True, default='')
|
||||
results = models.CharField(max_length=1000, null=True, blank=True, default='')
|
||||
is_success = models.BooleanField(default=False)
|
||||
is_finish = models.BooleanField(default=False)
|
||||
|
||||
|
||||
class SysUser(models.Model):
|
||||
username = models.CharField(max_length=100)
|
||||
password = models.CharField(max_length=100)
|
||||
comment = models.CharField(max_length=100, null=True, blank=True, default='')
|
||||
|
||||
|
||||
class PermRole(models.Model):
|
||||
name = models.CharField(max_length=100, unique=True)
|
||||
comment = models.CharField(max_length=100, null=True, blank=True, default='')
|
||||
|
@ -41,4 +27,4 @@ class PermRule(models.Model):
|
|||
role = models.ManyToManyField(PermRole, related_name='perm_rule')
|
||||
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
return self.name
|
||||
|
|
|
@ -1,15 +1,163 @@
|
|||
# coding: utf-8
|
||||
|
||||
|
||||
from django.db.models.query import QuerySet
|
||||
from jumpserver.api import *
|
||||
import uuid
|
||||
import re
|
||||
from jumpserver.tasks import playbook_run
|
||||
|
||||
from jumpserver.models import Setting
|
||||
from jperm.models import PermLog
|
||||
|
||||
from jperm.models import PermRole
|
||||
from jperm.models import PermRule
|
||||
|
||||
|
||||
def get_group_user_perm(ob):
|
||||
"""
|
||||
ob为用户或用户组
|
||||
获取用户、用户组授权的资产、资产组
|
||||
return:
|
||||
{’asset_group': {
|
||||
asset_group1: {'asset': [], 'role': [role1, role2], 'rule': [rule1, rule2]},
|
||||
asset_group2: {'asset: [], 'role': [role1, role2], 'rule': [rule1, rule2]},
|
||||
}
|
||||
'asset':{
|
||||
asset1: {'role': [role1, role2], 'rule': [rule1, rule2]},
|
||||
asset2: {'role': [role1, role2], 'rule': [rule1, rule2]},
|
||||
}
|
||||
]},
|
||||
'rule':[rule1, rule2,]
|
||||
}
|
||||
"""
|
||||
perm = {}
|
||||
if isinstance(ob, User):
|
||||
rule_all = PermRule.objects.filter(user=ob)
|
||||
elif isinstance(ob, UserGroup):
|
||||
rule_all = PermRule.objects.filter(user_group=ob)
|
||||
else:
|
||||
rule_all = []
|
||||
|
||||
perm['rule'] = rule_all
|
||||
perm_asset_group = perm['asset_group'] = {}
|
||||
perm_asset = perm['asset'] = {}
|
||||
for rule in rule_all:
|
||||
asset_groups = rule.asset_group.all()
|
||||
assets = rule.asset.all()
|
||||
|
||||
# 获取一个规则用户授权的资产
|
||||
for asset in assets:
|
||||
if perm_asset.get(asset):
|
||||
perm_asset[asset].get('role', set()).update(set(rule.role.all()))
|
||||
perm_asset[asset].get('rule', set()).add(rule)
|
||||
else:
|
||||
perm_asset[asset] = {'role': set(rule.role.all()), 'rule': set([rule])}
|
||||
|
||||
# 获取一个规则用户授权的资产组
|
||||
for asset_group in asset_groups:
|
||||
asset_group_assets = asset_group.asset_set.all()
|
||||
if perm_asset_group.get(asset_group):
|
||||
perm_asset_group[asset_group].get('role', set()).update(set(rule.role.all()))
|
||||
perm_asset_group[asset_group].get('rule', set()).add(rule)
|
||||
else:
|
||||
perm_asset_group[asset_group] = {'role': set(rule.role.all()), 'rule': set([rule]),
|
||||
'asset': asset_group_assets}
|
||||
|
||||
# 将资产组中的资产添加到资产授权中
|
||||
for asset in asset_group_assets:
|
||||
if perm_asset.get(asset):
|
||||
perm_asset[asset].get('role', set()).update(perm_asset_group[asset_group].get('role', set()))
|
||||
perm_asset[asset].get('rule', set()).update(perm_asset_group[asset_group].get('rule', set()))
|
||||
else:
|
||||
perm_asset[asset] = {'role': perm_asset_group[asset_group].get('role', set()),
|
||||
'rule': perm_asset_group[asset_group].get('rule', set())}
|
||||
return perm
|
||||
|
||||
|
||||
def get_group_asset_perm(ob):
|
||||
"""
|
||||
ob为资产或资产组
|
||||
获取资产,资产组授权的用户,用户组
|
||||
return:
|
||||
{’user_group': {
|
||||
user_group1: {'user': [], 'role': [role1, role2], 'rule': [rule1, rule2]},
|
||||
user_group2: {'user: [], 'role': [role1, role2], 'rule': [rule1, rule2]},
|
||||
}
|
||||
'user':{
|
||||
user1: {'role': [role1, role2], 'rule': [rule1, rule2]},
|
||||
user2: {'role': [role1, role2], 'rule': [rule1, rule2]},
|
||||
}
|
||||
]},
|
||||
'rule':[rule1, rule2,]
|
||||
}
|
||||
"""
|
||||
perm = {}
|
||||
if isinstance(ob, Asset):
|
||||
rule_all = PermRule.objects.filter(asset=ob)
|
||||
elif isinstance(ob, AssetGroup):
|
||||
rule_all = PermRule.objects.filter(asset_group=ob)
|
||||
else:
|
||||
rule_all = []
|
||||
|
||||
perm['rule'] = rule_all
|
||||
perm_user_group = perm['user_group'] = {}
|
||||
perm_user = perm['user'] = {}
|
||||
for rule in rule_all:
|
||||
user_groups = rule.user_group.all()
|
||||
users = rule.user.all()
|
||||
|
||||
# 获取一个规则资产的用户
|
||||
for user in users:
|
||||
if perm_user.get(user):
|
||||
perm_user[user].get('role', set()).update(set(rule.role.all()))
|
||||
perm_user[user].get('rule', set()).add(rule)
|
||||
else:
|
||||
perm_user[user] = {'role': set(rule.role.all()), 'rule': set([rule])}
|
||||
|
||||
# 获取一个规则资产授权的用户组
|
||||
for user_group in user_groups:
|
||||
user_group_users = user_group.user_set.all()
|
||||
if perm_user_group.get(user_group):
|
||||
perm_user_group[user_group].get('role', set()).update(set(rule.role.all()))
|
||||
perm_user_group[user_group].get('rule', set()).add(rule)
|
||||
else:
|
||||
perm_user_group[user_group] = {'role': set(rule.role.all()), 'rule': set([rule]),
|
||||
'user': user_group_users}
|
||||
|
||||
# 将用户组中的资产添加到用户授权中
|
||||
for user in user_group_users:
|
||||
if perm_user.get(user):
|
||||
perm_user[user].get('role', set()).update(perm_user_group[user_group].get('role', set()))
|
||||
perm_user[user].get('rule', set()).update(perm_user_group[user_group].get('rule', set()))
|
||||
else:
|
||||
perm_user[user] = {'role': perm_user_group[user_group].get('role', set()),
|
||||
'rule': perm_user_group[user_group].get('rule', set())}
|
||||
return perm
|
||||
|
||||
|
||||
def gen_resource(ob, perm=None):
|
||||
"""
|
||||
ob为用户或资产列表或资产queryset
|
||||
生成MyInventory需要的 resource文件
|
||||
"""
|
||||
res = []
|
||||
if isinstance(ob, User):
|
||||
if not perm:
|
||||
perm = get_group_user_perm(ob)
|
||||
|
||||
for asset, asset_info in perm.get('asset').items():
|
||||
asset_info = get_asset_info(asset)
|
||||
info = {'hostname': asset.hostname, 'ip': asset.ip, 'port': asset_info.get('port', 22)}
|
||||
try:
|
||||
role = sorted(list(perm.get('asset').get(asset).get('role')))[0]
|
||||
except IndexError:
|
||||
continue
|
||||
info['username'] = role.name
|
||||
info['password'] = role.password
|
||||
info['ssh_key'] = get_role_key(ob, role)
|
||||
res.append(info)
|
||||
elif isinstance(ob, (list, QuerySet)):
|
||||
for asset in ob:
|
||||
info = get_asset_info(asset)
|
||||
res.append(info)
|
||||
return res
|
||||
|
||||
|
||||
def get_object_list(model, id_list):
|
||||
|
@ -22,267 +170,6 @@ def get_object_list(model, id_list):
|
|||
return object_list
|
||||
|
||||
|
||||
def get_rand_file_path(base_dir=os.path.join(BASE_DIR, 'tmp')):
|
||||
"""获取随机文件路径"""
|
||||
filename = uuid.uuid1().hex
|
||||
return os.path.join(base_dir, filename)
|
||||
|
||||
|
||||
def get_inventory(host_group):
|
||||
"""生成资产表库存清单"""
|
||||
path = get_rand_file_path()
|
||||
f = open(path, 'w')
|
||||
for group, host_list in host_group.items():
|
||||
f.write('[%s]\n' % group)
|
||||
for ip in host_list:
|
||||
asset = get_object(Asset, ip=ip)
|
||||
if asset.use_default:
|
||||
f.write('%s\n' % ip)
|
||||
else:
|
||||
f.write('%s ansible_ssh_port=%s ansible_ssh_user=%s ansible_ssh_pass=%s\n' %
|
||||
(ip, asset.port, asset.username, CRYPTOR.decrypt(asset.password)))
|
||||
f.close()
|
||||
return path
|
||||
|
||||
|
||||
def get_playbook(template, var):
|
||||
"""根据playbook模板,生成playbook"""
|
||||
str_playbook = open(template).read()
|
||||
for k, v in var.items():
|
||||
str_playbook = re.sub(r'%s' % k, v, str_playbook) # 正则来替换传入的字符
|
||||
path = get_rand_file_path()
|
||||
f = open(path, 'w')
|
||||
f.write(str_playbook)
|
||||
return path
|
||||
|
||||
|
||||
def perm_user_api(perm_info):
|
||||
"""
|
||||
用户授权api,通过调用ansible API完成用户新建等,传入参数必须如下,列表中可以是对象,也可以是用户名和ip
|
||||
perm_info = {'del': {'users': [],
|
||||
'assets': [],
|
||||
},
|
||||
'new': {'users': [],
|
||||
'assets': []}}
|
||||
"""
|
||||
log = PermLog(action=perm_info.get('action', ''))
|
||||
try:
|
||||
new_users = perm_info.get('new', {}).get('users', [])
|
||||
new_assets = perm_info.get('new', {}).get('assets', [])
|
||||
del_users = perm_info.get('del', {}).get('users', [])
|
||||
del_assets = perm_info.get('del', {}).get('assets', [])
|
||||
print new_users, new_assets
|
||||
except IndexError:
|
||||
raise ServerError("Error: function perm_user_api传入参数错误")
|
||||
|
||||
try:
|
||||
new_ip = [asset.ip for asset in new_assets if isinstance(asset, Asset)]
|
||||
del_ip = [asset.ip for asset in del_assets if isinstance(asset, Asset)]
|
||||
new_username = [user.username for user in new_users]
|
||||
del_username = [user.username for user in del_users]
|
||||
except IndexError:
|
||||
raise ServerError("Error: function perm_user_api传入参数类型错误")
|
||||
|
||||
host_group = {'new': new_ip, 'del': del_ip}
|
||||
inventory = get_inventory(host_group)
|
||||
|
||||
the_new_users = ','.join(new_username)
|
||||
the_del_users = ','.join(del_username)
|
||||
|
||||
playbook = get_playbook(os.path.join(BASE_DIR, 'keys/../playbook', 'user_perm.yaml'),
|
||||
{'the_new_group': 'new', 'the_del_group': 'del',
|
||||
'the_new_users': the_new_users, 'the_del_users': the_del_users,
|
||||
'KEY_DIR': os.path.join(SSH_KEY_DIR, 'sysuser')})
|
||||
|
||||
print playbook, inventory
|
||||
|
||||
settings = get_object(Setting, name='default')
|
||||
results = playbook_run(inventory, playbook, settings)
|
||||
if not results.get('failures', 1) and not results.get('unreachable', ''):
|
||||
is_success = True
|
||||
else:
|
||||
is_success = False
|
||||
|
||||
log.results = results
|
||||
log.is_finish = True
|
||||
log.is_success = is_success
|
||||
log.save()
|
||||
return results
|
||||
|
||||
|
||||
def user_group_permed(user_group):
|
||||
assets = user_group.asset.all()
|
||||
asset_groups = user_group.asset_group.all()
|
||||
|
||||
for asset_group in asset_groups:
|
||||
assets.extend(asset_group.asset.all())
|
||||
|
||||
return {'assets': assets, 'asset_groups': asset_groups}
|
||||
|
||||
|
||||
def user_permed(user):
|
||||
asset_groups = []
|
||||
assets = []
|
||||
user_groups = user.group.all()
|
||||
asset_groups.extend(user.asset_group.all())
|
||||
assets.extend(user.asset.all())
|
||||
|
||||
for user_group in user_groups:
|
||||
asset_groups.extend(user_group_permed(user_group).get('assets', []))
|
||||
assets.extend((user_group_permed(user_group).get('asset_groups', [])))
|
||||
|
||||
return {'assets': assets, 'asset_groups': asset_groups}
|
||||
|
||||
|
||||
def _public_perm_api(info):
|
||||
"""
|
||||
公用的用户,用户组,主机,主机组编辑修改新建调用的api,用来完成授权
|
||||
info like that:
|
||||
{
|
||||
'type': 'new_user',
|
||||
'user': 'a',
|
||||
'group': ['A', 'B']
|
||||
}
|
||||
|
||||
{
|
||||
'type': 'edit_user',
|
||||
'user': 'a',
|
||||
'group': {'new': ['A'], 'del': []}
|
||||
}
|
||||
|
||||
{
|
||||
'type': 'del_user',
|
||||
'user': ['a', 'b']
|
||||
}
|
||||
|
||||
{
|
||||
'type': 'edit_user_group',
|
||||
'group': 'A',
|
||||
'user': {'del': ['a', 'b'], 'new': ['c', 'd']}
|
||||
}
|
||||
|
||||
{
|
||||
'type': 'del_user_group',
|
||||
'group': ['A']
|
||||
}
|
||||
|
||||
{
|
||||
'type': 'new_asset',
|
||||
'asset': 'a',
|
||||
'group': ['A', 'B']
|
||||
}
|
||||
|
||||
{
|
||||
'type': 'edit_asset',
|
||||
'asset': 'a',
|
||||
'group': {
|
||||
'del': ['A', ['B'],
|
||||
'new': ['C', ['D']]
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
'type': 'del_asset',
|
||||
'asset': ['a', 'b']
|
||||
}
|
||||
|
||||
{
|
||||
'type': 'edit_asset_group',
|
||||
'group': 'A',
|
||||
'asset': {'new': ['a', 'b'], 'del': ['c', 'd']}
|
||||
}
|
||||
|
||||
{
|
||||
'type': 'del_asset_group',
|
||||
'group': ['A', 'B']
|
||||
}
|
||||
"""
|
||||
|
||||
if info.get('type') == 'new_user':
|
||||
new_assets = []
|
||||
user = info.get('user')
|
||||
user_groups = info.get('group')
|
||||
for user_group in user_groups:
|
||||
new_assets.extend(user_group_permed(user_group).get('assets', []))
|
||||
|
||||
perm_info = {
|
||||
'action': 'new user: ' + user.name,
|
||||
'new': {'users': [user], 'assets': new_assets}
|
||||
}
|
||||
elif info.get('type') == 'edit_user':
|
||||
new_assets = []
|
||||
del_assets = []
|
||||
user = info.get('user')
|
||||
new_group = info.get('group').get('new')
|
||||
del_group = info.get('group').get('del')
|
||||
|
||||
for user_group in new_group:
|
||||
new_assets.extend(user_group_permed(user_group).get('assets', []))
|
||||
|
||||
for user_group in del_group:
|
||||
del_assets.extend((user_group_permed(user_group).get('assets', [])))
|
||||
|
||||
perm_info = {
|
||||
'action': 'edit user: ' + user.name,
|
||||
'del': {'users': [user], 'assets': del_assets},
|
||||
'new': {'users': [user], 'assets': new_assets}
|
||||
}
|
||||
|
||||
elif info.get('type') == 'del_user':
|
||||
user = info.get('user')
|
||||
del_assets = user_permed(user).get('assets', [])
|
||||
perm_info = {
|
||||
'action': 'del user: ' + user.name, 'del': {'users': [user], 'assets': del_assets},
|
||||
}
|
||||
|
||||
elif info.get('type') == 'edit_user_group':
|
||||
user_group = info.get('group')
|
||||
new_users = info.get('user').get('new')
|
||||
del_users = info.get('user').get('del')
|
||||
assets = user_group_permed(user_group).get('assets', [])
|
||||
|
||||
perm_info = {
|
||||
'action': 'edit user group: ' + user_group.name,
|
||||
'new': {'users': new_users, 'assets': assets},
|
||||
'del': {'users': del_users, 'assets': assets}
|
||||
}
|
||||
|
||||
elif info.get('type') == 'del_user_group':
|
||||
user_group = info.get('group', [])
|
||||
del_users = user_group.user_set.all()
|
||||
assets = user_group_permed(user_group).get('assets', [])
|
||||
|
||||
perm_info = {
|
||||
'action': "del user group: " + user_group.name, 'del': {'users': del_users, 'assets': assets}
|
||||
}
|
||||
else:
|
||||
return
|
||||
|
||||
try:
|
||||
results = perm_user_api(perm_info) # 通过API授权或回收
|
||||
except ServerError, e:
|
||||
return e
|
||||
else:
|
||||
return results
|
||||
|
||||
|
||||
def push_user(user, asset_groups_id):
|
||||
assets = []
|
||||
if not user:
|
||||
return {'error': '没有该用户'}
|
||||
for group_id in asset_groups_id:
|
||||
asset_group = get_object(AssetGroup, id=group_id)
|
||||
if asset_group:
|
||||
assets.extend(asset_group.asset_set.all())
|
||||
perm_info = {
|
||||
'action': 'Push user:' + user.username,
|
||||
'new': {'users': [user], 'assets': assets}
|
||||
}
|
||||
|
||||
results = perm_user_api(perm_info)
|
||||
return results
|
||||
|
||||
|
||||
def get_role_info(role_id, type="all"):
|
||||
"""
|
||||
获取role对应的一些信息
|
||||
|
|
|
@ -13,11 +13,4 @@ urlpatterns = patterns('jperm.views',
|
|||
(r'^role/perm_role_detail/$', perm_role_detail),
|
||||
(r'^role/perm_role_edit/$', perm_role_edit),
|
||||
(r'^role/perm_role_push/$', perm_role_push),
|
||||
|
||||
|
||||
(r'^log/$', log),
|
||||
(r'^sys_user_add/$', sys_user_add),
|
||||
(r'^perm_user_list/$', sys_user_list),
|
||||
(r'^sys_user_del/$', sys_user_del),
|
||||
(r'^sys_user_edit/$', sys_user_edit),
|
||||
)
|
||||
|
|
|
@ -51,6 +51,7 @@ def gen_keys():
|
|||
private_key = os.path.join(key_path_dir, 'id_rsa')
|
||||
public_key = os.path.join(key_path_dir, 'id_rsa.pub')
|
||||
key.write_private_key_file(private_key)
|
||||
os.chmod(private_key, 0644)
|
||||
|
||||
with open(public_key, 'w') as content_file:
|
||||
for data in [key.get_name(),
|
||||
|
|
109
jperm/views.py
|
@ -2,8 +2,6 @@
|
|||
|
||||
from django.db.models import Q
|
||||
from jperm.perm_api import *
|
||||
from jperm.models import PermLog as Log
|
||||
from jperm.models import SysUser
|
||||
from juser.user_api import gen_ssh_key
|
||||
|
||||
|
||||
|
@ -380,8 +378,6 @@ def perm_role_edit(request):
|
|||
return my_render('jperm/perm_role_list.html', locals(), request)
|
||||
|
||||
|
||||
|
||||
|
||||
@require_role('admin')
|
||||
def perm_role_push(request):
|
||||
"""
|
||||
|
@ -460,108 +456,3 @@ def perm_role_push(request):
|
|||
else:
|
||||
return HttpResponse(u"推送系统角色: %s" % ','.join(role_names))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@require_role('admin')
|
||||
def perm_group_list(request):
|
||||
header_title, path1, path2 = '用户组授权', '授权管理', '用户组授权'
|
||||
keyword = request.GET.get('search', '')
|
||||
user_groups_list = UserGroup.objects.all()
|
||||
if keyword:
|
||||
request = user_groups_list.filter(Q(name=keyword) | Q(comment=keyword))
|
||||
user_groups_list, p, user_groups, page_range, current_page, show_first, show_end = pages(user_groups_list, request)
|
||||
return my_render('jperm/perm_group_list.html', locals(), request)
|
||||
|
||||
|
||||
|
||||
@require_role('admin')
|
||||
def perm_group_edit(request):
|
||||
header_title, path1, path2 = '用户组授权', '授权管理', '授权更改'
|
||||
user_group_id = request.GET.get('id', '')
|
||||
user_group = get_object(UserGroup, id=user_group_id)
|
||||
asset_all = Asset.objects.all()
|
||||
asset_group_all = AssetGroup.objects.all()
|
||||
asset_permed = user_group.asset.all() # 获取授权的资产对象列表
|
||||
asset_group_permed = user_group.asset_group.all() # 获取授权的资产组对象列表
|
||||
if request.method == 'GET' and user_group:
|
||||
assets = [asset for asset in asset_all if asset not in asset_permed]
|
||||
asset_groups = [asset_group for asset_group in asset_group_all if asset_group not in asset_group_permed]
|
||||
return my_render('jperm/perm_group_edit.html', locals(), request)
|
||||
elif request.method == 'POST' and user_group:
|
||||
asset_id_select = request.POST.getlist('asset_select', [])
|
||||
asset_group_id_select = request.POST.getlist('asset_groups_select', [])
|
||||
asset_select = get_object_list(Asset, asset_id_select)
|
||||
asset_group_select = get_object_list(AssetGroup, asset_group_id_select)
|
||||
asset_new = list(set(asset_select) - set(asset_permed)) # 计算的得到新授权的资产对象列表
|
||||
asset_del = list(set(asset_permed) - set(asset_select)) # 计算得到回收权限的资产对象列表
|
||||
asset_group_new = list(set(asset_group_select) - set(asset_group_permed)) # 新授权的资产组对象列表
|
||||
asset_group_del = list(set(asset_group_permed) - set(asset_group_select)) # 回收的资产组对象列表
|
||||
users = user_group.user_set.all()
|
||||
perm_info = {
|
||||
'action': 'perm group edit: ' + user_group.name,
|
||||
'del': {'users': users, 'assets': asset_del},
|
||||
'new': {'users': users, 'assets': asset_new}
|
||||
}
|
||||
results = perm_user_api(perm_info)
|
||||
unreachable_asset = []
|
||||
failures_asset = []
|
||||
for ip in results.get('unreachable'):
|
||||
unreachable_asset.extend(filter(lambda x: x, Asset.objects.filter(ip=ip)))
|
||||
for ip in results.get('failures'):
|
||||
failures_asset.extend(filter(lambda x: x, Asset.objects.filter(ip=ip)))
|
||||
failures_asset.extend(unreachable_asset) # 失败的授权要统计
|
||||
for asset in failures_asset:
|
||||
if asset in asset_select:
|
||||
asset_select.remove(asset)
|
||||
else:
|
||||
asset_select.append(asset)
|
||||
user_group.asset = asset_select
|
||||
user_group.asset_group = asset_group_select
|
||||
user_group.save() # 保存到数据库
|
||||
return HttpResponse(json.dumps(results, sort_keys=True, indent=4), content_type="application/json")
|
||||
else:
|
||||
return HttpResponse('输入错误')
|
||||
|
||||
|
||||
def log(request):
|
||||
header_title, path1, path2 = '授权记录', '授权管理', '授权记录'
|
||||
log_all = Log.objects.all().order_by('-datetime')
|
||||
log_all, p, logs, page_range, current_page, show_first, show_end = pages(log_all, request)
|
||||
return my_render('jperm/perm_log.html', locals(), request)
|
||||
|
||||
|
||||
def sys_user_add(request):
|
||||
asset_group_all = AssetGroup.objects.all()
|
||||
if request.method == 'POST':
|
||||
username = request.POST.get('username', '')
|
||||
password = request.POST.get('password', '')
|
||||
asset_groups_id = request.POST.getlist('asset_groups_select', [])
|
||||
comment = request.POST.get('comment')
|
||||
sys_user = SysUser(username=username, password=password, comment=comment)
|
||||
sys_user.save()
|
||||
gen_ssh_key(username, key_dir=os.path.join(SSH_KEY_DIR, 'sysuser'), authorized_keys=False)
|
||||
results = push_user(sys_user, asset_groups_id)
|
||||
return HttpResponse(json.dumps(results, sort_keys=True, indent=4), content_type="application/json")
|
||||
return my_render('jperm/sys_user_add.html', locals(), request)
|
||||
|
||||
|
||||
def sys_user_list(request):
|
||||
users_list = SysUser.objects.all()
|
||||
users_list, p, users, page_range, current_page, show_first, show_end = pages(users_list, request)
|
||||
return my_render('jperm/sys_user_list.html', locals(), request)
|
||||
|
||||
|
||||
def sys_user_edit(request):
|
||||
pass
|
||||
|
||||
|
||||
def sys_user_del(request):
|
||||
pass
|
||||
|
||||
|
|
|
@ -3,24 +3,27 @@
|
|||
import os, sys, time, re
|
||||
from Crypto.Cipher import AES
|
||||
import crypt
|
||||
import pwd
|
||||
from binascii import b2a_hex, a2b_hex
|
||||
import hashlib
|
||||
import datetime
|
||||
import random
|
||||
import subprocess
|
||||
from settings import *
|
||||
import json
|
||||
import logging
|
||||
|
||||
from settings import *
|
||||
from django.core.paginator import Paginator, EmptyPage, InvalidPage
|
||||
from django.http import HttpResponse, Http404
|
||||
from django.template import RequestContext
|
||||
from juser.models import User, UserGroup
|
||||
from jlog.models import Log
|
||||
from jlog.models import Log, TtyLog
|
||||
from jasset.models import Asset, AssetGroup
|
||||
from jperm.models import PermRule, PermRole
|
||||
from jumpserver.models import Setting
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.shortcuts import render_to_response
|
||||
from django.core.mail import send_mail
|
||||
import json
|
||||
import logging
|
||||
|
||||
|
||||
def set_log(level):
|
||||
|
@ -28,11 +31,15 @@ def set_log(level):
|
|||
return a log file object
|
||||
根据提示设置log打印
|
||||
"""
|
||||
log_file = os.path.join(LOG_DIR, 'jumpserver.log')
|
||||
if not os.path.isfile(log_file):
|
||||
os.mknod(log_file)
|
||||
os.chmod(log_file, 0777)
|
||||
log_level_total = {'debug': logging.DEBUG, 'info': logging.INFO, 'warning': logging.WARN, 'error': logging.ERROR,
|
||||
'critical': logging.CRITICAL}
|
||||
logger_f = logging.getLogger('jumpserver')
|
||||
logger_f.setLevel(logging.DEBUG)
|
||||
fh = logging.FileHandler(os.path.join(LOG_DIR, 'jumpserver.log'))
|
||||
fh = logging.FileHandler(log_file)
|
||||
fh.setLevel(log_level_total.get(level, logging.DEBUG))
|
||||
formatter = logging.Formatter('%(asctime)s - %(filename)s - %(levelname)s - %(message)s')
|
||||
fh.setFormatter(formatter)
|
||||
|
@ -40,6 +47,60 @@ def set_log(level):
|
|||
return logger_f
|
||||
|
||||
|
||||
def get_asset_info(asset):
|
||||
default = get_object(Setting, name='default')
|
||||
info = {'hostname': asset.hostname, 'ip': asset.ip}
|
||||
if asset.use_default_auth:
|
||||
if default:
|
||||
info['port'] = default.default_port
|
||||
info['username'] = default.default_user
|
||||
info['password'] = CRYPTOR.decrypt(default.default_password)
|
||||
info['ssh_key'] = default.default_pri_key_path
|
||||
else:
|
||||
info['port'] = asset.port
|
||||
info['username'] = asset.username
|
||||
info['password'] = asset.password
|
||||
|
||||
return info
|
||||
|
||||
|
||||
def get_role(user, asset):
|
||||
roles = []
|
||||
rules = PermRule.objects.filter(user=user, asset=asset)
|
||||
for rule in rules:
|
||||
roles.extend(list(rule.role.all()))
|
||||
return roles
|
||||
|
||||
|
||||
def get_role_key(user, role):
|
||||
"""
|
||||
由于role的key的权限是所有人可以读的, ansible要求为600,所以拷贝一份到特殊目录
|
||||
:param user:
|
||||
:param role:
|
||||
:return: self key path
|
||||
"""
|
||||
user_role_key_dir = os.path.join(KEY_DIR, 'user')
|
||||
user_role_key_path = os.path.join(user_role_key_dir, '%s_%s.pem' % (user.username, role.name))
|
||||
mkdir(user_role_key_dir, mode=777)
|
||||
if not os.path.isfile(user_role_key_path):
|
||||
with open(os.path.join(role.key_path, 'id_rsa')) as fk:
|
||||
with open(user_role_key_path, 'w') as fu:
|
||||
fu.write(fk.read())
|
||||
|
||||
print user_role_key_path, user.username
|
||||
chown(user_role_key_path, user.username)
|
||||
os.chmod(user_role_key_path, 0600)
|
||||
return user_role_key_path
|
||||
|
||||
|
||||
def chown(path, user, group=''):
|
||||
if not group:
|
||||
group = user
|
||||
uid = pwd.getpwnam(user).pw_uid
|
||||
gid = pwd.getpwnam(group).pwd_gid
|
||||
os.chown(path, uid, gid)
|
||||
|
||||
|
||||
def page_list_return(total, current=1):
|
||||
"""
|
||||
page
|
||||
|
@ -56,7 +117,7 @@ def pages(post_objects, request):
|
|||
page public function , return page's object tuple
|
||||
分页公用函数,返回分页的对象元组
|
||||
"""
|
||||
paginator = Paginator(post_objects, 10)
|
||||
paginator = Paginator(post_objects, 20)
|
||||
try:
|
||||
current_page = int(request.GET.get('page', '1'))
|
||||
except ValueError:
|
||||
|
@ -157,8 +218,7 @@ class PyCrypt(object):
|
|||
try:
|
||||
plain_text = cryptor.decrypt(a2b_hex(text))
|
||||
except TypeError:
|
||||
# raise ServerError('Decrypt password error, TYpe error.')
|
||||
pass
|
||||
raise ServerError('Decrypt password error, TYpe error.')
|
||||
return plain_text.rstrip('\0')
|
||||
|
||||
|
||||
|
@ -386,16 +446,16 @@ def bash(cmd):
|
|||
return subprocess.call(cmd, shell=True)
|
||||
|
||||
|
||||
def mkdir(dir_name, username='root', mode=0755):
|
||||
def mkdir(dir_name, username='', mode=0755):
|
||||
"""
|
||||
insure the dir exist and mode ok
|
||||
目录存在,如果不存在就建立,并且权限正确
|
||||
"""
|
||||
if not os.path.isdir(dir_name):
|
||||
os.makedirs(dir_name)
|
||||
os.chmod(dir_name, mode)
|
||||
os.chmod(dir_name, mode)
|
||||
if username:
|
||||
bash('chown %s:%s %s' % (username, username, dir_name))
|
||||
chown(dir_name, username)
|
||||
|
||||
|
||||
def http_success(request, msg):
|
||||
|
|
|
@ -130,7 +130,7 @@ def gen_ssh_key(username, password='',
|
|||
"""
|
||||
logger.debug('生成ssh key, 并设置authorized_keys')
|
||||
private_key_file = os.path.join(key_dir, username)
|
||||
mkdir(key_dir)
|
||||
mkdir(key_dir, mode=777)
|
||||
if os.path.isfile(private_key_file):
|
||||
os.unlink(private_key_file)
|
||||
ret = bash('echo -e "y\n"|ssh-keygen -t rsa -f %s -b %s -P "%s"' % (private_key_file, length, password))
|
||||
|
@ -143,7 +143,7 @@ def gen_ssh_key(username, password='',
|
|||
with open(authorized_key_file, 'w') as auth_f:
|
||||
auth_f.write(pub_f.read())
|
||||
os.chmod(authorized_key_file, 0600)
|
||||
bash('chown %s:%s %s' % (username, username, authorized_key_file))
|
||||
chown(authorized_key_file, username)
|
||||
|
||||
|
||||
def server_add_user(username, password, ssh_key_pwd, ssh_key_login_need):
|
||||
|
|
|
@ -86,17 +86,17 @@ function move(from, to, from_o, to_o) {
|
|||
});
|
||||
}
|
||||
|
||||
//function move_left(from, to, from_o, to_o) {
|
||||
// $("#" + from + " option").each(function () {
|
||||
// if ($(this).prop("selected") == true) {
|
||||
// $("#" + to).append(this);
|
||||
// if( typeof from_o !== 'undefined'){
|
||||
// $("#"+to_o).append($("#"+from_o +" option[value='"+this.value+"']"));
|
||||
// }
|
||||
// }
|
||||
// $(this).attr("selected",'true');
|
||||
// });
|
||||
//}
|
||||
function move_left(from, to, from_o, to_o) {
|
||||
$("#" + from + " option").each(function () {
|
||||
if ($(this).prop("selected") == true) {
|
||||
$("#" + to).append(this);
|
||||
if( typeof from_o !== 'undefined'){
|
||||
$("#"+to_o).append($("#"+from_o +" option[value='"+this.value+"']"));
|
||||
}
|
||||
}
|
||||
$(this).attr("selected",'true');
|
||||
});
|
||||
}
|
||||
|
||||
//function move_all(from, to) {
|
||||
// $("#" + from).children().each(function () {
|
||||
|
|
After Width: | Height: | Size: 5.8 KiB |
After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 7.5 KiB |
0
static/js/layer/skin/default/xubox_loading0.gif → static/js/layer/skin/default/loading-0.gif
Normal file → Executable file
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 5.7 KiB |
0
static/js/layer/skin/default/xubox_loading1.gif → static/js/layer/skin/default/loading-1.gif
Normal file → Executable file
Before Width: | Height: | Size: 701 B After Width: | Height: | Size: 701 B |
0
static/js/layer/skin/default/xubox_loading2.gif → static/js/layer/skin/default/loading-2.gif
Normal file → Executable file
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 210 B |
Before Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 221 B |
|
@ -1,45 +1,8 @@
|
|||
/**
|
||||
/*!
|
||||
|
||||
@Name: layer拓展样式
|
||||
@Date: 2012.12.13
|
||||
@Author: 贤心
|
||||
@blog: sentsin.com
|
||||
|
||||
**/
|
||||
|
||||
.xubox_iconext{background:url(default/icon_ext.png) no-repeat;}
|
||||
|
||||
/* prompt模式 */
|
||||
.xubox_layer .xubox_form{width:240px; height:30px; line-height:30px; padding: 0 5px; border: 1px solid #ccc; background: url(default/textbg.png) #fff repeat-x; color:#333;}
|
||||
.xubox_layer .xubox_formArea{width:300px; height:100px; line-height:20px;}
|
||||
|
||||
/* tab模式 */
|
||||
.xubox_layer .xubox_tab{position:relative; background-color:#fff; box-shadow:1px 1px 50px rgba(0,0,0,.4)}
|
||||
.xubox_layer .xubox_tabmove{position:absolute; width:600px; height:30px; top:0; left:0;}
|
||||
.xubox_layer .xubox_tabtit{ display:block; height:34px; border-bottom:1px solid #ccc; background-color:#eee;}
|
||||
.xubox_layer .xubox_tabtit span{position:relative; float:left; width:120px; height:34px; line-height:34px; text-align:center; cursor:default;}
|
||||
.xubox_layer .xubox_tabtit span.xubox_tabnow{left:-1px; _top:1px; height:35px; border-left:1px solid #ccc; border-right:1px solid #ccc; background-color:#fff; z-index:10;}
|
||||
.xubox_layer .xubox_tab_main{line-height:24px; clear:both;}
|
||||
.xubox_layer .xubox_tab_main .xubox_tabli{display:none;}
|
||||
.xubox_layer .xubox_tab_main .xubox_tabli.xubox_tab_layer{display:block;}
|
||||
.xubox_layer .xubox_tabclose{position:absolute; right:10px; top:5px; cursor:pointer;}
|
||||
|
||||
/* photo模式 */
|
||||
.xubox_bigimg, .xubox_intro{height:300px}
|
||||
.xubox_bigimg{position:relative; display:block; width:600px; text-align:center; background:url(default/xubox_loading1.gif) center center no-repeat #000; overflow:hidden; }
|
||||
.xubox_bigimg img{position:relative; display:inline-block; visibility: hidden;}
|
||||
.xubox_intro{position:absolute; right:-315px; top:0; width:300px; background-color:#fff; overflow-x:hidden; overflow-y:auto;}
|
||||
.xubox_imgsee{display:none;}
|
||||
.xubox_prev, .xubox_next{position:absolute; top:50%; width:27px; _width:44px; height:44px; margin-top:-22px; outline:none;blr:expression(this.onFocus=this.blur());}
|
||||
.xubox_prev{left:10px; background-position:-5px -5px; _background-position:-70px -5px;}
|
||||
.xubox_prev:hover{background-position:-33px -5px; _background-position:-120px -5px;}
|
||||
.xubox_next{right:10px; _right:8px; background-position:-5px -50px; _background-position:-70px -50px;}
|
||||
.xubox_next:hover{background-position:-33px -50px; _background-position:-120px -50px;}
|
||||
.xubox_imgbar{position:absolute; left:0; bottom:0; width:100%; height:32px; line-height:32px; background-color:rgba(0,0,0,.8); background-color:#000\9; filter:Alpha(opacity=80); color:#fff; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; font-size:0;}
|
||||
.xubox_imgtit{/*position:absolute; left:20px;*/}
|
||||
.xubox_imgtit *{display:inline-block; *display:inline; *zoom:1; vertical-align:top; font-size:12px;}
|
||||
.xubox_imgtit a{max-width:65%; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; color:#fff;}
|
||||
.xubox_imgtit a:hover{color:#fff; text-decoration:underline;}
|
||||
.xubox_imgtit em{padding-left:10px;}
|
||||
|
||||
|
||||
*/.layui-layer-imgbar,.layui-layer-imgtit a,.layui-layer-tab .layui-layer-title span{text-overflow:ellipsis;white-space:nowrap}.layui-layer-iconext{background:url(default/icon-ext.png) no-repeat}html #layui_layer_skinlayerextcss{display:none;position:absolute;width:1989px}.layui-layer-prompt .layui-layer-input{display:block;width:220px;height:30px;margin:0 auto;line-height:30px;padding:0 5px;border:1px solid #ccc;box-shadow:1px 1px 5px rgba(0,0,0,.1) inset;color:#333}.layui-layer-prompt textarea.layui-layer-input{width:300px;height:100px;line-height:20px}.layui-layer-tab{box-shadow:1px 1px 50px rgba(0,0,0,.4)}.layui-layer-tab .layui-layer-title{padding-left:0;border-bottom:1px solid #ccc;background-color:#eee;overflow:visible}.layui-layer-tab .layui-layer-title span{position:relative;float:left;min-width:80px;max-width:260px;padding:0 20px;text-align:center;cursor:default;overflow:hidden}.layui-layer-tab .layui-layer-title span.layui-layer-tabnow{height:43px;border-left:1px solid #ccc;border-right:1px solid #ccc;background-color:#fff;z-index:10}.layui-layer-tab .layui-layer-title span:first-child{border-left:none}.layui-layer-tabmain{line-height:24px;clear:both}.layui-layer-tabmain .layui-layer-tabli{display:none}.layui-layer-tabmain .layui-layer-tabli.xubox_tab_layer{display:block}.xubox_tabclose{position:absolute;right:10px;top:5px;cursor:pointer}.layui-layer-photos{-webkit-animation-duration:1s;animation-duration:1s;background:url(default/xubox_loading1.gif) center center no-repeat #000}.layui-layer-photos .layui-layer-content{overflow:hidden;text-align:center}.layui-layer-photos .layui-layer-phimg img{position:relative;width:100%;display:inline-block;*display:inline;*zoom:1;vertical-align:top}.layui-layer-imgbar,.layui-layer-imguide{display:none}.layui-layer-imgnext,.layui-layer-imgprev{position:absolute;top:50%;width:27px;_width:44px;height:44px;margin-top:-22px;outline:0;blr:expression(this.onFocus=this.blur())}.layui-layer-imgprev{left:10px;background-position:-5px -5px;_background-position:-70px -5px}.layui-layer-imgprev:hover{background-position:-33px -5px;_background-position:-120px -5px}.layui-layer-imgnext{right:10px;_right:8px;background-position:-5px -50px;_background-position:-70px -50px}.layui-layer-imgnext:hover{background-position:-33px -50px;_background-position:-120px -50px}.layui-layer-imgbar{position:absolute;left:0;bottom:0;width:100%;height:32px;line-height:32px;background-color:rgba(0,0,0,.8);background-color:#000\9;filter:Alpha(opacity=80);color:#fff;overflow:hidden;font-size:0}.layui-layer-imgtit *{display:inline-block;*display:inline;*zoom:1;vertical-align:top;font-size:12px}.layui-layer-imgtit a{max-width:65%;overflow:hidden;color:#fff}.layui-layer-imgtit a:hover{color:#fff;text-decoration:underline}.layui-layer-imgtit em{padding-left:10px;font-style:normal}
|
|
@ -19,7 +19,7 @@
|
|||
<script src="/static/js/base.js"></script>
|
||||
|
||||
<!-- pop windows layer-->
|
||||
<script src="/static/js/layer/layer.min.js"></script>
|
||||
<script src="/static/js/layer/layer.js"></script>
|
||||
|
||||
<!-- highcharts -->
|
||||
<script src="/static/js/highcharts/highcharts.js"></script>
|
||||
|
|
|
@ -42,13 +42,11 @@
|
|||
|
||||
<form id="assetForm" method="post" class="form-horizontal">
|
||||
|
||||
{{ af.hostname|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></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 }}
|
||||
<p class="col-sm-offset-2">Tips: 如果IP地址不填写, IP默认会设置与主机名一致</p>
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
|
@ -63,6 +61,7 @@
|
|||
</div>
|
||||
|
||||
<div class="form-group" id="admin_account" style="display: none">
|
||||
<div class="hr-line-dashed"></div>
|
||||
<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">
|
||||
|
@ -74,6 +73,14 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group" id="id_port" style="display: none">
|
||||
<div class="hr-line-dashed"></div>
|
||||
<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>
|
||||
{{ af.group|bootstrap_horizontal }}
|
||||
|
||||
|
@ -113,15 +120,17 @@
|
|||
$('document').ready(function(){
|
||||
$('#id_use_default_auth').click(function(){
|
||||
if ($(this).is(':checked')){
|
||||
$('#admin_account').css('display', 'none')
|
||||
$('#admin_account').css('display', 'none');
|
||||
$('#id_port').css('display', 'none')
|
||||
}
|
||||
else {
|
||||
$('#admin_account').css('display', 'block')
|
||||
$('#admin_account').css('display', 'block');
|
||||
$('#id_port').css('display', 'block')
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
var required_fields = ["id_hostname", "id_ip", "id_port"];
|
||||
var required_fields = ["id_hostname", "id_port"];
|
||||
required_fields.forEach(function(field) {
|
||||
$('label[for="' + field + '"]').parent().addClass("required");
|
||||
});
|
||||
|
@ -134,18 +143,24 @@
|
|||
check_port: [/^\d{1,5}$/, '端口号不正确'],
|
||||
},
|
||||
fields: {
|
||||
"ip": {
|
||||
rule: "required;check_ip",
|
||||
tip: "输入IP",
|
||||
{# "ip": {#}
|
||||
{# rule: "required;check_ip",#}
|
||||
{# tip: "输入IP",#}
|
||||
{# ok: "",#}
|
||||
{# msg: {required: "必须填写!"}#}
|
||||
{# },#}
|
||||
"hostname": {
|
||||
rule: "required",
|
||||
tip: "填写主机名",
|
||||
ok: "",
|
||||
msg: {required: "必须填写!"}
|
||||
},
|
||||
"port": {
|
||||
rule: "required;check_port",
|
||||
tip: "输入端口号",
|
||||
ok: "",
|
||||
msg: {required: "必须填写!"}
|
||||
}
|
||||
{# "port": {#}
|
||||
{# rule: "required;check_port",#}
|
||||
{# tip: "输入端口号",#}
|
||||
{# ok: "",#}
|
||||
{# msg: {required: "必须填写!"}#}
|
||||
{# }#}
|
||||
},
|
||||
valid: function(form) {
|
||||
form.submit();
|
||||
|
|
|
@ -1,166 +0,0 @@
|
|||
{% 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 %}
|
|
@ -200,6 +200,7 @@
|
|||
</div>
|
||||
<div class="ibox-title">
|
||||
<h5>主机修改记录</h5>
|
||||
<a href="/jasset/asset_edit/?id={{ asset.id }}" data-toggle="tooltip" class="text-success pull-center" data-placement="bottom" title="修改">    点击修改</a>
|
||||
<div class="ibox-tools">
|
||||
<a class="collapse-link">
|
||||
<i class="fa fa-chevron-up"></i>
|
||||
|
|
|
@ -34,19 +34,20 @@
|
|||
{% endif %}
|
||||
<form id="assetForm" method="post" class="form-horizontal">
|
||||
|
||||
{{ af.ip|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{{ af.hostname|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{{ af.ip|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{{ af.other_ip|bootstrap_horizontal }}
|
||||
<p class="col-sm-offset-2">Tips: 多个IP使用,号隔开</p>
|
||||
|
||||
<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>#}
|
||||
{# {{ af.port|bootstrap_horizontal }}#}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
|
@ -60,6 +61,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="admin_account" {% if asset.use_default_auth %} style="display: none" {% endif %}>
|
||||
<div class="hr-line-dashed"></div>
|
||||
<label class="col-sm-2 control-label"> 管理用户名 <span class="red-fonts">*</span> </label>
|
||||
<div class="col-sm-3">
|
||||
<input type="text" value="{{ asset.username }}" name="username" class="form-control">
|
||||
|
@ -71,6 +73,13 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group" id="id_port" {% if asset.use_default_auth %} style="display: none" {% endif %}>
|
||||
<div class="hr-line-dashed"></div>
|
||||
<label class="col-sm-2 control-label"> 端口<span class="red-fonts">*</span> </label>
|
||||
<div class="col-sm-8">
|
||||
<input type="text" placeholder="Port" value="{{ asset.port }}" name="port" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{{ af.group|bootstrap_horizontal }}
|
||||
|
@ -156,15 +165,17 @@
|
|||
$('document').ready(function(){
|
||||
$('#id_use_default_auth').click(function(){
|
||||
if ($(this).is(':checked')){
|
||||
$('#admin_account').css('display', 'none')
|
||||
$('#admin_account').css('display', 'none');
|
||||
$('#id_port').css('display', 'none')
|
||||
}
|
||||
else {
|
||||
$('#admin_account').css('display', 'block')
|
||||
$('#admin_account').css('display', 'block');
|
||||
$('#id_port').css('display', 'block')
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
var required_fields = ["id_ip", "id_port"];
|
||||
var required_fields = ["id_hostname", "id_port"];
|
||||
required_fields.forEach(function(field) {
|
||||
$('label[for="' + field + '"]').parent().addClass("required");
|
||||
});
|
||||
|
@ -177,18 +188,23 @@
|
|||
check_port: [/^\d{1,5}$/, '端口号不正确'],
|
||||
},
|
||||
fields: {
|
||||
"ip": {
|
||||
rule: "required;check_ip",
|
||||
tip: "输入IP",
|
||||
"hostname": {
|
||||
rule: "required",
|
||||
tip: "填写主机名",
|
||||
ok: "",
|
||||
msg: {required: "必须填写!"}
|
||||
},
|
||||
"port": {
|
||||
rule: "required;check_port",
|
||||
tip: "输入端口号",
|
||||
ok: "",
|
||||
msg: {required: "必须填写!"}
|
||||
}
|
||||
{# "ip": {#}
|
||||
{# rule: "required;check_ip",#}
|
||||
{# tip: "输入IP",#}
|
||||
{# ok: "",#}
|
||||
{# msg: {required: "必须填写!"}#}
|
||||
{# },#}
|
||||
{# "port": {#}
|
||||
{# rule: "required;check_port",#}
|
||||
{# tip: "输入端口号",#}
|
||||
{# ok: "",#}
|
||||
{# msg: {required: "必须填写!"}#}
|
||||
},
|
||||
valid: function(form) {
|
||||
form.submit();
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
<link href="/static/css/style.css" rel="stylesheet">
|
||||
|
||||
<script src="/static/js/jquery-2.1.1.js"></script>
|
||||
{# <style>#}
|
||||
{# body {background: #ffffff;}#}
|
||||
{# </style>#}
|
||||
<style>
|
||||
body {background: #ffffff;}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
{% load bootstrap %}
|
||||
|
@ -20,21 +20,21 @@
|
|||
<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-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">
|
||||
|
@ -49,33 +49,43 @@
|
|||
{{ af.port|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<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>
|
||||
<<<<<<< HEAD
|
||||
<input type="radio" checked="" value="no_action" id="no" name="use_default_auth" class="auth"><span> 不修改 </span>
|
||||
=======
|
||||
<input type="radio" checked="" value="" id="no" name="use_default_auth" class="auth"><span> 不修改 </span>
|
||||
>>>>>>> cmdb
|
||||
</label>
|
||||
</div>
|
||||
<div class="radio i-checks">
|
||||
<label>
|
||||
<<<<<<< HEAD
|
||||
<input type="radio" id="default" name="use_default_auth" class="auth"><span> 使用默认 </span>
|
||||
=======
|
||||
<input type="radio" id="default" name="use_default_auth" class="auth" value="default"><span> 使用默认 </span>
|
||||
>>>>>>> cmdb
|
||||
</label>
|
||||
</div>
|
||||
<div class="radio i-checks">
|
||||
<label>
|
||||
<<<<<<< HEAD
|
||||
<input type="radio" id="pass" name="use_default_auth" class="auth"><span> 用户名密码 </span>
|
||||
=======
|
||||
<input type="radio" id="pass" name="use_default_auth" class="auth" value="user_passwd"><span> 用户名密码 </span>
|
||||
>>>>>>> cmdb
|
||||
</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">
|
||||
|
@ -101,7 +111,7 @@
|
|||
</div>
|
||||
<div class="col-sm-3">
|
||||
<div>
|
||||
<select id="groups_selected" name="project" class="form-control m-b" size="10" multiple>
|
||||
<select id="groups_selected" name="group" class="form-control m-b" size="10" multiple>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -117,7 +127,7 @@
|
|||
<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>
|
||||
<button class="btn btn-primary"> 提交 </button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -128,6 +138,7 @@
|
|||
</div>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
<<<<<<< HEAD
|
||||
$('#host_edit').click(function () {
|
||||
var args = {};
|
||||
var match = null;
|
||||
|
@ -140,6 +151,8 @@
|
|||
$('#uuid').val(ids)
|
||||
});
|
||||
|
||||
=======
|
||||
>>>>>>> cmdb
|
||||
$('.auth').click(function(){
|
||||
if ($(this).attr('id') == 'pass'){
|
||||
$('#admin_account').css('display', 'block')
|
||||
|
|
|
@ -70,7 +70,7 @@
|
|||
<div class="col-sm-2">
|
||||
<label>
|
||||
<select name="status" class="form-control m-b" onchange="change_info()">
|
||||
<option value="">状态</option>
|
||||
<option value="">所有状态</option>
|
||||
{% for s in asset_status %}
|
||||
{% ifequal s.0|int2str status %}
|
||||
<option value="{{ s.0 }}" selected> {{ s.1 }}</option>
|
||||
|
@ -103,8 +103,8 @@
|
|||
<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" name="ip"> IP地址 </th>
|
||||
<th class="text-center"> IDC </th>
|
||||
<th class="text-center"> 所属主机组 </th>
|
||||
{# <th class="text-center"> 配置信息 </th>#}
|
||||
|
@ -119,8 +119,8 @@
|
|||
<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|default_if_none:"" }} </td>
|
||||
<td class="text-center"> {{ asset.hostname|default_if_none:"" }} </td>
|
||||
<td class="text-center"> {{ asset.ip|default_if_none:"" }} </td>
|
||||
<td class="text-center"> {{ asset.idc.name|default_if_none:"" }} </td>
|
||||
<td class="text-center">{{ asset.group.all|group_str2 }}</td>
|
||||
{# <td class="text-center">{{ asset.cpu }}|{{ asset.memory }}|{{ asset.disk }}</td>#}
|
||||
|
@ -184,26 +184,26 @@
|
|||
});
|
||||
|
||||
$(".iframe").on('click', function(){
|
||||
var ids = getIDall();
|
||||
if (ids == ''){
|
||||
var asset_id_all = getIDall();
|
||||
if (asset_id_all == ''){
|
||||
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);
|
||||
}
|
||||
});
|
||||
var url= $(this).attr("value") + '?asset_id_all=' + asset_id_all;
|
||||
layer.open({
|
||||
type: 2,
|
||||
title: 'JumpServer - 批量修改主机',
|
||||
maxmin: true,
|
||||
shift: 'top',
|
||||
border: [2, 0.3, '#1AB394'],
|
||||
shade: [0.5, '#000000'],
|
||||
shadeClose: true,
|
||||
area : ['800px' , '600px'],
|
||||
content: url,
|
||||
cancel: function(){
|
||||
location.replace(location.href);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('.search-btn-excel').unbind('click').bind('click',function(){
|
||||
|
|
|
@ -31,10 +31,6 @@
|
|||
<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>
|
||||
|
@ -44,7 +40,13 @@
|
|||
|
||||
<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>
|
||||
<option value="{{ asset.id }}">{{ asset.hostname }} - {{ 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 asset_select %}
|
||||
<option value="{{ asset.id }}">{{ asset.hostname }} - {{ asset.ip }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
|
||||
|
@ -80,7 +82,7 @@
|
|||
<div>
|
||||
<select id="assets" name="assets" class="form-control m-b" size="12" multiple>
|
||||
{% for asset in asset_all %}
|
||||
<option value="{{ asset.id }}">{{ asset.hostname|default_if_none:"" }} - {{ asset.ip|default_if_none:"" }} - {{ asset.port|default_if_none:"" }}</option>
|
||||
<option value="{{ asset.id }}">{{ asset.hostname|default_if_none:"" }} - {{ asset.ip|default_if_none:"" }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
|
|
@ -1,201 +0,0 @@
|
|||
{% 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> 主机组<span class="text-info">{{ group.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">
|
||||
<div class="">
|
||||
<a target="_blank" href="/jasset/asset_add" class="btn btn-sm btn-primary"> 添加主机 </a>
|
||||
<b class="pull-right">提示: 此页面删除只从本主机组中剔除主机 </b>
|
||||
</div>
|
||||
|
||||
<form id="contents_form" name="contents_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('contents_form')"></th>
|
||||
<th class="text-center" name="j_ip"> IP地址 </th>
|
||||
<th class="text-center"> 端口号 </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"> 是否激活 </th>
|
||||
<th class="text-center" name="j_time"> 添加时间 </th>
|
||||
<th class="text-center" name="j_comment"> 备注 </th>
|
||||
<th class="text-center"> 操作 </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for asset in contacts.object_list %}
|
||||
<tr class="gradeX">
|
||||
<td class="text-center" name="j_id" value="{{ asset.id|default_if_none:"" }}" data-editable='false'><input name="id" value="{{ asset.id }}" type="checkbox" class="i-checks"></td>
|
||||
<td class="text-center" name="j_ip"> {{ asset.ip|default_if_none:"" }} </td>
|
||||
<td class="text-center" name="j_port"> {{ asset.port|default_if_none:"" }} </td>
|
||||
<td class="text-center" name="j_idc"> {{ asset.idc.name|default_if_none:"" }} </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|default_if_none:"" }} </td>
|
||||
<td class="text-center" data-editable='false'>
|
||||
<a href="/jasset/asset_detail/?id={{ asset.id }}" class="iframe btn btn-xs btn-primary">详情</a>
|
||||
<a href="/jasset/asset_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 %}
|
||||
</tbody>
|
||||
</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')" />
|
||||
</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={{ group.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={{ group.id }}" title="第{{ page }}页">{{ page }}</a></li>
|
||||
{% else %}
|
||||
<li class="paginate_button" aria-controls="editable" tabindex="0"><a href="?keyword={{ keyword }}&page={{ page }}&id={{ group.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={{ group.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={{ group.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={{ group.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={{ group.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={{ group.id }}" title="第{{ page }}页">{{ page }}</a></li>
|
||||
{% else %}
|
||||
<li class="paginate_button" aria-controls="editable" tabindex="0"><a href="?page={{ page }}&id={{ group.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={{ group.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={{ group.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: "asset",
|
||||
url: "/jasset/host_edit/batch/",
|
||||
data: {"editable": selectData[0], "len_table": selectData[1]},
|
||||
success: function (data) {
|
||||
alert("修改成功");
|
||||
window.open("/jasset/host_list/", "_self");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function del(form) {
|
||||
var checkboxes = document.getElementById(form);
|
||||
var id_list = {};
|
||||
var group_id = $('#group_id').attr("value");
|
||||
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/group_del_host/?id=group",
|
||||
data: {"id_list": id_list, "len_list": j, "group_id": group_id},
|
||||
success: function (data) {
|
||||
window.open(window.location.href, "_self");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
|
@ -31,10 +31,6 @@
|
|||
<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>
|
||||
|
@ -44,13 +40,13 @@
|
|||
|
||||
<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>
|
||||
<option value="{{ asset.id }}">{{ asset.hostname }} - {{ asset.ip }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
|
||||
<select id="asset_select_total" name="asset_select" class="form-control m-b" size="12" multiple style="display: none">
|
||||
<select id="asset_select_total" name="j_hosts" class="form-control m-b" size="12" multiple style="display: none">
|
||||
{% for asset in asset_select %}
|
||||
<option value="{{ asset.id }}">{{ asset.ip }}</option>
|
||||
<option value="{{ asset.id }}">{{ asset.hostname }} - {{ asset.ip }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
|
||||
|
@ -86,7 +82,7 @@
|
|||
<div>
|
||||
<select id="assets" name="assets" class="form-control m-b" size="12" multiple>
|
||||
{% for asset in asset_no_select %}
|
||||
<option value="{{ asset.id }}">{{ asset.hostname|default_if_none:"" }} - {{ asset.ip|default_if_none:"" }} - {{ asset.port|default_if_none:"" }}</option>
|
||||
<option value="{{ asset.id }}">{{ asset.hostname|default_if_none:"" }} - {{ asset.ip|default_if_none:"" }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
@ -103,7 +99,7 @@
|
|||
<div>
|
||||
<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.hostname|default_if_none:"" }} - {{ asset.ip|default_if_none:"" }} - {{ asset.port|default_if_none:"" }}</option>
|
||||
<option value="{{ asset.id }}">{{ asset.hostname|default_if_none:"" }} - {{ asset.ip|default_if_none:"" }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
|
|
@ -58,10 +58,10 @@
|
|||
<input name="id" value="{{ asset_group.id }}" type="checkbox" class="i-checks">
|
||||
</td>
|
||||
<td class="text-center"> {{ asset_group.name }} </td>
|
||||
<td class="text-center"> <a href="/jasset/group_detail/?id={{ asset_group.id }}">{{ asset_group.asset_set.count }}</a> </td>
|
||||
<td class="text-center"> <a href="/jasset/asset_list/?group_id={{ asset_group.id }}">{{ asset_group.asset_set.count }}</a> </td>
|
||||
<td class="text-center"> {{ asset_group.comment }} </td>
|
||||
<td class="text-center">
|
||||
<a href="/jasset/group_detail/?id={{ asset_group.id }}" class="btn btn-xs btn-info">详情</a>
|
||||
<a href="/jasset/asset_list/?group_id={{ asset_group.id }}" class="btn btn-xs btn-info">详情</a>
|
||||
<a href="/jasset/group_edit/?id={{ asset_group.id }}" class="btn btn-xs btn-info">编辑</a>
|
||||
<a value="/jasset/group_del/?id={{ asset_group.id }}" class="btn btn-xs btn-danger group_del">删除</a>
|
||||
</td>
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
{% extends 'base.html' %}
|
||||
{% 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>
|
||||
<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="panel blank-panel">
|
||||
<div class="panel-options">
|
||||
<ul class="nav nav-tabs">
|
||||
<li><a href="/jasset/host_add/" class="text-center"><i class="fa fa-laptop"></i> 单台添加 </a></li>
|
||||
<li class="active"><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 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>请严格按照文本框内主机信息格式填写, 多台主机回车换行, 具体格式如下: </p>
|
||||
<p class="text-info">IP地址 端口号 登录方式 IDC名 所属主机组 所属部门 激活/禁用 备注 </p>
|
||||
<form id="assetMulti" method="post" class="form-horizontal">
|
||||
<div><textarea id="j_multi" name="j_multi" type="text" placeholder="192.168.1.1 22 LDAP 北京联通 [网站,数据库] 运维部 激活 网站服务器" class="form-control" style="width:700px;height:500px">192.168.1.1 22 LDAP 北京联通 ['网站','数据库'] ['运维部','测试部'] 激活 网站服务器</textarea></div>
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-4 col-sm-offset-4">
|
||||
<button class="btn btn-white" type="submit"> 重置 </button>
|
||||
<button class="btn btn-primary" type="submit"> 提交 </button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{% endblock %}
|
|
@ -1,172 +0,0 @@
|
|||
{% 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> 主机详细信息列表</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>
|
||||
<span>点击别名栏修改主机别名, 可在跳板机上使用别名直接登录.</span>
|
||||
<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="button" class="btn btn-sm btn-primary" onclick="host_search()">
|
||||
Search
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<form id="contents_form" name="contents_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('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"> 所属部门 </th>
|
||||
<th class="text-center"> 所属主机组 </th>
|
||||
<th class="text-center"> 别名 </th>
|
||||
<th class="text-center" name="j_comment"> 备注 </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" data-editable='false' name="j_ip"> {{ post.ip }} </td>
|
||||
<td class="text-center" data-editable='false' name="j_port"> {{ post.port }} </td>
|
||||
<td class="text-center" data-editable='false' name="j_type"> {{ post.login_type|get_login_type }} </td>
|
||||
<td class="text-center" data-editable='false' name="j_idc"> {{ post.idc.name }} </td>
|
||||
<td class="text-center" data-editable='false' name="j_dept">{{ post.dept.all | group_str2 }}</td>
|
||||
<td class="text-center" data-editable='false' name="j_group">{{ post.bis_group.all | group_str2_all }}</td>
|
||||
<td class="text-center" name="j_alias"> {{ post|get_user_alias:user_id }} </td>
|
||||
<td class="text-center" data-editable='false' name="j_comment"> {{ post.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>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<input type="button" id="alter_button" class="btn btn-warning btn-sm" name="alter_button" value="修改" onclick="alter('contents_form')" />
|
||||
</div>
|
||||
{% include 'paginator.html' %}
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
$('#editable').editableTableWidget();
|
||||
});
|
||||
|
||||
$(".iframe").on('click', function(){
|
||||
var url= $(this).attr("value");
|
||||
$.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}
|
||||
});
|
||||
});
|
||||
|
||||
function alter(form) {
|
||||
selectData = GetTableDataBox();
|
||||
if (selectData[1] != 0) {
|
||||
$.ajax({
|
||||
type: "post",
|
||||
url: "/jasset/host_edit_common/batch/",
|
||||
data: {"editable": selectData[0], "len_table": selectData[1]},
|
||||
success: function (data) {
|
||||
alert("修改成功");
|
||||
window.open("/jasset/host_list/", "_self");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
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/host_del/multi/",
|
||||
data: {"id_list": id_list, "len_list": j},
|
||||
success: function (data) {
|
||||
window.open("/jasset/host_list/", "_self");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function host_search(){
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: "/jasset/search/",
|
||||
data: $("#search_form").serialize(),
|
||||
success: function (data) {
|
||||
$("#contents_form").html(data);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$("#search_input").keydown(function(e){
|
||||
if(e.keyCode==13){
|
||||
host_search()
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
|
@ -1,177 +0,0 @@
|
|||
{% 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> 主机详细信息列表</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>
|
||||
<a target="_blank" href="/jasset/host_add" class="btn btn-sm btn-primary "> 添加 </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="button" class="btn btn-sm btn-primary" onclick="host_search()">-->
|
||||
<!--Search-->
|
||||
<!--</button>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
<!--</form>-->
|
||||
</div>
|
||||
|
||||
<form id="contents_form" name="contents_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('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"> 所属部门 </th>
|
||||
<th class="text-center"> 所属主机组 </th>
|
||||
<th class="text-center"> 是否激活 </th>
|
||||
<th class="text-center" name="j_comment"> 备注 </th>
|
||||
<th class="text-center"> 操作 </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for post in posts %}
|
||||
<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_dept">{{ post.dept.all | group_str2 }}</td>
|
||||
<td class="text-center" name="j_group">{{ post.bis_group.all | group_str2_all }}</td>
|
||||
<td class="text-center" name="j_active"> {{ post.is_active|bool2str }} </td>
|
||||
<td class="text-center" name="j_comment"> {{ post.comment }} </td>
|
||||
<td class="text-center" data-editable='false'>
|
||||
<a value="/jasset/{{ post.ip }}/" class="iframe btn btn-xs btn-primary">详情</a>
|
||||
{% ifnotequal session_role_id 0 %}
|
||||
<a href="/jasset/host_edit/?id={{ post.id }}" class="btn btn-xs btn-info">编辑</a>
|
||||
<a href="/jasset/host_del/{{ post.id }}" class="btn btn-xs btn-danger">删除</a>
|
||||
{% endifnotequal %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</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')" />
|
||||
</div>
|
||||
<!--{% include 'paginator.html' %}-->
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
$('#editable').editableTableWidget();
|
||||
});
|
||||
|
||||
$(".iframe").on('click', function(){
|
||||
var url= $(this).attr("value");
|
||||
$.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}
|
||||
});
|
||||
});
|
||||
|
||||
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");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
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/host_del/multi/",
|
||||
data: {"id_list": id_list, "len_list": j},
|
||||
success: function (data) {
|
||||
window.open("/jasset/host_list/", "_self");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function host_search(){
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: "/jasset/search/",
|
||||
data: $("#search_form").serialize(),
|
||||
success: function (data) {
|
||||
$("#contents_form").html(data);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$("#search_input").keydown(function(e){
|
||||
if(e.keyCode==13){
|
||||
host_search()
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
|
@ -1,169 +0,0 @@
|
|||
{% load mytags %}
|
||||
<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')"></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"> 所属业务组 </th>
|
||||
{% ifnotequal session_role_id 0 %}
|
||||
<th class="text-center"> 是否激活 </th>
|
||||
{% else %}
|
||||
<th class="text-center"> 别名 </th>
|
||||
{% endifnotequal %}
|
||||
<th class="text-center" name="j_time"> 添加时间 </th>
|
||||
<th class="text-center" name="j_comment"> 备注 </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" 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>
|
||||
{% ifnotequal session_role_id 0 %}
|
||||
<td class="text-center" name="j_alias"> {{ post.is_active|bool2str }} </td>
|
||||
{% else %}
|
||||
<td class="text-center" name="j_active"> {{ post|get_user_alias:user_id }} </td>
|
||||
{% endifnotequal %}
|
||||
<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" data-editable='false'>
|
||||
<a value="/jasset/{{ post.ip }}/" class="iframe btn btn-xs btn-primary">详情</a>
|
||||
{% ifnotequal session_role_id 0 %}
|
||||
<a href="/jasset/host_edit/?id={{ post.id }}" class="btn btn-xs btn-info">编辑</a>
|
||||
<a href="/jasset/host_del/{{ post.id }}" class="btn btn-xs btn-danger">删除</a>
|
||||
{% endifnotequal %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</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')" />
|
||||
</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 contacts.has_previous %}
|
||||
<li class="paginate_button previous" aria-controls="editable" tabindex="0" id="editable_previous">
|
||||
<a href="?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="?page=1" 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 }}" title="第{{ page }}页">{{ page }}</a></li>
|
||||
{% else %}
|
||||
<li class="paginate_button" aria-controls="editable" tabindex="0"><a href="?keyword={{ keyword }}&page={{ page }}" 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 }}" 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 }}">Next</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="paginate_button next disabled" aria-controls="editable" tabindex="0" id="editable_next">
|
||||
<a href="#">Next</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
$('#editable').editableTableWidget();
|
||||
});
|
||||
|
||||
$(".iframe").on('click', function(){
|
||||
var url= $(this).attr("value");
|
||||
$.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}
|
||||
});
|
||||
});
|
||||
|
||||
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");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
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/host_del/multi/",
|
||||
data: {"id_list": id_list, "len_list": j},
|
||||
success: function (data) {
|
||||
window.open("/jasset/host_list/", "_self");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function host_search(){
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: "/jasset/search/",
|
||||
data: $("#search_form").serialize(),
|
||||
success: function (data) {
|
||||
$("#contents_form").html(data);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$("#search_input").keydown(function(e){
|
||||
if(e.keyCode==13){
|
||||
host_search()
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
</script>
|
|
@ -1,229 +0,0 @@
|
|||
{% 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 %}
|
|
@ -52,6 +52,8 @@
|
|||
{% endifequal %}
|
||||
<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"> 操作 </th>
|
||||
</tr>
|
||||
|
@ -59,14 +61,16 @@
|
|||
<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" 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"> <a href="/jasset/asset_list/?idc_id={{ post.id }}">{{ post.asset_set.count }}</a> </td>
|
||||
<td class="text-center"> {{ post.linkman }} </td>
|
||||
<td class="text-center"> {{ post.phone }} </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/asset_list/?idc_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>
|
||||
<a href="/jasset/idc_del/?id={{ post.id }}" class="btn btn-xs btn-danger idc_del">删除</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
@ -75,7 +79,7 @@
|
|||
<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="del_check" class="btn btn-danger btn-sm" name="del_button" value="删除"/>
|
||||
<!--<input type="button" id="alter_button" class="btn btn-warning btn-sm" name="alter_button" value="修改" onclick="alter('contents_form')" />-->
|
||||
{% endifequal %}
|
||||
</div>
|
||||
|
@ -89,27 +93,37 @@
|
|||
</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");
|
||||
$(document).ready(function(){
|
||||
$('.idc_del').click(function(){
|
||||
var row = $(this).closest('tr');
|
||||
if (confirm('确定删除?')) {
|
||||
$.get(
|
||||
$(this).attr('value'),
|
||||
{},
|
||||
function (data) {
|
||||
row.remove();
|
||||
}
|
||||
)
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$('#del_check').click(function(){
|
||||
var check_array = [];
|
||||
if (confirm('确定删除?')){
|
||||
$('tr.gradeX input:checked').each(function(){
|
||||
check_array.push($(this).attr('value'))
|
||||
});
|
||||
$.get(
|
||||
'/jasset/idc_del/',
|
||||
{id: check_array.join(',')},
|
||||
function(data){
|
||||
$('tr.gradeX input:checked').closest('tr').remove();
|
||||
}
|
||||
)
|
||||
|
||||
}
|
||||
})
|
||||
});
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
|
@ -118,6 +118,37 @@
|
|||
{% endblock %}
|
||||
{% block self_footer_js %}
|
||||
<script>
|
||||
|
||||
$('#ruleForm').submit(function() {
|
||||
var result = {}
|
||||
var data = $(this).serializeArray();
|
||||
$.each(data, function(i, field){
|
||||
result[field.name] = field.value;
|
||||
});
|
||||
if (result['user'] || result['usergroup'] || result['asset'] || result['assetgroup'] || result['rulename'] || result['role']) {
|
||||
if (result['rulename'] === '') {
|
||||
alert("请添加授权名称")
|
||||
return false
|
||||
}
|
||||
if (! result['user'] && ! result['usergroup']) {
|
||||
alert("用户和用户组必选1个")
|
||||
return false
|
||||
}
|
||||
if (! result['asset'] && ! result['assetgroup']) {
|
||||
alert("资产和资产组必选1个")
|
||||
return false
|
||||
}
|
||||
if (! result['role']) {
|
||||
alert("请填写角色")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
} else {
|
||||
alert("请填必选项")
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
$(document).ready(function(){
|
||||
$("input.role").click(function(){
|
||||
if($("input.role[value=GA]").is( ":checked" )){
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
<ul class="nav nav-second-level">
|
||||
<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="asset_add asset_add_batch"><a href="/jasset/asset_add/">添加资产</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>
|
||||
|
@ -29,11 +29,11 @@
|
|||
<li id="jperm">
|
||||
<a href="#"><i class="fa fa-edit"></i> <span class="nav-label">授权管理</span><span class="fa arrow"></span></a>
|
||||
<ul class="nav nav-second-level">
|
||||
<li class="dept_perm_list dept_perm_edit">
|
||||
<li class="rule ">
|
||||
<a href="/jperm/rule/">授权规则</a>
|
||||
</li>
|
||||
|
||||
<li class="sudo_list sudo_edit sudo_add cmd_list cmd_edit cmd_add sudo_detail">
|
||||
<li class="role">
|
||||
<a href="/jperm/role/">系统角色</a>
|
||||
</li>
|
||||
<li class="apply_show online"><a href="/jperm/apply_show/online/">权限审批</a></li>
|
||||
|
|