1<?php 2/* 3** Zabbix 4** Copyright (C) 2001-2021 Zabbix SIA 5** 6** This program is free software; you can redistribute it and/or modify 7** it under the terms of the GNU General Public License as published by 8** the Free Software Foundation; either version 2 of the License, or 9** (at your option) any later version. 10** 11** This program is distributed in the hope that it will be useful, 12** but WITHOUT ANY WARRANTY; without even the implied warranty of 13** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14** GNU General Public License for more details. 15** 16** You should have received a copy of the GNU General Public License 17** along with this program; if not, write to the Free Software 18** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19**/ 20 21 22require_once dirname(__FILE__).'/include/config.inc.php'; 23require_once dirname(__FILE__).'/include/services.inc.php'; 24require_once dirname(__FILE__).'/include/triggers.inc.php'; 25require_once dirname(__FILE__).'/include/html.inc.php'; 26 27$page['title'] = _('Configuration of services'); 28$page['file'] = 'services.php'; 29$page['scripts'] = ['class.calendar.js']; 30 31require_once dirname(__FILE__).'/include/page_header.php'; 32 33// VAR TYPE OPTIONAL FLAGS VALIDATION EXCEPTION 34$fields = [ 35 'serviceid' => [T_ZBX_INT, O_OPT, P_SYS, DB_ID, null], 36 'name' => [T_ZBX_STR, O_OPT, null, NOT_EMPTY, 'isset({add}) || isset({update})', _('Name')], 37 'algorithm' => [T_ZBX_INT, O_OPT, null, IN('0,1,2'),'isset({add}) || isset({update})'], 38 'showsla' => [T_ZBX_INT, O_OPT, null, IN([SERVICE_SHOW_SLA_OFF, SERVICE_SHOW_SLA_ON]), null], 39 'goodsla' => [T_ZBX_DBL, O_OPT, null, BETWEEN(0, 100), null, 40 _('Calculate SLA, acceptable SLA (in %)') 41 ], 42 'sortorder' => [T_ZBX_INT, O_OPT, null, BETWEEN(0, 999), null, _('Sort order (0->999)')], 43 'times' => [T_ZBX_STR, O_OPT, null, null, null], 44 'triggerid' => [T_ZBX_INT, O_OPT, P_SYS, DB_ID, null], 45 'trigger' => [T_ZBX_STR, O_OPT, null, null, null], 46 'new_service_time' => [T_ZBX_STR, O_OPT, null, null, null], 47 'new_service_time_from' => [T_ZBX_ABS_TIME, O_OPT, null, NOT_EMPTY, null, _('From')], 48 'new_service_time_till' => [T_ZBX_ABS_TIME, O_OPT, null, NOT_EMPTY, null, _('Till')], 49 'children' => [T_ZBX_STR, O_OPT, P_SYS, null, null], 50 'parentid' => [T_ZBX_INT, O_OPT, P_SYS, DB_ID, null], 51 'parentname' => [T_ZBX_STR, O_OPT, null, null, null], 52 // actions 53 'add' => [T_ZBX_STR, O_OPT, P_SYS|P_ACT, null, null], 54 'update' => [T_ZBX_STR, O_OPT, P_SYS|P_ACT, null, null], 55 'add_service_time' => [T_ZBX_STR, O_OPT, P_SYS|P_ACT, null, null], 56 'delete' => [T_ZBX_STR, O_OPT, P_SYS|P_ACT, null, null], 57 // others 58 'form' => [T_ZBX_STR, O_OPT, P_SYS, null, null], 59 'form_refresh' => [T_ZBX_INT, O_OPT, null, null, null] 60]; 61check_fields($fields); 62 63/* 64 * Permissions 65 */ 66if (!empty($_REQUEST['serviceid'])) { 67 $options = [ 68 'output' => API_OUTPUT_EXTEND, 69 'serviceids' => $_REQUEST['serviceid'] 70 ]; 71 72 if (isset($_REQUEST['delete'])) { 73 $options['output'] = ['serviceid', 'name']; 74 } 75 else { 76 $options['selectParent'] = ['serviceid', 'name']; 77 $options['selectDependencies'] = API_OUTPUT_EXTEND; 78 $options['selectTimes'] = API_OUTPUT_EXTEND; 79 } 80 81 $service = API::Service()->get($options); 82 $service = reset($service); 83 if (!$service && hasRequest('delete')) { 84 show_error_message(_('No permissions to referred object or it does not exist!')); 85 } 86 elseif (!$service) { 87 access_deny(); 88 } 89} 90 91/* 92 * Actions 93 */ 94 95// delete 96if (hasRequest('delete') && $service) { 97 DBstart(); 98 99 $result = API::Service()->delete([$service['serviceid']]); 100 101 if ($result) { 102 add_audit(AUDIT_ACTION_DELETE, AUDIT_RESOURCE_IT_SERVICE, 'Name ['.$service['name'].'] id ['.$service['serviceid'].']'); 103 unset($_REQUEST['form']); 104 } 105 unset($service); 106 107 $result = DBend($result); 108 show_messages($result, _('Service deleted'), _('Cannot delete service')); 109} 110 111$service_times = []; 112 113if (hasRequest('add') || hasRequest('update')) { 114 DBstart(); 115 116 $children = getRequest('children', []); 117 $dependencies = []; 118 119 foreach ($children as $child) { 120 $dependencies[] = [ 121 'dependsOnServiceid' => $child['serviceid'], 122 'soft' => (isset($child['soft'])) ? $child['soft'] : 0 123 ]; 124 } 125 126 $request = [ 127 'name' => getRequest('name'), 128 'triggerid' => getRequest('triggerid'), 129 'algorithm' => getRequest('algorithm'), 130 'showsla' => getRequest('showsla', SERVICE_SHOW_SLA_OFF), 131 'sortorder' => getRequest('sortorder'), 132 'times' => getRequest('times', []), 133 'parentid' => getRequest('parentid'), 134 'dependencies' => $dependencies 135 ]; 136 137 if (hasRequest('goodsla')) { 138 $request['goodsla'] = getRequest('goodsla'); 139 } 140 141 if (isset($service['serviceid'])) { 142 $request['serviceid'] = $service['serviceid']; 143 144 $result = API::Service()->update($request); 145 146 $messageSuccess = _('Service updated'); 147 $messageFailed = _('Cannot update service'); 148 $auditAction = AUDIT_ACTION_UPDATE; 149 } 150 else { 151 $result = API::Service()->create($request); 152 153 $messageSuccess = _('Service created'); 154 $messageFailed = _('Cannot add service'); 155 $auditAction = AUDIT_ACTION_ADD; 156 } 157 158 if ($result) { 159 $serviceid = (isset($service['serviceid'])) ? $service['serviceid'] : reset($result['serviceids']); 160 add_audit($auditAction, AUDIT_RESOURCE_IT_SERVICE, 'Name ['.$_REQUEST['name'].'] id ['.$serviceid.']'); 161 unset($_REQUEST['form']); 162 } 163 164 $result = DBend($result); 165 show_messages($result, $messageSuccess, $messageFailed); 166} 167// Validate and get service times. 168elseif (hasRequest('add_service_time') && hasRequest('new_service_time')) { 169 $new_service_time = getRequest('new_service_time'); 170 $_REQUEST['times'] = getRequest('times', []); 171 $result = true; 172 173 if ($new_service_time['type'] == SERVICE_TIME_TYPE_ONETIME_DOWNTIME) { 174 $absolute_time_parser = new CAbsoluteTimeParser(); 175 176 $absolute_time_parser->parse(getRequest('new_service_time_from')); 177 $new_service_time_from = $absolute_time_parser->getDateTime(true); 178 179 if (!validateDateInterval($new_service_time_from->format('Y'), $new_service_time_from->format('m'), 180 $new_service_time_from->format('d'))) { 181 $result = false; 182 error(_s('"%s" must be between 1970.01.01 and 2038.01.18.', _('From'))); 183 } 184 185 $absolute_time_parser->parse(getRequest('new_service_time_till')); 186 $new_service_time_till = $absolute_time_parser->getDateTime(true); 187 188 if (!validateDateInterval($new_service_time_till->format('Y'), $new_service_time_till->format('m'), 189 $new_service_time_till->format('d'))) { 190 $result = false; 191 error(_s('"%s" must be between 1970.01.01 and 2038.01.18.', _('Till'))); 192 } 193 194 if ($result) { 195 $new_service_time['ts_from'] = $new_service_time_from->getTimestamp(); 196 $new_service_time['ts_to'] = $new_service_time_till->getTimestamp(); 197 } 198 } 199 else { 200 $new_service_time['ts_from'] = dowHrMinToSec($new_service_time['from_week'], $new_service_time['from_hour'], 201 $new_service_time['from_minute'] 202 ); 203 $new_service_time['ts_to'] = dowHrMinToSec($new_service_time['to_week'], $new_service_time['to_hour'], 204 $new_service_time['to_minute'] 205 ); 206 } 207 208 if ($result) { 209 try { 210 checkServiceTime($new_service_time); 211 212 // If this time is not already there, adding it for inserting. 213 unset($new_service_time['from_week']); 214 unset($new_service_time['to_week']); 215 unset($new_service_time['from_hour']); 216 unset($new_service_time['to_hour']); 217 unset($new_service_time['from_minute']); 218 unset($new_service_time['to_minute']); 219 220 if (!str_in_array($new_service_time, $_REQUEST['times'])) { 221 $_REQUEST['times'][] = $new_service_time; 222 } 223 } 224 catch (APIException $e) { 225 error($e->getMessage()); 226 } 227 } 228 229 show_messages(); 230} 231else { 232 unset($_REQUEST['new_service_time']['from_week']); 233 unset($_REQUEST['new_service_time']['to_week']); 234 unset($_REQUEST['new_service_time']['from_hour']); 235 unset($_REQUEST['new_service_time']['to_hour']); 236 unset($_REQUEST['new_service_time']['from_minute']); 237 unset($_REQUEST['new_service_time']['to_minute']); 238} 239 240if (hasRequest('form')) { 241 $data = [ 242 'form' => getRequest('form'), 243 'form_refresh' => getRequest('form_refresh', 0), 244 'service' => (getRequest('serviceid', 0) != 0) ? $service : null, 245 'times' => getRequest('times', []), 246 'new_service_time' => getRequest('new_service_time', ['type' => SERVICE_TIME_TYPE_UPTIME]) 247 ]; 248 249 // Populate the form from the object from the database. 250 if (getRequest('serviceid', 0) != 0 && !hasRequest('form_refresh')) { 251 $data['name'] = $data['service']['name']; 252 $data['algorithm'] = $data['service']['algorithm']; 253 $data['showsla'] = $data['service']['showsla']; 254 $data['goodsla'] = $data['service']['goodsla']; 255 $data['sortorder'] = $data['service']['sortorder']; 256 $data['triggerid'] = isset($data['service']['triggerid']) ? $data['service']['triggerid'] : 0; 257 $data['times'] = $service['times']; 258 259 // parent 260 if ($parent = $service['parent']) { 261 $data['parentid'] = $parent['serviceid']; 262 $data['parentname'] = $parent['name']; 263 } 264 else { 265 $data['parentid'] = 0; 266 $data['parentname'] = 'root'; 267 } 268 269 // get children 270 $data['children'] = []; 271 if ($service['dependencies']) { 272 $child_services = API::Service()->get([ 273 'serviceids' => zbx_objectValues($service['dependencies'], 'servicedownid'), 274 'selectTrigger' => ['description'], 275 'output' => ['name', 'triggerid'], 276 'preservekeys' => true 277 ]); 278 279 foreach ($service['dependencies'] as $dependency) { 280 $child_service = $child_services[$dependency['servicedownid']]; 281 $data['children'][] = [ 282 'name' => $child_service['name'], 283 'triggerid' => $child_service['triggerid'], 284 'trigger' => ($child_service['triggerid'] == 0) ? '' : $child_service['trigger']['description'], 285 'serviceid' => $dependency['servicedownid'], 286 'soft' => $dependency['soft'] 287 ]; 288 } 289 290 CArrayHelper::sort($data['children'], ['name', 'serviceid']); 291 } 292 } 293 // Populate the form from a submitted request. 294 else { 295 $new_service_time = getRequest('new_service_time'); 296 297 if ($new_service_time && $new_service_time['type'] == SERVICE_TIME_TYPE_ONETIME_DOWNTIME) { 298 $data['new_service_time_from'] = hasRequest('new_service_time_from') 299 ? getRequest('new_service_time_from') 300 : (new DateTime('today'))->format(ZBX_DATE_TIME); 301 302 $data['new_service_time_till'] = hasRequest('new_service_time_till') 303 ? getRequest('new_service_time_till') 304 : (new DateTime('tomorrow'))->format(ZBX_DATE_TIME); 305 } 306 307 $data['name'] = getRequest('name', ''); 308 $data['algorithm'] = getRequest('algorithm', SERVICE_ALGORITHM_MAX); 309 $data['showsla'] = getRequest('showsla', SERVICE_SHOW_SLA_OFF); 310 $data['goodsla'] = getRequest('goodsla', SERVICE_SLA); 311 $data['sortorder'] = getRequest('sortorder', 0); 312 $data['triggerid'] = getRequest('triggerid', 0); 313 $data['parentid'] = getRequest('parentid', 0); 314 $data['parentname'] = getRequest('parentname', ''); 315 $data['children'] = getRequest('children', []); 316 } 317 318 // get trigger 319 if ($data['triggerid'] > 0) { 320 $trigger = API::Trigger()->get([ 321 'triggerids' => $data['triggerid'], 322 'output' => ['description'], 323 'selectHosts' => ['name'], 324 'expandDescription' => true 325 ]); 326 $trigger = reset($trigger); 327 $host = reset($trigger['hosts']); 328 $data['trigger'] = $host['name'].NAME_DELIMITER.$trigger['description']; 329 } 330 else { 331 $data['trigger'] = ''; 332 } 333 334 // render view 335 $servicesView = new CView('configuration.services.edit', $data); 336 $servicesView->render(); 337 $servicesView->show(); 338} 339else { 340 // services 341 $services = API::Service()->get([ 342 'output' => ['name', 'serviceid', 'algorithm', 'sortorder'], 343 'selectParent' => ['serviceid'], 344 'selectDependencies' => ['servicedownid', 'soft', 'linkid'], 345 'selectTrigger' => ['description'], 346 'preservekeys' => true 347 ]); 348 349 sortServices($services); 350 351 $treeData = []; 352 createServiceConfigurationTree($services, $treeData); 353 $tree = new CServiceTree('service_conf_tree', $treeData, [ 354 'caption' => _('Service'), 355 'action' => _('Action'), 356 'algorithm' => _('Status calculation'), 357 'description' => _('Trigger') 358 ]); 359 if (empty($tree)) { 360 error(_('Cannot format tree.')); 361 } 362 363 $data = ['tree' => $tree]; 364 365 // render view 366 $servicesView = new CView('configuration.services.list', $data); 367 $servicesView->render(); 368 $servicesView->show(); 369} 370 371require_once dirname(__FILE__).'/include/page_footer.php'; 372