fix check threshold modals and add client/serverside validation. Allow viewing alert script results in alerts overview. Fix diskspace check history computation. other fixes and improvements
This commit is contained in:
@@ -534,14 +534,22 @@ class Agent(BaseAuditModel):
|
|||||||
):
|
):
|
||||||
templates.append(core.workstation_policy.alert_template)
|
templates.append(core.workstation_policy.alert_template)
|
||||||
|
|
||||||
# check if client, site, or agent has been excluded from templates in order and return if not
|
# go through the templates and return the first one that isn't excluded
|
||||||
for template in templates:
|
for template in templates:
|
||||||
|
# check if client, site, or agent has been excluded from template
|
||||||
if (
|
if (
|
||||||
client.pk in template.excluded_clients.all()
|
client.pk in template.excluded_clients.all()
|
||||||
or site.pk in template.excluded_sites.all()
|
or site.pk in template.excluded_sites.all()
|
||||||
or self.pk in template.excluded_agents.all()
|
or self.pk in template.excluded_agents.all()
|
||||||
):
|
):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# see if template is excluding desktops
|
||||||
|
if (
|
||||||
|
self.monitoring_type == "workstation"
|
||||||
|
and not template.agent_include_desktops
|
||||||
|
):
|
||||||
|
continue
|
||||||
else:
|
else:
|
||||||
return template
|
return template
|
||||||
|
|
||||||
@@ -751,7 +759,7 @@ class Agent(BaseAuditModel):
|
|||||||
alert.resolved_action_execution_time = "{:.4f}".format(
|
alert.resolved_action_execution_time = "{:.4f}".format(
|
||||||
r["execution_time"]
|
r["execution_time"]
|
||||||
)
|
)
|
||||||
alert.resolved_action_run = True
|
alert.resolved_action_run = djangotime.now()
|
||||||
alert.save()
|
alert.save()
|
||||||
else:
|
else:
|
||||||
logger.error(
|
logger.error(
|
||||||
@@ -825,7 +833,7 @@ class Agent(BaseAuditModel):
|
|||||||
alert.action_stdout = r["stdout"]
|
alert.action_stdout = r["stdout"]
|
||||||
alert.action_stderr = r["stderr"]
|
alert.action_stderr = r["stderr"]
|
||||||
alert.action_execution_time = "{:.4f}".format(r["execution_time"])
|
alert.action_execution_time = "{:.4f}".format(r["execution_time"])
|
||||||
alert.action_run = True
|
alert.action_run = djangotime.now()
|
||||||
alert.save()
|
alert.save()
|
||||||
else:
|
else:
|
||||||
logger.error(
|
logger.error(
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# Generated by Django 3.1.4 on 2021-02-07 14:26
|
# Generated by Django 3.1.4 on 2021-02-12 14:08
|
||||||
|
|
||||||
import django.contrib.postgres.fields
|
import django.contrib.postgres.fields
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
@@ -8,14 +8,44 @@ import django.db.models.deletion
|
|||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('scripts', '0006_auto_20201210_2145'),
|
('agents', '0029_delete_agentoutage'),
|
||||||
('autotasks', '0016_automatedtask_status'),
|
|
||||||
('agents', '0028_auto_20210206_1534'),
|
|
||||||
('clients', '0008_auto_20201103_1430'),
|
('clients', '0008_auto_20201103_1430'),
|
||||||
|
('autotasks', '0017_auto_20210210_1512'),
|
||||||
|
('scripts', '0005_auto_20201207_1606'),
|
||||||
('alerts', '0003_auto_20201021_1815'),
|
('alerts', '0003_auto_20201021_1815'),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='alert',
|
||||||
|
name='action_execution_time',
|
||||||
|
field=models.CharField(blank=True, max_length=100, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='alert',
|
||||||
|
name='action_retcode',
|
||||||
|
field=models.IntegerField(blank=True, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='alert',
|
||||||
|
name='action_run',
|
||||||
|
field=models.DateTimeField(blank=True, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='alert',
|
||||||
|
name='action_stderr',
|
||||||
|
field=models.TextField(blank=True, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='alert',
|
||||||
|
name='action_stdout',
|
||||||
|
field=models.TextField(blank=True, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='alert',
|
||||||
|
name='action_timeout',
|
||||||
|
field=models.PositiveIntegerField(blank=True, null=True),
|
||||||
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='alert',
|
model_name='alert',
|
||||||
name='alert_type',
|
name='alert_type',
|
||||||
@@ -26,11 +56,66 @@ class Migration(migrations.Migration):
|
|||||||
name='assigned_task',
|
name='assigned_task',
|
||||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='alert', to='autotasks.automatedtask'),
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='alert', to='autotasks.automatedtask'),
|
||||||
),
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='alert',
|
||||||
|
name='email_sent',
|
||||||
|
field=models.DateTimeField(blank=True, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='alert',
|
||||||
|
name='hidden',
|
||||||
|
field=models.BooleanField(default=False),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='alert',
|
||||||
|
name='resolved_action_execution_time',
|
||||||
|
field=models.CharField(blank=True, max_length=100, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='alert',
|
||||||
|
name='resolved_action_retcode',
|
||||||
|
field=models.IntegerField(blank=True, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='alert',
|
||||||
|
name='resolved_action_run',
|
||||||
|
field=models.DateTimeField(blank=True, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='alert',
|
||||||
|
name='resolved_action_stderr',
|
||||||
|
field=models.TextField(blank=True, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='alert',
|
||||||
|
name='resolved_action_stdout',
|
||||||
|
field=models.TextField(blank=True, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='alert',
|
||||||
|
name='resolved_action_timeout',
|
||||||
|
field=models.PositiveIntegerField(blank=True, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='alert',
|
||||||
|
name='resolved_email_sent',
|
||||||
|
field=models.DateTimeField(blank=True, null=True),
|
||||||
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='alert',
|
model_name='alert',
|
||||||
name='resolved_on',
|
name='resolved_on',
|
||||||
field=models.DateTimeField(blank=True, null=True),
|
field=models.DateTimeField(blank=True, null=True),
|
||||||
),
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='alert',
|
||||||
|
name='resolved_sms_sent',
|
||||||
|
field=models.DateTimeField(blank=True, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='alert',
|
||||||
|
name='sms_sent',
|
||||||
|
field=models.DateTimeField(blank=True, null=True),
|
||||||
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='alert',
|
model_name='alert',
|
||||||
name='snoozed',
|
name='snoozed',
|
||||||
@@ -47,6 +132,8 @@ class Migration(migrations.Migration):
|
|||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
('name', models.CharField(max_length=100)),
|
('name', models.CharField(max_length=100)),
|
||||||
('is_active', models.BooleanField(default=True)),
|
('is_active', models.BooleanField(default=True)),
|
||||||
|
('action_args', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(blank=True, max_length=255, null=True), blank=True, default=list, null=True, size=None)),
|
||||||
|
('resolved_action_args', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(blank=True, max_length=255, null=True), blank=True, default=list, null=True, size=None)),
|
||||||
('email_recipients', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(blank=True, max_length=100), blank=True, default=list, null=True, size=None)),
|
('email_recipients', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(blank=True, max_length=100), blank=True, default=list, null=True, size=None)),
|
||||||
('text_recipients', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(blank=True, max_length=100), blank=True, default=list, null=True, size=None)),
|
('text_recipients', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(blank=True, max_length=100), blank=True, default=list, null=True, size=None)),
|
||||||
('email_from', models.EmailField(blank=True, max_length=254, null=True)),
|
('email_from', models.EmailField(blank=True, max_length=254, null=True)),
|
||||||
@@ -75,10 +162,11 @@ class Migration(migrations.Migration):
|
|||||||
('task_always_text', models.BooleanField(blank=True, default=False, null=True)),
|
('task_always_text', models.BooleanField(blank=True, default=False, null=True)),
|
||||||
('task_always_alert', models.BooleanField(blank=True, default=False, null=True)),
|
('task_always_alert', models.BooleanField(blank=True, default=False, null=True)),
|
||||||
('task_periodic_alert_days', models.PositiveIntegerField(blank=True, default=0, null=True)),
|
('task_periodic_alert_days', models.PositiveIntegerField(blank=True, default=0, null=True)),
|
||||||
('actions', models.ManyToManyField(blank=True, related_name='alert_templates', to='scripts.Script')),
|
('action', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='alert_template', to='scripts.script')),
|
||||||
('excluded_agents', models.ManyToManyField(blank=True, related_name='alert_exclusions', to='agents.Agent')),
|
('excluded_agents', models.ManyToManyField(blank=True, related_name='alert_exclusions', to='agents.Agent')),
|
||||||
('excluded_clients', models.ManyToManyField(blank=True, related_name='alert_exclusions', to='clients.Client')),
|
('excluded_clients', models.ManyToManyField(blank=True, related_name='alert_exclusions', to='clients.Client')),
|
||||||
('excluded_sites', models.ManyToManyField(blank=True, related_name='alert_exclusions', to='clients.Site')),
|
('excluded_sites', models.ManyToManyField(blank=True, related_name='alert_exclusions', to='clients.Site')),
|
||||||
|
('resolved_action', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='resolved_alert_template', to='scripts.script')),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
# Generated by Django 3.1.4 on 2021-02-07 18:36
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('scripts', '0006_auto_20201210_2145'),
|
|
||||||
('alerts', '0004_auto_20210207_1426'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='alerttemplate',
|
|
||||||
name='resolved_actions',
|
|
||||||
field=models.ManyToManyField(blank=True, related_name='alert_templates_resolved', to='scripts.Script'),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
@@ -1,129 +0,0 @@
|
|||||||
# Generated by Django 3.1.4 on 2021-02-10 15:12
|
|
||||||
|
|
||||||
import django.contrib.postgres.fields
|
|
||||||
from django.db import migrations, models
|
|
||||||
import django.db.models.deletion
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('scripts', '0006_auto_20201210_2145'),
|
|
||||||
('alerts', '0005_alerttemplate_resolved_actions'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.RemoveField(
|
|
||||||
model_name='alerttemplate',
|
|
||||||
name='actions',
|
|
||||||
),
|
|
||||||
migrations.RemoveField(
|
|
||||||
model_name='alerttemplate',
|
|
||||||
name='resolved_actions',
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='alert',
|
|
||||||
name='action_execution_time',
|
|
||||||
field=models.CharField(blank=True, max_length=100, null=True),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='alert',
|
|
||||||
name='action_retcode',
|
|
||||||
field=models.IntegerField(blank=True, null=True),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='alert',
|
|
||||||
name='action_run',
|
|
||||||
field=models.BooleanField(default=False),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='alert',
|
|
||||||
name='action_stderr',
|
|
||||||
field=models.TextField(blank=True, null=True),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='alert',
|
|
||||||
name='action_stdout',
|
|
||||||
field=models.TextField(blank=True, null=True),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='alert',
|
|
||||||
name='action_timeout',
|
|
||||||
field=models.PositiveIntegerField(blank=True, null=True),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='alert',
|
|
||||||
name='email_sent',
|
|
||||||
field=models.DateTimeField(blank=True, null=True),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='alert',
|
|
||||||
name='hidden',
|
|
||||||
field=models.BooleanField(default=False),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='alert',
|
|
||||||
name='resolved_action_execution_time',
|
|
||||||
field=models.CharField(blank=True, max_length=100, null=True),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='alert',
|
|
||||||
name='resolved_action_retcode',
|
|
||||||
field=models.IntegerField(blank=True, null=True),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='alert',
|
|
||||||
name='resolved_action_run',
|
|
||||||
field=models.BooleanField(default=False),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='alert',
|
|
||||||
name='resolved_action_stderr',
|
|
||||||
field=models.TextField(blank=True, null=True),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='alert',
|
|
||||||
name='resolved_action_stdout',
|
|
||||||
field=models.TextField(blank=True, null=True),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='alert',
|
|
||||||
name='resolved_action_timeout',
|
|
||||||
field=models.PositiveIntegerField(blank=True, null=True),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='alert',
|
|
||||||
name='resolved_email_sent',
|
|
||||||
field=models.DateTimeField(blank=True, null=True),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='alert',
|
|
||||||
name='resolved_sms_sent',
|
|
||||||
field=models.DateTimeField(blank=True, null=True),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='alert',
|
|
||||||
name='sms_sent',
|
|
||||||
field=models.DateTimeField(blank=True, null=True),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='alerttemplate',
|
|
||||||
name='action',
|
|
||||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='alert_template', to='scripts.script'),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='alerttemplate',
|
|
||||||
name='action_args',
|
|
||||||
field=django.contrib.postgres.fields.ArrayField(base_field=models.CharField(blank=True, max_length=255, null=True), blank=True, default=list, null=True, size=None),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='alerttemplate',
|
|
||||||
name='resolved_action',
|
|
||||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='resolved_alert_template', to='scripts.script'),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='alerttemplate',
|
|
||||||
name='resolved_action_args',
|
|
||||||
field=django.contrib.postgres.fields.ArrayField(base_field=models.CharField(blank=True, max_length=255, null=True), blank=True, default=list, null=True, size=None),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
@@ -3,8 +3,6 @@ from django.contrib.postgres.fields import ArrayField
|
|||||||
from django.db.models.fields import BooleanField, PositiveIntegerField
|
from django.db.models.fields import BooleanField, PositiveIntegerField
|
||||||
from django.utils import timezone as djangotime
|
from django.utils import timezone as djangotime
|
||||||
|
|
||||||
from typing import Union, Type
|
|
||||||
|
|
||||||
SEVERITY_CHOICES = [
|
SEVERITY_CHOICES = [
|
||||||
("info", "Informational"),
|
("info", "Informational"),
|
||||||
("warning", "Warning"),
|
("warning", "Warning"),
|
||||||
@@ -56,13 +54,13 @@ class Alert(models.Model):
|
|||||||
sms_sent = models.DateTimeField(null=True, blank=True)
|
sms_sent = models.DateTimeField(null=True, blank=True)
|
||||||
resolved_sms_sent = models.DateTimeField(null=True, blank=True)
|
resolved_sms_sent = models.DateTimeField(null=True, blank=True)
|
||||||
hidden = models.BooleanField(default=False)
|
hidden = models.BooleanField(default=False)
|
||||||
action_run = models.BooleanField(default=False)
|
action_run = models.DateTimeField(null=True, blank=True)
|
||||||
action_timeout = models.PositiveIntegerField(null=True, blank=True)
|
action_timeout = models.PositiveIntegerField(null=True, blank=True)
|
||||||
action_stdout = models.TextField(null=True, blank=True)
|
action_stdout = models.TextField(null=True, blank=True)
|
||||||
action_stderr = models.TextField(null=True, blank=True)
|
action_stderr = models.TextField(null=True, blank=True)
|
||||||
action_retcode = models.IntegerField(null=True, blank=True)
|
action_retcode = models.IntegerField(null=True, blank=True)
|
||||||
action_execution_time = models.CharField(max_length=100, null=True, blank=True)
|
action_execution_time = models.CharField(max_length=100, null=True, blank=True)
|
||||||
resolved_action_run = models.BooleanField(default=False)
|
resolved_action_run = models.DateTimeField(null=True, blank=True)
|
||||||
resolved_action_timeout = models.PositiveIntegerField(null=True, blank=True)
|
resolved_action_timeout = models.PositiveIntegerField(null=True, blank=True)
|
||||||
resolved_action_stdout = models.TextField(null=True, blank=True)
|
resolved_action_stdout = models.TextField(null=True, blank=True)
|
||||||
resolved_action_stderr = models.TextField(null=True, blank=True)
|
resolved_action_stderr = models.TextField(null=True, blank=True)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# Generated by Django 3.1.4 on 2021-02-07 14:26
|
# Generated by Django 3.1.4 on 2021-02-12 14:08
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
@@ -7,7 +7,7 @@ import django.db.models.deletion
|
|||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('alerts', '0004_auto_20210207_1426'),
|
('alerts', '0004_auto_20210212_1408'),
|
||||||
('automation', '0006_delete_policyexclusions'),
|
('automation', '0006_delete_policyexclusions'),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ class Policy(BaseAuditModel):
|
|||||||
def delete(self, *args, **kwargs):
|
def delete(self, *args, **kwargs):
|
||||||
from automation.tasks import generate_agent_checks_task
|
from automation.tasks import generate_agent_checks_task
|
||||||
|
|
||||||
agents = list(self.related_agents().values_list("pk", flat=True))
|
agents = list(self.related_agents().only("pk").values_list("pk", flat=True))
|
||||||
super(BaseAuditModel, self).delete(*args, **kwargs)
|
super(BaseAuditModel, self).delete(*args, **kwargs)
|
||||||
|
|
||||||
generate_agent_checks_task.delay(agents, create_tasks=True)
|
generate_agent_checks_task.delay(agents, create_tasks=True)
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ def generate_agent_tasks_from_policies_task(policypk):
|
|||||||
"pk", "monitoring_type"
|
"pk", "monitoring_type"
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
agents = policy.related_agents()
|
agents = policy.related_agents().only("pk")
|
||||||
|
|
||||||
for agent in agents:
|
for agent in agents:
|
||||||
agent.generate_tasks_from_policies()
|
agent.generate_tasks_from_policies()
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import random
|
|||||||
import string
|
import string
|
||||||
import datetime as dt
|
import datetime as dt
|
||||||
|
|
||||||
|
from django.utils import timezone as djangotime
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.contrib.postgres.fields import ArrayField
|
from django.contrib.postgres.fields import ArrayField
|
||||||
@@ -289,7 +290,7 @@ class AutomatedTask(BaseAuditModel):
|
|||||||
alert.resolved_action_execution_time = "{:.4f}".format(
|
alert.resolved_action_execution_time = "{:.4f}".format(
|
||||||
r["execution_time"]
|
r["execution_time"]
|
||||||
)
|
)
|
||||||
alert.resolved_action_run = True
|
alert.resolved_action_run = djangotime.now()
|
||||||
alert.save()
|
alert.save()
|
||||||
else:
|
else:
|
||||||
logger.error(
|
logger.error(
|
||||||
@@ -303,6 +304,11 @@ class AutomatedTask(BaseAuditModel):
|
|||||||
else:
|
else:
|
||||||
alert = Alert.objects.get(assigned_task=self, resolved=False)
|
alert = Alert.objects.get(assigned_task=self, resolved=False)
|
||||||
|
|
||||||
|
# check if alert severity changed on task and update the alert
|
||||||
|
if self.alert_severity != alert.severity:
|
||||||
|
alert.severity = self.alert_severity
|
||||||
|
alert.save(update_fields=["severity"])
|
||||||
|
|
||||||
# create alert in dashboard if enabled
|
# create alert in dashboard if enabled
|
||||||
if (
|
if (
|
||||||
self.dashboard_alert
|
self.dashboard_alert
|
||||||
@@ -359,7 +365,7 @@ class AutomatedTask(BaseAuditModel):
|
|||||||
alert.action_stdout = r["stdout"]
|
alert.action_stdout = r["stdout"]
|
||||||
alert.action_stderr = r["stderr"]
|
alert.action_stderr = r["stderr"]
|
||||||
alert.action_execution_time = "{:.4f}".format(r["execution_time"])
|
alert.action_execution_time = "{:.4f}".format(r["execution_time"])
|
||||||
alert.action_run = True
|
alert.action_run = djangotime.now()
|
||||||
alert.save()
|
alert.save()
|
||||||
else:
|
else:
|
||||||
logger.error(
|
logger.error(
|
||||||
|
|||||||
24
api/tacticalrmm/checks/migrations/0021_auto_20210212_1429.py
Normal file
24
api/tacticalrmm/checks/migrations/0021_auto_20210212_1429.py
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# Generated by Django 3.1.4 on 2021-02-12 14:29
|
||||||
|
|
||||||
|
import django.core.validators
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('checks', '0020_auto_20210210_1512'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='check',
|
||||||
|
name='error_threshold',
|
||||||
|
field=models.PositiveIntegerField(blank=True, default=0, null=True, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(99)]),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='check',
|
||||||
|
name='warning_threshold',
|
||||||
|
field=models.PositiveIntegerField(blank=True, default=0, null=True, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(99)]),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -5,8 +5,10 @@ import json
|
|||||||
import pytz
|
import pytz
|
||||||
from statistics import mean
|
from statistics import mean
|
||||||
|
|
||||||
|
from django.utils import timezone as djangotime
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.core.validators import MinValueValidator, MaxValueValidator
|
||||||
from django.contrib.postgres.fields import ArrayField
|
from django.contrib.postgres.fields import ArrayField
|
||||||
from rest_framework.fields import JSONField
|
from rest_framework.fields import JSONField
|
||||||
from typing import List, Any
|
from typing import List, Any
|
||||||
@@ -113,10 +115,17 @@ class Check(BaseAuditModel):
|
|||||||
|
|
||||||
# threshold percent for diskspace, cpuload or memory check
|
# threshold percent for diskspace, cpuload or memory check
|
||||||
error_threshold = models.PositiveIntegerField(
|
error_threshold = models.PositiveIntegerField(
|
||||||
|
validators=[MinValueValidator(0), MaxValueValidator(99)],
|
||||||
null=True,
|
null=True,
|
||||||
blank=True,
|
blank=True,
|
||||||
|
default=0,
|
||||||
|
)
|
||||||
|
warning_threshold = models.PositiveIntegerField(
|
||||||
|
null=True,
|
||||||
|
blank=True,
|
||||||
|
validators=[MinValueValidator(0), MaxValueValidator(99)],
|
||||||
|
default=0,
|
||||||
)
|
)
|
||||||
warning_threshold = models.PositiveIntegerField(null=True, blank=True, default=0)
|
|
||||||
# diskcheck i.e C:, D: etc
|
# diskcheck i.e C:, D: etc
|
||||||
disk = models.CharField(max_length=2, null=True, blank=True)
|
disk = models.CharField(max_length=2, null=True, blank=True)
|
||||||
# ping checks
|
# ping checks
|
||||||
@@ -314,7 +323,7 @@ class Check(BaseAuditModel):
|
|||||||
alert.resolved_action_execution_time = "{:.4f}".format(
|
alert.resolved_action_execution_time = "{:.4f}".format(
|
||||||
r["execution_time"]
|
r["execution_time"]
|
||||||
)
|
)
|
||||||
alert.resolved_action_run = True
|
alert.resolved_action_run = djangotime.now()
|
||||||
alert.save()
|
alert.save()
|
||||||
else:
|
else:
|
||||||
logger.error(
|
logger.error(
|
||||||
@@ -327,6 +336,11 @@ class Check(BaseAuditModel):
|
|||||||
else:
|
else:
|
||||||
alert = Alert.objects.get(assigned_check=self, resolved=False)
|
alert = Alert.objects.get(assigned_check=self, resolved=False)
|
||||||
|
|
||||||
|
# check if alert severity changed on check and update the alert
|
||||||
|
if self.alert_severity != alert.severity:
|
||||||
|
alert.severity = self.alert_severity
|
||||||
|
alert.save(update_fields=["severity"])
|
||||||
|
|
||||||
# create alert in dashboard if enabled
|
# create alert in dashboard if enabled
|
||||||
if (
|
if (
|
||||||
self.dashboard_alert
|
self.dashboard_alert
|
||||||
@@ -384,7 +398,7 @@ class Check(BaseAuditModel):
|
|||||||
alert.action_stdout = r["stdout"]
|
alert.action_stdout = r["stdout"]
|
||||||
alert.action_stderr = r["stderr"]
|
alert.action_stderr = r["stderr"]
|
||||||
alert.action_execution_time = "{:.4f}".format(r["execution_time"])
|
alert.action_execution_time = "{:.4f}".format(r["execution_time"])
|
||||||
alert.action_run = True
|
alert.action_run = djangotime.now()
|
||||||
alert.save()
|
alert.save()
|
||||||
else:
|
else:
|
||||||
logger.error(
|
logger.error(
|
||||||
@@ -408,15 +422,12 @@ class Check(BaseAuditModel):
|
|||||||
|
|
||||||
avg = int(mean(self.history))
|
avg = int(mean(self.history))
|
||||||
|
|
||||||
if self.warning_threshold and avg > self.warning_threshold:
|
|
||||||
self.status = "failing"
|
|
||||||
self.alert_severity = "warning"
|
|
||||||
else:
|
|
||||||
self.status = "passing"
|
|
||||||
|
|
||||||
if self.error_threshold and avg > self.error_threshold:
|
if self.error_threshold and avg > self.error_threshold:
|
||||||
self.status = "failing"
|
self.status = "failing"
|
||||||
self.alert_severity = "error"
|
self.alert_severity = "error"
|
||||||
|
elif self.warning_threshold and avg > self.warning_threshold:
|
||||||
|
self.status = "failing"
|
||||||
|
self.alert_severity = "warning"
|
||||||
else:
|
else:
|
||||||
self.status = "passing"
|
self.status = "passing"
|
||||||
|
|
||||||
@@ -430,25 +441,23 @@ class Check(BaseAuditModel):
|
|||||||
total = bytes2human(data["total"])
|
total = bytes2human(data["total"])
|
||||||
free = bytes2human(data["free"])
|
free = bytes2human(data["free"])
|
||||||
|
|
||||||
if (
|
if self.error_threshold and (100 - percent_used) < self.error_threshold:
|
||||||
|
self.status = "failing"
|
||||||
|
self.alert_severity = "error"
|
||||||
|
elif (
|
||||||
self.warning_threshold
|
self.warning_threshold
|
||||||
and (100 - percent_used) < self.warning_threshold
|
and (100 - percent_used) < self.warning_threshold
|
||||||
):
|
):
|
||||||
self.status = "failing"
|
self.status = "failing"
|
||||||
self.alert_severity = "warning"
|
self.alert_severity = "warning"
|
||||||
else:
|
|
||||||
self.status = "passing"
|
|
||||||
|
|
||||||
if self.error_threshold and (100 - percent_used) < self.error_threshold:
|
|
||||||
self.status = "failing"
|
|
||||||
self.alert_severity = "error"
|
|
||||||
else:
|
else:
|
||||||
self.status = "passing"
|
self.status = "passing"
|
||||||
|
|
||||||
self.more_info = f"Total: {total}B, Free: {free}B"
|
self.more_info = f"Total: {total}B, Free: {free}B"
|
||||||
|
|
||||||
# add check history
|
# add check history
|
||||||
self.add_check_history(percent_used)
|
self.add_check_history(100 - percent_used)
|
||||||
else:
|
else:
|
||||||
self.status = "failing"
|
self.status = "failing"
|
||||||
self.alert_severity = "error"
|
self.alert_severity = "error"
|
||||||
@@ -630,15 +639,11 @@ class Check(BaseAuditModel):
|
|||||||
# handle status
|
# handle status
|
||||||
if self.status == "failing":
|
if self.status == "failing":
|
||||||
self.fail_count += 1
|
self.fail_count += 1
|
||||||
self.save(update_fields=["status", "fail_count"])
|
self.save(update_fields=["status", "fail_count", "alert_severity"])
|
||||||
|
|
||||||
elif self.status == "passing":
|
elif self.status == "passing":
|
||||||
|
self.fail_count = 0
|
||||||
if self.fail_count != 0:
|
self.save(update_fields=["status", "fail_count", "alert_severity"])
|
||||||
self.fail_count = 0
|
|
||||||
self.save(update_fields=["status", "fail_count"])
|
|
||||||
else:
|
|
||||||
self.save(update_fields=["status"])
|
|
||||||
|
|
||||||
self.handle_alert()
|
self.handle_alert()
|
||||||
|
|
||||||
|
|||||||
@@ -40,19 +40,30 @@ class CheckSerializer(serializers.ModelSerializer):
|
|||||||
check_type = val["check_type"]
|
check_type = val["check_type"]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return val
|
return val
|
||||||
|
|
||||||
# disk checks
|
# disk checks
|
||||||
# make sure no duplicate diskchecks exist for an agent/policy
|
# make sure no duplicate diskchecks exist for an agent/policy
|
||||||
if check_type == "diskspace" and not self.instance: # only on create
|
if check_type == "diskspace":
|
||||||
checks = (
|
if not self.instance: # only on create
|
||||||
Check.objects.filter(**self.context)
|
checks = (
|
||||||
.filter(check_type="diskspace")
|
Check.objects.filter(**self.context)
|
||||||
.exclude(managed_by_policy=True)
|
.filter(check_type="diskspace")
|
||||||
)
|
.exclude(managed_by_policy=True)
|
||||||
for check in checks:
|
)
|
||||||
if val["disk"] in check.disk:
|
for check in checks:
|
||||||
raise serializers.ValidationError(
|
if val["disk"] in check.disk:
|
||||||
f"A disk check for Drive {val['disk']} already exists!"
|
raise serializers.ValidationError(
|
||||||
)
|
f"A disk check for Drive {val['disk']} already exists!"
|
||||||
|
)
|
||||||
|
|
||||||
|
if (
|
||||||
|
val["warning_threshold"] < val["error_threshold"]
|
||||||
|
and val["warning_threshold"] > 0
|
||||||
|
and val["error_threshold"] > 0
|
||||||
|
):
|
||||||
|
raise serializers.ValidationError(
|
||||||
|
f"Warning threshold must be greater than Error Threshold"
|
||||||
|
)
|
||||||
|
|
||||||
# ping checks
|
# ping checks
|
||||||
if check_type == "ping":
|
if check_type == "ping":
|
||||||
@@ -74,6 +85,14 @@ class CheckSerializer(serializers.ModelSerializer):
|
|||||||
raise serializers.ValidationError(
|
raise serializers.ValidationError(
|
||||||
"A cpuload check for this agent already exists"
|
"A cpuload check for this agent already exists"
|
||||||
)
|
)
|
||||||
|
if (
|
||||||
|
val["warning_threshold"] > val["error_threshold"]
|
||||||
|
and val["warning_threshold"] > 0
|
||||||
|
and val["error_threshold"] > 0
|
||||||
|
):
|
||||||
|
raise serializers.ValidationError(
|
||||||
|
f"Warning threshold must be less than Error Threshold"
|
||||||
|
)
|
||||||
|
|
||||||
if check_type == "memory" and not self.instance:
|
if check_type == "memory" and not self.instance:
|
||||||
if (
|
if (
|
||||||
@@ -85,6 +104,15 @@ class CheckSerializer(serializers.ModelSerializer):
|
|||||||
"A memory check for this agent already exists"
|
"A memory check for this agent already exists"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (
|
||||||
|
val["warning_threshold"] > val["error_threshold"]
|
||||||
|
and val["warning_threshold"] > 0
|
||||||
|
and val["error_threshold"] > 0
|
||||||
|
):
|
||||||
|
raise serializers.ValidationError(
|
||||||
|
f"Warning threshold must be less than Error Threshold"
|
||||||
|
)
|
||||||
|
|
||||||
return val
|
return val
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# Generated by Django 3.1.4 on 2021-02-07 14:26
|
# Generated by Django 3.1.4 on 2021-02-12 14:08
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
@@ -7,7 +7,7 @@ import django.db.models.deletion
|
|||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('alerts', '0004_auto_20210207_1426'),
|
('alerts', '0004_auto_20210212_1408'),
|
||||||
('clients', '0008_auto_20201103_1430'),
|
('clients', '0008_auto_20201103_1430'),
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# Generated by Django 3.1.4 on 2021-02-07 14:50
|
# Generated by Django 3.1.4 on 2021-02-12 14:08
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
@@ -7,7 +7,7 @@ import django.db.models.deletion
|
|||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('alerts', '0004_auto_20210207_1426'),
|
('alerts', '0004_auto_20210212_1408'),
|
||||||
('core', '0012_coresettings_check_history_prune_days'),
|
('core', '0012_coresettings_check_history_prune_days'),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -1,42 +0,0 @@
|
|||||||
# Generated by Django 3.1.4 on 2020-12-10 21:45
|
|
||||||
|
|
||||||
from django.db import migrations
|
|
||||||
from django.conf import settings
|
|
||||||
import os
|
|
||||||
import base64
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
|
|
||||||
def move_scripts_to_db(apps, schema_editor):
|
|
||||||
print("")
|
|
||||||
Script = apps.get_model("scripts", "Script")
|
|
||||||
for script in Script.objects.all():
|
|
||||||
if not script.script_type == "builtin":
|
|
||||||
|
|
||||||
if script.filename:
|
|
||||||
filepath = f"{settings.SCRIPTS_DIR}/userdefined/{script.filename}"
|
|
||||||
else:
|
|
||||||
print(f"No filename on script found. Skipping")
|
|
||||||
continue
|
|
||||||
|
|
||||||
# test if file exists
|
|
||||||
if os.path.exists(filepath):
|
|
||||||
print(f"Found script {script.name}. Importing code.")
|
|
||||||
|
|
||||||
with open(filepath, "rb") as f:
|
|
||||||
script_bytes = f.read().decode("utf-8").encode("ascii", "ignore")
|
|
||||||
script.code_base64 = base64.b64encode(script_bytes).decode("ascii")
|
|
||||||
script.save(update_fields=["code_base64"])
|
|
||||||
else:
|
|
||||||
print(
|
|
||||||
f"Script file {script.name} was not found on the disk. You will need to edit the script in the UI"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
("scripts", "0005_auto_20201207_1606"),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [migrations.RunPython(move_scripts_to_db, migrations.RunPython.noop)]
|
|
||||||
@@ -172,7 +172,7 @@
|
|||||||
<span
|
<span
|
||||||
style="cursor: pointer; text-decoration: underline"
|
style="cursor: pointer; text-decoration: underline"
|
||||||
class="text-primary"
|
class="text-primary"
|
||||||
@click="scriptMoreInfo(props.row)"
|
@click="showScriptOutput(props.row)"
|
||||||
>output</span
|
>output</span
|
||||||
>
|
>
|
||||||
</q-td>
|
</q-td>
|
||||||
@@ -191,16 +191,6 @@
|
|||||||
<q-dialog v-model="showAddAutomatedTask" position="top">
|
<q-dialog v-model="showAddAutomatedTask" position="top">
|
||||||
<AddAutomatedTask @close="showAddAutomatedTask = false" />
|
<AddAutomatedTask @close="showAddAutomatedTask = false" />
|
||||||
</q-dialog>
|
</q-dialog>
|
||||||
|
|
||||||
<q-dialog v-model="showScriptOutput">
|
|
||||||
<ScriptOutput
|
|
||||||
@close="
|
|
||||||
showScriptOutput = false;
|
|
||||||
scriptInfo = {};
|
|
||||||
"
|
|
||||||
:scriptInfo="scriptInfo"
|
|
||||||
/>
|
|
||||||
</q-dialog>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -214,15 +204,13 @@ import ScriptOutput from "@/components/modals/checks/ScriptOutput";
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "AutomatedTasksTab",
|
name: "AutomatedTasksTab",
|
||||||
components: { AddAutomatedTask, ScriptOutput },
|
components: { AddAutomatedTask },
|
||||||
mixins: [mixins],
|
mixins: [mixins],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
showAddAutomatedTask: false,
|
showAddAutomatedTask: false,
|
||||||
showEditAutomatedTask: false,
|
showEditAutomatedTask: false,
|
||||||
showScriptOutput: false,
|
|
||||||
editTaskPk: null,
|
editTaskPk: null,
|
||||||
showScriptOutput: false,
|
|
||||||
scriptInfo: {},
|
scriptInfo: {},
|
||||||
columns: [
|
columns: [
|
||||||
{ name: "enabled", align: "left", field: "enabled" },
|
{ name: "enabled", align: "left", field: "enabled" },
|
||||||
@@ -310,9 +298,12 @@ export default {
|
|||||||
refreshTasks(id) {
|
refreshTasks(id) {
|
||||||
this.$store.dispatch("loadAutomatedTasks", id);
|
this.$store.dispatch("loadAutomatedTasks", id);
|
||||||
},
|
},
|
||||||
scriptMoreInfo(props) {
|
showScriptOutput(script) {
|
||||||
this.scriptInfo = props;
|
this.$q.dialog({
|
||||||
this.showScriptOutput = true;
|
component: ScriptOutput,
|
||||||
|
parent: this,
|
||||||
|
scriptInfo: script,
|
||||||
|
});
|
||||||
},
|
},
|
||||||
showEditTask(task) {
|
showEditTask(task) {
|
||||||
this.$q
|
this.$q
|
||||||
|
|||||||
@@ -214,7 +214,7 @@
|
|||||||
v-else-if="props.row.check_type === 'script'"
|
v-else-if="props.row.check_type === 'script'"
|
||||||
style="cursor: pointer; text-decoration: underline"
|
style="cursor: pointer; text-decoration: underline"
|
||||||
class="text-primary"
|
class="text-primary"
|
||||||
@click="scriptMoreInfo(props.row)"
|
@click="showScriptOutput(props.row)"
|
||||||
>Last Output</span
|
>Last Output</span
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
@@ -225,7 +225,7 @@
|
|||||||
>Last Output</span
|
>Last Output</span
|
||||||
>
|
>
|
||||||
</q-td>
|
</q-td>
|
||||||
<q-td>{{ props.row.last_run }}</q-td>
|
<q-td>{{ props.row.last_run || "Never" }}</q-td>
|
||||||
<q-td v-if="props.row.assigned_task !== null && props.row.assigned_task.length > 1"
|
<q-td v-if="props.row.assigned_task !== null && props.row.assigned_task.length > 1"
|
||||||
>{{ props.row.assigned_task.length }} Tasks</q-td
|
>{{ props.row.assigned_task.length }} Tasks</q-td
|
||||||
>
|
>
|
||||||
@@ -258,15 +258,6 @@
|
|||||||
<q-dialog v-model="showScriptCheck">
|
<q-dialog v-model="showScriptCheck">
|
||||||
<ScriptCheck @close="showScriptCheck = false" :agentpk="selectedAgentPk" :mode="mode" :checkpk="checkpk" />
|
<ScriptCheck @close="showScriptCheck = false" :agentpk="selectedAgentPk" :mode="mode" :checkpk="checkpk" />
|
||||||
</q-dialog>
|
</q-dialog>
|
||||||
<q-dialog v-model="showScriptOutput">
|
|
||||||
<ScriptOutput
|
|
||||||
@close="
|
|
||||||
showScriptOutput = false;
|
|
||||||
scriptInfo = {};
|
|
||||||
"
|
|
||||||
:scriptInfo="scriptInfo"
|
|
||||||
/>
|
|
||||||
</q-dialog>
|
|
||||||
<q-dialog v-model="showEventLogOutput">
|
<q-dialog v-model="showEventLogOutput">
|
||||||
<EventLogCheckOutput
|
<EventLogCheckOutput
|
||||||
@close="
|
@close="
|
||||||
@@ -304,7 +295,6 @@ export default {
|
|||||||
WinSvcCheck,
|
WinSvcCheck,
|
||||||
EventLogCheck,
|
EventLogCheck,
|
||||||
ScriptCheck,
|
ScriptCheck,
|
||||||
ScriptOutput,
|
|
||||||
EventLogCheckOutput,
|
EventLogCheckOutput,
|
||||||
},
|
},
|
||||||
mixins: [mixins],
|
mixins: [mixins],
|
||||||
@@ -319,9 +309,7 @@ export default {
|
|||||||
showWinSvcCheck: false,
|
showWinSvcCheck: false,
|
||||||
showEventLogCheck: false,
|
showEventLogCheck: false,
|
||||||
showScriptCheck: false,
|
showScriptCheck: false,
|
||||||
showScriptOutput: false,
|
|
||||||
showEventLogOutput: false,
|
showEventLogOutput: false,
|
||||||
scriptInfo: {},
|
|
||||||
evtlogdata: {},
|
evtlogdata: {},
|
||||||
columns: [
|
columns: [
|
||||||
{ name: "smsalert", field: "text_alert", align: "left" },
|
{ name: "smsalert", field: "text_alert", align: "left" },
|
||||||
@@ -425,10 +413,6 @@ export default {
|
|||||||
html: true,
|
html: true,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
scriptMoreInfo(props) {
|
|
||||||
this.scriptInfo = props;
|
|
||||||
this.showScriptOutput = true;
|
|
||||||
},
|
|
||||||
eventLogMoreInfo(props) {
|
eventLogMoreInfo(props) {
|
||||||
this.evtlogdata = props;
|
this.evtlogdata = props;
|
||||||
this.showEventLogOutput = true;
|
this.showEventLogOutput = true;
|
||||||
@@ -460,6 +444,13 @@ export default {
|
|||||||
check: check,
|
check: check,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
showScriptOutput(script) {
|
||||||
|
this.$q.dialog({
|
||||||
|
component: ScriptOutput,
|
||||||
|
parent: this,
|
||||||
|
scriptInfo: script,
|
||||||
|
});
|
||||||
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(["selectedAgentPk", "checks", "tabsTableHeight"]),
|
...mapGetters(["selectedAgentPk", "checks", "tabsTableHeight"]),
|
||||||
|
|||||||
@@ -78,7 +78,7 @@
|
|||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
style="cursor: pointer; text-decoration: underline"
|
style="cursor: pointer; text-decoration: underline"
|
||||||
@click="scriptMoreInfo(props.row)"
|
@click="showScriptOutput(props.row)"
|
||||||
class="script-cell text-primary"
|
class="script-cell text-primary"
|
||||||
>output</span
|
>output</span
|
||||||
>
|
>
|
||||||
@@ -103,9 +103,6 @@
|
|||||||
</q-table>
|
</q-table>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
|
|
||||||
<q-dialog v-model="showScriptOutput" @hide="closeScriptOutput">
|
|
||||||
<ScriptOutput @close="closeScriptOutput" :scriptInfo="scriptInfo" />
|
|
||||||
</q-dialog>
|
|
||||||
<q-dialog v-model="showEventLogOutput" @hide="closeEventLogOutput">
|
<q-dialog v-model="showEventLogOutput" @hide="closeEventLogOutput">
|
||||||
<EventLogCheckOutput @close="closeEventLogOutput" :evtlogdata="evtLogData" />
|
<EventLogCheckOutput @close="closeEventLogOutput" :evtlogdata="evtLogData" />
|
||||||
</q-dialog>
|
</q-dialog>
|
||||||
@@ -120,7 +117,6 @@ import EventLogCheckOutput from "@/components/modals/checks/EventLogCheckOutput"
|
|||||||
export default {
|
export default {
|
||||||
name: "PolicyStatus",
|
name: "PolicyStatus",
|
||||||
components: {
|
components: {
|
||||||
ScriptOutput,
|
|
||||||
EventLogCheckOutput,
|
EventLogCheckOutput,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
@@ -139,10 +135,8 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
showScriptOutput: false,
|
|
||||||
showEventLogOutput: false,
|
showEventLogOutput: false,
|
||||||
evtLogData: {},
|
evtLogData: {},
|
||||||
scriptInfo: {},
|
|
||||||
data: [],
|
data: [],
|
||||||
columns: [
|
columns: [
|
||||||
{ name: "agent", label: "Hostname", field: "agent", align: "left", sortable: true },
|
{ name: "agent", label: "Hostname", field: "agent", align: "left", sortable: true },
|
||||||
@@ -225,14 +219,17 @@ export default {
|
|||||||
html: true,
|
html: true,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
scriptMoreInfo(check) {
|
|
||||||
this.scriptInfo = check;
|
|
||||||
this.showScriptOutput = true;
|
|
||||||
},
|
|
||||||
eventLogMoreInfo(check) {
|
eventLogMoreInfo(check) {
|
||||||
this.evtLogData = check;
|
this.evtLogData = check;
|
||||||
this.showEventLogOutput = true;
|
this.showEventLogOutput = true;
|
||||||
},
|
},
|
||||||
|
showScriptOutput(script) {
|
||||||
|
this.$q.dialog({
|
||||||
|
component: ScriptOutput,
|
||||||
|
parent: this,
|
||||||
|
scriptInfo: script,
|
||||||
|
});
|
||||||
|
},
|
||||||
show() {
|
show() {
|
||||||
this.$refs.dialog.show();
|
this.$refs.dialog.show();
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -208,6 +208,10 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (this.check.check_type === "diskspace") {
|
||||||
|
this.chartOptions["yaxis"]["reversed"] = true;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Set the y-axis labels to Failing and Passing
|
// Set the y-axis labels to Failing and Passing
|
||||||
this.chartOptions["yaxis"] = {
|
this.chartOptions["yaxis"] = {
|
||||||
|
|||||||
@@ -56,6 +56,21 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="col-2 q-my-sm">Failure action timeout</div>
|
||||||
|
<div class="col-10 q-mb-sm">
|
||||||
|
<q-input
|
||||||
|
outlined
|
||||||
|
type="number"
|
||||||
|
v-model.number="template.action_timeout"
|
||||||
|
dense
|
||||||
|
:rules="[
|
||||||
|
val => !!val || 'Failure action timeout is required',
|
||||||
|
val => val > 0 || 'Timeout must be greater than 0',
|
||||||
|
val => val > 60 || 'Timeout must be 60 or less',
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="col-2 q-my-sm">
|
<div class="col-2 q-my-sm">
|
||||||
<span style="text-decoration: underline; cursor: help"
|
<span style="text-decoration: underline; cursor: help"
|
||||||
>Resolved action
|
>Resolved action
|
||||||
@@ -92,6 +107,21 @@
|
|||||||
new-value-mode="add"
|
new-value-mode="add"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="col-2 q-my-sm">Resolved action timeout</div>
|
||||||
|
<div class="col-10 q-mb-sm">
|
||||||
|
<q-input
|
||||||
|
outlined
|
||||||
|
type="number"
|
||||||
|
v-model.number="template.resolved_action_timeout"
|
||||||
|
dense
|
||||||
|
:rules="[
|
||||||
|
val => !!val || 'Resolved action timeout is required',
|
||||||
|
val => val > 0 || 'Timeout must be greater than 0',
|
||||||
|
val => val > 60 || 'Timeout must be 60 or less',
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
|
|
||||||
<div class="q-pl-md text-subtitle1">Email Settings (Overrides global email settings)</div>
|
<div class="q-pl-md text-subtitle1">Email Settings (Overrides global email settings)</div>
|
||||||
@@ -222,7 +252,7 @@
|
|||||||
type="number"
|
type="number"
|
||||||
v-model.number="template.agent_periodic_alert_days"
|
v-model.number="template.agent_periodic_alert_days"
|
||||||
dense
|
dense
|
||||||
:rules="[val => val >= 0]"
|
:rules="[val => val >= 0 || 'Periodic days must be 0 or greater']"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
@@ -338,7 +368,7 @@
|
|||||||
type="number"
|
type="number"
|
||||||
v-model.number="template.check_periodic_alert_days"
|
v-model.number="template.check_periodic_alert_days"
|
||||||
dense
|
dense
|
||||||
:rules="[val => val >= 0]"
|
:rules="[val => val >= 0 || 'Periodic days must be 0 or greater']"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
@@ -482,8 +512,10 @@ export default {
|
|||||||
is_active: true,
|
is_active: true,
|
||||||
action: null,
|
action: null,
|
||||||
action_args: [],
|
action_args: [],
|
||||||
|
action_timeout: 15,
|
||||||
resolved_action: null,
|
resolved_action: null,
|
||||||
resolved_action_args: [],
|
resolved_action_args: [],
|
||||||
|
resolved_action_timeout: 15,
|
||||||
email_recipients: [],
|
email_recipients: [],
|
||||||
email_from: "",
|
email_from: "",
|
||||||
text_recipients: [],
|
text_recipients: [],
|
||||||
|
|||||||
@@ -113,6 +113,24 @@
|
|||||||
<q-icon name="flag" size="sm" class="cursor-pointer" @click="resolveAlert(props.row)">
|
<q-icon name="flag" size="sm" class="cursor-pointer" @click="resolveAlert(props.row)">
|
||||||
<q-tooltip>Resolve alert</q-tooltip>
|
<q-tooltip>Resolve alert</q-tooltip>
|
||||||
</q-icon>
|
</q-icon>
|
||||||
|
<q-icon
|
||||||
|
v-if="props.row.action_run"
|
||||||
|
name="mdi-archive-alert"
|
||||||
|
size="sm"
|
||||||
|
class="cursor-pointer"
|
||||||
|
@click="showScriptOutput(props.row, true)"
|
||||||
|
>
|
||||||
|
<q-tooltip>Show failure action run results</q-tooltip>
|
||||||
|
</q-icon>
|
||||||
|
<q-icon
|
||||||
|
v-if="props.row.resolved_action_run"
|
||||||
|
name="mdi-archive-check"
|
||||||
|
size="sm"
|
||||||
|
class="cursor-pointer"
|
||||||
|
@click="showScriptOutput(props.row, false)"
|
||||||
|
>
|
||||||
|
<q-tooltip>Show resolved action run results</q-tooltip>
|
||||||
|
</q-icon>
|
||||||
</div>
|
</div>
|
||||||
</q-td>
|
</q-td>
|
||||||
</template>
|
</template>
|
||||||
@@ -130,6 +148,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import mixins from "@/mixins/mixins";
|
import mixins from "@/mixins/mixins";
|
||||||
|
import ScriptOutput from "@/components/modals/checks/ScriptOutput";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "AlertsOverview",
|
name: "AlertsOverview",
|
||||||
@@ -380,6 +399,30 @@ export default {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
showScriptOutput(alert, failure = false) {
|
||||||
|
let results = {};
|
||||||
|
if (failure) {
|
||||||
|
results.readable_desc = `${alert.alert_type} failure action results`;
|
||||||
|
results.execution_time = alert.action_execution_time;
|
||||||
|
results.retcode = alert.action_retcode;
|
||||||
|
results.stdout = alert.action_stdout;
|
||||||
|
results.errout = alert.action_errout;
|
||||||
|
results.last_run = alert.action_run;
|
||||||
|
} else {
|
||||||
|
results.readable_desc = `${alert.alert_type} resolved action results`;
|
||||||
|
results.execution_time = alert.resolved_action_execution_time;
|
||||||
|
results.retcode = alert.resolved_action_retcode;
|
||||||
|
results.stdout = alert.resolved_action_stdout;
|
||||||
|
results.errout = alert.resolved_action_errout;
|
||||||
|
results.last_run = alert.resolved_action_run;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$q.dialog({
|
||||||
|
component: ScriptOutput,
|
||||||
|
parent: this,
|
||||||
|
scriptInfo: results,
|
||||||
|
});
|
||||||
|
},
|
||||||
alertColor(severity) {
|
alertColor(severity) {
|
||||||
if (severity === "error") {
|
if (severity === "error") {
|
||||||
return "red";
|
return "red";
|
||||||
|
|||||||
@@ -11,25 +11,19 @@
|
|||||||
<q-card-section>
|
<q-card-section>
|
||||||
<q-input
|
<q-input
|
||||||
outlined
|
outlined
|
||||||
|
type="number"
|
||||||
v-model.number="cpuloadcheck.warning_threshold"
|
v-model.number="cpuloadcheck.warning_threshold"
|
||||||
label="Warning Threshold (%)"
|
label="Warning Threshold (%)"
|
||||||
:rules="[
|
:rules="[val => val >= 0 || 'Minimum threshold is 0', val => val < 100 || 'Maximum threshold is 99']"
|
||||||
val => !!val || '*Required',
|
|
||||||
val => val >= 1 || 'Minimum threshold is 1',
|
|
||||||
val => val < 100 || 'Maximum threshold is 99',
|
|
||||||
]"
|
|
||||||
/>
|
/>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
<q-input
|
<q-input
|
||||||
outlined
|
outlined
|
||||||
|
type="number"
|
||||||
v-model.number="cpuloadcheck.error_threshold"
|
v-model.number="cpuloadcheck.error_threshold"
|
||||||
label="Error Threshold (%)"
|
label="Error Threshold (%)"
|
||||||
:rules="[
|
:rules="[val => val >= 0 || 'Minimum threshold is 0', val => val < 100 || 'Maximum threshold is 99']"
|
||||||
val => !!val || '*Required',
|
|
||||||
val => val >= 1 || 'Minimum threshold is 1',
|
|
||||||
val => val < 100 || 'Maximum threshold is 99',
|
|
||||||
]"
|
|
||||||
/>
|
/>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
@@ -74,22 +68,12 @@ export default {
|
|||||||
failOptions: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
|
failOptions: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
|
||||||
thresholdIsValid() {
|
|
||||||
return (
|
|
||||||
this.cpuloadcheck.warning_threshold === 0 ||
|
|
||||||
this.cpuloadcheck.error_threshold === 0 ||
|
|
||||||
this.cpuloadcheck.warning_threshold < this.cpuloadcheck.error_threshold
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
getCheck() {
|
getCheck() {
|
||||||
axios.get(`/checks/${this.checkpk}/check/`).then(r => (this.cpuloadcheck = r.data));
|
axios.get(`/checks/${this.checkpk}/check/`).then(r => (this.cpuloadcheck = r.data));
|
||||||
},
|
},
|
||||||
addCheck() {
|
addCheck() {
|
||||||
if (!this.thresholdIsValid) {
|
if (!this.isValidThreshold(this.cpuloadcheck.warning_threshold, this.cpuloadcheck.error_threshold)) {
|
||||||
this.notifyError("Warning Threshold needs to be less than Error threshold");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,8 +92,7 @@ export default {
|
|||||||
.catch(e => this.notifyError(e.response.data.non_field_errors));
|
.catch(e => this.notifyError(e.response.data.non_field_errors));
|
||||||
},
|
},
|
||||||
editCheck() {
|
editCheck() {
|
||||||
if (!this.thresholdIsValid) {
|
if (!this.isValidThreshold(this.cpuloadcheck.warning_threshold, this.cpuloadcheck.error_threshold)) {
|
||||||
this.notifyError("Warning Threshold needs to be less than Error threshold");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,25 +20,19 @@
|
|||||||
<q-card-section>
|
<q-card-section>
|
||||||
<q-input
|
<q-input
|
||||||
outlined
|
outlined
|
||||||
|
type="number"
|
||||||
v-model.number="diskcheck.warning_threshold"
|
v-model.number="diskcheck.warning_threshold"
|
||||||
label="Warning Threshold (%)"
|
label="Warning Threshold Remaining (%)"
|
||||||
:rules="[
|
:rules="[val => val >= 0 || 'Minimum threshold is 0', val => val < 100 || 'Maximum threshold is 99']"
|
||||||
val => !!val || '*Required',
|
|
||||||
val => val >= 1 || 'Minimum threshold is 1',
|
|
||||||
val => val < 100 || 'Maximum threshold is 99',
|
|
||||||
]"
|
|
||||||
/>
|
/>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
<q-input
|
<q-input
|
||||||
outlined
|
outlined
|
||||||
|
type="number"
|
||||||
v-model.number="diskcheck.error_threshold"
|
v-model.number="diskcheck.error_threshold"
|
||||||
label="Error Threshold (%)"
|
label="Error Threshold Remaining (%)"
|
||||||
:rules="[
|
:rules="[val => val >= 0 || 'Minimum threshold is 0', val => val < 100 || 'Maximum threshold is 99']"
|
||||||
val => !!val || '*Required',
|
|
||||||
val => val >= 1 || 'Minimum threshold is 1',
|
|
||||||
val => val < 100 || 'Maximum threshold is 99',
|
|
||||||
]"
|
|
||||||
/>
|
/>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
@@ -62,7 +56,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { mapState, mapGetters } from "vuex";
|
import { mapGetters } from "vuex";
|
||||||
import mixins from "@/mixins/mixins";
|
import mixins from "@/mixins/mixins";
|
||||||
export default {
|
export default {
|
||||||
name: "DiskSpaceCheck",
|
name: "DiskSpaceCheck",
|
||||||
@@ -102,8 +96,7 @@ export default {
|
|||||||
axios.get(`/checks/${this.checkpk}/check/`).then(r => (this.diskcheck = r.data));
|
axios.get(`/checks/${this.checkpk}/check/`).then(r => (this.diskcheck = r.data));
|
||||||
},
|
},
|
||||||
addCheck() {
|
addCheck() {
|
||||||
if (!this.thresholdIsValid) {
|
if (!this.isValidThreshold(this.diskcheck.warning_threshold, this.diskcheck.error_threshold, true)) {
|
||||||
this.notifyError("Warning Threshold needs to be greater than Error threshold");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,8 +115,7 @@ export default {
|
|||||||
.catch(e => this.notifyError(e.response.data.non_field_errors));
|
.catch(e => this.notifyError(e.response.data.non_field_errors));
|
||||||
},
|
},
|
||||||
editCheck() {
|
editCheck() {
|
||||||
if (!this.thresholdIsValid) {
|
if (!this.isValidThreshold(this.diskcheck.warning_threshold, this.diskcheck.error_threshold, true)) {
|
||||||
this.notifyError("Warning Threshold needs to be greater than Error threshold");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,13 +136,6 @@ export default {
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(["agentDisks"]),
|
...mapGetters(["agentDisks"]),
|
||||||
thresholdIsValid() {
|
|
||||||
return (
|
|
||||||
!!this.diskcheck.warning_threshold ||
|
|
||||||
!!this.diskcheck.error_threshold ||
|
|
||||||
this.diskcheck.warning_threshold > this.diskcheck.error_threshold
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
if (this.mode === "add") {
|
if (this.mode === "add") {
|
||||||
|
|||||||
@@ -11,25 +11,19 @@
|
|||||||
<q-card-section>
|
<q-card-section>
|
||||||
<q-input
|
<q-input
|
||||||
outlined
|
outlined
|
||||||
|
type="number"
|
||||||
v-model.number="memcheck.warning_threshold"
|
v-model.number="memcheck.warning_threshold"
|
||||||
label="Warning Threshold (%)"
|
label="Warning Threshold (%)"
|
||||||
:rules="[
|
:rules="[val => val >= 0 || 'Minimum threshold is 0', val => val < 100 || 'Maximum threshold is 99']"
|
||||||
val => !!val || '*Required',
|
|
||||||
val => val >= 1 || 'Minimum threshold is 1',
|
|
||||||
val => val < 100 || 'Maximum threshold is 99',
|
|
||||||
]"
|
|
||||||
/>
|
/>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
<q-input
|
<q-input
|
||||||
outlined
|
outlined
|
||||||
|
type="number"
|
||||||
v-model.number="memcheck.error_threshold"
|
v-model.number="memcheck.error_threshold"
|
||||||
label="Error Threshold (%)"
|
label="Error Threshold (%)"
|
||||||
:rules="[
|
:rules="[val => val >= 0 || 'Minimum threshold is 0', val => val < 100 || 'Maximum threshold is 99']"
|
||||||
val => !!val || '*Required',
|
|
||||||
val => val >= 1 || 'Minimum threshold is 1',
|
|
||||||
val => val < 100 || 'Maximum threshold is 99',
|
|
||||||
]"
|
|
||||||
/>
|
/>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
@@ -74,22 +68,12 @@ export default {
|
|||||||
failOptions: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
|
failOptions: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
|
||||||
thresholdIsValid() {
|
|
||||||
return (
|
|
||||||
this.memcheck.warning_threshold === 0 ||
|
|
||||||
this.memcheck.error_threshold === 0 ||
|
|
||||||
this.memcheck.warning_threshold < this.memcheck.error_threshold
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
getCheck() {
|
getCheck() {
|
||||||
axios.get(`/checks/${this.checkpk}/check/`).then(r => (this.memcheck = r.data));
|
axios.get(`/checks/${this.checkpk}/check/`).then(r => (this.memcheck = r.data));
|
||||||
},
|
},
|
||||||
addCheck() {
|
addCheck() {
|
||||||
if (!this.thresholdIsValid) {
|
if (!this.isValidThreshold(this.memcheck.warning_threshold, this.memcheck.error_threshold)) {
|
||||||
this.notifyError("Warning Threshold needs to be less than Error threshold");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,8 +92,7 @@ export default {
|
|||||||
.catch(e => this.notifyError(e.response.data.non_field_errors));
|
.catch(e => this.notifyError(e.response.data.non_field_errors));
|
||||||
},
|
},
|
||||||
editCheck() {
|
editCheck() {
|
||||||
if (!this.thresholdIsValid) {
|
if (!this.isValidThreshold(this.memcheck.warning_threshold, this.memcheck.error_threshold)) {
|
||||||
this.notifyError("Warning Threshold needs to be less than Error threshold");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,44 +1,56 @@
|
|||||||
<template>
|
<template>
|
||||||
<q-card style="min-width: 70vw" class="q-pa-xs">
|
<q-dialog ref="dialog" @hide="onHide">
|
||||||
<q-card-section>
|
<q-card class="q-dialog-plugin q-pa-xs" style="min-width: 70vw">
|
||||||
<div class="row items-center">
|
<q-bar>
|
||||||
<div class="text-h6">{{ scriptInfo.readable_desc }}</div>
|
{{ scriptInfo.readable_desc }}
|
||||||
<q-space />
|
<q-space />
|
||||||
<q-btn icon="close" flat round dense v-close-popup />
|
<q-btn dense flat icon="close" v-close-popup>
|
||||||
</div>
|
<q-tooltip content-class="bg-white text-primary">Close</q-tooltip>
|
||||||
<div>
|
</q-btn>
|
||||||
Last Run:
|
</q-bar>
|
||||||
<code>{{ scriptInfo.last_run }}</code>
|
<q-card-section>
|
||||||
<br />Run Time:
|
<div>
|
||||||
<code>{{ scriptInfo.execution_time}} seconds</code>
|
Last Run:
|
||||||
<br />Return Code:
|
<code>{{ scriptInfo.last_run }}</code>
|
||||||
<code>{{ scriptInfo.retcode }}</code>
|
<br />Run Time:
|
||||||
|
<code>{{ scriptInfo.execution_time }} seconds</code>
|
||||||
|
<br />Return Code:
|
||||||
|
<code>{{ scriptInfo.retcode }}</code>
|
||||||
|
<br />
|
||||||
|
</div>
|
||||||
<br />
|
<br />
|
||||||
</div>
|
<div v-if="scriptInfo.stdout">
|
||||||
<br />
|
Standard Output
|
||||||
<div v-if="scriptInfo.stdout">
|
<q-separator />
|
||||||
Standard Output
|
<q-scroll-area style="height: 50vh; max-height: 70vh">
|
||||||
<q-separator />
|
<pre>{{ scriptInfo.stdout }}</pre>
|
||||||
<q-scroll-area style="height: 50vh; max-height: 70vh;">
|
</q-scroll-area>
|
||||||
<pre>{{ scriptInfo.stdout }}</pre>
|
</div>
|
||||||
</q-scroll-area>
|
<div v-if="scriptInfo.stderr">
|
||||||
</div>
|
Standard Error:
|
||||||
<div v-if="scriptInfo.stderr">
|
<q-scroll-area style="height: 50vh; max-height: 70vh">
|
||||||
Standard Error:
|
<pre>{{ scriptInfo.stderr }}</pre>
|
||||||
<q-scroll-area style="height: 50vh; max-height: 70vh;">
|
</q-scroll-area>
|
||||||
<pre>{{ scriptInfo.stderr }}</pre>
|
</div>
|
||||||
</q-scroll-area>
|
</q-card-section>
|
||||||
</div>
|
</q-card>
|
||||||
</q-card-section>
|
</q-dialog>
|
||||||
</q-card>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: "ScriptOutput",
|
name: "ScriptOutput",
|
||||||
props: ["scriptInfo"],
|
props: ["scriptInfo"],
|
||||||
beforeDestroy() {
|
methods: {
|
||||||
this.$emit("close");
|
show() {
|
||||||
|
this.$refs.dialog.show();
|
||||||
|
},
|
||||||
|
hide() {
|
||||||
|
this.$refs.dialog.hide();
|
||||||
|
},
|
||||||
|
onHide() {
|
||||||
|
this.$emit("hide");
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
@@ -84,6 +84,25 @@ export default {
|
|||||||
notifyInfo(msg, timeout = 2000) {
|
notifyInfo(msg, timeout = 2000) {
|
||||||
Notify.create(notifyInfoConfig(msg, timeout));
|
Notify.create(notifyInfoConfig(msg, timeout));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
isValidThreshold(warning, error, diskcheck = false) {
|
||||||
|
if (warning === 0 && error === 0) {
|
||||||
|
Notify.create(notifyErrorConfig("Warning Threshold or Error Threshold need to be set", 2000));
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!diskcheck && warning > error && warning > 0 && error > 0) {
|
||||||
|
Notify.create(notifyErrorConfig("Warning Threshold must be less than Error Threshold", 2000));
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (diskcheck && warning < error && warning > 0 && error > 0) {
|
||||||
|
Notify.create(notifyErrorConfig("Warning Threshold must be more than Error Threshold", 2000));
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
isValidEmail(val) {
|
isValidEmail(val) {
|
||||||
const email = /^(?=[a-zA-Z0-9@._%+-]{6,254}$)[a-zA-Z0-9._%+-]{1,64}@(?:[a-zA-Z0-9-]{1,63}\.){1,8}[a-zA-Z]{2,63}$/;
|
const email = /^(?=[a-zA-Z0-9@._%+-]{6,254}$)[a-zA-Z0-9._%+-]{1,64}@(?:[a-zA-Z0-9-]{1,63}\.){1,8}[a-zA-Z]{2,63}$/;
|
||||||
return email.test(val);
|
return email.test(val);
|
||||||
|
|||||||
Reference in New Issue
Block a user