blob: 7b315a86180e4e25d2de106d367b84152fd11574 [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 },
Ed Tanous42079ec2024-11-16 13:32:29 -0800315 }
316
Ed Tanous7ccfe682024-11-16 14:36:16 -0800317 out = ""
318 args = []
319 argtypes = []
320 for arg_index, arg in enumerate(entry.get("ParamTypes", [])):
321 arg_index += 1
Ed Tanous644cdcb2024-11-17 11:12:41 -0800322 typename = "std::string_view"
Ed Tanouse8f66f02025-10-08 15:42:52 -0700323 if arg == "number":
324 typename = "uint64_t"
Ed Tanous644cdcb2024-11-17 11:12:41 -0800325 for typestring, entries in arg_nonstring_types.items():
326 if arg_index in entries.get(entry_id, []):
327 typename = typestring
328
Ed Tanous7ccfe682024-11-16 14:36:16 -0800329 argtypes.append(typename)
330 args.append(f"{typename} arg{arg_index}")
331 function_name = entry_id[0].lower() + entry_id[1:]
332 arg = ", ".join(args)
Ed Tanous10cf50d2025-05-06 16:10:32 -0700333 out += f"nlohmann::json::object_t {function_name}({arg})"
Ed Tanous7ccfe682024-11-16 14:36:16 -0800334
335 if is_header:
336 out += ";\n\n"
337 else:
338 out += "\n{\n"
339 to_array_type = ""
Igor Kanyukada9dc902025-02-26 14:08:11 +0000340 arg_param = "{}"
Ed Tanous7ccfe682024-11-16 14:36:16 -0800341 if argtypes:
342 outargs = []
343 for index, typename in enumerate(argtypes):
344 index += 1
345 if typename == "const nlohmann::json&":
346 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 -0800347 elif typename == "uint64_t":
Ed Tanous7ccfe682024-11-16 14:36:16 -0800348 out += f"std::string arg{index}Str = std::to_string(arg{index});\n"
349
350 for index, typename in enumerate(argtypes):
351 index += 1
352 if typename == "const boost::urls::url_view_base&":
353 outargs.append(f"arg{index}.buffer()")
354 to_array_type = "<std::string_view>"
355 elif typename == "const nlohmann::json&":
356 outargs.append(f"arg{index}Str")
357 to_array_type = "<std::string_view>"
Ed Tanous644cdcb2024-11-17 11:12:41 -0800358 elif typename == "uint64_t":
Ed Tanous7ccfe682024-11-16 14:36:16 -0800359 outargs.append(f"arg{index}Str")
360 to_array_type = "<std::string_view>"
361 else:
362 outargs.append(f"arg{index}")
363 argstring = ", ".join(outargs)
Ed Tanous7ccfe682024-11-16 14:36:16 -0800364 arg_param = f"std::to_array{to_array_type}({{{argstring}}})"
Patrick Williams4a102cd2025-02-27 14:52:54 -0500365 out += f" return getLog(redfish::registries::{struct_name}::Index::{function_name}, {arg_param});"
Ed Tanous7ccfe682024-11-16 14:36:16 -0800366 out += "\n}\n\n"
Ed Tanousf175c282024-12-02 15:12:50 -0800367 if registry_name == "Base":
368 args.insert(0, "crow::Response& res")
Ed Tanous7ccfe682024-11-16 14:36:16 -0800369 if entry_id == "InternalError":
Ed Tanousf175c282024-12-02 15:12:50 -0800370 if is_header:
371 args.append(
372 "std::source_location location = std::source_location::current()"
373 )
374 else:
375 args.append("const std::source_location location")
376 arg = ", ".join(args)
377 out += f"void {function_name}({arg})"
378 if is_header:
379 out += ";\n"
Ed Tanous7ccfe682024-11-16 14:36:16 -0800380 else:
Ed Tanousf175c282024-12-02 15:12:50 -0800381 out += "\n{\n"
382 if entry_id == "InternalError":
383 out += """BMCWEB_LOG_CRITICAL("Internal Error {}({}:{}) `{}`: ", location.file_name(),
384 location.line(), location.column(),
385 location.function_name());\n"""
386
387 if entry_id == "ServiceTemporarilyUnavailable":
388 out += "res.addHeader(boost::beast::http::field::retry_after, arg1);"
389
Igor Kanyuka557ab0d2025-02-18 15:20:38 +0000390 res = get_response_code(entry_id)
Ed Tanousf175c282024-12-02 15:12:50 -0800391 if res:
392 out += f" res.result(boost::beast::http::status::{res});\n"
Igor Kanyukada9dc902025-02-26 14:08:11 +0000393 args_out = ", ".join([f"arg{x + 1}" for x in range(len(argtypes))])
Ed Tanousf175c282024-12-02 15:12:50 -0800394
395 addMessageToJson = {
396 "PropertyDuplicate": 1,
397 "ResourceAlreadyExists": 2,
398 "CreateFailedMissingReqProperties": 1,
399 "PropertyValueFormatError": 2,
400 "PropertyValueNotInList": 2,
401 "PropertyValueTypeError": 2,
402 "PropertyValueError": 1,
403 "PropertyNotWritable": 1,
404 "PropertyValueModified": 1,
405 "PropertyMissing": 1,
406 }
407
408 addMessageToRoot = [
409 "SessionTerminated",
410 "SubscriptionTerminated",
411 "AccountRemoved",
412 "Created",
413 "Success",
Ed Tanousf175c282024-12-02 15:12:50 -0800414 ]
415
416 if entry_id in addMessageToJson:
417 out += f" addMessageToJson(res.jsonValue, {function_name}({args_out}), arg{addMessageToJson[entry_id]});\n"
418 elif entry_id in addMessageToRoot:
419 out += f" addMessageToJsonRoot(res.jsonValue, {function_name}({args_out}));\n"
420 else:
421 out += f" addMessageToErrorJson(res.jsonValue, {function_name}({args_out}));\n"
422 out += "}\n"
Ed Tanous7ccfe682024-11-16 14:36:16 -0800423 out += "\n"
424 return out
425
426
Ed Tanousf175c282024-12-02 15:12:50 -0800427def create_error_registry(
Igor Kanyukada9dc902025-02-26 14:08:11 +0000428 registry_info: RegistryInfo,
429 registry_name: str,
430 namespace_name: str,
431 filename: str,
432) -> None:
433 file, json_dict, namespace, url = registry_info
Ed Tanousf175c282024-12-02 15:12:50 -0800434 base_filename = filename + "_messages"
Patrick Williams4a102cd2025-02-27 14:52:54 -0500435 struct_name = to_pascal_case(namespace_name)
Ed Tanous42079ec2024-11-16 13:32:29 -0800436
Ed Tanous42079ec2024-11-16 13:32:29 -0800437 error_messages_hpp = os.path.join(
Ed Tanousf175c282024-12-02 15:12:50 -0800438 SCRIPT_DIR, "..", "redfish-core", "include", f"{base_filename}.hpp"
Ed Tanous42079ec2024-11-16 13:32:29 -0800439 )
Ed Tanousf8cca872024-11-16 22:47:34 -0800440 messages = json_dict["Messages"]
441
Ed Tanous42079ec2024-11-16 13:32:29 -0800442 with open(
443 error_messages_hpp,
444 "w",
445 ) as out:
446 out.write(PRAGMA_ONCE)
447 out.write(WARNING)
448 out.write(
449 """
Ed Tanous4aad6ed2025-01-30 09:35:06 -0800450// These generated headers are a superset of what is needed.
451// clang sees them as an error, so ignore
452// NOLINTBEGIN(misc-include-cleaner)
Ed Tanous42079ec2024-11-16 13:32:29 -0800453#include "http_response.hpp"
454
455#include <boost/url/url_view_base.hpp>
456#include <nlohmann/json.hpp>
457
Ed Tanous4aad6ed2025-01-30 09:35:06 -0800458#include <cstdint>
Ed Tanous42079ec2024-11-16 13:32:29 -0800459#include <source_location>
Ed Tanous42079ec2024-11-16 13:32:29 -0800460#include <string_view>
Ed Tanous4aad6ed2025-01-30 09:35:06 -0800461// NOLINTEND(misc-include-cleaner)
Ed Tanous42079ec2024-11-16 13:32:29 -0800462
463namespace redfish
464{
465
466namespace messages
467{
Ed Tanous42079ec2024-11-16 13:32:29 -0800468"""
469 )
Ed Tanous42079ec2024-11-16 13:32:29 -0800470 for entry_id, entry in messages.items():
471 message = entry["Message"]
472 for index in range(1, 10):
473 message = message.replace(f"'%{index}'", f"<arg{index}>")
474 message = message.replace(f"%{index}", f"<arg{index}>")
475
Ed Tanousf175c282024-12-02 15:12:50 -0800476 if registry_name == "Base":
477 out.write("/**\n")
478 out.write(f"* @brief Formats {entry_id} message into JSON\n")
479 out.write(f'* Message body: "{message}"\n')
480 out.write("*\n")
481 arg_index = 0
482 for arg_index, arg in enumerate(entry.get("ParamTypes", [])):
483 arg_index += 1
Ed Tanous42079ec2024-11-16 13:32:29 -0800484
Ed Tanousf175c282024-12-02 15:12:50 -0800485 out.write(
486 f"* @param[in] arg{arg_index} Parameter of message that will replace %{arg_index} in its body.\n"
487 )
488 out.write("*\n")
Ed Tanous42079ec2024-11-16 13:32:29 -0800489 out.write(
Ed Tanousf175c282024-12-02 15:12:50 -0800490 f"* @returns Message {entry_id} formatted to JSON */\n"
Ed Tanous42079ec2024-11-16 13:32:29 -0800491 )
Ed Tanous42079ec2024-11-16 13:32:29 -0800492
Ed Tanousf175c282024-12-02 15:12:50 -0800493 out.write(
494 make_error_function(
495 entry_id, entry, True, registry_name, namespace_name
496 )
497 )
Ed Tanous42079ec2024-11-16 13:32:29 -0800498 out.write(" }\n")
499 out.write("}\n")
Ed Tanous7ccfe682024-11-16 14:36:16 -0800500
501 error_messages_cpp = os.path.join(
Ed Tanousf175c282024-12-02 15:12:50 -0800502 SCRIPT_DIR, "..", "redfish-core", "src", f"{base_filename}.cpp"
Ed Tanous7ccfe682024-11-16 14:36:16 -0800503 )
504 with open(
505 error_messages_cpp,
506 "w",
507 ) as out:
508 out.write(WARNING)
Ed Tanousf175c282024-12-02 15:12:50 -0800509 out.write(f'\n#include "{base_filename}.hpp"\n')
Ed Tanous847deee2024-12-02 15:28:10 -0800510 headers = []
Ed Tanous7ccfe682024-11-16 14:36:16 -0800511
Ed Tanous847deee2024-12-02 15:28:10 -0800512 headers.append('"registries.hpp"')
Ed Tanousf175c282024-12-02 15:12:50 -0800513 if registry_name == "Base":
514 reg_name_lower = "base"
Ed Tanous6c038f22025-01-14 09:46:04 -0800515 headers.append('"error_message_utils.hpp"')
Ed Tanous847deee2024-12-02 15:28:10 -0800516 headers.append('"http_response.hpp"')
517 headers.append('"logging.hpp"')
518 headers.append("<boost/beast/http/field.hpp>")
519 headers.append("<boost/beast/http/status.hpp>")
520 headers.append("<boost/url/url_view_base.hpp>")
521 headers.append("<source_location>")
Ed Tanousf175c282024-12-02 15:12:50 -0800522 else:
523 reg_name_lower = namespace_name.lower()
Ed Tanous847deee2024-12-02 15:28:10 -0800524 headers.append(f'"registries/{reg_name_lower}_message_registry.hpp"')
Ed Tanous7ccfe682024-11-16 14:36:16 -0800525
Ed Tanous847deee2024-12-02 15:28:10 -0800526 headers.append("<nlohmann/json.hpp>")
527 headers.append("<array>")
528 headers.append("<cstddef>")
529 headers.append("<span>")
Ed Tanous847deee2024-12-02 15:28:10 -0800530 headers.append("<string_view>")
531
532 for header in headers:
533 out.write(f"#include {header}\n")
534
Ed Tanousf175c282024-12-02 15:12:50 -0800535 out.write(
536 """
Ed Tanous7ccfe682024-11-16 14:36:16 -0800537// Clang can't seem to decide whether this header needs to be included or not,
538// and is inconsistent. Include it for now
539// NOLINTNEXTLINE(misc-include-cleaner)
Ed Tanous2ca56192025-09-16 13:19:08 -0700540#include <cstdint>
541// NOLINTNEXTLINE(misc-include-cleaner)
542#include <string>
543// NOLINTNEXTLINE(misc-include-cleaner)
Ed Tanous7ccfe682024-11-16 14:36:16 -0800544#include <utility>
545
546namespace redfish
547{
548
549namespace messages
550{
Ed Tanousf175c282024-12-02 15:12:50 -0800551"""
552 )
Ed Tanousf175c282024-12-02 15:12:50 -0800553 out.write(
554 """
Ed Tanous10cf50d2025-05-06 16:10:32 -0700555static nlohmann::json::object_t getLog(redfish::registries::{struct_name}::Index name,
Ed Tanousf175c282024-12-02 15:12:50 -0800556 std::span<const std::string_view> args)
557{{
558 size_t index = static_cast<size_t>(name);
Patrick Williams4a102cd2025-02-27 14:52:54 -0500559 if (index >= redfish::registries::{struct_name}::registry.size())
Ed Tanousf175c282024-12-02 15:12:50 -0800560 {{
561 return {{}};
562 }}
Patrick Williams4a102cd2025-02-27 14:52:54 -0500563 return getLogFromRegistry(redfish::registries::{struct_name}::header,
564 redfish::registries::{struct_name}::registry, index, args);
Ed Tanousf175c282024-12-02 15:12:50 -0800565}}
566
567""".format(
Patrick Williams4a102cd2025-02-27 14:52:54 -0500568 struct_name=struct_name
Ed Tanousf175c282024-12-02 15:12:50 -0800569 )
Ed Tanous7ccfe682024-11-16 14:36:16 -0800570 )
571 for entry_id, entry in messages.items():
572 out.write(
573 f"""/**
574 * @internal
575 * @brief Formats {entry_id} message into JSON
576 *
577 * See header file for more information
578 * @endinternal
579 */
580"""
581 )
582 message = entry["Message"]
Ed Tanousf175c282024-12-02 15:12:50 -0800583 out.write(
584 make_error_function(
585 entry_id, entry, False, registry_name, namespace_name
586 )
587 )
Ed Tanous7ccfe682024-11-16 14:36:16 -0800588
589 out.write(" }\n")
590 out.write("}\n")
591 os.system(f"clang-format -i {error_messages_hpp} {error_messages_cpp}")
Ed Tanous42079ec2024-11-16 13:32:29 -0800592
593
Igor Kanyukada9dc902025-02-26 14:08:11 +0000594def make_privilege_registry() -> None:
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600595 path, json_file, type_name, url = make_getter(
Gunnar Mills5910d942024-04-16 12:07:17 -0500596 "Redfish_1.5.0_PrivilegeRegistry.json",
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600597 "privilege_registry.hpp",
598 "privilege",
599 )
600 with open(path, "w") as registry:
Nan Zhou043bec02022-09-20 18:12:13 +0000601 registry.write(PRIVILEGE_HEADER)
Ed Tanoused398212021-06-09 17:05:54 -0700602
Igor Kanyukada9dc902025-02-26 14:08:11 +0000603 privilege_dict: t.Dict[str, t.Tuple[t.Any, str | None]] = {}
Ed Tanoused398212021-06-09 17:05:54 -0700604 for mapping in json_file["Mappings"]:
605 # first pass, identify all the unique privilege sets
606 for operation, privilege_list in mapping["OperationMap"].items():
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600607 privilege_dict[
608 get_privilege_string_from_list(privilege_list)
Igor Kanyukada9dc902025-02-26 14:08:11 +0000609 ] = (
610 privilege_list,
611 None,
612 )
Abhishek Patelfff6a4d2021-07-21 11:29:45 -0500613 if "SubordinateOverrides" in mapping:
614 for subordinateOverride in mapping["SubordinateOverrides"]:
615 for operation, privilege_list in subordinateOverride[
616 "OperationMap"
617 ].items():
618 privilege_dict[
619 get_privilege_string_from_list(privilege_list)
620 ] = (
621 privilege_list,
622 None,
623 )
Ed Tanoused398212021-06-09 17:05:54 -0700624 for index, key in enumerate(privilege_dict):
Igor Kanyukada9dc902025-02-26 14:08:11 +0000625 (privilege_list, _) = privilege_dict[key]
Ed Tanoused398212021-06-09 17:05:54 -0700626 name = get_variable_name_for_privilege_set(privilege_list)
Ed Tanousf395daa2021-08-02 08:56:24 -0700627 registry.write(
Ed Tanous5b9ef702022-02-17 12:19:32 -0800628 "const std::array<Privileges, {length}> "
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600629 "privilegeSet{name} = {key};\n".format(
630 length=len(privilege_list), name=name, key=key
631 )
Ed Tanous5b9ef702022-02-17 12:19:32 -0800632 )
Ed Tanoused398212021-06-09 17:05:54 -0700633 privilege_dict[key] = (privilege_list, name)
Ed Tanoused398212021-06-09 17:05:54 -0700634
635 for mapping in json_file["Mappings"]:
636 entity = mapping["Entity"]
Ed Tanous4d99bbb2022-02-17 10:02:57 -0800637 registry.write("// {}\n".format(entity))
Ed Tanoused398212021-06-09 17:05:54 -0700638 for operation, privilege_list in mapping["OperationMap"].items():
639 privilege_string = get_privilege_string_from_list(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600640 privilege_list
641 )
Ed Tanoused398212021-06-09 17:05:54 -0700642 operation = operation.lower()
643
Ed Tanousf395daa2021-08-02 08:56:24 -0700644 registry.write(
645 "const static auto& {}{} = privilegeSet{};\n".format(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600646 operation, entity, privilege_dict[privilege_string][1]
647 )
648 )
Ed Tanoused398212021-06-09 17:05:54 -0700649 registry.write("\n")
Abhishek Patelfff6a4d2021-07-21 11:29:45 -0500650 if "SubordinateOverrides" in mapping:
651 for subordinateOverrides in mapping["SubordinateOverrides"]:
652 target_list_list = subordinateOverrides["Targets"]
653 registry.write("// Subordinate override for ")
654 concateVarName = ""
655 for target in target_list_list:
656 registry.write(target + " -> ")
657 concateVarName += target
658 registry.write(entity)
659 registry.write("\n")
660 for operation, privilege_list in subordinateOverrides[
661 "OperationMap"
662 ].items():
663 privilege_string = get_privilege_string_from_list(
664 privilege_list
665 )
666 operation = operation.lower()
667 registry.write(
668 "const static auto& {}{}SubOver{} = privilegeSet{};\n".format(
669 operation,
670 entity,
671 concateVarName,
672 privilege_dict[privilege_string][1],
673 )
674 )
675 registry.write("\n")
Ed Tanous5b9ef702022-02-17 12:19:32 -0800676 registry.write(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600677 "} // namespace redfish::privileges\n// clang-format on\n"
678 )
Ed Tanoused398212021-06-09 17:05:54 -0700679
680
Igor Kanyukada9dc902025-02-26 14:08:11 +0000681def to_pascal_case(text: str) -> str:
Gunnar Mills665e7602024-04-10 13:14:41 -0500682 s = text.replace("_", " ")
Igor Kanyukada9dc902025-02-26 14:08:11 +0000683 s1 = s.split()
Gunnar Mills665e7602024-04-10 13:14:41 -0500684 if len(text) == 0:
685 return text
Igor Kanyukada9dc902025-02-26 14:08:11 +0000686 return "".join(i.capitalize() for i in s1[0:])
Gunnar Mills665e7602024-04-10 13:14:41 -0500687
688
Igor Kanyukada9dc902025-02-26 14:08:11 +0000689def main() -> None:
Ed Tanousc8895b02025-01-03 11:44:08 -0800690 dmtf_registries = OrderedDict(
691 [
692 ("base", "1.19.0"),
693 ("composition", "1.1.2"),
Igor Kanyuka0bce6a92025-02-21 12:40:12 +0000694 ("environmental", "1.1.0"),
Ed Tanousc8895b02025-01-03 11:44:08 -0800695 ("ethernet_fabric", "1.0.1"),
696 ("fabric", "1.0.2"),
697 ("heartbeat_event", "1.0.1"),
698 ("job_event", "1.0.1"),
699 ("license", "1.0.3"),
700 ("log_service", "1.0.1"),
701 ("network_device", "1.0.3"),
702 ("platform", "1.0.1"),
703 ("power", "1.0.1"),
704 ("resource_event", "1.3.0"),
705 ("sensor_event", "1.0.1"),
706 ("storage_device", "1.2.1"),
707 ("task_event", "1.0.3"),
708 ("telemetry", "1.0.0"),
Alexander Hansend3616d12025-08-12 13:25:55 +0200709 ("update", "1.2.0"),
Ed Tanousc8895b02025-01-03 11:44:08 -0800710 ]
711 )
Gunnar Mills665e7602024-04-10 13:14:41 -0500712
Nan Zhou49aa131f2022-09-20 18:41:37 +0000713 parser = argparse.ArgumentParser()
714 parser.add_argument(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600715 "--registries",
716 type=str,
Gunnar Mills665e7602024-04-10 13:14:41 -0500717 default="privilege,openbmc,"
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700718 + ",".join([dmtf for dmtf in dmtf_registries]),
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600719 help="Comma delimited list of registries to update",
720 )
Nan Zhou49aa131f2022-09-20 18:41:37 +0000721
722 args = parser.parse_args()
723
724 registries = set(args.registries.split(","))
Igor Kanyukada9dc902025-02-26 14:08:11 +0000725 registries_map: t.OrderedDict[str, RegistryInfo] = OrderedDict()
Nan Zhou49aa131f2022-09-20 18:41:37 +0000726
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700727 for registry, version in dmtf_registries.items():
Gunnar Mills665e7602024-04-10 13:14:41 -0500728 if registry in registries:
729 registry_pascal_case = to_pascal_case(registry)
Igor Kanyuka557ab0d2025-02-18 15:20:38 +0000730 registries_map[registry] = make_getter(
731 f"{registry_pascal_case}.{version}.json",
732 f"{registry}_message_registry.hpp",
733 registry,
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600734 )
Ed Tanous3e5faba2023-08-16 15:11:29 -0700735 if "openbmc" in registries:
Igor Kanyuka557ab0d2025-02-18 15:20:38 +0000736 registries_map["openbmc"] = openbmc_local_getter()
Nan Zhou49aa131f2022-09-20 18:41:37 +0000737
Igor Kanyukada9dc902025-02-26 14:08:11 +0000738 update_registries(list(registries_map.values()))
Nan Zhou49aa131f2022-09-20 18:41:37 +0000739
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700740 if "base" in registries_map:
741 create_error_registry(
Ed Tanousc8895b02025-01-03 11:44:08 -0800742 registries_map["base"],
Ed Tanousc8895b02025-01-03 11:44:08 -0800743 "Base",
744 "base",
745 "error",
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700746 )
747 if "heartbeat_event" in registries_map:
748 create_error_registry(
749 registries_map["heartbeat_event"],
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700750 "HeartbeatEvent",
751 "heartbeat_event",
752 "heartbeat",
753 )
754 if "resource_event" in registries_map:
755 create_error_registry(
756 registries_map["resource_event"],
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700757 "ResourceEvent",
758 "resource_event",
759 "resource",
760 )
761 if "task_event" in registries_map:
762 create_error_registry(
Ed Tanousc8895b02025-01-03 11:44:08 -0800763 registries_map["task_event"],
Ed Tanousc8895b02025-01-03 11:44:08 -0800764 "TaskEvent",
765 "task_event",
766 "task",
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700767 )
Alexander Hansend3616d12025-08-12 13:25:55 +0200768 if "update" in registries_map:
769 create_error_registry(
770 registries_map["update"],
771 "Update",
772 "update",
773 "update",
774 )
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700775
Nan Zhou49aa131f2022-09-20 18:41:37 +0000776 if "privilege" in registries:
777 make_privilege_registry()
778
779
780if __name__ == "__main__":
781 main()