histogram: Make histograms crash less
[ninja.git] / application / controllers / command.php
blob37b187cd0994b6a0b8d171b1ef77760f5c7ffbf5
1 <?php defined('SYSPATH') OR die('No direct access allowed.');
2 /**
3 * CMD controller
5 * Requires authentication. See the helper nagioscmd for more info.
7 * op5, and the op5 logo are trademarks, servicemarks, registered servicemarks
8 * or registered trademarks of op5 AB.
9 * All other trademarks, servicemarks, registered trademarks, and registered
10 * servicemarks mentioned herein may be the property of their respective owner(s).
11 * The information contained herein is provided AS IS with NO WARRANTY OF ANY
12 * KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY, AND FITNESS FOR A
13 * PARTICULAR PURPOSE.
15 class Command_Controller extends Authenticated_Controller
17 private $command_id = false;
18 private $cmd_params = array();
19 private $csrf_token = false;
20 /**
21 * @var int = 300, if the starting time of a scheduled downtime is
22 * older than this many seconds, it's considered to have been added retrospectively
24 private $grace_time_in_s = 300;
26 /**
27 * Initializes a page with the correct view, java-scripts and css
28 * @param $view The name of the page we want to print
30 protected function init_page($view)
32 $this->template->content = $this->add_view($view);
33 $this->template->disable_refresh = true;
36 /**
37 * @param string $submitted_start_time (Y-m-d H:i:s)
38 * @param string $submitted_end_time (Y-m-d H:i:s)
39 * @return true | string (string = error message)
41 private function _validate_dates($submitted_start_time, $submitted_end_time) {
42 $start_time = nagstat::timestamp_format(nagstat::date_format(), $submitted_start_time);
43 $end_time = nagstat::timestamp_format(nagstat::date_format(), $submitted_end_time);
44 $errors = array();
45 if(!$start_time || !$end_time) {
46 if(!$start_time && !$end_time) {
47 return "Neither of your submitted dates are valid, please <a href='javascript:history.back();'>adjust them</a>";
48 } else {
49 return sprintf("%s is not a valid date, please <a href='javascript:history.back();'>adjust it</a>", $start_time ? $submitted_end_time : $submitted_start_time);
52 if($start_time > $end_time) {
53 return sprintf("The downtime can not end before it starts. Please <a href='javascript:history.back();'>adjust it</a>", $submitted_start_time);
55 return true;
58 /**
59 * Create a standard checkbox item
60 * @param $description The user visible text for this option
61 * @param $name The internal name for this option
62 * @return array suitable for passing to the request template
64 protected function cb($description, $name)
66 $value = Execute_Command_Model::get_setting($name);
67 return array('type' => 'checkbox', 'name' => $description, 'default' => $value);
70 /**
71 * Request a command to be submitted
72 * This method prints input fields to be selected for the
73 * named command.
74 * @param $name The requested command to run
75 * @param $parameters The parameters (host_name etc) for the command
77 public function submit($cmd = false, $params=false)
79 $this->init_page('command/request');
80 $this->xtra_js[] = $this->add_path('command/js/command.js');
82 if ($cmd === false) {
83 $cmd = $this->input->get('cmd_typ');
86 if ($params === false) {
87 $params = $_GET;
90 if (($auth_check = nagioscmd::is_authorized_for($params)) !== true)
91 return $this->unauthorized($auth_check);
93 $this->template->content->cmd_typ = $cmd;
95 $command = new Execute_Command_Model;
96 $info = $command->get_command_info($cmd, $params);
97 $param = $info['params'];
98 switch ($cmd) {
99 case 'DEL_HOST_COMMENT':
100 case 'DEL_SVC_COMMENT':
101 $param['comment_id']['type'] = 'immutable';
102 break;
103 case 'SCHEDULE_HOST_CHECK':
104 case 'SCHEDULE_SVC_CHECK':
105 case 'SCHEDULE_HOST_SVC_CHECKS':
106 $param['_force'] = $this->cb(_('Force Check'), '_force');
107 break;
109 case 'PROCESS_HOST_CHECK_RESULT':
110 case 'PROCESS_SERVICE_CHECK_RESULT':
111 $param['_perfdata'] = array
112 ('type' => 'string',
113 'size' => 100,
114 'name' => _('Performance data'));
115 break;
117 case 'SCHEDULE_HOST_DOWNTIME':
118 $this->template->inline_js = "grace_time_in_s = '$this->grace_time_in_s'";
119 $this->xtra_js[] = $this->add_path('command/js/schedule_downtime.js');
120 $param['_child-hosts'] = array
121 ('type' => 'select',
122 'options' => array
123 ('none' => _('Do nothing'),
124 'triggered' => _('Schedule triggered downtime'),
125 'fixed' => _('Schedule fixed downtime')),
126 'default' => 'triggered',
127 'name' => _('Child Hosts'));
128 # fallthrough
129 case 'SCHEDULE_HOSTGROUP_HOST_DOWNTIME':
130 break;
131 case 'SCHEDULE_SVC_DOWNTIME':
132 $this->template->inline_js = "grace_time_in_s = '$this->grace_time_in_s'";
133 $this->xtra_js[] = $this->add_path('command/js/schedule_downtime.js');
134 break;
136 case 'SEND_CUSTOM_SVC_NOTIFICATION':
137 case 'SEND_CUSTOM_HOST_NOTIFICATION':
138 $param['_broadcast'] = $this->cb(_('Broadcast'), '_broadcast');
139 $param['_force'] = $this->cb(_('Force notification'), '_force');
140 $param['_increment'] = $this->cb(_('Increment notification number'), '_increment');
141 break;
143 case 'ENABLE_HOST_SVC_CHECKS':
144 case 'DISABLE_HOST_SVC_CHECKS':
145 case 'ENABLE_HOSTGROUP_SVC_CHECKS':
146 case 'DISABLE_HOSTGROUP_SVC_CHECKS':
147 case 'ENABLE_SERVICEGROUP_SVC_CHECKS':
148 case 'DISABLE_SERVICEGROUP_SVC_CHECKS':
149 $en_dis = $cmd{0} === 'E' ? _('Enable') : _('Disable');
150 $param['_host-too'] = $this->cb(sprintf(_('%s checks for host too'), $en_dis), '_host-too');
151 break;
153 case 'ENABLE_HOST_CHECK':
154 case 'DISABLE_HOST_CHECK':
155 $en_dis = $cmd{0} === 'E' ? _('Enable') : _('Disable');
156 $param['_services-too'] = $this->cb(sprintf(_('%s checks for services too'), $en_dis), '_services-too');
157 break;
159 case 'ENABLE_HOST_SVC_NOTIFICATIONS':
160 case 'DISABLE_HOST_SVC_NOTIFICATIONS':
161 $en_dis = $cmd{0} === 'E' ? _('Enable') : _('Disable');
162 $param['_host-too'] = $this->cb(sprintf(_('%s notifications for host too'), $en_dis), '_host-too');
163 break;
165 case 'ACKNOWLEDGE_HOST_PROBLEM':
166 $param['_services-too'] = $this->cb(_('Acknowledge any problems on services too'), '_services-too');
167 break;
168 case 'REMOVE_HOST_ACKNOWLEDGEMENT':
169 $param['_services-too'] = $this->cb(_('Remove any acknowledgements on services too'), '_services-too');
170 break;
171 case 'NACOMA_DEL_SERVICE':
172 $res = array();
173 foreach ($params['service'] as $service) {
174 if (($hg = nacoma::getHostgroupForService($service)))
175 $res[$service] = $hg;
178 if ($res) {
179 $info['brief'] = ngettext(
180 "You've selected a service that is saved on a hostgroup",
181 "You've selected services that are saved on hostgroups", count($res));;
182 $info['description'] = '<ul>';
183 foreach ($res as $svc => $hg) {
184 $info['description'] .= sprintf(_('<li>%s is saved on %s</li>'), $svc, $hg);
186 $info['description'] .= '</ul><p>'.ngettext(
187 'Deleting it will delete it from all hosts in the hostgroup. Are you sure? You might instead want to create a better service directly on the host.',
188 'Deleting them will delete them from all the hosts in the hostgroup. Are you sure? You might instead want to create better services directly on the affected hosts.', count($res)).'</p>';
189 break;
191 case 'NACOMA_DEL_HOST':
192 return $this->commit($cmd, $params);
193 break;
194 default:
195 break;
197 $info['params'] = $param;
199 $this->template->content->info = $info;
200 return $info;
203 protected function schedule_retrospectively($selector_type, $target_type, $obj_names, $start_time, $end_time, $comment)
205 $start_time = nagstat::timestamp_format(nagstat::date_format(), $start_time);
206 $end_time = nagstat::timestamp_format(nagstat::date_format(), $end_time);
207 $now = time();
209 if ($start_time + $this->grace_time_in_s >= $now)
210 return;
212 if (!is_array($obj_names))
213 $obj_names = array($obj_names);
215 // Some Assembly Required
216 if ($selector_type != $target_type) {
217 $ls = Livestatus::instance();
218 $individual_objs = array();
219 if ($target_type === 'service' && $selector_type === 'servicegroup') {
220 foreach ($obj_names as $gname) {
221 foreach ($ls->getServices(array('filter' => array('groups' => array('>=' => $gname)), 'columns' => array('host_name', 'description'))) as $row) {
222 $individual_objs[] = $row['host_name'].';'.$row['description'];
226 else if ($target_type === 'service' && $selector_type === 'hostgroup') {
227 foreach ($obj_names as $gname) {
228 foreach ($ls->getServices(array('filter' => array('host_groups' => array('>=' => $gname)), 'columns' => array('host_name', 'description'))) as $row) {
229 $individual_objs[] = $row['host_name'].';'.$row['description'];
233 else if ($target_type === 'host' && $selector_type === 'hostgroup') {
234 foreach ($obj_names as $gname) {
235 foreach ($ls->getHosts(array('filter' => array('groups' => array('>=' => $gname)), 'columns' => array('name'))) as $row) {
236 $individual_objs[$row['name']] = 1;
239 $individual_objs = array_keys($individual_objs);
241 else if ($target_type === 'host' && $selector_type === 'servicegroup') {
242 foreach ($obj_names as $gname) {
243 foreach ($ls->getServices(array('filter' => array('groups' => array('>=' => $gname)), 'columns' => array('host_name'))) as $row) {
244 $individual_objs[$row['host_name']] = 1;
247 $individual_objs = array_keys($individual_objs);
249 else if ($target_type === 'service' && $selector_type === 'host') {
250 foreach ($obj_names as $hname) {
251 foreach ($ls->getServices(array('filter' => array('host_name' => $hname), 'columns' => array('host_name', 'description'))) as $row) {
252 $individual_objs[] = $row['host_name'].';'.$row['description'];
256 $obj_names = $individual_objs;
259 $db = Database::instance();
260 foreach ($obj_names as $obj_name) {
261 if ($target_type == 'service') {
262 list($host_name, $service_desc) = explode(';', $obj_name);
263 $host_name = $db->escape($host_name);
264 $service_desc = $db->escape($service_desc);
266 else {
267 $host_name = $db->escape($obj_name);
268 $service_desc = "''";
270 $start_msg = $db->escape(ucfirst($selector_type)." has entered a period of retroactively added scheduled downtime, reported by '".Auth::instance()->get_user()->username."', reason: '".$comment."'");
271 $end_msg = $db->escape(ucfirst($selector_type)." has exited a period of retroactively added scheduled downtime, reported by '".Auth::instance()->get_user()->username."', reason: '".$comment."'");
273 $db->query("INSERT INTO report_data(timestamp, event_type, host_name, service_description, downtime_depth, output) VALUES ($start_time, 1103, $host_name, $service_desc, 1, $start_msg)");
274 $db->query("INSERT INTO report_data_extras(timestamp, event_type, host_name, service_description, downtime_depth, output) VALUES ($start_time, 1103, $host_name, $service_desc, 1, $start_msg)");
275 $db->query("INSERT INTO report_data(timestamp, event_type, host_name, service_description, downtime_depth, output) VALUES ($end_time, 1104, $host_name, $service_desc, 0, $end_msg)");
276 $db->query("INSERT INTO report_data_extras(timestamp, event_type, host_name, service_description, downtime_depth, output) VALUES ($end_time, 1104, $host_name, $service_desc, 0, $end_msg)");
281 * Takes the command parameters given by the "submit" function
282 * and creates a Nagios command that gets fed to Nagios through
283 * the query handler.
285 public function commit($cmd = false, $param=false)
287 if (!$cmd) {
288 if(!isset($_REQUEST['cmd_typ']))
289 return $this->unauthorized();
290 $cmd = $_REQUEST['cmd_typ'];
293 if (!$param)
294 $param = isset($_REQUEST['cmd_param']) ? $_REQUEST['cmd_param'] : array();
296 $this->init_page('command/commit');
297 $this->template->content->cmd_typ = $cmd;
299 $nagios_commands = array();
300 if (($auth_check = nagioscmd::is_authorized_for($param, $cmd)) !== true)
301 return $this->unauthorized($auth_check);
303 $param['author'] = Auth::instance()->get_user()->username;
305 if (isset($param['comment']) && trim($param['comment'])=='') {
306 # comments shouldn't ever be empty
307 $this->template->content->result = false;
308 $this->template->content->error = _("Required field 'Comment' was not entered").'<br />'.
309 _(sprintf('Go %s back %s and verify that you entered all required information correctly', '<a href="javascript:history.back();">', '</a>'));
310 return false;
312 $fallthrough = false;
313 switch ($cmd) {
314 case 'SCHEDULE_HOST_CHECK':
315 case 'SCHEDULE_SVC_CHECK':
316 case 'SCHEDULE_HOST_SVC_CHECKS':
317 if (!empty($param['_force'])) {
318 unset($param['force']);
319 $cmd = 'SCHEDULE_FORCED' . substr($cmd, strlen("SCHEDULE"));
321 break;
323 case 'PROCESS_HOST_CHECK_RESULT':
324 case 'PROCESS_SERVICE_CHECK_RESULT':
325 if (!empty($param['_perfdata']) && !empty($param['plugin_output'])) {
326 $param['plugin_output'] .= "|".$param['_perfdata'];
327 unset($param['perfdata']);
329 break;
331 case 'SCHEDULE_HOST_DOWNTIME':
332 $date_validation_result = $this->_validate_dates($param['start_time'], $param['end_time']);
333 if($date_validation_result !== true) {
334 $this->template->content->result = false;
335 $this->template->content->error = $date_validation_result;
336 return;
338 if (!empty($param['_child-hosts']) && $param['_child-hosts'] != 'none') {
339 $what = $param['_child-hosts'];
340 unset($param['_child-hosts']);
341 if ($what === 'triggered') {
342 $cmd = 'SCHEDULE_AND_PROPAGATE_TRIGGERED_HOST_DOWNTIME';
343 } elseif ($what === 'fixed') {
344 $cmd = 'SCHEDULE_AND_PROPAGATE_HOST_DOWNTIME';
347 if(isset($param['fixed']) && $param['fixed']) {
348 $this->schedule_retrospectively('host', 'host', $param['host_name'], $param['start_time'], $param['end_time'], $param['comment']);
350 $fallthrough = true;
351 # fallthrough to services-too handling
352 case 'SCHEDULE_HOSTGROUP_HOST_DOWNTIME':
353 if(!$fallthrough && isset($param['fixed']) && $param['fixed']) {
354 $this->schedule_retrospectively('hostgroup', 'host', $param['hostgroup_name'], $param['start_time'], $param['end_time'], $param['comment']);
356 if (!empty($param['_services-too'])) {
357 unset($param['_services-too']);
358 if ($fallthrough) {
359 $nagios_commands = array_merge($this->_build_command('SCHEDULE_HOST_SVC_DOWNTIME', $param), $nagios_commands);
360 } else {
361 $nagios_commands = array_merge($this->_build_command('SCHEDULE_HOSTGROUP_SVC_DOWNTIME', $param), $nagios_commands);
363 if(isset($param['fixed']) && $param['fixed']) {
364 $grouptype = $fallthrough?'host':'hostgroup';
365 $this->schedule_retrospectively($grouptype, 'service', $param[$grouptype.'_name'], $param['start_time'], $param['end_time'], $param['comment']);
368 break;
370 case 'SEND_CUSTOM_HOST_NOTIFICATION':
371 case 'SEND_CUSTOM_SVC_NOTIFICATION':
372 $options = 0;
373 if (isset($param['_broadcast'])) {
374 unset($param['_broadcast']);
375 $options |= 1;
377 if (isset($param['_force'])) {
378 unset($param['_force']);
379 $options |= 2;
381 if (isset($param['_increment'])) {
382 unset($param['_increment']);
383 $options |= 4;
386 $param['options'] = $options;
387 break;
389 case 'ENABLE_HOST_SVC_CHECKS':
390 case 'DISABLE_HOST_SVC_CHECKS':
391 $xcmd = $cmd{0} === 'D' ? 'DISABLE' : 'ENABLE';
392 $xcmd .= '_HOST_CHECK';
393 if (!empty($param['_host-too']))
394 $nagios_commands = $this->_build_command($xcmd, $param);
395 break;
397 case 'ENABLE_HOST_CHECK':
398 case 'DISABLE_HOST_CHECK':
399 $xcmd = $cmd{0} === 'D' ? 'DISABLE' : 'ENABLE';
400 $xcmd .= '_HOST_SVC_CHECKS';
401 if (!empty($param['_services-too']))
402 $nagios_commands = $this->_build_command($xcmd, $param);
403 break;
405 case 'ENABLE_HOST_SVC_NOTIFICATIONS':
406 case 'DISABLE_HOST_SVC_NOTIFICATIONS':
407 $xcmd = $cmd{0} === 'D' ? 'DISABLE' : 'ENABLE';
408 $xcmd .= '_HOST_NOTIFICATIONS';
409 if (!empty($param['_host-too']))
410 $nagios_commands = $this->_build_command($xcmd, $param);
411 break;
412 case 'ENABLE_HOSTGROUP_SVC_CHECKS':
413 case 'DISABLE_HOSTGROUP_SVC_CHECKS':
414 case 'ENABLE_SERVICEGROUP_SVC_CHECKS':
415 case 'DISABLE_SERVICEGROUP_SVC_CHECKS':
416 case 'ENABLE_HOSTGROUP_SVC_NOTIFICATIONS':
417 case 'DISABLE_HOSTGROUP_SVC_NOTIFICATIONS':
418 case 'ENABLE_SERVICEGROUP_SVC_NOTIFICATIONS':
419 case 'DISABLE_SERVICEGROUP_SVC_NOTIFICATIONS':
420 case 'SCHEDULE_HOSTGROUP_SVC_DOWNTIME':
421 case 'SCHEDULE_SERVICEGROUP_SVC_DOWNTIME':
422 if(strpos($cmd, 'DOWNTIME') && isset($param['fixed']) && $param['fixed']) {
423 $grouptype = strtolower(substr($cmd, 9, strpos($cmd, '_', 10) - 9));
424 $this->schedule_retrospectively($grouptype, 'service', $param[$grouptype.'_name'], $param['start_time'], $param['end_time'], $param['comment']);
425 if (!empty($param['_host-too']))
426 $this->schedule_retrospectively($grouptype, 'host', $param[$grouptype.'_name'], $param['start_time'], $param['end_time'], $param['comment']);
428 if (!empty($param['_host-too'])) {
429 unset($param['_host-too']);
430 $xcmd = str_replace('SVC', 'HOST', $cmd);
431 $nagios_commands = $this->_build_command($xcmd, $param);
433 break;
434 case 'SCHEDULE_SVC_DOWNTIME':
435 if(isset($param['fixed']) && $param['fixed']) {
436 $this->schedule_retrospectively('service', 'service', $param['service'], $param['start_time'], $param['end_time'], $param['comment']);
438 $date_validation_result = $this->_validate_dates($param['start_time'], $param['end_time']);
439 if($date_validation_result !== true) {
440 $this->template->content->result = false;
441 $this->template->content->error = $date_validation_result;
442 return;
444 break;
445 case 'ACKNOWLEDGE_HOST_PROBLEM':
446 case 'REMOVE_HOST_ACKNOWLEDGEMENT':
447 if (!empty($param['_services-too'])) {
448 unset($param['_services-too']);
449 $xcmd = str_replace('HOST', 'SVC', $cmd);
450 $ls = Livestatus::instance();
451 $host_names = $param['host_name'];
452 if (!is_array($host_names))
453 $host_names = array($host_names);
454 $xparam = $param;
455 unset($xparam['host_name']);
456 foreach ($host_names as $host_name) {
457 $services = $ls->getServices(array('filter' => array('host_name' => $host_name), 'columns' => array('description')));
458 if($services) {
459 foreach($services as $service) {
460 $xparam['service'] = $host_name.';'.$service['description'];
461 $nagios_commands = $this->_build_command($xcmd, $xparam, $nagios_commands);
466 break;
467 case 'SCHEDULE_SERVICEGROUP_HOST_DOWNTIME':
468 if(isset($param['fixed']) && $param['fixed']) {
469 $this->schedule_retrospectively('servicegroup', 'host', $param['servicegroup_name'], $param['start_time'], $param['end_time'], $param['comment']);
471 break;
472 case 'NACOMA_DEL_HOST':
473 case 'NACOMA_DEL_SERVICE':
474 // Delete the host/service then route to NACOMA SAVE_CONFIG page
475 $res = true;
476 if (isset($param['service'])) {
477 foreach ($param['service'] as $service) {
478 $res &= nacoma::delService($service);
482 if (isset($param['host_name'])) {
483 foreach ($param['host_name'] as $host) {
484 $res &= nacoma::delHost($host);
488 if ($res)
489 return url::redirect('/configuration/configure?page=export.php');
490 break;
493 $nagios_commands = $this->_build_command($cmd, $param, $nagios_commands);
495 if (empty($nagios_commands))
496 $this->template->content->result = false;
498 $this->template->content->result = true;
499 while ($ncmd = array_pop($nagios_commands)) {
500 //Clarification: not submitting any more commands if a
501 //previous one failed (indicated by && which
502 //never continues if result is false
503 $this->template->content->result = $this->template->content->result && nagioscmd::submit_to_nagios($ncmd);
508 * Display "You're not authorized" message
510 public function unauthorized($state=false)
512 $this->template->content = $this->add_view('command/unauthorized');
513 $this->template->content->error_message = _('You are not authorized to submit the specified command.');
514 switch ($state) {
515 case -1: # No command passed
516 $this->template->content->error_message = _('No command specified.');
517 $this->template->content->error_description = _('Please enter a valid '.
518 'command or use the available links in the GUI.');
519 break;
520 case -2: # Contact can't submit commands
521 $this->template->content->error_description = _("Your contact doesn't seem to configured ".
522 "to allow you to submit commands (i.e 'can_submit_commands' is not enabled). Please contact an administrator ".
523 "to enable this for you. ");
524 break;
525 case -3: # not authorized from cgi.cfg, and not a configured contact
526 $this->template->content->error_description = _("Your account doesn't have a " .
527 "configured contact, nor does it have permissions to submit commands to all " .
528 "objects. Please contact an administrator for assistance.");
529 break;
530 case -4:
531 $this->template->content->error_description = _("Your account isn't authorized " .
532 "to submit commands for this object type. Please contact an administrator for assistance.");
533 break;
534 case -5:
535 $this->template->content->error_description = _("Your account isn't authorized " .
536 "to submit commands for this object. Please contact an administrator for assistance.");
537 break;
539 default: # fallthrough, not authorized for anything
540 $this->template->content->error_description = _('Read the section of the '.
541 'documentation that deals with authentication and authorization in the CGIs for more information.');
544 $this->template->content->return_link_lable = _('Return from where you came');
548 * Translated helptexts for this controller
550 public static function _helptexts($id)
552 # No helptexts defined yet - this is just an example
553 # Tag unfinished helptexts with @@@HELPTEXT:<key> to make it
554 # easier to find those later
555 $helptexts = array(
556 'downtime_id' =>
557 _ ("The downtime you want to delete/cancel"),
558 'triggered_by' =>
559 _ ("With triggered downtime the start of the downtime ".
560 "is triggered by the start of some other scheduled " .
561 "host or service downtime"),
562 'duration' =>
563 _("Duration is given as a decimal value of full hours. " .
564 "Thus, 1h 15m should be written as <b>1.25</b>"),
566 if (array_key_exists($id, $helptexts)) {
567 echo $helptexts[$id];
569 else
570 echo sprintf(_("This helptext ('%s') is not translated yet"), $id);
574 * Handle submitting of one command for multiple objects
576 public function multi_action()
578 if (!isset($_REQUEST['multi_action'])) {
579 $this->template->content = $this->add_view('error');
580 $this->template->content->error_message = '<br /> &nbsp;'._('ERROR: Missing action parameter - unable to process request');
581 return false;
583 if (!isset($_REQUEST['object_select'])) {
584 $this->template->content = $this->add_view('error');
585 $this->template->content->error_message = '<br /> &nbsp;'._('ERROR: Missing objects - unable to process request');
586 return false;
588 if (!isset($_REQUEST['obj_type'])) {
589 $this->template->content = $this->add_view('error');
590 $this->template->content->error_message = '<br /> &nbsp;'._('ERROR: Missing object type - unable to process request');
591 return false;
594 $cmd_typ = $_REQUEST['multi_action'];
595 $obj_type = $_REQUEST['obj_type'];
596 $objects = $_REQUEST['object_select'];
598 $param_name = false;
599 switch ($obj_type) {
600 case 'hosts':
601 $param_name = 'host_name';
602 break;
603 case 'services':
604 $param_name = 'service';
605 break;
606 case 'hostgroups':
607 $param_name = 'hostgroup_name';
608 break;
609 case 'servicegroups':
610 $param_name = 'servicegroup_name';
611 break;
612 case 'comments':
613 $param_name = 'comment_id';
614 break;
615 case 'downtimes':
616 $param_name = 'downtime_id';
617 break;
620 $params = false;
622 foreach ($objects as $obj) {
623 $params[$param_name][] = $obj;
626 if (!empty($params) && !empty($cmd_typ)) {
627 $params['cmd_typ'] = $cmd_typ;
628 return $this->submit($cmd_typ, $params);
631 $this->template->content = $this->add_view('error');
632 $this->template->content->error_message = '<br /> &nbsp;'._('ERROR: Missing parameters - unable to process request');
633 return false;
637 * Wrapper around nagioscmd::build_command() to be able
638 * to create valid commands for multiple objects at once
640 public function _build_command($cmd = false, $param = false, $nagios_commands = false)
642 if (
643 (isset($param['host_name']) && is_array($param['host_name'])) ||
644 (isset($param['service']) && is_array($param['service'])) )
645 { # we have a multi command, i.e one command for multiple objects
647 # remove host_name (or service) from param
648 if (isset($param['host_name'])) {
649 $obj_list = $param['host_name'];
650 unset($param['host_name']);
651 $param_str = 'host_name';
652 } else {
653 $obj_list = $param['service'];
654 unset($param['service']);
655 $param_str = 'service';
658 # create new param array for each object
659 foreach ($obj_list as $obj) {
660 $multi_param = false;
661 $multi_param = $param;
662 $multi_param[$param_str] = $obj;
663 $nagios_commands[] = nagioscmd::build_command($cmd, $multi_param);
665 } else if ((isset($param['downtime_id']) && is_array($param['downtime_id'])) ||
666 (isset($param['trigger_id']) && is_array($param['trigger_id'])) ||
667 (isset($param['comment_id']) && is_array($param['comment_id']))) {
668 if (isset($param['trigger_id']))
669 $param_str = 'trigger_id';
670 elseif (isset($param['downtime_id']))
671 $param_str = 'downtime_id';
672 else
673 $param_str = 'comment_id';
674 foreach ($param[$param_str] as $did) {
675 $parts = explode(';',$did,2);
676 $replace_to_service = false;
677 if( count($parts) == 2 ) {
678 $did = $parts[0];
679 $replace_to_service = $parts[1] != 0;
681 $multi_param = $param;
682 $multi_param[$param_str] = $did;
684 $this_cmd = nagioscmd::cmd_info($cmd); /* Needs to be extraced so _HOST_ can be replaced to _SVC_ */
685 if( $replace_to_service )
686 $this_cmd['template'] = str_replace('_HOST_','_SVC_',$this_cmd['template']);
687 $nagios_commands[] = nagioscmd::build_command($this_cmd, $multi_param);
689 } else {
690 $nagios_commands[] = nagioscmd::build_command($cmd, $param);
693 return $nagios_commands;
697 * Executes custom commands and return output to ajax call.
698 * @param $command_name string
699 * @param $type string
700 * @param $host string
701 * @param $service string
702 * @return string
704 public function exec_custom_command($command_name, $type=false, $host=false, $service=false)
706 // Stop redirects
707 $this->auto_render=false;
708 if ($host === false) {
709 echo "No object type or identifier were set. Aborting.";
710 return;
712 // Get object data.
713 $ls = Livestatus::instance();
714 if(!empty($host) && empty($service)) {
715 $result_data = $ls->getHosts(array('filter' => array('name' => $host)));
717 else if(!empty($host) && !empty($service)) {
718 $result_data = $ls->getServices(array('filter' => array('host_name' => $host, 'description' => $service)));
720 $obj = (object)$result_data[0];
722 $custom_variables = array_combine($obj->custom_variable_names, $obj->custom_variable_values);
723 $custom_commands = Custom_command_Model::parse_custom_variables($custom_variables, $command_name);
724 if (empty($custom_commands)) {
725 echo "You are not authorized to run this command or it doesn't exist.";
726 return;
727 } else {
728 $command = $custom_commands[$command_name];
729 $command = nagstat::process_macros($command, $obj, $type);
730 // Set host/service comment that the command has been run
731 switch($type) {
732 case 'host':
733 $comment = "ADD_HOST_COMMENT;".$host.";1;".Auth::instance()->get_user()->username.";Executed custom command: ".ucwords(strtolower(str_replace('_', ' ', $command_name)));
734 break;
735 case 'service':
736 $comment = "ADD_SVC_COMMENT;".$host.";".$service.";1;".Auth::instance()->get_user()->username.";Executed custom command: ".ucwords(strtolower(str_replace('_', ' ', $command_name)));
737 break;
739 // Submit logs to nagios as comments.
740 $nagios_base_path = Kohana::config('config.nagios_base_path');
741 nagioscmd::submit_to_nagios($comment);
742 exec($command, $output, $status);
744 if ($status === 0) {
745 if (is_array($output)) {
746 $output = implode('<br />', $output);
748 echo $output;
749 } else {
750 echo "Script failed with status: " . $status;
751 return;