19 #include <sys/types.h>    26 static cib_t *fake_cib = NULL;
    27 static GList *fake_resource_list = NULL;
    28 static const GList *fake_op_fail_list = NULL;
    31                                const char *use_date);
    46     char *action_name = NULL;
    47     const char *prefix = 
"";
    48     const char *action_host = NULL;
    49     const char *clone_name = NULL;
    50     const char *task = 
action->task;
    52     if (
action->node != NULL) {
    53         action_host = 
action->node->details->uname;
    55         action_host = 
"<none>";
    60         task = 
action->cancel_task;
    64         clone_name = 
action->rsc->clone_name;
    67     if (clone_name != NULL) {
    69         guint interval_ms = 0;
    78             const char *n_type = g_hash_table_lookup(
action->meta,
    80             const char *n_task = g_hash_table_lookup(
action->meta,
    81                                                      "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)
   197     set_effective_date(
scheduler, 
true, use_date);
   224                   bool all_actions, 
bool verbose)
   227     FILE *dot_strm = fopen(dot_file, 
"w");
   229     if (dot_strm == NULL) {
   233     fprintf(dot_strm, 
" digraph \"g\" {\n");
   236         const char *style = 
"dashed";
   237         const char *font = 
"black";
   238         const char *color = 
"black";
   239         char *action_name = create_action_name(
action, verbose);
   249         } 
else if ((
action->rsc != NULL)
   269         fprintf(dot_strm, 
"\"%s\" [ style=%s color=\"%s\" fontcolor=\"%s\"]\n",
   270                 action_name, style, color, font);
   278         for (GList *before_iter = 
action->actions_before;
   279              before_iter != NULL; before_iter = before_iter->next) {
   283             char *before_name = NULL;
   284             char *after_name = NULL;
   285             const char *style = 
"dashed";
   286             bool optional = 
true;
   300             if (all_actions || !optional) {
   301                 before_name = create_action_name(before->
action, verbose);
   302                 after_name = create_action_name(
action, verbose);
   303                 fprintf(dot_strm, 
"\"%s\" -> \"%s\" [ style = %s]\n",
   304                         before_name, after_name, style);
   311     fprintf(dot_strm, 
"}\n");
   330 profile_file(
const char *xml_file, 
long long repeat,
   334     xmlNode *cib_object = NULL;
   365     for (
int i = 0; i < repeat; ++i) {
   366         xmlNode *
input = cib_object;
   372         set_effective_date(
scheduler, 
false, use_date);
   378     out->
message(out, 
"profile", xml_file, start, end);
   386     struct dirent **namelist;
   388     int file_num = scandir(dir, &namelist, 0, alphasort);
   394         char buffer[FILENAME_MAX];
   399             if (
'.' == namelist[file_num]->d_name[0]) {
   400                 free(namelist[file_num]);
   405                 free(namelist[file_num]);
   408             snprintf(buffer, 
sizeof(buffer), 
"%s/%s",
   409                      dir, namelist[file_num]->d_name);
   410             if (stat(buffer, &prop) == 0 && S_ISREG(prop.st_mode)) {
   411                 profile_file(buffer, repeat, 
scheduler, use_date);
   413             free(namelist[file_num]);
   436                    const char *use_date)
   439     time_t original_date = 0;
   448         out->
info(out, 
"Setting effective cluster time: %s", use_date);
   452     } 
else if (original_date != 0) {
   455         if (print_original) {
   459             out->
info(out, 
"Using the original execution date of: %s", when);
   481     out->
message(out, 
"inject-pseudo-action", node, task);
   503     const char *rtype = NULL;
   504     const char *rclass = NULL;
   505     const char *resource = NULL;
   506     const char *rprovider = NULL;
   507     const char *resource_config_name = NULL;
   512     xmlNode *cib_node = NULL;
   513     xmlNode *cib_resource = NULL;
   524         crm_debug(
"No history injection for %s op on %s", operation, node);
   528     if (action_rsc == NULL) { 
   540     if (resource_config_name == NULL) { 
   545     resource = resource_config_name;
   549         if ((longname != NULL)
   558         out->
message(out, 
"inject-rsc-action", resource, operation, node,
   575                                  ((router_node == NULL)? uuid: node));
   581                                                  resource_config_name,
   582                                                  rclass, rtype, rprovider);
   583     if (cib_resource == NULL) {
   584         crm_err(
"Could not simulate action %d history for resource %s",
   593                                        target_outcome, 
"User-injected result");
   594     out->
message(out, 
"inject-rsc-action", resource, op->
op_type, node,
   598     for (
const GList *iter = fake_op_fail_list;
   599          iter != NULL; iter = iter->next) {
   600         const char *spec = (
const char *) iter->data;
   602         const char *match_name = NULL;
   607         if (strncasecmp(key, spec, strlen(key)) == 0) {
   608             match_name = resource;
   613         if ((match_name == NULL)
   614             && (strcmp(resource, resource_config_name) != 0)) {
   618             if (strncasecmp(key, spec, strlen(key)) == 0) {
   619                 match_name = resource_config_name;
   624         if (match_name == NULL) {
   629         rc = sscanf(spec, 
"%*[^=]=%d", (
int *) &op->
rc);
   631             out->
err(out, 
"Invalid failed operation '%s' "   632                           "(result code must be integer)", spec);
   636         out->
info(out, 
"Pretending action %d failed with rc=%d",
   677     out->
message(out, 
"inject-cluster-action", node, task, rsc);
   701         GString *xpath = g_string_sized_new(512);
   718         fake_cib->
cmds->
remove(fake_cib, (
const char *) xpath->str, NULL,
   721         g_string_truncate(xpath, 0);
   726         fake_cib->
cmds->
remove(fake_cib, (
const char *) xpath->str, NULL,
   730         g_string_free(xpath, TRUE);
   741                           const GList *op_fail_list)
   747         simulate_pseudo_action,
   748         simulate_resource_action,
   749         simulate_cluster_action,
   750         simulate_fencing_action,
   756     fake_op_fail_list = op_fail_list;
   759         out->
begin_list(out, NULL, NULL, 
"Executing Cluster Transition");
   770     fake_resource_list = NULL;
   773         out->
err(out, 
"Transition failed: %s",
   776         out->
err(out, 
"An invalid transition was produced");
   782         xmlNode *cib_object = NULL;
   783         int rc = fake_cib->
cmds->
query(fake_cib, NULL, &cib_object,
   797                uint32_t section_opts, 
const char *use_date,
   798                const char *input_file, 
const char *graph_file,
   799                const char *dot_file)
   803     xmlNodePtr 
input = NULL;
   832             printed = out->
info(out,
   833                                 "%d of %d resource instances DISABLED and "   834                                 "%d BLOCKED from further action due to failure",
   844                              section_opts, 
"Current cluster status",
   852         || (injections->
node_up != NULL)
   858         || (injections->
watchdog != NULL)) {
   875     if (input_file != NULL) {
   898                             "Assignment Scores and Utilization Information");
   903             out->
begin_list(out, NULL, NULL, 
"Assignment Scores");
   908             out->
begin_list(out, NULL, NULL, 
"Utilization Information");
   923         if (logger_out == NULL) {
   933         if (graph_file != NULL) {
   942         if (dot_file != NULL) {
   943             rc = write_sim_dotfile(
scheduler, dot_file,
   973     set_effective_date(
scheduler, 
true, use_date);
   983     print_cluster_status(
scheduler, 0, section_opts, 
"Revised Cluster Status",
   994               unsigned int section_opts, 
const char *use_date,
   995               const char *input_file, 
const char *graph_file,
   996               const char *dot_file)
  1010                         use_date, input_file, graph_file, dot_file);
 
void(* end_list)(pcmk__output_t *out)
 
#define PCMK__XA_OPERATION_KEY
 
xmlNode * pcmk__xml_copy(xmlNode *parent, xmlNode *src)
 
Actions are ordered if on same node (or migration target for migrate_to) 
 
enum pcmk__graph_status pcmk__simulate_transition(pcmk_scheduler_t *scheduler, cib_t *cib, const GList *op_fail_list)
 
Control output from tools. 
 
#define PCMK__XA_ROUTER_NODE
 
int pcmk__scan_min_int(const char *text, int *result, int minimum)
 
#define crm_time_log_timeofday
 
int cib__signon_query(pcmk__output_t *out, cib_t **cib, xmlNode **cib_object)
 
bool pcmk__strcase_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
 
int(* message)(pcmk__output_t *out, const char *message_id,...)
 
crm_time_t * pcmk__copy_timet(time_t source)
 
#define PCMK_XE_PRIMITIVE
 
#define PCMK__OP_FMT
printf-style format to create operation key from resource, action, interval 
 
pcmk_resource_t * pe_find_resource(GList *rsc_list, const char *id)
 
G_GNUC_INTERNAL xmlNode * pcmk__inject_node_state_change(cib_t *cib_conn, const char *node, bool up)
 
void pe_reset_working_set(pcmk_scheduler_t *scheduler)
Reset scheduler data to default state without freeing it. 
 
#define PCMK__META_OP_TARGET_RC
 
bool(* is_quiet)(pcmk__output_t *out)
 
#define PCMK_ACTION_META_DATA
 
crm_exit_t pcmk_rc2exitc(int rc)
Map a function return code to the most similar exit code. 
 
int pcmk__update_configured_schema(xmlNode **xml, bool to_logs)
Update XML from its configured schema to the latest major series. 
 
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value. 
 
G_GNUC_INTERNAL xmlNode * pcmk__inject_node(cib_t *cib_conn, const char *node, const char *uuid)
 
#define PCMK__META_STONITH_ACTION
 
void pcmk__schedule_actions(xmlNode *cib, unsigned long long flags, pcmk_scheduler_t *scheduler)
 
enum crm_exit_e crm_exit_t
 
void pcmk__xml_output_finish(pcmk__output_t *out, crm_exit_t exit_status, xmlNodePtr *xml)
 
#define CRM_LOG_ASSERT(expr)
 
int(* info)(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
 
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)
 
#define PCMK__META_ON_NODE
 
gboolean cluster_status(pcmk_scheduler_t *scheduler)
 
#define PCMK_XA_OPERATION
 
#define PCMK__XE_TRANSIENT_ATTRIBUTES
 
#define PCMK__OUTPUT_SPACER_IF(out_obj, cond)
 
char * crm_time_as_string(const crm_time_t *dt, int flags)
Get a string representation of a crm_time_t object. 
 
enum pcmk__graph_status pcmk__execute_graph(pcmk__graph_t *graph)
 
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...)
 
int pcmk__simulate(pcmk_scheduler_t *scheduler, pcmk__output_t *out, const pcmk_injections_t *injections, unsigned int flags, uint32_t section_opts, const char *use_date, const char *input_file, const char *graph_file, const char *dot_file)
 
void pcmk__inject_scheduler_input(pcmk_scheduler_t *scheduler, cib_t *cib, const pcmk_injections_t *injections)
 
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. 
 
void pcmk__set_graph_functions(pcmk__graph_functions_t *fns)
 
xmlNode * pcmk__xe_first_child(const xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
 
xmlNode * pcmk_find_cib_element(xmlNode *cib, const char *element_name)
Find an element in the CIB. 
 
int pcmk__xml_output_new(pcmk__output_t **out, xmlNodePtr *xml)
 
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__g_strcat(GString *buffer,...) G_GNUC_NULL_TERMINATED
 
bool pcmk__validate_xml(xmlNode *xml_blob, const char *validation, xmlRelaxNGValidityErrorFunc error_handler, void *error_handler_context)
 
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
 
#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)
 
int(*) int(*) void(* err)(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
 
void pcmk__update_graph(pcmk__graph_t *graph, const pcmk__graph_action_t *action)
 
#define PCMK__META_ON_NODE_UUID
 
void pcmk__register_lib_messages(pcmk__output_t *out)
 
void pcmk__free_graph(pcmk__graph_t *graph)
 
void(* finish)(pcmk__output_t *out, crm_exit_t exit_status, bool print, void **copy_dest)
 
Action completed, result is known. 
 
int(* query)(cib_t *cib, const char *section, xmlNode **output_data, int call_options)
 
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 PCMK_ACTION_STONITH
 
#define PCMK_ACTION_NOTIFIED
 
#define crm_time_log(level, prefix, dt, flags)
 
int pcmk_legacy2rc(int legacy_rc)
 
G_GNUC_INTERNAL void pcmk__output_actions(pcmk_scheduler_t *scheduler)
 
int(* replace)(cib_t *cib, const char *section, xmlNode *data, int call_options)
 
void pe__register_messages(pcmk__output_t *out)
 
#define PCMK_ACTION_DELETE
 
char * pcmk__op_key(const char *rsc_id, const char *op_type, guint interval_ms)
Generate an operation key (RESOURCE_ACTION_INTERVAL) 
 
void free_xml(xmlNode *child)
 
int cib__clean_up_connection(cib_t **cib)
 
Function and executable result codes. 
 
int pcmk__xml_write_file(const xmlNode *xml, const char *filename, bool compress, unsigned int *nbytes)
 
pcmk__graph_t * pcmk__unpack_graph(const xmlNode *xml_graph, const char *reference)
 
#define PCMK_ACTION_CANCEL
 
void cleanup_calculations(pcmk_scheduler_t *scheduler)
Reset scheduler data to defaults without freeing it or constraints. 
 
void pcmk__output_free(pcmk__output_t *out)
 
xmlNode * pcmk__xml_read(const char *filename)
 
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. 
 
#define pcmk__assert(expr)
 
char * pcmk__notify_key(const char *rsc_id, const char *notify_type, const char *op_type)
 
#define crm_log_xml_err(xml, text)
 
#define PCMK_META_INTERVAL
 
#define crm_err(fmt, args...)
 
pcmk_scheduler_t * scheduler
 
char * pcmk__our_nodename
Node name of the local node. 
 
#define pcmk__set_graph_action_flags(action, flags_to_set)
 
crm_time_t * crm_time_new(const char *string)
 
Synthetic cluster events that can be injected into the cluster for running simulations. 
 
void lrmd_free_event(lrmd_event_data_t *event)
Free an executor event. 
 
This structure contains everything that makes up a single output formatter. 
 
void(* begin_list)(pcmk__output_t *out, const char *singular_noun, const char *plural_noun, const char *format,...) G_GNUC_PRINTF(4
 
const char * pcmk__graph_status2text(enum pcmk__graph_status state)
 
#define PCMK__XE_NODE_STATE
 
enum pe_action_flags flags
 
#define PCMK_XA_EXECUTION_DATE
 
#define pcmk__set_action_flags(action, flags_to_set)
 
void pcmk__profile_dir(const char *dir, long long repeat, pcmk_scheduler_t *scheduler, const char *use_date)
 
void pcmk__log_graph(unsigned int log_level, pcmk__graph_t *graph)
 
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)
 
const char * crm_meta_value(GHashTable *hash, const char *field)
Get the value of a meta-attribute. 
 
xmlNode * pcmk__xe_create(xmlNode *parent, const char *name)
 
#define PCMK_XA_CRM_DEBUG_ORIGIN
 
#define pcmk__set_scheduler_flags(scheduler, flags_to_set)
 
#define crm_time_log_date
 
bool pcmk__ends_with_ext(const char *s, const char *match)
 
int pcmk__log_output_new(pcmk__output_t **out)
 
#define PCMK_ACTION_NOTIFY
 
No relation (compare with equality rather than bit set) 
 
#define PCMK_SCORE_INFINITY
Integer score to use to represent "infinity".