diff --git a/apps/accounts/automations/endpoint.py b/apps/accounts/automations/endpoint.py index 2a1a821ea..c1a19c968 100644 --- a/apps/accounts/automations/endpoint.py +++ b/apps/accounts/automations/endpoint.py @@ -1,8 +1,9 @@ +from .push_account.manager import PushAccountManager from .change_secret.manager import ChangeSecretManager -from .gather_accounts.manager import GatherAccountsManager from .verify_account.manager import VerifyAccountManager -from .push_account.manager import PushAccountManager from .backup_account.manager import AccountBackupManager +from .gather_accounts.manager import GatherAccountsManager +from .verify_gateway_account.manager import VerifyGatewayAccountManager from ..const import AutomationTypes @@ -12,6 +13,7 @@ class ExecutionManager: AutomationTypes.change_secret: ChangeSecretManager, AutomationTypes.verify_account: VerifyAccountManager, AutomationTypes.gather_accounts: GatherAccountsManager, + AutomationTypes.verify_gateway_account: VerifyGatewayAccountManager, # TODO 后期迁移到自动化策略中 'backup_account': AccountBackupManager, } diff --git a/apps/accounts/automations/verify_gateway_account/__init__.py b/apps/accounts/automations/verify_gateway_account/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/apps/accounts/automations/verify_gateway_account/manager.py b/apps/accounts/automations/verify_gateway_account/manager.py new file mode 100644 index 000000000..94da021b5 --- /dev/null +++ b/apps/accounts/automations/verify_gateway_account/manager.py @@ -0,0 +1,21 @@ +from common.utils import get_logger +from accounts.const import AutomationTypes +from assets.automations.ping_gateway.manager import PingGatewayManager + +logger = get_logger(__name__) + + +class VerifyGatewayAccountManager(PingGatewayManager): + + @classmethod + def method_type(cls): + return AutomationTypes.verify_gateway_account + + @staticmethod + def before_runner_start(): + logger.info(">>> 开始执行测试网关账号可连接性任务") + + def get_accounts(self, gateway): + usernames = self.execution.snapshot['accounts'] + accounts = gateway.accounts.filter(username__in=usernames) + return accounts diff --git a/apps/accounts/const/automation.py b/apps/accounts/const/automation.py index 2c3b37bde..5671f50f5 100644 --- a/apps/accounts/const/automation.py +++ b/apps/accounts/const/automation.py @@ -23,6 +23,7 @@ class AutomationTypes(models.TextChoices): change_secret = 'change_secret', _('Change secret') verify_account = 'verify_account', _('Verify account') gather_accounts = 'gather_accounts', _('Gather accounts') + verify_gateway_account = 'verify_gateway_account', _('Verify gateway account') @classmethod def get_type_model(cls, tp): diff --git a/apps/accounts/tasks/common.py b/apps/accounts/tasks/common.py index f45032939..1f422ab5f 100644 --- a/apps/accounts/tasks/common.py +++ b/apps/accounts/tasks/common.py @@ -1,5 +1,6 @@ -# -*- coding: utf-8 -*- -# + +import uuid + from assets.tasks.common import generate_data from common.const.choices import Trigger @@ -7,6 +8,14 @@ from common.const.choices import Trigger def automation_execute_start(task_name, tp, child_snapshot=None): from accounts.models import AutomationExecution data = generate_data(task_name, tp, child_snapshot) + + while True: + try: + _id = data['id'] + AutomationExecution.objects.get(id=_id) + data['id'] = str(uuid.uuid4()) + except AutomationExecution.DoesNotExist: + break execution = AutomationExecution.objects.create( trigger=Trigger.manual, **data ) diff --git a/apps/accounts/tasks/verify_account.py b/apps/accounts/tasks/verify_account.py index 0b69262f5..4c478ce89 100644 --- a/apps/accounts/tasks/verify_account.py +++ b/apps/accounts/tasks/verify_account.py @@ -3,8 +3,9 @@ from django.utils.translation import gettext_noop from django.utils.translation import ugettext as _ from common.utils import get_logger -from accounts.tasks.common import automation_execute_start +from assets.const import GATEWAY_NAME from accounts.const import AutomationTypes +from accounts.tasks.common import automation_execute_start from orgs.utils import org_aware_func logger = get_logger(__name__) @@ -13,25 +14,36 @@ __all__ = [ ] -@org_aware_func("assets") -def verify_accounts_connectivity_util(accounts, assets, task_name): - from accounts.models import VerifyAccountAutomation - task_name = VerifyAccountAutomation.generate_unique_name(task_name) +def verify_connectivity_util(assets, tp, accounts, task_name): + if not assets or not accounts: + return account_usernames = list(accounts.values_list('username', flat=True)) - child_snapshot = { 'accounts': account_usernames, 'assets': [str(asset.id) for asset in assets], } - tp = AutomationTypes.verify_account automation_execute_start(task_name, tp, child_snapshot) +@org_aware_func("assets") +def verify_accounts_connectivity_util(accounts, assets, task_name): + gateway_assets = assets.filter(platform__name=GATEWAY_NAME) + verify_connectivity_util( + gateway_assets, AutomationTypes.verify_gateway_account, accounts, task_name + ) + + non_gateway_assets = assets.exclude(platform__name=GATEWAY_NAME) + verify_connectivity_util( + non_gateway_assets, AutomationTypes.verify_account, accounts, task_name + ) + + @shared_task(queue="ansible", verbose_name=_('Verify asset account availability')) def verify_accounts_connectivity(account_ids, asset_ids): from assets.models import Asset - from accounts.models import Account + from accounts.models import Account, VerifyAccountAutomation assets = Asset.objects.filter(id__in=asset_ids) accounts = Account.objects.filter(id__in=account_ids) task_name = gettext_noop("Verify accounts connectivity") + task_name = VerifyAccountAutomation.generate_unique_name(task_name) return verify_accounts_connectivity_util(accounts, assets, task_name) diff --git a/apps/assets/automations/ping_gateway/manager.py b/apps/assets/automations/ping_gateway/manager.py index 7e40cda4e..5ffbc2734 100644 --- a/apps/assets/automations/ping_gateway/manager.py +++ b/apps/assets/automations/ping_gateway/manager.py @@ -5,8 +5,8 @@ from django.utils import timezone from django.utils.translation import ugettext_lazy as _ from common.utils import get_logger -from assets.const import AutomationTypes, Connectivity from assets.models import Gateway +from assets.const import AutomationTypes, Connectivity logger = get_logger(__name__) @@ -91,7 +91,7 @@ class PingGatewayManager: @staticmethod def on_host_success(gateway, account): - logger.info('\033[32m {}\033[0m\n'.format(gateway)) + logger.info('\033[32m {} -> {}\033[0m\n'.format(gateway, account)) gateway.set_connectivity(Connectivity.OK) if not account: return @@ -99,25 +99,35 @@ class PingGatewayManager: @staticmethod def on_host_error(gateway, account, error): - logger.info('\033[31m {} 原因: {} \033[0m\n'.format(gateway, error)) + logger.info('\033[31m {} -> {} 原因: {} \033[0m\n'.format(gateway, account, error)) gateway.set_connectivity(Connectivity.FAILED) if not account: return account.set_connectivity(Connectivity.FAILED) + @staticmethod + def before_runner_start(): + logger.info(">>> 开始执行测试网关可连接性任务") + + def get_accounts(self, gateway): + account = gateway.select_account + return [account] + def run(self): asset_ids = self.execution.snapshot['assets'] gateways = Gateway.objects.filter(id__in=asset_ids) self.execution.date_start = timezone.now() - logger.info(">>> 开始执行测试网关可连接性任务") + self.before_runner_start() + for gateway in gateways: - account = gateway.select_account - ok, e = self.execute_task(gateway, account) - if ok: - self.on_host_success(gateway, account) - else: - self.on_host_error(gateway, account, e) - print('\n') + accounts = self.get_accounts(gateway) + for account in accounts: + ok, e = self.execute_task(gateway, account) + if ok: + self.on_host_success(gateway, account) + else: + self.on_host_error(gateway, account, e) + print('\n') self.execution.status = 'success' self.execution.date_finished = timezone.now() self.execution.save() diff --git a/apps/assets/models/asset/common.py b/apps/assets/models/asset/common.py index afe905ac3..c7d8238e0 100644 --- a/apps/assets/models/asset/common.py +++ b/apps/assets/models/asset/common.py @@ -230,6 +230,10 @@ class Asset(NodesRelationMixin, AbsConnectivity, JMSOrgBaseModel): def is_type(self, tp): return self.type == tp + @property + def is_gateway(self): + return self.platform.name == const.GATEWAY_NAME + @lazyproperty def gateway(self): if self.domain_id: diff --git a/apps/assets/tasks/ping.py b/apps/assets/tasks/ping.py index c0b53a9c8..7117c8bc7 100644 --- a/apps/assets/tasks/ping.py +++ b/apps/assets/tasks/ping.py @@ -17,7 +17,7 @@ __all__ = [ ] -def test_connectivity_util(assets, tp, task_name=None, local_port=None): +def test_connectivity_util(assets, tp, task_name, local_port=None): if not assets: return diff --git a/apps/ops/ansible/inventory.py b/apps/ops/ansible/inventory.py index 6ac8cdb83..e50a0801f 100644 --- a/apps/ops/ansible/inventory.py +++ b/apps/ops/ansible/inventory.py @@ -122,7 +122,7 @@ class JMSInventory: host.update(ansible_config) gateway = None - if asset.domain: + if not asset.is_gateway and asset.domain: gateway = asset.domain.select_gateway() if ansible_connection == 'local':