asset add batch

pull/26/head
wangyong 2015-11-14 23:09:13 +08:00
parent ec7b543bf2
commit 0f29745bfa
11 changed files with 733 additions and 177 deletions

459
jasset/ansible_api.py Normal file
View File

@ -0,0 +1,459 @@
# -*- coding: utf-8 -*-
from ansible.inventory.group import Group
from ansible.inventory.host import Host
from ansible.inventory import Inventory
from ansible.runner import Runner
from ansible.playbook import PlayBook
from ansible import callbacks
from ansible import utils
from passlib.hash import sha512_crypt
# from utils import get_rand_pass
import random
import os.path
API_DIR = os.path.dirname(os.path.abspath(__file__))
ANSIBLE_DIR = os.path.join(API_DIR, 'playbooks')
def get_rand_pass():
"""
get a reandom password.
"""
lower = [chr(i) for i in range(97,123)]
upper = [chr(i).upper() for i in range(97,123)]
digit = [str(i) for i in range(10)]
password_pool = []
password_pool.extend(lower)
password_pool.extend(upper)
password_pool.extend(digit)
pass_list = [random.choice(password_pool) for i in range(1,14)]
pass_list.insert(random.choice(range(1,14)), '@')
pass_list.insert(random.choice(range(1,14)), random.choice(digit))
password = ''.join(pass_list)
return password
class AnsibleError(StandardError):
"""
the base AnsibleError which contains error(required),
data(optional) and message(optional).
存储所有Ansible 异常对象
"""
def __init__(self, error, data='', message=''):
super(AnsibleError, self).__init__(message)
self.error = error
self.data = data
self.message = message
class CommandValueError(AnsibleError):
"""
indicate the input value has error or invalid.
the data specifies the error field of input form.
输入不合法 异常对象
"""
def __init__(self, field, message=''):
super(CommandValueError, self).__init__('value:invalid', field, message)
class MyInventory(object):
"""
this is my ansible inventory object.
"""
def __init__(self, resource):
"""
resource的数据格式是一个列表字典比如
{
"group1": {
"hosts": [{"hostname": "10.10.10.10", "port": "22", "username": "test", "password": "mypass"}, ...],
"vars": {"var1": value1, "var2": value2, ...}
}
}
如果你只传入1个列表这默认该列表内的所有主机属于my_group组,比如
[{"hostname": "10.10.10.10", "port": "22", "username": "test", "password": "mypass"}, ...]
"""
self.resource = resource
self.inventory = Inventory()
self.gen_inventory()
def add_group(self, hosts, groupname, groupvars=None):
"""
add hosts to a group
"""
my_group = Group(name=groupname)
# if group variables exists, add them to group
if groupvars:
for key, value in groupvars.iteritems():
my_group.set_variable(key, value)
# add hosts to group
for host in hosts:
# set connection variables
hostname = host.get("hostname")
hostport = host.get("port")
username = host.get("username")
password = host.get("password")
my_host = Host(name=hostname, port=hostport)
my_host.set_variable('ansible_ssh_host', hostname)
my_host.set_variable('ansible_ssh_port', hostport)
my_host.set_variable('ansible_ssh_user', username)
my_host.set_variable('ansible_ssh_pass', password)
# set other variables
for key, value in host.iteritems():
if key not in ["hostname", "port", "username", "password"]:
my_host.set_variable(key, value)
# add to group
my_group.add_host(my_host)
self.inventory.add_group(my_group)
def gen_inventory(self):
"""
add hosts to inventory.
"""
if isinstance(self.resource, list):
self.add_group(self.resource, 'my_group')
elif isinstance(self.resource, dict):
for groupname, hosts_and_vars in self.resource.iteritems():
self.add_group(hosts_and_vars.get("hosts"), groupname, hosts_and_vars.get("vars"))
class Command(MyInventory):
"""
this is a command object for parallel execute command.
"""
def __init__(self, *args, **kwargs):
super(Command, self).__init__(*args, **kwargs)
self.results = ''
def run(self, command, module_name="command", timeout=5, forks=10, group='my_group'):
"""
run command from andible ad-hoc.
command : 必须是一个需要执行的命令字符串 比如
'uname -a'
"""
if module_name not in ["raw", "command", "shell"]:
raise CommandValueError("module_name",
"module_name must be of the 'raw, command, shell'")
hoc = Runner(module_name=module_name,
module_args=command,
timeout=timeout,
inventory=self.inventory,
subset=group,
forks=forks
)
self.results = hoc.run()
if self.stdout:
return {"ok": self.stdout}
else:
msg = []
if self.stderr:
msg.append(self.stderr)
if self.dark:
msg.append(self.dark)
return {"failed": msg}
@property
def raw_results(self):
"""
get the ansible raw results.
"""
return self.results
@property
def exec_time(self):
"""
get the command execute time.
"""
result = {}
all = self.results.get("contacted")
for key, value in all.iteritems():
result[key] = {
"start": value.get("start"),
"end" : value.get("end"),
"delta": value.get("delta"),}
return result
@property
def stdout(self):
"""
get the comamnd standard output.
"""
result = {}
all = self.results.get("contacted")
for key, value in all.iteritems():
result[key] = value.get("stdout")
return result
@property
def stderr(self):
"""
get the command standard error.
"""
result = {}
all = self.results.get("contacted")
for key, value in all.iteritems():
result[key] = {
"stderr": value.get("stderr"),
"warnings": value.get("warnings"),}
return result
@property
def dark(self):
"""
get the dark results.
"""
return self.results.get("dark")
class Tasks(Command):
"""
this is a tasks object for include the common command.
"""
def __init__(self, *args, **kwargs):
super(Tasks, self).__init__(*args, **kwargs)
def __run(self, module_args, module_name="command", timeout=5, forks=10, group='my_group'):
"""
run command from andible ad-hoc.
command : 必须是一个需要执行的命令字符串 比如
'uname -a'
"""
hoc = Runner(module_name=module_name,
module_args=module_args,
timeout=timeout,
inventory=self.inventory,
subset=group,
forks=forks
)
self.results = hoc.run()
@property
def msg(self):
"""
get the contacted and dark msg
"""
msg = {}
for result in ["contacted", "dark"]:
all = self.results.get(result)
for key, value in all.iteritems():
if value.get("msg"):
msg[key] = value.get("msg")
return msg
def push_key(self, user, key_path):
"""
push the ssh authorized key to target.
"""
module_args = 'user="%s" key="{{ lookup("file", "%s") }}"' % (user, key_path)
self.__run(module_args, "authorized_key")
return {"status": "failed","msg": self.msg} if self.msg else {"status": "ok"}
def del_key(self, user, key_path):
"""
push the ssh authorized key to target.
"""
module_args = 'user="%s" key="{{ lookup("file", "%s") }}" state="absent"' % (user, key_path)
self.__run(module_args, "authorized_key")
return {"status": "failed","msg": self.msg} if self.msg else {"status": "ok"}
def add_user(self, username, password):
"""
add a host user.
"""
encrypt_pass = sha512_crypt.encrypt(password)
module_args = 'name=%s shell=/bin/bash password=%s' % (username, encrypt_pass)
self.__run(module_args, "user")
return {"status": "failed","msg": self.msg} if self.msg else {"status": "ok"}
def add_multi_user(self, *args):
"""
add multi user
:param args:
user
:return:
"""
results = {}
users = {}
action = results["action_info"] = {}
for user in args:
users[user] = get_rand_pass()
for user, password in users.iteritems():
ret = self.add_user(user, password)
action[user] = ret
results["user_info"] = users
return results
def del_user(self, username):
"""
delete a host user.
"""
module_args = 'name=%s state=absent remove=yes move_home=yes force=yes' % (username)
self.__run(module_args, "user")
return {"status": "failed","msg": self.msg} if self.msg else {"status": "ok"}
def add_init_users(self):
"""
add initail users: SA, DBA, DEV
"""
results = {}
action = results["action_info"] = {}
users = {"SA": get_rand_pass(), "DBA": get_rand_pass(), "DEV": get_rand_pass()}
for user, password in users.iteritems():
ret = self.add_user(user, password)
action[user] = ret
results["user_info"] = users
return results
def del_init_users(self):
"""
delete initail users: SA, DBA, DEV
"""
results = {}
action = results["action_info"] = {}
for user in ["SA", "DBA", "DEV"]:
ret = self.del_user(user)
action[user] = ret
return results
def get_host_info(self):
"""
use the setup module get host informations
:return:
all_ip is list
processor_count is int
system_dist_version is string
system_type is string
disk is dict (device_name: device_size}
system_dist is string
processor_type is string
default_ip is string
hostname is string
product_sn is string
memory_total is int (MB)
default_mac is string
product_name is string
"""
self.__run('', 'setup')
result = {}
all = self.results.get("contacted")
for key, value in all.iteritems():
setup =value.get("ansible_facts")
# get disk informations
disk_all = setup.get("ansible_devices")
disk_need = {}
for disk_name, disk_info in disk_all.iteritems():
if disk_name.startswith('sd') or disk_name.startswith('hd') or disk_name.startswith('vd'):
disk_need[disk_name] = disk_info.get("size")
result[key] = {
"other_ip": setup.get("ansible_all_ipv4_addresses"),
"hostname": setup.get("ansible_hostname" ),
"ip": setup.get("ansible_default_ipv4").get("address"),
"mac": setup.get("ansible_default_ipv4").get("macaddress"),
"brand": setup.get("ansible_product_name"),
"cpu_type": setup.get("ansible_processor"),
"cpu_cores": setup.get("ansible_processor_count"),
"memory": setup.get("ansible_memtotal_mb"),
"disk": disk_need,
"system_type": setup.get("ansible_distribution"),
"system_version": setup.get("ansible_distribution_version"),
"asset_type": setup.get("ansible_system"),
"sn": setup.get("ansible_product_serial")
}
return {"status": "failed", "msg": self.msg} if self.msg else {"status": "ok", "result": result}
class CustomAggregateStats(callbacks.AggregateStats):
"""
Holds stats about per-host activity during playbook runs.
"""
def __init__(self):
super(CustomAggregateStats, self).__init__()
self.results = []
def compute(self, runner_results, setup=False, poll=False,
ignore_errors=False):
"""
Walk through all results and increment stats.
"""
super(CustomAggregateStats, self).compute(runner_results, setup, poll,
ignore_errors)
self.results.append(runner_results)
def summarize(self, host):
"""
Return information about a particular host
"""
summarized_info = super(CustomAggregateStats, self).summarize(host)
# Adding the info I need
summarized_info['result'] = self.results
return summarized_info
class MyPlaybook(MyInventory):
"""
this is my playbook object for execute playbook.
"""
def __init__(self, *args, **kwargs):
super(MyPlaybook, self).__init__(*args, **kwargs)
def run(self, playbook_relational_path, extra_vars=None):
"""
run ansible playbook,
only surport relational path.
"""
stats = callbacks.AggregateStats()
playbook_cb = callbacks.PlaybookCallbacks(verbose=utils.VERBOSITY)
runner_cb = callbacks.PlaybookRunnerCallbacks(stats, verbose=utils.VERBOSITY)
playbook_path = os.path.join(ANSIBLE_DIR, playbook_relational_path)
pb = PlayBook(
playbook = playbook_path,
stats = stats,
callbacks = playbook_cb,
runner_callbacks = runner_cb,
inventory = self.inventory,
extra_vars = extra_vars,
check=False)
self.results = pb.run()
@property
def raw_results(self):
"""
get the raw results after playbook run.
"""
return self.results
class App(MyPlaybook):
"""
this is a app object for inclue the common playbook.
"""
def __init__(self, *args, **kwargs):
super(App, self).__init__(*args, **kwargs)
if __name__ == "__main__":
pass

