blob: 13fb52aac82d28031f50077be6f2573780e000b1 [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
Ed Tanous42079ec2024-11-16 13:32:29 -08005from collections import OrderedDict
Jason M. Bills70304cb2019-03-27 12:03:59 -07006
Nan Zhou6eaf0bd2022-08-07 01:18:45 +00007import requests
Jason M. Bills70304cb2019-03-27 12:03:59 -07008
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -06009PRAGMA_ONCE = """#pragma once
10"""
Nan Zhou043bec02022-09-20 18:12:13 +000011
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -060012WARNING = """/****************************************************************
Ed Tanous1cf53df2022-02-17 09:09:25 -080013 * READ THIS WARNING FIRST
Jason M. Bills70304cb2019-03-27 12:03:59 -070014 * This is an auto-generated header which contains definitions
15 * for Redfish DMTF defined messages.
Ed Tanous1cf53df2022-02-17 09:09:25 -080016 * DO NOT modify this registry outside of running the
Jason M. Bills0e2d0692022-04-01 13:59:05 -070017 * parse_registries.py script. The definitions contained within
Ed Tanous1cf53df2022-02-17 09:09:25 -080018 * this file are owned by DMTF. Any modifications to these files
19 * should be first pushed to the relevant registry in the DMTF
20 * github organization.
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -060021 ***************************************************************/"""
Ed Tanous1cf53df2022-02-17 09:09:25 -080022
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -060023REGISTRY_HEADER = (
24 PRAGMA_ONCE
25 + WARNING
26 + """
Nan Zhou01c78a02022-09-20 18:17:20 +000027#include "registries.hpp"
28
29#include <array>
Jason M. Bills70304cb2019-03-27 12:03:59 -070030
Ed Tanous4d99bbb2022-02-17 10:02:57 -080031// clang-format off
32
Ed Tanousfffb8c12022-02-07 23:53:03 -080033namespace redfish::registries::{}
Jason M. Bills70304cb2019-03-27 12:03:59 -070034{{
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -060035"""
36)
Jason M. Bills70304cb2019-03-27 12:03:59 -070037
38SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
39
Jason M. Billsac706372020-02-18 11:36:47 -080040include_path = os.path.realpath(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -060041 os.path.join(SCRIPT_DIR, "..", "redfish-core", "include", "registries")
42)
Jason M. Bills70304cb2019-03-27 12:03:59 -070043
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -060044proxies = {"https": os.environ.get("https_proxy", None)}
Jason M. Bills70304cb2019-03-27 12:03:59 -070045
Jason M. Bills70304cb2019-03-27 12:03:59 -070046
James Feiste51c7102020-03-17 10:38:18 -070047def make_getter(dmtf_name, header_name, type_name):
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -060048 url = "https://redfish.dmtf.org/registries/{}".format(dmtf_name)
James Feiste51c7102020-03-17 10:38:18 -070049 dmtf = requests.get(url, proxies=proxies)
50 dmtf.raise_for_status()
Ed Tanous42079ec2024-11-16 13:32:29 -080051 json_file = json.loads(dmtf.text, object_pairs_hook=OrderedDict)
James Feiste51c7102020-03-17 10:38:18 -070052 path = os.path.join(include_path, header_name)
53 return (path, json_file, type_name, url)
54
55
Ed Tanous3e5faba2023-08-16 15:11:29 -070056def openbmc_local_getter():
Ed Tanous66aabb72024-12-10 16:34:14 -080057 url = "https://github.com/openbmc/bmcweb/blob/master/redfish-core/include/registries/openbmc.json"
Ed Tanous3e5faba2023-08-16 15:11:29 -070058 with open(
59 os.path.join(
60 SCRIPT_DIR,
61 "..",
62 "redfish-core",
63 "include",
64 "registries",
65 "openbmc.json",
66 ),
67 "rb",
68 ) as json_file:
69 json_file = json.load(json_file)
70
71 path = os.path.join(include_path, "openbmc_message_registry.hpp")
72 return (path, json_file, "openbmc", url)
73
74
Nan Zhou49aa131f2022-09-20 18:41:37 +000075def update_registries(files):
76 # Remove the old files
77 for file, json_dict, namespace, url in files:
78 try:
79 os.remove(file)
80 except BaseException:
81 print("{} not found".format(file))
Jason M. Bills70304cb2019-03-27 12:03:59 -070082
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -060083 with open(file, "w") as registry:
Ed Tanous56b81992024-12-02 10:36:37 -080084
85 version_split = json_dict["RegistryVersion"].split(".")
86
Nan Zhou49aa131f2022-09-20 18:41:37 +000087 registry.write(REGISTRY_HEADER.format(namespace))
88 # Parse the Registry header info
Ed Tanous5b9ef702022-02-17 12:19:32 -080089 registry.write(
Nan Zhou49aa131f2022-09-20 18:41:37 +000090 "const Header header = {{\n"
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -060091 ' "{json_dict[@Redfish.Copyright]}",\n'
92 ' "{json_dict[@odata.type]}",\n'
Ed Tanous56b81992024-12-02 10:36:37 -080093 " {version_split[0]},\n"
94 " {version_split[1]},\n"
95 " {version_split[2]},\n"
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -060096 ' "{json_dict[Name]}",\n'
97 ' "{json_dict[Language]}",\n'
98 ' "{json_dict[Description]}",\n'
99 ' "{json_dict[RegistryPrefix]}",\n'
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600100 ' "{json_dict[OwningEntity]}",\n'
Nan Zhou49aa131f2022-09-20 18:41:37 +0000101 "}};\n"
102 "constexpr const char* url =\n"
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600103 ' "{url}";\n'
Nan Zhou49aa131f2022-09-20 18:41:37 +0000104 "\n"
105 "constexpr std::array registry =\n"
106 "{{\n".format(
107 json_dict=json_dict,
108 url=url,
Ed Tanous56b81992024-12-02 10:36:37 -0800109 version_split=version_split,
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600110 )
111 )
Ed Tanous30a3c432022-02-07 09:37:21 -0800112
Nan Zhou49aa131f2022-09-20 18:41:37 +0000113 messages_sorted = sorted(json_dict["Messages"].items())
114 for messageId, message in messages_sorted:
115 registry.write(
116 " MessageEntry{{\n"
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600117 ' "{messageId}",\n'
Nan Zhou49aa131f2022-09-20 18:41:37 +0000118 " {{\n"
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600119 ' "{message[Description]}",\n'
120 ' "{message[Message]}",\n'
121 ' "{message[MessageSeverity]}",\n'
Nan Zhou49aa131f2022-09-20 18:41:37 +0000122 " {message[NumberOfArgs]},\n"
123 " {{".format(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600124 messageId=messageId, message=message
125 )
126 )
Nan Zhou49aa131f2022-09-20 18:41:37 +0000127 paramTypes = message.get("ParamTypes")
128 if paramTypes:
129 for paramType in paramTypes:
130 registry.write(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600131 '\n "{}",'.format(paramType)
Nan Zhou49aa131f2022-09-20 18:41:37 +0000132 )
133 registry.write("\n },\n")
134 else:
135 registry.write("},\n")
136 registry.write(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600137 ' "{message[Resolution]}",\n'
138 " }}}},\n".format(message=message)
139 )
Nan Zhou49aa131f2022-09-20 18:41:37 +0000140
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600141 registry.write("\n};\n\nenum class Index\n{\n")
Nan Zhou49aa131f2022-09-20 18:41:37 +0000142 for index, (messageId, message) in enumerate(messages_sorted):
143 messageId = messageId[0].lower() + messageId[1:]
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600144 registry.write(" {} = {},\n".format(messageId, index))
Nan Zhou49aa131f2022-09-20 18:41:37 +0000145 registry.write(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600146 "}};\n}} // namespace redfish::registries::{}\n".format(
147 namespace
148 )
149 )
Ed Tanoused398212021-06-09 17:05:54 -0700150
151
152def get_privilege_string_from_list(privilege_list):
153 privilege_string = "{{\n"
154 for privilege_json in privilege_list:
155 privileges = privilege_json["Privilege"]
156 privilege_string += " {"
157 for privilege in privileges:
158 if privilege == "NoAuth":
159 continue
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600160 privilege_string += '"'
Ed Tanoused398212021-06-09 17:05:54 -0700161 privilege_string += privilege
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600162 privilege_string += '",\n'
Ed Tanoused398212021-06-09 17:05:54 -0700163 if privilege != "NoAuth":
164 privilege_string = privilege_string[:-2]
165 privilege_string += "}"
166 privilege_string += ",\n"
167 privilege_string = privilege_string[:-2]
168 privilege_string += "\n}}"
169 return privilege_string
170
Ed Tanousf395daa2021-08-02 08:56:24 -0700171
Ed Tanoused398212021-06-09 17:05:54 -0700172def get_variable_name_for_privilege_set(privilege_list):
173 names = []
174 for privilege_json in privilege_list:
175 privileges = privilege_json["Privilege"]
176 names.append("And".join(privileges))
177 return "Or".join(names)
178
Ed Tanousf395daa2021-08-02 08:56:24 -0700179
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600180PRIVILEGE_HEADER = (
181 PRAGMA_ONCE
182 + WARNING
183 + """
Nan Zhou01c78a02022-09-20 18:17:20 +0000184#include "privileges.hpp"
185
186#include <array>
Nan Zhou043bec02022-09-20 18:12:13 +0000187
188// clang-format off
189
190namespace redfish::privileges
191{
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600192"""
193)
Nan Zhou043bec02022-09-20 18:12:13 +0000194
195
Ed Tanous7ccfe682024-11-16 14:36:16 -0800196def get_response_code(entry_id, entry):
197 codes = {
198 "InternalError": "internal_server_error",
199 "OperationTimeout": "internal_server_error",
200 "PropertyValueResourceConflict": "conflict",
201 "ResourceInUse": "service_unavailable",
202 "ServiceTemporarilyUnavailable": "service_unavailable",
203 "ResourceCannotBeDeleted": "method_not_allowed",
204 "PropertyValueModified": "ok",
205 "InsufficientPrivilege": "forbidden",
206 "AccountForSessionNoLongerExists": "forbidden",
207 "ServiceDisabled": "service_unavailable",
208 "ServiceInUnknownState": "service_unavailable",
209 "EventSubscriptionLimitExceeded": "service_unavailable",
210 "ResourceAtUriUnauthorized": "unauthorized",
211 "SessionTerminated": "ok",
212 "SubscriptionTerminated": "ok",
213 "PropertyNotWritable": "forbidden",
214 "MaximumErrorsExceeded": "internal_server_error",
215 "GeneralError": "internal_server_error",
216 "PreconditionFailed": "precondition_failed",
217 "OperationFailed": "bad_gateway",
218 "ServiceShuttingDown": "service_unavailable",
219 "AccountRemoved": "ok",
220 "PropertyValueExternalConflict": "conflict",
221 "InsufficientStorage": "insufficient_storage",
222 "OperationNotAllowed": "method_not_allowed",
223 "ResourceNotFound": "not_found",
224 "CouldNotEstablishConnection": "not_found",
225 "AccessDenied": "forbidden",
226 "Success": None,
227 "Created": "created",
228 "NoValidSession": "forbidden",
229 "SessionLimitExceeded": "service_unavailable",
230 "ResourceExhaustion": "service_unavailable",
231 "AccountModified": "ok",
232 "PasswordChangeRequired": None,
233 "ResourceInStandby": "service_unavailable",
234 "GenerateSecretKeyRequired": "forbidden",
235 }
236
237 code = codes.get(entry_id, "NOCODE")
238 if code != "NOCODE":
239 return code
240
241 return "bad_request"
242
243
Ed Tanousf175c282024-12-02 15:12:50 -0800244def make_error_function(
245 entry_id, entry, is_header, registry_name, namespace_name
246):
Ed Tanous644cdcb2024-11-17 11:12:41 -0800247 arg_nonstring_types = {
248 "const boost::urls::url_view_base&": {
249 "AccessDenied": [1],
250 "CouldNotEstablishConnection": [1],
251 "GenerateSecretKeyRequired": [1],
252 "InvalidObject": [1],
253 "PasswordChangeRequired": [1],
254 "PropertyValueResourceConflict": [3],
255 "ResetRequired": [1],
256 "ResourceAtUriInUnknownFormat": [1],
257 "ResourceAtUriUnauthorized": [1],
258 "ResourceCreationConflict": [1],
259 "ResourceMissingAtURI": [1],
260 "SourceDoesNotSupportProtocol": [1],
261 },
262 "const nlohmann::json&": {
263 "ActionParameterValueError": [1],
264 "ActionParameterValueFormatError": [1],
265 "ActionParameterValueTypeError": [1],
266 "PropertyValueExternalConflict": [2],
267 "PropertyValueFormatError": [1],
268 "PropertyValueIncorrect": [2],
269 "PropertyValueModified": [2],
270 "PropertyValueNotInList": [1],
271 "PropertyValueOutOfRange": [1],
272 "PropertyValueResourceConflict": [2],
273 "PropertyValueTypeError": [1],
274 "QueryParameterValueFormatError": [1],
275 "QueryParameterValueTypeError": [1],
276 },
277 "uint64_t": {
278 "ArraySizeTooLong": [2],
279 "InvalidIndex": [1],
280 "StringValueTooLong": [2],
Ed Tanousf175c282024-12-02 15:12:50 -0800281 "TaskProgressChanged": [2],
Ed Tanous644cdcb2024-11-17 11:12:41 -0800282 },
Ed Tanous42079ec2024-11-16 13:32:29 -0800283 }
284
Ed Tanous7ccfe682024-11-16 14:36:16 -0800285 out = ""
286 args = []
287 argtypes = []
288 for arg_index, arg in enumerate(entry.get("ParamTypes", [])):
289 arg_index += 1
Ed Tanous644cdcb2024-11-17 11:12:41 -0800290 typename = "std::string_view"
291 for typestring, entries in arg_nonstring_types.items():
292 if arg_index in entries.get(entry_id, []):
293 typename = typestring
294
Ed Tanous7ccfe682024-11-16 14:36:16 -0800295 argtypes.append(typename)
296 args.append(f"{typename} arg{arg_index}")
297 function_name = entry_id[0].lower() + entry_id[1:]
298 arg = ", ".join(args)
299 out += f"nlohmann::json {function_name}({arg})"
300
301 if is_header:
302 out += ";\n\n"
303 else:
304 out += "\n{\n"
305 to_array_type = ""
306 if argtypes:
307 outargs = []
308 for index, typename in enumerate(argtypes):
309 index += 1
310 if typename == "const nlohmann::json&":
311 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 -0800312 elif typename == "uint64_t":
Ed Tanous7ccfe682024-11-16 14:36:16 -0800313 out += f"std::string arg{index}Str = std::to_string(arg{index});\n"
314
315 for index, typename in enumerate(argtypes):
316 index += 1
317 if typename == "const boost::urls::url_view_base&":
318 outargs.append(f"arg{index}.buffer()")
319 to_array_type = "<std::string_view>"
320 elif typename == "const nlohmann::json&":
321 outargs.append(f"arg{index}Str")
322 to_array_type = "<std::string_view>"
Ed Tanous644cdcb2024-11-17 11:12:41 -0800323 elif typename == "uint64_t":
Ed Tanous7ccfe682024-11-16 14:36:16 -0800324 outargs.append(f"arg{index}Str")
325 to_array_type = "<std::string_view>"
326 else:
327 outargs.append(f"arg{index}")
328 argstring = ", ".join(outargs)
Ed Tanous7ccfe682024-11-16 14:36:16 -0800329
330 if argtypes:
331 arg_param = f"std::to_array{to_array_type}({{{argstring}}})"
332 else:
333 arg_param = "{}"
Ed Tanousf175c282024-12-02 15:12:50 -0800334 out += f" return getLog(redfish::registries::{namespace_name}::Index::{function_name}, {arg_param});"
Ed Tanous7ccfe682024-11-16 14:36:16 -0800335 out += "\n}\n\n"
Ed Tanousf175c282024-12-02 15:12:50 -0800336 if registry_name == "Base":
337 args.insert(0, "crow::Response& res")
Ed Tanous7ccfe682024-11-16 14:36:16 -0800338 if entry_id == "InternalError":
Ed Tanousf175c282024-12-02 15:12:50 -0800339 if is_header:
340 args.append(
341 "std::source_location location = std::source_location::current()"
342 )
343 else:
344 args.append("const std::source_location location")
345 arg = ", ".join(args)
346 out += f"void {function_name}({arg})"
347 if is_header:
348 out += ";\n"
Ed Tanous7ccfe682024-11-16 14:36:16 -0800349 else:
Ed Tanousf175c282024-12-02 15:12:50 -0800350 out += "\n{\n"
351 if entry_id == "InternalError":
352 out += """BMCWEB_LOG_CRITICAL("Internal Error {}({}:{}) `{}`: ", location.file_name(),
353 location.line(), location.column(),
354 location.function_name());\n"""
355
356 if entry_id == "ServiceTemporarilyUnavailable":
357 out += "res.addHeader(boost::beast::http::field::retry_after, arg1);"
358
359 res = get_response_code(entry_id, entry)
360 if res:
361 out += f" res.result(boost::beast::http::status::{res});\n"
362 args_out = ", ".join([f"arg{x+1}" for x in range(len(argtypes))])
363
364 addMessageToJson = {
365 "PropertyDuplicate": 1,
366 "ResourceAlreadyExists": 2,
367 "CreateFailedMissingReqProperties": 1,
368 "PropertyValueFormatError": 2,
369 "PropertyValueNotInList": 2,
370 "PropertyValueTypeError": 2,
371 "PropertyValueError": 1,
372 "PropertyNotWritable": 1,
373 "PropertyValueModified": 1,
374 "PropertyMissing": 1,
375 }
376
377 addMessageToRoot = [
378 "SessionTerminated",
379 "SubscriptionTerminated",
380 "AccountRemoved",
381 "Created",
382 "Success",
383 "PasswordChangeRequired",
384 ]
385
386 if entry_id in addMessageToJson:
387 out += f" addMessageToJson(res.jsonValue, {function_name}({args_out}), arg{addMessageToJson[entry_id]});\n"
388 elif entry_id in addMessageToRoot:
389 out += f" addMessageToJsonRoot(res.jsonValue, {function_name}({args_out}));\n"
390 else:
391 out += f" addMessageToErrorJson(res.jsonValue, {function_name}({args_out}));\n"
392 out += "}\n"
Ed Tanous7ccfe682024-11-16 14:36:16 -0800393 out += "\n"
394 return out
395
396
Ed Tanousf175c282024-12-02 15:12:50 -0800397def create_error_registry(
398 entry, registry_version, registry_name, namespace_name, filename
399):
Ed Tanous42079ec2024-11-16 13:32:29 -0800400 file, json_dict, namespace, url = entry
Ed Tanousf175c282024-12-02 15:12:50 -0800401 base_filename = filename + "_messages"
Ed Tanous42079ec2024-11-16 13:32:29 -0800402
Ed Tanous42079ec2024-11-16 13:32:29 -0800403 error_messages_hpp = os.path.join(
Ed Tanousf175c282024-12-02 15:12:50 -0800404 SCRIPT_DIR, "..", "redfish-core", "include", f"{base_filename}.hpp"
Ed Tanous42079ec2024-11-16 13:32:29 -0800405 )
Ed Tanousf8cca872024-11-16 22:47:34 -0800406 messages = json_dict["Messages"]
407
Ed Tanous42079ec2024-11-16 13:32:29 -0800408 with open(
409 error_messages_hpp,
410 "w",
411 ) as out:
412 out.write(PRAGMA_ONCE)
413 out.write(WARNING)
414 out.write(
415 """
416
417#include "http_response.hpp"
418
419#include <boost/url/url_view_base.hpp>
420#include <nlohmann/json.hpp>
421
Ed Tanous42079ec2024-11-16 13:32:29 -0800422#include <source_location>
Ed Tanous42079ec2024-11-16 13:32:29 -0800423#include <string_view>
424
425// IWYU pragma: no_forward_declare crow::Response
426
427namespace redfish
428{
429
430namespace messages
431{
Ed Tanous42079ec2024-11-16 13:32:29 -0800432"""
433 )
Ed Tanousf175c282024-12-02 15:12:50 -0800434 if registry_name == "Base":
435 out.write(
436 f'constexpr const char* messageVersionPrefix = "{registry_name}.{registry_version}.";'
437 )
438 out.write(
439 """
440 constexpr const char* messageAnnotation = "@Message.ExtendedInfo";
Ed Tanous42079ec2024-11-16 13:32:29 -0800441
Ed Tanousf175c282024-12-02 15:12:50 -0800442 /**
443 * @brief Moves all error messages from the |source| JSON to |target|
444 */
445 void moveErrorsToErrorJson(nlohmann::json& target, nlohmann::json& source);
Ed Tanous352945b2024-11-17 22:45:51 -0800446
Ed Tanousf175c282024-12-02 15:12:50 -0800447 """
448 )
Ed Tanous42079ec2024-11-16 13:32:29 -0800449 for entry_id, entry in messages.items():
450 message = entry["Message"]
451 for index in range(1, 10):
452 message = message.replace(f"'%{index}'", f"<arg{index}>")
453 message = message.replace(f"%{index}", f"<arg{index}>")
454
Ed Tanousf175c282024-12-02 15:12:50 -0800455 if registry_name == "Base":
456 out.write("/**\n")
457 out.write(f"* @brief Formats {entry_id} message into JSON\n")
458 out.write(f'* Message body: "{message}"\n')
459 out.write("*\n")
460 arg_index = 0
461 for arg_index, arg in enumerate(entry.get("ParamTypes", [])):
462 arg_index += 1
Ed Tanous42079ec2024-11-16 13:32:29 -0800463
Ed Tanousf175c282024-12-02 15:12:50 -0800464 out.write(
465 f"* @param[in] arg{arg_index} Parameter of message that will replace %{arg_index} in its body.\n"
466 )
467 out.write("*\n")
Ed Tanous42079ec2024-11-16 13:32:29 -0800468 out.write(
Ed Tanousf175c282024-12-02 15:12:50 -0800469 f"* @returns Message {entry_id} formatted to JSON */\n"
Ed Tanous42079ec2024-11-16 13:32:29 -0800470 )
Ed Tanous42079ec2024-11-16 13:32:29 -0800471
Ed Tanousf175c282024-12-02 15:12:50 -0800472 out.write(
473 make_error_function(
474 entry_id, entry, True, registry_name, namespace_name
475 )
476 )
Ed Tanous42079ec2024-11-16 13:32:29 -0800477 out.write(" }\n")
478 out.write("}\n")
Ed Tanous7ccfe682024-11-16 14:36:16 -0800479
480 error_messages_cpp = os.path.join(
Ed Tanousf175c282024-12-02 15:12:50 -0800481 SCRIPT_DIR, "..", "redfish-core", "src", f"{base_filename}.cpp"
Ed Tanous7ccfe682024-11-16 14:36:16 -0800482 )
483 with open(
484 error_messages_cpp,
485 "w",
486 ) as out:
487 out.write(WARNING)
Ed Tanousf175c282024-12-02 15:12:50 -0800488 out.write(f'\n#include "{base_filename}.hpp"\n')
Ed Tanous847deee2024-12-02 15:28:10 -0800489 headers = []
Ed Tanous7ccfe682024-11-16 14:36:16 -0800490
Ed Tanous847deee2024-12-02 15:28:10 -0800491 headers.append('"registries.hpp"')
Ed Tanousf175c282024-12-02 15:12:50 -0800492 if registry_name == "Base":
493 reg_name_lower = "base"
Ed Tanous847deee2024-12-02 15:28:10 -0800494 headers.append('"http_response.hpp"')
495 headers.append('"logging.hpp"')
496 headers.append("<boost/beast/http/field.hpp>")
497 headers.append("<boost/beast/http/status.hpp>")
498 headers.append("<boost/url/url_view_base.hpp>")
499 headers.append("<source_location>")
Ed Tanousf175c282024-12-02 15:12:50 -0800500 else:
501 reg_name_lower = namespace_name.lower()
Ed Tanous847deee2024-12-02 15:28:10 -0800502 headers.append(f'"registries/{reg_name_lower}_message_registry.hpp"')
Ed Tanous7ccfe682024-11-16 14:36:16 -0800503
Ed Tanous847deee2024-12-02 15:28:10 -0800504 headers.append("<nlohmann/json.hpp>")
505 headers.append("<array>")
506 headers.append("<cstddef>")
507 headers.append("<span>")
508
Ed Tanousa8a5bc12024-12-02 15:43:16 -0800509 if registry_name not in ("ResourceEvent", "HeartbeatEvent"):
Ed Tanous847deee2024-12-02 15:28:10 -0800510 headers.append("<cstdint>")
511 headers.append("<string>")
512 headers.append("<string_view>")
513
514 for header in headers:
515 out.write(f"#include {header}\n")
516
Ed Tanousf175c282024-12-02 15:12:50 -0800517 out.write(
518 """
Ed Tanous7ccfe682024-11-16 14:36:16 -0800519// Clang can't seem to decide whether this header needs to be included or not,
520// and is inconsistent. Include it for now
521// NOLINTNEXTLINE(misc-include-cleaner)
522#include <utility>
523
524namespace redfish
525{
526
527namespace messages
528{
Ed Tanousf175c282024-12-02 15:12:50 -0800529"""
530 )
Ed Tanous7ccfe682024-11-16 14:36:16 -0800531
Ed Tanousf175c282024-12-02 15:12:50 -0800532 if registry_name == "Base":
533 out.write(
534 """
Ed Tanous7ccfe682024-11-16 14:36:16 -0800535static void addMessageToErrorJson(nlohmann::json& target,
536 const nlohmann::json& message)
537{
538 auto& error = target["error"];
539
540 // If this is the first error message, fill in the information from the
541 // first error message to the top level struct
542 if (!error.is_object())
543 {
544 auto messageIdIterator = message.find("MessageId");
545 if (messageIdIterator == message.end())
546 {
547 BMCWEB_LOG_CRITICAL(
548 "Attempt to add error message without MessageId");
549 return;
550 }
551
552 auto messageFieldIterator = message.find("Message");
553 if (messageFieldIterator == message.end())
554 {
555 BMCWEB_LOG_CRITICAL("Attempt to add error message without Message");
556 return;
557 }
558 error["code"] = *messageIdIterator;
559 error["message"] = *messageFieldIterator;
560 }
561 else
562 {
563 // More than 1 error occurred, so the message has to be generic
564 error["code"] = std::string(messageVersionPrefix) + "GeneralError";
565 error["message"] = "A general error has occurred. See Resolution for "
566 "information on how to resolve the error.";
567 }
568
569 // This check could technically be done in the default construction
570 // branch above, but because we need the pointer to the extended info field
571 // anyway, it's more efficient to do it here.
572 auto& extendedInfo = error[messages::messageAnnotation];
573 if (!extendedInfo.is_array())
574 {
575 extendedInfo = nlohmann::json::array();
576 }
577
578 extendedInfo.push_back(message);
579}
580
581void moveErrorsToErrorJson(nlohmann::json& target, nlohmann::json& source)
582{
583 if (!source.is_object())
584 {
585 return;
586 }
587 auto errorIt = source.find("error");
588 if (errorIt == source.end())
589 {
590 // caller puts error message in root
591 messages::addMessageToErrorJson(target, source);
592 source.clear();
593 return;
594 }
595 auto extendedInfoIt = errorIt->find(messages::messageAnnotation);
596 if (extendedInfoIt == errorIt->end())
597 {
598 return;
599 }
600 const nlohmann::json::array_t* extendedInfo =
601 (*extendedInfoIt).get_ptr<const nlohmann::json::array_t*>();
602 if (extendedInfo == nullptr)
603 {
604 source.erase(errorIt);
605 return;
606 }
607 for (const nlohmann::json& message : *extendedInfo)
608 {
609 addMessageToErrorJson(target, message);
610 }
611 source.erase(errorIt);
612}
613
614static void addMessageToJsonRoot(nlohmann::json& target,
615 const nlohmann::json& message)
616{
617 if (!target[messages::messageAnnotation].is_array())
618 {
619 // Force object to be an array
620 target[messages::messageAnnotation] = nlohmann::json::array();
621 }
622
623 target[messages::messageAnnotation].push_back(message);
624}
625
626static void addMessageToJson(nlohmann::json& target,
627 const nlohmann::json& message,
628 std::string_view fieldPath)
629{
630 std::string extendedInfo(fieldPath);
631 extendedInfo += messages::messageAnnotation;
632
633 nlohmann::json& field = target[extendedInfo];
634 if (!field.is_array())
635 {
636 // Force object to be an array
637 field = nlohmann::json::array();
638 }
639
640 // Object exists and it is an array so we can just push in the message
641 field.push_back(message);
642}
Ed Tanous7ccfe682024-11-16 14:36:16 -0800643"""
Ed Tanousf175c282024-12-02 15:12:50 -0800644 )
645 out.write(
646 """
647static nlohmann::json getLog(redfish::registries::{namespace_name}::Index name,
648 std::span<const std::string_view> args)
649{{
650 size_t index = static_cast<size_t>(name);
651 if (index >= redfish::registries::{namespace_name}::registry.size())
652 {{
653 return {{}};
654 }}
655 return getLogFromRegistry(redfish::registries::{namespace_name}::header,
656 redfish::registries::{namespace_name}::registry, index, args);
657}}
658
659""".format(
660 namespace_name=namespace_name
661 )
Ed Tanous7ccfe682024-11-16 14:36:16 -0800662 )
663 for entry_id, entry in messages.items():
664 out.write(
665 f"""/**
666 * @internal
667 * @brief Formats {entry_id} message into JSON
668 *
669 * See header file for more information
670 * @endinternal
671 */
672"""
673 )
674 message = entry["Message"]
Ed Tanousf175c282024-12-02 15:12:50 -0800675 out.write(
676 make_error_function(
677 entry_id, entry, False, registry_name, namespace_name
678 )
679 )
Ed Tanous7ccfe682024-11-16 14:36:16 -0800680
681 out.write(" }\n")
682 out.write("}\n")
683 os.system(f"clang-format -i {error_messages_hpp} {error_messages_cpp}")
Ed Tanous42079ec2024-11-16 13:32:29 -0800684
685
Ed Tanoused398212021-06-09 17:05:54 -0700686def make_privilege_registry():
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600687 path, json_file, type_name, url = make_getter(
Gunnar Mills5910d942024-04-16 12:07:17 -0500688 "Redfish_1.5.0_PrivilegeRegistry.json",
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600689 "privilege_registry.hpp",
690 "privilege",
691 )
692 with open(path, "w") as registry:
Nan Zhou043bec02022-09-20 18:12:13 +0000693 registry.write(PRIVILEGE_HEADER)
Ed Tanoused398212021-06-09 17:05:54 -0700694
695 privilege_dict = {}
696 for mapping in json_file["Mappings"]:
697 # first pass, identify all the unique privilege sets
698 for operation, privilege_list in mapping["OperationMap"].items():
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600699 privilege_dict[
700 get_privilege_string_from_list(privilege_list)
701 ] = (privilege_list,)
Ed Tanoused398212021-06-09 17:05:54 -0700702 for index, key in enumerate(privilege_dict):
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600703 (privilege_list,) = privilege_dict[key]
Ed Tanoused398212021-06-09 17:05:54 -0700704 name = get_variable_name_for_privilege_set(privilege_list)
Ed Tanousf395daa2021-08-02 08:56:24 -0700705 registry.write(
Ed Tanous5b9ef702022-02-17 12:19:32 -0800706 "const std::array<Privileges, {length}> "
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600707 "privilegeSet{name} = {key};\n".format(
708 length=len(privilege_list), name=name, key=key
709 )
Ed Tanous5b9ef702022-02-17 12:19:32 -0800710 )
Ed Tanoused398212021-06-09 17:05:54 -0700711 privilege_dict[key] = (privilege_list, name)
Ed Tanoused398212021-06-09 17:05:54 -0700712
713 for mapping in json_file["Mappings"]:
714 entity = mapping["Entity"]
Ed Tanous4d99bbb2022-02-17 10:02:57 -0800715 registry.write("// {}\n".format(entity))
Ed Tanoused398212021-06-09 17:05:54 -0700716 for operation, privilege_list in mapping["OperationMap"].items():
717 privilege_string = get_privilege_string_from_list(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600718 privilege_list
719 )
Ed Tanoused398212021-06-09 17:05:54 -0700720 operation = operation.lower()
721
Ed Tanousf395daa2021-08-02 08:56:24 -0700722 registry.write(
723 "const static auto& {}{} = privilegeSet{};\n".format(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600724 operation, entity, privilege_dict[privilege_string][1]
725 )
726 )
Ed Tanoused398212021-06-09 17:05:54 -0700727 registry.write("\n")
Ed Tanous5b9ef702022-02-17 12:19:32 -0800728 registry.write(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600729 "} // namespace redfish::privileges\n// clang-format on\n"
730 )
Ed Tanoused398212021-06-09 17:05:54 -0700731
732
Gunnar Mills665e7602024-04-10 13:14:41 -0500733def to_pascal_case(text):
734 s = text.replace("_", " ")
735 s = s.split()
736 if len(text) == 0:
737 return text
738 return "".join(i.capitalize() for i in s[0:])
739
740
Nan Zhou49aa131f2022-09-20 18:41:37 +0000741def main():
Gunnar Mills665e7602024-04-10 13:14:41 -0500742 dmtf_registries = (
Jishnu CMb575cae2024-10-01 01:33:49 -0500743 ("base", "1.19.0"),
Gunnar Mills665e7602024-04-10 13:14:41 -0500744 ("composition", "1.1.2"),
745 ("environmental", "1.0.1"),
746 ("ethernet_fabric", "1.0.1"),
747 ("fabric", "1.0.2"),
748 ("heartbeat_event", "1.0.1"),
749 ("job_event", "1.0.1"),
750 ("license", "1.0.3"),
751 ("log_service", "1.0.1"),
752 ("network_device", "1.0.3"),
753 ("platform", "1.0.1"),
754 ("power", "1.0.1"),
755 ("resource_event", "1.3.0"),
756 ("sensor_event", "1.0.1"),
757 ("storage_device", "1.2.1"),
758 ("task_event", "1.0.3"),
759 ("telemetry", "1.0.0"),
760 ("update", "1.0.2"),
761 )
762
Nan Zhou49aa131f2022-09-20 18:41:37 +0000763 parser = argparse.ArgumentParser()
764 parser.add_argument(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600765 "--registries",
766 type=str,
Gunnar Mills665e7602024-04-10 13:14:41 -0500767 default="privilege,openbmc,"
768 + ",".join([dmtf[0] for dmtf in dmtf_registries]),
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600769 help="Comma delimited list of registries to update",
770 )
Nan Zhou49aa131f2022-09-20 18:41:37 +0000771
772 args = parser.parse_args()
773
774 registries = set(args.registries.split(","))
775 files = []
776
Gunnar Mills665e7602024-04-10 13:14:41 -0500777 for registry, version in dmtf_registries:
778 if registry in registries:
779 registry_pascal_case = to_pascal_case(registry)
780 files.append(
781 make_getter(
782 f"{registry_pascal_case}.{version}.json",
783 f"{registry}_message_registry.hpp",
784 registry,
785 )
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600786 )
Ed Tanous3e5faba2023-08-16 15:11:29 -0700787 if "openbmc" in registries:
788 files.append(openbmc_local_getter())
Nan Zhou49aa131f2022-09-20 18:41:37 +0000789
790 update_registries(files)
791
Ed Tanousf175c282024-12-02 15:12:50 -0800792 create_error_registry(
793 files[0], dmtf_registries[0][1], "Base", "base", "error"
794 )
795 create_error_registry(
Ed Tanousa8a5bc12024-12-02 15:43:16 -0800796 files[5],
797 dmtf_registries[5][1],
798 "HeartbeatEvent",
799 "heartbeat_event",
800 "heartbeat",
801 )
802 create_error_registry(
Ed Tanous847deee2024-12-02 15:28:10 -0800803 files[12],
804 dmtf_registries[12][1],
805 "ResourceEvent",
806 "resource_event",
807 "resource",
808 )
809 create_error_registry(
Ed Tanousf175c282024-12-02 15:12:50 -0800810 files[15], dmtf_registries[15][1], "TaskEvent", "task_event", "task"
811 )
Ed Tanous42079ec2024-11-16 13:32:29 -0800812
Nan Zhou49aa131f2022-09-20 18:41:37 +0000813 if "privilege" in registries:
814 make_privilege_registry()
815
816
817if __name__ == "__main__":
818 main()