From a30e9fa6c209ad310bddc079c4afd14fb4876f4f Mon Sep 17 00:00:00 2001 From: Ken Gaillot Date: Mon, 3 Apr 2017 15:33:24 -0500 Subject: [PATCH 1/8] Fix: libpe_status: avoid memory leak when bundle resource fails to unpack --- lib/pengine/container.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/lib/pengine/container.c b/lib/pengine/container.c index 09113ae..cae62f0 100644 --- a/lib/pengine/container.c +++ b/lib/pengine/container.c @@ -599,10 +599,22 @@ container_unpack(resource_t * rsc, pe_working_set_t * data_set) GListPtr childIter = NULL; resource_t *new_rsc = NULL; container_mount_t *mount = NULL; - container_port_t *port = calloc(1, sizeof(container_port_t)); + container_port_t *port = NULL; int offset = 0, max = 1024; - char *buffer = calloc(1, max+1); + char *buffer = NULL; + + if (common_unpack(xml_resource, &new_rsc, rsc, data_set) == FALSE) { + pe_err("Failed unpacking resource %s", ID(rsc->xml)); + if (new_rsc != NULL && new_rsc->fns != NULL) { + new_rsc->fns->free(new_rsc); + } + return FALSE; + } + + container_data->child = new_rsc; + container_data->child->orig_xml = xml_obj; // Also the trigger for common_free() + // to free xml_resource as container_data->child->xml mount = calloc(1, sizeof(container_mount_t)); mount->source = strdup(DEFAULT_REMOTE_KEY_LOCATION); @@ -618,27 +630,16 @@ container_unpack(resource_t * rsc, pe_working_set_t * data_set) mount->flags = 1; container_data->mounts = g_list_append(container_data->mounts, mount); + port = calloc(1, sizeof(container_port_t)); if(container_data->control_port) { port->source = strdup(container_data->control_port); } else { port->source = crm_itoa(DEFAULT_REMOTE_PORT); } - port->target = strdup(port->source); container_data->ports = g_list_append(container_data->ports, port); - if (common_unpack(xml_resource, &new_rsc, rsc, data_set) == FALSE) { - pe_err("Failed unpacking resource %s", crm_element_value(rsc->xml, XML_ATTR_ID)); - if (new_rsc != NULL && new_rsc->fns != NULL) { - new_rsc->fns->free(new_rsc); - } - return FALSE; - } - - container_data->child = new_rsc; - container_data->child->orig_xml = xml_obj; // Also the trigger for common_free() - // to free xml_resource as container_data->child->xml - + buffer = calloc(1, max+1); for(childIter = container_data->child->children; childIter != NULL; childIter = childIter->next) { container_grouping_t *tuple = calloc(1, sizeof(container_grouping_t)); tuple->child = childIter->data; -- 1.8.3.1 From 21ed491adc82fd04b39bc2d6035527b1514e99f4 Mon Sep 17 00:00:00 2001 From: Ken Gaillot Date: Mon, 3 Apr 2017 15:40:56 -0500 Subject: [PATCH 2/8] Refactor: libpe_status: remove dead code died in 09f233dd --- lib/pengine/unpack.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/lib/pengine/unpack.c b/lib/pengine/unpack.c index ef51cd5..6aa51dd 100644 --- a/lib/pengine/unpack.c +++ b/lib/pengine/unpack.c @@ -637,7 +637,6 @@ gboolean unpack_remote_nodes(xmlNode * xml_resources, pe_working_set_t * data_set) { xmlNode *xml_obj = NULL; - GHashTable *rsc_name_check = NULL; /* generate remote nodes from resource config before unpacking resources */ for (xml_obj = __xml_first_child(xml_resources); xml_obj != NULL; xml_obj = __xml_next_element(xml_obj)) { @@ -691,10 +690,6 @@ unpack_remote_nodes(xmlNode * xml_resources, pe_working_set_t * data_set) } } } - if (rsc_name_check) { - g_hash_table_destroy(rsc_name_check); - } - return TRUE; } -- 1.8.3.1 From 3093687bc307b0a554ba5837d28ca1fc11f22935 Mon Sep 17 00:00:00 2001 From: Ken Gaillot Date: Mon, 3 Apr 2017 15:43:55 -0500 Subject: [PATCH 3/8] Low: pengine: ensure other container in constraint has Docker info Not really necessary, but makes static analysis happy --- pengine/container.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pengine/container.c b/pengine/container.c index 1623861..3da19aa 100644 --- a/pengine/container.c +++ b/pengine/container.c @@ -313,13 +313,16 @@ container_create_probe(resource_t * rsc, node_t * node, action_t * complete, * Partly this is to ensure that replicas_per_host is * observed, but also to ensure that the containers * don't fail to start because the necessary port - * mappings (which wont include an IP for uniqueness) + * mappings (which won't include an IP for uniqueness) * are already taken */ for (GListPtr tIter = container_data->tuples; tIter != NULL && container_data->replicas_per_host == 1; tIter = tIter->next) { container_grouping_t *other = (container_grouping_t *)tIter->data; - if(other != tuple) { + + if ((other != tuple) && (other != NULL) + && (other->docker != NULL)) { + custom_action_order(tuple->docker, generate_op_key(tuple->docker->id, RSC_STATUS, 0), NULL, other->docker, generate_op_key(other->docker->id, RSC_START, 0), NULL, pe_order_optional, data_set); -- 1.8.3.1 From 50399650dbd6425218638cef32c77f02a0807472 Mon Sep 17 00:00:00 2001 From: Ken Gaillot Date: Mon, 3 Apr 2017 15:46:01 -0500 Subject: [PATCH 4/8] Low: libpe_status: ensure resource is not NULL not really necessary, but makes static analysis happy --- lib/pengine/container.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/pengine/container.c b/lib/pengine/container.c index cae62f0..2a60e4c 100644 --- a/lib/pengine/container.c +++ b/lib/pengine/container.c @@ -440,6 +440,7 @@ container_unpack(resource_t * rsc, pe_working_set_t * data_set) xmlNode *xml_resource = NULL; container_variant_data_t *container_data = NULL; + CRM_ASSERT(rsc != NULL); pe_rsc_trace(rsc, "Processing resource %s...", rsc->id); container_data = calloc(1, sizeof(container_variant_data_t)); -- 1.8.3.1 From a755fb0a64873c16aac9924d95b0c2bdb13f5065 Mon Sep 17 00:00:00 2001 From: Ken Gaillot Date: Mon, 3 Apr 2017 16:52:54 -0500 Subject: [PATCH 5/8] Low: libpe_status: improve container print functions --- lib/pengine/container.c | 92 ++++++++++++++++++++++++++++++------------------- 1 file changed, 56 insertions(+), 36 deletions(-) diff --git a/lib/pengine/container.c b/lib/pengine/container.c index 2a60e4c..2af2558 100644 --- a/lib/pengine/container.c +++ b/lib/pengine/container.c @@ -716,6 +716,21 @@ find_container_child(const char *stem, resource_t * rsc, node_t *node) } static void +print_rsc_in_list(resource_t *rsc, const char *pre_text, long options, + void *print_data) +{ + if (rsc != NULL) { + if (options & pe_print_html) { + status_print("
  • "); + } + rsc->fns->print(rsc, pre_text, options, print_data); + if (options & pe_print_html) { + status_print("
  • \n"); + } + } +} + +static void container_print_xml(resource_t * rsc, const char *pre_text, long options, void *print_data) { container_variant_data_t *container_data = NULL; @@ -725,39 +740,31 @@ container_print_xml(resource_t * rsc, const char *pre_text, long options, void * if (pre_text == NULL) { pre_text = ""; } - child_text = crm_concat(pre_text, " ", ' '); + child_text = crm_concat(pre_text, " ", ' '); - status_print("%sid); + status_print("type=\"docker\" "); + status_print("image=\"%s\" ", container_data->image); + status_print("unique=\"%s\" ", is_set(rsc->flags, pe_rsc_unique)? "true" : "false"); status_print("managed=\"%s\" ", is_set(rsc->flags, pe_rsc_managed) ? "true" : "false"); status_print("failed=\"%s\" ", is_set(rsc->flags, pe_rsc_failed) ? "true" : "false"); status_print(">\n"); - get_container_variant_data(container_data, rsc); - - status_print("%sDocker container: %s [%s]%s%s", - pre_text, rsc->id, container_data->image, - is_set(rsc->flags, pe_rsc_unique) ? " (unique)" : "", - is_set(rsc->flags, pe_rsc_managed) ? "" : " (unmanaged)"); - for (GListPtr gIter = container_data->tuples; gIter != NULL; gIter = gIter->next) { container_grouping_t *tuple = (container_grouping_t *)gIter->data; CRM_ASSERT(tuple); - if(tuple->ip) { - tuple->ip->fns->print(tuple->ip, child_text, options, print_data); - } - if(tuple->child) { - tuple->child->fns->print(tuple->child, child_text, options, print_data); - } - if(tuple->docker) { - tuple->docker->fns->print(tuple->docker, child_text, options, print_data); - } - if(tuple->remote) { - tuple->remote->fns->print(tuple->remote, child_text, options, print_data); - } - } - status_print("%s\n", pre_text); + status_print("%s \n", pre_text, tuple->offset); + print_rsc_in_list(tuple->ip, child_text, options, print_data); + print_rsc_in_list(tuple->child, child_text, options, print_data); + print_rsc_in_list(tuple->docker, child_text, options, print_data); + print_rsc_in_list(tuple->remote, child_text, options, print_data); + status_print("%s \n", pre_text); + } + status_print("%s\n", pre_text); free(child_text); } @@ -809,37 +816,50 @@ container_print(resource_t * rsc, const char *pre_text, long options, void *prin pre_text = " "; } - child_text = crm_strdup_printf(" %s", pre_text); status_print("%sDocker container%s: %s [%s]%s%s\n", pre_text, container_data->replicas>1?" set":"", rsc->id, container_data->image, is_set(rsc->flags, pe_rsc_unique) ? " (unique)" : "", is_set(rsc->flags, pe_rsc_managed) ? "" : " (unmanaged)"); + if (options & pe_print_html) { + status_print("
    \n
      \n"); + } + for (GListPtr gIter = container_data->tuples; gIter != NULL; gIter = gIter->next) { container_grouping_t *tuple = (container_grouping_t *)gIter->data; CRM_ASSERT(tuple); + if (options & pe_print_html) { + status_print("
    • "); + } + if(is_set(options, pe_print_clone_details)) { + child_text = crm_strdup_printf(" %s", pre_text); if(g_list_length(container_data->tuples) > 1) { status_print(" %sReplica[%d]\n", pre_text, tuple->offset); } - - if(tuple->ip) { - tuple->ip->fns->print(tuple->ip, child_text, options, print_data); - } - if(tuple->docker) { - tuple->docker->fns->print(tuple->docker, child_text, options, print_data); - } - if(tuple->remote) { - tuple->remote->fns->print(tuple->remote, child_text, options, print_data); + if (options & pe_print_html) { + status_print("
      \n
        \n"); } - if(tuple->child) { - tuple->child->fns->print(tuple->child, child_text, options, print_data); + print_rsc_in_list(tuple->ip, child_text, options, print_data); + print_rsc_in_list(tuple->docker, child_text, options, print_data); + print_rsc_in_list(tuple->remote, child_text, options, print_data); + print_rsc_in_list(tuple->child, child_text, options, print_data); + if (options & pe_print_html) { + status_print("
      \n"); } } else { - char *child_text = crm_strdup_printf("%s ", pre_text); + child_text = crm_strdup_printf("%s ", pre_text); tuple_print(tuple, child_text, options, print_data); } + free(child_text); + + if (options & pe_print_html) { + status_print("
    • \n"); + } + } + if (options & pe_print_html) { + status_print("
    \n"); } } -- 1.8.3.1 From 1302b775b8bc4913b894081707f9ad386402d25d Mon Sep 17 00:00:00 2001 From: Ken Gaillot Date: Mon, 3 Apr 2017 17:06:06 -0500 Subject: [PATCH 6/8] Low: tools: update crm_mon RNG schema for bundles --- xml/crm_mon.rng | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/xml/crm_mon.rng b/xml/crm_mon.rng index 653c15e..731c118 100644 --- a/xml/crm_mon.rng +++ b/xml/crm_mon.rng @@ -241,6 +241,9 @@ + + + @@ -298,4 +301,27 @@ + + + + + + docker + + + + + + + + + + + + + + + + + -- 1.8.3.1 From 3b5f0f58bae3b2764222eede878da5801336b2c9 Mon Sep 17 00:00:00 2001 From: Ken Gaillot Date: Mon, 3 Apr 2017 18:21:19 -0500 Subject: [PATCH 7/8] Fix: libpe_status: run-command should apply even without a primitive --- lib/pengine/container.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/pengine/container.c b/lib/pengine/container.c index 2af2558..9c59be6 100644 --- a/lib/pengine/container.c +++ b/lib/pengine/container.c @@ -301,6 +301,10 @@ create_docker_resource( * create_nvp(xml_obj, "monitor_cmd", "/usr/libexec/pacemaker/lrmd_internal_ctl -c poke"); */ } else { + if(data->docker_run_command) { + create_nvp(xml_obj, "run_cmd", data->docker_run_command); + } + /* TODO: Allow users to specify their own? * * We don't know what's in the container, so we just want -- 1.8.3.1 From 75b29dee7fa4adf0141f8932b060392a238adbc7 Mon Sep 17 00:00:00 2001 From: Ken Gaillot Date: Mon, 3 Apr 2017 17:44:03 -0500 Subject: [PATCH 8/8] Fix: libpe_status: implement active check for bundles --- lib/pengine/container.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/lib/pengine/container.c b/lib/pengine/container.c index 9c59be6..b93d98f 100644 --- a/lib/pengine/container.c +++ b/lib/pengine/container.c @@ -683,10 +683,58 @@ container_unpack(resource_t * rsc, pe_working_set_t * data_set) return TRUE; } +static int +tuple_rsc_active(resource_t *rsc, gboolean all) +{ + if (rsc) { + gboolean child_active = rsc->fns->active(rsc, all); + + if (child_active && !all) { + return TRUE; + } else if (!child_active && all) { + return FALSE; + } + } + return -1; +} + gboolean container_active(resource_t * rsc, gboolean all) { - return TRUE; + container_variant_data_t *container_data = NULL; + GListPtr iter = NULL; + + get_container_variant_data(container_data, rsc); + for (iter = container_data->tuples; iter != NULL; iter = iter->next) { + container_grouping_t *tuple = (container_grouping_t *)(iter->data); + int rsc_active; + + rsc_active = tuple_rsc_active(tuple->ip, all); + if (rsc_active >= 0) { + return (gboolean) rsc_active; + } + + rsc_active = tuple_rsc_active(tuple->child, all); + if (rsc_active >= 0) { + return (gboolean) rsc_active; + } + + rsc_active = tuple_rsc_active(tuple->docker, all); + if (rsc_active >= 0) { + return (gboolean) rsc_active; + } + + rsc_active = tuple_rsc_active(tuple->remote, all); + if (rsc_active >= 0) { + return (gboolean) rsc_active; + } + } + + /* If "all" is TRUE, we've already checked that no resources were inactive, + * so return TRUE; if "all" is FALSE, we didn't find any active resources, + * so return FALSE. + */ + return all; } resource_t * -- 1.8.3.1