View File

@ -1,5 +1,5 @@
# coding: utf-8
import ast
import xlrd
import xlsxwriter
from django.db.models import AutoField
from jumpserver.api import *
@ -226,7 +226,7 @@ def asset_diff(before, after):
def asset_diff_one(before, after):
print before.__dict__, after.__dict__
fields = Asset._meta.get_all_field_names()
fields = Asset._meta.get_all_field_names()
for field in fields:
print before.field, after.field
@ -270,7 +270,7 @@ def db_asset_alert(asset, username, alert_dic):
else:
name = asset.username
alert_info = [field_name, u'默认', name] if unicode(value[0]) == 'True' else \
[field_name, name, u'默认']
[field_name, name, u'默认']
elif field in ['username', 'password']:
continue
@ -281,7 +281,7 @@ def db_asset_alert(asset, username, alert_dic):
continue
else:
alert_info = [u'是否激活', u'激活', u'禁用'] if unicode(value[0]) == 'True' else \
[u'是否激活', u'禁用', u'激活']
[u'是否激活', u'禁用', u'激活']
else:
alert_info = [field_name, unicode(value[0]), unicode(value[1])]
@ -310,8 +310,10 @@ def write_excel(asset_all):
group_all = '/'.join(group_list)
status = asset.get_status_display()
alter_dic = [asset.hostname, asset.ip, asset.idc.name, asset.mac, asset.remote_ip, asset.cpu, asset.memory,
asset.disk, asset.system_type, asset.cabinet, group_all, status, asset.comment]
idc_name = asset.idc.name if asset.idc else u''
alter_dic = [asset.hostname, asset.ip, idc_name, asset.mac, asset.remote_ip, asset.cpu, asset.memory,
asset.disk, (asset.system_type + asset.system_version), asset.cabinet, group_all, status,
asset.comment]
data.append(alter_dic)
format = workbook.add_format()
format.set_border(1)
@ -342,6 +344,62 @@ def write_excel(asset_all):
def copy_model_instance(obj):
initial = dict([(f.name, getattr(obj, f.name))
for f in obj._meta.fields
if not isinstance(f, AutoField) and\
not f in obj._meta.parents.values()])
return obj.__class__(**initial)
if not isinstance(f, AutoField) and \
not f in obj._meta.parents.values()])
return obj.__class__(**initial)
def ansible_record(asset, ansible_dic, username):
alert_dic = {}
asset_dic = asset.__dict__
for field, value in ansible_dic.items():
old = asset_dic.get(field)
new = ansible_dic.get(field)
if unicode(old) != unicode(new):
print old, new, type(old), type(new)
setattr(asset, field, value)
asset.save()
alert_dic[field] = [old, new]
db_asset_alert(asset, username, alert_dic)
def excel_to_db(excel_file):
"""
Asset add batch function
"""
try:
data = xlrd.open_workbook(filename=None, file_contents=excel_file.read())
except Exception, e:
return False
else:
table = data.sheets()[0]
rows = table.nrows
group_instance = []
for row_num in range(1, rows):
row = table.row_values(row_num)
if row:
ip, port, hostname, use_default_auth, username, password, group = row
print ip
use_default_auth = 1 if use_default_auth == u'默认' else 0
if get_object(Asset, ip=ip):
continue
if ip and port:
asset = Asset(ip=ip,
port=port,
use_default_auth=use_default_auth,
username=username,
password=password
)
asset.save()
group_list = group.split('/')
for group_name in group_list:
group = get_object(AssetGroup, name=group_name)
if group:
group_instance.append(group)
if group_instance:
print group_instance
asset.group = group_instance
asset.save()
return True

