25static const char *profiling_dir = NULL;
27static cib_t *fake_cib = NULL;
28static GList *fake_resource_list = NULL;
29static const GList *fake_op_fail_list = NULL;
32 const char *use_date);
47 char *action_name = NULL;
48 const char *prefix =
"";
49 const char *action_host = NULL;
50 const char *history_id = NULL;
51 const char *task =
action->task;
53 if (
action->node != NULL) {
54 action_host =
action->node->priv->name;
56 action_host =
"<none>";
61 task =
action->cancel_task;
65 history_id =
action->rsc->priv->history_id;
68 if (history_id != NULL) {
70 guint interval_ms = 0;
79 const char *n_type = g_hash_table_lookup(
action->meta,
81 const char *n_task = g_hash_table_lookup(
action->meta,
82 "notify_key_operation");
90 if (action_host != NULL) {
92 prefix, key, action_host);
100 const char *op = g_hash_table_lookup(
action->meta,
104 prefix,
action->task, op, action_host);
106 }
else if (
action->rsc && action_host) {
108 prefix,
action->uuid, action_host);
110 }
else if (action_host) {
112 prefix,
action->task, action_host);
122 action_name = with_id;
139 uint32_t section_opts,
const char *title,
150 all = g_list_prepend(all, (gpointer)
"*");
153 out->
begin_list(out, NULL, NULL,
"%s", title);
154 out->
message(out,
"cluster-status",
176 out->
begin_list(out, NULL, NULL,
"Transition Summary");
193 const char *use_date,
unsigned int flags)
199 set_effective_date(
scheduler,
true, use_date);
227 bool all_actions,
bool verbose)
230 FILE *dot_strm = fopen(dot_file,
"w");
232 if (dot_strm == NULL) {
236 fprintf(dot_strm,
" digraph \"g\" {\n");
239 const char *style =
"dashed";
240 const char *font =
"black";
241 const char *color = NULL;
242 char *action_name = create_action_name(
action, verbose);
252 }
else if ((
action->rsc != NULL)
272 fprintf(dot_strm,
"\"%s\" [ style=%s color=\"%s\" fontcolor=\"%s\"]\n",
273 action_name, style, color, font);
281 for (GList *before_iter =
action->actions_before;
282 before_iter != NULL; before_iter = before_iter->next) {
286 char *before_name = NULL;
287 char *after_name = NULL;
288 const char *style =
"dashed";
289 bool optional =
true;
303 if (all_actions || !optional) {
304 before_name = create_action_name(before->
action, verbose);
305 after_name = create_action_name(
action, verbose);
306 fprintf(dot_strm,
"\"%s\" -> \"%s\" [ style = %s]\n",
307 before_name, after_name, style);
314 fprintf(dot_strm,
"}\n");
331profile_filter(
const struct dirent *entry)
333 const char *filename = entry->d_name;
342 if (filename[0] ==
'.') {
343 crm_trace(
"Not profiling hidden file '%s'", filename);
347 crm_trace(
"Not profiling file '%s' without '.xml' extension", filename);
352 if ((stat(buf, &sb) != 0) || !S_ISREG(sb.st_mode)) {
353 crm_trace(
"Not profiling file '%s': not a regular file", filename);
380profile_file(
const char *xml_file,
unsigned int repeat,
384 xmlNode *cib_object = NULL;
405 for (
int i = 0; i < repeat; ++i) {
410 set_effective_date(
scheduler,
false, use_date);
416 out->
message(out,
"profile", xml_file, start, end);
424 unsigned int repeat,
const char *use_date)
428 struct dirent **namelist = NULL;
449 num_files = scandir(dir, &namelist, profile_filter, alphasort);
450 profiling_dir = NULL;
456 if (num_files == 0) {
462 for (
int i = 0; i < num_files; i++) {
466 profile_file(
path, repeat,
scheduler, scheduler_flags, use_date);
493 const char *use_date)
496 time_t original_date = 0;
505 out->
info(out,
"Setting effective cluster time: %s", use_date);
509 }
else if (original_date != 0) {
512 if (print_original) {
517 out->
info(out,
"Using the original execution date of: %s", when);
539 out->
message(out,
"inject-pseudo-action", node, task);
561 const char *rtype = NULL;
562 const char *rclass = NULL;
563 const char *resource = NULL;
564 const char *rprovider = NULL;
565 const char *resource_config_name = NULL;
570 xmlNode *cib_node = NULL;
571 xmlNode *cib_resource = NULL;
582 crm_debug(
"No history injection for %s op on %s", operation, node);
586 if (action_rsc == NULL) {
598 if (resource_config_name == NULL) {
603 resource = resource_config_name;
607 if ((longname != NULL)
616 out->
message(out,
"inject-rsc-action", resource, operation, node,
633 ((router_node == NULL)? uuid: node));
639 resource_config_name,
640 rclass, rtype, rprovider);
641 if (cib_resource == NULL) {
642 crm_err(
"Could not simulate action %d history for resource %s",
651 target_outcome,
"User-injected result");
652 out->
message(out,
"inject-rsc-action", resource, op->
op_type, node,
656 for (
const GList *iter = fake_op_fail_list;
657 iter != NULL; iter = iter->next) {
658 const char *spec = (
const char *) iter->data;
660 const char *match_name = NULL;
661 const char *offset = NULL;
666 if (strncasecmp(key, spec, strlen(key)) == 0) {
667 match_name = resource;
672 if ((match_name == NULL)
673 && (strcmp(resource, resource_config_name) != 0)) {
677 if (strncasecmp(key, spec, strlen(key)) == 0) {
678 match_name = resource_config_name;
683 if (match_name == NULL) {
688 rc = sscanf(spec,
"%*[^=]=%d", (
int *) &op->
rc);
690 out->
err(out,
"Invalid failed operation '%s' "
691 "(result code must be integer)", spec);
695 out->
info(out,
"Pretending action %d failed with rc=%d",
746 out->
message(out,
"inject-cluster-action", node, task, rsc);
770 GString *xpath = g_string_sized_new(512);
787 fake_cib->
cmds->
remove(fake_cib, (
const char *) xpath->str, NULL,
790 g_string_truncate(xpath, 0);
795 fake_cib->
cmds->
remove(fake_cib, (
const char *) xpath->str, NULL,
799 g_string_free(xpath, TRUE);
810 const GList *op_fail_list)
816 simulate_pseudo_action,
817 simulate_resource_action,
818 simulate_cluster_action,
819 simulate_fencing_action,
825 fake_op_fail_list = op_fail_list;
828 out->
begin_list(out, NULL, NULL,
"Executing Cluster Transition");
839 fake_resource_list = NULL;
842 out->
err(out,
"Transition failed: %s",
845 out->
err(out,
"An invalid transition was produced");
851 xmlNode *cib_object = NULL;
852 int rc = fake_cib->
cmds->
query(fake_cib, NULL, &cib_object,
866 uint32_t section_opts,
const char *use_date,
867 const char *input_file,
const char *graph_file,
868 const char *dot_file)
872 xmlNodePtr
input = NULL;
893 printed = out->
info(out,
894 "%d of %d resource instances DISABLED and "
895 "%d BLOCKED from further action due to failure",
905 section_opts,
"Current cluster status",
913 || (injections->
node_up != NULL)
919 || (injections->
watchdog != NULL)) {
934 if (input_file != NULL) {
949 "Assignment Scores and Utilization Information");
954 out->
begin_list(out, NULL, NULL,
"Assignment Scores");
959 out->
begin_list(out, NULL, NULL,
"Utilization Information");
974 if (logger_out == NULL) {
984 if (graph_file != NULL) {
993 if (dot_file != NULL) {
994 rc = write_sim_dotfile(
scheduler, dot_file,
1024 set_effective_date(
scheduler,
true, use_date);
1034 print_cluster_status(
scheduler, 0, section_opts,
"Revised Cluster Status",
1046 unsigned int section_opts,
const char *use_date,
1047 const char *input_file,
const char *graph_file,
1048 const char *dot_file)
1062 (uint32_t) section_opts, use_date, input_file,
1063 graph_file, dot_file);
@ pcmk__ar_none
No relation (compare with equality rather than bit set)
@ pcmk__ar_if_on_same_node_or_target
Actions are ordered if on same node (or migration target for migrate_to)
#define PCMK_ACTION_CANCEL
#define PCMK_ACTION_META_DATA
#define PCMK_ACTION_START
#define PCMK_ACTION_NOTIFIED
#define PCMK_ACTION_DELETE
#define PCMK_ACTION_STONITH
#define PCMK_ACTION_NOTIFY
@ pcmk__action_added_to_graph
char * pcmk__notify_key(const char *rsc_id, const char *notify_type, const char *op_type)
#define pcmk__set_action_flags(action, flags_to_set)
char * pcmk__op_key(const char *rsc_id, const char *op_type, guint interval_ms)
Generate an operation key (RESOURCE_ACTION_INTERVAL)
#define PCMK__OP_FMT
printf-style format to create operation key from resource, action, interval
int cib__clean_up_connection(cib_t **cib)
int cib__signon_query(pcmk__output_t *out, cib_t **cib, xmlNode **cib_object)
xmlNode * pcmk_find_cib_element(xmlNode *cib, const char *element_name)
Find an element in the CIB.
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
@ pcmk_pacemakerd_state_invalid
#define crm_time_log_timeofday
char * crm_time_as_string(const crm_time_t *dt, int flags)
Get a string representation of a crm_time_t object.
#define crm_time_log_date
crm_time_t * crm_time_new(const char *string)
#define crm_time_log(level, prefix, dt, flags)
crm_time_t * pcmk__copy_timet(time_t source)
G_GNUC_INTERNAL xmlNode * pcmk__inject_action_result(xmlNode *cib_resource, lrmd_event_data_t *op, const char *node, int target_rc)
G_GNUC_INTERNAL xmlNode * pcmk__inject_node(cib_t *cib_conn, const char *node, const char *uuid)
G_GNUC_INTERNAL xmlNode * pcmk__inject_node_state_change(cib_t *cib_conn, const char *node, bool up)
G_GNUC_INTERNAL void pcmk__inject_scheduler_input(pcmk_scheduler_t *scheduler, cib_t *cib, const pcmk_injections_t *injections)
G_GNUC_INTERNAL void pcmk__inject_failcount(pcmk__output_t *out, cib_t *cib_conn, xmlNode *cib_node, const char *resource, const char *task, guint interval_ms, int rc, bool infinity)
G_GNUC_INTERNAL void pcmk__output_actions(pcmk_scheduler_t *scheduler)
G_GNUC_INTERNAL xmlNode * pcmk__inject_resource_history(pcmk__output_t *out, xmlNode *cib_node, const char *resource, const char *lrm_name, const char *rclass, const char *rtype, const char *rprovider)
#define CRM_LOG_ASSERT(expr)
#define crm_log_xml_err(xml, text)
#define crm_debug(fmt, args...)
#define crm_err(fmt, args...)
#define crm_trace(fmt, args...)
void lrmd_free_event(lrmd_event_data_t *event)
Free an executor event.
pcmk_scheduler_t * scheduler
const char * crm_meta_value(GHashTable *hash, const char *field)
Get the value of a meta-attribute.
#define PCMK_META_INTERVAL
#define PCMK_VALUE_INFINITY
#define PCMK__META_ON_NODE_UUID
#define PCMK__META_ON_NODE
#define PCMK__META_OP_TARGET_RC
#define PCMK__META_STONITH_ACTION
Control output from tools.
@ pcmk_show_failed_detail
@ pcmk_show_inactive_rscs
void pcmk__xml_output_finish(pcmk__output_t *out, crm_exit_t exit_status, xmlNodePtr *xml)
void pcmk__output_free(pcmk__output_t *out)
int pcmk__xml_output_new(pcmk__output_t **out, xmlNodePtr *xml)
#define PCMK__OUTPUT_SPACER_IF(out_obj, cond)
int pcmk__log_output_new(pcmk__output_t **out)
@ pcmk_sim_show_utilization
int pcmk__simulate(pcmk_scheduler_t *scheduler, pcmk__output_t *out, const pcmk_injections_t *injections, uint32_t flags, uint32_t section_opts, const char *use_date, const char *input_file, const char *graph_file, const char *dot_file)
int pcmk_simulate(xmlNodePtr *xml, pcmk_scheduler_t *scheduler, const pcmk_injections_t *injections, unsigned int flags, unsigned int section_opts, const char *use_date, const char *input_file, const char *graph_file, const char *dot_file)
Simulate a cluster's response to events.
enum pcmk__graph_status pcmk__simulate_transition(pcmk_scheduler_t *scheduler, cib_t *cib, const GList *op_fail_list)
int pcmk__profile_dir(pcmk__output_t *out, uint32_t flags, const char *dir, unsigned int repeat, const char *use_date)
@ pcmk__fence_history_none
void pcmk__register_lib_messages(pcmk__output_t *out)
void pcmk__schedule_actions(pcmk_scheduler_t *scheduler)
@ pcmk__graph_action_confirmed
@ pcmk__graph_action_failed
void pcmk__free_graph(pcmk__graph_t *graph)
pcmk__graph_t * pcmk__unpack_graph(const xmlNode *xml_graph, const char *reference)
void pcmk__set_graph_functions(pcmk__graph_functions_t *fns)
const char * pcmk__graph_status2text(enum pcmk__graph_status state)
enum pcmk__graph_status pcmk__execute_graph(pcmk__graph_t *graph)
lrmd_event_data_t * pcmk__event_from_graph_action(const xmlNode *resource, const pcmk__graph_action_t *action, int status, int rc, const char *exit_reason)
void pcmk__update_graph(pcmk__graph_t *graph, const pcmk__graph_action_t *action)
void pcmk__log_graph(unsigned int log_level, pcmk__graph_t *graph)
#define pcmk__set_graph_action_flags(action, flags_to_set)
void pe__register_messages(pcmk__output_t *out)
Function and executable result codes.
@ pcmk_rc_invalid_transition
@ PCMK_EXEC_DONE
Action completed, result is known.
int pcmk_legacy2rc(int legacy_rc)
enum crm_exit_e crm_exit_t
Exit status codes for tools and daemons.
crm_exit_t pcmk_rc2exitc(int rc)
Map a function return code to the most similar exit code.
#define pcmk__assert(expr)
void pcmk_free_scheduler(pcmk_scheduler_t *scheduler)
Free scheduler data.
pcmk_scheduler_t * pcmk_new_scheduler(void)
Create a new object to hold scheduler data.
void pcmk_reset_scheduler(pcmk_scheduler_t *scheduler)
Reset scheduler data to defaults.
#define pcmk__set_scheduler_flags(scheduler, flags_to_set)
@ pcmk__sched_in_maintenance
@ pcmk__sched_show_utilization
@ pcmk__sched_output_scores
bool pcmk__validate_xml(xmlNode *xml_blob, const char *validation, xmlRelaxNGValidityErrorFunc error_handler, void *error_handler_context)
int pcmk__update_configured_schema(xmlNode **xml, bool to_logs)
Update XML from its configured schema to the latest major series.
bool pcmk_str_is_infinity(const char *s)
#define PCMK_SCORE_INFINITY
Integer score to use to represent "infinity".
pcmk_resource_t * pe_find_resource(GList *rsc_list, const char *id)
gboolean cluster_status(pcmk_scheduler_t *scheduler)
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
int pcmk__scan_min_int(const char *text, int *result, int minimum)
bool pcmk__ends_with_ext(const char *s, const char *match)
bool pcmk__strcase_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
int pcmk__guint_from_hash(GHashTable *table, const char *key, guint default_val, guint *result)
bool pcmk__str_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
void pcmk__g_strcat(GString *buffer,...) G_GNUC_NULL_TERMINATED
int(* remove)(cib_t *cib, const char *section, xmlNode *data, int call_options)
int(* query)(cib_t *cib, const char *section, xmlNode **output_data, int call_options)
int(* replace)(cib_t *cib, const char *section, xmlNode *data, int call_options)
int(* modify)(cib_t *cib, const char *section, xmlNode *data, int call_options)
cib_api_operations_t * cmds
char * failed_stop_offset
Failcount after one failed stop action.
char * failed_start_offset
Failcount after one failed start action.
This structure contains everything that makes up a single output formatter.
void(* end_list)(pcmk__output_t *out)
int(* message)(pcmk__output_t *out, const char *message_id,...)
bool(* is_quiet)(pcmk__output_t *out)
int int void(* err)(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
void(* finish)(pcmk__output_t *out, crm_exit_t exit_status, bool print, void **copy_dest)
void(* begin_list)(pcmk__output_t *out, const char *singular_noun, const char *plural_noun, const char *format,...) G_GNUC_PRINTF(4
int(* info)(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
pcmk__scheduler_private_t * priv
Synthetic cluster events that can be injected into the cluster for running simulations.
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
char * crm_element_value_copy(const xmlNode *data, const char *name)
Retrieve a copy of the value of an XML attribute.
int crm_element_value_epoch(const xmlNode *xml, const char *name, time_t *dest)
Retrieve the seconds-since-epoch value of an XML attribute.
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
xmlNode * pcmk__xe_first_child(const xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
xmlNode * pcmk__xe_create(xmlNode *parent, const char *name)
xmlNode * pcmk__xml_copy(xmlNode *parent, xmlNode *src)
void pcmk__xml_free(xmlNode *xml)
xmlNode * pcmk__xml_read(const char *filename)
int pcmk__xml_write_file(const xmlNode *xml, const char *filename, bool compress)
#define PCMK_XA_EXECUTION_DATE
#define PCMK_XA_OPERATION
#define PCMK_XE_PRIMITIVE
#define PCMK_XA_CRM_DEBUG_ORIGIN
#define PCMK__XE_TRANSIENT_ATTRIBUTES
#define PCMK__XA_ROUTER_NODE
#define PCMK__XA_OPERATION_KEY
#define PCMK__XE_NODE_STATE