19 #include <sys/types.h> 25 #define STATUS_PATH_MAX 512 28 static cib_t *fake_cib = NULL;
29 static GList *fake_resource_list = NULL;
30 static GList *fake_op_fail_list = NULL;
48 char *action_name = NULL;
49 const char *prefix =
"";
50 const char *action_host = NULL;
51 const char *clone_name = NULL;
52 const char *task =
action->task;
54 if (
action->node != NULL) {
55 action_host =
action->node->details->uname;
57 action_host =
"<none>";
62 task =
action->cancel_task;
66 clone_name =
action->rsc->clone_name;
69 if (clone_name != NULL) {
71 guint interval_ms = 0;
81 const char *n_type = g_hash_table_lookup(
action->meta,
83 const char *n_task = g_hash_table_lookup(
action->meta,
84 "notify_key_operation");
93 if (action_host != NULL) {
95 prefix, key, action_host);
102 const char *op = g_hash_table_lookup(
action->meta,
"stonith_action");
105 prefix,
action->task, op, action_host);
107 }
else if (
action->rsc && action_host) {
109 prefix,
action->uuid, action_host);
111 }
else if (action_host) {
113 prefix,
action->task, action_host);
123 action_name = with_id;
140 uint32_t section_opts,
const char *title,
bool print_spacer)
149 all = g_list_prepend(all, (gpointer)
"*");
152 out->
begin_list(out, NULL, NULL,
"%s", title);
154 section_opts, show_opts, NULL, all, all);
173 out->
begin_list(out, NULL, NULL,
"Transition Summary");
190 char *use_date,
unsigned int flags)
194 set_effective_date(
data_set,
true, use_date);
221 bool all_actions,
bool verbose)
224 FILE *dot_strm = fopen(dot_file,
"w");
226 if (dot_strm == NULL) {
230 fprintf(dot_strm,
" digraph \"g\" {\n");
233 const char *style =
"dashed";
234 const char *font =
"black";
235 const char *color =
"black";
236 char *action_name = create_action_name(
action, verbose);
246 }
else if ((
action->rsc != NULL)
266 fprintf(dot_strm,
"\"%s\" [ style=%s color=\"%s\" fontcolor=\"%s\"]\n",
267 action_name, style, color, font);
275 GList *gIter2 = NULL;
277 for (gIter2 =
action->actions_before; gIter2 != NULL; gIter2 = gIter2->next) {
280 char *before_name = NULL;
281 char *after_name = NULL;
282 const char *style =
"dashed";
283 bool optional =
true;
296 if (all_actions || !optional) {
297 before_name = create_action_name(before->
action, verbose);
298 after_name = create_action_name(
action, verbose);
299 fprintf(dot_strm,
"\"%s\" -> \"%s\" [ style = %s]\n",
300 before_name, after_name, style);
307 fprintf(dot_strm,
"}\n");
330 xmlNode *cib_object = NULL;
361 for (
int i = 0; i < repeat; ++i) {
362 xmlNode *
input = (repeat == 1)? cib_object :
copy_xml(cib_object);
365 set_effective_date(
data_set,
false, use_date);
371 out->
message(out,
"profile", xml_file, start, end);
378 struct dirent **namelist;
380 int file_num = scandir(dir, &namelist, 0,
alphasort);
386 char buffer[FILENAME_MAX];
391 if (
'.' == namelist[file_num]->d_name[0]) {
392 free(namelist[file_num]);
397 free(namelist[file_num]);
400 snprintf(buffer,
sizeof(buffer),
"%s/%s", dir, namelist[file_num]->d_name);
401 if (stat(buffer, &prop) == 0 && S_ISREG(prop.st_mode)) {
402 profile_file(buffer, repeat,
data_set, use_date);
404 free(namelist[file_num]);
430 time_t original_date = 0;
438 out->
info(out,
"Setting effective cluster time: %s", use_date);
442 }
else if (original_date) {
447 if (print_original) {
451 out->
info(out,
"Using the original execution date of: %s", when);
473 out->
message(out,
"inject-pseudo-action", node, task);
495 const char *rtype = NULL;
496 const char *rclass = NULL;
497 const char *resource = NULL;
498 const char *rprovider = NULL;
499 const char *resource_config_name = NULL;
504 xmlNode *cib_node = NULL;
505 xmlNode *cib_resource = NULL;
515 crm_debug(
"No history injection for %s op on %s", operation, node);
519 if (action_rsc == NULL) {
531 if (resource_config_name == NULL) {
536 resource = resource_config_name;
540 if ((longname != NULL)
548 out->
message(out,
"inject-rsc-action", resource, operation, node,
565 ((router_node == NULL)? uuid: node));
571 resource_config_name,
572 rclass, rtype, rprovider);
573 if (cib_resource == NULL) {
574 crm_err(
"Could not simulate action %d history for resource %s",
583 target_outcome,
"User-injected result");
584 out->
message(out,
"inject-rsc-action", resource, op->
op_type, node,
588 for (GList *iter = fake_op_fail_list; iter != NULL; iter = iter->next) {
589 char *spec = (
char *) iter->data;
591 const char *match_name = NULL;
596 if (strncasecmp(key, spec, strlen(key)) == 0) {
597 match_name = resource;
602 if ((match_name == NULL)
603 && (strcmp(resource, resource_config_name) != 0)) {
607 if (strncasecmp(key, spec, strlen(key)) == 0) {
608 match_name = resource_config_name;
613 if (match_name == NULL) {
618 rc = sscanf(spec,
"%*[^=]=%d", (
int *) &op->
rc);
620 out->
err(out,
"Invalid failed operation '%s' " 621 "(result code must be integer)", spec);
625 out->
info(out,
"Pretending action %d failed with rc=%d",
665 out->
message(out,
"inject-cluster-action", node, task, rsc);
729 simulate_pseudo_action,
730 simulate_resource_action,
731 simulate_cluster_action,
732 simulate_fencing_action,
738 fake_op_fail_list = op_fail_list;
741 out->
begin_list(out, NULL, NULL,
"Executing Cluster Transition");
752 fake_resource_list = NULL;
755 out->
err(out,
"Transition failed: %s",
758 out->
err(out,
"An invalid transition was produced");
764 xmlNode *cib_object = NULL;
765 int rc = fake_cib->
cmds->
query(fake_cib, NULL, &cib_object,
779 uint32_t section_opts,
char *use_date,
char *input_file,
780 char *graph_file,
char *dot_file)
784 xmlNodePtr
input = NULL;
802 printed = out->
info(out,
803 "%d of %d resource instances DISABLED and " 804 "%d BLOCKED from further action due to failure",
815 section_opts,
"Current cluster status",
823 || (injections->
node_up != NULL)
829 || (injections->
watchdog != NULL)) {
846 if (input_file != NULL) {
869 "Allocation Scores and Utilization Information");
874 out->
begin_list(out, NULL, NULL,
"Allocation Scores");
879 out->
begin_list(out, NULL, NULL,
"Utilization Information");
884 if (logger_out == NULL) {
893 if (logger_out == NULL) {
903 if (graph_file != NULL) {
911 if (dot_file != NULL) {
912 rc = write_sim_dotfile(
data_set, dot_file,
942 set_effective_date(
data_set,
true, use_date);
952 print_cluster_status(
data_set, 0, section_opts,
"Revised Cluster Status",
963 unsigned int section_opts,
char *use_date,
char *input_file,
964 char *graph_file,
char *dot_file)
978 use_date, input_file, graph_file, dot_file);
void(* end_list)(pcmk__output_t *out)
void pcmk__update_graph(crm_graph_t *graph, crm_action_t *action)
pcmk__output_t * pcmk__new_logger(void)
const char * pcmk__graph_status2text(enum transition_status state)
#define pe__set_action_flags(action, flags_to_set)
void pcmk__inject_scheduler_input(pe_working_set_t *data_set, cib_t *cib, pcmk_injections_t *injections)
Control output from tools.
int pcmk__scan_min_int(const char *text, int *result, int minimum)
#define crm_time_log_timeofday
bool pcmk__strcase_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
int(* message)(pcmk__output_t *out, const char *message_id,...)
Internal tracking for transition graph creation.
#define pe_flag_no_compat
xmlNode * first_named_child(const xmlNode *parent, const char *name)
G_GNUC_INTERNAL xmlNode * pcmk__inject_node_state_change(cib_t *cib_conn, const char *node, bool up)
#define pe_flag_maintenance_mode
bool(* is_quiet)(pcmk__output_t *out)
G_GNUC_INTERNAL void pcmk__inject_failcount(pcmk__output_t *out, xmlNode *cib_node, const char *resource, const char *task, guint interval_ms, int rc)
#define XML_TAG_TRANSIENT_NODEATTRS
int alphasort(const void *dirent1, const void *dirent2)
const char * crm_meta_value(GHashTable *hash, const char *field)
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
void lrmd_free_event(lrmd_event_data_t *event)
Free an executor event.
int write_xml_file(xmlNode *xml_node, const char *filename, gboolean compress)
Write XML to a file.
G_GNUC_INTERNAL xmlNode * pcmk__inject_node(cib_t *cib_conn, const char *node, const char *uuid)
enum crm_exit_e crm_exit_t
pe_resource_t * pe_find_resource(GList *rsc_list, const char *id_rh)
#define CRM_LOG_ASSERT(expr)
int(* info)(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
xmlNode * filename2xml(const char *filename)
gboolean validate_xml(xmlNode *xml_blob, const char *validation, gboolean to_logs)
int pcmk__out_prologue(pcmk__output_t **out, xmlNodePtr *xml)
#define PCMK__OUTPUT_SPACER_IF(out_obj, cond)
#define XML_LRM_ATTR_TASK_KEY
xmlNode * copy_xml(xmlNode *src_node)
int cib__signon_query(cib_t **cib, xmlNode **cib_object)
#define XML_LRM_ATTR_TASK
void pe_reset_working_set(pe_working_set_t *data_set)
Reset a working set to default state without freeing it.
void cleanup_calculations(pe_working_set_t *data_set)
Reset working set to default state without freeing it or constraints.
char * pcmk__notify_key(const char *rsc_id, const char *notify_type, const char *op_type)
int pcmk__guint_from_hash(GHashTable *table, const char *key, guint default_val, guint *result)
cib_api_operations_t * cmds
#define crm_debug(fmt, args...)
#define pe_flag_sanitized
int pcmk_simulate(xmlNodePtr *xml, pe_working_set_t *data_set, pcmk_injections_t *injections, unsigned int flags, unsigned int section_opts, char *use_date, char *input_file, char *graph_file, char *dot_file)
Simulate a cluster's response to events.
lrmd_event_data_t * pcmk__event_from_graph_action(xmlNode *resource, crm_action_t *action, int status, int rc, const char *exit_reason)
char * crm_element_value_copy(const xmlNode *data, const char *name)
Retrieve a copy of the value of an XML attribute.
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
#define XML_CIB_TAG_RESOURCE
enum transition_status pcmk__simulate_transition(pe_working_set_t *data_set, cib_t *cib, GList *op_fail_list)
xmlNode * pcmk_find_cib_element(xmlNode *cib, const char *element_name)
Find an element in the CIB.
void pcmk__profile_dir(const char *dir, long long repeat, pe_working_set_t *data_set, char *use_date)
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
void crm_time_set_timet(crm_time_t *target, time_t *source)
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
int(* modify)(cib_t *cib, const char *section, xmlNode *data, int call_options)
void pcmk__set_graph_functions(crm_graph_functions_t *fns)
#define XML_AGENT_ATTR_PROVIDER
int(*) void(* err)(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
void pcmk__register_lib_messages(pcmk__output_t *out)
pe_working_set_t * data_set
void(* finish)(pcmk__output_t *out, crm_exit_t exit_status, bool print, void **copy_dest)
xmlNode * create_xml_node(xmlNode *parent, const char *name)
Action completed, result is known.
int(* query)(cib_t *cib, const char *section, xmlNode **output_data, int call_options)
void pcmk__free_graph(crm_graph_t *graph)
int crm_element_value_epoch(const xmlNode *xml, const char *name, time_t *dest)
Retrieve the seconds-since-epoch value of an XML attribute.
#define crm_time_log(level, prefix, dt, flags)
#define crm__set_graph_action_flags(action, flags_to_set)
int pcmk_legacy2rc(int legacy_rc)
int pcmk__simulate(pe_working_set_t *data_set, pcmk__output_t *out, pcmk_injections_t *injections, unsigned int flags, uint32_t section_opts, char *use_date, char *input_file, char *graph_file, char *dot_file)
G_GNUC_INTERNAL void pcmk__output_actions(pe_working_set_t *data_set)
int(* replace)(cib_t *cib, const char *section, xmlNode *data, int call_options)
void pe__register_messages(pcmk__output_t *out)
#define XML_LRM_ATTR_ROUTER_NODE
void free_xml(xmlNode *child)
void pcmk__out_epilogue(pcmk__output_t *out, xmlNodePtr *xml, int retval)
int cib__clean_up_connection(cib_t **cib)
Function and executable result codes.
char * pcmk__op_key(const char *rsc_id, const char *op_type, guint interval_ms)
Generate an operation key (RESOURCE_ACTION_INTERVAL)
char * crm_time_as_string(crm_time_t *dt, int flags)
#define XML_LRM_ATTR_TARGET_UUID
void pcmk__output_free(pcmk__output_t *out)
void pcmk__log_graph(unsigned int log_level, crm_graph_t *graph)
#define crm_log_xml_err(xml, text)
#define pe_flag_show_utilization
#define crm_err(fmt, args...)
gboolean cluster_status(pe_working_set_t *data_set)
crm_time_t * crm_time_new(const char *string)
Synthetic cluster events that can be injected into the cluster for running simulations.
This structure contains everything that makes up a single output formatter.
#define XML_LRM_ATTR_INTERVAL_MS
void(* begin_list)(pcmk__output_t *out, const char *singular_noun, const char *plural_noun, const char *format,...) G_GNUC_PRINTF(4
#define pe__set_working_set_flags(working_set, flags_to_set)
enum transition_status pcmk__execute_graph(crm_graph_t *graph)
crm_graph_t * pcmk__unpack_graph(xmlNode *xml_graph, const char *reference)
enum pe_action_flags flags
#define XML_CIB_TAG_STATUS
G_GNUC_INTERNAL xmlNode * pcmk__inject_action_result(xmlNode *cib_resource, lrmd_event_data_t *op, int target_rc)
int(* remove)(cib_t *cib, const char *section, xmlNode *data, int call_options)
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)
Data types for cluster status.
#define XML_LRM_ATTR_TARGET
gboolean cli_config_update(xmlNode **xml, int *best_version, gboolean to_logs)
#define pe_flag_show_scores
void pcmk__schedule_actions(xmlNode *cib, unsigned long long flags, pe_working_set_t *data_set)
#define crm_time_log_date
bool pcmk__ends_with_ext(const char *s, const char *match)
#define XML_ATTR_TE_TARGET_RC
#define XML_AGENT_ATTR_CLASS