diff --git a/GNUmakefile b/GNUmakefile index f28dea8..7a4c929 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -325,7 +325,7 @@ clang: test -e $(CLANG_analyzer) scan-build $(CLANG_checkers:%=-enable-checker %) make -# V3 = scandir unsetenv alphasort +# V3 = scandir unsetenv alphasort xalloc # V2 = setenv strerror strchrnul strndup # http://www.gnu.org/software/gnulib/manual/html_node/Initial-import.html#Initial-import GNU_MODS = crypto/md5 diff --git a/crmd/lrm.c b/crmd/lrm.c index b68f657..8315f6f 100644 --- a/crmd/lrm.c +++ b/crmd/lrm.c @@ -630,7 +630,7 @@ append_restart_list(lrmd_rsc_info_t * rsc, lrmd_event_data_t * op, xmlNode * upd crm_xml_add(restart, param, value); } len += strlen(param) + 2; - list = realloc(list, len + 1); + list = realloc_safe(list, len + 1); sprintf(list + start, " %s ", param); } diff --git a/cts/CIB.py b/cts/CIB.py index d26efdb..7922d8b 100644 --- a/cts/CIB.py +++ b/cts/CIB.py @@ -298,7 +298,28 @@ class CIB11(ConfigBase): # Group Resource g = Group(self.Factory, "group-1") g.add_child(self.NewIP()) - g.add_child(self.NewIP()) + + if self.CM.Env["have_systemd"]: + dummy_service_file = """ +[Unit] +Description=Dummy resource that takes a while to start + +[Service] +Type=notify +ExecStart=/usr/bin/python -c 'import time; import systemd.daemon;time.sleep(10); systemd.daemon.notify("READY=1"); time.sleep(3600)' +ExecStop=sleep 10 +ExecStop=/bin/kill -KILL $MAINPID +""" + + os.system("cat <<-END >/tmp/DummySD.service\n%s\nEND" % (dummy_service_file)) + + self.CM.install_helper("DummySD.service", destdir="/usr/lib/systemd/system/", sourcedir="/tmp") + sysd = Resource(self.Factory, "petulant", "DummySD", "service") + sysd.add_op("monitor", "P10S") + g.add_child(sysd) + else: + g.add_child(self.NewIP()) + g.add_child(self.NewIP()) # Group with the master diff --git a/cts/environment.py b/cts/environment.py index d741452..2b2a343 100644 --- a/cts/environment.py +++ b/cts/environment.py @@ -283,9 +283,9 @@ class Environment: break; self["cts-master"] = master - if self.has_key("have_systemd"): - self["have_systemd"] = not rsh(discover, "systemctl list-units") - + if not self.has_key("have_systemd"): + self["have_systemd"] = not self.rsh(self.target, "systemctl list-units") + self.detect_syslog() self.detect_at_boot() self.detect_ip_offset() diff --git a/fencing/standalone_config.c b/fencing/standalone_config.c index 01c22b6..4319c4a 100644 --- a/fencing/standalone_config.c +++ b/fencing/standalone_config.c @@ -170,7 +170,7 @@ standalone_cfg_add_node(const char *node, const char *device, const char *ports) if (tmp) { offset = strlen(tmp); - tmp = realloc(tmp, len + offset + 1); + tmp = realloc_safe(tmp, len + offset + 1); } else { tmp = malloc(len); } diff --git a/include/crm_internal.h b/include/crm_internal.h index 3eb88de..169d6d3 100644 --- a/include/crm_internal.h +++ b/include/crm_internal.h @@ -341,4 +341,16 @@ void cib_ipc_servers_destroy(qb_ipcs_service_t *ipcs_ro, qb_ipcs_service_t *ipcs_rw, qb_ipcs_service_t *ipcs_shm); +static inline void *realloc_safe(void *ptr, size_t size) +{ + void *ret = realloc(ptr, size); + + if(ret == NULL) { + abort(); + } + + return ret; +} + + #endif /* CRM_INTERNAL__H */ diff --git a/lib/ais/plugin.c b/lib/ais/plugin.c index 3d4f369..ab534fa 100644 --- a/lib/ais/plugin.c +++ b/lib/ais/plugin.c @@ -1214,7 +1214,7 @@ pcmk_generate_membership_data(void) g_hash_table_foreach(membership_list, member_loop_fn, &data); size = strlen(data.string); - data.string = realloc(data.string, size + 9); /* 9 = + nul */ + data.string = realloc_safe(data.string, size + 9); /* 9 = + nul */ sprintf(data.string + size, ""); return data.string; } diff --git a/lib/ais/utils.c b/lib/ais/utils.c index e56fb6d..94a2505 100644 --- a/lib/ais/utils.c +++ b/lib/ais/utils.c @@ -409,7 +409,7 @@ append_member(char *data, crm_node_t * node) if (node->version) { size += (9 + strlen(node->version)); } - data = realloc(data, size); + data = realloc_safe(data, size); offset += snprintf(data + offset, size - offset, "id); if (node->uname) { diff --git a/lib/cluster/cpg.c b/lib/cluster/cpg.c index 6c86e83..cda6326 100644 --- a/lib/cluster/cpg.c +++ b/lib/cluster/cpg.c @@ -584,7 +584,7 @@ send_cluster_text(int class, const char *data, msg->header.size = sizeof(AIS_Message) + msg->size; if (msg->size < CRM_BZ2_THRESHOLD) { - msg = realloc(msg, msg->header.size); + msg = realloc_safe(msg, msg->header.size); memcpy(msg->data, data, msg->size); } else { @@ -595,14 +595,14 @@ send_cluster_text(int class, const char *data, if (crm_compress_string(uncompressed, msg->size, 0, &compressed, &new_size)) { msg->header.size = sizeof(AIS_Message) + new_size; - msg = realloc(msg, msg->header.size); + msg = realloc_safe(msg, msg->header.size); memcpy(msg->data, compressed, new_size); msg->is_compressed = TRUE; msg->compressed_size = new_size; } else { - msg = realloc(msg, msg->header.size); + msg = realloc_safe(msg, msg->header.size); memcpy(msg->data, data, msg->size); } diff --git a/lib/cluster/heartbeat.c b/lib/cluster/heartbeat.c index a801c8e..6f6a388 100644 --- a/lib/cluster/heartbeat.c +++ b/lib/cluster/heartbeat.c @@ -106,7 +106,7 @@ convert_ha_field(xmlNode * parent, void *msg_v, int lpc) crm_trace("Trying to decompress %d bytes", (int)orig_len); retry: - uncompressed = realloc(uncompressed, size); + uncompressed = realloc_safe(uncompressed, size); memset(uncompressed, 0, size); used = size - 1; /* always leave room for a trailing '\0' * BZ2_bzBuffToBuffDecompress wont say anything if diff --git a/lib/common/logging.c b/lib/common/logging.c index d64b77a..f211d80 100644 --- a/lib/common/logging.c +++ b/lib/common/logging.c @@ -956,7 +956,7 @@ crm_log_args(int argc, char **argv) } len = 2 + strlen(argv[lpc]); /* +1 space, +1 EOS */ - arg_string = realloc(arg_string, len + existing_len); + arg_string = realloc_safe(arg_string, len + existing_len); existing_len += sprintf(arg_string + existing_len, "%s ", argv[lpc]); } diff --git a/lib/common/remote.c b/lib/common/remote.c index f11ebcd..2a5b449 100644 --- a/lib/common/remote.c +++ b/lib/common/remote.c @@ -520,7 +520,7 @@ crm_remote_recv_once(crm_remote_t * remote) remote->buffer_size = 2 * read_len; crm_trace("Expanding buffer to %u bytes", remote->buffer_size); - remote->buffer = realloc(remote->buffer, remote->buffer_size + 1); + remote->buffer = realloc_safe(remote->buffer, remote->buffer_size + 1); CRM_ASSERT(remote->buffer != NULL); } diff --git a/lib/common/utils.c b/lib/common/utils.c index eacd8e9..d70778d 100644 --- a/lib/common/utils.c +++ b/lib/common/utils.c @@ -1712,7 +1712,7 @@ crm_create_long_opts(struct crm_option *long_options) * This dummy entry allows us to differentiate between the two in crm_get_option() * and exit with the correct error code */ - long_opts = realloc(long_opts, (index + 1) * sizeof(struct option)); + long_opts = realloc_safe(long_opts, (index + 1) * sizeof(struct option)); long_opts[index].name = "__dummmy__"; long_opts[index].has_arg = 0; long_opts[index].flag = 0; @@ -1724,7 +1724,7 @@ crm_create_long_opts(struct crm_option *long_options) continue; } - long_opts = realloc(long_opts, (index + 1) * sizeof(struct option)); + long_opts = realloc_safe(long_opts, (index + 1) * sizeof(struct option)); /*fprintf(stderr, "Creating %d %s = %c\n", index, * long_options[lpc].name, long_options[lpc].val); */ long_opts[index].name = long_options[lpc].name; @@ -1735,7 +1735,7 @@ crm_create_long_opts(struct crm_option *long_options) } /* Now create the list terminator */ - long_opts = realloc(long_opts, (index + 1) * sizeof(struct option)); + long_opts = realloc_safe(long_opts, (index + 1) * sizeof(struct option)); long_opts[index].name = NULL; long_opts[index].has_arg = 0; long_opts[index].flag = 0; @@ -1759,7 +1759,7 @@ crm_set_options(const char *short_options, const char *app_usage, struct crm_opt for (lpc = 0; long_options[lpc].name != NULL; lpc++) { if (long_options[lpc].val && long_options[lpc].val != '-' && long_options[lpc].val < UCHAR_MAX) { - local_short_options = realloc(local_short_options, opt_string_len + 4); + local_short_options = realloc_safe(local_short_options, opt_string_len + 4); local_short_options[opt_string_len++] = long_options[lpc].val; /* getopt(3) says: Two colons mean an option takes an optional arg; */ if (long_options[lpc].has_arg == optional_argument) { @@ -2517,7 +2517,7 @@ add_list_element(char *list, const char *value) } len = last + 2; /* +1 space, +1 EOS */ len += strlen(value); - list = realloc(list, len); + list = realloc_safe(list, len); sprintf(list + last, " %s", value); return list; } diff --git a/lib/common/xml.c b/lib/common/xml.c index e63a582..0effd47 100644 --- a/lib/common/xml.c +++ b/lib/common/xml.c @@ -206,7 +206,7 @@ static inline bool TRACKING_CHANGES(xmlNode *xml) } else if(rc >= ((max) - (offset))) { \ char *tmp = NULL; \ (max) = QB_MAX(CHUNK_SIZE, (max) * 2); \ - tmp = realloc((buffer), (max) + 1); \ + tmp = realloc_safe((buffer), (max) + 1); \ CRM_ASSERT(tmp); \ (buffer) = tmp; \ } else { \ @@ -223,7 +223,7 @@ insert_prefix(int options, char **buffer, int *offset, int *max, int depth) if ((*buffer) == NULL || spaces >= ((*max) - (*offset))) { (*max) = QB_MAX(CHUNK_SIZE, (*max) * 2); - (*buffer) = realloc((*buffer), (*max) + 1); + (*buffer) = realloc_safe((*buffer), (*max) + 1); } memset((*buffer) + (*offset), ' ', spaces); (*offset) += spaces; @@ -305,7 +305,7 @@ static void __xml_schema_add( int last = xml_schema_max; xml_schema_max++; - known_schemas = realloc(known_schemas, xml_schema_max*sizeof(struct schema_s)); + known_schemas = realloc_safe(known_schemas, xml_schema_max*sizeof(struct schema_s)); CRM_ASSERT(known_schemas != NULL); memset(known_schemas+last, 0, sizeof(struct schema_s)); known_schemas[last].type = type; @@ -2759,6 +2759,7 @@ create_xml_node(xmlNode * parent, const char *name) xmlNode *node = NULL; if (name == NULL || name[0] == 0) { + CRM_CHECK(name != NULL || name[0] == 0, return NULL); return NULL; } @@ -2905,7 +2906,7 @@ crm_xml_err(void *ctx, const char *msg, ...) buf = NULL; } else { - buffer = realloc(buffer, 1 + buffer_len + len); + buffer = realloc_safe(buffer, 1 + buffer_len + len); memcpy(buffer + buffer_len, buf, len); buffer_len += len; buffer[buffer_len] = 0; @@ -2997,7 +2998,7 @@ stdin2xml(void) break; } - xml_buffer = realloc(xml_buffer, next); + xml_buffer = realloc_safe(xml_buffer, next); read_chars = fread(xml_buffer + data_length, 1, XML_BUFFER_SIZE, stdin); data_length += read_chars; } while (read_chars > 0); @@ -3043,7 +3044,7 @@ decompress_file(const char *filename) rc = BZ_OK; while (rc == BZ_OK) { - buffer = realloc(buffer, XML_BUFFER_SIZE + length + 1); + buffer = realloc_safe(buffer, XML_BUFFER_SIZE + length + 1); read_len = BZ2_bzRead(&rc, bz_file, buffer + length, XML_BUFFER_SIZE); crm_trace("Read %ld bytes from file: %d", (long)read_len, rc); @@ -3301,7 +3302,7 @@ crm_xml_escape_shuffle(char *text, int start, int *length, const char *replace) int offset = strlen(replace) - 1; /* We have space for 1 char already */ *length += offset; - text = realloc(text, *length); + text = realloc_safe(text, *length); for (lpc = (*length) - 1; lpc > (start + offset); lpc--) { text[lpc] = text[lpc - offset]; @@ -5369,7 +5370,7 @@ crm_xml_init(void) if(init) { init = FALSE; /* The default allocator XML_BUFFER_ALLOC_EXACT does far too many - * realloc()s and it can take upwards of 18 seconds (yes, seconds) + * realloc_safe()s and it can take upwards of 18 seconds (yes, seconds) * to dump a 28kb tree which XML_BUFFER_ALLOC_DOUBLEIT can do in * less than 1 second. */ @@ -5987,7 +5988,7 @@ get_xpath_object_relative(const char *xpath, xmlNode * xml_obj, int error_level) len += strlen(xpath); xpath_full = strdup(xpath_prefix); - xpath_full = realloc(xpath_full, len + 1); + xpath_full = realloc_safe(xpath_full, len + 1); strncat(xpath_full, xpath, len); result = get_xpath_object(xpath_full, xml_obj, error_level); diff --git a/lib/fencing/st_client.c b/lib/fencing/st_client.c index 06b9492..e51d673 100644 --- a/lib/fencing/st_client.c +++ b/lib/fencing/st_client.c @@ -308,7 +308,7 @@ append_arg(gpointer key, gpointer value, gpointer user_data) last = strlen(*args); } - *args = realloc(*args, last + len); + *args = realloc_safe(*args, last + len); crm_trace("Appending: %s=%s", (char *)key, (char *)value); sprintf((*args) + last, "%s=%s\n", (char *)key, (char *)value); } @@ -627,7 +627,7 @@ read_output(int fd) * 'more' is always less than our buffer size */ crm_trace("Got %d more bytes: %.200s...", more, buffer); - output = realloc(output, len + more + 1); + output = realloc_safe(output, len + more + 1); snprintf(output + len, more + 1, "%s", buffer); len += more; } diff --git a/lib/services/services_linux.c b/lib/services/services_linux.c index 8d6f450..de29706 100644 --- a/lib/services/services_linux.c +++ b/lib/services/services_linux.c @@ -94,7 +94,7 @@ svc_read_output(int fd, svc_action_t * op, bool is_stderr) if (rc > 0) { crm_trace("Got %d characters starting with %.20s", rc, buf); buf[rc] = 0; - data = realloc(data, len + rc + 1); + data = realloc_safe(data, len + rc + 1); len += sprintf(data + len, "%s", buf); } else if (errno != EINTR) { diff --git a/lib/services/systemd.c b/lib/services/systemd.c index a8bf1b4..c0a1721 100644 --- a/lib/services/systemd.c +++ b/lib/services/systemd.c @@ -462,10 +462,11 @@ systemd_async_dispatch(DBusPendingCall *pending, void *user_data) if(op) { crm_trace("Got result: %p for %p for %s, %s", reply, pending, op->rsc, op->action); op->opaque->pending = NULL; + systemd_exec_result(reply, op); + } else { crm_trace("Got result: %p for %p", reply, pending); } - systemd_exec_result(reply, op); if(pending) { dbus_pending_call_unref(pending); @@ -491,6 +492,8 @@ systemd_unit_check(const char *name, const char *state, void *userdata) op->rc = PCMK_OCF_OK; } else if (g_strcmp0(state, "activating") == 0) { op->rc = PCMK_OCF_PENDING; + } else if (g_strcmp0(state, "deactivating") == 0) { + op->rc = PCMK_OCF_PENDING; } else { op->rc = PCMK_OCF_NOT_RUNNING; } diff --git a/lrmd/lrmd.c b/lrmd/lrmd.c index d3ede18..0f5f529 100644 --- a/lrmd/lrmd.c +++ b/lrmd/lrmd.c @@ -790,10 +790,30 @@ action_complete(svc_action_t * action) cmd->real_action = cmd->action; cmd->action = strdup("monitor"); + } else if(cmd->exec_rc == PCMK_OCF_OK && safe_str_eq(cmd->action, "stop")) { + goagain = true; + cmd->real_action = cmd->action; + cmd->action = strdup("monitor"); + } else if(cmd->real_action) { /* Ok, so this is the follow up monitor action to check if start actually completed */ if(cmd->lrmd_op_status == PCMK_LRM_OP_DONE && cmd->exec_rc == PCMK_OCF_PENDING) { goagain = true; + + } else { + int time_sum = 0; + int timeout_left = 0; + struct timeb now = { 0, }; + + ftime(&now); + time_sum = time_diff_ms(&now, &cmd->t_first_run); + timeout_left = cmd->timeout_orig - time_sum; + crm_debug("%s %s is now complete (elapsed=%dms, remaining=%dms): %s (%d)", + cmd->rsc_id, cmd->real_action, time_sum, timeout_left, services_ocf_exitcode_str(cmd->exec_rc), cmd->exec_rc); + + if(cmd->lrmd_op_status == PCMK_LRM_OP_DONE && cmd->exec_rc == PCMK_OCF_NOT_RUNNING && safe_str_eq(cmd->real_action, "stop")) { + cmd->exec_rc = PCMK_OCF_OK; + } } } } @@ -827,13 +847,22 @@ action_complete(svc_action_t * action) delay = timeout_left/2; } + delay = QB_MIN(2000, delay); if (delay < timeout_left) { cmd->start_delay = delay; cmd->timeout = timeout_left; - if(cmd->exec_rc != PCMK_OCF_OK) { - crm_info("%s %s failed (rc=%d): re-scheduling (elapsed=%dms, remaining=%dms, start_delay=%dms)", - cmd->rsc_id, cmd->action, cmd->exec_rc, time_sum, timeout_left, delay); + if(cmd->exec_rc == PCMK_OCF_OK) { + crm_debug("%s %s may still be in progress: re-scheduling (elapsed=%dms, remaining=%dms, start_delay=%dms)", + cmd->rsc_id, cmd->real_action, time_sum, timeout_left, delay); + + } else if(cmd->exec_rc == PCMK_OCF_PENDING) { + crm_info("%s %s is still in progress: re-scheduling (elapsed=%dms, remaining=%dms, start_delay=%dms)", + cmd->rsc_id, cmd->action, time_sum, timeout_left, delay); + + } else { + crm_notice("%s %s failed '%s' (%d): re-scheduling (elapsed=%dms, remaining=%dms, start_delay=%dms)", + cmd->rsc_id, cmd->action, services_ocf_exitcode_str(cmd->exec_rc), cmd->exec_rc, time_sum, timeout_left, delay); } cmd_reset(cmd); diff --git a/pengine/allocate.c b/pengine/allocate.c index 45e2212..748ca54 100644 --- a/pengine/allocate.c +++ b/pengine/allocate.c @@ -1913,7 +1913,7 @@ expand_list(GListPtr list, char **rsc_list, char **node_list) } crm_trace("Adding %s (%dc) at offset %d", rsc_id, len - 2, existing_len); - *rsc_list = realloc(*rsc_list, len + existing_len); + *rsc_list = realloc_safe(*rsc_list, len + existing_len); sprintf(*rsc_list + existing_len, "%s ", rsc_id); } @@ -1930,7 +1930,7 @@ expand_list(GListPtr list, char **rsc_list, char **node_list) } crm_trace("Adding %s (%dc) at offset %d", uname, len - 2, existing_len); - *node_list = realloc(*node_list, len + existing_len); + *node_list = realloc_safe(*node_list, len + existing_len); sprintf(*node_list + existing_len, "%s ", uname); } } diff --git a/replace/scandir.c b/replace/scandir.c index 7a8efea..0011630 100644 --- a/replace/scandir.c +++ b/replace/scandir.c @@ -202,7 +202,7 @@ scandir(const char *directory_name, if (counter + 1 == allocated) { allocated <<= 1; array = (struct dirent **) - realloc((char *)array, allocated * sizeof(struct dirent *)); + realloc_safe((char *)array, allocated * sizeof(struct dirent *)); if (array == NULL) { closedir(directory); free(array); diff --git a/tools/crm_resource.c b/tools/crm_resource.c index 6e510e1..236d43c 100644 --- a/tools/crm_resource.c +++ b/tools/crm_resource.c @@ -1399,16 +1399,20 @@ static void display_list(GList *items, const char *tag) static int update_dataset(cib_t *cib, pe_working_set_t * data_set, bool simulate) { + char *pid = NULL; + char *shadow_file = NULL; + cib_t *shadow_cib = NULL; xmlNode *cib_xml_copy = NULL; int rc = cib->cmds->query(cib, NULL, &cib_xml_copy, cib_scope_local | cib_sync_call); if(rc != pcmk_ok) { fprintf(stdout, "Could not obtain the current CIB: %s (%d)\n", pcmk_strerror(rc), rc); - return crm_exit(rc); + goto cleanup; } else if (cli_config_update(&cib_xml_copy, NULL, FALSE) == FALSE) { fprintf(stderr, "Could not upgrade the current CIB\n"); - return -ENOKEY; + rc = -ENOKEY; + goto cleanup; } set_working_set_defaults(data_set); @@ -1416,70 +1420,103 @@ update_dataset(cib_t *cib, pe_working_set_t * data_set, bool simulate) data_set->now = crm_time_new(NULL); if(simulate) { - char *pid = crm_itoa(getpid()); - cib_t *shadow_cib = cib_shadow_new(pid); - char *shadow_file = get_shadow_file(pid); + pid = crm_itoa(getpid()); + shadow_cib = cib_shadow_new(pid); + shadow_file = get_shadow_file(pid); if (shadow_cib == NULL) { fprintf(stderr, "Could not create shadow cib: '%s'\n", pid); - crm_exit(-ENXIO); + rc = -ENXIO; + goto cleanup; } + free(pid); rc = write_xml_file(cib_xml_copy, shadow_file, FALSE); if (rc < 0) { fprintf(stderr, "Could not populate shadow cib: %s (%d)\n", pcmk_strerror(rc), rc); - free_xml(cib_xml_copy); - return rc; + goto cleanup; } rc = shadow_cib->cmds->signon(shadow_cib, crm_system_name, cib_command); if(rc != pcmk_ok) { fprintf(stderr, "Could not connect to shadow cib: %s (%d)\n", pcmk_strerror(rc), rc); - free_xml(cib_xml_copy); - return rc; + goto cleanup; } do_calculations(data_set, cib_xml_copy, NULL); run_simulation(data_set, shadow_cib, NULL, TRUE); rc = update_dataset(shadow_cib, data_set, FALSE); - cib_delete(shadow_cib); - /* unlink(shadow_file); */ - free(shadow_file); - } else { cluster_status(data_set); } + cleanup: + cib_delete(shadow_cib); + free_xml(cib_xml_copy); + free(pid); + + if(shadow_file) { + unlink(shadow_file); + free(shadow_file); + } + return rc; } static int -max_delay_in(pe_working_set_t * data_set, GList *resources) +max_delay_for_resource(pe_working_set_t * data_set, resource_t *rsc) { + int delay = 0; int max_delay = 0; - GList *item = NULL; - for (item = resources; item != NULL; item = item->next) { - resource_t *rsc = pe_find_resource(data_set->resources, (const char *)item->data); + if(rsc && rsc->children) { + GList *iter = NULL; - if(rsc) { - char *key = g_strdup_printf("%s_%s_0", rsc->id, RSC_STOP); - action_t *stop = custom_action(rsc, key, RSC_STOP, NULL, TRUE, FALSE, data_set); - const char *value = g_hash_table_lookup(stop->meta, XML_ATTR_TIMEOUT); - int delay = crm_int_helper(value, NULL); + for(iter = rsc->children; iter; iter = iter->next) { + resource_t *child = (resource_t *)iter->data; + delay = max_delay_for_resource(data_set, child); if(delay > max_delay) { - crm_trace("Calculated new delay of %s ms due to %s", value, rsc->id); + double seconds = delay / 1000; + crm_trace("Calculated new delay of %.1fs due to %s", seconds, child->id); max_delay = delay; } - - pe_free_action(stop); } + + } else if(rsc) { + char *key = g_strdup_printf("%s_%s_0", rsc->id, RSC_STOP); + action_t *stop = custom_action(rsc, key, RSC_STOP, NULL, TRUE, FALSE, data_set); + const char *value = g_hash_table_lookup(stop->meta, XML_ATTR_TIMEOUT); + + max_delay = crm_int_helper(value, NULL); + pe_free_action(stop); } + return max_delay; +} + +static int +max_delay_in(pe_working_set_t * data_set, GList *resources) +{ + int max_delay = 0; + GList *item = NULL; + + for (item = resources; item != NULL; item = item->next) { + int delay = 0; + resource_t *rsc = pe_find_resource(data_set->resources, (const char *)item->data); + + delay = max_delay_for_resource(data_set, rsc); + + if(delay > max_delay) { + double seconds = delay / 1000; + crm_trace("Calculated new delay of %.1fs due to %s", seconds, rsc->id); + max_delay = delay; + } + } + return 5 + (max_delay / 1000); } @@ -1507,7 +1544,7 @@ resource_restart(resource_t * rsc, const char *host, int timeout_ms, cib_t * cib return -ENXIO; } - + attr_set_type = XML_TAG_META_SETS; rsc_id = strdup(rsc->id); if(rsc->variant > pe_group) { is_clone = TRUE; @@ -1536,6 +1573,7 @@ resource_restart(resource_t * rsc, const char *host, int timeout_ms, cib_t * cib rc = update_dataset(cib, &data_set, FALSE); if(rc != pcmk_ok) { fprintf(stdout, "Could not get new resource list: %s (%d)\n", pcmk_strerror(rc), rc); + free(rsc_id); return rc; } @@ -1553,6 +1591,7 @@ resource_restart(resource_t * rsc, const char *host, int timeout_ms, cib_t * cib } if(rc != pcmk_ok) { fprintf(stderr, "Could not set target-role for %s: %s (%d)\n", rsc_id, pcmk_strerror(rc), rc); + free(rsc_id); return crm_exit(rc); } @@ -1615,6 +1654,7 @@ resource_restart(resource_t * rsc, const char *host, int timeout_ms, cib_t * cib if(rc != pcmk_ok) { fprintf(stderr, "Could not unset target-role for %s: %s (%d)\n", rsc_id, pcmk_strerror(rc), rc); + free(rsc_id); return crm_exit(rc); } @@ -1659,6 +1699,7 @@ resource_restart(resource_t * rsc, const char *host, int timeout_ms, cib_t * cib } while(g_list_length(list_delta) > 0); + free(rsc_id); return pcmk_ok; failure: @@ -1668,6 +1709,7 @@ resource_restart(resource_t * rsc, const char *host, int timeout_ms, cib_t * cib } else { delete_resource_attr(rsc_id, NULL, NULL, XML_RSC_ATTR_TARGET_ROLE, cib, &data_set); } + free(rsc_id); return rc; }