[Ocfs2-tools-commits] jlbec commits r511 - trunk/clusterbo
svn-commits at oss.oracle.com
svn-commits at oss.oracle.com
Thu Dec 23 20:02:05 CST 2004
Author: jlbec
Date: 2004-12-23 20:02:04 -0600 (Thu, 23 Dec 2004)
New Revision: 511
Modified:
trunk/clusterbo/o2cb_ctl.c
Log:
o Add lots more option parsing and make it start to do stuff
Modified: trunk/clusterbo/o2cb_ctl.c
===================================================================
--- trunk/clusterbo/o2cb_ctl.c 2004-12-23 20:40:45 UTC (rev 510)
+++ trunk/clusterbo/o2cb_ctl.c 2004-12-24 02:02:04 UTC (rev 511)
@@ -37,9 +37,10 @@
#include "o2cb_config.h"
#define PROGNAME "o2cb_ctl"
+#define O2CB_CONFIG_FILE "/etc/cluster.conf"
typedef enum {
- O2CB_OP_NONE,
+ O2CB_OP_NONE = 0,
O2CB_OP_INFO,
O2CB_OP_CREATE,
O2CB_OP_DELETE,
@@ -47,12 +48,26 @@
} O2CBOperation;
typedef enum {
+ O2CB_TYPE_NONE = 0,
O2CB_TYPE_CLUSTER,
O2CB_TYPE_NODE,
} O2CBType;
+typedef struct _O2CBContext O2CBContext;
typedef struct _OptionAttr OptionAttr;
+struct _O2CBContext
+{
+ O2CBOperation oc_op;
+ O2CBType oc_type;
+ gchar *oc_manager;
+ GList *oc_objects;
+ GList *oc_attrs;
+ gboolean oc_compact_info;
+ gboolean oc_modify_running;
+ O2CBConfig *oc_config;
+};
+
struct _OptionAttr
{
int oa_set;
@@ -60,7 +75,8 @@
gchar *oa_value;
};
-static void print_version()
+
+static void print_version(void)
{
fprintf(stdout, PROGNAME " version %s\n", VERSION);
exit(0);
@@ -71,14 +87,187 @@
FILE *output = rc ? stderr : stdout;
fprintf(output,
- "Usage: " PROGNAME " -C -l <manager> -n <object> [-a <attribute> ] ...\n"
- );
+ "Usage: " PROGNAME " -C -l <manager> -n <object> -t <type> [-i] [-a <attribute> ] ...\n"
+ " " PROGNAME " -D -l <manager> -n <object> [-u]\n"
+ " " PROGNAME " -I [-o|-z] -l <manager> [-n <object>] [-t <type>] [-a <attribute>] ...\n"
+ " " PROGNAME " -H -l <manager> [-n <object>] [-t <type>] [-a <attribute>] ...\n"
+ " " PROGNAME " -h\n"
+ " " PROGNAME " -V\n");
exit(rc);
} /* print_usage() */
-static gint append_attr(const gchar *attr_string, GList **list)
+static gint add_object(O2CBContext *ctxt, const gchar *object)
{
+ ctxt->oc_objects = g_list_append(ctxt->oc_objects,
+ g_strdup(object));
+
+ return 0;
+}
+
+static gboolean valid_attr(O2CBContext *ctxt, OptionAttr *attr)
+{
+ int i;
+ struct va_table
+ {
+ O2CBType va_type;
+ gchar *va_name;
+ } vat[] = {
+ {O2CB_TYPE_CLUSTER, "name"},
+ {O2CB_TYPE_CLUSTER, "online"},
+ {O2CB_TYPE_NODE, "name"},
+ {O2CB_TYPE_NODE, "number"},
+ {O2CB_TYPE_NODE, "ip_address"},
+ {O2CB_TYPE_NODE, "ip_port"},
+ };
+
+ for (i = 0; i < (sizeof(vat) / sizeof(*vat)); i++)
+ {
+ if ((vat[i].va_type == ctxt->oc_type) &&
+ !strcmp(vat[i].va_name, attr->oa_name))
+ return TRUE;
+ }
+
+ return FALSE;
+} /* valid_attr() */
+
+/* Must be called after oc_type is set */
+static gint validate_attrs(O2CBContext *ctxt)
+{
+ GList *list;
+ OptionAttr *attr;
+
+ list = ctxt->oc_attrs;
+
+ while (list)
+ {
+ attr = (OptionAttr *)(list->data);
+ if (!valid_attr(ctxt, attr))
+ {
+ fprintf(stderr,
+ PROGNAME ": Invalid attribute: \"%s\"\n",
+ attr->oa_name);
+ return -EINVAL;
+ }
+ list = list->next;
+ }
+
+ return 0;
+} /* validate_attrs() */
+
+static void clear_attrs(O2CBContext *ctxt)
+{
+ GList *list;
+ OptionAttr *attr;
+
+ list = ctxt->oc_attrs;
+
+ if (!list)
+ return;
+
+ while (list)
+ {
+ attr = (OptionAttr *)list->data;
+ if (attr->oa_name)
+ g_free(attr->oa_name);
+ if (attr->oa_value)
+ g_free(attr->oa_value);
+ g_free(attr);
+
+ list->data = NULL;
+ list = list->next;
+ }
+
+ g_list_free(ctxt->oc_attrs);
+} /* clear_attrs() */
+
+
+static gboolean attr_set(O2CBContext *ctxt, const gchar *attr_name)
+{
+ OptionAttr *attr;
+ GList *list;
+
+ list = ctxt->oc_attrs;
+ while (list)
+ {
+ attr = (OptionAttr *)list->data;
+ if (!strcmp(attr->oa_name, attr_name))
+ return attr->oa_set;
+ list = list->next;
+ }
+
+ return FALSE;
+} /* attr_set() */
+
+
+static const gchar *attr_string(O2CBContext *ctxt,
+ const gchar *attr_name,
+ const gchar *def_value)
+{
+ OptionAttr *attr;
+ GList *list;
+
+ list = ctxt->oc_attrs;
+ while (list)
+ {
+ attr = (OptionAttr *)list->data;
+ if (!strcmp(attr->oa_name, attr_name))
+ {
+ if (!attr->oa_set)
+ return def_value;
+ return attr->oa_value;
+ }
+ }
+
+ return def_value;
+} /* attr_string() */
+
+
+static gboolean attr_boolean(O2CBContext *ctxt,
+ const gchar *attr_name,
+ gboolean def_value)
+{
+ int i;
+ GList *list;
+ OptionAttr *attr;
+ struct b_table
+ {
+ gchar *match;
+ gboolean value;
+ } bt[] = {
+ {"0", FALSE}, {"1", TRUE},
+ {"f", FALSE}, {"t", TRUE},
+ {"false", FALSE}, {"true", TRUE},
+ {"n", FALSE}, {"y", TRUE},
+ {"no", FALSE}, {"yes", TRUE},
+ {"off", FALSE}, {"on", TRUE}
+ };
+
+ list = ctxt->oc_attrs;
+ while (list)
+ {
+ attr = (OptionAttr *)list->data;
+ if (!strcmp(attr->oa_name, attr_name))
+ {
+ if (!attr->oa_set || !attr->oa_value || !*(attr->oa_value))
+ break;
+ for (i = 0; i < (sizeof(bt) / sizeof(*bt)); i++)
+ {
+ if (!strcmp(bt[i].match, attr->oa_value))
+ return bt[i].value;
+ }
+ fprintf(stderr,
+ PROGNAME ": Invalid value for attribute \"%s\": %s\n",
+ attr_name, attr->oa_value);
+ return -EINVAL;
+ }
+ }
+
+ return def_value;
+} /* attr_boolean() */
+
+static gint append_attr(O2CBContext *ctxt, const gchar *attr_string)
+{
char **p;
OptionAttr *attr;
@@ -91,28 +280,27 @@
attr = g_new(OptionAttr, 1);
attr->oa_name = g_strdup(p[0]);
- attr->oa_value = g_strdup(p[1] ? p[1] : "");
+ attr->oa_value = g_strdup(p[1]);
attr->oa_set = 1;
g_strfreev(p);
- *list = g_list_append(*list, attr);
+ ctxt->oc_attrs = g_list_append(ctxt->oc_attrs, attr);
return 0;
} /* append_attr() */
extern char *optarg;
extern int optopt;
extern int opterr;
-static gint parse_options(gint argc, gchar *argv[], O2CBOperation *op,
- gchar **manager, gchar **object,
- gchar **stype, GList **prog_attrs)
+extern int optind;
+static gint parse_options(gint argc, gchar *argv[], O2CBContext *ctxt)
{
- int c, rc, doubledash;
- OptionAttr *attr;
+ int c, rc;
+ gboolean mi, mu, mo, mz;
- doubledash = 0;
+ mi = mu = mo = mz = FALSE;
opterr = 0;
- while ((c = getopt(argc, argv, ":hVCDIHl:n:t:a:-:")) != EOF)
+ while ((c = getopt(argc, argv, ":hVCDIHidozl:n:t:a:-:")) != EOF)
{
switch (c)
{
@@ -125,12 +313,6 @@
break;
case '-':
- if (!optarg || !*optarg)
- {
- doubledash = 1;
- break;
- }
-
if (!strcmp(optarg, "version"))
print_version();
else if (!strcmp(optarg, "help"))
@@ -144,36 +326,52 @@
break;
case 'C':
- if (*op != O2CB_OP_NONE)
+ if (ctxt->oc_op != O2CB_OP_NONE)
return -EINVAL;
- *op = O2CB_OP_CREATE;
+ ctxt->oc_op = O2CB_OP_CREATE;
break;
case 'D':
- if (*op != O2CB_OP_NONE)
+ if (ctxt->oc_op != O2CB_OP_NONE)
return -EINVAL;
- *op = O2CB_OP_DELETE;
+ ctxt->oc_op = O2CB_OP_DELETE;
break;
case 'I':
- if (*op != O2CB_OP_NONE)
+ if (ctxt->oc_op != O2CB_OP_NONE)
return -EINVAL;
- *op = O2CB_OP_INFO;
+ ctxt->oc_op = O2CB_OP_INFO;
break;
case 'H':
- if (*op != O2CB_OP_NONE)
+ if (ctxt->oc_op != O2CB_OP_NONE)
return -EINVAL;
- *op = O2CB_OP_CHANGE;
+ ctxt->oc_op = O2CB_OP_CHANGE;
break;
+ case 'i':
+ mi = TRUE;
+ break;
+
+ case 'u':
+ mu = TRUE;
+ break;
+
+ case 'z':
+ mz = TRUE;
+ break;
+
+ case 'o':
+ mo = TRUE;
+ break;
+
case 'l':
if (!optarg || !*optarg)
{
fprintf(stderr, PROGNAME ": Argument to \'-l\' cannot be \"\"\n");
return -EINVAL;
}
- *manager = optarg;
+ ctxt->oc_manager = g_strdup(optarg);
break;
case 'n':
@@ -182,7 +380,7 @@
fprintf(stderr, PROGNAME ": Argument to \'-n\' cannot be \"\"\n");
return -EINVAL;
}
- *object = optarg;
+ add_object(ctxt, optarg);
break;
case 't':
@@ -191,7 +389,15 @@
fprintf(stderr, PROGNAME ": Argument to \'-t\' cannot be \"\"\n");
return -EINVAL;
}
- *stype = optarg;
+ if (!strcmp(optarg, "cluster"))
+ ctxt->oc_type = O2CB_TYPE_CLUSTER;
+ else if (!strcmp(optarg, "node"))
+ ctxt->oc_type = O2CB_TYPE_NODE;
+ else
+ {
+ fprintf(stderr, PROGNAME ": Object type \"%s\" is invalid\n", optarg);
+ return -EINVAL;
+ }
break;
case 'a':
@@ -200,7 +406,7 @@
fprintf(stderr, PROGNAME ": Argument to \'-a\' cannot be \"\"\n");
return -EINVAL;
}
- rc = append_attr(optarg, prog_attrs);
+ rc = append_attr(ctxt, optarg);
if (rc)
return rc;
@@ -221,22 +427,224 @@
return -EINVAL;
break;
}
+ }
- if (doubledash)
- break;
+ if (optind < argc) {
+ fprintf(stderr, PROGNAME ": Extraneous arguments: \"");
+ for (; optind < argc; optind++)
+ {
+ fprintf(stderr, "%s", argv[optind]);
+ if ((optind + 1) < argc)
+ fprintf(stderr, " ");
+ }
+ fprintf(stderr, "\"\n");
+ return -E2BIG;
}
+
+ if (!ctxt->oc_manager)
+ {
+ fprintf(stderr, PROGNAME ": You must specify a manager device\n");
+ return -EINVAL;
+ }
+
+ if (mu && (ctxt->oc_op != O2CB_OP_DELETE))
+ c = 'u';
+ else if (mi && (ctxt->oc_op != O2CB_OP_CREATE))
+ c = 'i';
+ else if (mz && (ctxt->oc_op != O2CB_OP_INFO))
+ c = 'z';
+ else if (mo && (ctxt->oc_op != O2CB_OP_INFO))
+ c = 'o';
+
+ if (c != EOF)
+ {
+ fprintf(stderr, PROGNAME ": Argument \'-%c\' is not valid for this operation\n", c);
+ return -EINVAL;
+ }
+
+ if (mz && mo)
+ {
+ fprintf(stderr, PROGNAME ": Cannot specify \'-z\' and \'-o\' at the same time\n");
+ return -EINVAL;
+ }
+
+ if ((ctxt->oc_op == O2CB_OP_INFO) && mo)
+ ctxt->oc_compact_info = TRUE;
+ if ((ctxt->oc_op == O2CB_OP_CREATE) && mi)
+ ctxt->oc_modify_running = TRUE;
+ if ((ctxt->oc_op == O2CB_OP_DELETE) && mu)
+ ctxt->oc_modify_running = TRUE;
+
+ return 0;
} /* parse_options() */
+static gint load_config(O2CBContext *ctxt)
+{
+ ctxt->oc_config = o2cb_config_load(O2CB_CONFIG_FILE);
+ if (!ctxt->oc_config)
+ {
+ fprintf(stderr,
+ PROGNAME ": Unable to load cluster configuration file \"%s\"\n",
+ O2CB_CONFIG_FILE);
+ return -EIO;
+ }
+ return 0;
+} /* load_config() */
+
+static gint find_objects_for_type(O2CBContext *ctxt)
+{
+ fprintf(stderr,
+ PROGNAME ": Discovery by type not yet supported\n");
+ return -ENOTSUP;
+} /* find_objects_for_type() */
+
+static gint find_type_for_objects(O2CBContext *ctxt)
+{
+ int rc;
+ gchar *object, *name;
+ gulong num;
+ JIterator *iter;
+ O2CBNode *node;
+
+ object = (gchar *)ctxt->oc_objects->data;
+
+ name = o2cb_config_get_cluster_name(ctxt->oc_config);
+ if (!strcmp(name, object))
+ {
+ ctxt->oc_type = O2CB_TYPE_CLUSTER;
+ return 0;
+ }
+ g_free(name);
+
+ num = strtoul(object, &name, 10);
+ if (name && !*name && (num < UINT_MAX))
+ {
+ /* The object key is a number, hence a node number.
+ * object == NULL means check num, not object. */
+ g_free(object);
+ object = NULL;
+ }
+
+ iter = o2cb_config_get_nodes(ctxt->oc_config);
+ if (!iter)
+ return -ENOMEM;
+
+ rc = -ENOENT;
+ while (j_iterator_has_more(iter))
+ {
+ node = (O2CBNode *)j_iterator_get_next(iter);
+ if (object)
+ {
+ name = o2cb_node_get_name(node);
+ rc = strcmp(name, object);
+ g_free(name);
+ if (!rc)
+ {
+ ctxt->oc_type = O2CB_TYPE_NODE;
+ break;
+ }
+ }
+ else
+ {
+ if (num == o2cb_node_get_number(node))
+ {
+ ctxt->oc_type = O2CB_TYPE_NODE;
+ rc = 0;
+ break;
+ }
+ }
+ }
+
+ j_iterator_free(iter);
+
+ return rc;
+} /* find_type_for_objects() */
+
+static gint run_change(O2CBContext *ctxt)
+{
+ gint rc;
+
+ if (!ctxt->oc_type && !ctxt->oc_objects)
+ {
+ fprintf(stderr,
+ PROGNAME ": Operation \'-H\' requires an object or object type\n");
+ return -EINVAL;
+ }
+
+ rc = load_config(ctxt);
+ if (rc)
+ return rc;
+
+ if (ctxt->oc_type && !ctxt->oc_objects)
+ {
+ rc = find_objects_for_type(ctxt);
+ if (rc)
+ return rc;
+ }
+ else if (ctxt->oc_objects && !ctxt->oc_type)
+ {
+ rc = find_type_for_objects(ctxt);
+ if (rc)
+ return rc;
+ }
+
+ if (ctxt->oc_type == O2CB_TYPE_NODE)
+ {
+ fprintf(stderr,
+ PROGNAME ": Node changes not yet supported\n");
+ return -ENOTSUP;
+ }
+ else if (ctxt->oc_type == O2CB_TYPE_CLUSTER)
+ {
+ }
+ else
+ {
+ fprintf(stderr,
+ PROGNAME ": Invalid object type!\n");
+ return -EINVAL;
+ }
+
+ return rc;
+} /* run_change() */
+
gint main(gint argc, gchar *argv[])
{
int rc;
- gchar *manager, *target, *stype;
- O2CBOperation op;
- GList *prog_attrs = NULL;
+ O2CBContext ctxt = {0, };
- rc = parse_options(argc, argv, &op,
- &manager, &target, &stype,
- &prog_attrs);
+ rc = parse_options(argc, argv, &ctxt);
+ if (rc)
+ print_usage(rc);
+
+ switch (ctxt.oc_op)
+ {
+ case O2CB_OP_NONE:
+ fprintf(stderr,
+ PROGNAME ": You must specify an operation\n");
+ print_usage(-EINVAL);
+ break;
+
+ case O2CB_OP_CREATE:
+ case O2CB_OP_DELETE:
+ case O2CB_OP_INFO:
+ rc = -ENOTSUP;
+ fprintf(stderr,
+ PROGNAME ": Not yet supported\n");
+ break;
+
+ case O2CB_OP_CHANGE:
+ rc = run_change(&ctxt);
+ break;
+
+ default:
+ rc = -EINVAL;
+ fprintf(stderr,
+ PROGNAME ": Eeek! Invalid operation!\n");
+ break;
+ }
+
+ clear_attrs(&ctxt);
+
return 0;
} /* main() */
More information about the Ocfs2-tools-commits
mailing list