kafs.c \
arg_completion.c \
arg_parse.c \
+ arg_resolve.c \
display.c \
display_error.c \
display_vol.c \
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))
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
*/
--- /dev/null
+/* 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);
+}
#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
/*
* 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);
--- /dev/null
+/* 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;
+}