blob: fda21246789c4711549c4bfbb08c8211103d833e [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
422#include <cstdint>
423#include <source_location>
424#include <string>
425#include <string_view>
426
427// IWYU pragma: no_forward_declare crow::Response
428
429namespace redfish
430{
431
432namespace messages
433{
Ed Tanous42079ec2024-11-16 13:32:29 -0800434"""
435 )
Ed Tanousf175c282024-12-02 15:12:50 -0800436 if registry_name == "Base":
437 out.write(
438 f'constexpr const char* messageVersionPrefix = "{registry_name}.{registry_version}.";'
439 )
440 out.write(
441 """
442 constexpr const char* messageAnnotation = "@Message.ExtendedInfo";
Ed Tanous42079ec2024-11-16 13:32:29 -0800443
Ed Tanousf175c282024-12-02 15:12:50 -0800444 /**
445 * @brief Moves all error messages from the |source| JSON to |target|
446 */
447 void moveErrorsToErrorJson(nlohmann::json& target, nlohmann::json& source);
Ed Tanous352945b2024-11-17 22:45:51 -0800448
Ed Tanousf175c282024-12-02 15:12:50 -0800449 """
450 )
Ed Tanous42079ec2024-11-16 13:32:29 -0800451 for entry_id, entry in messages.items():
452 message = entry["Message"]
453 for index in range(1, 10):
454 message = message.replace(f"'%{index}'", f"<arg{index}>")
455 message = message.replace(f"%{index}", f"<arg{index}>")
456
Ed Tanousf175c282024-12-02 15:12:50 -0800457 if registry_name == "Base":
458 out.write("/**\n")
459 out.write(f"* @brief Formats {entry_id} message into JSON\n")
460 out.write(f'* Message body: "{message}"\n')
461 out.write("*\n")
462 arg_index = 0
463 for arg_index, arg in enumerate(entry.get("ParamTypes", [])):
464 arg_index += 1
Ed Tanous42079ec2024-11-16 13:32:29 -0800465
Ed Tanousf175c282024-12-02 15:12:50 -0800466 out.write(
467 f"* @param[in] arg{arg_index} Parameter of message that will replace %{arg_index} in its body.\n"
468 )
469 out.write("*\n")
Ed Tanous42079ec2024-11-16 13:32:29 -0800470 out.write(
Ed Tanousf175c282024-12-02 15:12:50 -0800471 f"* @returns Message {entry_id} formatted to JSON */\n"
Ed Tanous42079ec2024-11-16 13:32:29 -0800472 )
Ed Tanous42079ec2024-11-16 13:32:29 -0800473
Ed Tanousf175c282024-12-02 15:12:50 -0800474 out.write(
475 make_error_function(
476 entry_id, entry, True, registry_name, namespace_name
477 )
478 )
Ed Tanous42079ec2024-11-16 13:32:29 -0800479 out.write(" }\n")
480 out.write("}\n")
Ed Tanous7ccfe682024-11-16 14:36:16 -0800481
482 error_messages_cpp = os.path.join(
Ed Tanousf175c282024-12-02 15:12:50 -0800483 SCRIPT_DIR, "..", "redfish-core", "src", f"{base_filename}.cpp"
Ed Tanous7ccfe682024-11-16 14:36:16 -0800484 )
485 with open(
486 error_messages_cpp,
487 "w",
488 ) as out:
489 out.write(WARNING)
Ed Tanousf175c282024-12-02 15:12:50 -0800490 out.write(f'\n#include "{base_filename}.hpp"\n')
Ed Tanous847deee2024-12-02 15:28:10 -0800491 headers = []
Ed Tanous7ccfe682024-11-16 14:36:16 -0800492
Ed Tanous847deee2024-12-02 15:28:10 -0800493 headers.append('"registries.hpp"')
Ed Tanousf175c282024-12-02 15:12:50 -0800494 if registry_name == "Base":
495 reg_name_lower = "base"
Ed Tanous847deee2024-12-02 15:28:10 -0800496 headers.append('"http_response.hpp"')
497 headers.append('"logging.hpp"')
498 headers.append("<boost/beast/http/field.hpp>")
499 headers.append("<boost/beast/http/status.hpp>")
500 headers.append("<boost/url/url_view_base.hpp>")
501 headers.append("<source_location>")
Ed Tanousf175c282024-12-02 15:12:50 -0800502 else:
503 reg_name_lower = namespace_name.lower()
Ed Tanous847deee2024-12-02 15:28:10 -0800504 headers.append(f'"registries/{reg_name_lower}_message_registry.hpp"')
Ed Tanous7ccfe682024-11-16 14:36:16 -0800505
Ed Tanous847deee2024-12-02 15:28:10 -0800506 headers.append("<nlohmann/json.hpp>")
507 headers.append("<array>")
508 headers.append("<cstddef>")
509 headers.append("<span>")
510
511 if registry_name != "ResourceEvent":
512 headers.append("<cstdint>")
513 headers.append("<string>")
514 headers.append("<string_view>")
515
516 for header in headers:
517 out.write(f"#include {header}\n")
518
Ed Tanousf175c282024-12-02 15:12:50 -0800519 out.write(
520 """
Ed Tanous7ccfe682024-11-16 14:36:16 -0800521// Clang can't seem to decide whether this header needs to be included or not,
522// and is inconsistent. Include it for now
523// NOLINTNEXTLINE(misc-include-cleaner)
524#include <utility>
525
526namespace redfish
527{
528
529namespace messages
530{
Ed Tanousf175c282024-12-02 15:12:50 -0800531"""
532 )
Ed Tanous7ccfe682024-11-16 14:36:16 -0800533
Ed Tanousf175c282024-12-02 15:12:50 -0800534 if registry_name == "Base":
535 out.write(
536 """
Ed Tanous7ccfe682024-11-16 14:36:16 -0800537static void addMessageToErrorJson(nlohmann::json& target,
538 const nlohmann::json& message)
539{
540 auto& error = target["error"];
541
542 // If this is the first error message, fill in the information from the
543 // first error message to the top level struct
544 if (!error.is_object())
545 {
546 auto messageIdIterator = message.find("MessageId");
547 if (messageIdIterator == message.end())
548 {
549 BMCWEB_LOG_CRITICAL(
550 "Attempt to add error message without MessageId");
551 return;
552 }
553
554 auto messageFieldIterator = message.find("Message");
555 if (messageFieldIterator == message.end())
556 {
557 BMCWEB_LOG_CRITICAL("Attempt to add error message without Message");
558 return;
559 }
560 error["code"] = *messageIdIterator;
561 error["message"] = *messageFieldIterator;
562 }
563 else
564 {
565 // More than 1 error occurred, so the message has to be generic
566 error["code"] = std::string(messageVersionPrefix) + "GeneralError";
567 error["message"] = "A general error has occurred. See Resolution for "
568 "information on how to resolve the error.";
569 }
570
571 // This check could technically be done in the default construction
572 // branch above, but because we need the pointer to the extended info field
573 // anyway, it's more efficient to do it here.
574 auto& extendedInfo = error[messages::messageAnnotation];
575 if (!extendedInfo.is_array())
576 {
577 extendedInfo = nlohmann::json::array();
578 }
579
580 extendedInfo.push_back(message);
581}
582
583void moveErrorsToErrorJson(nlohmann::json& target, nlohmann::json& source)
584{
585 if (!source.is_object())
586 {
587 return;
588 }
589 auto errorIt = source.find("error");
590 if (errorIt == source.end())
591 {
592 // caller puts error message in root
593 messages::addMessageToErrorJson(target, source);
594 source.clear();
595 return;
596 }
597 auto extendedInfoIt = errorIt->find(messages::messageAnnotation);
598 if (extendedInfoIt == errorIt->end())
599 {
600 return;
601 }
602 const nlohmann::json::array_t* extendedInfo =
603 (*extendedInfoIt).get_ptr<const nlohmann::json::array_t*>();
604 if (extendedInfo == nullptr)
605 {
606 source.erase(errorIt);
607 return;
608 }
609 for (const nlohmann::json& message : *extendedInfo)
610 {
611 addMessageToErrorJson(target, message);
612 }
613 source.erase(errorIt);
614}
615
616static void addMessageToJsonRoot(nlohmann::json& target,
617 const nlohmann::json& message)
618{
619 if (!target[messages::messageAnnotation].is_array())
620 {
621 // Force object to be an array
622 target[messages::messageAnnotation] = nlohmann::json::array();
623 }
624
625 target[messages::messageAnnotation].push_back(message);
626}
627
628static void addMessageToJson(nlohmann::json& target,
629 const nlohmann::json& message,
630 std::string_view fieldPath)
631{
632 std::string extendedInfo(fieldPath);
633 extendedInfo += messages::messageAnnotation;
634
635 nlohmann::json& field = target[extendedInfo];
636 if (!field.is_array())
637 {
638 // Force object to be an array
639 field = nlohmann::json::array();
640 }
641
642 // Object exists and it is an array so we can just push in the message
643 field.push_back(message);
644}
Ed Tanous7ccfe682024-11-16 14:36:16 -0800645"""
Ed Tanousf175c282024-12-02 15:12:50 -0800646 )
647 out.write(
648 """
649static nlohmann::json getLog(redfish::registries::{namespace_name}::Index name,
650 std::span<const std::string_view> args)
651{{
652 size_t index = static_cast<size_t>(name);
653 if (index >= redfish::registries::{namespace_name}::registry.size())
654 {{
655 return {{}};
656 }}
657 return getLogFromRegistry(redfish::registries::{namespace_name}::header,
658 redfish::registries::{namespace_name}::registry, index, args);
659}}
660
661""".format(
662 namespace_name=namespace_name
663 )
Ed Tanous7ccfe682024-11-16 14:36:16 -0800664 )
665 for entry_id, entry in messages.items():
666 out.write(
667 f"""/**
668 * @internal
669 * @brief Formats {entry_id} message into JSON
670 *
671 * See header file for more information
672 * @endinternal
673 */
674"""
675 )
676 message = entry["Message"]
Ed Tanousf175c282024-12-02 15:12:50 -0800677 out.write(
678 make_error_function(
679 entry_id, entry, False, registry_name, namespace_name
680 )
681 )
Ed Tanous7ccfe682024-11-16 14:36:16 -0800682
683 out.write(" }\n")
684 out.write("}\n")
685 os.system(f"clang-format -i {error_messages_hpp} {error_messages_cpp}")
Ed Tanous42079ec2024-11-16 13:32:29 -0800686
687
Ed Tanoused398212021-06-09 17:05:54 -0700688def make_privilege_registry():
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600689 path, json_file, type_name, url = make_getter(
Gunnar Mills5910d942024-04-16 12:07:17 -0500690 "Redfish_1.5.0_PrivilegeRegistry.json",
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600691 "privilege_registry.hpp",
692 "privilege",
693 )
694 with open(path, "w") as registry:
Nan Zhou043bec02022-09-20 18:12:13 +0000695 registry.write(PRIVILEGE_HEADER)
Ed Tanoused398212021-06-09 17:05:54 -0700696
697 privilege_dict = {}
698 for mapping in json_file["Mappings"]:
699 # first pass, identify all the unique privilege sets
700 for operation, privilege_list in mapping["OperationMap"].items():
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600701 privilege_dict[
702 get_privilege_string_from_list(privilege_list)
703 ] = (privilege_list,)
Ed Tanoused398212021-06-09 17:05:54 -0700704 for index, key in enumerate(privilege_dict):
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600705 (privilege_list,) = privilege_dict[key]
Ed Tanoused398212021-06-09 17:05:54 -0700706 name = get_variable_name_for_privilege_set(privilege_list)
Ed Tanousf395daa2021-08-02 08:56:24 -0700707 registry.write(
Ed Tanous5b9ef702022-02-17 12:19:32 -0800708 "const std::array<Privileges, {length}> "
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600709 "privilegeSet{name} = {key};\n".format(
710 length=len(privilege_list), name=name, key=key
711 )
Ed Tanous5b9ef702022-02-17 12:19:32 -0800712 )
Ed Tanoused398212021-06-09 17:05:54 -0700713 privilege_dict[key] = (privilege_list, name)
Ed Tanoused398212021-06-09 17:05:54 -0700714
715 for mapping in json_file["Mappings"]:
716 entity = mapping["Entity"]
Ed Tanous4d99bbb2022-02-17 10:02:57 -0800717 registry.write("// {}\n".format(entity))
Ed Tanoused398212021-06-09 17:05:54 -0700718 for operation, privilege_list in mapping["OperationMap"].items():
719 privilege_string = get_privilege_string_from_list(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600720 privilege_list
721 )
Ed Tanoused398212021-06-09 17:05:54 -0700722 operation = operation.lower()
723
Ed Tanousf395daa2021-08-02 08:56:24 -0700724 registry.write(
725 "const static auto& {}{} = privilegeSet{};\n".format(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600726 operation, entity, privilege_dict[privilege_string][1]
727 )
728 )
Ed Tanoused398212021-06-09 17:05:54 -0700729 registry.write("\n")
Ed Tanous5b9ef702022-02-17 12:19:32 -0800730 registry.write(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600731 "} // namespace redfish::privileges\n// clang-format on\n"
732 )
Ed Tanoused398212021-06-09 17:05:54 -0700733
734
Gunnar Mills665e7602024-04-10 13:14:41 -0500735def to_pascal_case(text):
736 s = text.replace("_", " ")
737 s = s.split()
738 if len(text) == 0:
739 return text
740 return "".join(i.capitalize() for i in s[0:])
741
742
Nan Zhou49aa131f2022-09-20 18:41:37 +0000743def main():
Gunnar Mills665e7602024-04-10 13:14:41 -0500744 dmtf_registries = (
Jishnu CMb575cae2024-10-01 01:33:49 -0500745 ("base", "1.19.0"),
Gunnar Mills665e7602024-04-10 13:14:41 -0500746 ("composition", "1.1.2"),
747 ("environmental", "1.0.1"),
748 ("ethernet_fabric", "1.0.1"),
749 ("fabric", "1.0.2"),
750 ("heartbeat_event", "1.0.1"),
751 ("job_event", "1.0.1"),
752 ("license", "1.0.3"),
753 ("log_service", "1.0.1"),
754 ("network_device", "1.0.3"),
755 ("platform", "1.0.1"),
756 ("power", "1.0.1"),
757 ("resource_event", "1.3.0"),
758 ("sensor_event", "1.0.1"),
759 ("storage_device", "1.2.1"),
760 ("task_event", "1.0.3"),
761 ("telemetry", "1.0.0"),
762 ("update", "1.0.2"),
763 )
764
Nan Zhou49aa131f2022-09-20 18:41:37 +0000765 parser = argparse.ArgumentParser()
766 parser.add_argument(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600767 "--registries",
768 type=str,
Gunnar Mills665e7602024-04-10 13:14:41 -0500769 default="privilege,openbmc,"
770 + ",".join([dmtf[0] for dmtf in dmtf_registries]),
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600771 help="Comma delimited list of registries to update",
772 )
Nan Zhou49aa131f2022-09-20 18:41:37 +0000773
774 args = parser.parse_args()
775
776 registries = set(args.registries.split(","))
777 files = []
778
Gunnar Mills665e7602024-04-10 13:14:41 -0500779 for registry, version in dmtf_registries:
780 if registry in registries:
781 registry_pascal_case = to_pascal_case(registry)
782 files.append(
783 make_getter(
784 f"{registry_pascal_case}.{version}.json",
785 f"{registry}_message_registry.hpp",
786 registry,
787 )
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600788 )
Ed Tanous3e5faba2023-08-16 15:11:29 -0700789 if "openbmc" in registries:
790 files.append(openbmc_local_getter())
Nan Zhou49aa131f2022-09-20 18:41:37 +0000791
792 update_registries(files)
793
Ed Tanousf175c282024-12-02 15:12:50 -0800794 create_error_registry(
795 files[0], dmtf_registries[0][1], "Base", "base", "error"
796 )
797 create_error_registry(
Ed Tanous847deee2024-12-02 15:28:10 -0800798 files[12],
799 dmtf_registries[12][1],
800 "ResourceEvent",
801 "resource_event",
802 "resource",
803 )
804 create_error_registry(
Ed Tanousf175c282024-12-02 15:12:50 -0800805 files[15], dmtf_registries[15][1], "TaskEvent", "task_event", "task"
806 )
Ed Tanous42079ec2024-11-16 13:32:29 -0800807
Nan Zhou49aa131f2022-09-20 18:41:37 +0000808 if "privilege" in registries:
809 make_privilege_registry()
810
811
812if __name__ == "__main__":
813 main()