From c257925e22ad6af0a219fd1d62cc1b7a86a404ea Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 6 Jul 2020 10:37:26 +0100 Subject: [PATCH] cmd: Implement "vos status" Signed-off-by: David Howells --- kafs/Makefile | 4 +- kafs/arg_parse.h | 8 +++ kafs/arg_resolve.c | 157 +++++++++++++++++++++++++++++++++++++++++++++ kafs/display.c | 31 +++++++++ kafs/display.h | 2 + kafs/vos_status.c | 112 ++++++++++++++++++++++++++++++++ 6 files changed, 313 insertions(+), 1 deletion(-) create mode 100644 kafs/arg_resolve.c create mode 100644 kafs/vos_status.c diff --git a/kafs/Makefile b/kafs/Makefile index 5d839b3..ad08be5 100644 --- a/kafs/Makefile +++ b/kafs/Makefile @@ -7,6 +7,7 @@ CORE_SRCS := \ kafs.c \ arg_completion.c \ arg_parse.c \ + arg_resolve.c \ display.c \ display_error.c \ display_vol.c \ @@ -31,7 +32,8 @@ PTS_SRCS := \ VOS_SRCS := \ vos.c \ vos_help.c \ - vos_listvldb.c + vos_listvldb.c \ + vos_status.c CORE_OBJS := $(patsubst %.c,%.o,$(CORE_SRCS)) BOS_OBJS := $(patsubst %.c,%.o,$(BOS_SRCS)) diff --git a/kafs/arg_parse.h b/kafs/arg_parse.h index 7df6f36..34edaf8 100644 --- a/kafs/arg_parse.h +++ b/kafs/arg_parse.h @@ -96,6 +96,14 @@ extern void free_extracted_args(struct extracted_arg *arg); extern struct extracted_arg *extract_arguments(struct kafs_context *ctx, char **args, const struct kafs_command *cmd); +/* + * arg_resolve.c + */ +extern bool kafs_resolve_volserver_spec(struct kafs_context *, struct kafs_volserver_spec *, + struct kafs_fileserver **); +extern bool kafs_resolve_fileserver_spec(struct kafs_context *, struct kafs_fileserver_spec *, + struct kafs_fileserver **); + /* * kafs.c */ diff --git a/kafs/arg_resolve.c b/kafs/arg_resolve.c new file mode 100644 index 0000000..6fef375 --- /dev/null +++ b/kafs/arg_resolve.c @@ -0,0 +1,157 @@ +/* Argument resolver + * + * Copyright (C) 2020 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include "rxrpc.h" +#include "afs_xg.h" +#include "arg_parse.h" + +/* + * Convert a name into a server list. + */ +static bool kafs_resolve_server_spec(struct kafs_context *ctx, + const char *name, + bool is_volserver, + struct kafs_fileserver **_server) +{ + struct kafs_fileserver *server; + struct sockaddr_rxrpc *addrs, *srx; + struct addrinfo *ai = NULL, *p; + const char *service = is_volserver ? "afs3-volser" : "afs3-fileserver"; + char *canon = NULL; + unsigned short service_id = is_volserver ? VOLSERVICE_ID : FS_SERVICE; + int err, n; + + struct addrinfo hints = { + .ai_family = AF_UNSPEC, + .ai_socktype = SOCK_DGRAM, + .ai_protocol = IPPROTO_UDP, + }; + + _enter("%s", name); + + server = calloc(1, sizeof(*server)); + if (!server) { + kafs_nomem(ctx); + goto error; + } + server->ref = 1; + + err = getaddrinfo(name, service, &hints, &ai); + if (err != 0) { + fprintf(stderr, "%s: %s\n", name, gai_strerror(err)); + goto error; + } + + /* Count the number of usable addresses */ + n = 0; + for (p = ai; p; p = p->ai_next) { + switch (p->ai_family) { + case AF_INET: + case AF_INET6: + n++; + break; + default: + break; + } + } + + addrs = calloc(n, sizeof(struct sockaddr_rxrpc)); + if (!addrs) + goto nomem; + + srx = addrs; + for (p = ai; p; p = p->ai_next) { + if (p->ai_canonname && !canon) + canon = p->ai_canonname; + + srx->srx_family = AF_RXRPC; + srx->srx_service = service_id; + srx->transport_type = p->ai_socktype; + srx->transport_len = p->ai_addrlen; + switch (p->ai_family) { + case AF_INET: + case AF_INET6: + memcpy(&srx->transport, p->ai_addr, p->ai_addrlen); + srx++; + break; + default: + break; + } + } + + server->name = strdup(canon ?: name); + if (!server->name) + goto nomem; + + if (is_volserver) { + server->vs_nr_addrs = n; + server->vs_addrs = addrs; + } else { + server->fs_nr_addrs = n; + server->fs_addrs = addrs; + } + + *_server = server; + freeaddrinfo(ai); + _leave(" = t [%u,%u]", server->vs_nr_addrs, server->fs_nr_addrs); + return true; + +nomem: + perror(NULL); +error: + freeaddrinfo(ai); + free(addrs); + put_kafs_fileserver(server); + return false; +} + +/** + * kafs_resolve_volserver_spec - Resolve a volume server spec + * @ctx: The cell and authentication context + * @vs: The volume server specifier + * @_server: Where to return the server record. + * + * Resolve a volume server specified as a name or address into a set of + * addresses that can be used to contact it. The addresses are attached to a + * server record, which is returned. + */ +bool kafs_resolve_volserver_spec(struct kafs_context *ctx, + struct kafs_volserver_spec *vs, + struct kafs_fileserver **_server) +{ + return kafs_resolve_server_spec(ctx, vs->name, true, _server); +} + +/** + * kafs_resolve_fileserver_spec - Resolve a fileserver spec + * @ctx: The cell and authentication context + * @vs: The fileserver specifier + * @_server: Where to return the server record. + * + * Resolve a fileserver specified as a name or address into a set of addresses + * that can be used to contact it. The addresses are attached to a server + * record, which is returned. + */ +bool kafs_resolve_fileserver_spec(struct kafs_context *ctx, + struct kafs_fileserver_spec *fs, + struct kafs_fileserver **_server) +{ + return kafs_resolve_server_spec(ctx, fs->name, false, _server); +} diff --git a/kafs/display.c b/kafs/display.c index aa01bef..d9ba95e 100644 --- a/kafs/display.c +++ b/kafs/display.c @@ -18,6 +18,37 @@ #include "afs_xg.h" #include "display.h" +/** + * kafs_print_time - Print a time in standard format + * @time: The time to display. + * + * Print a time in a standard format for AFS tools to stdout. + */ +void kafs_print_time(time_t time) +{ + struct tm tm; + char buf[128]; + + localtime_r(&time, &tm); + strftime(buf, 128, "%a %b %d %H:%M:%S %Y", &tm); + printf("%s", buf); +} + +/** + * kafs_print_time_or_never - Print a time in standard format + * @time: The time to display. + * + * Print a time in a standard format for AFS tools to stdout. If @time is 0, + * then "Never" will be printed instead. + */ +void kafs_print_time_or_never(time_t time) +{ + if (!time) + printf("Never"); + return kafs_print_time(time); +} + + /** * kafs_sprint_address - Convert/resolve an address into text * @ctx: The cell and authentication context diff --git a/kafs/display.h b/kafs/display.h index 40f450f..20e5c35 100644 --- a/kafs/display.h +++ b/kafs/display.h @@ -20,6 +20,8 @@ struct kafs_vldb_site; /* * display.c */ +extern void kafs_print_time(time_t); +extern void kafs_print_time_or_never(time_t); extern void kafs_sprint_address(struct kafs_context *, struct sockaddr_rxrpc *, char *, size_t); extern void kafs_sprint_partition(struct kafs_context *, struct kafs_partition *, char *, size_t); diff --git a/kafs/vos_status.c b/kafs/vos_status.c new file mode 100644 index 0000000..edb23cd --- /dev/null +++ b/kafs/vos_status.c @@ -0,0 +1,112 @@ +/* The "vos status" command + * + * Copyright (C) 2020 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include "kafs.h" +#include "arg_parse.h" +#include "volservice.h" +#include "afs_xg.h" +#include "display.h" + +/*** + * COMMAND: vos status - Report a volume server's status + * ARG: "-server " + * ARG: "[-cell ]" + * ARG: "[-noauth]" - Auth + * ARG: "[-localauth]" - Auth + * ARG: "[-verbose]" + * ARG: "[-encrypt]" - Auth + * ARG: "[-noresolve]" + * + * Report a volume server's status + */ +bool COMMAND_vos_status( + struct kafs_context *ctx, + struct kafs_volserver_spec *a_server, + bool a_verbose, + bool a_noresolve) +{ + struct kafs_vol_transaction_info_list transactions = {}; + struct kafs_fileserver *server; + unsigned int i; + char pbuf[32]; + int ret = false; + + _enter(""); + + ctx->no_resolve = a_noresolve; + + if (!kafs_resolve_volserver_spec(ctx, a_server, &server)) + return false; + + if (!kafs_open_volserver(ctx, server)) + goto out; + + if (!kafs_vol_monitor_transaction(ctx, server, &transactions)) + goto out; + + if (transactions.count == 0) { + printf("No active transactions on %s\n", server->name); + ret = true; + goto out_result; + } + + printf("--------------------------------------------\n"); + for (i = 0; i < transactions.count; i++) { + struct kafs_vol_transaction_info *trans = &transactions.info[i]; + struct kafs_partition part; + unsigned int iflags = trans->iflags; + + printf("transaction: %d created: ", trans->tid); + kafs_print_time(trans->creation_time); + printf("\n"); + printf("lastActiveTime: "); + kafs_print_time(trans->time); + printf("\n"); + + if (iflags & ITOffline) + printf("attachFlags: offline\n"); + else if (iflags & ITBusy) + printf("attachFlags: busy\n"); + else if (iflags & ITReadOnly) + printf("attachFlags: readonly\n"); + else if (iflags & ITCreate) + printf("attachFlags: create\n"); + else if (iflags & ITCreateVolID) + printf("attachFlags: createvolid\n"); + else + printf("attachFlags: %u\n", trans->iflags); + + memset(&part, 0, sizeof(part)); + part.id = trans->partition; + kafs_sprint_partition(ctx, &part, pbuf, sizeof(pbuf)), + printf("volume: %u partition %s procedure %s", + trans->volid, pbuf, trans->last_proc_name); + printf("packetRead: %u", trans->read_next); + printf(" lastReceiveTime: %lu", trans->last_receive_time); + printf(" packetSend: %u", trans->transmit_next); + printf("\n"); + printf(" lastSendTime: %lu\n", trans->last_send_time); + printf("--------------------------------------------\n"); + } + + ret = true; + +out_result: + clear_kafs_vol_transaction_info_list(&transactions); +out: + kafs_close_volserver(ctx, server); + _leave(" = %u", ret); + return ret; +} -- 2.50.1