[Ocfs2-tools-devel] [PATCH 12/32] o2cb: Add ops add-node and remove-node

Sunil Mushran sunil.mushran at oracle.com
Tue Sep 14 15:54:42 PDT 2010


add-node and remove-node manipulate node info in the o2cb config file.

Signed-off-by: Sunil Mushran <sunil.mushran at oracle.com>
---
 o2cb_ctl/Makefile   |    3 +-
 o2cb_ctl/o2cbtool.c |   13 +++
 o2cb_ctl/o2cbtool.h |    7 ++
 o2cb_ctl/op_node.c  |  272 +++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 294 insertions(+), 1 deletions(-)
 create mode 100644 o2cb_ctl/op_node.c

diff --git a/o2cb_ctl/Makefile b/o2cb_ctl/Makefile
index 1f5cbac..ba6e75a 100644
--- a/o2cb_ctl/Makefile
+++ b/o2cb_ctl/Makefile
@@ -27,7 +27,7 @@ DEFINES = -DVERSION=\"$(VERSION)\"
 
 O2CB_CONFIG_CFILES = o2cb_config.c jconfig.c jiterator.c
 O2CB_CTL_CFILES = ${O2CB_CONFIG_CFILES} o2cb_ctl.c
-O2CB_CFILES = ${O2CB_CONFIG_CFILES} o2cbtool.c op_cluster.c
+O2CB_CFILES = ${O2CB_CONFIG_CFILES} o2cbtool.c op_cluster.c op_node.c
 
 O2CB_CTL_OBJS = $(subst .c,.o,$(O2CB_CTL_CFILES))
 O2CB_OBJS = $(subst .c,.o,$(O2CB_CFILES))
@@ -48,6 +48,7 @@ o2cb_config_CPPFLAGS = $(GLIB_CFLAGS) -DG_DISABLE_DEPRECATED
 o2cb_ctl_CPPFLAGS = $(GLIB_CFLAGS) -DG_DISABLE_DEPRECATED
 o2cbtool_CPPFLAGS = $(GLIB_CFLAGS) -DG_DISABLE_DEPRECATED
 op_cluster_CPPFLAGS = $(GLIB_CFLAGS) -DG_DISABLE_DEPRECATED
+op_node_CPPFLAGS = $(GLIB_CFLAGS) -DG_DISABLE_DEPRECATED
 
 o2cb_ctl: $(O2CB_CTL_OBJS) $(LIBOCFS2_DEPS) $(LIBO2CB_DEPS)
 	$(LINK) $(LIBO2CB_LIBS) $(GLIB_LIBS) $(LIBOCFS2_LIBS) $(COM_ERR_LIBS)
diff --git a/o2cb_ctl/o2cbtool.c b/o2cb_ctl/o2cbtool.c
index 156a3da..4baeea2 100644
--- a/o2cb_ctl/o2cbtool.c
+++ b/o2cb_ctl/o2cbtool.c
@@ -35,6 +35,19 @@ struct o2cb_command o2cbtool_cmds[] = {
 		.o_help = "Removes cluster from the config file.",
 	},
 	{
+		.o_name = "add-node",
+		.o_action = o2cbtool_add_node,
+		.o_usage = "[--ip <ip>] [--port <port>] [--number <num>] "
+			"<clustername> <nodename>",
+		.o_help = "Adds a node to the cluster in the config file.",
+	},
+	{
+		.o_name = "remove-node",
+		.o_action = o2cbtool_remove_node,
+		.o_usage = "<clustername> <nodename>",
+		.o_help = "Removes a node from the cluster in the config file.",
+	},
+	{
 		.o_name = NULL,
 		.o_action = NULL,
 	},
diff --git a/o2cb_ctl/o2cbtool.h b/o2cb_ctl/o2cbtool.h
index 59d6066..79506a9 100644
--- a/o2cb_ctl/o2cbtool.h
+++ b/o2cb_ctl/o2cbtool.h
@@ -41,6 +41,7 @@
 #include "tools-internal/utils.h"
 
 #define O2CB_DEFAULT_CONFIG_FILE	"/etc/ocfs2/cluster.conf"
