From 9a62a7aaab00c6c5a8d926dd6d947e775cde9565 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Fri, 17 Feb 2023 17:14:53 +0800 Subject: [PATCH] =?UTF-8?q?pref:=20=E4=BF=AE=E6=94=B9=20activity=20log=20(?= =?UTF-8?q?#9571)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * pref: 修改 activity log * perf: 优化 acitivity * pref: 修改 activity * fix: 修复一些运行问题 * fix: app.py 中添加 tasks import * fix: 添加 activity_callback * fix: 添加 execute_account_backup_plan activity_callback * fix: 添加 activity_callback -> gather_asset_accounts * fix: 对 celery 任务添加 activity_callback 回调 * fix: 修改翻译 --------- Co-authored-by: ibuler Co-authored-by: jiangweidong Co-authored-by: Bai --- apps/accounts/api/automations/base.py | 2 +- apps/accounts/apps.py | 1 + .../automations/backup_account/handlers.py | 24 +- .../models/automations/backup_account.py | 15 + apps/accounts/tasks/automation.py | 23 +- apps/accounts/tasks/backup_account.py | 14 +- apps/accounts/tasks/gather_accounts.py | 5 +- apps/accounts/tasks/push_account.py | 5 +- apps/accounts/tasks/verify_account.py | 5 +- apps/assets/api/asset/asset.py | 5 +- apps/assets/api/node.py | 7 +- apps/assets/apps.py | 2 + apps/assets/models/automations/base.py | 10 +- apps/assets/serializers/asset/common.py | 8 +- apps/assets/signal_handlers/asset.py | 5 +- apps/assets/tasks/automation.py | 17 +- apps/assets/tasks/gather_facts.py | 35 +- apps/assets/tasks/nodes_amount.py | 2 +- apps/assets/tasks/ping.py | 37 +- apps/assets/tasks/ping_gateway.py | 24 +- apps/audits/api.py | 11 +- apps/audits/apps.py | 2 + apps/audits/models.py | 2 + apps/audits/serializers.py | 3 +- apps/audits/signal_handlers/activity_log.py | 127 ++--- apps/audits/tasks.py | 2 + apps/authentication/apps.py | 2 + apps/authentication/tasks.py | 2 +- apps/common/apps.py | 1 + apps/common/tasks.py | 13 +- apps/jumpserver/settings/base.py | 2 +- apps/locale/ja/LC_MESSAGES/django.mo | 4 +- apps/locale/ja/LC_MESSAGES/django.po | 457 ++++++++---------- apps/locale/zh/LC_MESSAGES/django.mo | 4 +- apps/locale/zh/LC_MESSAGES/django.po | 418 ++++++++-------- apps/ops/signal_handlers.py | 12 + apps/ops/tasks.py | 28 +- apps/orgs/apps.py | 1 + apps/orgs/signal_handlers/cache.py | 2 +- apps/perms/apps.py | 1 + apps/perms/tasks.py | 4 +- apps/settings/apps.py | 1 + apps/terminal/apps.py | 1 + apps/terminal/connect_methods.py | 2 + apps/terminal/tasks.py | 4 +- apps/users/apps.py | 1 + 46 files changed, 700 insertions(+), 653 deletions(-) diff --git a/apps/accounts/api/automations/base.py b/apps/accounts/api/automations/base.py index 700484e9b..f4aec2093 100644 --- a/apps/accounts/api/automations/base.py +++ b/apps/accounts/api/automations/base.py @@ -110,6 +110,6 @@ class AutomationExecutionViewSet( serializer.is_valid(raise_exception=True) automation = serializer.validated_data.get('automation') task = execute_automation.delay( - pid=str(automation.pk), trigger=Trigger.manual, tp=self.tp + automation=automation, trigger=Trigger.manual ) return Response({'task': task.id}, status=status.HTTP_201_CREATED) diff --git a/apps/accounts/apps.py b/apps/accounts/apps.py index 6fd8c2d9b..89ad972a9 100644 --- a/apps/accounts/apps.py +++ b/apps/accounts/apps.py @@ -7,4 +7,5 @@ class AccountsConfig(AppConfig): def ready(self): from . import signal_handlers + from . import tasks __all__ = signal_handlers diff --git a/apps/accounts/automations/backup_account/handlers.py b/apps/accounts/automations/backup_account/handlers.py index 743a38c84..65c96c67d 100644 --- a/apps/accounts/automations/backup_account/handlers.py +++ b/apps/accounts/automations/backup_account/handlers.py @@ -77,15 +77,10 @@ class AssetAccountHandler(BaseAccountHandler): return filename @classmethod - def create_data_map(cls, types: list): + def create_data_map(cls, accounts): data_map = defaultdict(list) - # TODO 可以优化一下查询 在账号上做 category 的缓存 避免数据量大时连表操作 - qs = Account.objects.filter( - asset__platform__type__in=types - ).annotate(type=F('asset__platform__type')) - - if not qs.exists(): + if not accounts.exists(): return data_map type_dict = {} @@ -93,18 +88,18 @@ class AssetAccountHandler(BaseAccountHandler): for j in i['children']: type_dict[j['value']] = j['display_name'] - header_fields = cls.get_header_fields(AccountSecretSerializer(qs.first())) + header_fields = cls.get_header_fields(AccountSecretSerializer(accounts.first())) account_type_map = defaultdict(list) - for account in qs: + for account in accounts: account_type_map[account.type].append(account) data_map = {} - for tp, accounts in account_type_map.items(): + for tp, _accounts in account_type_map.items(): sheet_name = type_dict.get(tp, tp) - data = AccountSecretSerializer(accounts, many=True).data + data = AccountSecretSerializer(_accounts, many=True).data data_map.update(cls.add_rows(data, header_fields, sheet_name)) - logger.info('\n\033[33m- 共收集 {} 条账号\033[0m'.format(qs.count())) + logger.info('\n\033[33m- 共备份 {} 条账号\033[0m'.format(accounts.count())) return data_map @@ -123,9 +118,8 @@ class AccountBackupHandler: # Print task start date time_start = time.time() files = [] - types = self.execution.types - - data_map = AssetAccountHandler.create_data_map(types) + accounts = self.execution.backup_accounts + data_map = AssetAccountHandler.create_data_map(accounts) if not data_map: return files diff --git a/apps/accounts/models/automations/backup_account.py b/apps/accounts/models/automations/backup_account.py index 473e2f3c0..3c213b00d 100644 --- a/apps/accounts/models/automations/backup_account.py +++ b/apps/accounts/models/automations/backup_account.py @@ -5,7 +5,9 @@ import uuid from celery import current_task from django.db import models +from django.db.models import F from django.utils.translation import ugettext_lazy as _ +from common.utils import lazyproperty from common.const.choices import Trigger from common.db.encoder import ModelJSONFieldEncoder @@ -70,6 +72,10 @@ class AccountBackupAutomation(PeriodTaskModelMixin, JMSOrgBaseModel): ) return execution.start() + @lazyproperty + def latest_execution(self): + return self.execution.first() + class AccountBackupExecution(OrgModelMixin): id = models.UUIDField(default=uuid.uuid4, primary_key=True) @@ -112,6 +118,15 @@ class AccountBackupExecution(OrgModelMixin): return [] return recipients.values() + @lazyproperty + def backup_accounts(self): + from accounts.models import Account + # TODO 可以优化一下查询 在账号上做 category 的缓存 避免数据量大时连表操作 + qs = Account.objects.filter( + asset__platform__type__in=self.types + ).annotate(type=F('asset__platform__type')) + return qs + @property def manager_type(self): return 'backup_account' diff --git a/apps/accounts/tasks/automation.py b/apps/accounts/tasks/automation.py index 67d4c4a90..27758c0be 100644 --- a/apps/accounts/tasks/automation.py +++ b/apps/accounts/tasks/automation.py @@ -1,20 +1,21 @@ from celery import shared_task from django.utils.translation import gettext_lazy as _ -from orgs.utils import tmp_to_root_org, tmp_to_org -from common.utils import get_logger, get_object_or_none -from accounts.const import AutomationTypes +from common.utils import get_logger +from orgs.utils import tmp_to_org logger = get_logger(__file__) -@shared_task(queue='ansible', verbose_name=_('Account execute automation')) -def execute_automation(pid, trigger, tp): - model = AutomationTypes.get_type_model(tp) - with tmp_to_root_org(): - instance = get_object_or_none(model, pk=pid) - if not instance: - logger.error("No automation task found: {}".format(pid)) - return +def task_activity_callback(self, instance, *args): + asset_ids = instance.get_all_asset_ids() + return asset_ids, instance.org_id + + +@shared_task( + queue='ansible', verbose_name=_('Account execute automation'), + activity_callback=task_activity_callback +) +def execute_automation(instance, trigger): with tmp_to_org(instance.org): instance.execute(trigger) diff --git a/apps/accounts/tasks/backup_account.py b/apps/accounts/tasks/backup_account.py index 1009ea5b7..446ce0374 100644 --- a/apps/accounts/tasks/backup_account.py +++ b/apps/accounts/tasks/backup_account.py @@ -9,7 +9,19 @@ from orgs.utils import tmp_to_org, tmp_to_root_org logger = get_logger(__file__) -@shared_task(verbose_name=_('Execute account backup plan')) +def task_activity_callback(self, pid, trigger): + with tmp_to_root_org(): + plan = get_object_or_none(AccountBackupAutomation, pk=pid) + if not plan: + return + if not plan.latest_execution: + return + resource_ids = plan.latest_execution.backup_accounts + org_id = plan.org_id + return resource_ids, org_id + + +@shared_task(verbose_name=_('Execute account backup plan'), activity_callback=task_activity_callback) def execute_account_backup_plan(pid, trigger): from accounts.models import AccountBackupAutomation with tmp_to_root_org(): diff --git a/apps/accounts/tasks/gather_accounts.py b/apps/accounts/tasks/gather_accounts.py index 434c2c0d8..d0b322b10 100644 --- a/apps/accounts/tasks/gather_accounts.py +++ b/apps/accounts/tasks/gather_accounts.py @@ -25,7 +25,10 @@ def gather_asset_accounts_util(nodes, task_name): automation_execute_start(task_name, tp, task_snapshot) -@shared_task(queue="ansible", verbose_name=_('Gather asset accounts')) +@shared_task( + queue="ansible", verbose_name=_('Gather asset accounts'), + activity_callback=lambda self, node_ids, task_name=None: (node_ids, None) +) def gather_asset_accounts(node_ids, task_name=None): if task_name is None: task_name = gettext_noop("Gather assets accounts") diff --git a/apps/accounts/tasks/push_account.py b/apps/accounts/tasks/push_account.py index 2b3e9279a..7a24e3b45 100644 --- a/apps/accounts/tasks/push_account.py +++ b/apps/accounts/tasks/push_account.py @@ -33,7 +33,10 @@ def push_accounts_to_assets_util(accounts, assets): push_util(account, assets, task_name) -@shared_task(queue="ansible", verbose_name=_('Push accounts to assets')) +@shared_task( + queue="ansible", verbose_name=_('Push accounts to assets'), + activity_callback=lambda self, account_ids, asset_ids: (account_ids, None) +) def push_accounts_to_assets(account_ids, asset_ids): from assets.models import Asset from accounts.models import Account diff --git a/apps/accounts/tasks/verify_account.py b/apps/accounts/tasks/verify_account.py index 219c7fdaa..5db0f61a0 100644 --- a/apps/accounts/tasks/verify_account.py +++ b/apps/accounts/tasks/verify_account.py @@ -38,7 +38,10 @@ def verify_accounts_connectivity_util(accounts, assets, task_name): ) -@shared_task(queue="ansible", verbose_name=_('Verify asset account availability')) +@shared_task( + queue="ansible", verbose_name=_('Verify asset account availability'), + activity_callback=lambda self, account_ids, asset_ids: (account_ids, None) +) def verify_accounts_connectivity(account_ids, asset_ids): from assets.models import Asset from accounts.models import Account, VerifyAccountAutomation diff --git a/apps/assets/api/asset/asset.py b/apps/assets/api/asset/asset.py index c076723ec..b032615e6 100644 --- a/apps/assets/api/asset/asset.py +++ b/apps/assets/api/asset/asset.py @@ -151,12 +151,11 @@ class AssetsTaskMixin: def perform_assets_task(self, serializer): data = serializer.validated_data assets = data.get("assets", []) - asset_ids = [asset.id for asset in assets] if data["action"] == "refresh": - task = update_assets_hardware_info_manual(asset_ids) + task = update_assets_hardware_info_manual(assets) else: - task = test_assets_connectivity_manual(asset_ids) + task = test_assets_connectivity_manual(assets) return task def perform_create(self, serializer): diff --git a/apps/assets/api/node.py b/apps/assets/api/node.py index 40d8aed97..3658a29f1 100644 --- a/apps/assets/api/node.py +++ b/apps/assets/api/node.py @@ -11,7 +11,6 @@ from rest_framework.response import Response from rest_framework.serializers import ValidationError from assets.models import Asset -from rbac.permissions import RBACPermission from common.api import SuggestionMixin from common.const.http import POST from common.const.signals import PRE_REMOVE, POST_REMOVE @@ -20,6 +19,7 @@ from common.utils import get_logger from orgs.mixins import generics from orgs.mixins.api import OrgBulkModelViewSet from orgs.utils import current_org +from rbac.permissions import RBACPermission from .. import serializers from ..models import Node from ..tasks import ( @@ -28,7 +28,6 @@ from ..tasks import ( check_node_assets_amount_task ) - logger = get_logger(__file__) __all__ = [ 'NodeViewSet', 'NodeAssetsApi', 'NodeAddAssetsApi', @@ -224,7 +223,7 @@ class NodeTaskCreateApi(generics.CreateAPIView): return if action == "refresh": - task = update_node_assets_hardware_info_manual(node.id) + task = update_node_assets_hardware_info_manual(node) else: - task = test_node_assets_connectivity_manual(node.id) + task = test_node_assets_connectivity_manual(node) self.set_serializer_data(serializer, task) diff --git a/apps/assets/apps.py b/apps/assets/apps.py index e1bb43544..a91b10ffc 100644 --- a/apps/assets/apps.py +++ b/apps/assets/apps.py @@ -14,3 +14,5 @@ class AssetsConfig(AppConfig): def ready(self): super().ready() from . import signal_handlers + from . import tasks + diff --git a/apps/assets/models/automations/base.py b/apps/assets/models/automations/base.py index fb3a3fa61..423ba9d09 100644 --- a/apps/assets/models/automations/base.py +++ b/apps/assets/models/automations/base.py @@ -80,6 +80,10 @@ class BaseAutomation(PeriodTaskModelMixin, JMSOrgBaseModel): def executed_amount(self): return self.executions.count() + @property + def latest_execution(self): + return self.executions.first() + def execute(self, trigger=Trigger.manual): try: eid = current_task.request.id @@ -125,12 +129,16 @@ class AutomationExecution(OrgModelMixin): def manager_type(self): return self.snapshot['type'] - def get_all_assets(self): + def get_all_asset_ids(self): node_ids = self.snapshot['nodes'] asset_ids = self.snapshot['assets'] nodes = Node.objects.filter(id__in=node_ids) node_asset_ids = Node.get_nodes_all_assets(*nodes).values_list('id', flat=True) asset_ids = set(list(asset_ids) + list(node_asset_ids)) + return asset_ids + + def get_all_assets(self): + asset_ids = self.get_all_asset_ids() return Asset.objects.filter(id__in=asset_ids) def all_assets_group_by_platform(self): diff --git a/apps/assets/serializers/asset/common.py b/apps/assets/serializers/asset/common.py index 0d1bbcb87..137a2ae3c 100644 --- a/apps/assets/serializers/asset/common.py +++ b/apps/assets/serializers/asset/common.py @@ -68,8 +68,8 @@ class AssetAccountSerializer( class Meta: model = Account fields_mini = [ - 'id', 'name', 'username', 'privileged', 'is_active', - 'version', 'secret_type', + 'id', 'name', 'username', 'privileged', + 'is_active', 'version', 'secret_type', ] fields_write_only = [ 'secret', 'push_now', 'template' @@ -259,8 +259,6 @@ class AssetSerializer(BulkOrgResourceModelSerializer, WritableNestedModelSeriali def accounts_create(accounts_data, asset): for data in accounts_data: data['asset'] = asset - secret = data.get('secret') - data['secret'] = decrypt_password(secret) if secret else secret AssetAccountSerializer().create(data) @atomic @@ -274,8 +272,6 @@ class AssetSerializer(BulkOrgResourceModelSerializer, WritableNestedModelSeriali @atomic def update(self, instance, validated_data): - if not validated_data.get('accounts'): - validated_data.pop('accounts', None) nodes_display = validated_data.pop('nodes_display', '') instance = super().update(instance, validated_data) self.perform_nodes_display_create(instance, nodes_display) diff --git a/apps/assets/signal_handlers/asset.py b/apps/assets/signal_handlers/asset.py index be25988f6..25c54bb8e 100644 --- a/apps/assets/signal_handlers/asset.py +++ b/apps/assets/signal_handlers/asset.py @@ -11,6 +11,7 @@ from assets.tasks import test_assets_connectivity_task, gather_assets_facts_task from common.const.signals import POST_REMOVE, PRE_REMOVE from common.decorators import on_transaction_commit, merge_delay_run, key_by_org from common.utils import get_logger +from orgs.utils import current_org logger = get_logger(__file__) @@ -23,7 +24,7 @@ def on_node_pre_save(sender, instance: Node, **kwargs): @merge_delay_run(ttl=5, key=key_by_org) def test_assets_connectivity_handler(assets=()): task_name = gettext_noop("Test assets connectivity ") - test_assets_connectivity_task.delay(assets, task_name) + test_assets_connectivity_task.delay(assets, str(current_org.id), task_name) @merge_delay_run(ttl=5, key=key_by_org) @@ -32,7 +33,7 @@ def gather_assets_facts_handler(assets=()): logger.info("No assets to update hardware info") return name = gettext_noop("Gather asset hardware info") - gather_assets_facts_task.delay(assets=assets, task_name=name) + gather_assets_facts_task.delay(assets, str(current_org.id), task_name=name) @merge_delay_run(ttl=5, key=key_by_org) diff --git a/apps/assets/tasks/automation.py b/apps/assets/tasks/automation.py index 582fe7ea2..4e7d340c2 100644 --- a/apps/assets/tasks/automation.py +++ b/apps/assets/tasks/automation.py @@ -8,7 +8,22 @@ from assets.const import AutomationTypes logger = get_logger(__file__) -@shared_task(queue='ansible', verbose_name=_('Asset execute automation')) +def task_activity_callback(self, pid, trigger, tp): + model = AutomationTypes.get_type_model(tp) + with tmp_to_root_org(): + instance = get_object_or_none(model, pk=pid) + if not instance: + return + if not instance.latest_execution: + return + resource_ids = instance.latest_execution.get_all_asset_ids() + return resource_ids, instance.org_id + + +@shared_task( + queue='ansible', verbose_name=_('Asset execute automation'), + activity_callback=task_activity_callback +) def execute_automation(pid, trigger, tp): model = AutomationTypes.get_type_model(tp) with tmp_to_root_org(): diff --git a/apps/assets/tasks/gather_facts.py b/apps/assets/tasks/gather_facts.py index cbbaeacbc..b541bde69 100644 --- a/apps/assets/tasks/gather_facts.py +++ b/apps/assets/tasks/gather_facts.py @@ -1,13 +1,12 @@ # -*- coding: utf-8 -*- # -from itertools import chain from celery import shared_task from django.utils.translation import gettext_noop, gettext_lazy as _ from assets.const import AutomationTypes from common.utils import get_logger -from orgs.utils import tmp_to_org +from orgs.utils import tmp_to_org, current_org from .common import quickstart_automation logger = get_logger(__file__) @@ -18,22 +17,17 @@ __all__ = [ ] -@shared_task(queue="ansible", verbose_name=_('Gather assets facts')) -def gather_assets_facts_task(assets=None, nodes=None, task_name=None): +@shared_task( + queue="ansible", verbose_name=_('Gather assets facts'), + activity_callback=lambda self, asset_ids, org_id, *args, **kwargs: (asset_ids, org_id) +) +def gather_assets_facts_task(asset_ids, org_id, task_name=None): from assets.models import GatherFactsAutomation if task_name is None: task_name = gettext_noop("Gather assets facts") task_name = GatherFactsAutomation.generate_unique_name(task_name) - - nodes = nodes or [] - assets = assets or [] - resources = chain(assets, nodes) - if not resources: - raise ValueError("nodes or assets must be given") - org_id = list(resources)[0].org_id task_snapshot = { - 'assets': [str(asset.id) for asset in assets], - 'nodes': [str(node.id) for node in nodes], + 'assets': asset_ids, } tp = AutomationTypes.gather_facts @@ -41,15 +35,14 @@ def gather_assets_facts_task(assets=None, nodes=None, task_name=None): quickstart_automation(task_name, tp, task_snapshot) -def update_assets_hardware_info_manual(asset_ids): - from assets.models import Asset - assets = Asset.objects.filter(id__in=asset_ids) +def update_assets_hardware_info_manual(assets): task_name = gettext_noop("Update assets hardware info: ") - return gather_assets_facts_task.delay(assets=assets, task_name=task_name) + asset_ids = [str(i.id) for i in assets] + return gather_assets_facts_task.delay(asset_ids, str(current_org.id), task_name=task_name) -def update_node_assets_hardware_info_manual(node_id): - from assets.models import Node - node = Node.objects.get(id=node_id) +def update_node_assets_hardware_info_manual(node): + asset_ids = node.get_all_asset_ids() + asset_ids = [str(i) for i in asset_ids] task_name = gettext_noop("Update node asset hardware information: ") - return gather_assets_facts_task.delay(nodes=[node], task_name=task_name) + return gather_assets_facts_task.delay(asset_ids, str(current_org.id), task_name=task_name) diff --git a/apps/assets/tasks/nodes_amount.py b/apps/assets/tasks/nodes_amount.py index f8d8d38a4..58344aa11 100644 --- a/apps/assets/tasks/nodes_amount.py +++ b/apps/assets/tasks/nodes_amount.py @@ -30,7 +30,7 @@ def check_node_assets_amount_task(org_id=None): logger.error(error) -@register_as_period_task(crontab=CRONTAB_AT_AM_TWO) @shared_task(verbose_name=_('Periodic check the amount of assets under the node')) +@register_as_period_task(crontab=CRONTAB_AT_AM_TWO) def check_node_assets_amount_period_task(): check_node_assets_amount_task() diff --git a/apps/assets/tasks/ping.py b/apps/assets/tasks/ping.py index 973085db3..3882fe0b3 100644 --- a/apps/assets/tasks/ping.py +++ b/apps/assets/tasks/ping.py @@ -1,10 +1,10 @@ # ~*~ coding: utf-8 ~*~ from celery import shared_task -from django.utils.translation import gettext_noop +from django.utils.translation import gettext_noop, gettext_lazy as _ from assets.const import AutomationTypes from common.utils import get_logger -from orgs.utils import org_aware_func +from orgs.utils import tmp_to_org, current_org from .common import quickstart_automation logger = get_logger(__file__) @@ -16,28 +16,31 @@ __all__ = [ ] -@shared_task -@org_aware_func('assets') -def test_assets_connectivity_task(assets, task_name=None): +@shared_task( + verbose_name=_('Test assets connectivity'), queue='ansible', + activity_callback=lambda self, asset_ids, org_id, *args, **kwargs: (asset_ids, org_id) +) +def test_assets_connectivity_task(asset_ids, org_id, task_name=None): from assets.models import PingAutomation if task_name is None: - task_name = gettext_noop("Test assets connectivity ") + task_name = gettext_noop("Test assets connectivity") task_name = PingAutomation.generate_unique_name(task_name) - task_snapshot = {'assets': [str(asset.id) for asset in assets]} - quickstart_automation(task_name, AutomationTypes.ping, task_snapshot) + task_snapshot = {'assets': asset_ids} + with tmp_to_org(org_id): + quickstart_automation(task_name, AutomationTypes.ping, task_snapshot) -def test_assets_connectivity_manual(asset_ids): - from assets.models import Asset - assets = Asset.objects.filter(id__in=asset_ids) +def test_assets_connectivity_manual(assets): task_name = gettext_noop("Test assets connectivity ") - return test_assets_connectivity_task.delay(assets, task_name) + asset_ids = [str(i.id) for i in assets] + org_id = str(current_org.id) + return test_assets_connectivity_task.delay(asset_ids, org_id, task_name) -def test_node_assets_connectivity_manual(node_id): - from assets.models import Node - node = Node.objects.get(id=node_id) +def test_node_assets_connectivity_manual(node): task_name = gettext_noop("Test if the assets under the node are connectable ") - assets = node.get_all_assets() - return test_assets_connectivity_task.delay(assets, task_name) + asset_ids = node.get_all_asset_ids() + asset_ids = [str(i) for i in asset_ids] + org_id = str(current_org.id) + return test_assets_connectivity_task.delay(asset_ids, org_id, task_name) diff --git a/apps/assets/tasks/ping_gateway.py b/apps/assets/tasks/ping_gateway.py index 1af76e347..b6f14fa91 100644 --- a/apps/assets/tasks/ping_gateway.py +++ b/apps/assets/tasks/ping_gateway.py @@ -1,10 +1,10 @@ # ~*~ coding: utf-8 ~*~ from celery import shared_task -from django.utils.translation import gettext_noop +from django.utils.translation import gettext_noop, ugettext_lazy as _ from assets.const import AutomationTypes from common.utils import get_logger -from orgs.utils import org_aware_func +from orgs.utils import org_aware_func, tmp_to_org, current_org from .common import quickstart_automation logger = get_logger(__file__) @@ -15,20 +15,24 @@ __all__ = [ ] -@shared_task +@shared_task( + verbose_name=_('Test gateways connectivity'), queue='ansible', + activity_callback=lambda self, asset_ids, org_id, *args, **kwargs: (asset_ids, org_id) +) @org_aware_func('assets') -def test_gateways_connectivity_task(assets, local_port, task_name=None): +def test_gateways_connectivity_task(asset_ids, org_id, local_port, task_name=None): from assets.models import PingAutomation if task_name is None: - task_name = gettext_noop("Test gateways connectivity ") + task_name = gettext_noop("Test gateways connectivity") task_name = PingAutomation.generate_unique_name(task_name) - task_snapshot = {'assets': [str(asset.id) for asset in assets], 'local_port': local_port} - quickstart_automation(task_name, AutomationTypes.ping_gateway, task_snapshot) + task_snapshot = {'assets': asset_ids, 'local_port': local_port} + with tmp_to_org(org_id): + quickstart_automation(task_name, AutomationTypes.ping_gateway, task_snapshot) def test_gateways_connectivity_manual(gateway_ids, local_port): from assets.models import Asset - gateways = Asset.objects.filter(id__in=gateway_ids) - task_name = gettext_noop("Test gateways connectivity ") - return test_gateways_connectivity_task.delay(gateways, local_port, task_name) + gateways = Asset.objects.filter(id__in=gateway_ids).values_list('id', flat=True) + task_name = gettext_noop("Test gateways connectivity") + return test_gateways_connectivity_task.delay(gateways, str(current_org.id), local_port, task_name) diff --git a/apps/audits/api.py b/apps/audits/api.py index 09946ce39..752777fc6 100644 --- a/apps/audits/api.py +++ b/apps/audits/api.py @@ -3,7 +3,7 @@ from importlib import import_module from django.conf import settings -from django.db.models import F, Value, CharField +from django.db.models import F, Value, CharField, Q from rest_framework import generics from rest_framework.mixins import ListModelMixin, CreateModelMixin, RetrieveModelMixin from rest_framework.permissions import IsAuthenticated @@ -14,6 +14,7 @@ from common.plugins.es import QuerySet as ESQuerySet from ops.models.job import JobAuditLog from orgs.mixins.api import OrgGenericViewSet, OrgBulkModelViewSet from orgs.utils import current_org, tmp_to_root_org +from users.models import User from .backends import TYPE_ENGINE_MAPPING from .const import ActivityChoices from .models import FTPLog, UserLoginLog, OperateLog, PasswordChangeLog, ActivityLog @@ -92,8 +93,12 @@ class ResourceActivityAPIView(generics.ListAPIView): } @staticmethod - def get_operate_log_qs(fields, limit=30, **filters): - queryset = OperateLog.objects.filter(**filters).annotate( + def get_operate_log_qs(fields, limit=30, resource_id=None): + q = Q(resource_id=resource_id) + user = User.objects.filter(id=resource_id).first() + if user: + q |= Q(user=str(user)) + queryset = OperateLog.objects.filter(q).annotate( r_type=Value(ActivityChoices.operate_log, CharField()), r_detail_id=F('id'), r_detail=Value(None, CharField()), r_user=F('user'), r_action=F('action'), diff --git a/apps/audits/apps.py b/apps/audits/apps.py index 26d7be9ca..6e198176b 100644 --- a/apps/audits/apps.py +++ b/apps/audits/apps.py @@ -10,5 +10,7 @@ class AuditsConfig(AppConfig): def ready(self): from . import signal_handlers + from . import tasks + if settings.SYSLOG_ENABLE: post_save.connect(signal_handlers.on_audits_log_create) diff --git a/apps/audits/models.py b/apps/audits/models.py index 29a67911f..552d6162a 100644 --- a/apps/audits/models.py +++ b/apps/audits/models.py @@ -107,7 +107,9 @@ class ActivityLog(OrgModelMixin): datetime = models.DateTimeField( auto_now=True, verbose_name=_('Datetime'), db_index=True ) + # 日志的描述信息 detail = models.TextField(default='', blank=True, verbose_name=_('Detail')) + # 详情ID, 结合 type 来使用, (实例ID 和 CeleryTaskID) detail_id = models.CharField( max_length=36, default=None, null=True, verbose_name=_('Detail ID') ) diff --git a/apps/audits/serializers.py b/apps/audits/serializers.py index 26e96cbf5..e1bdbab4f 100644 --- a/apps/audits/serializers.py +++ b/apps/audits/serializers.py @@ -107,6 +107,7 @@ class SessionAuditSerializer(serializers.ModelSerializer): class ActivityUnionLogSerializer(serializers.Serializer): + id = serializers.CharField() timestamp = serializers.SerializerMethodField() detail_url = serializers.SerializerMethodField() content = serializers.SerializerMethodField() @@ -120,7 +121,7 @@ class ActivityUnionLogSerializer(serializers.Serializer): def get_content(obj): if not obj['r_detail']: action = obj['r_action'].replace('_', ' ').capitalize() - ctn = _('User {} {} this resource').format(obj['r_user'], _(action)) + ctn = _('User %s %s this resource') % (obj['r_user'], _(action)) else: ctn = i18n_trans(obj['r_detail']) return ctn diff --git a/apps/audits/signal_handlers/activity_log.py b/apps/audits/signal_handlers/activity_log.py index 154a0b441..eab8f63a6 100644 --- a/apps/audits/signal_handlers/activity_log.py +++ b/apps/audits/signal_handlers/activity_log.py @@ -8,18 +8,20 @@ from accounts.const import AutomationTypes from accounts.models import AccountBackupAutomation from assets.models import Asset, Node from audits.models import ActivityLog -from common.utils import get_object_or_none, i18n_fmt +from common.utils import get_object_or_none, i18n_fmt, get_logger from jumpserver.utils import current_request from ops.celery import app -from orgs.utils import tmp_to_root_org from orgs.models import Organization +from orgs.utils import tmp_to_root_org, current_org from terminal.models import Session from users.models import User from ..const import ActivityChoices from ..models import UserLoginLog +logger = get_logger(__name__) -class ActivityLogHandler(object): + +class TaskActivityHandler(object): @staticmethod def _func_accounts_execute_automation(*args, **kwargs): @@ -80,12 +82,6 @@ class ActivityLogHandler(object): asset_ids = node.get_all_assets().values_list('id', flat=True) return '', asset_ids - def get_celery_task_info(self, task_name, *args, **kwargs): - task_display, resource_ids = self.get_info_by_task_name( - task_name, *args, **kwargs - ) - return task_display, resource_ids - @staticmethod def get_task_display(task_name, **kwargs): task = app.tasks.get(task_name) @@ -107,6 +103,8 @@ class ActivityLogHandler(object): task_display = '%s-%s' % (task_display, task_type) return task_display, resource_ids + +class ActivityLogHandler: @staticmethod def session_for_activity(obj): detail = i18n_fmt( @@ -119,75 +117,84 @@ class ActivityLogHandler(object): def login_log_for_activity(obj): login_status = gettext_noop('Success') if obj.status else gettext_noop('Failed') detail = i18n_fmt(gettext_noop('User %s login system %s'), obj.username, login_status) - user_id = User.objects.filter(username=obj.username).values('id').first() + + username = obj.username + user_id = User.objects.filter(username=username) \ + .values_list('id', flat=True).first() resource_list = [] if user_id: - resource_list = [user_id['id']] + resource_list = [user_id] return resource_list, detail, ActivityChoices.login_log, Organization.SYSTEM_ID - -activity_handler = ActivityLogHandler() + @staticmethod + def task_log_for_celery(headers, body): + task_id, task_name = headers.get('id'), headers.get('task') + task = app.tasks.get(task_name) + if not task: + raise ValueError('Task not found: {}'.format(task_name)) + activity_callback = getattr(task, 'activity_callback', None) + if not callable(activity_callback): + return [], '', '' + args, kwargs = body[:2] + data = activity_callback(*args, **kwargs) + if data is None: + return [], '', '' + resource_ids, org_id, user = data + ('',) * (3 - len(data)) + if not user: + user = str(current_request.user) if current_request else 'System' + if org_id is None: + org_id = current_org.org_id + task_display = getattr(task, 'verbose_name', _('Unknown')) + detail = i18n_fmt( + gettext_noop('User %s perform a task for this resource: %s'), + user, task_display + ) + return resource_ids, detail, org_id -@signals.before_task_publish.connect -def before_task_publish_for_activity_log(headers=None, **kwargs): - task_id, task_name = headers.get('id'), headers.get('task') - args, kwargs = kwargs['body'][:2] - task_display, resource_ids = activity_handler.get_celery_task_info( - task_name, args, **kwargs - ) - if not current_request: - user = 'System' - else: - user = str(current_request.user) - - detail = i18n_fmt( - gettext_noop('User %s perform a task (%s) for this resource'), - user, task_display - ) +def create_activities(resource_ids, detail, detail_id, action, org_id): + if not resource_ids: + return activities = [ - ActivityLog(resource_id=resource_id, type=ActivityChoices.task, detail=detail) + ActivityLog( + resource_id=getattr(resource_id, 'pk', resource_id), + type=action, detail=detail, detail_id=detail_id, org_id=org_id + ) for resource_id in resource_ids ] ActivityLog.objects.bulk_create(activities) - activity_info = { - 'activity_ids': [a.id for a in activities] - } - kwargs['activity_info'] = activity_info + return activities -@signals.task_prerun.connect -def on_celery_task_pre_run_for_activity_log(task_id='', **kwargs): - activity_info = kwargs['kwargs'].pop('activity_info', None) - if activity_info is None: - return +@signals.after_task_publish.connect +def after_task_publish_for_activity_log(headers=None, body=None, **kwargs): + """ Tip: https://docs.celeryq.dev/en/stable/internals/protocol.html#message-protocol-task-v2 """ + try: + task_id = headers.get('id') + resource_ids, detail, org_id = ActivityLogHandler.task_log_for_celery(headers, body) + except Exception as e: + logger.error(f'Get celery task info error: {e}', exc_info=True) + else: + logger.debug(f'Create activity log for celery task: {task_id}') + create_activities(resource_ids, detail, task_id, action=ActivityChoices.task, org_id=org_id) - activities = [] - for activity_id in activity_info['activity_ids']: - activities.append( - ActivityLog(id=activity_id, detail_id=task_id) - ) - ActivityLog.objects.bulk_update(activities, ('detail_id',)) + +model_activity_handler_map = { + Session: ActivityLogHandler.session_for_activity, + UserLoginLog: ActivityLogHandler.login_log_for_activity, +} def on_session_or_login_log_created(sender, instance=None, created=False, **kwargs): - handler_mapping = { - 'Session': activity_handler.session_for_activity, - 'UserLoginLog': activity_handler.login_log_for_activity - } - model_name = sender._meta.object_name - if not created or model_name not in handler_mapping: + if not created: return - resource_ids, detail, act_type, org_id = handler_mapping[model_name](instance) - activities = [ - ActivityLog( - resource_id=i, type=act_type, detail=detail, - detail_id=instance.id, org_id=org_id - ) - for i in resource_ids - ] - ActivityLog.objects.bulk_create(activities) + func = model_activity_handler_map.get(sender) + if not func: + logger.error('Activity log handler not found: {}'.format(sender)) + + resource_ids, detail, act_type, org_id = func(instance) + return create_activities(resource_ids, detail, instance.id, act_type, org_id) for sd in [Session, UserLoginLog]: diff --git a/apps/audits/tasks.py b/apps/audits/tasks.py index 7cd172bdd..3c4abded3 100644 --- a/apps/audits/tasks.py +++ b/apps/audits/tasks.py @@ -49,6 +49,8 @@ def clean_ftp_log_period(): FTPLog.objects.filter(date_start__lt=expired_day).delete() +@shared_task(verbose_name=_('Clean audits log')) +@register_as_period_task(interval=3600 * 24) def clean_celery_tasks_period(): logger.debug("Start clean celery task history") expire_days = get_log_keep_day('TASK_LOG_KEEP_DAYS') diff --git a/apps/authentication/apps.py b/apps/authentication/apps.py index 6516ed70e..615bb255e 100644 --- a/apps/authentication/apps.py +++ b/apps/authentication/apps.py @@ -9,5 +9,7 @@ class AuthenticationConfig(AppConfig): def ready(self): from . import signal_handlers from . import notifications + from . import tasks + super().ready() diff --git a/apps/authentication/tasks.py b/apps/authentication/tasks.py index 978e4ace0..f731d6670 100644 --- a/apps/authentication/tasks.py +++ b/apps/authentication/tasks.py @@ -8,7 +8,7 @@ from django.utils import timezone from django.utils.translation import gettext_lazy as _ -@register_as_period_task(interval=3600 * 24) @shared_task(verbose_name=_('Clean expired session')) +@register_as_period_task(interval=3600 * 24) def clean_django_sessions(): Session.objects.filter(expire_date__lt=timezone.now()).delete() diff --git a/apps/common/apps.py b/apps/common/apps.py index c55e4c6e3..89e735a09 100644 --- a/apps/common/apps.py +++ b/apps/common/apps.py @@ -9,6 +9,7 @@ class CommonConfig(AppConfig): def ready(self): from . import signal_handlers + from . import tasks from .signals import django_ready excludes = ['migrate', 'compilemessages', 'makemigrations'] for i in excludes: diff --git a/apps/common/tasks.py b/apps/common/tasks.py index 45828492b..76616803a 100644 --- a/apps/common/tasks.py +++ b/apps/common/tasks.py @@ -10,7 +10,14 @@ from .utils import get_logger logger = get_logger(__file__) -@shared_task(verbose_name=_("Send email")) +def task_activity_callback(self, subject, message, from_email, recipient_list, **kwargs): + from users.models import User + email_list = recipient_list + resource_ids = list(User.objects.filter(email__in=email_list).values_list('id', flat=True)) + return resource_ids + + +@shared_task(verbose_name=_("Send email"), activity_callback=task_activity_callback) def send_mail_async(*args, **kwargs): """ Using celery to send email async @@ -19,7 +26,7 @@ def send_mail_async(*args, **kwargs): Example: send_mail_sync.delay(subject, message, from_mail, recipient_list, fail_silently=False, html_message=None) - Also you can ignore the from_mail, unlike django send_mail, from_email is not a require args: + Also, you can ignore the from_mail, unlike django send_mail, from_email is not a required args: Example: send_mail_sync.delay(subject, message, recipient_list, fail_silently=False, html_message=None) @@ -37,7 +44,7 @@ def send_mail_async(*args, **kwargs): logger.error("Sending mail error: {}".format(e)) -@shared_task(verbose_name=_("Send email attachment")) +@shared_task(verbose_name=_("Send email attachment"), activity_callback=task_activity_callback) def send_mail_attachment_async(subject, message, recipient_list, attachment_list=None): if attachment_list is None: attachment_list = [] diff --git a/apps/jumpserver/settings/base.py b/apps/jumpserver/settings/base.py index 8835bd073..e956dbd69 100644 --- a/apps/jumpserver/settings/base.py +++ b/apps/jumpserver/settings/base.py @@ -92,7 +92,6 @@ INSTALLED_APPS = [ 'acls.apps.AclsConfig', 'notifications.apps.NotificationsConfig', 'rbac.apps.RBACConfig', - 'common.apps.CommonConfig', 'jms_oidc_rp', 'rest_framework', 'rest_framework_swagger', @@ -111,6 +110,7 @@ INSTALLED_APPS = [ 'django.contrib.messages', 'django.contrib.staticfiles', 'django.forms', + 'common.apps.CommonConfig', # 这个放到内置的最后, django ready 'simple_history', # 这个要放到最后,别特么瞎改顺序 ] diff --git a/apps/locale/ja/LC_MESSAGES/django.mo b/apps/locale/ja/LC_MESSAGES/django.mo index 1f5fd2ea6..28cbce867 100644 --- a/apps/locale/ja/LC_MESSAGES/django.mo +++ b/apps/locale/ja/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6bbad43c6fd75da933f86aa609c54641cfbf45099564b07e5090d007287af984 -size 135540 +oid sha256:6717c42fb411e6469fc755487eea88e926088a5a73dcf00a0d52e1b9986ae147 +size 136360 diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index a2c658ec5..70fbc2f46 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-02-16 15:25+0800\n" +"POT-Creation-Date: 2023-02-17 16:56+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -159,23 +159,23 @@ msgid "Only create" msgstr "作成のみ" #: accounts/models/account.py:47 accounts/models/gathered_account.py:14 -#: accounts/serializers/account/account.py:95 +#: accounts/serializers/account/account.py:97 #: accounts/serializers/account/gathered_account.py:10 #: accounts/serializers/automations/change_secret.py:107 #: accounts/serializers/automations/change_secret.py:127 #: acls/models/base.py:100 acls/serializers/base.py:56 -#: assets/models/asset/common.py:97 assets/models/asset/common.py:282 +#: assets/models/asset/common.py:97 assets/models/asset/common.py:284 #: assets/models/cmd_filter.py:36 assets/serializers/domain.py:19 #: assets/serializers/label.py:27 audits/models.py:36 #: authentication/models/connection_token.py:33 #: perms/models/asset_permission.py:64 perms/serializers/permission.py:27 #: terminal/backends/command/models.py:21 terminal/models/session/session.py:31 #: terminal/notifications.py:95 terminal/serializers/command.py:16 -#: tickets/models/ticket/apply_asset.py:16 xpack/plugins/cloud/models.py:220 +#: tickets/models/ticket/apply_asset.py:16 xpack/plugins/cloud/models.py:212 msgid "Asset" msgstr "資産" -#: accounts/models/account.py:51 accounts/serializers/account/account.py:99 +#: accounts/models/account.py:51 accounts/serializers/account/account.py:101 #: authentication/serializers/connect_token_secret.py:50 msgid "Su from" msgstr "から切り替え" @@ -185,7 +185,7 @@ msgstr "から切り替え" msgid "Version" msgstr "バージョン" -#: accounts/models/account.py:55 accounts/serializers/account/account.py:96 +#: accounts/models/account.py:55 accounts/serializers/account/account.py:98 #: users/models/user.py:768 msgid "Source" msgstr "ソース" @@ -207,43 +207,39 @@ msgid "Can view asset account secret" msgstr "資産アカウントの秘密を表示できます" #: accounts/models/account.py:65 -msgid "Can change asset account secret" -msgstr "資産口座の秘密を変更できます" - -#: accounts/models/account.py:66 msgid "Can view asset history account" msgstr "資産履歴アカウントを表示できます" -#: accounts/models/account.py:67 +#: accounts/models/account.py:66 msgid "Can view asset history account secret" msgstr "資産履歴アカウントパスワードを表示できます" -#: accounts/models/account.py:104 +#: accounts/models/account.py:111 msgid "Account template" msgstr "アカウント テンプレート" -#: accounts/models/account.py:109 +#: accounts/models/account.py:116 msgid "Can view asset account template secret" msgstr "アセット アカウント テンプレートのパスワードを表示できます" -#: accounts/models/account.py:110 +#: accounts/models/account.py:117 msgid "Can change asset account template secret" msgstr "アセット アカウント テンプレートのパスワードを変更できます" -#: accounts/models/automations/backup_account.py:25 +#: accounts/models/automations/backup_account.py:27 #: accounts/models/automations/change_secret.py:47 #: accounts/serializers/account/backup.py:32 #: accounts/serializers/automations/change_secret.py:56 msgid "Recipient" msgstr "受信者" -#: accounts/models/automations/backup_account.py:34 -#: accounts/models/automations/backup_account.py:96 +#: accounts/models/automations/backup_account.py:36 +#: accounts/models/automations/backup_account.py:102 msgid "Account backup plan" msgstr "アカウントバックアップ計画" -#: accounts/models/automations/backup_account.py:77 -#: assets/models/automations/base.py:110 audits/models.py:43 +#: accounts/models/automations/backup_account.py:83 +#: assets/models/automations/base.py:114 audits/models.py:43 #: ops/models/base.py:55 ops/models/celery.py:63 ops/models/job.py:116 #: perms/models/asset_permission.py:72 terminal/models/applet/host.py:108 #: terminal/models/session/session.py:44 @@ -252,37 +248,37 @@ msgstr "アカウントバックアップ計画" msgid "Date start" msgstr "開始日" -#: accounts/models/automations/backup_account.py:80 +#: accounts/models/automations/backup_account.py:86 #: authentication/templates/authentication/_msg_oauth_bind.html:11 #: notifications/notifications.py:186 msgid "Time" msgstr "時間" -#: accounts/models/automations/backup_account.py:84 +#: accounts/models/automations/backup_account.py:90 msgid "Account backup snapshot" msgstr "アカウントのバックアップスナップショット" -#: accounts/models/automations/backup_account.py:88 +#: accounts/models/automations/backup_account.py:94 #: accounts/serializers/account/backup.py:39 #: accounts/serializers/automations/base.py:44 -#: assets/models/automations/base.py:117 +#: assets/models/automations/base.py:121 #: assets/serializers/automations/base.py:40 msgid "Trigger mode" msgstr "トリガーモード" -#: accounts/models/automations/backup_account.py:91 audits/models.py:158 -#: terminal/models/session/sharing.py:107 xpack/plugins/cloud/models.py:176 +#: accounts/models/automations/backup_account.py:97 audits/models.py:160 +#: terminal/models/session/sharing.py:107 xpack/plugins/cloud/models.py:168 msgid "Reason" msgstr "理由" -#: accounts/models/automations/backup_account.py:93 +#: accounts/models/automations/backup_account.py:99 #: accounts/serializers/automations/change_secret.py:106 #: accounts/serializers/automations/change_secret.py:129 #: ops/serializers/job.py:64 terminal/serializers/session.py:49 msgid "Is success" msgstr "成功は" -#: accounts/models/automations/backup_account.py:101 +#: accounts/models/automations/backup_account.py:107 msgid "Account backup execution" msgstr "アカウントバックアップの実行" @@ -323,7 +319,7 @@ msgid "Can add push account execution" msgstr "プッシュ アカウントの作成の実行" #: accounts/models/automations/change_secret.py:17 accounts/models/base.py:36 -#: accounts/serializers/account/account.py:132 +#: accounts/serializers/account/account.py:134 #: accounts/serializers/account/base.py:16 #: accounts/serializers/automations/change_secret.py:46 #: authentication/serializers/connect_token_secret.py:41 @@ -365,7 +361,7 @@ msgid "Date started" msgstr "開始日" #: accounts/models/automations/change_secret.py:74 -#: assets/models/automations/base.py:111 ops/models/base.py:56 +#: assets/models/automations/base.py:115 ops/models/base.py:56 #: ops/models/celery.py:64 ops/models/job.py:117 #: terminal/models/applet/host.py:109 msgid "Date finished" @@ -381,7 +377,7 @@ msgid "Change secret record" msgstr "パスワード レコードの変更" #: accounts/models/automations/gather_account.py:15 -#: accounts/tasks/gather_accounts.py:28 +#: accounts/tasks/gather_accounts.py:29 msgid "Gather asset accounts" msgstr "アカウントのコレクション" @@ -391,7 +387,7 @@ msgstr "トリガー方式" #: accounts/models/automations/push_account.py:14 accounts/models/base.py:34 #: accounts/models/gathered_account.py:15 acls/serializers/base.py:18 -#: acls/serializers/base.py:49 assets/models/_user.py:23 audits/models.py:143 +#: acls/serializers/base.py:49 assets/models/_user.py:23 audits/models.py:145 #: authentication/forms.py:25 authentication/forms.py:27 #: authentication/models/temp_token.py:9 #: authentication/templates/authentication/_msg_different_city.html:9 @@ -429,7 +425,7 @@ msgstr "アカウントの確認" #: assets/serializers/platform.py:131 #: authentication/serializers/connect_token_secret.py:103 ops/mixin.py:21 #: ops/models/adhoc.py:21 ops/models/celery.py:15 ops/models/celery.py:57 -#: ops/models/job.py:26 ops/models/playbook.py:22 ops/serializers/job.py:19 +#: ops/models/job.py:26 ops/models/playbook.py:23 ops/serializers/job.py:19 #: ops/serializers/playbook.py:19 orgs/models.py:69 #: perms/models/asset_permission.py:56 rbac/models/role.py:29 #: settings/models.py:33 settings/serializers/sms.py:6 @@ -511,22 +507,22 @@ msgstr "" "{} -暗号化変更タスクが完了しました: 暗号化パスワードが設定されていません-個人" "情報にアクセスしてください-> ファイル暗号化パスワードを設定してください" -#: accounts/serializers/account/account.py:65 +#: accounts/serializers/account/account.py:67 #: assets/serializers/asset/common.py:64 settings/serializers/auth/sms.py:75 msgid "Template" msgstr "テンプレート" -#: accounts/serializers/account/account.py:68 +#: accounts/serializers/account/account.py:70 #: assets/serializers/asset/common.py:61 msgid "Push now" msgstr "今すぐプッシュ" -#: accounts/serializers/account/account.py:70 +#: accounts/serializers/account/account.py:72 #: accounts/serializers/account/base.py:62 msgid "Has secret" msgstr "エスクローされたパスワード" -#: accounts/serializers/account/account.py:75 applications/models.py:11 +#: accounts/serializers/account/account.py:77 applications/models.py:11 #: assets/models/label.py:21 assets/models/platform.py:75 #: assets/serializers/asset/common.py:119 assets/serializers/cagegory.py:8 #: assets/serializers/platform.py:93 assets/serializers/platform.py:132 @@ -535,7 +531,7 @@ msgstr "エスクローされたパスワード" msgid "Category" msgstr "カテゴリ" -#: accounts/serializers/account/account.py:76 +#: accounts/serializers/account/account.py:78 #: accounts/serializers/automations/base.py:43 acls/models/command_acl.py:24 #: acls/serializers/command_acl.py:18 applications/models.py:14 #: assets/models/_user.py:50 assets/models/automations/base.py:20 @@ -546,15 +542,15 @@ msgstr "カテゴリ" #: perms/serializers/user_permission.py:26 terminal/models/applet/applet.py:30 #: terminal/models/component/storage.py:57 #: terminal/models/component/storage.py:146 terminal/serializers/applet.py:28 -#: terminal/serializers/session.py:26 terminal/serializers/storage.py:181 -#: tickets/models/comment.py:26 tickets/models/flow.py:56 -#: tickets/models/ticket/apply_application.py:16 +#: terminal/serializers/session.py:26 terminal/serializers/storage.py:224 +#: terminal/serializers/storage.py:236 tickets/models/comment.py:26 +#: tickets/models/flow.py:56 tickets/models/ticket/apply_application.py:16 #: tickets/models/ticket/general.py:275 tickets/serializers/flow.py:53 #: tickets/serializers/ticket/ticket.py:19 msgid "Type" msgstr "タイプ" -#: accounts/serializers/account/account.py:91 +#: accounts/serializers/account/account.py:93 msgid "Asset not found" msgstr "資産が存在しません" @@ -584,7 +580,7 @@ msgid "Key password" msgstr "キーパスワード" #: accounts/serializers/account/base.py:79 -#: assets/serializers/asset/common.py:287 +#: assets/serializers/asset/common.py:283 msgid "Spec info" msgstr "特別情報" @@ -604,7 +600,7 @@ msgid "Nodes" msgstr "ノード" #: accounts/serializers/automations/base.py:42 -#: assets/models/automations/base.py:113 +#: assets/models/automations/base.py:117 #: assets/serializers/automations/base.py:39 msgid "Automation snapshot" msgstr "自動スナップショット" @@ -622,12 +618,12 @@ msgid "* Password length range 6-30 bits" msgstr "* パスワードの長さの範囲6-30ビット" #: accounts/serializers/automations/change_secret.py:110 -#: assets/models/automations/base.py:122 +#: assets/models/automations/base.py:126 msgid "Automation task execution" msgstr "自動タスク実行履歴" #: accounts/serializers/automations/change_secret.py:150 audits/const.py:52 -#: audits/models.py:42 audits/signal_handlers/activity_log.py:120 +#: audits/models.py:42 audits/signal_handlers/activity_log.py:118 #: common/const/choices.py:18 ops/const.py:56 ops/serializers/celery.py:39 #: terminal/const.py:59 terminal/models/session/sharing.py:103 #: tickets/views/approve.py:114 @@ -635,32 +631,32 @@ msgid "Success" msgstr "成功" #: accounts/serializers/automations/change_secret.py:151 audits/const.py:53 -#: audits/signal_handlers/activity_log.py:120 common/const/choices.py:19 +#: audits/signal_handlers/activity_log.py:118 common/const/choices.py:19 #: ops/const.py:58 terminal/const.py:60 xpack/plugins/cloud/const.py:41 msgid "Failed" msgstr "失敗しました" -#: accounts/tasks/automation.py:11 +#: accounts/tasks/automation.py:16 msgid "Account execute automation" msgstr "アカウント実行の自動化" -#: accounts/tasks/backup_account.py:12 +#: accounts/tasks/backup_account.py:24 msgid "Execute account backup plan" msgstr "アカウントのバックアップ計画を実施する" -#: accounts/tasks/gather_accounts.py:31 +#: accounts/tasks/gather_accounts.py:34 msgid "Gather assets accounts" msgstr "資産の口座番号を収集する" -#: accounts/tasks/push_account.py:30 accounts/tasks/push_account.py:36 +#: accounts/tasks/push_account.py:30 accounts/tasks/push_account.py:37 msgid "Push accounts to assets" msgstr "アカウントをアセットにプッシュ:" -#: accounts/tasks/verify_account.py:41 +#: accounts/tasks/verify_account.py:42 msgid "Verify asset account availability" msgstr "アセット アカウントの可用性を確認する" -#: accounts/tasks/verify_account.py:47 +#: accounts/tasks/verify_account.py:50 msgid "Verify accounts connectivity" msgstr "アカウント接続のテスト" @@ -724,7 +720,7 @@ msgstr "アクティブ" #: acls/models/base.py:98 acls/models/login_acl.py:13 #: acls/serializers/base.py:55 acls/serializers/login_acl.py:21 #: assets/models/cmd_filter.py:24 assets/models/label.py:16 audits/models.py:32 -#: audits/models.py:51 audits/models.py:127 +#: audits/models.py:51 audits/models.py:129 #: authentication/models/connection_token.py:29 #: authentication/models/sso_token.py:16 #: notifications/models/notification.py:12 @@ -911,25 +907,25 @@ msgstr "" "デフォルトポートは9000で、HTTPインタフェースとネイティブインタフェースは異な" "るポートを使用する" -#: assets/api/asset/asset.py:136 +#: assets/api/asset/asset.py:145 msgid "Cannot create asset directly, you should create a host or other" msgstr "" "資産を直接作成することはできません。ホストまたはその他を作成する必要がありま" "す" -#: assets/api/domain.py:57 +#: assets/api/domain.py:61 msgid "Number required" msgstr "必要な数" -#: assets/api/node.py:58 +#: assets/api/node.py:57 msgid "You can't update the root node name" msgstr "ルートノード名を更新できません" -#: assets/api/node.py:65 +#: assets/api/node.py:64 msgid "You can't delete the root node ({})" msgstr "ルートノード ({}) を削除できません。" -#: assets/api/node.py:68 +#: assets/api/node.py:67 msgid "Deletion failed and the node contains assets" msgstr "削除に失敗し、ノードにアセットが含まれています。" @@ -962,7 +958,8 @@ msgid "Connect failed" msgstr "接続に失敗しました" #: assets/const/automation.py:6 audits/const.py:6 audits/const.py:35 -#: audits/signal_handlers/activity_log.py:92 common/utils/ip/geoip/utils.py:31 +#: audits/signal_handlers/activity_log.py:88 +#: audits/signal_handlers/activity_log.py:147 common/utils/ip/geoip/utils.py:31 #: common/utils/ip/geoip/utils.py:37 common/utils/ip/utils.py:84 msgid "Unknown" msgstr "不明" @@ -1058,18 +1055,18 @@ msgstr "SSHパブリックキー" #: assets/models/_user.py:27 assets/models/cmd_filter.py:40 #: assets/models/cmd_filter.py:88 assets/models/group.py:23 #: assets/models/platform.py:79 common/db/models.py:37 ops/models/adhoc.py:27 -#: ops/models/job.py:42 ops/models/playbook.py:25 rbac/models/role.py:37 +#: ops/models/job.py:42 ops/models/playbook.py:26 rbac/models/role.py:37 #: settings/models.py:38 terminal/models/applet/applet.py:35 #: terminal/models/applet/applet.py:151 terminal/models/applet/host.py:110 #: terminal/models/component/endpoint.py:24 #: terminal/models/component/endpoint.py:100 #: terminal/models/session/session.py:46 tickets/models/comment.py:32 #: tickets/models/ticket/general.py:297 users/models/user.py:756 -#: xpack/plugins/cloud/models.py:35 xpack/plugins/cloud/models.py:119 +#: xpack/plugins/cloud/models.py:35 xpack/plugins/cloud/models.py:111 msgid "Comment" msgstr "コメント" -#: assets/models/_user.py:28 assets/models/automations/base.py:109 +#: assets/models/_user.py:28 assets/models/automations/base.py:113 #: assets/models/cmd_filter.py:41 assets/models/group.py:22 #: common/db/models.py:35 ops/models/base.py:54 ops/models/job.py:115 #: users/models/user.py:943 @@ -1166,7 +1163,7 @@ msgstr "アドレス" #: assets/models/asset/common.py:109 assets/models/platform.py:111 #: authentication/serializers/connect_token_secret.py:108 #: perms/serializers/user_permission.py:23 -#: xpack/plugins/cloud/serializers/account_attrs.py:179 +#: xpack/plugins/cloud/serializers/account_attrs.py:187 msgid "Platform" msgstr "プラットフォーム" @@ -1180,35 +1177,35 @@ msgstr "ドメイン" msgid "Labels" msgstr "ラベル" -#: assets/models/asset/common.py:285 +#: assets/models/asset/common.py:287 msgid "Can refresh asset hardware info" msgstr "資産ハードウェア情報を更新できます" -#: assets/models/asset/common.py:286 +#: assets/models/asset/common.py:288 msgid "Can test asset connectivity" msgstr "資産接続をテストできます" -#: assets/models/asset/common.py:287 +#: assets/models/asset/common.py:289 msgid "Can push account to asset" msgstr "アカウントをアセットにプッシュできます" -#: assets/models/asset/common.py:288 +#: assets/models/asset/common.py:290 msgid "Can verify account" msgstr "アカウントを確認できます" -#: assets/models/asset/common.py:289 +#: assets/models/asset/common.py:291 msgid "Can match asset" msgstr "アセットを一致させることができます" -#: assets/models/asset/common.py:290 +#: assets/models/asset/common.py:292 msgid "Add asset to node" msgstr "ノードにアセットを追加する" -#: assets/models/asset/common.py:291 +#: assets/models/asset/common.py:293 msgid "Move asset to node" msgstr "アセットをノードに移動する" -#: assets/models/asset/common.py:292 +#: assets/models/asset/common.py:294 msgid "Remove asset from node" msgstr "ノードからアセットを削除" @@ -1253,26 +1250,26 @@ msgid "Submit selector" msgstr "ボタンセレクターを確認する" #: assets/models/automations/base.py:17 assets/models/cmd_filter.py:38 -#: assets/serializers/asset/common.py:286 rbac/tree.py:36 +#: assets/serializers/asset/common.py:282 rbac/tree.py:36 msgid "Accounts" msgstr "アカウント" -#: assets/models/automations/base.py:28 assets/models/automations/base.py:106 +#: assets/models/automations/base.py:28 assets/models/automations/base.py:110 msgid "Automation task" msgstr "自動化されたタスク" -#: assets/models/automations/base.py:99 +#: assets/models/automations/base.py:103 msgid "Asset automation task" msgstr "アセットの自動化タスク" -#: assets/models/automations/base.py:108 audits/models.py:163 +#: assets/models/automations/base.py:112 audits/models.py:165 #: audits/serializers.py:50 ops/models/base.py:49 ops/models/job.py:108 #: terminal/models/applet/applet.py:150 terminal/models/applet/host.py:107 #: terminal/models/component/status.py:27 terminal/serializers/applet.py:17 #: terminal/serializers/applet_host.py:93 tickets/models/ticket/general.py:283 #: tickets/serializers/super_ticket.py:13 -#: tickets/serializers/ticket/ticket.py:20 xpack/plugins/cloud/models.py:172 -#: xpack/plugins/cloud/models.py:224 +#: tickets/serializers/ticket/ticket.py:20 xpack/plugins/cloud/models.py:164 +#: xpack/plugins/cloud/models.py:216 msgid "Status" msgstr "ステータス" @@ -1491,8 +1488,7 @@ msgstr "自動充填" #: assets/serializers/asset/common.py:122 assets/serializers/platform.py:95 #: authentication/serializers/connect_token_secret.py:28 #: authentication/serializers/connect_token_secret.py:66 -#: perms/serializers/user_permission.py:24 xpack/plugins/cloud/models.py:107 -#: xpack/plugins/cloud/serializers/task.py:38 +#: perms/serializers/user_permission.py:24 xpack/plugins/cloud/models.py:99 msgid "Protocols" msgstr "プロトコル" @@ -1512,13 +1508,15 @@ msgstr "ポート番号が範囲外です (1-65535)" msgid "Protocol is required: {}" msgstr "プロトコルが必要です: {}" -#: assets/serializers/asset/common.py:288 +#: assets/serializers/asset/common.py:284 msgid "Auto info" msgstr "自動情報" -#: assets/serializers/asset/database.py:24 common/serializers/fields.py:100 +#: assets/serializers/asset/database.py:25 common/serializers/fields.py:100 #: tickets/serializers/ticket/common.py:58 #: xpack/plugins/cloud/serializers/account_attrs.py:56 +#: xpack/plugins/cloud/serializers/account_attrs.py:79 +#: xpack/plugins/cloud/serializers/account_attrs.py:143 msgid "This field is required." msgstr "このフィールドは必須です。" @@ -1608,10 +1606,8 @@ msgid "SFTP home" msgstr "SFTP ルート パス" #: assets/serializers/platform.py:42 -#, fuzzy -#| msgid "Input username" msgid "Auth with username" -msgstr "カスタム ユーザー名" +msgstr "ユーザー名で認証する" #: assets/serializers/platform.py:70 msgid "Gather accounts enabled" @@ -1629,32 +1625,27 @@ msgstr "主要" msgid "Default Domain" msgstr "デフォルト ドメイン" -#: assets/signal_handlers/asset.py:25 assets/tasks/ping.py:24 -#: assets/tasks/ping.py:34 +#: assets/signal_handlers/asset.py:26 assets/tasks/ping.py:35 msgid "Test assets connectivity " msgstr "アセット接続のテスト。" -#: assets/signal_handlers/asset.py:34 -#, fuzzy -#| msgid "Update assets hardware info: " +#: assets/signal_handlers/asset.py:35 msgid "Gather asset hardware info" -msgstr "資産のハードウェア情報を更新する:" +msgstr "資産ハードウェア情報の収集" -#: assets/tasks/automation.py:11 +#: assets/tasks/automation.py:24 msgid "Asset execute automation" msgstr "アセット実行の自動化" -#: assets/tasks/gather_facts.py:21 assets/tasks/gather_facts.py:25 -#, fuzzy -#| msgid "Gather asset facts" +#: assets/tasks/gather_facts.py:21 assets/tasks/gather_facts.py:27 msgid "Gather assets facts" msgstr "資産情報の収集" -#: assets/tasks/gather_facts.py:47 +#: assets/tasks/gather_facts.py:39 msgid "Update assets hardware info: " msgstr "資産のハードウェア情報を更新する:" -#: assets/tasks/gather_facts.py:54 +#: assets/tasks/gather_facts.py:47 msgid "Update node asset hardware information: " msgstr "ノード資産のハードウェア情報を更新します。" @@ -1669,19 +1660,22 @@ msgstr "" "セルフチェックのタスクはすでに実行されており、繰り返し開始することはできませ" "ん" -#: assets/tasks/nodes_amount.py:34 +#: assets/tasks/nodes_amount.py:33 msgid "Periodic check the amount of assets under the node" msgstr "ノードの下にあるアセットの数を定期的に確認する" -#: assets/tasks/ping.py:41 +#: assets/tasks/ping.py:20 assets/tasks/ping.py:26 +msgid "Test assets connectivity" +msgstr "アセット接続のテスト。" + +#: assets/tasks/ping.py:42 msgid "Test if the assets under the node are connectable " msgstr "ノード配下のアセットが接続できるかテストする" -#: assets/tasks/ping_gateway.py:23 assets/tasks/ping_gateway.py:33 -#, fuzzy -#| msgid "Test assets connectivity " -msgid "Test gateways connectivity " -msgstr "アセット接続のテスト。" +#: assets/tasks/ping_gateway.py:19 assets/tasks/ping_gateway.py:26 +#: assets/tasks/ping_gateway.py:37 +msgid "Test gateways connectivity" +msgstr "ゲートウェイ接続のテスト。" #: assets/tasks/utils.py:17 msgid "Asset has been disabled, skipped: {}" @@ -1781,18 +1775,14 @@ msgid "Operate log" msgstr "ログの操作" #: audits/const.py:40 -#, fuzzy -#| msgid "Session" msgid "Session log" -msgstr "セッション" +msgstr "セッションログ" #: audits/const.py:41 -#, fuzzy -#| msgid "Login acl" msgid "Login log" -msgstr "ログインacl" +msgstr "ログインログ" -#: audits/const.py:42 ops/signal_handlers.py:74 +#: audits/const.py:42 ops/signal_handlers.py:86 #: terminal/models/applet/host.py:111 terminal/models/component/task.py:24 msgid "Task" msgstr "タスク" @@ -1809,7 +1799,7 @@ msgstr "是" msgid "No" msgstr "否" -#: audits/models.py:34 audits/models.py:61 audits/models.py:130 +#: audits/models.py:34 audits/models.py:61 audits/models.py:132 #: terminal/models/session/session.py:38 terminal/models/session/sharing.py:95 msgid "Remote addr" msgstr "リモートaddr" @@ -1834,71 +1824,69 @@ msgstr "リソースタイプ" msgid "Resource" msgstr "リソース" -#: audits/models.py:62 audits/models.py:108 audits/models.py:132 +#: audits/models.py:62 audits/models.py:108 audits/models.py:134 #: terminal/serializers/command.py:43 msgid "Datetime" msgstr "時間" #: audits/models.py:101 -#, fuzzy -#| msgid "Active" msgid "Activity type" -msgstr "アクティブ" +msgstr "活動の種類" -#: audits/models.py:110 +#: audits/models.py:111 msgid "Detail" msgstr "詳細" -#: audits/models.py:112 +#: audits/models.py:114 msgid "Detail ID" msgstr "詳細 ID" -#: audits/models.py:116 +#: audits/models.py:118 msgid "Activity log" msgstr "活動記録" -#: audits/models.py:128 +#: audits/models.py:130 msgid "Change by" msgstr "による変更" -#: audits/models.py:138 +#: audits/models.py:140 msgid "Password change log" msgstr "パスワード変更ログ" -#: audits/models.py:145 +#: audits/models.py:147 msgid "Login type" msgstr "ログインタイプ" -#: audits/models.py:147 tickets/models/ticket/login_confirm.py:10 +#: audits/models.py:149 tickets/models/ticket/login_confirm.py:10 msgid "Login ip" msgstr "ログインIP" -#: audits/models.py:149 +#: audits/models.py:151 #: authentication/templates/authentication/_msg_different_city.html:11 #: tickets/models/ticket/login_confirm.py:11 msgid "Login city" msgstr "ログイン都市" -#: audits/models.py:152 audits/serializers.py:64 +#: audits/models.py:154 audits/serializers.py:64 msgid "User agent" msgstr "ユーザーエージェント" -#: audits/models.py:155 audits/serializers.py:48 +#: audits/models.py:157 audits/serializers.py:48 #: authentication/templates/authentication/_mfa_confirm_modal.html:14 #: users/forms/profile.py:65 users/models/user.py:740 #: users/serializers/profile.py:124 msgid "MFA" msgstr "MFA" -#: audits/models.py:165 +#: audits/models.py:167 msgid "Date login" msgstr "日付ログイン" -#: audits/models.py:167 audits/serializers.py:66 +#: audits/models.py:169 audits/serializers.py:66 msgid "Authentication backend" msgstr "認証バックエンド" -#: audits/models.py:211 +#: audits/models.py:213 msgid "User login log" msgstr "ユーザーログインログ" @@ -1906,28 +1894,25 @@ msgstr "ユーザーログインログ" msgid "Reason display" msgstr "理由表示" -#: audits/serializers.py:123 -#, fuzzy -#| msgid "User {} {} this resource." -msgid "User {} {} this resource" -msgstr "ユーザー {} {} が現在のリソースをサブスクライブしました。" - -#: audits/signal_handlers/activity_log.py:113 -#, fuzzy, python-format -#| msgid "Push accounts to assets" -msgid "User %s use account %s login asset %s" -msgstr "アカウントをアセットにプッシュ:" - -#: audits/signal_handlers/activity_log.py:121 -#, fuzzy, python-format -#| msgid "User [{}] login this system.[{}]" -msgid "User %s login system %s" -msgstr "ユーザー {} がサービスにログインしました。[{}]" - -#: audits/signal_handlers/activity_log.py:145 +#: audits/serializers.py:124 #, python-format -msgid "User %s perform a task (%s) for this resource" -msgstr "" +msgid "User %s %s this resource" +msgstr "ユーザー %s %s が現在のリソースをサブスクライブしました。" + +#: audits/signal_handlers/activity_log.py:111 +#, python-format +msgid "User %s use account %s login asset %s" +msgstr "ユーザー %s はアカウント %s を使用してプロパティ %s にログインします" + +#: audits/signal_handlers/activity_log.py:119 +#, python-format +msgid "User %s login system %s" +msgstr "ユーザー %s はシステム %s にログインしています" + +#: audits/signal_handlers/activity_log.py:149 +#, python-format +msgid "User %s perform a task for this resource: %s" +msgstr "ユーザー %s が現在のリソースでタスク (%s) を実行しました" #: audits/signal_handlers/login_log.py:27 msgid "SSH Key" @@ -1965,27 +1950,31 @@ msgstr "DingTalk" msgid "Temporary token" msgstr "仮パスワード" -#: audits/tasks.py:44 +#: audits/tasks.py:52 msgid "Clean audits log" msgstr "監査ログのクリーンアップ" +#: audits/tasks.py:92 +msgid "Clean audits session task log" +msgstr "監査セッション タスク ログのクリーンアップ" + #: authentication/api/confirm.py:40 msgid "This action require verify your MFA" msgstr "この操作には、MFAを検証する必要があります" -#: authentication/api/connection_token.py:269 +#: authentication/api/connection_token.py:268 msgid "Account not found" msgstr "アカウントが見つかりません" -#: authentication/api/connection_token.py:272 +#: authentication/api/connection_token.py:271 msgid "Permission expired" msgstr "承認の有効期限が切れています" -#: authentication/api/connection_token.py:284 +#: authentication/api/connection_token.py:283 msgid "ACL action is reject" msgstr "ACL アクションは拒否です" -#: authentication/api/connection_token.py:288 +#: authentication/api/connection_token.py:287 msgid "ACL action is review" msgstr "ACL アクションはレビューです" @@ -2518,7 +2507,7 @@ msgstr "{} 空にしてはならない" msgid "Is valid" msgstr "有効です" -#: authentication/tasks.py:12 +#: authentication/tasks.py:11 msgid "Clean expired session" msgstr "期限切れのセッションをクリアする" @@ -3100,11 +3089,11 @@ msgstr "間違ったデータ タイプです。リストにする必要があ msgid "Invalid choice: {}" msgstr "無効なオプション: {}" -#: common/tasks.py:13 common/utils/verify_code.py:16 +#: common/tasks.py:20 common/utils/verify_code.py:16 msgid "Send email" msgstr "メールを送る" -#: common/tasks.py:40 +#: common/tasks.py:47 msgid "Send email attachment" msgstr "メールの添付ファイルを送信" @@ -3354,7 +3343,7 @@ msgid "Args" msgstr "アルグ" #: ops/models/adhoc.py:26 ops/models/base.py:16 ops/models/base.py:53 -#: ops/models/job.py:35 ops/models/job.py:114 ops/models/playbook.py:24 +#: ops/models/job.py:35 ops/models/job.py:114 ops/models/playbook.py:25 #: terminal/models/session/sharing.py:23 msgid "Creator" msgstr "作成者" @@ -3372,7 +3361,7 @@ msgid "Date last run" msgstr "最終実行日" #: ops/models/base.py:51 ops/models/job.py:112 -#: xpack/plugins/cloud/models.py:170 +#: xpack/plugins/cloud/models.py:162 msgid "Result" msgstr "結果" @@ -3464,11 +3453,11 @@ msgstr "ジョブ実行" msgid "Job audit log" msgstr "ジョブ監査ログ" -#: ops/models/playbook.py:27 +#: ops/models/playbook.py:28 msgid "CreateMethod" msgstr "创建方式" -#: ops/models/playbook.py:28 +#: ops/models/playbook.py:29 msgid "VCS URL" msgstr "" @@ -3516,22 +3505,14 @@ msgstr "終了しました" msgid "Time cost" msgstr "時を過ごす" -#: ops/tasks.py:27 +#: ops/tasks.py:32 msgid "Run ansible task" msgstr "Ansible タスクを実行する" -#: ops/tasks.py:44 +#: ops/tasks.py:61 msgid "Run ansible task execution" msgstr "Ansible タスクの実行を開始する" -#: ops/tasks.py:58 -msgid "Periodic clear celery tasks" -msgstr "定期的にCeleryタスクをクリア" - -#: ops/tasks.py:60 -msgid "Clean celery log period" -msgstr "きれいなセロリログ期間" - #: ops/tasks.py:77 msgid "Clear celery periodic tasks" msgstr "タスクログを定期的にクリアする" @@ -3714,11 +3695,11 @@ msgstr "資産権限の有効期限が近づいています" msgid "asset permissions of organization {}" msgstr "組織 {} の資産権限" -#: perms/tasks.py:28 +#: perms/tasks.py:27 msgid "Check asset permission expired" msgstr "アセット認証ルールの有効期限が切れていることを確認する" -#: perms/tasks.py:40 +#: perms/tasks.py:39 msgid "Send asset permission expired notification" msgstr "アセット許可の有効期限通知を送信する" @@ -4423,7 +4404,7 @@ msgid "SSO auth key TTL" msgstr "Token有効期間" #: settings/serializers/auth/sso.py:17 -#: xpack/plugins/cloud/serializers/account_attrs.py:176 +#: xpack/plugins/cloud/serializers/account_attrs.py:184 msgid "Unit: second" msgstr "単位: 秒" @@ -5617,10 +5598,8 @@ msgid "Can download session replay" msgstr "セッション再生をダウンロードできます" #: terminal/models/session/session.py:34 -#, fuzzy -#| msgid "Account " msgid "Account id" -msgstr "アカウント" +msgstr "アカウント ID" #: terminal/models/session/session.py:36 terminal/models/session/sharing.py:100 msgid "Login from" @@ -5847,7 +5826,7 @@ msgstr "アクセスキー" msgid "Access key secret" msgstr "アクセスキーシークレット" -#: terminal/serializers/storage.py:65 xpack/plugins/cloud/models.py:217 +#: terminal/serializers/storage.py:65 xpack/plugins/cloud/models.py:209 msgid "Region" msgstr "リージョン" @@ -5899,27 +5878,23 @@ msgstr "証明書の検証を無視する" msgid "Not found" msgstr "見つかりません" -#: terminal/tasks.py:31 +#: terminal/tasks.py:28 msgid "Periodic delete terminal status" msgstr "端末の状態を定期的にクリーンアップする" -#: terminal/tasks.py:40 +#: terminal/tasks.py:37 msgid "Clean orphan session" msgstr "孤立したセッションをクリアする" -#: terminal/tasks.py:59 -msgid "Periodic clean expired session" -msgstr "期限切れのセッションを定期的にクリーンアップする" - -#: terminal/tasks.py:85 +#: terminal/tasks.py:56 msgid "Upload session replay to external storage" msgstr "セッションの記録を外部ストレージにアップロードする" -#: terminal/tasks.py:112 +#: terminal/tasks.py:83 msgid "Run applet host deployment" msgstr "アプリケーション マシンの展開を実行する" -#: terminal/tasks.py:119 +#: terminal/tasks.py:90 msgid "Install applet" msgstr "アプリをインストールする" @@ -6990,55 +6965,47 @@ msgstr "リージョン" msgid "Hostname strategy" msgstr "ホスト名戦略" -#: xpack/plugins/cloud/models.py:100 -msgid "Unix admin user" -msgstr "Unix adminユーザー" - -#: xpack/plugins/cloud/models.py:104 -msgid "Windows admin user" -msgstr "Windows管理者" - -#: xpack/plugins/cloud/models.py:110 xpack/plugins/cloud/serializers/task.py:41 +#: xpack/plugins/cloud/models.py:102 xpack/plugins/cloud/serializers/task.py:40 msgid "IP network segment group" msgstr "IPネットワークセグメントグループ" -#: xpack/plugins/cloud/models.py:113 xpack/plugins/cloud/serializers/task.py:46 +#: xpack/plugins/cloud/models.py:105 xpack/plugins/cloud/serializers/task.py:45 msgid "Sync IP type" msgstr "同期IPタイプ" -#: xpack/plugins/cloud/models.py:116 xpack/plugins/cloud/serializers/task.py:64 +#: xpack/plugins/cloud/models.py:108 xpack/plugins/cloud/serializers/task.py:62 msgid "Always update" msgstr "常に更新" -#: xpack/plugins/cloud/models.py:122 +#: xpack/plugins/cloud/models.py:114 msgid "Date last sync" msgstr "最終同期日" -#: xpack/plugins/cloud/models.py:127 xpack/plugins/cloud/models.py:168 +#: xpack/plugins/cloud/models.py:119 xpack/plugins/cloud/models.py:160 msgid "Sync instance task" msgstr "インスタンスの同期タスク" -#: xpack/plugins/cloud/models.py:179 xpack/plugins/cloud/models.py:227 +#: xpack/plugins/cloud/models.py:171 xpack/plugins/cloud/models.py:219 msgid "Date sync" msgstr "日付の同期" -#: xpack/plugins/cloud/models.py:183 +#: xpack/plugins/cloud/models.py:175 msgid "Sync instance task execution" msgstr "インスタンスタスクの同期実行" -#: xpack/plugins/cloud/models.py:207 +#: xpack/plugins/cloud/models.py:199 msgid "Sync task" msgstr "同期タスク" -#: xpack/plugins/cloud/models.py:211 +#: xpack/plugins/cloud/models.py:203 msgid "Sync instance task history" msgstr "インスタンスタスク履歴の同期" -#: xpack/plugins/cloud/models.py:214 +#: xpack/plugins/cloud/models.py:206 msgid "Instance" msgstr "インスタンス" -#: xpack/plugins/cloud/models.py:231 +#: xpack/plugins/cloud/models.py:223 msgid "Sync instance detail" msgstr "同期インスタンスの詳細" @@ -7252,52 +7219,52 @@ msgstr "テナントID" msgid "Subscription ID" msgstr "サブスクリプションID" -#: xpack/plugins/cloud/serializers/account_attrs.py:95 -#: xpack/plugins/cloud/serializers/account_attrs.py:100 -#: xpack/plugins/cloud/serializers/account_attrs.py:116 -#: xpack/plugins/cloud/serializers/account_attrs.py:141 +#: xpack/plugins/cloud/serializers/account_attrs.py:98 +#: xpack/plugins/cloud/serializers/account_attrs.py:103 +#: xpack/plugins/cloud/serializers/account_attrs.py:119 +#: xpack/plugins/cloud/serializers/account_attrs.py:149 msgid "API Endpoint" msgstr "APIエンドポイント" -#: xpack/plugins/cloud/serializers/account_attrs.py:106 +#: xpack/plugins/cloud/serializers/account_attrs.py:109 msgid "Auth url" msgstr "認証アドレス" -#: xpack/plugins/cloud/serializers/account_attrs.py:107 +#: xpack/plugins/cloud/serializers/account_attrs.py:110 msgid "eg: http://openstack.example.com:5000/v3" msgstr "例えば: http://openstack.example.com:5000/v3" -#: xpack/plugins/cloud/serializers/account_attrs.py:110 +#: xpack/plugins/cloud/serializers/account_attrs.py:113 msgid "User domain" msgstr "ユーザードメイン" -#: xpack/plugins/cloud/serializers/account_attrs.py:117 +#: xpack/plugins/cloud/serializers/account_attrs.py:120 msgid "Cert File" msgstr "証明書ファイル" -#: xpack/plugins/cloud/serializers/account_attrs.py:118 +#: xpack/plugins/cloud/serializers/account_attrs.py:121 msgid "Key File" msgstr "キーファイル" -#: xpack/plugins/cloud/serializers/account_attrs.py:134 +#: xpack/plugins/cloud/serializers/account_attrs.py:137 msgid "Service account key" msgstr "サービスアカウントキー" -#: xpack/plugins/cloud/serializers/account_attrs.py:135 +#: xpack/plugins/cloud/serializers/account_attrs.py:138 msgid "The file is in JSON format" msgstr "ファイルはJSON形式です。" -#: xpack/plugins/cloud/serializers/account_attrs.py:148 +#: xpack/plugins/cloud/serializers/account_attrs.py:156 msgid "IP address invalid `{}`, {}" msgstr "IPアドレスが無効: '{}', {}" -#: xpack/plugins/cloud/serializers/account_attrs.py:154 +#: xpack/plugins/cloud/serializers/account_attrs.py:162 msgid "" "Format for comma-delimited string,Such as: 192.168.1.0/24, " "10.0.0.0-10.0.0.255" msgstr "形式はコンマ区切りの文字列です,例:192.168.1.0/24,10.0.0.0-10.0.0.255" -#: xpack/plugins/cloud/serializers/account_attrs.py:158 +#: xpack/plugins/cloud/serializers/account_attrs.py:166 msgid "" "The port is used to detect the validity of the IP address. When the " "synchronization task is executed, only the valid IP address will be " @@ -7307,19 +7274,19 @@ msgstr "" "実行されると、有効な IP アドレスのみが同期されます。
ポートが0の場合、す" "べてのIPアドレスが有効です。" -#: xpack/plugins/cloud/serializers/account_attrs.py:166 +#: xpack/plugins/cloud/serializers/account_attrs.py:174 msgid "Hostname prefix" msgstr "ホスト名プレフィックス" -#: xpack/plugins/cloud/serializers/account_attrs.py:169 +#: xpack/plugins/cloud/serializers/account_attrs.py:177 msgid "IP segment" msgstr "IP セグメント" -#: xpack/plugins/cloud/serializers/account_attrs.py:173 +#: xpack/plugins/cloud/serializers/account_attrs.py:181 msgid "Test port" msgstr "テストポート" -#: xpack/plugins/cloud/serializers/account_attrs.py:176 +#: xpack/plugins/cloud/serializers/account_attrs.py:184 msgid "Test timeout" msgstr "テストタイムアウト" @@ -7345,9 +7312,9 @@ msgstr "実行回数" msgid "Instance count" msgstr "インスタンス数" -#: xpack/plugins/cloud/serializers/task.py:63 -msgid "Linux admin user" -msgstr "Linux管理者" +#: xpack/plugins/cloud/tasks.py:27 +msgid "Run sync instance task" +msgstr "同期インスタンス タスクを実行する" #: xpack/plugins/cloud/utils.py:69 msgid "Account unavailable" @@ -7416,39 +7383,3 @@ msgstr "究極のエディション" #: xpack/plugins/license/models.py:85 msgid "Community edition" msgstr "コミュニティ版" - -#~ msgid "AdHoc" -#~ msgstr "タスクの各バージョン" - -#~ msgid "Terminal ID" -#~ msgstr "ターミナル ID" - -#~ msgid "{} used account[{}], login method[{}] login the asset." -#~ msgstr "" -#~ "{} トムはアカウント[{}]、ログイン方法[{}]を使ってこの資産を登録しました" - -#, fuzzy -#~| msgid "Hello" -#~ msgid "Hello {}" -#~ msgstr "こんにちは" - -#~ msgid "User {} has executed change auth plan for this account.({})" -#~ msgstr "ユーザー {} はこのアカウントのために改密計画を実行しました。({})" - -#~ msgid "User {} login into this service.[{}]" -#~ msgstr "ユーザー {} がサービスにログインしました。[{}]" - -#~ msgid "Update some assets hardware info. " -#~ msgstr "一部の資産ハードウェア情報を更新します。" - -#~ msgid "Manually update the hardware information of assets" -#~ msgstr "アセット情報を手動で更新する" - -#~ msgid "Manually update the hardware information of assets under a node" -#~ msgstr "ノードの下の資産情報を手動で更新する" - -#~ msgid "Manually test the connectivity of a asset" -#~ msgstr "アセットの接続を手動でテストする" - -#~ msgid "Manually test the connectivity of assets under a node" -#~ msgstr "ノードの下のアセットの接続を手動でテストする" diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index 6c54f5efe..70af7fd7f 100644 --- a/apps/locale/zh/LC_MESSAGES/django.mo +++ b/apps/locale/zh/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:910ef049b67560a279f8e0e702d74c1343f36c53d95ef84a32782c08c92a184a -size 111866 +oid sha256:8109162896c38e80e2a22895cd42e48b174e7b44897d7ea34c4c19f8eb865e81 +size 112043 diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 17d4dc406..476a01b37 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: JumpServer 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-02-16 15:25+0800\n" +"POT-Creation-Date: 2023-02-17 16:56+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -158,23 +158,23 @@ msgid "Only create" msgstr "仅创建" #: accounts/models/account.py:47 accounts/models/gathered_account.py:14 -#: accounts/serializers/account/account.py:95 +#: accounts/serializers/account/account.py:97 #: accounts/serializers/account/gathered_account.py:10 #: accounts/serializers/automations/change_secret.py:107 #: accounts/serializers/automations/change_secret.py:127 #: acls/models/base.py:100 acls/serializers/base.py:56 -#: assets/models/asset/common.py:97 assets/models/asset/common.py:282 +#: assets/models/asset/common.py:97 assets/models/asset/common.py:284 #: assets/models/cmd_filter.py:36 assets/serializers/domain.py:19 #: assets/serializers/label.py:27 audits/models.py:36 #: authentication/models/connection_token.py:33 #: perms/models/asset_permission.py:64 perms/serializers/permission.py:27 #: terminal/backends/command/models.py:21 terminal/models/session/session.py:31 #: terminal/notifications.py:95 terminal/serializers/command.py:16 -#: tickets/models/ticket/apply_asset.py:16 xpack/plugins/cloud/models.py:220 +#: tickets/models/ticket/apply_asset.py:16 xpack/plugins/cloud/models.py:212 msgid "Asset" msgstr "资产" -#: accounts/models/account.py:51 accounts/serializers/account/account.py:99 +#: accounts/models/account.py:51 accounts/serializers/account/account.py:101 #: authentication/serializers/connect_token_secret.py:50 msgid "Su from" msgstr "切换自" @@ -184,7 +184,7 @@ msgstr "切换自" msgid "Version" msgstr "版本" -#: accounts/models/account.py:55 accounts/serializers/account/account.py:96 +#: accounts/models/account.py:55 accounts/serializers/account/account.py:98 #: users/models/user.py:768 msgid "Source" msgstr "来源" @@ -206,43 +206,39 @@ msgid "Can view asset account secret" msgstr "可以查看资产账号密码" #: accounts/models/account.py:65 -msgid "Can change asset account secret" -msgstr "可以更改资产账号密码" - -#: accounts/models/account.py:66 msgid "Can view asset history account" msgstr "可以查看资产历史账号" -#: accounts/models/account.py:67 +#: accounts/models/account.py:66 msgid "Can view asset history account secret" msgstr "可以查看资产历史账号密码" -#: accounts/models/account.py:104 +#: accounts/models/account.py:111 msgid "Account template" msgstr "账号模版" -#: accounts/models/account.py:109 +#: accounts/models/account.py:116 msgid "Can view asset account template secret" msgstr "可以查看资产账号模版密码" -#: accounts/models/account.py:110 +#: accounts/models/account.py:117 msgid "Can change asset account template secret" msgstr "可以更改资产账号模版密码" -#: accounts/models/automations/backup_account.py:25 +#: accounts/models/automations/backup_account.py:27 #: accounts/models/automations/change_secret.py:47 #: accounts/serializers/account/backup.py:32 #: accounts/serializers/automations/change_secret.py:56 msgid "Recipient" msgstr "收件人" -#: accounts/models/automations/backup_account.py:34 -#: accounts/models/automations/backup_account.py:96 +#: accounts/models/automations/backup_account.py:36 +#: accounts/models/automations/backup_account.py:102 msgid "Account backup plan" msgstr "账号备份计划" -#: accounts/models/automations/backup_account.py:77 -#: assets/models/automations/base.py:110 audits/models.py:43 +#: accounts/models/automations/backup_account.py:83 +#: assets/models/automations/base.py:114 audits/models.py:43 #: ops/models/base.py:55 ops/models/celery.py:63 ops/models/job.py:116 #: perms/models/asset_permission.py:72 terminal/models/applet/host.py:108 #: terminal/models/session/session.py:44 @@ -251,37 +247,37 @@ msgstr "账号备份计划" msgid "Date start" msgstr "开始日期" -#: accounts/models/automations/backup_account.py:80 +#: accounts/models/automations/backup_account.py:86 #: authentication/templates/authentication/_msg_oauth_bind.html:11 #: notifications/notifications.py:186 msgid "Time" msgstr "时间" -#: accounts/models/automations/backup_account.py:84 +#: accounts/models/automations/backup_account.py:90 msgid "Account backup snapshot" msgstr "账号备份快照" -#: accounts/models/automations/backup_account.py:88 +#: accounts/models/automations/backup_account.py:94 #: accounts/serializers/account/backup.py:39 #: accounts/serializers/automations/base.py:44 -#: assets/models/automations/base.py:117 +#: assets/models/automations/base.py:121 #: assets/serializers/automations/base.py:40 msgid "Trigger mode" msgstr "触发模式" -#: accounts/models/automations/backup_account.py:91 audits/models.py:158 -#: terminal/models/session/sharing.py:107 xpack/plugins/cloud/models.py:176 +#: accounts/models/automations/backup_account.py:97 audits/models.py:160 +#: terminal/models/session/sharing.py:107 xpack/plugins/cloud/models.py:168 msgid "Reason" msgstr "原因" -#: accounts/models/automations/backup_account.py:93 +#: accounts/models/automations/backup_account.py:99 #: accounts/serializers/automations/change_secret.py:106 #: accounts/serializers/automations/change_secret.py:129 #: ops/serializers/job.py:64 terminal/serializers/session.py:49 msgid "Is success" msgstr "是否成功" -#: accounts/models/automations/backup_account.py:101 +#: accounts/models/automations/backup_account.py:107 msgid "Account backup execution" msgstr "账号备份执行" @@ -322,7 +318,7 @@ msgid "Can add push account execution" msgstr "创建推送账号执行" #: accounts/models/automations/change_secret.py:17 accounts/models/base.py:36 -#: accounts/serializers/account/account.py:132 +#: accounts/serializers/account/account.py:134 #: accounts/serializers/account/base.py:16 #: accounts/serializers/automations/change_secret.py:46 #: authentication/serializers/connect_token_secret.py:41 @@ -364,7 +360,7 @@ msgid "Date started" msgstr "开始日期" #: accounts/models/automations/change_secret.py:74 -#: assets/models/automations/base.py:111 ops/models/base.py:56 +#: assets/models/automations/base.py:115 ops/models/base.py:56 #: ops/models/celery.py:64 ops/models/job.py:117 #: terminal/models/applet/host.py:109 msgid "Date finished" @@ -380,7 +376,7 @@ msgid "Change secret record" msgstr "改密记录" #: accounts/models/automations/gather_account.py:15 -#: accounts/tasks/gather_accounts.py:28 +#: accounts/tasks/gather_accounts.py:29 msgid "Gather asset accounts" msgstr "收集账号" @@ -390,7 +386,7 @@ msgstr "触发方式" #: accounts/models/automations/push_account.py:14 accounts/models/base.py:34 #: accounts/models/gathered_account.py:15 acls/serializers/base.py:18 -#: acls/serializers/base.py:49 assets/models/_user.py:23 audits/models.py:143 +#: acls/serializers/base.py:49 assets/models/_user.py:23 audits/models.py:145 #: authentication/forms.py:25 authentication/forms.py:27 #: authentication/models/temp_token.py:9 #: authentication/templates/authentication/_msg_different_city.html:9 @@ -428,7 +424,7 @@ msgstr "账号验证" #: assets/serializers/platform.py:131 #: authentication/serializers/connect_token_secret.py:103 ops/mixin.py:21 #: ops/models/adhoc.py:21 ops/models/celery.py:15 ops/models/celery.py:57 -#: ops/models/job.py:26 ops/models/playbook.py:22 ops/serializers/job.py:19 +#: ops/models/job.py:26 ops/models/playbook.py:23 ops/serializers/job.py:19 #: ops/serializers/playbook.py:19 orgs/models.py:69 #: perms/models/asset_permission.py:56 rbac/models/role.py:29 #: settings/models.py:33 settings/serializers/sms.py:6 @@ -507,22 +503,22 @@ msgstr "" "{} - 改密任务已完成: 未设置加密密码 - 请前往个人信息 -> 文件加密密码中设置加" "密密码" -#: accounts/serializers/account/account.py:65 +#: accounts/serializers/account/account.py:67 #: assets/serializers/asset/common.py:64 settings/serializers/auth/sms.py:75 msgid "Template" msgstr "模板" -#: accounts/serializers/account/account.py:68 +#: accounts/serializers/account/account.py:70 #: assets/serializers/asset/common.py:61 msgid "Push now" msgstr "立即推送" -#: accounts/serializers/account/account.py:70 +#: accounts/serializers/account/account.py:72 #: accounts/serializers/account/base.py:62 msgid "Has secret" msgstr "已托管密码" -#: accounts/serializers/account/account.py:75 applications/models.py:11 +#: accounts/serializers/account/account.py:77 applications/models.py:11 #: assets/models/label.py:21 assets/models/platform.py:75 #: assets/serializers/asset/common.py:119 assets/serializers/cagegory.py:8 #: assets/serializers/platform.py:93 assets/serializers/platform.py:132 @@ -531,7 +527,7 @@ msgstr "已托管密码" msgid "Category" msgstr "类别" -#: accounts/serializers/account/account.py:76 +#: accounts/serializers/account/account.py:78 #: accounts/serializers/automations/base.py:43 acls/models/command_acl.py:24 #: acls/serializers/command_acl.py:18 applications/models.py:14 #: assets/models/_user.py:50 assets/models/automations/base.py:20 @@ -542,15 +538,15 @@ msgstr "类别" #: perms/serializers/user_permission.py:26 terminal/models/applet/applet.py:30 #: terminal/models/component/storage.py:57 #: terminal/models/component/storage.py:146 terminal/serializers/applet.py:28 -#: terminal/serializers/session.py:26 terminal/serializers/storage.py:181 -#: tickets/models/comment.py:26 tickets/models/flow.py:56 -#: tickets/models/ticket/apply_application.py:16 +#: terminal/serializers/session.py:26 terminal/serializers/storage.py:224 +#: terminal/serializers/storage.py:236 tickets/models/comment.py:26 +#: tickets/models/flow.py:56 tickets/models/ticket/apply_application.py:16 #: tickets/models/ticket/general.py:275 tickets/serializers/flow.py:53 #: tickets/serializers/ticket/ticket.py:19 msgid "Type" msgstr "类型" -#: accounts/serializers/account/account.py:91 +#: accounts/serializers/account/account.py:93 msgid "Asset not found" msgstr "资产不存在" @@ -580,7 +576,7 @@ msgid "Key password" msgstr "密钥密码" #: accounts/serializers/account/base.py:79 -#: assets/serializers/asset/common.py:287 +#: assets/serializers/asset/common.py:283 msgid "Spec info" msgstr "特殊信息" @@ -600,7 +596,7 @@ msgid "Nodes" msgstr "节点" #: accounts/serializers/automations/base.py:42 -#: assets/models/automations/base.py:113 +#: assets/models/automations/base.py:117 #: assets/serializers/automations/base.py:39 msgid "Automation snapshot" msgstr "自动化快照" @@ -618,12 +614,12 @@ msgid "* Password length range 6-30 bits" msgstr "* 密码长度范围 6-30 位" #: accounts/serializers/automations/change_secret.py:110 -#: assets/models/automations/base.py:122 +#: assets/models/automations/base.py:126 msgid "Automation task execution" msgstr "自动化任务执行历史" #: accounts/serializers/automations/change_secret.py:150 audits/const.py:52 -#: audits/models.py:42 audits/signal_handlers/activity_log.py:120 +#: audits/models.py:42 audits/signal_handlers/activity_log.py:118 #: common/const/choices.py:18 ops/const.py:56 ops/serializers/celery.py:39 #: terminal/const.py:59 terminal/models/session/sharing.py:103 #: tickets/views/approve.py:114 @@ -631,32 +627,32 @@ msgid "Success" msgstr "成功" #: accounts/serializers/automations/change_secret.py:151 audits/const.py:53 -#: audits/signal_handlers/activity_log.py:120 common/const/choices.py:19 +#: audits/signal_handlers/activity_log.py:118 common/const/choices.py:19 #: ops/const.py:58 terminal/const.py:60 xpack/plugins/cloud/const.py:41 msgid "Failed" msgstr "失败" -#: accounts/tasks/automation.py:11 +#: accounts/tasks/automation.py:16 msgid "Account execute automation" msgstr "账号执行自动化" -#: accounts/tasks/backup_account.py:12 +#: accounts/tasks/backup_account.py:24 msgid "Execute account backup plan" msgstr "执行账号备份计划" -#: accounts/tasks/gather_accounts.py:31 +#: accounts/tasks/gather_accounts.py:34 msgid "Gather assets accounts" msgstr "收集资产上的账号" -#: accounts/tasks/push_account.py:30 accounts/tasks/push_account.py:36 +#: accounts/tasks/push_account.py:30 accounts/tasks/push_account.py:37 msgid "Push accounts to assets" msgstr "推送账号到资产" -#: accounts/tasks/verify_account.py:41 +#: accounts/tasks/verify_account.py:42 msgid "Verify asset account availability" msgstr "验证资产账号可用性" -#: accounts/tasks/verify_account.py:47 +#: accounts/tasks/verify_account.py:50 msgid "Verify accounts connectivity" msgstr "测试账号可连接性" @@ -720,7 +716,7 @@ msgstr "激活中" #: acls/models/base.py:98 acls/models/login_acl.py:13 #: acls/serializers/base.py:55 acls/serializers/login_acl.py:21 #: assets/models/cmd_filter.py:24 assets/models/label.py:16 audits/models.py:32 -#: audits/models.py:51 audits/models.py:127 +#: audits/models.py:51 audits/models.py:129 #: authentication/models/connection_token.py:29 #: authentication/models/sso_token.py:16 #: notifications/models/notification.py:12 @@ -903,23 +899,23 @@ msgid "" "different ports" msgstr "默认端口为9000, HTTP接口和本机接口使用不同的端口" -#: assets/api/asset/asset.py:136 +#: assets/api/asset/asset.py:145 msgid "Cannot create asset directly, you should create a host or other" msgstr "不能直接创建资产, 你应该创建主机或其他资产" -#: assets/api/domain.py:57 +#: assets/api/domain.py:61 msgid "Number required" msgstr "需要为数字" -#: assets/api/node.py:58 +#: assets/api/node.py:57 msgid "You can't update the root node name" msgstr "不能修改根节点名称" -#: assets/api/node.py:65 +#: assets/api/node.py:64 msgid "You can't delete the root node ({})" msgstr "不能删除根节点 ({})" -#: assets/api/node.py:68 +#: assets/api/node.py:67 msgid "Deletion failed and the node contains assets" msgstr "删除失败,节点包含资产" @@ -952,7 +948,8 @@ msgid "Connect failed" msgstr "连接失败" #: assets/const/automation.py:6 audits/const.py:6 audits/const.py:35 -#: audits/signal_handlers/activity_log.py:92 common/utils/ip/geoip/utils.py:31 +#: audits/signal_handlers/activity_log.py:88 +#: audits/signal_handlers/activity_log.py:147 common/utils/ip/geoip/utils.py:31 #: common/utils/ip/geoip/utils.py:37 common/utils/ip/utils.py:84 msgid "Unknown" msgstr "未知" @@ -1048,18 +1045,18 @@ msgstr "SSH公钥" #: assets/models/_user.py:27 assets/models/cmd_filter.py:40 #: assets/models/cmd_filter.py:88 assets/models/group.py:23 #: assets/models/platform.py:79 common/db/models.py:37 ops/models/adhoc.py:27 -#: ops/models/job.py:42 ops/models/playbook.py:25 rbac/models/role.py:37 +#: ops/models/job.py:42 ops/models/playbook.py:26 rbac/models/role.py:37 #: settings/models.py:38 terminal/models/applet/applet.py:35 #: terminal/models/applet/applet.py:151 terminal/models/applet/host.py:110 #: terminal/models/component/endpoint.py:24 #: terminal/models/component/endpoint.py:100 #: terminal/models/session/session.py:46 tickets/models/comment.py:32 #: tickets/models/ticket/general.py:297 users/models/user.py:756 -#: xpack/plugins/cloud/models.py:35 xpack/plugins/cloud/models.py:119 +#: xpack/plugins/cloud/models.py:35 xpack/plugins/cloud/models.py:111 msgid "Comment" msgstr "备注" -#: assets/models/_user.py:28 assets/models/automations/base.py:109 +#: assets/models/_user.py:28 assets/models/automations/base.py:113 #: assets/models/cmd_filter.py:41 assets/models/group.py:22 #: common/db/models.py:35 ops/models/base.py:54 ops/models/job.py:115 #: users/models/user.py:943 @@ -1156,7 +1153,7 @@ msgstr "地址" #: assets/models/asset/common.py:109 assets/models/platform.py:111 #: authentication/serializers/connect_token_secret.py:108 #: perms/serializers/user_permission.py:23 -#: xpack/plugins/cloud/serializers/account_attrs.py:179 +#: xpack/plugins/cloud/serializers/account_attrs.py:187 msgid "Platform" msgstr "系统平台" @@ -1170,35 +1167,35 @@ msgstr "网域" msgid "Labels" msgstr "标签管理" -#: assets/models/asset/common.py:285 +#: assets/models/asset/common.py:287 msgid "Can refresh asset hardware info" msgstr "可以更新资产硬件信息" -#: assets/models/asset/common.py:286 +#: assets/models/asset/common.py:288 msgid "Can test asset connectivity" msgstr "可以测试资产连接性" -#: assets/models/asset/common.py:287 +#: assets/models/asset/common.py:289 msgid "Can push account to asset" msgstr "可以推送账号到资产" -#: assets/models/asset/common.py:288 +#: assets/models/asset/common.py:290 msgid "Can verify account" msgstr "可以验证账号" -#: assets/models/asset/common.py:289 +#: assets/models/asset/common.py:291 msgid "Can match asset" msgstr "可以匹配资产" -#: assets/models/asset/common.py:290 +#: assets/models/asset/common.py:292 msgid "Add asset to node" msgstr "添加资产到节点" -#: assets/models/asset/common.py:291 +#: assets/models/asset/common.py:293 msgid "Move asset to node" msgstr "移动资产到节点" -#: assets/models/asset/common.py:292 +#: assets/models/asset/common.py:294 msgid "Remove asset from node" msgstr "从节点移除资产" @@ -1243,26 +1240,26 @@ msgid "Submit selector" msgstr "确认按钮选择器" #: assets/models/automations/base.py:17 assets/models/cmd_filter.py:38 -#: assets/serializers/asset/common.py:286 rbac/tree.py:36 +#: assets/serializers/asset/common.py:282 rbac/tree.py:36 msgid "Accounts" msgstr "账号管理" -#: assets/models/automations/base.py:28 assets/models/automations/base.py:106 +#: assets/models/automations/base.py:28 assets/models/automations/base.py:110 msgid "Automation task" msgstr "自动化任务" -#: assets/models/automations/base.py:99 +#: assets/models/automations/base.py:103 msgid "Asset automation task" msgstr "资产自动化任务" -#: assets/models/automations/base.py:108 audits/models.py:163 +#: assets/models/automations/base.py:112 audits/models.py:165 #: audits/serializers.py:50 ops/models/base.py:49 ops/models/job.py:108 #: terminal/models/applet/applet.py:150 terminal/models/applet/host.py:107 #: terminal/models/component/status.py:27 terminal/serializers/applet.py:17 #: terminal/serializers/applet_host.py:93 tickets/models/ticket/general.py:283 #: tickets/serializers/super_ticket.py:13 -#: tickets/serializers/ticket/ticket.py:20 xpack/plugins/cloud/models.py:172 -#: xpack/plugins/cloud/models.py:224 +#: tickets/serializers/ticket/ticket.py:20 xpack/plugins/cloud/models.py:164 +#: xpack/plugins/cloud/models.py:216 msgid "Status" msgstr "状态" @@ -1481,8 +1478,7 @@ msgstr "自动代填" #: assets/serializers/asset/common.py:122 assets/serializers/platform.py:95 #: authentication/serializers/connect_token_secret.py:28 #: authentication/serializers/connect_token_secret.py:66 -#: perms/serializers/user_permission.py:24 xpack/plugins/cloud/models.py:107 -#: xpack/plugins/cloud/serializers/task.py:38 +#: perms/serializers/user_permission.py:24 xpack/plugins/cloud/models.py:99 msgid "Protocols" msgstr "协议组" @@ -1502,13 +1498,15 @@ msgstr "端口超出范围 (1-65535)" msgid "Protocol is required: {}" msgstr "协议是必填的: {}" -#: assets/serializers/asset/common.py:288 +#: assets/serializers/asset/common.py:284 msgid "Auto info" msgstr "自动化信息" -#: assets/serializers/asset/database.py:24 common/serializers/fields.py:100 +#: assets/serializers/asset/database.py:25 common/serializers/fields.py:100 #: tickets/serializers/ticket/common.py:58 #: xpack/plugins/cloud/serializers/account_attrs.py:56 +#: xpack/plugins/cloud/serializers/account_attrs.py:79 +#: xpack/plugins/cloud/serializers/account_attrs.py:143 msgid "This field is required." msgstr "该字段是必填项。" @@ -1598,10 +1596,8 @@ msgid "SFTP home" msgstr "SFTP 根路径" #: assets/serializers/platform.py:42 -#, fuzzy -#| msgid "Input username" msgid "Auth with username" -msgstr "自定义用户名" +msgstr "使用用户名认证" #: assets/serializers/platform.py:70 msgid "Gather accounts enabled" @@ -1619,32 +1615,27 @@ msgstr "主要的" msgid "Default Domain" msgstr "默认网域" -#: assets/signal_handlers/asset.py:25 assets/tasks/ping.py:24 -#: assets/tasks/ping.py:34 +#: assets/signal_handlers/asset.py:26 assets/tasks/ping.py:35 msgid "Test assets connectivity " msgstr "测试资产可连接性" -#: assets/signal_handlers/asset.py:34 -#, fuzzy -#| msgid "Update assets hardware info: " +#: assets/signal_handlers/asset.py:35 msgid "Gather asset hardware info" -msgstr "更新资产硬件信息" +msgstr "收集资产硬件信息" -#: assets/tasks/automation.py:11 +#: assets/tasks/automation.py:24 msgid "Asset execute automation" msgstr "资产执行自动化" -#: assets/tasks/gather_facts.py:21 assets/tasks/gather_facts.py:25 -#, fuzzy -#| msgid "Gather asset facts" +#: assets/tasks/gather_facts.py:21 assets/tasks/gather_facts.py:27 msgid "Gather assets facts" msgstr "收集资产信息" -#: assets/tasks/gather_facts.py:47 +#: assets/tasks/gather_facts.py:39 msgid "Update assets hardware info: " msgstr "更新资产硬件信息" -#: assets/tasks/gather_facts.py:54 +#: assets/tasks/gather_facts.py:47 msgid "Update node asset hardware information: " msgstr "更新节点资产硬件信息: " @@ -1657,19 +1648,22 @@ msgid "" "The task of self-checking is already running and cannot be started repeatedly" msgstr "自检程序已经在运行,不能重复启动" -#: assets/tasks/nodes_amount.py:34 +#: assets/tasks/nodes_amount.py:33 msgid "Periodic check the amount of assets under the node" msgstr "周期性检查节点下资产数量" -#: assets/tasks/ping.py:41 +#: assets/tasks/ping.py:20 assets/tasks/ping.py:26 +msgid "Test assets connectivity" +msgstr "测试资产可连接性" + +#: assets/tasks/ping.py:42 msgid "Test if the assets under the node are connectable " msgstr "测试节点下资产是否可连接" -#: assets/tasks/ping_gateway.py:23 assets/tasks/ping_gateway.py:33 -#, fuzzy -#| msgid "Test assets connectivity " -msgid "Test gateways connectivity " -msgstr "测试资产可连接性" +#: assets/tasks/ping_gateway.py:19 assets/tasks/ping_gateway.py:26 +#: assets/tasks/ping_gateway.py:37 +msgid "Test gateways connectivity" +msgstr "测试网关可连接性" #: assets/tasks/utils.py:17 msgid "Asset has been disabled, skipped: {}" @@ -1769,18 +1763,14 @@ msgid "Operate log" msgstr "操作日志" #: audits/const.py:40 -#, fuzzy -#| msgid "Session" msgid "Session log" -msgstr "会话" +msgstr "会话日志" #: audits/const.py:41 -#, fuzzy -#| msgid "Login acl" msgid "Login log" -msgstr "登录访问控制" +msgstr "登录日志" -#: audits/const.py:42 ops/signal_handlers.py:74 +#: audits/const.py:42 ops/signal_handlers.py:86 #: terminal/models/applet/host.py:111 terminal/models/component/task.py:24 msgid "Task" msgstr "任务" @@ -1797,7 +1787,7 @@ msgstr "是" msgid "No" msgstr "否" -#: audits/models.py:34 audits/models.py:61 audits/models.py:130 +#: audits/models.py:34 audits/models.py:61 audits/models.py:132 #: terminal/models/session/session.py:38 terminal/models/session/sharing.py:95 msgid "Remote addr" msgstr "远端地址" @@ -1822,71 +1812,69 @@ msgstr "资源类型" msgid "Resource" msgstr "资源" -#: audits/models.py:62 audits/models.py:108 audits/models.py:132 +#: audits/models.py:62 audits/models.py:108 audits/models.py:134 #: terminal/serializers/command.py:43 msgid "Datetime" msgstr "日期" #: audits/models.py:101 -#, fuzzy -#| msgid "Active" msgid "Activity type" -msgstr "激活中" +msgstr "活动类型" -#: audits/models.py:110 +#: audits/models.py:111 msgid "Detail" msgstr "详情" -#: audits/models.py:112 +#: audits/models.py:114 msgid "Detail ID" msgstr "详情 ID" -#: audits/models.py:116 +#: audits/models.py:118 msgid "Activity log" msgstr "" -#: audits/models.py:128 +#: audits/models.py:130 msgid "Change by" msgstr "修改者" -#: audits/models.py:138 +#: audits/models.py:140 msgid "Password change log" msgstr "改密日志" -#: audits/models.py:145 +#: audits/models.py:147 msgid "Login type" msgstr "登录方式" -#: audits/models.py:147 tickets/models/ticket/login_confirm.py:10 +#: audits/models.py:149 tickets/models/ticket/login_confirm.py:10 msgid "Login ip" msgstr "登录IP" -#: audits/models.py:149 +#: audits/models.py:151 #: authentication/templates/authentication/_msg_different_city.html:11 #: tickets/models/ticket/login_confirm.py:11 msgid "Login city" msgstr "登录城市" -#: audits/models.py:152 audits/serializers.py:64 +#: audits/models.py:154 audits/serializers.py:64 msgid "User agent" msgstr "用户代理" -#: audits/models.py:155 audits/serializers.py:48 +#: audits/models.py:157 audits/serializers.py:48 #: authentication/templates/authentication/_mfa_confirm_modal.html:14 #: users/forms/profile.py:65 users/models/user.py:740 #: users/serializers/profile.py:124 msgid "MFA" msgstr "MFA" -#: audits/models.py:165 +#: audits/models.py:167 msgid "Date login" msgstr "登录日期" -#: audits/models.py:167 audits/serializers.py:66 +#: audits/models.py:169 audits/serializers.py:66 msgid "Authentication backend" msgstr "认证方式" -#: audits/models.py:211 +#: audits/models.py:213 msgid "User login log" msgstr "用户登录日志" @@ -1894,23 +1882,24 @@ msgstr "用户登录日志" msgid "Reason display" msgstr "原因描述" -#: audits/serializers.py:123 -msgid "User {} {} this resource" -msgstr "用户 {} {} 了当前资源" +#: audits/serializers.py:124 +#, python-format +msgid "User %s %s this resource" +msgstr "用户 %s %s 了当前资源" -#: audits/signal_handlers/activity_log.py:113 +#: audits/signal_handlers/activity_log.py:111 #, python-format msgid "User %s use account %s login asset %s" msgstr "用户 %s 使用账号 %s 登录资产 %s" -#: audits/signal_handlers/activity_log.py:121 +#: audits/signal_handlers/activity_log.py:119 #, python-format msgid "User %s login system %s" msgstr "用户 %s 登录系统 %s" -#: audits/signal_handlers/activity_log.py:145 +#: audits/signal_handlers/activity_log.py:149 #, python-format -msgid "User %s perform a task (%s) for this resource" +msgid "User %s perform a task for this resource: %s" msgstr "用户 %s 在当前资源, 执行了任务 (%s)" #: audits/signal_handlers/login_log.py:27 @@ -1949,27 +1938,31 @@ msgstr "钉钉" msgid "Temporary token" msgstr "临时密码" -#: audits/tasks.py:44 +#: audits/tasks.py:52 msgid "Clean audits log" msgstr "清理审计日志" +#: audits/tasks.py:92 +msgid "Clean audits session task log" +msgstr "清理审计会话任务日志" + #: authentication/api/confirm.py:40 msgid "This action require verify your MFA" msgstr "此操作需要验证您的 MFA" -#: authentication/api/connection_token.py:269 +#: authentication/api/connection_token.py:268 msgid "Account not found" msgstr "账号未找到" -#: authentication/api/connection_token.py:272 +#: authentication/api/connection_token.py:271 msgid "Permission expired" msgstr "授权已过期" -#: authentication/api/connection_token.py:284 +#: authentication/api/connection_token.py:283 msgid "ACL action is reject" msgstr "ACL 动作是拒绝" -#: authentication/api/connection_token.py:288 +#: authentication/api/connection_token.py:287 msgid "ACL action is review" msgstr "ACL 动作是复核" @@ -2490,7 +2483,7 @@ msgstr "{} 不能为空" msgid "Is valid" msgstr "是否有效" -#: authentication/tasks.py:12 +#: authentication/tasks.py:11 msgid "Clean expired session" msgstr "清除过期会话" @@ -3064,11 +3057,11 @@ msgstr "错误的数据类型,应该是列表" msgid "Invalid choice: {}" msgstr "无效选项: {}" -#: common/tasks.py:13 common/utils/verify_code.py:16 +#: common/tasks.py:20 common/utils/verify_code.py:16 msgid "Send email" msgstr "发件邮件" -#: common/tasks.py:40 +#: common/tasks.py:47 msgid "Send email attachment" msgstr "发送邮件附件" @@ -3312,7 +3305,7 @@ msgid "Args" msgstr "参数" #: ops/models/adhoc.py:26 ops/models/base.py:16 ops/models/base.py:53 -#: ops/models/job.py:35 ops/models/job.py:114 ops/models/playbook.py:24 +#: ops/models/job.py:35 ops/models/job.py:114 ops/models/playbook.py:25 #: terminal/models/session/sharing.py:23 msgid "Creator" msgstr "创建者" @@ -3330,7 +3323,7 @@ msgid "Date last run" msgstr "最后运行日期" #: ops/models/base.py:51 ops/models/job.py:112 -#: xpack/plugins/cloud/models.py:170 +#: xpack/plugins/cloud/models.py:162 msgid "Result" msgstr "结果" @@ -3422,11 +3415,11 @@ msgstr "作业执行" msgid "Job audit log" msgstr "作业审计日志" -#: ops/models/playbook.py:27 +#: ops/models/playbook.py:28 msgid "CreateMethod" msgstr "创建方式" -#: ops/models/playbook.py:28 +#: ops/models/playbook.py:29 msgid "VCS URL" msgstr "" @@ -3474,22 +3467,14 @@ msgstr "是否完成" msgid "Time cost" msgstr "花费时间" -#: ops/tasks.py:27 +#: ops/tasks.py:32 msgid "Run ansible task" msgstr "运行 Ansible 任务" -#: ops/tasks.py:44 +#: ops/tasks.py:61 msgid "Run ansible task execution" msgstr "开始执行 Ansible 任务" -#: ops/tasks.py:58 -msgid "Periodic clear celery tasks" -msgstr "周期清理不可用任务" - -#: ops/tasks.py:60 -msgid "Clean celery log period" -msgstr "定期清除任务日志" - #: ops/tasks.py:77 msgid "Clear celery periodic tasks" msgstr "清理周期任务" @@ -3671,11 +3656,11 @@ msgstr "资产授权规则将要过期" msgid "asset permissions of organization {}" msgstr "组织 ({}) 的资产授权" -#: perms/tasks.py:28 +#: perms/tasks.py:27 msgid "Check asset permission expired" msgstr "校验资产授权规则已过期" -#: perms/tasks.py:40 +#: perms/tasks.py:39 msgid "Send asset permission expired notification" msgstr "发送资产权限过期通知" @@ -4377,7 +4362,7 @@ msgid "SSO auth key TTL" msgstr "令牌有效期" #: settings/serializers/auth/sso.py:17 -#: xpack/plugins/cloud/serializers/account_attrs.py:176 +#: xpack/plugins/cloud/serializers/account_attrs.py:184 msgid "Unit: second" msgstr "单位: 秒" @@ -5537,10 +5522,8 @@ msgid "Can download session replay" msgstr "可以下载会话录像" #: terminal/models/session/session.py:34 -#, fuzzy -#| msgid "Account " msgid "Account id" -msgstr "账号" +msgstr "账号 ID" #: terminal/models/session/session.py:36 terminal/models/session/sharing.py:100 msgid "Login from" @@ -5765,7 +5748,7 @@ msgstr "Access key ID(AK)" msgid "Access key secret" msgstr "Access key secret(SK)" -#: terminal/serializers/storage.py:65 xpack/plugins/cloud/models.py:217 +#: terminal/serializers/storage.py:65 xpack/plugins/cloud/models.py:209 msgid "Region" msgstr "地域" @@ -5817,27 +5800,23 @@ msgstr "忽略证书认证" msgid "Not found" msgstr "没有发现" -#: terminal/tasks.py:31 +#: terminal/tasks.py:28 msgid "Periodic delete terminal status" msgstr "周期清理终端状态" -#: terminal/tasks.py:40 +#: terminal/tasks.py:37 msgid "Clean orphan session" msgstr "清除孤儿会话" -#: terminal/tasks.py:59 -msgid "Periodic clean expired session" -msgstr "周期清理过期会话" - -#: terminal/tasks.py:85 +#: terminal/tasks.py:56 msgid "Upload session replay to external storage" msgstr "上传会话录像到外部存储" -#: terminal/tasks.py:112 +#: terminal/tasks.py:83 msgid "Run applet host deployment" msgstr "运行应用机部署" -#: terminal/tasks.py:119 +#: terminal/tasks.py:90 msgid "Install applet" msgstr "安装应用" @@ -6890,55 +6869,47 @@ msgstr "地域" msgid "Hostname strategy" msgstr "主机名策略" -#: xpack/plugins/cloud/models.py:100 -msgid "Unix admin user" -msgstr "Unix 管理员" - -#: xpack/plugins/cloud/models.py:104 -msgid "Windows admin user" -msgstr "Windows 管理员" - -#: xpack/plugins/cloud/models.py:110 xpack/plugins/cloud/serializers/task.py:41 +#: xpack/plugins/cloud/models.py:102 xpack/plugins/cloud/serializers/task.py:40 msgid "IP network segment group" msgstr "IP网段组" -#: xpack/plugins/cloud/models.py:113 xpack/plugins/cloud/serializers/task.py:46 +#: xpack/plugins/cloud/models.py:105 xpack/plugins/cloud/serializers/task.py:45 msgid "Sync IP type" msgstr "同步IP类型" -#: xpack/plugins/cloud/models.py:116 xpack/plugins/cloud/serializers/task.py:64 +#: xpack/plugins/cloud/models.py:108 xpack/plugins/cloud/serializers/task.py:62 msgid "Always update" msgstr "总是更新" -#: xpack/plugins/cloud/models.py:122 +#: xpack/plugins/cloud/models.py:114 msgid "Date last sync" msgstr "最后同步日期" -#: xpack/plugins/cloud/models.py:127 xpack/plugins/cloud/models.py:168 +#: xpack/plugins/cloud/models.py:119 xpack/plugins/cloud/models.py:160 msgid "Sync instance task" msgstr "同步实例任务" -#: xpack/plugins/cloud/models.py:179 xpack/plugins/cloud/models.py:227 +#: xpack/plugins/cloud/models.py:171 xpack/plugins/cloud/models.py:219 msgid "Date sync" msgstr "同步日期" -#: xpack/plugins/cloud/models.py:183 +#: xpack/plugins/cloud/models.py:175 msgid "Sync instance task execution" msgstr "同步实例任务执行" -#: xpack/plugins/cloud/models.py:207 +#: xpack/plugins/cloud/models.py:199 msgid "Sync task" msgstr "同步任务" -#: xpack/plugins/cloud/models.py:211 +#: xpack/plugins/cloud/models.py:203 msgid "Sync instance task history" msgstr "同步实例任务历史" -#: xpack/plugins/cloud/models.py:214 +#: xpack/plugins/cloud/models.py:206 msgid "Instance" msgstr "实例" -#: xpack/plugins/cloud/models.py:231 +#: xpack/plugins/cloud/models.py:223 msgid "Sync instance detail" msgstr "同步实例详情" @@ -7152,52 +7123,52 @@ msgstr "租户 ID" msgid "Subscription ID" msgstr "订阅 ID" -#: xpack/plugins/cloud/serializers/account_attrs.py:95 -#: xpack/plugins/cloud/serializers/account_attrs.py:100 -#: xpack/plugins/cloud/serializers/account_attrs.py:116 -#: xpack/plugins/cloud/serializers/account_attrs.py:141 +#: xpack/plugins/cloud/serializers/account_attrs.py:98 +#: xpack/plugins/cloud/serializers/account_attrs.py:103 +#: xpack/plugins/cloud/serializers/account_attrs.py:119 +#: xpack/plugins/cloud/serializers/account_attrs.py:149 msgid "API Endpoint" msgstr "API 端点" -#: xpack/plugins/cloud/serializers/account_attrs.py:106 +#: xpack/plugins/cloud/serializers/account_attrs.py:109 msgid "Auth url" msgstr "认证地址" -#: xpack/plugins/cloud/serializers/account_attrs.py:107 +#: xpack/plugins/cloud/serializers/account_attrs.py:110 msgid "eg: http://openstack.example.com:5000/v3" msgstr "如: http://openstack.example.com:5000/v3" -#: xpack/plugins/cloud/serializers/account_attrs.py:110 +#: xpack/plugins/cloud/serializers/account_attrs.py:113 msgid "User domain" msgstr "用户域" -#: xpack/plugins/cloud/serializers/account_attrs.py:117 +#: xpack/plugins/cloud/serializers/account_attrs.py:120 msgid "Cert File" msgstr "证书文件" -#: xpack/plugins/cloud/serializers/account_attrs.py:118 +#: xpack/plugins/cloud/serializers/account_attrs.py:121 msgid "Key File" msgstr "密钥文件" -#: xpack/plugins/cloud/serializers/account_attrs.py:134 +#: xpack/plugins/cloud/serializers/account_attrs.py:137 msgid "Service account key" msgstr "服务账号密钥" -#: xpack/plugins/cloud/serializers/account_attrs.py:135 +#: xpack/plugins/cloud/serializers/account_attrs.py:138 msgid "The file is in JSON format" msgstr "JSON 格式的文件" -#: xpack/plugins/cloud/serializers/account_attrs.py:148 +#: xpack/plugins/cloud/serializers/account_attrs.py:156 msgid "IP address invalid `{}`, {}" msgstr "IP 地址无效: `{}`, {}" -#: xpack/plugins/cloud/serializers/account_attrs.py:154 +#: xpack/plugins/cloud/serializers/account_attrs.py:162 msgid "" "Format for comma-delimited string,Such as: 192.168.1.0/24, " "10.0.0.0-10.0.0.255" msgstr "格式为逗号分隔的字符串,如:192.168.1.0/24,10.0.0.0-10.0.0.255" -#: xpack/plugins/cloud/serializers/account_attrs.py:158 +#: xpack/plugins/cloud/serializers/account_attrs.py:166 msgid "" "The port is used to detect the validity of the IP address. When the " "synchronization task is executed, only the valid IP address will be " @@ -7206,19 +7177,19 @@ msgstr "" "端口用来检测 IP 地址的有效性,在同步任务执行时,只会同步有效的 IP 地址。
" "如果端口为 0,则表示所有 IP 地址均有效。" -#: xpack/plugins/cloud/serializers/account_attrs.py:166 +#: xpack/plugins/cloud/serializers/account_attrs.py:174 msgid "Hostname prefix" msgstr "主机名前缀" -#: xpack/plugins/cloud/serializers/account_attrs.py:169 +#: xpack/plugins/cloud/serializers/account_attrs.py:177 msgid "IP segment" msgstr "IP 网段" -#: xpack/plugins/cloud/serializers/account_attrs.py:173 +#: xpack/plugins/cloud/serializers/account_attrs.py:181 msgid "Test port" msgstr "测试端口" -#: xpack/plugins/cloud/serializers/account_attrs.py:176 +#: xpack/plugins/cloud/serializers/account_attrs.py:184 msgid "Test timeout" msgstr "测试超时时间" @@ -7242,9 +7213,9 @@ msgstr "执行次数" msgid "Instance count" msgstr "实例个数" -#: xpack/plugins/cloud/serializers/task.py:63 -msgid "Linux admin user" -msgstr "Linux 管理员" +#: xpack/plugins/cloud/tasks.py:27 +msgid "Run sync instance task" +msgstr "执行同步实例任务" #: xpack/plugins/cloud/utils.py:69 msgid "Account unavailable" @@ -7314,6 +7285,27 @@ msgstr "旗舰版" msgid "Community edition" msgstr "社区版" +#~ msgid "Can change asset account secret" +#~ msgstr "可以更改资产账号密码" + +#~ msgid "Periodic clear celery tasks" +#~ msgstr "周期清理不可用任务" + +#~ msgid "Clean celery log period" +#~ msgstr "定期清除任务日志" + +#~ msgid "Periodic clean expired session" +#~ msgstr "周期清理过期会话" + +#~ msgid "Unix admin user" +#~ msgstr "Unix 管理员" + +#~ msgid "Windows admin user" +#~ msgstr "Windows 管理员" + +#~ msgid "Linux admin user" +#~ msgstr "Linux 管理员" + #~ msgid "AdHoc" #~ msgstr "任务各版本" diff --git a/apps/ops/signal_handlers.py b/apps/ops/signal_handlers.py index e72b88f25..508a993e7 100644 --- a/apps/ops/signal_handlers.py +++ b/apps/ops/signal_handlers.py @@ -10,6 +10,7 @@ from django.utils import translation, timezone from django.utils.translation import gettext as _ from common.db.utils import close_old_connections, get_logger +from common.signals import django_ready from .celery import app from .models import CeleryTaskExecution, CeleryTask, Job @@ -45,6 +46,17 @@ def sync_registered_tasks(*args, **kwargs): pass +@receiver(django_ready) +def check_registered_tasks(*args, **kwargs): + attrs = ['verbose_name', 'activity_callback'] + for name, task in app.tasks.items(): + if name.startswith('celery.'): + continue + for attr in attrs: + if not hasattr(task, attr): + print('>>> Task {} has no attribute {}'.format(name, attr)) + + @signals.before_task_publish.connect def before_task_publish(headers=None, **kwargs): task_id = headers.get('id') diff --git a/apps/ops/tasks.py b/apps/ops/tasks.py index a9559a4cf..aff569ba7 100644 --- a/apps/ops/tasks.py +++ b/apps/ops/tasks.py @@ -19,7 +19,19 @@ from .notifications import ServerPerformanceCheckUtil logger = get_logger(__file__) -@shared_task(soft_time_limit=60, queue="ansible", verbose_name=_("Run ansible task")) +def job_task_activity_callback(self, job_id, trigger): + job = get_object_or_none(Job, id=job_id) + if not job: + return + resource_ids = [job.id] + org_id = job.org_id + return resource_ids, org_id + + +@shared_task( + soft_time_limit=60, queue="ansible", verbose_name=_("Run ansible task"), + activity_callback=job_task_activity_callback +) def run_ops_job(job_id): job = get_object_or_none(Job, id=job_id) with tmp_to_org(job.org): @@ -36,7 +48,19 @@ def run_ops_job(job_id): logger.error("Start adhoc execution error: {}".format(e)) -@shared_task(soft_time_limit=60, queue="ansible", verbose_name=_("Run ansible task execution")) +def job_execution_task_activity_callback(self, execution_id, trigger): + execution = get_object_or_none(JobExecution, id=execution_id) + if not execution: + return + resource_ids = [execution.id] + org_id = execution.org_id + return resource_ids, org_id + + +@shared_task( + soft_time_limit=60, queue="ansible", verbose_name=_("Run ansible task execution"), + activity_callback=job_execution_task_activity_callback +) def run_ops_job_execution(execution_id, **kwargs): execution = get_object_or_none(JobExecution, id=execution_id) try: diff --git a/apps/orgs/apps.py b/apps/orgs/apps.py index 14a48203c..70505d0f0 100644 --- a/apps/orgs/apps.py +++ b/apps/orgs/apps.py @@ -7,4 +7,5 @@ class OrgsConfig(AppConfig): verbose_name = _('App organizations') def ready(self): + from . import tasks from . import signal_handlers diff --git a/apps/orgs/signal_handlers/cache.py b/apps/orgs/signal_handlers/cache.py index 48a67149d..7349d9623 100644 --- a/apps/orgs/signal_handlers/cache.py +++ b/apps/orgs/signal_handlers/cache.py @@ -87,7 +87,7 @@ class OrgResourceStatisticsRefreshUtil: if not cache_field_name: return org = getattr(instance, 'org', None) - cls.refresh_org_fields((org, cache_field_name)) + cls.refresh_org_fields(((org, cache_field_name),)) @receiver(post_save) diff --git a/apps/perms/apps.py b/apps/perms/apps.py index 432c194cd..7bb606080 100644 --- a/apps/perms/apps.py +++ b/apps/perms/apps.py @@ -12,3 +12,4 @@ class PermsConfig(AppConfig): super().ready() from . import signal_handlers from . import notifications + from . import tasks diff --git a/apps/perms/tasks.py b/apps/perms/tasks.py index cd4e7bd86..4420322d1 100644 --- a/apps/perms/tasks.py +++ b/apps/perms/tasks.py @@ -24,8 +24,8 @@ from django.utils.translation import gettext_lazy as _ logger = get_logger(__file__) -@register_as_period_task(interval=settings.PERM_EXPIRED_CHECK_PERIODIC) @shared_task(verbose_name=_('Check asset permission expired')) +@register_as_period_task(interval=settings.PERM_EXPIRED_CHECK_PERIODIC) @atomic() @tmp_to_root_org() def check_asset_permission_expired(): @@ -36,8 +36,8 @@ def check_asset_permission_expired(): UserPermTreeExpireUtil().expire_perm_tree_for_perms(perm_ids) -@register_as_period_task(crontab=CRONTAB_AT_AM_TEN) @shared_task(verbose_name=_('Send asset permission expired notification')) +@register_as_period_task(crontab=CRONTAB_AT_AM_TEN) @atomic() @tmp_to_root_org() def check_asset_permission_will_expired(): diff --git a/apps/settings/apps.py b/apps/settings/apps.py index 8bef81db3..2f96498cc 100644 --- a/apps/settings/apps.py +++ b/apps/settings/apps.py @@ -7,4 +7,5 @@ class SettingsConfig(AppConfig): verbose_name = _('Settings') def ready(self): + from . import tasks from . import signal_handlers diff --git a/apps/terminal/apps.py b/apps/terminal/apps.py index fa46ca9e2..d383d01cd 100644 --- a/apps/terminal/apps.py +++ b/apps/terminal/apps.py @@ -11,4 +11,5 @@ class TerminalConfig(AppConfig): def ready(self): from . import signal_handlers from . import notifications + from . import tasks return super().ready() diff --git a/apps/terminal/connect_methods.py b/apps/terminal/connect_methods.py index 4fe895beb..10ecdfab5 100644 --- a/apps/terminal/connect_methods.py +++ b/apps/terminal/connect_methods.py @@ -181,6 +181,7 @@ class ConnectMethodUtil: 'match': 'm2m' }, TerminalType.magnus: { + 'web_methods': [], 'listen': [], 'support': [ Protocol.mysql, Protocol.postgresql, @@ -190,6 +191,7 @@ class ConnectMethodUtil: 'match': 'map' }, TerminalType.razor: { + 'web_methods': [], 'listen': [Protocol.rdp], 'support': [Protocol.rdp], 'match': 'map' diff --git a/apps/terminal/tasks.py b/apps/terminal/tasks.py index 747468c3f..4b9fd9af3 100644 --- a/apps/terminal/tasks.py +++ b/apps/terminal/tasks.py @@ -80,14 +80,14 @@ def upload_session_replay_to_external_storage(session_id): return -@shared_task(verbose_name=_('Run applet host deployment')) +@shared_task(verbose_name=_('Run applet host deployment'), activity_callback=lambda did: ([did], )) def run_applet_host_deployment(did): with tmp_to_builtin_org(system=1): deployment = AppletHostDeployment.objects.get(id=did) deployment.start() -@shared_task(verbose_name=_('Install applet')) +@shared_task(verbose_name=_('Install applet'), activity_callback=lambda did, applet_id: ([did],)) def run_applet_host_deployment_install_applet(did, applet_id): with tmp_to_builtin_org(system=1): deployment = AppletHostDeployment.objects.get(id=did) diff --git a/apps/users/apps.py b/apps/users/apps.py index bd569c9fe..ead9987be 100644 --- a/apps/users/apps.py +++ b/apps/users/apps.py @@ -11,4 +11,5 @@ class UsersConfig(AppConfig): def ready(self): from . import signal_handlers from . import notifications + from . import tasks super().ready()