From b08139341ab0e4c939d8be64f3c4e9eda633691a Mon Sep 17 00:00:00 2001 From: Andreas Joachim Peters Date: Thu, 16 Jan 2025 15:42:29 +0100 Subject: [PATCH] MGM: implement the concept of alternative spaces - fixes EOS-6286 DOC: document the concept of alternative spaces --- doc/diopside/manual/interfaces.rst | 25 ++++++++++++++++++++++++- mgm/Policy.cc | 23 ++++++++++++++++++++++- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/doc/diopside/manual/interfaces.rst b/doc/diopside/manual/interfaces.rst index c3f4c6f1f..98cdd46e4 100644 --- a/doc/diopside/manual/interfaces.rst +++ b/doc/diopside/manual/interfaces.rst @@ -1118,6 +1118,7 @@ The following policies can be configured key values =================== ================================================= space default,... + altspaces [space1[,space2[,space3]]] layout plain,replica,raid5,raid6,raiddp,archive,qrain nstripes 1..255 checksum adler,md5,sha1,crc32,crc32c @@ -1229,9 +1230,31 @@ Examples: # files uploaded selecting the rep4 space will be stored with 4 replicas, if non space is selected they will get the default for the target directory or the default space # define a space with 4 replica policy - eos space config rep4 space.policys.nstripes=4 + eos space config rep4 space.policy.nstripes=4 eos space config rep4 space.policy.layout=replica + + ############## + # Example 3 # + ############## + # When the policy is consulted for a write operation, alternative storage spaces can be defined as fallbacks. + # These alternatives are used when the available space in the primary storage, as determined by the policy, is exceeded. + # For instance, if files are initially placed in an NVME storage space and it becomes full, the system can fall back + # to an alternative space, such as an HDD. If the HDD space is also exhausted, another fallback, like OLDHDD, can be tried. + # If all alternative spaces are exhausted, the policy will revert to the initially selected space, and the placement + # operation will fail due to insufficient space. + + + # define as default the NVME space + eos space config default space.policy.space=NVME + + # define the HDD space as alternative to the NVME space + eos space config NVME space.policy.altspaces=HDD,OLDHDD + + # define several alternative spaces HDD,OLDHDD if the NVME space has no nominal bytes left + # HDD is tried first and if there are nominal bytes left that one is taken + eos space config NVME space.policy.altspaces=HDD,OLDHDD + Storage Tiering ^^^^^^^^^^^^^^^ Currently we support two tiering scenarios: diff --git a/mgm/Policy.cc b/mgm/Policy.cc index c5cfb74e4..c6a8b5d57 100644 --- a/mgm/Policy.cc +++ b/mgm/Policy.cc @@ -40,7 +40,8 @@ EOSMGMNAMESPACE_BEGIN const std::vector Policy::gBasePolicyKeys = { "policy.space", "policy.layout", "policy.nstripes", "policy.checksum", "policy.blocksize", "policy.blockchecksum", - "policy.localredirect", "policy.updateconversion","policy.readconversion"}; + "policy.localredirect", "policy.updateconversion","policy.readconversion", + "policy.altspaces"}; const std::vector Policy::gBasePolicyRWKeys = { "policy.bandwidth", "policy.iopriority", "policy.iotype", @@ -170,6 +171,26 @@ Policy::GetLayoutAndSpace(const char* path, } } + // Check if the given space is under the nominal value, otherwise loop through altspaces and take the first having capacity + if (rw) { + if (FsView::gFsView.UnderNominalQuota(space, (vid.uid==0))) { + std::string altspaces_key = "policy.altspaces"; + if (auto kv = spacepolicies.find(altspaces_key); + kv != spacepolicies.end() && (!kv->second.empty())) { + std::vector alt_spaces; + eos::common::StringConversion::Tokenize(kv->second, + alt_spaces, + ":"); + for (auto aspace:alt_spaces) { + if (!FsView::gFsView.UnderNominalQuota(aspace, (vid.uid==0))) { + eos_static_info("msg=\"space '%s' is under nominal quota - selected alternative space '%s'", space.c_str(), aspace.c_str()); + space = aspace; // select this one and continue + break; + } + } + } + } + } // Replace the non empty settings from the default space have been already // defined before if (!conversion && space != "default") {