diff --git a/apps/assets/automations/__init__.py b/apps/assets/automations/__init__.py new file mode 100644 index 000000000..478e9740d --- /dev/null +++ b/apps/assets/automations/__init__.py @@ -0,0 +1 @@ +from .methods import platform_automation_methods diff --git a/apps/assets/playbooks/base/__init__.py b/apps/assets/automations/backup/__init__.py similarity index 100% rename from apps/assets/playbooks/base/__init__.py rename to apps/assets/automations/backup/__init__.py diff --git a/apps/assets/task_handlers/backup/handlers.py b/apps/assets/automations/backup/handlers.py similarity index 100% rename from apps/assets/task_handlers/backup/handlers.py rename to apps/assets/automations/backup/handlers.py diff --git a/apps/assets/task_handlers/backup/manager.py b/apps/assets/automations/backup/manager.py similarity index 100% rename from apps/assets/task_handlers/backup/manager.py rename to apps/assets/automations/backup/manager.py diff --git a/apps/assets/playbooks/change_password/__init__.py b/apps/assets/automations/base/__init__.py similarity index 100% rename from apps/assets/playbooks/change_password/__init__.py rename to apps/assets/automations/base/__init__.py diff --git a/apps/assets/automations/base/base_inventory.txt b/apps/assets/automations/base/base_inventory.txt new file mode 100644 index 000000000..a2b73db16 --- /dev/null +++ b/apps/assets/automations/base/base_inventory.txt @@ -0,0 +1,14 @@ +## all connection vars +hostname asset_name=name asset_type=type asset_primary_protocol=ssh asset_primary_port=22 asset_protocols=[] + +## local connection +hostname ansible_connection=local + +## local connection with gateway +hostname ansible_connection=ssh ansible_user=gateway.username ansible_port=gateway.port ansible_host=gateway.host ansible_ssh_private_key_file=gateway.key + +## ssh connection for windows +hostname ansible_connection=ssh ansible_shell_type=powershell/cmd ansible_user=windows.username ansible_port=windows.port ansible_host=windows.host ansible_ssh_private_key_file=windows.key + +## ssh connection +hostname ansible_user=user ansible_password=pass ansible_host=host ansible_port=port ansible_ssh_private_key_file=key ssh_args="-o StrictHostKeyChecking=no" diff --git a/apps/assets/automations/base/manager.py b/apps/assets/automations/base/manager.py new file mode 100644 index 000000000..83097d0eb --- /dev/null +++ b/apps/assets/automations/base/manager.py @@ -0,0 +1,70 @@ +import os + +from django.conf import settings +from django.utils import timezone + +from ops.ansible import JMSInventory + + +class BasePlaybookManager: + ansible_account_policy = 'privileged_first' + + def __init__(self, execution): + self.execution = execution + self.automation = execution.automation + + def get_grouped_assets(self): + return self.automation.all_assets_group_by_platform() + + @property + def playbook_dir_path(self): + ansible_dir = settings.ANSIBLE_DIR + path = os.path.join( + ansible_dir, self.automation.type, self.automation.name, + timezone.now().strftime('%Y%m%d_%H%M%S') + ) + return path + + @property + def inventory_path(self): + return os.path.join(self.playbook_dir_path, 'inventory', 'hosts.json') + + @property + def playbook_path(self): + return os.path.join(self.playbook_dir_path, 'project', 'main.yml') + + def generate(self): + self.prepare_playbook_dir() + self.generate_inventory() + self.generate_playbook() + + def prepare_playbook_dir(self): + inventory_dir = os.path.dirname(self.inventory_path) + playbook_dir = os.path.dirname(self.playbook_path) + for d in [inventory_dir, playbook_dir]: + if not os.path.exists(d): + os.makedirs(d, exist_ok=True, mode=0o755) + + def inventory_kwargs(self): + raise NotImplemented + + def generate_inventory(self): + inventory = JMSInventory( + assets=self.automation.get_all_assets(), + account_policy=self.ansible_account_policy, + **self.inventory_kwargs() + ) + inventory.write_to_file(self.inventory_path) + print("Generate inventory done: {}".format(self.inventory_path)) + + def generate_playbook(self): + raise NotImplemented + + def get_runner(self): + raise NotImplemented + + def run(self, **kwargs): + self.generate() + runner = self.get_runner() + return runner.run(**kwargs) + diff --git a/apps/assets/playbooks/generate_playbook/__init__.py b/apps/assets/automations/change_password/__init__.py similarity index 100% rename from apps/assets/playbooks/generate_playbook/__init__.py rename to apps/assets/automations/change_password/__init__.py diff --git a/apps/assets/automations/change_password/database/change_password_mysql/main.yml b/apps/assets/automations/change_password/database/change_password_mysql/main.yml new file mode 100644 index 000000000..483554a1e --- /dev/null +++ b/apps/assets/automations/change_password/database/change_password_mysql/main.yml @@ -0,0 +1,29 @@ +- hosts: demo + tasks: + - name: ping + ping: + + #- name: print variables + # debug: + # msg: "Username: {{ account.username }}, Password: {{ account.password }}" + + - name: Change password + user: + name: "{{ account.username }}" + password: "{{ account.password | password_hash('des') }}" + update_password: always + when: account.password + + - name: Change public key + authorized_key: + user: "{{ account.username }}" + key: "{{ account.public_key }}" + state: present + when: account.public_key + + - name: Verify password + ping: + vars: + ansible_user: "{{ account.username }}" + ansible_pass: "{{ account.password }}" + ansible_ssh_connection: paramiko diff --git a/apps/assets/playbooks/change_password/database/change_password_mysql/manifest.yml b/apps/assets/automations/change_password/database/change_password_mysql/manifest.yml similarity index 100% rename from apps/assets/playbooks/change_password/database/change_password_mysql/manifest.yml rename to apps/assets/automations/change_password/database/change_password_mysql/manifest.yml diff --git a/apps/assets/automations/change_password/database/change_password_oracle/main.yml b/apps/assets/automations/change_password/database/change_password_oracle/main.yml new file mode 100644 index 000000000..483554a1e --- /dev/null +++ b/apps/assets/automations/change_password/database/change_password_oracle/main.yml @@ -0,0 +1,29 @@ +- hosts: demo + tasks: + - name: ping + ping: + + #- name: print variables + # debug: + # msg: "Username: {{ account.username }}, Password: {{ account.password }}" + + - name: Change password + user: + name: "{{ account.username }}" + password: "{{ account.password | password_hash('des') }}" + update_password: always + when: account.password + + - name: Change public key + authorized_key: + user: "{{ account.username }}" + key: "{{ account.public_key }}" + state: present + when: account.public_key + + - name: Verify password + ping: + vars: + ansible_user: "{{ account.username }}" + ansible_pass: "{{ account.password }}" + ansible_ssh_connection: paramiko diff --git a/apps/assets/playbooks/change_password/database/change_password_oracle/manifest.yml b/apps/assets/automations/change_password/database/change_password_oracle/manifest.yml similarity index 100% rename from apps/assets/playbooks/change_password/database/change_password_oracle/manifest.yml rename to apps/assets/automations/change_password/database/change_password_oracle/manifest.yml diff --git a/apps/assets/playbooks/change_password/database/change_password_mysql/main.yml b/apps/assets/automations/change_password/database/change_password_postgresql/main.yml similarity index 100% rename from apps/assets/playbooks/change_password/database/change_password_mysql/main.yml rename to apps/assets/automations/change_password/database/change_password_postgresql/main.yml diff --git a/apps/assets/playbooks/change_password/database/change_password_postgresql/manifest.yml b/apps/assets/automations/change_password/database/change_password_postgresql/manifest.yml similarity index 100% rename from apps/assets/playbooks/change_password/database/change_password_postgresql/manifest.yml rename to apps/assets/automations/change_password/database/change_password_postgresql/manifest.yml diff --git a/apps/assets/playbooks/change_password/database/change_password_mysql/roles/change_password/tasks/main.yml b/apps/assets/automations/change_password/database/change_password_postgresql/roles/change_password/tasks/main.yml similarity index 100% rename from apps/assets/playbooks/change_password/database/change_password_mysql/roles/change_password/tasks/main.yml rename to apps/assets/automations/change_password/database/change_password_postgresql/roles/change_password/tasks/main.yml diff --git a/apps/assets/playbooks/change_password/database/change_password_oracle/main.yml b/apps/assets/automations/change_password/database/change_password_sqlserver/main.yml similarity index 100% rename from apps/assets/playbooks/change_password/database/change_password_oracle/main.yml rename to apps/assets/automations/change_password/database/change_password_sqlserver/main.yml diff --git a/apps/assets/playbooks/change_password/database/change_password_sqlserver/manifest.yml b/apps/assets/automations/change_password/database/change_password_sqlserver/manifest.yml similarity index 100% rename from apps/assets/playbooks/change_password/database/change_password_sqlserver/manifest.yml rename to apps/assets/automations/change_password/database/change_password_sqlserver/manifest.yml diff --git a/apps/assets/playbooks/change_password/database/change_password_oracle/roles/change_password/tasks/main.yml b/apps/assets/automations/change_password/database/change_password_sqlserver/roles/change_password/tasks/main.yml similarity index 100% rename from apps/assets/playbooks/change_password/database/change_password_oracle/roles/change_password/tasks/main.yml rename to apps/assets/automations/change_password/database/change_password_sqlserver/roles/change_password/tasks/main.yml diff --git a/apps/assets/automations/change_password/demo_inventory.txt b/apps/assets/automations/change_password/demo_inventory.txt new file mode 100644 index 000000000..dcc7d1b6d --- /dev/null +++ b/apps/assets/automations/change_password/demo_inventory.txt @@ -0,0 +1,2 @@ +# all base inventory in base/base_inventory.txt +asset_name(ip)_account_username account={"username": "", "password": "xxx"} ...base_inventory_vars diff --git a/apps/assets/automations/change_password/host/change_password_aix/main.yml b/apps/assets/automations/change_password/host/change_password_aix/main.yml new file mode 100644 index 000000000..483554a1e --- /dev/null +++ b/apps/assets/automations/change_password/host/change_password_aix/main.yml @@ -0,0 +1,29 @@ +- hosts: demo + tasks: + - name: ping + ping: + + #- name: print variables + # debug: + # msg: "Username: {{ account.username }}, Password: {{ account.password }}" + + - name: Change password + user: + name: "{{ account.username }}" + password: "{{ account.password | password_hash('des') }}" + update_password: always + when: account.password + + - name: Change public key + authorized_key: + user: "{{ account.username }}" + key: "{{ account.public_key }}" + state: present + when: account.public_key + + - name: Verify password + ping: + vars: + ansible_user: "{{ account.username }}" + ansible_pass: "{{ account.password }}" + ansible_ssh_connection: paramiko diff --git a/apps/assets/playbooks/change_password/host/change_password_aix/manifest.yml b/apps/assets/automations/change_password/host/change_password_aix/manifest.yml similarity index 100% rename from apps/assets/playbooks/change_password/host/change_password_aix/manifest.yml rename to apps/assets/automations/change_password/host/change_password_aix/manifest.yml diff --git a/apps/assets/automations/change_password/host/change_password_linux/main.yml b/apps/assets/automations/change_password/host/change_password_linux/main.yml new file mode 100644 index 000000000..1ad590cff --- /dev/null +++ b/apps/assets/automations/change_password/host/change_password_linux/main.yml @@ -0,0 +1,29 @@ +- hosts: demo + tasks: + - name: Test privileged account + ping: + + #- name: print variables + # debug: + # msg: "Username: {{ account.username }}, Password: {{ account.password }}" + + - name: Change password + user: + name: "{{ account.username }}" + password: "{{ account.password | password_hash('des') }}" + update_password: always + when: account.secret_type == 'password' + + - name: Change public key + authorized_key: + user: "{{ account.username }}" + key: "{{ account.public_key }}" + state: present + when: account.public_key + + - name: Verify password + ping: + vars: + ansible_user: "{{ account.username }}" + ansible_pass: "{{ account.password }}" + ansible_ssh_connection: paramiko diff --git a/apps/assets/playbooks/change_password/host/change_password_linux/manifest.yml b/apps/assets/automations/change_password/host/change_password_linux/manifest.yml similarity index 100% rename from apps/assets/playbooks/change_password/host/change_password_linux/manifest.yml rename to apps/assets/automations/change_password/host/change_password_linux/manifest.yml diff --git a/apps/assets/automations/change_password/host/change_password_local_windows/main.yml b/apps/assets/automations/change_password/host/change_password_local_windows/main.yml new file mode 100644 index 000000000..483554a1e --- /dev/null +++ b/apps/assets/automations/change_password/host/change_password_local_windows/main.yml @@ -0,0 +1,29 @@ +- hosts: demo + tasks: + - name: ping + ping: + + #- name: print variables + # debug: + # msg: "Username: {{ account.username }}, Password: {{ account.password }}" + + - name: Change password + user: + name: "{{ account.username }}" + password: "{{ account.password | password_hash('des') }}" + update_password: always + when: account.password + + - name: Change public key + authorized_key: + user: "{{ account.username }}" + key: "{{ account.public_key }}" + state: present + when: account.public_key + + - name: Verify password + ping: + vars: + ansible_user: "{{ account.username }}" + ansible_pass: "{{ account.password }}" + ansible_ssh_connection: paramiko diff --git a/apps/assets/playbooks/change_password/host/change_password_local_windows/manifest.yml b/apps/assets/automations/change_password/host/change_password_local_windows/manifest.yml similarity index 100% rename from apps/assets/playbooks/change_password/host/change_password_local_windows/manifest.yml rename to apps/assets/automations/change_password/host/change_password_local_windows/manifest.yml diff --git a/apps/assets/automations/change_password/manager.py b/apps/assets/automations/change_password/manager.py new file mode 100644 index 000000000..ea0bb9a26 --- /dev/null +++ b/apps/assets/automations/change_password/manager.py @@ -0,0 +1,91 @@ +import os +import shutil +from copy import deepcopy +from collections import defaultdict + +import yaml +from django.utils.translation import gettext as _ + +from ops.ansible import PlaybookRunner, JMSInventory +from ..base.manager import BasePlaybookManager +from assets.automations.methods import platform_automation_methods + + +class ChangePasswordManager(BasePlaybookManager): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.id_method_mapper = { + method['id']: method + for method in platform_automation_methods + } + self.method_hosts_mapper = defaultdict(list) + + def host_duplicator(self, host, asset=None, account=None, platform=None, **kwargs): + accounts = asset.accounts.all() + if account: + accounts = accounts.exclude(id=account.id) + if '*' not in self.automation.accounts: + accounts = accounts.filter(username__in=self.automation.accounts) + + automation = platform.automation + change_password_enabled = automation and \ + automation.change_password_enabled and \ + automation.change_password_method and \ + automation.change_password_method in self.id_method_mapper + + if not change_password_enabled: + host.exclude = _('Change password disabled') + return [host] + + hosts = [] + for account in accounts: + h = deepcopy(host) + h['name'] += '_' + account.username + h['account'] = { + 'name': account.name, + 'username': account.username, + 'secret_type': account.secret_type, + 'secret': account.secret, + } + hosts.append(h) + self.method_hosts_mapper[automation.change_password_method].append(h['name']) + return hosts + + def inventory_kwargs(self): + return { + 'host_duplicator': self.host_duplicator + } + + def generate_playbook(self): + playbook = [] + for method_id, host_names in self.method_hosts_mapper.items(): + method = self.id_method_mapper[method_id] + playbook_dir_path = method['dir'] + playbook_dir_name = os.path.dirname(playbook_dir_path) + shutil.copytree(playbook_dir_path, self.playbook_dir_path) + sub_playbook_path = os.path.join(self.playbook_dir_path, playbook_dir_name, 'main.yml') + + with open(sub_playbook_path, 'r') as f: + host_playbook_play = yaml.safe_load(f) + + plays = [] + for name in host_names: + play = deepcopy(host_playbook_play) + play['hosts'] = name + plays.append(play) + + with open(sub_playbook_path, 'w') as f: + yaml.safe_dump(plays, f, default_flow_style=False) + + playbook.append({ + 'name': method['name'], + 'import_playbook': playbook_dir_name + '/' + 'main.yml' + }) + + with open(self.playbook_path, 'w') as f: + yaml.safe_dump(playbook, f, default_flow_style=False) + + print("Generate playbook done: " + self.playbook_path) + + + diff --git a/apps/assets/automations/endpoint.py b/apps/assets/automations/endpoint.py new file mode 100644 index 000000000..f99defdd8 --- /dev/null +++ b/apps/assets/automations/endpoint.py @@ -0,0 +1,7 @@ +# from .backup.manager import AccountBackupExecutionManager +# +# +class ExecutionManager: + manager_type = { + } + diff --git a/apps/assets/task_handlers/backup/__init__.py b/apps/assets/automations/generate_playbook/__init__.py similarity index 100% rename from apps/assets/task_handlers/backup/__init__.py rename to apps/assets/automations/generate_playbook/__init__.py diff --git a/apps/assets/playbooks/generate_playbook/change_password.py b/apps/assets/automations/generate_playbook/change_password.py similarity index 100% rename from apps/assets/playbooks/generate_playbook/change_password.py rename to apps/assets/automations/generate_playbook/change_password.py diff --git a/apps/assets/playbooks/generate_playbook/verify.py b/apps/assets/automations/generate_playbook/verify.py similarity index 100% rename from apps/assets/playbooks/generate_playbook/verify.py rename to apps/assets/automations/generate_playbook/verify.py diff --git a/apps/assets/playbooks/__init__.py b/apps/assets/automations/methods.py similarity index 96% rename from apps/assets/playbooks/__init__.py rename to apps/assets/automations/methods.py index 59f705fb9..811d0c77d 100644 --- a/apps/assets/playbooks/__init__.py +++ b/apps/assets/automations/methods.py @@ -1,5 +1,6 @@ import os import yaml +import json from functools import partial BASE_DIR = os.path.dirname(os.path.abspath(__file__)) @@ -62,4 +63,4 @@ platform_automation_methods = get_platform_automation_methods() if __name__ == '__main__': - print(get_platform_automation_methods()) + print(json.dumps(platform_automation_methods, indent=4)) diff --git a/apps/assets/const/types.py b/apps/assets/const/types.py index 454a5d358..0d8b86afa 100644 --- a/apps/assets/const/types.py +++ b/apps/assets/const/types.py @@ -38,7 +38,7 @@ class AllTypes(ChoicesMixin): @classmethod def set_automation_methods(cls, category, tp, constraints): - from assets.playbooks import filter_platform_methods + from assets.automations import filter_platform_methods automation = constraints.get('automation', {}) automation_methods = {} for item, enabled in automation.items(): diff --git a/apps/assets/models/__init__.py b/apps/assets/models/__init__.py index e79b2fff5..376355657 100644 --- a/apps/assets/models/__init__.py +++ b/apps/assets/models/__init__.py @@ -10,6 +10,7 @@ from .gathered_user import * from .favorite_asset import * from .account import * from .backup import * +from .automations import * from ._user import * # 废弃以下 # from ._authbook import * diff --git a/apps/assets/models/asset/common.py b/apps/assets/models/asset/common.py index ef64e5fb6..5703c82dc 100644 --- a/apps/assets/models/asset/common.py +++ b/apps/assets/models/asset/common.py @@ -4,6 +4,7 @@ import logging import uuid +from collections import defaultdict from django.db import models from django.db.models import Q @@ -41,6 +42,12 @@ class AssetQuerySet(models.QuerySet): def has_protocol(self, name): return self.filter(protocols__contains=name) + def group_by_platform(self) -> dict: + groups = defaultdict(list) + for asset in self.all(): + groups[asset.platform].append(asset) + return groups + class NodesRelationMixin: NODES_CACHE_KEY = 'ASSET_NODES_{}' @@ -126,6 +133,22 @@ class Asset(AbsConnectivity, NodesRelationMixin, JMSOrgBaseModel): names.append(n.name + ':' + n.value) return names + @lazyproperty + def primary_protocol(self): + return self.protocols.first() + + @lazyproperty + def protocol(self): + if not self.primary_protocol: + return 'none' + return self.primary_protocol.name + + @lazyproperty + def port(self): + if not self.primary_protocol: + return 0 + return self.primary_protocol.port + @property def protocols_as_list(self): return [{'name': p.name, 'port': p.port} for p in self.protocols.all()] diff --git a/apps/assets/models/automation/__init__.py b/apps/assets/models/automations/__init__.py similarity index 100% rename from apps/assets/models/automation/__init__.py rename to apps/assets/models/automations/__init__.py diff --git a/apps/assets/models/automation/account_discovery.py b/apps/assets/models/automations/account_discovery.py similarity index 89% rename from apps/assets/models/automation/account_discovery.py rename to apps/assets/models/automations/account_discovery.py index bfe9d0d80..9572986f3 100644 --- a/apps/assets/models/automation/account_discovery.py +++ b/apps/assets/models/automations/account_discovery.py @@ -1,6 +1,7 @@ from django.utils.translation import ugettext_lazy as _ from ops.const import StrategyChoice +from ops.ansible.runner import PlaybookRunner from .base import BaseAutomation diff --git a/apps/assets/models/automation/account_reconcile.py b/apps/assets/models/automations/account_reconcile.py similarity index 100% rename from apps/assets/models/automation/account_reconcile.py rename to apps/assets/models/automations/account_reconcile.py diff --git a/apps/assets/models/automation/account_verify.py b/apps/assets/models/automations/account_verify.py similarity index 100% rename from apps/assets/models/automation/account_verify.py rename to apps/assets/models/automations/account_verify.py diff --git a/apps/assets/models/automation/base.py b/apps/assets/models/automations/base.py similarity index 54% rename from apps/assets/models/automation/base.py rename to apps/assets/models/automations/base.py index a9b8ab087..ba0d393ea 100644 --- a/apps/assets/models/automation/base.py +++ b/apps/assets/models/automations/base.py @@ -8,16 +8,17 @@ from common.db.fields import EncryptJsonDictTextField from orgs.mixins.models import OrgModelMixin, JMSOrgBaseModel from ops.mixin import PeriodTaskModelMixin from ops.tasks import execute_automation_strategy -from ops.task_handlers import ExecutionManager +from assets.models import Node, Asset +from assets.automations.endpoint import ExecutionManager class BaseAutomation(JMSOrgBaseModel, PeriodTaskModelMixin): accounts = models.JSONField(default=list, verbose_name=_("Accounts")) nodes = models.ManyToManyField( - 'assets.Node', related_name='automation_strategy', blank=True, verbose_name=_("Nodes") + 'assets.Node', blank=True, verbose_name=_("Nodes") ) assets = models.ManyToManyField( - 'assets.Asset', related_name='automation_strategy', blank=True, verbose_name=_("Assets") + 'assets.Asset', blank=True, verbose_name=_("Assets") ) type = models.CharField(max_length=16, verbose_name=_('Type')) comment = models.TextField(blank=True, verbose_name=_('Comment')) @@ -25,6 +26,17 @@ class BaseAutomation(JMSOrgBaseModel, PeriodTaskModelMixin): def __str__(self): return self.name + '@' + str(self.created_by) + def get_all_assets(self): + nodes = self.nodes.all() + node_asset_ids = Node.get_nodes_all_assets(*nodes).values_list('id', flat=True) + direct_asset_ids = self.assets.all().values_list('id', flat=True) + asset_ids = set(list(direct_asset_ids) + list(node_asset_ids)) + return Asset.objects.filter(id__in=asset_ids) + + def all_assets_group_by_platform(self): + assets = self.get_all_assets().prefetch_related('platform') + return assets.group_by_platform() + def get_register_task(self): name = "automation_strategy_period_{}".format(str(self.id)[:8]) task = execute_automation_strategy.name @@ -40,13 +52,15 @@ class BaseAutomation(JMSOrgBaseModel, PeriodTaskModelMixin): 'nodes': list(self.assets.all().values_list('id', flat=True)), } - def execute(self, trigger): + def execute(self, trigger=Trigger.manual): try: eid = current_task.request.id except AttributeError: eid = str(uuid.uuid4()) - execution = AutomationStrategyExecution.objects.create( - id=eid, strategy=self, snapshot=self.to_attr_json(), trigger=trigger + + execution = AutomationExecution.objects.create( + id=eid, strategy=self, trigger=trigger, + snapshot=self.to_attr_json(), ) return execution.start() @@ -55,22 +69,22 @@ class BaseAutomation(JMSOrgBaseModel, PeriodTaskModelMixin): verbose_name = _("Automation plan") -class AutomationStrategyExecution(OrgModelMixin): +class AutomationExecution(OrgModelMixin): id = models.UUIDField(default=uuid.uuid4, primary_key=True) - - date_created = models.DateTimeField(auto_now_add=True) - timedelta = models.FloatField(default=0.0, verbose_name=_('Time'), null=True) - date_start = models.DateTimeField(auto_now_add=True, verbose_name=_('Date start')) - + automation = models.ForeignKey( + 'BaseAutomation', related_name='executions', on_delete=models.CASCADE, + verbose_name=_('Automation strategy') + ) + status = models.CharField(max_length=16, default='pending') + date_created = models.DateTimeField(auto_now_add=True, verbose_name=_('Date created')) + date_start = models.DateTimeField(null=True, verbose_name=_('Date start'), db_index=True) + date_finished = models.DateTimeField(null=True, verbose_name=_("Date finished")) snapshot = EncryptJsonDictTextField( default=dict, blank=True, null=True, verbose_name=_('Automation snapshot') ) - strategy = models.ForeignKey( - 'BaseAutomation', related_name='execution', on_delete=models.CASCADE, - verbose_name=_('Automation strategy') - ) trigger = models.CharField( - max_length=128, default=Trigger.manual, choices=Trigger.choices, verbose_name=_('Trigger mode') + max_length=128, default=Trigger.manual, choices=Trigger.choices, + verbose_name=_('Trigger mode') ) class Meta: @@ -83,28 +97,3 @@ class AutomationStrategyExecution(OrgModelMixin): def start(self): manager = ExecutionManager(execution=self) return manager.run() - - -class AutomationStrategyTask(OrgModelMixin): - id = models.UUIDField(default=uuid.uuid4, primary_key=True) - asset = models.ForeignKey( - 'assets.Asset', on_delete=models.CASCADE, verbose_name=_('Asset') - ) - account = models.ForeignKey( - 'assets.Account', on_delete=models.CASCADE, verbose_name=_('Account') - ) - is_success = models.BooleanField(default=False, verbose_name=_('Is success')) - timedelta = models.FloatField(default=0.0, null=True, verbose_name=_('Time')) - date_start = models.DateTimeField(auto_now_add=True, verbose_name=_('Date start')) - reason = models.CharField(max_length=1024, blank=True, null=True, verbose_name=_('Reason')) - execution = models.ForeignKey( - 'AutomationStrategyExecution', related_name='task', on_delete=models.CASCADE, - verbose_name=_('Automation strategy execution') - ) - - class Meta: - verbose_name = _('Automation strategy task') - - @property - def handler_type(self): - return self.execution.snapshot['type'] diff --git a/apps/assets/models/automation/change_secret.py b/apps/assets/models/automations/change_secret.py similarity index 96% rename from apps/assets/models/automation/change_secret.py rename to apps/assets/models/automations/change_secret.py index d176f5c6a..4a2c304c2 100644 --- a/apps/assets/models/automation/change_secret.py +++ b/apps/assets/models/automations/change_secret.py @@ -2,7 +2,7 @@ from django.db import models from django.utils.translation import ugettext_lazy as _ from common.db import fields -from ops.const import SSHKeyStrategy, PasswordStrategy, StrategyChoice +from ops.const import PasswordStrategy, StrategyChoice from ops.utils import generate_random_password from .base import BaseAutomation diff --git a/apps/assets/playbooks/base/generator.py b/apps/assets/playbooks/base/generator.py deleted file mode 100644 index 972d12409..000000000 --- a/apps/assets/playbooks/base/generator.py +++ /dev/null @@ -1,33 +0,0 @@ -import os -import time -import shutil -from typing import List - -from django.conf import settings - -from assets.models import Asset - - -class BaseRunner: - src_filepath: str - - def __init__(self, assets: List[Asset], strategy): - self.assets = assets - self.strategy = strategy - self.temp_folder = self.temp_folder_path() - - @staticmethod - def temp_folder_path(): - project_dir = settings.PROJECT_DIR - tmp_dir = os.path.join(project_dir, 'tmp') - filepath = os.path.join(tmp_dir, str(time.time())) - return filepath - - def del_temp_folder(self): - shutil.rmtree(self.temp_folder) - - def generate_temp_playbook(self): - src = self.src_filepath - dst = os.path.join(self.temp_folder, self.strategy) - shutil.copytree(src, dst) - return dst diff --git a/apps/assets/playbooks/base/runner.py b/apps/assets/playbooks/base/runner.py deleted file mode 100644 index 1370db6ba..000000000 --- a/apps/assets/playbooks/base/runner.py +++ /dev/null @@ -1,47 +0,0 @@ -import os -import tempfile -import shutil -from typing import List - -from django.conf import settings - -from assets.models import Asset - - -class BasePlaybookGenerator: - def __init__(self, assets: list[Asset], strategy, ansible_connection='ssh'): - self.assets = assets - self.strategy = strategy - self.playbook_dir = self.temp_folder_path() - - def generate(self): - self.prepare_playbook_dir() - self.generate_inventory() - self.generate_playbook() - - def prepare_playbook_dir(self): - pass - - def generate_inventory(self): - pass - - def generate_playbook(self): - pass - - @property - def base_dir(self): - tmp_dir = os.path.join(settings.PROJECT_DIR, 'tmp') - path = os.path.join(tmp_dir, self.strategy) - return path - - def temp_folder_path(self): - return tempfile.mkdtemp(dir=self.base_dir) - - def del_temp_folder(self): - shutil.rmtree(self.playbook_dir) - - def generate_temp_playbook(self): - src = self.src_filepath - dst = os.path.join(self.temp_folder, self.strategy) - shutil.copytree(src, dst) - return dst diff --git a/apps/assets/playbooks/change_password/database/change_password_postgresql/main.yml b/apps/assets/playbooks/change_password/database/change_password_postgresql/main.yml deleted file mode 100644 index 402c7fa8d..000000000 --- a/apps/assets/playbooks/change_password/database/change_password_postgresql/main.yml +++ /dev/null @@ -1,10 +0,0 @@ -{% for account in accounts %} -- hosts: {{ account.asset.name }} - vars: - account: - username: {{ account.username }} - password: {{ account.password }} - public_key: {{ account.public_key }} - roles: - - change_password -{% endfor %} diff --git a/apps/assets/playbooks/change_password/database/change_password_postgresql/roles/change_password/tasks/main.yml b/apps/assets/playbooks/change_password/database/change_password_postgresql/roles/change_password/tasks/main.yml deleted file mode 100644 index 903cd9115..000000000 --- a/apps/assets/playbooks/change_password/database/change_password_postgresql/roles/change_password/tasks/main.yml +++ /dev/null @@ -1,27 +0,0 @@ -- name: ping - ping: - -#- name: print variables -# debug: -# msg: "Username: {{ account.username }}, Password: {{ account.password }}" - -- name: Change password - user: - name: "{{ account.username }}" - password: "{{ account.password | password_hash('des') }}" - update_password: always - when: account.password - -- name: Change public key - authorized_key: - user: "{{ account.username }}" - key: "{{ account.public_key }}" - state: present - when: account.public_key - -- name: Verify password - ping: - vars: - ansible_user: "{{ account.username }}" - ansible_pass: "{{ account.password }}" - ansible_ssh_connection: paramiko diff --git a/apps/assets/playbooks/change_password/database/change_password_sqlserver/main.yml b/apps/assets/playbooks/change_password/database/change_password_sqlserver/main.yml deleted file mode 100644 index 402c7fa8d..000000000 --- a/apps/assets/playbooks/change_password/database/change_password_sqlserver/main.yml +++ /dev/null @@ -1,10 +0,0 @@ -{% for account in accounts %} -- hosts: {{ account.asset.name }} - vars: - account: - username: {{ account.username }} - password: {{ account.password }} - public_key: {{ account.public_key }} - roles: - - change_password -{% endfor %} diff --git a/apps/assets/playbooks/change_password/database/change_password_sqlserver/roles/change_password/tasks/main.yml b/apps/assets/playbooks/change_password/database/change_password_sqlserver/roles/change_password/tasks/main.yml deleted file mode 100644 index 903cd9115..000000000 --- a/apps/assets/playbooks/change_password/database/change_password_sqlserver/roles/change_password/tasks/main.yml +++ /dev/null @@ -1,27 +0,0 @@ -- name: ping - ping: - -#- name: print variables -# debug: -# msg: "Username: {{ account.username }}, Password: {{ account.password }}" - -- name: Change password - user: - name: "{{ account.username }}" - password: "{{ account.password | password_hash('des') }}" - update_password: always - when: account.password - -- name: Change public key - authorized_key: - user: "{{ account.username }}" - key: "{{ account.public_key }}" - state: present - when: account.public_key - -- name: Verify password - ping: - vars: - ansible_user: "{{ account.username }}" - ansible_pass: "{{ account.password }}" - ansible_ssh_connection: paramiko diff --git a/apps/assets/playbooks/change_password/host/change_password_aix/main.yml b/apps/assets/playbooks/change_password/host/change_password_aix/main.yml deleted file mode 100644 index 402c7fa8d..000000000 --- a/apps/assets/playbooks/change_password/host/change_password_aix/main.yml +++ /dev/null @@ -1,10 +0,0 @@ -{% for account in accounts %} -- hosts: {{ account.asset.name }} - vars: - account: - username: {{ account.username }} - password: {{ account.password }} - public_key: {{ account.public_key }} - roles: - - change_password -{% endfor %} diff --git a/apps/assets/playbooks/change_password/host/change_password_aix/roles/change_password/tasks/main.yml b/apps/assets/playbooks/change_password/host/change_password_aix/roles/change_password/tasks/main.yml deleted file mode 100644 index 903cd9115..000000000 --- a/apps/assets/playbooks/change_password/host/change_password_aix/roles/change_password/tasks/main.yml +++ /dev/null @@ -1,27 +0,0 @@ -- name: ping - ping: - -#- name: print variables -# debug: -# msg: "Username: {{ account.username }}, Password: {{ account.password }}" - -- name: Change password - user: - name: "{{ account.username }}" - password: "{{ account.password | password_hash('des') }}" - update_password: always - when: account.password - -- name: Change public key - authorized_key: - user: "{{ account.username }}" - key: "{{ account.public_key }}" - state: present - when: account.public_key - -- name: Verify password - ping: - vars: - ansible_user: "{{ account.username }}" - ansible_pass: "{{ account.password }}" - ansible_ssh_connection: paramiko diff --git a/apps/assets/playbooks/change_password/host/change_password_linux/main.yml b/apps/assets/playbooks/change_password/host/change_password_linux/main.yml deleted file mode 100644 index a7d0f9417..000000000 --- a/apps/assets/playbooks/change_password/host/change_password_linux/main.yml +++ /dev/null @@ -1,8 +0,0 @@ -- hosts: all - vars: - account: - username: {{ account.username }} - password: {{ account.password }} - public_key: {{ account.public_key }} - roles: - - change_password diff --git a/apps/assets/playbooks/change_password/host/change_password_linux/roles/change_password/tasks/main.yml b/apps/assets/playbooks/change_password/host/change_password_linux/roles/change_password/tasks/main.yml deleted file mode 100644 index e0ba9c73f..000000000 --- a/apps/assets/playbooks/change_password/host/change_password_linux/roles/change_password/tasks/main.yml +++ /dev/null @@ -1,23 +0,0 @@ -- name: Check connection - ping: - -- name: Change password - user: - name: "{{ account.username }}" - password: "{{ account.password | password_hash('sha512') }}" - update_password: always - when: account.password - -- name: Change public key - authorized_key: - user: "{{ account.username }}" - key: "{{ account.public_key }}" - state: present - when: account.public_key - -- name: Verify password - ping: - vars: - ansible_user: "{{ account.username }}" - ansible_pass: "{{ account.password }}" - ansible_ssh_connection: paramiko diff --git a/apps/assets/playbooks/change_password/host/change_password_local_windows/main.yml b/apps/assets/playbooks/change_password/host/change_password_local_windows/main.yml deleted file mode 100644 index 402c7fa8d..000000000 --- a/apps/assets/playbooks/change_password/host/change_password_local_windows/main.yml +++ /dev/null @@ -1,10 +0,0 @@ -{% for account in accounts %} -- hosts: {{ account.asset.name }} - vars: - account: - username: {{ account.username }} - password: {{ account.password }} - public_key: {{ account.public_key }} - roles: - - change_password -{% endfor %} diff --git a/apps/assets/playbooks/change_password/host/change_password_local_windows/roles/change_password/tasks/main.yml b/apps/assets/playbooks/change_password/host/change_password_local_windows/roles/change_password/tasks/main.yml deleted file mode 100644 index 903cd9115..000000000 --- a/apps/assets/playbooks/change_password/host/change_password_local_windows/roles/change_password/tasks/main.yml +++ /dev/null @@ -1,27 +0,0 @@ -- name: ping - ping: - -#- name: print variables -# debug: -# msg: "Username: {{ account.username }}, Password: {{ account.password }}" - -- name: Change password - user: - name: "{{ account.username }}" - password: "{{ account.password | password_hash('des') }}" - update_password: always - when: account.password - -- name: Change public key - authorized_key: - user: "{{ account.username }}" - key: "{{ account.public_key }}" - state: present - when: account.public_key - -- name: Verify password - ping: - vars: - ansible_user: "{{ account.username }}" - ansible_pass: "{{ account.password }}" - ansible_ssh_connection: paramiko diff --git a/apps/assets/playbooks/host/ansible_posix_ping/main.yml b/apps/assets/playbooks/host/ansible_posix_ping/main.yml deleted file mode 100644 index 4ccdb3074..000000000 --- a/apps/assets/playbooks/host/ansible_posix_ping/main.yml +++ /dev/null @@ -1,13 +0,0 @@ -- hosts: centos - gather_facts: no - vars: - account: - username: web - password: test123 - - tasks: - - name: Verify password - ping: - vars: - ansible_user: "{{ account.username }}" - ansible_pass: "{{ account.password }}" diff --git a/apps/assets/playbooks/host/ansible_posix_ping/manifest.yml b/apps/assets/playbooks/host/ansible_posix_ping/manifest.yml deleted file mode 100644 index 6cd223f1c..000000000 --- a/apps/assets/playbooks/host/ansible_posix_ping/manifest.yml +++ /dev/null @@ -1,10 +0,0 @@ -id: ansible_posix_ping -name: Ansible posix ping -description: Ansible ping -category: host -type: - - linux - - unix - - macos - - bsd -method: verify_account diff --git a/apps/assets/playbooks/host/ansible_win_ping/main.yml b/apps/assets/playbooks/host/ansible_win_ping/main.yml deleted file mode 100644 index 726d04a53..000000000 --- a/apps/assets/playbooks/host/ansible_win_ping/main.yml +++ /dev/null @@ -1,13 +0,0 @@ -- hosts: centos - gather_facts: no - vars: - account: - username: web - password: test123 - - tasks: - - name: Verify password - win_ping: - vars: - ansible_user: "{{ account.username }}" - ansible_pass: "{{ account.password }}" diff --git a/apps/assets/playbooks/host/ansible_win_ping/manifest.yml b/apps/assets/playbooks/host/ansible_win_ping/manifest.yml deleted file mode 100644 index fe881de3b..000000000 --- a/apps/assets/playbooks/host/ansible_win_ping/manifest.yml +++ /dev/null @@ -1,6 +0,0 @@ -id: ansible_win_ping -name: Ansible win ping -category: host -type: - - windows -method: verify_account diff --git a/apps/assets/playbooks/strategy/change_password/roles/linux/main.yml b/apps/assets/playbooks/strategy/change_password/roles/linux/main.yml deleted file mode 100644 index 16f0d1037..000000000 --- a/apps/assets/playbooks/strategy/change_password/roles/linux/main.yml +++ /dev/null @@ -1,12 +0,0 @@ -- hosts: all - vars: - connection_type: ssh - password: - value: {{ password }} - public_key: - value: {{ jms_key }} - exclusive: {{ exclusive }} - key_strategy: {{ key_strategy }} - private_key_file: {{ private_key_file }} - roles: - - linux diff --git a/apps/assets/playbooks/strategy/change_password/roles/linux/tasks/main.yml b/apps/assets/playbooks/strategy/change_password/roles/linux/tasks/main.yml deleted file mode 100644 index cc9467ca1..000000000 --- a/apps/assets/playbooks/strategy/change_password/roles/linux/tasks/main.yml +++ /dev/null @@ -1,36 +0,0 @@ -- name: Check connection - ping: - -- name: Change password - user: - name: "{{ item }}" - password: "{{ password.value | password_hash('sha512') }}" - update_password: always - with_items: "{{ usernames }}" - when: "{{ password.value }}" - -- name: Change public key - authorized_key: - user: "{{ item }}" - key: "{{ lookup('file', id_rsa.pub) }}" - state: present - exclusive: "{{ public_key.exclusive }}" - with_items: "{{ usernames }}" - when: "{{ public_key.value and key_strategy != 'set_jms' }}" - -- name: Change public key - lineinfile: - user: "{{ item }}" - dest: /home/{{ item }}/.ssh/authorized_keys regexp='.*{{ public_key.value }}$ - state: absent - with_items: "{{ usernames }}" - when: "{{ public_key.value and key_strategy == 'set_jms' }}" - -- name: Verify user - ping: - vars: - ansible_user: "{{ item }}" - ansible_pass: "{{ password.value }}" - ansible_ssh_private_key_file: "{{ private_key_file }}" - ansible_connection: "{{ connection_type | default('ssh') }}" - with_items: "{{ usernames }}" diff --git a/apps/assets/playbooks/strategy/verify/roles/linux/main.yml b/apps/assets/playbooks/strategy/verify/roles/linux/main.yml deleted file mode 100644 index 03c666df7..000000000 --- a/apps/assets/playbooks/strategy/verify/roles/linux/main.yml +++ /dev/null @@ -1,5 +0,0 @@ -- hosts: all - vars: - connection_type: ssh - roles: - - linux diff --git a/apps/assets/playbooks/strategy/verify/roles/linux/tasks/main.yml b/apps/assets/playbooks/strategy/verify/roles/linux/tasks/main.yml deleted file mode 100644 index ff9e1eb99..000000000 --- a/apps/assets/playbooks/strategy/verify/roles/linux/tasks/main.yml +++ /dev/null @@ -1,8 +0,0 @@ -- name: Verify user - ping: - vars: - ansible_user: "{{ item.username }}" - ansible_pass: "{{ item.username }}" - ansible_connection: "{{ connection_type | default('ssh') }}" - ansible_ssh_private_key_file: "{{ item.private_key_file }}" - with_items: "{{ account_info }}" diff --git a/apps/assets/task_handlers/__init__.py b/apps/assets/task_handlers/__init__.py deleted file mode 100644 index d557c449e..000000000 --- a/apps/assets/task_handlers/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .endpoint import * diff --git a/apps/assets/task_handlers/endpoint.py b/apps/assets/task_handlers/endpoint.py deleted file mode 100644 index 729fc8648..000000000 --- a/apps/assets/task_handlers/endpoint.py +++ /dev/null @@ -1,10 +0,0 @@ -from .backup.manager import AccountBackupExecutionManager - - -class ExecutionManager: - manager_type = { - 'backup': AccountBackupExecutionManager - } - - def __new__(cls, execution): - return AccountBackupExecutionManager(execution) diff --git a/apps/ops/ansible/callback.py b/apps/ops/ansible/callback.py index 59734b07d..84e106e64 100644 --- a/apps/ops/ansible/callback.py +++ b/apps/ops/ansible/callback.py @@ -71,7 +71,7 @@ class DefaultCallback: def runner_on_start(self, event_data, **kwargs): pass - def runer_retry(self, event_data, **kwargs): + def runner_retry(self, event_data, **kwargs): pass def runner_on_file_diff(self, event_data, **kwargs): diff --git a/apps/ops/ansible/inventory.py b/apps/ops/ansible/inventory.py index 6a7e3c5aa..5528f1a14 100644 --- a/apps/ops/ansible/inventory.py +++ b/apps/ops/ansible/inventory.py @@ -1,7 +1,7 @@ # ~*~ coding: utf-8 ~*~ -from collections import defaultdict import json import os +from collections import defaultdict from django.utils.translation import gettext as _ @@ -10,7 +10,7 @@ __all__ = ['JMSInventory'] class JMSInventory: - def __init__(self, assets, account='', account_policy='smart', host_var_callback=None): + def __init__(self, assets, account='', account_policy='smart', host_var_callback=None, host_duplicator=None): """ :param assets: :param account: account username name if not set use account_policy @@ -21,6 +21,7 @@ class JMSInventory: self.account_username = account self.account_policy = account_policy self.host_var_callback = host_var_callback + self.host_duplicator = host_duplicator @staticmethod def clean_assets(assets): @@ -59,11 +60,16 @@ class JMSInventory: return {"ansible_ssh_common_args": proxy_command} def asset_to_host(self, asset, account, automation, protocols): - host = {'name': asset.name, 'vars': { - 'asset_id': str(asset.id), 'asset_name': asset.name, - 'asset_type': asset.type, 'asset_category': asset.category, + host = { + 'name': asset.name, + 'asset': { + 'id': asset.id, 'name': asset.name, 'ip': asset.ip, + 'type': asset.type, 'category': asset.category, + 'protocol': asset.protocol, 'port': asset.port, + 'protocols': [{'name': p.name, 'port': p.port} for p in protocols], + }, 'exclude': '' - }} + } ansible_connection = automation.ansible_config.get('ansible_connection', 'ssh') gateway = None if asset.domain: @@ -91,15 +97,15 @@ class JMSInventory: elif account.secret_type == 'private_key' and account.secret: host['ssh_private_key'] = account.private_key_file else: - host['vars']['exclude'] = _("No account found") + host['exclude'] = _("No account found") if gateway: - host['vars'].update(self.make_proxy_command(gateway)) + host.update(self.make_proxy_command(gateway)) if self.host_var_callback: callback_var = self.host_var_callback(asset) if isinstance(callback_var, dict): - host['vars'].update(callback_var) + host.update(callback_var) return host def select_account(self, asset): @@ -137,8 +143,11 @@ class JMSInventory: account = self.select_account(asset) host = self.asset_to_host(asset, account, automation, protocols) if not automation.ansible_enabled: - host['vars']['exclude'] = _('Ansible disabled') - hosts.append(host) + host['exclude'] = _('Ansible disabled') + if self.host_duplicator: + hosts.extend(self.host_duplicator(host, asset=asset, account=account, platform=platform)) + else: + hosts.append(host) exclude_hosts = list(filter(lambda x: x.get('exclude'), hosts)) if exclude_hosts: @@ -150,8 +159,6 @@ class JMSInventory: data = {'all': {'hosts': {}}} for host in hosts: name = host.pop('name') - var = host.pop('vars', {}) - host.update(var) data['all']['hosts'][name] = host return data diff --git a/apps/ops/models/base.py b/apps/ops/models/base.py index f43e0c584..e91af13a6 100644 --- a/apps/ops/models/base.py +++ b/apps/ops/models/base.py @@ -52,7 +52,7 @@ class BaseAnsibleExecution(models.Model): creator = models.ForeignKey('users.User', verbose_name=_("Creator"), on_delete=models.SET_NULL, null=True) date_created = models.DateTimeField(auto_now_add=True, verbose_name=_('Date created')) date_start = models.DateTimeField(null=True, verbose_name=_('Date start'), db_index=True) - date_finished = models.DateTimeField(null=True) + date_finished = models.DateTimeField(null=True, verbose_name=_("Date finished")) class Meta: abstract = True diff --git a/apps/ops/task_handlers/__init__.py b/apps/ops/task_handlers/__init__.py deleted file mode 100644 index d557c449e..000000000 --- a/apps/ops/task_handlers/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .endpoint import * diff --git a/apps/ops/task_handlers/base/__init__.py b/apps/ops/task_handlers/base/__init__.py deleted file mode 100644 index 2dc0b1a17..000000000 --- a/apps/ops/task_handlers/base/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from .manager import * -from .handlers import * diff --git a/apps/ops/task_handlers/base/handlers.py b/apps/ops/task_handlers/base/handlers.py deleted file mode 100644 index 1df6d946c..000000000 --- a/apps/ops/task_handlers/base/handlers.py +++ /dev/null @@ -1,16 +0,0 @@ -""" -执行改密计划的基类 -""" -from common.utils import get_logger - -logger = get_logger(__file__) - - -class BaseHandler: - def __init__(self, task, show_step_info=True): - self.task = task - self.conn = None - self.retry_times = 3 - self.current_step = 0 - self.is_frozen = False # 任务状态冻结标志 - self.show_step_info = show_step_info diff --git a/apps/ops/task_handlers/base/manager.py b/apps/ops/task_handlers/base/manager.py deleted file mode 100644 index 080bf866c..000000000 --- a/apps/ops/task_handlers/base/manager.py +++ /dev/null @@ -1,78 +0,0 @@ -# -*- coding: utf-8 -*- -# -import time -from openpyxl import Workbook -from django.utils import timezone - -from common.utils import get_logger -from common.utils.timezone import local_now_display - -logger = get_logger(__file__) - - -class BaseExecutionManager: - task_back_up_serializer: None - - def __init__(self, execution): - self.execution = execution - self.date_start = timezone.now() - self.time_start = time.time() - self.date_end = None - self.time_end = None - self.timedelta = 0 - self.total_tasks = [] - - def on_tasks_pre_run(self, tasks): - raise NotImplementedError - - def on_per_task_pre_run(self, task, total, index): - raise NotImplementedError - - def create_csv_file(self, tasks, file_name): - raise NotImplementedError - - def get_handler_cls(self): - raise NotImplemented - - def do_run(self): - tasks = self.total_tasks = self.execution.create_plan_tasks() - self.on_tasks_pre_run(tasks) - total = len(tasks) - - for index, task in enumerate(tasks, start=1): - self.on_per_task_pre_run(task, total, index) - task.start(show_step_info=False) - - def pre_run(self): - self.execution.date_start = self.date_start - self.execution.save() - self.show_execution_steps() - - def show_execution_steps(self): - pass - - def show_summary(self): - split_line = '#' * 40 - summary = self.execution.result_summary - logger.info(f'\n{split_line} 改密计划执行结果汇总 {split_line}') - logger.info( - '\n成功: {succeed}, 失败: {failed}, 总数: {total}\n' - ''.format(**summary) - ) - - def post_run(self): - self.time_end = time.time() - self.date_end = timezone.now() - - logger.info('\n\n' + '-' * 80) - logger.info('任务执行结束 {}\n'.format(local_now_display())) - self.timedelta = int(self.time_end - self.time_start) - logger.info('用时: {}s'.format(self.timedelta)) - self.execution.timedelta = self.timedelta - self.execution.save() - self.show_summary() - - def run(self): - self.pre_run() - self.do_run() - self.post_run() diff --git a/apps/ops/task_handlers/change_auth/__init__.py b/apps/ops/task_handlers/change_auth/__init__.py deleted file mode 100644 index 2dc0b1a17..000000000 --- a/apps/ops/task_handlers/change_auth/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from .manager import * -from .handlers import * diff --git a/apps/ops/task_handlers/change_auth/handlers.py b/apps/ops/task_handlers/change_auth/handlers.py deleted file mode 100644 index c982a089d..000000000 --- a/apps/ops/task_handlers/change_auth/handlers.py +++ /dev/null @@ -1,10 +0,0 @@ -# -*- coding: utf-8 -*- -# -from common.utils import get_logger -from ..base import BaseHandler - -logger = get_logger(__name__) - - -class ChangeAuthHandler(BaseHandler): - pass diff --git a/apps/ops/task_handlers/change_auth/manager.py b/apps/ops/task_handlers/change_auth/manager.py deleted file mode 100644 index a9f77927c..000000000 --- a/apps/ops/task_handlers/change_auth/manager.py +++ /dev/null @@ -1,12 +0,0 @@ -# -*- coding: utf-8 -*- -# -from common.utils import get_logger -from ..base import BaseExecutionManager -from .handlers import ChangeAuthHandler - -logger = get_logger(__name__) - - -class ChangeAuthExecutionManager(BaseExecutionManager): - def get_handler_cls(self): - return ChangeAuthHandler diff --git a/apps/ops/task_handlers/collect/__init__.py b/apps/ops/task_handlers/collect/__init__.py deleted file mode 100644 index 2dc0b1a17..000000000 --- a/apps/ops/task_handlers/collect/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from .manager import * -from .handlers import * diff --git a/apps/ops/task_handlers/collect/handlers.py b/apps/ops/task_handlers/collect/handlers.py deleted file mode 100644 index 81b1e748d..000000000 --- a/apps/ops/task_handlers/collect/handlers.py +++ /dev/null @@ -1,10 +0,0 @@ -# -*- coding: utf-8 -*- -# -from common.utils import get_logger -from ..base import BaseHandler - -logger = get_logger(__name__) - - -class CollectHandler(BaseHandler): - pass diff --git a/apps/ops/task_handlers/collect/manager.py b/apps/ops/task_handlers/collect/manager.py deleted file mode 100644 index 18a685d7f..000000000 --- a/apps/ops/task_handlers/collect/manager.py +++ /dev/null @@ -1,10 +0,0 @@ -# -*- coding: utf-8 -*- -# -from common.utils import get_logger -from ..base import BaseExecutionManager - -logger = get_logger(__name__) - - -class CollectExecutionManager(object): - pass diff --git a/apps/ops/task_handlers/endpoint.py b/apps/ops/task_handlers/endpoint.py deleted file mode 100644 index 2d95dcad5..000000000 --- a/apps/ops/task_handlers/endpoint.py +++ /dev/null @@ -1,31 +0,0 @@ -from ops.const import StrategyChoice -from .push import PushExecutionManager, PushHandler -from .verify import VerifyExecutionManager, VerifyHandler -from .collect import CollectExecutionManager, CollectHandler -from .change_auth import ChangeAuthExecutionManager, ChangeAuthHandler - - -class ExecutionManager: - manager_type = { - StrategyChoice.push: PushExecutionManager, - StrategyChoice.verify: VerifyExecutionManager, - StrategyChoice.collect: CollectExecutionManager, - StrategyChoice.change_password: ChangeAuthExecutionManager, - } - - def __new__(cls, execution): - manager = cls.manager_type[execution.manager_type] - return manager(execution) - - -class TaskHandler: - handler_type = { - StrategyChoice.push: PushHandler, - StrategyChoice.verify: VerifyHandler, - StrategyChoice.collect: CollectHandler, - StrategyChoice.change_password: ChangeAuthHandler, - } - - def __new__(cls, task, show_step_info): - handler = cls.handler_type[task.handler_type] - return handler(task, show_step_info) diff --git a/apps/ops/task_handlers/push/__init__.py b/apps/ops/task_handlers/push/__init__.py deleted file mode 100644 index 2dc0b1a17..000000000 --- a/apps/ops/task_handlers/push/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from .manager import * -from .handlers import * diff --git a/apps/ops/task_handlers/push/handlers.py b/apps/ops/task_handlers/push/handlers.py deleted file mode 100644 index 891ac4bb6..000000000 --- a/apps/ops/task_handlers/push/handlers.py +++ /dev/null @@ -1,10 +0,0 @@ -# -*- coding: utf-8 -*- -# -from common.utils import get_logger -from ..base import BaseHandler - -logger = get_logger(__name__) - - -class PushHandler(BaseHandler): - pass diff --git a/apps/ops/task_handlers/push/manager.py b/apps/ops/task_handlers/push/manager.py deleted file mode 100644 index 933f9a0cc..000000000 --- a/apps/ops/task_handlers/push/manager.py +++ /dev/null @@ -1,10 +0,0 @@ -# -*- coding: utf-8 -*- -# -from common.utils import get_logger -from ..base import BaseExecutionManager - -logger = get_logger(__name__) - - -class PushExecutionManager(BaseExecutionManager): - pass diff --git a/apps/ops/task_handlers/verify/__init__.py b/apps/ops/task_handlers/verify/__init__.py deleted file mode 100644 index 2dc0b1a17..000000000 --- a/apps/ops/task_handlers/verify/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from .manager import * -from .handlers import * diff --git a/apps/ops/task_handlers/verify/handlers.py b/apps/ops/task_handlers/verify/handlers.py deleted file mode 100644 index 7a7f69881..000000000 --- a/apps/ops/task_handlers/verify/handlers.py +++ /dev/null @@ -1,10 +0,0 @@ -# -*- coding: utf-8 -*- -# -from common.utils import get_logger -from ..base import BaseHandler - -logger = get_logger(__name__) - - -class VerifyHandler(BaseHandler): - pass diff --git a/apps/ops/task_handlers/verify/manager.py b/apps/ops/task_handlers/verify/manager.py deleted file mode 100644 index a3727f1de..000000000 --- a/apps/ops/task_handlers/verify/manager.py +++ /dev/null @@ -1,10 +0,0 @@ -# -*- coding: utf-8 -*- -# -from common.utils import get_logger -from ..base import BaseExecutionManager - -logger = get_logger(__name__) - - -class VerifyExecutionManager(BaseExecutionManager): - pass diff --git a/apps/ops/utils.py b/apps/ops/utils.py index ea9d74cbc..44c486ded 100644 --- a/apps/ops/utils.py +++ b/apps/ops/utils.py @@ -8,7 +8,7 @@ from common.utils import get_logger, get_object_or_none from orgs.utils import org_aware_func from jumpserver.const import PROJECT_DIR -from .models import Task, AdHoc +from .models import AdHoc from .const import DEFAULT_PASSWORD_RULES logger = get_logger(__file__)