echo "$node_name" >> "$nodes_cfg_tmp"
done
rm -f "$nodes_cfg"
diff --git a/src/clm/README b/src/clm/README
index dee3e64f2..50e683ca5 100644
--- a/src/clm/README
+++ b/src/clm/README
@@ -64,11 +64,18 @@ the script will check if the new node is eligible
to be added to the cluster,
and if so add the necessary IMM objects so that the node will be
able to join
the next time it tries. The script will be called with one or more
command-line
arguments, where each argument is a comma-separated list of
properties of a node
-that wishes to join the cluster. Currently, the comma-separated list
in each
-command-line argument contains only two entries, but the script
should be
-forwards compatible with future extensions where more entries may be
added to
-the comma-separated list. The first entry in the list is the node id
represented
-as a decimal number. The second entry in the list is the name of the
node.
+that wishes to join the cluster. The comma separator can be changed by
+setting variable CLMNA_IFS in clmna.conf to use another field
separator, the
+field separator is passed in environment variable CLM_IFS to the
+opensaf_scale_out script.
+Currently, the comma-separated list in each command-line argument
contains
+four entries, node-id, node-name, node-ipaddress, user-data.
+But the script should be forwards compatible with future extensions
where more
+entries may be added to the comma-separated list. The first entry in
the list
+is the node id represented as a decimal number. The second entry in
the list is
+the name of the node. The third entry is the IP address of the node.
The fourth
+entry is optional user data that can be entered in a file named
+/etc/opensaf/clm_user_data, up to 256 characters can be given.
NOTE: the script must be idempotent, i.e. it must be harmless to
call it more
than one time with the same parameters. The second call should do
nothing since
diff --git a/src/clm/clmd/clms_cb.h b/src/clm/clmd/clms_cb.h
index 1bcc451cf..e381f8f2f 100644
--- a/src/clm/clmd/clms_cb.h
+++ b/src/clm/clmd/clms_cb.h
@@ -254,6 +254,8 @@ typedef struct clms_cb_t {
bool is_scale_out_thread_running;
/* Full path to the scale-out script, or NULL if feature is
disabled */
char *scale_out_script;
+ /* internal field separator */
+ char ifs;
} CLMS_CB;
typedef struct clms_lock_tmr_t { SaNameT node_name; } CLMS_LOCK_TMR;
diff --git a/src/clm/clmd/clms_evt.c b/src/clm/clmd/clms_evt.c
index 84e7b3c6d..8352af869 100644
--- a/src/clm/clmd/clms_evt.c
+++ b/src/clm/clmd/clms_evt.c
@@ -44,7 +44,7 @@ static uint32_t proc_rda_evt(CLMSV_CLMS_EVT *evt);
static uint32_t proc_mds_quiesced_ack_msg(CLMSV_CLMS_EVT *evt);
static uint32_t proc_node_lock_tmr_exp_msg(CLMSV_CLMS_EVT *evt);
static uint32_t proc_node_up_msg(CLMS_CB *cb, CLMSV_CLMS_EVT *evt);
-static void execute_scale_out_script(int argc, char *argv[]);
+static void execute_scale_out_script(int argc, char *argv[], char
clm_ifs);
static void *scale_out_thread(void *arg);
static void start_scale_out_thread(CLMS_CB *cb);
static void scale_out_node(CLMS_CB *cb,
@@ -300,15 +300,17 @@ done:
* and the second string is the node name. This function blocks
until the script
* has exited.
*/
-static void execute_scale_out_script(int argc, char *argv[])
+static void execute_scale_out_script(int argc, char *argv[], char
clm_ifs)
{
struct rlimit rlim;
int nofile = 1024;
- char *const env[] = {scale_out_path_env, NULL};
+ char *env[3];
+ char ifs[10];
TRACE_ENTER();
osafassert(argc >= 1 && argv[argc] == NULL);
- LOG_NO("Running script %s to scale out %d node(s)", argv[0],
argc - 1);
+ LOG_NO("Running script %s to scale out %d node(s), clm_ifs: [%c] ",
+ argv[0], argc - 1, clm_ifs);
if (getrlimit(RLIMIT_NOFILE, &rlim) == 0) {
if (rlim.rlim_cur != RLIM_INFINITY &&
@@ -326,6 +328,10 @@ static void execute_scale_out_script(int argc,
char *argv[])
if (child_pid == 0) {
for (int fd = 3; fd < nofile; ++fd)
close(fd);
+ snprintf(ifs, sizeof(ifs), "CLM_IFS=%c", clm_ifs);
+ env[0] = scale_out_path_env;
+ env[1] = ifs;
+ env[2] = NULL;
execve(argv[0], argv, env);
_Exit(123);
} else if (child_pid != (pid_t)-1) {
@@ -396,7 +402,8 @@ static void *scale_out_thread(void *arg)
osaf_mutex_unlock_ordie(&cb->scale_out_data_mutex);
if (no_of_pending_nodes == 0)
break;
- execute_scale_out_script(no_of_pending_nodes + 1, argv);
+ execute_scale_out_script(no_of_pending_nodes + 1, argv,
+ cb->ifs);
for (size_t i = 0; i != no_of_pending_nodes; ++i) {
free(argv[i + 1]);
}
@@ -453,6 +460,8 @@ static void scale_out_node(CLMS_CB *cb,
const clmsv_clms_node_up_info_t *nodeup_info)
{
char node_name[SA_MAX_NAME_LENGTH];
+ char user_data[SA_MAX_NAME_LENGTH];
+ char ifs; // Internal Field Separator
TRACE_ENTER();
size_t name_len = nodeup_info->node_name.length <
SA_MAX_NAME_LENGTH
@@ -461,6 +470,14 @@ static void scale_out_node(CLMS_CB *cb,
memcpy(node_name, nodeup_info->node_name.value, name_len);
node_name[name_len] = '\0';
+ size_t user_data_len = nodeup_info->user_data.length <
SA_MAX_NAME_LENGTH
+ ? nodeup_info->user_data.length
+ : (SA_MAX_NAME_LENGTH - 1);
+ memcpy(user_data, nodeup_info->user_data.value, user_data_len);
+ user_data[user_data_len] = '\0';
+
+ ifs = cb->ifs = nodeup_info->ifs;
+
osaf_mutex_lock_ordie(&cb->scale_out_data_mutex);
size_t no_of_pending_nodes = cb->no_of_pending_nodes;
size_t no_of_inprogress_nodes = cb->no_of_inprogress_nodes;
@@ -497,8 +514,9 @@ static void scale_out_node(CLMS_CB *cb,
memcpy(node_address, nodeup_info->address.value, addr_len);
node_address[addr_len] = '\0';
char *strp;
- if (asprintf(&strp, "%" PRIu32 ",%s,%s,", nodeup_info->node_id,
- node_name, node_address) != -1) {
+ if (asprintf(&strp, "%" PRIu32 "%c%s%c%s%c%s%c",
+ nodeup_info->node_id, ifs, node_name,
+ ifs, node_address, ifs, user_data, ifs) != -1) {
LOG_NO("Queuing request to scale out node 0x%" PRIx32
" (%s)",
nodeup_info->node_id, node_name);
diff --git a/src/clm/clmd/clms_mds.c b/src/clm/clmd/clms_mds.c
index 1eb0e1e62..ab647f30a 100644
--- a/src/clm/clmd/clms_mds.c
+++ b/src/clm/clmd/clms_mds.c
@@ -787,6 +787,27 @@ static uint32_t clms_dec_nodeup_msg(NCS_UBAID
*uba, CLMSV_MSG *msg)
TRACE("nodename %s length %d",
msg->info.api_info.param.nodeup_info.node_name.value,
msg->info.api_info.param.nodeup_info.node_name.length);
+
+ memset(&msg->info.api_info.param.nodeup_info.user_data, 0,
sizeof(SaNameT));
+ p8 = ncs_dec_flatten_space(uba, local_data, 2);
+ if (p8 != NULL) {
+ total_bytes += clmsv_decodeSaNameT(
+ uba, &(msg->info.api_info.param.nodeup_info.user_data));
+ TRACE("userdata %s length %d",
+ msg->info.api_info.param.nodeup_info.user_data.value,
+ msg->info.api_info.param.nodeup_info.user_data.length);
+ }
+
+ p8 = ncs_dec_flatten_space(uba, local_data, 1);
+ uint8_t ifs = 0;
+ if (p8 != NULL) {
+ ifs = ncs_decode_8bit(&p8);
+ ncs_dec_skip_space(uba, 1);
+ total_bytes += 1;
+ TRACE("CLM_IFS : [%c] ", ifs);
+ }
+ msg->info.api_info.param.nodeup_info.ifs = ifs;
+
p8 = ncs_dec_flatten_space(uba, local_data, 8);
// Old protocol versions don't have the boot_time field. Use
the current
// wall clock time if boot_time isn't present in the message.
diff --git a/src/clm/clmnd/cb.h b/src/clm/clmnd/cb.h
index 9b26a9bf5..2973e152f 100644
--- a/src/clm/clmnd/cb.h
+++ b/src/clm/clmnd/cb.h
@@ -37,6 +37,8 @@
typedef struct node_detail_t {
SaUint32T node_id;
SaNameT node_name;
+ SaNameT user_data;
+ SaInt8T ifs;
SaTimeT boot_time;
SaUint16T no_of_addresses;
SaClmNodeAddressT address;
diff --git a/src/clm/clmnd/clmna.conf b/src/clm/clmnd/clmna.conf
index 18a5a1b5a..ed4b1a754 100644
--- a/src/clm/clmnd/clmna.conf
+++ b/src/clm/clmnd/clmna.conf
@@ -31,5 +31,9 @@ export CLMNA_ENV_HEALTHCHECK_KEY="Default"
#export CLMNA_ADDR_FAMILY=1
#export CLMNA_ADDR_VALUE=10.130.100.114
+# The string argument passed to the opensaf_scale_out script is
default
+# comma separated. To use another separator character uncomment the
next line.
+#export CLMNA_IFS=";"
+
# Uncomment the next line to enable info level logging
#args="--loglevel=info"
diff --git a/src/clm/clmnd/main.c b/src/clm/clmnd/main.c
index 3a8479600..183570258 100644
--- a/src/clm/clmnd/main.c
+++ b/src/clm/clmnd/main.c
@@ -15,7 +15,7 @@
* Ericsson AB
*
*/
-
+#include <stdio.h>
#include <errno.h>
#include <inttypes.h>
#include <saClm.h>
@@ -389,6 +389,20 @@ static uint32_t clmna_mds_enc(struct
ncsmds_callback_info *info)
total_bytes += clmsv_encodeSaNameT(
uba,
&(msg->info.api_info.param.nodeup_info.node_name));
+
+ total_bytes += clmsv_encodeSaNameT(
+ uba,
+ &(msg->info.api_info.param.nodeup_info.user_data));
+
+ p8 = ncs_enc_reserve_space(uba, 1);
+ ncs_encode_8bit(
+ &p8,
+ msg->info.api_info.param.nodeup_info.ifs);
+ ncs_enc_claim_space(uba, 1);
+ total_bytes += 1;
+ TRACE("Encoded CLM_IFS: [%c] ",
+ msg->info.api_info.param.nodeup_info.ifs);
+
p8 = ncs_enc_reserve_space(uba, 8);
ncs_encode_64bit(
&p8,
@@ -508,9 +522,46 @@ static uint32_t clmna_mds_init(void)
return rc;
}
+static void get_user_data(NODE_INFO *node)
+{
+ FILE *fp;
+
+ fp = fopen(PKGSYSCONFDIR "/clm_user_data", "r");
+ if (fp == NULL) {
+ LOG_IN("Could not open file %s - %s", PKGSYSCONFDIR
"/clm_user_data",
+ strerror(errno));
+ return;
+ }
+
+ if (fgets((char*) node->user_data.value,
sizeof(node->user_data.value),
+ fp) != NULL) {
+ node->user_data.length = strnlen((char *)node->user_data.value,
+ sizeof(node->user_data.value));
+ } else {
+ LOG_WA("Could not read file %s", PKGSYSCONFDIR
"/clm_user_data");
+ }
+
+ if (memchr(node->user_data.value, node->ifs,
node->user_data.length) != NULL) {
+ LOG_WA("CLM IFS [%c] was found in %s", node->ifs,
node->user_data.value);
+ memset(&node->user_data, 0, sizeof(SaNameT));
+ }
+
+ fclose(fp);
+
+}
+
static int get_node_info(NODE_INFO *node)
{
FILE *fp;
+ const char *ifs;
+
+ if ((ifs = getenv("CLMNA_IFS")) == NULL) {
+ node->ifs = ','; // default field separator
+ } else {
+ node->ifs = *ifs;
+ }
+
+ get_user_data(node);
fp = fopen(PKGSYSCONFDIR "/node_name", "r");
if (fp == NULL) {
@@ -528,6 +579,11 @@ static int get_node_info(NODE_INFO *node)
node->node_name.length = strlen((char *)node->node_name.value);
TRACE("node name: '%s'", node->node_name.value);
+ if (memchr(node->node_name.value, node->ifs,
node->node_name.length) != NULL) {
+ LOG_ER("CLM IFS [%c] was found in %s", node->ifs,
node->node_name.value);
+ return -1;
+ }
+
fp = fopen(PKGLOCALSTATEDIR "/node_id", "r");
if (fp == NULL) {
LOG_ER("Could not open file %s - %s",
@@ -561,7 +617,8 @@ static int get_node_info(NODE_INFO *node)
if (errno != 0 || *endptr != '\0' || *family == '\0')
family = NULL;
}
- if (family != NULL && value != NULL) {
+ if (family != NULL && value != NULL &&
+ memchr(value, node->ifs, strlen(value)) == NULL) {
size_t len = strlen(value);
if (len > SA_CLM_MAX_ADDRESS_LENGTH)
len = SA_CLM_MAX_ADDRESS_LENGTH;
@@ -678,6 +735,9 @@ static void clmna_process_dummyup_msg(void)
msg.info.api_info.param.nodeup_info.no_of_addresses =
self_node.no_of_addresses;
msg.info.api_info.param.nodeup_info.address =
self_node.address;
+ msg.info.api_info.param.nodeup_info.user_data =
self_node.user_data;
+ msg.info.api_info.param.nodeup_info.ifs = self_node.ifs;
+
stop_scale_out_retry_tmr();
start_scale_out_retry_tmr(CLMNA_JOIN_RETRY_TIME);
uint32_t rc = clmna_mds_msg_send(&msg);
diff --git a/src/clm/common/clmsv_msg.h b/src/clm/common/clmsv_msg.h
index f312659f7..8eb71e836 100644
--- a/src/clm/common/clmsv_msg.h
+++ b/src/clm/common/clmsv_msg.h
@@ -139,6 +139,8 @@ typedef struct clmsv_track_info_t {
typedef struct {
SaUint32T node_id;
SaNameT node_name;
+ SaNameT user_data;
+ SaInt8T ifs; /* Internal Field Separator */
SaTimeT boot_time;
SaUint16T no_of_addresses;
SaClmNodeAddressT address;