[Sheepdog] [PATCH] collie: add subcommand usage description
MORITA Kazutaka
morita.kazutaka at lab.ntt.co.jp
Thu Aug 4 19:40:55 CEST 2011
This patch adds subcomand help.
Example:
$ collie vdi setattr -h
vdi setattr - set a vdi attribute
Usage:
collie vdi setattr <vdiname> <key> [value] [-d] [-x] [-a address] [-p port] [-h]
Command parameters:
-d, --delete delete a key
-x, --exclusive write in an exclusive mode
-a, --address specify the daemon address (default: localhost)
-p, --port specify the daemon port
-h, --help display this help and exit
Signed-off-by: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
---
collie/collie.c | 257 ++++++++++++++++++++++++++++++++++++++-----------------
1 files changed, 177 insertions(+), 80 deletions(-)
diff --git a/collie/collie.c b/collie/collie.c
index 2cdc161..3b60644 100644
--- a/collie/collie.c
+++ b/collie/collie.c
@@ -41,37 +41,36 @@ static int raw_output = 0;
#define TEXT_NORMAL "\033[0m"
#define TEXT_BOLD "\033[1m"
-#define COMMON_LONG_OPTIONS \
- {"address", required_argument, NULL, 'a'}, \
- {"port", required_argument, NULL, 'p'}, \
- {"raw", no_argument, NULL, 'r'}, \
- {"help", no_argument, NULL, 'h'}, \
+struct sd_option {
+ int val;
+ const char *name;
+ int has_arg;
+ const char *desc;
+};
-#define COMMON_SHORT_OPTIONS "a:p:hr"
+static const struct sd_option collie_options[] = {
-static void usage(int status)
-{
- if (status)
- fprintf(stderr, "Try `%s --help' for more information.\n", program_name);
- else {
- printf("Usage: %s command subcommand [options]\n", program_name);
- printf("Sheepdog Administrator Utilty\n\
-\n\
-Command syntax:\n\
- cluster (info|format|shutdown)\n\
- node (info|list)\n\
- vdi (list|tree|graph|delete|object|setattr|getattr)\n\
-\n\
-Common parameters:\n\
- -a, --address specify the daemon address (default: localhost)\n\
- -p, --port specify the daemon port\n\
- -r, --raw raw output mode: omit headers, separate fields with\n\
- single spaces and print all sizes in decimal bytes\n\
- -h, --help display this help and exit\n\
-");
- }
- exit(status);
-}
+ /* common options */
+ {'a', "address", 1, "specify the daemon address (default: localhost)"},
+ {'p', "port", 1, "specify the daemon port"},
+ {'r', "raw", 0, "raw output mode: omit headers, separate fields with\n\
+ single spaces and print all sizes in decimal bytes"},
+ {'h', "help", 0, "display this help and exit"},
+
+ /* vdi options */
+ {'i', "index", 1, "specify the index of data objects"},
+ {'s', "snapshot", 1, "specify a snapshot id or tag name"},
+ {'x', "exclusive", 0, "write in an exclusive mode"},
+ {'d', "delete", 0, "delete a key"},
+
+ /* cluster options */
+ {'c', "copies", 1, "set the number of data redundancy"},
+
+ { 0, NULL, 0, NULL },
+};
+
+static void usage(int status);
+static void subcommand_usage(char *cmd, char *subcmd, int status);
static uint64_t node_list_version;
@@ -616,6 +615,9 @@ static void parse_objs(uint64_t oid, obj_parser_func_t func, void *data)
struct subcommand {
const char *name;
+ const char *arg;
+ const char *opts;
+ const char *desc;
unsigned long flags;
int (*fn)(int, char **);
};
@@ -718,8 +720,10 @@ static int node_info(int argc, char **argv)
}
static struct subcommand node_cmd[] = {
- {"list", SUBCMD_FLAG_NEED_NODELIST, node_list},
- {"info", SUBCMD_FLAG_NEED_NODELIST, node_info},
+ {"list", NULL, "aprh", "list nodes",
+ SUBCMD_FLAG_NEED_NODELIST, node_list},
+ {"info", NULL, "aprh", "show each node information",
+ SUBCMD_FLAG_NEED_NODELIST, node_info},
{NULL,},
};
@@ -1127,26 +1131,23 @@ out:
}
static struct subcommand vdi_cmd[] = {
- {"delete", SUBCMD_FLAG_NEED_NODELIST|SUBCMD_FLAG_NEED_THIRD_ARG, vdi_delete},
- {"list", SUBCMD_FLAG_NEED_NODELIST, vdi_list},
- {"tree", SUBCMD_FLAG_NEED_NODELIST, vdi_tree},
- {"graph", SUBCMD_FLAG_NEED_NODELIST, vdi_graph},
- {"object", SUBCMD_FLAG_NEED_NODELIST|SUBCMD_FLAG_NEED_THIRD_ARG, vdi_object},
- {"setattr", SUBCMD_FLAG_NEED_NODELIST|SUBCMD_FLAG_NEED_THIRD_ARG, vdi_setattr},
- {"getattr", SUBCMD_FLAG_NEED_NODELIST|SUBCMD_FLAG_NEED_THIRD_ARG, vdi_getattr},
+ {"delete", "<vdiname>", "saph", "delete a image",
+ SUBCMD_FLAG_NEED_NODELIST|SUBCMD_FLAG_NEED_THIRD_ARG, vdi_delete},
+ {"list", "[vdiname]", "aprh", "list images",
+ SUBCMD_FLAG_NEED_NODELIST, vdi_list},
+ {"tree", NULL, "aph", "show images in tree view format",
+ SUBCMD_FLAG_NEED_NODELIST, vdi_tree},
+ {"graph", NULL, "aph", "show images with Graphviz dot format",
+ SUBCMD_FLAG_NEED_NODELIST, vdi_graph},
+ {"object", "<vdiname>", "isaph", "show object information in the image",
+ SUBCMD_FLAG_NEED_NODELIST|SUBCMD_FLAG_NEED_THIRD_ARG, vdi_object},
+ {"setattr", "<vdiname> <key> [value]", "dxaph", "set a vdi attribute",
+ SUBCMD_FLAG_NEED_NODELIST|SUBCMD_FLAG_NEED_THIRD_ARG, vdi_setattr},
+ {"getattr", "<vdiname> <key>", "aph", "get a vdi attribute",
+ SUBCMD_FLAG_NEED_NODELIST|SUBCMD_FLAG_NEED_THIRD_ARG, vdi_getattr},
{NULL,},
};
-static struct option vdi_long_options[] =
-{
- COMMON_LONG_OPTIONS
- {"index", required_argument, NULL, 'i'},
- {"snapshot", required_argument, NULL, 's'},
- {"exclusive", no_argument, NULL, 'x'},
- {"delete", no_argument, NULL, 'd'},
- {NULL, 0, NULL, 0},
-};
-
static int vdi_parser(int ch, char *opt)
{
switch (ch) {
@@ -1256,49 +1257,82 @@ static int cluster_shutdown(int argc, char **argv)
}
static struct subcommand cluster_cmd[] = {
- {"info", 0, cluster_info},
- {"format", 0, cluster_format},
- {"shutdown", SUBCMD_FLAG_NEED_NODELIST, cluster_shutdown},
+ {"info", NULL, "aprh", "show cluster information",
+ 0, cluster_info},
+ {"format", NULL, "caph", "create a Sheepdog storage",
+ 0, cluster_format},
+ {"shutdown", NULL, "aph", "stop Sheepdog",
+ SUBCMD_FLAG_NEED_NODELIST, cluster_shutdown},
{NULL,},
};
-static struct option cluster_long_options[] =
-{
- COMMON_LONG_OPTIONS
- {"copies", required_argument, NULL, 'c'},
- {NULL, 0, NULL, 0},
-};
-
static struct {
const char *name;
struct subcommand *sub;
- struct option *lopts;
- const char *sopts;
int (*parser)(int, char *);
- void (*help)(void);
} commands[] = {
{"vdi", vdi_cmd,
- vdi_long_options,
- COMMON_SHORT_OPTIONS "i:s:xd",
vdi_parser,},
{"node", node_cmd,},
{"cluster", cluster_cmd,
- cluster_long_options,
- COMMON_SHORT_OPTIONS "c:",
cluster_parser,},
};
-static struct option common_long_options[] =
-{
- COMMON_LONG_OPTIONS
- {NULL, 0, NULL, 0},
-};
-
-static struct option *long_options = common_long_options;
-static const char *short_options = COMMON_SHORT_OPTIONS;
static int (*command_parser)(int, char *);
static int (*command_fn)(int, char **);
-static void (*command_help)(void);
+static const char *command_options;
+static const char *command_arg;
+static const char *command_desc;
+
+static const struct sd_option *find_opt(int ch)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(collie_options); i++) {
+ if (collie_options[i].val == ch)
+ return collie_options + i;
+ }
+ fprintf(stderr, "internal error\n");
+ exit(EXIT_SYSFAIL);
+}
+
+static char *build_short_options(const char *opts)
+{
+ static char sopts[256], *p;
+ const struct sd_option *sd_opt;
+ int i, len = strlen(opts);
+
+ p = sopts;
+ for (i = 0; i < len; i++) {
+ sd_opt = find_opt(opts[i]);
+ *p++ = sd_opt->val;
+ if (sd_opt->has_arg)
+ *p++ = ':';
+ }
+ *p = '\0';
+
+ return sopts;
+}
+
+static struct option *build_long_options(const char *opts)
+{
+ static struct option lopts[256], *p;
+ const struct sd_option *sd_opt;
+ int i, len = strlen(opts);
+
+ p = lopts;
+ for (i = 0; i < len; i++) {
+ sd_opt = find_opt(opts[i]);
+ p->name = sd_opt->name;
+ p->has_arg = sd_opt->has_arg;
+ p->flag = NULL;
+ p->val = sd_opt->val;
+ p++;
+ }
+ memset(p, 0, sizeof(struct option));
+
+ return lopts;
+}
static unsigned long setup_command(char *cmd, char *subcmd)
{
@@ -1309,11 +1343,8 @@ static unsigned long setup_command(char *cmd, char *subcmd)
for (i = 0; i < ARRAY_SIZE(commands); i++) {
if (!strncmp(commands[i].name, cmd, strlen(commands[i].name))) {
found = 1;
- if (commands[i].parser) {
+ if (commands[i].parser)
command_parser = commands[i].parser;
- long_options = commands[i].lopts;
- short_options = commands[i].sopts;
- }
break;
}
}
@@ -1326,6 +1357,9 @@ static unsigned long setup_command(char *cmd, char *subcmd)
for (s = commands[i].sub; s->name; s++) {
if (!strncmp(s->name, subcmd, strlen(s->name))) {
command_fn = s->fn;
+ command_options = s->opts;
+ command_arg = s->arg;
+ command_desc = s->desc;
flags = s->flags;
break;
}
@@ -1342,10 +1376,71 @@ static unsigned long setup_command(char *cmd, char *subcmd)
return flags;
}
+static void usage(int status)
+{
+ int i;
+ struct subcommand *s;
+ char name[64];
+
+ if (status)
+ fprintf(stderr, "Try `%s --help' for more information.\n", program_name);
+ else {
+ printf("Usage: %s <command> <subcommand> [options]\n", program_name);
+ printf("Sheepdog Administrator Utilty\n");
+ printf("\n");
+ printf("Command syntax:\n");
+ for (i = 0; i < ARRAY_SIZE(commands); i++) {
+ for (s = commands[i].sub; s->name; s++) {
+ sprintf(name, "%s %s", commands[i].name, s->name);
+ printf(" %-24s%s\n", name, s->desc);
+ }
+ }
+ printf("\n");
+ printf("For more information, "
+ "type \"%s <command> <subcommand> --help\".\n", program_name);
+ }
+ exit(status);
+}
+
+static void subcommand_usage(char *cmd, char *subcmd, int status)
+{
+ int i, len = strlen(command_options);
+ const struct sd_option *sd_opt;
+ char name[64];
+
+ printf("%s %s - %s\n", cmd, subcmd, command_desc);
+ printf("\n");
+ printf("Usage:\n");
+ printf(" %s %s %s", program_name, cmd, subcmd);
+ if (command_arg)
+ printf(" %s", command_arg);
+
+ for (i = 0; i < len; i++) {
+ sd_opt = find_opt(command_options[i]);
+ if (sd_opt->has_arg)
+ printf(" [-%c %s]", sd_opt->val, sd_opt->name);
+ else
+ printf(" [-%c]", sd_opt->val);
+ }
+ printf("\n");
+ printf("\n");
+
+ printf("Command parameters:\n");
+ for (i = 0; i < len; i++) {
+ sd_opt = find_opt(command_options[i]);
+ sprintf(name, "-%c, --%s", sd_opt->val, sd_opt->name);
+ printf(" %-24s%s\n", name, sd_opt->desc);
+ }
+
+ exit(status);
+}
+
int main(int argc, char **argv)
{
int ch, longindex, ret;
unsigned long flags;
+ struct option *long_options;
+ const char *short_options;
if (argc < 3)
usage(0);
@@ -1354,6 +1449,9 @@ int main(int argc, char **argv)
optind = 3;
+ long_options = build_long_options(command_options);
+ short_options = build_short_options(command_options);
+
while ((ch = getopt_long(argc, argv, short_options, long_options,
&longindex)) >= 0) {
@@ -1368,8 +1466,7 @@ int main(int argc, char **argv)
raw_output = 1;
break;
case 'h':
- if (command_help)
- command_help();
+ subcommand_usage(argv[1], argv[2], EXIT_SUCCESS);
break;
case '?':
usage(EXIT_USAGE);
--
1.7.2.5
More information about the sheepdog
mailing list