diff --git a/jasset/ansible_api.py b/jasset/ansible_api.py new file mode 100644 index 000000000..7041c7bf1 --- /dev/null +++ b/jasset/ansible_api.py @@ -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 + + diff --git a/jasset/asset_api.py b/jasset/asset_api.py index b0f3c9b8c..998d669c5 100644 --- a/jasset/asset_api.py +++ b/jasset/asset_api.py @@ -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) \ No newline at end of file + 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 diff --git a/jasset/models.py b/jasset/models.py index 020caf431..f58202dc7 100644 --- a/jasset/models.py +++ b/jasset/models.py @@ -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"备注") diff --git a/jasset/models_bak.py b/jasset/models_bak.py deleted file mode 100644 index 9c9252a7f..000000000 --- a/jasset/models_bak.py +++ /dev/null @@ -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 diff --git a/jasset/urls.py b/jasset/urls.py index da902558a..c9ec8c462 100644 --- a/jasset/urls.py +++ b/jasset/urls.py @@ -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), ) \ No newline at end of file diff --git a/jasset/views.py b/jasset/views.py index fd2eadc1f..ba5becbdd 100644 --- a/jasset/views.py +++ b/jasset/views.py @@ -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) diff --git a/jumpserver/templatetags/mytags.py b/jumpserver/templatetags/mytags.py index 0a63dc333..b6ad516d7 100644 --- a/jumpserver/templatetags/mytags.py +++ b/jumpserver/templatetags/mytags.py @@ -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(',') diff --git a/templates/jasset/asset_add.html b/templates/jasset/asset_add.html index c7442209d..1d8eacc28 100644 --- a/templates/jasset/asset_add.html +++ b/templates/jasset/asset_add.html @@ -27,7 +27,7 @@
diff --git a/templates/jasset/asset_add_batch.html b/templates/jasset/asset_add_batch.html new file mode 100644 index 000000000..2a9512a98 --- /dev/null +++ b/templates/jasset/asset_add_batch.html @@ -0,0 +1,65 @@ +{% extends 'base.html' %} +{% block content %} +{% include 'nav_cat_bar.html' %} + +
+
+
+
+
+
填写主机基本信息
+
+ + + + + + + + + + +
+
+ +
+
+ +
+
+ {% if emg %} +
{{ emg }}
+ {% endif %} + {% if smg %} +
{{ smg }}
+ {% endif %} +

请下载Excel文件, 按照格式填写主机信息, 上传导入. 点击下载模板

+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ +{% endblock %} \ No newline at end of file diff --git a/templates/jasset/asset_detail.html b/templates/jasset/asset_detail.html index 4733ab04e..1f8d0d130 100644 --- a/templates/jasset/asset_detail.html +++ b/templates/jasset/asset_detail.html @@ -37,6 +37,20 @@ 主机名 {{ asset.hostname }} + + 其他IP + + + {% if asset.other_ip %} + {% for ip in asset.other_ip|ip_str_to_list %} + + + + {% endfor %} + {% endif %} +
{{ ip }}
+ + 远控IP {{ asset.remote_ip }} @@ -77,11 +91,21 @@ 内存 - {{ asset.memory }} + {{ asset.memory }}M 硬盘 - {{ asset.disk }} + + + {% if asset.disk %} + {% for disk, value in asset.disk|str_to_dic %} + + + + {% endfor %} + {% endif %} +
{{ disk }}     {{ value }}
+ 资产编号 @@ -95,6 +119,10 @@ 主机类型 {{ asset.get_asset_type_display }} + + 系统版本 + {{ asset.system_type }} {{ asset.system_version }} + 运行环境 {{ asset.get_env_display }} diff --git a/templates/jasset/asset_list.html b/templates/jasset/asset_list.html index 7a7bbf937..133e41eea 100644 --- a/templates/jasset/asset_list.html +++ b/templates/jasset/asset_list.html @@ -107,7 +107,8 @@ 主机名 IDC 所属主机组 - 配置信息 +{# 配置信息 #} + 操作系统 使用默认管理 操作 @@ -122,12 +123,14 @@ {{ asset.hostname }} {{ asset.idc.name }} {{ asset.group.all|group_str2 }} - {{ asset.cpu }}|{{ asset.memory }}|{{ asset.disk }} +{# {{ asset.cpu }}|{{ asset.memory }}|{{ asset.disk }}#} + {{ asset.system_type }}{{ asset.system_version }} {{ asset.use_default_auth|bool2str }} 详情 {% ifnotequal session_role_id 0 %} 编辑 + 更新 删除 {% endifnotequal %}