Skip to content

Commit c3b1414

Browse files
chore: change workflow commons from dict to a pydantic model
1 parent 1987844 commit c3b1414

9 files changed

Lines changed: 996 additions & 1282 deletions

src/dirac_cwl/commands/analyze_xml_summary.py

Lines changed: 22 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2,84 +2,61 @@
22

33
import os
44

5-
from DIRAC.TransformationSystem.Client.FileReport import FileReport
6-
from DIRAC.WorkloadManagementSystem.Client.JobReport import JobReport
7-
from LHCbDIRAC.Core.Utilities.XMLSummaries import XMLSummary
85
from LHCbDIRAC.Workflow.Modules.AnalyseXMLSummary import _areInputsOK, _isXMLSummaryOK
96
from LHCbDIRAC.Workflow.Modules.BookkeepingReport import _generate_xml_object
107

118
from dirac_cwl.core.exceptions import WorkflowProcessingException
129

1310
from .core import PostProcessCommand
14-
from .utils import prepare_lhcb_workflow_commons, save_workflow_commons
11+
from .workflow_commons import StepStatus, WorkflowCommons
1512

1613

1714
class AnalyseXmlSummary(PostProcessCommand):
1815
"""Performs a series of checks on the XMLSummary output to make sure the execution was done correctly."""
1916

20-
def execute(self, job_path, **kwargs):
17+
def execute(self, job_path: os.PathLike, **kwargs):
2118
"""Execute the command.
2219
2320
:param job_path: Path to the job working directory.
2421
:param kwargs: Additional keyword arguments.
2522
"""
2623
failed = False
27-
workflow_commons = {}
24+
workflow_commons = None
2825
try:
29-
workflow_commons_path = kwargs.get("workflow_commons_path", os.path.join(job_path, "workflow_commons.json"))
26+
workflow_commons = WorkflowCommons.load(job_path)
3027

31-
workflow_commons = prepare_lhcb_workflow_commons(
32-
workflow_commons_path,
33-
extra_mandatory_values=[
34-
"bk_step_id",
35-
],
36-
extra_default_values={
37-
"bookkeeping_LFNs": [],
38-
"size": {},
39-
"md5": {},
40-
"guid": {},
41-
"sim_description": "NoSimConditions",
42-
},
43-
)
44-
45-
if not workflow_commons["step_status"]["OK"]:
28+
if workflow_commons.step_status == StepStatus.Failed:
4629
return
4730