View File

@ -80,7 +80,7 @@ class Asset(models.Model):
status = models.IntegerField(max_length=2, choices=ASSET_STATUS, blank=True, null=True, default=1, verbose_name=u"机器状态")
asset_type = models.IntegerField(max_length=2, choices=ASSET_TYPE, blank=True, null=True, verbose_name=u"主机类型")
env = models.IntegerField(max_length=2, choices=ASSET_ENV, blank=True, null=True, verbose_name=u"运行环境")
sn = models.CharField(max_length=32, blank=True, null=True, verbose_name=u"SN编号")
sn = models.CharField(max_length=128, blank=True, null=True, verbose_name=u"SN编号")
date_added = models.DateTimeField(auto_now=True, default=datetime.datetime.now(), null=True)
is_active = models.BooleanField(default=True, verbose_name=u"是否激活")
comment = models.CharField(max_length=128, blank=True, null=True, verbose_name=u"备注")

View File

@ -1,151 +0,0 @@
# coding: utf-8
import datetime
from django.db import models
from juser.models import User, UserGroup
class AssetGroup(models.Model):
GROUP_TYPE = (
('P', 'PRIVATE'),
('A', 'ASSET'),
)
name = models.CharField(max_length=80, unique=True)
comment = models.CharField(max_length=160, blank=True, null=True)
def __unicode__(self):
return self.name
def get_asset(self):
return self.asset_set.all()
def get_asset_info(self, printable=False):
assets = self.get_asset()
ip_comment = {}
for asset in assets:
ip_comment[asset.ip] = asset.comment
for ip in sorted(ip_comment):
if ip_comment[ip]:
print '%-15s -- %s' % (ip, ip_comment[ip])
else:
print '%-15s' % ip
print ''
def get_asset_num(self):
return len(self.get_asset())
def get_user_group(self):
perm_list = self.perm_set.all()
user_group_list = []
for perm in perm_list:
user_group_list.append(perm.user_group)
return user_group_list
def get_user(self):
user_list = []
user_group_list = self.get_user_group()
for user_group in user_group_list:
user_list.extend(user_group.user_set.all())
return user_list
def is_permed(self, user=None, user_group=None):
if user:
if user in self.get_user():
return True
if user_group:
if user_group in self.get_user_group():
return True
return False
class IDC(models.Model):
name = models.CharField(max_length=32, unique=True)
bandwidth = models.CharField(max_length=32, blank=True, null=True)
linkman = models.CharField(max_length=16, blank=True, null=True)
phone = models.CharField(max_length=32, blank=True, null=True)
address = models.CharField(max_length=128, blank=True, null=True)
network = models.TextField(blank=True, null=True)
date_added = models.DateField(auto_now=True, default=datetime.datetime.now())
operator = models.IntegerField(max_length=32, blank=True, null=True)
comment = models.CharField(max_length=128, blank=True, null=True)
def __unicode__(self):
return self.name
class Asset(models.Model):
"""
asset modle
"""
ENVIRONMENT = (
(0, U'生产环境'),
(1, U'测试环境')
)
SERVER_STATUS = (
(0, u"已使用"),
(1, u"未使用"),
(2, u"报废")
)
ASSET_TYPE = (
(0, u"服务器"),
(2, u"网络设备"),
(3, u"其他")
)
ip = models.IPAddressField(unique=True)
second_ip = models.CharField(max_length=255, blank=True, null=True)
hostname = models.CharField(max_length=64, blank=True, null=True)
port = models.IntegerField(max_length=6)
group = models.ManyToManyField(AssetGroup, blank=True, null=True)
username = models.CharField(max_length=16, blank=True, null=True)
password = models.CharField(max_length=64, blank=True, null=True)
use_default_auth = models.BooleanField(default=True)
idc = models.ForeignKey(IDC, blank=True, null=True, on_delete=models.SET_NULL)
mac = models.CharField(max_length=20, blank=True, null=True)
remote_ip = models.IPAddressField(unique=True, blank=True, null=True)
brand = models.CharField(max_length=64, blank=True, null=True)
cpu = models.CharField(max_length=64, blank=True, null=True)
memory = models.CharField(max_length=128, blank=True, null=True)
disk = models.CharField(max_length=128, blank=True, null=True)
system_type = models.CharField(max_length=32, blank=True, null=True)
system_version = models.CharField(max_length=8, blank=True, null=True)
cabinet = models.CharField(max_length=32, blank=True, null=True)
position = models.IntegerField(max_length=2, blank=True, null=True)
number = models.CharField(max_length=32, blank=True, null=True)
status = models.IntegerField(max_length=2, choices=SERVER_STATUS, default=1)
asset_type = models.IntegerField(max_length=2, choices=ASSET_TYPE, blank=True, null=True)
env = models.CharField(max_length=32, choices=ENVIRONMENT, blank=True, null=True)
sn = models.CharField(max_length=32, blank=True, null=True)
date_added = models.DateTimeField(auto_now=True, default=datetime.datetime.now())
is_active = models.BooleanField(default=True)
comment = models.CharField(max_length=128, blank=True, null=True)
def __unicode__(self):
return self.ip
def get_user(self):
perm_list = []
asset_group_all = self.bis_group.all()
for asset_group in asset_group_all:
perm_list.extend(asset_group.perm_set.all())
user_group_list = []
for perm in perm_list:
user_group_list.append(perm.user_group)
user_permed_list = []
for user_group in user_group_list:
user_permed_list.extend(user_group.user_set.all())
user_permed_list = list(set(user_permed_list))
return user_permed_list
class AssetAlias(models.Model):
user = models.ForeignKey(User)
asset = models.ForeignKey(Asset)
alias = models.CharField(max_length=100, null=True)
def __unicode__(self):
return self.alias

