blob: a557f659a202ad349dc870b329af9c593c8741a7 [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
Igor Kanyuka5bfed262025-02-21 16:50:25 +0000101 description = json_dict.get("Description", "")
Ed Tanous5b9ef702022-02-17 12:19:32 -0800102 registry.write(
Nan Zhou49aa131f2022-09-20 18:41:37 +0000103 "const Header header = {{\n"
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600104 ' "{json_dict[@Redfish.Copyright]}",\n'
105 ' "{json_dict[@odata.type]}",\n'
Ed Tanous56b81992024-12-02 10:36:37 -0800106 " {version_split[0]},\n"
107 " {version_split[1]},\n"
108 " {version_split[2]},\n"
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600109 ' "{json_dict[Name]}",\n'
110 ' "{json_dict[Language]}",\n'
Igor Kanyuka5bfed262025-02-21 16:50:25 +0000111 ' "{description}",\n'
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600112 ' "{json_dict[RegistryPrefix]}",\n'
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600113 ' "{json_dict[OwningEntity]}",\n'
Nan Zhou49aa131f2022-09-20 18:41:37 +0000114 "}};\n"
115 "constexpr const char* url =\n"
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600116 ' "{url}";\n'
Nan Zhou49aa131f2022-09-20 18:41:37 +0000117 "\n"
118 "constexpr std::array registry =\n"
119 "{{\n".format(
120 json_dict=json_dict,
121 url=url,
Ed Tanous56b81992024-12-02 10:36:37 -0800122 version_split=version_split,
Igor Kanyuka5bfed262025-02-21 16:50:25 +0000123 description=description,
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600124 )
125 )
Ed Tanous30a3c432022-02-07 09:37:21 -0800126
Nan Zhou49aa131f2022-09-20 18:41:37 +0000127 messages_sorted = sorted(json_dict["Messages"].items())
128 for messageId, message in messages_sorted:
129 registry.write(
130 " MessageEntry{{\n"
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600131 ' "{messageId}",\n'
Nan Zhou49aa131f2022-09-20 18:41:37 +0000132 " {{\n"
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600133 ' "{message[Description]}",\n'
134 ' "{message[Message]}",\n'
135 ' "{message[MessageSeverity]}",\n'
Nan Zhou49aa131f2022-09-20 18:41:37 +0000136 " {message[NumberOfArgs]},\n"
137 " {{".format(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600138 messageId=messageId, message=message
139 )
140 )
Nan Zhou49aa131f2022-09-20 18:41:37 +0000141 paramTypes = message.get("ParamTypes")
142 if paramTypes:
143 for paramType in paramTypes:
144 registry.write(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600145 '\n "{}",'.format(paramType)
Nan Zhou49aa131f2022-09-20 18:41:37 +0000146 )
147 registry.write("\n },\n")
148 else:
149 registry.write("},\n")
150 registry.write(
Igor Kanyukada9dc902025-02-26 14:08:11 +0000151 ' "{message[Resolution]}",\n }}}},\n'.format(
152 message=message
153 )
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600154 )
Nan Zhou49aa131f2022-09-20 18:41:37 +0000155
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600156 registry.write("\n};\n\nenum class Index\n{\n")
Nan Zhou49aa131f2022-09-20 18:41:37 +0000157 for index, (messageId, message) in enumerate(messages_sorted):
158 messageId = messageId[0].lower() + messageId[1:]
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600159 registry.write(" {} = {},\n".format(messageId, index))
Nan Zhou49aa131f2022-09-20 18:41:37 +0000160 registry.write(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600161 "}};\n}} // namespace redfish::registries::{}\n".format(
162 namespace
163 )
164 )
Ed Tanoused398212021-06-09 17:05:54 -0700165
166
Igor Kanyukada9dc902025-02-26 14:08:11 +0000167def get_privilege_string_from_list(
168 privilege_list: t.List[t.Dict[str, t.Any]],
169) -> str:
Ed Tanoused398212021-06-09 17:05:54 -0700170 privilege_string = "{{\n"
171 for privilege_json in privilege_list:
172 privileges = privilege_json["Privilege"]
173 privilege_string += " {"
Igor Kanyukada9dc902025-02-26 14:08:11 +0000174 last_privelege = ""
Ed Tanoused398212021-06-09 17:05:54 -0700175 for privilege in privileges:
Igor Kanyukada9dc902025-02-26 14:08:11 +0000176 last_privelege = privilege
Ed Tanoused398212021-06-09 17:05:54 -0700177 if privilege == "NoAuth":
178 continue
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600179 privilege_string += '"'
Ed Tanoused398212021-06-09 17:05:54 -0700180 privilege_string += privilege
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600181 privilege_string += '",\n'
Igor Kanyukada9dc902025-02-26 14:08:11 +0000182 if last_privelege != "NoAuth":
Ed Tanoused398212021-06-09 17:05:54 -0700183 privilege_string = privilege_string[:-2]
184 privilege_string += "}"
185 privilege_string += ",\n"
186 privilege_string = privilege_string[:-2]
187 privilege_string += "\n}}"
188 return privilege_string
189
Ed Tanousf395daa2021-08-02 08:56:24 -0700190
Igor Kanyukada9dc902025-02-26 14:08:11 +0000191def get_variable_name_for_privilege_set(
192 privilege_list: t.List[t.Dict[str, t.Any]],
193) -> str:
Ed Tanoused398212021-06-09 17:05:54 -0700194 names = []
195 for privilege_json in privilege_list:
196 privileges = privilege_json["Privilege"]
197 names.append("And".join(privileges))
198 return "Or".join(names)
199
Ed Tanousf395daa2021-08-02 08:56:24 -0700200
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600201PRIVILEGE_HEADER = (
Ed Tanous40e9b922024-09-10 13:50:16 -0700202 COPYRIGHT
203 + PRAGMA_ONCE
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600204 + WARNING
205 + """
Nan Zhou01c78a02022-09-20 18:17:20 +0000206#include "privileges.hpp"
207
208#include <array>
Nan Zhou043bec02022-09-20 18:12:13 +0000209
210// clang-format off
211
212namespace redfish::privileges
213{
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600214"""
215)
Nan Zhou043bec02022-09-20 18:12:13 +0000216
217
Igor Kanyukada9dc902025-02-26 14:08:11 +0000218def get_response_code(entry_id: str) -> str | None:
Ed Tanous7ccfe682024-11-16 14:36:16 -0800219 codes = {
Myung Bae3498f482025-04-09 06:22:54 -0400220 "AccessDenied": "forbidden",
Ed Tanous7ccfe682024-11-16 14:36:16 -0800221 "AccountForSessionNoLongerExists": "forbidden",
Myung Bae3498f482025-04-09 06:22:54 -0400222 "AccountModified": "ok",
223 "AccountRemoved": "ok",
224 "CouldNotEstablishConnection": "not_found",
225 "Created": "created",
226 "EventSubscriptionLimitExceeded": "service_unavailable",
227 "GeneralError": "internal_server_error",
228 "GenerateSecretKeyRequired": "forbidden",
229 "InsufficientPrivilege": "forbidden",
230 "InsufficientStorage": "insufficient_storage",
231 "InternalError": "internal_server_error",
232 "MaximumErrorsExceeded": "internal_server_error",
233 "NoValidSession": "forbidden",
234 "OperationFailed": "bad_gateway",
235 "OperationNotAllowed": "method_not_allowed",
236 "OperationTimeout": "internal_server_error",
237 "PasswordChangeRequired": None,
238 "PreconditionFailed": "precondition_failed",
239 "PropertyNotWritable": "forbidden",
240 "PropertyValueExternalConflict": "conflict",
241 "PropertyValueModified": "ok",
242 "PropertyValueResourceConflict": "conflict",
243 "ResourceAtUriUnauthorized": "unauthorized",
244 "ResourceCannotBeDeleted": "method_not_allowed",
245 "ResourceExhaustion": "service_unavailable",
246 "ResourceInStandby": "service_unavailable",
247 "ResourceInUse": "service_unavailable",
248 "ResourceNotFound": "not_found",
Myung Bae7f84d8c2023-03-14 13:44:15 -0700249 "RestrictedRole": "forbidden",
Ed Tanous7ccfe682024-11-16 14:36:16 -0800250 "ServiceDisabled": "service_unavailable",
251 "ServiceInUnknownState": "service_unavailable",
Myung Bae3498f482025-04-09 06:22:54 -0400252 "ServiceShuttingDown": "service_unavailable",
253 "ServiceTemporarilyUnavailable": "service_unavailable",
254 "SessionLimitExceeded": "service_unavailable",
Ed Tanous7ccfe682024-11-16 14:36:16 -0800255 "SessionTerminated": "ok",
256 "SubscriptionTerminated": "ok",
Ed Tanous7ccfe682024-11-16 14:36:16 -0800257 "Success": None,
Ed Tanous7ccfe682024-11-16 14:36:16 -0800258 }
259
Igor Kanyuka557ab0d2025-02-18 15:20:38 +0000260 return codes.get(entry_id, "bad_request")
Ed Tanous7ccfe682024-11-16 14:36:16 -0800261
262
Ed Tanousf175c282024-12-02 15:12:50 -0800263def make_error_function(
Igor Kanyukada9dc902025-02-26 14:08:11 +0000264 entry_id: str,
265 entry: t.Dict[str, t.Any],
266 is_header: bool,
267 registry_name: str,
268 namespace_name: str,
269) -> str:
Ed Tanous644cdcb2024-11-17 11:12:41 -0800270 arg_nonstring_types = {
271 "const boost::urls::url_view_base&": {
272 "AccessDenied": [1],
273 "CouldNotEstablishConnection": [1],
274 "GenerateSecretKeyRequired": [1],
275 "InvalidObject": [1],
276 "PasswordChangeRequired": [1],
277 "PropertyValueResourceConflict": [3],
278 "ResetRequired": [1],
279 "ResourceAtUriInUnknownFormat": [1],
280 "ResourceAtUriUnauthorized": [1],
281 "ResourceCreationConflict": [1],
282 "ResourceMissingAtURI": [1],
283 "SourceDoesNotSupportProtocol": [1],
284 },
285 "const nlohmann::json&": {
286 "ActionParameterValueError": [1],
287 "ActionParameterValueFormatError": [1],
288 "ActionParameterValueTypeError": [1],
289 "PropertyValueExternalConflict": [2],
290 "PropertyValueFormatError": [1],
291 "PropertyValueIncorrect": [2],
292 "PropertyValueModified": [2],
293 "PropertyValueNotInList": [1],
294 "PropertyValueOutOfRange": [1],
295 "PropertyValueResourceConflict": [2],
296 "PropertyValueTypeError": [1],
297 "QueryParameterValueFormatError": [1],
298 "QueryParameterValueTypeError": [1],
299 },
300 "uint64_t": {
301 "ArraySizeTooLong": [2],
302 "InvalidIndex": [1],
303 "StringValueTooLong": [2],
Ed Tanousf175c282024-12-02 15:12:50 -0800304 "TaskProgressChanged": [2],
Ed Tanous644cdcb2024-11-17 11:12:41 -0800305 },
Ed Tanous42079ec2024-11-16 13:32:29 -0800306 }
307
Ed Tanous7ccfe682024-11-16 14:36:16 -0800308 out = ""
309 args = []
310 argtypes = []
311 for arg_index, arg in enumerate(entry.get("ParamTypes", [])):
312 arg_index += 1
Ed Tanous644cdcb2024-11-17 11:12:41 -0800313 typename = "std::string_view"
314 for typestring, entries in arg_nonstring_types.items():
315 if arg_index in entries.get(entry_id, []):
316 typename = typestring
317
Ed Tanous7ccfe682024-11-16 14:36:16 -0800318 argtypes.append(typename)
319 args.append(f"{typename} arg{arg_index}")
320 function_name = entry_id[0].lower() + entry_id[1:]
321 arg = ", ".join(args)
322 out += f"nlohmann::json {function_name}({arg})"
323
324 if is_header:
325 out += ";\n\n"
326 else:
327 out += "\n{\n"
328 to_array_type = ""
Igor Kanyukada9dc902025-02-26 14:08:11 +0000329 arg_param = "{}"
Ed Tanous7ccfe682024-11-16 14:36:16 -0800330 if argtypes:
331 outargs = []
332 for index, typename in enumerate(argtypes):
333 index += 1
334 if typename == "const nlohmann::json&":
335 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 -0800336 elif typename == "uint64_t":
Ed Tanous7ccfe682024-11-16 14:36:16 -0800337 out += f"std::string arg{index}Str = std::to_string(arg{index});\n"
338
339 for index, typename in enumerate(argtypes):
340 index += 1
341 if typename == "const boost::urls::url_view_base&":
342 outargs.append(f"arg{index}.buffer()")
343 to_array_type = "<std::string_view>"
344 elif typename == "const nlohmann::json&":
345 outargs.append(f"arg{index}Str")
346 to_array_type = "<std::string_view>"
Ed Tanous644cdcb2024-11-17 11:12:41 -0800347 elif typename == "uint64_t":
Ed Tanous7ccfe682024-11-16 14:36:16 -0800348 outargs.append(f"arg{index}Str")
349 to_array_type = "<std::string_view>"
350 else:
351 outargs.append(f"arg{index}")
352 argstring = ", ".join(outargs)
Ed Tanous7ccfe682024-11-16 14:36:16 -0800353 arg_param = f"std::to_array{to_array_type}({{{argstring}}})"
Ed Tanousf175c282024-12-02 15:12:50 -0800354 out += f" return getLog(redfish::registries::{namespace_name}::Index::{function_name}, {arg_param});"
Ed Tanous7ccfe682024-11-16 14:36:16 -0800355 out += "\n}\n\n"
Ed Tanousf175c282024-12-02 15:12:50 -0800356 if registry_name == "Base":
357 args.insert(0, "crow::Response& res")
Ed Tanous7ccfe682024-11-16 14:36:16 -0800358 if entry_id == "InternalError":
Ed Tanousf175c282024-12-02 15:12:50 -0800359 if is_header:
360 args.append(
361 "std::source_location location = std::source_location::current()"
362 )
363 else:
364 args.append("const std::source_location location")
365 arg = ", ".join(args)
366 out += f"void {function_name}({arg})"
367 if is_header:
368 out += ";\n"
Ed Tanous7ccfe682024-11-16 14:36:16 -0800369 else:
Ed Tanousf175c282024-12-02 15:12:50 -0800370 out += "\n{\n"
371 if entry_id == "InternalError":
372 out += """BMCWEB_LOG_CRITICAL("Internal Error {}({}:{}) `{}`: ", location.file_name(),
373 location.line(), location.column(),
374 location.function_name());\n"""
375
376 if entry_id == "ServiceTemporarilyUnavailable":
377 out += "res.addHeader(boost::beast::http::field::retry_after, arg1);"
378
Igor Kanyuka557ab0d2025-02-18 15:20:38 +0000379 res = get_response_code(entry_id)
Ed Tanousf175c282024-12-02 15:12:50 -0800380 if res:
381 out += f" res.result(boost::beast::http::status::{res});\n"
Igor Kanyukada9dc902025-02-26 14:08:11 +0000382 args_out = ", ".join([f"arg{x + 1}" for x in range(len(argtypes))])
Ed Tanousf175c282024-12-02 15:12:50 -0800383
384 addMessageToJson = {
385 "PropertyDuplicate": 1,
386 "ResourceAlreadyExists": 2,
387 "CreateFailedMissingReqProperties": 1,
388 "PropertyValueFormatError": 2,
389 "PropertyValueNotInList": 2,
390 "PropertyValueTypeError": 2,
391 "PropertyValueError": 1,
392 "PropertyNotWritable": 1,
393 "PropertyValueModified": 1,
394 "PropertyMissing": 1,
395 }
396
397 addMessageToRoot = [
398 "SessionTerminated",
399 "SubscriptionTerminated",
400 "AccountRemoved",
401 "Created",
402 "Success",
403 "PasswordChangeRequired",
404 ]
405
406 if entry_id in addMessageToJson:
407 out += f" addMessageToJson(res.jsonValue, {function_name}({args_out}), arg{addMessageToJson[entry_id]});\n"
408 elif entry_id in addMessageToRoot:
409 out += f" addMessageToJsonRoot(res.jsonValue, {function_name}({args_out}));\n"
410 else:
411 out += f" addMessageToErrorJson(res.jsonValue, {function_name}({args_out}));\n"
412 out += "}\n"
Ed Tanous7ccfe682024-11-16 14:36:16 -0800413 out += "\n"
414 return out
415
416
Ed Tanousf175c282024-12-02 15:12:50 -0800417def create_error_registry(
Igor Kanyukada9dc902025-02-26 14:08:11 +0000418 registry_info: RegistryInfo,
419 registry_name: str,
420 namespace_name: str,
421 filename: str,
422) -> None:
423 file, json_dict, namespace, url = registry_info
Ed Tanousf175c282024-12-02 15:12:50 -0800424 base_filename = filename + "_messages"
Ed Tanous42079ec2024-11-16 13:32:29 -0800425
Ed Tanous42079ec2024-11-16 13:32:29 -0800426 error_messages_hpp = os.path.join(
Ed Tanousf175c282024-12-02 15:12:50 -0800427 SCRIPT_DIR, "..", "redfish-core", "include", f"{base_filename}.hpp"
Ed Tanous42079ec2024-11-16 13:32:29 -0800428 )
Ed Tanousf8cca872024-11-16 22:47:34 -0800429 messages = json_dict["Messages"]
430
Ed Tanous42079ec2024-11-16 13:32:29 -0800431 with open(
432 error_messages_hpp,
433 "w",
434 ) as out:
435 out.write(PRAGMA_ONCE)
436 out.write(WARNING)
437 out.write(
438 """
Ed Tanous4aad6ed2025-01-30 09:35:06 -0800439// These generated headers are a superset of what is needed.
440// clang sees them as an error, so ignore
441// NOLINTBEGIN(misc-include-cleaner)
Ed Tanous42079ec2024-11-16 13:32:29 -0800442#include "http_response.hpp"
443
444#include <boost/url/url_view_base.hpp>
445#include <nlohmann/json.hpp>
446
Ed Tanous4aad6ed2025-01-30 09:35:06 -0800447#include <cstdint>
Ed Tanous42079ec2024-11-16 13:32:29 -0800448#include <source_location>
Ed Tanous42079ec2024-11-16 13:32:29 -0800449#include <string_view>
Ed Tanous4aad6ed2025-01-30 09:35:06 -0800450// NOLINTEND(misc-include-cleaner)
Ed Tanous42079ec2024-11-16 13:32:29 -0800451
452namespace redfish
453{
454
455namespace messages
456{
Ed Tanous42079ec2024-11-16 13:32:29 -0800457"""
458 )
Ed Tanous42079ec2024-11-16 13:32:29 -0800459 for entry_id, entry in messages.items():
460 message = entry["Message"]
461 for index in range(1, 10):
462 message = message.replace(f"'%{index}'", f"<arg{index}>")
463 message = message.replace(f"%{index}", f"<arg{index}>")
464
Ed Tanousf175c282024-12-02 15:12:50 -0800465 if registry_name == "Base":
466 out.write("/**\n")
467 out.write(f"* @brief Formats {entry_id} message into JSON\n")
468 out.write(f'* Message body: "{message}"\n')
469 out.write("*\n")
470 arg_index = 0
471 for arg_index, arg in enumerate(entry.get("ParamTypes", [])):
472 arg_index += 1
Ed Tanous42079ec2024-11-16 13:32:29 -0800473
Ed Tanousf175c282024-12-02 15:12:50 -0800474 out.write(
475 f"* @param[in] arg{arg_index} Parameter of message that will replace %{arg_index} in its body.\n"
476 )
477 out.write("*\n")
Ed Tanous42079ec2024-11-16 13:32:29 -0800478 out.write(
Ed Tanousf175c282024-12-02 15:12:50 -0800479 f"* @returns Message {entry_id} formatted to JSON */\n"
Ed Tanous42079ec2024-11-16 13:32:29 -0800480 )
Ed Tanous42079ec2024-11-16 13:32:29 -0800481
Ed Tanousf175c282024-12-02 15:12:50 -0800482 out.write(
483 make_error_function(
484 entry_id, entry, True, registry_name, namespace_name
485 )
486 )
Ed Tanous42079ec2024-11-16 13:32:29 -0800487 out.write(" }\n")
488 out.write("}\n")
Ed Tanous7ccfe682024-11-16 14:36:16 -0800489
490 error_messages_cpp = os.path.join(
Ed Tanousf175c282024-12-02 15:12:50 -0800491 SCRIPT_DIR, "..", "redfish-core", "src", f"{base_filename}.cpp"
Ed Tanous7ccfe682024-11-16 14:36:16 -0800492 )
493 with open(
494 error_messages_cpp,
495 "w",
496 ) as out:
497 out.write(WARNING)
Ed Tanousf175c282024-12-02 15:12:50 -0800498 out.write(f'\n#include "{base_filename}.hpp"\n')
Ed Tanous847deee2024-12-02 15:28:10 -0800499 headers = []
Ed Tanous7ccfe682024-11-16 14:36:16 -0800500
Ed Tanous847deee2024-12-02 15:28:10 -0800501 headers.append('"registries.hpp"')
Ed Tanousf175c282024-12-02 15:12:50 -0800502 if registry_name == "Base":
503 reg_name_lower = "base"
Ed Tanous6c038f22025-01-14 09:46:04 -0800504 headers.append('"error_message_utils.hpp"')
Ed Tanous847deee2024-12-02 15:28:10 -0800505 headers.append('"http_response.hpp"')
506 headers.append('"logging.hpp"')
507 headers.append("<boost/beast/http/field.hpp>")
508 headers.append("<boost/beast/http/status.hpp>")
509 headers.append("<boost/url/url_view_base.hpp>")
510 headers.append("<source_location>")
Ed Tanousf175c282024-12-02 15:12:50 -0800511 else:
512 reg_name_lower = namespace_name.lower()
Ed Tanous847deee2024-12-02 15:28:10 -0800513 headers.append(f'"registries/{reg_name_lower}_message_registry.hpp"')
Ed Tanous7ccfe682024-11-16 14:36:16 -0800514
Ed Tanous847deee2024-12-02 15:28:10 -0800515 headers.append("<nlohmann/json.hpp>")
516 headers.append("<array>")
517 headers.append("<cstddef>")
518 headers.append("<span>")
519
Ed Tanousa8a5bc12024-12-02 15:43:16 -0800520 if registry_name not in ("ResourceEvent", "HeartbeatEvent"):
Ed Tanous847deee2024-12-02 15:28:10 -0800521 headers.append("<cstdint>")
522 headers.append("<string>")
523 headers.append("<string_view>")
524
525 for header in headers:
526 out.write(f"#include {header}\n")
527
Ed Tanousf175c282024-12-02 15:12:50 -0800528 out.write(
529 """
Ed Tanous7ccfe682024-11-16 14:36:16 -0800530// Clang can't seem to decide whether this header needs to be included or not,
531// and is inconsistent. Include it for now
532// NOLINTNEXTLINE(misc-include-cleaner)
533#include <utility>
534
535namespace redfish
536{
537
538namespace messages
539{
Ed Tanousf175c282024-12-02 15:12:50 -0800540"""
541 )
Ed Tanousf175c282024-12-02 15:12:50 -0800542 out.write(
543 """
544static nlohmann::json getLog(redfish::registries::{namespace_name}::Index name,
545 std::span<const std::string_view> args)
546{{
547 size_t index = static_cast<size_t>(name);
548 if (index >= redfish::registries::{namespace_name}::registry.size())
549 {{
550 return {{}};
551 }}
552 return getLogFromRegistry(redfish::registries::{namespace_name}::header,
553 redfish::registries::{namespace_name}::registry, index, args);
554}}
555
556""".format(
557 namespace_name=namespace_name
558 )
Ed Tanous7ccfe682024-11-16 14:36:16 -0800559 )
560 for entry_id, entry in messages.items():
561 out.write(
562 f"""/**
563 * @internal
564 * @brief Formats {entry_id} message into JSON
565 *
566 * See header file for more information
567 * @endinternal
568 */
569"""
570 )
571 message = entry["Message"]
Ed Tanousf175c282024-12-02 15:12:50 -0800572 out.write(
573 make_error_function(
574 entry_id, entry, False, registry_name, namespace_name
575 )
576 )
Ed Tanous7ccfe682024-11-16 14:36:16 -0800577
578 out.write(" }\n")
579 out.write("}\n")
580 os.system(f"clang-format -i {error_messages_hpp} {error_messages_cpp}")
Ed Tanous42079ec2024-11-16 13:32:29 -0800581
582
Igor Kanyukada9dc902025-02-26 14:08:11 +0000583def make_privilege_registry() -> None:
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600584 path, json_file, type_name, url = make_getter(
Gunnar Mills5910d942024-04-16 12:07:17 -0500585 "Redfish_1.5.0_PrivilegeRegistry.json",
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600586 "privilege_registry.hpp",
587 "privilege",
588 )
589 with open(path, "w") as registry:
Nan Zhou043bec02022-09-20 18:12:13 +0000590 registry.write(PRIVILEGE_HEADER)
Ed Tanoused398212021-06-09 17:05:54 -0700591
Igor Kanyukada9dc902025-02-26 14:08:11 +0000592 privilege_dict: t.Dict[str, t.Tuple[t.Any, str | None]] = {}
Ed Tanoused398212021-06-09 17:05:54 -0700593 for mapping in json_file["Mappings"]:
594 # first pass, identify all the unique privilege sets
595 for operation, privilege_list in mapping["OperationMap"].items():
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600596 privilege_dict[
597 get_privilege_string_from_list(privilege_list)
Igor Kanyukada9dc902025-02-26 14:08:11 +0000598 ] = (
599 privilege_list,
600 None,
601 )
Ed Tanoused398212021-06-09 17:05:54 -0700602 for index, key in enumerate(privilege_dict):
Igor Kanyukada9dc902025-02-26 14:08:11 +0000603 (privilege_list, _) = privilege_dict[key]
Ed Tanoused398212021-06-09 17:05:54 -0700604 name = get_variable_name_for_privilege_set(privilege_list)
Ed Tanousf395daa2021-08-02 08:56:24 -0700605 registry.write(
Ed Tanous5b9ef702022-02-17 12:19:32 -0800606 "const std::array<Privileges, {length}> "
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600607 "privilegeSet{name} = {key};\n".format(
608 length=len(privilege_list), name=name, key=key
609 )
Ed Tanous5b9ef702022-02-17 12:19:32 -0800610 )
Ed Tanoused398212021-06-09 17:05:54 -0700611 privilege_dict[key] = (privilege_list, name)
Ed Tanoused398212021-06-09 17:05:54 -0700612
613 for mapping in json_file["Mappings"]:
614 entity = mapping["Entity"]
Ed Tanous4d99bbb2022-02-17 10:02:57 -0800615 registry.write("// {}\n".format(entity))
Ed Tanoused398212021-06-09 17:05:54 -0700616 for operation, privilege_list in mapping["OperationMap"].items():
617 privilege_string = get_privilege_string_from_list(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600618 privilege_list
619 )
Ed Tanoused398212021-06-09 17:05:54 -0700620 operation = operation.lower()
621
Ed Tanousf395daa2021-08-02 08:56:24 -0700622 registry.write(
623 "const static auto& {}{} = privilegeSet{};\n".format(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600624 operation, entity, privilege_dict[privilege_string][1]
625 )
626 )
Ed Tanoused398212021-06-09 17:05:54 -0700627 registry.write("\n")
Ed Tanous5b9ef702022-02-17 12:19:32 -0800628 registry.write(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600629 "} // namespace redfish::privileges\n// clang-format on\n"
630 )
Ed Tanoused398212021-06-09 17:05:54 -0700631
632
Igor Kanyukada9dc902025-02-26 14:08:11 +0000633def to_pascal_case(text: str) -> str:
Gunnar Mills665e7602024-04-10 13:14:41 -0500634 s = text.replace("_", " ")
Igor Kanyukada9dc902025-02-26 14:08:11 +0000635 s1 = s.split()
Gunnar Mills665e7602024-04-10 13:14:41 -0500636 if len(text) == 0:
637 return text
Igor Kanyukada9dc902025-02-26 14:08:11 +0000638 return "".join(i.capitalize() for i in s1[0:])
Gunnar Mills665e7602024-04-10 13:14:41 -0500639
640
Igor Kanyukada9dc902025-02-26 14:08:11 +0000641def main() -> None:
Ed Tanousc8895b02025-01-03 11:44:08 -0800642 dmtf_registries = OrderedDict(
643 [
644 ("base", "1.19.0"),
645 ("composition", "1.1.2"),
Igor Kanyuka0bce6a92025-02-21 12:40:12 +0000646 ("environmental", "1.1.0"),
Ed Tanousc8895b02025-01-03 11:44:08 -0800647 ("ethernet_fabric", "1.0.1"),
648 ("fabric", "1.0.2"),
649 ("heartbeat_event", "1.0.1"),
650 ("job_event", "1.0.1"),
651 ("license", "1.0.3"),
652 ("log_service", "1.0.1"),
653 ("network_device", "1.0.3"),
654 ("platform", "1.0.1"),
655 ("power", "1.0.1"),
656 ("resource_event", "1.3.0"),
657 ("sensor_event", "1.0.1"),
658 ("storage_device", "1.2.1"),
659 ("task_event", "1.0.3"),
660 ("telemetry", "1.0.0"),
661 ("update", "1.0.2"),
662 ]
663 )
Gunnar Mills665e7602024-04-10 13:14:41 -0500664
Nan Zhou49aa131f2022-09-20 18:41:37 +0000665 parser = argparse.ArgumentParser()
666 parser.add_argument(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600667 "--registries",
668 type=str,
Gunnar Mills665e7602024-04-10 13:14:41 -0500669 default="privilege,openbmc,"
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700670 + ",".join([dmtf for dmtf in dmtf_registries]),
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600671 help="Comma delimited list of registries to update",
672 )
Nan Zhou49aa131f2022-09-20 18:41:37 +0000673
674 args = parser.parse_args()
675
676 registries = set(args.registries.split(","))
Igor Kanyukada9dc902025-02-26 14:08:11 +0000677 registries_map: t.OrderedDict[str, RegistryInfo] = OrderedDict()
Nan Zhou49aa131f2022-09-20 18:41:37 +0000678
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700679 for registry, version in dmtf_registries.items():
Gunnar Mills665e7602024-04-10 13:14:41 -0500680 if registry in registries:
681 registry_pascal_case = to_pascal_case(registry)
Igor Kanyuka557ab0d2025-02-18 15:20:38 +0000682 registries_map[registry] = make_getter(
683 f"{registry_pascal_case}.{version}.json",
684 f"{registry}_message_registry.hpp",
685 registry,
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600686 )
Ed Tanous3e5faba2023-08-16 15:11:29 -0700687 if "openbmc" in registries:
Igor Kanyuka557ab0d2025-02-18 15:20:38 +0000688 registries_map["openbmc"] = openbmc_local_getter()
Nan Zhou49aa131f2022-09-20 18:41:37 +0000689
Igor Kanyukada9dc902025-02-26 14:08:11 +0000690 update_registries(list(registries_map.values()))
Nan Zhou49aa131f2022-09-20 18:41:37 +0000691
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700692 if "base" in registries_map:
693 create_error_registry(
Ed Tanousc8895b02025-01-03 11:44:08 -0800694 registries_map["base"],
Ed Tanousc8895b02025-01-03 11:44:08 -0800695 "Base",
696 "base",
697 "error",
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700698 )
699 if "heartbeat_event" in registries_map:
700 create_error_registry(
701 registries_map["heartbeat_event"],
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700702 "HeartbeatEvent",
703 "heartbeat_event",
704 "heartbeat",
705 )
706 if "resource_event" in registries_map:
707 create_error_registry(
708 registries_map["resource_event"],
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700709 "ResourceEvent",
710 "resource_event",
711 "resource",
712 )
713 if "task_event" in registries_map:
714 create_error_registry(
Ed Tanousc8895b02025-01-03 11:44:08 -0800715 registries_map["task_event"],
Ed Tanousc8895b02025-01-03 11:44:08 -0800716 "TaskEvent",
717 "task_event",
718 "task",
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700719 )
720
Nan Zhou49aa131f2022-09-20 18:41:37 +0000721 if "privilege" in registries:
722 make_privilege_registry()
723
724
725if __name__ == "__main__":
726 main()