From 263df4db1dff39dcb1c7bab9d4336799c345f859 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Thu, 31 Dec 2020 16:21:04 -0600 Subject: [PATCH] Progress: controller program, restructure some of f*_execute functionality, and add or update documentation. For the controller program: - add "freeze", "thaw", "pause", and "resume". - improve simulation to actually perform an execute, but with a stub execution (an empty bash script). - print more information when performing the stubbed simulation. - simulation should not stop on errors when simulating, there are a number of cases where stopping is still happening. - add a microsleep during the stubbed execution to better simulate synchronous vs asynchronous behavior. - The F_schedule is no longer being returned from the child process, do not treat it as a child exit state. - add more documentation. --- level_0/f_execute/c/execute-common.h | 21 ++++ level_1/fl_execute/c/execute-common.h | 35 ++---- level_2/fll_execute/c/execute.h | 2 +- level_3/controller/c/private-common.h | 21 +++- level_3/controller/c/private-controller.c | 1 + level_3/controller/c/private-rule.c | 117 +++++++++++++++++---- level_3/controller/c/private-rule.h | 17 ++- .../settings/example/rules/command/multiple.rule | 2 +- .../data/settings/example/rules/script/php.rule | 4 +- .../settings/example/rules/script/succeed.rule | 2 +- level_3/controller/documents/actions.txt | 74 +++++++++++++ level_3/controller/documents/rule.txt | 8 +- level_3/controller/documents/simulate.txt | 24 +++++ level_3/controller/specifications/rule.txt | 6 ++ 14 files changed, 269 insertions(+), 65 deletions(-) create mode 100644 level_3/controller/documents/actions.txt create mode 100644 level_3/controller/documents/simulate.txt diff --git a/level_0/f_execute/c/execute-common.h b/level_0/f_execute/c/execute-common.h index 52dfedb..71a8d00 100644 --- a/level_0/f_execute/c/execute-common.h +++ b/level_0/f_execute/c/execute-common.h @@ -16,6 +16,27 @@ extern "C" { #endif +/** + * A structure representing a scheduler and its parameters for execution. + * + * policy: the scheduler policy. + * priority: the scheduler priority; + */ +#ifndef _di_f_execute_scheduler_t_ + typedef struct { + int policy; + int priority; + } f_execute_scheduler_t; + + #define f_execute_scheduler_t_initialize { 0, 0 } + + #define f_macro_execute_scheduler_t_initialize(policy, priority) { policy, priority } + + #define f_execute_scheduler_t_clear(scheduler) \ + scheduler.policy = 0; \ + scheduler.priority = 0; +#endif // _di_f_execute_scheduler_t_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_1/fl_execute/c/execute-common.h b/level_1/fl_execute/c/execute-common.h index 7cc9e2c..a3f919f 100644 --- a/level_1/fl_execute/c/execute-common.h +++ b/level_1/fl_execute/c/execute-common.h @@ -52,27 +52,6 @@ extern "C" { #endif // _di_fl_execute_parameter_t_ /** - * A structure representing a scheduler and its parameters for execution. - * - * policy: the scheduler policy. - * priority: the scheduler priority; - */ -#ifndef _di_fl_execute_scheduler_t_ - typedef struct { - int policy; - int priority; - } fl_execute_scheduler_t; - - #define fl_execute_scheduler_t_initialize { 0, 0 } - - #define fl_macro_execute_scheduler_t_initialize(policy, priority) { policy, priority } - - #define fl_execute_scheduler_t_clear(scheduler) \ - scheduler.policy = 0; \ - scheduler.priority = 0; -#endif // _di_fl_execute_scheduler_t_ - -/** * A structure for containing identity and access related parameters for the execute functions that call the execv() family of functions. * * There are likely many more identity and access related things that can be done but this focuses on a small core set of those. @@ -84,34 +63,34 @@ extern "C" { * id_user: the id of the user to assign the child process to, set to 0 to not use. * id_group: the id of the group to assign the child process to, set to 0 to not use. * capability: all of the capabilities to assign the child process to, set to 0 to not use (f_capability_t is a pointer). + * control_group: an array of cgroups (control groups) to assign the child PID to, set to 0 to not use. * id_groups: the ids of each supplemental group to assign the child process to, set to 0 to not use. * scheduler: the scheduler to assign the child process to, set to 0 to not use. - * control_group: an array of cgroups (control groups) to assign the child PID to, set to 0 to not use. */ #ifndef _di_fl_execute_as_t_ typedef struct { int *nice; uid_t *id_user; gid_t *id_group; - f_capability_t capability; - f_int32s_t *id_groups; - fl_execute_scheduler_t *scheduler; + f_capability_t capability; f_control_group_t *control_group; + f_int32s_t *id_groups; + f_execute_scheduler_t *scheduler; } fl_execute_as_t; #define fl_execute_as_t_initialize { 0, 0, 0, 0, 0, 0, 0 } - #define fl_macro_execute_as_t_initialize(nice, id_user, id_group, capability, id_groups, scheduler, control_group) { nice, id_user, id_group, capability, id_groups, scheduler, control_group } + #define fl_macro_execute_as_t_initialize(nice, id_user, id_group, capability, control_group, id_groups, scheduler) { nice, id_user, id_group, capability, control_group, id_groups, scheduler } #define fl_execute_as_t_clear(as) \ as.nice = 0; \ as.id_user = 0; \ as.id_group = 0; \ as.capability = 0; \ + as.control_group = 0; \ as.id_groups = 0; \ - as.scheduler = 0; \ - as.control_group = 0; + as.scheduler = 0; #endif // _di_fl_execute_as_t_ #ifdef __cplusplus diff --git a/level_2/fll_execute/c/execute.h b/level_2/fll_execute/c/execute.h index 3db3dc5..fc2a082 100644 --- a/level_2/fll_execute/c/execute.h +++ b/level_2/fll_execute/c/execute.h @@ -429,7 +429,7 @@ extern "C" { * F_none on success. * F_child on success but this is the child thread. * F_capability (with error bit) on failure to set capabilities in the child (only the child process returns this). - * F_control_group (with error bit) on failure to set capabilities in the child (only the parent process returns this). + * F_control_group (with error bit) on failure to set control group in the child (only the parent process returns this). * F_child (with error bit) on any failure without an explicit failure code (like F_group) before calling execute but this is the child thread. * F_failure (with error bit) on execution failure. * F_fork (with error bit) on fork failure. diff --git a/level_3/controller/c/private-common.h b/level_3/controller/c/private-common.h index 714397a..8ded89f 100644 --- a/level_3/controller/c/private-common.h +++ b/level_3/controller/c/private-common.h @@ -34,6 +34,7 @@ extern "C" { #define controller_string_fail "fail" #define controller_string_failsafe "failsafe" #define controller_string_fifo "fifo" + #define controller_string_freeze "freeze" #define controller_string_group "group" #define controller_string_groups "groups" #define controller_string_how "how" @@ -51,6 +52,7 @@ extern "C" { #define controller_string_other "other" #define controller_string_parameter "parameter" #define controller_string_path "path" + #define controller_string_pause "pause" #define controller_string_pid "pid" #define controller_string_program "program" #define controller_string_ready "ready" @@ -58,6 +60,7 @@ extern "C" { #define controller_string_require "require" #define controller_string_required "required" #define controller_string_restart "restart" + #define controller_string_resume "resume" #define controller_string_round_robin "round_robin" #define controller_string_rule "rule" #define controller_string_rules "rules" @@ -69,6 +72,7 @@ extern "C" { #define controller_string_stop "stop" #define controller_string_succeed "succeed" #define controller_string_synchronous "synchronous" + #define controller_string_thaw "thaw" #define controller_string_timeout "timeout" #define controller_string_type "type" #define controller_string_use "use" @@ -99,6 +103,7 @@ extern "C" { #define controller_string_fail_length 4 #define controller_string_failsafe_length 8 #define controller_string_fifo_length 4 + #define controller_string_freeze_length 6 #define controller_string_group_length 5 #define controller_string_how_length 3 #define controller_string_idle_length 4 @@ -115,6 +120,7 @@ extern "C" { #define controller_string_other_length 5 #define controller_string_parameter_length 9 #define controller_string_path_length 4 + #define controller_string_pause_length 5 #define controller_string_pid_length 3 #define controller_string_program_length 7 #define controller_string_ready_length 5 @@ -122,6 +128,7 @@ extern "C" { #define controller_string_require_length 7 #define controller_string_required_length 8 #define controller_string_restart_length 7 + #define controller_string_resume_length 6 #define controller_string_round_robin_length 11 #define controller_string_rule_length 4 #define controller_string_rules_length 5 @@ -133,6 +140,7 @@ extern "C" { #define controller_string_stop_length 4 #define controller_string_succeed_length 7 #define controller_string_synchronous_length 11 + #define controller_string_thaw_length 4 #define controller_string_timeout_length 7 #define controller_string_type_length 4 #define controller_string_use_length 3 @@ -157,12 +165,16 @@ extern "C" { enum { controller_rule_action_type_create = 1, + controller_rule_action_type_freeze, controller_rule_action_type_group, controller_rule_action_type_kill, - controller_rule_action_type_restart, + controller_rule_action_type_pause, controller_rule_action_type_reload, + controller_rule_action_type_restart, + controller_rule_action_type_resume, controller_rule_action_type_start, controller_rule_action_type_stop, + controller_rule_action_type_thaw, controller_rule_action_type_use, controller_rule_action_type_user, }; @@ -287,7 +299,8 @@ extern "C" { #define controller_rule_option_asynchronous 0x1 #define controller_rule_option_require 0x2 #define controller_rule_option_simulate 0x4 - #define controller_rule_option_wait 0x8 + #define controller_rule_option_validate 0x8 + #define controller_rule_option_wait 0x10 // bitwise codes representing properties on controller_rule_t that have been found in the rule file. #define controller_rule_has_control_group 0x1 @@ -327,7 +340,7 @@ extern "C" { f_capability_t capability; f_control_group_t control_group; f_int32s_t groups; - fl_execute_scheduler_t scheduler; + f_execute_scheduler_t scheduler; controller_rule_items_t items; } controller_rule_t; @@ -357,7 +370,7 @@ extern "C" { f_capability_t_initialize, \ f_control_group_t_initialize, \ f_int32s_t_initialize, \ - fl_execute_scheduler_t_initialize, \ + f_execute_scheduler_t_initialize, \ controller_rule_items_initialize, \ } diff --git a/level_3/controller/c/private-controller.c b/level_3/controller/c/private-controller.c index 6ba50be..8111999 100644 --- a/level_3/controller/c/private-controller.c +++ b/level_3/controller/c/private-controller.c @@ -567,6 +567,7 @@ extern "C" { controller_entry_actions_t *actions = 0; const bool simulate = data->parameters[controller_parameter_test].result == f_console_result_found; + const bool validate = data->parameters[controller_parameter_validate].result == f_console_result_found; cache->ats.used = 0; cache->line_action = 0; diff --git a/level_3/controller/c/private-rule.c b/level_3/controller/c/private-rule.c index 04f6643..2d295ac 100644 --- a/level_3/controller/c/private-rule.c +++ b/level_3/controller/c/private-rule.c @@ -369,23 +369,26 @@ extern "C" { if (cache.name_action.used) { fprintf(output.to.stream, "%s '", item ? "action" : "value"); - fprintf(output.to.stream, "%s%s%s%s", output.context.after->string, output.notable.before->string, cache.name_action.string, output.notable.after->string); - fprintf(output.to.stream, "%s' on line ", output.context.before->string); + fprintf(output.to.stream, "%s%s", output.context.after->string, output.notable.before->string); + f_print_dynamic(output.to.stream, cache.name_action); + fprintf(output.to.stream, "%s%s' on line ", output.notable.after->string, output.context.before->string); fprintf(output.to.stream, "%s%s%llu%s", output.context.after->string, output.notable.before->string, cache.line_action, output.notable.after->string); fprintf(output.to.stream, "%s for ", output.context.before->string); } if (cache.name_item.used) { fprintf(output.to.stream, "rule %s '", item ? "item" : "setting"); - fprintf(output.to.stream, "%s%s%s%s", output.context.after->string, output.notable.before->string, cache.name_item.string, output.notable.after->string); - fprintf(output.to.stream, "%s' on line ", output.context.before->string); + fprintf(output.to.stream, "%s%s", output.context.after->string, output.notable.before->string); + f_print_dynamic(output.to.stream, cache.name_item); + fprintf(output.to.stream, "%s%s' on line ", output.notable.after->string, output.context.before->string); fprintf(output.to.stream, "%s%s%llu%s", output.context.after->string, output.notable.before->string, cache.line_item, output.notable.after->string); fprintf(output.to.stream, "%s for ", output.context.before->string); } if (cache.name_file.used) { fprintf(output.to.stream, "file '"); - fprintf(output.to.stream, "%s%s%s%s", output.context.after->string, output.notable.before->string, cache.name_file.string, output.notable.after->string); + fprintf(output.to.stream, "%s%s", output.context.after->string, output.notable.before->string); + f_print_dynamic(output.to.stream, cache.name_file); fprintf(output.to.stream, "%s'.%s%c", output.context.before->string, output.context.after->string, f_string_eol_s[0]); } } @@ -442,7 +445,7 @@ extern "C" { #endif // _di_controller_rule_error_print_need_want_wish_ #ifndef _di_controller_rule_execute_ - f_return_status controller_rule_execute(const controller_cache_t cache, const f_array_length_t index, const uint8_t type, controller_data_t *data, controller_setting_t *setting) { + f_return_status controller_rule_execute(const controller_cache_t cache, const f_array_length_t index, const uint8_t type, const bool simulate, controller_data_t *data, controller_setting_t *setting) { f_status_t status = F_none; f_status_t success = F_false; @@ -535,7 +538,7 @@ extern "C" { parameter.option |= fl_execute_parameter_option_path; } - status = controller_rule_execute_foreground(item->type, *action, 0, action->parameters, 0, ¶meter, &as, data); + status = controller_rule_execute_foreground(item->type, *action, simulate, 0, action->parameters, 0, ¶meter, &as, data); if (status == F_child) { break; @@ -543,7 +546,8 @@ extern "C" { if (F_status_is_error(status)) { action->status = F_status_set_error(F_failure); - break; + + if (!simulate) break; } success = F_true; @@ -555,7 +559,7 @@ extern "C" { parameter.option |= fl_execute_parameter_option_path; } - status = controller_rule_execute_foreground(item->type, *action, rule->script.used ? rule->script.string : controller_default_program_script, arguments_none, 0, ¶meter, &as, data); + status = controller_rule_execute_foreground(item->type, *action, simulate, rule->script.used ? rule->script.string : controller_default_program_script, arguments_none, 0, ¶meter, &as, data); if (status == F_child) { break; @@ -563,7 +567,8 @@ extern "C" { if (F_status_is_error(status)) { action->status = F_status_set_error(F_failure); - break; + + if (!simulate) break; } success = F_true; @@ -574,11 +579,12 @@ extern "C" { parameter.option |= fl_execute_parameter_option_path; } - status = controller_rule_execute_pid_with(item->type, *action, 0, action->parameters, 0, ¶meter, &as, data); + status = controller_rule_execute_pid_with(item->type, *action, simulate, 0, action->parameters, 0, ¶meter, &as, data); if (F_status_is_error(status)) { action->status = F_status_set_error(F_failure); - break; + + if (!simulate) break; } success = F_true; @@ -604,7 +610,7 @@ extern "C" { if (status == F_child || status == F_signal) break; } // for - if (status == F_child || status == F_signal || F_status_is_error(status)) break; + if (status == F_child || status == F_signal || F_status_is_error(status) && !simulate) break; } // for fl_string_maps_delete(&environment); @@ -628,7 +634,9 @@ extern "C" { #endif // _di_controller_rule_execute_ #ifndef _di_controller_rule_execute_pid_with_ - f_return_status controller_rule_execute_pid_with(const uint8_t type, const controller_rule_action_t action, const f_string_t program, const f_string_dynamics_t arguments, const uint8_t options, fl_execute_parameter_t * const parameter, fl_execute_as_t * const as, controller_data_t *data) { + f_return_status controller_rule_execute_pid_with(const uint8_t type, const controller_rule_action_t action, const bool simulate, const f_string_t program, const f_string_dynamics_t arguments, const uint8_t options, fl_execute_parameter_t * const parameter, fl_execute_as_t * const as, controller_data_t *data) { + + f_status_t status = F_none; int result = 0; // @todo check to see if pid file exists. @@ -637,12 +645,39 @@ extern "C" { // in which case fll_execute_program() is called. // otherwise this needs to call an asynchronous execute process. // until then, this controller_rule_execute_pid_with() function is not correct and only represents a process that forks to the background. - f_status_t status = fll_execute_program(program, arguments, parameter, as, &result); + + if (simulate) { + + if (data->error.verbosity != f_console_verbosity_quiet) { + fprintf(data->output.stream, "%c", f_string_eol_s[0]); + fprintf(data->output.stream, "Simulating execution of '"); + fprintf(data->output.stream, "%s%s%s", data->context.title.string, program ? program : arguments.used && arguments.array[0].used ? arguments.array[0].string : f_string_empty_s, data->context.reset.string); + fprintf(data->output.stream, "' with the arguments: '%s", data->context.title.string); + + for (f_array_length_t i = program ? 0 : 1; i < arguments.used; ++i) { + fprintf(data->output.stream, "%s%s", (program && i || !program && i > 1) ? " " : "", arguments.array[i].string); + } // for + + fprintf(data->output.stream, "%s'.%c", data->context.reset.string, f_string_eol_s[0]); + } + + // sleep for less than a second to better show simulation of synchronous vs asynchronous. + usleep(200000); + + const f_string_static_t simulated_program = f_macro_string_static_t_initialize(f_string_empty_s, 0); + const f_string_statics_t simulated_arguments = f_string_statics_t_initialize; + fl_execute_parameter_t simulated_parameter = fl_macro_execute_parameter_t_initialize(parameter->option, parameter->environment, parameter->signals, &simulated_program); + + status = fll_execute_program(controller_default_program_script, simulated_arguments, &simulated_parameter, as, &result); + } + else { + status = fll_execute_program(program, arguments, parameter, as, &result); + } if (F_status_is_error(status)) { status = F_status_set_fine(status); - if (status == F_child || status == F_capability || status == F_group || status == F_nice || status == F_schedule || status == F_user) { + if (status == F_child || status == F_capability || status == F_group || status == F_nice || status == F_user) { status = F_child; } else { @@ -687,15 +722,43 @@ extern "C" { #endif // _di_controller_rule_execute_pid_with_ #ifndef _di_controller_rule_execute_foreground_ - f_return_status controller_rule_execute_foreground(const uint8_t type, const controller_rule_action_t action, const f_string_t program, const f_string_dynamics_t arguments, const uint8_t options, fl_execute_parameter_t * const parameter, fl_execute_as_t * const as, controller_data_t *data) { + f_return_status controller_rule_execute_foreground(const uint8_t type, const controller_rule_action_t action, const bool simulate, const f_string_t program, const f_string_dynamics_t arguments, const uint8_t options, fl_execute_parameter_t * const parameter, fl_execute_as_t * const as, controller_data_t *data) { + + f_status_t status = F_none; int result = 0; - f_status_t status = fll_execute_program(program, arguments, parameter, as, &result); + if (simulate) { + + if (data->error.verbosity != f_console_verbosity_quiet) { + fprintf(data->output.stream, "%c", f_string_eol_s[0]); + fprintf(data->output.stream, "Simulating execution of '"); + fprintf(data->output.stream, "%s%s%s", data->context.title.string, program ? program : arguments.used && arguments.array[0].used ? arguments.array[0].string : f_string_empty_s, data->context.reset.string); + fprintf(data->output.stream, "' with the arguments: '%s", data->context.title.string); + + for (f_array_length_t i = program ? 0 : 1; i < arguments.used; ++i) { + fprintf(data->output.stream, "%s%s", (program && i || !program && i > 1) ? " " : "", arguments.array[i].string); + } // for + + fprintf(data->output.stream, "%s'.%c", data->context.reset.string, f_string_eol_s[0]); + } + + // sleep for less than a second to better show simulation of synchronous vs asynchronous. + usleep(200000); + + const f_string_static_t simulated_program = f_macro_string_static_t_initialize(f_string_empty_s, 0); + const f_string_statics_t simulated_arguments = f_string_statics_t_initialize; + fl_execute_parameter_t simulated_parameter = fl_macro_execute_parameter_t_initialize(parameter->option, parameter->environment, parameter->signals, &simulated_program); + + status = fll_execute_program(controller_default_program_script, simulated_arguments, &simulated_parameter, as, &result); + } + else { + status = fll_execute_program(program, arguments, parameter, as, &result); + } if (F_status_is_error(status)) { status = F_status_set_fine(status); - if (status == F_child || status == F_capability || status == F_group || status == F_nice || status == F_schedule || status == F_user) { + if (status == F_child || status == F_capability || status == F_group || status == F_nice || status == F_user) { status = F_child; } else { @@ -861,9 +924,15 @@ extern "C" { else if (fl_string_dynamic_compare_string(controller_string_kill, cache->name_action, controller_string_kill_length) == F_equal_to) { type = controller_rule_action_type_kill; } + else if (fl_string_dynamic_compare_string(controller_string_pause, cache->name_action, controller_string_pause_length) == F_equal_to) { + type = controller_rule_action_type_pause; + } else if (fl_string_dynamic_compare_string(controller_string_restart, cache->name_action, controller_string_restart_length) == F_equal_to) { type = controller_rule_action_type_restart; } + else if (fl_string_dynamic_compare_string(controller_string_resume, cache->name_action, controller_string_resume_length) == F_equal_to) { + type = controller_rule_action_type_resume; + } else if (fl_string_dynamic_compare_string(controller_string_reload, cache->name_action, controller_string_reload_length) == F_equal_to) { type = controller_rule_action_type_reload; } @@ -1057,11 +1126,15 @@ extern "C" { f_return_status controller_rule_process(const f_array_length_t index, const uint8_t action, const uint8_t options, controller_data_t *data, controller_setting_t *setting, controller_cache_t *cache) { switch (action) { + case controller_rule_action_type_freeze: case controller_rule_action_type_kill: + case controller_rule_action_type_pause: case controller_rule_action_type_reload: case controller_rule_action_type_restart: + case controller_rule_action_type_resume: case controller_rule_action_type_start: case controller_rule_action_type_stop: + case controller_rule_action_type_thaw: break; default: @@ -1243,7 +1316,7 @@ extern "C" { memcpy(cache_name_file, cache->name_file.string, cache->name_file.used); // @todo: this should pass or use the asynchronous state. - status = controller_rule_process(at, controller_rule_action_type_start, options, data, setting, cache); + status = controller_rule_process(at, action, options, data, setting, cache); if (status == F_child || status == F_signal) break; @@ -1306,7 +1379,7 @@ extern "C" { } // for } - if (!(options & controller_rule_option_simulate) && F_status_is_error_not(status)) { + if (!(options & controller_rule_option_validate) && F_status_is_error_not(status)) { // find at least one of the requested action when the rule is required. if (options & controller_rule_option_require) { @@ -1343,7 +1416,7 @@ extern "C" { } if (F_status_is_error_not(status)) { - status = controller_rule_execute(*cache, index, action, data, setting); + status = controller_rule_execute(*cache, index, action, options & controller_rule_option_simulate, data, setting); if (F_status_is_error(status)) { controller_rule_error_print(data->error, *cache, F_true); diff --git a/level_3/controller/c/private-rule.h b/level_3/controller/c/private-rule.h index b5f14ac..b795fbf 100644 --- a/level_3/controller/c/private-rule.h +++ b/level_3/controller/c/private-rule.h @@ -214,10 +214,15 @@ extern "C" { * * Only subset of the action type codes are supported: * - controller_rule_action_type_kill + * - controller_rule_action_type_pause * - controller_rule_action_type_reload * - controller_rule_action_type_restart + * - controller_rule_action_type_resume * - controller_rule_action_type_start * - controller_rule_action_type_stop + * @param simulate + * If TRUE, then run a simulated action (outputing result and executing an empty script). + * If FALSE, perform the real execution. * @param data * The program data. * @param setting @@ -233,7 +238,7 @@ extern "C" { * On failure, the individual status for the rule is set to an appropriate error status. */ #ifndef _di_controller_rule_execute_ - extern f_return_status controller_rule_execute(const controller_cache_t cache, const f_array_length_t index, const uint8_t type, controller_data_t *data, controller_setting_t *setting) f_gcc_attribute_visibility_internal; + extern f_return_status controller_rule_execute(const controller_cache_t cache, const f_array_length_t index, const uint8_t type, const bool simulate, controller_data_t *data, controller_setting_t *setting) f_gcc_attribute_visibility_internal; #endif // _di_controller_rule_execute_ /** @@ -253,6 +258,9 @@ extern "C" { * - controller_rule_action_type_restart * - controller_rule_action_type_start * - controller_rule_action_type_stop + * @param simulate + * If TRUE, then run a simulated action (outputing result and executing an empty script). + * If FALSE, perform the real execution. * @param program * The program to use (such as "bash"). * @param arguments @@ -279,7 +287,7 @@ extern "C" { * @see fll_execute_program() */ #ifndef _di_controller_rule_execute_pid_with_ - extern f_return_status controller_rule_execute_pid_with(const uint8_t type, const controller_rule_action_t action, const f_string_t program, const f_string_dynamics_t arguments, const uint8_t options, fl_execute_parameter_t * const parameter, fl_execute_as_t * const as, controller_data_t *data) f_gcc_attribute_visibility_internal; + extern f_return_status controller_rule_execute_pid_with(const uint8_t type, const controller_rule_action_t action, const bool simulate, const f_string_t program, const f_string_dynamics_t arguments, const uint8_t options, fl_execute_parameter_t * const parameter, fl_execute_as_t * const as, controller_data_t *data) f_gcc_attribute_visibility_internal; #endif // _di_controller_rule_execute_pid_with_ /** @@ -296,6 +304,9 @@ extern "C" { * - controller_rule_action_type_restart * - controller_rule_action_type_start * - controller_rule_action_type_stop + * @param simulate + * If TRUE, then run a simulated action (outputing result and executing an empty script). + * If FALSE, perform the real execution. * @param program * The program to use (such as "bash"). * @param arguments @@ -321,7 +332,7 @@ extern "C" { * @see fll_execute_program() */ #ifndef _di_controller_rule_execute_foreground_ - extern f_return_status controller_rule_execute_foreground(const uint8_t type, const controller_rule_action_t action, const f_string_t program, const f_string_dynamics_t arguments, const uint8_t options, fl_execute_parameter_t * const parameter, fl_execute_as_t * const as, controller_data_t *data) f_gcc_attribute_visibility_internal; + extern f_return_status controller_rule_execute_foreground(const uint8_t type, const controller_rule_action_t action, const bool simulate, const f_string_t program, const f_string_dynamics_t arguments, const uint8_t options, fl_execute_parameter_t * const parameter, fl_execute_as_t * const as, controller_data_t *data) f_gcc_attribute_visibility_internal; #endif // _di_controller_rule_execute_foreground_ /** diff --git a/level_3/controller/data/settings/example/rules/command/multiple.rule b/level_3/controller/data/settings/example/rules/command/multiple.rule index bb18ec3..88efe7c 100644 --- a/level_3/controller/data/settings/example/rules/command/multiple.rule +++ b/level_3/controller/data/settings/example/rules/command/multiple.rule @@ -28,4 +28,4 @@ command: start whoami command: - start date + start date -u diff --git a/level_3/controller/data/settings/example/rules/script/php.rule b/level_3/controller/data/settings/example/rules/script/php.rule index cb67fd5..bf6c405 100644 --- a/level_3/controller/data/settings/example/rules/script/php.rule +++ b/level_3/controller/data/settings/example/rules/script/php.rule @@ -15,7 +15,7 @@ script: var_dump(getenv()); print("\n"); - print("Now executing 'date' program, assuming that it exists in \$PATH.\n"); - passthru("date"); + print("Now executing 'date -u' program, assuming that it exists in \$PATH.\n"); + passthru("date -u"); print("\n"); } diff --git a/level_3/controller/data/settings/example/rules/script/succeed.rule b/level_3/controller/data/settings/example/rules/script/succeed.rule index 925df1c..be066b2 100644 --- a/level_3/controller/data/settings/example/rules/script/succeed.rule +++ b/level_3/controller/data/settings/example/rules/script/succeed.rule @@ -11,7 +11,7 @@ script: echo "Hello this is script #1 and should succeed." echo - date + date -u echo } diff --git a/level_3/controller/documents/actions.txt b/level_3/controller/documents/actions.txt new file mode 100644 index 0000000..e2ae340 --- /dev/null +++ b/level_3/controller/documents/actions.txt @@ -0,0 +1,74 @@ +# fss-0002 + +Actions Documentation: + This describes the intent and purpose of the actions provided for individual Rules (or things related to a Rule). + + Each Action represents a specific intent and purpose but many of these actions are customizable via the rule file. + One should expect an Action to operate as described here but the system administrator or distributor is fully capable of doing something different. + For those doing something different, appropriate documentation is suggested. + + These actions should be usable by any "control" program that communicates with this "controller" program. + Should any "control" or "controller" program implementation not support any particular Action for any reason, one should report that the Action is unsupported. + + Freeze Action\: + The Freeze Action is an extension of a Control Group. + This is internal to the "controller" program and is not customizable via any Rule file. + For a customizable "freeze"-like capability, look into the Pause and Resume Actions. + This is complemented by the Thaw Action. + + This designates that a processes Control Group is to be frozen. + All Rules (or any process not controlled by the "controller") that is within the same Control Group will be frozen. + (@todo consider instead designing this around the Control Groups instead of a "rule".) + (This documentation will likely change with consideration to the above @todo once this gets implemented.) + + This must not attempt to freeze (or unfreeze) the Control Group that the "controller" belongs to. + Therefore, if a Rule does not specify a Control Group, then it is likely that the Freeze Action will be unsupported for that Rule/Control Group. + + Kill Action\: + Forcefully terminate some process controlled by the "controller". + This action cannot be blocked and it is recommended to use a Stop Action instead for a more proper termination. + + Pause Action\: + The Pause Action will pause (or freeze) the process controlled by the Rule. + Although similar to the Freeze Action, this is intended to communicate to an individual process and inform to Pause. + This is complemented by the Resume Action. + + Restart Action\: + The Restart Action will either perform a Stop Action and then a Restart Action or it will perform the Restart Action designated in some Rule file. + Ideally this should inform some process to perform its own restart routines. + + Resume Action\: + The Resume Action will unpause (or unfreeze) the process controlled by the Rule. + Although similar to the Thaw Action, this is intended to communicate to an individual process and inform to Resume. + This is complemented by the Pause Action. + + Reload Action\: + The Reload Action will perform the Reload Action designated in some Rule file. + Ideally this should inform some process to perform its own reload routines. + Many programs often differentiate the concept "reload" from the concept "restart" in that the program remains running during a "reload". + + Start Action\: + The Start Action will perform the Start Action designated in some Rule file. + This action should be used to start some program or script. + This is the action called by Entry file. + This is complemented by the Stop Action. + + Stop Action\: + The Stop Action will perform the Stop Action designated in some Rule file. + This action should be used to stop some program or script. + This is the action called for all running controlled processes on shutdown. + This is complemented by the Start Action. + + Thaw Action\: + The Thaw Action is an extension of a Control Group. + This is internal to the "controller" program and is not customizable via any Rule file. + For a customizable "thaw"-like capability, look into the "pause" and "resume" Actions. + This is complemented by the Freeze Action. + + This designates that a processes Control Group is to be unfrozen. + All Rules (or any process not controlled by the "controller") that is within the same Control Group will be unfrozen. + (@todo consider instead designing this around the Control Groups instead of a "rule".) + (This documentation will likely change with consideration to the above @todo once this gets implemented.) + + This must not attempt to freeze (or unfreeze) the Control Group that the "controller" belongs to. + Therefore, if a Rule does not specify a Control Group, then it is likely that the Thaw Action will be unsupported for that Rule/Control Group. diff --git a/level_3/controller/documents/rule.txt b/level_3/controller/documents/rule.txt index 45199d6..537c63d 100644 --- a/level_3/controller/documents/rule.txt +++ b/level_3/controller/documents/rule.txt @@ -62,13 +62,15 @@ Rule Documentation: A "script" is assumed to be in GNU Bash, which is the default expected behavior, but the specification does not explicitly require this. Another scripting language can be used but changing this incurs the responsibility to ensure all rules are updated to the appropriate scripting language. - There are five primary inner Content to perform: "kill", "restart", "reload", "start", and "stop". + There are seven primary inner Content to perform: "kill", "pause", "restart", "resume", "reload", "start", and "stop". The "kill" Content is performed whenever this rule is executed using the kill action (which is, in general, a forced stop). - The "start" Content is performed whenever this rule is executed using the start action. - The "stop" Content is performed whenever this rule is executed using the stop action. + The "pause" Content is performed whenever this rule is executed using the pause action. The "restart" Content is performed whenever this rule is executed using the restart action. + The "resume" Content is performed whenever this rule is executed using the resume action. The "reload" Content is performed whenever this rule is executed using the reload action. + The "start" Content is performed whenever this rule is executed using the start action. + The "stop" Content is performed whenever this rule is executed using the stop action. When "restart" Content is not provided, then "start" and "stop" is called when the rule is executed using the restart action, if both "start" and "stop" are provided. When "reload", "start", or "stop" Content are not provided, then no respective action is performed. diff --git a/level_3/controller/documents/simulate.txt b/level_3/controller/documents/simulate.txt new file mode 100644 index 0000000..5a45319 --- /dev/null +++ b/level_3/controller/documents/simulate.txt @@ -0,0 +1,24 @@ +# fss-0002 + +Simulate Documentation: + This describes the intent and purpose of the simulation (and testing) parameters. + + The "controller" program is design to support being run as an alternative to an init program (such as Sysvinit or SystemD). + To help prevent problems, testing and simulation functionality is provided. + + The "test" functionality, by itself will simply check the syntax of the Entry and Rule files (for Rule files specified in the Entry file). + Errors are reported and nothing is executed. + + The "test" functionality, when specified along with the "simulate" functionality, will perform just like the "test" functionality without the "simulate" except that additional information of the Rules to be executed will be printed. + There will be no execution or simulated execution of any Rule when both "test" and "simulate" are used togethor. + + The "simulate" functionality, by itself will perform a simulated execution of all Rules designated by the Entry file. + The simulation is not a true simulation in that no program is ever called to pretend to perform any operations. + Furthermore, any "script" specified inside a Rule is only simulated as a whole and not its individual parts. + + When a Rule is simulated, an empty script command (generally defaulting to "bash") is executed in place of the actual program being executed for each program or script in the Rule file that is to be executed. + This allows for testing the designated permissions and other settings that would be applied when calling some program. + At this time, any Control Groups are not simulated but are actually created and the simulating process will actually be placed within the Control Group. + (@todo consider adding an additional parameter optionally to disable this behavior and ignore Control Groups during simulation.) + + (@todo both "test" and "simulate" functionality will need to consider being supported for testing individual Rules when requested by some "control" program.) diff --git a/level_3/controller/specifications/rule.txt b/level_3/controller/specifications/rule.txt index 32d1100..afd0b9e 100644 --- a/level_3/controller/specifications/rule.txt +++ b/level_3/controller/specifications/rule.txt @@ -55,6 +55,8 @@ Rule Specification: The "command" and "script" Rule Types allow the following the FSS-0001 (Extended)\: "kill": One or more Content representing a program being executed and its arguments. + "pause": One or more Content representing a program being executed and its arguments. + "resume": One or more Content representing a program being executed and its arguments. "restart": One or more Content representing a program being executed and its arguments. "reload": One or more Content representing a program being executed and its arguments. "start": One or more Content representing a program being executed and its arguments. @@ -62,6 +64,8 @@ Rule Specification: The "command" and "service" Rule Types allow the following the FSS-0003 (Extended List)\: "kill": A list repesenting multiple programs and their respective arguments to execute. + "pause": A list repesenting multiple programs and their respective arguments to execute. + "resume": A list repesenting multiple programs and their respective arguments to execute. "restart": A list repesenting multiple programs and their respective arguments to execute. "reload": A list repesenting multiple programs and their respective arguments to execute. "start": A list repesenting multiple programs and their respective arguments to execute. @@ -69,6 +73,8 @@ Rule Specification: The "script" Rule Types allow the following the FSS-0003 (Extended List)\: "kill": A list repesenting the contents of a (Bash) shell script. + "pause": A list repesenting the contents of a (Bash) shell script. + "resume": A list repesenting the contents of a (Bash) shell script. "restart": A list repesenting the contents of a (Bash) shell script. "reload": A list repesenting the contents of a (Bash) shell script. "start": A list repesenting the contents of a (Bash) shell script. -- 1.8.3.1