From e0d7dbd02e935138dff74123f5cb65134e15025a Mon Sep 17 00:00:00 2001 From: Ivo Kurzemnieks Date: Fri, 3 Jul 2020 17:47:39 +0300 Subject: ..F....... [ZBXNEXT-2754] renamed routes and controllers related XML export to just export, added a new export button with styles and replaced the old export button --- sass/stylesheets/sass/screen.scss | 38 ++++++- ui/app/controllers/CControllerExport.php | 123 +++++++++++++++++++++ ui/app/controllers/CControllerExportXml.php | 120 -------------------- ui/app/views/administration.mediatype.list.php | 13 +-- ui/app/views/administration.valuemap.list.php | 13 +-- ui/app/views/layout.export.php | 29 +++++ ui/app/views/layout.xml.php | 29 ----- ui/assets/styles/blue-theme.css | 23 +++- ui/assets/styles/dark-theme.css | 23 +++- ui/assets/styles/hc-dark.css | 23 +++- ui/assets/styles/hc-light.css | 23 +++- ui/include/classes/api/services/CConfiguration.php | 4 +- .../export/writers/CExportWriterFactory.php | 23 ++++ ui/include/classes/html/CActionButtonList.php | 62 ++++++----- ui/include/classes/html/CButtonDropdown.php | 3 +- ui/include/classes/html/CButtonExport.php | 57 ++++++++++ ui/include/classes/mvc/CRouter.php | 12 +- ui/include/defines.inc.php | 2 + ui/include/views/configuration.host.list.php | 13 +-- ui/include/views/configuration.template.list.php | 13 +-- ui/include/views/monitoring.screen.list.php | 13 +-- ui/include/views/monitoring.sysmap.list.php | 13 +-- 22 files changed, 433 insertions(+), 239 deletions(-) create mode 100644 ui/app/controllers/CControllerExport.php delete mode 100644 ui/app/controllers/CControllerExportXml.php create mode 100644 ui/app/views/layout.export.php delete mode 100644 ui/app/views/layout.xml.php create mode 100644 ui/include/classes/html/CButtonExport.php diff --git a/sass/stylesheets/sass/screen.scss b/sass/stylesheets/sass/screen.scss index e27f510ffe5..c36e5c4faa6 100644 --- a/sass/stylesheets/sass/screen.scss +++ b/sass/stylesheets/sass/screen.scss @@ -7056,6 +7056,35 @@ table.preprocessing-test-results { } } +.btn-split { + display: inline-flex; + position: relative; + + // Fix for buttons that have no content. + vertical-align: top; + + li { + button { + margin: 0 -1px 0 0; + border-radius: 0; + } + + &:first-child button { + border-radius: 2px 0 0 2px; + } + + &:last-child button { + border-radius: 0 2px 2px 0; + margin-right: 10px; + } + + &:only-child button { + border-radius: 2px; + margin-right: 10px; + } + } +} + .btn-dropdown-toggle { white-space: nowrap; overflow: hidden; @@ -7073,12 +7102,17 @@ table.preprocessing-test-results { height: 22px; content: ''; } + + &::after { + top: 6px; + right: 2px; + } } &::after { position: absolute; - top: 6px; - right: 2px; + top: 7px; + right: 17px; width: 10px; height: 10px; content: ''; diff --git a/ui/app/controllers/CControllerExport.php b/ui/app/controllers/CControllerExport.php new file mode 100644 index 00000000000..c5d6cb551be --- /dev/null +++ b/ui/app/controllers/CControllerExport.php @@ -0,0 +1,123 @@ + 'required|string', + 'backurl' => 'required|string', + 'valuemapids' => 'not_empty|array_db valuemaps.valuemapid', + 'hosts' => 'not_empty|array_db hosts.hostid', + 'mediatypeids' => 'not_empty|array_db media_type.mediatypeid', + 'screens' => 'not_empty|array_db screens.screenid', + 'maps' => 'not_empty|array_db sysmaps.sysmapid', + 'templates' => 'not_empty|array_db hosts.hostid', + 'format' => 'in '.implode(',', [CExportWriterFactory::YAML, CExportWriterFactory::XML, CExportWriterFactory::JSON]) + ]; + + $ret = $this->validateInput($fields); + + if (!$ret) { + $this->setResponse(new CControllerResponseFatal()); + } + + return $ret; + } + + protected function checkPermissions() { + switch ($this->getInput('action')) { + case 'export.mediatypes': + case 'export.valuemaps': + return (CWebUser::$data['type'] >= USER_TYPE_SUPER_ADMIN); + + case 'export.hosts': + case 'export.templates': + return (CWebUser::$data['type'] >= USER_TYPE_ZABBIX_ADMIN); + + case 'export.screens': + case 'export.sysmaps': + return (CWebUser::$data['type'] >= USER_TYPE_ZABBIX_USER); + + default: + return false; + } + } + + protected function doAction() { + $action = $this->getInput('action'); + $format = $this->getInput('format', CExportWriterFactory::YAML); + + switch ($action) { + case 'export.valuemaps': + $export = new CConfigurationExport(['valueMaps' => $this->getInput('valuemapids', [])]); + break; + + case 'export.hosts': + $export = new CConfigurationExport(['hosts' => $this->getInput('hosts', [])]); + break; + + case 'export.mediatypes': + $export = new CConfigurationExport(['mediaTypes' => $this->getInput('mediatypeids', [])]); + break; + + case 'export.screens': + $export = new CConfigurationExport(['screens' => $this->getInput('screens', [])]); + break; + + case 'export.sysmaps': + $export = new CConfigurationExport(['maps' => $this->getInput('maps', [])]); + break; + + case 'export.templates': + $export = new CConfigurationExport(['templates' => $this->getInput('templates', [])]); + break; + + default: + $this->setResponse(new CControllerResponseFatal()); + + return; + } + + $export->setBuilder(new CConfigurationExportBuilder()); + $export->setWriter(CExportWriterFactory::getWriter($format)); + + $export_data = $export->export(); + + if ($export_data === false) { + // Access denied. + + $response = new CControllerResponseRedirect( + $this->getInput('backurl', 'zabbix.php?action=dashboard.view')); + + $response->setMessageError(_('No permissions to referred object or it does not exist!')); + } + else { + $response = new CControllerResponseData([ + 'main_block' => $export_data, + 'content_type' => CExportWriterFactory::getContentType($format), + 'page' => ['file' => 'zbx_export_'.substr($action, 7).'.'.$format] + ]); + } + + $this->setResponse($response); + } +} diff --git a/ui/app/controllers/CControllerExportXml.php b/ui/app/controllers/CControllerExportXml.php deleted file mode 100644 index 6b1238b7008..00000000000 --- a/ui/app/controllers/CControllerExportXml.php +++ /dev/null @@ -1,120 +0,0 @@ - 'required|string', - 'backurl' => 'required|string', - 'valuemapids' => 'not_empty|array_db valuemaps.valuemapid', - 'hosts' => 'not_empty|array_db hosts.hostid', - 'mediatypeids' => 'not_empty|array_db media_type.mediatypeid', - 'screens' => 'not_empty|array_db screens.screenid', - 'maps' => 'not_empty|array_db sysmaps.sysmapid', - 'templates' => 'not_empty|array_db hosts.hostid' - ]; - - $ret = $this->validateInput($fields); - - if (!$ret) { - $this->setResponse(new CControllerResponseFatal()); - } - - return $ret; - } - - protected function checkPermissions() { - switch ($this->getInput('action')) { - case 'export.mediatypes.xml': - case 'export.valuemaps.xml': - return (CWebUser::$data['type'] >= USER_TYPE_SUPER_ADMIN); - - case 'export.hosts.xml': - case 'export.templates.xml': - return (CWebUser::$data['type'] >= USER_TYPE_ZABBIX_ADMIN); - - case 'export.screens.xml': - case 'export.sysmaps.xml': - return (CWebUser::$data['type'] >= USER_TYPE_ZABBIX_USER); - - default: - return false; - } - } - - protected function doAction() { - $action = $this->getInput('action'); - - switch ($action) { - case 'export.valuemaps.xml': - $export = new CConfigurationExport(['valueMaps' => $this->getInput('valuemapids', [])]); - break; - - case 'export.hosts.xml': - $export = new CConfigurationExport(['hosts' => $this->getInput('hosts', [])]); - break; - - case 'export.mediatypes.xml': - $export = new CConfigurationExport(['mediaTypes' => $this->getInput('mediatypeids', [])]); - break; - - case 'export.screens.xml': - $export = new CConfigurationExport(['screens' => $this->getInput('screens', [])]); - break; - - case 'export.sysmaps.xml': - $export = new CConfigurationExport(['maps' => $this->getInput('maps', [])]); - break; - - case 'export.templates.xml': - $export = new CConfigurationExport(['templates' => $this->getInput('templates', [])]); - break; - - default: - $this->setResponse(new CControllerResponseFatal()); - - return; - } - - $export->setBuilder(new CConfigurationExportBuilder()); - $export->setWriter(CExportWriterFactory::getWriter(CExportWriterFactory::XML)); - - $export_data = $export->export(); - - if ($export_data === false) { - // Access denied. - - $response = new CControllerResponseRedirect( - $this->getInput('backurl', 'zabbix.php?action=dashboard.view')); - - $response->setMessageError(_('No permissions to referred object or it does not exist!')); - } - else { - $response = new CControllerResponseData([ - 'main_block' => $export_data, - 'page' => ['file' => 'zbx_export_' . substr($action, 7)] - ]); - } - - $this->setResponse($response); - } -} diff --git a/ui/app/views/administration.mediatype.list.php b/ui/app/views/administration.mediatype.list.php index d812ef30675..6f8aa6cec7e 100644 --- a/ui/app/views/administration.mediatype.list.php +++ b/ui/app/views/administration.mediatype.list.php @@ -161,14 +161,13 @@ $mediaTypeForm->addItem([ new CActionButtonList('action', 'mediatypeids', [ 'mediatype.enable' => ['name' => _('Enable'), 'confirm' => _('Enable selected media types?')], 'mediatype.disable' => ['name' => _('Disable'), 'confirm' => _('Disable selected media types?')], - 'mediatype.export' => ['name' => _('Export'), 'redirect' => - (new CUrl('zabbix.php')) - ->setArgument('action', 'export.mediatypes.xml') - ->setArgument('backurl', (new CUrl('zabbix.php')) + 'mediatype.export' => [ + 'content' => new CButtonExport('export.mediatypes', + (new CUrl('zabbix.php')) ->setArgument('action', 'mediatype.list') - ->setArgument('page', $data['page'] == 1 ? null : $data['page']) - ->getUrl()) - ->getUrl() + ->setArgument('page', ($data['page'] == 1) ? null : $data['page']) + ->getUrl() + ) ], 'mediatype.delete' => ['name' => _('Delete'), 'confirm' => _('Delete selected media types?')] ], 'mediatype') diff --git a/ui/app/views/administration.valuemap.list.php b/ui/app/views/administration.valuemap.list.php index df4bb0d9803..1184af2060a 100644 --- a/ui/app/views/administration.valuemap.list.php +++ b/ui/app/views/administration.valuemap.list.php @@ -87,14 +87,13 @@ $form->addItem([ $table, $data['paging'], new CActionButtonList('action', 'valuemapids', [ - 'valuemap.export' => ['name' => _('Export'), 'redirect' => - (new CUrl('zabbix.php')) - ->setArgument('action', 'export.valuemaps.xml') - ->setArgument('backurl', (new CUrl('zabbix.php')) + 'valuemap.export' => [ + 'content' => new CButtonExport('export.valuemaps', + (new CUrl('zabbix.php')) ->setArgument('action', 'valuemap.list') - ->setArgument('page', $data['page'] == 1 ? null : $data['page']) - ->getUrl()) - ->getUrl() + ->setArgument('page', ($data['page'] == 1) ? null : $data['page']) + ->getUrl() + ) ], 'valuemap.delete' => ['name' => _('Delete'), 'confirm' => _('Delete selected value maps?')] ]) diff --git a/ui/app/views/layout.export.php b/ui/app/views/layout.export.php new file mode 100644 index 00000000000..a0db647bb66 --- /dev/null +++ b/ui/app/views/layout.export.php @@ -0,0 +1,29 @@ + API_OBJECT, 'fields' => [ - 'format' => ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED, 'in' => implode(',', [CExportWriterFactory::XML, CExportWriterFactory::JSON])], + 'format' => ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED, 'in' => implode(',', [CExportWriterFactory::YAML, CExportWriterFactory::XML, CExportWriterFactory::JSON])], 'options' => ['type' => API_OBJECT, 'flags' => API_REQUIRED, 'fields' => [ 'groups' => ['type' => API_IDS], 'hosts' => ['type' => API_IDS], @@ -69,7 +69,7 @@ class CConfiguration extends CApiService { */ public function import($params) { $api_input_rules = ['type' => API_OBJECT, 'fields' => [ - 'format' => ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED, 'in' => implode(',', [CImportReaderFactory::XML, CImportReaderFactory::JSON])], + 'format' => ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED, 'in' => implode(',', [CExportWriterFactory::YAML, CImportReaderFactory::XML, CImportReaderFactory::JSON])], 'source' => ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED], 'rules' => ['type' => API_OBJECT, 'flags' => API_REQUIRED, 'fields' => [ 'applications' => ['type' => API_OBJECT, 'fields' => [ diff --git a/ui/include/classes/export/writers/CExportWriterFactory.php b/ui/include/classes/export/writers/CExportWriterFactory.php index ed36c368f9f..12150399bdb 100644 --- a/ui/include/classes/export/writers/CExportWriterFactory.php +++ b/ui/include/classes/export/writers/CExportWriterFactory.php @@ -23,6 +23,7 @@ class CExportWriterFactory { const XML = 'xml'; const JSON = 'json'; + const YAML = 'yml'; /** * Get the writer object for specified type. @@ -42,6 +43,28 @@ class CExportWriterFactory { case self::JSON: return new CJsonExportWriter(); + case self::YAML: + return null; + + default: + throw new Exception('Incorrect export writer type.'); + } + } + + public static function getContentType($type) { + switch ($type) { + case self::XML: + // See https://www.ietf.org/rfc/rfc2376.txt + return 'text/xml'; + + case self::JSON: + // See https://www.ietf.org/rfc/rfc4627.txt + return 'application/json'; + + case self::YAML: + // See https://github.com/rails/rails/blob/d41d586/actionpack/lib/action_dispatch/http/mime_types.rb#L39 + return 'text/yaml'; + default: throw new Exception('Incorrect export writer type.'); } diff --git a/ui/include/classes/html/CActionButtonList.php b/ui/include/classes/html/CActionButtonList.php index 11aef41e777..87a13d7d470 100644 --- a/ui/include/classes/html/CActionButtonList.php +++ b/ui/include/classes/html/CActionButtonList.php @@ -61,6 +61,7 @@ class CActionButtonList extends CObject { * @param string $buttons_data[]['name'] Button caption. * @param string $buttons_data[]['confirm'] Confirmation text (optional). * @param string $buttons_data[]['redirect'] Redirect URL (optional). + * @param CTag $buttons_data[]['content'] A HTML tag. For example a CButton wrapped in CList object. * @param string|null $name_prefix Prefix for sessionStorage used for storing currently selected * checkboxes. */ @@ -69,36 +70,41 @@ class CActionButtonList extends CObject { $this->name_prefix = $name_prefix ? $name_prefix : null; foreach ($buttons_data as $action => $button_data) { - $button = (new CSubmit($action_name, $button_data['name'])) - ->addClass(ZBX_STYLE_BTN_ALT) - ->removeAttribute('id'); - - if (array_key_exists('redirect', $button_data)) { - $button - // Removing parameters not to conflict with the redirecting URL. - ->removeAttribute('name') - ->removeAttribute('value') - ->onClick('var $_form = jQuery(this).closest("form");'. - // Save the original form action. - 'if (!$_form.data("action")) {'. - '$_form.data("action", $_form.attr("action"));'. - '}'. - '$_form.attr("action", '.json_encode($button_data['redirect']).');' - ); + if (array_key_exists('content', $button_data)) { + $button = $button_data['content']; } else { - $button - ->setAttribute('value', $action) - ->onClick('var $_form = jQuery(this).closest("form");'. - // Restore the original form action, if previously saved. - 'if ($_form.data("action")) {'. - '$_form.attr("action", $_form.data("action"));'. - '}' - ); - } - - if (array_key_exists('confirm', $button_data)) { - $button->setAttribute('confirm', $button_data['confirm']); + $button = (new CSubmit($action_name, $button_data['name'])) + ->addClass(ZBX_STYLE_BTN_ALT) + ->removeAttribute('id'); + + if (array_key_exists('redirect', $button_data)) { + $button + // Removing parameters not to conflict with the redirecting URL. + ->removeAttribute('name') + ->removeAttribute('value') + ->onClick('var $_form = jQuery(this).closest("form");'. + // Save the original form action. + 'if (!$_form.data("action")) {'. + '$_form.data("action", $_form.attr("action"));'. + '}'. + '$_form.attr("action", '.json_encode($button_data['redirect']).');' + ); + } + else { + $button + ->setAttribute('value', $action) + ->onClick('var $_form = jQuery(this).closest("form");'. + // Restore the original form action, if previously saved. + 'if ($_form.data("action")) {'. + '$_form.attr("action", $_form.data("action"));'. + '}' + ); + } + + if (array_key_exists('confirm', $button_data)) { + $button->setAttribute('confirm', $button_data['confirm']); + } } $this->buttons[$action] = $button; diff --git a/ui/include/classes/html/CButtonDropdown.php b/ui/include/classes/html/CButtonDropdown.php index b90f50e225b..63256d1d947 100644 --- a/ui/include/classes/html/CButtonDropdown.php +++ b/ui/include/classes/html/CButtonDropdown.php @@ -29,7 +29,6 @@ class CButtonDropdown extends CButton { /** * Button style names. */ - public const ZBX_STYLE_BTN_TOGGLE = 'btn-dropdown-toggle'; public const ZBX_STYLE_BTN_VALUE = 'dropdown-value'; /** @@ -54,7 +53,7 @@ class CButtonDropdown extends CButton { $this->setId(uniqid('btn-dropdown-')); $this->addClass(ZBX_STYLE_BTN_ALT); - $this->addClass(self::ZBX_STYLE_BTN_TOGGLE); + $this->addClass(ZBX_STYLE_BTN_TOGGLE); $this->dropdown_items = $items; if ($value !== null) { diff --git a/ui/include/classes/html/CButtonExport.php b/ui/include/classes/html/CButtonExport.php new file mode 100644 index 00000000000..4ee58a0c3a0 --- /dev/null +++ b/ui/include/classes/html/CButtonExport.php @@ -0,0 +1,57 @@ +removeAttribute('id') + ->removeAttribute('name') + ->removeAttribute('value') + ->addClass(ZBX_STYLE_BTN_ALT) + ->onClick('var $_form = jQuery(this).closest("form");'. + // Save the original form action. + 'if (!$_form.data("action")) {'. + '$_form.data("action", $_form.attr("action"));'. + '}'. + '$_form.attr("action", '.json_encode( + (new CUrl('zabbix.php')) + ->setArgument('action', $action) + ->setArgument('format', CExportWriterFactory::XML) + ->setArgument('backurl', $back_url) + ->getUrl() + ).');' + ), + (new CButton('export')) + ->addClass(ZBX_STYLE_BTN_ALT) + ->addClass(ZBX_STYLE_BTN_TOGGLE) + ]); + + $this->addClass(ZBX_STYLE_BTN_SPLIT); + } +} diff --git a/ui/include/classes/mvc/CRouter.php b/ui/include/classes/mvc/CRouter.php index 3fdb49db5b5..758a38580cd 100644 --- a/ui/include/classes/mvc/CRouter.php +++ b/ui/include/classes/mvc/CRouter.php @@ -78,12 +78,12 @@ class CRouter { 'dashboard.widget.rfrate' => ['CControllerDashboardWidgetRfRate', 'layout.json', null], 'dashboard.widget.sanitize' => ['CControllerDashboardWidgetSanitize', 'layout.json', null], 'discovery.view' => ['CControllerDiscoveryView', 'layout.htmlpage', 'monitoring.discovery.view'], - 'export.hosts.xml' => ['CControllerExportXml', 'layout.xml', null], - 'export.mediatypes.xml' => ['CControllerExportXml', 'layout.xml', null], - 'export.screens.xml' => ['CControllerExportXml', 'layout.xml', null], - 'export.sysmaps.xml' => ['CControllerExportXml', 'layout.xml', null], - 'export.templates.xml' => ['CControllerExportXml', 'layout.xml', null], - 'export.valuemaps.xml' => ['CControllerExportXml', 'layout.xml', null], + 'export.hosts' => ['CControllerExport', 'layout.export', null], + 'export.mediatypes' => ['CControllerExport', 'layout.export', null], + 'export.screens' => ['CControllerExport', 'layout.export', null], + 'export.sysmaps' => ['CControllerExport', 'layout.export', null], + 'export.templates' => ['CControllerExport', 'layout.export', null], + 'export.valuemaps' => ['CControllerExport', 'layout.export', null], 'favourite.create' => ['CControllerFavouriteCreate', 'layout.javascript', null], 'favourite.delete' => ['CControllerFavouriteDelete', 'layout.javascript', null], 'gui.edit' => ['CControllerGuiEdit', 'layout.htmlpage', 'administration.gui.edit'], diff --git a/ui/include/defines.inc.php b/ui/include/defines.inc.php index f33397d04df..bd07e20cd98 100644 --- a/ui/include/defines.inc.php +++ b/ui/include/defines.inc.php @@ -1570,6 +1570,8 @@ define('ZBX_STYLE_ARROW_UP', 'arrow-up'); define('ZBX_STYLE_BLUE', 'blue'); define('ZBX_STYLE_BTN_ADD_FAV', 'btn-add-fav'); define('ZBX_STYLE_BTN_ALT', 'btn-alt'); +define('ZBX_STYLE_BTN_SPLIT', 'btn-split'); +define('ZBX_STYLE_BTN_TOGGLE', 'btn-dropdown-toggle'); define('ZBX_STYLE_BTN_BACK_MAP', 'btn-back-map'); define('ZBX_STYLE_BTN_BACK_MAP_CONTAINER', 'btn-back-map-container'); define('ZBX_STYLE_BTN_BACK_MAP_CONTENT', 'btn-back-map-content'); diff --git a/ui/include/views/configuration.host.list.php b/ui/include/views/configuration.host.list.php index c3e08f229de..510a368e6bb 100644 --- a/ui/include/views/configuration.host.list.php +++ b/ui/include/views/configuration.host.list.php @@ -466,13 +466,12 @@ $form->addItem([ [ 'host.massenable' => ['name' => _('Enable'), 'confirm' => _('Enable selected hosts?')], 'host.massdisable' => ['name' => _('Disable'), 'confirm' => _('Disable selected hosts?')], - 'host.export' => ['name' => _('Export'), 'redirect' => - (new CUrl('zabbix.php')) - ->setArgument('action', 'export.hosts.xml') - ->setArgument('backurl', (new CUrl('hosts.php')) - ->setArgument('page', $data['page'] == 1 ? null : $data['page']) - ->getUrl()) - ->getUrl() + 'host.export' => [ + 'content' => new CButtonExport('export.hosts', + (new CUrl('hosts.php')) + ->setArgument('page', ($data['page'] == 1) ? null : $data['page']) + ->getUrl() + ) ], 'host.massupdateform' => ['name' => _('Mass update')], 'host.massdelete' => ['name' => _('Delete'), 'confirm' => _('Delete selected hosts?')] diff --git a/ui/include/views/configuration.template.list.php b/ui/include/views/configuration.template.list.php index da7b56faf3e..8b35412c0b2 100644 --- a/ui/include/views/configuration.template.list.php +++ b/ui/include/views/configuration.template.list.php @@ -311,13 +311,12 @@ $form->addItem([ $data['paging'], new CActionButtonList('action', 'templates', [ - 'template.export' => ['name' => _('Export'), 'redirect' => - (new CUrl('zabbix.php')) - ->setArgument('action', 'export.templates.xml') - ->setArgument('backurl', (new CUrl('templates.php')) - ->setArgument('page', $data['page'] == 1 ? null : $data['page']) - ->getUrl()) - ->getUrl() + 'template.export' => [ + 'content' => new CButtonExport('export.templates', + (new CUrl('templates.php')) + ->setArgument('page', ($data['page'] == 1) ? null : $data['page']) + ->getUrl() + ) ], 'template.massupdateform' => ['name' => _('Mass update')], 'template.massdelete' => ['name' => _('Delete'), 'confirm' => _('Delete selected templates?')], diff --git a/ui/include/views/monitoring.screen.list.php b/ui/include/views/monitoring.screen.list.php index 4d53f7359a6..cd669a4e130 100644 --- a/ui/include/views/monitoring.screen.list.php +++ b/ui/include/views/monitoring.screen.list.php @@ -121,13 +121,12 @@ foreach ($data['screens'] as $screen) { $buttons = []; if (!$data['templateid']) { - $buttons['screen.export'] = ['name' => _('Export'), 'redirect' => - (new CUrl('zabbix.php')) - ->setArgument('action', 'export.screens.xml') - ->setArgument('backurl', (new CUrl('screenconf.php')) - ->setArgument('page', $data['page'] == 1 ? null : $data['page']) - ->getUrl()) - ->getUrl() + $buttons['screen.export'] = [ + 'content' => new CButtonExport('export.screens', + (new CUrl('screenconf.php')) + ->setArgument('page', ($data['page'] == 1) ? null : $data['page']) + ->getUrl() + ) ]; } diff --git a/ui/include/views/monitoring.sysmap.list.php b/ui/include/views/monitoring.sysmap.list.php index f77680965ad..30b5b05ed4d 100644 --- a/ui/include/views/monitoring.sysmap.list.php +++ b/ui/include/views/monitoring.sysmap.list.php @@ -94,13 +94,12 @@ $sysmapForm->addItem([ $sysmapTable, $this->data['paging'], new CActionButtonList('action', 'maps', [ - 'map.export' => ['name' => _('Export'), 'redirect' => - (new CUrl('zabbix.php')) - ->setArgument('action', 'export.sysmaps.xml') - ->setArgument('backurl', (new CUrl('sysmaps.php')) - ->setArgument('page', $data['page'] == 1 ? null : $data['page']) - ->getUrl()) - ->getUrl() + 'map.export' => [ + 'content' => new CButtonExport('export.sysmaps', + (new CUrl('sysmaps.php')) + ->setArgument('page', ($data['page'] == 1) ? null : $data['page']) + ->getUrl() + ) ], 'map.massdelete' => ['name' => _('Delete'), 'confirm' => _('Delete selected maps?')] ]) -- cgit v1.2.3 From f0fff69ec4634b44aa5d6b600b00a49734f718e0 Mon Sep 17 00:00:00 2001 From: Ivo Kurzemnieks Date: Tue, 7 Jul 2020 14:50:15 +0300 Subject: ..F....... [ZBXNEXT-2754] changed split button elements to inline blocks, added another callback to dropdown menu, changed default format to YAML, removed unused defines --- sass/stylesheets/sass/screen.scss | 12 ++++------ ui/assets/styles/blue-theme.css | 28 +++++++++++----------- ui/assets/styles/dark-theme.css | 28 +++++++++++----------- ui/assets/styles/hc-dark.css | 28 +++++++++++----------- ui/assets/styles/hc-light.css | 28 +++++++++++----------- ui/include/classes/html/CButtonDropdown.php | 5 +++- ui/include/classes/html/CButtonExport.php | 36 +++++++++++++++++++++++++++-- ui/include/debug.inc.php | 2 +- ui/include/defines.inc.php | 10 -------- ui/js/init.js | 3 +-- ui/js/menupopup.js | 33 +++++++++++++++++++++----- 11 files changed, 128 insertions(+), 85 deletions(-) diff --git a/sass/stylesheets/sass/screen.scss b/sass/stylesheets/sass/screen.scss index c36e5c4faa6..c49f62c2c5d 100644 --- a/sass/stylesheets/sass/screen.scss +++ b/sass/stylesheets/sass/screen.scss @@ -7057,13 +7057,13 @@ table.preprocessing-test-results { } .btn-split { - display: inline-flex; + display: inline-block; position: relative; - - // Fix for buttons that have no content. - vertical-align: top; + margin-right: 10px; li { + display: inline-block; + button { margin: 0 -1px 0 0; border-radius: 0; @@ -7075,12 +7075,10 @@ table.preprocessing-test-results { &:last-child button { border-radius: 0 2px 2px 0; - margin-right: 10px; } &:only-child button { border-radius: 2px; - margin-right: 10px; } } } @@ -7112,7 +7110,7 @@ table.preprocessing-test-results { &::after { position: absolute; top: 7px; - right: 17px; + right: 6px; width: 10px; height: 10px; content: ''; diff --git a/ui/assets/styles/blue-theme.css b/ui/assets/styles/blue-theme.css index 06e335f47ea..7fe4b24bd04 100644 --- a/ui/assets/styles/blue-theme.css +++ b/ui/assets/styles/blue-theme.css @@ -5443,20 +5443,20 @@ table.preprocessing-test-results .rel-container { background-position: -399px -510px; } .btn-split { - display: inline-flex; + display: inline-block; position: relative; - vertical-align: top; } - .btn-split li button { - margin: 0 -1px 0 0; - border-radius: 0; } - .btn-split li:first-child button { - border-radius: 2px 0 0 2px; } - .btn-split li:last-child button { - border-radius: 0 2px 2px 0; - margin-right: 10px; } - .btn-split li:only-child button { - border-radius: 2px; - margin-right: 10px; } + margin-right: 10px; } + .btn-split li { + display: inline-block; } + .btn-split li button { + margin: 0 -1px 0 0; + border-radius: 0; } + .btn-split li:first-child button { + border-radius: 2px 0 0 2px; } + .btn-split li:last-child button { + border-radius: 0 2px 2px 0; } + .btn-split li:only-child button { + border-radius: 2px; } .btn-dropdown-toggle { white-space: nowrap; @@ -5478,7 +5478,7 @@ table.preprocessing-test-results .rel-container { .btn-dropdown-toggle::after { position: absolute; top: 7px; - right: 17px; + right: 6px; width: 10px; height: 10px; content: ''; diff --git a/ui/assets/styles/dark-theme.css b/ui/assets/styles/dark-theme.css index c2730e9ef11..4ad027f3465 100644 --- a/ui/assets/styles/dark-theme.css +++ b/ui/assets/styles/dark-theme.css @@ -5454,20 +5454,20 @@ table.preprocessing-test-results .rel-container { background-position: -399px -510px; } .btn-split { - display: inline-flex; + display: inline-block; position: relative; - vertical-align: top; } - .btn-split li button { - margin: 0 -1px 0 0; - border-radius: 0; } - .btn-split li:first-child button { - border-radius: 2px 0 0 2px; } - .btn-split li:last-child button { - border-radius: 0 2px 2px 0; - margin-right: 10px; } - .btn-split li:only-child button { - border-radius: 2px; - margin-right: 10px; } + margin-right: 10px; } + .btn-split li { + display: inline-block; } + .btn-split li button { + margin: 0 -1px 0 0; + border-radius: 0; } + .btn-split li:first-child button { + border-radius: 2px 0 0 2px; } + .btn-split li:last-child button { + border-radius: 0 2px 2px 0; } + .btn-split li:only-child button { + border-radius: 2px; } .btn-dropdown-toggle { white-space: nowrap; @@ -5489,7 +5489,7 @@ table.preprocessing-test-results .rel-container { .btn-dropdown-toggle::after { position: absolute; top: 7px; - right: 17px; + right: 6px; width: 10px; height: 10px; content: ''; diff --git a/ui/assets/styles/hc-dark.css b/ui/assets/styles/hc-dark.css index aaadf43ca8d..6c96b825f42 100644 --- a/ui/assets/styles/hc-dark.css +++ b/ui/assets/styles/hc-dark.css @@ -5398,20 +5398,20 @@ table.preprocessing-test-results .rel-container { background-position: -399px -510px; } .btn-split { - display: inline-flex; + display: inline-block; position: relative; - vertical-align: top; } - .btn-split li button { - margin: 0 -1px 0 0; - border-radius: 0; } - .btn-split li:first-child button { - border-radius: 2px 0 0 2px; } - .btn-split li:last-child button { - border-radius: 0 2px 2px 0; - margin-right: 10px; } - .btn-split li:only-child button { - border-radius: 2px; - margin-right: 10px; } + margin-right: 10px; } + .btn-split li { + display: inline-block; } + .btn-split li button { + margin: 0 -1px 0 0; + border-radius: 0; } + .btn-split li:first-child button { + border-radius: 2px 0 0 2px; } + .btn-split li:last-child button { + border-radius: 0 2px 2px 0; } + .btn-split li:only-child button { + border-radius: 2px; } .btn-dropdown-toggle { white-space: nowrap; @@ -5433,7 +5433,7 @@ table.preprocessing-test-results .rel-container { .btn-dropdown-toggle::after { position: absolute; top: 7px; - right: 17px; + right: 6px; width: 10px; height: 10px; content: ''; diff --git a/ui/assets/styles/hc-light.css b/ui/assets/styles/hc-light.css index 1887eb9b5df..2bb51ef030e 100644 --- a/ui/assets/styles/hc-light.css +++ b/ui/assets/styles/hc-light.css @@ -5398,20 +5398,20 @@ table.preprocessing-test-results .rel-container { background-position: -399px -510px; } .btn-split { - display: inline-flex; + display: inline-block; position: relative; - vertical-align: top; } - .btn-split li button { - margin: 0 -1px 0 0; - border-radius: 0; } - .btn-split li:first-child button { - border-radius: 2px 0 0 2px; } - .btn-split li:last-child button { - border-radius: 0 2px 2px 0; - margin-right: 10px; } - .btn-split li:only-child button { - border-radius: 2px; - margin-right: 10px; } + margin-right: 10px; } + .btn-split li { + display: inline-block; } + .btn-split li button { + margin: 0 -1px 0 0; + border-radius: 0; } + .btn-split li:first-child button { + border-radius: 2px 0 0 2px; } + .btn-split li:last-child button { + border-radius: 0 2px 2px 0; } + .btn-split li:only-child button { + border-radius: 2px; } .btn-dropdown-toggle { white-space: nowrap; @@ -5433,7 +5433,7 @@ table.preprocessing-test-results .rel-container { .btn-dropdown-toggle::after { position: absolute; top: 7px; - right: 17px; + right: 6px; width: 10px; height: 10px; content: ''; diff --git a/ui/include/classes/html/CButtonDropdown.php b/ui/include/classes/html/CButtonDropdown.php index 63256d1d947..4ca0518716d 100644 --- a/ui/include/classes/html/CButtonDropdown.php +++ b/ui/include/classes/html/CButtonDropdown.php @@ -73,7 +73,10 @@ class CButtonDropdown extends CButton { ->setId(zbx_formatDomId($name.'[btn]')) ->setMenuPopup([ 'type' => 'dropdown', - 'data' => ['items' => $this->dropdown_items] + 'data' => [ + 'items' => $this->dropdown_items, + 'toggle_class' => ZBX_STYLE_BTN_TOGGLE + ] ])) ->addItem((new CInput('hidden', $name, $this->getAttribute('value'))) ->addClass(self::ZBX_STYLE_BTN_VALUE) diff --git a/ui/include/classes/html/CButtonExport.php b/ui/include/classes/html/CButtonExport.php index 4ee58a0c3a0..3b993eca24c 100644 --- a/ui/include/classes/html/CButtonExport.php +++ b/ui/include/classes/html/CButtonExport.php @@ -42,14 +42,46 @@ class CButtonExport extends CList { '$_form.attr("action", '.json_encode( (new CUrl('zabbix.php')) ->setArgument('action', $action) - ->setArgument('format', CExportWriterFactory::XML) + ->setArgument('format', CExportWriterFactory::YAML) ->setArgument('backurl', $back_url) ->getUrl() ).');' ), - (new CButton('export')) + (new CButton('export', '​')) ->addClass(ZBX_STYLE_BTN_ALT) ->addClass(ZBX_STYLE_BTN_TOGGLE) + ->setMenuPopup([ + 'type' => 'dropdown', + 'data' => [ + 'submit_form' => true, + 'items' => [ + [ + 'label' => _('YAML'), + 'url' => (new CUrl('zabbix.php')) + ->setArgument('action', $action) + ->setArgument('format', CExportWriterFactory::YAML) + ->setArgument('backurl', $back_url) + ->getUrl() + ], + [ + 'label' => _('XML'), + 'url' => (new CUrl('zabbix.php')) + ->setArgument('action', $action) + ->setArgument('format', CExportWriterFactory::XML) + ->setArgument('backurl', $back_url) + ->getUrl() + ], + [ + 'label' => _('JSON'), + 'url' => (new CUrl('zabbix.php')) + ->setArgument('action', $action) + ->setArgument('format', CExportWriterFactory::JSON) + ->setArgument('backurl', $back_url) + ->getUrl() + ] + ] + ] + ]) ]); $this->addClass(ZBX_STYLE_BTN_SPLIT); diff --git a/ui/include/debug.inc.php b/ui/include/debug.inc.php index 00fcf9ccef5..07152c8bb44 100644 --- a/ui/include/debug.inc.php +++ b/ui/include/debug.inc.php @@ -97,7 +97,7 @@ function sdFile($data, $persist = false, $fileName = 'debug.txt') { fclose($fileStream); } -function sdff($msg, $fileName = '/tmp/zabbix.log') { +function sdff($msg, $fileName = 'C:/Development/zabbix-src/feature/ZBXNEXT-2754-5.1/ui/conf/log.txt') { $fileStreem = @fopen($fileName, 'a'); if (is_array($msg)) { $toImplode = []; diff --git a/ui/include/defines.inc.php b/ui/include/defines.inc.php index bd07e20cd98..a6a1bad8a7e 100644 --- a/ui/include/defines.inc.php +++ b/ui/include/defines.inc.php @@ -1267,16 +1267,6 @@ define('SERVER_CHECK_INTERVAL', 10); define('DATE_TIME_FORMAT_SECONDS_XML', 'Y-m-d\TH:i:s\Z'); -// XML export|import tags -define('XML_TAG_MACRO', 'macro'); -define('XML_TAG_HOST', 'host'); -define('XML_TAG_HOSTINVENTORY', 'host_inventory'); -define('XML_TAG_ITEM', 'item'); -define('XML_TAG_TRIGGER', 'trigger'); -define('XML_TAG_GRAPH', 'graph'); -define('XML_TAG_GRAPH_ELEMENT', 'graph_element'); -define('XML_TAG_DEPENDENCY', 'dependency'); - define('ZBX_DEFAULT_IMPORT_HOST_GROUP', 'Imported hosts'); // XML import flags diff --git a/ui/js/init.js b/ui/js/init.js index 5db35d0761b..0a5b2b9020f 100644 --- a/ui/js/init.js +++ b/ui/js/init.js @@ -255,8 +255,7 @@ jQuery(function($) { return { of: $obj, my: 'left top', - at: 'left top+24', - collision: 'none' + at: 'left bottom' }; case 'submenu': diff --git a/ui/js/menupopup.js b/ui/js/menupopup.js index 6a814ab7fe1..1a7c9906907 100644 --- a/ui/js/menupopup.js +++ b/ui/js/menupopup.js @@ -915,20 +915,41 @@ function getMenuPopupDropdown(options, trigger_elem) { var items = []; jQuery.each(options.items, function(i, item) { - items.push({ + var row = { label: item.label, - url: item.url || 'javascript:void(0);', - class: item.class, - clickCallback: () => { + url: item.url || 'javascript:void(0);' + }; + + if (item.class) { + row.class = item.class; + } + + if (options.toggle_class) { + row.clickCallback = () => { jQuery(trigger_elem) .removeClass() - .addClass(['btn-alt', 'btn-dropdown-toggle', item.class].join(' ')); + .addClass(['btn-alt', options.toggle_class, item.class].join(' ')); jQuery('input[type=hidden]', jQuery(trigger_elem).parent()) .val(item.value) .trigger('change'); } - }); + } + else if (options.submit_form) { + row.url = 'javascript:void(0);'; + row.clickCallback = () => { + var $_form = trigger_elem.closest('form'); + + if (!$_form.data("action")) { + $_form.data("action", $_form.attr("action")); + } + + $_form.attr("action", item.url); + $_form.submit(); + } + } + + items.push(row); }); return [{ -- cgit v1.2.3 From 0570e373f39b3dd0dd025d5b77ef75f424784725 Mon Sep 17 00:00:00 2001 From: Ivo Kurzemnieks Date: Tue, 7 Jul 2020 14:53:09 +0300 Subject: ..F....... [ZBXNEXT-2754] reverted changes made in debug --- ui/include/debug.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/include/debug.inc.php b/ui/include/debug.inc.php index 07152c8bb44..00fcf9ccef5 100644 --- a/ui/include/debug.inc.php +++ b/ui/include/debug.inc.php @@ -97,7 +97,7 @@ function sdFile($data, $persist = false, $fileName = 'debug.txt') { fclose($fileStream); } -function sdff($msg, $fileName = 'C:/Development/zabbix-src/feature/ZBXNEXT-2754-5.1/ui/conf/log.txt') { +function sdff($msg, $fileName = '/tmp/zabbix.log') { $fileStreem = @fopen($fileName, 'a'); if (is_array($msg)) { $toImplode = []; -- cgit v1.2.3 From 68e9eb53eed6b2d1ede1f014ba80f6ac53826912 Mon Sep 17 00:00:00 2001 From: Ivo Kurzemnieks Date: Wed, 8 Jul 2020 16:54:38 +0300 Subject: A......... [ZBXNEXT-2754] added YAML import/export writer and reader --- .../export/writers/CExportWriterFactory.php | 16 +++---- .../classes/export/writers/CYamlExportWriter.php | 37 +++++++++++++++ .../import/readers/CImportReaderFactory.php | 16 +++++-- .../classes/import/readers/CYamlImportReader.php | 54 ++++++++++++++++++++++ .../import/validators/CXmlValidatorGeneral.php | 5 +- 5 files changed, 115 insertions(+), 13 deletions(-) create mode 100644 ui/include/classes/export/writers/CYamlExportWriter.php create mode 100644 ui/include/classes/import/readers/CYamlImportReader.php diff --git a/ui/include/classes/export/writers/CExportWriterFactory.php b/ui/include/classes/export/writers/CExportWriterFactory.php index 12150399bdb..83b4aef53a3 100644 --- a/ui/include/classes/export/writers/CExportWriterFactory.php +++ b/ui/include/classes/export/writers/CExportWriterFactory.php @@ -21,9 +21,9 @@ class CExportWriterFactory { + const YAML = 'yml'; const XML = 'xml'; const JSON = 'json'; - const YAML = 'yml'; /** * Get the writer object for specified type. @@ -37,15 +37,15 @@ class CExportWriterFactory { */ public static function getWriter($type) { switch ($type) { + case self::YAML: + return new CYamlExportWriter(); + case self::XML: return new CXmlExportWriter(); case self::JSON: return new CJsonExportWriter(); - case self::YAML: - return null; - default: throw new Exception('Incorrect export writer type.'); } @@ -53,6 +53,10 @@ class CExportWriterFactory { public static function getContentType($type) { switch ($type) { + case self::YAML: + // See https://github.com/rails/rails/blob/d41d586/actionpack/lib/action_dispatch/http/mime_types.rb#L39 + return 'text/yaml'; + case self::XML: // See https://www.ietf.org/rfc/rfc2376.txt return 'text/xml'; @@ -61,10 +65,6 @@ class CExportWriterFactory { // See https://www.ietf.org/rfc/rfc4627.txt return 'application/json'; - case self::YAML: - // See https://github.com/rails/rails/blob/d41d586/actionpack/lib/action_dispatch/http/mime_types.rb#L39 - return 'text/yaml'; - default: throw new Exception('Incorrect export writer type.'); } diff --git a/ui/include/classes/export/writers/CYamlExportWriter.php b/ui/include/classes/export/writers/CYamlExportWriter.php new file mode 100644 index 00000000000..0609ed07cdf --- /dev/null +++ b/ui/include/classes/export/writers/CYamlExportWriter.php @@ -0,0 +1,37 @@ +format) { - case 'xml': + case CImportReaderFactory::XML: $is_valid_tag = ($tag === $prefix.($index == 0 ? '' : $index) || $tag === $index); break; - case 'json': + case CImportReaderFactory::YAML: + case CImportReaderFactory::JSON: $is_valid_tag = ctype_digit(strval($tag)); break; -- cgit v1.2.3 From 30495b01432c56d526673aee5411b938d0f55e31 Mon Sep 17 00:00:00 2001 From: Ivo Kurzemnieks Date: Wed, 8 Jul 2020 17:52:28 +0300 Subject: ..F....... [ZBXNEXT-2754] added PHPLibYAML extension check in setup and system information --- ui/include/classes/setup/CFrontendSetup.php | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/ui/include/classes/setup/CFrontendSetup.php b/ui/include/classes/setup/CFrontendSetup.php index 6699dc1e10b..bafa1a5fe6a 100644 --- a/ui/include/classes/setup/CFrontendSetup.php +++ b/ui/include/classes/setup/CFrontendSetup.php @@ -33,6 +33,7 @@ class CFrontendSetup { const MIN_PHP_MAX_INPUT_TIME = 300; const MIN_PHP_GD_VERSION = '2.0'; const MIN_PHP_LIBXML_VERSION = '2.6.15'; + const MIN_PHP_LIBYAML_VERION = '2.0.2'; // See https://pecl.php.net/package/yaml const REQUIRED_PHP_ARG_SEPARATOR_OUTPUT = '&'; /** @@ -77,6 +78,7 @@ class CFrontendSetup { $result[] = $this->checkPhpGdJpeg(); $result[] = $this->checkPhpGdGif(); $result[] = $this->checkPhpGdFreeType(); + $result[] = $this->checkPhpLibYAML(); $result[] = $this->checkPhpLibxml(); $result[] = $this->checkPhpXmlWriter(); $result[] = $this->checkPhpXmlReader(); @@ -478,6 +480,27 @@ class CFrontendSetup { ]; } + /** + * Checks for PHP LibYAML extension. + * + * @return array + */ + public function checkPhpLibYAML() { + if (!$current = phpversion('yaml')) { + $current = _('unknown'); + } + + $check = version_compare($current, self::MIN_PHP_LIBYAML_VERION, '>='); + + return [ + 'name' => _('PHP LibYAML'), + 'current' => $current, + 'required' => self::MIN_PHP_LIBYAML_VERION, + 'result' => $check ? self::CHECK_OK : self::CHECK_FATAL, + 'error' => _('PHP LibYAML extension missing.') + ]; + } + /** * Checks for PHP libxml extension. * -- cgit v1.2.3 From 4ecb985b7b760394410180bb67023165cf5af7ab Mon Sep 17 00:00:00 2001 From: Ivo Kurzemnieks Date: Wed, 8 Jul 2020 17:57:37 +0300 Subject: .......... [ZBXNEXT-2754] added changelog --- ChangeLog.d/feature/ZBXNEXT-2754 | 1 + 1 file changed, 1 insertion(+) create mode 100644 ChangeLog.d/feature/ZBXNEXT-2754 diff --git a/ChangeLog.d/feature/ZBXNEXT-2754 b/ChangeLog.d/feature/ZBXNEXT-2754 new file mode 100644 index 00000000000..0963176f107 --- /dev/null +++ b/ChangeLog.d/feature/ZBXNEXT-2754 @@ -0,0 +1 @@ +A.F....... [ZBXNEXT-2754] added YAML as default import/export format (Ivo) -- cgit v1.2.3 From 8df6271c4a16ef91fa5db6bcbbba86c794f79d50 Mon Sep 17 00:00:00 2001 From: Anton Fayantsev Date: Fri, 10 Jul 2020 11:43:47 +0300 Subject: .........T [ZBX-11785] fixed dbstat query for postgresql v12 --- ChangeLog.d/bugfix/ZBX-17785 | 1 + templates/db/postgresql/postgresql/pgsql.dbstat.sql | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 ChangeLog.d/bugfix/ZBX-17785 diff --git a/ChangeLog.d/bugfix/ZBX-17785 b/ChangeLog.d/bugfix/ZBX-17785 new file mode 100644 index 00000000000..926447cca5d --- /dev/null +++ b/ChangeLog.d/bugfix/ZBX-17785 @@ -0,0 +1 @@ +.........T [ZBX-11785] fixed dbstat query for postgresql v12 (afayantsev) diff --git a/templates/db/postgresql/postgresql/pgsql.dbstat.sql b/templates/db/postgresql/postgresql/pgsql.dbstat.sql index d874658ccca..9a6e4c4de86 100644 --- a/templates/db/postgresql/postgresql/pgsql.dbstat.sql +++ b/templates/db/postgresql/postgresql/pgsql.dbstat.sql @@ -14,4 +14,4 @@ SELECT json_object_agg(datname, row_to_json(T)) FROM ( temp_files, temp_bytes, deadlocks - FROM pg_stat_database) T + FROM pg_stat_database where datname is not null) T -- cgit v1.2.3 From 092f40837e2ee9a7f8e4d746e43ccf87ed218923 Mon Sep 17 00:00:00 2001 From: Miks Kronkalns Date: Fri, 10 Jul 2020 15:04:04 +0300 Subject: ..F....... [ZBXNEXT-2754] fixed coding style --- ui/app/controllers/CControllerExport.php | 2 +- ui/app/views/layout.export.php | 2 +- ui/include/classes/export/writers/CExportWriterFactory.php | 12 +++++++++++- ui/include/classes/export/writers/CYamlExportWriter.php | 4 ++-- ui/include/classes/import/readers/CYamlImportReader.php | 12 +++++++----- ui/include/classes/setup/CFrontendSetup.php | 2 +- 6 files changed, 23 insertions(+), 11 deletions(-) diff --git a/ui/app/controllers/CControllerExport.php b/ui/app/controllers/CControllerExport.php index c5d6cb551be..50a659165ba 100644 --- a/ui/app/controllers/CControllerExport.php +++ b/ui/app/controllers/CControllerExport.php @@ -113,7 +113,7 @@ class CControllerExport extends CController { else { $response = new CControllerResponseData([ 'main_block' => $export_data, - 'content_type' => CExportWriterFactory::getContentType($format), + 'mime_type' => CExportWriterFactory::getMimeType($format), 'page' => ['file' => 'zbx_export_'.substr($action, 7).'.'.$format] ]); } diff --git a/ui/app/views/layout.export.php b/ui/app/views/layout.export.php index a0db647bb66..38a1b1d88fd 100644 --- a/ui/app/views/layout.export.php +++ b/ui/app/views/layout.export.php @@ -23,7 +23,7 @@ * @var CView $this */ -header('Content-Type: '.$data['content_type'].'; charset=utf-8'); +header('Content-Type: '.$data['mime_type'].'; charset=utf-8'); header('Content-Disposition: attachment; filename="'.$data['page']['file'].'"'); echo $data['main_block']; diff --git a/ui/include/classes/export/writers/CExportWriterFactory.php b/ui/include/classes/export/writers/CExportWriterFactory.php index 83b4aef53a3..6f0e07ac15e 100644 --- a/ui/include/classes/export/writers/CExportWriterFactory.php +++ b/ui/include/classes/export/writers/CExportWriterFactory.php @@ -51,7 +51,17 @@ class CExportWriterFactory { } } - public static function getContentType($type) { + /** + * Get content mime-type for specified type. + * + * @static + * @throws Exception + * + * @param string $type + * + * @return string + */ + public static function getMimeType(string $type): string { switch ($type) { case self::YAML: // See https://github.com/rails/rails/blob/d41d586/actionpack/lib/action_dispatch/http/mime_types.rb#L39 diff --git a/ui/include/classes/export/writers/CYamlExportWriter.php b/ui/include/classes/export/writers/CYamlExportWriter.php index 0609ed07cdf..13b0f2cc140 100644 --- a/ui/include/classes/export/writers/CYamlExportWriter.php +++ b/ui/include/classes/export/writers/CYamlExportWriter.php @@ -1,4 +1,4 @@ - Date: Fri, 10 Jul 2020 17:15:22 +0300 Subject: A.F....... [ZBXNEXT-2754] changed default file extension from yml to yaml --- ui/include/classes/export/writers/CExportWriterFactory.php | 2 +- ui/include/classes/import/readers/CImportReaderFactory.php | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/ui/include/classes/export/writers/CExportWriterFactory.php b/ui/include/classes/export/writers/CExportWriterFactory.php index 6f0e07ac15e..d2e9235c70b 100644 --- a/ui/include/classes/export/writers/CExportWriterFactory.php +++ b/ui/include/classes/export/writers/CExportWriterFactory.php @@ -21,7 +21,7 @@ class CExportWriterFactory { - const YAML = 'yml'; + const YAML = 'yaml'; const XML = 'xml'; const JSON = 'json'; diff --git a/ui/include/classes/import/readers/CImportReaderFactory.php b/ui/include/classes/import/readers/CImportReaderFactory.php index 0888aa04df6..56bf1a0bd9c 100644 --- a/ui/include/classes/import/readers/CImportReaderFactory.php +++ b/ui/include/classes/import/readers/CImportReaderFactory.php @@ -21,7 +21,7 @@ class CImportReaderFactory { - const YAML = 'yml'; + const YAML = 'yaml'; const XML = 'xml'; const JSON = 'json'; @@ -63,6 +63,7 @@ class CImportReaderFactory { */ public static function fileExt2ImportFormat($ext) { switch ($ext) { + case 'yaml': case 'yml': return CImportReaderFactory::YAML; -- cgit v1.2.3 From e8f59a8c788f122ee1c0c8ff71eb20613bad00e1 Mon Sep 17 00:00:00 2001 From: Ivo Kurzemnieks Date: Thu, 16 Jul 2020 18:00:03 +0300 Subject: A......... [ZBXNEXT-2754] added import/export string normalizer --- ui/include/classes/api/services/CConfiguration.php | 4 +- ui/include/classes/export/CConfigurationExport.php | 3 +- .../classes/export/CConfigurationExportBuilder.php | 9 +- .../converters/CArrayKeysImportConverter.php | 75 ----------------- .../import/converters/CImportDataNormalizer.php | 98 ++++++++++++++++++++++ .../classes/import/validators/C50XmlValidator.php | 14 ++-- 6 files changed, 116 insertions(+), 87 deletions(-) delete mode 100644 ui/include/classes/import/converters/CArrayKeysImportConverter.php create mode 100644 ui/include/classes/import/converters/CImportDataNormalizer.php diff --git a/ui/include/classes/api/services/CConfiguration.php b/ui/include/classes/api/services/CConfiguration.php index 0554c6d3962..45efc60fb02 100644 --- a/ui/include/classes/api/services/CConfiguration.php +++ b/ui/include/classes/api/services/CConfiguration.php @@ -177,8 +177,8 @@ class CConfiguration extends CApiService { // Add default values in place of missed tags. $data = (new CDefaultImportConverter($schema))->convert($data); - // Normalize array keys. - $data = (new CArrayKeysImportConverter($schema))->convert($data); + // Normalize array keys and strings. + $data = (new CImportDataNormalizer($schema))->normalize($data); // Transform converter. $data = (new CTransformImportConverter($schema))->convert($data); diff --git a/ui/include/classes/export/CConfigurationExport.php b/ui/include/classes/export/CConfigurationExport.php index da061e0ca18..2400d62eb14 100644 --- a/ui/include/classes/export/CConfigurationExport.php +++ b/ui/include/classes/export/CConfigurationExport.php @@ -136,7 +136,8 @@ class CConfigurationExport { try { $this->gatherData(); - $schema = (new CImportValidatorFactory('xml')) + // Parameter in CImportValidatorFactory is irrelavant here, since export does not validate data. + $schema = (new CImportValidatorFactory(CExportWriterFactory::YAML)) ->getObject(ZABBIX_EXPORT_VERSION) ->getSchema(); diff --git a/ui/include/classes/export/CConfigurationExportBuilder.php b/ui/include/classes/export/CConfigurationExportBuilder.php index 0e0596df9f4..eaf73bf0022 100644 --- a/ui/include/classes/export/CConfigurationExportBuilder.php +++ b/ui/include/classes/export/CConfigurationExportBuilder.php @@ -44,11 +44,11 @@ class CConfigurationExportBuilder { } /** - * Build XML data. + * Build data structure. * * @param array $schema Tag schema from validation class. * @param array $data Export data. - * @param string $main_tag XML tag (for error reporting). + * @param string $main_tag Main element (for error reporting). * * @return array */ @@ -66,6 +66,7 @@ class CConfigurationExportBuilder { $store = []; foreach ($rules as $tag => $val) { $is_required = $val['type'] & XML_REQUIRED; + $is_string = $val['type'] & XML_STRING; $is_array = $val['type'] & XML_ARRAY; $is_indexed_array = $val['type'] & XML_INDEXED_ARRAY; $has_data = array_key_exists($tag, $row); @@ -99,6 +100,10 @@ class CConfigurationExportBuilder { continue; } + if ($is_string && $value !== null) { + $value = str_replace("\r\n", "\n", $value); + } + if (array_key_exists('in', $val)) { if (!array_key_exists($value, $val['in'])) { throw new Exception(_s('Invalid tag "%1$s": %2$s.', $tag, diff --git a/ui/include/classes/import/converters/CArrayKeysImportConverter.php b/ui/include/classes/import/converters/CArrayKeysImportConverter.php deleted file mode 100644 index ddaf6c8f657..00000000000 --- a/ui/include/classes/import/converters/CArrayKeysImportConverter.php +++ /dev/null @@ -1,75 +0,0 @@ -rules = $schema; - } - - public function convert($data) { - $data['zabbix_export'] = $this->normalizeArrayKeys($data['zabbix_export'], $this->rules); - - return $data; - } - - /** - * Convert array keys to numeric. - * - * @param mixed $data Import data. - * @param array $rules XML rules. - * - * @return array - */ - protected function normalizeArrayKeys($data, array $rules) { - if (!is_array($data)) { - return $data; - } - - if ($rules['type'] & XML_ARRAY) { - foreach ($rules['rules'] as $tag => $tag_rules) { - if (array_key_exists('ex_rules', $tag_rules)) { - $tag_rules = call_user_func($tag_rules['ex_rules'], $data); - } - - if (array_key_exists($tag, $data)) { - $data[$tag] = $this->normalizeArrayKeys($data[$tag], $tag_rules); - } - } - } - elseif ($rules['type'] & XML_INDEXED_ARRAY) { - $prefix = $rules['prefix']; - - foreach ($data as $tag => $value) { - $data[$tag] = $this->normalizeArrayKeys($value, $rules['rules'][$prefix]); - } - - $data = array_values($data); - } - - return $data; - } -} diff --git a/ui/include/classes/import/converters/CImportDataNormalizer.php b/ui/include/classes/import/converters/CImportDataNormalizer.php new file mode 100644 index 00000000000..795b8696927 --- /dev/null +++ b/ui/include/classes/import/converters/CImportDataNormalizer.php @@ -0,0 +1,98 @@ +rules = $schema; + } + + public function normalize($data) { + $data['zabbix_export'] = $this->normalizeArrayKeys($data['zabbix_export']); + $data['zabbix_export'] = $this->normalizeStrings($data['zabbix_export']); + + return $data; + } + + /** + * Convert array keys to numeric. + * + * @param mixed $data Import data. + * + * @return array + */ + protected function normalizeArrayKeys($data) { + if (!is_array($data)) { + return $data; + } + + if ($this->rules['type'] & XML_ARRAY) { + foreach ($this->rules['rules'] as $tag => $tag_rules) { + if (array_key_exists('ex_rules', $tag_rules)) { + $tag_rules = call_user_func($tag_rules['ex_rules'], $data); + } + + if (array_key_exists($tag, $data)) { + $data[$tag] = $this->normalizeArrayKeys($data[$tag], $tag_rules); + } + } + } + elseif ($this->rules['type'] & XML_INDEXED_ARRAY) { + $prefix = $this->rules['prefix']; + + foreach ($data as $tag => $value) { + $data[$tag] = $this->normalizeArrayKeys($value, $this->rules['rules'][$prefix]); + } + + $data = array_values($data); + } + + return $data; + } + + /** + * Add CR to string type fields. + * + * @param mixed $data Import data. + * + * @return mixed + */ + protected function normalizeStrings($data) { + if ($this->rules['type'] & XML_STRING) { + $data = str_replace("\r\n", "\n", $data); + + if (array_key_exists('flags', $this->rules) && $this->rules['flags'] & self::EOL_LF) { + } + else { + $data = str_replace("\n", "\r\n", $data); + } + } + + return $data; + } +} diff --git a/ui/include/classes/import/validators/C50XmlValidator.php b/ui/include/classes/import/validators/C50XmlValidator.php index 7b9a8653c36..43c7965067b 100644 --- a/ui/include/classes/import/validators/C50XmlValidator.php +++ b/ui/include/classes/import/validators/C50XmlValidator.php @@ -457,7 +457,7 @@ class C50XmlValidator { 'preprocessing' => ['type' => XML_INDEXED_ARRAY, 'prefix' => 'step', 'rules' => [ 'step' => ['type' => XML_ARRAY, 'rules' => [ 'type' => ['type' => XML_STRING | XML_REQUIRED, 'in' => $this->PREPROCESSING_STEP_TYPE], - 'params' => ['type' => XML_STRING | XML_REQUIRED], + 'params' => ['type' => XML_STRING | XML_REQUIRED, 'flags' => CImportDataNormalizer::EOL_LF], 'error_handler' => ['type' => XML_STRING, 'default' => CXmlConstantValue::ORIGINAL_ERROR, 'in' => $this->ITEM_PREPROCESSING_ERROR_HANDLER], 'error_handler_params' => ['type' => XML_STRING, 'default' => ''] ]] @@ -598,7 +598,7 @@ class C50XmlValidator { 'preprocessing' => ['type' => XML_INDEXED_ARRAY, 'prefix' => 'step', 'rules' => [ 'step' => ['type' => XML_ARRAY, 'rules' => [ 'type' => ['type' => XML_STRING | XML_REQUIRED, 'in' => $this->PREPROCESSING_STEP_TYPE], - 'params' => ['type' => XML_STRING | XML_REQUIRED], + 'params' => ['type' => XML_STRING | XML_REQUIRED, 'flags' => CImportDataNormalizer::EOL_LF], 'error_handler' => ['type' => XML_STRING, 'default' => CXmlConstantValue::ORIGINAL_ERROR, 'in' => $this->ITEM_PREPROCESSING_ERROR_HANDLER], 'error_handler_params' => ['type' => XML_STRING, 'default' => ''] ]] @@ -811,7 +811,7 @@ class C50XmlValidator { 'preprocessing' => ['type' => XML_INDEXED_ARRAY, 'prefix' => 'step', 'rules' => [ 'step' => ['type' => XML_ARRAY, 'rules' => [ 'type' => ['type' => XML_STRING | XML_REQUIRED, 'in' => $this->PREPROCESSING_STEP_TYPE_DRULE], - 'params' => ['type' => XML_STRING | XML_REQUIRED], + 'params' => ['type' => XML_STRING | XML_REQUIRED, 'flags' => CImportDataNormalizer::EOL_LF], 'error_handler' => ['type' => XML_STRING, 'default' => CXmlConstantValue::ORIGINAL_ERROR, 'in' => $this->ITEM_PREPROCESSING_ERROR_HANDLER], 'error_handler_params' => ['type' => XML_STRING, 'default' => ''] ]] @@ -1068,7 +1068,7 @@ class C50XmlValidator { 'preprocessing' => ['type' => XML_INDEXED_ARRAY, 'prefix' => 'step', 'rules' => [ 'step' => ['type' => XML_ARRAY, 'rules' => [ 'type' => ['type' => XML_STRING | XML_REQUIRED, 'in' => $this->PREPROCESSING_STEP_TYPE], - 'params' => ['type' => XML_STRING | XML_REQUIRED], + 'params' => ['type' => XML_STRING | XML_REQUIRED, 'flags' => CImportDataNormalizer::EOL_LF], 'error_handler' => ['type' => XML_STRING, 'default' => CXmlConstantValue::ORIGINAL_ERROR, 'in' => $this->ITEM_PREPROCESSING_ERROR_HANDLER], 'error_handler_params' => ['type' => XML_STRING, 'default' => ''] ]] @@ -1207,7 +1207,7 @@ class C50XmlValidator { 'preprocessing' => ['type' => XML_INDEXED_ARRAY, 'prefix' => 'step', 'rules' => [ 'step' => ['type' => XML_ARRAY, 'rules' => [ 'type' => ['type' => XML_STRING | XML_REQUIRED, 'in' => $this->PREPROCESSING_STEP_TYPE], - 'params' => ['type' => XML_STRING | XML_REQUIRED], + 'params' => ['type' => XML_STRING | XML_REQUIRED, 'flags' => CImportDataNormalizer::EOL_LF], 'error_handler' => ['type' => XML_STRING, 'default' => CXmlConstantValue::ORIGINAL_ERROR, 'in' => $this->ITEM_PREPROCESSING_ERROR_HANDLER], 'error_handler_params' => ['type' => XML_STRING, 'default' => ''] ]] @@ -1418,7 +1418,7 @@ class C50XmlValidator { 'preprocessing' => ['type' => XML_INDEXED_ARRAY, 'prefix' => 'step', 'rules' => [ 'step' => ['type' => XML_ARRAY, 'rules' => [ 'type' => ['type' => XML_STRING | XML_REQUIRED, 'in' => $this->PREPROCESSING_STEP_TYPE_DRULE], - 'params' => ['type' => XML_STRING | XML_REQUIRED], + 'params' => ['type' => XML_STRING | XML_REQUIRED, 'flags' => CImportDataNormalizer::EOL_LF], 'error_handler' => ['type' => XML_STRING, 'default' => CXmlConstantValue::ORIGINAL_ERROR, 'in' => $this->ITEM_PREPROCESSING_ERROR_HANDLER], 'error_handler_params' => ['type' => XML_STRING, 'default' => ''] ]] @@ -2259,7 +2259,7 @@ class C50XmlValidator { switch ($data['type']) { case CXmlConstantName::SCRIPT: case CXmlConstantValue::MEDIA_TYPE_SCRIPT: - return ['type' => XML_STRING, 'default' => '', 'preprocessor' => [$this, 'scriptParameterPreprocessor'], 'export' => [$this, 'scriptParameterExport']]; + return ['type' => XML_STRING, 'flags' => CImportDataNormalizer::EOL_LF, 'default' => '', 'preprocessor' => [$this, 'scriptParameterPreprocessor'], 'export' => [$this, 'scriptParameterExport']]; case CXmlConstantName::WEBHOOK: case CXmlConstantValue::MEDIA_TYPE_WEBHOOK: -- cgit v1.2.3 From 1f98cf1742c890163fb6e15ef49d9836f22e1022 Mon Sep 17 00:00:00 2001 From: Ivo Kurzemnieks Date: Fri, 17 Jul 2020 15:27:30 +0300 Subject: ..F....... [ZBXNEXT-2754] minor code improvements --- .../classes/import/converters/CImportDataNormalizer.php | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/ui/include/classes/import/converters/CImportDataNormalizer.php b/ui/include/classes/import/converters/CImportDataNormalizer.php index 795b8696927..cf54cc77e73 100644 --- a/ui/include/classes/import/converters/CImportDataNormalizer.php +++ b/ui/include/classes/import/converters/CImportDataNormalizer.php @@ -1,4 +1,4 @@ -rules['type'] & XML_STRING) { $data = str_replace("\r\n", "\n", $data); - - if (array_key_exists('flags', $this->rules) && $this->rules['flags'] & self::EOL_LF) { - } - else { - $data = str_replace("\n", "\r\n", $data); - } + $data = (array_key_exists('flags', $this->rules) && $this->rules['flags'] & self::EOL_LF) + ? str_replace("\n", "\r\n", $data) + : $data; } return $data; -- cgit v1.2.3 From deea0015ab92cbd2c4b91781b7016d154d47aaad Mon Sep 17 00:00:00 2001 From: Ivo Kurzemnieks Date: Fri, 17 Jul 2020 15:56:41 +0300 Subject: ..F....... [ZBXNEXT-2754] fixed invalid if condition --- ui/include/classes/import/converters/CImportDataNormalizer.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/include/classes/import/converters/CImportDataNormalizer.php b/ui/include/classes/import/converters/CImportDataNormalizer.php index cf54cc77e73..c658dc348a2 100644 --- a/ui/include/classes/import/converters/CImportDataNormalizer.php +++ b/ui/include/classes/import/converters/CImportDataNormalizer.php @@ -86,8 +86,8 @@ class CImportDataNormalizer { if ($this->rules['type'] & XML_STRING) { $data = str_replace("\r\n", "\n", $data); $data = (array_key_exists('flags', $this->rules) && $this->rules['flags'] & self::EOL_LF) - ? str_replace("\n", "\r\n", $data) - : $data; + ? $data + : str_replace("\n", "\r\n", $data); } return $data; -- cgit v1.2.3 From a051452c840db254e1a859cd6e813e07c47a32f8 Mon Sep 17 00:00:00 2001 From: Ivo Kurzemnieks Date: Mon, 20 Jul 2020 10:07:05 +0300 Subject: A......... [ZBXNEXT-2754] fixed map export not validating schema --- ui/include/classes/export/CConfigurationExport.php | 2 +- ui/include/classes/export/CConfigurationExportBuilder.php | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/ui/include/classes/export/CConfigurationExport.php b/ui/include/classes/export/CConfigurationExport.php index 2400d62eb14..e594ace334d 100644 --- a/ui/include/classes/export/CConfigurationExport.php +++ b/ui/include/classes/export/CConfigurationExport.php @@ -175,7 +175,7 @@ class CConfigurationExport { } if ($this->data['maps']) { - $this->builder->buildMaps($this->data['maps']); + $this->builder->buildMaps($schema['rules']['maps'], $this->data['maps']); } if ($this->data['mediaTypes']) { diff --git a/ui/include/classes/export/CConfigurationExportBuilder.php b/ui/include/classes/export/CConfigurationExportBuilder.php index eaf73bf0022..952f14199bc 100644 --- a/ui/include/classes/export/CConfigurationExportBuilder.php +++ b/ui/include/classes/export/CConfigurationExportBuilder.php @@ -345,7 +345,7 @@ class CConfigurationExportBuilder { * * @param array $maps */ - public function buildMaps(array $maps) { + public function buildMaps(array $schema, array $maps) { $this->data['maps'] = []; CArrayHelper::sort($maps, ['name']); @@ -388,6 +388,8 @@ class CConfigurationExportBuilder { 'links' => $this->formatMapLinks($map['links'], $tmpSelements) ]; } + + $this->data['maps'] = $this->build($schema, $this->data['maps'], 'maps'); } /** -- cgit v1.2.3 From bbe505776cb6cc40c96c15dbbd351e071942c692 Mon Sep 17 00:00:00 2001 From: Miks Kronkalns Date: Mon, 20 Jul 2020 10:44:38 +0300 Subject: ..F....... [ZBXNEXT-2754] fixed coding style --- ui/include/classes/export/CConfigurationExportBuilder.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ui/include/classes/export/CConfigurationExportBuilder.php b/ui/include/classes/export/CConfigurationExportBuilder.php index 952f14199bc..b69458660c3 100644 --- a/ui/include/classes/export/CConfigurationExportBuilder.php +++ b/ui/include/classes/export/CConfigurationExportBuilder.php @@ -343,7 +343,8 @@ class CConfigurationExportBuilder { /** * Format maps. * - * @param array $maps + * @param array $schema Tag schema from validation class. + * @param array $maps Export data. */ public function buildMaps(array $schema, array $maps) { $this->data['maps'] = []; -- cgit v1.2.3 From 4004ed5cc7eff29a4a1d5567fd048bd5b3b5a484 Mon Sep 17 00:00:00 2001 From: Ivo Kurzemnieks Date: Mon, 20 Jul 2020 13:22:46 +0300 Subject: A......... [ZBXNEXT-2754] fixed array key normalizer, undefined indexes while exporting and unrelated typo --- ui/include/classes/export/CConfigurationExport.php | 12 ++++++++---- .../classes/import/converters/CImportDataNormalizer.php | 17 +++++++++-------- ui/include/classes/import/importers/CMapImporter.php | 2 +- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/ui/include/classes/export/CConfigurationExport.php b/ui/include/classes/export/CConfigurationExport.php index e594ace334d..86ab460560e 100644 --- a/ui/include/classes/export/CConfigurationExport.php +++ b/ui/include/classes/export/CConfigurationExport.php @@ -1443,10 +1443,14 @@ class CConfigurationExport { break; } - $selement['iconid_off'] = $selement['iconid_off'] > 0 ? $images[$selement['iconid_off']] : ''; - $selement['iconid_on'] = $selement['iconid_on'] > 0 ? $images[$selement['iconid_on']] : ''; - $selement['iconid_disabled'] = $selement['iconid_disabled'] > 0 ? $images[$selement['iconid_disabled']] : ''; - $selement['iconid_maintenance'] = $selement['iconid_maintenance'] > 0 ? $images[$selement['iconid_maintenance']] : ''; + $selement['iconid_off'] = ($selement['iconid_off'] > 0) ? $images[$selement['iconid_off']] : []; + $selement['iconid_on'] = ($selement['iconid_on'] > 0) ? $images[$selement['iconid_on']] : []; + $selement['iconid_disabled'] = ($selement['iconid_disabled'] > 0) + ? $images[$selement['iconid_disabled']] + : []; + $selement['iconid_maintenance'] = ($selement['iconid_maintenance'] > 0) + ? $images[$selement['iconid_maintenance']] + : []; } unset($selement); diff --git a/ui/include/classes/import/converters/CImportDataNormalizer.php b/ui/include/classes/import/converters/CImportDataNormalizer.php index c658dc348a2..b0a57683ded 100644 --- a/ui/include/classes/import/converters/CImportDataNormalizer.php +++ b/ui/include/classes/import/converters/CImportDataNormalizer.php @@ -33,7 +33,7 @@ class CImportDataNormalizer { } public function normalize($data) { - $data['zabbix_export'] = $this->normalizeArrayKeys($data['zabbix_export']); + $data['zabbix_export'] = $this->normalizeArrayKeys($data['zabbix_export'], $this->rules); $data['zabbix_export'] = $this->normalizeStrings($data['zabbix_export']); return $data; @@ -43,16 +43,17 @@ class CImportDataNormalizer { * Convert array keys to numeric. * * @param mixed $data Import data. + * @param array $rules Schema rules. * - * @return array + * @return mixed */ - protected function normalizeArrayKeys($data) { + protected function normalizeArrayKeys($data, array $rules) { if (!is_array($data)) { return $data; } - if ($this->rules['type'] & XML_ARRAY) { - foreach ($this->rules['rules'] as $tag => $tag_rules) { + if ($rules['type'] & XML_ARRAY) { + foreach ($rules['rules'] as $tag => $tag_rules) { if (array_key_exists('ex_rules', $tag_rules)) { $tag_rules = call_user_func($tag_rules['ex_rules'], $data); } @@ -62,11 +63,11 @@ class CImportDataNormalizer { } } } - elseif ($this->rules['type'] & XML_INDEXED_ARRAY) { - $prefix = $this->rules['prefix']; + elseif ($rules['type'] & XML_INDEXED_ARRAY) { + $prefix = $rules['prefix']; foreach ($data as $tag => $value) { - $data[$tag] = $this->normalizeArrayKeys($value, $this->rules['rules'][$prefix]); + $data[$tag] = $this->normalizeArrayKeys($value, $rules['rules'][$prefix]); } $data = array_values($data); diff --git a/ui/include/classes/import/importers/CMapImporter.php b/ui/include/classes/import/importers/CMapImporter.php index 2601eae46d7..a2226477e19 100644 --- a/ui/include/classes/import/importers/CMapImporter.php +++ b/ui/include/classes/import/importers/CMapImporter.php @@ -187,7 +187,7 @@ class CMapImporter extends CImporter { 'icon_off' => 'iconid_off', 'icon_on' => 'iconid_on', 'icon_disabled' => 'iconid_disabled', - 'icon_maintenance' => 'iconid_maintenance', + 'icon_maintenance' => 'iconid_maintenance' ]; foreach ($icons as $element => $field) { if (array_key_exists($element, $selement)) { -- cgit v1.2.3 From 661c802722d937c9b3fd90d468f4549730ef16b1 Mon Sep 17 00:00:00 2001 From: Natalja Karpinska Date: Fri, 24 Jul 2020 09:14:11 +0300 Subject: .......... [ZBXNEXT-2754] fixed tests, added yaml format in error message and additional pre-requisites checks on setup page --- ui/tests/api_json/testConfiguration.php | 8 ++++---- ui/tests/selenium/testFormAdministrationGeneralInstallation.php | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/ui/tests/api_json/testConfiguration.php b/ui/tests/api_json/testConfiguration.php index 615f02a9c0d..49fb742d2c0 100644 --- a/ui/tests/api_json/testConfiguration.php +++ b/ui/tests/api_json/testConfiguration.php @@ -44,7 +44,7 @@ class testConfiguration extends CAPITest { ], 'format' => '' ], - 'expected_error' => 'Invalid parameter "/format": value must be one of xml, json.' + 'expected_error' => 'Invalid parameter "/format": value must be one of yaml, xml, json.' ], [ 'export' => [ @@ -55,7 +55,7 @@ class testConfiguration extends CAPITest { ], 'format' => 'test' ], - 'expected_error' => 'Invalid parameter "/format": value must be one of xml, json.' + 'expected_error' => 'Invalid parameter "/format": value must be one of yaml, xml, json.' ], [ 'export' => [ @@ -213,7 +213,7 @@ class testConfiguration extends CAPITest { ], 'source' => '{"zabbix_export":{"version":"3.2","date":"2016-12-09T07:29:55Z"}}' ], - 'expected_error' => 'Invalid parameter "/format": value must be one of xml, json.' + 'expected_error' => 'Invalid parameter "/format": value must be one of yaml, xml, json.' ], [ 'import' => [ @@ -225,7 +225,7 @@ class testConfiguration extends CAPITest { ], 'source' => '{"zabbix_export":{"version":"3.2","date":"2016-12-09T07:29:55Z"}}' ], - 'expected_error' => 'Invalid parameter "/format": value must be one of xml, json.' + 'expected_error' => 'Invalid parameter "/format": value must be one of yaml, xml, json.' ], [ 'import' => [ diff --git a/ui/tests/selenium/testFormAdministrationGeneralInstallation.php b/ui/tests/selenium/testFormAdministrationGeneralInstallation.php index 6546f148731..c92a4451eef 100644 --- a/ui/tests/selenium/testFormAdministrationGeneralInstallation.php +++ b/ui/tests/selenium/testFormAdministrationGeneralInstallation.php @@ -47,10 +47,13 @@ class testFormAdministrationGeneralInstallation extends CLegacyWebTest { 'PHP gd', 'PHP gd PNG support', 'PHP gd JPEG support', + 'PHP gd GIF support', 'PHP gd FreeType support', + 'PHP LibYAML', 'PHP libxml', 'PHP xmlwriter', 'PHP xmlreader', + 'PHP LDAP', 'PHP ctype', 'PHP session', 'PHP option "session.auto_start"', -- cgit v1.2.3 From 029fae1cf7cd5e783560a9172fab11cf96c326db Mon Sep 17 00:00:00 2001 From: Ivo Kurzemnieks Date: Fri, 24 Jul 2020 16:40:03 +0300 Subject: ..F....... [ZBXNEXT-2754] fixed import delete missing message --- ui/include/views/js/conf.import.js.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/include/views/js/conf.import.js.php b/ui/include/views/js/conf.import.js.php index dd0329ac625..3bd335f6c67 100644 --- a/ui/include/views/js/conf.import.js.php +++ b/ui/include/views/js/conf.import.js.php @@ -28,7 +28,7 @@ jQuery(function($) { $('#import').click(function() { if ($('.deleteMissing:checked').length > 0) { - return confirm(); + return confirm(); } }); }); -- cgit v1.2.3 From 8c6dd74499bf62364c1ac7374b24bd4d258a1c6a Mon Sep 17 00:00:00 2001 From: Valdis Murzins Date: Fri, 24 Jul 2020 18:00:17 +0300 Subject: ..F....... [ZBXNEXT-2754] created button icon for chevron in css --- sass/stylesheets/sass/screen.scss | 47 +++++++++++++++++++++++++++++++ ui/assets/styles/blue-theme.css | 26 +++++++++++++++++ ui/assets/styles/dark-theme.css | 26 +++++++++++++++++ ui/assets/styles/hc-dark.css | 26 +++++++++++++++++ ui/assets/styles/hc-light.css | 26 +++++++++++++++++ ui/include/classes/html/CButtonExport.php | 2 +- ui/include/defines.inc.php | 1 + 7 files changed, 153 insertions(+), 1 deletion(-) diff --git a/sass/stylesheets/sass/screen.scss b/sass/stylesheets/sass/screen.scss index 6001b2fb788..846f005689e 100644 --- a/sass/stylesheets/sass/screen.scss +++ b/sass/stylesheets/sass/screen.scss @@ -7085,6 +7085,53 @@ table.preprocessing-test-results { } } +.btn-toggle-chevron { + position: relative; + + &[aria-expanded="true"] { + @include btn-hover-active($btn-font-color, $btn-bg-color); + } + + &::after { + content: ''; + position: absolute; + right: 8px; + top: calc(50% - 3px); + width: 5px; + height: 5px; + border-top: 1px solid $btn-alt-font-color; + border-right: 1px solid $btn-alt-font-color; + transform: rotate(135deg) translate(-1px,1px); + transition: transform .3s; + } + + &[disabled] { + &::after { + border-top-color: $btn-disabled-font-color; + border-right-color: $btn-disabled-font-color; + } + } + + &:enabled { + &:active, + &[aria-expanded="true"] { + &::after { + transform: rotate(315deg) translate(-1px,1px); + } + } + + &:hover, + &:focus, + &:active, + &[aria-expanded="true"] { + &::after { + border-top-color: $btn-font-color; + border-right-color: $btn-font-color; + } + } + } +} + .btn-dropdown-toggle { white-space: nowrap; overflow: hidden; diff --git a/ui/assets/styles/blue-theme.css b/ui/assets/styles/blue-theme.css index b58a428823c..8b6e847946a 100644 --- a/ui/assets/styles/blue-theme.css +++ b/ui/assets/styles/blue-theme.css @@ -5460,6 +5460,32 @@ table.preprocessing-test-results .rel-container { .btn-split li:only-child button { border-radius: 2px; } +.btn-toggle-chevron { + position: relative; } + .btn-toggle-chevron[aria-expanded="true"] { + color: #ffffff; + background-color: #02659f; + border-color: #02659f; } + .btn-toggle-chevron::after { + content: ''; + position: absolute; + right: 8px; + top: calc(50% - 3px); + width: 5px; + height: 5px; + border-top: 1px solid #0275b8; + border-right: 1px solid #0275b8; + transform: rotate(135deg) translate(-1px, 1px); + transition: transform .3s; } + .btn-toggle-chevron[disabled]::after { + border-top-color: #acbbc2; + border-right-color: #acbbc2; } + .btn-toggle-chevron:enabled:active::after, .btn-toggle-chevron:enabled[aria-expanded="true"]::after { + transform: rotate(315deg) translate(-1px, 1px); } + .btn-toggle-chevron:enabled:hover::after, .btn-toggle-chevron:enabled:focus::after, .btn-toggle-chevron:enabled:active::after, .btn-toggle-chevron:enabled[aria-expanded="true"]::after { + border-top-color: #ffffff; + border-right-color: #ffffff; } + .btn-dropdown-toggle { white-space: nowrap; overflow: hidden; diff --git a/ui/assets/styles/dark-theme.css b/ui/assets/styles/dark-theme.css index d65b234023e..62e0d1eec8a 100644 --- a/ui/assets/styles/dark-theme.css +++ b/ui/assets/styles/dark-theme.css @@ -5471,6 +5471,32 @@ table.preprocessing-test-results .rel-container { .btn-split li:only-child button { border-radius: 2px; } +.btn-toggle-chevron { + position: relative; } + .btn-toggle-chevron[aria-expanded="true"] { + color: #f2f2f2; + background-color: #5e737e; + border-color: #5e737e; } + .btn-toggle-chevron::after { + content: ''; + position: absolute; + right: 8px; + top: calc(50% - 3px); + width: 5px; + height: 5px; + border-top: 1px solid #768d99; + border-right: 1px solid #768d99; + transform: rotate(135deg) translate(-1px, 1px); + transition: transform .3s; } + .btn-toggle-chevron[disabled]::after { + border-top-color: #525252; + border-right-color: #525252; } + .btn-toggle-chevron:enabled:active::after, .btn-toggle-chevron:enabled[aria-expanded="true"]::after { + transform: rotate(315deg) translate(-1px, 1px); } + .btn-toggle-chevron:enabled:hover::after, .btn-toggle-chevron:enabled:focus::after, .btn-toggle-chevron:enabled:active::after, .btn-toggle-chevron:enabled[aria-expanded="true"]::after { + border-top-color: #f2f2f2; + border-right-color: #f2f2f2; } + .btn-dropdown-toggle { white-space: nowrap; overflow: hidden; diff --git a/ui/assets/styles/hc-dark.css b/ui/assets/styles/hc-dark.css index 15925c1d9eb..6723d617323 100644 --- a/ui/assets/styles/hc-dark.css +++ b/ui/assets/styles/hc-dark.css @@ -5415,6 +5415,32 @@ table.preprocessing-test-results .rel-container { .btn-split li:only-child button { border-radius: 2px; } +.btn-toggle-chevron { + position: relative; } + .btn-toggle-chevron[aria-expanded="true"] { + color: #333333; + background-color: lightgray; + border-color: lightgray; } + .btn-toggle-chevron::after { + content: ''; + position: absolute; + right: 8px; + top: calc(50% - 3px); + width: 5px; + height: 5px; + border-top: 1px solid #ffffff; + border-right: 1px solid #ffffff; + transform: rotate(135deg) translate(-1px, 1px); + transition: transform .3s; } + .btn-toggle-chevron[disabled]::after { + border-top-color: #7d7d7d; + border-right-color: #7d7d7d; } + .btn-toggle-chevron:enabled:active::after, .btn-toggle-chevron:enabled[aria-expanded="true"]::after { + transform: rotate(315deg) translate(-1px, 1px); } + .btn-toggle-chevron:enabled:hover::after, .btn-toggle-chevron:enabled:focus::after, .btn-toggle-chevron:enabled:active::after, .btn-toggle-chevron:enabled[aria-expanded="true"]::after { + border-top-color: #333333; + border-right-color: #333333; } + .btn-dropdown-toggle { white-space: nowrap; overflow: hidden; diff --git a/ui/assets/styles/hc-light.css b/ui/assets/styles/hc-light.css index e0051c0f9d3..cac713f2a9f 100644 --- a/ui/assets/styles/hc-light.css +++ b/ui/assets/styles/hc-light.css @@ -5415,6 +5415,32 @@ table.preprocessing-test-results .rel-container { .btn-split li:only-child button { border-radius: 2px; } +.btn-toggle-chevron { + position: relative; } + .btn-toggle-chevron[aria-expanded="true"] { + color: #ffffff; + background-color: #484848; + border-color: #484848; } + .btn-toggle-chevron::after { + content: ''; + position: absolute; + right: 8px; + top: calc(50% - 3px); + width: 5px; + height: 5px; + border-top: 1px solid #000000; + border-right: 1px solid #000000; + transform: rotate(135deg) translate(-1px, 1px); + transition: transform .3s; } + .btn-toggle-chevron[disabled]::after { + border-top-color: #999999; + border-right-color: #999999; } + .btn-toggle-chevron:enabled:active::after, .btn-toggle-chevron:enabled[aria-expanded="true"]::after { + transform: rotate(315deg) translate(-1px, 1px); } + .btn-toggle-chevron:enabled:hover::after, .btn-toggle-chevron:enabled:focus::after, .btn-toggle-chevron:enabled:active::after, .btn-toggle-chevron:enabled[aria-expanded="true"]::after { + border-top-color: #ffffff; + border-right-color: #ffffff; } + .btn-dropdown-toggle { white-space: nowrap; overflow: hidden; diff --git a/ui/include/classes/html/CButtonExport.php b/ui/include/classes/html/CButtonExport.php index 3b993eca24c..093efb78a45 100644 --- a/ui/include/classes/html/CButtonExport.php +++ b/ui/include/classes/html/CButtonExport.php @@ -49,7 +49,7 @@ class CButtonExport extends CList { ), (new CButton('export', '​')) ->addClass(ZBX_STYLE_BTN_ALT) - ->addClass(ZBX_STYLE_BTN_TOGGLE) + ->addClass(ZBX_STYLE_BTN_TOGGLE_CHEVRON) ->setMenuPopup([ 'type' => 'dropdown', 'data' => [ diff --git a/ui/include/defines.inc.php b/ui/include/defines.inc.php index 13441b83574..87b3fa844ac 100644 --- a/ui/include/defines.inc.php +++ b/ui/include/defines.inc.php @@ -1567,6 +1567,7 @@ define('ZBX_STYLE_ARROW_UP', 'arrow-up'); define('ZBX_STYLE_BLUE', 'blue'); define('ZBX_STYLE_BTN_ADD_FAV', 'btn-add-fav'); define('ZBX_STYLE_BTN_ALT', 'btn-alt'); +define('ZBX_STYLE_BTN_TOGGLE_CHEVRON', 'btn-toggle-chevron'); define('ZBX_STYLE_BTN_SPLIT', 'btn-split'); define('ZBX_STYLE_BTN_TOGGLE', 'btn-dropdown-toggle'); define('ZBX_STYLE_BTN_BACK_MAP', 'btn-back-map'); -- cgit v1.2.3 From 322053e9c36b14aa60566d65963cf59de73abe5f Mon Sep 17 00:00:00 2001 From: Ivo Kurzemnieks Date: Fri, 24 Jul 2020 18:33:10 +0300 Subject: A.F....... [ZBXNEXT-2754] added usage of configuration.export API in export controller, added error message when library is missing and added pretty print for JSON --- ui/app/controllers/CControllerExport.php | 43 ++++++++---------- ui/include/classes/api/services/CConfiguration.php | 53 +++++++++++++++++++++- .../classes/export/writers/CJsonExportWriter.php | 8 +++- 3 files changed, 78 insertions(+), 26 deletions(-) diff --git a/ui/app/controllers/CControllerExport.php b/ui/app/controllers/CControllerExport.php index 50a659165ba..37bd77df536 100644 --- a/ui/app/controllers/CControllerExport.php +++ b/ui/app/controllers/CControllerExport.php @@ -64,31 +64,35 @@ class CControllerExport extends CController { protected function doAction() { $action = $this->getInput('action'); - $format = $this->getInput('format', CExportWriterFactory::YAML); + $params = [ + 'format' => $this->getInput('format', CExportWriterFactory::YAML), + 'prettyprint' => true, + 'options' => [] + ]; switch ($action) { case 'export.valuemaps': - $export = new CConfigurationExport(['valueMaps' => $this->getInput('valuemapids', [])]); + $params['options']['valueMaps'] = $this->getInput('valuemapids', []); break; case 'export.hosts': - $export = new CConfigurationExport(['hosts' => $this->getInput('hosts', [])]); + $params['options']['hosts'] = $this->getInput('hosts', []); break; case 'export.mediatypes': - $export = new CConfigurationExport(['mediaTypes' => $this->getInput('mediatypeids', [])]); + $params['options']['mediaTypes'] = $this->getInput('mediatypeids', []); break; case 'export.screens': - $export = new CConfigurationExport(['screens' => $this->getInput('screens', [])]); + $params['options']['screens'] = $this->getInput('screens', []); break; case 'export.sysmaps': - $export = new CConfigurationExport(['maps' => $this->getInput('maps', [])]); + $params['options']['maps'] = $this->getInput('maps', []); break; case 'export.templates': - $export = new CConfigurationExport(['templates' => $this->getInput('templates', [])]); + $params['options']['templates'] = $this->getInput('templates', []); break; default: @@ -97,26 +101,19 @@ class CControllerExport extends CController { return; } - $export->setBuilder(new CConfigurationExportBuilder()); - $export->setWriter(CExportWriterFactory::getWriter($format)); - - $export_data = $export->export(); - - if ($export_data === false) { - // Access denied. - - $response = new CControllerResponseRedirect( - $this->getInput('backurl', 'zabbix.php?action=dashboard.view')); + $result = API::Configuration()->export($params); - $response->setMessageError(_('No permissions to referred object or it does not exist!')); - } - else { + if ($result) { $response = new CControllerResponseData([ - 'main_block' => $export_data, - 'mime_type' => CExportWriterFactory::getMimeType($format), - 'page' => ['file' => 'zbx_export_'.substr($action, 7).'.'.$format] + 'main_block' => $result, + 'mime_type' => CExportWriterFactory::getMimeType($params['format']), + 'page' => ['file' => 'zbx_export_'.substr($action, 7).'.'.$params['format']] ]); } + else { + $response = new CControllerResponseRedirect($this->getInput('backurl', 'zabbix.php?action=dashboard.view')); + $response->setMessageError(_('Export failed')); + } $this->setResponse($response); } diff --git a/ui/include/classes/api/services/CConfiguration.php b/ui/include/classes/api/services/CConfiguration.php index 45efc60fb02..f88b0940205 100644 --- a/ui/include/classes/api/services/CConfiguration.php +++ b/ui/include/classes/api/services/CConfiguration.php @@ -32,6 +32,7 @@ class CConfiguration extends CApiService { public function export(array $params) { $api_input_rules = ['type' => API_OBJECT, 'fields' => [ 'format' => ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED, 'in' => implode(',', [CExportWriterFactory::YAML, CExportWriterFactory::XML, CExportWriterFactory::JSON])], + 'prettyprint' => ['type' => API_BOOLEAN, 'default' => false], 'options' => ['type' => API_OBJECT, 'flags' => API_REQUIRED, 'fields' => [ 'groups' => ['type' => API_IDS], 'hosts' => ['type' => API_IDS], @@ -47,10 +48,34 @@ class CConfiguration extends CApiService { self::exception(ZBX_API_ERROR_PARAMETERS, $error); } + switch ($params['format']) { + case CExportWriterFactory::YAML: + $lib_yaml = (new CFrontendSetup())->checkPhpLibYAML(); + + if ($lib_yaml['result'] == CFrontendSetup::CHECK_FATAL) { + self::exception(ZBX_API_ERROR_INTERNAL, $lib_yaml['error']); + } + break; + + case CExportWriterFactory::XML: + $lib_xml = (new CFrontendSetup())->checkPhpLibxml(); + + if ($lib_xml['result'] == CFrontendSetup::CHECK_FATAL) { + self::exception(ZBX_API_ERROR_INTERNAL, $lib_xml['error']); + } + + $xml_writer = (new CFrontendSetup())->checkPhpXmlWriter(); + + if ($xml_writer['result'] == CFrontendSetup::CHECK_FATAL) { + self::exception(ZBX_API_ERROR_INTERNAL, $xml_writer['error']); + } + break; + } + $export = new CConfigurationExport($params['options']); $export->setBuilder(new CConfigurationExportBuilder()); $writer = CExportWriterFactory::getWriter($params['format']); - $writer->formatOutput(false); + $writer->formatOutput($params['prettyprint']); $export->setWriter($writer); $export_data = $export->export(); @@ -69,7 +94,7 @@ class CConfiguration extends CApiService { */ public function import($params) { $api_input_rules = ['type' => API_OBJECT, 'fields' => [ - 'format' => ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED, 'in' => implode(',', [CExportWriterFactory::YAML, CImportReaderFactory::XML, CImportReaderFactory::JSON])], + 'format' => ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED, 'in' => implode(',', [CImportReaderFactory::YAML, CImportReaderFactory::XML, CImportReaderFactory::JSON])], 'source' => ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED], 'rules' => ['type' => API_OBJECT, 'flags' => API_REQUIRED, 'fields' => [ 'applications' => ['type' => API_OBJECT, 'fields' => [ @@ -147,6 +172,30 @@ class CConfiguration extends CApiService { self::exception(ZBX_API_ERROR_PARAMETERS, $error); } + switch ($params['format']) { + case CImportReaderFactory::YAML: + $lib_yaml = (new CFrontendSetup())->checkPhpLibYAML(); + + if ($lib_yaml['result'] == CFrontendSetup::CHECK_FATAL) { + self::exception(ZBX_API_ERROR_INTERNAL, $lib_yaml['error']); + } + break; + + case CImportReaderFactory::XML: + $lib_xml = (new CFrontendSetup())->checkPhpLibxml(); + + if ($lib_xml['result'] == CFrontendSetup::CHECK_FATAL) { + self::exception(ZBX_API_ERROR_INTERNAL, $lib_xml['error']); + } + + $xml_reader = (new CFrontendSetup())->checkPhpXmlReader(); + + if ($xml_reader['result'] == CFrontendSetup::CHECK_FATAL) { + self::exception(ZBX_API_ERROR_INTERNAL, $xml_reader['error']); + } + break; + } + $importReader = CImportReaderFactory::getReader($params['format']); $data = $importReader->read($params['source']); diff --git a/ui/include/classes/export/writers/CJsonExportWriter.php b/ui/include/classes/export/writers/CJsonExportWriter.php index 3c2d530b36b..562b7dc4b75 100644 --- a/ui/include/classes/export/writers/CJsonExportWriter.php +++ b/ui/include/classes/export/writers/CJsonExportWriter.php @@ -32,6 +32,12 @@ class CJsonExportWriter extends CExportWriter { * @return string */ public function write(array $array) { - return json_encode($array, JSON_UNESCAPED_SLASHES); + $options = JSON_UNESCAPED_SLASHES; + + if ($this->formatOutput) { + $options |= JSON_PRETTY_PRINT; + } + + return json_encode($array, $options); } } -- cgit v1.2.3 From 329e84632761ce3fc981e3b9d533661868136caa Mon Sep 17 00:00:00 2001 From: Ivo Kurzemnieks Date: Fri, 24 Jul 2020 19:02:06 +0300 Subject: A......... [ZBXNEXT-2754] added special validation if yaml files contain gibberish --- ui/include/classes/import/readers/CYamlImportReader.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ui/include/classes/import/readers/CYamlImportReader.php b/ui/include/classes/import/readers/CYamlImportReader.php index 3eb5b398a78..8aad995f897 100644 --- a/ui/include/classes/import/readers/CYamlImportReader.php +++ b/ui/include/classes/import/readers/CYamlImportReader.php @@ -47,6 +47,16 @@ class CYamlImportReader extends CImportReader { restore_error_handler(); + /* + * Unfortunately yaml_parse() not always returns FALSE. If file is empty, it returns NULL and if file contains + * gibberish and not a "zabbix_export" array, $data contains same input string, but Import Validator expects + * $data to be an array. Create a custom error message for these cases. + */ + if (!is_array($data) && $data !== false) { + $data = false; + $error = _('Invalid file content'); + } + if ($data === false) { throw new ErrorException(_s('Cannot read YAML: %1$s.', $error)); } -- cgit v1.2.3 From dc707c61ebcf0702c2cdd02bf69b29b3b0964bc5 Mon Sep 17 00:00:00 2001 From: Anton Fayantsev Date: Fri, 31 Jul 2020 10:00:25 +0300 Subject: .........T [ZBX-17785] fixed ChangeLog entry --- ChangeLog.d/bugfix/ZBX-17785 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog.d/bugfix/ZBX-17785 b/ChangeLog.d/bugfix/ZBX-17785 index 926447cca5d..681bce76661 100644 --- a/ChangeLog.d/bugfix/ZBX-17785 +++ b/ChangeLog.d/bugfix/ZBX-17785 @@ -1 +1 @@ -.........T [ZBX-11785] fixed dbstat query for postgresql v12 (afayantsev) +.........T [ZBX-17785] fixed dbstat query for postgresql v12 (afayantsev) -- cgit v1.2.3 From c81ecb38372362b7ac3619d96dc7f0fa134dfd49 Mon Sep 17 00:00:00 2001 From: Yulia Chukina Date: Mon, 3 Aug 2020 13:30:44 +0300 Subject: .........T [ZBXNEXT-6010] fixed readme file --- templates/db/oracle_odbc/README.md | 11 +++++++---- templates/db/oracle_odbc/template_db_oracle_odbc.xml | 6 +++--- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/templates/db/oracle_odbc/README.md b/templates/db/oracle_odbc/README.md index d946291297f..18329f77249 100644 --- a/templates/db/oracle_odbc/README.md +++ b/templates/db/oracle_odbc/README.md @@ -3,7 +3,7 @@ ## Overview -For Zabbix version: 5.0 +For Zabbix version: 5.0 The template is developed for monitoring DBMS Oracle Database single instance via ODBC. This template was tested on: @@ -58,12 +58,15 @@ DSN = $ORACLE.DSN isql $TNS_NAME $DB_USER $DB_PASSWORD ``` -5. If result succesful (fix the mistakes in odbc.ini if not), configure zabbix-server for Oracle ENV Usage or zabbix-proxy if you use proxy for Oracle DB monitoring +5. Сonfigure zabbix-serve or zabbix-proxy for Oracle ENV Usage. Edit or add new file: + Edit or add new file /etc/sysconfig/zabbix-server # for server + /etc/sysconfig/zabbix-proxy # for proxy - Add + + Then, add: ``` export ORACLE_HOME=/usr/lib/oracle/19.6/client64 export PATH=$PATH:$ORACLE_HOME/bin @@ -218,7 +221,7 @@ There are no template links in this template. |Zabbix_raw_items |Oracle: Get CDB and No-CDB info |

Get info about CDB and No-CDB databases on instansce.

|ODBC |db.odbc.get[get_cdb_info,"{$ORACLE.DSN}"]

**Expression**:

`SELECT name as DBNAME, DECODE(open_mode, 'MOUNTED', 1, 'READ ONLY', 2, 'READ WRITE', 3, 'READ ONLY WITH APPLY', 4, 'MIGRATE', 5, 0) AS open_mode, DECODE(database_role, 'SNAPSHOT STANDBY', 1, 'LOGICAL STANDBY', 2, 'PHYSICAL STANDBY', 3, 'PRIMARY', 4, 'FAR SYNC', 5, 0) AS ROLE, DECODE(force_logging, 'YES',1,'NO',0,0) AS force_logging, DECODE(log_mode, 'MANUAL',2 ,'ARCHIVELOG',1,'NOARCHIVELOG',0,0) AS log_mode FROM v$database ` | |Zabbix_raw_items |Oracle: Get PDB info |

Get info about PDB databases on instansce.

|ODBC |db.odbc.get[get_pdb_info,"{$ORACLE.DSN}"]

**Expression**:

`SELECT name as DBNAME, DECODE(open_mode, 'MOUNTED', 1, 'READ ONLY', 2, 'READ WRITE', 3, 'READ ONLY WITH APPLY', 4, 'MIGRATE', 5, 0) AS open_mode FROM v$pdbs; ` | |Zabbix_raw_items |Oracle: Get archive log info | |ODBC |db.odbc.get[get_archivelog_stat,"{$ORACLE.DSN}"]

**Expression**:

`SELECT d.dest_name, DECODE (d.status, 'VALID',3, 'DEFERRED', 2, 'ERROR', 1, 0) AS status, d.log_sequence, d.error FROM v$archive_dest d , v$database db WHERE d.status != 'INACTIVE' AND db.log_mode = 'ARCHIVELOG'; ` | -|Zabbix_raw_items |Oracle: Get ASM stats |

Get ASM disk groups stats.

|ODBC |db.odbc.get[get_asm_stat,"{$ORACLE.DSN}"]

**Expression**:

`SELECT name AS dg_name, ROUND(total_mb / DECODE(TYPE, 'NORMAL', 2, 'HIGH', 3, 'EXTERN', 1)*1024) AS size_byte, ROUND(usable_file_mb *1024 ) AS free_size_byte, ROUND(100-(usable_file_mb /(total_mb / DECODE(TYPE, 'NORMAL', 2, 'HIGH', 3, 'EXTERN', 1)))* 100, 2) AS used_percent FROM v$asm_diskgroup ; ` | +|Zabbix_raw_items |Oracle: Get ASM stats |

Get ASM disk groups stats.

|ODBC |db.odbc.get[get_asm_stat,"{$ORACLE.DSN}"]

**Expression**:

`SELECT name AS dg_name, ROUND(total_mb / DECODE(TYPE, 'NORMAL', 2, 'HIGH', 3, 'EXTERN', 1)*1024*1024) AS size_byte, ROUND(usable_file_mb*1024*1024 ) AS free_size_byte, ROUND(100-(usable_file_mb /(total_mb / DECODE(TYPE, 'NORMAL', 2, 'HIGH', 3, 'EXTERN', 1)))* 100, 2) AS used_percent FROM v$asm_diskgroup ; ` | ## Triggers diff --git a/templates/db/oracle_odbc/template_db_oracle_odbc.xml b/templates/db/oracle_odbc/template_db_oracle_odbc.xml index 75ca4a08609..e78ec821227 100644 --- a/templates/db/oracle_odbc/template_db_oracle_odbc.xml +++ b/templates/db/oracle_odbc/template_db_oracle_odbc.xml @@ -1,7 +1,7 @@ 5.0 - 2020-07-30T11:20:49Z + 2020-08-03T10:27:51Z Templates/Databases @@ -68,8 +68,8 @@ WHERE d.status != 'INACTIVE' AND db.log_mode = 'ARCHIVELOG'; TEXT SELECT name AS dg_name, -ROUND(total_mb / DECODE(TYPE, 'NORMAL', 2, 'HIGH', 3, 'EXTERN', 1)*1024) AS size_byte, -ROUND(usable_file_mb *1024 ) AS free_size_byte, +ROUND(total_mb / DECODE(TYPE, 'NORMAL', 2, 'HIGH', 3, 'EXTERN', 1)*1024*1024) AS size_byte, +ROUND(usable_file_mb*1024*1024 ) AS free_size_byte, ROUND(100-(usable_file_mb /(total_mb / DECODE(TYPE, 'NORMAL', 2, 'HIGH', 3, 'EXTERN', 1)))* 100, 2) AS used_percent FROM v$asm_diskgroup ; {$ORACLE.USER} -- cgit v1.2.3 From afb6d977f2f3f190d397ff98cd895392e77586f9 Mon Sep 17 00:00:00 2001 From: Natalja Karpinska Date: Mon, 3 Aug 2020 16:19:42 +0300 Subject: .......... [ZBXNEXT-2754] added api tests for yaml format --- ui/tests/api_json/data/data_test.sql | 2 +- ui/tests/api_json/testConfiguration.php | 276 +++++++++++++++++++++++++++----- 2 files changed, 235 insertions(+), 43 deletions(-) diff --git a/ui/tests/api_json/data/data_test.sql b/ui/tests/api_json/data/data_test.sql index 952aeee3428..1c818f6d4b5 100644 --- a/ui/tests/api_json/data/data_test.sql +++ b/ui/tests/api_json/data/data_test.sql @@ -242,7 +242,7 @@ INSERT INTO interface (interfaceid, hostid, main, type, useip, ip, dns, port) VA INSERT INTO hosts (hostid, host, status, description) VALUES (99003, 'Api active proxy in action', 5, ''); INSERT INTO hosts (hostid, host, status, description) VALUES (99004, 'Api active proxy with host', 5, ''); INSERT INTO hosts (hostid, proxy_hostid, host, name, status, description) VALUES (99005, 99004,'API Host monitored with proxy', 'API Host monitored with proxy', 0, ''); -INSERT INTO interface (interfaceid,hostid,main,type,useip,ip,dns,port) values (99003,99004,1,1,1,'127.0.0.1','','10050'); +INSERT INTO interface (interfaceid,hostid,main,type,useip,ip,dns,port) values (99003,99005,1,1,1,'127.0.0.1','','10050'); INSERT INTO actions (actionid, name, eventsource, evaltype, status, esc_period) VALUES (90, 'API action with proxy', 1, 0, 0, '1h'); INSERT INTO operations (operationid, actionid, operationtype, esc_period, esc_step_from, esc_step_to, evaltype) VALUES (90, 90, 0, 0, 1, 1, 0); INSERT INTO opmessage (operationid, default_msg, subject, message, mediatypeid) VALUES (90, 0, 'Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}', 'Discovery rule: {DISCOVERY.RULE.NAME}', NULL); diff --git a/ui/tests/api_json/testConfiguration.php b/ui/tests/api_json/testConfiguration.php index 49fb742d2c0..31da167fb8e 100644 --- a/ui/tests/api_json/testConfiguration.php +++ b/ui/tests/api_json/testConfiguration.php @@ -25,12 +25,13 @@ class testConfiguration extends CAPITest { public static function export_fail_data() { return [ + // Check format parameter. [ 'export' => [ 'options' => [ 'hosts' => [ '50009' - ], + ] ] ], 'expected_error' => 'Invalid parameter "/": the parameter "format" is missing.' @@ -40,7 +41,7 @@ class testConfiguration extends CAPITest { 'options' => [ 'hosts' => [ '50009' - ], + ] ], 'format' => '' ], @@ -51,18 +52,19 @@ class testConfiguration extends CAPITest { 'options' => [ 'hosts' => [ '50009' - ], + ] ], - 'format' => 'test' + 'format' => 'æų' ], 'expected_error' => 'Invalid parameter "/format": value must be one of yaml, xml, json.' ], + // Check unexpected parameter. [ 'export' => [ 'options' => [ 'groups' => [ '50012' - ], + ] ], 'format' => 'test', 'hosts' => '50009' @@ -80,18 +82,70 @@ class testConfiguration extends CAPITest { ], 'expected_error' => 'Invalid parameter "/options": unexpected parameter "applications".' ], + [ + 'export' => [ + 'options' => [ + 'groups' => [ + '50009' + ], + 'group' => [ + '50009' + ] + ], + 'format' => 'xml' + ], + 'expected_error' => 'Invalid parameter "/options": unexpected parameter "group".' + ], + // Check missing options parameter. [ 'export' => [ 'format' => 'xml' ], 'expected_error' => 'Invalid parameter "/": the parameter "options" is missing.' + ], + // Check prettyprint parameter. + [ + 'export' => [ + 'options' => [ + 'groups' => [ + '50012' + ] + ], + 'format' => 'yaml', + 'prettyprint' => 'test' + ], + 'expected_error' => 'Invalid parameter "/prettyprint": a boolean is expected.' + ], + [ + 'export' => [ + 'options' => [ + 'groups' => [ + '50012' + ] + ], + 'format' => 'json', + 'prettyprint' => '' + ], + 'expected_error' => 'Invalid parameter "/prettyprint": a boolean is expected.' + ], + [ + 'export' => [ + 'options' => [ + 'groups' => [ + '50012' + ] + ], + 'format' => 'yaml', + 'prettyprint' => 'æų' + ], + 'expected_error' => 'Invalid parameter "/prettyprint": a boolean is expected.' ] ]; } /** - * @dataProvider export_fail_data - */ + * @dataProvider export_fail_data + */ public function testConfiguration_ExportFail($export, $expected_error) { $this->call('configuration.export', $export, $expected_error); } @@ -109,10 +163,10 @@ class testConfiguration extends CAPITest { } /** - * @dataProvider export_string_ids - */ + * @dataProvider export_string_ids + */ public function testConfiguration_ExportIdsNotNumber($options) { - $formats = ['xml', 'json']; + $formats = ['xml', 'json', 'yaml']; foreach ($formats as $parameter){ $this->call('configuration.export', @@ -120,7 +174,7 @@ class testConfiguration extends CAPITest { 'options' => [ $options => [ $options - ], + ] ], 'format' => $parameter ], @@ -132,40 +186,91 @@ class testConfiguration extends CAPITest { public static function export_success_data() { return [ [ - ['groups' => ['50012']] + [ + 'options' => [ + 'groups' => [] + ], + 'prettyprint' => true + ] + ], + [ + [ + 'options' => [ + 'groups' => ['11111111111111'] + ], + 'prettyprint' => true + ] ], [ - ['hosts' => ['50009']] + [ + 'options' => [ + 'groups' => ['50012'] + ], + 'prettyprint' => true + ] ], [ - ['images' => ['1']] + [ + 'options' => [ + 'hosts' => ['50009'] + ], + 'prettyprint' => false + ] + ], + [ + [ + 'options' => [ + 'groups' => ['50012'], + 'hosts' => ['50009'] + ] + ] ], [ - ['maps' => ['1']] + [ + 'options' => [ + 'images' => ['1'] + ] + ] ], [ - ['screens' => ['3']] + [ + 'options' => [ + 'maps' => ['1'] + ] + ] ], [ - ['templates' => ['10069']] + [ + 'options' => [ + 'screens' => ['3'] + ] + ] ], [ - ['valueMaps' => ['1']] + [ + 'options' => [ + 'templates' => ['10069'] + ] + ] ], + [ + [ + 'options' => [ + 'valueMaps' => ['1'] + ] + ] + ] ]; } /** - * @dataProvider export_success_data - */ + * @dataProvider export_success_data + */ public function testConfiguration_ExportSuccess($data) { - $formats = ['xml', 'json']; + $formats = ['xml', 'json', 'yaml']; - foreach ($formats as $parameter){ - $this->call('configuration.export', [ - 'options' => $data, - 'format' => $parameter - ]); + foreach ($formats as $parameter) { + $this->call('configuration.export', array_merge($data, ['format' => $parameter])); } } @@ -240,6 +345,19 @@ class testConfiguration extends CAPITest { ], 'expected_error' => 'Invalid parameter "/": unexpected parameter "hosts".' ], + [ + 'import' => [ + 'format' => 'json', + 'rules' => [ + 'groups' => [ + 'createMissing' => true + ] + ], + 'source' => '{"zabbix_export":{"version":"3.2","date":"2016-12-09T07:29:55Z"}}', + 'prettyprint' => true + ], + 'expected_error' => 'Invalid parameter "/": unexpected parameter "prettyprint".' + ], // Check rules. [ 'import' => [ @@ -290,8 +408,8 @@ class testConfiguration extends CAPITest { } /** - * @dataProvider import_fail_data - */ + * @dataProvider import_fail_data + */ public function testConfiguration_ImportFail($import, $expected_error) { $this->call('configuration.import', $import, $expected_error); } @@ -377,8 +495,8 @@ class testConfiguration extends CAPITest { } /** - * @dataProvider import_rules_parameters - */ + * @dataProvider import_rules_parameters + */ public function testConfiguration_ImportBooleanTypeAndUnexpectedParameters($import) { foreach ($import['expected'] as $expected) { $this->call('configuration.import', [ @@ -413,12 +531,12 @@ class testConfiguration extends CAPITest { return [ [[ 'format' => 'xml', - 'source' => '' , + 'source' => '', 'error' => 'Cannot read XML: XML is empty.' ]], [[ 'format' => 'xml', - 'source' => 'test' , + 'source' => 'test', 'error' => 'Cannot read XML: (4) Start tag expected, \'<\' not found [Line: 1 | Column: 1].' ]], [[ @@ -430,7 +548,7 @@ class testConfiguration extends CAPITest { [[ 'format' => 'xml', 'source' => ' - 2016-12-09T07:12:45Z' , + 2016-12-09T07:12:45Z', 'error' => 'Invalid tag "/zabbix_export/version": unsupported version number.' ]], [[ @@ -440,45 +558,92 @@ class testConfiguration extends CAPITest { // can be different error message text 'error_contains' => 'Cannot read XML:' ]], + // JSON format. [[ 'format' => 'json', - 'source' => '' , + 'source' => '', // can be different error message text 'Cannot read JSON: Syntax error.' or 'Cannot read JSON: No error.' 'error_contains' => 'Cannot read JSON: ' ]], [[ 'format' => 'json', - 'source' => 'test' , + 'source' => 'test', // can be different error message text 'Cannot read JSON: Syntax error.' or 'Cannot read JSON: boolean expected.' 'error_contains' => 'Cannot read JSON: ' ]], [[ 'format' => 'json', - 'source' => '{"zabbix_export":{"date":"2016-12-09T07:29:55Z"}}' , + 'source' => '{"zabbix_export":{"date":"2016-12-09T07:29:55Z"}}', 'error' => 'Invalid tag "/zabbix_export": the tag "version" is missing.' ]], [[ 'format' => 'json', - 'source' => '{"zabbix_export":{"version":"","date":"2016-12-09T07:29:55Z"}}' , + 'source' => '{"zabbix_export":{"version":"","date":"2016-12-09T07:29:55Z"}}', 'error' => 'Invalid tag "/zabbix_export/version": unsupported version number.' ]], [[ 'format' => 'json', - 'source' => '{"export":{"version":"3.2","date":"2016-12-09T07:29:55Z"}}' , + 'source' => '{"export":{"version":"3.2","date":"2016-12-09T07:29:55Z"}}', 'error' => 'Invalid tag "/": unexpected tag "export".' ]], [[ 'format' => 'json', - 'source' => '{"export":{"version":"3.2","date":"2016-12-09T07:29:55Z"}' , + 'source' => '{"zabbix_export":{"version":"3.2","date":"2016-12-09T07:29:55Z"}', // can be different error message text 'Cannot read JSON: Syntax error.' or 'Cannot read JSON: unexpected end of data.' 'error_contains' => 'Cannot read JSON: ' - ]] + ]], + // YAML format. + [[ + 'format' => 'yaml', + 'source' => '', + 'error_contains' => 'Cannot read YAML: Invalid file content.' + ]], + [[ + 'format' => 'yaml', + 'source' => 'æų', + 'error_contains' => 'Cannot read YAML: Invalid file content.' + ]], + [[ + 'format' => 'yaml', + 'source' => "---\nzabbix_export:\n date: \"2020-07-27T12:58:01Z\"\n", + 'error' => 'Invalid tag "/zabbix_export": the tag "version" is missing.' + ]], + [[ + 'format' => 'yaml', + 'source' => "---\nzabbix_export:\n version: \"5.0\"\ndate: \"2020-07-27T12:58:01Z\"\n", + 'error' => 'Invalid tag "/": unexpected tag "date".' + ]], + [[ + 'format' => 'yaml', + 'source' => "---\nzabbix_export:\n version: \"\"\n date: \"2020-07-27T12:58:01Z\"\n", + 'error' => 'Invalid tag "/zabbix_export/version": unsupported version number.' + ]], + [[ + 'format' => 'yaml', + 'source' => "---\nexport:\n version: \"4.0\"\n date: \"2020-08-03T11:38:33Z\"\n...\n", + 'error' => 'Invalid tag "/": unexpected tag "export".' + ]], + [[ + 'format' => 'yaml', + 'source' => '---\nzabbix_export:\n version: \"4.0\"\n date: \"2020-08-03T11:38:33Z', + 'error_contains' => 'Cannot read YAML: scanning error encountered during parsing' + ]], + [[ + 'format' => 'yaml', + 'source' => '\n5.02020-08-03T12:36:11Z\n', + 'error' => 'Cannot read YAML: Invalid file content.' + ]], + [[ + 'format' => 'yaml', + 'source' => '{\"zabbix_export\":{\"version\":\"5.0\",\"date\":\"2020-08-03T12:36:39Z\"}}', + 'error' => 'Cannot read YAML: scanning error encountered during parsing: found unexpected \':\' (line 1, column 19), context while scanning a plain scalar (line 1, column 2).' + ]], ]; } /** - * @dataProvider import_source - */ + * @dataProvider import_source + */ public function testConfiguration_ImportInvalidSource($data) { $result = $this->call('configuration.import', [ 'format' => $data['format'], @@ -524,6 +689,12 @@ class testConfiguration extends CAPITest { 'source' => '{"zabbix_export":{"version":"3.2","date":"2016-12-09T12:29:57Z","groups":[{"name":"API host group json import"}]}}', 'sql' => 'select * from hstgrp where name=\'API host group json import\'' ], + [ + 'format' => 'yaml', + 'parameter' => 'groups', + 'source' => "---\nzabbix_export:\n version: \"4.0\"\n date: \"2020-08-03T12:41:17Z\"\n groups:\n - name: API host group yaml import\n...\n", + 'sql' => 'select * from hstgrp where name=\'API host group yaml import\'' + ], [ 'format' => 'xml', 'parameter' => 'screens', @@ -548,6 +719,13 @@ class testConfiguration extends CAPITest { . '"hsize":"1","vsize":"1"}]}}', 'sql' => 'select * from screens where name=\'API screen json import\'' ], + [ + 'format' => 'yaml', + 'parameter' => 'screens', + 'source' => "---\nzabbix_export:\n version: \"4.0\"\n date: \"2020-08-03T12:44:35Z\"\n". + " screens:\n - name: API screen yaml import\n hsize: \"1\"\n vsize: \"1\"\n screen_items: []\n...\n", + 'sql' => 'select * from screens where name=\'API screen yaml import\'' + ], [ 'format' => 'xml', 'parameter' => 'valueMaps', @@ -575,6 +753,13 @@ class testConfiguration extends CAPITest { 'source' => '{"zabbix_export":{"version":"3.2","date":"2016-12-12T07:18:00Z","value_maps":[{"name":"API valueMap json import",' . '"mappings":[{"value":"1","newvalue":"Up"}]}]}}', 'sql' => 'select * from valuemaps where name=\'API valueMap json import\'' + ], + [ + 'format' => 'yaml', + 'parameter' => 'valueMaps', + 'source' => "---\nzabbix_export:\n version: \"4.0\"\n date: \"2020-08-03T12:47:05Z\"\n". + " value_maps:\n - name: API valueMap yaml import\n mappings:\n - value: One\n newvalue: Up\n...\n", + 'sql' => 'select * from valuemaps where name=\'API valueMap yaml import\'' ] ]; } @@ -623,6 +808,13 @@ class testConfiguration extends CAPITest { 'sql' => 'select * from hstgrp where name=\'API host group json import as non Super Admin\'', 'expected_error' => 'Only Super Admins can create host groups.' ], + [ + 'format' => 'yaml', + 'parameter' => 'groups', + 'source' => "---\nzabbix_export:\n version: \"4.0\"\n date: \"2020-08-03T12:41:17Z\"\n groups:\n - name: API host group yaml import as non Super Admin\n...\n", + 'sql' => 'select * from hstgrp where name=\'API host group yaml import as non Super Admin\'', + 'expected_error' => 'Only Super Admins can create host groups.' + ], [ 'format' => 'xml', 'parameter' => 'valueMaps', -- cgit v1.2.3 From 146f90660d9c67b35e2d09e0a6f0e134a70cf4b3 Mon Sep 17 00:00:00 2001 From: Eriks Sneiders Date: Mon, 3 Aug 2020 16:22:37 +0300 Subject: ...G...... [ZBXNEXT-6100] added native go support for vfs.fs.size/get/discovery/inode keys to linux agent 2 * commit '9852bd6777d57f3609b38e5c251d3b46cab4e7bd': ...G...... [ZBXNEXT-6100] added change-logs for all vfs.fs tasks ZBXNEXT-6100/6101/6102/6103 ...G...... [DEV-1621] reverted float64 format change for windows vfs.fs.get ...G...... [DEV-1621] fixed vfs.fs.size based on sub issues ...G...... [DEV-1621] fixed vfs.fs.get based on sub issues ...G...... [DEV-1623] code clean up ...G...... [DEV-1623] changed how pused and pfree are calculated to closer match C agent ...G...... [DEV-1623] fixed windows build for vfs.fs.inode key agent2 ...G...... [DEV-1623] added native support for vfs.fs.inode key for Agent 2 ...G...... [DEV-1624] added native support for vfs.fs.get key for Agent 2 ...G...... [DEV-1625] added native support for vfs.fs.discovery key for Agent 2 ...G...... [DEV-1621] fixed build for windows agent 2 ...G...... [DEV-1621] added native support for vfs.fs.size[fs,] key for Agent 2 (cherry picked from commit 75fc12d0c6c79ef520404c0e31f81335e4518580) --- ChangeLog.d/feature/ZBXNEXT-6100 | 1 + ChangeLog.d/feature/ZBXNEXT-6101 | 1 + ChangeLog.d/feature/ZBXNEXT-6102 | 1 + ChangeLog.d/feature/ZBXNEXT-6103 | 1 + src/go/cmd/zabbix_agent2/testrun_darwin.go | 1 + src/go/cmd/zabbix_agent2/testrun_linux.go | 1 + src/go/cmd/zabbix_agent2/testrun_windows.go | 1 + src/go/pkg/zbxlib/checks_linux.go | 8 -- src/go/plugins/plugins_linux.go | 1 + src/go/plugins/vfs/fs/fs.go | 29 ++--- src/go/plugins/vfs/fs/fs_nix.go | 162 ++++++++++++++++++++++++++++ src/go/plugins/vfs/fs/fs_windows.go | 19 +++- src/go/plugins/zabbix/async/async_nix.go | 1 - src/go/plugins/zabbix/sync/sync_nix.go | 3 - 14 files changed, 201 insertions(+), 29 deletions(-) create mode 100644 ChangeLog.d/feature/ZBXNEXT-6100 create mode 100644 ChangeLog.d/feature/ZBXNEXT-6101 create mode 100644 ChangeLog.d/feature/ZBXNEXT-6102 create mode 100644 ChangeLog.d/feature/ZBXNEXT-6103 create mode 100644 src/go/plugins/vfs/fs/fs_nix.go diff --git a/ChangeLog.d/feature/ZBXNEXT-6100 b/ChangeLog.d/feature/ZBXNEXT-6100 new file mode 100644 index 00000000000..351e281ba83 --- /dev/null +++ b/ChangeLog.d/feature/ZBXNEXT-6100 @@ -0,0 +1 @@ +...G...... [ZBXNEXT-6100] add native linux vfs.fs.size[fs,] metric support to agent2 (esneiders) diff --git a/ChangeLog.d/feature/ZBXNEXT-6101 b/ChangeLog.d/feature/ZBXNEXT-6101 new file mode 100644 index 00000000000..eb77395064c --- /dev/null +++ b/ChangeLog.d/feature/ZBXNEXT-6101 @@ -0,0 +1 @@ +...G...... [ZBXNEXT-6101] add native linux vfs.fs.inode[fs,] metric support to agent2 (esneiders) diff --git a/ChangeLog.d/feature/ZBXNEXT-6102 b/ChangeLog.d/feature/ZBXNEXT-6102 new file mode 100644 index 00000000000..6b63f6fcc22 --- /dev/null +++ b/ChangeLog.d/feature/ZBXNEXT-6102 @@ -0,0 +1 @@ +...G...... [ZBXNEXT-6102] add native linux vfs.fs.get metric support to agent2 (esneiders) diff --git a/ChangeLog.d/feature/ZBXNEXT-6103 b/ChangeLog.d/feature/ZBXNEXT-6103 new file mode 100644 index 00000000000..c728b84b0c6 --- /dev/null +++ b/ChangeLog.d/feature/ZBXNEXT-6103 @@ -0,0 +1 @@ +...G...... [ZBXNEXT-6103] add native linux vfs.fs.discovery metric support to agent2 (esneiders) diff --git a/src/go/cmd/zabbix_agent2/testrun_darwin.go b/src/go/cmd/zabbix_agent2/testrun_darwin.go index 399fcb7575a..d6deb160c94 100644 --- a/src/go/cmd/zabbix_agent2/testrun_darwin.go +++ b/src/go/cmd/zabbix_agent2/testrun_darwin.go @@ -57,6 +57,7 @@ func checkMetrics(s scheduler.Scheduler) { `vfs.fs.size[/,free]`, `vfs.fs.inode[/,free]`, `vfs.fs.discovery`, + `vfs.fs.get`, `vfs.dev.write[sda,operations]`, `net.tcp.listen[80]`, `net.udp.listen[68]`, diff --git a/src/go/cmd/zabbix_agent2/testrun_linux.go b/src/go/cmd/zabbix_agent2/testrun_linux.go index b329d762f0c..8fe3598f72e 100644 --- a/src/go/cmd/zabbix_agent2/testrun_linux.go +++ b/src/go/cmd/zabbix_agent2/testrun_linux.go @@ -59,6 +59,7 @@ func checkMetrics(s scheduler.Scheduler) { `vfs.fs.size[/,free]`, `vfs.fs.inode[/,free]`, `vfs.fs.discovery`, + `vfs.fs.get`, `vfs.dev.write[sda,operations]`, `net.tcp.listen[80]`, `net.udp.listen[68]`, diff --git a/src/go/cmd/zabbix_agent2/testrun_windows.go b/src/go/cmd/zabbix_agent2/testrun_windows.go index 72a98e874ee..73af9f86fee 100644 --- a/src/go/cmd/zabbix_agent2/testrun_windows.go +++ b/src/go/cmd/zabbix_agent2/testrun_windows.go @@ -55,6 +55,7 @@ func checkMetrics(s scheduler.Scheduler) { `zabbix.stats[127.0.0.1,10051]`, `vfs.fs.size[c:,free]`, `vfs.fs.discovery`, + `vfs.fs.get`, `net.tcp.listen[80]`, `net.if.in[MS TCP Loopback interface,bytes]`, `net.if.out[MS TCP Loopback interface,bytes]`, diff --git a/src/go/pkg/zbxlib/checks_linux.go b/src/go/pkg/zbxlib/checks_linux.go index 74875f58d52..6443c5243d3 100644 --- a/src/go/pkg/zbxlib/checks_linux.go +++ b/src/go/pkg/zbxlib/checks_linux.go @@ -116,14 +116,6 @@ func resolveMetric(key string) (cfunc unsafe.Pointer) { cfunc = unsafe.Pointer(C.VFS_DIR_COUNT) case "vfs.dir.size": cfunc = unsafe.Pointer(C.VFS_DIR_SIZE) - case "vfs.fs.discovery": - cfunc = unsafe.Pointer(C.VFS_FS_DISCOVERY) - case "vfs.fs.inode": - cfunc = unsafe.Pointer(C.VFS_FS_INODE) - case "vfs.fs.size": - cfunc = unsafe.Pointer(C.VFS_FS_SIZE) - case "vfs.fs.get": - cfunc = unsafe.Pointer(C.VFS_FS_GET) case "vm.memory.size": cfunc = unsafe.Pointer(C.VM_MEMORY_SIZE) } diff --git a/src/go/plugins/plugins_linux.go b/src/go/plugins/plugins_linux.go index 714f7839e02..003250d6c66 100644 --- a/src/go/plugins/plugins_linux.go +++ b/src/go/plugins/plugins_linux.go @@ -38,6 +38,7 @@ import ( _ "zabbix.com/plugins/systemrun" _ "zabbix.com/plugins/vfs/dev" _ "zabbix.com/plugins/vfs/file" + _ "zabbix.com/plugins/vfs/fs" _ "zabbix.com/plugins/web" _ "zabbix.com/plugins/zabbix/async" _ "zabbix.com/plugins/zabbix/stats" diff --git a/src/go/plugins/vfs/fs/fs.go b/src/go/plugins/vfs/fs/fs.go index 2b609e202ee..db9d23f85df 100644 --- a/src/go/plugins/vfs/fs/fs.go +++ b/src/go/plugins/vfs/fs/fs.go @@ -1,5 +1,3 @@ -// +build windows - /* ** Zabbix ** Copyright (C) 2001-2020 Zabbix SIA @@ -53,6 +51,15 @@ type FsInfo struct { FsType *string `json:"{#FSTYPE},omitempty"` DriveType *string `json:"{#FSDRIVETYPE},omitempty"` Bytes *FsStats `json:"bytes,omitempty"` + Inodes *FsStats `json:"inodes,omitempty"` +} + +type FsInfoNew struct { + FsName *string `json:"fsname,omitempty"` + FsType *string `json:"fstype,omitempty"` + DriveType *string `json:"fsdrivetype,omitempty"` + Bytes *FsStats `json:"bytes,omitempty"` + Inodes *FsStats `json:"inodes,omitempty"` } type Plugin struct { @@ -80,7 +87,7 @@ func (p *Plugin) exportGet(params []string) (value interface{}, err error) { if len(params) != 0 { return nil, errors.New(errorInvalidParameters) } - var d []*FsInfo + var d []*FsInfoNew if d, err = p.getFsInfoStats(); err != nil { return } @@ -91,7 +98,7 @@ func (p *Plugin) exportGet(params []string) (value interface{}, err error) { return string(b), nil } -func (p *Plugin) exportSize(params []string) (value interface{}, err error) { +func (p *Plugin) export(params []string, getStats func(string) (*FsStats, error)) (value interface{}, err error) { if len(params) < 1 || params[0] == "" { return nil, errors.New("Invalid first parameter.") } @@ -115,7 +122,7 @@ func (p *Plugin) exportSize(params []string) (value interface{}, err error) { } } var stats *FsStats - if stats, err = getFsStats(params[0]); err != nil { + if stats, err = getStats(params[0]); err != nil { return } @@ -142,16 +149,10 @@ func (p *Plugin) Export(key string, params []string, ctx plugin.ContextProvider) case "vfs.fs.get": return p.exportGet(params) case "vfs.fs.size": - return p.exportSize(params) + return p.export(params, getFsStats) + case "vfs.fs.inode": + return p.export(params, getFsInode) default: return nil, plugin.UnsupportedMetricError } } - -func init() { - plugin.RegisterMetrics(&impl, "VfsFs", - "vfs.fs.discovery", "List of mounted filesystems. Used for low-level discovery.", - "vfs.fs.get", "List of mounted filesystems with statistics.", - "vfs.fs.size", "Disk space in bytes or in percentage from total.", - ) -} diff --git a/src/go/plugins/vfs/fs/fs_nix.go b/src/go/plugins/vfs/fs/fs_nix.go new file mode 100644 index 00000000000..99ea97f9fbf --- /dev/null +++ b/src/go/plugins/vfs/fs/fs_nix.go @@ -0,0 +1,162 @@ +// +build !windows + +/* +** Zabbix +** Copyright (C) 2001-2019 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. +**/ + +package vfsfs + +import ( + "bufio" + "io" + "os" + "strings" + + "golang.org/x/sys/unix" + "zabbix.com/pkg/plugin" +) + +func (p *Plugin) getFsInfoStats() (data []*FsInfoNew, err error) { + allData, err := p.getFsInfo() + if err != nil { + return nil, err + } + + fsmap := make(map[string]*FsInfoNew) + for _, info := range allData { + bytes, err := getFsStats(*info.FsName) + if err != nil { + p.Debugf(`cannot discern stats for the mount: %s`, *info.FsName) + continue + } + + inodes, err := getFsInode(*info.FsName) + if err != nil { + p.Debugf(`cannot discern inode for the mount: %s`, *info.FsName) + continue + } + + if bytes.Total > 0 && inodes.Total > 0 { + fsmap[*info.FsName] = &FsInfoNew{info.FsName, info.FsType, nil, bytes, inodes} + } + } + + allData, err = p.getFsInfo() + if err != nil { + return nil, err + } + + for _, info := range allData { + if fsInfo, ok := fsmap[*info.FsName]; ok { + data = append(data, fsInfo) + } + } + + return +} + +func (p *Plugin) readMounts(file io.Reader) (data []*FsInfo, err error) { + scanner := bufio.NewScanner(file) + for scanner.Scan() { + line := scanner.Text() + mnt := strings.Split(line, " ") + if len(mnt) < 3 { + p.Debugf(`cannot discern the mount in given line: %s`, line) + continue + } + data = append(data, &FsInfo{FsName: &mnt[1], FsType: &mnt[2]}) + } + + if err = scanner.Err(); err != nil { + return nil, err + } + + return +} + +func (p *Plugin) getFsInfo() (data []*FsInfo, err error) { + file, err := os.Open("/proc/mounts") + if err != nil { + return nil, err + } + defer file.Close() + + data, err = p.readMounts(file) + if err != nil { + return nil, err + } + + return data, nil +} + +func getFsStats(path string) (stats *FsStats, err error) { + fs := unix.Statfs_t{} + err = unix.Statfs(path, &fs) + if err != nil { + return nil, err + } + + var avialable uint64 + if fs.Bavail > 0 { + avialable = fs.Bavail + } + + total := fs.Blocks * uint64(fs.Bsize) + free := avialable * uint64(fs.Bsize) + used := (fs.Blocks - fs.Bfree) * uint64(fs.Bsize) + pfree := 100.00 * float64(avialable) / float64(fs.Blocks-fs.Bfree+fs.Bavail) + stats = &FsStats{ + Total: total, + Free: free, + Used: used, + PFree: pfree, + PUsed: 100 - pfree, + } + + return +} + +func getFsInode(path string) (stats *FsStats, err error) { + fs := unix.Statfs_t{} + err = unix.Statfs(path, &fs) + if err != nil { + return nil, err + } + + total := fs.Files + free := fs.Ffree + used := fs.Files - fs.Ffree + stats = &FsStats{ + Total: total, + Free: free, + Used: used, + PFree: 100 * float64(free) / float64(total), + PUsed: 100 * float64(total-free) / float64(total), + } + + return +} + +func init() { + plugin.RegisterMetrics(&impl, "VfsFs", + "vfs.fs.discovery", "List of mounted filesystems. Used for low-level discovery.", + "vfs.fs.get", "List of mounted filesystems with statistics.", + "vfs.fs.size", "Disk space in bytes or in percentage from total.", + "vfs.fs.inode", "Disk space in bytes or in percentage from total.", + ) +} diff --git a/src/go/plugins/vfs/fs/fs_windows.go b/src/go/plugins/vfs/fs/fs_windows.go index 2cf2e1c4b96..05e41ecdedb 100644 --- a/src/go/plugins/vfs/fs/fs_windows.go +++ b/src/go/plugins/vfs/fs/fs_windows.go @@ -23,6 +23,7 @@ import ( "syscall" "golang.org/x/sys/windows" + "zabbix.com/pkg/plugin" ) func getMountPaths() (paths []string, err error) { @@ -145,14 +146,14 @@ func (p *Plugin) getFsInfo() (data []*FsInfo, err error) { return } -func (p *Plugin) getFsInfoStats() (data []*FsInfo, err error) { +func (p *Plugin) getFsInfoStats() (data []*FsInfoNew, err error) { var paths []string if paths, err = getMountPaths(); err != nil { return } - fsmap := make(map[string]*FsInfo) + fsmap := make(map[string]*FsInfoNew) for _, path := range paths { - var info FsInfo + var info FsInfoNew if fsname, fstype, drivetype, fserr := getFsInfo(path); fserr == nil { info.FsName = &fsname info.FsType = &fstype @@ -179,3 +180,15 @@ func (p *Plugin) getFsInfoStats() (data []*FsInfo, err error) { } return } + +func getFsInode(string) (*FsStats, error) { + return nil, plugin.UnsupportedMetricError +} + +func init() { + plugin.RegisterMetrics(&impl, "VfsFs", + "vfs.fs.discovery", "List of mounted filesystems. Used for low-level discovery.", + "vfs.fs.get", "List of mounted filesystems with statistics.", + "vfs.fs.size", "Disk space in bytes or in percentage from total.", + ) +} diff --git a/src/go/plugins/zabbix/async/async_nix.go b/src/go/plugins/zabbix/async/async_nix.go index 91c4155c424..031817c26ff 100644 --- a/src/go/plugins/zabbix/async/async_nix.go +++ b/src/go/plugins/zabbix/async/async_nix.go @@ -36,6 +36,5 @@ func getMetrics() []string { "system.sw.os", "Operating system information.", "system.swap.in", "Swap in (from device into memory) statistics.", "system.swap.out", "Swap out (from memory onto device) statistics.", - "vfs.fs.discovery", "List of mounted filesystems. Used for low-level discovery.", } } diff --git a/src/go/plugins/zabbix/sync/sync_nix.go b/src/go/plugins/zabbix/sync/sync_nix.go index 9a454bdadfb..1c9dee0c069 100644 --- a/src/go/plugins/zabbix/sync/sync_nix.go +++ b/src/go/plugins/zabbix/sync/sync_nix.go @@ -34,9 +34,6 @@ func getMetrics() []string { "system.swap.size", "Swap space size in bytes or in percentage from total.", "vfs.dir.count", "Directory entry count.", "vfs.dir.size", "Directory size (in bytes).", - "vfs.fs.inode", "Number or percentage of inodes.", - "vfs.fs.size", "Disk space in bytes or in percentage from total.", - "vfs.fs.get", "List of mounted filesystems with statistics.", "vm.memory.size", "Memory size in bytes or in percentage from total.", } } -- cgit v1.2.3 From 7c0974dbda30a9a22773cd0f9a844bef4ca590f6 Mon Sep 17 00:00:00 2001 From: Miks Kronkalns Date: Tue, 4 Aug 2020 09:51:30 +0300 Subject: ..F....... [ZBX-18106] fixed map navigation tree widget copying * commit '0fd2c9e7af9e9ff5eb2cf48cf3f27d2b5314d2db': ..F....... [ZBX-18106] fixed coding style ..F....... [ZBX-18106] reverted unneeded changes ..F....... [ZBX-18106] fixed map navigation tree widget copying (cherry picked from commit f2ca4f1a754570cdb0ec37b3be19284af4cd9f43) --- ChangeLog.d/bugfix/ZBX-18106 | 1 + ui/js/class.cnavtree.js | 12 +++++++++++- ui/js/dashboard.grid.js | 7 ++++++- 3 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 ChangeLog.d/bugfix/ZBX-18106 diff --git a/ChangeLog.d/bugfix/ZBX-18106 b/ChangeLog.d/bugfix/ZBX-18106 new file mode 100644 index 00000000000..c9c626f6d55 --- /dev/null +++ b/ChangeLog.d/bugfix/ZBX-18106 @@ -0,0 +1 @@ +..F....... [ZBX-18106] fixed map navigation tree widget copying (miks) diff --git a/ui/js/class.cnavtree.js b/ui/js/class.cnavtree.js index 5ed44cafa32..c52a3ccfda3 100644 --- a/ui/js/class.cnavtree.js +++ b/ui/js/class.cnavtree.js @@ -1267,6 +1267,14 @@ jQuery(function($) { }); }, + // onWidgetCopy trigger method + onWidgetCopy: function() { + var $this = $(this); + return this.each(function() { + updateWidgetFields($this); + }); + }, + // onEditStart trigger method onEditStart: function() { var $this = $(this); @@ -1314,7 +1322,9 @@ jQuery(function($) { lastId: 0 }); - var triggers = ['onEditStart', 'beforeDashboardSave','beforeConfigLoad', 'onDashboardReady']; + var triggers = ['onEditStart', 'beforeDashboardSave', 'onWidgetCopy', 'beforeConfigLoad', + 'onDashboardReady' + ]; $.each(triggers, function(index, trigger) { $(".dashbrd-grid-container").dashboardGrid("addAction", trigger, diff --git a/ui/js/dashboard.grid.js b/ui/js/dashboard.grid.js index 64449797811..469b7d7b6e9 100644 --- a/ui/js/dashboard.grid.js +++ b/ui/js/dashboard.grid.js @@ -3853,7 +3853,7 @@ }, /** - * Function to store copied widget into storage handler. + * Function to store copied widget into storage buffer. * * @param {object} widget Widget object copied. * @@ -3861,6 +3861,11 @@ */ copyWidget: function(widget) { return this.each(function() { + var $this = $(this), + data = $this.data('dashboardGrid'); + + doAction('onWidgetCopy', $this, data, widget); + var w = { type: widget.type, pos: { -- cgit v1.2.3 From 35ff451f5814209e5d9f4808463b872af3bb754b Mon Sep 17 00:00:00 2001 From: Marina Generalova Date: Tue, 4 Aug 2020 12:14:37 +0300 Subject: .........T [ZBXNEXT-6010] README.md edited --- templates/db/oracle_odbc/README.md | 70 +++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/templates/db/oracle_odbc/README.md b/templates/db/oracle_odbc/README.md index 18329f77249..65091574cc9 100644 --- a/templates/db/oracle_odbc/README.md +++ b/templates/db/oracle_odbc/README.md @@ -15,7 +15,7 @@ This template was tested on: > See [Zabbix template operation](https://www.zabbix.com/documentation/current/manual/config/templates_out_of_the_box/odbc_checks) for basic instructions. -1. Create an Oracle DB user for monitoring. +1. Create an Oracle DB user for monitoring: ``` CREATE USER zabbix_mon IDENTIFIED BY ; -- Grant access to the zabbix_mon user. @@ -39,12 +39,12 @@ This template was tested on: GRANT SELECT ON DBA_TABLESPACE_USAGE_METRICS TO zabbix_mon; GRANT SELECT ON DBA_USERS TO zabbix_mon; ``` -**Note! Be sure that ODBC connects to Oracle with session parameter NLS_NUMERIC_CHARACTERS= '.,' It is important for correct display float numbers in Zabbix.** +**Note! Make sure that ODBC connects to Oracle with session parameter NLS_NUMERIC_CHARACTERS= '.,' It is important for displaying float numbers in Zabbix correctly.** 2. Install the ODBC driver on the Zabbix server or the Zabbix proxy. See Oracle documentation for instructions: https://www.oracle.com/database/technologies/releasenote-odbc-ic.html. -3. Add new record to odbc.ini +3. Add a new record to odbc.ini: ``` [$ORACLE.DSN] Driver = Oracle 19 ODBC driver @@ -53,14 +53,13 @@ DSN = $ORACLE.DSN ``` **Note! Credentials in the odbc.ini do not work for Oracle.** -4. Check the connection via isql +4. Check the connection via isql: ``` isql $TNS_NAME $DB_USER $DB_PASSWORD ``` -5. Сonfigure zabbix-serve or zabbix-proxy for Oracle ENV Usage. Edit or add new file: +5. Сonfigure Zabbix server or Zabbix proxy for Oracle ENV Usage. Edit or add a new file: - Edit or add new file /etc/sysconfig/zabbix-server # for server @@ -74,9 +73,9 @@ isql $TNS_NAME $DB_USER $DB_PASSWORD export TNS_ADMIN=$ORACLE_HOME/network/admin ``` -6. Restart Zabbix-server or zabbix-proxy service +6. Restart Zabbix server or Zabbix proxy. -7. Set the user name and password in host macros ({$ORACLE.USER} and {$ORACLE.PASSWORD}). +7. Set the username and password in host macros ({$ORACLE.USER} and {$ORACLE.PASSWORD}). 8. Set the {$ORACLE.DSN} in host macros. @@ -98,21 +97,22 @@ No specific Zabbix configuration is required. |{$ORACLE.DBNAME.MATCHES} |

This macro is used in database discovery. It can be overridden on the host or linked template level.

|`.*` | |{$ORACLE.DBNAME.NOT_MATCHES} |

This macro is used in database discovery. It can be overridden on the host or linked template level.

|`PDB\$SEED` | |{$ORACLE.DSN} |

System data source name

|`` | -|{$ORACLE.EXPIRE.PASSWORD.MIN.WARN} |

The number of days before password expired for trigger expression.

|`7` | +|{$ORACLE.EXPIRE.PASSWORD.MIN.WARN} |

Number of days of warning before password expires (for trigger expression).

|`7` | |{$ORACLE.PASSWORD} |

Oracle user password.

|`` | -|{$ORACLE.PGA.USE.MAX.WARN} |

Maximum percentage of PGA usage for trigger expression.

|`90` | +|{$ORACLE.PGA.USE.MAX.WARN} |

Maximum percentage of PGA usage alert treshold (for trigger expression). +

|`90` | |{$ORACLE.PORT} |

Oracle DB TCP port.

|`1521` | -|{$ORACLE.PROCESSES.MAX.WARN} |

Maximum percentage of active processes for trigger expression.

|`80` | -|{$ORACLE.REDO.MIN.WARN} |

Minimum number of REDO logs for trigger expression.

|`3` | -|{$ORACLE.SESSION.LOCK.MAX.TIME} |

Maximum wait seconds for count of long time locked sessions query.

|`600` | -|{$ORACLE.SESSION.LONG.LOCK.MAX.WARN} |

Maximum number of long locked sessions usage for trigger expression.

|`3` | -|{$ORACLE.SESSIONS.LOCK.MAX.WARN} |

Maximum percentage of locked sessions usage for trigger expression.

|`20` | -|{$ORACLE.SESSIONS.MAX.WARN} |

Maximum percentage of active sessions for trigger expression.

|`80` | -|{$ORACLE.SHARED.FREE.MIN.WARN} |

Minimum percent of free shared pool for trigger expression.

|`5` | -|{$ORACLE.TABLESPACE.NAME.MATCHES} |

This macro is used in tablespace discovery. It can be overridden on the host or linked template level.

|`.*` | -|{$ORACLE.TABLESPACE.NAME.NOT_MATCHES} |

This macro is used in tablespace discovery. It can be overridden on the host or linked template level.

|`CHANGE_IF_NEEDED` | -|{$ORACLE.TBS.USED.PCT.MAX.HIGH} |

Maximum percentage of used tablespace for high trigger expression.

|`90` | -|{$ORACLE.TBS.USED.PCT.MAX.WARN} |

Maximum percentage of used tablespace for warning trigger expression.

|`80` | +|{$ORACLE.PROCESSES.MAX.WARN} |

Maximum percentage of active processes alert treshold (for trigger expression).

|`80` | +|{$ORACLE.REDO.MIN.WARN} |

Minimum number of REDO logs alert treshold (for trigger expression).

|`3` | +|{$ORACLE.SESSION.LOCK.MAX.TIME} |

Maximum session lock duration in seconds for count the session as a prolongely locked query.

|`600` | +|{$ORACLE.SESSION.LONG.LOCK.MAX.WARN} |

Maximum number of the prolongely locked sessions alert treshold (for trigger expression).

|`3` | +|{$ORACLE.SESSIONS.LOCK.MAX.WARN} |

Maximum percentage of locked sessions alert treshold (for trigger expression).

|`20` | +|{$ORACLE.SESSIONS.MAX.WARN} |

Maximum percentage of active sessions alert treshold (for trigger expression).

|`80` | +|{$ORACLE.SHARED.FREE.MIN.WARN} |

Minimum percentage of free shared pool alert treshold (for trigger expression).

|`5` | +|{$ORACLE.TABLESPACE.NAME.MATCHES} |

This macro is used in tablespace discovery. It can be overridden on a host or linked template level.

|`.*` | +|{$ORACLE.TABLESPACE.NAME.NOT_MATCHES} |

This macro is used in tablespace discovery. It can be overridden on a host or linked template level.

|`CHANGE_IF_NEEDED` | +|{$ORACLE.TBS.USED.PCT.MAX.HIGH} |

Maximum percentage of used tablespace high severity alert treshold (for trigger expression).

|`90` | +|{$ORACLE.TBS.USED.PCT.MAX.WARN} |

Maximum percentage of used tablespace warning severity alert treshold (for trigger expression).

|`80` | |{$ORACLE.USER} |

Oracle username.

|`` | ## Template links @@ -166,7 +166,7 @@ There are no template links in this template. |Oracle |Oracle: Active background sessions |

The number of active background sessions.

|DEPENDENT |oracle.session_active_background

**Preprocessing**:

- JSONPATH: `$[?(@.METRIC=='SESSION::Active Background')].VALUE.first()`

⛔️ON_FAIL: `CUSTOM_VALUE -> 0`

| |Oracle |Oracle: Inactive user sessions |

The number of inactive user sessions.

|DEPENDENT |oracle.session_inactive_user

**Preprocessing**:

- JSONPATH: `$[?(@.METRIC=='SESSION::Inactive User')].VALUE.first()`

⛔️ON_FAIL: `CUSTOM_VALUE -> 0`

| |Oracle |Oracle: Sessions lock rate |

The percentage of locked sessions. Locks are mechanisms that prevent destructive interaction between transactions accessing the same resource—either user objects such as tables and rows or system objects not visible to users, such as shared data structures in memory and data dictionary rows.

|DEPENDENT |oracle.session_lock_rate

**Preprocessing**:

- JSONPATH: `$[?(@.METRIC=='SESSION::Lock rate')].VALUE.first()`

| -|Oracle |Oracle: Sessions locked over {$ORACLE.SESSION.LOCK.MAX.TIME}s |

Count of long time locked sessions. (You can change maximum session lock duration in seconds for query by {$ORACLE.SESSION.LOCK.MAX.TIME} macro. Default 600 sec)

|DEPENDENT |oracle.session_long_time_locked

**Preprocessing**:

- JSONPATH: `$[?(@.METRIC=='SESSION::Long time locked')].VALUE.first()`

| +|Oracle |Oracle: Sessions locked over {$ORACLE.SESSION.LOCK.MAX.TIME}s |

Count of the prolongely locked sessions. (You can change maximum session lock duration in seconds for query by {$ORACLE.SESSION.LOCK.MAX.TIME} macro. Default 600 sec)

|DEPENDENT |oracle.session_long_time_locked

**Preprocessing**:

- JSONPATH: `$[?(@.METRIC=='SESSION::Long time locked')].VALUE.first()`

| |Oracle |Oracle: Sessions concurrency |

The percentage of concurrency. Concurrency is a DB behaviour when different transactions request to change the same resource - in case of modifying data transactions sequentially block temporarily the right to change data, the rest of the transactions are waiting for access. In the case when access for resource is locked for a long time, then the concurrency grows (like the transaction queue) and this often has an extremely negative impact on performance. A high contention value does not indicate the root cause of the problem, but is a signal to search for it.

|DEPENDENT |oracle.session_concurrency_rate

**Preprocessing**:

- JSONPATH: `$[?(@.METRIC=='SESSION::Concurrency rate')].VALUE.first()`

| |Oracle |Oracle: User '{$ORACLE.USER}' expire password |

The number of days before zabbix account password expired.

|DEPENDENT |oracle.user_expire_password

**Preprocessing**:

- JSONPATH: `$[?(@.METRIC=='USER::Expire password')].VALUE.first()`

| |Oracle |Oracle: Active serial sessions |

The number of active serial sessions.

|DEPENDENT |oracle.active_serial_sessions

**Preprocessing**:

- JSONPATH: `$[?(@.METRIC=='SYS::Active Serial Sessions')].VALUE.first()`

| @@ -231,32 +231,32 @@ There are no template links in this template. |Oracle: LISTENER process is not running | |`{TEMPLATE_NAME:proc.num[,,,"tnslsnr LISTENER"].max(#3)}=0` |DISASTER | | |Oracle: Version has changed (new version value received: {ITEM.VALUE}) |

Oracle DB version has changed. Ack to close.

|`{TEMPLATE_NAME:oracle.version.diff()}=1 and {TEMPLATE_NAME:oracle.version.strlen()}>0` |INFO |

Manual close: YES

| |Oracle: has been restarted (uptime < 10m) |

Uptime is less than 10 minutes

|`{TEMPLATE_NAME:oracle.uptime.last()}<10m` |INFO |

Manual close: YES

| -|Oracle: Failed to fetch info data (or no data for 5m) |

Zabbix has not received data for items for the last 5 minutes. The database might be unavailable for connecting

|`{TEMPLATE_NAME:oracle.uptime.nodata(5m)}=1` |WARNING |

**Depends on**:

- Oracle: Port {$ORACLE.PORT} is unavailable

| +|Oracle: Failed to fetch info data (or no data for 5m) |

Zabbix has not received data for items for the last 5 minutes. The database might be unavailable for connecting.

|`{TEMPLATE_NAME:oracle.uptime.nodata(5m)}=1` |WARNING |

**Depends on**:

- Oracle: Port {$ORACLE.PORT} is unavailable

| |Oracle: Instance name has changed (new name received: {ITEM.VALUE}) |

Oracle DB Instance name has changed. Ack to close.

|`{TEMPLATE_NAME:oracle.instance_name.diff()}=1 and {TEMPLATE_NAME:oracle.instance_name.strlen()}>0` |INFO |

Manual close: YES

| |Oracle: Instance hostname has changed (new hostname received: {ITEM.VALUE}) |

Oracle DB Instance hostname has changed. Ack to close.

|`{TEMPLATE_NAME:oracle.instance_hostname.diff()}=1 and {TEMPLATE_NAME:oracle.instance_hostname.strlen()}>0` |INFO |

Manual close: YES

| -|Oracle: Too many active processes (over {$ORACLE.PROCESSES.MAX.WARN}% for 5 min) |

Active process are using more than {$ORACLE.PROCESSES.MAX.WARN}% of the available Process number

|`{TEMPLATE_NAME:oracle.processes_count.min(5m)} * 100 / {Template DB Oracle by ODBC:oracle.processes_limit.last()} > {$ORACLE.PROCESSES.MAX.WARN}` |WARNING | | -|Oracle: Too many database files (over {$ORACLE.DB.FILE.MAX.WARN}% for 5 min) |

Number of datafiles more than {$ORACLE.DB.FILE.MAX.WARN}% of the available datafile files limit.

|`{TEMPLATE_NAME:oracle.db_files_count.min(5m)} * 100 / {Template DB Oracle by ODBC:oracle.db_files_limit.last()} > {$ORACLE.DB.FILE.MAX.WARN}` |WARNING | | -|Oracle: Shared pool free is too low (less {$ORACLE.SHARED.FREE.MIN.WARN}% for 5m) |

The shared pool free memory percent less than {$ORACLE.SHARED.FREE.MIN.WARN}% in the last 5 minutes.

|`{TEMPLATE_NAME:oracle.shared_pool_free.max(5m)}<{$ORACLE.SHARED.FREE.MIN.WARN}` |WARNING | | -|Oracle: Too many active sessions (over {$ORACLE.SESSIONS.MAX.WARN}% for 5 min) |

Active sessions are using more than {$ORACLE.SESSIONS.MAX.WARN}% of the available sessions

|`{TEMPLATE_NAME:oracle.session_count.min(5m)} * 100 / {Template DB Oracle by ODBC:oracle.session_limit.last()} > {$ORACLE.SESSIONS.MAX.WARN}` |WARNING | | +|Oracle: Too many active processes (over {$ORACLE.PROCESSES.MAX.WARN}% for 5 min) |

Active processes are using more than {$ORACLE.PROCESSES.MAX.WARN}% of the available number of processes.

|`{TEMPLATE_NAME:oracle.processes_count.min(5m)} * 100 / {Template DB Oracle by ODBC:oracle.processes_limit.last()} > {$ORACLE.PROCESSES.MAX.WARN}` |WARNING | | +|Oracle: Too many database files (over {$ORACLE.DB.FILE.MAX.WARN}% for 5 min) |

Number of datafiles is higher than {$ORACLE.DB.FILE.MAX.WARN}% of the available datafile files limit.

|`{TEMPLATE_NAME:oracle.db_files_count.min(5m)} * 100 / {Template DB Oracle by ODBC:oracle.db_files_limit.last()} > {$ORACLE.DB.FILE.MAX.WARN}` |WARNING | | +|Oracle: Shared pool free is too low (less {$ORACLE.SHARED.FREE.MIN.WARN}% for 5m) |

The shared pool free memory percent has been less than {$ORACLE.SHARED.FREE.MIN.WARN}% in the last 5 minutes.

|`{TEMPLATE_NAME:oracle.shared_pool_free.max(5m)}<{$ORACLE.SHARED.FREE.MIN.WARN}` |WARNING | | +|Oracle: Too many active sessions (over {$ORACLE.SESSIONS.MAX.WARN}% for 5 min) |

Active sessions are using more than {$ORACLE.SESSIONS.MAX.WARN}% of the available sessions.

|`{TEMPLATE_NAME:oracle.session_count.min(5m)} * 100 / {Template DB Oracle by ODBC:oracle.session_limit.last()} > {$ORACLE.SESSIONS.MAX.WARN}` |WARNING | | |Oracle: Too many locked sessions (over {$ORACLE.SESSIONS.LOCK.MAX.WARN}% for 5 min) |

Number of locked sessions is over {$ORACLE.SESSIONS.LOCK.MAX.WARN}% of the running sessions.

|`{TEMPLATE_NAME:oracle.session_lock_rate.min(5m)} > {$ORACLE.SESSIONS.LOCK.MAX.WARN}` |WARNING | | |Oracle: Too many sessions locked over {$ORACLE.SESSION.LOCK.MAX.TIME}s (over {$ORACLE.SESSION.LONG.LOCK.MAX.WARN} for 5 min) |

Number of sessions locked over {$ORACLE.SESSION.LOCK.MAX.TIME} seconds is too high. Long-term locks can negatively affect database performance, therefore, if they are detected, you should first find the most difficult queries from the database point of view and analyze possible resource leaks.

|`{TEMPLATE_NAME:oracle.session_long_time_locked.min(5m)} > {$ORACLE.SESSION.LONG.LOCK.MAX.WARN}` |WARNING | | |Oracle: Too hight database concurrency (over {$ORACLE.CONCURRENCY.MAX.WARN}% for 5 min) |

Concurrency rate is over {$ORACLE.CONCURRENCY.MAX.WARN}%. A high contention value does not indicate the root cause of the problem, but is a signal to search for it. In the case of high competition, an analysis of resource consumption should be carried out, the most "heavy" queries made in the database, possibly - session tracing. All this will help determine the root cause and possible optimization points both in the database configuration and in the logic of building queries of the application itself.

|`{TEMPLATE_NAME:oracle.session_concurrency_rate.min(5m)} > {$ORACLE.CONCURRENCY.MAX.WARN}` |WARNING | | -|Oracle: Zabbix account will expire soon (under {$ORACLE.EXPIRE.PASSWORD.MIN.WARN} days) |

Password for zabbix user in database will expire soon.

|`{TEMPLATE_NAME:oracle.user_expire_password.last()} < {$ORACLE.EXPIRE.PASSWORD.MIN.WARN}` |WARNING | | -|Oracle: Total PGA inuse is too high (over {$ORACLE.PGA.USE.MAX.WARN}% for 5 min) |

Total PGA inuse is more than {$ORACLE.PGA.USE.MAX.WARN}% of PGA_AGGREGATE_TARGET.

|`{TEMPLATE_NAME:oracle.total_pga_used.min(5m)} * 100 / {Template DB Oracle by ODBC:oracle.pga_target.last()} > {$ORACLE.PGA.USE.MAX.WARN}` |WARNING | | +|Oracle: Zabbix account will expire soon (under {$ORACLE.EXPIRE.PASSWORD.MIN.WARN} days) |

Password for zabbix user in the database will expire soon.

|`{TEMPLATE_NAME:oracle.user_expire_password.last()} < {$ORACLE.EXPIRE.PASSWORD.MIN.WARN}` |WARNING | | +|Oracle: Total PGA inuse is too high (over {$ORACLE.PGA.USE.MAX.WARN}% for 5 min) |

Total PGA in use is more than {$ORACLE.PGA.USE.MAX.WARN}% of PGA_AGGREGATE_TARGET.

|`{TEMPLATE_NAME:oracle.total_pga_used.min(5m)} * 100 / {Template DB Oracle by ODBC:oracle.pga_target.last()} > {$ORACLE.PGA.USE.MAX.WARN}` |WARNING | | |Oracle: Number of REDO logs available for switching is too low (less {$ORACLE.REDO.MIN.WARN} for 5 min) |

Number of available for log switching inactive/unused REDOs is low (Database down risk)

|`{TEMPLATE_NAME:oracle.redo_logs_available.max(5m)} < {$ORACLE.REDO.MIN.WARN}` |WARNING | | |Oracle Database '{#DBNAME}': Open status in mount mode |

The Oracle DB has a MOUNTED state.

|`{TEMPLATE_NAME:oracle.db_open_mode["{#DBNAME}"].last()}=1` |WARNING | | |Oracle Database '{#DBNAME}': Open status has changed (new value received: {ITEM.VALUE}) |

Oracle DB open status has changed. Ack to close.

|`{TEMPLATE_NAME:oracle.db_open_mode["{#DBNAME}"].diff()}=1` |INFO |

Manual close: YES

**Depends on**:

- Oracle Database '{#DBNAME}': Open status in mount mode

| |Oracle Database '{#DBNAME}': Role has changed (new value received: {ITEM.VALUE}) |

Oracle DB role has changed. Ack to close.

|`{TEMPLATE_NAME:oracle.db_role["{#DBNAME}"].diff()}=1` |INFO |

Manual close: YES

| -|Oracle Database '{#DBNAME}': Force logging is deactivate for DB with active Archivelog |

Force Logging mode - it is very important metric for Databases in 'ARCHIVELOG'. This feature allows to forcibly write all transactions to the REDO.

|`{TEMPLATE_NAME:oracle.db_force_logging["{#DBNAME}"].last()} = 0 and {Template DB Oracle by ODBC:oracle.db_log_mode["{#DBNAME}"].last()} = 1` |WARNING | | +|Oracle Database '{#DBNAME}': Force logging is deactivated for DB with active Archivelog |

Force Logging mode - it is very important metric for Databases in 'ARCHIVELOG'. This feature allows to forcibly write all transactions to the REDO.

|`{TEMPLATE_NAME:oracle.db_force_logging["{#DBNAME}"].last()} = 0 and {Template DB Oracle by ODBC:oracle.db_log_mode["{#DBNAME}"].last()} = 1` |WARNING | | |Oracle Database '{#DBNAME}': Open status in mount mode |

The Oracle DB has a MOUNTED state.

|`{TEMPLATE_NAME:oracle.pdb_open_mode["{#DBNAME}"].last()}=1` |WARNING | | |Oracle Database '{#DBNAME}': Open status has changed (new value received: {ITEM.VALUE}) |

Oracle DB open status has changed. Ack to close.

|`{TEMPLATE_NAME:oracle.pdb_open_mode["{#DBNAME}"].diff()}=1` |INFO |

Manual close: YES

| -|Oracle TBS '{#TABLESPACE}': Tablespace usage is is too high (over {$ORACLE.TBS.USED.PCT.MAX.WARN}% for 5m) | |`{TEMPLATE_NAME:oracle.tbs_used_pct["{#TABLESPACE}"].min(5m)}>{$ORACLE.TBS.USED.PCT.MAX.WARN}` |WARNING |

**Depends on**:

- Oracle TBS '{#TABLESPACE}': Tablespace Usage is is too high (over {$ORACLE.TBS.USED.PCT.MAX.HIGH}% for 5m)

| -|Oracle TBS '{#TABLESPACE}': Tablespace Usage is is too high (over {$ORACLE.TBS.USED.PCT.MAX.HIGH}% for 5m) | |`{TEMPLATE_NAME:oracle.tbs_used_pct["{#TABLESPACE}"].min(5m)}>{$ORACLE.TBS.USED.PCT.MAX.HIGH}` |HIGH | | -|Oracle TBS '{#TABLESPACE}': Tablespase is OFFLINE |

The tablespase is in offline state.

|`{TEMPLATE_NAME:oracle.tbs_status["{#TABLESPACE}"].last()}=2` |WARNING | | +|Oracle TBS '{#TABLESPACE}': Tablespace usage is too high (over {$ORACLE.TBS.USED.PCT.MAX.WARN}% for 5m). | |`{TEMPLATE_NAME:oracle.tbs_used_pct["{#TABLESPACE}"].min(5m)}>{$ORACLE.TBS.USED.PCT.MAX.WARN}` |WARNING |

**Depends on**:

- Oracle TBS '{#TABLESPACE}': Tablespace Usage is is too high (over {$ORACLE.TBS.USED.PCT.MAX.HIGH}% for 5m)

| +|Oracle TBS '{#TABLESPACE}': Tablespace Usage is too high (over {$ORACLE.TBS.USED.PCT.MAX.HIGH}% for 5m). | |`{TEMPLATE_NAME:oracle.tbs_used_pct["{#TABLESPACE}"].min(5m)}>{$ORACLE.TBS.USED.PCT.MAX.HIGH}` |HIGH | | +|Oracle TBS '{#TABLESPACE}': Tablespase is OFFLINE |

The tablespase is in the offline state.

|`{TEMPLATE_NAME:oracle.tbs_status["{#TABLESPACE}"].last()}=2` |WARNING | | |Oracle TBS '{#TABLESPACE}': Tablespace status has changed (new value received: {ITEM.VALUE}) |

Oracle tablespace status has changed. Ack to close.

|`{TEMPLATE_NAME:oracle.tbs_status["{#TABLESPACE}"].diff()}=1` |INFO |

Manual close: YES

**Depends on**:

- Oracle TBS '{#TABLESPACE}': Tablespase is OFFLINE

| |Archivelog '{#DEST_NAME}': Log Archive is not valid |

ARL destination not in 3 - Valid or 2 - Deferred.

|`{TEMPLATE_NAME:oracle.archivelog_log_status["{#DEST_NAME}"].last()}<2` |HIGH | | -|ASM '{#DG_NAME}': Disk group usage is is too high (over {$ORACLE.ASM.USED.PCT.MAX.WARN}% for 5m) | |`{TEMPLATE_NAME:oracle.asm_used_pct["{#DG_NAME}"].min(5m)}>{$ORACLE.ASM.USED.PCT.MAX.WARN}` |WARNING |

**Depends on**:

- ASM '{#DG_NAME}': Disk group usage is is too high (over {$ORACLE.ASM.USED.PCT.MAX.HIGH}% for 5m)

| -|ASM '{#DG_NAME}': Disk group usage is is too high (over {$ORACLE.ASM.USED.PCT.MAX.HIGH}% for 5m) | |`{TEMPLATE_NAME:oracle.asm_used_pct["{#DG_NAME}"].min(5m)}>{$ORACLE.ASM.USED.PCT.MAX.HIGH}` |HIGH | | +|ASM '{#DG_NAME}': Disk group usage is too high (over {$ORACLE.ASM.USED.PCT.MAX.WARN}% for 5m) | |`{TEMPLATE_NAME:oracle.asm_used_pct["{#DG_NAME}"].min(5m)}>{$ORACLE.ASM.USED.PCT.MAX.WARN}` |WARNING |

**Depends on**:

- ASM '{#DG_NAME}': Disk group usage is is too high (over {$ORACLE.ASM.USED.PCT.MAX.HIGH}% for 5m)

| +|ASM '{#DG_NAME}': Disk group usage is too high (over {$ORACLE.ASM.USED.PCT.MAX.HIGH}% for 5m) | |`{TEMPLATE_NAME:oracle.asm_used_pct["{#DG_NAME}"].min(5m)}>{$ORACLE.ASM.USED.PCT.MAX.HIGH}` |HIGH | | ## Feedback -- cgit v1.2.3 From 944023ab186803f1dc5a896e577e95d39d6eb812 Mon Sep 17 00:00:00 2001 From: Yulia Chukina Date: Tue, 4 Aug 2020 13:04:49 +0300 Subject: .........T [ZBXNEXT-6010] some descriptions edited --- templates/db/oracle_odbc/README.md | 16 ++--- .../db/oracle_odbc/template_db_oracle_odbc.xml | 68 +++++++++++----------- 2 files changed, 43 insertions(+), 41 deletions(-) diff --git a/templates/db/oracle_odbc/README.md b/templates/db/oracle_odbc/README.md index 65091574cc9..a49b3b317cd 100644 --- a/templates/db/oracle_odbc/README.md +++ b/templates/db/oracle_odbc/README.md @@ -3,7 +3,7 @@ ## Overview -For Zabbix version: 5.0 +For Zabbix version: 5.0 The template is developed for monitoring DBMS Oracle Database single instance via ODBC. This template was tested on: @@ -60,6 +60,7 @@ isql $TNS_NAME $DB_USER $DB_PASSWORD 5. Сonfigure Zabbix server or Zabbix proxy for Oracle ENV Usage. Edit or add a new file: + Edit or add new file /etc/sysconfig/zabbix-server # for server @@ -94,13 +95,12 @@ No specific Zabbix configuration is required. |{$ORACLE.ASM.USED.PCT.MAX.WARN} |

Maximum percentage of used ASM disk group for warning trigger expression.

|`90` | |{$ORACLE.CONCURRENCY.MAX.WARN} |

Maximum percentage of sessions concurrency usage for trigger expression.

|`80` | |{$ORACLE.DB.FILE.MAX.WARN} |

Maximum percentage of database files for trigger expression.

|`80` | -|{$ORACLE.DBNAME.MATCHES} |

This macro is used in database discovery. It can be overridden on the host or linked template level.

|`.*` | -|{$ORACLE.DBNAME.NOT_MATCHES} |

This macro is used in database discovery. It can be overridden on the host or linked template level.

|`PDB\$SEED` | +|{$ORACLE.DBNAME.MATCHES} |

This macro is used in database discovery. It can be overridden on a host or linked template level.

|`.*` | +|{$ORACLE.DBNAME.NOT_MATCHES} |

This macro is used in database discovery. It can be overridden on a host or linked template level.

|`PDB\$SEED` | |{$ORACLE.DSN} |

System data source name

|`` | |{$ORACLE.EXPIRE.PASSWORD.MIN.WARN} |

Number of days of warning before password expires (for trigger expression).

|`7` | |{$ORACLE.PASSWORD} |

Oracle user password.

|`` | -|{$ORACLE.PGA.USE.MAX.WARN} |

Maximum percentage of PGA usage alert treshold (for trigger expression). -

|`90` | +|{$ORACLE.PGA.USE.MAX.WARN} |

Maximum percentage of PGA usage alert treshold (for trigger expression).

|`90` | |{$ORACLE.PORT} |

Oracle DB TCP port.

|`1521` | |{$ORACLE.PROCESSES.MAX.WARN} |

Maximum percentage of active processes alert treshold (for trigger expression).

|`80` | |{$ORACLE.REDO.MIN.WARN} |

Minimum number of REDO logs alert treshold (for trigger expression).

|`3` | @@ -250,13 +250,13 @@ There are no template links in this template. |Oracle Database '{#DBNAME}': Force logging is deactivated for DB with active Archivelog |

Force Logging mode - it is very important metric for Databases in 'ARCHIVELOG'. This feature allows to forcibly write all transactions to the REDO.

|`{TEMPLATE_NAME:oracle.db_force_logging["{#DBNAME}"].last()} = 0 and {Template DB Oracle by ODBC:oracle.db_log_mode["{#DBNAME}"].last()} = 1` |WARNING | | |Oracle Database '{#DBNAME}': Open status in mount mode |

The Oracle DB has a MOUNTED state.

|`{TEMPLATE_NAME:oracle.pdb_open_mode["{#DBNAME}"].last()}=1` |WARNING | | |Oracle Database '{#DBNAME}': Open status has changed (new value received: {ITEM.VALUE}) |

Oracle DB open status has changed. Ack to close.

|`{TEMPLATE_NAME:oracle.pdb_open_mode["{#DBNAME}"].diff()}=1` |INFO |

Manual close: YES

| -|Oracle TBS '{#TABLESPACE}': Tablespace usage is too high (over {$ORACLE.TBS.USED.PCT.MAX.WARN}% for 5m). | |`{TEMPLATE_NAME:oracle.tbs_used_pct["{#TABLESPACE}"].min(5m)}>{$ORACLE.TBS.USED.PCT.MAX.WARN}` |WARNING |

**Depends on**:

- Oracle TBS '{#TABLESPACE}': Tablespace Usage is is too high (over {$ORACLE.TBS.USED.PCT.MAX.HIGH}% for 5m)

| +|Oracle TBS '{#TABLESPACE}': Tablespace usage is too high (over {$ORACLE.TBS.USED.PCT.MAX.WARN}% for 5m). | |`{TEMPLATE_NAME:oracle.tbs_used_pct["{#TABLESPACE}"].min(5m)}>{$ORACLE.TBS.USED.PCT.MAX.WARN}` |WARNING |

**Depends on**:

- Oracle TBS '{#TABLESPACE}': Tablespace Usage is too high (over {$ORACLE.TBS.USED.PCT.MAX.HIGH}% for 5m).

| |Oracle TBS '{#TABLESPACE}': Tablespace Usage is too high (over {$ORACLE.TBS.USED.PCT.MAX.HIGH}% for 5m). | |`{TEMPLATE_NAME:oracle.tbs_used_pct["{#TABLESPACE}"].min(5m)}>{$ORACLE.TBS.USED.PCT.MAX.HIGH}` |HIGH | | |Oracle TBS '{#TABLESPACE}': Tablespase is OFFLINE |

The tablespase is in the offline state.

|`{TEMPLATE_NAME:oracle.tbs_status["{#TABLESPACE}"].last()}=2` |WARNING | | |Oracle TBS '{#TABLESPACE}': Tablespace status has changed (new value received: {ITEM.VALUE}) |

Oracle tablespace status has changed. Ack to close.

|`{TEMPLATE_NAME:oracle.tbs_status["{#TABLESPACE}"].diff()}=1` |INFO |

Manual close: YES

**Depends on**:

- Oracle TBS '{#TABLESPACE}': Tablespase is OFFLINE

| |Archivelog '{#DEST_NAME}': Log Archive is not valid |

ARL destination not in 3 - Valid or 2 - Deferred.

|`{TEMPLATE_NAME:oracle.archivelog_log_status["{#DEST_NAME}"].last()}<2` |HIGH | | -|ASM '{#DG_NAME}': Disk group usage is too high (over {$ORACLE.ASM.USED.PCT.MAX.WARN}% for 5m) | |`{TEMPLATE_NAME:oracle.asm_used_pct["{#DG_NAME}"].min(5m)}>{$ORACLE.ASM.USED.PCT.MAX.WARN}` |WARNING |

**Depends on**:

- ASM '{#DG_NAME}': Disk group usage is is too high (over {$ORACLE.ASM.USED.PCT.MAX.HIGH}% for 5m)

| -|ASM '{#DG_NAME}': Disk group usage is too high (over {$ORACLE.ASM.USED.PCT.MAX.HIGH}% for 5m) | |`{TEMPLATE_NAME:oracle.asm_used_pct["{#DG_NAME}"].min(5m)}>{$ORACLE.ASM.USED.PCT.MAX.HIGH}` |HIGH | | +|ASM '{#DG_NAME}': Disk group usage is too high (over {$ORACLE.ASM.USED.PCT.MAX.WARN}% for 5m) |

Usage percent of ASM disk group is over {$ORACLE.ASM.USED.PCT.MAX.WARN}

|`{TEMPLATE_NAME:oracle.asm_used_pct["{#DG_NAME}"].min(5m)}>{$ORACLE.ASM.USED.PCT.MAX.WARN}` |WARNING |

**Depends on**:

- ASM '{#DG_NAME}': Disk group usage is too high (over {$ORACLE.ASM.USED.PCT.MAX.HIGH}% for 5m)

| +|ASM '{#DG_NAME}': Disk group usage is too high (over {$ORACLE.ASM.USED.PCT.MAX.HIGH}% for 5m) |

Usage percent of ASM disk group is over {$ORACLE.ASM.USED.PCT.MAX.WARN}

|`{TEMPLATE_NAME:oracle.asm_used_pct["{#DG_NAME}"].min(5m)}>{$ORACLE.ASM.USED.PCT.MAX.HIGH}` |HIGH | | ## Feedback diff --git a/templates/db/oracle_odbc/template_db_oracle_odbc.xml b/templates/db/oracle_odbc/template_db_oracle_odbc.xml index e78ec821227..6eb97c7ce8a 100644 --- a/templates/db/oracle_odbc/template_db_oracle_odbc.xml +++ b/templates/db/oracle_odbc/template_db_oracle_odbc.xml @@ -1,7 +1,7 @@ 5.0 - 2020-08-03T10:27:51Z + 2020-08-04T10:02:29Z Templates/Databases @@ -1485,7 +1485,7 @@ SELECT 0 7d FLOAT - Count of long time locked sessions. (You can change maximum session lock duration in seconds for query by {$ORACLE.SESSION.LOCK.MAX.TIME} macro. Default 600 sec) + Count of the prolongely locked sessions. (You can change maximum session lock duration in seconds for query by {$ORACLE.SESSION.LOCK.MAX.TIME} macro. Default 600 sec) Oracle @@ -1687,7 +1687,7 @@ SELECT {max(5m)}<{$ORACLE.SHARED.FREE.MIN.WARN} Oracle: Shared pool free is too low (less {$ORACLE.SHARED.FREE.MIN.WARN}% for 5m) WARNING - The shared pool free memory percent less than {$ORACLE.SHARED.FREE.MIN.WARN}% in the last 5 minutes. + The shared pool free memory percent has been less than {$ORACLE.SHARED.FREE.MIN.WARN}% in the last 5 minutes. @@ -1842,7 +1842,7 @@ SELECT {nodata(5m)}=1 Oracle: Failed to fetch info data (or no data for 5m) WARNING - Zabbix has not received data for items for the last 5 minutes. The database might be unavailable for connecting + Zabbix has not received data for items for the last 5 minutes. The database might be unavailable for connecting. Oracle: Port {$ORACLE.PORT} is unavailable @@ -1880,7 +1880,7 @@ SELECT {last()} < {$ORACLE.EXPIRE.PASSWORD.MIN.WARN} Oracle: Zabbix account will expire soon (under {$ORACLE.EXPIRE.PASSWORD.MIN.WARN} days) WARNING - Password for zabbix user in database will expire soon. + Password for zabbix user in the database will expire soon. @@ -2147,19 +2147,21 @@ FROM v$archive_dest d , v$database db WHERE d.status != 'INACTIVE' AND db.log_mo {min(5m)}>{$ORACLE.ASM.USED.PCT.MAX.WARN} - ASM '{#DG_NAME}': Disk group usage is is too high (over {$ORACLE.ASM.USED.PCT.MAX.WARN}% for 5m) + ASM '{#DG_NAME}': Disk group usage is too high (over {$ORACLE.ASM.USED.PCT.MAX.WARN}% for 5m) WARNING + Usage percent of ASM disk group is over {$ORACLE.ASM.USED.PCT.MAX.WARN} - ASM '{#DG_NAME}': Disk group usage is is too high (over {$ORACLE.ASM.USED.PCT.MAX.HIGH}% for 5m) + ASM '{#DG_NAME}': Disk group usage is too high (over {$ORACLE.ASM.USED.PCT.MAX.HIGH}% for 5m) {Template DB Oracle by ODBC:oracle.asm_used_pct["{#DG_NAME}"].min(5m)}>{$ORACLE.ASM.USED.PCT.MAX.HIGH} {min(5m)}>{$ORACLE.ASM.USED.PCT.MAX.HIGH} - ASM '{#DG_NAME}': Disk group usage is is too high (over {$ORACLE.ASM.USED.PCT.MAX.HIGH}% for 5m) + ASM '{#DG_NAME}': Disk group usage is too high (over {$ORACLE.ASM.USED.PCT.MAX.HIGH}% for 5m) HIGH + Usage percent of ASM disk group is over {$ORACLE.ASM.USED.PCT.MAX.WARN} @@ -2365,9 +2367,9 @@ FROM v$archive_dest d , v$database db WHERE d.status != 'INACTIVE' AND db.log_mo {Template DB Oracle by ODBC:oracle.db_force_logging["{#DBNAME}"].last()} = 0 and {Template DB Oracle by ODBC:oracle.db_log_mode["{#DBNAME}"].last()} = 1 - Oracle Database '{#DBNAME}': Force logging is deactivate for DB with active Archivelog + Oracle Database '{#DBNAME}': Force logging is deactivated for DB with active Archivelog WARNING - Force Logging mode - it is very important metric for Databases in 'ARCHIVELOG'. This feature allows to forcibly write all transactions to the REDO. + Force Logging mode - it is very important metric for Databases in 'ARCHIVELOG'. This feature allows to forcibly write all transactions to the REDO. @@ -2545,7 +2547,7 @@ contents FROM DBA_TABLESPACES; {last()}=2 Oracle TBS '{#TABLESPACE}': Tablespase is OFFLINE WARNING - The tablespase is in offline state. + The tablespase is in the offline state. {diff()}=1 @@ -2609,18 +2611,18 @@ contents FROM DBA_TABLESPACES; {min(5m)}>{$ORACLE.TBS.USED.PCT.MAX.WARN} - Oracle TBS '{#TABLESPACE}': Tablespace usage is is too high (over {$ORACLE.TBS.USED.PCT.MAX.WARN}% for 5m) + Oracle TBS '{#TABLESPACE}': Tablespace usage is too high (over {$ORACLE.TBS.USED.PCT.MAX.WARN}% for 5m). WARNING - Oracle TBS '{#TABLESPACE}': Tablespace Usage is is too high (over {$ORACLE.TBS.USED.PCT.MAX.HIGH}% for 5m) + Oracle TBS '{#TABLESPACE}': Tablespace Usage is too high (over {$ORACLE.TBS.USED.PCT.MAX.HIGH}% for 5m). {Template DB Oracle by ODBC:oracle.tbs_used_pct["{#TABLESPACE}"].min(5m)}>{$ORACLE.TBS.USED.PCT.MAX.HIGH} {min(5m)}>{$ORACLE.TBS.USED.PCT.MAX.HIGH} - Oracle TBS '{#TABLESPACE}': Tablespace Usage is is too high (over {$ORACLE.TBS.USED.PCT.MAX.HIGH}% for 5m) + Oracle TBS '{#TABLESPACE}': Tablespace Usage is too high (over {$ORACLE.TBS.USED.PCT.MAX.HIGH}% for 5m). HIGH @@ -2675,12 +2677,12 @@ contents FROM DBA_TABLESPACES; {$ORACLE.DBNAME.MATCHES} .* - This macro is used in database discovery. It can be overridden on the host or linked template level. + This macro is used in database discovery. It can be overridden on a host or linked template level. {$ORACLE.DBNAME.NOT_MATCHES} PDB\$SEED - This macro is used in database discovery. It can be overridden on the host or linked template level. + This macro is used in database discovery. It can be overridden on a host or linked template level. {$ORACLE.DSN} @@ -2690,7 +2692,7 @@ contents FROM DBA_TABLESPACES; {$ORACLE.EXPIRE.PASSWORD.MIN.WARN} 7 - The number of days before password expired for trigger expression. + Number of days of warning before password expires (for trigger expression). {$ORACLE.PASSWORD} @@ -2700,7 +2702,7 @@ contents FROM DBA_TABLESPACES; {$ORACLE.PGA.USE.MAX.WARN} 90 - Maximum percentage of PGA usage for trigger expression. + Maximum percentage of PGA usage alert treshold (for trigger expression). {$ORACLE.PORT} @@ -2710,57 +2712,57 @@ contents FROM DBA_TABLESPACES; {$ORACLE.PROCESSES.MAX.WARN} 80 - Maximum percentage of active processes for trigger expression. + Maximum percentage of active processes alert treshold (for trigger expression). {$ORACLE.REDO.MIN.WARN} 3 - Minimum number of REDO logs for trigger expression. + Minimum number of REDO logs alert treshold (for trigger expression). {$ORACLE.SESSION.LOCK.MAX.TIME} 600 - Maximum wait seconds for count of long time locked sessions query. + Maximum session lock duration in seconds for count the session as a prolongely locked query. {$ORACLE.SESSION.LONG.LOCK.MAX.WARN} 3 - Maximum number of long locked sessions usage for trigger expression. + Maximum number of the prolongely locked sessions alert treshold (for trigger expression). {$ORACLE.SESSIONS.LOCK.MAX.WARN} 20 - Maximum percentage of locked sessions usage for trigger expression. + Maximum percentage of locked sessions alert treshold (for trigger expression). {$ORACLE.SESSIONS.MAX.WARN} 80 - Maximum percentage of active sessions for trigger expression. + Maximum percentage of active sessions alert treshold (for trigger expression). {$ORACLE.SHARED.FREE.MIN.WARN} 5 - Minimum percent of free shared pool for trigger expression. + Minimum percentage of free shared pool alert treshold (for trigger expression). {$ORACLE.TABLESPACE.NAME.MATCHES} .* - This macro is used in tablespace discovery. It can be overridden on the host or linked template level. + This macro is used in tablespace discovery. It can be overridden on a host or linked template level. {$ORACLE.TABLESPACE.NAME.NOT_MATCHES} CHANGE_IF_NEEDED - This macro is used in tablespace discovery. It can be overridden on the host or linked template level. + This macro is used in tablespace discovery. It can be overridden on a host or linked template level. {$ORACLE.TBS.USED.PCT.MAX.HIGH} 90 - Maximum percentage of used tablespace for high trigger expression. + Maximum percentage of used tablespace high severity alert treshold (for trigger expression). {$ORACLE.TBS.USED.PCT.MAX.WARN} 80 - Maximum percentage of used tablespace for warning trigger expression. + Maximum percentage of used tablespace warning severity alert treshold (for trigger expression). {$ORACLE.USER} @@ -2781,25 +2783,25 @@ contents FROM DBA_TABLESPACES; {Template DB Oracle by ODBC:oracle.processes_count.min(5m)} * 100 / {Template DB Oracle by ODBC:oracle.processes_limit.last()} > {$ORACLE.PROCESSES.MAX.WARN} Oracle: Too many active processes (over {$ORACLE.PROCESSES.MAX.WARN}% for 5 min) WARNING - Active process are using more than {$ORACLE.PROCESSES.MAX.WARN}% of the available Process number + Active processes are using more than {$ORACLE.PROCESSES.MAX.WARN}% of the available number of processes. {Template DB Oracle by ODBC:oracle.session_count.min(5m)} * 100 / {Template DB Oracle by ODBC:oracle.session_limit.last()} > {$ORACLE.SESSIONS.MAX.WARN} Oracle: Too many active sessions (over {$ORACLE.SESSIONS.MAX.WARN}% for 5 min) WARNING - Active sessions are using more than {$ORACLE.SESSIONS.MAX.WARN}% of the available sessions + Active sessions are using more than {$ORACLE.SESSIONS.MAX.WARN}% of the available sessions. {Template DB Oracle by ODBC:oracle.db_files_count.min(5m)} * 100 / {Template DB Oracle by ODBC:oracle.db_files_limit.last()} > {$ORACLE.DB.FILE.MAX.WARN} Oracle: Too many database files (over {$ORACLE.DB.FILE.MAX.WARN}% for 5 min) WARNING - Number of datafiles more than {$ORACLE.DB.FILE.MAX.WARN}% of the available datafile files limit. + Number of datafiles is higher than {$ORACLE.DB.FILE.MAX.WARN}% of the available datafile files limit. {Template DB Oracle by ODBC:oracle.total_pga_used.min(5m)} * 100 / {Template DB Oracle by ODBC:oracle.pga_target.last()} > {$ORACLE.PGA.USE.MAX.WARN} Oracle: Total PGA inuse is too high (over {$ORACLE.PGA.USE.MAX.WARN}% for 5 min) WARNING - Total PGA inuse is more than {$ORACLE.PGA.USE.MAX.WARN}% of PGA_AGGREGATE_TARGET. + Total PGA in use is more than {$ORACLE.PGA.USE.MAX.WARN}% of PGA_AGGREGATE_TARGET. -- cgit v1.2.3 From c6d65ce35e2ffc890e99f4c5e146e7a0dc8cbd02 Mon Sep 17 00:00:00 2001 From: Yulia Chukina Date: Tue, 4 Aug 2020 13:17:11 +0300 Subject: .........T [ZBXNEXT-6010] resolve merge conflct --- templates/db/oracle_odbc/template_db_oracle_odbc.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/db/oracle_odbc/template_db_oracle_odbc.xml b/templates/db/oracle_odbc/template_db_oracle_odbc.xml index 6eb97c7ce8a..fe21fa52af5 100644 --- a/templates/db/oracle_odbc/template_db_oracle_odbc.xml +++ b/templates/db/oracle_odbc/template_db_oracle_odbc.xml @@ -1,7 +1,7 @@ 5.0 - 2020-08-04T10:02:29Z + 2020-07-30T14:23:21Z Templates/Databases -- cgit v1.2.3 From 37cfb1959505dce432cab05e0f515198fcef7574 Mon Sep 17 00:00:00 2001 From: Aleksejs Sestakovs Date: Tue, 4 Aug 2020 14:39:38 +0300 Subject: ...G...... [ZBX-17815] fixed connection timeout when persistent buffer enabled * commit '33aaf442a74caada8bc70c7e8a314f69c084a6b1': ...G...... [ZBX-17815] remove empty line ...G...... [ZBX-17815] added the comment about the updateConnection() ...G...... [ZBX-17815] restored seemingly redundant 1) setDeadline() from tls.go recvTLS() ...G...... [ZBX-17815] removed redundant 1) setDeadline() from tls.go recvTLS() and 2) updateConnections() from resultCache.go ...G...... [ZBX-17815] fixed connection timeout when persistent buffer enabled (cherry picked from commit 88cb33ba69cedfa67418598f2b1cde6b0f3e625b) --- ChangeLog.d/bugfix/ZBX-17815 | 1 + src/go/internal/agent/resultcache/diskcache.go | 1 + src/go/internal/agent/resultcache/resultcache.go | 4 +++- 3 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 ChangeLog.d/bugfix/ZBX-17815 diff --git a/ChangeLog.d/bugfix/ZBX-17815 b/ChangeLog.d/bugfix/ZBX-17815 new file mode 100644 index 00000000000..842a6d42f6e --- /dev/null +++ b/ChangeLog.d/bugfix/ZBX-17815 @@ -0,0 +1 @@ +...G...... [ZBX-17815] fixed connection timeout when persistent buffer enabled (asestakovs) diff --git a/src/go/internal/agent/resultcache/diskcache.go b/src/go/internal/agent/resultcache/diskcache.go index 2768d07276b..076d27fdbbe 100644 --- a/src/go/internal/agent/resultcache/diskcache.go +++ b/src/go/internal/agent/resultcache/diskcache.go @@ -410,6 +410,7 @@ func (c *DiskCache) run() { func (c *DiskCache) updateOptions(options *agent.AgentOptions) { c.storagePeriod = int64(options.PersistentBufferPeriod) + c.timeout = options.Timeout } func (c *DiskCache) insertResultTable(table string) string { diff --git a/src/go/internal/agent/resultcache/resultcache.go b/src/go/internal/agent/resultcache/resultcache.go index 0e9c454a82a..9552cf0ab80 100644 --- a/src/go/internal/agent/resultcache/resultcache.go +++ b/src/go/internal/agent/resultcache/resultcache.go @@ -61,8 +61,9 @@ const ( type ResultCache interface { Start() Stop() - UpdateOptions(options *agent.AgentOptions) Upload(u Uploader) + // TODO: will be used once the runtime configuration reload is implemented + UpdateOptions(options *agent.AgentOptions) } type AgentData struct { @@ -116,6 +117,7 @@ func (c *cacheData) Write(result *plugin.Result) { c.input <- result } +// TODO: will be used once the runtime configuration reload is implemented func (c *cacheData) UpdateOptions(options *agent.AgentOptions) { c.input <- options } -- cgit v1.2.3 From 88332506254610fac89e887bd27868348da948e0 Mon Sep 17 00:00:00 2001 From: Andris Zeila Date: Wed, 5 Aug 2020 15:58:58 +0300 Subject: ...G...... [ZBX-16998] improved agent binary compatibility by removing __thread attribute when not building agent2 * commit '7f7970126f09818d4567acd2d7a91ec7a0b71106': .D........ [ZBX-16998] added changelog entry .......... [ZBX-16998] fixed agent2 build on windows ...G...... [ZBX-16998] removed __thread usage when building only C targets (cherry picked from commit 75ea8679f05b892a9d09c6ba5fe3ecb9b47e332f) --- ChangeLog.d/bugfix/ZBX-16998 | 1 + build/mingw/Makefile | 4 +++- configure.ac | 1 + include/zbxtypes.h | 14 +++++++++++--- 4 files changed, 16 insertions(+), 4 deletions(-) create mode 100644 ChangeLog.d/bugfix/ZBX-16998 diff --git a/ChangeLog.d/bugfix/ZBX-16998 b/ChangeLog.d/bugfix/ZBX-16998 new file mode 100644 index 00000000000..5d024706467 --- /dev/null +++ b/ChangeLog.d/bugfix/ZBX-16998 @@ -0,0 +1 @@ +...G...... [ZBX-16998] improved agent binary compatibility by removing __thread attribute when not building agent2 (wiper) diff --git a/build/mingw/Makefile b/build/mingw/Makefile index 972c5a8d182..dcb5fc33530 100644 --- a/build/mingw/Makefile +++ b/build/mingw/Makefile @@ -33,7 +33,9 @@ OBJS = \ $(OUTPUTDIR)\eventlog.o \ $(TARGETDIR)\resource.syso -CFLAGS := $(CFLAGS) -O2 -g -DUNICODE -DHAVE_STDINT_H=1 -I$(TOPDIR)\build\win32\include -I$(TOPDIR)\build\mingw -I$(TOPDIR)\include +CFLAGS := $(CFLAGS) -O2 -g -DUNICODE -DHAVE_STDINT_H=1 -DZBX_BUILD_AGENT2=1 -DHAVE_THREAD_LOCAL=1 \ + -I$(TOPDIR)\build\win32\include -I$(TOPDIR)\build\mingw -I$(TOPDIR)\include + RFLAGS := $(RFLAGS) --input-format=rc -O coff GOPATH := $(GOPATH);$(TOPDIR)\go TAGS := diff --git a/configure.ac b/configure.ac index 0fb70af4804..39a1d278dd8 100644 --- a/configure.ac +++ b/configure.ac @@ -1734,6 +1734,7 @@ if test "x$agent2" = "xyes"; then if test "x$GO" = "xno"; then AC_MSG_ERROR([Unable to find "go" executable in path]) fi + AC_DEFINE(ZBX_BUILD_AGENT2,1,[Define to 1 if Agent2 is being built.]) fi if test "x$java" = "xyes"; then diff --git a/include/zbxtypes.h b/include/zbxtypes.h index b64ca0dde44..0d3a5b421ed 100644 --- a/include/zbxtypes.h +++ b/include/zbxtypes.h @@ -20,12 +20,20 @@ #ifndef ZABBIX_TYPES_H #define ZABBIX_TYPES_H +#include "sysinc.h" + #if defined(_WINDOWS) # define ZBX_THREAD_LOCAL __declspec(thread) #else -# if defined(HAVE_THREAD_LOCAL) && (defined(__GNUC__) || defined(__clang__) || defined(__MINGW32__)) -# define ZBX_THREAD_LOCAL __thread -# else +/* for non windows build thread local storage is required only for agent2 */ +# if defined(ZBX_BUILD_AGENT2) +# if defined(HAVE_THREAD_LOCAL) && (defined(__GNUC__) || defined(__clang__) || defined(__MINGW32__)) +# define ZBX_THREAD_LOCAL __thread +# else +# error "C compiler is not compatible with agent2 assembly" +# endif +# endif +# if !defined(ZBX_THREAD_LOCAL) # define ZBX_THREAD_LOCAL # endif #endif -- cgit v1.2.3 From b0373f45adffee7bac5ed3dc563e87e8ff6e2131 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C4=81rti=C5=86=C5=A1=20T=C4=81lbergs?= Date: Thu, 6 Aug 2020 09:56:23 +0300 Subject: A.F....... [ZBX-17468] fixed excess audit log record being added on host status update * commit '23e0443cc605602151b2c93c914a61063e5afcd3': A......... [ZBX-17468] fixed auditlog for host.create method A......... [ZBX-17468] removed redundant fields from API request 'output' section A......... [ZBX-17468] removed auditing readonly fields A......... [ZBX-17468] fixed using "extend" in hosts API ..F....... [ZBX-17468] fixed API hosts mass update auditlog .D........ [ZBX-17468] added change log entry (cherry picked from commit f00e13dba080b99f453b98db9331b3750f43395f) --- ChangeLog.d/bugfix/ZBX-17468 | 1 + ui/hostgroups.php | 9 --------- ui/hosts.php | 28 ++++++--------------------- ui/include/classes/api/CAudit.php | 1 + ui/include/classes/api/services/CHost.php | 32 ++++++++++++++++++++----------- ui/include/hosts.inc.php | 27 -------------------------- 6 files changed, 29 insertions(+), 69 deletions(-) create mode 100644 ChangeLog.d/bugfix/ZBX-17468 diff --git a/ChangeLog.d/bugfix/ZBX-17468 b/ChangeLog.d/bugfix/ZBX-17468 new file mode 100644 index 00000000000..8d8bf29ec8d --- /dev/null +++ b/ChangeLog.d/bugfix/ZBX-17468 @@ -0,0 +1 @@ +A.F....... [ZBX-17468] fixed excess audit log record being added on host status update (talbergs) diff --git a/ui/hostgroups.php b/ui/hostgroups.php index 4c828edc3ae..e8306e0ee8a 100644 --- a/ui/hostgroups.php +++ b/ui/hostgroups.php @@ -160,7 +160,6 @@ elseif (hasRequest('action')) { elseif (getRequest('action') == 'hostgroup.massenable' || getRequest('action') == 'hostgroup.massdisable') { $enable = (getRequest('action') == 'hostgroup.massenable'); $status = $enable ? HOST_STATUS_MONITORED : HOST_STATUS_NOT_MONITORED; - $auditAction = $enable ? AUDIT_ACTION_ENABLE : AUDIT_ACTION_DISABLE; $groupIds = getRequest('groups', []); @@ -180,14 +179,6 @@ elseif (hasRequest('action')) { 'hosts' => $hosts, 'status' => $status ]); - - if ($result) { - foreach ($hosts as $host) { - add_audit_ext($auditAction, AUDIT_RESOURCE_HOST, $host['hostid'], $host['host'], 'hosts', - ['status' => $host['status']], ['status' => $status] - ); - } - } } $result = DBend($result); diff --git a/ui/hosts.php b/ui/hosts.php index 9e40fc1dd51..3aa3ac8f780 100644 --- a/ui/hosts.php +++ b/ui/hosts.php @@ -839,16 +839,9 @@ elseif (hasRequest('add') || hasRequest('update')) { } if ($create) { - $hostIds = API::Host()->create($host); - - if ($hostIds) { - $hostId = reset($hostIds['hostids']); - } - else { + if (!API::Host()->create($host)) { throw new Exception(); } - - add_audit_ext(AUDIT_ACTION_ADD, AUDIT_RESOURCE_HOST, $hostId, $host['host'], null, null, null); } else { $host['hostid'] = $hostId; @@ -856,16 +849,6 @@ elseif (hasRequest('add') || hasRequest('update')) { if (!API::Host()->update($host)) { throw new Exception(); } - - $dbHostNew = API::Host()->get([ - 'output' => API_OUTPUT_EXTEND, - 'hostids' => $hostId, - 'editable' => true - ]); - $dbHostNew = reset($dbHostNew); - - add_audit_ext(AUDIT_ACTION_UPDATE, AUDIT_RESOURCE_HOST, $dbHostNew['hostid'], $dbHostNew['host'], 'hosts', - $dbHost, $dbHostNew); } // full clone @@ -1001,13 +984,14 @@ elseif (hasRequest('hosts') && hasRequest('action') && str_in_array(getRequest(' 'templated_hosts' => true, 'output' => ['hostid'] ]); - $actHosts = zbx_objectValues($actHosts, 'hostid'); if ($actHosts) { - DBstart(); + foreach ($actHosts as &$host) { + $host['status'] = $status; + } + unset($host); - $result = updateHostStatus($actHosts, $status); - $result = DBend($result); + $result = (bool) API::Host()->update($actHosts); if ($result) { uncheckTableRows(); diff --git a/ui/include/classes/api/CAudit.php b/ui/include/classes/api/CAudit.php index 0b4aaee8e77..bb1f7c6453f 100644 --- a/ui/include/classes/api/CAudit.php +++ b/ui/include/classes/api/CAudit.php @@ -35,6 +35,7 @@ class CAudit { AUDIT_RESOURCE_DISCOVERY_RULE => ['druleid', 'name', 'drules'], AUDIT_RESOURCE_GRAPH => ['graphid', 'name', 'graphs'], AUDIT_RESOURCE_GRAPH_PROTOTYPE => ['graphid', 'name', 'graphs'], + AUDIT_RESOURCE_HOST => ['hostid', 'name', 'hosts'], AUDIT_RESOURCE_HOST_GROUP => ['groupid', 'name', 'groups'], AUDIT_RESOURCE_HOST_PROTOTYPE => ['hostid', 'host', 'hosts'], AUDIT_RESOURCE_ICON_MAP => ['iconmapid', 'name', 'icon_map'], diff --git a/ui/include/classes/api/services/CHost.php b/ui/include/classes/api/services/CHost.php index cacba3db1b9..00f0bb06a44 100644 --- a/ui/include/classes/api/services/CHost.php +++ b/ui/include/classes/api/services/CHost.php @@ -700,7 +700,7 @@ class CHost extends CHostGeneral { $hostids = []; $ins_tags = []; - foreach ($hosts as $host) { + foreach ($hosts as &$host) { // If visible name is not given or empty it should be set to host name. if (!array_key_exists('name', $host) || !trim($host['name'])) { $host['name'] = $host['host']; @@ -768,6 +768,9 @@ class CHost extends CHostGeneral { DB::insert('host_inventory', [$hostInventory], false); } } + unset($host); + + $this->addAuditBulk(AUDIT_ACTION_ADD, AUDIT_RESOURCE_HOST, $hosts); if ($ins_tags) { DB::insert('host_tag', $ins_tags); @@ -971,7 +974,10 @@ class CHost extends CHostGeneral { sort($hostids); $db_hosts = $this->get([ - 'output' => ['hostid', 'host'], + 'output' => ['hostid', 'proxy_hostid', 'host', 'status', 'ipmi_authtype', 'ipmi_privilege', 'ipmi_username', + 'ipmi_password', 'name', 'description', 'tls_connect', 'tls_accept', 'tls_issuer', 'tls_subject', + 'tls_psk_identity', 'tls_psk', 'inventory_mode' + ], 'hostids' => $hostids, 'editable' => true, 'preservekeys' => true @@ -1117,12 +1123,8 @@ class CHost extends CHostGeneral { $updateInventory['inventory_mode'] = $data['inventory_mode']; } - if (isset($data['status'])) { - $updateStatus = $data['status']; - } - unset($data['hosts'], $data['groups'], $data['interfaces'], $data['templates_clear'], $data['templates'], - $data['macros'], $data['inventory'], $data['inventory_mode'], $data['status']); + $data['macros'], $data['inventory'], $data['inventory_mode']); if (!zbx_empty($data)) { DB::update('hosts', [ @@ -1131,10 +1133,6 @@ class CHost extends CHostGeneral { ]); } - if (isset($updateStatus)) { - updateHostStatus($hostids, $updateStatus); - } - /* * Update template linkage */ @@ -1326,6 +1324,18 @@ class CHost extends CHostGeneral { } } + $new_hosts = []; + foreach ($db_hosts as $hostid => $db_host) { + $new_host = $data + $db_host; + if ($new_host['status'] != $db_host['status']) { + info(_s('Updated status of host "%1$s".', $new_host['host'])); + } + + $new_hosts[] = $new_host; + } + + $this->addAuditBulk(AUDIT_ACTION_UPDATE, AUDIT_RESOURCE_HOST, $new_hosts, $db_hosts); + return ['hostids' => $inputHostIds]; } diff --git a/ui/include/hosts.inc.php b/ui/include/hosts.inc.php index ed8f83a4cfe..43a103bb9fc 100644 --- a/ui/include/hosts.inc.php +++ b/ui/include/hosts.inc.php @@ -533,33 +533,6 @@ function get_host_by_hostid($hostid, $no_error_message = 0) { return false; } -function updateHostStatus($hostids, $status) { - zbx_value2array($hostids); - - $hostIds = []; - $oldStatus = ($status == HOST_STATUS_MONITORED ? HOST_STATUS_NOT_MONITORED : HOST_STATUS_MONITORED); - - $db_hosts = DBselect( - 'SELECT h.hostid,h.host,h.status'. - ' FROM hosts h'. - ' WHERE '.dbConditionInt('h.hostid', $hostids). - ' AND h.status='.zbx_dbstr($oldStatus) - ); - while ($host = DBfetch($db_hosts)) { - $hostIds[] = $host['hostid']; - - $host_new = $host; - $host_new['status'] = $status; - add_audit_ext(AUDIT_ACTION_UPDATE, AUDIT_RESOURCE_HOST, $host['hostid'], $host['host'], 'hosts', $host, $host_new); - info(_s('Updated status of host "%1$s".', $host['host'])); - } - - return DB::update('hosts', [ - 'values' => ['status' => $status], - 'where' => ['hostid' => $hostIds] - ]); -} - /** * Get parent templates for each given application. * -- cgit v1.2.3 From 9078bba3fef1dbe339e9a049a426b65d142009dc Mon Sep 17 00:00:00 2001 From: Vladislavs Sokurenko Date: Thu, 6 Aug 2020 16:13:20 +0300 Subject: ........S. [ZBX-18169] fixed housekeeper not deleting history and trends for deleted items if storage period is not overridden * commit '64ebd9722d634c676dc4b9bd2e8f6a68e3c75c17': .D........ [ZBX-18169] added ChangeLog entry ........S. [ZBX-18169] fixed housekeeper not deleting history and trends for deleted items if storage period is not overridden (cherry picked from commit 9c3ca976629e6c03d9aa6a8cfcdcca8729188fc4) --- ChangeLog.d/bugfix/ZBX-18169 | 1 + src/zabbix_server/housekeeper/housekeeper.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 ChangeLog.d/bugfix/ZBX-18169 diff --git a/ChangeLog.d/bugfix/ZBX-18169 b/ChangeLog.d/bugfix/ZBX-18169 new file mode 100644 index 00000000000..4fd9c09be49 --- /dev/null +++ b/ChangeLog.d/bugfix/ZBX-18169 @@ -0,0 +1 @@ +........S. [ZBX-18169] fixed housekeeper not deleting history and trends for deleted items if storage period is not overridden (vso) diff --git a/src/zabbix_server/housekeeper/housekeeper.c b/src/zabbix_server/housekeeper/housekeeper.c index b8f98b41437..59861f47b7e 100644 --- a/src/zabbix_server/housekeeper/housekeeper.c +++ b/src/zabbix_server/housekeeper/housekeeper.c @@ -909,7 +909,7 @@ static int housekeeping_cleanup(void) /* assemble list of tables included in the housekeeping procedure */ for (table = hk_cleanup_tables; NULL != table->name; table++) { - if (ZBX_HK_MODE_REGULAR != *table->poption_mode || ZBX_HK_OPTION_ENABLED == *table->poption_global) + if (ZBX_HK_MODE_REGULAR != *table->poption_mode) continue; table_name_esc = DBdyn_escape_string(table->name); -- cgit v1.2.3 From bbb9d01adaad6b5c49d5a28297560eae92d86ee7 Mon Sep 17 00:00:00 2001 From: Ivo Kurzemnieks Date: Thu, 6 Aug 2020 18:30:49 +0300 Subject: ..F....... [ZBX-18132] added OpenSSL extension check in frontend setup and SAML authentication form * commit 'd70ac7d61413240362d67b0ad6f09304189f2606': ..F....... [ZBX-18132] added OpenSSL extension check in frontend setup and SAML authentication form --- ChangeLog.d/bugfix/ZBX-18132 | 1 + .../controllers/CControllerAuthenticationEdit.php | 4 +++ .../CControllerAuthenticationUpdate.php | 10 ++++++ .../views/administration.authentication.edit.php | 38 +++++++++++----------- ui/include/classes/setup/CFrontendSetup.php | 18 ++++++++++ 5 files changed, 52 insertions(+), 19 deletions(-) create mode 100644 ChangeLog.d/bugfix/ZBX-18132 diff --git a/ChangeLog.d/bugfix/ZBX-18132 b/ChangeLog.d/bugfix/ZBX-18132 new file mode 100644 index 00000000000..7842e843c0a --- /dev/null +++ b/ChangeLog.d/bugfix/ZBX-18132 @@ -0,0 +1 @@ +..F....... [ZBX-18132] added OpenSSL extension check in frontend setup and SAML authentication form (Ivo) diff --git a/ui/app/controllers/CControllerAuthenticationEdit.php b/ui/app/controllers/CControllerAuthenticationEdit.php index 298c945b85a..8e30f6fe3fb 100644 --- a/ui/app/controllers/CControllerAuthenticationEdit.php +++ b/ui/app/controllers/CControllerAuthenticationEdit.php @@ -87,6 +87,7 @@ class CControllerAuthenticationEdit extends CController { protected function doAction() { $ldap_status = (new CFrontendSetup())->checkPhpLdapModule(); + $openssl_status = (new CFrontendSetup())->checkPhpOpenSsl(); $data = [ 'action_submit' => 'authentication.update', @@ -94,6 +95,7 @@ class CControllerAuthenticationEdit extends CController { 'ldap_error' => ($ldap_status['result'] == CFrontendSetup::CHECK_OK) ? '' : $ldap_status['error'], 'ldap_test_password' => '', 'ldap_test_user' => CWebUser::$data['alias'], + 'saml_error' => ($openssl_status['result'] == CFrontendSetup::CHECK_OK) ? '' : $openssl_status['error'], 'change_bind_password' => 0, 'form_refresh' => 0 ]; @@ -146,6 +148,8 @@ class CControllerAuthenticationEdit extends CController { $data['ldap_enabled'] = ($ldap_status['result'] == CFrontendSetup::CHECK_OK && $data['ldap_configured'] == ZBX_AUTH_LDAP_ENABLED); + $data['saml_enabled'] = ($openssl_status['result'] == CFrontendSetup::CHECK_OK + && $data['saml_auth_enabled'] == ZBX_AUTH_SAML_ENABLED); $response = new CControllerResponseData($data); $response->setTitle(_('Configuration of authentication')); diff --git a/ui/app/controllers/CControllerAuthenticationUpdate.php b/ui/app/controllers/CControllerAuthenticationUpdate.php index 53cac78e739..9dba61be15a 100644 --- a/ui/app/controllers/CControllerAuthenticationUpdate.php +++ b/ui/app/controllers/CControllerAuthenticationUpdate.php @@ -183,6 +183,14 @@ class CControllerAuthenticationUpdate extends CController { * @return bool */ private function validateSamlAuth() { + $openssl_status = (new CFrontendSetup())->checkPhpOpenSsl(); + + if ($openssl_status['result'] != CFrontendSetup::CHECK_OK) { + $this->response->setMessageError($openssl_status['error']); + + return false; + } + $saml_fields = ['saml_idp_entityid', 'saml_sso_url', 'saml_sp_entityid', 'saml_username_attribute']; $config = select_config(); $this->getInputs($config, $saml_fields); @@ -221,6 +229,7 @@ class CControllerAuthenticationUpdate extends CController { if (!$auth_valid) { $this->response->setFormData($this->getInputAll()); $this->setResponse($this->response); + return; } @@ -229,6 +238,7 @@ class CControllerAuthenticationUpdate extends CController { $this->response->setMessageOk(_('LDAP login successful')); $this->response->setFormData($this->getInputAll()); $this->setResponse($this->response); + return; } diff --git a/ui/app/views/administration.authentication.edit.php b/ui/app/views/administration.authentication.edit.php index 2489607b998..b20f0914324 100644 --- a/ui/app/views/administration.authentication.edit.php +++ b/ui/app/views/administration.authentication.edit.php @@ -138,38 +138,38 @@ $ldap_tab = (new CFormList('list_ldap')) ); // SAML authentication fields. -$is_saml_auth_enabled = ($data['saml_auth_enabled'] == ZBX_AUTH_SAML_ENABLED); - $saml_tab = (new CFormList('list_saml')) ->addRow(new CLabel(_('Enable SAML authentication'), 'saml_auth_enabled'), - (new CCheckBox('saml_auth_enabled', ZBX_AUTH_SAML_ENABLED)) - ->setChecked($is_saml_auth_enabled) - ->setUncheckedValue(ZBX_AUTH_LDAP_DISABLED) + $data['saml_error'] + ? (new CLabel($data['saml_error']))->addClass(ZBX_STYLE_RED) + : (new CCheckBox('saml_auth_enabled', ZBX_AUTH_SAML_ENABLED)) + ->setChecked($data['saml_auth_enabled'] == ZBX_AUTH_SAML_ENABLED) + ->setUncheckedValue(ZBX_AUTH_SAML_DISABLED) ) ->addRow((new CLabel(_('IdP entity ID'), 'saml_idp_entityid'))->setAsteriskMark(), (new CTextBox('saml_idp_entityid', $data['saml_idp_entityid'], false, DB::getFieldLength('config', 'saml_idp_entityid') )) - ->setEnabled($is_saml_auth_enabled) + ->setEnabled($data['saml_enabled']) ->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH) ->setAriaRequired() ) ->addRow((new CLabel(_('SSO service URL'), 'saml_sso_url'))->setAsteriskMark(), (new CTextBox('saml_sso_url', $data['saml_sso_url'], false, DB::getFieldLength('config', 'saml_sso_url'))) - ->setEnabled($is_saml_auth_enabled) + ->setEnabled($data['saml_enabled']) ->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH) ->setAriaRequired() ) ->addRow(new CLabel(_('SLO service URL'), 'saml_slo_url'), (new CTextBox('saml_slo_url', $data['saml_slo_url'], false, DB::getFieldLength('config', 'saml_slo_url'))) - ->setEnabled($is_saml_auth_enabled) + ->setEnabled($data['saml_enabled']) ->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH) ) ->addRow((new CLabel(_('Username attribute'), 'saml_username_attribute'))->setAsteriskMark(), (new CTextBox('saml_username_attribute', $data['saml_username_attribute'], false, DB::getFieldLength('config', 'saml_username_attribute') )) - ->setEnabled($is_saml_auth_enabled) + ->setEnabled($data['saml_enabled']) ->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH) ->setAriaRequired() ) @@ -177,7 +177,7 @@ $saml_tab = (new CFormList('list_saml')) (new CTextBox('saml_sp_entityid', $data['saml_sp_entityid'], false, DB::getFieldLength('config', 'saml_sp_entityid') )) - ->setEnabled($is_saml_auth_enabled) + ->setEnabled($data['saml_enabled']) ->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH) ->setAriaRequired() ) @@ -185,7 +185,7 @@ $saml_tab = (new CFormList('list_saml')) (new CTextBox('saml_nameid_format', $data['saml_nameid_format'], false, DB::getFieldLength('config', 'saml_nameid_format') )) - ->setEnabled($is_saml_auth_enabled) + ->setEnabled($data['saml_enabled']) ->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH) ->setAttribute('placeholder', 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient') ) @@ -196,31 +196,31 @@ $saml_tab = (new CFormList('list_saml')) ->setLabel(_('Messages')) ->setChecked($data['saml_sign_messages'] == 1) ->setUncheckedValue(0) - ->setEnabled($is_saml_auth_enabled) + ->setEnabled($data['saml_enabled']) ) ->addItem((new CCheckBox('saml_sign_assertions')) ->setLabel(_('Assertions')) ->setChecked($data['saml_sign_assertions'] == 1) ->setUncheckedValue(0) - ->setEnabled($is_saml_auth_enabled) + ->setEnabled($data['saml_enabled']) ) ->addItem((new CCheckBox('saml_sign_authn_requests')) ->setLabel(_('AuthN requests')) ->setChecked($data['saml_sign_authn_requests'] == 1) ->setUncheckedValue(0) - ->setEnabled($is_saml_auth_enabled) + ->setEnabled($data['saml_enabled']) ) ->addItem((new CCheckBox('saml_sign_logout_requests')) ->setLabel(_('Logout requests')) ->setChecked($data['saml_sign_logout_requests'] == 1) ->setUncheckedValue(0) - ->setEnabled($is_saml_auth_enabled) + ->setEnabled($data['saml_enabled']) ) ->addItem((new CCheckBox('saml_sign_logout_responses')) ->setLabel(_('Logout responses')) ->setChecked($data['saml_sign_logout_responses'] == 1) ->setUncheckedValue(0) - ->setEnabled($is_saml_auth_enabled) + ->setEnabled($data['saml_enabled']) ) ) ->addRow(_('Encrypt'), @@ -230,20 +230,20 @@ $saml_tab = (new CFormList('list_saml')) ->setLabel(_('Name ID')) ->setChecked($data['saml_encrypt_nameid'] == 1) ->setUncheckedValue(0) - ->setEnabled($is_saml_auth_enabled) + ->setEnabled($data['saml_enabled']) ) ->addItem((new CCheckBox('saml_encrypt_assertions')) ->setLabel(_('Assertions')) ->setChecked($data['saml_encrypt_assertions'] == 1) ->setUncheckedValue(0) - ->setEnabled($is_saml_auth_enabled) + ->setEnabled($data['saml_enabled']) ) ) ->addRow(new CLabel(_('Case sensitive login'), 'saml_case_sensitive'), (new CCheckBox('saml_case_sensitive')) ->setChecked($data['saml_case_sensitive'] == ZBX_AUTH_CASE_SENSITIVE) ->setUncheckedValue(ZBX_AUTH_CASE_INSENSITIVE) - ->setEnabled($is_saml_auth_enabled) + ->setEnabled($data['saml_enabled']) ); (new CWidget()) diff --git a/ui/include/classes/setup/CFrontendSetup.php b/ui/include/classes/setup/CFrontendSetup.php index e3105881095..ca7585525ac 100644 --- a/ui/include/classes/setup/CFrontendSetup.php +++ b/ui/include/classes/setup/CFrontendSetup.php @@ -82,6 +82,7 @@ class CFrontendSetup { $result[] = $this->checkPhpXmlWriter(); $result[] = $this->checkPhpXmlReader(); $result[] = $this->checkPhpLdapModule(); + $result[] = $this->checkPhpOpenSsl(); $result[] = $this->checkPhpCtype(); $result[] = $this->checkPhpSession(); $result[] = $this->checkPhpSessionAutoStart(); @@ -557,6 +558,23 @@ class CFrontendSetup { ]; } + /** + * Checks for PHP OpenSSL extension. + * + * @return array + */ + public function checkPhpOpenSsl() { + $current = extension_loaded('openssl'); + + return [ + 'name' => _('PHP OpenSSL'), + 'current' => $current ? _('on') : _('off'), + 'required' => null, + 'result' => $current ? self::CHECK_OK : self::CHECK_WARNING, + 'error' => _('PHP OpenSSL extension missing.') + ]; + } + /** * Checks for PHP ctype extension. * -- cgit v1.2.3 From 34f8fa0b5f32bc618c1baf0bb755057e92810219 Mon Sep 17 00:00:00 2001 From: Ivo Kurzemnieks Date: Thu, 6 Aug 2020 18:40:07 +0300 Subject: ..F....... [ZBX-18149] fixed discovered hosts showing links to host prototypes which should not possible * commit 'bf469ddc602a1f65b5240626cf5ee4d08e931aa9': ..F....... [ZBX-18149] removed accidentally added field to request ..F....... [ZBX-18149] fixed discovered hosts showing links to host prototypes which should not possible --- ChangeLog.d/bugfix/ZBX-18149 | 1 + ui/host_discovery.php | 2 +- ui/include/views/configuration.host.discovery.list.php | 14 ++++++++------ 3 files changed, 10 insertions(+), 7 deletions(-) create mode 100644 ChangeLog.d/bugfix/ZBX-18149 diff --git a/ChangeLog.d/bugfix/ZBX-18149 b/ChangeLog.d/bugfix/ZBX-18149 new file mode 100644 index 00000000000..049a662219a --- /dev/null +++ b/ChangeLog.d/bugfix/ZBX-18149 @@ -0,0 +1 @@ +..F....... [ZBX-18149] fixed discovered hosts showing links to host prototypes which should not possible (Ivo) diff --git a/ui/host_discovery.php b/ui/host_discovery.php index 83fb13431e0..94074b9025b 100644 --- a/ui/host_discovery.php +++ b/ui/host_discovery.php @@ -817,7 +817,7 @@ else { // Select LLD rules. $options = [ 'output' => API_OUTPUT_EXTEND, - 'selectHosts' => ['hostid', 'name', 'status'], + 'selectHosts' => ['hostid', 'name', 'status', 'flags'], 'selectItems' => API_OUTPUT_COUNT, 'selectGraphs' => API_OUTPUT_COUNT, 'selectTriggers' => API_OUTPUT_COUNT, diff --git a/ui/include/views/configuration.host.discovery.list.php b/ui/include/views/configuration.host.discovery.list.php index d9a8c7f9d00..c0c2f56bbce 100644 --- a/ui/include/views/configuration.host.discovery.list.php +++ b/ui/include/views/configuration.host.discovery.list.php @@ -263,12 +263,14 @@ foreach ($data['discoveries'] as $discovery) { ), CViewHelper::showNum($discovery['graphs']) ], - [ - new CLink(_('Host prototypes'), - (new CUrl('host_prototypes.php'))->setArgument('parent_discoveryid', $discovery['itemid']) - ), - CViewHelper::showNum($discovery['hostPrototypes']) - ], + ($discovery['hosts'][0]['flags'] == ZBX_FLAG_DISCOVERY_NORMAL) + ? [ + new CLink(_('Host prototypes'), + (new CUrl('host_prototypes.php'))->setArgument('parent_discoveryid', $discovery['itemid']) + ), + CViewHelper::showNum($discovery['hostPrototypes']) + ] + : '', (new CDiv(CHtml::encode($discovery['key_'])))->addClass(ZBX_STYLE_WORDWRAP), $discovery['delay'], item_type2str($discovery['type']), -- cgit v1.2.3