48-
if "xml_summary_path" in workflow_commons:
49-
xf_o = XMLSummary(workflow_commons["xml_summary_path"])
50-
else:
51-
xf_o = _generate_xml_object(
52-
workflow_commons["cleaned_application_name"],
53-
workflow_commons["production_id"],
54-
workflow_commons["prod_job_id"],
55-
workflow_commons["command_number"],
56-
workflow_commons["command_id"],
31+
if not workflow_commons.xf_o:
32+
workflow_commons.xf_o = _generate_xml_object(
33+
workflow_commons.cleaned_application_name,
34+
workflow_commons.production_id,
35+
workflow_commons.prod_job_id,
36+
workflow_commons.step_number,
37+
workflow_commons.step_id,
5738
)
5839

59-
file_report = FileReport()
60-
job_report = JobReport(workflow_commons["job_id"])
61-
62-
file_report.statusDict = workflow_commons["file_report_files_dict"]
63-
64-
jobOk = _isXMLSummaryOK(xf_o)
40+
jobOk = _isXMLSummaryOK(workflow_commons.xf_o)
6541

6642
if jobOk:
6743
jobOk = _areInputsOK(
68-
xf_o,
69-
workflow_commons["inputs"],
70-
workflow_commons["number_of_events"],
71-
workflow_commons["production_id"],
72-
file_report,
44+
workflow_commons.xf_o,
45+
workflow_commons.inputs,
46+
workflow_commons.number_of_events,
47+
workflow_commons.production_id,
48+
workflow_commons.file_report,
7349
)
7450
if not jobOk:
75-
job_report.setApplicationStatus("XMLSummary reports error")
51+
workflow_commons.job_report.setApplicationStatus("XMLSummary reports error")
7652
raise WorkflowProcessingException("XMLSummary reports error")
7753

78-
job_report.setApplicationStatus(f"{workflow_commons['application_name']} Step OK")
54+
workflow_commons.job_report.setApplicationStatus(f"{workflow_commons.application_name} Step OK")
7955

8056
except Exception as e:
8157
failed = True
8258
raise WorkflowProcessingException(e) from e
8359

8460
finally:
85-
save_workflow_commons(workflow_commons, workflow_commons_path, failed=failed)
61+
if workflow_commons:
62+
workflow_commons.save(job_path, failed=failed)

src/dirac_cwl/commands/bookkeeping_report.py

Lines changed: 52 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@
33
import os
44

55
from DIRAC.Workflow.Utilities.Utils import getStepCPUTimes
6-
from LHCbDIRAC.BookkeepingSystem.Client.BookkeepingClient import BookkeepingClient
76
from LHCbDIRAC.Core.Utilities.ProductionData import constructProductionLFNs
8-
from LHCbDIRAC.Core.Utilities.XMLSummaries import XMLSummary
97
from LHCbDIRAC.Workflow.Modules.BookkeepingReport import (
108
_generate_xml_object,
119
_generateInputFiles,
@@ -18,105 +16,85 @@
1816
from dirac_cwl.core.exceptions import WorkflowProcessingException
1917

2018
from .core import PostProcessCommand
21-
from .utils import prepare_lhcb_workflow_commons, save_workflow_commons
19+
from .workflow_commons import StepStatus, WorkflowCommons
2220

2321

2422
class BookkeepingReport(PostProcessCommand):
2523
"""Generates a bookkeeping report file based on the XMLSummary and the pool XML catalog."""
2624

27-
def execute(self, job_path, **kwargs):
25+
def execute(self, job_path: os.PathLike, **kwargs):
2826
"""Execute the command.
2927
3028
:param job_path: Path to the job working directory.
3129
:param kwargs: Additional keyword arguments.
3230
"""
3331
failed = False
34-
workflow_commons = {}
32+
workflow_commons = None
3533
try:
3634
# Obtain Workflow Commons
37-
workflow_commons_path = kwargs.get("workflow_commons_path", os.path.join(job_path, "workflow_commons.json"))
38-
39-
workflow_commons = prepare_lhcb_workflow_commons(
40-
workflow_commons_path,
41-
extra_mandatory_values=[
42-
"bk_step_id",
43-
],
44-
extra_default_values={
45-
"bookkeeping_LFNs": [],
46-
"size": {},
47-
"md5": {},
48-
"guid": {},
49-
"sim_description": "NoSimConditions",
50-
},
51-
)
35+
workflow_commons = WorkflowCommons.load(job_path)
5236

53-
if not workflow_commons["step_status"]["OK"]:
37+
if workflow_commons.step_status == StepStatus.Failed:
5438
return
5539

5640
# Setup variables
57-
start_time = workflow_commons.get("start_time", None)
58-
5941
cpu_times = {}
60-
if start_time:
61-
cpu_times["StartTime"] = start_time
62-
if "start_stats" in workflow_commons:
63-
cpu_times["StartStats"] = workflow_commons["start_stats"]
42+
if workflow_commons.start_time:
43+
cpu_times["StartTime"] = workflow_commons.start_time
44+
if workflow_commons.start_stats:
45+
cpu_times["StartStats"] = workflow_commons.start_stats
6446

6547
exectime, cputime = getStepCPUTimes(cpu_times)
6648

6749
number_of_processors = getNumberOfProcessorsToUse(
68-
workflow_commons["job_id"], workflow_commons["max_number_of_processors"]
50+
workflow_commons.job_id, workflow_commons.max_number_of_processors
6951
)
7052

71-
bk_client = BookkeepingClient()
72-
7353
parameters = {
74-
"PRODUCTION_ID": workflow_commons["production_id"],
75-
"JOB_ID": workflow_commons["prod_job_id"],
76-
"configVersion": workflow_commons["config_version"],
77-
"outputList": workflow_commons["outputs"],
78-
"configName": workflow_commons["config_name"],
79-
"outputDataFileMask": workflow_commons["output_data_file_mask"],
54+
"PRODUCTION_ID": workflow_commons.production_id,
55+
"JOB_ID": workflow_commons.prod_job_id,
56+
"configVersion": workflow_commons.config_version,
57+
"outputList": workflow_commons.outputs,
58+
"configName": workflow_commons.config_name,
59+
"outputDataFileMask": workflow_commons.output_data_file_mask,
8060
}
8161

82-
if "bookkeeping_LFNs" in workflow_commons and "production_output_data" in workflow_commons:
83-
bk_lfns = workflow_commons["bookkeeping_LFNs"]
62+
if workflow_commons.bookkeeping_lfns and workflow_commons.production_output_data:
63+
bk_lfns = workflow_commons.bookkeeping_lfns
8464

8565
if not isinstance(bk_lfns, list):
8666
bk_lfns = [i.strip() for i in bk_lfns.split(";")]
8767

8868
else:
89-
result = constructProductionLFNs(parameters, bk_client)
69+
result = constructProductionLFNs(parameters, workflow_commons.bk_client)
9070
if not result["OK"]:
9171
raise WorkflowProcessingException("Could not create production LFNs")
9272

9373
bk_lfns = result["Value"]["BookkeepingLFNs"]
9474

95-
ldate, ltime, ldatestart, ltimestart = _process_time(start_time)
75+
ldate, ltime, ldatestart, ltimestart = _process_time(workflow_commons.start_time)
9676

9777
# Obtain XMLSummary
98-
if "xml_summary_path" in workflow_commons:
99-
xf_o = XMLSummary(workflow_commons["xml_summary_path"])
100-
else:
101-
xf_o = _generate_xml_object(
102-
workflow_commons["cleaned_application_name"],
103-
workflow_commons["production_id"],
104-
workflow_commons["prod_job_id"],
105-
workflow_commons["command_number"],
106-
workflow_commons["command_id"],
78+
if not workflow_commons.xf_o:
79+
workflow_commons.xf_o = _generate_xml_object(
80+
workflow_commons.cleaned_application_name,
81+
workflow_commons.production_id,
82+
workflow_commons.prod_job_id,
83+
workflow_commons.step_number,
84+
workflow_commons.step_id,
10785
)
10886

10987
info_dict = {
11088
"exectime": exectime,
11189
"cputime": cputime,
11290
"numberOfProcessors": number_of_processors,
113-
"production_id": workflow_commons["production_id"],
114-
"jobID": workflow_commons["job_id"],
115-
"siteName": workflow_commons["site_name"],
116-
"jobType": workflow_commons["job_type"],
117-
"applicationName": workflow_commons["application_name"],
118-
"applicationVersion": workflow_commons["application_version"],
119-
"numberOfEvents": workflow_commons["number_of_events"],
91+
"production_id": workflow_commons.production_id,
92+
"jobID": workflow_commons.job_id,
93+
"siteName": workflow_commons.site_name,
94+
"jobType": workflow_commons.job_type,
95+
"applicationName": workflow_commons.application_name,
96+
"applicationVersion": workflow_commons.application_version,
97+
"numberOfEvents": workflow_commons.number_of_events,
12098
}
12199

122100
# Generate job_info object
@@ -126,38 +104,38 @@ def execute(self, job_path, **kwargs):
126104
ltimestart,
127105
ldate,
128106
ltime,
129-
xf_o,
130-
workflow_commons["inputs"],
131-
workflow_commons["command_id"],
132-
workflow_commons["bk_step_id"],
133-
bk_client,
134-
workflow_commons["config_name"],
135-
workflow_commons["config_version"],
107+
workflow_commons.xf_o,
108+
workflow_commons.inputs,
109+
workflow_commons.step_id,
110+
workflow_commons.bk_step_id,
111+
workflow_commons.bk_client,
112+
workflow_commons.config_name,
113+
workflow_commons.config_version,
136114
)
137115

138116
# Add input files to job_info
139-
_generateInputFiles(job_info, bk_lfns, workflow_commons["inputs"])
117+
_generateInputFiles(job_info, bk_lfns, workflow_commons.inputs)
140118

141119
# Add output files to job_info
142120
_generateOutputFiles(
143121
job_info,
144122
bk_lfns,
145-
workflow_commons["event_type"],
146-
workflow_commons["application_name"],
147-
xf_o,
148-
workflow_commons["outputs"],
149-
workflow_commons["inputs"],
123+
workflow_commons.event_type,
124+
workflow_commons.application_name,
125+
workflow_commons.xf_o,
126+
workflow_commons.outputs,
127+
workflow_commons.inputs,
150128
)
151129

152130
# Generate SimulationConditions
153-
if workflow_commons["application_name"] == "Gauss":
154-
job_info.simulation_condition = workflow_commons["sim_description"]
131+
if workflow_commons.application_name == "Gauss":
132+
job_info.simulation_condition = workflow_commons.sim_description
155133

156134
# Convert job_info object to XML
157135
doc = job_info.to_xml()
158136

159137
# Write to file
160-
bfilename = f"bookkeeping_{workflow_commons['command_id']}.xml"
138+
bfilename = f"bookkeeping_{workflow_commons.step_id}.xml"
161139
with open(bfilename, "wb") as bfile:
162140
bfile.write(doc)
163141

@@ -166,4 +144,5 @@ def execute(self, job_path, **kwargs):
166144
raise WorkflowProcessingException(e) from e
167145

168146
finally:
169-
save_workflow_commons(workflow_commons, workflow_commons_path, failed=failed)
147+
if workflow_commons:
148+
workflow_commons.save(job_path, failed=failed)

0 commit comments

Comments
 (0)