Example #1
0
/* Get info on a kb from any number of nodes. For all kbs, or all nodes,
   set the corresponding argument to NULL */
fsa_kb_info *fsaf_fetch_kb_info(const unsigned char *kb_name,
                                fsa_node_addr *nodes)
{
    fsa_node_addr *cur_node;
    int free_nodes = 0; /* free nodes if they werem't passed to function */

    /* if no nodes given, get all nodes from config */
    if (nodes == NULL) {
        fsa_error(LOG_DEBUG, "fetching kb info for all nodes");
        GKeyFile *conf = fsa_get_config();
        nodes = fsa_get_node_list(conf);
        fsa_config_free(conf);
        free_nodes = 1;
    }

    unsigned char *buf;
    unsigned char header_buf[ADM_HEADER_LEN]; /* store single header packet */
    int nbytes, sock_fd, rv;

    struct addrinfo hints;

    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;

    /* command to be sent to all stores */
    int cmd_len; /* length of command packet */
    unsigned char *cmd_pkt; /* command packet itself */
    fsa_kb_info *ki_list = NULL;
    uint8_t cmdval;
    uint16_t datasize;
    char ipaddr[INET6_ADDRSTRLEN]; /* large enough to hold a v4 or v6 addr */

    if (kb_name == NULL) {
        /* get info on all kbs */
        fsa_error(LOG_DEBUG, "fetching info for all kbs");
        cmd_pkt = fsap_encode_cmd_get_kb_info_all(&cmd_len);
    }
    else {
        /* request info on named kb */
        fsa_error(LOG_DEBUG, "fetching info for kb '%s'", kb_name);
        cmd_pkt = fsap_encode_cmd_get_kb_info(kb_name, &cmd_len);
    }

    fsa_error(LOG_DEBUG, "admin command length is %d bytes", cmd_len);

    /* connect to each storage node */
    for (cur_node = nodes; cur_node != NULL; cur_node = cur_node->next) {
        sock_fd = fsaf_connect_to_admind(cur_node->host, cur_node->port,
                                         &hints, ipaddr);
        if (sock_fd == -1) {
            fsa_error(LOG_ERR, "failed to connect to %s:%d, skipping node",
                      cur_node->host, cur_node->port);
            continue;
        }

        /* send command to node */
        nbytes = cmd_len;
        rv = fsa_sendall(sock_fd, cmd_pkt, &nbytes);
        if (rv == -1) {
            fsa_error(LOG_ERR, "failed to send command to %s:%d, skipping node",
                      cur_node->host, cur_node->port);
            continue;
        }

        fsa_error(LOG_DEBUG,
                  "header (%d bytes) sent to %s:%d, waiting for response",
                  nbytes, cur_node->host, cur_node->port);

        /* get response header from node */
        rv = fsa_fetch_header(sock_fd, header_buf);
        if (rv == -1) {
            fsa_error(LOG_ERR,
                      "failed to get response from %s:%d, skipping node",
                      cur_node->host, cur_node->port);
            continue;
        }

        fsa_error(LOG_DEBUG, "response received from %s:%d",
                  cur_node->host, cur_node->port);

        /* server sent us data */
        rv = fsap_decode_header(header_buf, &cmdval, &datasize);
        if (rv == -1) {
            fsa_error(LOG_ERR, "unable to decode header from %s:%d",
                      cur_node->host, cur_node->port);
            close(sock_fd);
            continue;
        }

        /* alloc buffer for receiving further data into */
        buf = (unsigned char *)malloc(datasize);
        if (buf == NULL) {
            errno = ENOMEM;
            free(cmd_pkt);
            return NULL;
        }

        fsa_error(LOG_DEBUG, "response header from %s:%d decoded",
                  cur_node->host, cur_node->port);

        /* handle response from client */
        if (cmdval == ADM_RSP_GET_KB_INFO_ALL) {
            fsa_error(LOG_DEBUG, "ADM_RSP_GET_KB_INFO_ALL received");
            fsa_error(LOG_DEBUG, "fetching data from client");

            nbytes = fsaf_recv_from_admind(sock_fd, buf, datasize);
            if (nbytes <= 0) {
                /* error already handled */
                free(buf);
                continue;
            }

            /* local list of kb info for a single node */
            fsa_kb_info *kid = fsap_decode_rsp_get_kb_info_all(buf);
            free(buf);
            fsa_kb_info *tmp_ki = NULL;
            fsa_kb_info *cur_ki = NULL;

            /* add kb info to list of info across nodes */
            if (kid != NULL) {
                tmp_ki = kid; /* pointer to start of list */
                cur_ki = kid;
                int done = 0;

                while (!done) {
                    cur_ki->ipaddr = (unsigned char *)strdup(ipaddr);
                    if (cur_ki->next == NULL) {
                        /* if last item in list */
                        cur_ki->next = ki_list; /* append existing vals */
                        ki_list = tmp_ki; /* point to new head */
                        done = 1;
                    }
                    else {
                        cur_ki = cur_ki->next;
                    }
                }
            }
        }
        else if (cmdval == ADM_RSP_GET_KB_INFO) {
            fsa_error(LOG_DEBUG, "ADM_RSP_GET_KB_INFO_ALL received");
            fsa_error(LOG_DEBUG, "fetching data from client");

            nbytes = fsaf_recv_from_admind(sock_fd, buf, datasize);
            if (nbytes <= 0) {
                /* error already handled */
                free(buf);
                continue;
            }

            fsa_kb_info *kid = fsap_decode_rsp_get_kb_info(buf);
            free(buf);

            if (kid != NULL) {
                /* copy ip addr to struct */
                kid->ipaddr = (unsigned char *)strdup(ipaddr);
                kid->next = ki_list;
                ki_list = kid;
            }
        }

        close(sock_fd);
    }

    free(cmd_pkt);
    if (free_nodes) {
        fsa_node_addr_free(nodes);
    }

    return ki_list;
}
Example #2
0
/* Send command to a server, and receive an response.
   Arguments: node, sock_fd - the server to send to
              cmd, len - the command to send, and its length
   Returns: undecoded response from server
   Sets:    response - ADM_RSP_* code
            bufsize - size of response from server
            err - success/error status of call */
