lctl-nodemap_del_range.8 \
lctl-nodemap-del.8 \
lctl-nodemap_del.8 \
+ lctl-nodemap-info.8 \
+ lctl-nodemap_info.8 \
lctl-nodemap-modify.8 \
lctl-nodemap_modify.8 \
lctl-nodemap-set-fileset.8 \
--- /dev/null
+.TH LCTL-NODEMAP_INFO 8 2025-03-10 Lustre "Lustre Configuration Utilities"
+.SH NAME
+lctl-nodemap_info \- present information about nodemaps
+.SH SYNOPSIS
+.SY "lctl nodemap_info"
+or
+.SY "lctl nodemap info"
+.BI --name " NODEMAP_NAME"
+.BI --property " PROPERTY_NAME"
+.B --list
+.YS
+.SH DESCRIPTION
+.B nodemap_info
+presents information about the defined nodemaps. This includes whether nodemaps
+are active, a list of the defined nodemaps, and the values of specific nodemap
+parameters. If no options are specified, all nodemaps and their properties
+are presented.
+.SH OPTIONS
+.TP
+.BI --name " NODEMAP_NAME"
+Specifies the name of the nodemap to present information about. If not
+specified, all nodemaps are presented. This option can be used in conjunction
+with the
+.B --property
+option to present the value of a specific property for a specific nodemap.
+.TP
+.BI --property " PROPERTY_NAME"
+Specifies the name of the property to present the value of. If not specified,
+all properties are presented. This option can be used in conjunction with the
+.B --name
+option to present the value of a specific property for a specific nodemap.
+.TP
+.B --list
+Presents the global nodemap state and Lists all defined nodemaps and available
+nodemap properties.
+.SH EXAMPLES
+List general nodemap information:
+.EX
+.B # lctl nodemap_info --list
+.EE
+.PP
+List the values of all properties for all nodemaps:
+.EX
+.B # lctl nodemap_info
+.EE
+.PP
+List the values for all properties for the "remote" nodemap:
+.EX
+.B # lctl nodemap_info --name remote
+.EE
+.PP
+List the value of the specific "ranges" property for the "remote" nodemap:
+.EX
+.B # lctl nodemap_info --name remote --property ranges
+.EE
+.PP
+List the value of the specific "ranges" property for all nodemaps:
+.EX
+.B # lctl nodemap_info --property ranges
+.EE
+.SH AVAILABILITY
+.B lctl nodemap_info
+is part of the
+.BR lustre (7)
+filesystem package since release 2.16.52
+.\" Added in commit v2.16.52_105_g03b41c3
+.SH SEE ALSO
+.BR lustre (7),
+.BR lctl-nodemap-activate (8),
+.BR lctl-nodemap-add (8),
+.BR lctl-nodemap-add-idmap (8),
+.BR lctl-nodemap-add-range (8),
+.BR lctl-nodemap-del (8),
+.BR lctl-nodemap-del-idmap (8),
+.BR lctl-nodemap-del-range (8),
+.BR lctl-nodemap-modify (8),
+.BR lctl-nodemap-set-fileset (8)
--- /dev/null
+.so man8/lctl-nodemap-info.8
nodemap_activate="nodemap activate"
nodemap_add="nodemap add"
nodemap_del="nodemap del"
+ nodemap_info="nodemap info"
nodemap_modify="nodemap modify"
nodemap_add_range="nodemap add_range"
nodemap_del_range="nodemap del_range"
nodemap_activate="nodemap_activate"
nodemap_add="nodemap_add"
nodemap_del="nodemap_del"
+ nodemap_info="nodemap_info"
nodemap_modify="nodemap_modify"
nodemap_add_range="nodemap_add_range"
nodemap_del_range="nodemap_del_range"
wait_nm_sync test25 id
- do_facet mgs $LCTL nodemap_info > $tmpfile
- do_facet mds $LCTL nodemap_info > $tmpfile2
+ do_facet mgs $LCTL $nodemap_info > $tmpfile
+ do_facet mds $LCTL $nodemap_info > $tmpfile2
if ! $SHARED_KEY; then
# will conflict with SK's nodemaps
zconf_umount_clients $CLIENTS $MOUNT ||
error "unable to umount clients $CLIENTS"
- do_facet mgs $LCTL nodemap_info > $tmpfile3
+ do_facet mgs $LCTL $nodemap_info > $tmpfile3
diff -q $tmpfile3 $tmpfile >& /dev/null ||
- error "nodemap_info diff on MGS after remount"
+ error "$nodemap_info diff on MGS after remount"
- do_facet mds $LCTL nodemap_info > $tmpfile4
+ do_facet mds $LCTL $nodemap_info > $tmpfile4
diff -q $tmpfile4 $tmpfile2 >& /dev/null ||
- error "nodemap_info diff on MDS after remount"
+ error "$nodemap_info diff on MDS after remount"
# cleanup nodemap
do_facet mgs $LCTL nodemap_del test25 ||
}
run_test 25 "test save and reload nodemap config"
+test_25a() {
+ local nm="c0"
+ local info_dump=$(mktemp)
+ local param_dump=$(mktemp)
+
+ (( $MGS_VERSION >= $(version_code 2.16.52) )) ||
+ skip "Need MGS >= 2.16.52 for updated nodemap_info"
+
+ nodemap_test_setup
+ stack_trap nodemap_test_cleanup EXIT
+
+ if $SHARED_KEY; then
+ export SK_UNIQUE_NM=true
+ fi
+
+ # fill some more values on nodemap
+ # We test only local here, so no wait_nm_sync required
+ do_facet mgs $LCTL nodemap_add_offset --name $nm \
+ --offset 1000000 --limit 100000 ||
+ error "cannot set offset $nm"
+ do_facet mgs $LCTL nodemap_set_fileset --name $nm \
+ --fileset "/somedir" ||
+ error "unable to add fileset info"
+
+ # full nodemap dump
+ do_facet mgs $LCTL $nodemap_info > $info_dump ||
+ error "$nodemap_info failed"
+ stack_trap "rm -f $info_dump" EXIT
+ do_facet mgs $LCTL get_param -R nodemap > $param_dump
+ stack_trap "rm -f $param_dump" EXIT
+
+ diff -q $info_dump $param_dump >& /dev/null ||
+ error "$nodemap_info differs from get_param output"
+
+ # nodemap dump for $nm
+ do_facet mgs $LCTL $nodemap_info --name $nm > $info_dump ||
+ error "$nodemap_info failed"
+ do_facet mgs $LCTL get_param -R nodemap.$nm > $param_dump
+
+ diff -q $info_dump $param_dump >& /dev/null ||
+ error "$nodemap_info differs from get_param output"
+
+ # nodemap dump for $nm and property fileset
+ do_facet mgs $LCTL $nodemap_info --name $nm \
+ --property fileset > $info_dump ||
+ error "$nodemap_info failed"
+ do_facet mgs $LCTL get_param nodemap.$nm.fileset > $param_dump
+
+ diff -q $info_dump $param_dump >& /dev/null ||
+ error "$nodemap_info differs from get_param output"
+
+ # cross nodemap dump for property ranges
+ do_facet mgs $LCTL $nodemap_info --property ranges > $info_dump ||
+ error "$nodemap_info failed"
+ do_facet mgs $LCTL get_param -R nodemap.*.ranges > $param_dump
+
+ # back to non-nodemap setup
+ if $SHARED_KEY; then
+ export SK_UNIQUE_NM=false
+ fi
+}
+run_test 25a "test nodemap info values"
+
test_26() {
nodemap_version_check || return 0
"usage: nodemap test_id --nid NID --idtype {uid|gid|projid} --id ID"},
{.pc_name = "info", .pc_func = jt_nodemap_info,
.pc_help = "print nodemap information\n"
- "usage: nodemap info {list|nodemap_name|all}"},
+ "usage: nodemap info --list --name NODEMAP_NAME --property PROPERTY_NAME"},
{.pc_help = NULL }
};
JT_SUBCMD(nodemap);
"Usage: nodemap_test_id --nid NID --idtype ID_TYPE --id ID"},
{"nodemap_info", jt_nodemap_info, 0,
"print nodemap information\n"
- "Usage: nodemap_info [list|nodemap_name|all]"},
+ "usage: nodemap_info --list --name NODEMAP_NAME --property PROPERTY_NAME"},
{"nodemap", jt_nodemap, nodemap_cmdlist, ""},
/* Changelog commands */
PT_CONFPARAM
};
-#ifdef HAVE_SERVER_SUPPORT
-/**
- * Output information about nodemaps.
- * \param argc number of args
- * \param argv[] variable string arguments
- *
- * [list|nodemap_name|all] \a list will list all nodemaps (default).
- * Specifying a \a nodemap_name will
- * display info about that specific nodemap.
- * \a all will display info for all nodemaps.
- * \retval 0 on success
- */
-int jt_nodemap_info(int argc, char **argv)
-{
- const char usage_str[] = "usage: nodemap_info [list|nodemap_name|all]\n";
- struct param_opts popt;
- int rc = 0;
-
- memset(&popt, 0, sizeof(popt));
- popt.po_show_name = 1;
-
- if (argc > 2) {
- fprintf(stderr, usage_str);
- return -1;
- }
-
- if (argc == 1 || strcmp("list", argv[1]) == 0) {
- popt.po_only_dir = 1;
- rc = jt_lcfg_listparam(3, (char*[3])
- { "list_param", "-D", "nodemap/*" });
- } else if (strcmp("all", argv[1]) == 0) {
- rc = jt_lcfg_getparam(3, (char*[3])
- { "get_param", "-N", "nodemap/*/*" });
- } else {
- char pattern[PATH_MAX];
-
- snprintf(pattern, sizeof(pattern), "nodemap/%s/*", argv[1]);
- rc = jt_lcfg_getparam(3, (char*[3])
- { "get_param", "-N", pattern });
- if (rc == -ESRCH)
- fprintf(stderr,
- "error: nodemap_info: cannot find nodemap %s\n",
- argv[1]);
- }
- return rc;
-}
-#endif
-
#define PS_NONE 0
#define PS_PARAM_FOUND 1
#define PS_PARAM_SET 2
#include <unistd.h>
#include <limits.h>
#include "obdctl.h"
+#include "lstddef.h"
#include "lustreapi_internal.h"
#include <libcfs/util/list.h>
#include <libcfs/util/ioctl.h>
}
/**
+ * Output information about nodemaps.
+ * \param argc number of args
+ * \param argv[] variable string arguments
+ *
+ *
+ * --name nodemap to present info about
+ * --property nodemap property to present
+ * --list list nodemap state, all nodemaps, and properties
+ *
+ * deprecated positional parameters:
+ * [list|nodemap_name|all] \a list will list all nodemaps (default).
+ * Specifying a \a nodemap_name will
+ * display info about that specific nodemap.
+ * \a all will display info for all nodemaps.
+ * \retval 0 on success
+ */
+int jt_nodemap_info(int argc, char **argv)
+{
+ char *nodemap_name = NULL;
+ char *property = NULL;
+ bool list = false;
+ char pattern[PATH_MAX];
+ bool is_active = false;
+ char *active_str = NULL;
+ size_t buflen;
+ glob_t param;
+ int c, i;
+ int rc = 0;
+
+ struct nodemap_info_param_desc {
+ const char *param;
+ const char *desc;
+ };
+
+ static const struct nodemap_info_param_desc param_desc[] = {
+ { "admin_nodemap", "root is not squashed on policy group" },
+ { "audit_mode",
+ "client can record FS access events to the Changelogs" },
+ { "deny_mount", "disable client mounts" },
+ { "deny_unknown", "deny access for unknown (squashed) users" },
+ { "exports",
+ "list of client connections (NIDs) for this nodemap" },
+ { "fileset", "fileset restrictions for this nodemap" },
+ { "forbid_encryption",
+ "prevent clients from using encryption" },
+ { "id", "unique identifier for this nodemap" },
+ { "idmap", "identity mapping rules for UID/GID/PROJID translation" },
+ { "map_mode", "identity mapping mode" },
+ { "offset", "idmap range offset for identity translation" },
+ { "ranges", "NID ranges assigned to this nodemap" },
+ { "rbac", "role-based admin control settings" },
+ { "readonly_mount", "force clients to mount read-only" },
+ { "sepol", "SELinux policy for this nodemap" },
+ { "squash_gid", "GID for unmapped users" },
+ { "squash_projid", "project ID for unmapped projects" },
+ { "squash_uid", "UID for unmapped users" },
+ { "trusted_nodemap",
+ "accept client identities without mapping" },
+ };
+
+ static struct option long_opts[] = {
+ { .val = 'l', .name = "list", .has_arg = no_argument },
+ { .val = 'p', .name = "property", .has_arg = required_argument },
+ { .val = 'n', .name = "name", .has_arg = required_argument },
+ { .val = 'h', .name = "help", .has_arg = no_argument },
+ { .name = NULL }
+ };
+
+ while ((c = getopt_long(argc, argv, "hln:p:", long_opts, NULL)) != -1) {
+ switch (c) {
+ case 'n':
+ nodemap_name = optarg;
+ break;
+ case 'p':
+ property = optarg;
+ break;
+ case 'l':
+ list = true;
+ break;
+ case 'h':
+ case '?':
+ default:
+ return CMD_HELP;
+ }
+ }
+
+ if ((nodemap_name || property || list) && optind < argc) {
+ fprintf(stderr,
+ "error: using both positional and named arguments is not allowed\n");
+ return CMD_HELP;
+ }
+
+ if ((nodemap_name || property) && list) {
+ fprintf(stderr,
+ "error: using both --list and --name or --property is not allowed\n");
+ return CMD_HELP;
+ }
+
+ /* Legacy positional arguments are handled here */
+ if (optind < argc) {
+#if LUSTRE_VERSION_CODE > OBD_OCD_VERSION(2, 17, 53, 0)
+ fprintf(stdout,
+ "Positional parameters are deprecated. Please use --name and --property instead.\n");
+#endif
+ if ((argc - optind) > 1) {
+ fprintf(stderr,
+ "error: only one positional parameter allowed\n");
+ return CMD_HELP;
+ }
+
+ if (strcmp("list", argv[optind]) == 0) {
+ rc = snprintf(pattern, sizeof(pattern), "nodemap.*");
+ if (rc < 0 || rc >= sizeof(pattern)) {
+ fprintf(stderr,
+ "error: setting list pattern failed\n");
+ return -EINVAL;
+ }
+
+ rc = jt_lcfg_listparam(3, (char * [3]) { "list_param",
+ "-D",
+ pattern });
+ return rc;
+ }
+
+ if (strcmp("all", argv[optind]) == 0) {
+ rc = snprintf(pattern, sizeof(pattern), "nodemap.*.*");
+ } else {
+ rc = snprintf(pattern, sizeof(pattern), "nodemap.%s.*",
+ argv[optind]);
+ }
+
+ if (rc < 0 || rc >= sizeof(pattern)) {
+ fprintf(stderr,
+ "error: get_param pattern too long.\n");
+ return -EINVAL;
+ }
+
+ rc = jt_lcfg_getparam(3, (char * [3]) { "get_param", "-N",
+ pattern });
+ if (rc == -ENOENT) {
+ fprintf(stderr,
+ "error: nodemap_info: cannot find nodemap or property %s\n",
+ argv[optind]);
+ }
+ return rc;
+ }
+
+ /* Handle -l argument here */
+ if (list) {
+ /* Get nodemap active state */
+ rc = cfs_get_param_paths(¶m, "nodemap/active");
+ if (rc) {
+ fprintf(stderr,
+ "error: cannot get nodemap active param: %s\n",
+ strerror(errno));
+ return rc;
+ }
+
+ rc = llapi_param_get_value(param.gl_pathv[0], &active_str,
+ &buflen);
+ if (rc || !active_str) {
+ fprintf(stderr,
+ "error: cannot get nodemap active state\n");
+ cfs_free_param_data(¶m);
+ return rc;
+ }
+
+ is_active = (active_str[0] == '1');
+ printf("Global nodemap state:\n\t%s\n",
+ is_active ? "active" : "inactive");
+ free(active_str);
+ cfs_free_param_data(¶m);
+
+ /* list all nodemaps */
+ printf("\nDefined nodemaps:\n");
+ rc = cfs_get_param_paths(¶m, "nodemap/*");
+ if (rc) {
+ fprintf(stderr, "error: cannot get nodemap list: %s\n",
+ strerror(errno));
+ return rc;
+ }
+
+ for (i = 0; i < param.gl_pathc; i++) {
+ /* move to last '/' to skip nodemap prefix */
+ nodemap_name = strrchr(param.gl_pathv[i], '/');
+ /* skip '/' and check nodemap isn't empty or "active" */
+ if (nodemap_name && *(++nodemap_name) &&
+ strcmp(nodemap_name, "active") != 0)
+ printf("\t%s\n", nodemap_name);
+ }
+ cfs_free_param_data(¶m);
+
+ /* list all nodemap parameters */
+ printf("\nAvailable nodemap parameters:\n");
+ for (i = 0; i < ARRAY_SIZE(param_desc); i++) {
+ printf("\t%-20s %s\n", param_desc[i].param,
+ param_desc[i].desc);
+ }
+ return rc;
+ }
+
+ /* Handle -n and -p arguments and default case here */
+ if (nodemap_name && property) {
+ rc = snprintf(pattern, sizeof(pattern), "nodemap.%s.%s",
+ nodemap_name, property);
+ } else if (nodemap_name) {
+ rc = snprintf(pattern, sizeof(pattern), "nodemap.%s.*",
+ nodemap_name);
+ } else if (property) {
+ rc = snprintf(pattern, sizeof(pattern), "nodemap.*.%s",
+ property);
+ } else {
+ rc = snprintf(pattern, sizeof(pattern), "nodemap.active");
+ if (rc < 0 || rc >= sizeof(pattern)) {
+ fprintf(stderr,
+ "error: setting active pattern failed\n");
+ return -EINVAL;
+ }
+
+ rc = jt_lcfg_getparam(2, (char * [2]) { "get_param",
+ pattern });
+ if (rc)
+ return rc;
+
+ rc = snprintf(pattern, sizeof(pattern), "nodemap.*.*");
+ }
+
+ if (rc < 0 || rc >= sizeof(pattern)) {
+ fprintf(stderr, "error: nodemap name or property too long\n");
+ return -EINVAL;
+ }
+
+ rc = jt_lcfg_getparam(2, (char * [2]) { "get_param", pattern });
+
+ return rc;
+}
+
+/**
* Add a nodemap's UID/GID/PROJID offset
*
* \param argc number of args