| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418 |
- /* Parses the interactive commands */
- #include <config.h>
- #include <string.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <netinet/in.h>
- #ifdef HAVE_READLINE_HISTORY_H
- #include <readline/history.h>
- #endif
- #include <corosync/coroapi.h>
- #include "vqsim.h"
- static void do_usage(void)
- {
- printf(" All node IDs in the cluster are unique and belong to a numbered 'partition' (default=0)\n");
- printf("\n");
- printf("up [<partition>:][<nodeid>[,<nodeid>] ...] [[<partition>:][<nodeid>...]] [...]\n");
- printf(" bring node(s) online in the specified partition(s)\n");
- printf("down <nodeid>,[<nodeid>...]\n");
- printf(" send nodes offline (shut them down)\n");
- printf("move/split [<partition>:][<nodeid>[,<nodeid>] ...] [[<partition>:][<nodeid>...]] [...]\n");
- printf(" Move nodes from one partition to another (netsplit)\n");
- printf(" <partition> here is the partition to move the nodes to\n");
- printf("join <partition> <partition> [<partition>] ... \n");
- printf(" Join partitions together (reverse of a netsplit)\n");
- printf("qdevice on|off [<partition>:][<nodeid>[,<nodeid>] ...] [[<partition>:][<nodeid>...]] [...]\n");
- printf(" Enable quorum device in specified nodes\n");
- printf("autofence on|off\n");
- printf(" automatically 'down' nodes on inquorate side on netsplit\n");
- printf("timeout <n> (default 250)\n");
- printf(" Wait a maximum of <n> milli-seconds for the next command to complete.\n");
- printf("sync on|off (default on)\n");
- printf(" enable/disable synchronous execution of commands (wait for completion)\n");
- printf("assert on|off (default off)\n");
- printf(" Abort the simulation run if a timeout expires\n");
- printf("show Show current nodes status\n");
- printf("exit\n\n");
- }
- /* Commands return 0 if they return immediately, >1 if we are waiting for replies from nodes */
- typedef int (*cmd_routine_t)(int argc, char **argv);
- static int run_up_cmd(int argc, char **argv);
- static int run_down_cmd(int argc, char **argv);
- static int run_join_cmd(int argc, char **argv);
- static int run_move_cmd(int argc, char **argv);
- static int run_exit_cmd(int argc, char **argv);
- static int run_show_cmd(int argc, char **argv);
- static int run_timeout_cmd(int argc, char **argv);
- static int run_assert_cmd(int argc, char **argv);
- static int run_autofence_cmd(int argc, char **argv);
- static int run_qdevice_cmd(int argc, char **argv);
- static int run_sync_cmd(int argc, char **argv);
- static struct cmd_list_struct {
- const char *cmd;
- int min_args;
- cmd_routine_t cmd_runner;
- } cmd_list[] = {
- { "up", 1, run_up_cmd},
- { "down", 1, run_down_cmd},
- { "move", 2, run_move_cmd},
- { "split", 2, run_move_cmd},
- { "join", 2, run_join_cmd},
- { "autofence", 1, run_autofence_cmd},
- { "qdevice", 1, run_qdevice_cmd},
- { "show", 0, run_show_cmd},
- { "timeout", 1, run_timeout_cmd},
- { "sync", 1, run_sync_cmd},
- { "assert", 1, run_assert_cmd},
- { "exit", 0, run_exit_cmd},
- { "quit", 0, run_exit_cmd},
- { "q", 0, run_exit_cmd},
- };
- static int num_cmds = (sizeof(cmd_list)) / sizeof(struct cmd_list_struct);
- #define MAX_ARGS 1024
- /* Takes a <partition>:[<node>[,<node>]...] list and return it
- as a partition and a list of nodes.
- Returns 0 if successful, -1 if not
- */
- static int parse_partition_nodelist(char *string, int *partition, int *num_nodes, int **retnodes)
- {
- int i;
- int nodecount;
- int len;
- int last_comma;
- char *nodeptr;
- int *nodes;
- char *colonptr = strchr(string, ':');
- if (colonptr) {
- *colonptr = '\0';
- nodeptr = colonptr+1;
- *partition = atoi(string);
- }
- else {
- /* Default to partition 0 */
- *partition = 0;
- nodeptr = string;
- }
- /* Count the number of commas and allocate space for the nodes */
- nodecount = 0;
- for (i=0; i<strlen(nodeptr); i++) {
- if (nodeptr[i] == ',') {
- nodecount++;
- }
- }
- nodecount++; /* The one between the last comma and the trailing NUL */
- if (nodecount < 1 || nodecount > MAX_NODES) {
- return -1;
- }
- nodes = malloc(sizeof(int) * nodecount);
- if (!nodes) {
- return -1;
- }
- nodecount = 0;
- last_comma = 0;
- len = strlen(nodeptr);
- for (i=0; i<=len; i++) {
- if (nodeptr[i] == ',' || nodeptr[i] == '\0') {
- nodeptr[i] = '\0';
- nodes[nodecount++] = atoi(&nodeptr[last_comma]);
- last_comma = i+1;
- }
- }
- *num_nodes = nodecount;
- *retnodes = nodes;
- return 0;
- }
- void parse_input_command(char *rl_cmd)
- {
- int i;
- int argc = 0;
- int valid_cmd = 0;
- char *argv[MAX_ARGS];
- int last_arg_start = 0;
- int last_was_space = 0;
- int len;
- int ret = 0;
- char *cmd;
- /* ^D quits */
- if (rl_cmd == NULL) {
- (void)run_exit_cmd(0, NULL);
- }
- /* '#' starts a comment */
- if (rl_cmd[0] == '#') {
- return;
- }
- cmd = strdup(rl_cmd);
- /* Split cmd up into args
- * destroying the original string mwahahahaha
- */
- len = strlen(cmd);
- /* Span leading spaces */
- for (i=0; cmd[i] == ' '; i++)
- ;
- last_arg_start = i;
- for (; i<=len; i++) {
- if (cmd[i] == ' ' || cmd[i] == '\0') {
- /* Allow multiple spaces */
- if (last_was_space) {
- continue;
- }
- cmd[i] = '\0';
- last_was_space = 1;
- argv[argc] = &cmd[last_arg_start];
- argc++;
- }
- else {
- if (last_was_space) {
- last_arg_start = i;
- }
- last_was_space = 0;
- }
- }
- /* Ignore null commands */
- if (strlen(argv[0]) == 0) {
- free(cmd);
- resume_kb_input(0);
- return;
- }
- #ifdef HAVE_READLINE_HISTORY_H
- add_history(rl_cmd);
- #endif
- /* Dispatch command */
- for (i=0; i<num_cmds; i++) {
- if (strcasecmp(argv[0], cmd_list[i].cmd) == 0) {
- if (argc < cmd_list[i].min_args) {
- break;
- }
- ret = cmd_list[i].cmd_runner(argc, argv);
- valid_cmd = 1;
- }
- }
- if (!valid_cmd) {
- do_usage();
- }
- free(cmd);
- /* ret==0 means we can return immediately to command-line input */
- if (ret == 0) {
- resume_kb_input(ret);
- }
- }
- static int run_up_cmd(int argc, char **argv)
- {
- int partition;
- int num_nodes;
- int *nodelist;
- int i,j;
- int succeeded = 0;
- if (argc <= 1) {
- return 0;
- }
- cmd_start_sync_command();
- for (i=1; i<argc; i++) {
- if (parse_partition_nodelist(argv[i], &partition, &num_nodes, &nodelist) == 0) {
- for (j=0; j<num_nodes; j++) {
- if (!cmd_start_new_node(nodelist[j], partition)) {
- succeeded++;
- }
- }
- free(nodelist);
- }
- }
- return succeeded;
- }
- static int run_down_cmd(int argc, char **argv)
- {
- int nodeid;
- int i;
- int succeeded = 0;
- cmd_start_sync_command();
- for (i=1; i<argc; i++) {
- nodeid = atoi(argv[1]);
- if (!cmd_stop_node(nodeid)) {
- succeeded++;
- }
- }
- return succeeded;
- }
- static int run_join_cmd(int argc, char **argv)
- {
- int i;
- if (argc < 2) {
- printf("join needs at least two partition numbers\n");
- return 0;
- }
- cmd_start_sync_command();
- for (i=2; i<argc; i++) {
- cmd_join_partitions(atoi(argv[1]), atoi(argv[i]));
- }
- cmd_update_all_partitions(1);
- return 1;
- }
- static int run_move_cmd(int argc, char **argv)
- {
- int i;
- int partition;
- int num_nodes;
- int *nodelist;
- cmd_start_sync_command();
- for (i=1; i<argc; i++) {
- if (parse_partition_nodelist(argv[i], &partition, &num_nodes, &nodelist) == 0) {
- cmd_move_nodes(partition, num_nodes, nodelist);
- free(nodelist);
- }
- }
- cmd_update_all_partitions(1);
- return 1;
- }
- static int run_autofence_cmd(int argc, char **argv)
- {
- int onoff = -1;
- if (strcasecmp(argv[1], "on") == 0) {
- onoff = 1;
- }
- if (strcasecmp(argv[1], "off") == 0) {
- onoff = 0;
- }
- if (onoff == -1) {
- fprintf(stderr, "ERR: autofence value must be 'on' or 'off'\n");
- }
- else {
- cmd_set_autofence(onoff);
- }
- return 0;
- }
- static int run_qdevice_cmd(int argc, char **argv)
- {
- int i,j;
- int partition;
- int num_nodes;
- int *nodelist;
- int onoff = -1;
- if (strcasecmp(argv[1], "on") == 0) {
- onoff = 1;
- }
- if (strcasecmp(argv[1], "off") == 0) {
- onoff = 0;
- }
- if (onoff == -1) {
- fprintf(stderr, "ERR: qdevice should be 'on' or 'off'\n");
- return 0;
- }
- for (i=2; i<argc; i++) {
- if (parse_partition_nodelist(argv[i], &partition, &num_nodes, &nodelist) == 0) {
- for (j=0; j<num_nodes; j++) {
- cmd_qdevice_poll(nodelist[j], onoff);
- }
- free(nodelist);
- }
- }
- cmd_update_all_partitions(0);
- return 0;
- }
- static int run_show_cmd(int argc, char **argv)
- {
- cmd_show_node_states();
- return 0;
- }
- static int run_timeout_cmd(int argc, char **argv)
- {
- cmd_set_timeout(atol(argv[1]));
- return 0;
- }
- static int run_sync_cmd(int argc, char **argv)
- {
- int onoff = -1;
- if (strcasecmp(argv[1], "on") == 0) {
- onoff = 1;
- }
- if (strcasecmp(argv[1], "off") == 0) {
- onoff = 0;
- }
- if (onoff == -1) {
- fprintf(stderr, "ERR: sync value must be 'on' or 'off'\n");
- }
- else {
- cmd_set_sync(onoff);
- }
- return 0;
- }
- static int run_assert_cmd(int argc, char **argv)
- {
- int onoff = -1;
- if (strcasecmp(argv[1], "on") == 0) {
- onoff = 1;
- }
- if (strcasecmp(argv[1], "off") == 0) {
- onoff = 0;
- }
- if (onoff == -1) {
- fprintf(stderr, "ERR: assert value must be 'on' or 'off'\n");
- }
- else {
- cmd_set_assert(onoff);
- }
- return 0;
- }
- static int run_exit_cmd(int argc, char **argv)
- {
- cmd_stop_all_nodes();
- exit(0);
- }
|