From 3533bf588b0b0fcbed187e4f7e13edd046a7e5c2 Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 14 Aug 2018 18:08:07 +0800 Subject: [PATCH 1/5] =?UTF-8?q?[Bugfix]=20=E4=BF=AE=E5=A4=8D=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E8=B5=84=E4=BA=A7=E6=8A=A5=E9=94=99=E6=97=A0=E6=8F=90?= =?UTF-8?q?=E7=A4=BA=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/templates/assets/asset_update.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/assets/templates/assets/asset_update.html b/apps/assets/templates/assets/asset_update.html index 7ed1da05a..caff4286d 100644 --- a/apps/assets/templates/assets/asset_update.html +++ b/apps/assets/templates/assets/asset_update.html @@ -12,7 +12,7 @@ {% block form %}
- {% if form.no_field_errors %} + {% if form.non_field_errors %}
{{ form.non_field_errors }}
From 7ddf7f2a79d84cb5fb98bb1e94e3023961b49dc2 Mon Sep 17 00:00:00 2001 From: ibuler Date: Wed, 15 Aug 2018 12:00:47 +0800 Subject: [PATCH 2/5] =?UTF-8?q?[Update]=20=E4=BF=AE=E6=94=B9cpu=E7=9A=84?= =?UTF-8?q?=E6=95=B0=E9=87=8F=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/models/asset.py | 3 ++- apps/assets/tasks.py | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/assets/models/asset.py b/apps/assets/models/asset.py index 97bcd4b47..b1d728e37 100644 --- a/apps/assets/models/asset.py +++ b/apps/assets/models/asset.py @@ -100,6 +100,7 @@ class Asset(OrgModelMixin): verbose_name=_('CPU model')) cpu_count = models.IntegerField(null=True, verbose_name=_('CPU count')) 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, verbose_name=_('Memory')) disk_total = models.CharField(max_length=1024, null=True, blank=True, @@ -171,7 +172,7 @@ class Asset(OrgModelMixin): def hardware_info(self): if self.cpu_count: return '{} Core {} {}'.format( - self.cpu_count * self.cpu_cores, + self.cpu_vcpus or self.cpu_count * self.cpu_cores, self.memory, self.disk_total ) else: diff --git a/apps/assets/tasks.py b/apps/assets/tasks.py index f1773df11..54d6f7f8e 100644 --- a/apps/assets/tasks.py +++ b/apps/assets/tasks.py @@ -60,6 +60,7 @@ def set_assets_hardware_info(result, **kwargs): ___cpu_model = ___cpu_model[:64] ___cpu_count = info.get('ansible_processor_count', 0) ___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'))) disk_info = {} for dev, dev_info in info.get('ansible_devices', {}).items(): From 00928dd46d63a51c84dfef57bf4b21db57541724 Mon Sep 17 00:00:00 2001 From: ibuler Date: Wed, 15 Aug 2018 15:01:27 +0800 Subject: [PATCH 3/5] =?UTF-8?q?[Update]=20=E4=B8=8D=E9=80=89=E6=8B=A9?= =?UTF-8?q?=E8=8A=82=E7=82=B9=E9=BB=98=E8=AE=A4=E5=AF=BC=E5=87=BA=E6=89=80?= =?UTF-8?q?=E6=9C=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/templates/assets/asset_list.html | 3 ++- apps/assets/views/asset.py | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/apps/assets/templates/assets/asset_list.html b/apps/assets/templates/assets/asset_list.html index 3e1a8cfcd..79c34c043 100644 --- a/apps/assets/templates/assets/asset_list.html +++ b/apps/assets/templates/assets/asset_list.html @@ -451,10 +451,11 @@ $(document).ready(function(){ $.each(rows, function (index, obj) { assets.push(obj.id) }); + var _node_id = current_node ? current_node : null; $.ajax({ url: "{% url "assets:asset-export" %}", 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", success: function (data, textStatus) { window.open(data.redirect) diff --git a/apps/assets/views/asset.py b/apps/assets/views/asset.py index eb9972e94..c36ad9cc9 100644 --- a/apps/assets/views/asset.py +++ b/apps/assets/views/asset.py @@ -214,13 +214,13 @@ class AssetExportView(LoginRequiredMixin, View): def post(self, request, *args, **kwargs): try: 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: return HttpResponse('Json object not valid', status=400) - if not assets_id and assets_node_id: - assets_node = get_object_or_none(Node, id=assets_node_id) - assets = assets_node.get_all_assets() + if not assets_id: + node = get_object_or_none(Node, id=node_id) if node_id else Node.root() + assets = node.get_all_assets() for asset in assets: assets_id.append(asset.id) From 5b93a1a0a582cc3cd446aab958eedadee0d767bc Mon Sep 17 00:00:00 2001 From: ibuler Date: Wed, 15 Aug 2018 17:44:06 +0800 Subject: [PATCH 4/5] =?UTF-8?q?[Bugfix]=20=E4=BF=AE=E5=A4=8D=E5=8D=95?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/forms/domain.py | 4 ++ apps/i18n/zh/LC_MESSAGES/django.mo | Bin 37866 -> 37960 bytes apps/i18n/zh/LC_MESSAGES/django.po | 74 ++++++++++++++++------------- apps/orgs/models.py | 8 ++++ 4 files changed, 54 insertions(+), 32 deletions(-) diff --git a/apps/assets/forms/domain.py b/apps/assets/forms/domain.py index 1b005ec2f..66f490bad 100644 --- a/apps/assets/forms/domain.py +++ b/apps/assets/forms/domain.py @@ -36,6 +36,10 @@ class DomainForm(forms.ModelForm): 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): # Because we define custom field, so we need rewrite :method: `save` diff --git a/apps/i18n/zh/LC_MESSAGES/django.mo b/apps/i18n/zh/LC_MESSAGES/django.mo index 97879c6d07121799ee285171697bc8b519a47acb..a7bbb98a31e029a30757823dac27fec41ae0b835 100644 GIT binary patch delta 11953 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 delta 11914 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 diff --git a/apps/i18n/zh/LC_MESSAGES/django.po b/apps/i18n/zh/LC_MESSAGES/django.po index 1e4c69daa..335c491e0 100644 --- a/apps/i18n/zh/LC_MESSAGES/django.po +++ b/apps/i18n/zh/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Jumpserver 0.3.3\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" "Last-Translator: ibuler \n" "Language-Team: Jumpserver team\n" @@ -103,7 +103,7 @@ msgid "Port" msgstr "端口" #: 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_list.html:23 #: assets/templates/assets/label_list.html:16 @@ -123,7 +123,11 @@ msgstr "端口" msgid "Asset" 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/domain.py:18 assets/models/group.py:20 #: assets/models/label.py:18 assets/templates/assets/admin_user_detail.html:56 @@ -156,7 +160,7 @@ msgstr "资产" msgid "Name" 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/templates/assets/admin_user_list.html:24 #: assets/templates/assets/domain_gateway_list.html:60 @@ -303,42 +307,48 @@ msgstr "CPU数量" msgid "CPU cores" 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" msgstr "内存" -#: assets/models/asset.py:106 +#: assets/models/asset.py:107 msgid "Disk total" msgstr "硬盘大小" -#: assets/models/asset.py:108 +#: assets/models/asset.py:109 msgid "Disk info" 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 msgid "OS" msgstr "操作系统" -#: assets/models/asset.py:113 +#: assets/models/asset.py:114 msgid "OS version" msgstr "系统版本" -#: assets/models/asset.py:115 +#: assets/models/asset.py:116 msgid "OS arch" msgstr "系统架构" -#: assets/models/asset.py:117 +#: assets/models/asset.py:118 msgid "Hostname raw" 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_update.html:39 templates/_nav.html:27 msgid "Labels" 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/templates/assets/admin_user_detail.html:68 #: assets/templates/assets/asset_detail.html:117 @@ -350,7 +360,7 @@ msgstr "标签管理" msgid "Created by" 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/label.py:24 assets/templates/assets/admin_user_detail.html:64 #: assets/templates/assets/domain_detail.html:68 @@ -364,7 +374,7 @@ msgstr "创建者" msgid "Date created" 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/domain.py:48 assets/models/group.py:23 #: assets/models/label.py:22 assets/templates/assets/admin_user_detail.html:72 @@ -474,7 +484,7 @@ msgstr "默认资产组" msgid "User" 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 msgid "Value" msgstr "值" @@ -483,7 +493,7 @@ msgstr "值" msgid "Category" msgstr "分类" -#: assets/models/node.py:18 +#: assets/models/node.py:19 msgid "Key" msgstr "" @@ -557,35 +567,35 @@ msgstr "系统用户" msgid "%(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 "更新资产硬件信息" msgstr "" -#: assets/tasks.py:135 +#: assets/tasks.py:136 msgid "定期更新资产硬件信息" msgstr "" -#: assets/tasks.py:213 +#: assets/tasks.py:214 msgid "定期测试管理账号可连接性: {}" msgstr "" -#: assets/tasks.py:220 +#: assets/tasks.py:221 msgid "测试管理行号可连接性: {}" msgstr "" -#: assets/tasks.py:230 +#: assets/tasks.py:231 msgid "测试资产可连接性" msgstr "" -#: assets/tasks.py:300 +#: assets/tasks.py:301 msgid "Test system user connectability: {}" msgstr "测试系统用户可连接性: {}" -#: assets/tasks.py:316 +#: assets/tasks.py:317 msgid "定期测试系统用户可连接性: {}" msgstr "" -#: assets/tasks.py:401 +#: assets/tasks.py:402 msgid "推送系统用户到入资产: {}" msgstr "" @@ -850,7 +860,7 @@ msgstr "选择节点" #: assets/templates/assets/admin_user_detail.html:100 #: 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_list.html:139 templates/_modal.html:22 #: terminal/templates/terminal/session_detail.html:108 @@ -1052,7 +1062,7 @@ msgstr "重命名成功" msgid "Rename failed, do not change the root node name" msgstr "重命名失败,不可以更改根节点名称" -#: assets/templates/assets/asset_list.html:625 +#: assets/templates/assets/asset_list.html:626 #: assets/templates/assets/system_user_list.html:134 #: users/templates/users/user_detail.html:369 #: users/templates/users/user_detail.html:394 @@ -1063,20 +1073,20 @@ msgstr "重命名失败,不可以更改根节点名称" msgid "Are you sure?" msgstr "你确认吗?" -#: assets/templates/assets/asset_list.html:626 +#: assets/templates/assets/asset_list.html:627 msgid "This will delete the selected assets !!!" msgstr "删除选择资产" -#: assets/templates/assets/asset_list.html:634 +#: assets/templates/assets/asset_list.html:635 msgid "Asset Deleted." msgstr "已被删除" -#: assets/templates/assets/asset_list.html:635 -#: assets/templates/assets/asset_list.html:640 +#: assets/templates/assets/asset_list.html:636 +#: assets/templates/assets/asset_list.html:641 msgid "Asset Delete" msgstr "删除" -#: assets/templates/assets/asset_list.html:639 +#: assets/templates/assets/asset_list.html:640 msgid "Asset Deleting failed." msgstr "删除失败" diff --git a/apps/orgs/models.py b/apps/orgs/models.py index f9e866741..ed44b8b7e 100644 --- a/apps/orgs/models.py +++ b/apps/orgs/models.py @@ -56,6 +56,8 @@ class Organization(models.Model): from users.models import User if self.is_default(): users = User.objects.filter(orgs__isnull=True) + elif not self.is_real(): + users = User.objects.all() else: users = self.users.all() users = users.exclude(role=User.ROLE_APP) @@ -96,6 +98,12 @@ class Organization(models.Model): def root(cls): return cls(id=cls.ROOT_ID, name='Root') + def is_root(self): + if self.id is self.ROOT_ID: + return True + else: + return False + def is_default(self): if self.id is self.DEFAULT_ID: return True From 2ac5786ba10535a3cacd444b592491b8221b6992 Mon Sep 17 00:00:00 2001 From: ibuler Date: Thu, 16 Aug 2018 12:44:39 +0800 Subject: [PATCH 5/5] =?UTF-8?q?[Bugfix]=20=E4=BF=AE=E5=A4=8DHostname?= =?UTF-8?q?=E5=8F=AF=E8=83=BD=E4=B8=8D=E5=94=AF=E4=B8=80=E5=BC=95=E8=B5=B7?= =?UTF-8?q?=E7=9A=84=E4=BB=BB=E5=8A=A1=E6=89=A7=E8=A1=8C=E5=A4=B1=E8=B4=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/api/asset.py | 2 +- apps/assets/models/asset.py | 20 +++++++++---- apps/assets/models/label.py | 2 +- apps/assets/tasks.py | 14 ++++----- apps/assets/utils.py | 4 +-- apps/ops/inventory.py | 4 +-- apps/orgs/mixins.py | 60 ++++++++++++++++++++++++++++++++++++- apps/orgs/models.py | 41 +++++++++++++++---------- 8 files changed, 113 insertions(+), 34 deletions(-) diff --git a/apps/assets/api/asset.py b/apps/assets/api/asset.py index e2ce1b62a..a4701add9 100644 --- a/apps/assets/api/asset.py +++ b/apps/assets/api/asset.py @@ -48,7 +48,7 @@ class AssetViewSet(IDInFilterMixin, LabelFilter, BulkModelViewSet): return 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 show_current_asset: diff --git a/apps/assets/models/asset.py b/apps/assets/models/asset.py index b1d728e37..b554c5c3a 100644 --- a/apps/assets/models/asset.py +++ b/apps/assets/models/asset.py @@ -6,8 +6,10 @@ import uuid import logging import random from functools import reduce +from collections import defaultdict from django.db import models +from django.db.models import Q from django.utils.translation import ugettext_lazy as _ from django.core.cache import cache @@ -162,11 +164,19 @@ class Asset(OrgModelMixin): nodes = list(reduce(lambda x, y: set(x) | set(y), nodes)) return nodes - @property - def org_name(self): - from orgs.models import Organization - org = Organization.get_instance(self.org_id) - return org.name + @classmethod + def get_queryset_by_fullname_list(cls, fullname_list): + org_fullname_map = defaultdict(list) + for fullname in fullname_list: + 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 def hardware_info(self): diff --git a/apps/assets/models/label.py b/apps/assets/models/label.py index 7f1d08fa1..abc71e694 100644 --- a/apps/assets/models/label.py +++ b/apps/assets/models/label.py @@ -35,4 +35,4 @@ class Label(OrgModelMixin): class Meta: db_table = "assets_label" - unique_together = [('name', 'value')] + unique_together = [('name', 'value', 'org_id')] diff --git a/apps/assets/tasks.py b/apps/assets/tasks.py index 54d6f7f8e..463c3006a 100644 --- a/apps/assets/tasks.py +++ b/apps/assets/tasks.py @@ -44,7 +44,7 @@ def set_assets_hardware_info(result, **kwargs): logger.error("Get asset info failed: {}".format(hostname)) continue - asset = get_object_or_none(Asset, hostname=hostname) + asset = Asset.objects.get_object_by_fullname(hostname) if not asset: continue @@ -96,7 +96,7 @@ def update_assets_hardware_info_util(assets, task_name=None): # task_name = _("Update some assets hardware info") task_name = _("更新资产硬件信息") 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: logger.info("Not hosts get, may be asset is not active or not unixlike platform") return {} @@ -135,7 +135,7 @@ def update_assets_hardware_info_period(): # task_name = _("Update assets hardware info period") task_name = _("定期更新资产硬件信息") 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() ] tasks = const.UPDATE_ASSETS_HARDWARE_TASKS @@ -182,7 +182,7 @@ def test_admin_user_connectability_util(admin_user, task_name): from ops.utils import update_or_create_ansible_task 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 not hosts: return @@ -229,7 +229,7 @@ def test_asset_connectability_util(assets, task_name=None): if task_name is None: # task_name = _("Test assets connectability") 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: logger.info("No hosts, passed") return {} @@ -281,7 +281,7 @@ def test_system_user_connectability_util(system_user, task_name): """ from ops.utils import update_or_create_ansible_task 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 if not hosts: logger.info("No hosts, passed") @@ -379,7 +379,7 @@ def push_system_user_util(system_users, assets, task_name): logger.info("Not tasks, passed") 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: logger.info("Not hosts, passed") return {} diff --git a/apps/assets/utils.py b/apps/assets/utils.py index f841e4a79..9cee82a46 100644 --- a/apps/assets/utils.py +++ b/apps/assets/utils.py @@ -12,8 +12,8 @@ def get_assets_by_id_list(id_list): return Asset.objects.filter(id__in=id_list) -def get_assets_by_hostname_list(hostname_list): - return Asset.objects.filter(hostname__in=hostname_list) +def get_assets_by_fullname_list(hostname_list): + return Asset.objects.get_queryset_by_fullname_list(hostname_list) def get_system_user_by_name(name): diff --git a/apps/ops/inventory.py b/apps/ops/inventory.py index 7ed89e75c..117d961a9 100644 --- a/apps/ops/inventory.py +++ b/apps/ops/inventory.py @@ -2,7 +2,7 @@ # 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__ = [ 'JMSInventory' @@ -44,7 +44,7 @@ class JMSInventory(BaseInventory): super().__init__(host_list=host_list) 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 def convert_to_ansible(self, asset, run_as_admin=False): diff --git a/apps/orgs/mixins.py b/apps/orgs/mixins.py index 0355b02f8..648611d50 100644 --- a/apps/orgs/mixins.py +++ b/apps/orgs/mixins.py @@ -8,7 +8,7 @@ from django.shortcuts import redirect from django.forms import ModelForm 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 .models import Organization @@ -39,6 +39,25 @@ class OrgManager(models.Manager): tl.times += 1 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): if not current_org: 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) objects = OrgManager() + sep = '@' + def save(self, *args, **kwargs): if current_org and current_org.is_real(): self.org_id = current_org.id 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: abstract = True diff --git a/apps/orgs/models.py b/apps/orgs/models.py index ed44b8b7e..3ddd91f71 100644 --- a/apps/orgs/models.py +++ b/apps/orgs/models.py @@ -4,6 +4,8 @@ from django.db import models from django.core.cache import cache from django.utils.translation import ugettext_lazy as _ +from common.utils import is_uuid + class Organization(models.Model): 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')) CACHE_PREFIX = 'JMS_ORG_{}' - ROOT_ID = 'ROOT' - DEFAULT_ID = 'DEFAULT' + ROOT_ID_NAME = 'ROOT' + DEFAULT_ID_NAME = 'DEFAULT' def __str__(self): return self.name def set_to_cache(self): - key = self.CACHE_PREFIX.format(self.id) - cache.set(key, self, 3600) + key_id = self.CACHE_PREFIX.format(self.id) + key_name = self.CACHE_PREFIX.format(self.name) + cache.set(key_id, self, 3600) + cache.set(key_name, self, 3600) def expire_cache(self): - key = self.CACHE_PREFIX.format(self.id) - cache.set(key, self, 1) + key_id = self.CACHE_PREFIX.format(self.id) + key_name = self.CACHE_PREFIX.format(self.name) + cache.delete(key_id) + cache.delete(key_name) @classmethod def get_instance_from_cache(cls, oid): @@ -35,18 +41,23 @@ class Organization(models.Model): return cache.get(key, None) @classmethod - def get_instance(cls, oid, default=True): - cached = cls.get_instance_from_cache(oid) + def get_instance(cls, id_or_name, default=True): + cached = cls.get_instance_from_cache(id_or_name) if 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() - elif oid == cls.ROOT_ID: + elif id_or_name == cls.ROOT_ID_NAME: return cls.root() 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() except cls.DoesNotExist: org = cls.default() if default else None @@ -92,20 +103,20 @@ class Organization(models.Model): @classmethod def default(cls): - return cls(id=cls.DEFAULT_ID, name="Default") + return cls(id=cls.DEFAULT_ID_NAME, name=cls.DEFAULT_ID_NAME) @classmethod 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_root(self): - if self.id is self.ROOT_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: + if self.id is self.DEFAULT_ID_NAME: return True else: return False