blob: d60e523ce7638acd877201f16cb9c0f4e1ffe8c5 [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",
253 "PropertyNotWritable": "forbidden",
254 "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)
337 out += f"nlohmann::json {function_name}({arg})"
338
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",
418 "PasswordChangeRequired",
419 ]
420
421 if entry_id in addMessageToJson:
422 out += f" addMessageToJson(res.jsonValue, {function_name}({args_out}), arg{addMessageToJson[entry_id]});\n"
423 elif entry_id in addMessageToRoot:
424 out += f" addMessageToJsonRoot(res.jsonValue, {function_name}({args_out}));\n"
425 else:
426 out += f" addMessageToErrorJson(res.jsonValue, {function_name}({args_out}));\n"
427 out += "}\n"
Ed Tanous7ccfe682024-11-16 14:36:16 -0800428 out += "\n"
429 return out
430
431
Ed Tanousf175c282024-12-02 15:12:50 -0800432def create_error_registry(
Igor Kanyukada9dc902025-02-26 14:08:11 +0000433 registry_info: RegistryInfo,
434 registry_name: str,
435 namespace_name: str,
436 filename: str,
437) -> None:
438 file, json_dict, namespace, url = registry_info
Ed Tanousf175c282024-12-02 15:12:50 -0800439 base_filename = filename + "_messages"
Patrick Williams4a102cd2025-02-27 14:52:54 -0500440 struct_name = to_pascal_case(namespace_name)
Ed Tanous42079ec2024-11-16 13:32:29 -0800441
Ed Tanous42079ec2024-11-16 13:32:29 -0800442 error_messages_hpp = os.path.join(
Ed Tanousf175c282024-12-02 15:12:50 -0800443 SCRIPT_DIR, "..", "redfish-core", "include", f"{base_filename}.hpp"
Ed Tanous42079ec2024-11-16 13:32:29 -0800444 )
Ed Tanousf8cca872024-11-16 22:47:34 -0800445 messages = json_dict["Messages"]
446
Ed Tanous42079ec2024-11-16 13:32:29 -0800447 with open(
448 error_messages_hpp,
449 "w",
450 ) as out:
451 out.write(PRAGMA_ONCE)
452 out.write(WARNING)
453 out.write(
454 """
Ed Tanous4aad6ed2025-01-30 09:35:06 -0800455// These generated headers are a superset of what is needed.
456// clang sees them as an error, so ignore
457// NOLINTBEGIN(misc-include-cleaner)
Ed Tanous42079ec2024-11-16 13:32:29 -0800458#include "http_response.hpp"
459
460#include <boost/url/url_view_base.hpp>
461#include <nlohmann/json.hpp>
462
Ed Tanous4aad6ed2025-01-30 09:35:06 -0800463#include <cstdint>
Ed Tanous42079ec2024-11-16 13:32:29 -0800464#include <source_location>
Ed Tanous42079ec2024-11-16 13:32:29 -0800465#include <string_view>
Ed Tanous4aad6ed2025-01-30 09:35:06 -0800466// NOLINTEND(misc-include-cleaner)
Ed Tanous42079ec2024-11-16 13:32:29 -0800467
468namespace redfish
469{
470
471namespace messages
472{
Ed Tanous42079ec2024-11-16 13:32:29 -0800473"""
474 )
Ed Tanous42079ec2024-11-16 13:32:29 -0800475 for entry_id, entry in messages.items():
476 message = entry["Message"]
477 for index in range(1, 10):
478 message = message.replace(f"'%{index}'", f"<arg{index}>")
479 message = message.replace(f"%{index}", f"<arg{index}>")
480
Ed Tanousf175c282024-12-02 15:12:50 -0800481 if registry_name == "Base":
482 out.write("/**\n")
483 out.write(f"* @brief Formats {entry_id} message into JSON\n")
484 out.write(f'* Message body: "{message}"\n')
485 out.write("*\n")
486 arg_index = 0
487 for arg_index, arg in enumerate(entry.get("ParamTypes", [])):
488 arg_index += 1
Ed Tanous42079ec2024-11-16 13:32:29 -0800489
Ed Tanousf175c282024-12-02 15:12:50 -0800490 out.write(
491 f"* @param[in] arg{arg_index} Parameter of message that will replace %{arg_index} in its body.\n"
492 )
493 out.write("*\n")
Ed Tanous42079ec2024-11-16 13:32:29 -0800494 out.write(
Ed Tanousf175c282024-12-02 15:12:50 -0800495 f"* @returns Message {entry_id} formatted to JSON */\n"
Ed Tanous42079ec2024-11-16 13:32:29 -0800496 )
Ed Tanous42079ec2024-11-16 13:32:29 -0800497
Ed Tanousf175c282024-12-02 15:12:50 -0800498 out.write(
499 make_error_function(
500 entry_id, entry, True, registry_name, namespace_name
501 )
502 )
Ed Tanous42079ec2024-11-16 13:32:29 -0800503 out.write(" }\n")
504 out.write("}\n")
Ed Tanous7ccfe682024-11-16 14:36:16 -0800505
506 error_messages_cpp = os.path.join(
Ed Tanousf175c282024-12-02 15:12:50 -0800507 SCRIPT_DIR, "..", "redfish-core", "src", f"{base_filename}.cpp"
Ed Tanous7ccfe682024-11-16 14:36:16 -0800508 )
509 with open(
510 error_messages_cpp,
511 "w",
512 ) as out:
513 out.write(WARNING)
Ed Tanousf175c282024-12-02 15:12:50 -0800514 out.write(f'\n#include "{base_filename}.hpp"\n')
Ed Tanous847deee2024-12-02 15:28:10 -0800515 headers = []
Ed Tanous7ccfe682024-11-16 14:36:16 -0800516
Ed Tanous847deee2024-12-02 15:28:10 -0800517 headers.append('"registries.hpp"')
Ed Tanousf175c282024-12-02 15:12:50 -0800518 if registry_name == "Base":
519 reg_name_lower = "base"
Ed Tanous6c038f22025-01-14 09:46:04 -0800520 headers.append('"error_message_utils.hpp"')
Ed Tanous847deee2024-12-02 15:28:10 -0800521 headers.append('"http_response.hpp"')
522 headers.append('"logging.hpp"')
523 headers.append("<boost/beast/http/field.hpp>")
524 headers.append("<boost/beast/http/status.hpp>")
525 headers.append("<boost/url/url_view_base.hpp>")
526 headers.append("<source_location>")
Ed Tanousf175c282024-12-02 15:12:50 -0800527 else:
528 reg_name_lower = namespace_name.lower()
Ed Tanous847deee2024-12-02 15:28:10 -0800529 headers.append(f'"registries/{reg_name_lower}_message_registry.hpp"')
Ed Tanous7ccfe682024-11-16 14:36:16 -0800530
Ed Tanous847deee2024-12-02 15:28:10 -0800531 headers.append("<nlohmann/json.hpp>")
532 headers.append("<array>")
533 headers.append("<cstddef>")
534 headers.append("<span>")
535
Ed Tanousa8a5bc12024-12-02 15:43:16 -0800536 if registry_name not in ("ResourceEvent", "HeartbeatEvent"):
Ed Tanous847deee2024-12-02 15:28:10 -0800537 headers.append("<cstdint>")
538 headers.append("<string>")
539 headers.append("<string_view>")
540
541 for header in headers:
542 out.write(f"#include {header}\n")
543
Ed Tanousf175c282024-12-02 15:12:50 -0800544 out.write(
545 """
Ed Tanous7ccfe682024-11-16 14:36:16 -0800546// Clang can't seem to decide whether this header needs to be included or not,
547// and is inconsistent. Include it for now
548// NOLINTNEXTLINE(misc-include-cleaner)
549#include <utility>
550
551namespace redfish
552{
553
554namespace messages
555{
Ed Tanousf175c282024-12-02 15:12:50 -0800556"""
557 )
Ed Tanousf175c282024-12-02 15:12:50 -0800558 out.write(
559 """
Patrick Williams4a102cd2025-02-27 14:52:54 -0500560static nlohmann::json getLog(redfish::registries::{struct_name}::Index name,
Ed Tanousf175c282024-12-02 15:12:50 -0800561 std::span<const std::string_view> args)
562{{
563 size_t index = static_cast<size_t>(name);
Patrick Williams4a102cd2025-02-27 14:52:54 -0500564 if (index >= redfish::registries::{struct_name}::registry.size())
Ed Tanousf175c282024-12-02 15:12:50 -0800565 {{
566 return {{}};
567 }}
Patrick Williams4a102cd2025-02-27 14:52:54 -0500568 return getLogFromRegistry(redfish::registries::{struct_name}::header,
569 redfish::registries::{struct_name}::registry, index, args);
Ed Tanousf175c282024-12-02 15:12:50 -0800570}}
571
572""".format(
Patrick Williams4a102cd2025-02-27 14:52:54 -0500573 struct_name=struct_name
Ed Tanousf175c282024-12-02 15:12:50 -0800574 )
Ed Tanous7ccfe682024-11-16 14:36:16 -0800575 )
576 for entry_id, entry in messages.items():
577 out.write(
578 f"""/**
579 * @internal
580 * @brief Formats {entry_id} message into JSON
581 *
582 * See header file for more information
583 * @endinternal
584 */
585"""
586 )
587 message = entry["Message"]
Ed Tanousf175c282024-12-02 15:12:50 -0800588 out.write(
589 make_error_function(
590 entry_id, entry, False, registry_name, namespace_name
591 )
592 )
Ed Tanous7ccfe682024-11-16 14:36:16 -0800593
594 out.write(" }\n")
595 out.write("}\n")
596 os.system(f"clang-format -i {error_messages_hpp} {error_messages_cpp}")
Ed Tanous42079ec2024-11-16 13:32:29 -0800597
598
Igor Kanyukada9dc902025-02-26 14:08:11 +0000599def make_privilege_registry() -> None:
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600600 path, json_file, type_name, url = make_getter(
Gunnar Mills5910d942024-04-16 12:07:17 -0500601 "Redfish_1.5.0_PrivilegeRegistry.json",
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600602 "privilege_registry.hpp",
603 "privilege",
604 )
605 with open(path, "w") as registry:
Nan Zhou043bec02022-09-20 18:12:13 +0000606 registry.write(PRIVILEGE_HEADER)
Ed Tanoused398212021-06-09 17:05:54 -0700607
Igor Kanyukada9dc902025-02-26 14:08:11 +0000608 privilege_dict: t.Dict[str, t.Tuple[t.Any, str | None]] = {}
Ed Tanoused398212021-06-09 17:05:54 -0700609 for mapping in json_file["Mappings"]:
610 # first pass, identify all the unique privilege sets
611 for operation, privilege_list in mapping["OperationMap"].items():
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600612 privilege_dict[
613 get_privilege_string_from_list(privilege_list)
Igor Kanyukada9dc902025-02-26 14:08:11 +0000614 ] = (
615 privilege_list,
616 None,
617 )
Ed Tanoused398212021-06-09 17:05:54 -0700618 for index, key in enumerate(privilege_dict):
Igor Kanyukada9dc902025-02-26 14:08:11 +0000619 (privilege_list, _) = privilege_dict[key]
Ed Tanoused398212021-06-09 17:05:54 -0700620 name = get_variable_name_for_privilege_set(privilege_list)
Ed Tanousf395daa2021-08-02 08:56:24 -0700621 registry.write(
Ed Tanous5b9ef702022-02-17 12:19:32 -0800622 "const std::array<Privileges, {length}> "
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600623 "privilegeSet{name} = {key};\n".format(
624 length=len(privilege_list), name=name, key=key
625 )
Ed Tanous5b9ef702022-02-17 12:19:32 -0800626 )
Ed Tanoused398212021-06-09 17:05:54 -0700627 privilege_dict[key] = (privilege_list, name)
Ed Tanoused398212021-06-09 17:05:54 -0700628
629 for mapping in json_file["Mappings"]:
630 entity = mapping["Entity"]
Ed Tanous4d99bbb2022-02-17 10:02:57 -0800631 registry.write("// {}\n".format(entity))
Ed Tanoused398212021-06-09 17:05:54 -0700632 for operation, privilege_list in mapping["OperationMap"].items():
633 privilege_string = get_privilege_string_from_list(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600634 privilege_list
635 )
Ed Tanoused398212021-06-09 17:05:54 -0700636 operation = operation.lower()
637
Ed Tanousf395daa2021-08-02 08:56:24 -0700638 registry.write(
639 "const static auto& {}{} = privilegeSet{};\n".format(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600640 operation, entity, privilege_dict[privilege_string][1]
641 )
642 )
Ed Tanoused398212021-06-09 17:05:54 -0700643 registry.write("\n")
Ed Tanous5b9ef702022-02-17 12:19:32 -0800644 registry.write(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600645 "} // namespace redfish::privileges\n// clang-format on\n"
646 )
Ed Tanoused398212021-06-09 17:05:54 -0700647
648
Igor Kanyukada9dc902025-02-26 14:08:11 +0000649def to_pascal_case(text: str) -> str:
Gunnar Mills665e7602024-04-10 13:14:41 -0500650 s = text.replace("_", " ")
Igor Kanyukada9dc902025-02-26 14:08:11 +0000651 s1 = s.split()
Gunnar Mills665e7602024-04-10 13:14:41 -0500652 if len(text) == 0:
653 return text
Igor Kanyukada9dc902025-02-26 14:08:11 +0000654 return "".join(i.capitalize() for i in s1[0:])
Gunnar Mills665e7602024-04-10 13:14:41 -0500655
656
Igor Kanyukada9dc902025-02-26 14:08:11 +0000657def main() -> None:
Ed Tanousc8895b02025-01-03 11:44:08 -0800658 dmtf_registries = OrderedDict(
659 [
660 ("base", "1.19.0"),
661 ("composition", "1.1.2"),
Igor Kanyuka0bce6a92025-02-21 12:40:12 +0000662 ("environmental", "1.1.0"),
Ed Tanousc8895b02025-01-03 11:44:08 -0800663 ("ethernet_fabric", "1.0.1"),
664 ("fabric", "1.0.2"),
665 ("heartbeat_event", "1.0.1"),
666 ("job_event", "1.0.1"),
667 ("license", "1.0.3"),
668 ("log_service", "1.0.1"),
669 ("network_device", "1.0.3"),
670 ("platform", "1.0.1"),
671 ("power", "1.0.1"),
672 ("resource_event", "1.3.0"),
673 ("sensor_event", "1.0.1"),
674 ("storage_device", "1.2.1"),
675 ("task_event", "1.0.3"),
676 ("telemetry", "1.0.0"),
677 ("update", "1.0.2"),
678 ]
679 )
Gunnar Mills665e7602024-04-10 13:14:41 -0500680
Nan Zhou49aa131f2022-09-20 18:41:37 +0000681 parser = argparse.ArgumentParser()
682 parser.add_argument(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600683 "--registries",
684 type=str,
Gunnar Mills665e7602024-04-10 13:14:41 -0500685 default="privilege,openbmc,"
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700686 + ",".join([dmtf for dmtf in dmtf_registries]),
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600687 help="Comma delimited list of registries to update",
688 )
Nan Zhou49aa131f2022-09-20 18:41:37 +0000689
690 args = parser.parse_args()
691
692 registries = set(args.registries.split(","))
Igor Kanyukada9dc902025-02-26 14:08:11 +0000693 registries_map: t.OrderedDict[str, RegistryInfo] = OrderedDict()
Nan Zhou49aa131f2022-09-20 18:41:37 +0000694
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700695 for registry, version in dmtf_registries.items():
Gunnar Mills665e7602024-04-10 13:14:41 -0500696 if registry in registries:
697 registry_pascal_case = to_pascal_case(registry)
Igor Kanyuka557ab0d2025-02-18 15:20:38 +0000698 registries_map[registry] = make_getter(
699 f"{registry_pascal_case}.{version}.json",
700 f"{registry}_message_registry.hpp",
701 registry,
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600702 )
Ed Tanous3e5faba2023-08-16 15:11:29 -0700703 if "openbmc" in registries:
Igor Kanyuka557ab0d2025-02-18 15:20:38 +0000704 registries_map["openbmc"] = openbmc_local_getter()
Nan Zhou49aa131f2022-09-20 18:41:37 +0000705
Igor Kanyukada9dc902025-02-26 14:08:11 +0000706 update_registries(list(registries_map.values()))
Nan Zhou49aa131f2022-09-20 18:41:37 +0000707
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700708 if "base" in registries_map:
709 create_error_registry(
Ed Tanousc8895b02025-01-03 11:44:08 -0800710 registries_map["base"],
Ed Tanousc8895b02025-01-03 11:44:08 -0800711 "Base",
712 "base",
713 "error",
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700714 )
715 if "heartbeat_event" in registries_map:
716 create_error_registry(
717 registries_map["heartbeat_event"],
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700718 "HeartbeatEvent",
719 "heartbeat_event",
720 "heartbeat",
721 )
722 if "resource_event" in registries_map:
723 create_error_registry(
724 registries_map["resource_event"],
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700725 "ResourceEvent",
726 "resource_event",
727 "resource",
728 )
729 if "task_event" in registries_map:
730 create_error_registry(
Ed Tanousc8895b02025-01-03 11:44:08 -0800731 registries_map["task_event"],
Ed Tanousc8895b02025-01-03 11:44:08 -0800732 "TaskEvent",
733 "task_event",
734 "task",
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700735 )
736
Nan Zhou49aa131f2022-09-20 18:41:37 +0000737 if "privilege" in registries:
738 make_privilege_registry()
739
740
741if __name__ == "__main__":
742 main()