wmglobalqueue 2.4.0.2__py3-none-any.whl → 2.4.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of wmglobalqueue might be problematic. Click here for more details.
- Utils/CertTools.py +38 -0
- WMCore/Database/CMSCouch.py +86 -5
- WMCore/Database/CouchMonitoring.py +450 -0
- WMCore/Services/Rucio/Rucio.py +5 -2
- WMCore/Services/RucioConMon/RucioConMon.py +24 -31
- WMCore/Services/WMStatsServer/WMStatsServer.py +2 -2
- WMCore/WMInit.py +176 -27
- WMCore/WMSpec/WMWorkloadTools.py +17 -5
- WMCore/__init__.py +1 -1
- wmglobalqueue-2.4.2.dist-info/METADATA +26 -0
- {wmglobalqueue-2.4.0.2.dist-info → wmglobalqueue-2.4.2.dist-info}/RECORD +102 -101
- {wmglobalqueue-2.4.0.2.dist-info → wmglobalqueue-2.4.2.dist-info}/WHEEL +1 -1
- wmglobalqueue-2.4.0.2.dist-info/METADATA +0 -24
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/bin/wmc-dist-patch +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/bin/wmc-dist-unpatch +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/bin/wmc-httpd +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/.couchapprc +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/README.md +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/_attachments/index.html +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/_attachments/js/ElementInfoByWorkflow.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/_attachments/js/StuckElementInfo.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/_attachments/js/WorkloadInfoTable.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/_attachments/js/dataTable.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/_attachments/js/namespace.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/_attachments/style/main.css +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/couchapp.json +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/filters/childQueueFilter.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/filters/filterDeletedDocs.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/filters/queueFilter.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/language +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/lib/mustache.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/lib/validate.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/lib/workqueue_utils.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/lists/elementsDetail.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/lists/filter.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/lists/stuckElements.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/lists/workRestrictions.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/lists/workflowSummary.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/rewrites.json +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/shows/redirect.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/shows/status.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/templates/ElementSummaryByWorkflow.html +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/templates/StuckElementSummary.html +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/templates/TaskStatus.html +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/templates/WorkflowSummary.html +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/templates/partials/workqueue-common-lib.html +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/templates/partials/yui-lib-remote.html +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/templates/partials/yui-lib.html +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/updates/in-place.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/validate_doc_update.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/vendor/couchapp/_attachments/jquery.couch.app.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/vendor/couchapp/_attachments/jquery.pathbinder.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/activeData/map.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/activeData/reduce.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/activeParentData/map.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/activeParentData/reduce.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/activePileupData/map.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/activePileupData/reduce.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/analyticsData/map.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/analyticsData/reduce.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/availableByPriority/map.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/conflicts/map.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/elements/map.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/elementsByData/map.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/elementsByParent/map.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/elementsByParentData/map.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/elementsByPileupData/map.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/elementsByStatus/map.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/elementsBySubscription/map.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/elementsByWorkflow/map.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/elementsByWorkflow/reduce.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/elementsDetailByWorkflowAndStatus/map.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/jobInjectStatusByRequest/map.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/jobInjectStatusByRequest/reduce.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/jobStatusByRequest/map.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/jobStatusByRequest/reduce.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/jobsByChildQueueAndPriority/map.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/jobsByChildQueueAndPriority/reduce.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/jobsByChildQueueAndStatus/map.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/jobsByChildQueueAndStatus/reduce.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/jobsByRequest/map.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/jobsByRequest/reduce.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/jobsByStatus/map.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/jobsByStatus/reduce.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/jobsByStatusAndPriority/map.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/jobsByStatusAndPriority/reduce.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/openRequests/map.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/recent-items/map.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/siteWhitelistByRequest/map.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/siteWhitelistByRequest/reduce.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/specsByWorkflow/map.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/stuckElements/map.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/wmbsInjectStatusByRequest/map.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/wmbsInjectStatusByRequest/reduce.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/wmbsUrl/map.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/wmbsUrl/reduce.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/wmbsUrlByRequest/map.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/wmbsUrlByRequest/reduce.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/workflowSummary/map.js +0 -0
- {wmglobalqueue-2.4.0.2.data → wmglobalqueue-2.4.2.data}/data/data/couchapps/WorkQueue/views/workflowSummary/reduce.js +0 -0
- {wmglobalqueue-2.4.0.2.dist-info → wmglobalqueue-2.4.2.dist-info/licenses}/LICENSE +0 -0
- {wmglobalqueue-2.4.0.2.dist-info → wmglobalqueue-2.4.2.dist-info/licenses}/NOTICE +0 -0
- {wmglobalqueue-2.4.0.2.dist-info → wmglobalqueue-2.4.2.dist-info}/top_level.txt +0 -0
|
@@ -11,7 +11,6 @@ from future import standard_library
|
|
|
11
11
|
|
|
12
12
|
from urllib.parse import urlencode
|
|
13
13
|
|
|
14
|
-
import gzip
|
|
15
14
|
import json
|
|
16
15
|
import logging
|
|
17
16
|
|
|
@@ -40,14 +39,13 @@ class RucioConMon(Service):
|
|
|
40
39
|
super(RucioConMon, self).__init__(configDict)
|
|
41
40
|
self['logger'].debug("Initializing RucioConMon with url: %s", self['endpoint'])
|
|
42
41
|
|
|
43
|
-
def _getResult(self, uri, callname="", clearCache=False, args=None
|
|
42
|
+
def _getResult(self, uri, callname="", clearCache=False, args=None):
|
|
44
43
|
"""
|
|
45
44
|
Either fetch data from the cache file or query the data-service
|
|
46
45
|
:param uri: The endpoint uri
|
|
47
46
|
:param callname: alias for caller function
|
|
48
47
|
:param clearCache: parameter to control the cache behavior
|
|
49
48
|
:param args: additional parameters to HTTP request call
|
|
50
|
-
:param binary: specifies request for binary object from HTTP requests (e.g. zipped content)
|
|
51
49
|
:return: A dictionary
|
|
52
50
|
"""
|
|
53
51
|
|
|
@@ -67,32 +65,25 @@ class RucioConMon(Service):
|
|
|
67
65
|
|
|
68
66
|
if clearCache:
|
|
69
67
|
self.clearCache(cachedApi, args)
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
with self.refreshCache(cachedApi, apiUrl, decoder=False, binary=True) as istream:
|
|
73
|
-
results = gzip.decompress(istream.read())
|
|
74
|
-
return results
|
|
75
|
-
else:
|
|
76
|
-
with self.refreshCache(cachedApi, apiUrl) as istream:
|
|
77
|
-
results = istream.read()
|
|
78
|
-
|
|
79
|
-
results = json.loads(results)
|
|
80
|
-
return results
|
|
68
|
+
with self.refreshCache(cachedApi, apiUrl, decoder=True, binary=False) as istream:
|
|
69
|
+
return json.load(istream)
|
|
81
70
|
|
|
82
|
-
def _getResultZipped(self, uri, callname="", clearCache=True
|
|
71
|
+
def _getResultZipped(self, uri, callname="", clearCache=True):
|
|
83
72
|
"""
|
|
84
|
-
This method
|
|
85
|
-
of the normal json
|
|
73
|
+
This method retrieves gzipped content, instead of the standard json format.
|
|
86
74
|
:param uri: The endpoint uri
|
|
87
75
|
:param callname: alias for caller function
|
|
88
76
|
:param clearCache: parameter to control the cache behavior
|
|
89
|
-
:
|
|
90
|
-
:return: a list of LFNs
|
|
77
|
+
:return: yields a single record from the data retrieved
|
|
91
78
|
"""
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
79
|
+
cachedApi = callname
|
|
80
|
+
if clearCache:
|
|
81
|
+
self.clearCache(cachedApi)
|
|
82
|
+
|
|
83
|
+
with self.refreshCache(cachedApi, uri, decoder=False, binary=True) as istream:
|
|
84
|
+
for line in istream:
|
|
85
|
+
line = decodeBytesToUnicode(line).replace("\n", "")
|
|
86
|
+
yield line
|
|
96
87
|
|
|
97
88
|
def getRSEStats(self):
|
|
98
89
|
"""
|
|
@@ -109,7 +100,7 @@ class RucioConMon(Service):
|
|
|
109
100
|
Gets the list of all unmerged files in an RSE
|
|
110
101
|
:param rseName: The RSE whose list of unmerged files to be retrieved
|
|
111
102
|
:param zipped: If True the interface providing the zipped lists will be called
|
|
112
|
-
:return:
|
|
103
|
+
:return: a generator of unmerged files for the RSE in question
|
|
113
104
|
"""
|
|
114
105
|
# NOTE: The default API provided by Rucio Consistency Monitor is in a form of a
|
|
115
106
|
# zipped file/stream. Currently we are using the newly provided json API
|
|
@@ -117,12 +108,14 @@ class RucioConMon(Service):
|
|
|
117
108
|
# implement the method with the zipped API and use disc cache for
|
|
118
109
|
# reading/streaming from file. This will prevent any set arithmetic
|
|
119
110
|
# in the future.
|
|
120
|
-
if
|
|
121
|
-
uri = "files?rse=%s&format=json" % rseName
|
|
122
|
-
rseUnmerged = self._getResult(uri, callname=rseName)
|
|
123
|
-
return rseUnmerged
|
|
124
|
-
else:
|
|
111
|
+
if zipped:
|
|
125
112
|
uri = "files?rse=%s&format=raw" % rseName
|
|
126
113
|
callname = '{}.zipped'.format(rseName)
|
|
127
|
-
rseUnmerged = self._getResultZipped(uri,
|
|
128
|
-
|
|
114
|
+
rseUnmerged = self._getResultZipped(uri, callname=callname, clearCache=True)
|
|
115
|
+
else:
|
|
116
|
+
uri = "files?rse=%s&format=json" % rseName
|
|
117
|
+
callname = '{}.json'.format(rseName)
|
|
118
|
+
rseUnmerged = self._getResult(uri, callname=callname)
|
|
119
|
+
# now lazily return items
|
|
120
|
+
for item in rseUnmerged:
|
|
121
|
+
yield item
|
|
@@ -128,7 +128,7 @@ class WMStatsServer(Service):
|
|
|
128
128
|
def getProtectedLFNs(self):
|
|
129
129
|
"""
|
|
130
130
|
A method to be used for fetching a list of all protected lfns from WMStatServer
|
|
131
|
-
:returns:
|
|
131
|
+
:returns: a unique list of protected LFNs
|
|
132
132
|
"""
|
|
133
133
|
callname = 'protectedlfns'
|
|
134
|
-
return self._getResult(callname, verb="GET")
|
|
134
|
+
return list(set(self._getResult(callname, verb="GET")))
|
WMCore/WMInit.py
CHANGED
|
@@ -13,6 +13,8 @@ import os.path
|
|
|
13
13
|
import sys
|
|
14
14
|
import threading
|
|
15
15
|
import traceback
|
|
16
|
+
import warnings
|
|
17
|
+
import wmcoredb
|
|
16
18
|
|
|
17
19
|
from WMCore.Configuration import loadConfigurationFile
|
|
18
20
|
from WMCore.DAOFactory import DAOFactory
|
|
@@ -20,7 +22,6 @@ from WMCore.Database.DBFactory import DBFactory
|
|
|
20
22
|
from WMCore.Database.Transaction import Transaction
|
|
21
23
|
from WMCore.WMBase import getWMBASE
|
|
22
24
|
from WMCore.WMException import WMException
|
|
23
|
-
from WMCore.WMFactory import WMFactory
|
|
24
25
|
|
|
25
26
|
|
|
26
27
|
class WMInitException(WMException):
|
|
@@ -54,11 +55,12 @@ def connectToDB():
|
|
|
54
55
|
|
|
55
56
|
socketLoc = getattr(wmAgentConfig.CoreDatabase, "socket", None)
|
|
56
57
|
connectUrl = getattr(wmAgentConfig.CoreDatabase, "connectUrl", None)
|
|
57
|
-
(dialect,
|
|
58
|
+
(dialect, _) = connectUrl.split(":", 1)
|
|
58
59
|
|
|
59
60
|
myWMInit = WMInit()
|
|
60
61
|
myWMInit.setDatabaseConnection(dbConfig=connectUrl, dialect=dialect,
|
|
61
62
|
socketLoc=socketLoc)
|
|
63
|
+
|
|
62
64
|
return
|
|
63
65
|
|
|
64
66
|
|
|
@@ -113,12 +115,12 @@ class WMInit(object):
|
|
|
113
115
|
return
|
|
114
116
|
|
|
115
117
|
options = {}
|
|
116
|
-
if dialect.lower()
|
|
117
|
-
dialect = 'MySQL
|
|
118
|
+
if dialect.lower() in ['mysql', 'mariadb']:
|
|
119
|
+
dialect = 'mariadb' # Both MySQL and MariaDB use the mariadb directory
|
|
118
120
|
if socketLoc != None:
|
|
119
121
|
options['unix_socket'] = socketLoc
|
|
120
122
|
elif dialect.lower() == 'oracle':
|
|
121
|
-
dialect = '
|
|
123
|
+
dialect = 'oracle' # Keep lowercase for consistency
|
|
122
124
|
elif dialect.lower() == 'http':
|
|
123
125
|
dialect = 'CouchDB'
|
|
124
126
|
else:
|
|
@@ -146,31 +148,178 @@ class WMInit(object):
|
|
|
146
148
|
|
|
147
149
|
This method needs to have been preceded by the
|
|
148
150
|
setDatabaseConnection.
|
|
151
|
+
|
|
152
|
+
@deprecated: Use setSchemaFromModules instead
|
|
153
|
+
"""
|
|
154
|
+
warnings.warn("setSchema is deprecated. Use setSchemaFromModules instead.", DeprecationWarning)
|
|
155
|
+
|
|
156
|
+
# create a map of old to new SQL module names
|
|
157
|
+
moduleMap = {
|
|
158
|
+
'WMCore.WMBS': 'wmbs',
|
|
159
|
+
'WMCore.ResourceControl': 'resourcecontrol',
|
|
160
|
+
'WMCore.BossAir': 'bossair',
|
|
161
|
+
'WMCore.Agent.Database': 'agent',
|
|
162
|
+
'WMComponent.DBS3Buffer': 'dbs3buffer',
|
|
163
|
+
'T0.WMBS': 'tier0',
|
|
164
|
+
'WMQuality.TestDB': 'testdb'
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
# convert old module names to new format
|
|
168
|
+
if modules:
|
|
169
|
+
modules = [moduleMap.get(module, module) for module in modules]
|
|
170
|
+
|
|
171
|
+
self.setSchemaFromModules(modules)
|
|
172
|
+
|
|
173
|
+
def setSchemaFromModules(self, sqlModules):
|
|
174
|
+
"""
|
|
175
|
+
Initialize database schema for one or more SQL packages.
|
|
176
|
+
It finds out which dialect is being used and then looks for the
|
|
177
|
+
appropriate SQL files in the sql directory.
|
|
178
|
+
|
|
179
|
+
:param sqlModules: List of SQL database modules to be initialized.
|
|
180
|
+
Current supported values are (default is 'wmbs'):
|
|
181
|
+
- 'wmbs'
|
|
182
|
+
- 'resourcecontrol'
|
|
183
|
+
- 'bossair'
|
|
184
|
+
- 'agent'
|
|
185
|
+
- 'dbs3buffer'
|
|
186
|
+
- 'tier0'
|
|
149
187
|
"""
|
|
150
|
-
modules = modules or []
|
|
151
188
|
myThread = threading.currentThread()
|
|
189
|
+
if not hasattr(myThread, 'dbi'):
|
|
190
|
+
raise WMInitException("Database connection not initialized. Call setDatabaseConnection first.")
|
|
191
|
+
|
|
192
|
+
# Get the database dialect
|
|
193
|
+
dialect = myThread.dialect.lower()
|
|
194
|
+
if dialect not in ['mariadb', 'oracle']:
|
|
195
|
+
raise WMInitException(f"Unsupported database dialect: {dialect}")
|
|
196
|
+
|
|
197
|
+
# Get the base directory (WMCore root)
|
|
198
|
+
if os.environ.get('WMCORE_ROOT'):
|
|
199
|
+
baseDir = os.environ['WMCORE_ROOT']
|
|
200
|
+
logging.info("SQL base directory based on WMCORE_ROOT: %s", baseDir)
|
|
201
|
+
else:
|
|
202
|
+
baseDir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))
|
|
203
|
+
logging.info("SQL base directory based on WMInit-relative path: %s", baseDir)
|
|
204
|
+
|
|
205
|
+
# Define the SQL files needed for each module and their dependencies
|
|
206
|
+
# The order matters - modules that depend on others should come later
|
|
207
|
+
moduleSQLFiles = {
|
|
208
|
+
'wmbs': {
|
|
209
|
+
'files': ['create_wmbs_tables.sql', 'create_wmbs_indexes.sql', 'initial_wmbs_data.sql'],
|
|
210
|
+
'dependencies': []
|
|
211
|
+
},
|
|
212
|
+
'resourcecontrol': {
|
|
213
|
+
'files': ['create_resourcecontrol.sql'],
|
|
214
|
+
'dependencies': ['wmbs']
|
|
215
|
+
},
|
|
216
|
+
'bossair': {
|
|
217
|
+
'files': ['create_bossair.sql'],
|
|
218
|
+
'dependencies': ['wmbs']
|
|
219
|
+
},
|
|
220
|
+
'agent': {
|
|
221
|
+
'files': ['create_agent.sql'],
|
|
222
|
+
'dependencies': []
|
|
223
|
+
},
|
|
224
|
+
'dbs3buffer': {
|
|
225
|
+
'files': ['create_dbs3buffer.sql'],
|
|
226
|
+
'dependencies': ['wmbs']
|
|
227
|
+
},
|
|
228
|
+
'tier0': {
|
|
229
|
+
'files': ['create_tier0_tables.sql', 'create_tier0_indexes.sql', 'create_tier0_functions.sql', 'initial_tier0_data.sql'],
|
|
230
|
+
'dependencies': ['wmbs', 'dbs3buffer']
|
|
231
|
+
},
|
|
232
|
+
'testdb': {
|
|
233
|
+
'files': ['create_testdb.sql'],
|
|
234
|
+
'dependencies': []
|
|
235
|
+
},
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
# Validate all requested modules exist
|
|
239
|
+
for module in sqlModules:
|
|
240
|
+
if module not in moduleSQLFiles:
|
|
241
|
+
raise WMInitException(f"Unknown module: {module}")
|
|
242
|
+
|
|
243
|
+
# Sort modules based on dependencies
|
|
244
|
+
sorted_modules = []
|
|
245
|
+
remaining_modules = set(sqlModules)
|
|
246
|
+
|
|
247
|
+
while remaining_modules:
|
|
248
|
+
# Find modules with no remaining dependencies
|
|
249
|
+
ready_modules = [
|
|
250
|
+
mod for mod in remaining_modules
|
|
251
|
+
if all(dep in sorted_modules for dep in moduleSQLFiles[mod]['dependencies'])
|
|
252
|
+
]
|
|
253
|
+
|
|
254
|
+
if not ready_modules:
|
|
255
|
+
# Circular dependency detected
|
|
256
|
+
raise WMInitException("Circular dependency detected in module dependencies")
|
|
257
|
+
|
|
258
|
+
sorted_modules.extend(ready_modules)
|
|
259
|
+
remaining_modules -= set(ready_modules)
|
|
260
|
+
|
|
261
|
+
# Execute SQL files in dependency order
|
|
262
|
+
for module in sorted_modules:
|
|
263
|
+
logging.info("Executing SQL files for: %s", module)
|
|
264
|
+
for sql_file in moduleSQLFiles[module]['files']:
|
|
265
|
+
dialect_sql_file = wmcoredb.get_sql_file(module_name=module, file_name=sql_file, backend=dialect)
|
|
266
|
+
|
|
267
|
+
# now execute each SQL statement
|
|
268
|
+
for stmt in self._getSQLStatements(dialect_sql_file, dialect):
|
|
269
|
+
try:
|
|
270
|
+
myThread.dbi.processData(stmt)
|
|
271
|
+
except Exception as ex:
|
|
272
|
+
msg = f"Error executing SQL file {dialect_sql_file}. "
|
|
273
|
+
msg += f"Statement: {stmt}"
|
|
274
|
+
msg += str(ex)
|
|
275
|
+
raise WMInitException(msg)
|
|
152
276
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
277
|
+
return
|
|
278
|
+
|
|
279
|
+
def _getSQLStatements(self, sqlFile, dialect):
|
|
280
|
+
"""
|
|
281
|
+
Return the SQL statements from the file.
|
|
282
|
+
For MariaDB, it accepts the whole SQL file content in a single statement.
|
|
283
|
+
For Oracle, it splits the SQL file content into statements using the slash (/) terminator
|
|
284
|
+
when it appears as the first character in a line.
|
|
285
|
+
"""
|
|
286
|
+
if not os.path.exists(sqlFile):
|
|
287
|
+
raise WMInitException(f"SQL file not found: {sqlFile}")
|
|
288
|
+
|
|
289
|
+
with open(sqlFile, 'r', encoding='utf-8') as f:
|
|
290
|
+
sql = f.read()
|
|
291
|
+
|
|
292
|
+
if dialect == 'mariadb':
|
|
293
|
+
return [sql]
|
|
294
|
+
elif dialect == 'oracle':
|
|
295
|
+
statements = []
|
|
296
|
+
current_statement = []
|
|
297
|
+
|
|
298
|
+
for line in sql.split('\n'):
|
|
299
|
+
line = line.strip()
|
|
300
|
+
# Skip empty lines and comments
|
|
301
|
+
if not line or line.startswith('--'):
|
|
302
|
+
continue
|
|
303
|
+
|
|
304
|
+
# If we find a slash terminator at the start of a line
|
|
305
|
+
if line == '/':
|
|
306
|
+
# Join all lines collected so far into a statement
|
|
307
|
+
stmt = '\n'.join(current_statement)
|
|
308
|
+
if stmt.strip():
|
|
309
|
+
statements.append(stmt)
|
|
310
|
+
current_statement = []
|
|
311
|
+
else:
|
|
312
|
+
current_statement.append(line)
|
|
313
|
+
|
|
314
|
+
# Add any remaining statement
|
|
315
|
+
if current_statement:
|
|
316
|
+
stmt = '\n'.join(current_statement)
|
|
317
|
+
if stmt.strip():
|
|
318
|
+
statements.append(stmt)
|
|
319
|
+
|
|
320
|
+
return statements
|
|
321
|
+
else:
|
|
322
|
+
raise WMInitException(f"Unsupported database dialect: {dialect}")
|
|
174
323
|
|
|
175
324
|
def clearDatabase(self, modules=None):
|
|
176
325
|
"""
|
WMCore/WMSpec/WMWorkloadTools.py
CHANGED
|
@@ -61,7 +61,7 @@ def makeLumiList(lumiDict):
|
|
|
61
61
|
lumiDict = json.loads(lumiDict)
|
|
62
62
|
ll = LumiList(compactList=lumiDict)
|
|
63
63
|
return ll.getCompactList()
|
|
64
|
-
except:
|
|
64
|
+
except Exception:
|
|
65
65
|
raise WMSpecFactoryException("Could not parse LumiList, %s: %s" % (type(lumiDict), lumiDict))
|
|
66
66
|
|
|
67
67
|
|
|
@@ -91,12 +91,24 @@ def _validateArgument(argument, value, argumentDefinition):
|
|
|
91
91
|
elif value is None:
|
|
92
92
|
return value
|
|
93
93
|
|
|
94
|
+
# is it a built-in type (int, str, bool, etc.) or a custom function
|
|
95
|
+
expected_type = argumentDefinition["type"]
|
|
94
96
|
try:
|
|
95
|
-
|
|
96
|
-
|
|
97
|
+
if expected_type == str and not isinstance(value, str):
|
|
98
|
+
raise TypeError(f"Argument '{argument}' with value {value} is not a string")
|
|
99
|
+
else:
|
|
100
|
+
# for other data types (or custom functions), just try to cast it to the expected type
|
|
101
|
+
value = expected_type(value)
|
|
102
|
+
except (ValueError, TypeError) as e:
|
|
97
103
|
msg = "Argument '%s' with value %r, has an incorrect data type: " % (argument, value)
|
|
98
|
-
msg += "%s. It must be %s" % (type(value),
|
|
99
|
-
|
|
104
|
+
msg += "%s. It must be convertible by %s" % (type(value), expected_type.__name__)
|
|
105
|
+
if str(e):
|
|
106
|
+
msg += f" (Error: {e})"
|
|
107
|
+
raise WMSpecFactoryException(msg) from None
|
|
108
|
+
except Exception as e:
|
|
109
|
+
msg = f"Generic exception raised during argument validation for argument: {argument} "
|
|
110
|
+
msg += "with value: %r. Error details: %s" % (value, str(e))
|
|
111
|
+
raise WMSpecFactoryException(msg) from None
|
|
100
112
|
|
|
101
113
|
_validateArgFunction(argument, value, argumentDefinition["validate"])
|
|
102
114
|
return value
|
WMCore/__init__.py
CHANGED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: wmglobalqueue
|
|
3
|
+
Version: 2.4.2
|
|
4
|
+
Home-page: https://github.com/dmwm/WMCore
|
|
5
|
+
Maintainer: CMS DMWM Group
|
|
6
|
+
Maintainer-email: hn-cms-wmdevelopment@cern.ch
|
|
7
|
+
License: Apache License, Version 2.0
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
License-File: NOTICE
|
|
10
|
+
Requires-Dist: CherryPy~=18.10.0
|
|
11
|
+
Requires-Dist: CMSMonitoring~=0.6.13
|
|
12
|
+
Requires-Dist: dbs3-client==4.0.19
|
|
13
|
+
Requires-Dist: future~=1.0.0
|
|
14
|
+
Requires-Dist: httplib2~=0.22.0
|
|
15
|
+
Requires-Dist: psutil~=7.0.0
|
|
16
|
+
Requires-Dist: pycurl~=7.45.6
|
|
17
|
+
Requires-Dist: retry~=0.9.2
|
|
18
|
+
Requires-Dist: rucio-clients~=36.5.0
|
|
19
|
+
Requires-Dist: Sphinx~=5.3.0
|
|
20
|
+
Requires-Dist: PyJWT~=2.9.0
|
|
21
|
+
Dynamic: home-page
|
|
22
|
+
Dynamic: license
|
|
23
|
+
Dynamic: license-file
|
|
24
|
+
Dynamic: maintainer
|
|
25
|
+
Dynamic: maintainer-email
|
|
26
|
+
Dynamic: requires-dist
|