Пример #1
0
class Platform(models.Model):
    CHARSET_CHOICES = (
        ('utf8', 'UTF-8'),
        ('gbk', 'GBK'),
    )
    BASE_CHOICES = (
        ('Linux', 'Linux'),
        ('Unix', 'Unix'),
        ('MacOS', 'MacOS'),
        ('BSD', 'BSD'),
        ('Windows', 'Windows'),
        ('Other', 'Other'),
    )
    name = models.SlugField(verbose_name=_("Name"),
                            unique=True,
                            allow_unicode=True)
    base = models.CharField(choices=BASE_CHOICES,
                            max_length=16,
                            default='Linux',
                            verbose_name=_("Base"))
    charset = models.CharField(default='utf8',
                               choices=CHARSET_CHOICES,
                               max_length=8,
                               verbose_name=_("Charset"))
    meta = JsonDictTextField(blank=True, null=True, verbose_name=_("Meta"))
    internal = models.BooleanField(default=False, verbose_name=_("Internal"))
    comment = models.TextField(blank=True,
                               null=True,
                               verbose_name=_("Comment"))

    @classmethod
    def default(cls):
        linux, created = cls.objects.get_or_create(defaults={'name': 'Linux'},
                                                   name='Linux')
        return linux.id

    def is_windows(self):
        return self.base.lower() in ('windows', )

    def is_unixlike(self):
        return self.base.lower() in ("linux", "unix", "macos", "bsd")

    def __str__(self):
        return self.name

    class Meta:
        verbose_name = _("Platform")