unsigned char *fsaf_send_recv_cmd(fsa_node_addr *node, int sock_fd,
                                 unsigned char *cmd, int len,
                                 int *response, int *bufsize, int *err)
{
    fsa_error(LOG_DEBUG,
              "sending command with length %d bytes to %s:%d on sock %d",
              len, node->host, node->port, sock_fd);

    int rv;
    static unsigned char header_buf[ADM_HEADER_LEN];

    *bufsize = 0; /* set to 0 until we create/fill a buffer */

    /* send command packet */
    rv = fsa_sendall(sock_fd, cmd, &len);
    if (rv == -1) {
        fsa_error(LOG_ERR,
                  "failed to send command to %s:%d",
                  node->host, node->port);
        *err = ADM_ERR_NETWORK;
        return NULL;
    }

    /* get response header */
    rv = fsa_fetch_header(sock_fd, header_buf);
    if (rv == -1) {
        fsa_error(LOG_ERR,
                  "failed to get response from %s:%d",
                  node->host, node->port);
        *err = ADM_ERR_NETWORK;
        return NULL;
    }

    fsa_error(LOG_DEBUG, "response received from %s:%d",
              node->host, node->port);

    /* server sent us data, so decode header */
    uint8_t cmdval;
    uint16_t datasize;
    rv = fsap_decode_header(header_buf, &cmdval, &datasize);
    if (rv == -1) {
        fsa_error(LOG_CRIT, "unable to decode header from %s:%d",
                  node->host, node->port);
        *err = ADM_ERR_PROTO;
        return NULL;
    }

    *response = cmdval;

    fsa_error(LOG_DEBUG, "response header from %s:%d decoded",
              node->host, node->port);

    unsigned char *buf = NULL;

    if (datasize > 0) {
        /* create buffer for rest of data from server */
        buf = (unsigned char *)malloc(datasize);
        if (buf == NULL) {
            errno = ENOMEM;
            *err = ADM_ERR_SEE_ERRNO;
            return NULL;
        }
        *bufsize = datasize;

        rv = fsaf_recv_from_admind(sock_fd, buf, datasize);
        if (rv <= 0) {
            /* error already handled */
            free(buf);
            *err = ADM_ERR_NETWORK;
            return NULL;
        }
    }

    *err = ADM_ERR_OK;
    return buf;
}
Example #3
0
/* Used to handle store starting/stopping, interface is mostly identical */
static int start_or_stop_stores(int action)
{
    int all = 0; /* if -a flag, then start/stop all, instead of kb name */
    int kb_name_len = 11;

    if (args_index < 0) {
        /* no argument given, display help text */
        fsa_error(
            LOG_ERR,
            "No store name(s) given. Use `%s help %s' for details",
            program_invocation_short_name, argv[cmd_index]
        );
        return 1;
    }

    if (strcmp("-a", argv[args_index]) == 0
        || strcmp("--all", argv[args_index]) == 0) {
        all = 1; /* all stores */
    }
    else {
        /* check for invalid store names */
        for (int i = args_index; i < argc; i++) {
            if (!fsa_is_valid_kb_name(argv[i])) {
                fsa_error(LOG_ERR, "'%s' is not a valid store name", argv[i]);
                return 1;
            }

            int len = strlen(argv[i]);
            if (len > kb_name_len) {
                kb_name_len = len;
            }
        }
    }
    
    /* get list of all storage nodes */
    fsa_node_addr *nodes = get_storage_nodes();

    /* Setup hints information */
    struct addrinfo hints;
    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;

    int sock_fd, len;
    char ipaddr[INET6_ADDRSTRLEN];
    unsigned char *buf;

    int node_num = 0;
    unsigned char *cmd = NULL;
    int n_errors = 0;

    /* to be set by fsa_send_recv_cmd */
    int response, bufsize, err;

    int print_node_header = 1;
    int print_store_header = 1;

    for (fsa_node_addr *n = nodes; n != NULL; n = n->next) {
        sock_fd = fsaf_connect_to_admind(n->host, n->port, &hints, ipaddr);

        print_node_line(node_num, n->host, print_node_header);
        print_node_header = 0;

        node_num += 1;

        if (sock_fd == -1) {
            print_colour("unreachable\n", ANSI_COLOUR_RED);
            continue;
        }
        
        if (all) {
            /* start/stop all kbs */
            if (action == STOP_STORE) {
                cmd = fsap_encode_cmd_stop_kb_all(&len);
            }
            else if (action == START_STORE) {
                cmd = fsap_encode_cmd_start_kb_all(&len);
            }

            if (cmd == NULL) {
                fsa_error(LOG_CRIT, "failed to encode %s command",
                          argv[cmd_index]);
                n_errors += 1;
                break;
            }

            fsa_error(LOG_DEBUG, "sending '%s' command to %s:%d",
                      argv[cmd_index], n->host, n->port);

            /* send command and get reply */
            buf = fsaf_send_recv_cmd(n, sock_fd, cmd, len,
                                     &response, &bufsize, &err);

            /* usually a network error */
            if (buf == NULL) {
                /* error already handled */
                n_errors += 1;
                break;
            }

            /* should get this if all went well */
            if (response == ADM_RSP_EXPECT_N_KB) {
                int rv;
                uint8_t rspval;
                uint16_t datasize;
                unsigned char header_buf[ADM_HEADER_LEN];
                fsa_kb_response *kbr = NULL;

                int max_kb_len;
                int expected_responses =
                    fsap_decode_rsp_expect_n_kb(buf, &max_kb_len);
                free(buf);

                fsa_error(LOG_DEBUG, "expecting %d responses from server",
                          expected_responses);

                /* print header */
                if (print_store_header) {
                    if (colour_flag) {
                        printf(ANSI_COLOUR_BLUE);
                    }

                    printf("  %-*s status\n", max_kb_len, "store_name");

                    if (colour_flag) {
                        printf(ANSI_COLOUR_RESET);
                    }
                }

                /* get packet from server for each kb started/stopped */
                for (int i = 0; i < expected_responses; i++) {
                    rv = fsa_fetch_header(sock_fd, header_buf);
                    if (rv == -1) {
                        fsa_error(LOG_ERR,
                                  "failed to get response from %s:%d",
                                  n->host, n->port);
                        break;
                    }

                    fsa_error(LOG_DEBUG, "got header %d/%d",
                              i+1, expected_responses);

                    rv = fsap_decode_header(header_buf, &rspval, &datasize);
                    if (rv == -1) {
                        fsa_error(LOG_CRIT,
                                  "unable to decode header from %s:%d",
                                  n->host, n->port);
                        break;
                    }

                    if (rspval == ADM_RSP_ABORT_EXPECT) {
                        fsa_error(LOG_ERR, "operation aborted by server");
                        break;
                    }

                    buf = (unsigned char *)malloc(datasize);
                    rv = fsaf_recv_from_admind(sock_fd, buf, datasize);
                    if (rv < 0) {
                        /* error already handled/logged */
                        free(buf);
                        break;
                    }

                    if (rspval == ADM_RSP_STOP_KB) {
                        kbr = fsap_decode_rsp_stop_kb(buf);
                        printf("  %-*s ", max_kb_len, kbr->kb_name);
                        switch (kbr->return_val) {
                            case ADM_ERR_OK:
                            case ADM_ERR_KB_STATUS_STOPPED:
                                print_colour("stopped", ANSI_COLOUR_GREEN);
                                break;
                            case ADM_ERR_KB_STATUS_UNKNOWN:
                                print_colour("unknown", ANSI_COLOUR_RED);
                                break;
                            default:
                                fsa_error(
                                    LOG_CRIT,
                                    "Unknown server response: %d",
                                    kbr->return_val
                                );
                                print_colour("unknown", ANSI_COLOUR_RED);
                                break;
                        }
                    }
                    else if (rspval == ADM_RSP_START_KB) {
                        kbr = fsap_decode_rsp_start_kb(buf);
                        printf("  %-*s ", max_kb_len, kbr->kb_name);
                        switch (kbr->return_val) {
                            case ADM_ERR_OK:
                            case ADM_ERR_KB_STATUS_RUNNING:
                                print_colour("running", ANSI_COLOUR_GREEN);
                                break;
                            case ADM_ERR_KB_STATUS_STOPPED:
                                print_colour("stopped", ANSI_COLOUR_YELLOW);
                                break;
                            case ADM_ERR_KB_STATUS_UNKNOWN:
                                print_colour("unknown", ANSI_COLOUR_RED);
                                break;
                            default:
                                fsa_error(
                                    LOG_CRIT,
                                    "Unknown server response: %d",
                                    kbr->return_val
                                );
                                print_colour("unknown", ANSI_COLOUR_RED);
                                break;
                        }
                    }
                    printf("\n");

                    free(buf);
                    buf = NULL;
                    fsa_kb_response_free(kbr);
                    kbr = NULL;
                }
            }
            else if (response == ADM_RSP_ERROR) {
                unsigned char *errmsg = fsap_decode_rsp_error(buf, bufsize);
                fsa_error(LOG_ERR, "server error: %s", errmsg);
                free(errmsg);
                free(buf);
            }
            else {
                fsa_error(LOG_ERR, "unexpected response from server: %d",
                          response);
                free(buf);
            }
        }
        else {
            /* print header */
            if (print_store_header) {
                if (colour_flag) {
                    printf(ANSI_COLOUR_BLUE);
                }

                printf("  %-*s status\n", kb_name_len, "store_name");

                if (colour_flag) {
                    printf(ANSI_COLOUR_RESET);
                }

                print_store_header = 0;
            }

            /* stop kbs given on command line */
            for (int i = args_index; i < argc; i++) {
                /* send start/stop command for each kb */
                if (action == STOP_STORE) {
                    cmd = fsap_encode_cmd_stop_kb((unsigned char *)argv[i],
                                                  &len);
                }
                else if (action == START_STORE) {
                    cmd = fsap_encode_cmd_start_kb((unsigned char *)argv[i],
                                                   &len);
                }

                if (cmd == NULL) {
                    fsa_error(LOG_CRIT, "failed to encode %s command",
                            argv[cmd_index]);
                    n_errors += 1;
                    break;
                }

                fsa_error(LOG_DEBUG, "sending %s '%s' command to %s:%d",
                          argv[cmd_index], argv[i], n->host, n->port);

                buf = fsaf_send_recv_cmd(n, sock_fd, cmd, len,
                                         &response, &bufsize, &err);
                free(cmd);
                cmd = NULL;

                /* usually a network error */
                if (buf == NULL) {
                    /* error already handled */
                    n_errors += 1;
                    break;
                }

                printf("  %-*s ", kb_name_len, argv[i]);

                fsa_kb_response *kbr = NULL;

                if (response == ADM_RSP_STOP_KB) {
                    kbr = fsap_decode_rsp_stop_kb(buf);
                    switch (kbr->return_val) {
                        case ADM_ERR_OK:
                        case ADM_ERR_KB_STATUS_STOPPED:
                            print_colour("stopped", ANSI_COLOUR_GREEN);
                            break;
                        case ADM_ERR_KB_NOT_EXISTS:
                            print_colour("store_not_found", ANSI_COLOUR_RED);
                            break;
                        default:
                            print_colour("unknown", ANSI_COLOUR_RED);
                            break;
                    }
                    printf("\n");
                    fsa_kb_response_free(kbr);
                }
                else if (response == ADM_RSP_START_KB) {
                    kbr = fsap_decode_rsp_start_kb(buf);
                    switch (kbr->return_val) {
                        case ADM_ERR_OK:
                        case ADM_ERR_KB_STATUS_RUNNING:
                            print_colour("running", ANSI_COLOUR_GREEN);
                            break;
                        case ADM_ERR_KB_STATUS_STOPPED:
                            print_colour("stopped", ANSI_COLOUR_YELLOW);
                            break;
                        case ADM_ERR_KB_NOT_EXISTS:
                            print_colour("store_not_found", ANSI_COLOUR_RED);
                            break;
                        default:
                            print_colour("unknown", ANSI_COLOUR_RED);
                            break;
                    }
                    printf("\n");
                    fsa_kb_response_free(kbr);
                }
                else if (response == ADM_RSP_ERROR) {
                    unsigned char *msg = fsap_decode_rsp_error(buf, bufsize);
                    printf("unknown: %s\n", msg);
                    free(msg);
                    n_errors += 1;
                }
                else {
                    fsa_error(LOG_CRIT, "unknown response from server");
                    n_errors += 1;
                }
                
                free(buf);
            }
        }

        /* done with current server */
        close(sock_fd);
    }

    if (n_errors > 0) {
        return 1;
    }
    return 0;
}