blob: a07803f5bceb5575804a44f0721fe8f292ebb8fe [file] [log] [blame]
Nan Zhou313c1b72022-03-25 11:47:55 -07001#!/usr/bin/env python3
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -06002import argparse
Jason M. Bills70304cb2019-03-27 12:03:59 -07003import json
Nan Zhou6eaf0bd2022-08-07 01:18:45 +00004import os
Igor Kanyukada9dc902025-02-26 14:08:11 +00005import typing as t
Ed Tanous42079ec2024-11-16 13:32:29 -08006from collections import OrderedDict
Jason M. Bills70304cb2019-03-27 12:03:59 -07007
Nan Zhou6eaf0bd2022-08-07 01:18:45 +00008import requests
Jason M. Bills70304cb2019-03-27 12:03:59 -07009
Igor Kanyukada9dc902025-02-26 14:08:11 +000010PRAGMA_ONCE: t.Final[
11 str
12] = """#pragma once
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -060013"""
Nan Zhou043bec02022-09-20 18:12:13 +000014
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -060015WARNING = """/****************************************************************
Ed Tanous1cf53df2022-02-17 09:09:25 -080016 * READ THIS WARNING FIRST
Jason M. Bills70304cb2019-03-27 12:03:59 -070017 * This is an auto-generated header which contains definitions
18 * for Redfish DMTF defined messages.
Ed Tanous1cf53df2022-02-17 09:09:25 -080019 * DO NOT modify this registry outside of running the
Jason M. Bills0e2d0692022-04-01 13:59:05 -070020 * parse_registries.py script. The definitions contained within
Ed Tanous1cf53df2022-02-17 09:09:25 -080021 * this file are owned by DMTF. Any modifications to these files
22 * should be first pushed to the relevant registry in the DMTF
23 * github organization.
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -060024 ***************************************************************/"""
Ed Tanous1cf53df2022-02-17 09:09:25 -080025
Igor Kanyukada9dc902025-02-26 14:08:11 +000026COPYRIGHT: t.Final[
27 str
28] = """// SPDX-License-Identifier: Apache-2.0
Ed Tanous40e9b922024-09-10 13:50:16 -070029// SPDX-FileCopyrightText: Copyright OpenBMC Authors
30"""
31
32INCLUDES = """
Nan Zhou01c78a02022-09-20 18:17:20 +000033#include "registries.hpp"
34
35#include <array>
Jason M. Bills70304cb2019-03-27 12:03:59 -070036
Ed Tanous4d99bbb2022-02-17 10:02:57 -080037// clang-format off
38
Ed Tanousfffb8c12022-02-07 23:53:03 -080039namespace redfish::registries::{}
Jason M. Bills70304cb2019-03-27 12:03:59 -070040{{
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -060041"""
Ed Tanous40e9b922024-09-10 13:50:16 -070042
Igor Kanyukada9dc902025-02-26 14:08:11 +000043REGISTRY_HEADER: t.Final[str] = f"{COPYRIGHT}{PRAGMA_ONCE}{WARNING}{INCLUDES}"
Jason M. Bills70304cb2019-03-27 12:03:59 -070044
Igor Kanyukada9dc902025-02-26 14:08:11 +000045SCRIPT_DIR: t.Final[str] = os.path.dirname(os.path.realpath(__file__))
Jason M. Bills70304cb2019-03-27 12:03:59 -070046
Igor Kanyukada9dc902025-02-26 14:08:11 +000047INCLUDE_PATH: t.Final[str] = os.path.realpath(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -060048 os.path.join(SCRIPT_DIR, "..", "redfish-core", "include", "registries")
49)
Jason M. Bills70304cb2019-03-27 12:03:59 -070050
Igor Kanyukada9dc902025-02-26 14:08:11 +000051PROXIES: t.Final[t.Dict[str, str]] = {
52 "https": os.environ.get("https_proxy", "")
53}
54
55RegistryInfo: t.TypeAlias = t.Tuple[str, t.Dict[str, t.Any], str, str]
Jason M. Bills70304cb2019-03-27 12:03:59 -070056
Jason M. Bills70304cb2019-03-27 12:03:59 -070057
Igor Kanyukada9dc902025-02-26 14:08:11 +000058def make_getter(
59 dmtf_name: str, header_name: str, type_name: str
60) -> RegistryInfo:
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -060061 url = "https://redfish.dmtf.org/registries/{}".format(dmtf_name)
Igor Kanyuka557ab0d2025-02-18 15:20:38 +000062 dmtf = requests.get(url, proxies=PROXIES)
James Feiste51c7102020-03-17 10:38:18 -070063 dmtf.raise_for_status()
Ed Tanous42079ec2024-11-16 13:32:29 -080064 json_file = json.loads(dmtf.text, object_pairs_hook=OrderedDict)
Igor Kanyuka557ab0d2025-02-18 15:20:38 +000065 path = os.path.join(INCLUDE_PATH, header_name)
James Feiste51c7102020-03-17 10:38:18 -070066 return (path, json_file, type_name, url)
67
68
Igor Kanyukada9dc902025-02-26 14:08:11 +000069def openbmc_local_getter() -> RegistryInfo:
Milton D. Miller II770362f2024-12-17 05:28:27 +000070 url = "https://raw.githubusercontent.com/openbmc/bmcweb/refs/heads/master/redfish-core/include/registries/openbmc.json"
Ed Tanous3e5faba2023-08-16 15:11:29 -070071 with open(
72 os.path.join(
73 SCRIPT_DIR,
74 "..",
75 "redfish-core",
76 "include",
77 "registries",
78 "openbmc.json",
79 ),
80 "rb",
Igor Kanyuka557ab0d2025-02-18 15:20:38 +000081 ) as json_file_fd:
82 json_file = json.load(json_file_fd)
Ed Tanous3e5faba2023-08-16 15:11:29 -070083
Igor Kanyuka557ab0d2025-02-18 15:20:38 +000084 path = os.path.join(INCLUDE_PATH, "openbmc_message_registry.hpp")
Ed Tanous3e5faba2023-08-16 15:11:29 -070085 return (path, json_file, "openbmc", url)
86
87
Igor Kanyukada9dc902025-02-26 14:08:11 +000088def update_registries(files: t.List[RegistryInfo]) -> None:
Nan Zhou49aa131f2022-09-20 18:41:37 +000089 # Remove the old files
90 for file, json_dict, namespace, url in files:
91 try:
92 os.remove(file)
93 except BaseException:
94 print("{} not found".format(file))
Jason M. Bills70304cb2019-03-27 12:03:59 -070095
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -060096 with open(file, "w") as registry:
Ed Tanous56b81992024-12-02 10:36:37 -080097 version_split = json_dict["RegistryVersion"].split(".")
98
Nan Zhou49aa131f2022-09-20 18:41:37 +000099 registry.write(REGISTRY_HEADER.format(namespace))
100 # Parse the Registry header info
Ed Tanous5b9ef702022-02-17 12:19:32 -0800101 registry.write(
Nan Zhou49aa131f2022-09-20 18:41:37 +0000102 "const Header header = {{\n"
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600103 ' "{json_dict[@Redfish.Copyright]}",\n'
104 ' "{json_dict[@odata.type]}",\n'
Ed Tanous56b81992024-12-02 10:36:37 -0800105 " {version_split[0]},\n"
106 " {version_split[1]},\n"
107 " {version_split[2]},\n"
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600108 ' "{json_dict[Name]}",\n'
109 ' "{json_dict[Language]}",\n'
110 ' "{json_dict[Description]}",\n'
111 ' "{json_dict[RegistryPrefix]}",\n'
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600112 ' "{json_dict[OwningEntity]}",\n'
Nan Zhou49aa131f2022-09-20 18:41:37 +0000113 "}};\n"
114 "constexpr const char* url =\n"
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600115 ' "{url}";\n'
Nan Zhou49aa131f2022-09-20 18:41:37 +0000116 "\n"
117 "constexpr std::array registry =\n"
118 "{{\n".format(
119 json_dict=json_dict,
120 url=url,
Ed Tanous56b81992024-12-02 10:36:37 -0800121 version_split=version_split,
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600122 )
123 )
Ed Tanous30a3c432022-02-07 09:37:21 -0800124
Nan Zhou49aa131f2022-09-20 18:41:37 +0000125 messages_sorted = sorted(json_dict["Messages"].items())
126 for messageId, message in messages_sorted:
127 registry.write(
128 " MessageEntry{{\n"
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600129 ' "{messageId}",\n'
Nan Zhou49aa131f2022-09-20 18:41:37 +0000130 " {{\n"
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600131 ' "{message[Description]}",\n'
132 ' "{message[Message]}",\n'
133 ' "{message[MessageSeverity]}",\n'
Nan Zhou49aa131f2022-09-20 18:41:37 +0000134 " {message[NumberOfArgs]},\n"
135 " {{".format(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600136 messageId=messageId, message=message
137 )
138 )
Nan Zhou49aa131f2022-09-20 18:41:37 +0000139 paramTypes = message.get("ParamTypes")
140 if paramTypes:
141 for paramType in paramTypes:
142 registry.write(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600143 '\n "{}",'.format(paramType)
Nan Zhou49aa131f2022-09-20 18:41:37 +0000144 )
145 registry.write("\n },\n")
146 else:
147 registry.write("},\n")
148 registry.write(
Igor Kanyukada9dc902025-02-26 14:08:11 +0000149 ' "{message[Resolution]}",\n }}}},\n'.format(
150 message=message
151 )
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600152 )
Nan Zhou49aa131f2022-09-20 18:41:37 +0000153
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600154 registry.write("\n};\n\nenum class Index\n{\n")
Nan Zhou49aa131f2022-09-20 18:41:37 +0000155 for index, (messageId, message) in enumerate(messages_sorted):
156 messageId = messageId[0].lower() + messageId[1:]
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600157 registry.write(" {} = {},\n".format(messageId, index))
Nan Zhou49aa131f2022-09-20 18:41:37 +0000158 registry.write(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600159 "}};\n}} // namespace redfish::registries::{}\n".format(
160 namespace
161 )
162 )
Ed Tanoused398212021-06-09 17:05:54 -0700163
164
Igor Kanyukada9dc902025-02-26 14:08:11 +0000165def get_privilege_string_from_list(
166 privilege_list: t.List[t.Dict[str, t.Any]],
167) -> str:
Ed Tanoused398212021-06-09 17:05:54 -0700168 privilege_string = "{{\n"
169 for privilege_json in privilege_list:
170 privileges = privilege_json["Privilege"]
171 privilege_string += " {"
Igor Kanyukada9dc902025-02-26 14:08:11 +0000172 last_privelege = ""
Ed Tanoused398212021-06-09 17:05:54 -0700173 for privilege in privileges:
Igor Kanyukada9dc902025-02-26 14:08:11 +0000174 last_privelege = privilege
Ed Tanoused398212021-06-09 17:05:54 -0700175 if privilege == "NoAuth":
176 continue
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600177 privilege_string += '"'
Ed Tanoused398212021-06-09 17:05:54 -0700178 privilege_string += privilege
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600179 privilege_string += '",\n'
Igor Kanyukada9dc902025-02-26 14:08:11 +0000180 if last_privelege != "NoAuth":
Ed Tanoused398212021-06-09 17:05:54 -0700181 privilege_string = privilege_string[:-2]
182 privilege_string += "}"
183 privilege_string += ",\n"
184 privilege_string = privilege_string[:-2]
185 privilege_string += "\n}}"
186 return privilege_string
187
Ed Tanousf395daa2021-08-02 08:56:24 -0700188
Igor Kanyukada9dc902025-02-26 14:08:11 +0000189def get_variable_name_for_privilege_set(
190 privilege_list: t.List[t.Dict[str, t.Any]],
191) -> str:
Ed Tanoused398212021-06-09 17:05:54 -0700192 names = []
193 for privilege_json in privilege_list:
194 privileges = privilege_json["Privilege"]
195 names.append("And".join(privileges))
196 return "Or".join(names)
197
Ed Tanousf395daa2021-08-02 08:56:24 -0700198
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600199PRIVILEGE_HEADER = (
Ed Tanous40e9b922024-09-10 13:50:16 -0700200 COPYRIGHT
201 + PRAGMA_ONCE
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600202 + WARNING
203 + """
Nan Zhou01c78a02022-09-20 18:17:20 +0000204#include "privileges.hpp"
205
206#include <array>
Nan Zhou043bec02022-09-20 18:12:13 +0000207
208// clang-format off
209
210namespace redfish::privileges
211{
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600212"""
213)
Nan Zhou043bec02022-09-20 18:12:13 +0000214
215
Igor Kanyukada9dc902025-02-26 14:08:11 +0000216def get_response_code(entry_id: str) -> str | None:
Ed Tanous7ccfe682024-11-16 14:36:16 -0800217 codes = {
Myung Bae3498f482025-04-09 06:22:54 -0400218 "AccessDenied": "forbidden",
Ed Tanous7ccfe682024-11-16 14:36:16 -0800219 "AccountForSessionNoLongerExists": "forbidden",
Myung Bae3498f482025-04-09 06:22:54 -0400220 "AccountModified": "ok",
221 "AccountRemoved": "ok",
222 "CouldNotEstablishConnection": "not_found",
223 "Created": "created",
224 "EventSubscriptionLimitExceeded": "service_unavailable",
225 "GeneralError": "internal_server_error",
226 "GenerateSecretKeyRequired": "forbidden",
227 "InsufficientPrivilege": "forbidden",
228 "InsufficientStorage": "insufficient_storage",
229 "InternalError": "internal_server_error",
230 "MaximumErrorsExceeded": "internal_server_error",
231 "NoValidSession": "forbidden",
232 "OperationFailed": "bad_gateway",
233 "OperationNotAllowed": "method_not_allowed",
234 "OperationTimeout": "internal_server_error",
235 "PasswordChangeRequired": None,
236 "PreconditionFailed": "precondition_failed",
237 "PropertyNotWritable": "forbidden",
238 "PropertyValueExternalConflict": "conflict",
239 "PropertyValueModified": "ok",
240 "PropertyValueResourceConflict": "conflict",
241 "ResourceAtUriUnauthorized": "unauthorized",
242 "ResourceCannotBeDeleted": "method_not_allowed",
243 "ResourceExhaustion": "service_unavailable",
244 "ResourceInStandby": "service_unavailable",
245 "ResourceInUse": "service_unavailable",
246 "ResourceNotFound": "not_found",
Myung Bae7f84d8c2023-03-14 13:44:15 -0700247 "RestrictedRole": "forbidden",
Ed Tanous7ccfe682024-11-16 14:36:16 -0800248 "ServiceDisabled": "service_unavailable",
249 "ServiceInUnknownState": "service_unavailable",
Myung Bae3498f482025-04-09 06:22:54 -0400250 "ServiceShuttingDown": "service_unavailable",
251 "ServiceTemporarilyUnavailable": "service_unavailable",
252 "SessionLimitExceeded": "service_unavailable",
Ed Tanous7ccfe682024-11-16 14:36:16 -0800253 "SessionTerminated": "ok",
254 "SubscriptionTerminated": "ok",
Ed Tanous7ccfe682024-11-16 14:36:16 -0800255 "Success": None,
Ed Tanous7ccfe682024-11-16 14:36:16 -0800256 }
257
Igor Kanyuka557ab0d2025-02-18 15:20:38 +0000258 return codes.get(entry_id, "bad_request")
Ed Tanous7ccfe682024-11-16 14:36:16 -0800259
260
Ed Tanousf175c282024-12-02 15:12:50 -0800261def make_error_function(
Igor Kanyukada9dc902025-02-26 14:08:11 +0000262 entry_id: str,
263 entry: t.Dict[str, t.Any],
264 is_header: bool,
265 registry_name: str,
266 namespace_name: str,
267) -> str:
Ed Tanous644cdcb2024-11-17 11:12:41 -0800268 arg_nonstring_types = {
269 "const boost::urls::url_view_base&": {
270 "AccessDenied": [1],
271 "CouldNotEstablishConnection": [1],
272 "GenerateSecretKeyRequired": [1],
273 "InvalidObject": [1],
274 "PasswordChangeRequired": [1],
275 "PropertyValueResourceConflict": [3],
276 "ResetRequired": [1],
277 "ResourceAtUriInUnknownFormat": [1],
278 "ResourceAtUriUnauthorized": [1],
279 "ResourceCreationConflict": [1],
280 "ResourceMissingAtURI": [1],
281 "SourceDoesNotSupportProtocol": [1],
282 },
283 "const nlohmann::json&": {
284 "ActionParameterValueError": [1],
285 "ActionParameterValueFormatError": [1],
286 "ActionParameterValueTypeError": [1],
287 "PropertyValueExternalConflict": [2],
288 "PropertyValueFormatError": [1],
289 "PropertyValueIncorrect": [2],
290 "PropertyValueModified": [2],
291 "PropertyValueNotInList": [1],
292 "PropertyValueOutOfRange": [1],
293 "PropertyValueResourceConflict": [2],
294 "PropertyValueTypeError": [1],
295 "QueryParameterValueFormatError": [1],
296 "QueryParameterValueTypeError": [1],
297 },
298 "uint64_t": {
299 "ArraySizeTooLong": [2],
300 "InvalidIndex": [1],
301 "StringValueTooLong": [2],
Ed Tanousf175c282024-12-02 15:12:50 -0800302 "TaskProgressChanged": [2],
Ed Tanous644cdcb2024-11-17 11:12:41 -0800303 },
Ed Tanous42079ec2024-11-16 13:32:29 -0800304 }
305
Ed Tanous7ccfe682024-11-16 14:36:16 -0800306 out = ""
307 args = []
308 argtypes = []
309 for arg_index, arg in enumerate(entry.get("ParamTypes", [])):
310 arg_index += 1
Ed Tanous644cdcb2024-11-17 11:12:41 -0800311 typename = "std::string_view"
312 for typestring, entries in arg_nonstring_types.items():
313 if arg_index in entries.get(entry_id, []):
314 typename = typestring
315
Ed Tanous7ccfe682024-11-16 14:36:16 -0800316 argtypes.append(typename)
317 args.append(f"{typename} arg{arg_index}")
318 function_name = entry_id[0].lower() + entry_id[1:]
319 arg = ", ".join(args)
320 out += f"nlohmann::json {function_name}({arg})"
321
322 if is_header:
323 out += ";\n\n"
324 else:
325 out += "\n{\n"
326 to_array_type = ""
Igor Kanyukada9dc902025-02-26 14:08:11 +0000327 arg_param = "{}"
Ed Tanous7ccfe682024-11-16 14:36:16 -0800328 if argtypes:
329 outargs = []
330 for index, typename in enumerate(argtypes):
331 index += 1
332 if typename == "const nlohmann::json&":
333 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 -0800334 elif typename == "uint64_t":
Ed Tanous7ccfe682024-11-16 14:36:16 -0800335 out += f"std::string arg{index}Str = std::to_string(arg{index});\n"
336
337 for index, typename in enumerate(argtypes):
338 index += 1
339 if typename == "const boost::urls::url_view_base&":
340 outargs.append(f"arg{index}.buffer()")
341 to_array_type = "<std::string_view>"
342 elif typename == "const nlohmann::json&":
343 outargs.append(f"arg{index}Str")
344 to_array_type = "<std::string_view>"
Ed Tanous644cdcb2024-11-17 11:12:41 -0800345 elif typename == "uint64_t":
Ed Tanous7ccfe682024-11-16 14:36:16 -0800346 outargs.append(f"arg{index}Str")
347 to_array_type = "<std::string_view>"
348 else:
349 outargs.append(f"arg{index}")
350 argstring = ", ".join(outargs)
Ed Tanous7ccfe682024-11-16 14:36:16 -0800351 arg_param = f"std::to_array{to_array_type}({{{argstring}}})"
Ed Tanousf175c282024-12-02 15:12:50 -0800352 out += f" return getLog(redfish::registries::{namespace_name}::Index::{function_name}, {arg_param});"
Ed Tanous7ccfe682024-11-16 14:36:16 -0800353 out += "\n}\n\n"
Ed Tanousf175c282024-12-02 15:12:50 -0800354 if registry_name == "Base":
355 args.insert(0, "crow::Response& res")
Ed Tanous7ccfe682024-11-16 14:36:16 -0800356 if entry_id == "InternalError":
Ed Tanousf175c282024-12-02 15:12:50 -0800357 if is_header:
358 args.append(
359 "std::source_location location = std::source_location::current()"
360 )
361 else:
362 args.append("const std::source_location location")
363 arg = ", ".join(args)
364 out += f"void {function_name}({arg})"
365 if is_header:
366 out += ";\n"
Ed Tanous7ccfe682024-11-16 14:36:16 -0800367 else:
Ed Tanousf175c282024-12-02 15:12:50 -0800368 out += "\n{\n"
369 if entry_id == "InternalError":
370 out += """BMCWEB_LOG_CRITICAL("Internal Error {}({}:{}) `{}`: ", location.file_name(),
371 location.line(), location.column(),
372 location.function_name());\n"""
373
374 if entry_id == "ServiceTemporarilyUnavailable":
375 out += "res.addHeader(boost::beast::http::field::retry_after, arg1);"
376
Igor Kanyuka557ab0d2025-02-18 15:20:38 +0000377 res = get_response_code(entry_id)
Ed Tanousf175c282024-12-02 15:12:50 -0800378 if res:
379 out += f" res.result(boost::beast::http::status::{res});\n"
Igor Kanyukada9dc902025-02-26 14:08:11 +0000380 args_out = ", ".join([f"arg{x + 1}" for x in range(len(argtypes))])
Ed Tanousf175c282024-12-02 15:12:50 -0800381
382 addMessageToJson = {
383 "PropertyDuplicate": 1,
384 "ResourceAlreadyExists": 2,
385 "CreateFailedMissingReqProperties": 1,
386 "PropertyValueFormatError": 2,
387 "PropertyValueNotInList": 2,
388 "PropertyValueTypeError": 2,
389 "PropertyValueError": 1,
390 "PropertyNotWritable": 1,
391 "PropertyValueModified": 1,
392 "PropertyMissing": 1,
393 }
394
395 addMessageToRoot = [
396 "SessionTerminated",
397 "SubscriptionTerminated",
398 "AccountRemoved",
399 "Created",
400 "Success",
401 "PasswordChangeRequired",
402 ]
403
404 if entry_id in addMessageToJson:
405 out += f" addMessageToJson(res.jsonValue, {function_name}({args_out}), arg{addMessageToJson[entry_id]});\n"
406 elif entry_id in addMessageToRoot:
407 out += f" addMessageToJsonRoot(res.jsonValue, {function_name}({args_out}));\n"
408 else:
409 out += f" addMessageToErrorJson(res.jsonValue, {function_name}({args_out}));\n"
410 out += "}\n"
Ed Tanous7ccfe682024-11-16 14:36:16 -0800411 out += "\n"
412 return out
413
414
Ed Tanousf175c282024-12-02 15:12:50 -0800415def create_error_registry(
Igor Kanyukada9dc902025-02-26 14:08:11 +0000416 registry_info: RegistryInfo,
417 registry_name: str,
418 namespace_name: str,
419 filename: str,
420) -> None:
421 file, json_dict, namespace, url = registry_info
Ed Tanousf175c282024-12-02 15:12:50 -0800422 base_filename = filename + "_messages"
Ed Tanous42079ec2024-11-16 13:32:29 -0800423
Ed Tanous42079ec2024-11-16 13:32:29 -0800424 error_messages_hpp = os.path.join(
Ed Tanousf175c282024-12-02 15:12:50 -0800425 SCRIPT_DIR, "..", "redfish-core", "include", f"{base_filename}.hpp"
Ed Tanous42079ec2024-11-16 13:32:29 -0800426 )
Ed Tanousf8cca872024-11-16 22:47:34 -0800427 messages = json_dict["Messages"]
428
Ed Tanous42079ec2024-11-16 13:32:29 -0800429 with open(
430 error_messages_hpp,
431 "w",
432 ) as out:
433 out.write(PRAGMA_ONCE)
434 out.write(WARNING)
435 out.write(
436 """
Ed Tanous4aad6ed2025-01-30 09:35:06 -0800437// These generated headers are a superset of what is needed.
438// clang sees them as an error, so ignore
439// NOLINTBEGIN(misc-include-cleaner)
Ed Tanous42079ec2024-11-16 13:32:29 -0800440#include "http_response.hpp"
441
442#include <boost/url/url_view_base.hpp>
443#include <nlohmann/json.hpp>
444
Ed Tanous4aad6ed2025-01-30 09:35:06 -0800445#include <cstdint>
Ed Tanous42079ec2024-11-16 13:32:29 -0800446#include <source_location>
Ed Tanous42079ec2024-11-16 13:32:29 -0800447#include <string_view>
Ed Tanous4aad6ed2025-01-30 09:35:06 -0800448// NOLINTEND(misc-include-cleaner)
Ed Tanous42079ec2024-11-16 13:32:29 -0800449
450namespace redfish
451{
452
453namespace messages
454{
Ed Tanous42079ec2024-11-16 13:32:29 -0800455"""
456 )
Ed Tanous42079ec2024-11-16 13:32:29 -0800457 for entry_id, entry in messages.items():
458 message = entry["Message"]
459 for index in range(1, 10):
460 message = message.replace(f"'%{index}'", f"<arg{index}>")
461 message = message.replace(f"%{index}", f"<arg{index}>")
462
Ed Tanousf175c282024-12-02 15:12:50 -0800463 if registry_name == "Base":
464 out.write("/**\n")
465 out.write(f"* @brief Formats {entry_id} message into JSON\n")
466 out.write(f'* Message body: "{message}"\n')
467 out.write("*\n")
468 arg_index = 0
469 for arg_index, arg in enumerate(entry.get("ParamTypes", [])):
470 arg_index += 1
Ed Tanous42079ec2024-11-16 13:32:29 -0800471
Ed Tanousf175c282024-12-02 15:12:50 -0800472 out.write(
473 f"* @param[in] arg{arg_index} Parameter of message that will replace %{arg_index} in its body.\n"
474 )
475 out.write("*\n")
Ed Tanous42079ec2024-11-16 13:32:29 -0800476 out.write(
Ed Tanousf175c282024-12-02 15:12:50 -0800477 f"* @returns Message {entry_id} formatted to JSON */\n"
Ed Tanous42079ec2024-11-16 13:32:29 -0800478 )
Ed Tanous42079ec2024-11-16 13:32:29 -0800479
Ed Tanousf175c282024-12-02 15:12:50 -0800480 out.write(
481 make_error_function(
482 entry_id, entry, True, registry_name, namespace_name
483 )
484 )
Ed Tanous42079ec2024-11-16 13:32:29 -0800485 out.write(" }\n")
486 out.write("}\n")
Ed Tanous7ccfe682024-11-16 14:36:16 -0800487
488 error_messages_cpp = os.path.join(
Ed Tanousf175c282024-12-02 15:12:50 -0800489 SCRIPT_DIR, "..", "redfish-core", "src", f"{base_filename}.cpp"
Ed Tanous7ccfe682024-11-16 14:36:16 -0800490 )
491 with open(
492 error_messages_cpp,
493 "w",
494 ) as out:
495 out.write(WARNING)
Ed Tanousf175c282024-12-02 15:12:50 -0800496 out.write(f'\n#include "{base_filename}.hpp"\n')
Ed Tanous847deee2024-12-02 15:28:10 -0800497 headers = []
Ed Tanous7ccfe682024-11-16 14:36:16 -0800498
Ed Tanous847deee2024-12-02 15:28:10 -0800499 headers.append('"registries.hpp"')
Ed Tanousf175c282024-12-02 15:12:50 -0800500 if registry_name == "Base":
501 reg_name_lower = "base"
Ed Tanous6c038f22025-01-14 09:46:04 -0800502 headers.append('"error_message_utils.hpp"')
Ed Tanous847deee2024-12-02 15:28:10 -0800503 headers.append('"http_response.hpp"')
504 headers.append('"logging.hpp"')
505 headers.append("<boost/beast/http/field.hpp>")
506 headers.append("<boost/beast/http/status.hpp>")
507 headers.append("<boost/url/url_view_base.hpp>")
508 headers.append("<source_location>")
Ed Tanousf175c282024-12-02 15:12:50 -0800509 else:
510 reg_name_lower = namespace_name.lower()
Ed Tanous847deee2024-12-02 15:28:10 -0800511 headers.append(f'"registries/{reg_name_lower}_message_registry.hpp"')
Ed Tanous7ccfe682024-11-16 14:36:16 -0800512
Ed Tanous847deee2024-12-02 15:28:10 -0800513 headers.append("<nlohmann/json.hpp>")
514 headers.append("<array>")
515 headers.append("<cstddef>")
516 headers.append("<span>")
517
Ed Tanousa8a5bc12024-12-02 15:43:16 -0800518 if registry_name not in ("ResourceEvent", "HeartbeatEvent"):
Ed Tanous847deee2024-12-02 15:28:10 -0800519 headers.append("<cstdint>")
520 headers.append("<string>")
521 headers.append("<string_view>")
522
523 for header in headers:
524 out.write(f"#include {header}\n")
525
Ed Tanousf175c282024-12-02 15:12:50 -0800526 out.write(
527 """
Ed Tanous7ccfe682024-11-16 14:36:16 -0800528// Clang can't seem to decide whether this header needs to be included or not,
529// and is inconsistent. Include it for now
530// NOLINTNEXTLINE(misc-include-cleaner)
531#include <utility>
532
533namespace redfish
534{
535
536namespace messages
537{
Ed Tanousf175c282024-12-02 15:12:50 -0800538"""
539 )
Ed Tanousf175c282024-12-02 15:12:50 -0800540 out.write(
541 """
542static nlohmann::json getLog(redfish::registries::{namespace_name}::Index name,
543 std::span<const std::string_view> args)
544{{
545 size_t index = static_cast<size_t>(name);
546 if (index >= redfish::registries::{namespace_name}::registry.size())
547 {{
548 return {{}};
549 }}
550 return getLogFromRegistry(redfish::registries::{namespace_name}::header,
551 redfish::registries::{namespace_name}::registry, index, args);
552}}
553
554""".format(
555 namespace_name=namespace_name
556 )
Ed Tanous7ccfe682024-11-16 14:36:16 -0800557 )
558 for entry_id, entry in messages.items():
559 out.write(
560 f"""/**
561 * @internal
562 * @brief Formats {entry_id} message into JSON
563 *
564 * See header file for more information
565 * @endinternal
566 */
567"""
568 )
569 message = entry["Message"]
Ed Tanousf175c282024-12-02 15:12:50 -0800570 out.write(
571 make_error_function(
572 entry_id, entry, False, registry_name, namespace_name
573 )
574 )
Ed Tanous7ccfe682024-11-16 14:36:16 -0800575
576 out.write(" }\n")
577 out.write("}\n")
578 os.system(f"clang-format -i {error_messages_hpp} {error_messages_cpp}")
Ed Tanous42079ec2024-11-16 13:32:29 -0800579
580
Igor Kanyukada9dc902025-02-26 14:08:11 +0000581def make_privilege_registry() -> None:
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600582 path, json_file, type_name, url = make_getter(
Gunnar Mills5910d942024-04-16 12:07:17 -0500583 "Redfish_1.5.0_PrivilegeRegistry.json",
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600584 "privilege_registry.hpp",
585 "privilege",
586 )
587 with open(path, "w") as registry:
Nan Zhou043bec02022-09-20 18:12:13 +0000588 registry.write(PRIVILEGE_HEADER)
Ed Tanoused398212021-06-09 17:05:54 -0700589
Igor Kanyukada9dc902025-02-26 14:08:11 +0000590 privilege_dict: t.Dict[str, t.Tuple[t.Any, str | None]] = {}
Ed Tanoused398212021-06-09 17:05:54 -0700591 for mapping in json_file["Mappings"]:
592 # first pass, identify all the unique privilege sets
593 for operation, privilege_list in mapping["OperationMap"].items():
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600594 privilege_dict[
595 get_privilege_string_from_list(privilege_list)
Igor Kanyukada9dc902025-02-26 14:08:11 +0000596 ] = (
597 privilege_list,
598 None,
599 )
Ed Tanoused398212021-06-09 17:05:54 -0700600 for index, key in enumerate(privilege_dict):
Igor Kanyukada9dc902025-02-26 14:08:11 +0000601 (privilege_list, _) = privilege_dict[key]
Ed Tanoused398212021-06-09 17:05:54 -0700602 name = get_variable_name_for_privilege_set(privilege_list)
Ed Tanousf395daa2021-08-02 08:56:24 -0700603 registry.write(
Ed Tanous5b9ef702022-02-17 12:19:32 -0800604 "const std::array<Privileges, {length}> "
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600605 "privilegeSet{name} = {key};\n".format(
606 length=len(privilege_list), name=name, key=key
607 )
Ed Tanous5b9ef702022-02-17 12:19:32 -0800608 )
Ed Tanoused398212021-06-09 17:05:54 -0700609 privilege_dict[key] = (privilege_list, name)
Ed Tanoused398212021-06-09 17:05:54 -0700610
611 for mapping in json_file["Mappings"]:
612 entity = mapping["Entity"]
Ed Tanous4d99bbb2022-02-17 10:02:57 -0800613 registry.write("// {}\n".format(entity))
Ed Tanoused398212021-06-09 17:05:54 -0700614 for operation, privilege_list in mapping["OperationMap"].items():
615 privilege_string = get_privilege_string_from_list(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600616 privilege_list
617 )
Ed Tanoused398212021-06-09 17:05:54 -0700618 operation = operation.lower()
619
Ed Tanousf395daa2021-08-02 08:56:24 -0700620 registry.write(
621 "const static auto& {}{} = privilegeSet{};\n".format(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600622 operation, entity, privilege_dict[privilege_string][1]
623 )
624 )
Ed Tanoused398212021-06-09 17:05:54 -0700625 registry.write("\n")
Ed Tanous5b9ef702022-02-17 12:19:32 -0800626 registry.write(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600627 "} // namespace redfish::privileges\n// clang-format on\n"
628 )
Ed Tanoused398212021-06-09 17:05:54 -0700629
630
Igor Kanyukada9dc902025-02-26 14:08:11 +0000631def to_pascal_case(text: str) -> str:
Gunnar Mills665e7602024-04-10 13:14:41 -0500632 s = text.replace("_", " ")
Igor Kanyukada9dc902025-02-26 14:08:11 +0000633 s1 = s.split()
Gunnar Mills665e7602024-04-10 13:14:41 -0500634 if len(text) == 0:
635 return text
Igor Kanyukada9dc902025-02-26 14:08:11 +0000636 return "".join(i.capitalize() for i in s1[0:])
Gunnar Mills665e7602024-04-10 13:14:41 -0500637
638
Igor Kanyukada9dc902025-02-26 14:08:11 +0000639def main() -> None:
Ed Tanousc8895b02025-01-03 11:44:08 -0800640 dmtf_registries = OrderedDict(
641 [
642 ("base", "1.19.0"),
643 ("composition", "1.1.2"),
Igor Kanyuka0bce6a92025-02-21 12:40:12 +0000644 ("environmental", "1.1.0"),
Ed Tanousc8895b02025-01-03 11:44:08 -0800645 ("ethernet_fabric", "1.0.1"),
646 ("fabric", "1.0.2"),
647 ("heartbeat_event", "1.0.1"),
648 ("job_event", "1.0.1"),
649 ("license", "1.0.3"),
650 ("log_service", "1.0.1"),
651 ("network_device", "1.0.3"),
652 ("platform", "1.0.1"),
653 ("power", "1.0.1"),
654 ("resource_event", "1.3.0"),
655 ("sensor_event", "1.0.1"),
656 ("storage_device", "1.2.1"),
657 ("task_event", "1.0.3"),
658 ("telemetry", "1.0.0"),
659 ("update", "1.0.2"),
660 ]
661 )
Gunnar Mills665e7602024-04-10 13:14:41 -0500662
Nan Zhou49aa131f2022-09-20 18:41:37 +0000663 parser = argparse.ArgumentParser()
664 parser.add_argument(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600665 "--registries",
666 type=str,
Gunnar Mills665e7602024-04-10 13:14:41 -0500667 default="privilege,openbmc,"
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700668 + ",".join([dmtf for dmtf in dmtf_registries]),
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600669 help="Comma delimited list of registries to update",
670 )
Nan Zhou49aa131f2022-09-20 18:41:37 +0000671
672 args = parser.parse_args()
673
674 registries = set(args.registries.split(","))
Igor Kanyukada9dc902025-02-26 14:08:11 +0000675 registries_map: t.OrderedDict[str, RegistryInfo] = OrderedDict()
Nan Zhou49aa131f2022-09-20 18:41:37 +0000676
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700677 for registry, version in dmtf_registries.items():
Gunnar Mills665e7602024-04-10 13:14:41 -0500678 if registry in registries:
679 registry_pascal_case = to_pascal_case(registry)
Igor Kanyuka557ab0d2025-02-18 15:20:38 +0000680 registries_map[registry] = make_getter(
681 f"{registry_pascal_case}.{version}.json",
682 f"{registry}_message_registry.hpp",
683 registry,
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600684 )
Ed Tanous3e5faba2023-08-16 15:11:29 -0700685 if "openbmc" in registries:
Igor Kanyuka557ab0d2025-02-18 15:20:38 +0000686 registries_map["openbmc"] = openbmc_local_getter()
Nan Zhou49aa131f2022-09-20 18:41:37 +0000687
Igor Kanyukada9dc902025-02-26 14:08:11 +0000688 update_registries(list(registries_map.values()))
Nan Zhou49aa131f2022-09-20 18:41:37 +0000689
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700690 if "base" in registries_map:
691 create_error_registry(
Ed Tanousc8895b02025-01-03 11:44:08 -0800692 registries_map["base"],
Ed Tanousc8895b02025-01-03 11:44:08 -0800693 "Base",
694 "base",
695 "error",
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700696 )
697 if "heartbeat_event" in registries_map:
698 create_error_registry(
699 registries_map["heartbeat_event"],
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700700 "HeartbeatEvent",
701 "heartbeat_event",
702 "heartbeat",
703 )
704 if "resource_event" in registries_map:
705 create_error_registry(
706 registries_map["resource_event"],
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700707 "ResourceEvent",
708 "resource_event",
709 "resource",
710 )
711 if "task_event" in registries_map:
712 create_error_registry(
Ed Tanousc8895b02025-01-03 11:44:08 -0800713 registries_map["task_event"],
Ed Tanousc8895b02025-01-03 11:44:08 -0800714 "TaskEvent",
715 "task_event",
716 "task",
Tam Nguyen7e6d0322024-12-27 09:47:38 +0700717 )
718
Nan Zhou49aa131f2022-09-20 18:41:37 +0000719 if "privilege" in registries:
720 make_privilege_registry()
721
722
723if __name__ == "__main__":
724 main()