+#define O2CB_DEFAULT_IP_PORT		7777
 
 struct o2cb_command {
 	int o_modified;
@@ -56,9 +57,15 @@ struct o2cb_command {
 
 enum {
 	CONFIG_FILE_OPTION = CHAR_MAX + 1,
+	IP_OPTION,
+	PORT_OPTION,
+	NODENUM_OPTION,
 };
 
 errcode_t o2cbtool_validate_clustername(char *clustername);
 
 errcode_t o2cbtool_add_cluster(struct o2cb_command *cmd);
 errcode_t o2cbtool_remove_cluster(struct o2cb_command *cmd);
+
+errcode_t o2cbtool_add_node(struct o2cb_command *cmd);
+errcode_t o2cbtool_remove_node(struct o2cb_command *cmd);
diff --git a/o2cb_ctl/op_node.c b/o2cb_ctl/op_node.c
new file mode 100644
index 0000000..723b2e7
--- /dev/null
+++ b/o2cb_ctl/op_node.c
@@ -0,0 +1,272 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * op_node.c
+ *
+ * Manipulates nodes in the o2cb cluster configuration
+ *
+ * Copyright (C) 2010 Oracle.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License, version 2,  as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include "o2cbtool.h"
+
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+static int add_node_parse_options(int argc, char *argv[], char **ip, int *port,
+				  int *nodenum, char **nodename,
+				  char **clustername)
+{
+	int c, ret = -1, show_usage = 0;
+	static struct option long_options[] = {
+		{ "ip", 1, 0, IP_OPTION },
+		{ "port", 1, 0, PORT_OPTION },
+		{ "number", 1, 0, NODENUM_OPTION },
+		{ 0, 0, 0, 0 },
+	};
+
+	while (1) {
+		c = getopt_long(argc, argv, "", long_options, NULL);
+		if (c == -1)
+			break;
+		switch (c) {
+		case IP_OPTION:
+			*ip = strdup(optarg);
+			if (!*ip) {
+				errorf("out-off-memory while copying ip\n");
+				goto bail;
+			}
+			break;
+		case PORT_OPTION:
+			*port = atoi(optarg);
+			break;
+		case NODENUM_OPTION:
+			*nodenum = atoi(optarg);
+			break;
+		default:
+			++show_usage;
+			break;
+		}
+	}
+
+	if (optind + 2 > argc || show_usage)
+		goto bail;
+
+	*clustername = argv[optind];
+
+	*nodename = tools_strstrip(argv[optind + 1]);
+	if (!strlen(*nodename)) {
+		errorf("node name cannot be zero length\n");
+		goto bail;
+	}
+
+	ret = 0;
+	verbosef(VL_DEBUG, "Add node '%s' in cluster '%s' having ip '%s', "
+		 "port '%d' and number '%d'\n", *nodename, *clustername,
+		 (*ip ? *ip : "auto"), *port, *nodenum); 
+
+bail:
+	return ret;
+}
+
+static int validate_ip_address(char *nodename, char **ip)
+{
+	struct addrinfo hints, *ai = NULL;
+	struct in_addr addr;
+	int ret;
+
+	/* if given, validate format */
+	if (*ip) {
+		ret = inet_pton(AF_INET, *ip, &addr);
+		if (ret <= 0) {
+			tcom_err(ret, "Bad IP Address '%s'", *ip);
+			ret = -1;
+		}
+		ret = (ret > 0) ? 0 : ret;
+		goto bail;
+	}
+
+	/* if not provided, discover it */
+	memset(&hints, 0, sizeof(hints));
+	hints.ai_family = AF_INET;
+	hints.ai_protocol = IPPROTO_TCP;
+	hints.ai_socktype = SOCK_STREAM;
+
+	ret = getaddrinfo(nodename, NULL, &hints, &ai);
+	if (ret) {
+		errorf("%s, while looking up the IP address for '%s'\n",
+		       gai_strerror(ret), nodename);
+		goto bail;
+	}
+
+	addr.s_addr = ((struct sockaddr_in *)(ai->ai_addr))->sin_addr.s_addr;
+
+	*ip = strdup(inet_ntoa(addr));
+	if (!*ip) {
+		tcom_err(O2CB_ET_NO_MEMORY, "while setting ip for node '%s'",
+			 nodename);
+		goto bail;
+	}
+
+	ret = 0;
+
+bail:
+	if (ai)
+		freeaddrinfo(ai);
+	if (!ret)
+		verbosef(VL_DEBUG, "Validated ip address '%s'\n", *ip);
+	return ret;
+}
+
+static int validate_nodenum(O2CBCluster *cluster, int *nodenum)
+{
+	O2CBNode *node;
+	int i, ret = -1;
+
+	/* if none, then get the first unused nodenum */
+	if (*nodenum == -1) {
+		for(i = 0; i < O2NM_MAX_NODES; ++i) {
+			node = o2cb_cluster_get_node(cluster, i);
+			if (!node) {
+				*nodenum = i;
+				ret = 0;
+				goto bail;
+			}
+		}
+		errorf("Cluster is full - No more nodes can be added to it\n");
+		goto bail;
+	}
+
+	/* if provided, validate range... */
+	if (!(*nodenum >= 0 && *nodenum < O2NM_MAX_NODES)) {
+		errorf("Nodenum should be >=0 and < %d but is %d\n",
+		       O2NM_MAX_NODES, *nodenum);
+		goto bail;
+	}
+
+	/* ... and ensure it is not inuse */
+	node = o2cb_cluster_get_node(cluster, *nodenum);
+	if (node) {
+		errorf("Choose another node number as '%d' is in use\n",
+		       *nodenum);
+		goto bail;
+	}
+
+	ret = 0;
+bail:
+	if (!ret)
+		verbosef(VL_DEBUG, "Validated node number '%d'\n", *nodenum);
+	return ret;
+}
+
+/*
+ * o2cb add-node [--ip <ip>] [--port <port>] [--number <num>]
+ * 			<clustername> <nodename>
+ */
+errcode_t o2cbtool_add_node(struct o2cb_command *cmd)
+{
+	O2CBCluster *cluster;
+	O2CBNode *node;
+	errcode_t ret;
+	gchar *clustername = '\0', *nodename = '\0', *ip = '\0';
+	gint port = -1, nodenum = -1;
+
+	ret = add_node_parse_options(cmd->o_argc, cmd->o_argv, &ip, &port,
+				     &nodenum, &nodename, &clustername);
+	if (ret) {
+		errorf("usage: %s %s\n", cmd->o_name, cmd->o_usage);
+		goto bail;
+	}
+
+	ret = -1;
+	cluster = o2cb_config_get_cluster_by_name(cmd->o_config, clustername);
+	if (!cluster) {
+		errorf("unknown cluster '%s'\n", clustername);
+		goto bail;
+	}
+
+	/* validate */
+	ret = validate_ip_address(nodename, &ip);
+	if (ret)
+		goto bail;
+
+	ret = validate_nodenum(cluster, &nodenum);
+	if (ret)
+		goto bail;
+
+	if (port == -1)
+		port = O2CB_DEFAULT_IP_PORT;
+
+	ret = -1;
+	node = o2cb_cluster_add_node(cluster, nodename);
+	if (!node) {
+		errorf("node '%s' already exists\n", nodename);
+		goto bail;
+	}
+
+	ret = o2cb_node_set_ip_string(node, ip);
+	if (ret) {
+		tcom_err(ret, "while setting ip '%s'", ip);
+		goto bail;
+	}
+
+	o2cb_node_set_port(node, port);
+	o2cb_node_set_number(node, nodenum);
+
+	cmd->o_modified = 1;
+	ret = 0;
+	verbosef(VL_APP, "Added node '%s' in cluster '%s' having ip '%s', "
+		 "port '%d' and number '%d'\n", nodename, clustername, ip,
+		 port, nodenum);
+
+bail:
+	return ret;
+}
+
+/*
+ * o2cb remove-node <clustername> <nodename>
+ */
+errcode_t o2cbtool_remove_node(struct o2cb_command *cmd)
+{
+	O2CBCluster *cluster;
+	errcode_t ret = -1;
+	gchar *clustername, *nodename;
+
+	if (cmd->o_argc < 3) {
+		errorf("usage: %s %s\n", cmd->o_name, cmd->o_usage);
+		goto bail;
+	}
+
+	clustername = cmd->o_argv[1];
+	nodename = cmd->o_argv[2];
+
+	cluster = o2cb_config_get_cluster_by_name(cmd->o_config, clustername);
+	if (!cluster) {
+		errorf("unknown cluster '%s'\n", clustername);
+		goto bail;
+	}
+
+	ret = o2cb_cluster_delete_node(cluster, nodename);
+	if (ret) {
+		errorf("unknown node '%s'\n", nodename);
+		goto bail;
+	}
+
+	cmd->o_modified = 1;
+	ret = 0;
+	verbosef(VL_APP, "Removed node '%s' from cluster '%s'\n", nodename,
+		 clustername);
+
+bail:
+	return ret;
+}
-- 
1.7.0.4




More information about the Ocfs2-tools-devel mailing list