blob: 992bdc8a73281e4ddbc9a2d5d0acd4064b5da589 [file] [log] [blame]
Nan Zhou313c1b72022-03-25 11:47:55 -07001#!/usr/bin/env python3
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -06002import argparse
Jason M. Bills70304cb2019-03-27 12:03:59 -07003import json
Nan Zhou6eaf0bd2022-08-07 01:18:45 +00004import os
Igor Kanyukada9dc902025-02-26 14:08:11 +00005import typing as t
Ed Tanous42079ec2024-11-16 13:32:29 -08006from collections import OrderedDict
Jason M. Bills70304cb2019-03-27 12:03:59 -07007
Nan Zhou6eaf0bd2022-08-07 01:18:45 +00008import requests
Jason M. Bills70304cb2019-03-27 12:03:59 -07009
Igor Kanyukada9dc902025-02-26 14:08:11 +000010PRAGMA_ONCE: t.Final[
11 str
12] = """#pragma once
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -060013"""
Nan Zhou043bec02022-09-20 18:12:13 +000014
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -060015WARNING = """/****************************************************************
Ed Tanous1cf53df2022-02-17 09:09:25 -080016 * READ THIS WARNING FIRST
Jason M. Bills70304cb2019-03-27 12:03:59 -070017 * This is an auto-generated header which contains definitions
18 * for Redfish DMTF defined messages.
Ed Tanous1cf53df2022-02-17 09:09:25 -080019 * DO NOT modify this registry outside of running the
Jason M. Bills0e2d0692022-04-01 13:59:05 -070020 * parse_registries.py script. The definitions contained within
Ed Tanous1cf53df2022-02-17 09:09:25 -080021 * this file are owned by DMTF. Any modifications to these files
22 * should be first pushed to the relevant registry in the DMTF
23 * github organization.
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -060024 ***************************************************************/"""
Ed Tanous1cf53df2022-02-17 09:09:25 -080025
Igor Kanyukada9dc902025-02-26 14:08:11 +000026COPYRIGHT: t.Final[
27 str
28] = """// SPDX-License-Identifier: Apache-2.0
Ed Tanous40e9b922024-09-10 13:50:16 -070029// SPDX-FileCopyrightText: Copyright OpenBMC Authors
30"""
31
32INCLUDES = """
Nan Zhou01c78a02022-09-20 18:17:20 +000033#include "registries.hpp"
34
35#include <array>
Jason M. Bills70304cb2019-03-27 12:03:59 -070036
Ed Tanous4d99bbb2022-02-17 10:02:57 -080037// clang-format off
38
Ed Tanousfffb8c12022-02-07 23:53:03 -080039namespace redfish::registries::{}
Jason M. Bills70304cb2019-03-27 12:03:59 -070040{{
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -060041"""
Ed Tanous40e9b922024-09-10 13:50:16 -070042
Igor Kanyukada9dc902025-02-26 14:08:11 +000043REGISTRY_HEADER: t.Final[str] = f"{COPYRIGHT}{PRAGMA_ONCE}{WARNING}{INCLUDES}"
Jason M. Bills70304cb2019-03-27 12:03:59 -070044
Igor Kanyukada9dc902025-02-26 14:08:11 +000045SCRIPT_DIR: t.Final[str] = os.path.dirname(os.path.realpath(__file__))
Jason M. Bills70304cb2019-03-27 12:03:59 -070046
Igor Kanyukada9dc902025-02-26 14:08:11 +000047INCLUDE_PATH: t.Final[str] = os.path.realpath(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -060048 os.path.join(SCRIPT_DIR, "..", "redfish-core", "include", "registries")
49)
Jason M. Bills70304cb2019-03-27 12:03:59 -070050
Igor Kanyukada9dc902025-02-26 14:08:11 +000051PROXIES: t.Final[t.Dict[str, str]] = {
52 "https": os.environ.get("https_proxy", "")
53}
54
55RegistryInfo: t.TypeAlias = t.Tuple[str, t.Dict[str, t.Any], str, str]
Jason M. Bills70304cb2019-03-27 12:03:59 -070056
Jason M. Bills70304cb2019-03-27 12:03:59 -070057
Igor Kanyukada9dc902025-02-26 14:08:11 +000058def make_getter(
59 dmtf_name: str, header_name: str, type_name: str
60) -> RegistryInfo:
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -060061 url = "https://redfish.dmtf.org/registries/{}".format(dmtf_name)
Igor Kanyuka557ab0d2025-02-18 15:20:38 +000062 dmtf = requests.get(url, proxies=PROXIES)
James Feiste51c7102020-03-17 10:38:18 -070063 dmtf.raise_for_status()
Ed Tanous42079ec2024-11-16 13:32:29 -080064 json_file = json.loads(dmtf.text, object_pairs_hook=OrderedDict)
Igor Kanyuka557ab0d2025-02-18 15:20:38 +000065 path = os.path.join(INCLUDE_PATH, header_name)
James Feiste51c7102020-03-17 10:38:18 -070066 return (path, json_file, type_name, url)
67
68
Igor Kanyukada9dc902025-02-26 14:08:11 +000069def openbmc_local_getter() -> RegistryInfo:
Milton D. Miller II770362f2024-12-17 05:28:27 +000070 url = "https://raw.githubusercontent.com/openbmc/bmcweb/refs/heads/master/redfish-core/include/registries/openbmc.json"
Ed Tanous3e5faba2023-08-16 15:11:29 -070071 with open(
72 os.path.join(
73 SCRIPT_DIR,
74 "..",
75 "redfish-core",
76 "include",
77 "registries",
78 "openbmc.json",
79 ),
80 "rb",
Igor Kanyuka557ab0d2025-02-18 15:20:38 +000081 ) as json_file_fd:
82 json_file = json.load(json_file_fd)
Ed Tanous3e5faba2023-08-16 15:11:29 -070083
Igor Kanyuka557ab0d2025-02-18 15:20:38 +000084 path = os.path.join(INCLUDE_PATH, "openbmc_message_registry.hpp")
Ed Tanous3e5faba2023-08-16 15:11:29 -070085 return (path, json_file, "openbmc", url)
86
87
Igor Kanyukada9dc902025-02-26 14:08:11 +000088def update_registries(files: t.List[RegistryInfo]) -> None:
Nan Zhou49aa131f2022-09-20 18:41:37 +000089 # Remove the old files
90 for file, json_dict, namespace, url in files:
91 try:
92 os.remove(file)
93 except BaseException:
94 print("{} not found".format(file))
Jason M. Bills70304cb2019-03-27 12:03:59 -070095
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -060096 with open(file, "w") as registry:
Ed Tanous56b81992024-12-02 10:36:37 -080097 version_split = json_dict["RegistryVersion"].split(".")
98
Nan Zhou49aa131f2022-09-20 18:41:37 +000099 registry.write(REGISTRY_HEADER.format(namespace))
100 # Parse the Registry header info
Ed Tanous5b9ef702022-02-17 12:19:32 -0800101 registry.write(
Nan Zhou49aa131f2022-09-20 18:41:37 +0000102 "const Header header = {{\n"
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600103 ' "{json_dict[@Redfish.Copyright]}",\n'
104 ' "{json_dict[@odata.type]}",\n'
Ed Tanous56b81992024-12-02 10:36:37 -0800105 " {version_split[0]},\n"
106 " {version_split[1]},\n"
107 " {version_split[2]},\n"
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600108 ' "{json_dict[Name]}",\n'
109 ' "{json_dict[Language]}",\n'
110 ' "{json_dict[Description]}",\n'
111 ' "{json_dict[RegistryPrefix]}",\n'
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600112 ' "{json_dict[OwningEntity]}",\n'
Nan Zhou49aa131f2022-09-20 18:41:37 +0000113 "}};\n"
114 "constexpr const char* url =\n"
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600115 ' "{url}";\n'
Nan Zhou49aa131f2022-09-20 18:41:37 +0000116 "\n"
117 "constexpr std::array registry =\n"
118 "{{\n".format(
119 json_dict=json_dict,
120 url=url,
Ed Tanous56b81992024-12-02 10:36:37 -0800121 version_split=version_split,
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600122 )
123 )
Ed Tanous30a3c432022-02-07 09:37:21 -0800124
Nan Zhou49aa131f2022-09-20 18:41:37 +0000125 messages_sorted = sorted(json_dict["Messages"].items())
126 for messageId, message in messages_sorted:
127 registry.write(
128 " MessageEntry{{\n"
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600129 ' "{messageId}",\n'
Nan Zhou49aa131f2022-09-20 18:41:37 +0000130 " {{\n"
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600131 ' "{message[Description]}",\n'
132 ' "{message[Message]}",\n'
133 ' "{message[MessageSeverity]}",\n'
Nan Zhou49aa131f2022-09-20 18:41:37 +0000134 " {message[NumberOfArgs]},\n"
135 " {{".format(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600136 messageId=messageId, message=message
137 )
138 )
Nan Zhou49aa131f2022-09-20 18:41:37 +0000139 paramTypes = message.get("ParamTypes")
140 if paramTypes:
141 for paramType in paramTypes:
142 registry.write(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600143 '\n "{}",'.format(paramType)
Nan Zhou49aa131f2022-09-20 18:41:37 +0000144 )
145 registry.write("\n },\n")
146 else:
147 registry.write("},\n")
148 registry.write(
Igor Kanyukada9dc902025-02-26 14:08:11 +0000149 ' "{message[Resolution]}",\n }}}},\n'.format(
150 message=message
151 )
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600152 )
Nan Zhou49aa131f2022-09-20 18:41:37 +0000153
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600154 registry.write("\n};\n\nenum class Index\n{\n")
Nan Zhou49aa131f2022-09-20 18:41:37 +0000155 for index, (messageId, message) in enumerate(messages_sorted):
156 messageId = messageId[0].lower() + messageId[1:]
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600157 registry.write(" {} = {},\n".format(messageId, index))
Nan Zhou49aa131f2022-09-20 18:41:37 +0000158 registry.write(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600159 "}};\n}} // namespace redfish::registries::{}\n".format(
160 namespace
161 )
162 )
Ed Tanoused398212021-06-09 17:05:54 -0700163
164
Igor Kanyukada9dc902025-02-26 14:08:11 +0000165def get_privilege_string_from_list(
166 privilege_list: t.List[t.Dict[str, t.Any]],
167) -> str:
Ed Tanoused398212021-06-09 17:05:54 -0700168 privilege_string = "{{\n"
169 for privilege_json in privilege_list:
170 privileges = privilege_json["Privilege"]
171 privilege_string += " {"
Igor Kanyukada9dc902025-02-26 14:08:11 +0000172 last_privelege = ""
Ed Tanoused398212021-06-09 17:05:54 -0700173 for privilege in privileges:
Igor Kanyukada9dc902025-02-26 14:08:11 +0000174 last_privelege = privilege
Ed Tanoused398212021-06-09 17:05:54 -0700175 if privilege == "NoAuth":
176 continue
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600177 privilege_string += '"'
Ed Tanoused398212021-06-09 17:05:54 -0700178 privilege_string += privilege
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600179 privilege_string += '",\n'
Igor Kanyukada9dc902025-02-26 14:08:11 +0000180 if last_privelege != "NoAuth":
Ed Tanoused398212021-06-09 17:05:54 -0700181 privilege_string = privilege_string[:-2]
182 privilege_string += "}"
183 privilege_string += ",\n"
184 privilege_string = privilege_string[:-2]
185 privilege_string += "\n}}"
186 return privilege_string
187
Ed Tanousf395daa2021-08-02 08:56:24 -0700188
Igor Kanyukada9dc902025-02-26 14:08:11 +0000189def get_variable_name_for_privilege_set(
190 privilege_list: t.List[t.Dict[str, t.Any]],
191) -> str:
Ed Tanoused398212021-06-09 17:05:54 -0700192 names = []
193 for privilege_json in privilege_list:
194 privileges = privilege_json["Privilege"]
195 names.append("And".join(privileges))
196 return "Or".join(names)
197
Ed Tanousf395daa2021-08-02 08:56:24 -0700198
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600199PRIVILEGE_HEADER = (
Ed Tanous40e9b922024-09-10 13:50:16 -0700200 COPYRIGHT
201 + PRAGMA_ONCE
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600202 + WARNING
203 + """
Nan Zhou01c78a02022-09-20 18:17:20 +0000204#include "privileges.hpp"
205
206#include <array>
Nan Zhou043bec02022-09-20 18:12:13 +0000207
208// clang-format off
209
210namespace redfish::privileges
211{
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600212"""
213)
Nan Zhou043bec02022-09-20 18:12:13 +0000214
215
Igor Kanyukada9dc902025-02-26 14:08:11 +0000216def get_response_code(entry_id: str) -> str | None:
Ed Tanous7ccfe682024-11-16 14:36:16 -0800217 codes = {
218 "InternalError": "internal_server_error",
219 "OperationTimeout": "internal_server_error",
220 "PropertyValueResourceConflict": "conflict",
221 "ResourceInUse": "service_unavailable",
222 "ServiceTemporarilyUnavailable": "service_unavailable",
223 "ResourceCannotBeDeleted": "method_not_allowed",
224 "PropertyValueModified": "ok",
225 "InsufficientPrivilege": "forbidden",
226 "AccountForSessionNoLongerExists": "forbidden",
227 "ServiceDisabled": "service_unavailable",
228 "ServiceInUnknownState": "service_unavailable",
229 "EventSubscriptionLimitExceeded": "service_unavailable",
230 "ResourceAtUriUnauthorized": "unauthorized",
231 "SessionTerminated": "ok",
232 "SubscriptionTerminated": "ok",
233 "PropertyNotWritable": "forbidden",
234 "MaximumErrorsExceeded": "internal_server_error",
235 "GeneralError": "internal_server_error",
236 "PreconditionFailed": "precondition_failed",
237 "OperationFailed": "bad_gateway",
238 "ServiceShuttingDown": "service_unavailable",
239 "AccountRemoved": "ok",
240 "PropertyValueExternalConflict": "conflict",
241 "InsufficientStorage": "insufficient_storage",
242 "OperationNotAllowed": "method_not_allowed",
243 "ResourceNotFound": "not_found",
244 "CouldNotEstablishConnection": "not_found",
245 "AccessDenied": "forbidden",
246 "Success": None,
247 "Created": "created",
248 "NoValidSession": "forbidden",
249 "SessionLimitExceeded": "service_unavailable",
250 "ResourceExhaustion": "service_unavailable",
251 "AccountModified": "ok",
252 "PasswordChangeRequired": None,
253 "ResourceInStandby": "service_unavailable",
254 "GenerateSecretKeyRequired": "forbidden",
255 }
256
Igor Kanyuka557ab0d2025-02-18 15:20:38 +0000257 return codes.get(entry_id, "bad_request")
Ed Tanous7ccfe682024-11-16 14:36:16 -0800258
259
Ed Tanousf175c282024-12-02 15:12:50 -0800260def make_error_function(
Igor Kanyukada9dc902025-02-26 14:08:11 +0000261 entry_id: str,
262 entry: t.Dict[str, t.Any],
263 is_header: bool,
264 registry_name: str,
265 namespace_name: str,
266) -> str:
Ed Tanous644cdcb2024-11-17 11:12:41 -0800267 arg_nonstring_types = {
268 "const boost::urls::url_view_base&": {
269 "AccessDenied": [1],
270 "CouldNotEstablishConnection": [1],
271 "GenerateSecretKeyRequired": [1],
272 "InvalidObject": [1],
273 "PasswordChangeRequired": [1],
274 "PropertyValueResourceConflict": [3],
275 "ResetRequired": [1],
276 "ResourceAtUriInUnknownFormat": [1],
277 "ResourceAtUriUnauthorized": [1],
278 "ResourceCreationConflict": [1],
279 "ResourceMissingAtURI": [1],
280 "SourceDoesNotSupportProtocol": [1],
281 },
282 "const nlohmann::json&": {
283 "ActionParameterValueError": [1],
284 "ActionParameterValueFormatError": [1],
285 "ActionParameterValueTypeError": [1],
286 "PropertyValueExternalConflict": [2],
287 "PropertyValueFormatError": [1],
288 "PropertyValueIncorrect": [2],
289 "PropertyValueModified": [2],
290 "PropertyValueNotInList": [1],
291 "PropertyValueOutOfRange": [1],
292 "PropertyValueResourceConflict": [2],
293 "PropertyValueTypeError": [1],
294 "QueryParameterValueFormatError": [1],
295 "QueryParameterValueTypeError": [1],
296 },
297 "uint64_t": {
298 "ArraySizeTooLong": [2],
299 "InvalidIndex": [1],
300 "StringValueTooLong": [2],
Ed Tanousf175c282024-12-02 15:12:50 -0800301 "TaskProgressChanged": [2],
Ed Tanous644cdcb2024-11-17 11:12:41 -0800302 },
Ed Tanous42079ec2024-11-16 13:32:29 -0800303 }
304
Ed Tanous7ccfe682024-11-16 14:36:16 -0800305 out = ""
306 args = []
307 argtypes = []
308 for arg_index, arg in enumerate(entry.get("ParamTypes", [])):
309 arg_index += 1
Ed Tanous644cdcb2024-11-17 11:12:41 -0800310 typename = "std::string_view"
311 for typestring, entries in arg_nonstring_types.items():
312 if arg_index in entries.get(entry_id, []):
313 typename = typestring
314
Ed Tanous7ccfe682024-11-16 14:36:16 -0800315 argtypes.append(typename)
316 args.append(f"{typename} arg{arg_index}")
317 function_name = entry_id[0].lower() + entry_id[1:]
318 arg = ", ".join(args)
319 out += f"nlohmann::json {function_name}({arg})"
320
321 if is_header:
322 out += ";\n\n"
323 else:
324 out += "\n{\n"
325 to_array_type = ""
Igor Kanyukada9dc902025-02-26 14:08:11 +0000326 arg_param = "{}"
Ed Tanous7ccfe682024-11-16 14:36:16 -0800327 if argtypes:
328 outargs = []
329 for index, typename in enumerate(argtypes):
330 index += 1
331 if typename == "const nlohmann::json&":
332 out += f"std::string arg{index}Str = arg{index}.dump(-1, ' ', true, nlohmann::json::error_handler_t::replace);\n"
Ed Tanous644cdcb2024-11-17 11:12:41 -0800333 elif typename == "uint64_t":
Ed Tanous7ccfe682024-11-16 14:36:16 -0800334 out += f"std::string arg{index}Str = std::to_string(arg{index});\n"
335
336 for index, typename in enumerate(argtypes):
337 index += 1
338 if typename == "const boost::urls::url_view_base&":
339 outargs.append(f"arg{index}.buffer()")
340 to_array_type = "<std::string_view>"
341 elif typename == "const nlohmann::json&":
342 outargs.append(f"arg{index}Str")
343 to_array_type = "<std::string_view>"
Ed Tanous644cdcb2024-11-17 11:12:41 -0800344 elif typename == "uint64_t":
Ed Tanous7ccfe682024-11-16 14:36:16 -0800345 outargs.append(f"arg{index}Str")
346 to_array_type = "<std::string_view>"
347 else:
348 outargs.append(f"arg{index}")
349 argstring = ", ".join(outargs)
Ed Tanous7ccfe682024-11-16 14:36:16 -0800350 arg_param = f"std::to_array{to_array_type}({{{argstring}}})"
Ed Tanousf175c282024-12-02 15:12:50 -0800351 out += f" return getLog(redfish::registries::{namespace_name}::Index::{function_name}, {arg_param});"
Ed Tanous7ccfe682024-11-16 14:36:16 -0800352 out += "\n}\n\n"
Ed Tanousf175c282024-12-02 15:12:50 -0800353 if registry_name == "Base":
354 args.insert(0, "crow::Response& res")
Ed Tanous7ccfe682024-11-16 14:36:16 -0800355 if entry_id == "InternalError":
Ed Tanousf175c282024-12-02 15:12:50 -0800356 if is_header:
357 args.append(
358 "std::source_location location = std::source_location::current()"
359 )
360 else:
361 args.append("const std::source_location location")
362 arg = ", ".join(args)
363 out += f"void {function_name}({arg})"
364 if is_header:
365 out += ";\n"
Ed Tanous7ccfe682024-11-16 14:36:16 -0800366 else:
Ed Tanousf175c282024-12-02 15:12:50 -0800367 out += "\n{\n"
368 if entry_id == "InternalError":
369 out += """BMCWEB_LOG_CRITICAL("Internal Error {}({}:{}) `{}`: ", location.file_name(),
370 location.line(), location.column(),
371 location.function_name());\n"""
372
373 if entry_id == "ServiceTemporarilyUnavailable":
374 out += "res.addHeader(boost::beast::http::field::retry_after, arg1);"
375
Igor Kanyuka557ab0d2025-02-18 15:20:38 +0000376 res = get_response_code(entry_id)
Ed Tanousf175c282024-12-02 15:12:50 -0800377 if res:
378 out += f" res.result(boost::beast::http::status::{res});\n"
Igor Kanyukada9dc902025-02-26 14:08:11 +0000379 args_out = ", ".join([f"arg{x + 1}" for x in range(len(argtypes))])
Ed Tanousf175c282024-12-02 15:12:50 -0800380
381 addMessageToJson = {
382 "PropertyDuplicate": 1,
383 "ResourceAlreadyExists": 2,
384 "CreateFailedMissingReqProperties": 1,
385 "PropertyValueFormatError": 2,
386 "PropertyValueNotInList": 2,
387 "PropertyValueTypeError": 2,
388 "PropertyValueError": 1,
389 "PropertyNotWritable": 1,
390 "PropertyValueModified": 1,
391 "PropertyMissing": 1,
392 }
393
394 addMessageToRoot = [
395 "SessionTerminated",
396 "SubscriptionTerminated",
397 "AccountRemoved",
398 "Created",
399 "Success",
400 "PasswordChangeRequired",
401 ]
402
403 if entry_id in addMessageToJson:
404 out += f" addMessageToJson(res.jsonValue, {function_name}({args_out}), arg{addMessageToJson[entry_id]});\n"
405 elif entry_id in addMessageToRoot:
406 out += f" addMessageToJsonRoot(res.jsonValue, {function_name}({args_out}));\n"
407 else:
408 out += f" addMessageToErrorJson(res.jsonValue, {function_name}({args_out}));\n"
409 out += "}\n"
Ed Tanous7ccfe682024-11-16 14:36:16 -0800410 out += "\n"
411 return out
412
413
Ed Tanousf175c282024-12-02 15:12:50 -0800414def create_error_registry(
Igor Kanyukada9dc902025-02-26 14:08:11 +0000415 registry_info: RegistryInfo,
416 registry_name: str,
417 namespace_name: str,
418 filename: str,
419) -> None:
420 file, json_dict, namespace, url = registry_info
Ed Tanousf175c282024-12-02 15:12:50 -0800421 base_filename = filename + "_messages"
Ed Tanous42079ec2024-11-16 13:32:29 -0800422
Ed Tanous42079ec2024-11-16 13:32:29 -0800423 error_messages_hpp = os.path.join(
Ed Tanousf175c282024-12-02 15:12:50 -0800424 SCRIPT_DIR, "..", "redfish-core", "include", f"{base_filename}.hpp"
Ed Tanous42079ec2024-11-16 13:32:29 -0800425 )
Ed Tanousf8cca872024-11-16 22:47:34 -0800426 messages = json_dict["Messages"]
427
Ed Tanous42079ec2024-11-16 13:32:29 -0800428 with open(
429 error_messages_hpp,
430 "w",
431 ) as out:
432 out.write(PRAGMA_ONCE)
433 out.write(WARNING)
434 out.write(
435 """
Ed Tanous4aad6ed2025-01-30 09:35:06 -0800436// These generated headers are a superset of what is needed.
437// clang sees them as an error, so ignore
438// NOLINTBEGIN(misc-include-cleaner)
Ed Tanous42079ec2024-11-16 13:32:29 -0800439#include "http_response.hpp"
440
441#include <boost/url/url_view_base.hpp>
442#include <nlohmann/json.hpp>
443
Ed Tanous4aad6ed2025-01-30 09:35:06 -0800444#include <cstdint>
Ed Tanous42079ec2024-11-16 13:32:29 -0800445#include <source_location>
Ed Tanous42079ec2024-11-16 13:32:29 -0800446#include <string_view>
Ed Tanous4aad6ed2025-01-30 09:35:06 -0800447// NOLINTEND(misc-include-cleaner)
Ed Tanous42079ec2024-11-16 13:32:29 -0800448
449namespace redfish
450{
451
452namespace messages
453{
Ed Tanous42079ec2024-11-16 13:32:29 -0800454"""
455 )
Ed Tanous42079ec2024-11-16 13:32:29 -0800456 for entry_id, entry in messages.items():
457 message = entry["Message"]
458 for index in range(1, 10):
459 message = message.replace(f"'%{index}'", f"<arg{index}>")
460 message = message.replace(f"%{index}", f"<arg{index}>")
461
Ed Tanousf175c282024-12-02 15:12:50 -0800462 if registry_name == "Base":
463 out.write("/**\n")
464 out.write(f"* @brief Formats {entry_id} message into JSON\n")
465 out.write(f'* Message body: "{message}"\n')
466 out.write("*\n")
467 arg_index = 0
468 for arg_index, arg in enumerate(entry.get("ParamTypes", [])):
469 arg_index += 1
Ed Tanous42079ec2024-11-16 13:32:29 -0800470
Ed Tanousf175c282024-12-02 15:12:50 -0800471 out.write(
472 f"* @param[in] arg{arg_index} Parameter of message that will replace %{arg_index} in its body.\n"
473 )
474 out.write("*\n")
Ed Tanous42079ec2024-11-16 13:32:29 -0800475 out.write(
Ed Tanousf175c282024-12-02 15:12:50 -0800476 f"* @returns Message {entry_id} formatted to JSON */\n"
Ed Tanous42079ec2024-11-16 13:32:29 -0800477 )
Ed Tanous42079ec2024-11-16 13:32:29 -0800478
Ed Tanousf175c282024-12-02 15:12:50 -0800479 out.write(
480 make_error_function(
481 entry_id, entry, True, registry_name, namespace_name
482 )
483 )
Ed Tanous42079ec2024-11-16 13:32:29 -0800484 out.write(" }\n")
485 out.write("}\n")
Ed Tanous7ccfe682024-11-16 14:36:16 -0800486
487 error_messages_cpp = os.path.join(
Ed Tanousf175c282024-12-02 15:12:50 -0800488 SCRIPT_DIR, "..", "redfish-core", "src", f"{base_filename}.cpp"
Ed Tanous7ccfe682024-11-16 14:36:16 -0800489 )
490 with open(
491 error_messages_cpp,
492 "w",
493 ) as out:
494 out.write(WARNING)
Ed Tanousf175c282024-12-02 15:12:50 -0800495 out.write(f'\n#include "{base_filename}.hpp"\n')
Ed Tanous847deee2024-12-02 15:28:10 -0800496 headers = []
Ed Tanous7ccfe682024-11-16 14:36:16 -0800497
Ed Tanous847deee2024-12-02 15:28:10 -0800498 headers.append('"registries.hpp"')
Ed Tanousf175c282024-12-02 15:12:50 -0800499 if registry_name == "Base":
500 reg_name_lower = "base"
Ed Tanous6c038f22025-01-14 09:46:04 -0800501 headers.append('"error_message_utils.hpp"')
Ed Tanous847deee2024-12-02 15:28:10 -0800502 headers.append('"http_response.hpp"')
503 headers.append('"logging.hpp"')
504 headers.append("<boost/beast/http/field.hpp>")
505 headers.append("<boost/beast/http/status.hpp>")
506 headers.append("<boost/url/url_view_base.hpp>")
507 headers.append("<source_location>")
Ed Tanousf175c282024-12-02 15:12:50 -0800508 else:
509 reg_name_lower = namespace_name.lower()
Ed Tanous847deee2024-12-02 15:28:10 -0800510 headers.append(f'"registries/{reg_name_lower}_message_registry.hpp"')
Ed Tanous7ccfe682024-11-16 14:36:16 -0800511
Ed Tanous847deee2024-12-02 15:28:10 -0800512 headers.append("<nlohmann/json.hpp>")
513 headers.append("<array>")
514 headers.append("<cstddef>")
515 headers.append("<span>")
516
Ed Tanousa8a5bc12024-12-02 15:43:16 -0800517 if registry_name not in ("ResourceEvent", "HeartbeatEvent"):
Ed Tanous847deee2024-12-02 15:28:10 -0800518 headers.append("<cstdint>")
519 headers.append("<string>")
520 headers.append("<string_view>")
521
522 for header in headers:
523 out.write(f"#include {header}\n")
524
Ed Tanousf175c282024-12-02 15:12:50 -0800525 out.write(
526 """
Ed Tanous7ccfe682024-11-16 14:36:16 -0800527// Clang can't seem to decide whether this header needs to be included or not,
528// and is inconsistent. Include it for now
529// NOLINTNEXTLINE(misc-include-cleaner)
530#include <utility>
531
532namespace redfish
533{
534
535namespace messages
536{
Ed Tanousf175c282024-12-02 15:12:50 -0800537"""
538 )
Ed Tanousf175c282024-12-02 15:12:50 -0800539 out.write(
540 """
541static nlohmann::json getLog(redfish::registries::{namespace_name}::Index name,
542 std::span<const std::string_view> args)
543{{
544 size_t index = static_cast<size_t>(name);
545 if (index >= redfish::registries::{namespace_name}::registry.size())
546 {{
547 return {{}};
548 }}
549 return getLogFromRegistry(redfish::registries::{namespace_name}::header,
550 redfish::registries::{namespace_name}::registry, index, args);
551}}
552
553""".format(
554 namespace_name=namespace_name
555 )
Ed Tanous7ccfe682024-11-16 14:36:16 -0800556 )
557 for entry_id, entry in messages.items():
558 out.write(
559 f"""/**
560 * @internal
561 * @brief Formats {entry_id} message into JSON
562 *
563 * See header file for more information
564 * @endinternal
565 */
566"""
567 )
568 message = entry["Message"]
Ed Tanousf175c282024-12-02 15:12:50 -0800569 out.write(
570 make_error_function(
571 entry_id, entry, False, registry_name, namespace_name
572 )
573 )
Ed Tanous7ccfe682024-11-16 14:36:16 -0800574
575 out.write(" }\n")
576 out.write("}\n")
577 os.system(f"clang-format -i {error_messages_hpp} {error_messages_cpp}")
Ed Tanous42079ec2024-11-16 13:32:29 -0800578
579
Igor Kanyukada9dc902025-02-26 14:08:11 +0000580def make_privilege_registry() -> None:
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600581 path, json_file, type_name, url = make_getter(
Gunnar Mills5910d942024-04-16 12:07:17 -0500582 "Redfish_1.5.0_PrivilegeRegistry.json",
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600583 "privilege_registry.hpp",
584 "privilege",
585 )
586 with open(path, "w") as registry:
Nan Zhou043bec02022-09-20 18:12:13 +0000587 registry.write(PRIVILEGE_HEADER)
Ed Tanoused398212021-06-09 17:05:54 -0700588
Igor Kanyukada9dc902025-02-26 14:08:11 +0000589 privilege_dict: t.Dict[str, t.Tuple[t.Any, str | None]] = {}
Ed Tanoused398212021-06-09 17:05:54 -0700590 for mapping in json_file["Mappings"]:
591 # first pass, identify all the unique privilege sets
592 for operation, privilege_list in mapping["OperationMap"].items():
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600593 privilege_dict[
594 get_privilege_string_from_list(privilege_list)
Igor Kanyukada9dc902025-02-26 14:08:11 +0000595 ] = (
596 privilege_list,
597 None,
598 )
Ed Tanoused398212021-06-09 17:05:54 -0700599 for index, key in enumerate(privilege_dict):
Igor Kanyukada9dc902025-02-26 14:08:11 +0000600 (privilege_list, _) = privilege_dict[key]
Ed Tanoused398212021-06-09 17:05:54 -0700601 name = get_variable_name_for_privilege_set(privilege_list)
Ed Tanousf395daa2021-08-02 08:56:24 -0700602 registry.write(
Ed Tanous5b9ef702022-02-17 12:19:32 -0800603 "const std::array<Privileges, {length}> "
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600604 "privilegeSet{name} = {key};\n".format(
605 length=len(privilege_list), name=name, key=key
606 )
Ed Tanous5b9ef702022-02-17 12:19:32 -0800607 )
Ed Tanoused398212021-06-09 17:05:54 -0700608 privilege_dict[key] = (privilege_list, name)
Ed Tanoused398212021-06-09 17:05:54 -0700609
610 for mapping in json_file["Mappings"]:
611 entity = mapping["Entity"]
Ed Tanous4d99bbb2022-02-17 10:02:57 -0800612 registry.write("// {}\n".format(entity))
Ed Tanoused398212021-06-09 17:05:54 -0700613 for operation, privilege_list in mapping["OperationMap"].items():
614 privilege_string = get_privilege_string_from_list(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600615 privilege_list
616 )
Ed Tanoused398212021-06-09 17:05:54 -0700617 operation = operation.lower()
618
Ed Tanousf395daa2021-08-02 08:56:24 -0700619 registry.write(
620 "const static auto& {}{} = privilegeSet{};\n".format(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600621 operation, entity, privilege_dict[privilege_string][1]
622 )
623 )
Ed Tanoused398212021-06-09 17:05:54 -0700624 registry.write("\n")
Ed Tanous5b9ef702022-02-17 12:19:32 -0800625 registry.write(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600626 "} // namespace redfish::privileges\n// clang-format on\n"
627 )
Ed Tanoused398212021-06-09 17:05:54 -0700628
629
Igor Kanyukada9dc902025-02-26 14:08:11 +0000630def to_pascal_case(text: str) -> str:
Gunnar Mills665e7602024-04-10 13:14:41 -0500631 s = text.replace("_", " ")
Igor Kanyukada9dc902025-02-26 14:08:11 +0000632 s1 = s.split()
Gunnar Mills665e7602024-04-10 13:14:41 -0500633 if len(text) == 0:
634 return text
Igor Kanyukada9dc902025-02-26 14:08:11 +0000635 return "".join(i.capitalize() for i in s1[0:])
Gunnar Mills665e7602024-04-10 13:14:41 -0500636
637
Igor Kanyukada9dc902025-02-26 14:08:11 +0000638def main() -> None:
Ed Tanousc8895b02025-01-03 11:44:08 -0800639 dmtf_registries = OrderedDict(
640 [
641 ("base", "1.19.0"),
642 ("composition", "1.1.2"),
Igor Kanyuka0bce6a92025-02-21 12:40:12 +0000643 ("environmental", "1.1.0"),
Ed Tanousc8895b02025-01-03 11:44:08 -0800644 ("ethernet_fabric", "1.0.1"),
645 ("fabric", "1.0.2"),
646 ("heartbeat_event", "1.0.1"),
647 ("job_event", "1.0.1"),
648 ("license", "1.0.3"),
649 ("log_service", "1.0.1"),
650 ("network_device", "1.0.3"),
651 ("platform", "1.0.1"),
652 ("power", "1.0.1"),
653 ("resource_event", "1.3.0"),
654 ("sensor_event", "1.0.1"),
655 ("storage_device", "1.2.1"),
656 ("task_event", "1.0.3"),
657 ("telemetry", "1.0.0"),
658 ("update", "1.0.2"),
659 ]
660 )
Gunnar Mills665e7602024-04-10 13:14:41 -0500661
Nan Zhou49aa131f2022-09-20 18:41:37 +0000662 parser = argparse.ArgumentParser()
663 parser.add_argument(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600664 "--registries",
665 type=str,
Gunnar Mills665e7602024-04-10 13:14:41 -0500666 default="privilege,openbmc,"
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700667 + ",".join([dmtf for dmtf in dmtf_registries]),
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600668 help="Comma delimited list of registries to update",
669 )
Nan Zhou49aa131f2022-09-20 18:41:37 +0000670
671 args = parser.parse_args()
672
673 registries = set(args.registries.split(","))
Igor Kanyukada9dc902025-02-26 14:08:11 +0000674 registries_map: t.OrderedDict[str, RegistryInfo] = OrderedDict()
Nan Zhou49aa131f2022-09-20 18:41:37 +0000675
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700676 for registry, version in dmtf_registries.items():
Gunnar Mills665e7602024-04-10 13:14:41 -0500677 if registry in registries:
678 registry_pascal_case = to_pascal_case(registry)
Igor Kanyuka557ab0d2025-02-18 15:20:38 +0000679 registries_map[registry] = make_getter(
680 f"{registry_pascal_case}.{version}.json",
681 f"{registry}_message_registry.hpp",
682 registry,
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600683 )
Ed Tanous3e5faba2023-08-16 15:11:29 -0700684 if "openbmc" in registries:
Igor Kanyuka557ab0d2025-02-18 15:20:38 +0000685 registries_map["openbmc"] = openbmc_local_getter()
Nan Zhou49aa131f2022-09-20 18:41:37 +0000686
Igor Kanyukada9dc902025-02-26 14:08:11 +0000687 update_registries(list(registries_map.values()))
Nan Zhou49aa131f2022-09-20 18:41:37 +0000688
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700689 if "base" in registries_map:
690 create_error_registry(
Ed Tanousc8895b02025-01-03 11:44:08 -0800691 registries_map["base"],
Ed Tanousc8895b02025-01-03 11:44:08 -0800692 "Base",
693 "base",
694 "error",
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700695 )
696 if "heartbeat_event" in registries_map:
697 create_error_registry(
698 registries_map["heartbeat_event"],
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700699 "HeartbeatEvent",
700 "heartbeat_event",
701 "heartbeat",
702 )
703 if "resource_event" in registries_map:
704 create_error_registry(
705 registries_map["resource_event"],
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700706 "ResourceEvent",
707 "resource_event",
708 "resource",
709 )
710 if "task_event" in registries_map:
711 create_error_registry(
Ed Tanousc8895b02025-01-03 11:44:08 -0800712 registries_map["task_event"],
Ed Tanousc8895b02025-01-03 11:44:08 -0800713 "TaskEvent",
714 "task_event",
715 "task",
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700716 )
717
Nan Zhou49aa131f2022-09-20 18:41:37 +0000718 if "privilege" in registries:
719 make_privilege_registry()
720
721
722if __name__ == "__main__":
723 main()