blob: 994b007bf5258fd080ebc153301a8dc9026a1123 [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')
491 if registry_name == "Base":
492 out.write(
493 """
Ed Tanous7ccfe682024-11-16 14:36:16 -0800494
495#include "http_response.hpp"
496#include "logging.hpp"
Ed Tanousf175c282024-12-02 15:12:50 -0800497"""
498 )
499 out.write(
500 """
Ed Tanous7ccfe682024-11-16 14:36:16 -0800501#include "registries.hpp"
Ed Tanousf175c282024-12-02 15:12:50 -0800502"""
503 )
504 if registry_name == "Base":
505 reg_name_lower = "base"
506 else:
507 reg_name_lower = namespace_name.lower()
508 out.write(
509 f'#include "registries/{reg_name_lower}_message_registry.hpp"'
510 )
511 if registry_name == "Base":
512 out.write(
513 """
Ed Tanous7ccfe682024-11-16 14:36:16 -0800514
Ed Tanousf175c282024-12-02 15:12:50 -0800515 #include <boost/beast/http/field.hpp>
516 #include <boost/beast/http/status.hpp>
517 #include <boost/url/url_view_base.hpp>
518"""
519 )
520 out.write(
521 """
Ed Tanous7ccfe682024-11-16 14:36:16 -0800522#include <nlohmann/json.hpp>
523
524#include <array>
525#include <cstddef>
526#include <cstdint>
Ed Tanousf175c282024-12-02 15:12:50 -0800527"""
528 )
529 if registry_name == "Base":
530 out.write(
531 """
Ed Tanous7ccfe682024-11-16 14:36:16 -0800532#include <source_location>
Ed Tanousf175c282024-12-02 15:12:50 -0800533"""
534 )
535 out.write(
536 """
Ed Tanous7ccfe682024-11-16 14:36:16 -0800537#include <span>
538#include <string>
539#include <string_view>
540
541// Clang can't seem to decide whether this header needs to be included or not,
542// and is inconsistent. Include it for now
543// NOLINTNEXTLINE(misc-include-cleaner)
544#include <utility>
545
546namespace redfish
547{
548
549namespace messages
550{
Ed Tanousf175c282024-12-02 15:12:50 -0800551"""
552 )
Ed Tanous7ccfe682024-11-16 14:36:16 -0800553
Ed Tanousf175c282024-12-02 15:12:50 -0800554 if registry_name == "Base":
555 out.write(
556 """
Ed Tanous7ccfe682024-11-16 14:36:16 -0800557static void addMessageToErrorJson(nlohmann::json& target,
558 const nlohmann::json& message)
559{
560 auto& error = target["error"];
561
562 // If this is the first error message, fill in the information from the
563 // first error message to the top level struct
564 if (!error.is_object())
565 {
566 auto messageIdIterator = message.find("MessageId");
567 if (messageIdIterator == message.end())
568 {
569 BMCWEB_LOG_CRITICAL(
570 "Attempt to add error message without MessageId");
571 return;
572 }
573
574 auto messageFieldIterator = message.find("Message");
575 if (messageFieldIterator == message.end())
576 {
577 BMCWEB_LOG_CRITICAL("Attempt to add error message without Message");
578 return;
579 }
580 error["code"] = *messageIdIterator;
581 error["message"] = *messageFieldIterator;
582 }
583 else
584 {
585 // More than 1 error occurred, so the message has to be generic
586 error["code"] = std::string(messageVersionPrefix) + "GeneralError";
587 error["message"] = "A general error has occurred. See Resolution for "
588 "information on how to resolve the error.";
589 }
590
591 // This check could technically be done in the default construction
592 // branch above, but because we need the pointer to the extended info field
593 // anyway, it's more efficient to do it here.
594 auto& extendedInfo = error[messages::messageAnnotation];
595 if (!extendedInfo.is_array())
596 {
597 extendedInfo = nlohmann::json::array();
598 }
599
600 extendedInfo.push_back(message);
601}
602
603void moveErrorsToErrorJson(nlohmann::json& target, nlohmann::json& source)
604{
605 if (!source.is_object())
606 {
607 return;
608 }
609 auto errorIt = source.find("error");
610 if (errorIt == source.end())
611 {
612 // caller puts error message in root
613 messages::addMessageToErrorJson(target, source);
614 source.clear();
615 return;
616 }
617 auto extendedInfoIt = errorIt->find(messages::messageAnnotation);
618 if (extendedInfoIt == errorIt->end())
619 {
620 return;
621 }
622 const nlohmann::json::array_t* extendedInfo =
623 (*extendedInfoIt).get_ptr<const nlohmann::json::array_t*>();
624 if (extendedInfo == nullptr)
625 {
626 source.erase(errorIt);
627 return;
628 }
629 for (const nlohmann::json& message : *extendedInfo)
630 {
631 addMessageToErrorJson(target, message);
632 }
633 source.erase(errorIt);
634}
635
636static void addMessageToJsonRoot(nlohmann::json& target,
637 const nlohmann::json& message)
638{
639 if (!target[messages::messageAnnotation].is_array())
640 {
641 // Force object to be an array
642 target[messages::messageAnnotation] = nlohmann::json::array();
643 }
644
645 target[messages::messageAnnotation].push_back(message);
646}
647
648static void addMessageToJson(nlohmann::json& target,
649 const nlohmann::json& message,
650 std::string_view fieldPath)
651{
652 std::string extendedInfo(fieldPath);
653 extendedInfo += messages::messageAnnotation;
654
655 nlohmann::json& field = target[extendedInfo];
656 if (!field.is_array())
657 {
658 // Force object to be an array
659 field = nlohmann::json::array();
660 }
661
662 // Object exists and it is an array so we can just push in the message
663 field.push_back(message);
664}
Ed Tanous7ccfe682024-11-16 14:36:16 -0800665"""
Ed Tanousf175c282024-12-02 15:12:50 -0800666 )
667 out.write(
668 """
669static nlohmann::json getLog(redfish::registries::{namespace_name}::Index name,
670 std::span<const std::string_view> args)
671{{
672 size_t index = static_cast<size_t>(name);
673 if (index >= redfish::registries::{namespace_name}::registry.size())
674 {{
675 return {{}};
676 }}
677 return getLogFromRegistry(redfish::registries::{namespace_name}::header,
678 redfish::registries::{namespace_name}::registry, index, args);
679}}
680
681""".format(
682 namespace_name=namespace_name
683 )
Ed Tanous7ccfe682024-11-16 14:36:16 -0800684 )
685 for entry_id, entry in messages.items():
686 out.write(
687 f"""/**
688 * @internal
689 * @brief Formats {entry_id} message into JSON
690 *
691 * See header file for more information
692 * @endinternal
693 */
694"""
695 )
696 message = entry["Message"]
Ed Tanousf175c282024-12-02 15:12:50 -0800697 out.write(
698 make_error_function(
699 entry_id, entry, False, registry_name, namespace_name
700 )
701 )
Ed Tanous7ccfe682024-11-16 14:36:16 -0800702
703 out.write(" }\n")
704 out.write("}\n")
705 os.system(f"clang-format -i {error_messages_hpp} {error_messages_cpp}")
Ed Tanous42079ec2024-11-16 13:32:29 -0800706
707
Ed Tanoused398212021-06-09 17:05:54 -0700708def make_privilege_registry():
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600709 path, json_file, type_name, url = make_getter(
Gunnar Mills5910d942024-04-16 12:07:17 -0500710 "Redfish_1.5.0_PrivilegeRegistry.json",
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600711 "privilege_registry.hpp",
712 "privilege",
713 )
714 with open(path, "w") as registry:
Nan Zhou043bec02022-09-20 18:12:13 +0000715 registry.write(PRIVILEGE_HEADER)
Ed Tanoused398212021-06-09 17:05:54 -0700716
717 privilege_dict = {}
718 for mapping in json_file["Mappings"]:
719 # first pass, identify all the unique privilege sets
720 for operation, privilege_list in mapping["OperationMap"].items():
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600721 privilege_dict[
722 get_privilege_string_from_list(privilege_list)
723 ] = (privilege_list,)
Ed Tanoused398212021-06-09 17:05:54 -0700724 for index, key in enumerate(privilege_dict):
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600725 (privilege_list,) = privilege_dict[key]
Ed Tanoused398212021-06-09 17:05:54 -0700726 name = get_variable_name_for_privilege_set(privilege_list)
Ed Tanousf395daa2021-08-02 08:56:24 -0700727 registry.write(
Ed Tanous5b9ef702022-02-17 12:19:32 -0800728 "const std::array<Privileges, {length}> "
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600729 "privilegeSet{name} = {key};\n".format(
730 length=len(privilege_list), name=name, key=key
731 )
Ed Tanous5b9ef702022-02-17 12:19:32 -0800732 )
Ed Tanoused398212021-06-09 17:05:54 -0700733 privilege_dict[key] = (privilege_list, name)
Ed Tanoused398212021-06-09 17:05:54 -0700734
735 for mapping in json_file["Mappings"]:
736 entity = mapping["Entity"]
Ed Tanous4d99bbb2022-02-17 10:02:57 -0800737 registry.write("// {}\n".format(entity))
Ed Tanoused398212021-06-09 17:05:54 -0700738 for operation, privilege_list in mapping["OperationMap"].items():
739 privilege_string = get_privilege_string_from_list(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600740 privilege_list
741 )
Ed Tanoused398212021-06-09 17:05:54 -0700742 operation = operation.lower()
743
Ed Tanousf395daa2021-08-02 08:56:24 -0700744 registry.write(
745 "const static auto& {}{} = privilegeSet{};\n".format(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600746 operation, entity, privilege_dict[privilege_string][1]
747 )
748 )
Ed Tanoused398212021-06-09 17:05:54 -0700749 registry.write("\n")
Ed Tanous5b9ef702022-02-17 12:19:32 -0800750 registry.write(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600751 "} // namespace redfish::privileges\n// clang-format on\n"
752 )
Ed Tanoused398212021-06-09 17:05:54 -0700753
754
Gunnar Mills665e7602024-04-10 13:14:41 -0500755def to_pascal_case(text):
756 s = text.replace("_", " ")
757 s = s.split()
758 if len(text) == 0:
759 return text
760 return "".join(i.capitalize() for i in s[0:])
761
762
Nan Zhou49aa131f2022-09-20 18:41:37 +0000763def main():
Gunnar Mills665e7602024-04-10 13:14:41 -0500764 dmtf_registries = (
Jishnu CMb575cae2024-10-01 01:33:49 -0500765 ("base", "1.19.0"),
Gunnar Mills665e7602024-04-10 13:14:41 -0500766 ("composition", "1.1.2"),
767 ("environmental", "1.0.1"),
768 ("ethernet_fabric", "1.0.1"),
769 ("fabric", "1.0.2"),
770 ("heartbeat_event", "1.0.1"),
771 ("job_event", "1.0.1"),
772 ("license", "1.0.3"),
773 ("log_service", "1.0.1"),
774 ("network_device", "1.0.3"),
775 ("platform", "1.0.1"),
776 ("power", "1.0.1"),
777 ("resource_event", "1.3.0"),
778 ("sensor_event", "1.0.1"),
779 ("storage_device", "1.2.1"),
780 ("task_event", "1.0.3"),
781 ("telemetry", "1.0.0"),
782 ("update", "1.0.2"),
783 )
784
Nan Zhou49aa131f2022-09-20 18:41:37 +0000785 parser = argparse.ArgumentParser()
786 parser.add_argument(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600787 "--registries",
788 type=str,
Gunnar Mills665e7602024-04-10 13:14:41 -0500789 default="privilege,openbmc,"
790 + ",".join([dmtf[0] for dmtf in dmtf_registries]),
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600791 help="Comma delimited list of registries to update",
792 )
Nan Zhou49aa131f2022-09-20 18:41:37 +0000793
794 args = parser.parse_args()
795
796 registries = set(args.registries.split(","))
797 files = []
798
Gunnar Mills665e7602024-04-10 13:14:41 -0500799 for registry, version in dmtf_registries:
800 if registry in registries:
801 registry_pascal_case = to_pascal_case(registry)
802 files.append(
803 make_getter(
804 f"{registry_pascal_case}.{version}.json",
805 f"{registry}_message_registry.hpp",
806 registry,
807 )
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600808 )
Ed Tanous3e5faba2023-08-16 15:11:29 -0700809 if "openbmc" in registries:
810 files.append(openbmc_local_getter())
Nan Zhou49aa131f2022-09-20 18:41:37 +0000811
812 update_registries(files)
813
Ed Tanousf175c282024-12-02 15:12:50 -0800814 create_error_registry(
815 files[0], dmtf_registries[0][1], "Base", "base", "error"
816 )
817 create_error_registry(
818 files[15], dmtf_registries[15][1], "TaskEvent", "task_event", "task"
819 )
Ed Tanous42079ec2024-11-16 13:32:29 -0800820
Nan Zhou49aa131f2022-09-20 18:41:37 +0000821 if "privilege" in registries:
822 make_privilege_registry()
823
824
825if __name__ == "__main__":
826 main()