]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: create file system with specific ID 42900/head
authorRamana Raja <rraja@redhat.com>
Mon, 28 Jun 2021 23:39:10 +0000 (19:39 -0400)
committerRamana Raja <rraja@redhat.com>
Tue, 24 Aug 2021 04:24:10 +0000 (00:24 -0400)
File system will need to be recreated when monitor databases are lost
and rebuilt. Some applications (e.g., CSI) expect that the recovered
file system have the same ID as before. Allow creating a file system
with a specific ID to help in such scenarios. This can now be done by
the `fs new` command using the argument 'fscid' and 'force' flag.
Newer file systems will no longer have increasing IDs as a corollary.

Fixes: https://tracker.ceph.com/issues/51340
Signed-off-by: Ramana Raja <rraja@redhat.com>
(cherry picked from commit a0a8ba5087f0b82588860cda188dfdb48a964771)

Conflicts:
qa/tasks/cephfs/test_admin.py
        fixed conflicts due tests reorder in master

PendingReleaseNotes
doc/cephfs/administration.rst
qa/tasks/cephfs/test_admin.py
src/mds/FSMap.cc
src/mds/FSMap.h
src/mon/FSCommands.cc
src/mon/MonCommands.h

index a775bc5668d02d950aa311d913e2b64da0d7e2f4..7a9a2cf9c6686f0d82067dff0110a2f06c5ae62e 100644 (file)
   If you want to return back the old behavior add 'ssl_options=' (empty) to
   ``rgw frontends`` configuration.
 
+* fs: A file system can be created with a specific ID ("fscid"). This is useful
+  in certain recovery scenarios, e.g., monitor database lost and rebuilt, and
+  the restored file system is expected to have the same ID as before.
+
 >=16.0.0
 --------
 
index c53161313c9bd322514ae2fd094775c468f836e0..ac238535890a1e0e1b046ed9b52b3e71cb44d0f0 100644 (file)
@@ -379,3 +379,14 @@ This removes a rank from the failed set.
 
 This command resets the file system state to defaults, except for the name and
 pools. Non-zero ranks are saved in the stopped set.