Пример #2
0
class AdHocExecution(OrgModelMixin):
    """
    AdHoc running history.
    """
    id = models.UUIDField(default=uuid.uuid4, primary_key=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='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)
    is_finished = models.BooleanField(default=False,
                                      verbose_name=_('Is finished'))
    is_success = models.BooleanField(default=False,
                                     verbose_name=_('Is success'))
    result = JsonDictTextField(blank=True,
                               null=True,
                               verbose_name=_('Adhoc raw result'))
    summary = JsonDictTextField(blank=True,
                                null=True,
                                verbose_name=_('Adhoc result summary'))

    @property
    def short_id(self):
        return str(self.id).split('-')[-1]

    @property
    def adhoc_short_id(self):
        return str(self.adhoc_id).split('-')[-1]

    @property
    def log_path(self):
        dt = datetime.datetime.now().strftime('%Y-%m-%d')
        log_dir = os.path.join(settings.PROJECT_DIR, 'data', 'ansible', dt)
        if not os.path.exists(log_dir):
            os.makedirs(log_dir)
        return os.path.join(log_dir, str(self.id) + '.log')

    def start_runner(self):
        runner = AdHocRunner(self.adhoc.inventory, options=self.adhoc.options)
        try:
            result = runner.run(
                self.adhoc.tasks,
                self.adhoc.pattern,
                self.task.name,
            )
            return result.results_raw, result.results_summary
        except AnsibleError as e:
            logger.warn("Failed run adhoc {}, {}".format(self.task.name, e))
            return {}, {}

    def start(self):
        self.task.latest_execution = self
        self.task.save()
        time_start = time.time()
        summary = {}
        raw = ''

        try:
            date_start_s = timezone.now().now().strftime('%Y-%m-%d %H:%M:%S')
            print(_("{} Start task: {}").format(date_start_s, self.task.name))
            raw, summary = self.start_runner()
        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().now()
            date_end_s = date_end.strftime('%Y-%m-%d %H:%M:%S')
            print(_("{} Task finish").format(date_end_s))
            print('.\n\n.')
            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', [])

    @property
    def failed_hosts(self):
        return self.summary.get('dark', {})

    def __str__(self):
        return self.short_id

    class Meta:
        db_table = "ops_adhoc_execution"
        get_latest_by = 'date_start'
Пример #3
0
class Ticket(OrgModelMixin, CommonModelMixin):
    class STATUS(ChoiceSet):
        OPEN = 'open', _("Open")
        CLOSED = 'closed', _("Closed")

    class TYPE(ChoiceSet):
        GENERAL = 'general', _("General")
        LOGIN_CONFIRM = 'login_confirm', _("Login confirm")
        REQUEST_ASSET_PERM = 'request_asset', _('Request asset permission')

    class ACTION(ChoiceSet):
        APPROVE = 'approve', _('Approve')
        REJECT = 'reject', _('Reject')

    user = models.ForeignKey('users.User',
                             on_delete=models.SET_NULL,
                             null=True,
                             related_name='%(class)s_requested',
                             verbose_name=_("User"))
    user_display = models.CharField(max_length=128,
                                    verbose_name=_("User display name"))

    title = models.CharField(max_length=256, verbose_name=_("Title"))
    body = models.TextField(verbose_name=_("Body"))
    meta = JsonDictTextField(verbose_name=_("Meta"), default='{}')
    assignee = models.ForeignKey('users.User',
                                 on_delete=models.SET_NULL,
                                 null=True,
                                 related_name='%(class)s_handled',
                                 verbose_name=_("Assignee"))
    assignee_display = models.CharField(
        max_length=128,
        blank=True,
        null=True,
        verbose_name=_("Assignee display name"),
        default='')
    assignees = models.ManyToManyField('users.User',
                                       related_name='%(class)s_assigned',
                                       verbose_name=_("Assignees"))
    assignees_display = models.CharField(
        max_length=128, verbose_name=_("Assignees display name"), blank=True)
    type = models.CharField(max_length=16,
                            choices=TYPE.choices,
                            default=TYPE.GENERAL,
                            verbose_name=_("Type"))
    status = models.CharField(choices=STATUS.choices,
                              max_length=16,
                              default='open')
    action = models.CharField(choices=ACTION.choices,
                              max_length=16,
                              default='',
                              blank=True)
    comment = models.TextField(default='',
                               blank=True,
                               verbose_name=_('Comment'))

    origin_objects = models.Manager()

    def __str__(self):
        return '{}: {}'.format(self.user_display, self.title)

    @property
    def body_as_html(self):
        return self.body.replace('\n', '<br/>')

    @property
    def status_display(self):
        return self.get_status_display()

    @property
    def type_display(self):
        return self.get_type_display()

    @property
    def action_display(self):
        return self.get_action_display()

    def create_status_comment(self, status, user):
        if status == self.STATUS.CLOSED:
            action = _("Close")
        else:
            action = _("Open")
        body = _('{} {} this ticket').format(self.user, action)
        self.comments.create(user=user, body=body)

    def perform_status(self, status, user, extra_comment=None):
        self.create_comment(self.STATUS.get(status), user, extra_comment)
        self.status = status
        self.assignee = user
        self.save()

    def create_comment(self, action_display, user, extra_comment=None):
        body = '{} {} {}'.format(user, action_display, _("this ticket"))
        if extra_comment is not None:
            body += extra_comment
        self.comments.create(body=body, user=user, user_display=str(user))

    def perform_action(self, action, user, extra_comment=None):
        self.create_comment(self.ACTION.get(action), user, extra_comment)
        self.action = action
        self.status = self.STATUS.CLOSED
        self.assignee = user
        self.save()

    def is_assignee(self, user):
        return self.assignees.filter(id=user.id).exists()

    def is_user(self, user):
        return self.user == user

    @classmethod
    def get_related_tickets(cls, user, queryset=None):
        if queryset is None:
            queryset = cls.objects.all()
        queryset = queryset.filter(Q(assignees=user) | Q(user=user)).distinct()
        return queryset

    @classmethod
    def get_assigned_tickets(cls, user, queryset=None):
        if queryset is None:
            queryset = cls.objects.all()
        queryset = queryset.filter(assignees=user)
        return queryset

    @classmethod
    def get_my_tickets(cls, user, queryset=None):
        if queryset is None:
            queryset = cls.objects.all()
        queryset = queryset.filter(user=user)
        return queryset

    class Meta:
        ordering = ('-date_created', )
Пример #4
0
class Ticket(CommonModelMixin):
    STATUS_OPEN = 'open'
    STATUS_CLOSED = 'closed'
    STATUS_CHOICES = ((STATUS_OPEN, _("Open")), (STATUS_CLOSED, _("Closed")))
    TYPE_GENERAL = 'general'
    TYPE_LOGIN_CONFIRM = 'login_confirm'
    TYPE_CHOICES = ((TYPE_GENERAL, _("General")), (TYPE_LOGIN_CONFIRM,
                                                   _("Login confirm")))
    ACTION_APPROVE = 'approve'
    ACTION_REJECT = 'reject'
    ACTION_CHOICES = (
        (ACTION_APPROVE, _('Approve')),
        (ACTION_REJECT, _('Reject')),
    )
    user = models.ForeignKey('users.User',
                             on_delete=models.SET_NULL,
                             null=True,
                             related_name='%(class)s_requested',
                             verbose_name=_("User"))
    user_display = models.CharField(max_length=128,
                                    verbose_name=_("User display name"))

    title = models.CharField(max_length=256, verbose_name=_("Title"))
    body = models.TextField(verbose_name=_("Body"))
    meta = JsonDictTextField(verbose_name=_("Meta"), default='{}')
    assignee = models.ForeignKey('users.User',
                                 on_delete=models.SET_NULL,
                                 null=True,
                                 related_name='%(class)s_handled',
                                 verbose_name=_("Assignee"))
    assignee_display = models.CharField(
        max_length=128,
        blank=True,
        null=True,
        verbose_name=_("Assignee display name"))
    assignees = models.ManyToManyField('users.User',
                                       related_name='%(class)s_assigned',
                                       verbose_name=_("Assignees"))
    assignees_display = models.CharField(
        max_length=128, verbose_name=_("Assignees display name"), blank=True)
    type = models.CharField(max_length=16,
                            choices=TYPE_CHOICES,
                            default=TYPE_GENERAL,
                            verbose_name=_("Type"))
    status = models.CharField(choices=STATUS_CHOICES,
                              max_length=16,
                              default='open')
    action = models.CharField(choices=ACTION_CHOICES,
                              max_length=16,
                              default='',
                              blank=True)

    def __str__(self):
        return '{}: {}'.format(self.user_display, self.title)

    @property
    def body_as_html(self):
        return self.body.replace('\n', '<br/>')

    @property
    def status_display(self):
        return self.get_status_display()

    @property
    def type_display(self):
        return self.get_type_display()

    @property
    def action_display(self):
        return self.get_action_display()

    def create_status_comment(self, status, user):
        if status == self.STATUS_CLOSED:
            action = _("Close")
        else:
            action = _("Open")
        body = _('{} {} this ticket').format(self.user, action)
        self.comments.create(user=user, body=body)

    def perform_status(self, status, user):
        if self.status == status:
            return
        self.status = status
        self.save()

    #  创建回复内容
    def create_action_comment(self, action, user):
        action_display = dict(self.ACTION_CHOICES).get(action)
        body = '{} {} {}'.format(user, action_display, _("this ticket"))
        self.comments.create(body=body, user=user, user_display=str(user))

    # 此处设置关闭工单
    def perform_action(self, action, user):
        # 创建工单意见内容
        self.create_action_comment(action, user)
        self.action = action
        self.status = self.STATUS_CLOSED
        self.assignee = user
        self.assignees_display = str(user)
        self.save()

    def is_assignee(self, user):
        return self.assignees.filter(id=user.id).exists()

    def is_user(self, user):
        return self.user == user

    @classmethod
    def get_related_tickets(cls, user, queryset=None):
        if queryset is None:
            queryset = cls.objects.all()
        queryset = queryset.filter(Q(assignees=user) | Q(user=user)).distinct()
        return queryset

    @classmethod
    def get_assigned_tickets(cls, user, queryset=None):
        if queryset is None:
            queryset = cls.objects.all()
        queryset = queryset.filter(assignees=user)
        return queryset

    @classmethod
    def get_my_tickets(cls, user, queryset=None):
        if queryset is None:
            queryset = cls.objects.all()
        queryset = queryset.filter(user=user)
        return queryset

    class Meta:
        ordering = ('-date_created', )