Whamcloud - gitweb
LU-17431 nodemap: allow modifying properties of a dynamic nm 13/54513/19
authorSebastien Buisson <sbuisson@ddn.com>
Thu, 21 Mar 2024 09:13:43 +0000 (10:13 +0100)
committerOleg Drokin <green@whamcloud.com>
Sun, 2 Feb 2025 06:23:05 +0000 (06:23 +0000)
Modify properties of a dynamic nodemap, by sending the appropriate
ioctl to the MDS or OSS device.
On kernel side, we need to allow handling a nodemap even if the
nodemap config file is not accessible (i.e. we are not on the
MGS). This dynamic nodemap is not stored on disk.

Signed-off-by: Sebastien Buisson <sbuisson@ddn.com>
Change-Id: I7253e51ecb8869c2d2ac268926c1c907005ec4a7
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/54513
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Marc Vef <mvef@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/tests/sanity-sec.sh
lustre/utils/lctl.c
lustre/utils/obd.c

index 3b83ea1..16cfad7 100755 (executable)
@@ -6794,6 +6794,9 @@ test_72() {
        local endnid=1.1.1.100@tcp
        local clid=500
        local fsid=1000
+       local properties="audit_mode deny_unknown forbid_encryption \
+                         readonly_mount"
+       local sepol="1:mls:31:40afb76d077c441b69af58cccaaa2ca63641ed6e21b0a887dc21a684f508b78f"
        local val
 
        (( OST1_VERSION >= $(version_code 2.15.64) )) ||
@@ -6802,6 +6805,13 @@ test_72() {
        [[ "$(facet_active_host mgs)" != "$(facet_active_host ost1)" ]] ||
                skip "Need servers on different hosts"
 
+       activedefault=$(do_facet mgs $LCTL get_param -n nodemap.active)
+       if [[ "$activedefault" != "1" ]]; then
+               do_facet mgs $LCTL nodemap_activate 1
+               wait_nm_sync active
+               stack_trap cleanup_active EXIT
+       fi
+
        do_facet mgs $LCTL nodemap_add $mgsnm ||
                error "adding $mgsnm on MGS failed"
        stack_trap "do_facet mgs $LCTL nodemap_del $mgsnm" EXIT
@@ -6810,7 +6820,7 @@ test_72() {
        do_facet mgs $LCTL nodemap_add_idmap --name $mgsnm --idtype uid \
                --idmap $mgsclid:$mgsfsid ||
                error "add_idmap for $mgsnm on MGS failed"
-       wait_nm_sync $mgsnm idmap '' inactive
+       wait_nm_sync $mgsnm idmap
 
        stack_trap "do_facet ost1 $LCTL nodemap_del $nm || true" EXIT
        do_facet ost1 $LCTL nodemap_add $nm &&
@@ -6849,6 +6859,74 @@ test_72() {
                error "dynamic nodemap wrong fs id $val"
        fi
 
+       for prop in $properties; do
+               do_facet ost1 $LCTL nodemap_modify --name $nm \
+                       --property $prop --value 1 ||
+                               error "dynamic modify of $prop failed"
+               val=$(do_facet ost1 $LCTL get_param -n nodemap.$nm.$prop)
+               [[ "x$val" == "x1" ]] || error "incorrect $prop $val"
+       done
+       prop=admin
+       do_facet ost1 $LCTL nodemap_modify --name $nm \
+               --property $prop --value 1 ||
+                       error "dynamic modify of $prop failed"
+       val=$(do_facet ost1 $LCTL get_param -n nodemap.$nm.admin_nodemap)
+       [[ "x$val" == "x1" ]] || error "incorrect $prop $val"
+       prop=trusted
+       do_facet ost1 $LCTL nodemap_modify --name $nm \
+               --property $prop --value 0 ||
+                       error "dynamic modify of $prop failed"
+       val=$(do_facet ost1 $LCTL get_param -n nodemap.$nm.trusted_nodemap)
+       [[ "x$val" == "x0" ]] || error "incorrect $prop $val"
+       prop=map_mode
+       do_facet ost1 $LCTL nodemap_modify --name $nm \
+               --property $prop --value uid ||
+                       error "dynamic modify of $prop failed"
+       val=$(do_facet ost1 $LCTL get_param -n nodemap.$nm.$prop)
+       [[ "x$val" == "xuid" ]] || error "incorrect $prop $val"
+       prop=rbac
+       do_facet ost1 $LCTL nodemap_modify --name $nm \
+               --property $prop --value file_perms ||
+                       error "dynamic modify of $prop failed"
+       val=$(do_facet ost1 $LCTL get_param -n nodemap.$nm.$prop)
+       [[ "x$val" == "xfile_perms" ]] || error "incorrect $prop $val"
+       prop=squash_uid
+       do_facet ost1 $LCTL nodemap_modify --name $nm \
+               --property $prop --value 77 ||
+                       error "dynamic modify of $prop failed"
+       val=$(do_facet ost1 $LCTL get_param -n nodemap.$nm.$prop)
+       [[ "x$val" == "x77" ]] || error "incorrect $prop $val"
+       prop=squash_gid
+       do_facet ost1 $LCTL nodemap_modify --name $nm \
+               --property $prop --value 77 ||
+                       error "dynamic modify of $prop failed"
+       val=$(do_facet ost1 $LCTL get_param -n nodemap.$nm.$prop)
+       [[ "x$val" == "x77" ]] || error "incorrect $prop $val"
+       prop=squash_projid
+       do_facet ost1 $LCTL nodemap_modify --name $nm \
+               --property $prop --value 77 ||
+                       error "dynamic modify of $prop failed"
+       val=$(do_facet ost1 $LCTL get_param -n nodemap.$nm.$prop)
+       [[ "x$val" == "x77" ]] || error "incorrect $prop $val"
+       prop=fileset
+       do_facet ost1 $LCTL nodemap_set_fileset --name $nm \
+               --fileset "/tmp" ||
+                       error "dynamic modify of $prop failed"
+       val=$(do_facet ost1 $LCTL get_param -n nodemap.$nm.$prop)
+       [[ "x$val" == "x/tmp" ]] || error "incorrect $prop $val"
+       prop=sepol
+       do_facet ost1 $LCTL nodemap_set_sepol --name $nm \
+               --sepol $sepol ||
+                       error "dynamic modify of $prop failed"
+       val=$(do_facet ost1 $LCTL get_param -n nodemap.$nm.$prop)
+       [[ "x$val" == "x$sepol" ]] || error "incorrect $prop $val"
+
+       val=$(do_facet ost1 $LCTL nodemap_test_id --nid $startnid \
+               --idtype uid --id $clid)
+       if [[ "x$val" != "x$fsid" ]]; then
+               error "dynamic test_id on server failed"
+       fi
+
        do_facet ost1 $LCTL nodemap_del_idmap --name $nm --idtype uid \
                --idmap $clid:$fsid ||
                        error "dynamic del_idmap on server failed"
@@ -6858,6 +6936,11 @@ test_72() {
                error "idmap should be empty, got $val"
        fi
 
+       val=$(do_facet ost1 $LCTL nodemap_test_nid $startnid)
+       if [[ "x$val" != "x$nm" ]]; then
+               error "dynamic test_nid on server failed"
+       fi
+
        do_facet ost1 $LCTL nodemap_del_range --name $nm --range $nids ||
                error "dynamic del_range on server failed"
        val=$(do_facet ost1 $LCTL get_param nodemap.$nm.ranges |
@@ -6883,6 +6966,9 @@ test_72() {
        do_facet ost1 $LCTL nodemap_del_idmap --name $mgsnm --idtype uid \
                --idmap $mgsclid:$mgsfsid &&
                        error "del_idmap $mgsnm on server should fail"
+       do_facet ost1 $LCTL nodemap_modify --name $mgsnm \
+               --property squash_projid --value 77 &&
+                       error "modify $mgsnm on server should fail"
        do_facet ost1 $LCTL nodemap_del $mgsnm &&
                error "nodemap del $mgsnm on server should fail"
        do_facet ost1 $LCTL get_param -R 'nodemap.*'
index 9e6c43f..b3277ad 100644 (file)
@@ -515,8 +515,8 @@ command_t cmdlist[] = {
         "delete a range from a nodemap\n"
         "usage: nodemap_del_range --name NODEMAP_NAME --range NID_RANGE"},
        {"nodemap_modify", jt_nodemap_modify, 0,
-        "modify a nodemap parameters\n"
-        "usage: nodemap_modify nodemap_name param value"},
+        "modify a nodemap parameter\n"
+        "usage: nodemap_modify --name NODEMAP_NAME --property PROPERTY_NAME --value VALUE"},
        {"nodemap_add_offset", jt_nodemap_add_offset, 0,
         "add an offset for UID/GID/PROJID mappings\n"
         "usage: nodemap_add_offset --name NODEMAP_NAME --offset OFFSET --limit LIMIT\n"},
@@ -531,14 +531,14 @@ command_t cmdlist[] = {
         "usage: nodemap_del_idmap --name NODEMAP_NAME --idtype ID_TYPE --idmap CLIENTID:FSID"},
        {"nodemap_set_fileset", jt_nodemap_set_fileset, 0,
         "set a fileset on a nodemap\n"
-        "usage: nodemap_set_fileset <fileset>"},
+        "usage: nodemap_set_fileset --name NODEMAP_NAME --fileset FILESET"},
        {"nodemap_set_sepol", jt_nodemap_set_sepol, 0,
         "set SELinux policy info on a nodemap\n"
-        "usage: nodemap_set_sepol <SELinux policy info>"},
+        "usage: nodemap_set_sepol --name NODEMAP_NAME --sepol SEPOL"},
        {"nodemap_test_nid", jt_nodemap_test_nid, 0,
-        "usage: nodemap_test_nid <nid>"},
+        "usage: nodemap_test_nid NID"},
        {"nodemap_test_id", jt_nodemap_test_id, 0,
-        "Usage: nodemap_test_id --nid <nid> --idtype [uid|gid] --id <id>"},
+        "Usage: nodemap_test_id --nid NID --idtype ID_TYPE --id ID"},
        {"nodemap_info", jt_nodemap_info, 0,
         "Usage: nodemap_info [list|nodemap_name|all]"},
 
index d7cfa0a..ccfb210 100644 (file)
@@ -4138,11 +4138,36 @@ del_usage:
  */
 int jt_nodemap_test_nid(int argc, char **argv)
 {
-       char    rawbuf[MAX_IOC_BUFLEN];
-       int     rc;
+       char rawbuf[MAX_IOC_BUFLEN];
+       char *nid = NULL;
+       int c, rc;
 
-       rc = nodemap_cmd(LCFG_NODEMAP_TEST_NID, false, &rawbuf, sizeof(rawbuf),
-                        argv[0], argv[1], NULL);
+       static struct option long_opts[] = {
+               { .val = 'h', .name = "help",    .has_arg = no_argument },
+               { .name = NULL } };
+
+       while ((c = getopt_long(argc, argv, "dh",
+                               long_opts, NULL)) != -1) {
+               switch (c) {
+               case 'h':
+               default:
+                       goto test_nid_usage;
+               }
+       }
+
+       if (optind < argc)
+               nid = argv[optind];
+
+       if (!nid) {
+               fprintf(stderr, "nodemap_test_nid: missing NID\n");
+test_nid_usage:
+               fprintf(stderr,
+                       "usage: nodemap_test_nid NID\n");
+               return -EINVAL;
+       }
+
+       rc = nodemap_cmd(LCFG_NODEMAP_TEST_NID, false, &rawbuf,
+                        sizeof(rawbuf), argv[0], nid, NULL);
        if (rc == 0)
                printf("%s\n", (char *)rawbuf);
 
@@ -4163,39 +4188,53 @@ int jt_nodemap_test_nid(int argc, char **argv)
  */
 int jt_nodemap_test_id(int argc, char **argv)
 {
-       char    rawbuf[MAX_IOC_BUFLEN];
-       char    *nidstr = NULL;
-       char    *idstr = NULL;
-       char    *typestr = NULL;
-       int     rc = 0;
-       int     c;
+       char rawbuf[MAX_IOC_BUFLEN];
+       char *nidstr = NULL;
+       char *idstr = NULL;
+       char *typestr = NULL;
+       int c, rc = 0;
 
        static struct option long_opts[] = {
+               { .val = 'h',   .name = "help", .has_arg = no_argument },
                { .val = 'i',   .name = "id",   .has_arg = required_argument },
                { .val = 'n',   .name = "nid",  .has_arg = required_argument },
                { .val = 't',   .name = "idtype",
                                                .has_arg = required_argument },
                { .name = NULL } };
 
-       while ((c = getopt_long(argc, argv, "n:t:i:",
+       while ((c = getopt_long(argc, argv, "hi:n:t:",
                                long_opts, NULL)) != -1) {
                switch (c) {
+               case 'i':
+                       idstr = optarg;
+                       break;
                case 'n':
                        nidstr = optarg;
                        break;
                case 't':
                        typestr = optarg;
                        break;
-               case 'i':
-                       idstr = optarg;
-                       break;
+               case 'h':
+               default:
+                       goto test_id_usage;
                }
        }
 
-       if (!nidstr || !typestr || !idstr) {
+       if (!nidstr) {
+               fprintf(stderr, "nodemap_test_id: missing NID\n");
+test_id_usage:
                fprintf(stderr,
-                       "usage: nodemap_test_id --nid <nid> --idtype [uid|gid] --id <id>\n");
-               return -1;
+                       "usage: nodemap_test_id --nid NID --idtype IDTYPE --id ID\n");
+               return -EINVAL;
+       }
+       if (!typestr) {
+               fprintf(stderr,
+                       "nodemap_test_id: missing idtype, must be one of uid, gid, projid\n");
+               goto test_id_usage;
+       }
+       if (!idstr) {
+               fprintf(stderr, "nodemap_test_id: missing id\n");
+               goto test_id_usage;
        }
 
        rc = nodemap_cmd(LCFG_NODEMAP_TEST_ID, false, &rawbuf, sizeof(rawbuf),
@@ -4404,30 +4443,39 @@ int jt_nodemap_set_fileset(int argc, char **argv)
 {
        char *nodemap_name = NULL;
        char *fileset_name = NULL;
-       int   rc = 0;
-       int   c;
+       int c, rc = 0;
 
        static struct option long_opts[] = {
        { .val = 'f',   .name = "fileset",      .has_arg = required_argument },
+       { .val = 'h',   .name = "help",         .has_arg = no_argument },
        { .val = 'n',   .name = "name",         .has_arg = required_argument },
        { .name = NULL } };
 
-       while ((c = getopt_long(argc, argv, "n:f:",
+       while ((c = getopt_long(argc, argv, "f:hn:",
                                long_opts, NULL)) != -1) {
                switch (c) {
-               case 'n':
-                       nodemap_name = optarg;
-                       break;
                case 'f':
                        fileset_name = optarg;
                        break;
+               case 'n':
+                       nodemap_name = optarg;
+                       break;
+               case 'h':
+               default:
+                       goto set_fileset_usage;
                }
        }
 
-       if (!nodemap_name || !fileset_name) {
+       if (!nodemap_name) {
+               fprintf(stderr, "nodemap_set_fileset: missing nodemap name\n");
+set_fileset_usage:
                fprintf(stderr,
-                       "usage: nodemap_set_fileset --name <name> --fileset <fileset>\n");
-               return -1;
+                       "usage: nodemap_set_fileset --name NODEMAP_NAME --fileset FILESET\n");
+               return -EINVAL;
+       }
+       if (!fileset_name) {
+               fprintf(stderr, "nodemap_set_fileset: missing NID range\n");
+               goto set_fileset_usage;
        }
 
        rc = nodemap_cmd(LCFG_NODEMAP_SET_FILESET, false, NULL, 0, argv[0],
@@ -4457,11 +4505,15 @@ int jt_nodemap_set_sepol(int argc, char **argv)
 {
        char *nodemap_name = NULL;
        char *sepol = NULL;
-       int   rc = 0;
-       int   c;
+       int c, rc = 0;
 
        static struct option long_options[] = {
                {
+                       .name           = "help",
+                       .has_arg        = no_argument,
+                       .val            = 'h',
+               },
+               {
                        .name           = "name",
                        .has_arg        = required_argument,
                        .val            = 'n',
@@ -4476,7 +4528,7 @@ int jt_nodemap_set_sepol(int argc, char **argv)
                }
        };
 
-       while ((c = getopt_long(argc, argv, "n:s:",
+       while ((c = getopt_long(argc, argv, "hn:s:",
                                long_options, NULL)) != -1) {
                switch (c) {
                case 'n':
@@ -4485,13 +4537,22 @@ int jt_nodemap_set_sepol(int argc, char **argv)
                case 's':
                        sepol = optarg;
                        break;
+               case 'h':
+               default:
+                       goto set_sepol_usage;
                }
        }
 
-       if (!nodemap_name || !sepol) {
+       if (!nodemap_name) {
+               fprintf(stderr, "nodemap_set_sepol: missing nodemap name\n");
+set_sepol_usage:
                fprintf(stderr,
-                       "usage: nodemap_set_sepol --name <name> --sepol <sepol>\n");
-               return -1;
+                       "usage: nodemap_set_sepol --name NODEMAP_NAME --sepol SEPOL\n");
+               return -EINVAL;
+       }
+       if (!sepol) {
+               fprintf(stderr, "nodemap_set_sepol: missing sepol\n");
+               goto set_sepol_usage;
        }
 
        rc = nodemap_cmd(LCFG_NODEMAP_SET_SEPOL, false, NULL, 0, argv[0],
@@ -4521,20 +4582,20 @@ int jt_nodemap_set_sepol(int argc, char **argv)
  */
 int jt_nodemap_modify(int argc, char **argv)
 {
-       int                     c;
-       int                     rc = 0;
        enum lcfg_command_type  cmd = 0;
-       char                    *nodemap_name = NULL;
-       char                    *param = NULL;
-       char                    *value = NULL;
+       char *nodemap_name = NULL;
+       char *param = NULL;
+       char *value = NULL;
+       int c, rc = 0;
 
        static struct option long_opts[] = {
+       { .val = 'h',   .name = "help",         .has_arg = no_argument },
        { .val = 'n',   .name = "name",         .has_arg = required_argument },
        { .val = 'p',   .name = "property",     .has_arg = required_argument },
        { .val = 'v',   .name = "value",        .has_arg = required_argument },
        { .name = NULL } };
 
-       while ((c = getopt_long(argc, argv, "n:p:v:",
+       while ((c = getopt_long(argc, argv, "hn:p:v:",
                                long_opts, NULL)) != -1) {
                switch (c) {
                case 'n':
@@ -4546,15 +4607,29 @@ int jt_nodemap_modify(int argc, char **argv)
                case 'v':
                        value = optarg;
                        break;
+               case 'h':
+               default:
+                       goto modify_usage;
                }
        }
 
-       if (!nodemap_name || !param || !value) {
+       if (!nodemap_name) {
+               fprintf(stderr, "nodemap_modify: missing nodemap name\n");
+modify_usage:
                fprintf(stderr,
-                       "usage: nodemap_modify --name <nodemap_name> --property <property_name> --value <value>\n");
+                       "usage: %s --name NODEMAP_NAME --property PROPERTY_NAME --value VALUE\n",
+                       argv[0]);
                fprintf(stderr,
                        "valid properties: admin trusted map_mode squash_uid squash_gid squash_projid deny_unknown audit_mode forbid_encryption readonly_mount rbac\n");
-               return -1;
+               return -EINVAL;
+       }
+       if (!param) {
+               fprintf(stderr, "nodemap_modify: missing property name\n");
+               goto modify_usage;
+       }
+       if (!value) {
+               fprintf(stderr, "nodemap_modify: missing value for property\n");
+               goto modify_usage;
        }
 
        if (strcmp("admin", param) == 0) {
@@ -4581,9 +4656,9 @@ int jt_nodemap_modify(int argc, char **argv)
                cmd = LCFG_NODEMAP_RBAC;
        } else {
                fprintf(stderr,
-                       "error: %s: nodemap_modify invalid subcommand: %s\n",
+                       "error: %s: nodemap_modify invalid property: %s\n",
                        jt_cmdname(argv[0]), param);
-               return -1;
+               goto modify_usage;
        }
 
        rc = nodemap_cmd(cmd, false, NULL, 0, argv[0], nodemap_name, param,