Skip to content

Commit 62e8d4b

Browse files
author
Ken Gaillot
authored
Merge pull request ClusterLabs#1355 from kgaillot/fixes11
Lots of small fixes
2 parents daaa6a0 + 176132f commit 62e8d4b

18 files changed

+927
-233
lines changed

include/crm/common/internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ gboolean crm_ends_with_ext(const char *s, const char *match);
6767
char *add_list_element(char *list, const char *value);
6868
bool crm_compress_string(const char *data, int length, int max, char **result,
6969
unsigned int *result_len);
70+
gint crm_alpha_sort(gconstpointer a, gconstpointer b);
7071

7172
static inline int
7273
crm_strlen_zero(const char *s)

lib/cluster/membership.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -837,10 +837,19 @@ crm_update_peer(const char *source, unsigned int id, uint64_t born, uint64_t see
837837
void
838838
crm_update_peer_uname(crm_node_t *node, const char *uname)
839839
{
840-
int i, len = strlen(uname);
840+
CRM_CHECK(uname != NULL,
841+
crm_err("Bug: can't update node name without name"); return);
842+
CRM_CHECK(node != NULL,
843+
crm_err("Bug: can't update node name to %s without node", uname);
844+
return);
845+
846+
if (safe_str_eq(uname, node->uname)) {
847+
crm_debug("Node uname '%s' did not change", uname);
848+
return;
849+
}
841850

842-
for (i = 0; i < len; i++) {
843-
if (uname[i] >= 'A' && uname[i] <= 'Z') {
851+
for (const char *c = uname; *c; ++c) {
852+
if ((*c >= 'A') && (*c <= 'Z')) {
844853
crm_warn("Node names with capitals are discouraged, consider changing '%s'",
845854
uname);
846855
break;
@@ -849,6 +858,8 @@ crm_update_peer_uname(crm_node_t *node, const char *uname)
849858

850859
free(node->uname);
851860
node->uname = strdup(uname);
861+
CRM_ASSERT(node->uname != NULL);
862+
852863
if (crm_status_callback) {
853864
crm_status_callback(crm_status_uname, node, NULL);
854865
}

lib/common/strings.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,3 +427,27 @@ crm_compress_string(const char *data, int length, int max, char **result, unsign
427427
*result = compressed;
428428
return TRUE;
429429
}
430+
431+
/*!
432+
* \brief Compare two strings alphabetically (case-insensitive)
433+
*
434+
* \param[in] a First string to compare
435+
* \param[in] b Second string to compare
436+
*
437+
* \return 0 if strings are equal, -1 if a < b, 1 if a > b
438+
*
439+
* \note Usable as a GCompareFunc with g_list_sort().
440+
* NULL is considered less than non-NULL.
441+
*/
442+
gint
443+
crm_alpha_sort(gconstpointer a, gconstpointer b)
444+
{
445+
if (!a && !b) {
446+
return 0;
447+
} else if (!a) {
448+
return -1;
449+
} else if (!b) {
450+
return 1;
451+
}
452+
return strcasecmp(a, b);
453+
}

lib/pengine/container.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
#include <crm_internal.h>
2020

21+
#include <ctype.h>
22+
2123
#include <crm/pengine/rules.h>
2224
#include <crm/pengine/status.h>
2325
#include <crm/pengine/internal.h>
@@ -1123,7 +1125,15 @@ container_print_xml(resource_t * rsc, const char *pre_text, long options, void *
11231125

11241126
status_print("%s<bundle ", pre_text);
11251127
status_print("id=\"%s\" ", rsc->id);
1126-
status_print("type=\"%s\" ", container_type_as_string(container_data->type));
1128+
1129+
// Always lowercase the container technology type for use as XML value
1130+
status_print("type=\"");
1131+
for (const char *c = container_type_as_string(container_data->type);
1132+
*c; ++c) {
1133+
status_print("%c", tolower(*c));
1134+
}
1135+
status_print("\" ");
1136+
11271137
status_print("image=\"%s\" ", container_data->image);
11281138
status_print("unique=\"%s\" ", is_set(rsc->flags, pe_rsc_unique)? "true" : "false");
11291139
status_print("managed=\"%s\" ", is_set(rsc->flags, pe_rsc_managed) ? "true" : "false");

lib/services/services.c

Lines changed: 48 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -904,7 +904,7 @@ handle_blocked_ops(void)
904904
"<resource-agent name='%s' version='" PCMK_DEFAULT_AGENT_VERSION "'>\n" \
905905
" <version>1.0</version>\n" \
906906
" <longdesc lang='en'>\n" \
907-
" %s\n" \
907+
"%s" \
908908
" </longdesc>\n" \
909909
" <shortdesc lang='en'>%s</shortdesc>\n" \
910910
" <parameters>\n" \
@@ -929,6 +929,9 @@ handle_blocked_ops(void)
929929
" </special>\n" \
930930
"</resource-agent>\n"
931931

932+
/* See "Comment Conventions for Init Scripts" in the LSB core specification at:
933+
* http://refspecs.linuxfoundation.org/lsb.shtml
934+
*/
932935
#define LSB_INITSCRIPT_INFOBEGIN_TAG "### BEGIN INIT INFO"
933936
#define LSB_INITSCRIPT_INFOEND_TAG "### END INIT INFO"
934937
#define PROVIDES "# Provides:"
@@ -962,7 +965,7 @@ handle_blocked_ops(void)
962965
static inline gboolean
963966
lsb_meta_helper_get_value(const char *line, char **value, const char *prefix)
964967
{
965-
if (!*value && !strncasecmp(line, prefix, strlen(prefix))) {
968+
if (!*value && !strncmp(line, prefix, strlen(prefix))) {
966969
*value = (char *)xmlEncodeEntitiesReentrant(NULL, BAD_CAST line+strlen(prefix));
967970
return TRUE;
968971
}
@@ -975,8 +978,8 @@ static int
975978
lsb_get_metadata(const char *type, char **output)
976979
{
977980
char ra_pathname[PATH_MAX] = { 0, };
978-
FILE *fp;
979-
char buffer[1024];
981+
FILE *fp = NULL;
982+
char buffer[1024] = { 0, };
980983
char *provides = NULL;
981984
char *req_start = NULL;
982985
char *req_stop = NULL;
@@ -987,7 +990,8 @@ lsb_get_metadata(const char *type, char **output)
987990
char *s_dscrpt = NULL;
988991
char *xml_l_dscrpt = NULL;
989992
int offset = 0;
990-
char description[DESC_MAX];
993+
bool in_header = FALSE;
994+
char description[DESC_MAX] = { 0, };
991995

992996
if (type[0] == '/') {
993997
snprintf(ra_pathname, sizeof(ra_pathname), "%s", type);
@@ -1005,6 +1009,16 @@ lsb_get_metadata(const char *type, char **output)
10051009
/* Enter into the LSB-compliant comment block */
10061010
while (fgets(buffer, sizeof(buffer), fp)) {
10071011

1012+
// Ignore lines up to and including the block delimiter
1013+
if (!strncmp(buffer, LSB_INITSCRIPT_INFOBEGIN_TAG,
1014+
strlen(LSB_INITSCRIPT_INFOBEGIN_TAG))) {
1015+
in_header = TRUE;
1016+
continue;
1017+
}
1018+
if (!in_header) {
1019+
continue;
1020+
}
1021+
10081022
/* Assume each of the following eight arguments contain one line */
10091023
if (lsb_meta_helper_get_value(buffer, &provides, PROVIDES)) {
10101024
continue;
@@ -1032,37 +1046,48 @@ lsb_get_metadata(const char *type, char **output)
10321046
}
10331047

10341048
/* Long description may cross multiple lines */
1035-
if ((offset == 0)
1036-
&& !strncasecmp(buffer, DESCRIPTION, strlen(DESCRIPTION))) {
1037-
/* Between # and keyword, more than one space, or a tab
1038-
* character, indicates the continuation line.
1039-
*
1040-
* Extracted from LSB init script standard
1041-
*/
1049+
if ((offset == 0) // haven't already found long description
1050+
&& !strncmp(buffer, DESCRIPTION, strlen(DESCRIPTION))) {
1051+
bool processed_line = TRUE;
1052+
1053+
// Get remainder of description line itself
1054+
offset += snprintf(description, DESC_MAX, "%s",
1055+
buffer + strlen(DESCRIPTION));
1056+
1057+
// Read any continuation lines of the description
1058+
buffer[0] = '\0';
10421059
while (fgets(buffer, sizeof(buffer), fp)) {
10431060
if (!strncmp(buffer, "# ", 3) || !strncmp(buffer, "#\t", 2)) {
1044-
buffer[0] = ' ';
1061+
/* '#' followed by a tab or more than one space indicates a
1062+
* continuation of the long description.
1063+
*/
10451064
offset += snprintf(description + offset, DESC_MAX - offset,
1046-
"%s", buffer);
1065+
"%s", buffer + 1);
10471066
} else {
1048-
fputs(buffer, fp);
1049-
break; /* Long description ends */
1067+
/* This line is not part of the long description,
1068+
* so continue with normal processing.
1069+
*/
1070+
processed_line = FALSE;
1071+
break;
10501072
}
10511073
}
1052-
continue;
1053-
}
10541074

1055-
if ((xml_l_dscrpt == NULL) && (offset > 0)) {
1075+
// Make long description safe to use in XML
10561076
xml_l_dscrpt = (char *)xmlEncodeEntitiesReentrant(NULL, BAD_CAST(description));
1077+
1078+
if (processed_line) {
1079+
// We grabbed the line into the long description
1080+
continue;
1081+
}
10571082
}
10581083

1059-
if (!strncasecmp(buffer, LSB_INITSCRIPT_INFOEND_TAG,
1060-
strlen(LSB_INITSCRIPT_INFOEND_TAG))) {
1061-
/* Get to the out border of LSB comment block */
1084+
// Stop if we leave the header block
1085+
if (!strncmp(buffer, LSB_INITSCRIPT_INFOEND_TAG,
1086+
strlen(LSB_INITSCRIPT_INFOEND_TAG))) {
10621087
break;
10631088
}
10641089
if (buffer[0] != '#') {
1065-
break; /* Out of comment block in the beginning */
1090+
break;
10661091
}
10671092
}
10681093
fclose(fp);

lib/services/systemd.c

Lines changed: 56 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ systemd_unit_by_name(const gchar * arg_name, svc_action_t *op)
357357
GList *
358358
systemd_unit_listall(void)
359359
{
360-
int lpc = 0;
360+
int nfiles = 0;
361361
GList *units = NULL;
362362
DBusMessageIter args;
363363
DBusMessageIter unit;
@@ -369,64 +369,95 @@ systemd_unit_listall(void)
369369
}
370370

371371
/*
372-
" <method name=\"ListUnits\">\n" \
373-
" <arg name=\"units\" type=\"a(ssssssouso)\" direction=\"out\"/>\n" \
372+
" <method name=\"ListUnitFiles\">\n" \
373+
" <arg name=\"files\" type=\"a(ss)\" direction=\"out\"/>\n" \
374374
" </method>\n" \
375375
*/
376376

377-
reply = systemd_call_simple_method("ListUnits");
377+
reply = systemd_call_simple_method("ListUnitFiles");
378378
if (reply == NULL) {
379379
return NULL;
380380
}
381381
if (!dbus_message_iter_init(reply, &args)) {
382-
crm_err("Could not list systemd units: systemd reply has no arguments");
382+
crm_err("Could not list systemd unit files: systemd reply has no arguments");
383383
dbus_message_unref(reply);
384384
return NULL;
385385
}
386386
if (!pcmk_dbus_type_check(reply, &args, DBUS_TYPE_ARRAY,
387387
__FUNCTION__, __LINE__)) {
388-
crm_err("Could not list systemd units: systemd reply has invalid arguments");
388+
crm_err("Could not list systemd unit files: systemd reply has invalid arguments");
389389
dbus_message_unref(reply);
390390
return NULL;
391391
}
392392

393393
dbus_message_iter_recurse(&args, &unit);
394-
while (dbus_message_iter_get_arg_type (&unit) != DBUS_TYPE_INVALID) {
394+
for (; dbus_message_iter_get_arg_type(&unit) != DBUS_TYPE_INVALID;
395+
dbus_message_iter_next(&unit)) {
396+
395397
DBusBasicValue value;
398+
const char *match = NULL;
399+
char *unit_name = NULL;
400+
char *basename = NULL;
396401

397402
if(!pcmk_dbus_type_check(reply, &unit, DBUS_TYPE_STRUCT, __FUNCTION__, __LINE__)) {
403+
crm_debug("ListUnitFiles reply has unexpected type");
398404
continue;
399405
}
400406

401407
dbus_message_iter_recurse(&unit, &elem);
402408
if(!pcmk_dbus_type_check(reply, &elem, DBUS_TYPE_STRING, __FUNCTION__, __LINE__)) {
409+
crm_debug("ListUnitFiles reply does not contain a string");
403410
continue;
404411
}
405412

406413
dbus_message_iter_get_basic(&elem, &value);
407-
crm_trace("DBus ListUnits listed: %s", value.str);
408-
if(value.str) {
409-
const char *match = systemd_unit_extension(value.str);
410-
411-
if (match) {
412-
char *unit_name;
413-
414-
if (!strcmp(match, ".service")) {
415-
/* service is the "default" unit type, so strip it */
416-
unit_name = strndup(value.str, match - value.str);
417-
} else {
418-
unit_name = strdup(value.str);
419-
}
420-
lpc++;
421-
units = g_list_append(units, unit_name);
422-
}
414+
if (value.str == NULL) {
415+
crm_debug("ListUnitFiles reply did not provide a string");
416+
continue;
417+
}
418+
crm_trace("DBus ListUnitFiles listed: %s", value.str);
419+
420+
match = systemd_unit_extension(value.str);
421+
if (match == NULL) {
422+
// Unit files always have an extension, so skip if not present
423+
crm_debug("ListUnitFiles entry '%s' does not have an extension",
424+
value.str);
425+
continue;
426+
}
427+
428+
// ListUnitFiles returns full path names
429+
basename = strrchr(value.str, '/');
430+
if (basename) {
431+
basename = basename + 1;
432+
} else {
433+
basename = value.str;
434+
}
435+
436+
/* Unit files will include types (such as .target) that we can't manage,
437+
* so filter the replies here.
438+
*/
439+
if (!strcmp(match, ".service")) {
440+
// Service is the "default" unit type, so strip it
441+
unit_name = strndup(basename, match - basename);
442+
443+
} else if (!strcmp(match, ".mount")
444+
|| !strcmp(match, ".socket")) {
445+
unit_name = strdup(basename);
446+
}
447+
if (unit_name == NULL) {
448+
crm_trace("ListUnitFiles entry '%s' is not manageable",
449+
value.str);
450+
continue;
423451
}
424-
dbus_message_iter_next (&unit);
452+
453+
nfiles++;
454+
units = g_list_prepend(units, unit_name);
425455
}
426456

427457
dbus_message_unref(reply);
428458

429-
crm_trace("Found %d systemd services", lpc);
459+
crm_trace("Found %d manageable systemd unit files", nfiles);
460+
units = g_list_sort(units, crm_alpha_sort);
430461
return units;
431462
}
432463

mcp/pacemaker.sysconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@
6464
# start, unless they were previously put into standby mode. If this variable is
6565
# set to "standby" or "online", it will force this node to join in the
6666
# specified state when starting.
67-
# (experimental; currently ignored for Pacemaker Remote nodes)
67+
# (only supported for cluster nodes, not Pacemaker Remote nodes)
6868
# PCMK_node_start_state=default
6969

7070
# If the cluster uses an older version of corosync (prior to 2.0), set this to

pengine/graph.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,11 @@ update_colo_start_chain(action_t *action)
442442
if (is_not_set(action->flags, pe_action_runnable) && safe_str_eq(action->task, RSC_START)) {
443443
rsc = uber_parent(action->rsc);
444444
if (rsc->parent) {
445-
// This is a bundle (uber_parent() stops _before_ the bundle)
445+
/* For bundles, uber_parent() returns the clone/master, not the
446+
* bundle, so the existence of rsc->parent implies this is a bundle.
447+
* In this case, we need the bundle resource, so that we can check
448+
* if all containers are stopped/stopping.
449+
*/
446450
rsc = rsc->parent;
447451
}
448452
}

pengine/regression.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -866,6 +866,7 @@ do_test remote-recover-all "Fencing when the connection has no home"
866866
do_test remote-recover-no-resources "Fencing when the connection has no home and no active resources"
867867
do_test remote-recover-unknown "Fencing when the connection has no home and the remote has no operation history"
868868
do_test remote-reconnect-delay "Waiting for remote reconnect interval to expire"
869+
do_test remote-connection-unrecoverable "Remote connection host must be fenced, with connection unrecoverable"
869870

870871
echo ""
871872
do_test resource-discovery "Exercises resource-discovery location constraint option."

0 commit comments

Comments
 (0)