blob: ceb781f66e72f585da524a485438e3ed33f9e46c [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():
57 url = ""
58 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:
Nan Zhou49aa131f2022-09-20 18:41:37 +000084 registry.write(REGISTRY_HEADER.format(namespace))
85 # Parse the Registry header info
Ed Tanous5b9ef702022-02-17 12:19:32 -080086 registry.write(
Nan Zhou49aa131f2022-09-20 18:41:37 +000087 "const Header header = {{\n"
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -060088 ' "{json_dict[@Redfish.Copyright]}",\n'
89 ' "{json_dict[@odata.type]}",\n'
90 ' "{json_dict[Id]}",\n'
91 ' "{json_dict[Name]}",\n'
92 ' "{json_dict[Language]}",\n'
93 ' "{json_dict[Description]}",\n'
94 ' "{json_dict[RegistryPrefix]}",\n'
95 ' "{json_dict[RegistryVersion]}",\n'
96 ' "{json_dict[OwningEntity]}",\n'
Nan Zhou49aa131f2022-09-20 18:41:37 +000097 "}};\n"
98 "constexpr const char* url =\n"
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -060099 ' "{url}";\n'
Nan Zhou49aa131f2022-09-20 18:41:37 +0000100 "\n"
101 "constexpr std::array registry =\n"
102 "{{\n".format(
103 json_dict=json_dict,
104 url=url,
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600105 )
106 )
Ed Tanous30a3c432022-02-07 09:37:21 -0800107
Nan Zhou49aa131f2022-09-20 18:41:37 +0000108 messages_sorted = sorted(json_dict["Messages"].items())
109 for messageId, message in messages_sorted:
110 registry.write(
111 " MessageEntry{{\n"
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600112 ' "{messageId}",\n'
Nan Zhou49aa131f2022-09-20 18:41:37 +0000113 " {{\n"
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600114 ' "{message[Description]}",\n'
115 ' "{message[Message]}",\n'
116 ' "{message[MessageSeverity]}",\n'
Nan Zhou49aa131f2022-09-20 18:41:37 +0000117 " {message[NumberOfArgs]},\n"
118 " {{".format(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600119 messageId=messageId, message=message
120 )
121 )
Nan Zhou49aa131f2022-09-20 18:41:37 +0000122 paramTypes = message.get("ParamTypes")
123 if paramTypes:
124 for paramType in paramTypes:
125 registry.write(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600126 '\n "{}",'.format(paramType)
Nan Zhou49aa131f2022-09-20 18:41:37 +0000127 )
128 registry.write("\n },\n")
129 else:
130 registry.write("},\n")
131 registry.write(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600132 ' "{message[Resolution]}",\n'
133 " }}}},\n".format(message=message)
134 )
Nan Zhou49aa131f2022-09-20 18:41:37 +0000135
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600136 registry.write("\n};\n\nenum class Index\n{\n")
Nan Zhou49aa131f2022-09-20 18:41:37 +0000137 for index, (messageId, message) in enumerate(messages_sorted):
138 messageId = messageId[0].lower() + messageId[1:]
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600139 registry.write(" {} = {},\n".format(messageId, index))
Nan Zhou49aa131f2022-09-20 18:41:37 +0000140 registry.write(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600141 "}};\n}} // namespace redfish::registries::{}\n".format(
142 namespace
143 )
144 )
Ed Tanoused398212021-06-09 17:05:54 -0700145
146
147def get_privilege_string_from_list(privilege_list):
148 privilege_string = "{{\n"
149 for privilege_json in privilege_list:
150 privileges = privilege_json["Privilege"]
151 privilege_string += " {"
152 for privilege in privileges:
153 if privilege == "NoAuth":
154 continue
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600155 privilege_string += '"'
Ed Tanoused398212021-06-09 17:05:54 -0700156 privilege_string += privilege
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600157 privilege_string += '",\n'
Ed Tanoused398212021-06-09 17:05:54 -0700158 if privilege != "NoAuth":
159 privilege_string = privilege_string[:-2]
160 privilege_string += "}"
161 privilege_string += ",\n"
162 privilege_string = privilege_string[:-2]
163 privilege_string += "\n}}"
164 return privilege_string
165
Ed Tanousf395daa2021-08-02 08:56:24 -0700166
Ed Tanoused398212021-06-09 17:05:54 -0700167def get_variable_name_for_privilege_set(privilege_list):
168 names = []
169 for privilege_json in privilege_list:
170 privileges = privilege_json["Privilege"]
171 names.append("And".join(privileges))
172 return "Or".join(names)
173
Ed Tanousf395daa2021-08-02 08:56:24 -0700174
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600175PRIVILEGE_HEADER = (
176 PRAGMA_ONCE
177 + WARNING
178 + """
Nan Zhou01c78a02022-09-20 18:17:20 +0000179#include "privileges.hpp"
180
181#include <array>
Nan Zhou043bec02022-09-20 18:12:13 +0000182
183// clang-format off
184
185namespace redfish::privileges
186{
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600187"""
188)
Nan Zhou043bec02022-09-20 18:12:13 +0000189
190
Ed Tanous7ccfe682024-11-16 14:36:16 -0800191def get_response_code(entry_id, entry):
192 codes = {
193 "InternalError": "internal_server_error",
194 "OperationTimeout": "internal_server_error",
195 "PropertyValueResourceConflict": "conflict",
196 "ResourceInUse": "service_unavailable",
197 "ServiceTemporarilyUnavailable": "service_unavailable",
198 "ResourceCannotBeDeleted": "method_not_allowed",
199 "PropertyValueModified": "ok",
200 "InsufficientPrivilege": "forbidden",
201 "AccountForSessionNoLongerExists": "forbidden",
202 "ServiceDisabled": "service_unavailable",
203 "ServiceInUnknownState": "service_unavailable",
204 "EventSubscriptionLimitExceeded": "service_unavailable",
205 "ResourceAtUriUnauthorized": "unauthorized",
206 "SessionTerminated": "ok",
207 "SubscriptionTerminated": "ok",
208 "PropertyNotWritable": "forbidden",
209 "MaximumErrorsExceeded": "internal_server_error",
210 "GeneralError": "internal_server_error",
211 "PreconditionFailed": "precondition_failed",
212 "OperationFailed": "bad_gateway",
213 "ServiceShuttingDown": "service_unavailable",
214 "AccountRemoved": "ok",
215 "PropertyValueExternalConflict": "conflict",
216 "InsufficientStorage": "insufficient_storage",
217 "OperationNotAllowed": "method_not_allowed",
218 "ResourceNotFound": "not_found",
219 "CouldNotEstablishConnection": "not_found",
220 "AccessDenied": "forbidden",
221 "Success": None,
222 "Created": "created",
223 "NoValidSession": "forbidden",
224 "SessionLimitExceeded": "service_unavailable",
225 "ResourceExhaustion": "service_unavailable",
226 "AccountModified": "ok",
227 "PasswordChangeRequired": None,
228 "ResourceInStandby": "service_unavailable",
229 "GenerateSecretKeyRequired": "forbidden",
230 }
231
232 code = codes.get(entry_id, "NOCODE")
233 if code != "NOCODE":
234 return code
235
236 return "bad_request"
237
238
Ed Tanous7ccfe682024-11-16 14:36:16 -0800239def make_error_function(entry_id, entry, is_header):
Ed Tanous644cdcb2024-11-17 11:12:41 -0800240 arg_nonstring_types = {
241 "const boost::urls::url_view_base&": {
242 "AccessDenied": [1],
243 "CouldNotEstablishConnection": [1],
244 "GenerateSecretKeyRequired": [1],
245 "InvalidObject": [1],
246 "PasswordChangeRequired": [1],
247 "PropertyValueResourceConflict": [3],
248 "ResetRequired": [1],
249 "ResourceAtUriInUnknownFormat": [1],
250 "ResourceAtUriUnauthorized": [1],
251 "ResourceCreationConflict": [1],
252 "ResourceMissingAtURI": [1],
253 "SourceDoesNotSupportProtocol": [1],
254 },
255 "const nlohmann::json&": {
256 "ActionParameterValueError": [1],
257 "ActionParameterValueFormatError": [1],
258 "ActionParameterValueTypeError": [1],
259 "PropertyValueExternalConflict": [2],
260 "PropertyValueFormatError": [1],
261 "PropertyValueIncorrect": [2],
262 "PropertyValueModified": [2],
263 "PropertyValueNotInList": [1],
264 "PropertyValueOutOfRange": [1],
265 "PropertyValueResourceConflict": [2],
266 "PropertyValueTypeError": [1],
267 "QueryParameterValueFormatError": [1],
268 "QueryParameterValueTypeError": [1],
269 },
270 "uint64_t": {
271 "ArraySizeTooLong": [2],
272 "InvalidIndex": [1],
273 "StringValueTooLong": [2],
274 },
Ed Tanous42079ec2024-11-16 13:32:29 -0800275 }
276
Ed Tanous7ccfe682024-11-16 14:36:16 -0800277 out = ""
278 args = []
279 argtypes = []
280 for arg_index, arg in enumerate(entry.get("ParamTypes", [])):
281 arg_index += 1
Ed Tanous644cdcb2024-11-17 11:12:41 -0800282 typename = "std::string_view"
283 for typestring, entries in arg_nonstring_types.items():
284 if arg_index in entries.get(entry_id, []):
285 typename = typestring
286
Ed Tanous7ccfe682024-11-16 14:36:16 -0800287 argtypes.append(typename)
288 args.append(f"{typename} arg{arg_index}")
289 function_name = entry_id[0].lower() + entry_id[1:]
290 arg = ", ".join(args)
291 out += f"nlohmann::json {function_name}({arg})"
292
293 if is_header:
294 out += ";\n\n"
295 else:
296 out += "\n{\n"
297 to_array_type = ""
298 if argtypes:
299 outargs = []
300 for index, typename in enumerate(argtypes):
301 index += 1
302 if typename == "const nlohmann::json&":
303 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 -0800304 elif typename == "uint64_t":
Ed Tanous7ccfe682024-11-16 14:36:16 -0800305 out += f"std::string arg{index}Str = std::to_string(arg{index});\n"
306
307 for index, typename in enumerate(argtypes):
308 index += 1
309 if typename == "const boost::urls::url_view_base&":
310 outargs.append(f"arg{index}.buffer()")
311 to_array_type = "<std::string_view>"
312 elif typename == "const nlohmann::json&":
313 outargs.append(f"arg{index}Str")
314 to_array_type = "<std::string_view>"
Ed Tanous644cdcb2024-11-17 11:12:41 -0800315 elif typename == "uint64_t":
Ed Tanous7ccfe682024-11-16 14:36:16 -0800316 outargs.append(f"arg{index}Str")
317 to_array_type = "<std::string_view>"
318 else:
319 outargs.append(f"arg{index}")
320 argstring = ", ".join(outargs)
Ed Tanous7ccfe682024-11-16 14:36:16 -0800321
322 if argtypes:
323 arg_param = f"std::to_array{to_array_type}({{{argstring}}})"
324 else:
325 arg_param = "{}"
326 out += f" return getLog(redfish::registries::base::Index::{function_name}, {arg_param});"
327 out += "\n}\n\n"
328 args.insert(0, "crow::Response& res")
329 if entry_id == "InternalError":
330 if is_header:
331 args.append(
332 "std::source_location location = std::source_location::current()"
333 )
334 else:
335 args.append("const std::source_location location")
336 arg = ", ".join(args)
337 out += f"void {function_name}({arg})"
338 if is_header:
339 out += ";\n"
340 else:
341 out += "\n{\n"
342 if entry_id == "InternalError":
343 out += """BMCWEB_LOG_CRITICAL("Internal Error {}({}:{}) `{}`: ", location.file_name(),
344 location.line(), location.column(),
345 location.function_name());\n"""
346
347 if entry_id == "ServiceTemporarilyUnavailable":
348 out += (
349 "res.addHeader(boost::beast::http::field::retry_after, arg1);"
350 )
351
352 res = get_response_code(entry_id, entry)
353 if res:
354 out += f" res.result(boost::beast::http::status::{res});\n"
355 args_out = ", ".join([f"arg{x+1}" for x in range(len(argtypes))])
356
357 addMessageToJson = {
358 "PropertyDuplicate": 1,
359 "ResourceAlreadyExists": 2,
360 "CreateFailedMissingReqProperties": 1,
361 "PropertyValueFormatError": 2,
362 "PropertyValueNotInList": 2,
363 "PropertyValueTypeError": 2,
364 "PropertyValueError": 1,
365 "PropertyNotWritable": 1,
366 "PropertyValueModified": 1,
367 "PropertyMissing": 1,
368 }
369
370 addMessageToRoot = [
371 "SessionTerminated",
372 "SubscriptionTerminated",
373 "AccountRemoved",
374 "Created",
375 "Success",
376 "PasswordChangeRequired",
377 ]
378
379 if entry_id in addMessageToJson:
380 out += f" addMessageToJson(res.jsonValue, {function_name}({args_out}), arg{addMessageToJson[entry_id]});\n"
381 elif entry_id in addMessageToRoot:
382 out += f" addMessageToJsonRoot(res.jsonValue, {function_name}({args_out}));\n"
383 else:
384 out += f" addMessageToErrorJson(res.jsonValue, {function_name}({args_out}));\n"
385 out += "}\n"
386 out += "\n"
387 return out
388
389
390def create_error_registry(entry):
Ed Tanous42079ec2024-11-16 13:32:29 -0800391 file, json_dict, namespace, url = entry
392
Ed Tanous42079ec2024-11-16 13:32:29 -0800393 error_messages_hpp = os.path.join(
394 SCRIPT_DIR, "..", "redfish-core", "include", "error_messages.hpp"
395 )
Ed Tanousf8cca872024-11-16 22:47:34 -0800396 messages = json_dict["Messages"]
397
Ed Tanous42079ec2024-11-16 13:32:29 -0800398 with open(
399 error_messages_hpp,
400 "w",
401 ) as out:
402 out.write(PRAGMA_ONCE)
403 out.write(WARNING)
404 out.write(
405 """
406
407#include "http_response.hpp"
408
409#include <boost/url/url_view_base.hpp>
410#include <nlohmann/json.hpp>
411
412#include <cstdint>
413#include <source_location>
414#include <string>
415#include <string_view>
416
417// IWYU pragma: no_forward_declare crow::Response
418
419namespace redfish
420{
421
422namespace messages
423{
424
425 constexpr const char* messageVersionPrefix = "Base.1.11.0.";
426 constexpr const char* messageAnnotation = "@Message.ExtendedInfo";
427
428 /**
429 * @brief Moves all error messages from the |source| JSON to |target|
430 */
431 void moveErrorsToErrorJson(nlohmann::json& target, nlohmann::json& source);
432
433"""
434 )
435
436 for entry_id, entry in messages.items():
437 message = entry["Message"]
438 for index in range(1, 10):
439 message = message.replace(f"'%{index}'", f"<arg{index}>")
440 message = message.replace(f"%{index}", f"<arg{index}>")
441
442 out.write("/**\n")
443 out.write(f"* @brief Formats {entry_id} message into JSON\n")
444 out.write(f'* Message body: "{message}"\n')
445 out.write("*\n")
446 arg_index = 0
447 for arg_index, arg in enumerate(entry.get("ParamTypes", [])):
448 arg_index += 1
449
450 out.write(
451 f"* @param[in] arg{arg_index} Parameter of message that will replace %{arg_index} in its body.\n"
452 )
453 out.write("*\n")
454 out.write(f"* @returns Message {entry_id} formatted to JSON */\n")
455
Ed Tanous7ccfe682024-11-16 14:36:16 -0800456 out.write(make_error_function(entry_id, entry, True))
Ed Tanous42079ec2024-11-16 13:32:29 -0800457 out.write(" }\n")
458 out.write("}\n")
Ed Tanous7ccfe682024-11-16 14:36:16 -0800459
460 error_messages_cpp = os.path.join(
461 SCRIPT_DIR, "..", "redfish-core", "src", "error_messages.cpp"
462 )
463 with open(
464 error_messages_cpp,
465 "w",
466 ) as out:
467 out.write(WARNING)
468 out.write(
469 """
470#include "error_messages.hpp"
471
472#include "http_response.hpp"
473#include "logging.hpp"
474#include "registries.hpp"
475#include "registries/base_message_registry.hpp"
476
477#include <boost/beast/http/field.hpp>
478#include <boost/beast/http/status.hpp>
479#include <boost/url/url_view_base.hpp>
480#include <nlohmann/json.hpp>
481
482#include <array>
483#include <cstddef>
484#include <cstdint>
485#include <source_location>
486#include <span>
487#include <string>
488#include <string_view>
489
490// Clang can't seem to decide whether this header needs to be included or not,
491// and is inconsistent. Include it for now
492// NOLINTNEXTLINE(misc-include-cleaner)
493#include <utility>
494
495namespace redfish
496{
497
498namespace messages
499{
500
501static void addMessageToErrorJson(nlohmann::json& target,
502 const nlohmann::json& message)
503{
504 auto& error = target["error"];
505
506 // If this is the first error message, fill in the information from the
507 // first error message to the top level struct
508 if (!error.is_object())
509 {
510 auto messageIdIterator = message.find("MessageId");
511 if (messageIdIterator == message.end())
512 {
513 BMCWEB_LOG_CRITICAL(
514 "Attempt to add error message without MessageId");
515 return;
516 }
517
518 auto messageFieldIterator = message.find("Message");
519 if (messageFieldIterator == message.end())
520 {
521 BMCWEB_LOG_CRITICAL("Attempt to add error message without Message");
522 return;
523 }
524 error["code"] = *messageIdIterator;
525 error["message"] = *messageFieldIterator;
526 }
527 else
528 {
529 // More than 1 error occurred, so the message has to be generic
530 error["code"] = std::string(messageVersionPrefix) + "GeneralError";
531 error["message"] = "A general error has occurred. See Resolution for "
532 "information on how to resolve the error.";
533 }
534
535 // This check could technically be done in the default construction
536 // branch above, but because we need the pointer to the extended info field
537 // anyway, it's more efficient to do it here.
538 auto& extendedInfo = error[messages::messageAnnotation];
539 if (!extendedInfo.is_array())
540 {
541 extendedInfo = nlohmann::json::array();
542 }
543
544 extendedInfo.push_back(message);
545}
546
547void moveErrorsToErrorJson(nlohmann::json& target, nlohmann::json& source)
548{
549 if (!source.is_object())
550 {
551 return;
552 }
553 auto errorIt = source.find("error");
554 if (errorIt == source.end())
555 {
556 // caller puts error message in root
557 messages::addMessageToErrorJson(target, source);
558 source.clear();
559 return;
560 }
561 auto extendedInfoIt = errorIt->find(messages::messageAnnotation);
562 if (extendedInfoIt == errorIt->end())
563 {
564 return;
565 }
566 const nlohmann::json::array_t* extendedInfo =
567 (*extendedInfoIt).get_ptr<const nlohmann::json::array_t*>();
568 if (extendedInfo == nullptr)
569 {
570 source.erase(errorIt);
571 return;
572 }
573 for (const nlohmann::json& message : *extendedInfo)
574 {
575 addMessageToErrorJson(target, message);
576 }
577 source.erase(errorIt);
578}
579
580static void addMessageToJsonRoot(nlohmann::json& target,
581 const nlohmann::json& message)
582{
583 if (!target[messages::messageAnnotation].is_array())
584 {
585 // Force object to be an array
586 target[messages::messageAnnotation] = nlohmann::json::array();
587 }
588
589 target[messages::messageAnnotation].push_back(message);
590}
591
592static void addMessageToJson(nlohmann::json& target,
593 const nlohmann::json& message,
594 std::string_view fieldPath)
595{
596 std::string extendedInfo(fieldPath);
597 extendedInfo += messages::messageAnnotation;
598
599 nlohmann::json& field = target[extendedInfo];
600 if (!field.is_array())
601 {
602 // Force object to be an array
603 field = nlohmann::json::array();
604 }
605
606 // Object exists and it is an array so we can just push in the message
607 field.push_back(message);
608}
609
610static nlohmann::json getLog(redfish::registries::base::Index name,
611 std::span<const std::string_view> args)
612{
613 size_t index = static_cast<size_t>(name);
614 if (index >= redfish::registries::base::registry.size())
615 {
616 return {};
617 }
618 return getLogFromRegistry(redfish::registries::base::header,
619 redfish::registries::base::registry, index, args);
620}
621
622"""
623 )
624 for entry_id, entry in messages.items():
625 out.write(
626 f"""/**
627 * @internal
628 * @brief Formats {entry_id} message into JSON
629 *
630 * See header file for more information
631 * @endinternal
632 */
633"""
634 )
635 message = entry["Message"]
636 out.write(make_error_function(entry_id, entry, False))
637
638 out.write(" }\n")
639 out.write("}\n")
640 os.system(f"clang-format -i {error_messages_hpp} {error_messages_cpp}")
Ed Tanous42079ec2024-11-16 13:32:29 -0800641
642
Ed Tanoused398212021-06-09 17:05:54 -0700643def make_privilege_registry():
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600644 path, json_file, type_name, url = make_getter(
Gunnar Mills5910d942024-04-16 12:07:17 -0500645 "Redfish_1.5.0_PrivilegeRegistry.json",
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600646 "privilege_registry.hpp",
647 "privilege",
648 )
649 with open(path, "w") as registry:
Nan Zhou043bec02022-09-20 18:12:13 +0000650 registry.write(PRIVILEGE_HEADER)
Ed Tanoused398212021-06-09 17:05:54 -0700651
652 privilege_dict = {}
653 for mapping in json_file["Mappings"]:
654 # first pass, identify all the unique privilege sets
655 for operation, privilege_list in mapping["OperationMap"].items():
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600656 privilege_dict[
657 get_privilege_string_from_list(privilege_list)
658 ] = (privilege_list,)
Ed Tanoused398212021-06-09 17:05:54 -0700659 for index, key in enumerate(privilege_dict):
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600660 (privilege_list,) = privilege_dict[key]
Ed Tanoused398212021-06-09 17:05:54 -0700661 name = get_variable_name_for_privilege_set(privilege_list)
Ed Tanousf395daa2021-08-02 08:56:24 -0700662 registry.write(
Ed Tanous5b9ef702022-02-17 12:19:32 -0800663 "const std::array<Privileges, {length}> "
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600664 "privilegeSet{name} = {key};\n".format(
665 length=len(privilege_list), name=name, key=key
666 )
Ed Tanous5b9ef702022-02-17 12:19:32 -0800667 )
Ed Tanoused398212021-06-09 17:05:54 -0700668 privilege_dict[key] = (privilege_list, name)
Ed Tanoused398212021-06-09 17:05:54 -0700669
670 for mapping in json_file["Mappings"]:
671 entity = mapping["Entity"]
Ed Tanous4d99bbb2022-02-17 10:02:57 -0800672 registry.write("// {}\n".format(entity))
Ed Tanoused398212021-06-09 17:05:54 -0700673 for operation, privilege_list in mapping["OperationMap"].items():
674 privilege_string = get_privilege_string_from_list(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600675 privilege_list
676 )
Ed Tanoused398212021-06-09 17:05:54 -0700677 operation = operation.lower()
678
Ed Tanousf395daa2021-08-02 08:56:24 -0700679 registry.write(
680 "const static auto& {}{} = privilegeSet{};\n".format(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600681 operation, entity, privilege_dict[privilege_string][1]
682 )
683 )
Ed Tanoused398212021-06-09 17:05:54 -0700684 registry.write("\n")
Ed Tanous5b9ef702022-02-17 12:19:32 -0800685 registry.write(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600686 "} // namespace redfish::privileges\n// clang-format on\n"
687 )
Ed Tanoused398212021-06-09 17:05:54 -0700688
689
Gunnar Mills665e7602024-04-10 13:14:41 -0500690def to_pascal_case(text):
691 s = text.replace("_", " ")
692 s = s.split()
693 if len(text) == 0:
694 return text
695 return "".join(i.capitalize() for i in s[0:])
696
697
Nan Zhou49aa131f2022-09-20 18:41:37 +0000698def main():
Gunnar Mills665e7602024-04-10 13:14:41 -0500699 dmtf_registries = (
Jishnu CMb575cae2024-10-01 01:33:49 -0500700 ("base", "1.19.0"),
Gunnar Mills665e7602024-04-10 13:14:41 -0500701 ("composition", "1.1.2"),
702 ("environmental", "1.0.1"),
703 ("ethernet_fabric", "1.0.1"),
704 ("fabric", "1.0.2"),
705 ("heartbeat_event", "1.0.1"),
706 ("job_event", "1.0.1"),
707 ("license", "1.0.3"),
708 ("log_service", "1.0.1"),
709 ("network_device", "1.0.3"),
710 ("platform", "1.0.1"),
711 ("power", "1.0.1"),
712 ("resource_event", "1.3.0"),
713 ("sensor_event", "1.0.1"),
714 ("storage_device", "1.2.1"),
715 ("task_event", "1.0.3"),
716 ("telemetry", "1.0.0"),
717 ("update", "1.0.2"),
718 )
719
Nan Zhou49aa131f2022-09-20 18:41:37 +0000720 parser = argparse.ArgumentParser()
721 parser.add_argument(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600722 "--registries",
723 type=str,
Gunnar Mills665e7602024-04-10 13:14:41 -0500724 default="privilege,openbmc,"
725 + ",".join([dmtf[0] for dmtf in dmtf_registries]),
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600726 help="Comma delimited list of registries to update",
727 )
Nan Zhou49aa131f2022-09-20 18:41:37 +0000728
729 args = parser.parse_args()
730
731 registries = set(args.registries.split(","))
732 files = []
733
Gunnar Mills665e7602024-04-10 13:14:41 -0500734 for registry, version in dmtf_registries:
735 if registry in registries:
736 registry_pascal_case = to_pascal_case(registry)
737 files.append(
738 make_getter(
739 f"{registry_pascal_case}.{version}.json",
740 f"{registry}_message_registry.hpp",
741 registry,
742 )
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600743 )
Ed Tanous3e5faba2023-08-16 15:11:29 -0700744 if "openbmc" in registries:
745 files.append(openbmc_local_getter())
Nan Zhou49aa131f2022-09-20 18:41:37 +0000746
747 update_registries(files)
748
Ed Tanous42079ec2024-11-16 13:32:29 -0800749 create_error_registry(files[0])
750
Nan Zhou49aa131f2022-09-20 18:41:37 +0000751 if "privilege" in registries:
752 make_privilege_registry()
753
754
755if __name__ == "__main__":
756 main()