blob: a7eb5bf93249293400b9b3b260c690c7dabdceb4 [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 Tanous42079ec2024-11-16 13:32:29 -0800240
241 arg_as_url = {
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
256 arg_as_json = {
257 "ActionParameterValueError": [1],
258 "ActionParameterValueFormatError": [1],
259 "ActionParameterValueTypeError": [1],
260 "PropertyValueExternalConflict": [2],
261 "PropertyValueFormatError": [1],
262 "PropertyValueIncorrect": [2],
263 "PropertyValueModified": [2],
264 "PropertyValueNotInList": [1],
265 "PropertyValueOutOfRange": [1],
266 "PropertyValueResourceConflict": [2],
267 "PropertyValueTypeError": [1],
268 "QueryParameterValueFormatError": [1],
269 "QueryParameterValueTypeError": [1],
270 }
271
272 arg_as_int = {
273 "StringValueTooLong": [2],
274 }
275
276 arg_as_uint64 = {
277 "ArraySizeTooLong": [2],
278 }
279 arg_as_int64 = {
280 "InvalidIndex": [1],
281 }
282
Ed Tanous7ccfe682024-11-16 14:36:16 -0800283 out = ""
284 args = []
285 argtypes = []
286 for arg_index, arg in enumerate(entry.get("ParamTypes", [])):
287 arg_index += 1
288 if arg_index in arg_as_url.get(entry_id, []):
289 typename = "const boost::urls::url_view_base&"
290 elif arg_index in arg_as_json.get(entry_id, []):
291 typename = "const nlohmann::json&"
292 elif arg_index in arg_as_int.get(entry_id, []):
293 typename = "int"
294 elif arg_index in arg_as_uint64.get(entry_id, []):
295 typename = "uint64_t"
296 elif arg_index in arg_as_int64.get(entry_id, []):
297 typename = "int64_t"
298 else:
299 typename = "std::string_view"
300 argtypes.append(typename)
301 args.append(f"{typename} arg{arg_index}")
302 function_name = entry_id[0].lower() + entry_id[1:]
303 arg = ", ".join(args)
304 out += f"nlohmann::json {function_name}({arg})"
305
306 if is_header:
307 out += ";\n\n"
308 else:
309 out += "\n{\n"
310 to_array_type = ""
311 if argtypes:
312 outargs = []
313 for index, typename in enumerate(argtypes):
314 index += 1
315 if typename == "const nlohmann::json&":
316 out += f"std::string arg{index}Str = arg{index}.dump(-1, ' ', true, nlohmann::json::error_handler_t::replace);\n"
317 elif typename in ("int64_t", "int", "uint64_t"):
318 out += f"std::string arg{index}Str = std::to_string(arg{index});\n"
319
320 for index, typename in enumerate(argtypes):
321 index += 1
322 if typename == "const boost::urls::url_view_base&":
323 outargs.append(f"arg{index}.buffer()")
324 to_array_type = "<std::string_view>"
325 elif typename == "const nlohmann::json&":
326 outargs.append(f"arg{index}Str")
327 to_array_type = "<std::string_view>"
328 elif typename in ("int64_t", "int", "uint64_t"):
329 outargs.append(f"arg{index}Str")
330 to_array_type = "<std::string_view>"
331 else:
332 outargs.append(f"arg{index}")
333 argstring = ", ".join(outargs)
334 # out += f" std::array<std::string_view, {len(argtypes)}> args{{{argstring}}};\n"
335
336 if argtypes:
337 arg_param = f"std::to_array{to_array_type}({{{argstring}}})"
338 else:
339 arg_param = "{}"
340 out += f" return getLog(redfish::registries::base::Index::{function_name}, {arg_param});"
341 out += "\n}\n\n"
342 args.insert(0, "crow::Response& res")
343 if entry_id == "InternalError":
344 if is_header:
345 args.append(
346 "std::source_location location = std::source_location::current()"
347 )
348 else:
349 args.append("const std::source_location location")
350 arg = ", ".join(args)
351 out += f"void {function_name}({arg})"
352 if is_header:
353 out += ";\n"
354 else:
355 out += "\n{\n"
356 if entry_id == "InternalError":
357 out += """BMCWEB_LOG_CRITICAL("Internal Error {}({}:{}) `{}`: ", location.file_name(),
358 location.line(), location.column(),
359 location.function_name());\n"""
360
361 if entry_id == "ServiceTemporarilyUnavailable":
362 out += (
363 "res.addHeader(boost::beast::http::field::retry_after, arg1);"
364 )
365
366 res = get_response_code(entry_id, entry)
367 if res:
368 out += f" res.result(boost::beast::http::status::{res});\n"
369 args_out = ", ".join([f"arg{x+1}" for x in range(len(argtypes))])
370
371 addMessageToJson = {
372 "PropertyDuplicate": 1,
373 "ResourceAlreadyExists": 2,
374 "CreateFailedMissingReqProperties": 1,
375 "PropertyValueFormatError": 2,
376 "PropertyValueNotInList": 2,
377 "PropertyValueTypeError": 2,
378 "PropertyValueError": 1,
379 "PropertyNotWritable": 1,
380 "PropertyValueModified": 1,
381 "PropertyMissing": 1,
382 }
383
384 addMessageToRoot = [
385 "SessionTerminated",
386 "SubscriptionTerminated",
387 "AccountRemoved",
388 "Created",
389 "Success",
390 "PasswordChangeRequired",
391 ]
392
393 if entry_id in addMessageToJson:
394 out += f" addMessageToJson(res.jsonValue, {function_name}({args_out}), arg{addMessageToJson[entry_id]});\n"
395 elif entry_id in addMessageToRoot:
396 out += f" addMessageToJsonRoot(res.jsonValue, {function_name}({args_out}));\n"
397 else:
398 out += f" addMessageToErrorJson(res.jsonValue, {function_name}({args_out}));\n"
399 out += "}\n"
400 out += "\n"
401 return out
402
403
404def create_error_registry(entry):
Ed Tanous42079ec2024-11-16 13:32:29 -0800405 file, json_dict, namespace, url = entry
406
Ed Tanous42079ec2024-11-16 13:32:29 -0800407 error_messages_hpp = os.path.join(
408 SCRIPT_DIR, "..", "redfish-core", "include", "error_messages.hpp"
409 )
Ed Tanousf8cca872024-11-16 22:47:34 -0800410 messages = json_dict["Messages"]
411
Ed Tanous42079ec2024-11-16 13:32:29 -0800412 with open(
413 error_messages_hpp,
414 "w",
415 ) as out:
416 out.write(PRAGMA_ONCE)
417 out.write(WARNING)
418 out.write(
419 """
420
421#include "http_response.hpp"
422
423#include <boost/url/url_view_base.hpp>
424#include <nlohmann/json.hpp>
425
426#include <cstdint>
427#include <source_location>
428#include <string>
429#include <string_view>
430
431// IWYU pragma: no_forward_declare crow::Response
432
433namespace redfish
434{
435
436namespace messages
437{
438
439 constexpr const char* messageVersionPrefix = "Base.1.11.0.";
440 constexpr const char* messageAnnotation = "@Message.ExtendedInfo";
441
442 /**
443 * @brief Moves all error messages from the |source| JSON to |target|
444 */
445 void moveErrorsToErrorJson(nlohmann::json& target, nlohmann::json& source);
446
447"""
448 )
449
450 for entry_id, entry in messages.items():
451 message = entry["Message"]
452 for index in range(1, 10):
453 message = message.replace(f"'%{index}'", f"<arg{index}>")
454 message = message.replace(f"%{index}", f"<arg{index}>")
455
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
463
464 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")
468 out.write(f"* @returns Message {entry_id} formatted to JSON */\n")
469
Ed Tanous7ccfe682024-11-16 14:36:16 -0800470 out.write(make_error_function(entry_id, entry, True))
Ed Tanous42079ec2024-11-16 13:32:29 -0800471 out.write(" }\n")
472 out.write("}\n")
Ed Tanous7ccfe682024-11-16 14:36:16 -0800473
474 error_messages_cpp = os.path.join(
475 SCRIPT_DIR, "..", "redfish-core", "src", "error_messages.cpp"
476 )
477 with open(
478 error_messages_cpp,
479 "w",
480 ) as out:
481 out.write(WARNING)
482 out.write(
483 """
484#include "error_messages.hpp"
485
486#include "http_response.hpp"
487#include "logging.hpp"
488#include "registries.hpp"
489#include "registries/base_message_registry.hpp"
490
491#include <boost/beast/http/field.hpp>
492#include <boost/beast/http/status.hpp>
493#include <boost/url/url_view_base.hpp>
494#include <nlohmann/json.hpp>
495
496#include <array>
497#include <cstddef>
498#include <cstdint>
499#include <source_location>
500#include <span>
501#include <string>
502#include <string_view>
503
504// Clang can't seem to decide whether this header needs to be included or not,
505// and is inconsistent. Include it for now
506// NOLINTNEXTLINE(misc-include-cleaner)
507#include <utility>
508
509namespace redfish
510{
511
512namespace messages
513{
514
515static void addMessageToErrorJson(nlohmann::json& target,
516 const nlohmann::json& message)
517{
518 auto& error = target["error"];
519
520 // If this is the first error message, fill in the information from the
521 // first error message to the top level struct
522 if (!error.is_object())
523 {
524 auto messageIdIterator = message.find("MessageId");
525 if (messageIdIterator == message.end())
526 {
527 BMCWEB_LOG_CRITICAL(
528 "Attempt to add error message without MessageId");
529 return;
530 }
531
532 auto messageFieldIterator = message.find("Message");
533 if (messageFieldIterator == message.end())
534 {
535 BMCWEB_LOG_CRITICAL("Attempt to add error message without Message");
536 return;
537 }
538 error["code"] = *messageIdIterator;
539 error["message"] = *messageFieldIterator;
540 }
541 else
542 {
543 // More than 1 error occurred, so the message has to be generic
544 error["code"] = std::string(messageVersionPrefix) + "GeneralError";
545 error["message"] = "A general error has occurred. See Resolution for "
546 "information on how to resolve the error.";
547 }
548
549 // This check could technically be done in the default construction
550 // branch above, but because we need the pointer to the extended info field
551 // anyway, it's more efficient to do it here.
552 auto& extendedInfo = error[messages::messageAnnotation];
553 if (!extendedInfo.is_array())
554 {
555 extendedInfo = nlohmann::json::array();
556 }
557
558 extendedInfo.push_back(message);
559}
560
561void moveErrorsToErrorJson(nlohmann::json& target, nlohmann::json& source)
562{
563 if (!source.is_object())
564 {
565 return;
566 }
567 auto errorIt = source.find("error");
568 if (errorIt == source.end())
569 {
570 // caller puts error message in root
571 messages::addMessageToErrorJson(target, source);
572 source.clear();
573 return;
574 }
575 auto extendedInfoIt = errorIt->find(messages::messageAnnotation);
576 if (extendedInfoIt == errorIt->end())
577 {
578 return;
579 }
580 const nlohmann::json::array_t* extendedInfo =
581 (*extendedInfoIt).get_ptr<const nlohmann::json::array_t*>();
582 if (extendedInfo == nullptr)
583 {
584 source.erase(errorIt);
585 return;
586 }
587 for (const nlohmann::json& message : *extendedInfo)
588 {
589 addMessageToErrorJson(target, message);
590 }
591 source.erase(errorIt);
592}
593
594static void addMessageToJsonRoot(nlohmann::json& target,
595 const nlohmann::json& message)
596{
597 if (!target[messages::messageAnnotation].is_array())
598 {
599 // Force object to be an array
600 target[messages::messageAnnotation] = nlohmann::json::array();
601 }
602
603 target[messages::messageAnnotation].push_back(message);
604}
605
606static void addMessageToJson(nlohmann::json& target,
607 const nlohmann::json& message,
608 std::string_view fieldPath)
609{
610 std::string extendedInfo(fieldPath);
611 extendedInfo += messages::messageAnnotation;
612
613 nlohmann::json& field = target[extendedInfo];
614 if (!field.is_array())
615 {
616 // Force object to be an array
617 field = nlohmann::json::array();
618 }
619
620 // Object exists and it is an array so we can just push in the message
621 field.push_back(message);
622}
623
624static nlohmann::json getLog(redfish::registries::base::Index name,
625 std::span<const std::string_view> args)
626{
627 size_t index = static_cast<size_t>(name);
628 if (index >= redfish::registries::base::registry.size())
629 {
630 return {};
631 }
632 return getLogFromRegistry(redfish::registries::base::header,
633 redfish::registries::base::registry, index, args);
634}
635
636"""
637 )
638 for entry_id, entry in messages.items():
639 out.write(
640 f"""/**
641 * @internal
642 * @brief Formats {entry_id} message into JSON
643 *
644 * See header file for more information
645 * @endinternal
646 */
647"""
648 )
649 message = entry["Message"]
650 out.write(make_error_function(entry_id, entry, False))
651
652 out.write(" }\n")
653 out.write("}\n")
654 os.system(f"clang-format -i {error_messages_hpp} {error_messages_cpp}")
Ed Tanous42079ec2024-11-16 13:32:29 -0800655
656
Ed Tanoused398212021-06-09 17:05:54 -0700657def make_privilege_registry():
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600658 path, json_file, type_name, url = make_getter(
Gunnar Mills5910d942024-04-16 12:07:17 -0500659 "Redfish_1.5.0_PrivilegeRegistry.json",
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600660 "privilege_registry.hpp",
661 "privilege",
662 )
663 with open(path, "w") as registry:
Nan Zhou043bec02022-09-20 18:12:13 +0000664 registry.write(PRIVILEGE_HEADER)
Ed Tanoused398212021-06-09 17:05:54 -0700665
666 privilege_dict = {}
667 for mapping in json_file["Mappings"]:
668 # first pass, identify all the unique privilege sets
669 for operation, privilege_list in mapping["OperationMap"].items():
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600670 privilege_dict[
671 get_privilege_string_from_list(privilege_list)
672 ] = (privilege_list,)
Ed Tanoused398212021-06-09 17:05:54 -0700673 for index, key in enumerate(privilege_dict):
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600674 (privilege_list,) = privilege_dict[key]
Ed Tanoused398212021-06-09 17:05:54 -0700675 name = get_variable_name_for_privilege_set(privilege_list)
Ed Tanousf395daa2021-08-02 08:56:24 -0700676 registry.write(
Ed Tanous5b9ef702022-02-17 12:19:32 -0800677 "const std::array<Privileges, {length}> "
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600678 "privilegeSet{name} = {key};\n".format(
679 length=len(privilege_list), name=name, key=key
680 )
Ed Tanous5b9ef702022-02-17 12:19:32 -0800681 )
Ed Tanoused398212021-06-09 17:05:54 -0700682 privilege_dict[key] = (privilege_list, name)
Ed Tanoused398212021-06-09 17:05:54 -0700683
684 for mapping in json_file["Mappings"]:
685 entity = mapping["Entity"]
Ed Tanous4d99bbb2022-02-17 10:02:57 -0800686 registry.write("// {}\n".format(entity))
Ed Tanoused398212021-06-09 17:05:54 -0700687 for operation, privilege_list in mapping["OperationMap"].items():
688 privilege_string = get_privilege_string_from_list(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600689 privilege_list
690 )
Ed Tanoused398212021-06-09 17:05:54 -0700691 operation = operation.lower()
692
Ed Tanousf395daa2021-08-02 08:56:24 -0700693 registry.write(
694 "const static auto& {}{} = privilegeSet{};\n".format(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600695 operation, entity, privilege_dict[privilege_string][1]
696 )
697 )
Ed Tanoused398212021-06-09 17:05:54 -0700698 registry.write("\n")
Ed Tanous5b9ef702022-02-17 12:19:32 -0800699 registry.write(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600700 "} // namespace redfish::privileges\n// clang-format on\n"
701 )
Ed Tanoused398212021-06-09 17:05:54 -0700702
703
Gunnar Mills665e7602024-04-10 13:14:41 -0500704def to_pascal_case(text):
705 s = text.replace("_", " ")
706 s = s.split()
707 if len(text) == 0:
708 return text
709 return "".join(i.capitalize() for i in s[0:])
710
711
Nan Zhou49aa131f2022-09-20 18:41:37 +0000712def main():
Gunnar Mills665e7602024-04-10 13:14:41 -0500713 dmtf_registries = (
Jishnu CMb575cae2024-10-01 01:33:49 -0500714 ("base", "1.19.0"),
Gunnar Mills665e7602024-04-10 13:14:41 -0500715 ("composition", "1.1.2"),
716 ("environmental", "1.0.1"),
717 ("ethernet_fabric", "1.0.1"),
718 ("fabric", "1.0.2"),
719 ("heartbeat_event", "1.0.1"),
720 ("job_event", "1.0.1"),
721 ("license", "1.0.3"),
722 ("log_service", "1.0.1"),
723 ("network_device", "1.0.3"),
724 ("platform", "1.0.1"),
725 ("power", "1.0.1"),
726 ("resource_event", "1.3.0"),
727 ("sensor_event", "1.0.1"),
728 ("storage_device", "1.2.1"),
729 ("task_event", "1.0.3"),
730 ("telemetry", "1.0.0"),
731 ("update", "1.0.2"),
732 )
733
Nan Zhou49aa131f2022-09-20 18:41:37 +0000734 parser = argparse.ArgumentParser()
735 parser.add_argument(
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600736 "--registries",
737 type=str,
Gunnar Mills665e7602024-04-10 13:14:41 -0500738 default="privilege,openbmc,"
739 + ",".join([dmtf[0] for dmtf in dmtf_registries]),
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600740 help="Comma delimited list of registries to update",
741 )
Nan Zhou49aa131f2022-09-20 18:41:37 +0000742
743 args = parser.parse_args()
744
745 registries = set(args.registries.split(","))
746 files = []
747
Gunnar Mills665e7602024-04-10 13:14:41 -0500748 for registry, version in dmtf_registries:
749 if registry in registries:
750 registry_pascal_case = to_pascal_case(registry)
751 files.append(
752 make_getter(
753 f"{registry_pascal_case}.{version}.json",
754 f"{registry}_message_registry.hpp",
755 registry,
756 )
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600757 )
Ed Tanous3e5faba2023-08-16 15:11:29 -0700758 if "openbmc" in registries:
759 files.append(openbmc_local_getter())
Nan Zhou49aa131f2022-09-20 18:41:37 +0000760
761 update_registries(files)
762
Ed Tanous42079ec2024-11-16 13:32:29 -0800763 create_error_registry(files[0])
764
Nan Zhou49aa131f2022-09-20 18:41:37 +0000765 if "privilege" in registries:
766 make_privilege_registry()
767
768
769if __name__ == "__main__":
770 main()