From 873af573d3982d2ffe6da7c4f154734b75bc2efd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9lo=C3=AFse=20Joffe?= Date: Wed, 12 Aug 2026 10:43:54 +0200 Subject: [PATCH] refactor: adapt ResourceStatus/SiteStatus singletons cache to binary --- src/DIRAC/Interfaces/API/DiracAdmin.py | 10 +-- .../Client/ResourceStatus.py | 7 +- .../ResourceStatusSystem/Client/SiteStatus.py | 11 ++- src/DIRAC/Resources/Storage/StorageElement.py | 16 +--- .../Agent/SiteDirector.py | 2 +- .../WorkloadManagementSystem/DB/JobDB.py | 4 - .../Test_ResourceStatus.py | 80 +++++++++++++++++++ .../ResourceStatusSystem/Test_SiteStatus.py | 7 +- 8 files changed, 106 insertions(+), 31 deletions(-) diff --git a/src/DIRAC/Interfaces/API/DiracAdmin.py b/src/DIRAC/Interfaces/API/DiracAdmin.py index e5dfa56f555..24daf75d607 100755 --- a/src/DIRAC/Interfaces/API/DiracAdmin.py +++ b/src/DIRAC/Interfaces/API/DiracAdmin.py @@ -122,16 +122,12 @@ def getBannedSites(self, printOutput=False): if not bannedSites["OK"]: return bannedSites - probingSites = self.sitestatus.getSites(siteState="Probing") - if not probingSites["OK"]: - return probingSites - - mergedList = sorted(bannedSites["Value"] + probingSites["Value"]) + bannedList = sorted(bannedSites["Value"]) if printOutput: - gLogger.notice("\n".join(mergedList)) + gLogger.notice("\n".join(bannedList)) - return S_OK(mergedList) + return S_OK(bannedList) ############################################################################# def getSiteSection(self, site, printOutput=False): diff --git a/src/DIRAC/ResourceStatusSystem/Client/ResourceStatus.py b/src/DIRAC/ResourceStatusSystem/Client/ResourceStatus.py index c2b6424662c..113097f98cd 100644 --- a/src/DIRAC/ResourceStatusSystem/Client/ResourceStatus.py +++ b/src/DIRAC/ResourceStatusSystem/Client/ResourceStatus.py @@ -257,9 +257,14 @@ def getCacheDictFromRawData(rawList): :return: dict of the form { ( elementName, elementType, statusType, vO ) : status, ... } """ + ALLOWED = {"Active", "Degraded"} res = {} for entry in rawList: - res.update({(entry[0], entry[1], entry[2], entry[4]): entry[3]}) + if entry[3] in ALLOWED: + status = "Active" + else: + status = "Banned" + res.update({(entry[0], entry[1], entry[2], entry[4]): status}) return res diff --git a/src/DIRAC/ResourceStatusSystem/Client/SiteStatus.py b/src/DIRAC/ResourceStatusSystem/Client/SiteStatus.py index cd5afd35697..536313c2483 100644 --- a/src/DIRAC/ResourceStatusSystem/Client/SiteStatus.py +++ b/src/DIRAC/ResourceStatusSystem/Client/SiteStatus.py @@ -147,7 +147,7 @@ def getUsableSites(self, siteNames=None): return siteStatusDictRes if not siteStatusDictRes["Value"]: return S_OK([]) - return S_OK([x[0] for x in siteStatusDictRes["Value"].items() if x[1] in ["Active", "Degraded"]]) + return S_OK([x[0] for x in siteStatusDictRes["Value"].items() if x[1] == "Active"]) def getSites(self, siteState="Active"): """ @@ -188,7 +188,7 @@ def getSites(self, siteState="Active"): else: # fix case sensitive string siteState = siteState.capitalize() - allowedStateList = ["Active", "Banned", "Degraded", "Probing", "Error", "Unknown"] + allowedStateList = ["Active", "Banned"] if siteState not in allowedStateList: return S_ERROR(errno.EINVAL, "Not a valid status, parameter rejected") @@ -275,9 +275,14 @@ def getCacheDictFromRawData(rawList): :return: dict of the form { ( elementName ) : status, ... } """ + ALLOWED = {"Active", "Degraded"} res = {} for entry in rawList: - res.update({(entry[0]): entry[1]}) + if entry[1] in ALLOWED: + status = "Active" + else: + status = "Banned" + res.update({(entry[0]): status}) return res diff --git a/src/DIRAC/Resources/Storage/StorageElement.py b/src/DIRAC/Resources/Storage/StorageElement.py index 902f0c33e9b..0e91ddfd843 100755 --- a/src/DIRAC/Resources/Storage/StorageElement.py +++ b/src/DIRAC/Resources/Storage/StorageElement.py @@ -547,21 +547,13 @@ def status(self): # If nothing is defined in the CS Access is allowed # If something is defined, then it must be set to Active - retDict["Read"] = not ( - "ReadAccess" in self.options and self.options["ReadAccess"] not in ("Active", "Degraded") - ) - retDict["Write"] = not ( - "WriteAccess" in self.options and self.options["WriteAccess"] not in ("Active", "Degraded") - ) - retDict["Remove"] = not ( - "RemoveAccess" in self.options and self.options["RemoveAccess"] not in ("Active", "Degraded") - ) + retDict["Read"] = not ("ReadAccess" in self.options and self.options["ReadAccess"] != "Active") + retDict["Write"] = not ("WriteAccess" in self.options and self.options["WriteAccess"] != "Active") + retDict["Remove"] = not ("RemoveAccess" in self.options and self.options["RemoveAccess"] != "Active") if retDict["Read"]: retDict["Check"] = True else: - retDict["Check"] = not ( - "CheckAccess" in self.options and self.options["CheckAccess"] not in ("Active", "Degraded") - ) + retDict["Check"] = not ("CheckAccess" in self.options and self.options["CheckAccess"] != "Active") diskSE = True tapeSE = False if "SEType" in self.options: diff --git a/src/DIRAC/WorkloadManagementSystem/Agent/SiteDirector.py b/src/DIRAC/WorkloadManagementSystem/Agent/SiteDirector.py index ef4a14426f4..715d2d489a0 100644 --- a/src/DIRAC/WorkloadManagementSystem/Agent/SiteDirector.py +++ b/src/DIRAC/WorkloadManagementSystem/Agent/SiteDirector.py @@ -222,7 +222,7 @@ def _buildQueueDict( self.log.error("Can not get the status of computing elements: ", result["Message"]) return result # Try to get CEs which have been probed and those unprobed (vO='all'). - ceMaskList = [ceName for ceName in result["Value"] if result["Value"][ceName]["all"] in ("Active", "Degraded")] + ceMaskList = [ceName for ceName in result["Value"] if result["Value"][ceName]["all"] == "Active"] # Filter the unusable queues for queueName in list(self.queueDict.keys()): diff --git a/src/DIRAC/WorkloadManagementSystem/DB/JobDB.py b/src/DIRAC/WorkloadManagementSystem/DB/JobDB.py index d1b1f08c096..d524abcd87b 100755 --- a/src/DIRAC/WorkloadManagementSystem/DB/JobDB.py +++ b/src/DIRAC/WorkloadManagementSystem/DB/JobDB.py @@ -1094,10 +1094,6 @@ def getSiteSummaryWeb(self, selectDict, sortList, startItem, maxItems): # Get the site mask status siteMask = {} - resultMask = self.siteClient.getSites("All") - if resultMask["OK"]: - for site in resultMask["Value"]: - siteMask[site] = "NoMask" resultMask = self.siteClient.getSites("Active") if resultMask["OK"]: for site in resultMask["Value"]: diff --git a/tests/Integration/ResourceStatusSystem/Test_ResourceStatus.py b/tests/Integration/ResourceStatusSystem/Test_ResourceStatus.py index a7eace12241..7633cc81a98 100644 --- a/tests/Integration/ResourceStatusSystem/Test_ResourceStatus.py +++ b/tests/Integration/ResourceStatusSystem/Test_ResourceStatus.py @@ -15,6 +15,7 @@ from DIRAC import gLogger from DIRAC.ResourceStatusSystem.Client.ResourceStatusClient import ResourceStatusClient +from DIRAC.ResourceStatusSystem.Client.ResourceStatus import ResourceStatus gLogger.setLevel("DEBUG") @@ -26,6 +27,12 @@ def fixtureResourceStatusClient(): yield ResourceStatusClient() +@pytest.fixture(name="rsClient") +def fixtureResourceStatus(): + resourceStatus = ResourceStatus() + yield resourceStatus + + def test_addAndRemove(rssClient: ResourceStatusClient): # clean up rssClient.deleteStatusElement("Site", "Status", "TestSite1234") @@ -422,3 +429,76 @@ def test_addIfNotThereStatusElement(rssClient: ResourceStatusClient): assert res["OK"] is True, res["Message"] # check if the returned value is empty assert not res["Value"] + + +def test_getElementStatus(rssClient: ResourceStatusClient, rsClient): + # make sure that the test resoureces are not presented in the db + rssClient.deleteStatusElement("Resource", "Status", "testActiveResource") + rssClient.deleteStatusElement("Resource", "Status", "testBannedResource") + rssClient.deleteStatusElement("Resource", "Status", "testResource") + + res = rssClient.insertStatusElement( + "Resource", + "Status", + "testActiveResource", + "all", + "Degraded", + "ComputingElement", + "reason", + Datetime, + Datetime, + "tokenOwner", + Datetime, + ) + + assert res["OK"] is True, res["Message"] + rsClient.rssCache.refreshCache() + + res = rsClient.getElementStatus("testActiveResource", "ComputingElement") + + assert res["OK"] is True, res["Message"] + assert res["Value"]["testActiveResource"]["all"] == "Active" + + res = rssClient.insertStatusElement( + "Resource", + "Status", + "testBannedResource", + "all", + "Probing", + "ComputingElement", + "reason", + Datetime, + Datetime, + "tokenOwner", + Datetime, + ) + + assert res["OK"] is True, res["Message"] + rsClient.rssCache.refreshCache() + + res = rsClient.getElementStatus("testBannedResource", "ComputingElement") + assert res["OK"] is True, res["Message"] + assert res["Value"]["testBannedResource"]["all"] == "Banned" + + res = rssClient.insertStatusElement( + "Resource", + "Status", + "testResource", + "all", + "Active", + "ComputingElement", + "reason", + Datetime, + Datetime, + "tokenOwner", + Datetime, + ) + assert res["OK"] is True, res["Message"] + rsClient.rssCache.refreshCache() + + res = rsClient.setElementStatus("testResource", "ComputingElement", "all", "Error") + assert res["OK"] is True, res["Message"] + rsClient.rssCache.refreshCache() + res = rsClient.getElementStatus("testResource", "ComputingElement") + assert res["OK"] is True, res["Message"] + assert res["Value"]["testResource"]["all"] == "Banned" diff --git a/tests/Integration/ResourceStatusSystem/Test_SiteStatus.py b/tests/Integration/ResourceStatusSystem/Test_SiteStatus.py index 4fa16c06024..bd8f24ba1ca 100644 --- a/tests/Integration/ResourceStatusSystem/Test_SiteStatus.py +++ b/tests/Integration/ResourceStatusSystem/Test_SiteStatus.py @@ -132,7 +132,7 @@ def test_addAndRemove_complicatedTest(stClient): result = stClient.getSites() assert result["OK"] is True, result["Message"] - inRSS = "testBanned.test.test" in result["Value"] + inRSS = "testActive.test.test" in result["Value"] # TEST getSites # ............................................................................... @@ -148,9 +148,10 @@ def test_addAndRemove_complicatedTest(stClient): # setting a status if inRSS: - result = stClient.setSiteStatus("testBanned.test.test", "Probing") + result = stClient.setSiteStatus("testActive.test.test", "Probing") assert result["OK"] is True, result["Message"] stClient.rssCache.refreshCache() - result = stClient.getSites("Probing") + result = stClient.getSites("Banned") assert result["OK"] is True, result["Message"] + assert "testActive.test.test" in result["Value"]