]> www.infradead.org Git - users/dhowells/kafs-utils.git/commitdiff
cmd: Implement "vos status"
authorDavid Howells <dhowells@redhat.com>
Mon, 6 Jul 2020 09:37:26 +0000 (10:37 +0100)
committerDavid Howells <dhowells@redhat.com>
Fri, 5 May 2023 09:05:31 +0000 (10:05 +0100)
Signed-off-by: David Howells <dhowells@redhat.com>
kafs/Makefile
kafs/arg_parse.h
kafs/arg_resolve.c [new file with mode: 0644]
kafs/display.c
kafs/display.h
kafs/vos_status.c [new file with mode: 0644]

index 5d839b363858fe9779e186d51f23406b3d8237c9..ad08be58ccdb0d6439b59350058280654a8aa32e 100644 (file)
@@ -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))
index 7df6f36721fb482af549a4f7065ba832d0ad2b49..34edaf8ed7090449346d798dc9b9e80503cc2318 100644 (file)
@@ -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 (file)
index 0000000..6fef375
--- /dev/null
@@ -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 <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <kafs/cellserv.h>
+#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);
+}
index aa01befa37239a9c471f46d11be5d48c3992c4dc..d9ba95ecbff57cb07ea52345806060b84972649c 100644 (file)
 #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
index 40f450f143b807d97a59c8f8dc3ba2b3dd39406b..20e5c350e0f39cec9e004b901e97387c2ce1a016 100644 (file)
@@ -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 (file)
index 0000000..edb23cd
--- /dev/null
@@ -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 <stdio.h>
+#include <string.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#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 <machine name>"
+ * ARG: "[-cell <cell name>]"
+ * 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;
+}