blob: 6f97bc1268371eb45f0ae4c43b8c59a4030c294d [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
Patrick Williams4a102cd2025-02-27 14:52:54 -050039namespace redfish::registries
40{{
41struct {}
Jason M. Bills70304cb2019-03-27 12:03:59 -070042{{
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -060043"""
Ed Tanous40e9b922024-09-10 13:50:16 -070044
Igor Kanyukada9dc902025-02-26 14:08:11 +000045REGISTRY_HEADER: t.Final[str] = f"{COPYRIGHT}{PRAGMA_ONCE}{WARNING}{INCLUDES}"
Jason M. Bills70304cb2019-03-27 12:03:59 -070046
Igor Kanyukada9dc902025-02-26 14:08:11 +000047SCRIPT_DIR: t.Final[str] = os.path.dirname(os.path.realpath(__file__))
Jason M. Bills70304cb2019-03-27 12:03:59 -070048
Igor Kanyukada9dc902025-02-26 14:08:11 +000049INCLUDE_PATH: t.Final[str] = os.path.realpath(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -060050 os.path.join(SCRIPT_DIR, "..", "redfish-core", "include", "registries")
51)
Jason M. Bills70304cb2019-03-27 12:03:59 -070052
Igor Kanyukada9dc902025-02-26 14:08:11 +000053PROXIES: t.Final[t.Dict[str, str]] = {
54 "https": os.environ.get("https_proxy", "")
55}
56
57RegistryInfo: t.TypeAlias = t.Tuple[str, t.Dict[str, t.Any], str, str]
Jason M. Bills70304cb2019-03-27 12:03:59 -070058
Jason M. Bills70304cb2019-03-27 12:03:59 -070059
Igor Kanyukada9dc902025-02-26 14:08:11 +000060def make_getter(
61 dmtf_name: str, header_name: str, type_name: str
62) -> RegistryInfo:
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -060063 url = "https://redfish.dmtf.org/registries/{}".format(dmtf_name)
Igor Kanyuka557ab0d2025-02-18 15:20:38 +000064 dmtf = requests.get(url, proxies=PROXIES)
James Feiste51c7102020-03-17 10:38:18 -070065 dmtf.raise_for_status()
Ed Tanous42079ec2024-11-16 13:32:29 -080066 json_file = json.loads(dmtf.text, object_pairs_hook=OrderedDict)
Igor Kanyuka557ab0d2025-02-18 15:20:38 +000067 path = os.path.join(INCLUDE_PATH, header_name)
James Feiste51c7102020-03-17 10:38:18 -070068 return (path, json_file, type_name, url)
69
70
Igor Kanyukada9dc902025-02-26 14:08:11 +000071def openbmc_local_getter() -> RegistryInfo:
Milton D. Miller II770362f2024-12-17 05:28:27 +000072 url = "https://raw.githubusercontent.com/openbmc/bmcweb/refs/heads/master/redfish-core/include/registries/openbmc.json"
Ed Tanous3e5faba2023-08-16 15:11:29 -070073 with open(
74 os.path.join(
75 SCRIPT_DIR,
76 "..",
77 "redfish-core",
78 "include",
79 "registries",
80 "openbmc.json",
81 ),
82 "rb",
Igor Kanyuka557ab0d2025-02-18 15:20:38 +000083 ) as json_file_fd:
84 json_file = json.load(json_file_fd)
Ed Tanous3e5faba2023-08-16 15:11:29 -070085
Igor Kanyuka557ab0d2025-02-18 15:20:38 +000086 path = os.path.join(INCLUDE_PATH, "openbmc_message_registry.hpp")
Ed Tanous3e5faba2023-08-16 15:11:29 -070087 return (path, json_file, "openbmc", url)
88
89
Igor Kanyukada9dc902025-02-26 14:08:11 +000090def update_registries(files: t.List[RegistryInfo]) -> None:
Nan Zhou49aa131f2022-09-20 18:41:37 +000091 # Remove the old files
92 for file, json_dict, namespace, url in files:
93 try:
94 os.remove(file)
95 except BaseException:
96 print("{} not found".format(file))
Jason M. Bills70304cb2019-03-27 12:03:59 -070097
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -060098 with open(file, "w") as registry:
Ed Tanous56b81992024-12-02 10:36:37 -080099 version_split = json_dict["RegistryVersion"].split(".")
100
Patrick Williams4a102cd2025-02-27 14:52:54 -0500101 struct_name = to_pascal_case(namespace)
102 registry.write(REGISTRY_HEADER.format(struct_name))
Nan Zhou49aa131f2022-09-20 18:41:37 +0000103 # Parse the Registry header info
Igor Kanyuka5bfed262025-02-21 16:50:25 +0000104 description = json_dict.get("Description", "")
Ed Tanous5b9ef702022-02-17 12:19:32 -0800105 registry.write(
Patrick Williams4a102cd2025-02-27 14:52:54 -0500106 "static constexpr Header header = {{\n"
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600107 ' "{json_dict[@Redfish.Copyright]}",\n'
108 ' "{json_dict[@odata.type]}",\n'
Ed Tanous56b81992024-12-02 10:36:37 -0800109 " {version_split[0]},\n"
110 " {version_split[1]},\n"
111 " {version_split[2]},\n"
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600112 ' "{json_dict[Name]}",\n'
113 ' "{json_dict[Language]}",\n'
Igor Kanyuka5bfed262025-02-21 16:50:25 +0000114 ' "{description}",\n'
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600115 ' "{json_dict[RegistryPrefix]}",\n'
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600116 ' "{json_dict[OwningEntity]}",\n'
Nan Zhou49aa131f2022-09-20 18:41:37 +0000117 "}};\n"
Patrick Williams4a102cd2025-02-27 14:52:54 -0500118 "\n"
119 "static constexpr const char* url =\n"
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600120 ' "{url}";\n'
Nan Zhou49aa131f2022-09-20 18:41:37 +0000121 "\n"
Patrick Williams4a102cd2025-02-27 14:52:54 -0500122 "static constexpr std::array registry =\n"
Nan Zhou49aa131f2022-09-20 18:41:37 +0000123 "{{\n".format(
124 json_dict=json_dict,
125 url=url,
Ed Tanous56b81992024-12-02 10:36:37 -0800126 version_split=version_split,
Igor Kanyuka5bfed262025-02-21 16:50:25 +0000127 description=description,
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600128 )
129 )
Ed Tanous30a3c432022-02-07 09:37:21 -0800130
Nan Zhou49aa131f2022-09-20 18:41:37 +0000131 messages_sorted = sorted(json_dict["Messages"].items())
132 for messageId, message in messages_sorted:
133 registry.write(
134 " MessageEntry{{\n"
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600135 ' "{messageId}",\n'
Nan Zhou49aa131f2022-09-20 18:41:37 +0000136 " {{\n"
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600137 ' "{message[Description]}",\n'
138 ' "{message[Message]}",\n'
139 ' "{message[MessageSeverity]}",\n'
Nan Zhou49aa131f2022-09-20 18:41:37 +0000140 " {message[NumberOfArgs]},\n"
141 " {{".format(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600142 messageId=messageId, message=message
143 )
144 )
Nan Zhou49aa131f2022-09-20 18:41:37 +0000145 paramTypes = message.get("ParamTypes")
146 if paramTypes:
147 for paramType in paramTypes:
148 registry.write(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600149 '\n "{}",'.format(paramType)
Nan Zhou49aa131f2022-09-20 18:41:37 +0000150 )
151 registry.write("\n },\n")
152 else:
153 registry.write("},\n")
154 registry.write(
Igor Kanyukada9dc902025-02-26 14:08:11 +0000155 ' "{message[Resolution]}",\n }}}},\n'.format(
156 message=message
157 )
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600158 )
Nan Zhou49aa131f2022-09-20 18:41:37 +0000159
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600160 registry.write("\n};\n\nenum class Index\n{\n")
Nan Zhou49aa131f2022-09-20 18:41:37 +0000161 for index, (messageId, message) in enumerate(messages_sorted):
162 messageId = messageId[0].lower() + messageId[1:]
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600163 registry.write(" {} = {},\n".format(messageId, index))
Patrick Williams4a102cd2025-02-27 14:52:54 -0500164 registry.write("};\n")
165 registry.write("}}; // struct {}\n".format(namespace))
166 registry.write("\n")
Nan Zhou49aa131f2022-09-20 18:41:37 +0000167 registry.write(
Patrick Williams4a102cd2025-02-27 14:52:54 -0500168 "[[gnu::constructor]] inline void register{}()\n".format(
169 to_pascal_case(namespace)
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600170 )
171 )
Patrick Williams4a102cd2025-02-27 14:52:54 -0500172 registry.write(
173 "{{ registerRegistry<{}>(); }}\n".format(
174 to_pascal_case(namespace)
175 )
176 )
177 registry.write("\n")
178 registry.write("} // namespace redfish::registries\n")
Ed Tanoused398212021-06-09 17:05:54 -0700179
180
Igor Kanyukada9dc902025-02-26 14:08:11 +0000181def get_privilege_string_from_list(
182 privilege_list: t.List[t.Dict[str, t.Any]],
183) -> str:
Ed Tanoused398212021-06-09 17:05:54 -0700184 privilege_string = "{{\n"
185 for privilege_json in privilege_list:
186 privileges = privilege_json["Privilege"]
187 privilege_string += " {"
Igor Kanyukada9dc902025-02-26 14:08:11 +0000188 last_privelege = ""
Ed Tanoused398212021-06-09 17:05:54 -0700189 for privilege in privileges:
Igor Kanyukada9dc902025-02-26 14:08:11 +0000190 last_privelege = privilege
Ed Tanoused398212021-06-09 17:05:54 -0700191 if privilege == "NoAuth":
192 continue
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600193 privilege_string += '"'
Ed Tanoused398212021-06-09 17:05:54 -0700194 privilege_string += privilege
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600195 privilege_string += '",\n'
Igor Kanyukada9dc902025-02-26 14:08:11 +0000196 if last_privelege != "NoAuth":
Ed Tanoused398212021-06-09 17:05:54 -0700197 privilege_string = privilege_string[:-2]
198 privilege_string += "}"
199 privilege_string += ",\n"
200 privilege_string = privilege_string[:-2]
201 privilege_string += "\n}}"
202 return privilege_string
203
Ed Tanousf395daa2021-08-02 08:56:24 -0700204
Igor Kanyukada9dc902025-02-26 14:08:11 +0000205def get_variable_name_for_privilege_set(
206 privilege_list: t.List[t.Dict[str, t.Any]],
207) -> str:
Ed Tanoused398212021-06-09 17:05:54 -0700208 names = []
209 for privilege_json in privilege_list:
210 privileges = privilege_json["Privilege"]
211 names.append("And".join(privileges))
212 return "Or".join(names)
213
Ed Tanousf395daa2021-08-02 08:56:24 -0700214
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600215PRIVILEGE_HEADER = (
Ed Tanous40e9b922024-09-10 13:50:16 -0700216 COPYRIGHT
217 + PRAGMA_ONCE
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600218 + WARNING
219 + """
Nan Zhou01c78a02022-09-20 18:17:20 +0000220#include "privileges.hpp"
221
222#include <array>
Nan Zhou043bec02022-09-20 18:12:13 +0000223
224// clang-format off
225
226namespace redfish::privileges
227{
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600228"""
229)
Nan Zhou043bec02022-09-20 18:12:13 +0000230
231
Igor Kanyukada9dc902025-02-26 14:08:11 +0000232def get_response_code(entry_id: str) -> str | None:
Ed Tanous7ccfe682024-11-16 14:36:16 -0800233 codes = {
Myung Bae3498f482025-04-09 06:22:54 -0400234 "AccessDenied": "forbidden",
Ed Tanous7ccfe682024-11-16 14:36:16 -0800235 "AccountForSessionNoLongerExists": "forbidden",
Myung Bae3498f482025-04-09 06:22:54 -0400236 "AccountModified": "ok",
237 "AccountRemoved": "ok",
238 "CouldNotEstablishConnection": "not_found",
239 "Created": "created",
240 "EventSubscriptionLimitExceeded": "service_unavailable",
241 "GeneralError": "internal_server_error",
242 "GenerateSecretKeyRequired": "forbidden",
243 "InsufficientPrivilege": "forbidden",
244 "InsufficientStorage": "insufficient_storage",
245 "InternalError": "internal_server_error",
246 "MaximumErrorsExceeded": "internal_server_error",
247 "NoValidSession": "forbidden",
248 "OperationFailed": "bad_gateway",
249 "OperationNotAllowed": "method_not_allowed",
250 "OperationTimeout": "internal_server_error",
251 "PasswordChangeRequired": None,
252 "PreconditionFailed": "precondition_failed",
Gunnar Mills9310d762025-06-04 09:24:08 -0500253 "PropertyNotWritable": "method_not_allowed",
Myung Bae3498f482025-04-09 06:22:54 -0400254 "PropertyValueExternalConflict": "conflict",
255 "PropertyValueModified": "ok",
256 "PropertyValueResourceConflict": "conflict",
257 "ResourceAtUriUnauthorized": "unauthorized",
258 "ResourceCannotBeDeleted": "method_not_allowed",
259 "ResourceExhaustion": "service_unavailable",
260 "ResourceInStandby": "service_unavailable",
261 "ResourceInUse": "service_unavailable",
262 "ResourceNotFound": "not_found",
Myung Bae7f84d8c2023-03-14 13:44:15 -0700263 "RestrictedRole": "forbidden",
Ed Tanous7ccfe682024-11-16 14:36:16 -0800264 "ServiceDisabled": "service_unavailable",
265 "ServiceInUnknownState": "service_unavailable",
Myung Bae3498f482025-04-09 06:22:54 -0400266 "ServiceShuttingDown": "service_unavailable",
267 "ServiceTemporarilyUnavailable": "service_unavailable",
268 "SessionLimitExceeded": "service_unavailable",
Ed Tanous7ccfe682024-11-16 14:36:16 -0800269 "SessionTerminated": "ok",
270 "SubscriptionTerminated": "ok",
Ed Tanous7ccfe682024-11-16 14:36:16 -0800271 "Success": None,
Ed Tanous7ccfe682024-11-16 14:36:16 -0800272 }
273
Igor Kanyuka557ab0d2025-02-18 15:20:38 +0000274 return codes.get(entry_id, "bad_request")
Ed Tanous7ccfe682024-11-16 14:36:16 -0800275
276
Ed Tanousf175c282024-12-02 15:12:50 -0800277def make_error_function(
Igor Kanyukada9dc902025-02-26 14:08:11 +0000278 entry_id: str,
279 entry: t.Dict[str, t.Any],
280 is_header: bool,
281 registry_name: str,
282 namespace_name: str,
283) -> str:
Patrick Williams4a102cd2025-02-27 14:52:54 -0500284 struct_name = to_pascal_case(namespace_name)
Ed Tanous644cdcb2024-11-17 11:12:41 -0800285 arg_nonstring_types = {
286 "const boost::urls::url_view_base&": {
287 "AccessDenied": [1],
288 "CouldNotEstablishConnection": [1],
289 "GenerateSecretKeyRequired": [1],
290 "InvalidObject": [1],
291 "PasswordChangeRequired": [1],
292 "PropertyValueResourceConflict": [3],
293 "ResetRequired": [1],
294 "ResourceAtUriInUnknownFormat": [1],
295 "ResourceAtUriUnauthorized": [1],
296 "ResourceCreationConflict": [1],
297 "ResourceMissingAtURI": [1],
298 "SourceDoesNotSupportProtocol": [1],
299 },
300 "const nlohmann::json&": {
301 "ActionParameterValueError": [1],
302 "ActionParameterValueFormatError": [1],
303 "ActionParameterValueTypeError": [1],
304 "PropertyValueExternalConflict": [2],
305 "PropertyValueFormatError": [1],
306 "PropertyValueIncorrect": [2],
307 "PropertyValueModified": [2],
308 "PropertyValueNotInList": [1],
309 "PropertyValueOutOfRange": [1],
310 "PropertyValueResourceConflict": [2],
311 "PropertyValueTypeError": [1],
312 "QueryParameterValueFormatError": [1],
313 "QueryParameterValueTypeError": [1],
314 },
315 "uint64_t": {
316 "ArraySizeTooLong": [2],
317 "InvalidIndex": [1],
318 "StringValueTooLong": [2],
Ed Tanousf175c282024-12-02 15:12:50 -0800319 "TaskProgressChanged": [2],
Ed Tanous644cdcb2024-11-17 11:12:41 -0800320 },
Ed Tanous42079ec2024-11-16 13:32:29 -0800321 }
322
Ed Tanous7ccfe682024-11-16 14:36:16 -0800323 out = ""
324 args = []
325 argtypes = []
326 for arg_index, arg in enumerate(entry.get("ParamTypes", [])):
327 arg_index += 1
Ed Tanous644cdcb2024-11-17 11:12:41 -0800328 typename = "std::string_view"
329 for typestring, entries in arg_nonstring_types.items():
330 if arg_index in entries.get(entry_id, []):
331 typename = typestring
332
Ed Tanous7ccfe682024-11-16 14:36:16 -0800333 argtypes.append(typename)
334 args.append(f"{typename} arg{arg_index}")
335 function_name = entry_id[0].lower() + entry_id[1:]
336 arg = ", ".join(args)
Ed Tanous10cf50d2025-05-06 16:10:32 -0700337 out += f"nlohmann::json::object_t {function_name}({arg})"
Ed Tanous7ccfe682024-11-16 14:36:16 -0800338
339 if is_header:
340 out += ";\n\n"
341 else:
342 out += "\n{\n"
343 to_array_type = ""
Igor Kanyukada9dc902025-02-26 14:08:11 +0000344 arg_param = "{}"
Ed Tanous7ccfe682024-11-16 14:36:16 -0800345 if argtypes:
346 outargs = []
347 for index, typename in enumerate(argtypes):
348 index += 1
349 if typename == "const nlohmann::json&":
350 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 -0800351 elif typename == "uint64_t":
Ed Tanous7ccfe682024-11-16 14:36:16 -0800352 out += f"std::string arg{index}Str = std::to_string(arg{index});\n"
353
354 for index, typename in enumerate(argtypes):
355 index += 1
356 if typename == "const boost::urls::url_view_base&":
357 outargs.append(f"arg{index}.buffer()")
358 to_array_type = "<std::string_view>"
359 elif typename == "const nlohmann::json&":
360 outargs.append(f"arg{index}Str")
361 to_array_type = "<std::string_view>"
Ed Tanous644cdcb2024-11-17 11:12:41 -0800362 elif typename == "uint64_t":
Ed Tanous7ccfe682024-11-16 14:36:16 -0800363 outargs.append(f"arg{index}Str")
364 to_array_type = "<std::string_view>"
365 else:
366 outargs.append(f"arg{index}")
367 argstring = ", ".join(outargs)
Ed Tanous7ccfe682024-11-16 14:36:16 -0800368 arg_param = f"std::to_array{to_array_type}({{{argstring}}})"
Patrick Williams4a102cd2025-02-27 14:52:54 -0500369 out += f" return getLog(redfish::registries::{struct_name}::Index::{function_name}, {arg_param});"
Ed Tanous7ccfe682024-11-16 14:36:16 -0800370 out += "\n}\n\n"
Ed Tanousf175c282024-12-02 15:12:50 -0800371 if registry_name == "Base":
372 args.insert(0, "crow::Response& res")
Ed Tanous7ccfe682024-11-16 14:36:16 -0800373 if entry_id == "InternalError":
Ed Tanousf175c282024-12-02 15:12:50 -0800374 if is_header:
375 args.append(
376 "std::source_location location = std::source_location::current()"
377 )
378 else:
379 args.append("const std::source_location location")
380 arg = ", ".join(args)
381 out += f"void {function_name}({arg})"
382 if is_header:
383 out += ";\n"
Ed Tanous7ccfe682024-11-16 14:36:16 -0800384 else:
Ed Tanousf175c282024-12-02 15:12:50 -0800385 out += "\n{\n"
386 if entry_id == "InternalError":
387 out += """BMCWEB_LOG_CRITICAL("Internal Error {}({}:{}) `{}`: ", location.file_name(),
388 location.line(), location.column(),
389 location.function_name());\n"""
390
391 if entry_id == "ServiceTemporarilyUnavailable":
392 out += "res.addHeader(boost::beast::http::field::retry_after, arg1);"
393
Igor Kanyuka557ab0d2025-02-18 15:20:38 +0000394 res = get_response_code(entry_id)
Ed Tanousf175c282024-12-02 15:12:50 -0800395 if res:
396 out += f" res.result(boost::beast::http::status::{res});\n"
Igor Kanyukada9dc902025-02-26 14:08:11 +0000397 args_out = ", ".join([f"arg{x + 1}" for x in range(len(argtypes))])
Ed Tanousf175c282024-12-02 15:12:50 -0800398
399 addMessageToJson = {
400 "PropertyDuplicate": 1,
401 "ResourceAlreadyExists": 2,
402 "CreateFailedMissingReqProperties": 1,
403 "PropertyValueFormatError": 2,
404 "PropertyValueNotInList": 2,
405 "PropertyValueTypeError": 2,
406 "PropertyValueError": 1,
407 "PropertyNotWritable": 1,
408 "PropertyValueModified": 1,
409 "PropertyMissing": 1,
410 }
411
412 addMessageToRoot = [
413 "SessionTerminated",
414 "SubscriptionTerminated",
415 "AccountRemoved",
416 "Created",
417 "Success",
Ed Tanousf175c282024-12-02 15:12:50 -0800418 ]
419
420 if entry_id in addMessageToJson:
421 out += f" addMessageToJson(res.jsonValue, {function_name}({args_out}), arg{addMessageToJson[entry_id]});\n"
422 elif entry_id in addMessageToRoot:
423 out += f" addMessageToJsonRoot(res.jsonValue, {function_name}({args_out}));\n"
424 else:
425 out += f" addMessageToErrorJson(res.jsonValue, {function_name}({args_out}));\n"
426 out += "}\n"
Ed Tanous7ccfe682024-11-16 14:36:16 -0800427 out += "\n"
428 return out
429
430
Ed Tanousf175c282024-12-02 15:12:50 -0800431def create_error_registry(
Igor Kanyukada9dc902025-02-26 14:08:11 +0000432 registry_info: RegistryInfo,
433 registry_name: str,
434 namespace_name: str,
435 filename: str,
436) -> None:
437 file, json_dict, namespace, url = registry_info
Ed Tanousf175c282024-12-02 15:12:50 -0800438 base_filename = filename + "_messages"
Patrick Williams4a102cd2025-02-27 14:52:54 -0500439 struct_name = to_pascal_case(namespace_name)
Ed Tanous42079ec2024-11-16 13:32:29 -0800440
Ed Tanous42079ec2024-11-16 13:32:29 -0800441 error_messages_hpp = os.path.join(
Ed Tanousf175c282024-12-02 15:12:50 -0800442 SCRIPT_DIR, "..", "redfish-core", "include", f"{base_filename}.hpp"
Ed Tanous42079ec2024-11-16 13:32:29 -0800443 )
Ed Tanousf8cca872024-11-16 22:47:34 -0800444 messages = json_dict["Messages"]
445
Ed Tanous42079ec2024-11-16 13:32:29 -0800446 with open(
447 error_messages_hpp,
448 "w",
449 ) as out:
450 out.write(PRAGMA_ONCE)
451 out.write(WARNING)
452 out.write(
453 """
Ed Tanous4aad6ed2025-01-30 09:35:06 -0800454// These generated headers are a superset of what is needed.
455// clang sees them as an error, so ignore
456// NOLINTBEGIN(misc-include-cleaner)
Ed Tanous42079ec2024-11-16 13:32:29 -0800457#include "http_response.hpp"
458
459#include <boost/url/url_view_base.hpp>
460#include <nlohmann/json.hpp>
461
Ed Tanous4aad6ed2025-01-30 09:35:06 -0800462#include <cstdint>
Ed Tanous42079ec2024-11-16 13:32:29 -0800463#include <source_location>
Ed Tanous42079ec2024-11-16 13:32:29 -0800464#include <string_view>
Ed Tanous4aad6ed2025-01-30 09:35:06 -0800465// NOLINTEND(misc-include-cleaner)
Ed Tanous42079ec2024-11-16 13:32:29 -0800466
467namespace redfish
468{
469
470namespace messages
471{
Ed Tanous42079ec2024-11-16 13:32:29 -0800472"""
473 )
Ed Tanous42079ec2024-11-16 13:32:29 -0800474 for entry_id, entry in messages.items():
475 message = entry["Message"]
476 for index in range(1, 10):
477 message = message.replace(f"'%{index}'", f"<arg{index}>")
478 message = message.replace(f"%{index}", f"<arg{index}>")
479
Ed Tanousf175c282024-12-02 15:12:50 -0800480 if registry_name == "Base":
481 out.write("/**\n")
482 out.write(f"* @brief Formats {entry_id} message into JSON\n")
483 out.write(f'* Message body: "{message}"\n')
484 out.write("*\n")
485 arg_index = 0
486 for arg_index, arg in enumerate(entry.get("ParamTypes", [])):
487 arg_index += 1
Ed Tanous42079ec2024-11-16 13:32:29 -0800488
Ed Tanousf175c282024-12-02 15:12:50 -0800489 out.write(
490 f"* @param[in] arg{arg_index} Parameter of message that will replace %{arg_index} in its body.\n"
491 )
492 out.write("*\n")
Ed Tanous42079ec2024-11-16 13:32:29 -0800493 out.write(
Ed Tanousf175c282024-12-02 15:12:50 -0800494 f"* @returns Message {entry_id} formatted to JSON */\n"
Ed Tanous42079ec2024-11-16 13:32:29 -0800495 )
Ed Tanous42079ec2024-11-16 13:32:29 -0800496
Ed Tanousf175c282024-12-02 15:12:50 -0800497 out.write(
498 make_error_function(
499 entry_id, entry, True, registry_name, namespace_name
500 )
501 )
Ed Tanous42079ec2024-11-16 13:32:29 -0800502 out.write(" }\n")
503 out.write("}\n")
Ed Tanous7ccfe682024-11-16 14:36:16 -0800504
505 error_messages_cpp = os.path.join(
Ed Tanousf175c282024-12-02 15:12:50 -0800506 SCRIPT_DIR, "..", "redfish-core", "src", f"{base_filename}.cpp"
Ed Tanous7ccfe682024-11-16 14:36:16 -0800507 )
508 with open(
509 error_messages_cpp,
510 "w",
511 ) as out:
512 out.write(WARNING)
Ed Tanousf175c282024-12-02 15:12:50 -0800513 out.write(f'\n#include "{base_filename}.hpp"\n')
Ed Tanous847deee2024-12-02 15:28:10 -0800514 headers = []
Ed Tanous7ccfe682024-11-16 14:36:16 -0800515
Ed Tanous847deee2024-12-02 15:28:10 -0800516 headers.append('"registries.hpp"')
Ed Tanousf175c282024-12-02 15:12:50 -0800517 if registry_name == "Base":
518 reg_name_lower = "base"
Ed Tanous6c038f22025-01-14 09:46:04 -0800519 headers.append('"error_message_utils.hpp"')
Ed Tanous847deee2024-12-02 15:28:10 -0800520 headers.append('"http_response.hpp"')
521 headers.append('"logging.hpp"')
522 headers.append("<boost/beast/http/field.hpp>")
523 headers.append("<boost/beast/http/status.hpp>")
524 headers.append("<boost/url/url_view_base.hpp>")
525 headers.append("<source_location>")
Ed Tanousf175c282024-12-02 15:12:50 -0800526 else:
527 reg_name_lower = namespace_name.lower()
Ed Tanous847deee2024-12-02 15:28:10 -0800528 headers.append(f'"registries/{reg_name_lower}_message_registry.hpp"')
Ed Tanous7ccfe682024-11-16 14:36:16 -0800529
Ed Tanous847deee2024-12-02 15:28:10 -0800530 headers.append("<nlohmann/json.hpp>")
531 headers.append("<array>")
532 headers.append("<cstddef>")
533 headers.append("<span>")
Ed Tanous847deee2024-12-02 15:28:10 -0800534 headers.append("<string_view>")
535
536 for header in headers:
537 out.write(f"#include {header}\n")
538
Ed Tanousf175c282024-12-02 15:12:50 -0800539 out.write(
540 """
Ed Tanous7ccfe682024-11-16 14:36:16 -0800541// Clang can't seem to decide whether this header needs to be included or not,
542// and is inconsistent. Include it for now
543// NOLINTNEXTLINE(misc-include-cleaner)
Ed Tanous2ca56192025-09-16 13:19:08 -0700544#include <cstdint>
545// NOLINTNEXTLINE(misc-include-cleaner)
546#include <string>
547// NOLINTNEXTLINE(misc-include-cleaner)
Ed Tanous7ccfe682024-11-16 14:36:16 -0800548#include <utility>
549
550namespace redfish
551{
552
553namespace messages
554{
Ed Tanousf175c282024-12-02 15:12:50 -0800555"""
556 )
Ed Tanousf175c282024-12-02 15:12:50 -0800557 out.write(
558 """
Ed Tanous10cf50d2025-05-06 16:10:32 -0700559static nlohmann::json::object_t getLog(redfish::registries::{struct_name}::Index name,
Ed Tanousf175c282024-12-02 15:12:50 -0800560 std::span<const std::string_view> args)
561{{
562 size_t index = static_cast<size_t>(name);
Patrick Williams4a102cd2025-02-27 14:52:54 -0500563 if (index >= redfish::registries::{struct_name}::registry.size())
Ed Tanousf175c282024-12-02 15:12:50 -0800564 {{
565 return {{}};
566 }}
Patrick Williams4a102cd2025-02-27 14:52:54 -0500567 return getLogFromRegistry(redfish::registries::{struct_name}::header,
568 redfish::registries::{struct_name}::registry, index, args);
Ed Tanousf175c282024-12-02 15:12:50 -0800569}}
570
571""".format(
Patrick Williams4a102cd2025-02-27 14:52:54 -0500572 struct_name=struct_name
Ed Tanousf175c282024-12-02 15:12:50 -0800573 )
Ed Tanous7ccfe682024-11-16 14:36:16 -0800574 )
575 for entry_id, entry in messages.items():
576 out.write(
577 f"""/**
578 * @internal
579 * @brief Formats {entry_id} message into JSON
580 *
581 * See header file for more information
582 * @endinternal
583 */
584"""
585 )
586 message = entry["Message"]
Ed Tanousf175c282024-12-02 15:12:50 -0800587 out.write(
588 make_error_function(
589 entry_id, entry, False, registry_name, namespace_name
590 )
591 )
Ed Tanous7ccfe682024-11-16 14:36:16 -0800592
593 out.write(" }\n")
594 out.write("}\n")
595 os.system(f"clang-format -i {error_messages_hpp} {error_messages_cpp}")
Ed Tanous42079ec2024-11-16 13:32:29 -0800596
597
Igor Kanyukada9dc902025-02-26 14:08:11 +0000598def make_privilege_registry() -> None:
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600599 path, json_file, type_name, url = make_getter(
Gunnar Mills5910d942024-04-16 12:07:17 -0500600 "Redfish_1.5.0_PrivilegeRegistry.json",
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600601 "privilege_registry.hpp",
602 "privilege",
603 )
604 with open(path, "w") as registry:
Nan Zhou043bec02022-09-20 18:12:13 +0000605 registry.write(PRIVILEGE_HEADER)
Ed Tanoused398212021-06-09 17:05:54 -0700606
Igor Kanyukada9dc902025-02-26 14:08:11 +0000607 privilege_dict: t.Dict[str, t.Tuple[t.Any, str | None]] = {}
Ed Tanoused398212021-06-09 17:05:54 -0700608 for mapping in json_file["Mappings"]:
609 # first pass, identify all the unique privilege sets
610 for operation, privilege_list in mapping["OperationMap"].items():
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600611 privilege_dict[
612 get_privilege_string_from_list(privilege_list)
Igor Kanyukada9dc902025-02-26 14:08:11 +0000613 ] = (
614 privilege_list,
615 None,
616 )
Abhishek Patelfff6a4d2021-07-21 11:29:45 -0500617 if "SubordinateOverrides" in mapping:
618 for subordinateOverride in mapping["SubordinateOverrides"]:
619 for operation, privilege_list in subordinateOverride[
620 "OperationMap"
621 ].items():
622 privilege_dict[
623 get_privilege_string_from_list(privilege_list)
624 ] = (
625 privilege_list,
626 None,
627 )
Ed Tanoused398212021-06-09 17:05:54 -0700628 for index, key in enumerate(privilege_dict):
Igor Kanyukada9dc902025-02-26 14:08:11 +0000629 (privilege_list, _) = privilege_dict[key]
Ed Tanoused398212021-06-09 17:05:54 -0700630 name = get_variable_name_for_privilege_set(privilege_list)
Ed Tanousf395daa2021-08-02 08:56:24 -0700631 registry.write(
Ed Tanous5b9ef702022-02-17 12:19:32 -0800632 "const std::array<Privileges, {length}> "
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600633 "privilegeSet{name} = {key};\n".format(
634 length=len(privilege_list), name=name, key=key
635 )
Ed Tanous5b9ef702022-02-17 12:19:32 -0800636 )
Ed Tanoused398212021-06-09 17:05:54 -0700637 privilege_dict[key] = (privilege_list, name)
Ed Tanoused398212021-06-09 17:05:54 -0700638
639 for mapping in json_file["Mappings"]:
640 entity = mapping["Entity"]
Ed Tanous4d99bbb2022-02-17 10:02:57 -0800641 registry.write("// {}\n".format(entity))
Ed Tanoused398212021-06-09 17:05:54 -0700642 for operation, privilege_list in mapping["OperationMap"].items():
643 privilege_string = get_privilege_string_from_list(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600644 privilege_list
645 )
Ed Tanoused398212021-06-09 17:05:54 -0700646 operation = operation.lower()
647
Ed Tanousf395daa2021-08-02 08:56:24 -0700648 registry.write(
649 "const static auto& {}{} = privilegeSet{};\n".format(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600650 operation, entity, privilege_dict[privilege_string][1]
651 )
652 )
Ed Tanoused398212021-06-09 17:05:54 -0700653 registry.write("\n")
Abhishek Patelfff6a4d2021-07-21 11:29:45 -0500654 if "SubordinateOverrides" in mapping:
655 for subordinateOverrides in mapping["SubordinateOverrides"]:
656 target_list_list = subordinateOverrides["Targets"]
657 registry.write("// Subordinate override for ")
658 concateVarName = ""
659 for target in target_list_list:
660 registry.write(target + " -> ")
661 concateVarName += target
662 registry.write(entity)
663 registry.write("\n")
664 for operation, privilege_list in subordinateOverrides[
665 "OperationMap"
666 ].items():
667 privilege_string = get_privilege_string_from_list(
668 privilege_list
669 )
670 operation = operation.lower()
671 registry.write(
672 "const static auto& {}{}SubOver{} = privilegeSet{};\n".format(
673 operation,
674 entity,
675 concateVarName,
676 privilege_dict[privilege_string][1],
677 )
678 )
679 registry.write("\n")
Ed Tanous5b9ef702022-02-17 12:19:32 -0800680 registry.write(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600681 "} // namespace redfish::privileges\n// clang-format on\n"
682 )
Ed Tanoused398212021-06-09 17:05:54 -0700683
684
Igor Kanyukada9dc902025-02-26 14:08:11 +0000685def to_pascal_case(text: str) -> str:
Gunnar Mills665e7602024-04-10 13:14:41 -0500686 s = text.replace("_", " ")
Igor Kanyukada9dc902025-02-26 14:08:11 +0000687 s1 = s.split()
Gunnar Mills665e7602024-04-10 13:14:41 -0500688 if len(text) == 0:
689 return text
Igor Kanyukada9dc902025-02-26 14:08:11 +0000690 return "".join(i.capitalize() for i in s1[0:])
Gunnar Mills665e7602024-04-10 13:14:41 -0500691
692
Igor Kanyukada9dc902025-02-26 14:08:11 +0000693def main() -> None:
Ed Tanousc8895b02025-01-03 11:44:08 -0800694 dmtf_registries = OrderedDict(
695 [
696 ("base", "1.19.0"),
697 ("composition", "1.1.2"),
Igor Kanyuka0bce6a92025-02-21 12:40:12 +0000698 ("environmental", "1.1.0"),
Ed Tanousc8895b02025-01-03 11:44:08 -0800699 ("ethernet_fabric", "1.0.1"),
700 ("fabric", "1.0.2"),
701 ("heartbeat_event", "1.0.1"),
702 ("job_event", "1.0.1"),
703 ("license", "1.0.3"),
704 ("log_service", "1.0.1"),
705 ("network_device", "1.0.3"),
706 ("platform", "1.0.1"),
707 ("power", "1.0.1"),
708 ("resource_event", "1.3.0"),
709 ("sensor_event", "1.0.1"),
710 ("storage_device", "1.2.1"),
711 ("task_event", "1.0.3"),
712 ("telemetry", "1.0.0"),
Alexander Hansend3616d12025-08-12 13:25:55 +0200713 ("update", "1.2.0"),
Ed Tanousc8895b02025-01-03 11:44:08 -0800714 ]
715 )
Gunnar Mills665e7602024-04-10 13:14:41 -0500716
Nan Zhou49aa131f2022-09-20 18:41:37 +0000717 parser = argparse.ArgumentParser()
718 parser.add_argument(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600719 "--registries",
720 type=str,
Gunnar Mills665e7602024-04-10 13:14:41 -0500721 default="privilege,openbmc,"
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700722 + ",".join([dmtf for dmtf in dmtf_registries]),
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600723 help="Comma delimited list of registries to update",
724 )
Nan Zhou49aa131f2022-09-20 18:41:37 +0000725
726 args = parser.parse_args()
727
728 registries = set(args.registries.split(","))
Igor Kanyukada9dc902025-02-26 14:08:11 +0000729 registries_map: t.OrderedDict[str, RegistryInfo] = OrderedDict()
Nan Zhou49aa131f2022-09-20 18:41:37 +0000730
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700731 for registry, version in dmtf_registries.items():
Gunnar Mills665e7602024-04-10 13:14:41 -0500732 if registry in registries:
733 registry_pascal_case = to_pascal_case(registry)
Igor Kanyuka557ab0d2025-02-18 15:20:38 +0000734 registries_map[registry] = make_getter(
735 f"{registry_pascal_case}.{version}.json",
736 f"{registry}_message_registry.hpp",
737 registry,
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600738 )
Ed Tanous3e5faba2023-08-16 15:11:29 -0700739 if "openbmc" in registries:
Igor Kanyuka557ab0d2025-02-18 15:20:38 +0000740 registries_map["openbmc"] = openbmc_local_getter()
Nan Zhou49aa131f2022-09-20 18:41:37 +0000741
Igor Kanyukada9dc902025-02-26 14:08:11 +0000742 update_registries(list(registries_map.values()))
Nan Zhou49aa131f2022-09-20 18:41:37 +0000743
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700744 if "base" in registries_map:
745 create_error_registry(
Ed Tanousc8895b02025-01-03 11:44:08 -0800746 registries_map["base"],
Ed Tanousc8895b02025-01-03 11:44:08 -0800747 "Base",
748 "base",
749 "error",
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700750 )
751 if "heartbeat_event" in registries_map:
752 create_error_registry(
753 registries_map["heartbeat_event"],
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700754 "HeartbeatEvent",
755 "heartbeat_event",
756 "heartbeat",
757 )
758 if "resource_event" in registries_map:
759 create_error_registry(
760 registries_map["resource_event"],
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700761 "ResourceEvent",
762 "resource_event",
763 "resource",
764 )
765 if "task_event" in registries_map:
766 create_error_registry(
Ed Tanousc8895b02025-01-03 11:44:08 -0800767 registries_map["task_event"],
Ed Tanousc8895b02025-01-03 11:44:08 -0800768 "TaskEvent",
769 "task_event",
770 "task",
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700771 )
Alexander Hansend3616d12025-08-12 13:25:55 +0200772 if "update" in registries_map:
773 create_error_registry(
774 registries_map["update"],
775 "Update",
776 "update",
777 "update",
778 )
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700779
Nan Zhou49aa131f2022-09-20 18:41:37 +0000780 if "privilege" in registries:
781 make_privilege_registry()
782
783
784if __name__ == "__main__":
785 main()