[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