greendirac 0.0.0a1__tar.gz
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.
- greendirac-0.0.0a1/PKG-INFO +15 -0
- greendirac-0.0.0a1/README.md +2 -0
- greendirac-0.0.0a1/pyproject.toml +3 -0
- greendirac-0.0.0a1/setup.cfg +27 -0
- greendirac-0.0.0a1/setup.py +3 -0
- greendirac-0.0.0a1/src/GreenDIRAC/WorkloadManagementSystem/Agent/GreenReportingAgent.py +226 -0
- greendirac-0.0.0a1/src/GreenDIRAC/WorkloadManagementSystem/Agent/__init__.py +0 -0
- greendirac-0.0.0a1/src/GreenDIRAC/WorkloadManagementSystem/__init__.py +0 -0
- greendirac-0.0.0a1/src/GreenDIRAC/__init__.py +0 -0
- greendirac-0.0.0a1/src/greendirac.egg-info/PKG-INFO +15 -0
- greendirac-0.0.0a1/src/greendirac.egg-info/SOURCES.txt +12 -0
- greendirac-0.0.0a1/src/greendirac.egg-info/dependency_links.txt +1 -0
- greendirac-0.0.0a1/src/greendirac.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: greendirac
|
|
3
|
+
Version: 0.0.0a1
|
|
4
|
+
Summary: GreenDIRAC is a DIRAC extension for the GreenDIGIT project
|
|
5
|
+
Home-page: https://github.com/GreenDIGIT-project/GreenDIRAC
|
|
6
|
+
Author: GreenDIRAC
|
|
7
|
+
Author-email: atsareg@in2p3.fr
|
|
8
|
+
License: GPLv3
|
|
9
|
+
Programming Language :: Python :: 3
|
|
10
|
+
Operating System :: OS Independent
|
|
11
|
+
Requires-Python: >=3.11
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
|
|
14
|
+
# GreenDIRAC
|
|
15
|
+
DIRAC developments for the GreenDIGIT Project
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
[metadata]
|
|
2
|
+
name = greendirac
|
|
3
|
+
version = 0.0.0a1
|
|
4
|
+
author = GreenDIRAC
|
|
5
|
+
author_email = atsareg@in2p3.fr
|
|
6
|
+
description = GreenDIRAC is a DIRAC extension for the GreenDIGIT project
|
|
7
|
+
long_description = file: README.md
|
|
8
|
+
long_description_content_type = text/markdown
|
|
9
|
+
url = https://github.com/GreenDIGIT-project/GreenDIRAC
|
|
10
|
+
license = GPLv3
|
|
11
|
+
Programming Language :: Python :: 3
|
|
12
|
+
Operating System :: OS Independent
|
|
13
|
+
|
|
14
|
+
[options]
|
|
15
|
+
package_dir =
|
|
16
|
+
= src
|
|
17
|
+
packages = find:
|
|
18
|
+
python_requires = >=3.11
|
|
19
|
+
include_package_data = True
|
|
20
|
+
|
|
21
|
+
[options.packages.find]
|
|
22
|
+
where = src
|
|
23
|
+
|
|
24
|
+
[egg_info]
|
|
25
|
+
tag_build =
|
|
26
|
+
tag_date = 0
|
|
27
|
+
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import pprint
|
|
2
|
+
import requests
|
|
3
|
+
from DIRAC import S_OK, S_ERROR, gConfig
|
|
4
|
+
from DIRAC.Core.Base.AgentModule import AgentModule
|
|
5
|
+
from DIRAC.WorkloadManagementSystem.Client import JobStatus
|
|
6
|
+
from DIRAC.WorkloadManagementSystem.DB.JobDB import JobDB
|
|
7
|
+
from DIRAC.ConfigurationSystem.Client.Helpers.Operations import Operations
|
|
8
|
+
from DIRAC.Core.Utilities.ObjectLoader import ObjectLoader
|
|
9
|
+
from DIRAC.ConfigurationSystem.Client.Helpers import Registry
|
|
10
|
+
from DIRAC.ConfigurationSystem.Client import PathFinder
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
JOB_PARAMETER_KEYS = ["ModelName",
|
|
14
|
+
"CPUNormalizationFactor",
|
|
15
|
+
"HostName",
|
|
16
|
+
"JobID",
|
|
17
|
+
"JobType",
|
|
18
|
+
"LoadAverage",
|
|
19
|
+
"MemoryUsed(kb)",
|
|
20
|
+
"NormCPUTime(s)",
|
|
21
|
+
"ScaledCPUTime(s)",
|
|
22
|
+
"Status",
|
|
23
|
+
"TotalCPUTime(s)",
|
|
24
|
+
"WallClockTime(s)",
|
|
25
|
+
"DiskSpace(MB)",
|
|
26
|
+
"CEQueue",
|
|
27
|
+
"GridCE",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
JOB_ATTRIBUTE_KEYS = [
|
|
31
|
+
"JobGroup",
|
|
32
|
+
"JobName",
|
|
33
|
+
"Owner",
|
|
34
|
+
"OwnerDN",
|
|
35
|
+
"OwnerGroup",
|
|
36
|
+
"RescheduleCounter",
|
|
37
|
+
"Site",
|
|
38
|
+
"SubmissionTime",
|
|
39
|
+
"StartExecTime",
|
|
40
|
+
"EndExecTime",
|
|
41
|
+
"SystemPriority",
|
|
42
|
+
"UserPriority",
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
TIME_STAMPS = [
|
|
46
|
+
"SubmissionTime",
|
|
47
|
+
"StartExecTime",
|
|
48
|
+
"EndExecTime",
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
# Some tentative values
|
|
52
|
+
DEFAULT_CI = 24
|
|
53
|
+
DEFAULT_PUE = 1.5
|
|
54
|
+
DEFAULT_TDP = 150
|
|
55
|
+
|
|
56
|
+
# Getting tokens at
|
|
57
|
+
|
|
58
|
+
METRICS_DB_URL = "https://mc-a4.lab.uvalight.net/gd-cim-api/submit"
|
|
59
|
+
METRICS_DB_TOKEN = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhdHNhcmVnQGluMnAzLmZyIiwiaXNzIjoiZ3JlZW5kaWdpdC1sb2dpbi11dmEiLCJpYXQiOjE3NTkzMDA5ODYsIm5iZiI6MTc1OTMwMDk4NiwiZXhwIjoxNzU5Mzg3Mzg2fQ.A4nygJEdhvOQjkLe-ckRDidqVbi6-s4kZXLRUZkwek8"
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class GreenReportingAgent(AgentModule):
|
|
63
|
+
"""
|
|
64
|
+
Agent for removing jobs in status "Deleted", and not only
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
def __init__(self, *args, **kwargs):
|
|
68
|
+
"""c'tor"""
|
|
69
|
+
super().__init__(*args, **kwargs)
|
|
70
|
+
|
|
71
|
+
# clients
|
|
72
|
+
self.jobDB = None
|
|
73
|
+
|
|
74
|
+
self.maxJobsAtOnce = 50
|
|
75
|
+
self.section = PathFinder.getAgentSection(self.agentName)
|
|
76
|
+
|
|
77
|
+
#############################################################################
|
|
78
|
+
def initialize(self):
|
|
79
|
+
"""Sets defaults"""
|
|
80
|
+
|
|
81
|
+
self.jobDB = JobDB()
|
|
82
|
+
self.elasticJobParametersDB = None
|
|
83
|
+
useESForJobParametersFlag = Operations().getValue("/Services/JobMonitoring/useESForJobParametersFlag", False)
|
|
84
|
+
if useESForJobParametersFlag:
|
|
85
|
+
try:
|
|
86
|
+
result = ObjectLoader().loadObject(
|
|
87
|
+
"WorkloadManagementSystem.DB.ElasticJobParametersDB", "ElasticJobParametersDB"
|
|
88
|
+
)
|
|
89
|
+
if not result["OK"]:
|
|
90
|
+
return result
|
|
91
|
+
self.elasticJobParametersDB = result["Value"](parentLogger=self.log)
|
|
92
|
+
except RuntimeError as excp:
|
|
93
|
+
return S_ERROR(f"Can't connect to ES DB: {excp}")
|
|
94
|
+
|
|
95
|
+
self.maxJobsAtOnce = self.am_getOption("MaxJobsAtOnce", self.maxJobsAtOnce)
|
|
96
|
+
|
|
97
|
+
self.cpuDict = {}
|
|
98
|
+
result = gConfig.getSections(f"{self.section}/CPUData")
|
|
99
|
+
if result["OK"]:
|
|
100
|
+
models = result["Value"]
|
|
101
|
+
for model in models:
|
|
102
|
+
self.cpuDict[model] = {}
|
|
103
|
+
self.cpuDict[model]["TDP"] = gConfig.getValue(f"{self.section}/CPUData/{model}/TDP", DEFAULT_TDP)
|
|
104
|
+
self.cpuDict[model]["Cores"] = gConfig.getValue(f"{self.section}/CPUData/{model}/Cores", 12)
|
|
105
|
+
|
|
106
|
+
print("AT >>> CPU data")
|
|
107
|
+
pprint.pprint(self.cpuDict)
|
|
108
|
+
|
|
109
|
+
return S_OK()
|
|
110
|
+
|
|
111
|
+
def execute(self):
|
|
112
|
+
"""Report job green parameters"""
|
|
113
|
+
|
|
114
|
+
condDict = {"Status": [JobStatus.DONE, JobStatus.FAILED], "ApplicationNumStatus": 0}
|
|
115
|
+
result = self.jobDB.selectJobs(condDict, limit=self.maxJobsAtOnce, orderAttribute="LastUpdateTime:DESC" )
|
|
116
|
+
if not result["OK"]:
|
|
117
|
+
return result
|
|
118
|
+
|
|
119
|
+
jobList = result["Value"]
|
|
120
|
+
if not jobList:
|
|
121
|
+
self.log.info("No jobs to report")
|
|
122
|
+
return S_OK()
|
|
123
|
+
|
|
124
|
+
print("Job List", jobList)
|
|
125
|
+
|
|
126
|
+
result = self.elasticJobParametersDB.getJobParameters(jobList)
|
|
127
|
+
if not result["OK"]:
|
|
128
|
+
self.log.info("No parameters found")
|
|
129
|
+
return S_ERROR("No parameters found")
|
|
130
|
+
jobParamsDict = result["Value"]
|
|
131
|
+
|
|
132
|
+
result = self.jobDB.getJobsAttributes(jobList)
|
|
133
|
+
if not result["OK"]:
|
|
134
|
+
self.log.info("No attributes found")
|
|
135
|
+
return S_ERROR("No attributes found")
|
|
136
|
+
jobAttrDict = result["Value"]
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
#pprint.pprint(jo)
|
|
140
|
+
#pprint.pprint(jobAttrDict)
|
|
141
|
+
print("hello world")
|
|
142
|
+
# Form records
|
|
143
|
+
records = []
|
|
144
|
+
for job in jobParamsDict:
|
|
145
|
+
jobDict = {}
|
|
146
|
+
for key in jobParamsDict[job]:
|
|
147
|
+
if key in JOB_PARAMETER_KEYS:
|
|
148
|
+
jobDict[key] = jobParamsDict[job][key]
|
|
149
|
+
for key in jobAttrDict[job]:
|
|
150
|
+
if key in JOB_ATTRIBUTE_KEYS:
|
|
151
|
+
if key in TIME_STAMPS:
|
|
152
|
+
jobDict[key] = str(jobAttrDict[job][key])
|
|
153
|
+
else:
|
|
154
|
+
jobDict[key] = jobAttrDict[job][key]
|
|
155
|
+
|
|
156
|
+
records.append(jobDict)
|
|
157
|
+
|
|
158
|
+
# Mark jobs as reported
|
|
159
|
+
result = self.jobDB.setJobAttributes(jobList, ["ApplicationNumStatus"], [9999])
|
|
160
|
+
if not result["OK"]:
|
|
161
|
+
self.log.error(f"Failed to set ApplicationNumStatus for job {job}", result["Message"])
|
|
162
|
+
|
|
163
|
+
#for record in records:
|
|
164
|
+
# pprint.pprint(record)
|
|
165
|
+
|
|
166
|
+
# Get the processor TDP
|
|
167
|
+
for record in records:
|
|
168
|
+
result = self.__getProcessorParameters(record.get("ModelName", "Unknown"))
|
|
169
|
+
if not result["OK"]:
|
|
170
|
+
self.log.error("Failed to get processor parameters")
|
|
171
|
+
continue
|
|
172
|
+
tdp, n_cores = result["Value"]
|
|
173
|
+
site = record.get("Site", "Unknown")
|
|
174
|
+
result = self.__getSiteParameters(record["Site"])
|
|
175
|
+
if not result["OK"]:
|
|
176
|
+
self.log.error("Failed to get site parameters")
|
|
177
|
+
continue
|
|
178
|
+
pue, ci, gocdb_name = result["Value"]
|
|
179
|
+
cpu = record.get("TotalCPUTime(s)", 0)
|
|
180
|
+
cpu = float(cpu)
|
|
181
|
+
record["Energy(kwh)"] = cpu*tdp/n_cores/1000./3600.
|
|
182
|
+
record["TDP"] = tdp
|
|
183
|
+
record["NCores"] = n_cores
|
|
184
|
+
record["VO"] = Registry.getVOForGroup(record["OwnerGroup"])
|
|
185
|
+
record["SiteName"] = gocdb_name
|
|
186
|
+
|
|
187
|
+
for record in records:
|
|
188
|
+
pprint.pprint(record)
|
|
189
|
+
result = self.__sendRecordToMB(record)
|
|
190
|
+
|
|
191
|
+
# Send records to the Metrics DB
|
|
192
|
+
|
|
193
|
+
return S_OK()
|
|
194
|
+
|
|
195
|
+
def __sendRecordToMB(self, record):
|
|
196
|
+
|
|
197
|
+
headers = { "Authorization": f"Bearer {METRICS_DB_TOKEN}",
|
|
198
|
+
"Content-Type": "application/json"
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
response = requests.post(METRICS_DB_URL,
|
|
202
|
+
headers = headers,
|
|
203
|
+
json = record
|
|
204
|
+
)
|
|
205
|
+
print(response.status_code)
|
|
206
|
+
print(response.text)
|
|
207
|
+
|
|
208
|
+
return S_OK()
|
|
209
|
+
|
|
210
|
+
def __getSiteParameters(self, site):
|
|
211
|
+
""" To be implemented """
|
|
212
|
+
|
|
213
|
+
grid = site.split(".")[0]
|
|
214
|
+
gocdb_name = gConfig.getValue(f"/Resources/Sites/{grid}/{site}/Name", site)
|
|
215
|
+
pue = gConfig.getValue(f"/Resources/Sites/{grid}/{site}/GreenParams/PUE", DEFAULT_PUE)
|
|
216
|
+
ci = gConfig.getValue(f"/Resources/Sites/{grid}/{site}/GreenParams/CI", DEFAULT_CI)
|
|
217
|
+
return S_OK((pue, ci, gocdb_name))
|
|
218
|
+
|
|
219
|
+
def __getProcessorParameters(self, model):
|
|
220
|
+
""" Get TDP and number of cores """
|
|
221
|
+
|
|
222
|
+
if model in self.cpuDict:
|
|
223
|
+
return S_OK((self.cpuDict[model]["TDP"], self.cpuDict[model]["Cores"]))
|
|
224
|
+
|
|
225
|
+
print(f"AT >>> oooooooooooooo CPU Model {model} is not in the configuration ooooooooooooooo")
|
|
226
|
+
return S_OK((200, 12))
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: greendirac
|
|
3
|
+
Version: 0.0.0a1
|
|
4
|
+
Summary: GreenDIRAC is a DIRAC extension for the GreenDIGIT project
|
|
5
|
+
Home-page: https://github.com/GreenDIGIT-project/GreenDIRAC
|
|
6
|
+
Author: GreenDIRAC
|
|
7
|
+
Author-email: atsareg@in2p3.fr
|
|
8
|
+
License: GPLv3
|
|
9
|
+
Programming Language :: Python :: 3
|
|
10
|
+
Operating System :: OS Independent
|
|
11
|
+
Requires-Python: >=3.11
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
|
|
14
|
+
# GreenDIRAC
|
|
15
|
+
DIRAC developments for the GreenDIGIT Project
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
setup.cfg
|
|
4
|
+
setup.py
|
|
5
|
+
src/GreenDIRAC/__init__.py
|
|
6
|
+
src/GreenDIRAC/WorkloadManagementSystem/__init__.py
|
|
7
|
+
src/GreenDIRAC/WorkloadManagementSystem/Agent/GreenReportingAgent.py
|
|
8
|
+
src/GreenDIRAC/WorkloadManagementSystem/Agent/__init__.py
|
|
9
|
+
src/greendirac.egg-info/PKG-INFO
|
|
10
|
+
src/greendirac.egg-info/SOURCES.txt
|
|
11
|
+
src/greendirac.egg-info/dependency_links.txt
|
|
12
|
+
src/greendirac.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
GreenDIRAC
|