mirror of https://github.com/jumpserver/jumpserver
commit
a2aa923abe
|
@ -48,7 +48,7 @@ class AssetViewSet(IDInFilterMixin, LabelFilter, BulkModelViewSet):
|
||||||
return
|
return
|
||||||
|
|
||||||
node = get_object_or_404(Node, id=node_id)
|
node = get_object_or_404(Node, id=node_id)
|
||||||
show_current_asset = self.request.query_params.get("show_current_asset")
|
show_current_asset = self.request.query_params.get("show_current_asset") in ('1', 'true')
|
||||||
|
|
||||||
if node.is_root():
|
if node.is_root():
|
||||||
if show_current_asset:
|
if show_current_asset:
|
||||||
|
|
|
@ -36,6 +36,10 @@ class DomainForm(forms.ModelForm):
|
||||||
|
|
||||||
|
|
||||||
class GatewayForm(PasswordAndKeyAuthForm, OrgModelForm):
|
class GatewayForm(PasswordAndKeyAuthForm, OrgModelForm):
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
password_field = self.fields.get('password')
|
||||||
|
password_field.help_text = _('Password should not contain special characters')
|
||||||
|
|
||||||
def save(self, commit=True):
|
def save(self, commit=True):
|
||||||
# Because we define custom field, so we need rewrite :method: `save`
|
# Because we define custom field, so we need rewrite :method: `save`
|
||||||
|
|
|
@ -6,8 +6,10 @@ import uuid
|
||||||
import logging
|
import logging
|
||||||
import random
|
import random
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
|
from collections import defaultdict
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
from django.db.models import Q
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
|
|
||||||
|
@ -100,6 +102,7 @@ class Asset(OrgModelMixin):
|
||||||
verbose_name=_('CPU model'))
|
verbose_name=_('CPU model'))
|
||||||
cpu_count = models.IntegerField(null=True, verbose_name=_('CPU count'))
|
cpu_count = models.IntegerField(null=True, verbose_name=_('CPU count'))
|
||||||
cpu_cores = models.IntegerField(null=True, verbose_name=_('CPU cores'))
|
cpu_cores = models.IntegerField(null=True, verbose_name=_('CPU cores'))
|
||||||
|
cpu_vcpus = models.IntegerField(null=True, verbose_name=_('CPU vcpus'))
|
||||||
memory = models.CharField(max_length=64, null=True, blank=True,
|
memory = models.CharField(max_length=64, null=True, blank=True,
|
||||||
verbose_name=_('Memory'))
|
verbose_name=_('Memory'))
|
||||||
disk_total = models.CharField(max_length=1024, null=True, blank=True,
|
disk_total = models.CharField(max_length=1024, null=True, blank=True,
|
||||||
|
@ -161,17 +164,25 @@ class Asset(OrgModelMixin):
|
||||||
nodes = list(reduce(lambda x, y: set(x) | set(y), nodes))
|
nodes = list(reduce(lambda x, y: set(x) | set(y), nodes))
|
||||||
return nodes
|
return nodes
|
||||||
|
|
||||||
@property
|
@classmethod
|
||||||
def org_name(self):
|
def get_queryset_by_fullname_list(cls, fullname_list):
|
||||||
from orgs.models import Organization
|
org_fullname_map = defaultdict(list)
|
||||||
org = Organization.get_instance(self.org_id)
|
for fullname in fullname_list:
|
||||||
return org.name
|
hostname, org = cls.split_fullname(fullname)
|
||||||
|
org_fullname_map[org].append(hostname)
|
||||||
|
filter_arg = Q()
|
||||||
|
for org, hosts in org_fullname_map.items():
|
||||||
|
if org.is_real():
|
||||||
|
filter_arg |= Q(hostname__in=hosts, org_id=org.id)
|
||||||
|
else:
|
||||||
|
filter_arg |= Q(Q(org_id__isnull=True) | Q(org_id=''), hostname__in=hosts)
|
||||||
|
return Asset.objects.filter(filter_arg)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def hardware_info(self):
|
def hardware_info(self):
|
||||||
if self.cpu_count:
|
if self.cpu_count:
|
||||||
return '{} Core {} {}'.format(
|
return '{} Core {} {}'.format(
|
||||||
self.cpu_count * self.cpu_cores,
|
self.cpu_vcpus or self.cpu_count * self.cpu_cores,
|
||||||
self.memory, self.disk_total
|
self.memory, self.disk_total
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -35,4 +35,4 @@ class Label(OrgModelMixin):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
db_table = "assets_label"
|
db_table = "assets_label"
|
||||||
unique_together = [('name', 'value')]
|
unique_together = [('name', 'value', 'org_id')]
|
||||||
|
|
|
@ -44,7 +44,7 @@ def set_assets_hardware_info(result, **kwargs):
|
||||||
logger.error("Get asset info failed: {}".format(hostname))
|
logger.error("Get asset info failed: {}".format(hostname))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
asset = get_object_or_none(Asset, hostname=hostname)
|
asset = Asset.objects.get_object_by_fullname(hostname)
|
||||||
if not asset:
|
if not asset:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
@ -60,6 +60,7 @@ def set_assets_hardware_info(result, **kwargs):
|
||||||
___cpu_model = ___cpu_model[:64]
|
___cpu_model = ___cpu_model[:64]
|
||||||
___cpu_count = info.get('ansible_processor_count', 0)
|
___cpu_count = info.get('ansible_processor_count', 0)
|
||||||
___cpu_cores = info.get('ansible_processor_cores', None) or len(info.get('ansible_processor', []))
|
___cpu_cores = info.get('ansible_processor_cores', None) or len(info.get('ansible_processor', []))
|
||||||
|
___cpu_vcpus = info.get('ansible_processor_vcpus', 0)
|
||||||
___memory = '%s %s' % capacity_convert('{} MB'.format(info.get('ansible_memtotal_mb')))
|
___memory = '%s %s' % capacity_convert('{} MB'.format(info.get('ansible_memtotal_mb')))
|
||||||
disk_info = {}
|
disk_info = {}
|
||||||
for dev, dev_info in info.get('ansible_devices', {}).items():
|
for dev, dev_info in info.get('ansible_devices', {}).items():
|
||||||
|
@ -95,7 +96,7 @@ def update_assets_hardware_info_util(assets, task_name=None):
|
||||||
# task_name = _("Update some assets hardware info")
|
# task_name = _("Update some assets hardware info")
|
||||||
task_name = _("更新资产硬件信息")
|
task_name = _("更新资产硬件信息")
|
||||||
tasks = const.UPDATE_ASSETS_HARDWARE_TASKS
|
tasks = const.UPDATE_ASSETS_HARDWARE_TASKS
|
||||||
hostname_list = [asset.hostname for asset in assets if asset.is_active and asset.is_unixlike()]
|
hostname_list = [asset.fullname for asset in assets if asset.is_active and asset.is_unixlike()]
|
||||||
if not hostname_list:
|
if not hostname_list:
|
||||||
logger.info("Not hosts get, may be asset is not active or not unixlike platform")
|
logger.info("Not hosts get, may be asset is not active or not unixlike platform")
|
||||||
return {}
|
return {}
|
||||||
|
@ -134,7 +135,7 @@ def update_assets_hardware_info_period():
|
||||||
# task_name = _("Update assets hardware info period")
|
# task_name = _("Update assets hardware info period")
|
||||||
task_name = _("定期更新资产硬件信息")
|
task_name = _("定期更新资产硬件信息")
|
||||||
hostname_list = [
|
hostname_list = [
|
||||||
asset.hostname for asset in Asset.objects.all()
|
asset.fullname for asset in Asset.objects.all()
|
||||||
if asset.is_active and asset.is_unixlike()
|
if asset.is_active and asset.is_unixlike()
|
||||||
]
|
]
|
||||||
tasks = const.UPDATE_ASSETS_HARDWARE_TASKS
|
tasks = const.UPDATE_ASSETS_HARDWARE_TASKS
|
||||||
|
@ -181,7 +182,7 @@ def test_admin_user_connectability_util(admin_user, task_name):
|
||||||
from ops.utils import update_or_create_ansible_task
|
from ops.utils import update_or_create_ansible_task
|
||||||
|
|
||||||
assets = admin_user.get_related_assets()
|
assets = admin_user.get_related_assets()
|
||||||
hosts = [asset.hostname for asset in assets
|
hosts = [asset.fullname for asset in assets
|
||||||
if asset.is_active and asset.is_unixlike()]
|
if asset.is_active and asset.is_unixlike()]
|
||||||
if not hosts:
|
if not hosts:
|
||||||
return
|
return
|
||||||
|
@ -228,7 +229,7 @@ def test_asset_connectability_util(assets, task_name=None):
|
||||||
if task_name is None:
|
if task_name is None:
|
||||||
# task_name = _("Test assets connectability")
|
# task_name = _("Test assets connectability")
|
||||||
task_name = _("测试资产可连接性")
|
task_name = _("测试资产可连接性")
|
||||||
hosts = [asset.hostname for asset in assets if asset.is_active and asset.is_unixlike()]
|
hosts = [asset.fullname for asset in assets if asset.is_active and asset.is_unixlike()]
|
||||||
if not hosts:
|
if not hosts:
|
||||||
logger.info("No hosts, passed")
|
logger.info("No hosts, passed")
|
||||||
return {}
|
return {}
|
||||||
|
@ -280,7 +281,7 @@ def test_system_user_connectability_util(system_user, task_name):
|
||||||
"""
|
"""
|
||||||
from ops.utils import update_or_create_ansible_task
|
from ops.utils import update_or_create_ansible_task
|
||||||
assets = system_user.get_assets()
|
assets = system_user.get_assets()
|
||||||
hosts = [asset.hostname for asset in assets if asset.is_active and asset.is_unixlike()]
|
hosts = [asset.fullname for asset in assets if asset.is_active and asset.is_unixlike()]
|
||||||
tasks = const.TEST_SYSTEM_USER_CONN_TASKS
|
tasks = const.TEST_SYSTEM_USER_CONN_TASKS
|
||||||
if not hosts:
|
if not hosts:
|
||||||
logger.info("No hosts, passed")
|
logger.info("No hosts, passed")
|
||||||
|
@ -378,7 +379,7 @@ def push_system_user_util(system_users, assets, task_name):
|
||||||
logger.info("Not tasks, passed")
|
logger.info("Not tasks, passed")
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
hosts = [asset.hostname for asset in assets if asset.is_active and asset.is_unixlike()]
|
hosts = [asset.fullname for asset in assets if asset.is_active and asset.is_unixlike()]
|
||||||
if not hosts:
|
if not hosts:
|
||||||
logger.info("Not hosts, passed")
|
logger.info("Not hosts, passed")
|
||||||
return {}
|
return {}
|
||||||
|
|
|
@ -451,10 +451,11 @@ $(document).ready(function(){
|
||||||
$.each(rows, function (index, obj) {
|
$.each(rows, function (index, obj) {
|
||||||
assets.push(obj.id)
|
assets.push(obj.id)
|
||||||
});
|
});
|
||||||
|
var _node_id = current_node ? current_node : null;
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: "{% url "assets:asset-export" %}",
|
url: "{% url "assets:asset-export" %}",
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
data: JSON.stringify({assets_id: assets, node_id: current_node.node_id}),
|
data: JSON.stringify({assets_id: assets, node_id: _node_id}),
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
success: function (data, textStatus) {
|
success: function (data, textStatus) {
|
||||||
window.open(data.redirect)
|
window.open(data.redirect)
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
{% block form %}
|
{% block form %}
|
||||||
<form action="" method="post" class="form-horizontal">
|
<form action="" method="post" class="form-horizontal">
|
||||||
{% if form.no_field_errors %}
|
{% if form.non_field_errors %}
|
||||||
<div class="alert alert-danger">
|
<div class="alert alert-danger">
|
||||||
{{ form.non_field_errors }}
|
{{ form.non_field_errors }}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -12,8 +12,8 @@ def get_assets_by_id_list(id_list):
|
||||||
return Asset.objects.filter(id__in=id_list)
|
return Asset.objects.filter(id__in=id_list)
|
||||||
|
|
||||||
|
|
||||||
def get_assets_by_hostname_list(hostname_list):
|
def get_assets_by_fullname_list(hostname_list):
|
||||||
return Asset.objects.filter(hostname__in=hostname_list)
|
return Asset.objects.get_queryset_by_fullname_list(hostname_list)
|
||||||
|
|
||||||
|
|
||||||
def get_system_user_by_name(name):
|
def get_system_user_by_name(name):
|
||||||
|
|
|
@ -214,13 +214,13 @@ class AssetExportView(LoginRequiredMixin, View):
|
||||||
def post(self, request, *args, **kwargs):
|
def post(self, request, *args, **kwargs):
|
||||||
try:
|
try:
|
||||||
assets_id = json.loads(request.body).get('assets_id', [])
|
assets_id = json.loads(request.body).get('assets_id', [])
|
||||||
assets_node_id = json.loads(request.body).get('node_id', None)
|
node_id = json.loads(request.body).get('node_id', None)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return HttpResponse('Json object not valid', status=400)
|
return HttpResponse('Json object not valid', status=400)
|
||||||
|
|
||||||
if not assets_id and assets_node_id:
|
if not assets_id:
|
||||||
assets_node = get_object_or_none(Node, id=assets_node_id)
|
node = get_object_or_none(Node, id=node_id) if node_id else Node.root()
|
||||||
assets = assets_node.get_all_assets()
|
assets = node.get_all_assets()
|
||||||
for asset in assets:
|
for asset in assets:
|
||||||
assets_id.append(asset.id)
|
assets_id.append(asset.id)
|
||||||
|
|
||||||
|
|
Binary file not shown.
|
@ -8,7 +8,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Jumpserver 0.3.3\n"
|
"Project-Id-Version: Jumpserver 0.3.3\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2018-08-13 15:01+0800\n"
|
"POT-Creation-Date: 2018-08-15 15:14+0800\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: ibuler <ibuler@qq.com>\n"
|
"Last-Translator: ibuler <ibuler@qq.com>\n"
|
||||||
"Language-Team: Jumpserver team<ibuler@qq.com>\n"
|
"Language-Team: Jumpserver team<ibuler@qq.com>\n"
|
||||||
|
@ -103,7 +103,7 @@ msgid "Port"
|
||||||
msgstr "端口"
|
msgstr "端口"
|
||||||
|
|
||||||
#: assets/forms/domain.py:15 assets/forms/label.py:13
|
#: assets/forms/domain.py:15 assets/forms/label.py:13
|
||||||
#: assets/models/asset.py:231 assets/templates/assets/admin_user_list.html:25
|
#: assets/models/asset.py:232 assets/templates/assets/admin_user_list.html:25
|
||||||
#: assets/templates/assets/domain_detail.html:60
|
#: assets/templates/assets/domain_detail.html:60
|
||||||
#: assets/templates/assets/domain_list.html:23
|
#: assets/templates/assets/domain_list.html:23
|
||||||
#: assets/templates/assets/label_list.html:16
|
#: assets/templates/assets/label_list.html:16
|
||||||
|
@ -123,7 +123,11 @@ msgstr "端口"
|
||||||
msgid "Asset"
|
msgid "Asset"
|
||||||
msgstr "资产"
|
msgstr "资产"
|
||||||
|
|
||||||
#: assets/forms/domain.py:55 assets/forms/user.py:79 assets/forms/user.py:139
|
#: assets/forms/domain.py:42
|
||||||
|
msgid "Password should not contain special characters"
|
||||||
|
msgstr "密码不能包含特殊字符"
|
||||||
|
|
||||||
|
#: assets/forms/domain.py:59 assets/forms/user.py:79 assets/forms/user.py:139
|
||||||
#: assets/models/base.py:22 assets/models/cluster.py:18
|
#: assets/models/base.py:22 assets/models/cluster.py:18
|
||||||
#: assets/models/domain.py:18 assets/models/group.py:20
|
#: assets/models/domain.py:18 assets/models/group.py:20
|
||||||
#: assets/models/label.py:18 assets/templates/assets/admin_user_detail.html:56
|
#: assets/models/label.py:18 assets/templates/assets/admin_user_detail.html:56
|
||||||
|
@ -156,7 +160,7 @@ msgstr "资产"
|
||||||
msgid "Name"
|
msgid "Name"
|
||||||
msgstr "名称"
|
msgstr "名称"
|
||||||
|
|
||||||
#: assets/forms/domain.py:56 assets/forms/user.py:80 assets/forms/user.py:140
|
#: assets/forms/domain.py:60 assets/forms/user.py:80 assets/forms/user.py:140
|
||||||
#: assets/models/base.py:23 assets/templates/assets/admin_user_detail.html:60
|
#: assets/models/base.py:23 assets/templates/assets/admin_user_detail.html:60
|
||||||
#: assets/templates/assets/admin_user_list.html:24
|
#: assets/templates/assets/admin_user_list.html:24
|
||||||
#: assets/templates/assets/domain_gateway_list.html:60
|
#: assets/templates/assets/domain_gateway_list.html:60
|
||||||
|
@ -303,42 +307,48 @@ msgstr "CPU数量"
|
||||||
msgid "CPU cores"
|
msgid "CPU cores"
|
||||||
msgstr "CPU核数"
|
msgstr "CPU核数"
|
||||||
|
|
||||||
#: assets/models/asset.py:104 assets/templates/assets/asset_detail.html:89
|
#: assets/models/asset.py:103
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid "CPU count"
|
||||||
|
msgid "CPU vcpus"
|
||||||
|
msgstr "CPU数量"
|
||||||
|
|
||||||
|
#: assets/models/asset.py:105 assets/templates/assets/asset_detail.html:89
|
||||||
msgid "Memory"
|
msgid "Memory"
|
||||||
msgstr "内存"
|
msgstr "内存"
|
||||||
|
|
||||||
#: assets/models/asset.py:106
|
#: assets/models/asset.py:107
|
||||||
msgid "Disk total"
|
msgid "Disk total"
|
||||||
msgstr "硬盘大小"
|
msgstr "硬盘大小"
|
||||||
|
|
||||||
#: assets/models/asset.py:108
|
#: assets/models/asset.py:109
|
||||||
msgid "Disk info"
|
msgid "Disk info"
|
||||||
msgstr "硬盘信息"
|
msgstr "硬盘信息"
|
||||||
|
|
||||||
#: assets/models/asset.py:111 assets/templates/assets/asset_detail.html:101
|
#: assets/models/asset.py:112 assets/templates/assets/asset_detail.html:101
|
||||||
#: assets/templates/assets/user_asset_list.html:166
|
#: assets/templates/assets/user_asset_list.html:166
|
||||||
msgid "OS"
|
msgid "OS"
|
||||||
msgstr "操作系统"
|
msgstr "操作系统"
|
||||||
|
|
||||||
#: assets/models/asset.py:113
|
#: assets/models/asset.py:114
|
||||||
msgid "OS version"
|
msgid "OS version"
|
||||||
msgstr "系统版本"
|
msgstr "系统版本"
|
||||||
|
|
||||||
#: assets/models/asset.py:115
|
#: assets/models/asset.py:116
|
||||||
msgid "OS arch"
|
msgid "OS arch"
|
||||||
msgstr "系统架构"
|
msgstr "系统架构"
|
||||||
|
|
||||||
#: assets/models/asset.py:117
|
#: assets/models/asset.py:118
|
||||||
msgid "Hostname raw"
|
msgid "Hostname raw"
|
||||||
msgstr "主机名原始"
|
msgstr "主机名原始"
|
||||||
|
|
||||||
#: assets/models/asset.py:121 assets/templates/assets/asset_create.html:34
|
#: assets/models/asset.py:122 assets/templates/assets/asset_create.html:34
|
||||||
#: assets/templates/assets/asset_detail.html:220
|
#: assets/templates/assets/asset_detail.html:220
|
||||||
#: assets/templates/assets/asset_update.html:39 templates/_nav.html:27
|
#: assets/templates/assets/asset_update.html:39 templates/_nav.html:27
|
||||||
msgid "Labels"
|
msgid "Labels"
|
||||||
msgstr "标签管理"
|
msgstr "标签管理"
|
||||||
|
|
||||||
#: assets/models/asset.py:123 assets/models/base.py:30
|
#: assets/models/asset.py:124 assets/models/base.py:30
|
||||||
#: assets/models/cluster.py:28 assets/models/group.py:21
|
#: assets/models/cluster.py:28 assets/models/group.py:21
|
||||||
#: assets/templates/assets/admin_user_detail.html:68
|
#: assets/templates/assets/admin_user_detail.html:68
|
||||||
#: assets/templates/assets/asset_detail.html:117
|
#: assets/templates/assets/asset_detail.html:117
|
||||||
|
@ -350,7 +360,7 @@ msgstr "标签管理"
|
||||||
msgid "Created by"
|
msgid "Created by"
|
||||||
msgstr "创建者"
|
msgstr "创建者"
|
||||||
|
|
||||||
#: assets/models/asset.py:126 assets/models/cluster.py:26
|
#: assets/models/asset.py:127 assets/models/cluster.py:26
|
||||||
#: assets/models/domain.py:21 assets/models/group.py:22
|
#: assets/models/domain.py:21 assets/models/group.py:22
|
||||||
#: assets/models/label.py:24 assets/templates/assets/admin_user_detail.html:64
|
#: assets/models/label.py:24 assets/templates/assets/admin_user_detail.html:64
|
||||||
#: assets/templates/assets/domain_detail.html:68
|
#: assets/templates/assets/domain_detail.html:68
|
||||||
|
@ -364,7 +374,7 @@ msgstr "创建者"
|
||||||
msgid "Date created"
|
msgid "Date created"
|
||||||
msgstr "创建日期"
|
msgstr "创建日期"
|
||||||
|
|
||||||
#: assets/models/asset.py:128 assets/models/base.py:27
|
#: assets/models/asset.py:129 assets/models/base.py:27
|
||||||
#: assets/models/cluster.py:29 assets/models/domain.py:19
|
#: assets/models/cluster.py:29 assets/models/domain.py:19
|
||||||
#: assets/models/domain.py:48 assets/models/group.py:23
|
#: assets/models/domain.py:48 assets/models/group.py:23
|
||||||
#: assets/models/label.py:22 assets/templates/assets/admin_user_detail.html:72
|
#: assets/models/label.py:22 assets/templates/assets/admin_user_detail.html:72
|
||||||
|
@ -474,7 +484,7 @@ msgstr "默认资产组"
|
||||||
msgid "User"
|
msgid "User"
|
||||||
msgstr "用户"
|
msgstr "用户"
|
||||||
|
|
||||||
#: assets/models/label.py:19 assets/models/node.py:19
|
#: assets/models/label.py:19 assets/models/node.py:20
|
||||||
#: assets/templates/assets/label_list.html:15 common/models.py:27
|
#: assets/templates/assets/label_list.html:15 common/models.py:27
|
||||||
msgid "Value"
|
msgid "Value"
|
||||||
msgstr "值"
|
msgstr "值"
|
||||||
|
@ -483,7 +493,7 @@ msgstr "值"
|
||||||
msgid "Category"
|
msgid "Category"
|
||||||
msgstr "分类"
|
msgstr "分类"
|
||||||
|
|
||||||
#: assets/models/node.py:18
|
#: assets/models/node.py:19
|
||||||
msgid "Key"
|
msgid "Key"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -557,35 +567,35 @@ msgstr "系统用户"
|
||||||
msgid "%(value)s is not an even number"
|
msgid "%(value)s is not an even number"
|
||||||
msgstr "%(value)s is not an even number"
|
msgstr "%(value)s is not an even number"
|
||||||
|
|
||||||
#: assets/tasks.py:96 assets/tasks.py:116
|
#: assets/tasks.py:97 assets/tasks.py:117
|
||||||
msgid "更新资产硬件信息"
|
msgid "更新资产硬件信息"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/tasks.py:135
|
#: assets/tasks.py:136
|
||||||
msgid "定期更新资产硬件信息"
|
msgid "定期更新资产硬件信息"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/tasks.py:213
|
#: assets/tasks.py:214
|
||||||
msgid "定期测试管理账号可连接性: {}"
|
msgid "定期测试管理账号可连接性: {}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/tasks.py:220
|
#: assets/tasks.py:221
|
||||||
msgid "测试管理行号可连接性: {}"
|
msgid "测试管理行号可连接性: {}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/tasks.py:230
|
#: assets/tasks.py:231
|
||||||
msgid "测试资产可连接性"
|
msgid "测试资产可连接性"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/tasks.py:300
|
#: assets/tasks.py:301
|
||||||
msgid "Test system user connectability: {}"
|
msgid "Test system user connectability: {}"
|
||||||
msgstr "测试系统用户可连接性: {}"
|
msgstr "测试系统用户可连接性: {}"
|
||||||
|
|
||||||
#: assets/tasks.py:316
|
#: assets/tasks.py:317
|
||||||
msgid "定期测试系统用户可连接性: {}"
|
msgid "定期测试系统用户可连接性: {}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/tasks.py:401
|
#: assets/tasks.py:402
|
||||||
msgid "推送系统用户到入资产: {}"
|
msgid "推送系统用户到入资产: {}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -850,7 +860,7 @@ msgstr "选择节点"
|
||||||
|
|
||||||
#: assets/templates/assets/admin_user_detail.html:100
|
#: assets/templates/assets/admin_user_detail.html:100
|
||||||
#: assets/templates/assets/asset_detail.html:200
|
#: assets/templates/assets/asset_detail.html:200
|
||||||
#: assets/templates/assets/asset_list.html:630
|
#: assets/templates/assets/asset_list.html:631
|
||||||
#: assets/templates/assets/system_user_detail.html:195
|
#: assets/templates/assets/system_user_detail.html:195
|
||||||
#: assets/templates/assets/system_user_list.html:139 templates/_modal.html:22
|
#: assets/templates/assets/system_user_list.html:139 templates/_modal.html:22
|
||||||
#: terminal/templates/terminal/session_detail.html:108
|
#: terminal/templates/terminal/session_detail.html:108
|
||||||
|
@ -1052,7 +1062,7 @@ msgstr "重命名成功"
|
||||||
msgid "Rename failed, do not change the root node name"
|
msgid "Rename failed, do not change the root node name"
|
||||||
msgstr "重命名失败,不可以更改根节点名称"
|
msgstr "重命名失败,不可以更改根节点名称"
|
||||||
|
|
||||||
#: assets/templates/assets/asset_list.html:625
|
#: assets/templates/assets/asset_list.html:626
|
||||||
#: assets/templates/assets/system_user_list.html:134
|
#: assets/templates/assets/system_user_list.html:134
|
||||||
#: users/templates/users/user_detail.html:369
|
#: users/templates/users/user_detail.html:369
|
||||||
#: users/templates/users/user_detail.html:394
|
#: users/templates/users/user_detail.html:394
|
||||||
|
@ -1063,20 +1073,20 @@ msgstr "重命名失败,不可以更改根节点名称"
|
||||||
msgid "Are you sure?"
|
msgid "Are you sure?"
|
||||||
msgstr "你确认吗?"
|
msgstr "你确认吗?"
|
||||||
|
|
||||||
#: assets/templates/assets/asset_list.html:626
|
#: assets/templates/assets/asset_list.html:627
|
||||||
msgid "This will delete the selected assets !!!"
|
msgid "This will delete the selected assets !!!"
|
||||||
msgstr "删除选择资产"
|
msgstr "删除选择资产"
|
||||||
|
|
||||||
#: assets/templates/assets/asset_list.html:634
|
#: assets/templates/assets/asset_list.html:635
|
||||||
msgid "Asset Deleted."
|
msgid "Asset Deleted."
|
||||||
msgstr "已被删除"
|
msgstr "已被删除"
|
||||||
|
|
||||||
#: assets/templates/assets/asset_list.html:635
|
#: assets/templates/assets/asset_list.html:636
|
||||||
#: assets/templates/assets/asset_list.html:640
|
#: assets/templates/assets/asset_list.html:641
|
||||||
msgid "Asset Delete"
|
msgid "Asset Delete"
|
||||||
msgstr "删除"
|
msgstr "删除"
|
||||||
|
|
||||||
#: assets/templates/assets/asset_list.html:639
|
#: assets/templates/assets/asset_list.html:640
|
||||||
msgid "Asset Deleting failed."
|
msgid "Asset Deleting failed."
|
||||||
msgstr "删除失败"
|
msgstr "删除失败"
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
from .ansible.inventory import BaseInventory
|
from .ansible.inventory import BaseInventory
|
||||||
from assets.utils import get_assets_by_hostname_list, get_system_user_by_name
|
from assets.utils import get_assets_by_fullname_list, get_system_user_by_name
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'JMSInventory'
|
'JMSInventory'
|
||||||
|
@ -44,7 +44,7 @@ class JMSInventory(BaseInventory):
|
||||||
super().__init__(host_list=host_list)
|
super().__init__(host_list=host_list)
|
||||||
|
|
||||||
def get_jms_assets(self):
|
def get_jms_assets(self):
|
||||||
assets = get_assets_by_hostname_list(self.hostname_list)
|
assets = get_assets_by_fullname_list(self.hostname_list)
|
||||||
return assets
|
return assets
|
||||||
|
|
||||||
def convert_to_ansible(self, asset, run_as_admin=False):
|
def convert_to_ansible(self, asset, run_as_admin=False):
|
||||||
|
|
|
@ -8,7 +8,7 @@ from django.shortcuts import redirect
|
||||||
from django.forms import ModelForm
|
from django.forms import ModelForm
|
||||||
from django.http.response import HttpResponseForbidden
|
from django.http.response import HttpResponseForbidden
|
||||||
|
|
||||||
from common.utils import get_logger
|
from common.utils import get_logger, is_uuid
|
||||||
from .utils import current_org, set_current_org, set_to_root_org
|
from .utils import current_org, set_current_org, set_to_root_org
|
||||||
from .models import Organization
|
from .models import Organization
|
||||||
|
|
||||||
|
@ -39,6 +39,25 @@ class OrgManager(models.Manager):
|
||||||
tl.times += 1
|
tl.times += 1
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
|
def filter_by_fullname(self, fullname, field=None):
|
||||||
|
ori_org = current_org
|
||||||
|
value, org = self.model.split_fullname(fullname)
|
||||||
|
set_current_org(org)
|
||||||
|
if not field:
|
||||||
|
if hasattr(self.model, 'name'):
|
||||||
|
field = 'name'
|
||||||
|
elif hasattr(self.model, 'hostname'):
|
||||||
|
field = 'hostname'
|
||||||
|
queryset = self.get_queryset().filter(**{field: value})
|
||||||
|
set_current_org(ori_org)
|
||||||
|
return queryset
|
||||||
|
|
||||||
|
def get_object_by_fullname(self, fullname, field=None):
|
||||||
|
queryset = self.filter_by_fullname(fullname, field=field)
|
||||||
|
if len(queryset) == 1:
|
||||||
|
return queryset[0]
|
||||||
|
return None
|
||||||
|
|
||||||
def all(self):
|
def all(self):
|
||||||
if not current_org:
|
if not current_org:
|
||||||
msg = 'You can `objects.set_current_org(org).all()` then run it'
|
msg = 'You can `objects.set_current_org(org).all()` then run it'
|
||||||
|
@ -57,11 +76,50 @@ class OrgModelMixin(models.Model):
|
||||||
org_id = models.CharField(max_length=36, null=True, blank=True, default=None)
|
org_id = models.CharField(max_length=36, null=True, blank=True, default=None)
|
||||||
objects = OrgManager()
|
objects = OrgManager()
|
||||||
|
|
||||||
|
sep = '@'
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
if current_org and current_org.is_real():
|
if current_org and current_org.is_real():
|
||||||
self.org_id = current_org.id
|
self.org_id = current_org.id
|
||||||
return super().save(*args, **kwargs)
|
return super().save(*args, **kwargs)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def split_fullname(cls, fullname, sep=None):
|
||||||
|
if not sep:
|
||||||
|
sep = cls.sep
|
||||||
|
index = fullname.rfind(sep)
|
||||||
|
if index == -1:
|
||||||
|
value = fullname
|
||||||
|
org = Organization.default()
|
||||||
|
else:
|
||||||
|
value = fullname[:index]
|
||||||
|
org = Organization.get_instance(fullname[index + 1:])
|
||||||
|
return value, org
|
||||||
|
|
||||||
|
@property
|
||||||
|
def org(self):
|
||||||
|
from orgs.models import Organization
|
||||||
|
org = Organization.get_instance(self.org_id)
|
||||||
|
return org
|
||||||
|
|
||||||
|
@property
|
||||||
|
def org_name(self):
|
||||||
|
return self.org.name
|
||||||
|
|
||||||
|
@property
|
||||||
|
def fullname(self, attr=None):
|
||||||
|
name = ''
|
||||||
|
if attr and hasattr(self, attr):
|
||||||
|
name = getattr(self, attr)
|
||||||
|
elif hasattr(self, 'name'):
|
||||||
|
name = self.name
|
||||||
|
elif hasattr(self, 'hostname'):
|
||||||
|
name = self.hostname
|
||||||
|
if self.org.is_real():
|
||||||
|
return name + self.sep + self.org_name
|
||||||
|
else:
|
||||||
|
return name
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
abstract = True
|
abstract = True
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,8 @@ from django.db import models
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
from common.utils import is_uuid
|
||||||
|
|
||||||
|
|
||||||
class Organization(models.Model):
|
class Organization(models.Model):
|
||||||
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
|
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
|
||||||
|
@ -15,19 +17,23 @@ class Organization(models.Model):
|
||||||
comment = models.TextField(max_length=128, default='', blank=True, verbose_name=_('Comment'))
|
comment = models.TextField(max_length=128, default='', blank=True, verbose_name=_('Comment'))
|
||||||
|
|
||||||
CACHE_PREFIX = 'JMS_ORG_{}'
|
CACHE_PREFIX = 'JMS_ORG_{}'
|
||||||
ROOT_ID = 'ROOT'
|
ROOT_ID_NAME = 'ROOT'
|
||||||
DEFAULT_ID = 'DEFAULT'
|
DEFAULT_ID_NAME = 'DEFAULT'
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
def set_to_cache(self):
|
def set_to_cache(self):
|
||||||
key = self.CACHE_PREFIX.format(self.id)
|
key_id = self.CACHE_PREFIX.format(self.id)
|
||||||
cache.set(key, self, 3600)
|
key_name = self.CACHE_PREFIX.format(self.name)
|
||||||
|
cache.set(key_id, self, 3600)
|
||||||
|
cache.set(key_name, self, 3600)
|
||||||
|
|
||||||
def expire_cache(self):
|
def expire_cache(self):
|
||||||
key = self.CACHE_PREFIX.format(self.id)
|
key_id = self.CACHE_PREFIX.format(self.id)
|
||||||
cache.set(key, self, 1)
|
key_name = self.CACHE_PREFIX.format(self.name)
|
||||||
|
cache.delete(key_id)
|
||||||
|
cache.delete(key_name)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_instance_from_cache(cls, oid):
|
def get_instance_from_cache(cls, oid):
|
||||||
|
@ -35,18 +41,23 @@ class Organization(models.Model):
|
||||||
return cache.get(key, None)
|
return cache.get(key, None)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_instance(cls, oid, default=True):
|
def get_instance(cls, id_or_name, default=True):
|
||||||
cached = cls.get_instance_from_cache(oid)
|
cached = cls.get_instance_from_cache(id_or_name)
|
||||||
if cached:
|
if cached:
|
||||||
return cached
|
return cached
|
||||||
|
|
||||||
if oid == cls.DEFAULT_ID:
|
if not id_or_name:
|
||||||
|
return cls.default() if default else None
|
||||||
|
elif id_or_name == cls.DEFAULT_ID_NAME:
|
||||||
return cls.default()
|
return cls.default()
|
||||||
elif oid == cls.ROOT_ID:
|
elif id_or_name == cls.ROOT_ID_NAME:
|
||||||
return cls.root()
|
return cls.root()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
org = cls.objects.get(id=oid)
|
if is_uuid(id_or_name):
|
||||||
|
org = cls.objects.get(id=id_or_name)
|
||||||
|
else:
|
||||||
|
org = cls.objects.get(name=id_or_name)
|
||||||
org.set_to_cache()
|
org.set_to_cache()
|
||||||
except cls.DoesNotExist:
|
except cls.DoesNotExist:
|
||||||
org = cls.default() if default else None
|
org = cls.default() if default else None
|
||||||
|
@ -56,6 +67,8 @@ class Organization(models.Model):
|
||||||
from users.models import User
|
from users.models import User
|
||||||
if self.is_default():
|
if self.is_default():
|
||||||
users = User.objects.filter(orgs__isnull=True)
|
users = User.objects.filter(orgs__isnull=True)
|
||||||
|
elif not self.is_real():
|
||||||
|
users = User.objects.all()
|
||||||
else:
|
else:
|
||||||
users = self.users.all()
|
users = self.users.all()
|
||||||
users = users.exclude(role=User.ROLE_APP)
|
users = users.exclude(role=User.ROLE_APP)
|
||||||
|
@ -90,14 +103,20 @@ class Organization(models.Model):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def default(cls):
|
def default(cls):
|
||||||
return cls(id=cls.DEFAULT_ID, name="Default")
|
return cls(id=cls.DEFAULT_ID_NAME, name=cls.DEFAULT_ID_NAME)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def root(cls):
|
def root(cls):
|
||||||
return cls(id=cls.ROOT_ID, name='Root')
|
return cls(id=cls.ROOT_ID_NAME, name=cls.ROOT_ID_NAME)
|
||||||
|
|
||||||
def is_default(self):
|
def is_root(self):
|
||||||
if self.id is self.DEFAULT_ID:
|
if self.id is self.ROOT_ID_NAME:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def is_default(self):
|
||||||
|
if self.id is self.DEFAULT_ID_NAME:
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
Loading…
Reference in New Issue