diff --git a/pandora_console/extras/mr/57.sql b/pandora_console/extras/mr/57.sql new file mode 100644 index 0000000000..839e090cc3 --- /dev/null +++ b/pandora_console/extras/mr/57.sql @@ -0,0 +1,6 @@ +START TRANSACTION; + +ALTER TABLE `tplanned_downtime` ADD COLUMN `cron_interval_from` VARCHAR(100) DEFAULT ''; +ALTER TABLE `tplanned_downtime` ADD COLUMN `cron_interval_to` VARCHAR(100) DEFAULT ''; + +COMMIT; \ No newline at end of file diff --git a/pandora_console/godmode/agentes/planned_downtime.editor.php b/pandora_console/godmode/agentes/planned_downtime.editor.php index dd4a8c29b0..f2d7109406 100644 --- a/pandora_console/godmode/agentes/planned_downtime.editor.php +++ b/pandora_console/godmode/agentes/planned_downtime.editor.php @@ -49,6 +49,7 @@ if (!$agent_d && !$agent_w) { set_unless_defined($config['past_planned_downtimes'], 1); require_once 'include/functions_users.php'; +require_once $config['homedir'].'/include/functions_cron.php'; // Buttons. $buttons = [ @@ -123,6 +124,18 @@ $periodically_time_to = (string) get_parameter( date(TIME_FORMAT, ($system_time + SECONDS_1HOUR)) ); +$hour_from = get_parameter('cron_hour_from', '*'); +$minute_from = get_parameter('cron_minute_from', '*'); +$mday_from = get_parameter('cron_mday_from', '*'); +$month_from = get_parameter('cron_month_from', '*'); +$wday_from = get_parameter('cron_wday_from', '*'); + +$hour_to = get_parameter('cron_hour_to', '*'); +$minute_to = get_parameter('cron_minute_to', '*'); +$mday_to = get_parameter('cron_mday_to', '*'); +$month_to = get_parameter('cron_month_to', '*'); +$wday_to = get_parameter('cron_wday_to', '*'); + $monday = (bool) get_parameter('monday'); $tuesday = (bool) get_parameter('tuesday'); $wednesday = (bool) get_parameter('wednesday'); @@ -262,6 +275,210 @@ if ($create_downtime || $update_downtime) { ); } else { $sql = ''; + + if ($type_execution === 'cron') { + $error_cron_from = false; + $error_cron_to = false; + $error_field = ''; + + // Validate 'from' cron values. + $hour_from = io_safe_output(trim($hour_from)); + if (preg_match('/^((?:([0-1]?[0-9]|2[0-3])|\*)\s*(?:(?:[\/-]([0-1]?[0-9]|2[0-3])))?\s*)$/', $hour_from, $matches) !== 1) { + $error_cron_from = true; + $error_field = __('hour (from)'); + } else { + $interval_values = explode('-', $hour_from); + + if (count($interval_values) > 1) { + $interval_from = $interval_values[0]; + $interval_to = $interval_values[1]; + + if ((int) $interval_to < (int) $interval_from) { + $error_cron_from = true; + } + } + } + + $minute_from = io_safe_output(trim($minute_from)); + if (preg_match('/^((?:(5[0-9]|[0-5]?[0-9])|\*)\s*(?:(?:[\/-](5[0-9]|[0-5]?[0-9])))?\s*)$/', $minute_from, $matches) !== 1) { + $error_cron_from = true; + $error_field = __('minute (from)'); + } else { + $interval_values = explode('-', $minute_from); + + if (count($interval_values) > 1) { + $interval_from = $interval_values[0]; + $interval_to = $interval_values[1]; + + if ((int) $interval_to < (int) $interval_from) { + $error_cron_from = true; + } + } + } + + $mday_from = io_safe_output(trim($mday_from)); + if (preg_match('/^((?:(0?[1-9]|[12][0-9]|3[01])|\*)\s*(?:(?:[\/-](0?[1-9]|[12][0-9]|3[01])))?\s*)$/', $mday_from, $matches) !== 1) { + $error_cron_from = true; + $error_field = __('month day (from)'); + } else { + $interval_values = explode('-', $mday_from); + + if (count($interval_values) > 1) { + $interval_from = $interval_values[0]; + $interval_to = $interval_values[1]; + + if ((int) $interval_to < (int) $interval_from) { + $error_cron_from = true; + } + } + } + + $month_from = io_safe_output(trim($month_from)); + if (preg_match('/^((?:([1-9]|1[012])|\*)\s*(?:(?:[\/-]([1-9]|1[012])))?\s*)$/', $month_from, $matches) !== 1) { + $error_cron_from = true; + $error_field = __('month (from)'); + } else { + $interval_values = explode('-', $month_from); + + if (count($interval_values) > 1) { + $interval_from = $interval_values[0]; + $interval_to = $interval_values[1]; + + if ((int) $interval_to < (int) $interval_from) { + $error_cron_from = true; + } + } + } + + $wday_from = io_safe_output(trim($wday_from)); + if (preg_match('/^((?:[0-6]|\*)\s*(?:(?:[\/-][0-6]))?\s*)$/', $wday_from, $matches) !== 1) { + $error_cron_from = true; + $error_field = __('week day (from)'); + } else { + $interval_values = explode('-', $wday_from); + if (count($interval_values) > 1) { + $interval_from = $interval_values[0]; + $interval_to = $interval_values[1]; + + if ((int) $interval_to < (int) $interval_from) { + $error_cron_from = true; + } + } + } + + // Validate 'to' cron values. + $hour_to = io_safe_output(trim($hour_to)); + if (preg_match('/^((?:([0-1]?[0-9]|2[0-3])|\*)\s*(?:(?:[\/-]([0-1]?[0-9]|2[0-3])))?\s*)$/', $hour_to, $matches) !== 1) { + $error_cron_to = true; + $error_field = __('hour (to)'); + } else { + $interval_values = explode('-', $hour_to); + + if (count($interval_values) > 1) { + $interval_from = $interval_values[0]; + $interval_to = $interval_values[1]; + + if ((int) $interval_to < (int) $interval_from) { + $error_cron_to = true; + } + } + } + + $minute_to = io_safe_output(trim($minute_to)); + if (preg_match('/^((?:(5[0-9]|[0-5]?[0-9])|\*)\s*(?:(?:[\/-](5[0-9]|[0-5]?[0-9])))?\s*)$/', $minute_to, $matches) !== 1) { + $error_cron_to = true; + $error_field = __('minute (to)'); + } else { + $interval_values = explode('-', $minute_to); + + if (count($interval_values) > 1) { + $interval_from = $interval_values[0]; + $interval_to = $interval_values[1]; + + if ((int) $interval_to < (int) $interval_from) { + $error_cron_to = true; + } + } + } + + $mday_to = io_safe_output(trim($mday_to)); + if (preg_match('/^((?:(0?[1-9]|[12][0-9]|3[01])|\*)\s*(?:(?:[\/-](0?[1-9]|[12][0-9]|3[01])))?\s*)$/', $mday_to, $matches) !== 1) { + $error_cron_to = true; + $error_field = __('month day (to)'); + } else { + $interval_values = explode('-', $mday_to); + + if (count($interval_values) > 1) { + $interval_from = $interval_values[0]; + $interval_to = $interval_values[1]; + + if ((int) $interval_to < (int) $interval_from) { + $error_cron_to = true; + } + } + } + + $month_to = io_safe_output(trim($month_to)); + if (preg_match('/^((?:([1-9]|1[012])|\*)\s*(?:(?:[\/-]([1-9]|1[012])))?\s*)$/', $month_to, $matches) !== 1) { + $error_cron_to = true; + $error_field = __('month (to)'); + } else { + $interval_values = explode('-', $month_to); + + if (count($interval_values) > 1) { + $interval_from = $interval_values[0]; + $interval_to = $interval_values[1]; + + if ((int) $interval_to < (int) $interval_from) { + $error_cron_to = true; + } + } + } + + $wday_to = io_safe_output(trim($wday_to)); + if (preg_match('/^((?:[0-6]|\*)\s*(?:(?:[\/-][0-6]))?\s*)$/', $wday_to, $matches) !== 1) { + $error_cron_to = true; + $error_field = __('week day (to)'); + } else { + $interval_values = explode('-', $wday_to); + if (count($interval_values) > 1) { + $interval_from = $interval_values[0]; + $interval_to = $interval_values[1]; + + if ((int) $interval_to < (int) $interval_from) { + $error_cron_to = true; + } + } + } + + if ($error_cron_from === true) { + ui_print_error_message( + __('Downtime start cron expression is not correct').': '.$error_field + ); + } + + if ($error_cron_to === true) { + ui_print_error_message( + __('Downtime stop cron expression is not correct').': '.$error_field + ); + } + + if ($error_cron_to === true || $error_cron_from) { + return; + } + + $cron_interval_from = io_safe_output($minute_from.' '.$hour_from.' '.$mday_from.' '.$month_from.' '.$wday_from); + $cron_interval_to = io_safe_output($minute_to.' '.$hour_to.' '.$mday_to.' '.$month_to.' '.$wday_to); + } + + if (cron_check_syntax($cron_interval_from) !== 1) { + $cron_interval_from = ''; + } + + if (cron_check_syntax($cron_interval_to) !== 1) { + $cron_interval_to = ''; + } + if ($create_downtime) { // Check AD permission on new downtime. if (!in_array($id_group, $user_groups_ad)) { @@ -298,6 +515,8 @@ if ($create_downtime || $update_downtime) { 'type_execution' => $type_execution, 'type_periodicity' => $type_periodicity, 'id_user' => $config['id_user'], + 'cron_interval_from' => $cron_interval_from, + 'cron_interval_to' => $cron_interval_to, ]; if ($config['dbtype'] == 'oracle') { $values['periodically_time_from'] = '1970/01/01 '.$values['periodically_time_from']; @@ -381,6 +600,8 @@ if ($create_downtime || $update_downtime) { 'type_execution' => $type_execution, 'type_periodicity' => $type_periodicity, 'id_user' => $config['id_user'], + 'cron_interval_from' => $cron_interval_from, + 'cron_interval_to' => $cron_interval_to, ]; if ($config['dbtype'] == 'oracle') { $values['periodically_time_from'] = '1970/01/01 '.$values['periodically_time_from']; @@ -458,6 +679,8 @@ if ($id_downtime > 0) { 'type_execution', 'type_periodicity', 'id_user', + 'cron_interval_from', + 'cron_interval_to', ]; switch ($config['dbtype']) { @@ -532,6 +755,36 @@ if ($id_downtime > 0) { $saturday = (bool) $result['saturday']; $sunday = (bool) $result['sunday']; + $cron_interval_from = explode(' ', $result['cron_interval_from']); + if (isset($cron_interval_from[4]) === true) { + $minute_from = $cron_interval_from[0]; + $hour_from = $cron_interval_from[1]; + $mday_from = $cron_interval_from[2]; + $month_from = $cron_interval_from[3]; + $wday_from = $cron_interval_from[4]; + } else { + $minute_from = '*'; + $hour_from = '*'; + $mday_from = '*'; + $month_from = '*'; + $wday_from = '*'; + } + + $cron_interval_to = explode(' ', $result['cron_interval_to']); + if (isset($cron_interval_to[4]) === true) { + $minute_to = $cron_interval_to[0]; + $hour_to = $cron_interval_to[1]; + $mday_to = $cron_interval_to[2]; + $month_to = $cron_interval_to[3]; + $wday_to = $cron_interval_to[4]; + } else { + $minute_to = '*'; + $hour_to = '*'; + $mday_to = '*'; + $month_to = '*'; + $wday_to = '*'; + } + $running = (bool) $result['executed']; } @@ -611,6 +864,7 @@ $table->data[4][1] = html_print_select( [ 'once' => __('Once'), 'periodically' => __('Periodically'), + 'cron' => __('Cron from/to'), ], 'type_execution', $type_execution, @@ -740,6 +994,18 @@ $table->data[5][1] = " + +
'; if ($id_downtime > 0) { @@ -1254,12 +1520,19 @@ function insert_downtime_agent($id_downtime, $user_groups_ad) switch ($("#type_execution").val()) { case 'once': $("#periodically_time").hide(); + $("#cron_time").hide(); $("#once_time").show(); break; case 'periodically': $("#once_time").hide(); + $("#cron_time").hide(); $("#periodically_time").show(); break; + case 'cron': + $("#once_time").hide(); + $("#periodically_time").hide(); + $("#cron_time").show(); + break; } } diff --git a/pandora_console/godmode/agentes/planned_downtime.list.php b/pandora_console/godmode/agentes/planned_downtime.list.php index a1e352fa1e..78f717d7d1 100755 --- a/pandora_console/godmode/agentes/planned_downtime.list.php +++ b/pandora_console/godmode/agentes/planned_downtime.list.php @@ -317,6 +317,7 @@ $row = []; $execution_type_fields = [ 'once' => __('Once'), 'periodically' => __('Periodically'), + 'cron' => __('Cron'), ]; $row[] = __('Execution type').' '.html_print_select( $execution_type_fields, @@ -460,10 +461,15 @@ if (empty($groups) === false) { strtotime($date_to.' 23:59:59') ); + $cron = sprintf( + 'type_execution = "cron"' + ); + $where_values .= sprintf( - ' AND ((%s) OR (%s))', + ' AND ((%s) OR (%s) OR (%s))', $periodically_w, - $once_w + $once_w, + $cron ); } @@ -471,6 +477,7 @@ if (empty($groups) === false) { $filter_performed = true; $where_values .= sprintf( ' AND (type_execution = "periodically" + OR type_execution = "cron" OR (type_execution = "once" AND date_to >= "%s"))', time() @@ -530,6 +537,8 @@ if (empty($groups) === false) { 'type_execution', 'type_periodicity', 'id_user', + 'cron_interval_from', + 'cron_interval_to', ]; $columns_str = implode(',', $columns); @@ -660,8 +669,9 @@ if ($downtimes === false && $filter_performed === false) { $data['type'] = $type_text[$downtime['type_downtime']]; $execution_text = [ - 'once' => __('once'), + 'once' => __('Once'), 'periodically' => __('Periodically'), + 'cron' => __('Cron'), ]; $data['execution'] = $execution_text[$downtime['type_execution']]; diff --git a/pandora_console/include/functions_html.php b/pandora_console/include/functions_html.php index b97e0398b6..9bf9b374b6 100644 --- a/pandora_console/include/functions_html.php +++ b/pandora_console/include/functions_html.php @@ -2237,7 +2237,7 @@ function html_print_extended_select_for_time( * * @return string HTML code if return parameter is true. */ -function html_print_extended_select_for_cron($hour='*', $minute='*', $mday='*', $month='*', $wday='*', $return=false, $disabled=false, $to=false) +function html_print_extended_select_for_cron($hour='*', $minute='*', $mday='*', $month='*', $wday='*', $return=false, $disabled=false, $to=false, $advanced=false, $adv_mode_name='') { // Hours for ($i = 0; $i < 24; $i++) { @@ -2286,18 +2286,104 @@ function html_print_extended_select_for_cron($hour='*', $minute='*', $mday='*', $table->head[3] = __('Month'); $table->head[4] = __('Week day'); - if ($to) { - $table->data[0][0] = html_print_select($hours, 'hour_to', $hour, '', __('Any'), '*', true, false, false, '', $disabled); - $table->data[0][1] = html_print_select($minutes, 'minute_to', $minute, '', __('Any'), '*', true, false, false, '', $disabled, false, $minutes_hidden_options); - $table->data[0][2] = html_print_select($mdays, 'mday_to', $mday, '', __('Any'), '*', true, false, false, '', $disabled); - $table->data[0][3] = html_print_select($months, 'month_to', $month, '', __('Any'), '*', true, false, false, '', $disabled); - $table->data[0][4] = html_print_select($wdays, 'wday_to', $wday, '', __('Any'), '*', true, false, false, '', $disabled); + if ($advanced === false) { + if ($to) { + $table->data[0][0] = html_print_select($hours, 'hour_to', $hour, '', __('Any'), '*', true, false, false, '', $disabled); + $table->data[0][1] = html_print_select($minutes, 'minute_to', $minute, '', __('Any'), '*', true, false, false, '', $disabled, false, $minutes_hidden_options); + $table->data[0][2] = html_print_select($mdays, 'mday_to', $mday, '', __('Any'), '*', true, false, false, '', $disabled); + $table->data[0][3] = html_print_select($months, 'month_to', $month, '', __('Any'), '*', true, false, false, '', $disabled); + $table->data[0][4] = html_print_select($wdays, 'wday_to', $wday, '', __('Any'), '*', true, false, false, '', $disabled); + } else { + $table->data[0][0] = html_print_select($hours, 'hour_from', $hour, '', __('Any'), '*', true, false, false, '', $disabled); + $table->data[0][1] = html_print_select($minutes, 'minute_from', $minute, '', __('Any'), '*', true, false, false, '', $disabled, false, $minutes_hidden_options); + $table->data[0][2] = html_print_select($mdays, 'mday_from', $mday, '', __('Any'), '*', true, false, false, '', $disabled); + $table->data[0][3] = html_print_select($months, 'month_from', $month, '', __('Any'), '*', true, false, false, '', $disabled); + $table->data[0][4] = html_print_select($wdays, 'wday_from', $wday, '', __('Any'), '*', true, false, false, '', $disabled); + } } else { - $table->data[0][0] = html_print_select($hours, 'hour_from', $hour, '', __('Any'), '*', true, false, false, '', $disabled); - $table->data[0][1] = html_print_select($minutes, 'minute_from', $minute, '', __('Any'), '*', true, false, false, '', $disabled, false, $minutes_hidden_options); - $table->data[0][2] = html_print_select($mdays, 'mday_from', $mday, '', __('Any'), '*', true, false, false, '', $disabled); - $table->data[0][3] = html_print_select($months, 'month_from', $month, '', __('Any'), '*', true, false, false, '', $disabled); - $table->data[0][4] = html_print_select($wdays, 'wday_from', $wday, '', __('Any'), '*', true, false, false, '', $disabled); + if ($adv_mode_name !== '') { + $adv_mode_name = '_'.$adv_mode_name; + } + + $table->data[0][0] = html_print_extended_select_for_downtime_cron( + 'cron_hour'.$adv_mode_name, + $hours, + $hour, + '', + __('Any'), + '*', + false, + true, + false, + false, + false, + 0, + 'Valid values: [0-23], [0-23]-[0-23], *, or step value (example: */3, 10/5)', + ); + + $table->data[0][1] = html_print_extended_select_for_downtime_cron( + 'cron_minute'.$adv_mode_name, + $minutes, + $minute, + '', + __('Any'), + '*', + false, + true, + false, + false, + false, + 0, + 'Valid values: [0-59], [0-59]-[0-59], *, or step value (example: */5, 10/1)', + ); + + $table->data[0][2] = html_print_extended_select_for_downtime_cron( + 'cron_mday'.$adv_mode_name, + $mdays, + $mday, + '', + __('Any'), + '*', + false, + true, + false, + false, + false, + 0, + 'Valid values: [1-31], [1-31]-[1-31], *, or step value (example: */5, 7/2)', + ); + + $table->data[0][3] = html_print_extended_select_for_downtime_cron( + 'cron_month'.$adv_mode_name, + $months, + $month, + '', + __('Any'), + '*', + false, + true, + false, + false, + false, + 0, + 'Valid values: [1-12], [1-12]-[1-12], *, or step value (example: */3, 9/1)', + ); + + $table->data[0][4] = html_print_extended_select_for_downtime_cron( + 'cron_wday'.$adv_mode_name, + $wdays, + $wday, + '', + __('Any'), + '*', + false, + true, + false, + false, + false, + 0, + 'Valid values: [0-6], [0-6]-[0-6], *, or step value (example: */2, 3/1)', + ); } return html_print_table($table, $return); @@ -6171,3 +6257,112 @@ function html_print_go_back_button(string $url, array $options=[], bool $return= return $output; } + + +/** + * Render select box for numeric values and text box for complex values. + * + * @param string $name Select form name. + * @param string $fields Fields to populate select box. + * @param mixed $selected Current selected value. It can be a single value or an array of selected values (in combination with multiple). + * @param string $script Javascript onChange (select) code. + * @param string $nothing Label when nothing is selected. + * @param mixed $nothing_value Value when nothing is selected. + * @param integer $size Size of the input. + * @param boolean $return Whether to return an output string or echo now (optional, echo by default). + * @param boolean $select_style Wherter to assign to combo a unique name (to have more than one on same page, like dashboard). + * @param boolean $unique_name Uunique name value. + * @param boolean $disabled Input renders as disabled. + * @param boolean $no_change No change value. + * @param boolean $text_help Tooltip. + + * @return string HTML code if return parameter is true. + */ +function html_print_extended_select_for_downtime_cron( + $name, + $fields, + $selected='', + $script='', + $nothing='', + $nothing_value='0', + $size=false, + $return=false, + $select_style=false, + $unique_name=true, + $disabled=false, + $no_change=0, + $text_help='' +) { + global $config; + + if ($unique_name === true) { + $uniq_name = uniqid($name); + } else { + $uniq_name = $name; + } + + ob_start(); + + echo '