Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/zabbix/zabbix.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJanis Freibergs <janis.freibergs@zabbix.com>2021-11-25 15:25:31 +0300
committerJanis Freibergs <janis.freibergs@zabbix.com>2021-11-25 15:25:31 +0300
commit86dd93671922df992b9745aa9eeb45ecb2dffc1b (patch)
treee2606885dec5eaba22a94c6c0528b4bd8eac2808
parent882f0efe3fbdd4bc81d55702c897b8687285b18d (diff)
..F....... [ZBXNEXT-6999] added temporary commit
-rw-r--r--create/src/schema.tmpl2
-rw-r--r--sass/stylesheets/sass/components/_menu-main.scss2
-rw-r--r--src/libs/zbxdbupgrade/dbupgrade_5050.c10
-rw-r--r--ui/app/controllers/CControllerPopupMassupdateService.php2
-rw-r--r--ui/app/controllers/CControllerPopupServiceEdit.php2
-rw-r--r--ui/app/controllers/CControllerPopupServiceStatusRuleEdit.php2
-rw-r--r--ui/app/controllers/CControllerPopupServiceTimeEdit.php2
-rw-r--r--ui/app/controllers/CControllerServiceCreate.php2
-rw-r--r--ui/app/controllers/CControllerServiceDelete.php2
-rw-r--r--ui/app/controllers/CControllerServiceList.php2
-rwxr-xr-xui/app/controllers/CControllerServiceListEdit.php2
-rwxr-xr-xui/app/controllers/CControllerServiceListEditRefresh.php2
-rw-r--r--ui/app/controllers/CControllerServiceListRefresh.php2
-rw-r--r--ui/app/controllers/CControllerServiceStatusRuleValidate.php2
-rw-r--r--ui/app/controllers/CControllerServiceTimeValidate.php2
-rw-r--r--ui/app/controllers/CControllerServiceUpdate.php2
-rw-r--r--ui/app/controllers/CControllerSlaList.php185
-rw-r--r--ui/app/controllers/CControllerUserroleCreate.php6
-rw-r--r--ui/app/controllers/CControllerUserroleEdit.php6
-rw-r--r--ui/app/controllers/CControllerUserroleUpdate.php6
-rw-r--r--ui/app/partials/services.service.list.edit.php (renamed from ui/app/partials/monitoring.service.list.edit.php)0
-rw-r--r--ui/app/partials/services.service.list.php (renamed from ui/app/partials/monitoring.service.list.php)0
-rw-r--r--ui/app/partials/services.sla.list.php97
-rw-r--r--ui/app/views/js/administration.userrole.edit.js.php8
-rw-r--r--[-rwxr-xr-x]ui/app/views/js/services.service.list.js.php (renamed from ui/app/views/js/monitoring.service.list.js.php)0
-rw-r--r--ui/app/views/js/services.sla.list.js.php165
-rw-r--r--ui/app/views/popup.sla.edit.php428
-rw-r--r--[-rwxr-xr-x]ui/app/views/services.service.list.edit.php (renamed from ui/app/views/monitoring.service.list.edit.php)4
-rw-r--r--[-rwxr-xr-x]ui/app/views/services.service.list.edit.refresh.php (renamed from ui/app/views/monitoring.service.list.edit.refresh.php)2
-rw-r--r--ui/app/views/services.service.list.php (renamed from ui/app/views/monitoring.service.list.php)4
-rw-r--r--ui/app/views/services.service.list.refresh.php (renamed from ui/app/views/monitoring.service.list.refresh.php)2
-rw-r--r--ui/app/views/services.sla.list.php101
-rw-r--r--ui/assets/styles/blue-theme.css6
-rw-r--r--ui/include/classes/helpers/CMenuHelper.php41
-rw-r--r--ui/include/classes/helpers/CRoleHelper.php78
-rw-r--r--ui/include/classes/helpers/CSlaHelper.php72
-rw-r--r--ui/include/classes/mvc/CRouter.php12
-rw-r--r--ui/include/defines.inc.php5
-rw-r--r--ui/tests/selenium/testSID.php4
39 files changed, 1218 insertions, 54 deletions
diff --git a/create/src/schema.tmpl b/create/src/schema.tmpl
index 56f9fd0a1e4..afb4688a90c 100644
--- a/create/src/schema.tmpl
+++ b/create/src/schema.tmpl
@@ -1929,6 +1929,6 @@ TABLE|dbversion|dbversionid|
FIELD |dbversionid |t_id | |NOT NULL |0
FIELD |mandatory |t_integer |'0' |NOT NULL |
FIELD |optional |t_integer |'0' |NOT NULL |
-ROW |1 |5050127 |5050127
+ROW |1 |5050128 |5050128
diff --git a/sass/stylesheets/sass/components/_menu-main.scss b/sass/stylesheets/sass/components/_menu-main.scss
index 5296387e8ac..ab3451a1005 100644
--- a/sass/stylesheets/sass/components/_menu-main.scss
+++ b/sass/stylesheets/sass/components/_menu-main.scss
@@ -7,6 +7,7 @@ $menu-main-icons: (
dashboard: -540px -664px,
problems: -540px -688px,
monitoring: -540px -712px,
+ services: -42px -832px,
inventory: -540px -736px,
reports: -540px -760px,
configuration: -540px -784px,
@@ -30,6 +31,7 @@ $menu-main-icons: (
// .icon-dashboard
// .icon-problems
// .icon-monitoring
+// .icon-services
// .icon-inventory
// .icon-reports
// .icon-configuration
diff --git a/src/libs/zbxdbupgrade/dbupgrade_5050.c b/src/libs/zbxdbupgrade/dbupgrade_5050.c
index 3cd1bec6246..f2eea80a5cc 100644
--- a/src/libs/zbxdbupgrade/dbupgrade_5050.c
+++ b/src/libs/zbxdbupgrade/dbupgrade_5050.c
@@ -1329,6 +1329,15 @@ static int DBpatch_5050127(void)
return DBadd_field("services", &field);
}
+static int DBpatch_5050128(void)
+{
+ if (ZBX_DB_OK > DBexecute("update role_rule set name='ui.services.services' where name='ui.monitoring.services'"))
+ return FAIL;
+
+ return SUCCEED;
+}
+
+
#endif
DBPATCH_START(5050)
@@ -1450,5 +1459,6 @@ DBPATCH_ADD(5050124, 0, 1)
DBPATCH_ADD(5050125, 0, 1)
DBPATCH_ADD(5050126, 0, 1)
DBPATCH_ADD(5050127, 0, 1)
+DBPATCH_ADD(5050128, 0, 1)
DBPATCH_END()
diff --git a/ui/app/controllers/CControllerPopupMassupdateService.php b/ui/app/controllers/CControllerPopupMassupdateService.php
index dc76e61ba07..d1ec953f963 100644
--- a/ui/app/controllers/CControllerPopupMassupdateService.php
+++ b/ui/app/controllers/CControllerPopupMassupdateService.php
@@ -50,7 +50,7 @@ class CControllerPopupMassupdateService extends CController {
* @throws APIException
*/
protected function checkPermissions(): bool {
- if (!$this->checkAccess(CRoleHelper::UI_MONITORING_SERVICES)) {
+ if (!$this->checkAccess(CRoleHelper::UI_SERVICES_SERVICES)) {
return false;
}
diff --git a/ui/app/controllers/CControllerPopupServiceEdit.php b/ui/app/controllers/CControllerPopupServiceEdit.php
index 96d1ec14120..d7c11cfdf47 100644
--- a/ui/app/controllers/CControllerPopupServiceEdit.php
+++ b/ui/app/controllers/CControllerPopupServiceEdit.php
@@ -48,7 +48,7 @@ class CControllerPopupServiceEdit extends CController {
* @throws APIException
*/
protected function checkPermissions(): bool {
- if (!$this->checkAccess(CRoleHelper::UI_MONITORING_SERVICES)) {
+ if (!$this->checkAccess(CRoleHelper::UI_SERVICES_SERVICES)) {
return false;
}
diff --git a/ui/app/controllers/CControllerPopupServiceStatusRuleEdit.php b/ui/app/controllers/CControllerPopupServiceStatusRuleEdit.php
index f457abd02a3..e501f523f92 100644
--- a/ui/app/controllers/CControllerPopupServiceStatusRuleEdit.php
+++ b/ui/app/controllers/CControllerPopupServiceStatusRuleEdit.php
@@ -47,7 +47,7 @@ class CControllerPopupServiceStatusRuleEdit extends CController {
}
protected function checkPermissions(): bool {
- return $this->checkAccess(CRoleHelper::UI_MONITORING_SERVICES);
+ return $this->checkAccess(CRoleHelper::UI_SERVICES_SERVICES);
}
protected function doAction(): void {
diff --git a/ui/app/controllers/CControllerPopupServiceTimeEdit.php b/ui/app/controllers/CControllerPopupServiceTimeEdit.php
index 515c6fc76da..b31be8009e6 100644
--- a/ui/app/controllers/CControllerPopupServiceTimeEdit.php
+++ b/ui/app/controllers/CControllerPopupServiceTimeEdit.php
@@ -54,7 +54,7 @@ class CControllerPopupServiceTimeEdit extends CController {
}
protected function checkPermissions(): bool {
- return $this->checkAccess(CRoleHelper::UI_MONITORING_SERVICES);
+ return $this->checkAccess(CRoleHelper::UI_SERVICES_SERVICES);
}
protected function doAction(): void {
diff --git a/ui/app/controllers/CControllerServiceCreate.php b/ui/app/controllers/CControllerServiceCreate.php
index 53f59fcfbf3..bfb0f162c2c 100644
--- a/ui/app/controllers/CControllerServiceCreate.php
+++ b/ui/app/controllers/CControllerServiceCreate.php
@@ -103,7 +103,7 @@ class CControllerServiceCreate extends CController {
}
protected function checkPermissions(): bool {
- return $this->checkAccess(CRoleHelper::UI_MONITORING_SERVICES);
+ return $this->checkAccess(CRoleHelper::UI_SERVICES_SERVICES);
}
/**
diff --git a/ui/app/controllers/CControllerServiceDelete.php b/ui/app/controllers/CControllerServiceDelete.php
index 653845a69ff..b314fd0df01 100644
--- a/ui/app/controllers/CControllerServiceDelete.php
+++ b/ui/app/controllers/CControllerServiceDelete.php
@@ -40,7 +40,7 @@ class CControllerServiceDelete extends CController {
* @throws APIException
*/
protected function checkPermissions(): bool {
- if (!$this->checkAccess(CRoleHelper::UI_MONITORING_SERVICES)) {
+ if (!$this->checkAccess(CRoleHelper::UI_SERVICES_SERVICES)) {
return false;
}
diff --git a/ui/app/controllers/CControllerServiceList.php b/ui/app/controllers/CControllerServiceList.php
index 73ab4e3004d..71abaed622b 100644
--- a/ui/app/controllers/CControllerServiceList.php
+++ b/ui/app/controllers/CControllerServiceList.php
@@ -50,7 +50,7 @@ class CControllerServiceList extends CControllerServiceListGeneral {
* @throws APIException
*/
protected function checkPermissions(): bool {
- if (!$this->checkAccess(CRoleHelper::UI_MONITORING_SERVICES)) {
+ if (!$this->checkAccess(CRoleHelper::UI_SERVICES_SERVICES)) {
return false;
}
diff --git a/ui/app/controllers/CControllerServiceListEdit.php b/ui/app/controllers/CControllerServiceListEdit.php
index eb224588d33..c815c9fc1c1 100755
--- a/ui/app/controllers/CControllerServiceListEdit.php
+++ b/ui/app/controllers/CControllerServiceListEdit.php
@@ -54,7 +54,7 @@ class CControllerServiceListEdit extends CControllerServiceListGeneral {
* @throws APIException
*/
protected function checkPermissions(): bool {
- if (!$this->checkAccess(CRoleHelper::UI_MONITORING_SERVICES) || !$this->canEdit()) {
+ if (!$this->checkAccess(CRoleHelper::UI_SERVICES_SERVICES) || !$this->canEdit()) {
return false;
}
diff --git a/ui/app/controllers/CControllerServiceListEditRefresh.php b/ui/app/controllers/CControllerServiceListEditRefresh.php
index 94805b21059..656ec8013d1 100755
--- a/ui/app/controllers/CControllerServiceListEditRefresh.php
+++ b/ui/app/controllers/CControllerServiceListEditRefresh.php
@@ -54,7 +54,7 @@ class CControllerServiceListEditRefresh extends CControllerServiceListGeneral {
}
protected function checkPermissions(): bool {
- if (!$this->checkAccess(CRoleHelper::UI_MONITORING_SERVICES) || !$this->canEdit()) {
+ if (!$this->checkAccess(CRoleHelper::UI_SERVICES_SERVICES) || !$this->canEdit()) {
return false;
}
diff --git a/ui/app/controllers/CControllerServiceListRefresh.php b/ui/app/controllers/CControllerServiceListRefresh.php
index d8d2a291307..1a9b875c5ff 100644
--- a/ui/app/controllers/CControllerServiceListRefresh.php
+++ b/ui/app/controllers/CControllerServiceListRefresh.php
@@ -51,7 +51,7 @@ class CControllerServiceListRefresh extends CControllerServiceListGeneral {
}
protected function checkPermissions(): bool {
- if (!$this->checkAccess(CRoleHelper::UI_MONITORING_SERVICES)) {
+ if (!$this->checkAccess(CRoleHelper::UI_SERVICES_SERVICES)) {
return false;
}
diff --git a/ui/app/controllers/CControllerServiceStatusRuleValidate.php b/ui/app/controllers/CControllerServiceStatusRuleValidate.php
index 3b20b8753a7..99b368f501f 100644
--- a/ui/app/controllers/CControllerServiceStatusRuleValidate.php
+++ b/ui/app/controllers/CControllerServiceStatusRuleValidate.php
@@ -84,7 +84,7 @@ class CControllerServiceStatusRuleValidate extends CController {
}
protected function checkPermissions(): bool {
- return $this->checkAccess(CRoleHelper::UI_MONITORING_SERVICES);
+ return $this->checkAccess(CRoleHelper::UI_SERVICES_SERVICES);
}
protected function doAction(): void {
diff --git a/ui/app/controllers/CControllerServiceTimeValidate.php b/ui/app/controllers/CControllerServiceTimeValidate.php
index 02d4c446ec9..3064f9c9a2f 100644
--- a/ui/app/controllers/CControllerServiceTimeValidate.php
+++ b/ui/app/controllers/CControllerServiceTimeValidate.php
@@ -109,7 +109,7 @@ class CControllerServiceTimeValidate extends CController {
}
protected function checkPermissions(): bool {
- return $this->checkAccess(CRoleHelper::UI_MONITORING_SERVICES);
+ return $this->checkAccess(CRoleHelper::UI_SERVICES_SERVICES);
}
protected function doAction(): void {
diff --git a/ui/app/controllers/CControllerServiceUpdate.php b/ui/app/controllers/CControllerServiceUpdate.php
index 41988240ad7..af2ab5f86e1 100644
--- a/ui/app/controllers/CControllerServiceUpdate.php
+++ b/ui/app/controllers/CControllerServiceUpdate.php
@@ -107,7 +107,7 @@ class CControllerServiceUpdate extends CController {
* @throws APIException
*/
protected function checkPermissions(): bool {
- if (!$this->checkAccess(CRoleHelper::UI_MONITORING_SERVICES)) {
+ if (!$this->checkAccess(CRoleHelper::UI_SERVICES_SERVICES)) {
return false;
}
diff --git a/ui/app/controllers/CControllerSlaList.php b/ui/app/controllers/CControllerSlaList.php
new file mode 100644
index 00000000000..ed3c4e2ed3f
--- /dev/null
+++ b/ui/app/controllers/CControllerSlaList.php
@@ -0,0 +1,185 @@
+<?php declare(strict_types = 1);
+/*
+** Zabbix
+** Copyright (C) 2001-2021 Zabbix SIA
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+**/
+
+
+class CControllerSlaList extends CController {
+
+ protected function init(): void {
+ $this->disableSIDValidation();
+ }
+
+ protected function checkInput(): bool {
+ $fields = [
+ 'filter_name' => 'string',
+ 'filter_status' => 'in '.implode(',', [
+ CSlaHelper::SLA_STATUS_ANY,
+ CSlaHelper::SLA_STATUS_ENABLED,
+ CSlaHelper::SLA_STATUS_DISABLED
+ ]),
+ 'filter_evaltype' => 'in '.TAG_EVAL_TYPE_AND_OR.','.TAG_EVAL_TYPE_OR,
+ 'filter_tags' => 'array',
+ 'filter_set' => 'in 1',
+ 'sort' => 'in '.implode(',', [
+ 'name',
+ 'slo',
+ 'effective_date',
+ 'status'
+ ]),
+ 'sortorder' => 'in '.implode(',', [ZBX_SORT_UP, ZBX_SORT_DOWN]),
+ 'page' => 'ge 1'
+ ];
+
+ $ret = $this->validateInput($fields);
+
+ if (!$ret) {
+ $this->setResponse(new CControllerResponseFatal());
+ }
+
+ return $ret;
+ }
+
+ /**
+ * @throws APIException
+ */
+ protected function checkPermissions(): bool {
+ return $this->checkAccess(CRoleHelper::UI_SERVICES_SLA);
+ }
+
+ /**
+ * @throws Exception
+ */
+ protected function doAction(): void {
+ $filter = [
+ 'name' => $this->getInput('filter_name', ''),
+ 'status' => $this->getInput('filter_status', CSlaHelper::SLA_STATUS_ANY),
+ 'evaltype' => $this->getInput('filter_evaltype', TAG_EVAL_TYPE_AND_OR),
+ 'tags' => [],
+ 'filter_set' => $this->hasInput('filter_set')
+ ];
+
+ foreach ($this->getInput('filter_tags', []) as $tag) {
+ if (!array_key_exists('tag', $tag) || !array_key_exists('value', $tag)
+ || ($tag['tag'] === '' && $tag['value'] === '')) {
+ continue;
+ }
+
+ $filter['tags'][] = $tag;
+ }
+
+ $paging_curl = (new CUrl('zabbix.php'))
+ ->setArgument('action', 'sla.list');
+
+ $reset_curl = clone $paging_curl;
+
+ if ($filter['filter_set']) {
+ $paging_curl
+ ->setArgument('filter_name', $filter['name'])
+ ->setArgument('filter_status', $filter['status'])
+ ->setArgument('filter_evaltype', $filter['evaltype'])
+ ->setArgument('filter_tags', $filter['tags'])
+ ->setArgument('filter_set', 1);
+ }
+
+ $page_num = $this->getInput('page', 1);
+ $per_page = CSettingsHelper::get(CSettingsHelper::SEARCH_LIMIT);
+ $sort_field = $this->getInput('sort', CProfile::get('sla.list.sort', 'name'));
+ $sort_order = $this->getInput('sortorder', CProfile::get('sla.list.sortorder', ZBX_SORT_UP));
+
+ $edit_mode_curl = (clone $paging_curl)
+ ->setArgument('action', 'service.list.edit')
+ ->setArgument('page', $page_num);
+
+ $data = [
+ 'can_edit' => CWebUser::checkAccess(CRoleHelper::ACTIONS_MANAGE_SLA),
+ 'filter' => $filter,
+ 'is_filtered' => $filter['filter_set'],
+ 'active_tab' => CProfile::get('web.sla.filter.active', 1),
+ 'refresh_interval' => CWebUser::getRefresh() * 1000,
+ 'reset_curl' => $reset_curl,
+ 'filter_url' => $paging_curl->getUrl(),
+ 'max_in_table' => CSettingsHelper::get(CSettingsHelper::MAX_IN_TABLE),
+ 'sort' => $sort_field,
+ 'sortorder' => $sort_order,
+ 'edit_mode_url' => $edit_mode_curl->getUrl(),
+ 'refresh_url' => (clone $paging_curl)
+ ->setArgument('action', 'sla.list.refresh')
+ ->getUrl(),
+ 'user' => [
+ 'debug_mode' => $this->getDebugMode()
+ ]
+ ];
+
+ $options = [
+ 'output' => [],
+ 'search' => ($filter['name'] === '')
+ ? null
+ : ['name' => $filter['name']],
+ 'filter' => [
+ 'status' => $filter['status']
+ ],
+ 'tags' => $filter['tags'],
+ 'evaltype' => $filter['evaltype'],
+ 'sortfield' => [$sort_field],
+ 'sortorder' => $sort_order,
+ 'preservekeys' => true
+ ];
+
+ if (in_array($filter['status'], [CSlaHelper::SLA_STATUS_ENABLED, CSlaHelper::SLA_STATUS_DISABLED])) {
+ $options['filter']['status'] = $filter['status'];
+ }
+
+ $x = 120;
+ $records = [];
+
+ while ($x-- > 0) {
+ $records[$x] = [
+ 'name' => 'My SLA-'.$x,
+ 'period' => mt_rand(0, 4),
+ 'slo' => 99.9999,
+ 'effective_date' => strtotime('+'.mt_rand(0, 365).' days'),
+ 'timezone' => array_rand(['UTC' => 1, 'Europe/Riga' => 1, 'Europe/Dublin']),
+ 'schedule_mode' => mt_rand(0, 1),
+ 'status' => mt_rand(0, 1),
+ 'description' => 'Description of SLA '.$x
+ ];
+ }
+
+ //$db_slaids = array_keys(API::Sla()->get($options));
+ $db_slaids = array_keys($records);
+
+ CPagerHelper::savePage('sla.list', $page_num);
+ $data['paging'] = CPagerHelper::paginate($page_num, $db_slaids, $sort_order, $paging_curl);
+
+ $options = [
+ 'output' => [],
+ 'selectTags' => ['tag', 'value'],
+ 'slaids' => $db_slaids,
+ 'limit' => $per_page,
+ 'offset' => $page_num * $per_page
+ ];
+
+ //$data['records'] = API::Sla()->get($options);
+ $data['records'] = $records;
+
+ $response = new CControllerResponseData($data);
+ $response->setTitle(_('SLA'));
+ $this->setResponse($response);
+ }
+}
diff --git a/ui/app/controllers/CControllerUserroleCreate.php b/ui/app/controllers/CControllerUserroleCreate.php
index db948a52a1e..d9b95f1df61 100644
--- a/ui/app/controllers/CControllerUserroleCreate.php
+++ b/ui/app/controllers/CControllerUserroleCreate.php
@@ -38,7 +38,10 @@ class CControllerUserroleCreate extends CControllerUserroleEditGeneral {
'ui_monitoring_latest_data' => 'in 0,1',
'ui_monitoring_maps' => 'in 0,1',
'ui_monitoring_discovery' => 'in 0,1',
- 'ui_monitoring_services' => 'in 0,1',
+ 'ui_services_services' => 'in 0,1',
+ 'ui_services_actions' => 'in 0,1',
+ 'ui_services_sla' => 'in 0,1',
+ 'ui_services_sla_report' => 'in 0,1',
'ui_inventory_overview' => 'in 0,1',
'ui_inventory_hosts' => 'in 0,1',
'ui_reports_system_info' => 'in 0,1',
@@ -74,6 +77,7 @@ class CControllerUserroleCreate extends CControllerUserroleEditGeneral {
'actions_execute_scripts' => 'in 0,1',
'actions_manage_api_tokens' => 'in 0,1',
'actions_manage_scheduled_reports' => 'in 0,1',
+ 'actions_manage_sla' => 'in 0,1',
'modules' => 'array',
'api_mode' => 'in '.implode(',', [ZBX_ROLE_RULE_API_MODE_DENY, ZBX_ROLE_RULE_API_MODE_ALLOW]),
'api_methods' => 'array',
diff --git a/ui/app/controllers/CControllerUserroleEdit.php b/ui/app/controllers/CControllerUserroleEdit.php
index bd76cbc2c7c..d578545c670 100644
--- a/ui/app/controllers/CControllerUserroleEdit.php
+++ b/ui/app/controllers/CControllerUserroleEdit.php
@@ -41,7 +41,10 @@ class CControllerUserroleEdit extends CControllerUserroleEditGeneral {
'ui_monitoring_latest_data' => 'in 0,1',
'ui_monitoring_maps' => 'in 0,1',
'ui_monitoring_discovery' => 'in 0,1',
- 'ui_monitoring_services' => 'in 0,1',
+ 'ui_services_services' => 'in 0,1',
+ 'ui_services_actions' => 'in 0,1',
+ 'ui_services_sla' => 'in 0,1',
+ 'ui_services_sla_report' => 'in 0,1',
'ui_inventory_overview' => 'in 0,1',
'ui_inventory_hosts' => 'in 0,1',
'ui_reports_system_info' => 'in 0,1',
@@ -77,6 +80,7 @@ class CControllerUserroleEdit extends CControllerUserroleEditGeneral {
'actions_execute_scripts' => 'in 0,1',
'actions_manage_api_tokens' => 'in 0,1',
'actions_manage_scheduled_reports' => 'in 0,1',
+ 'actions_manage_sla' => 'in 0,1',
'ui_default_access' => 'in 0,1',
'modules_default_access' => 'in 0,1',
'actions_default_access' => 'in 0,1',
diff --git a/ui/app/controllers/CControllerUserroleUpdate.php b/ui/app/controllers/CControllerUserroleUpdate.php
index e2a97d7b66c..997f35e128e 100644
--- a/ui/app/controllers/CControllerUserroleUpdate.php
+++ b/ui/app/controllers/CControllerUserroleUpdate.php
@@ -37,7 +37,10 @@ class CControllerUserroleUpdate extends CControllerUserroleEditGeneral {
'ui_monitoring_latest_data' => 'in 0,1',
'ui_monitoring_maps' => 'in 0,1',
'ui_monitoring_discovery' => 'in 0,1',
- 'ui_monitoring_services' => 'in 0,1',
+ 'ui_services_services' => 'in 0,1',
+ 'ui_services_actions' => 'in 0,1',
+ 'ui_services_sla' => 'in 0,1',
+ 'ui_services_sla_report' => 'in 0,1',
'ui_inventory_overview' => 'in 0,1',
'ui_inventory_hosts' => 'in 0,1',
'ui_reports_system_info' => 'in 0,1',
@@ -73,6 +76,7 @@ class CControllerUserroleUpdate extends CControllerUserroleEditGeneral {
'actions_execute_scripts' => 'in 0,1',
'actions_manage_api_tokens' => 'in 0,1',
'actions_manage_scheduled_reports' => 'in 0,1',
+ 'actions_manage_sla' => 'in 0,1',
'ui_default_access' => 'in 0,1',
'modules_default_access' => 'in 0,1',
'actions_default_access' => 'in 0,1',
diff --git a/ui/app/partials/monitoring.service.list.edit.php b/ui/app/partials/services.service.list.edit.php
index c8a1b4eabbc..c8a1b4eabbc 100644
--- a/ui/app/partials/monitoring.service.list.edit.php
+++ b/ui/app/partials/services.service.list.edit.php
diff --git a/ui/app/partials/monitoring.service.list.php b/ui/app/partials/services.service.list.php
index 6c22fbbc977..6c22fbbc977 100644
--- a/ui/app/partials/monitoring.service.list.php
+++ b/ui/app/partials/services.service.list.php
diff --git a/ui/app/partials/services.sla.list.php b/ui/app/partials/services.sla.list.php
new file mode 100644
index 00000000000..1ebf07ef0dc
--- /dev/null
+++ b/ui/app/partials/services.sla.list.php
@@ -0,0 +1,97 @@
+<?php declare(strict_types = 1);
+/*
+** Zabbix
+** Copyright (C) 2001-2021 Zabbix SIA
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+**/
+
+
+/**
+ * @var CPartial $this
+ */
+
+$form = (new CForm())
+ ->setId('sla-list')
+ ->setName('sla_list');
+
+$header = [
+ make_sorting_header(_('Name'), 'name', $data['sort'], $data['sortorder'], $data['filter_url'])
+ ->addStyle('width: 14%'),
+ (new CColHeader(_('SLO'))),
+ (new CColHeader(_('Effective date')))->addStyle('width: 24%'),
+ (new CColHeader(_('Reporting period')))->addStyle('width: 14%'),
+ (new CColHeader(_('Timezone'))),
+ (new CColHeader(_('Schedule'))),
+ (new CColHeader(_('SLA report'))),
+ (new CColHeader(_('Status'))),
+];
+
+if ($data['can_edit']) {
+ array_unshift($header,
+ (new CCheckBox('all_ids'))->onClick("checkAll('sla-list', 'all_ids', 'ids');")
+ );
+}
+
+$table = (new CTableInfo())
+ ->setHeader($header);
+
+foreach ($data['records'] as $recordid => $record) {
+ $row = [
+ $record['name'],
+ sprintf('%.4f', $record['slo']),
+ zbx_date2str(DATE_FORMAT, $record['effective_date']),
+ ];
+
+ if ($data['can_edit']) {
+ array_unshift($row,
+ new CCheckBox('ids['.$recordid.']', $recordid),
+ );
+ }
+
+ $table->addRow(new CRow($row));
+}
+
+
+$form->addItem([
+ $table,
+ $data['paging'],
+ new CActionButtonList('action', 'ids', [
+ 'sla.massenable' => [
+ 'content' => (new CSimpleButton(_('Enable')))
+ ->setAttribute('confirm', _('Enable selected SLAs?'))
+ ->onClick('view.massEnable(this);')
+ ->addClass(ZBX_STYLE_BTN_ALT)
+ ->addClass('no-chkbxrange')
+ ->removeAttribute('id')
+ ],
+ 'sla.massdisable' => [
+ 'content' => (new CSimpleButton(_('Disable')))
+ ->setAttribute('confirm', _('Disable selected SLAs?'))
+ ->onClick('view.massDisable(this);')
+ ->addClass(ZBX_STYLE_BTN_ALT)
+ ->addClass('no-chkbxrange')
+ ->removeAttribute('id')
+ ],
+ 'sla.massdelete' => [
+ 'content' => (new CSimpleButton(_('Delete')))
+ ->setAttribute('confirm', _('Delete selected SLAs?'))
+ ->onClick('view.massDeleteSlas(this);')
+ ->addClass(ZBX_STYLE_BTN_ALT)
+ ->addClass('no-chkbxrange')
+ ->removeAttribute('id')
+ ]
+ ], 'slas')
+])->show(); \ No newline at end of file
diff --git a/ui/app/views/js/administration.userrole.edit.js.php b/ui/app/views/js/administration.userrole.edit.js.php
index 0d04c88e2b3..e4189aba613 100644
--- a/ui/app/views/js/administration.userrole.edit.js.php
+++ b/ui/app/views/js/administration.userrole.edit.js.php
@@ -84,7 +84,10 @@
CRoleHelper::UI_MONITORING_LATEST_DATA => USER_TYPE_ZABBIX_USER,
CRoleHelper::UI_MONITORING_MAPS => USER_TYPE_ZABBIX_USER,
CRoleHelper::UI_MONITORING_DISCOVERY => USER_TYPE_ZABBIX_ADMIN,
- CRoleHelper::UI_MONITORING_SERVICES => USER_TYPE_ZABBIX_USER,
+ CRoleHelper::UI_SERVICES_SERVICES => USER_TYPE_ZABBIX_USER,
+ CRoleHelper::UI_SERVICES_ACTIONS => USER_TYPE_ZABBIX_ADMIN,
+ CRoleHelper::UI_SERVICES_SLA => USER_TYPE_ZABBIX_ADMIN,
+ CRoleHelper::UI_SERVICES_SLA_REPORT => USER_TYPE_ZABBIX_USER,
CRoleHelper::UI_INVENTORY_OVERVIEW => USER_TYPE_ZABBIX_USER,
CRoleHelper::UI_INVENTORY_HOSTS => USER_TYPE_ZABBIX_USER,
CRoleHelper::UI_REPORTS_SYSTEM_INFO => USER_TYPE_SUPER_ADMIN,
@@ -119,7 +122,8 @@
CRoleHelper::ACTIONS_ADD_PROBLEM_COMMENTS => USER_TYPE_ZABBIX_USER,
CRoleHelper::ACTIONS_EXECUTE_SCRIPTS => USER_TYPE_ZABBIX_USER,
CRoleHelper::ACTIONS_MANAGE_API_TOKENS => USER_TYPE_ZABBIX_USER,
- CRoleHelper::ACTIONS_MANAGE_SCHEDULED_REPORTS => USER_TYPE_ZABBIX_ADMIN
+ CRoleHelper::ACTIONS_MANAGE_SCHEDULED_REPORTS => USER_TYPE_ZABBIX_ADMIN,
+ CRoleHelper::ACTIONS_MANAGE_SLA => USER_TYPE_ZABBIX_ADMIN
], JSON_FORCE_OBJECT) ?>;
for (const [id, value] of Object.entries(access)) {
diff --git a/ui/app/views/js/monitoring.service.list.js.php b/ui/app/views/js/services.service.list.js.php
index 1f4e1e632ff..1f4e1e632ff 100755..100644
--- a/ui/app/views/js/monitoring.service.list.js.php
+++ b/ui/app/views/js/services.service.list.js.php
diff --git a/ui/app/views/js/services.sla.list.js.php b/ui/app/views/js/services.sla.list.js.php
new file mode 100644
index 00000000000..a86d0ffdf2e
--- /dev/null
+++ b/ui/app/views/js/services.sla.list.js.php
@@ -0,0 +1,165 @@
+<?php declare(strict_types = 1);
+/*
+** Zabbix
+** Copyright (C) 2001-2021 Zabbix SIA
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+**/
+
+
+/**
+ * @var CView $this
+ */
+?>
+
+<script type="text/x-jquery-tmpl" id="filter-tag-row-tmpl">
+ <?= CTagFilterFieldHelper::getTemplate() ?>
+</script>
+
+<script>
+ const view = {
+ mode_switch_url: null,
+ refresh_url: null,
+ refresh_interval: null,
+ back_url: null,
+ is_refresh_paused: false,
+ is_refresh_pending: false,
+
+ init({mode_switch_url, refresh_url, refresh_interval, back_url = null}) {
+ this.mode_switch_url = mode_switch_url;
+ this.refresh_url = refresh_url;
+ this.refresh_interval = refresh_interval;
+ this.back_url = back_url;
+
+ this.initViewModeSwitcher();
+ this.initTagFilter();
+ this.initActionButtons();
+ this.initRefresh();
+ },
+
+ initViewModeSwitcher() {
+ for (const element of document.getElementsByName('list_mode')) {
+ if (!element.checked) {
+ element.addEventListener('click', () => {
+ location.href = this.mode_switch_url;
+ });
+ }
+ }
+ },
+
+ initTagFilter() {
+ $('#filter-tags')
+ .dynamicRows({template: '#filter-tag-row-tmpl'})
+ .on('afteradd.dynamicRows', function() {
+ const rows = this.querySelectorAll('.form_row');
+ new CTagFilterItem(rows[rows.length - 1]);
+ });
+
+ document.querySelectorAll('#filter-tags .form_row').forEach(row => {
+ new CTagFilterItem(row);
+ });
+ },
+
+ initActionButtons() {
+ document.addEventListener('click', (e) => {
+ if (e.target.matches('.js-create-sla')) {
+ const options = e.target.dataset.slaid !== undefined
+ ? {slaid: [e.target.dataset.slaid]}
+ : {};
+
+ this.edit(options);
+ }
+ else if (e.target.classList.contains('js-edit-sla')) {
+ this.edit({slaid: e.target.dataset.slaid});
+ }
+ else if (e.target.classList.contains('js-massupdate-sla')) {
+ openMassupdatePopup(e.target, 'popup.massupdate.sla', {location_url: this.back_url});
+ }
+ });
+ },
+
+ initRefresh() {
+ if (this.refresh_interval > 0) {
+ setInterval(() => this.refresh(), this.refresh_interval);
+ }
+ },
+
+ edit(options = {}) {
+ this.pauseRefresh();
+
+ const overlay = PopUp('popup.sla.edit', options, 'service_edit', document.activeElement);
+
+ overlay.$dialogue[0].addEventListener('dialogue.submit', (e) => {
+ postMessageOk(e.detail.title);
+
+ if (e.detail.messages !== null) {
+ postMessageDetails('success', e.detail.messages);
+ }
+
+ location.href = location.href;
+ });
+
+ overlay.$dialogue[0].addEventListener('overlay.close', () => this.resumeRefresh(), {once: true});
+ },
+
+ pauseRefresh() {
+ this.is_refresh_paused = true;
+ },
+
+ resumeRefresh() {
+ this.is_refresh_paused = false;
+ },
+
+ refresh() {
+ if (this.is_refresh_paused || this.is_refresh_pending) {
+ return;
+ }
+
+ const record_list = document.getElementById('record-list');
+
+ if (record_list.querySelectorAll('[data-expanded="true"], [aria-expanded="true"]').length > 0) {
+ return;
+ }
+
+ this.is_refresh_pending = true;
+
+ record_list.classList.add('is-loading', 'is-loading-fadein', 'delayed-15s');
+
+ fetch(this.refresh_url)
+ .then((response) => response.json())
+ .then((response) => {
+ if ('errors' in response) {
+ clearMessages();
+ addMessage(response.errors);
+ }
+ else {
+ if ('messages' in response) {
+ clearMessages();
+ addMessage(response.messages);
+ }
+
+ record_list.outerHTML = response.body;
+
+ chkbxRange.init();
+ }
+ })
+ .finally(() => {
+ record_list.classList.remove('is-loading', 'is-loading-fadein', 'delayed-15s');
+
+ this.is_refresh_pending = false;
+ });
+ }
+ };
+</script>
diff --git a/ui/app/views/popup.sla.edit.php b/ui/app/views/popup.sla.edit.php
new file mode 100644
index 00000000000..270cc276627
--- /dev/null
+++ b/ui/app/views/popup.sla.edit.php
@@ -0,0 +1,428 @@
+<?php declare(strict_types = 1);
+/*
+** Zabbix
+** Copyright (C) 2001-2021 Zabbix SIA
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+**/
+
+
+/**
+ * @var CView $this
+ */
+
+$form = (new CForm('post'))
+ ->setId('sla-form')
+ ->setName('sla_form')
+ ->addItem(getMessages());
+
+// Enable form submitting on Enter.
+$form->addItem((new CInput('submit'))->addStyle('display: none;'));
+
+// Service tab.
+
+$parent_services = (new CMultiSelect([
+ 'name' => 'parent_serviceids[]',
+ 'object_name' => 'services',
+ 'data' => CArrayHelper::renameObjectsKeys($data['form']['parents'], ['serviceid' => 'id']),
+ 'custom_select' => true
+]))->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH);
+
+$service_tab = (new CFormGrid())
+ ->addItem([
+ (new CLabel(_('Name'), 'name'))->setAsteriskMark(),
+ new CFormField(
+ (new CTextBox('name', $data['form']['name'], false, DB::getFieldLength('services', 'name')))
+ ->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
+ ->setAriaRequired()
+ ->setAttribute('autofocus', 'autofocus')
+ )
+ ])
+ ->addItem([
+ new CLabel(_('Parent services'), 'parent_serviceids__ms'),
+ new CFormField($parent_services)
+ ])
+ ->addItem([
+ new CLabel(_('Problem tags')),
+ new CFormField(
+ (new CDiv([
+ (new CTable())
+ ->setId('problem_tags')
+ ->addStyle('min-width: '.ZBX_TEXTAREA_STANDARD_WIDTH.'px;')
+ ->setHeader(
+ (new CRowHeader([_('Name'), _('Operation'), _('Value'), _('Action')]))
+ ->addClass(ZBX_STYLE_GREY)
+ )
+ ->setFooter(
+ (new CCol(
+ (new CSimpleButton(_('Add')))
+ ->addClass(ZBX_STYLE_BTN_LINK)
+ ->addClass('element-table-add')
+ ))
+ ),
+ (new CScriptTemplate('problem-tag-row-tmpl'))
+ ->addItem(
+ (new CRow([
+ (new CTextBox('problem_tags[#{rowNum}][tag]', '#{tag}', false,
+ DB::getFieldLength('service_problem_tag', 'tag')
+ ))
+ ->addClass('js-problem-tag-input')
+ ->addClass('js-problem-tag-tag')
+ ->setAttribute('placeholder', _('tag'))
+ ->setWidth(ZBX_TEXTAREA_FILTER_SMALL_WIDTH),
+ (new CSelect('problem_tags[#{rowNum}][operator]'))
+ ->addClass('js-problem-tag-input')
+ ->addOptions(CSelect::createOptionsFromArray([
+ SERVICE_TAG_OPERATOR_EQUAL => _('Equals'),
+ SERVICE_TAG_OPERATOR_LIKE => _('Contains')
+ ]))
+ ->setValue(SERVICE_TAG_OPERATOR_EQUAL),
+ (new CTextBox('problem_tags[#{rowNum}][value]', '#{value}', false,
+ DB::getFieldLength('service_problem_tag', 'value')
+ ))
+ ->addClass('js-problem-tag-input')
+ ->setAttribute('placeholder', _('value'))
+ ->setWidth(ZBX_TEXTAREA_FILTER_SMALL_WIDTH),
+ (new CSimpleButton(_('Remove')))
+ ->addClass(ZBX_STYLE_BTN_LINK)
+ ->addClass('element-table-remove')
+ ]))->addClass('form_row')
+ )
+ ]))->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR)
+ )
+ ])
+ ->addItem([
+ (new CLabel(_('Sort order (0->999)'), 'sortorder'))->setAsteriskMark(),
+ new CFormField(
+ (new CTextBox('sortorder', $data['form']['sortorder'], false, 3))
+ ->setWidth(ZBX_TEXTAREA_TINY_WIDTH)
+ ->setAriaRequired()
+ )
+ ])
+ ->addItem([
+ new CLabel([
+ _('Status calculation rule'),
+ (new CSpan([
+ ' ',
+ makeWarningIcon(
+ _('Status calculation rule and additional rules are only applicable if child services exist.')
+ )
+ ]))
+ ->setId('algorithm-not-applicable-warning')
+ ->addStyle($data['form']['children'] ? 'display: none' : '')
+ ], 'algorithm_focusable'),
+ new CFormField(
+ (new CSelect('algorithm'))
+ ->setId('algorithm')
+ ->setFocusableElementId('algorithm_focusable')
+ ->setValue($data['form']['algorithm'])
+ ->addOptions(CSelect::createOptionsFromArray(CServiceHelper::getAlgorithmNames()))
+ )
+ ])
+ ->addItem(
+ (new CFormField(
+ (new CCheckBox('advanced_configuration'))
+ ->setLabel(_('Advanced configuration'))
+ ->setChecked($data['form']['advanced_configuration'])
+ ))->addClass(CFormField::ZBX_STYLE_FORM_FIELD_OFFSET_1)
+ );
+
+$additional_rules = (new CTable())
+ ->setId('status_rules')
+ ->setHeader(
+ (new CRowHeader([_('Name'), _('Action')]))->addClass(ZBX_STYLE_GREY)
+ );
+
+$additional_rules->addItem(
+ (new CTag('tfoot', true))
+ ->addItem(
+ (new CCol(
+ (new CSimpleButton(_('Add')))
+ ->addClass(ZBX_STYLE_BTN_LINK)
+ ->addClass('js-add')
+ ))->setColSpan(2)
+ )
+);
+
+$service_tab
+ ->addItem([
+ (new CLabel(_('Additional rules')))
+ ->setId('additional_rules_label')
+ ->addStyle('display: none;'),
+ (new CFormField(
+ (new CDiv($additional_rules))
+ ->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR)
+ ->addStyle('min-width: '.ZBX_TEXTAREA_BIG_WIDTH.'px;')
+ ))
+ ->setId('additional_rules_field')
+ ->addStyle('display: none;')
+ ])
+ ->addItem([
+ (new CLabel(_('Status propagation rule')))
+ ->setId('status_propagation_rules_label')
+ ->addStyle('display: none;'),
+ (new CFormField(
+ (new CSelect('propagation_rule'))
+ ->setId('propagation_rule')
+ ->setFocusableElementId('propagation_rule_focusable')
+ ->setValue($data['form']['propagation_rule'])
+ ->addOptions(CSelect::createOptionsFromArray(CServiceHelper::getStatusPropagationNames()))
+ ))
+ ->setId('status_propagation_rules_field')
+ ->addStyle('display: none;')
+ ]);
+
+$propagation_value_number = (new CRadioButtonList('propagation_value_number',
+ $data['form']['propagation_value_number'] !== null ? (int) $data['form']['propagation_value_number'] : null
+))
+ ->setId('propagation_value_number')
+ ->setModern(true);
+
+foreach (range(1, TRIGGER_SEVERITY_COUNT - 1) as $value) {
+ $propagation_value_number->addValue($value, $value, 'propagation_value_number_'.$value);
+}
+
+$propagation_value_status = (new CSeverity('propagation_value_status',
+ $data['form']['propagation_value_status'] !== null ? (int) $data['form']['propagation_value_status'] : null
+))->addValue(_('OK'), ZBX_SEVERITY_OK, ZBX_STYLE_NORMAL_BG);
+
+$service_tab
+ ->addItem([
+ (new CFormField([
+ $propagation_value_number,
+ $propagation_value_status
+ ]))
+ ->setId('status_propagation_value_field')
+ ->addStyle('display: none;')
+ ])
+ ->addItem([
+ (new CLabel(_('Weight')))
+ ->setId('weight_label')
+ ->addStyle('display: none;'),
+ (new CFormField(
+ (new CTextBox('weight', $data['form']['weight'], false, 7))->setWidth(ZBX_TEXTAREA_TINY_WIDTH)
+ ))
+ ->setId('weight_field')
+ ->addStyle('display: none;')
+ ]);
+
+// SLA tab.
+
+$times = (new CTable())
+ ->setId('times')
+ ->setHeader(
+ (new CRowHeader([_('Type'), _('Interval'), _('Note'), _('Action')]))->addClass(ZBX_STYLE_GREY)
+ );
+
+$times->addItem(
+ (new CTag('tfoot', true))
+ ->addItem(
+ (new CCol(
+ (new CSimpleButton(_('Add')))
+ ->addClass(ZBX_STYLE_BTN_LINK)
+ ->addClass('js-add')
+ ))->setColSpan(4)
+ )
+);
+
+$sla_tab = (new CFormGrid())
+ ->addItem([
+ new CLabel(_('SLA'), 'showsla'),
+ new CFormField(
+ new CHorList([
+ (new CCheckBox('showsla'))->setChecked($data['form']['showsla'] == SERVICE_SHOW_SLA_ON),
+ (new CTextBox('goodsla', $data['form']['goodsla'], false, 8))->setWidth(ZBX_TEXTAREA_TINY_WIDTH)
+ ])
+ )
+ ])
+ ->addItem([
+ new CLabel(_('Service times')),
+ new CFormField([
+ (new CDiv($times))
+ ->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR)
+ ->addStyle('min-width: '.ZBX_TEXTAREA_BIG_WIDTH.'px;')
+ ])
+ ]);
+
+// Tags tab.
+
+$tags_tab = (new CFormGrid())
+ ->addItem([
+ new CLabel(_('Tags')),
+ new CFormField(
+ (new CDiv())
+ ->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR)
+ ->addStyle('min-width: '.ZBX_TEXTAREA_BIG_WIDTH.'px;')
+ ->addItem([
+ renderTagTable($data['form']['tags'])
+ ->setId('tags-table')
+ ->setHeader((new CRowHeader([_('Name'), _('Value'), _('Action')]))->addClass(ZBX_STYLE_GREY)),
+ (new CScriptTemplate('tag-row-tmpl'))
+ ->addItem(renderTagTableRow('#{rowNum}', '', '', ['add_post_js' => false]))
+
+ ])
+ )
+ ]);
+
+// Child services tab.
+
+$child_services = (new CTable())
+ ->setId('children')
+ ->setAttribute('data-tab-indicator', count($data['form']['children']))
+ ->setHeader(
+ (new CRowHeader([
+ _('Service'),
+ _('Status calculation rule'),
+ _('Problem tags'),
+ _('Action')
+ ]))->addClass(ZBX_STYLE_GREY)
+ )
+ ->addItem(
+ (new CTag('tfoot', true))
+ ->addItem(
+ (new CCol(
+ (new CList())
+ ->addClass(ZBX_STYLE_INLINE_FILTER_FOOTER)
+ ->addItem(
+ (new CSimpleButton(_('Add')))
+ ->addClass(ZBX_STYLE_BTN_LINK)
+ ->addClass('js-add')
+ )
+ ->addItem(
+ (new CListItem(null))
+ ->addClass(ZBX_STYLE_INLINE_FILTER_STATS)
+ )
+ ))->setColSpan(4)
+ )
+ );
+
+$child_services_filter = (new CList())
+ ->setId('children-filter')
+ ->addClass(ZBX_STYLE_INLINE_FILTER)
+ ->addItem(new CLabel(_('Name'), 'children-filter-name'), ZBX_STYLE_INLINE_FILTER_LABEL)
+ ->addItem(
+ (new CTextBox(null))
+ ->setId('children-filter-name')
+ ->setWidth(ZBX_TEXTAREA_FILTER_STANDARD_WIDTH))
+ ->addItem(
+ (new CSimpleButton(_('Filter')))
+ ->addClass('js-filter')
+ )
+ ->addItem(
+ (new CSimpleButton(_('Reset')))
+ ->addClass('js-reset')
+ ->addClass(ZBX_STYLE_BTN_ALT)
+ );
+
+$child_services_tab = [
+ (new CFormGrid())
+ ->addItem(new CFormField($child_services_filter))
+ ->addItem([
+ new CLabel(_('Child services')),
+ new CFormField(
+ (new CDiv($child_services))
+ ->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR)
+ ->addStyle('min-width: '.ZBX_TEXTAREA_BIG_WIDTH.'px;')
+ )
+ ])
+];
+
+$tabs = (new CTabView())
+ ->setSelected(0)
+ ->addTab('service-tab', _('Service'), $service_tab)
+ ->addTab('sla-tab', _('SLA'), $sla_tab, TAB_INDICATOR_SLA)
+ ->addTab('tags-tab', _('Tags'), $tags_tab, TAB_INDICATOR_TAGS)
+ ->addTab('child-services-tab', _('Child services'), $child_services_tab, TAB_INDICATOR_CHILD_SERVICES);
+
+// Output.
+
+$form
+ ->addItem($tabs)
+ ->addItem(
+ (new CScriptTag('
+ const params = '.json_encode([
+ 'serviceid' => $data['serviceid'],
+ 'children' => $data['form']['children'],
+ 'children_problem_tags_html' => $data['form']['children_problem_tags_html'],
+ 'problem_tags' => $data['form']['problem_tags'],
+ 'status_rules' => $data['form']['status_rules'],
+ 'service_times' => $data['form']['times'],
+ 'create_url' => (new CUrl('zabbix.php'))
+ ->setArgument('action', 'service.create')
+ ->getUrl(),
+ 'update_url' => (new CUrl('zabbix.php'))
+ ->setArgument('action', 'service.update')
+ ->getUrl(),
+ 'search_limit' => CSettingsHelper::get(CSettingsHelper::SEARCH_LIMIT)
+ ]).'
+
+ params.algorithm_names = '.json_encode(CServiceHelper::getAlgorithmNames(), JSON_FORCE_OBJECT).';
+
+ service_edit_popup.init(params);
+ '))->setOnDocumentReady()
+ );
+
+if ($data['serviceid'] !== null) {
+ $title = _('Service');
+ $buttons = [
+ [
+ 'title' => _('Update'),
+ 'class' => 'js-update',
+ 'keepOpen' => true,
+ 'isSubmit' => true,
+ 'action' => 'service_edit_popup.submit();'
+ ],
+ [
+ 'title' => _('Clone'),
+ 'class' => implode(' ', [ZBX_STYLE_BTN_ALT, 'js-clone']),
+ 'keepOpen' => true,
+ 'action' => 'service_edit_popup.clone('.json_encode(_('New service')).');'
+ ],
+ [
+ 'title' => _('Add'),
+ 'class' => implode(' ', [ZBX_STYLE_DISPLAY_NONE, 'js-add']),
+ 'keepOpen' => true,
+ 'isSubmit' => true,
+ 'action' => 'service_edit_popup.submit();'
+ ]
+ ];
+}
+else {
+ $title = _('New service');
+ $buttons = [
+ [
+ 'title' => _('Add'),
+ 'class' => 'js-add',
+ 'keepOpen' => true,
+ 'isSubmit' => true,
+ 'action' => 'service_edit_popup.submit();'
+ ]
+ ];
+}
+
+$output = [
+ 'header' => $title,
+ 'body' => $form->toString(),
+ 'buttons' => $buttons,
+ 'script_inline' => getPagePostJs().
+ $this->readJsFile('popup.service.edit.js.php')
+];
+
+if ($data['user']['debug_mode'] == GROUP_DEBUG_MODE_ENABLED) {
+ CProfiler::getInstance()->stop();
+ $output['debug'] = CProfiler::getInstance()->make()->toString();
+}
+
+echo json_encode($output);
diff --git a/ui/app/views/monitoring.service.list.edit.php b/ui/app/views/services.service.list.edit.php
index aa0145a89dc..d137ed77a99 100755..100644
--- a/ui/app/views/monitoring.service.list.edit.php
+++ b/ui/app/views/services.service.list.edit.php
@@ -32,7 +32,7 @@ $this->addJsFile('layout.mode.js');
$this->addJsFile('class.tagfilteritem.js');
$this->addJsFile('class.calendar.js');
-$this->includeJsFile('monitoring.service.list.js.php');
+$this->includeJsFile('services.service.list.js.php');
$breadcrumbs = [];
$filter = null;
@@ -149,7 +149,7 @@ $filter->addFilterTab(_('Filter'), [
$breadcrumbs ? new CList([new CBreadcrumbs($breadcrumbs)]) : null
)
->addItem($filter)
- ->addItem(new CPartial('monitoring.service.list.edit', array_intersect_key($data, array_flip([
+ ->addItem(new CPartial('services.service.list.edit', array_intersect_key($data, array_flip([
'can_monitor_problems', 'path', 'is_filtered', 'max_in_table', 'service', 'services', 'events', 'tags',
'paging', 'back_url'
]))))
diff --git a/ui/app/views/monitoring.service.list.edit.refresh.php b/ui/app/views/services.service.list.edit.refresh.php
index c567382739f..c27fe4feb70 100755..100644
--- a/ui/app/views/monitoring.service.list.edit.refresh.php
+++ b/ui/app/views/services.service.list.edit.refresh.php
@@ -24,7 +24,7 @@
*/
$output = [
- 'body' => (new CPartial('monitoring.service.list.edit', $data))->getOutput()
+ 'body' => (new CPartial('services.service.list.edit', $data))->getOutput()
];
if (($messages = getMessages()) !== null) {
diff --git a/ui/app/views/monitoring.service.list.php b/ui/app/views/services.service.list.php
index b8a4db1458d..60c12815e9b 100644
--- a/ui/app/views/monitoring.service.list.php
+++ b/ui/app/views/services.service.list.php
@@ -27,7 +27,7 @@
$this->addJsFile('layout.mode.js');
$this->addJsFile('class.tagfilteritem.js');
-$this->includeJsFile('monitoring.service.list.js.php');
+$this->includeJsFile('services.service.list.js.php');
$this->enableLayoutModes();
$web_layout_mode = $this->getLayoutMode();
@@ -123,7 +123,7 @@ if ($web_layout_mode == ZBX_LAYOUT_NORMAL) {
$breadcrumbs ? new CList([new CBreadcrumbs($breadcrumbs)]) : null
)
->addItem($filter)
- ->addItem(new CPartial('monitoring.service.list', array_intersect_key($data, array_flip(['can_monitor_problems',
+ ->addItem(new CPartial('services.service.list', array_intersect_key($data, array_flip(['can_monitor_problems',
'path', 'is_filtered', 'max_in_table', 'service', 'services', 'events', 'tags', 'paging'
]))))
->show();
diff --git a/ui/app/views/monitoring.service.list.refresh.php b/ui/app/views/services.service.list.refresh.php
index b2d177406a3..b92a2a12e83 100644
--- a/ui/app/views/monitoring.service.list.refresh.php
+++ b/ui/app/views/services.service.list.refresh.php
@@ -24,7 +24,7 @@
*/
$output = [
- 'body' => (new CPartial('monitoring.service.list', $data))->getOutput()
+ 'body' => (new CPartial('services.service.list', $data))->getOutput()
];
if (($messages = getMessages()) !== null) {
diff --git a/ui/app/views/services.sla.list.php b/ui/app/views/services.sla.list.php
new file mode 100644
index 00000000000..07a6139efa9
--- /dev/null
+++ b/ui/app/views/services.sla.list.php
@@ -0,0 +1,101 @@
+<?php declare(strict_types = 1);
+/*
+** Zabbix
+** Copyright (C) 2001-2021 Zabbix SIA
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+**/
+
+
+/**
+ * @var CView $this
+ * @var array $data
+ */
+
+$this->addJsFile('layout.mode.js');
+$this->addJsFile('class.tagfilteritem.js');
+
+$this->includeJsFile('services.sla.list.js.php');
+
+$this->enableLayoutModes();
+$web_layout_mode = $this->getLayoutMode();
+
+$filter = null;
+
+if ($web_layout_mode == ZBX_LAYOUT_NORMAL) {
+ $filter = (new CFilter())
+ ->addVar('action', 'sla.list')
+ ->setResetUrl($data['reset_curl'])
+ ->setProfile('web.sla.filter')
+ ->setActiveTab($data['active_tab']);
+
+ $filter->addFilterTab(_('Filter'), [
+ (new CFormGrid())
+ ->addClass(CFormGrid::ZBX_STYLE_FORM_GRID_LABEL_WIDTH_TRUE)
+ ->addItem([
+ new CLabel(_('Name'), 'filter_name'),
+ new CFormField(
+ (new CTextBox('filter_name', $data['filter']['name']))
+ ->setWidth(ZBX_TEXTAREA_FILTER_STANDARD_WIDTH)
+ )
+ ])
+ ->addItem([
+ new CLabel(_('Status')),
+ new CFormField(
+ (new CRadioButtonList('filter_status', (int) $data['filter']['status']))
+ ->addValue(_('Any'), CSlaHelper::SLA_STATUS_ANY)
+ ->addValue(_('Enabled'), CSlaHelper::SLA_STATUS_ENABLED)
+ ->addValue(_('Disabled'), CSlaHelper::SLA_STATUS_DISABLED)
+ ->setModern(true)
+ )
+ ]),
+ (new CFormGrid())
+ ->addClass(CFormGrid::ZBX_STYLE_FORM_GRID_LABEL_WIDTH_TRUE)
+ ->addItem([
+ new CLabel(_('Tags')),
+ new CFormField(
+ CTagFilterFieldHelper::getTagFilterField([
+ 'evaltype' => $data['filter']['evaltype'],
+ 'tags' => $data['filter']['tags'] ?: [
+ ['tag' => '', 'value' => '', 'operator' => TAG_OPERATOR_LIKE]
+ ]
+ ])
+ )
+ ])
+ ]);
+}
+
+(new CWidget())
+ ->setTitle(_('SLA'))
+ ->setWebLayoutMode($web_layout_mode)
+ ->setControls(
+ (new CTag('nav', true,
+ (new CList())
+ ->addItem(get_icon('kioskmode', ['mode' => $web_layout_mode]))
+ ))->setAttribute('aria-label', _('Content controls'))
+ )
+ ->addItem($filter)
+ ->addItem(new CPartial('services.sla.list', $data))
+ ->show();
+
+(new CScriptTag('
+ view.init('.json_encode([
+ 'mode_switch_url' => $data['edit_mode_url'],
+ 'refresh_url' => $data['refresh_url'],
+ 'refresh_interval' => $data['refresh_interval']
+ ]).');
+'))
+ ->setOnDocumentReady()
+ ->show();
diff --git a/ui/assets/styles/blue-theme.css b/ui/assets/styles/blue-theme.css
index f45ea4b353c..e0786205fb0 100644
--- a/ui/assets/styles/blue-theme.css
+++ b/ui/assets/styles/blue-theme.css
@@ -1478,7 +1478,7 @@ footer {
.inline-filter-footer > li.inline-filter-stats {
color: #768d99; }
-.icon-dashboard::before, .icon-problems::before, .icon-monitoring::before, .icon-inventory::before, .icon-reports::before, .icon-configuration::before, .icon-administration::before {
+.icon-dashboard::before, .icon-problems::before, .icon-monitoring::before, .icon-services::before, .icon-inventory::before, .icon-reports::before, .icon-configuration::before, .icon-administration::before {
content: '';
width: 24px;
height: 24px;
@@ -1497,6 +1497,10 @@ footer {
background-position: -540px -712px;
transition: opacity 0.3s; }
+.icon-services::before {
+ background-position: -42px -832px;
+ transition: opacity 0.3s; }
+
.icon-inventory::before {
background-position: -540px -736px;
transition: opacity 0.3s; }
diff --git a/ui/include/classes/helpers/CMenuHelper.php b/ui/include/classes/helpers/CMenuHelper.php
index 65de90d325e..a772184616b 100644
--- a/ui/include/classes/helpers/CMenuHelper.php
+++ b/ui/include/classes/helpers/CMenuHelper.php
@@ -60,11 +60,6 @@ class CMenuHelper {
: null,
CWebUser::checkAccess(CRoleHelper::UI_MONITORING_DISCOVERY)
? (new CMenuItem(_('Discovery')))->setAction('discovery.view')
- : null,
- CWebUser::checkAccess(CRoleHelper::UI_MONITORING_SERVICES)
- ? (new CMenuItem(_('Services')))
- ->setAction('service.list')
- ->setAliases(['service.list.edit'])
: null
];
$submenu_monitoring = array_filter($submenu_monitoring);
@@ -78,6 +73,42 @@ class CMenuHelper {
);
}
+ $submenu_services = [
+ CWebUser::checkAccess(CRoleHelper::UI_SERVICES_SERVICES)
+ ? (new CMenuItem(_('Services')))
+ ->setAction('service.list')
+ ->setAliases(['service.list.edit'])
+ : null,
+ CWebUser::checkAccess(CRoleHelper::UI_SERVICES_ACTIONS)
+ ? (new CMenuItem(_('Service actions')))
+ ->setUrl(
+ (new CUrl('actionconf.php'))->setArgument('eventsource', EVENT_SOURCE_SERVICE),
+ 'actionconf.php?eventsource='.EVENT_SOURCE_SERVICE
+ )
+ : null,
+ CWebUser::checkAccess(CRoleHelper::UI_SERVICES_SLA)
+ ? (new CMenuItem(_('SLA')))
+ ->setAction('sla.list')
+ ->setAliases(['sla.list.edit'])
+ : null,
+ CWebUser::checkAccess(CRoleHelper::UI_SERVICES_SLA_REPORT)
+ ? (new CMenuItem(_('SLA report')))
+ ->setAction('sla_report.list')
+ ->setAliases(['sla_report.list.edit'])
+ : null
+ ];
+
+ $submenu_services = array_filter($submenu_services);
+
+ if ($submenu_services) {
+ $menu->add(
+ (new CMenuItem(_('Services')))
+ ->setId('view')
+ ->setIcon('icon-services')
+ ->setSubMenu(new CMenu($submenu_services))
+ );
+ }
+
$submenu_inventory = [
CWebUser::checkAccess(CRoleHelper::UI_INVENTORY_OVERVIEW)
? (new CMenuItem(_('Overview')))
diff --git a/ui/include/classes/helpers/CRoleHelper.php b/ui/include/classes/helpers/CRoleHelper.php
index 832d9842eb7..d1325068888 100644
--- a/ui/include/classes/helpers/CRoleHelper.php
+++ b/ui/include/classes/helpers/CRoleHelper.php
@@ -30,7 +30,6 @@ class CRoleHelper {
public const UI_MONITORING_LATEST_DATA = 'ui.monitoring.latest_data';
public const UI_MONITORING_MAPS = 'ui.monitoring.maps';
public const UI_MONITORING_DISCOVERY = 'ui.monitoring.discovery';
- public const UI_MONITORING_SERVICES = 'ui.monitoring.services';
public const UI_INVENTORY_OVERVIEW = 'ui.inventory.overview';
public const UI_INVENTORY_HOSTS = 'ui.inventory.hosts';
public const UI_REPORTS_SYSTEM_INFO = 'ui.reports.system_info';
@@ -40,6 +39,10 @@ class CRoleHelper {
public const UI_REPORTS_ACTION_LOG = 'ui.reports.action_log';
public const UI_REPORTS_NOTIFICATIONS = 'ui.reports.notifications';
public const UI_REPORTS_SCHEDULED_REPORTS = 'ui.reports.scheduled_reports';
+ public const UI_SERVICES_SERVICES = 'ui.services.services';
+ public const UI_SERVICES_ACTIONS = 'ui.services.actions';
+ public const UI_SERVICES_SLA = 'ui.services.sla';
+ public const UI_SERVICES_SLA_REPORT = 'ui.services.sla_report';
public const UI_CONFIGURATION_HOST_GROUPS = 'ui.configuration.host_groups';
public const UI_CONFIGURATION_TEMPLATES = 'ui.configuration.templates';
public const UI_CONFIGURATION_HOSTS = 'ui.configuration.hosts';
@@ -67,8 +70,10 @@ class CRoleHelper {
public const ACTIONS_EXECUTE_SCRIPTS = 'actions.execute_scripts';
public const ACTIONS_MANAGE_API_TOKENS = 'actions.manage_api_tokens';
public const ACTIONS_MANAGE_SCHEDULED_REPORTS = 'actions.manage_scheduled_reports';
+ public const ACTIONS_MANAGE_SLA = 'actions.manage_sla';
public const UI_SECTION_MONITORING = 'ui.monitoring';
+ public const UI_SECTION_SERVICES = 'ui.services';
public const UI_SECTION_INVENTORY = 'ui.inventory';
public const UI_SECTION_REPORTS = 'ui.reports';
public const UI_SECTION_CONFIGURATION = 'ui.configuration';
@@ -211,27 +216,50 @@ class CRoleHelper {
*/
public static function getUiElementsByUserType(int $user_type): array {
$rules = [
- self::UI_MONITORING_DASHBOARD, self::UI_MONITORING_PROBLEMS, self::UI_MONITORING_HOSTS,
- self::UI_MONITORING_LATEST_DATA, self::UI_MONITORING_MAPS, self::UI_MONITORING_SERVICES,
- self::UI_INVENTORY_OVERVIEW, self::UI_INVENTORY_HOSTS, self::UI_REPORTS_AVAILABILITY_REPORT,
- self::UI_REPORTS_TOP_TRIGGERS
+ self::UI_INVENTORY_HOSTS,
+ self::UI_INVENTORY_OVERVIEW,
+ self::UI_MONITORING_DASHBOARD,
+ self::UI_MONITORING_HOSTS,
+ self::UI_MONITORING_LATEST_DATA,
+ self::UI_MONITORING_MAPS,
+ self::UI_MONITORING_PROBLEMS,
+ self::UI_REPORTS_AVAILABILITY_REPORT,
+ self::UI_REPORTS_TOP_TRIGGERS,
+ self::UI_SERVICES_SERVICES,
+ self::UI_SERVICES_SLA_REPORT
];
if ($user_type === USER_TYPE_ZABBIX_ADMIN || $user_type === USER_TYPE_SUPER_ADMIN) {
$rules = array_merge($rules, [
- self::UI_MONITORING_DISCOVERY, self::UI_REPORTS_NOTIFICATIONS, self::UI_REPORTS_SCHEDULED_REPORTS,
- self::UI_CONFIGURATION_HOST_GROUPS, self::UI_CONFIGURATION_TEMPLATES, self::UI_CONFIGURATION_HOSTS,
- self::UI_CONFIGURATION_MAINTENANCE, self::UI_CONFIGURATION_ACTIONS, self::UI_CONFIGURATION_DISCOVERY
+ self::UI_CONFIGURATION_ACTIONS,
+ self::UI_CONFIGURATION_DISCOVERY,
+ self::UI_CONFIGURATION_HOST_GROUPS,
+ self::UI_CONFIGURATION_HOSTS,
+ self::UI_CONFIGURATION_MAINTENANCE,
+ self::UI_CONFIGURATION_TEMPLATES,
+ self::UI_MONITORING_DISCOVERY,
+ self::UI_REPORTS_NOTIFICATIONS,
+ self::UI_REPORTS_SCHEDULED_REPORTS,
+ self::UI_SERVICES_ACTIONS,
+ self::UI_SERVICES_SLA
]);
}
if ($user_type === USER_TYPE_SUPER_ADMIN) {
$rules = array_merge($rules, [
- self::UI_REPORTS_SYSTEM_INFO, self::UI_REPORTS_AUDIT, self::UI_REPORTS_ACTION_LOG,
- self::UI_CONFIGURATION_EVENT_CORRELATION, self::UI_ADMINISTRATION_GENERAL, self::UI_ADMINISTRATION_PROXIES,
- self::UI_ADMINISTRATION_AUTHENTICATION, self::UI_ADMINISTRATION_USER_GROUPS,
- self::UI_ADMINISTRATION_USER_ROLES, self::UI_ADMINISTRATION_USERS, self::UI_ADMINISTRATION_MEDIA_TYPES,
- self::UI_ADMINISTRATION_SCRIPTS, self::UI_ADMINISTRATION_QUEUE
+ self::UI_ADMINISTRATION_AUTHENTICATION,
+ self::UI_ADMINISTRATION_GENERAL,
+ self::UI_ADMINISTRATION_MEDIA_TYPES,
+ self::UI_ADMINISTRATION_PROXIES,
+ self::UI_ADMINISTRATION_QUEUE,
+ self::UI_ADMINISTRATION_SCRIPTS,
+ self::UI_ADMINISTRATION_USER_GROUPS,
+ self::UI_ADMINISTRATION_USER_ROLES,
+ self::UI_ADMINISTRATION_USERS,
+ self::UI_CONFIGURATION_EVENT_CORRELATION,
+ self::UI_REPORTS_ACTION_LOG,
+ self::UI_REPORTS_AUDIT,
+ self::UI_REPORTS_SYSTEM_INFO
]);
}
@@ -257,6 +285,7 @@ class CRoleHelper {
if ($user_type === USER_TYPE_ZABBIX_ADMIN || $user_type === USER_TYPE_SUPER_ADMIN) {
$rules[] = self::ACTIONS_EDIT_MAINTENANCE;
$rules[] = self::ACTIONS_MANAGE_SCHEDULED_REPORTS;
+ $rules[] = self::ACTIONS_MANAGE_SLA;
}
return $rules;
@@ -274,8 +303,9 @@ class CRoleHelper {
public static function getUiSectionsLabels(int $user_type): array {
$sections = [
self::UI_SECTION_MONITORING => _('Monitoring'),
+ self::UI_SECTION_SERVICES => _('Services'),
self::UI_SECTION_INVENTORY => _('Inventory'),
- self::UI_SECTION_REPORTS => _('Reports')
+ self::UI_SECTION_REPORTS => _('Reports'),
];
if ($user_type === USER_TYPE_ZABBIX_ADMIN || $user_type === USER_TYPE_SUPER_ADMIN) {
@@ -314,9 +344,22 @@ class CRoleHelper {
$labels += [self::UI_MONITORING_DISCOVERY => _('Discovery')];
}
- $labels += [self::UI_MONITORING_SERVICES => _('Services')];
+ return $labels;
+
+ case self::UI_SECTION_SERVICES:
+ $labels = [
+ self::UI_SERVICES_SERVICES => _('Services'),
+ self::UI_SERVICES_ACTIONS => _('Service actions'),
+ ];
+
+ if ($user_type === USER_TYPE_ZABBIX_ADMIN || $user_type === USER_TYPE_SUPER_ADMIN) {
+ $labels += [self::UI_SERVICES_SLA => _('SLA')];
+ }
+
+ $labels += [self::UI_SERVICES_SLA_REPORT => _('SLA report')];
return $labels;
+
case self::UI_SECTION_INVENTORY:
return [
self::UI_INVENTORY_OVERVIEW => _('Overview'),
@@ -424,7 +467,10 @@ class CRoleHelper {
];
if ($user_type === USER_TYPE_ZABBIX_ADMIN || $user_type === USER_TYPE_SUPER_ADMIN) {
- $labels += [self::ACTIONS_MANAGE_SCHEDULED_REPORTS => _('Manage scheduled reports')];
+ $labels += [
+ self::ACTIONS_MANAGE_SCHEDULED_REPORTS => _('Manage scheduled reports'),
+ self::ACTIONS_MANAGE_SLA => _('Manage SLA')
+ ];
}
return $labels;
diff --git a/ui/include/classes/helpers/CSlaHelper.php b/ui/include/classes/helpers/CSlaHelper.php
new file mode 100644
index 00000000000..9dddf48b525
--- /dev/null
+++ b/ui/include/classes/helpers/CSlaHelper.php
@@ -0,0 +1,72 @@
+<?php declare(strict_types = 1);
+/*
+** Zabbix
+** Copyright (C) 2001-2021 Zabbix SIA
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+**/
+
+
+/**
+ * A class designed to perform actions and contain constants related to SLA.
+ */
+class CSlaHelper {
+
+ public const SLA_STATUS_ANY = -1;
+ public const SLA_STATUS_ENABLED = 0;
+ public const SLA_STATUS_DISABLED = 1;
+
+ public const PERIOD_DAILY = 0;
+ public const PERIOD_WEEKLY = 1;
+ public const PERIOD_MONTHLY = 2;
+ public const PERIOD_QUARTERLY = 3;
+ public const PERIOD_ANNUALLY = 4;
+
+ public const SCHEDULE_MODE_NONSTOP = 0;
+ public const SCHEDULE_MODE_CUSTOM = 1;
+
+ public static function periodToStr(int $period): ?string {
+ static $period_strings;
+
+ if ($period_strings === null) {
+ $period_strings = [
+ self::PERIOD_DAILY => _('Daily'),
+ self::PERIOD_WEEKLY => _('Weekly'),
+ self::PERIOD_MONTHLY => _('Monthly'),
+ self::PERIOD_QUARTERLY => _('Quarterly'),
+ self::PERIOD_ANNUALLY => _('Annually')
+ ];
+ }
+
+ return array_key_exists($period, $period_strings)
+ ? $period_strings[$period]
+ : null;
+ }
+
+ public static function scheduleToStr(int $schedule_mode): ?string {
+ static $schedule_modes;
+
+ if ($schedule_modes === null) {
+ $schedule_modes = [
+ self::SCHEDULE_MODE_NONSTOP => _('24x7'),
+ self::SCHEDULE_MODE_CUSTOM => _('Custom')
+ ];
+ }
+
+ return array_key_exists($schedule_mode, $schedule_modes)
+ ? $schedule_modes[$schedule_mode]
+ : null;
+ }
+}
diff --git a/ui/include/classes/mvc/CRouter.php b/ui/include/classes/mvc/CRouter.php
index b7f7cc7508c..26b27378720 100644
--- a/ui/include/classes/mvc/CRouter.php
+++ b/ui/include/classes/mvc/CRouter.php
@@ -239,10 +239,14 @@ class CRouter {
'search' => ['CControllerSearch', 'layout.htmlpage', 'search'],
'service.create' => ['CControllerServiceCreate', 'layout.json', null],
'service.delete' => ['CControllerServiceDelete', null, null],
- 'service.list' => ['CControllerServiceList', 'layout.htmlpage', 'monitoring.service.list'],
- 'service.list.refresh' => ['CControllerServiceListRefresh', 'layout.json', 'monitoring.service.list.refresh'],
- 'service.list.edit' => ['CControllerServiceListEdit', 'layout.htmlpage', 'monitoring.service.list.edit'],
- 'service.list.edit.refresh' => ['CControllerServiceListEditRefresh', 'layout.json', 'monitoring.service.list.edit.refresh'],
+ 'service.list' => ['CControllerServiceList', 'layout.htmlpage', 'services.service.list'],
+ 'service.list.refresh' => ['CControllerServiceListRefresh', 'layout.json', 'services.service.list.refresh'],
+ 'service.list.edit' => ['CControllerServiceListEdit', 'layout.htmlpage', 'services.service.list.edit'],
+ 'service.list.edit.refresh' => ['CControllerServiceListEditRefresh', 'layout.json', 'services.service.list.edit.refresh'],
+ 'sla.create' => ['CControllerSlaCreate', 'layout.json', null],
+ 'sla.delete' => ['CControllerSlaDelete', null, null],
+ 'sla.list' => ['CControllerSlaList', 'layout.htmlpage', 'services.sla.list'],
+ 'sla.list.refresh' => ['CControllerSlaListRefresh', 'layout.json', 'services.sla.list.refresh'],
'service.statusrule.validate' => ['CControllerServiceStatusRuleValidate', 'layout.json', null],
'service.time.validate' => ['CControllerServiceTimeValidate', 'layout.json', null],
'service.update' => ['CControllerServiceUpdate', 'layout.json', null],
diff --git a/ui/include/defines.inc.php b/ui/include/defines.inc.php
index 8e1f1d49f19..0058a028869 100644
--- a/ui/include/defines.inc.php
+++ b/ui/include/defines.inc.php
@@ -22,7 +22,7 @@ define('ZABBIX_VERSION', '6.0.0alpha7');
define('ZABBIX_API_VERSION', '6.0.0');
define('ZABBIX_EXPORT_VERSION', '6.0');
-define('ZABBIX_DB_VERSION', 5050127);
+define('ZABBIX_DB_VERSION', 5050128);
define('DB_VERSION_SUPPORTED', 0);
define('DB_VERSION_LOWER_THAN_MINIMUM', 1);
@@ -2027,6 +2027,9 @@ define('ZBX_STYLE_ZSELECT_HOST_INTERFACE', 'z-select-host-interface');
define('ZBX_STYLE_DASHBOARD_LIST', 'dashboard-list');
define('ZBX_STYLE_DASHBOARD_LIST_ITEM', 'dashboard-list-item');
+define('ZBX_SLA_MAX_REPORTING_PERIODS', 100);
+define('ZBX_SLA_DEFAULT_REPORTING_PERIODS', 20);
+
// server variables
define('HTTPS', isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] && $_SERVER['HTTPS'] !== 'off');
diff --git a/ui/tests/selenium/testSID.php b/ui/tests/selenium/testSID.php
index 77b7ce6dae6..52dfe3e66a6 100644
--- a/ui/tests/selenium/testSID.php
+++ b/ui/tests/selenium/testSID.php
@@ -331,7 +331,7 @@ class testSID extends CWebTest {
// User role creation.
[['link' => 'zabbix.php?form_refresh=1&name=sadasda&type=1&ui_monitoring_dashboard=1&ui_monitoring_problems='.
'1&ui_monitoring_hosts=1&ui_monitoring_overview=1&ui_monitoring_latest_data=1&ui_monitoring_screens=1'.
- '&ui_monitoring_maps=1&ui_monitoring_discovery=0&ui_monitoring_services=1&ui_inventory_overview=1&'.
+ '&ui_monitoring_maps=1&ui_monitoring_discovery=0&ui_services_services=1&ui_inventory_overview=1&'.
'ui_inventory_hosts=1&ui_reports_system_info=0&ui_reports_availability_report=1&ui_reports_top_triggers'.
'=1&ui_reports_audit=0&ui_reports_action_log=0&ui_reports_notifications=0&ui_configuration_host_groups=0'.
'&ui_configuration_templates=0&ui_configuration_hosts=0&ui_configuration_maintenance=0&'.
@@ -348,7 +348,7 @@ class testSID extends CWebTest {
[['link' => 'zabbix.php?form_refresh=1&roleid=5&name=sadasda&type=2&ui_monitoring_dashboard=1&'.
'ui_monitoring_problems=1&ui_monitoring_hosts=1&ui_monitoring_overview=1&ui_monitoring_latest_data=1'.
'&ui_monitoring_screens=1&ui_monitoring_maps=1&ui_monitoring_discovery=0&ui_monitoring_discovery=1&'.
- 'ui_monitoring_services=1&ui_inventory_overview=1&ui_inventory_hosts=1&ui_reports_system_info=0&'.
+ 'ui_services_services=1&ui_inventory_overview=1&ui_inventory_hosts=1&ui_reports_system_info=0&'.
'ui_reports_availability_report=1&ui_reports_top_triggers=1&ui_reports_audit=0&ui_reports_action_log=0'.
'&ui_reports_notifications=0&ui_reports_notifications=1&ui_configuration_host_groups=0&'.
'ui_configuration_host_groups=1&ui_configuration_templates=0&ui_configuration_templates=1&'.