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.
@@ -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,2 @@
1
+ # GreenDIRAC
2
+ DIRAC developments for the GreenDIGIT Project
@@ -0,0 +1,3 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
@@ -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,3 @@
1
+ from setuptools import setup
2
+
3
+ setup()
@@ -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
@@ -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
+ GreenDIRAC