1.5.7 Merge to dev (#3766)

* [Update] 暂存,优化解决不了问题

* [Update] 待续(小白)

* [Update] 修改asset user

* [Update] 计划再次更改

* [Update] 修改asset user

* [Update] 暂存与喜爱

* [Update] Add id in

* [Update] 阶段性完成ops task该做

* [Update] 修改asset user api

* [Update] 修改asset user 任务,查看认证等

* [Update] 基本完成asset user改造

* [Update] dynamic user only allow 1

* [Update] 修改asset user task

* [Update] 修改node admin user task api

* [Update] remove file header license

* [Update] 添加sftp root

* [Update] 暂存

* [Update] 暂存

* [Update] 修改翻译

* [Update] 修改系统用户改为同名后,用户名改为空

* [Update] 基本完成CAS调研

* [Update] 支持cas server

* [Update] 支持cas server

* [Update] 添加requirements

* [Update] 为方便调试添加mysql ipython到包中

* [Update] 添加huaweiyun翻译

* [Update] 增加下载session 录像

* [Update] 只有第一次通知replay离线的使用方法

* [Update] 暂存一下

* [Bugfix] 获取系统用户信息报错

* [Bugfix] 修改system user info

* [Update] 改成清理10天git status

* [Update] 修改celery日志保留时间

* [Update]修复部分pip包依赖的版本不兼容问题 (#3672)

* [Update] 修复用户更新页面会清空用户public_key的问题

* Fix broken dependencies

Co-authored-by: BaiJiangJie <32935519+BaiJiangJie@users.noreply.github.com>

* [Update] 修改获取系统用户auth info

* [Update] Remove log

* [Bugfix] 修复sftp home设置的bug

* [Update] 授权的系统用户添加sftp root

* [Update] 修改系统用户关联的用户

* [Update] 修改placeholder

* [Update] 优化获取授权的系统用户

* [Update] 修改tasks

* [Update] tree service update

* [Update] 暂存

* [Update] 基本完成用户授权树和资产树改造

* [Update] Dashbaord perf

* [update] Add huawei cloud sdk requirements

* [Updte] 优化dashboard页面

* [Update] system user auth info 添加id

* [Update] 修改系统用户serializer

* [Update] 优化api

* [Update] LDAP Test Util (#3720)

* [Update] LDAPTestUtil 1

* [Update] LDAPTestUtil 2

* [Update] LDAPTestUtil 3

* [Update] LDAPTestUtil 4

* [Update] LDAPTestUtil 5

* [Update] LDAPTestUtil 6

* [Update] LDAPTestUtil 7

* [Update] session 已添加is success,并且添加display serializer

* [Bugfix] 修复无法删除空节点的bug

* [Update] 命令记录分组织显示

* [Update] Session is_success 添加迁移文件

* [Update] 批量命令添加org_id

* [Update] 修复一些文案,修改不绑定MFA,不能ssh登录

* [Update] 修改replay api, 返回session信息

* [Update] 解决无效es导致访问命令记录页面失败的问题

* [Update] 拆分profile view

* [Update] 修改一个翻译

* [Update] 修改aysnc api框架

* [Update] 命令列表添加risk level

* [Update] 完成录像打包下载

* [Update] 更改登陆otp页面

* [Update] 修改command 存储redis_level

* [Update] 修改翻译

* [Update] 修改系统用户的用户列表字段

* [Update] 使用新logo和统一Jumpserver为JumpServer

* [Update] 优化cloud task

* [Update] 统一period task

* [Update] 统一period form serializer字段

* [Update] 修改period task

* [Update] 修改资产网关信息

* [Update] 用户授权资产树资产信息添加domain

* [Update] 修改翻译

* [Update] 测试可连接性

* 1.5.7 bai (#3764)

* [Update] 修复index页面Bug;修复测试资产用户可连接性问题;

* [Update] 修改测试资产用户可连接

* [Bugfix] 修复backends问题

* [Update] 修改marksafe依赖版本

* [Update] 修改测试资产用户可连接性

* [Update] 修改检测服务器性能时获取percent值

* [Update] 更新依赖boto3=1.12.14

Co-authored-by: Yanzhe Lee <lee.yanzhe@yanzhe.org>
Co-authored-by: BaiJiangJie <32935519+BaiJiangJie@users.noreply.github.com>
Co-authored-by: Bai <bugatti_it@163.com>
This commit is contained in:
老广
2020-03-12 16:24:38 +08:00
committed by GitHub
parent 1f6a8e8f02
commit 1fd2e782f8
204 changed files with 6463 additions and 3860 deletions

View File

@@ -10,45 +10,35 @@ from django.db import models
from django.conf import settings
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
from django_celery_beat.models import PeriodicTask
from common.utils import get_logger, lazyproperty
from common.fields.model import (
JsonListTextField, JsonDictCharField, EncryptJsonDictCharField,
JsonDictTextField,
)
from orgs.utils import set_to_root_org, get_current_org, set_current_org
from ..celery.utils import (
delete_celery_periodic_task, create_or_update_celery_periodic_tasks,
disable_celery_periodic_task
)
from orgs.mixins.models import OrgModelMixin
from ..ansible import AdHocRunner, AnsibleError
from ..inventory import JMSInventory
from ..mixin import PeriodTaskModelMixin
__all__ = ["Task", "AdHoc", "AdHocRunHistory"]
__all__ = ["Task", "AdHoc", "AdHocExecution"]
logger = get_logger(__file__)
class Task(models.Model):
class Task(PeriodTaskModelMixin, OrgModelMixin):
"""
This task is different ansible task, Task like 'push system user', 'get asset info' ..
One task can have some versions of adhoc, run a task only run the latest version adhoc
"""
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
name = models.CharField(max_length=128, verbose_name=_('Name'))
interval = models.IntegerField(verbose_name=_("Interval"), null=True, blank=True, help_text=_("Units: seconds"))
crontab = models.CharField(verbose_name=_("Crontab"), null=True, blank=True, max_length=128, help_text=_("5 * * * *"))
is_periodic = models.BooleanField(default=False)
callback = models.CharField(max_length=128, blank=True, null=True, verbose_name=_("Callback")) # Callback must be a registered celery task
is_deleted = models.BooleanField(default=False)
comment = models.TextField(blank=True, verbose_name=_("Comment"))
created_by = models.CharField(max_length=128, blank=True, default='')
date_created = models.DateTimeField(auto_now_add=True, db_index=True, verbose_name=_("Date created"))
date_updated = models.DateTimeField(auto_now=True, verbose_name=_("Date updated"))
latest_adhoc = models.ForeignKey('ops.AdHoc', on_delete=models.SET_NULL, null=True, related_name='task_latest')
latest_history = models.ForeignKey('ops.AdHocRunHistory', on_delete=models.SET_NULL, null=True, related_name='task_latest')
latest_execution = models.ForeignKey('ops.AdHocExecution', on_delete=models.SET_NULL, null=True, related_name='task_latest')
total_run_amount = models.IntegerField(default=0)
success_run_amount = models.IntegerField(default=0)
_ignore_auto_created_by = True
@@ -63,29 +53,29 @@ class Task(models.Model):
@property
def is_success(self):
if self.latest_history:
return self.latest_history.is_success
if self.latest_execution:
return self.latest_execution.is_success
else:
return False
@property
def timedelta(self):
if self.latest_history:
return self.latest_history.timedelta
if self.latest_execution:
return self.latest_execution.timedelta
else:
return 0
@property
def date_start(self):
if self.latest_history:
return self.latest_history.date_start
if self.latest_execution:
return self.latest_execution.date_start
else:
return None
@property
def assets_amount(self):
if self.latest_history:
return self.latest_history.hosts_amount
if self.latest_execution:
return self.latest_execution.hosts_amount
return 0
def get_latest_adhoc(self):
@@ -106,8 +96,8 @@ class Task(models.Model):
failed = total - success
return {'total': total, 'success': success, 'failed': failed}
def get_run_history(self):
return self.history.all()
def get_run_execution(self):
return self.execution.all()
def run(self):
latest_adhoc = self.get_latest_adhoc()
@@ -116,58 +106,29 @@ class Task(models.Model):
else:
return {'error': 'No adhoc'}
def register_as_period_task(self):
from ..tasks import run_ansible_task
interval = None
crontab = None
if self.interval:
interval = self.interval
elif self.crontab:
crontab = self.crontab
tasks = {
self.__str__(): {
"task": run_ansible_task.name,
"interval": interval,
"crontab": crontab,
"args": (str(self.id),),
"kwargs": {"callback": self.callback},
"enabled": True,
}
}
create_or_update_celery_periodic_tasks(tasks)
def save(self, **kwargs):
instance = super().save(**kwargs)
if self.is_periodic:
self.register_as_period_task()
else:
disable_celery_periodic_task(self.__str__())
return instance
def delete(self, using=None, keep_parents=False):
super().delete(using=using, keep_parents=keep_parents)
delete_celery_periodic_task(self.__str__())
@property
def schedule(self):
try:
return PeriodicTask.objects.get(name=str(self))
except PeriodicTask.DoesNotExist:
return None
def period_key(self):
return self.__str__()
def get_register_task(self):
from ..tasks import run_ansible_task
name = self.__str__()
task = run_ansible_task.name
args = (str(self.id),)
kwargs = {"callback": self.callback}
return name, task, args, kwargs
def __str__(self):
return self.name + '@' + str(self.created_by)
return self.name + '@' + str(self.org_id)
class Meta:
db_table = 'ops_task'
unique_together = ('name', 'created_by')
unique_together = ('name', 'org_id')
ordering = ('-date_updated',)
get_latest_by = 'date_created'
class AdHoc(models.Model):
class AdHoc(OrgModelMixin):
"""
task: A task reference
_tasks: [{'name': 'task_name', 'action': {'module': '', 'args': ''}, 'other..': ''}, ]
@@ -185,7 +146,7 @@ class AdHoc(models.Model):
hosts = models.ManyToManyField('assets.Asset', verbose_name=_("Host"))
run_as_admin = models.BooleanField(default=False, verbose_name=_('Run as admin'))
run_as = models.CharField(max_length=64, default='', blank=True, null=True, verbose_name=_('Username'))
become = EncryptJsonDictCharField(max_length=1024, default='', null=True, blank=True, verbose_name=_("Become"))
become = EncryptJsonDictCharField(max_length=1024, default='', blank=True, null=True, verbose_name=_("Become"))
created_by = models.CharField(max_length=64, default='', blank=True, null=True, verbose_name=_('Create by'))
date_created = models.DateTimeField(auto_now_add=True, db_index=True)
@@ -217,22 +178,23 @@ class AdHoc(models.Model):
hid = current_task.request.id
except AttributeError:
hid = str(uuid.uuid4())
history = AdHocRunHistory(
execution = AdHocExecution(
id=hid, adhoc=self, task=self.task,
task_display=str(self.task)
task_display=str(self.task),
date_start=timezone.now(),
)
history.save()
return history.start()
execution.save()
return execution.start()
@property
def short_id(self):
return str(self.id).split('-')[-1]
@property
def latest_history(self):
def latest_execution(self):
try:
return self.history.all().latest()
except AdHocRunHistory.DoesNotExist:
return self.execution.all().latest()
except AdHocExecution.DoesNotExist:
return None
def save(self, **kwargs):
@@ -261,15 +223,15 @@ class AdHoc(models.Model):
get_latest_by = 'date_created'
class AdHocRunHistory(models.Model):
class AdHocExecution(OrgModelMixin):
"""
AdHoc running history.
"""
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
task = models.ForeignKey(Task, related_name='history', on_delete=models.SET_NULL, null=True)
task = models.ForeignKey(Task, related_name='execution', on_delete=models.SET_NULL, null=True)
task_display = models.CharField(max_length=128, blank=True, default='', verbose_name=_("Task display"))
hosts_amount = models.IntegerField(default=0, verbose_name=_("Host amount"))
adhoc = models.ForeignKey(AdHoc, related_name='history', on_delete=models.SET_NULL, null=True)
adhoc = models.ForeignKey(AdHoc, related_name='execution', on_delete=models.SET_NULL, null=True)
date_start = models.DateTimeField(auto_now_add=True, verbose_name=_('Start time'))
date_finished = models.DateTimeField(blank=True, null=True, verbose_name=_('End time'))
timedelta = models.FloatField(default=0.0, verbose_name=_('Time'), null=True)
@@ -308,13 +270,9 @@ class AdHocRunHistory(models.Model):
return {}, {}
def start(self):
self.task.latest_history = self
self.task.latest_execution = self
self.task.save()
current_org = get_current_org()
set_to_root_org()
time_start = time.time()
date_start = timezone.now()
is_success = False
summary = {}
raw = ''
@@ -322,31 +280,32 @@ class AdHocRunHistory(models.Model):
date_start_s = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
print(_("{} Start task: {}").format(date_start_s, self.task.name))
raw, summary = self.start_runner()
is_success = summary.get('success', False)
except Exception as e:
logger.error(e, exc_info=True)
raw = {"dark": {"all": str(e)}, "contacted": []}
finally:
self.clean_up(summary, time_start)
date_end = timezone.now()
date_end_s = date_end.strftime('%Y-%m-%d %H:%M:%S')
print(_("{} Task finish").format(date_end_s))
print('.\n\n.')
task = Task.objects.get(id=self.task_id)
task.total_run_amount = models.F('total_run_amount') + 1
if is_success:
task.success_run_amount = models.F('success_run_amount') + 1
task.save()
AdHocRunHistory.objects.filter(id=self.id).update(
date_start=date_start,
is_finished=True,
is_success=is_success,
date_finished=timezone.now(),
timedelta=time.time() - time_start,
summary=summary
)
set_current_org(current_org)
return raw, summary
def clean_up(self, summary, time_start):
is_success = summary.get('success', False)
task = Task.objects.get(id=self.task_id)
task.total_run_amount = models.F('total_run_amount') + 1
if is_success:
task.success_run_amount = models.F('success_run_amount') + 1
task.save()
AdHocExecution.objects.filter(id=self.id).update(
is_finished=True,
is_success=is_success,
date_finished=timezone.now(),
timedelta=time.time() - time_start,
summary=summary
)
@property
def success_hosts(self):
return self.summary.get('contacted', [])
@@ -359,5 +318,5 @@ class AdHocRunHistory(models.Model):
return self.short_id
class Meta:
db_table = "ops_adhoc_history"
db_table = "ops_adhoc_execution"
get_latest_by = 'date_start'

View File

@@ -11,11 +11,12 @@ from django.db import models
from orgs.models import Organization
from orgs.mixins.models import OrgModelMixin
from ..ansible.runner import CommandRunner
from ..inventory import JMSInventory
class CommandExecution(models.Model):
class CommandExecution(OrgModelMixin):
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
hosts = models.ManyToManyField('assets.Asset')
run_as = models.ForeignKey('assets.SystemUser', on_delete=models.CASCADE)
@@ -80,6 +81,7 @@ class CommandExecution(models.Model):
msg = _("Command `{}` is forbidden ........").format(self.command)
print('\033[31m' + msg + '\033[0m')
self.result = {"error": msg}
self.org_id = self.run_as.org_id
self.is_finished = True
self.date_finished = timezone.now()
self.save()