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 %}
+
+ {{ ip }} |
+
+ {% endfor %}
+ {% endif %}
+
+ |
+
远控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 %}
+
+ {{ disk }}     {{ value }} |
+
+ {% endfor %}
+ {% endif %}
+
+ |
资产编号 |
@@ -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 %}
|