View File

@ -4,15 +4,14 @@ from jasset.views import *
urlpatterns = patterns('',
url(r'^asset_add/$', asset_add),
# url(r"^host_add_multi/$", host_add_batch),
url(r"^asset_add_batch/$", asset_add_batch),
url(r'^group_del/$', group_del),
url(r'^asset_list/$', asset_list),
url(r'^asset_del/$', asset_del),
url(r"^asset_detail/$", asset_detail),
url(r'^asset_edit/$', asset_edit),
url(r'^asset_update/$', asset_update),
# url(r'^search/$', host_search),
# url(r"^host_detail/$", host_detail),
# url(r"^dept_host_ajax/$", dept_host_ajax),
# url(r"^show_all_ajax/$", show_all_ajax),
url(r'^group_add/$', group_add),
url(r'^group_list/$', group_list),
@ -27,4 +26,5 @@ urlpatterns = patterns('',
url(r'^idc_detail/$', idc_detail),
url(r'^idc_edit/$', idc_edit),
url(r'^idc_del/$', idc_del),
url(r'^upload/$', asset_upload),
)

View File

@ -1,14 +1,13 @@
# coding:utf-8
import ast
from django.db.models import Q
from django.shortcuts import get_object_or_404
from jasset.asset_api import *
from jumpserver.api import *
from jasset.forms import AssetForm, IdcForm
from jasset.models import Asset, IDC, AssetGroup, ASSET_TYPE, ASSET_STATUS
from ansible_api import Tasks
@require_role('admin')
@ -175,6 +174,12 @@ def asset_add(request):
return my_render('jasset/asset_add.html', locals(), request)
@require_role('admin')
def asset_add_batch(request):
header_title, path1, path2 = u'添加资产', u'资产管理', u'批量添加'
return my_render('jasset/asset_add_batch.html', locals(), request)
@require_role('admin')
def asset_del(request):
"""
@ -207,8 +212,6 @@ def asset_edit(request):
asset_id = request.GET.get('id', '')
username = request.session.get('username', 'admin')
# if not asset_id:
# return HttpResponse('没有该主机')
asset = get_object(Asset, id=asset_id)
asset_old = copy_model_instance(asset)
af = AssetForm(instance=asset)
@ -231,8 +234,8 @@ def asset_edit(request):
af_save.password = ''
af_save.save()
af_post.save_m2m()
asset_new = get_object(Asset, id=asset_id)
asset_diff_one(asset_old, asset_new)
# asset_new = get_object(Asset, id=asset_id)
# asset_diff_one(asset_old, asset_new)
info = asset_diff(af_post.__dict__.get('initial'), request.POST)
db_asset_alert(asset, username, info)
@ -306,7 +309,7 @@ def asset_edit_batch(request):
@require_role('admin')
def asset_detail(request):
"""
主机详情
Asset detail view
"""
header_title, path1, path2 = u'主机详细信息', u'资产管理', u'主机详情'
asset_id = request.GET.get('id', '')
@ -316,6 +319,53 @@ def asset_detail(request):
return my_render('jasset/asset_detail.html', locals(), request)
@require_role('admin')
def asset_update(request):
"""
Asset update host info via ansible view
"""
asset_id = request.GET.get('id', '')
asset = get_object(Asset, id=asset_id)
if not asset:
return HttpResponseRedirect('/jasset/asset_detail/?id=%s' % asset_id)
name = request.session.get('username', 'admin')
if asset.use_default_auth:
username = 'root'
password = '123456'
else:
username = asset.username
password = asset.password
resource = [{"hostname": asset.ip, "port": asset.port,
"username": username, "password": password}]
ansible_instance = Tasks(resource)
ansible_asset_info = ansible_instance.get_host_info()
if ansible_asset_info['status'] == 'ok':
asset_info = ansible_asset_info['result'][asset.ip]
if asset_info:
hostname = asset_info.get('hostname')
other_ip = ','.join(asset_info.get('other_ip'))
cpu_type = asset_info.get('cpu_type')[1]
cpu_cores = asset_info.get('cpu_cores')
cpu = cpu_type + ' * ' + unicode(cpu_cores)
memory = asset_info.get('memory')
disk = asset_info.get('disk')
sn = asset_info.get('sn')
brand = asset_info.get('brand')
system_type = asset_info.get('system_type')
system_version = asset_info.get('system_version')
asset_dic = {"hostname": hostname, "other_ip": other_ip, "cpu": cpu,
"memory": memory, "disk": disk, "system_type": system_type,
"system_version": system_version, "brand": brand, "sn": sn
}
ansible_record(asset, asset_dic, name)
return HttpResponseRedirect('/jasset/asset_detail/?id=%s' % asset_id)
@require_role('admin')
def idc_add(request):
"""
@ -343,6 +393,9 @@ def idc_add(request):
@require_role('admin')
def idc_list(request):
"""
IDC list view
"""
header_title, path1, path2 = u'查看IDC', u'资产管理', u'查看IDC'
posts = IDC.objects.all()
keyword = request.GET.get('keyword', '')
@ -358,6 +411,10 @@ def idc_list(request):
@require_role('admin')
def idc_edit(request):
"""
IDC edit view
"""
header_title, path1, path2 = u'编辑IDC', u'资产管理', u'编辑IDC'
idc_id = request.GET.get('id', '')
idc = get_object(IDC, id=idc_id)
if request.method == 'POST':
@ -372,7 +429,9 @@ def idc_edit(request):
@require_role('admin')
def idc_detail(request):
""" IDC详情 """
"""
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)
@ -384,7 +443,25 @@ def idc_detail(request):
@require_role('admin')
def idc_del(request):
"""
IDC delete view
"""
uuid = request.GET.get('uuid', '')
idc = get_object_or_404(IDC, uuid=uuid)
idc.delete()
return HttpResponseRedirect('/jasset/idc_list/')
@require_role('admin')
def asset_upload(request):
"""
Upload file view
"""
if request.method == 'POST':
excel_file = request.FILES.get('file_name', '')
ret = excel_to_db(excel_file)
if ret:
smg = u'批量添加成功'
else:
emg = u'批量添加失败,请检查格式.'
return my_render('jasset/asset_add_batch.html', locals(), request)

View File

@ -415,12 +415,29 @@ def str_to_list(info):
"""
str to list
"""
print ast.literal_eval(info), type(ast.literal_eval(info))
return ast.literal_eval(info)
@register.filter(name='str_to_dic')
def str_to_dic(info):
"""
str to list
"""
return ast.literal_eval(info).iteritems()
@register.filter(name='str_to_code')
def str_to_code(char_str):
if char_str:
return char_str
else:
return u''
@register.filter(name='ip_str_to_list')
def ip_str_to_list(ip_str):
"""
ip str to list
"""
return ip_str.split(',')

View File

@ -27,7 +27,7 @@
<div class="panel-options">
<ul class="nav nav-tabs">
<li class="active"><a href="/jasset/asset_add/" class="text-center"><i class="fa fa-laptop"></i> 单台添加 </a></li>
<li><a href="/jasset/host_add_multi" class="text-center"><i class="fa fa-bar-chart-o"></i> 批量添加 </a></li>
<li><a href="/jasset/asset_add_batch" class="text-center"><i class="fa fa-bar-chart-o"></i> 批量添加 </a></li>
</ul>
</div>
<div class="panel-body">

View File

@ -0,0 +1,65 @@
{% extends 'base.html' %}
{% block content %}
{% include 'nav_cat_bar.html' %}
<style>
.file-box{ position:relative;width:340px}
.txt{ height:22px; border:1px solid #cdcdcd; width:180px;}
.file{ position:absolute; top:0; right:80px; height:24px; filter:alpha(opacity:0);opacity: 0;width:260px }
</style>
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-lg-10">
<div class="ibox float-e-margins">
<div id="ibox-content" class="ibox-title">
<h5> 填写主机基本信息 </h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content">
<div class="panel blank-panel">
<div class="panel-options">
<ul class="nav nav-tabs">
<li><a href="/jasset/asset_add/" class="text-center"><i class="fa fa-laptop"></i> 单台添加 </a></li>
<li class="active"><a href="/jasset/asset_add_batch/" class="text-center"><i class="fa fa-bar-chart-o"></i> 批量添加 </a></li>
</ul>
</div>
<div class="panel-body">
<div id="tab-2" class="ibox float-e-margins tab-pane active">
{% if emg %}
<div class="alert alert-warning text-center">{{ emg }}</div>
{% endif %}
{% if smg %}
<div class="alert alert-success text-center">{{ smg }}</div>
{% endif %}
<p>请下载Excel文件, 按照格式填写主机信息, 上传导入. <a href="/static/files/excels/asset.xlsx">点击下载模板</a></p>
<form action="/jasset/upload/" method="POST" enctype="multipart/form-data">
<div class="file-box">
<input id='textfield' />
<input type="button" class="btn btn-info btn-sm" name="file_name" value="点击选择文件">
<input type="file" name="file_name" class="file" id="fileField" size="28" onchange="document.getElementById('textfield').value=this.value" />
<button class="btn btn-primary btn-sm" type="submit">上传文件</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -37,6 +37,20 @@
<td class="text-navy">主机名</td>
<td>{{ asset.hostname }}</td>
</tr>
<tr>
<td class="text-navy">其他IP</td>
<td>
<table class="table">
{% if asset.other_ip %}
{% for ip in asset.other_ip|ip_str_to_list %}
<tr>
<td>{{ ip }}</td>
</tr>
{% endfor %}
{% endif %}
</table>
</td>
</tr>
<tr>
<td class="text-navy">远控IP</td>
<td>{{ asset.remote_ip }}</td>
@ -77,11 +91,21 @@
</tr>
<tr>
<td class="text-navy">内存</td>
<td>{{ asset.memory }}</td>
<td>{{ asset.memory }}M</td>
</tr>
<tr>
<td class="text-navy">硬盘</td>
<td>{{ asset.disk }}</td>
<td>
<table class="table">
{% if asset.disk %}
{% for disk, value in asset.disk|str_to_dic %}
<tr>
<td><span class="text-navy">{{ disk }}</span> &nbsp&nbsp&nbsp {{ value }}</td>
</tr>
{% endfor %}
{% endif %}
</table>
</td>
</tr>
<tr>
<td class="text-navy">资产编号</td>
@ -95,6 +119,10 @@
<td class="text-navy">主机类型</td>
<td>{{ asset.get_asset_type_display }}</td>
</tr>
<tr>
<td class="text-navy">系统版本</td>
<td>{{ asset.system_type }} {{ asset.system_version }}</td>
</tr>
<tr>
<td class="text-navy">运行环境</td>
<td>{{ asset.get_env_display }}</td>

View File

@ -107,7 +107,8 @@
<th class="text-center"> 主机名 </th>
<th class="text-center"> IDC </th>
<th class="text-center"> 所属主机组 </th>
<th class="text-center"> 配置信息 </th>
{# <th class="text-center"> 配置信息 </th>#}
<th class="text-center"> 操作系统 </th>
<th class="text-center"> 使用默认管理 </th>
<th class="text-center"> 操作 </th>
</tr>
@ -122,12 +123,14 @@
<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.cpu }}|{{ asset.memory }}|{{ asset.disk }}</td>#}
<td class="text-center">{{ asset.system_type }}{{ asset.system_version }}</td>
<td class="text-center"> {{ asset.use_default_auth|bool2str }} </td>
<td class="text-center" data-editable='false'>
<a href="/jasset/asset_detail/?id={{ asset.id }}" class="btn btn-xs btn-primary">详情</a>
{% ifnotequal session_role_id 0 %}
<a href="/jasset/asset_edit/?id={{ asset.id }}" class="btn btn-xs btn-info">编辑</a>
<a href="/jasset/asset_update/?id={{ asset.id }}" class="btn btn-xs btn-info">更新</a>
<a value="/jasset/asset_del/?id={{ asset.id }}" class="btn btn-xs btn-danger asset_del">删除</a>
{% endifnotequal %}
</td>