+
+
+::
+
+    fs new <file system name> <metadata pool name> <data pool name> --fscid <fscid> --force
+
+This command creates a file system with a specific **fscid** (file system cluster ID).
+You may want to do this when an application expects the file system's ID to be
+stable after it has been recovered, e.g., after monitor databases are lost and
+rebuilt. Consequently, file system IDs don't always keep increasing with newer
+file systems.
index eebdee165ef2eddf98df7bbd7487e6ee0e039819..876be69290bc43f277291168b339378e56d6801e 100644 (file)
@@ -21,7 +21,7 @@ class TestAdminCommands(CephFSTestCase):
     """
 
     CLIENTS_REQUIRED = 1
-    MDSS_REQUIRED = 1
+    MDSS_REQUIRED = 3
 
     def test_fsnames_can_only_by_goodchars(self):
         n = 'test_fsnames_can_only_by_goodchars'
@@ -198,6 +198,72 @@ class TestAdminCommands(CephFSTestCase):
             self._check_pool_application_metadata_key_value(
                 pool_names[i], 'cephfs', keys[i], fs_name)
 
+    def test_fs_new_with_specific_id(self):
+        """
+        That a file system can be created with a specific ID.
+        """
+        fs_name = "test_fs_specific_id"
+        fscid = 100
+        keys = ['metadata', 'data']
+        pool_names = [fs_name+'-'+key for key in keys]
+        for p in pool_names:
+            self.run_cluster_cmd(f'osd pool create {p}')
+        self.run_cluster_cmd(f'fs new {fs_name} {pool_names[0]} {pool_names[1]} --fscid  {fscid} --force')
+        self.fs.status().get_fsmap(fscid)
+        for i in range(2):
+            self._check_pool_application_metadata_key_value(pool_names[i], 'cephfs', keys[i], fs_name)
+
+    def test_fs_new_with_specific_id_idempotency(self):
+        """
+        That command to create file system with specific ID is idempotent.
+        """
+        fs_name = "test_fs_specific_id"
+        fscid = 100
+        keys = ['metadata', 'data']
+        pool_names = [fs_name+'-'+key for key in keys]
+        for p in pool_names:
+            self.run_cluster_cmd(f'osd pool create {p}')
+        self.run_cluster_cmd(f'fs new {fs_name} {pool_names[0]} {pool_names[1]} --fscid  {fscid} --force')
+        self.run_cluster_cmd(f'fs new {fs_name} {pool_names[0]} {pool_names[1]} --fscid  {fscid} --force')
+        self.fs.status().get_fsmap(fscid)
+
+    def test_fs_new_with_specific_id_fails_without_force_flag(self):
+        """
+        That command to create file system with specific ID fails without '--force' flag.
+        """
+        fs_name = "test_fs_specific_id"
+        fscid = 100
+        keys = ['metadata', 'data']
+        pool_names = [fs_name+'-'+key for key in keys]
+        for p in pool_names:
+            self.run_cluster_cmd(f'osd pool create {p}')
+        try:
+            self.run_cluster_cmd(f'fs new {fs_name} {pool_names[0]} {pool_names[1]} --fscid  {fscid}')
+        except CommandFailedError as ce:
+            self.assertEqual(ce.exitstatus, errno.EINVAL,
+                "invalid error code on creating a file system with specifc ID without --force flag")
+        else:
+            self.fail("expected creating file system with specific ID without '--force' flag to fail")
+
+    def test_fs_new_with_specific_id_fails_already_in_use(self):
+        """
+        That creating file system with ID already in use fails.
+        """
+        fs_name = "test_fs_specific_id"
+        # file system ID already in use
+        fscid =  self.fs.status().map['filesystems'][0]['id']
+        keys = ['metadata', 'data']
+        pool_names = [fs_name+'-'+key for key in keys]
+        for p in pool_names:
+            self.run_cluster_cmd(f'osd pool create {p}')
+        try:
+            self.run_cluster_cmd(f'fs new {fs_name} {pool_names[0]} {pool_names[1]} --fscid  {fscid} --force')
+        except CommandFailedError as ce:
+            self.assertEqual(ce.exitstatus, errno.EINVAL,
+                "invalid error code on creating a file system with specifc ID that is already in use")
+        else:
+            self.fail("expected creating file system with ID already in use to fail")
+
 
 class TestDump(CephFSTestCase):
     CLIENTS_REQUIRED = 0
index 802124f9bc445248d1ed4b004c1e3a2277784a14..37c458660a01b5183fdf61142806345f8142aa24 100644 (file)
@@ -449,7 +449,8 @@ mds_gid_t Filesystem::get_standby_replay(mds_gid_t who) const
 }
 
 Filesystem::ref FSMap::create_filesystem(std::string_view name,
-    int64_t metadata_pool, int64_t data_pool, uint64_t features)
+    int64_t metadata_pool, int64_t data_pool, uint64_t features,
+    fs_cluster_id_t fscid)
 {
   auto fs = Filesystem::create();
   fs->mds_map.epoch = epoch;
@@ -461,10 +462,21 @@ Filesystem::ref FSMap::create_filesystem(std::string_view name,
   fs->mds_map.created = ceph_clock_now();
   fs->mds_map.modified = ceph_clock_now();
   fs->mds_map.enabled = true;
-  fs->fscid = next_filesystem_id++;
-  // ANONYMOUS is only for upgrades from legacy mdsmaps, we should
-  // have initialized next_filesystem_id such that it's never used here.
-  ceph_assert(fs->fscid != FS_CLUSTER_ID_ANONYMOUS);
+  if (fscid == FS_CLUSTER_ID_NONE) {
+    fs->fscid = next_filesystem_id++;
+  } else {
+    fs->fscid = fscid;
+    next_filesystem_id = std::max(fscid,  (fs_cluster_id_t)next_filesystem_id) + 1;
+  }
+
+  // File system's ID can be FS_CLUSTER_ID_ANONYMOUS if we're recovering
+  // a legacy file system by passing FS_CLUSTER_ID_ANONYMOUS as the desired
+  // file system ID
+  if (fscid != FS_CLUSTER_ID_ANONYMOUS) {
+    // ANONYMOUS is only for upgrades from legacy mdsmaps, we should
+    // have initialized next_filesystem_id such that it's never used here.
+    ceph_assert(fs->fscid != FS_CLUSTER_ID_ANONYMOUS);
+  }
   filesystems[fs->fscid] = fs;
 
   // Created first filesystem?  Set it as the one
index 1bd5ca7989582b99d7e33ba95ebc34636b032475..e44574b34a3376aa515b408c692c38afbe5c6fe6 100644 (file)
@@ -404,7 +404,8 @@ public:
    */
   Filesystem::ref create_filesystem(
       std::string_view name, int64_t metadata_pool,
-      int64_t data_pool, uint64_t features);
+      int64_t data_pool, uint64_t features,
+      fs_cluster_id_t fscid);
 
   /**
    * Remove the filesystem (it must exist).  Caller should already
index 396ac3118b4ea59462dc0e187acdb848a8b91658..4fcd1ade445a209dc0e1f4071589fd97b17d7ac0 100644 (file)
@@ -241,6 +241,18 @@ class FsNewHandler : public FileSystemCommandHandler
       }
     }
 
+    int64_t fscid = FS_CLUSTER_ID_NONE;
+    if (cmd_getval(cmdmap, "fscid", fscid)) {
+      if (!force) {
+        ss << "Pass --force to create a file system with a specific ID";
+        return -EINVAL;
+      }
+      if (fsmap.filesystem_exists(fscid)) {
+        ss << "filesystem already exists with id '" << fscid << "'";
+        return -EINVAL;
+      }
+    }
+
     pg_pool_t const *data_pool = mon->osdmon()->osdmap.get_pg_pool(data);
     ceph_assert(data_pool != NULL);  // Checked it existed above
     pg_pool_t const *metadata_pool = mon->osdmon()->osdmap.get_pg_pool(metadata);
@@ -280,7 +292,7 @@ class FsNewHandler : public FileSystemCommandHandler
 
     // All checks passed, go ahead and create.
     auto&& fs = fsmap.create_filesystem(fs_name, metadata, data,
-        mon->get_quorum_con_features());
+        mon->get_quorum_con_features(), fscid);
 
     ss << "new fs with metadata pool " << metadata << " and data pool " << data;
 
index cf4a6913de039212497be7c15c65c7cc9717b52b..383827bb338f8019313b37232ab53d1e96157d8b 100644 (file)
@@ -367,7 +367,8 @@ COMMAND("fs new "
        "name=metadata,type=CephString "
        "name=data,type=CephString "
        "name=force,type=CephBool,req=false "
-       "name=allow_dangerous_metadata_overlay,type=CephBool,req=false",
+       "name=allow_dangerous_metadata_overlay,type=CephBool,req=false "
+       "name=fscid,type=CephInt,range=0,req=false",
        "make new filesystem using named pools <metadata> and <data>",
        "fs", "rw")
 COMMAND("fs fail "