1#!/usr/bin/env python3 2import argparse 3import json 4import os 5from collections import OrderedDict 6 7import requests 8 9PRAGMA_ONCE = """#pragma once 10""" 11 12WARNING = """/**************************************************************** 13 * READ THIS WARNING FIRST 14 * This is an auto-generated header which contains definitions 15 * for Redfish DMTF defined messages. 16 * DO NOT modify this registry outside of running the 17 * parse_registries.py script. The definitions contained within 18 * 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. 21 ***************************************************************/""" 22 23REGISTRY_HEADER = ( 24 PRAGMA_ONCE 25 + WARNING 26 + """ 27#include "registries.hpp" 28 29#include <array> 30 31// clang-format off 32 33namespace redfish::registries::{} 34{{ 35""" 36) 37 38SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__)) 39 40include_path = os.path.realpath( 41 os.path.join(SCRIPT_DIR, "..", "redfish-core", "include", "registries") 42) 43 44proxies = {"https": os.environ.get("https_proxy", None)} 45 46 47def make_getter(dmtf_name, header_name, type_name): 48 url = "https://redfish.dmtf.org/registries/{}".format(dmtf_name) 49 dmtf = requests.get(url, proxies=proxies) 50 dmtf.raise_for_status() 51 json_file = json.loads(dmtf.text, object_pairs_hook=OrderedDict) 52 path = os.path.join(include_path, header_name) 53 return (path, json_file, type_name, url) 54 55 56def openbmc_local_getter(): 57 url = "https://github.com/openbmc/bmcweb/blob/master/redfish-core/include/registries/openbmc.json" 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 75def 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)) 82 83 with open(file, "w") as registry: 84 85 version_split = json_dict["RegistryVersion"].split(".") 86 87 registry.write(REGISTRY_HEADER.format(namespace)) 88 # Parse the Registry header info 89 registry.write( 90 "const Header header = {{\n" 91 ' "{json_dict[@Redfish.Copyright]}",\n' 92 ' "{json_dict[@odata.type]}",\n' 93 " {version_split[0]},\n" 94 " {version_split[1]},\n" 95 " {version_split[2]},\n" 96 ' "{json_dict[Name]}",\n' 97 ' "{json_dict[Language]}",\n' 98 ' "{json_dict[Description]}",\n' 99 ' "{json_dict[RegistryPrefix]}",\n' 100 ' "{json_dict[OwningEntity]}",\n' 101 "}};\n" 102 "constexpr const char* url =\n" 103 ' "{url}";\n' 104 "\n" 105 "constexpr std::array registry =\n" 106 "{{\n".format( 107 json_dict=json_dict, 108 url=url, 109 version_split=version_split, 110 ) 111 ) 112 113 messages_sorted = sorted(json_dict["Messages"].items()) 114 for messageId, message in messages_sorted: 115 registry.write( 116 " MessageEntry{{\n" 117 ' "{messageId}",\n' 118 " {{\n" 119 ' "{message[Description]}",\n' 120 ' "{message[Message]}",\n' 121 ' "{message[MessageSeverity]}",\n' 122 " {message[NumberOfArgs]},\n" 123 " {{".format( 124 messageId=messageId, message=message 125 ) 126 ) 127 paramTypes = message.get("ParamTypes") 128 if paramTypes: 129 for paramType in paramTypes: 130 registry.write( 131 '\n "{}",'.format(paramType) 132 ) 133 registry.write("\n },\n") 134 else: 135 registry.write("},\n") 136 registry.write( 137 ' "{message[Resolution]}",\n' 138 " }}}},\n".format(message=message) 139 ) 140 141 registry.write("\n};\n\nenum class Index\n{\n") 142 for index, (messageId, message) in enumerate(messages_sorted): 143 messageId = messageId[0].lower() + messageId[1:] 144 registry.write(" {} = {},\n".format(messageId, index)) 145 registry.write( 146 "}};\n}} // namespace redfish::registries::{}\n".format( 147 namespace 148 ) 149 ) 150 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 160 privilege_string += '"' 161 privilege_string += privilege 162 privilege_string += '",\n' 163 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 171 172def 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 179 180PRIVILEGE_HEADER = ( 181 PRAGMA_ONCE 182 + WARNING 183 + """ 184#include "privileges.hpp" 185 186#include <array> 187 188// clang-format off 189 190namespace redfish::privileges 191{ 192""" 193) 194 195 196def 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 244def make_error_function( 245 entry_id, entry, is_header, registry_name, namespace_name 246): 247 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], 281 "TaskProgressChanged": [2], 282 }, 283 } 284 285 out = "" 286 args = [] 287 argtypes = [] 288 for arg_index, arg in enumerate(entry.get("ParamTypes", [])): 289 arg_index += 1 290 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 295 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" 312 elif typename == "uint64_t": 313 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>" 323 elif typename == "uint64_t": 324 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) 329 330 if argtypes: 331 arg_param = f"std::to_array{to_array_type}({{{argstring}}})" 332 else: 333 arg_param = "{}" 334 out += f" return getLog(redfish::registries::{namespace_name}::Index::{function_name}, {arg_param});" 335 out += "\n}\n\n" 336 if registry_name == "Base": 337 args.insert(0, "crow::Response& res") 338 if entry_id == "InternalError": 339 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" 349 else: 350 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" 393 out += "\n" 394 return out 395 396 397def create_error_registry( 398 entry, registry_version, registry_name, namespace_name, filename 399): 400 file, json_dict, namespace, url = entry 401 base_filename = filename + "_messages" 402 403 error_messages_hpp = os.path.join( 404 SCRIPT_DIR, "..", "redfish-core", "include", f"{base_filename}.hpp" 405 ) 406 messages = json_dict["Messages"] 407 408 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 <source_location> 423#include <string_view> 424 425// IWYU pragma: no_forward_declare crow::Response 426 427namespace redfish 428{ 429 430namespace messages 431{ 432""" 433 ) 434 if registry_name == "Base": 435 out.write( 436 f'constexpr const char* messageVersionPrefix = "{registry_name}.{registry_version}.";' 437 ) 438 out.write( 439 """ 440 constexpr const char* messageAnnotation = "@Message.ExtendedInfo"; 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 for entry_id, entry in messages.items(): 450 message = entry["Message"] 451 for index in range(1, 10): 452 message = message.replace(f"'%{index}'", f"<arg{index}>") 453 message = message.replace(f"%{index}", f"<arg{index}>") 454 455 if registry_name == "Base": 456 out.write("/**\n") 457 out.write(f"* @brief Formats {entry_id} message into JSON\n") 458 out.write(f'* Message body: "{message}"\n') 459 out.write("*\n") 460 arg_index = 0 461 for arg_index, arg in enumerate(entry.get("ParamTypes", [])): 462 arg_index += 1 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( 469 f"* @returns Message {entry_id} formatted to JSON */\n" 470 ) 471 472 out.write( 473 make_error_function( 474 entry_id, entry, True, registry_name, namespace_name 475 ) 476 ) 477 out.write(" }\n") 478 out.write("}\n") 479 480 error_messages_cpp = os.path.join( 481 SCRIPT_DIR, "..", "redfish-core", "src", f"{base_filename}.cpp" 482 ) 483 with open( 484 error_messages_cpp, 485 "w", 486 ) as out: 487 out.write(WARNING) 488 out.write(f'\n#include "{base_filename}.hpp"\n') 489 headers = [] 490 491 headers.append('"registries.hpp"') 492 if registry_name == "Base": 493 reg_name_lower = "base" 494 headers.append('"http_response.hpp"') 495 headers.append('"logging.hpp"') 496 headers.append("<boost/beast/http/field.hpp>") 497 headers.append("<boost/beast/http/status.hpp>") 498 headers.append("<boost/url/url_view_base.hpp>") 499 headers.append("<source_location>") 500 else: 501 reg_name_lower = namespace_name.lower() 502 headers.append(f'"registries/{reg_name_lower}_message_registry.hpp"') 503 504 headers.append("<nlohmann/json.hpp>") 505 headers.append("<array>") 506 headers.append("<cstddef>") 507 headers.append("<span>") 508 509 if registry_name not in ("ResourceEvent", "HeartbeatEvent"): 510 headers.append("<cstdint>") 511 headers.append("<string>") 512 headers.append("<string_view>") 513 514 for header in headers: 515 out.write(f"#include {header}\n") 516 517 out.write( 518 """ 519// Clang can't seem to decide whether this header needs to be included or not, 520// and is inconsistent. Include it for now 521// NOLINTNEXTLINE(misc-include-cleaner) 522#include <utility> 523 524namespace redfish 525{ 526 527namespace messages 528{ 529""" 530 ) 531 532 if registry_name == "Base": 533 out.write( 534 """ 535static void addMessageToErrorJson(nlohmann::json& target, 536 const nlohmann::json& message) 537{ 538 auto& error = target["error"]; 539 540 // If this is the first error message, fill in the information from the 541 // first error message to the top level struct 542 if (!error.is_object()) 543 { 544 auto messageIdIterator = message.find("MessageId"); 545 if (messageIdIterator == message.end()) 546 { 547 BMCWEB_LOG_CRITICAL( 548 "Attempt to add error message without MessageId"); 549 return; 550 } 551 552 auto messageFieldIterator = message.find("Message"); 553 if (messageFieldIterator == message.end()) 554 { 555 BMCWEB_LOG_CRITICAL("Attempt to add error message without Message"); 556 return; 557 } 558 error["code"] = *messageIdIterator; 559 error["message"] = *messageFieldIterator; 560 } 561 else 562 { 563 // More than 1 error occurred, so the message has to be generic 564 error["code"] = std::string(messageVersionPrefix) + "GeneralError"; 565 error["message"] = "A general error has occurred. See Resolution for " 566 "information on how to resolve the error."; 567 } 568 569 // This check could technically be done in the default construction 570 // branch above, but because we need the pointer to the extended info field 571 // anyway, it's more efficient to do it here. 572 auto& extendedInfo = error[messages::messageAnnotation]; 573 if (!extendedInfo.is_array()) 574 { 575 extendedInfo = nlohmann::json::array(); 576 } 577 578 extendedInfo.push_back(message); 579} 580 581void moveErrorsToErrorJson(nlohmann::json& target, nlohmann::json& source) 582{ 583 if (!source.is_object()) 584 { 585 return; 586 } 587 auto errorIt = source.find("error"); 588 if (errorIt == source.end()) 589 { 590 // caller puts error message in root 591 messages::addMessageToErrorJson(target, source); 592 source.clear(); 593 return; 594 } 595 auto extendedInfoIt = errorIt->find(messages::messageAnnotation); 596 if (extendedInfoIt == errorIt->end()) 597 { 598 return; 599 } 600 const nlohmann::json::array_t* extendedInfo = 601 (*extendedInfoIt).get_ptr<const nlohmann::json::array_t*>(); 602 if (extendedInfo == nullptr) 603 { 604 source.erase(errorIt); 605 return; 606 } 607 for (const nlohmann::json& message : *extendedInfo) 608 { 609 addMessageToErrorJson(target, message); 610 } 611 source.erase(errorIt); 612} 613 614static void addMessageToJsonRoot(nlohmann::json& target, 615 const nlohmann::json& message) 616{ 617 if (!target[messages::messageAnnotation].is_array()) 618 { 619 // Force object to be an array 620 target[messages::messageAnnotation] = nlohmann::json::array(); 621 } 622 623 target[messages::messageAnnotation].push_back(message); 624} 625 626static void addMessageToJson(nlohmann::json& target, 627 const nlohmann::json& message, 628 std::string_view fieldPath) 629{ 630 std::string extendedInfo(fieldPath); 631 extendedInfo += messages::messageAnnotation; 632 633 nlohmann::json& field = target[extendedInfo]; 634 if (!field.is_array()) 635 { 636 // Force object to be an array 637 field = nlohmann::json::array(); 638 } 639 640 // Object exists and it is an array so we can just push in the message 641 field.push_back(message); 642} 643""" 644 ) 645 out.write( 646 """ 647static nlohmann::json getLog(redfish::registries::{namespace_name}::Index name, 648 std::span<const std::string_view> args) 649{{ 650 size_t index = static_cast<size_t>(name); 651 if (index >= redfish::registries::{namespace_name}::registry.size()) 652 {{ 653 return {{}}; 654 }} 655 return getLogFromRegistry(redfish::registries::{namespace_name}::header, 656 redfish::registries::{namespace_name}::registry, index, args); 657}} 658 659""".format( 660 namespace_name=namespace_name 661 ) 662 ) 663 for entry_id, entry in messages.items(): 664 out.write( 665 f"""/** 666 * @internal 667 * @brief Formats {entry_id} message into JSON 668 * 669 * See header file for more information 670 * @endinternal 671 */ 672""" 673 ) 674 message = entry["Message"] 675 out.write( 676 make_error_function( 677 entry_id, entry, False, registry_name, namespace_name 678 ) 679 ) 680 681 out.write(" }\n") 682 out.write("}\n") 683 os.system(f"clang-format -i {error_messages_hpp} {error_messages_cpp}") 684 685 686def make_privilege_registry(): 687 path, json_file, type_name, url = make_getter( 688 "Redfish_1.5.0_PrivilegeRegistry.json", 689 "privilege_registry.hpp", 690 "privilege", 691 ) 692 with open(path, "w") as registry: 693 registry.write(PRIVILEGE_HEADER) 694 695 privilege_dict = {} 696 for mapping in json_file["Mappings"]: 697 # first pass, identify all the unique privilege sets 698 for operation, privilege_list in mapping["OperationMap"].items(): 699 privilege_dict[ 700 get_privilege_string_from_list(privilege_list) 701 ] = (privilege_list,) 702 for index, key in enumerate(privilege_dict): 703 (privilege_list,) = privilege_dict[key] 704 name = get_variable_name_for_privilege_set(privilege_list) 705 registry.write( 706 "const std::array<Privileges, {length}> " 707 "privilegeSet{name} = {key};\n".format( 708 length=len(privilege_list), name=name, key=key 709 ) 710 ) 711 privilege_dict[key] = (privilege_list, name) 712 713 for mapping in json_file["Mappings"]: 714 entity = mapping["Entity"] 715 registry.write("// {}\n".format(entity)) 716 for operation, privilege_list in mapping["OperationMap"].items(): 717 privilege_string = get_privilege_string_from_list( 718 privilege_list 719 ) 720 operation = operation.lower() 721 722 registry.write( 723 "const static auto& {}{} = privilegeSet{};\n".format( 724 operation, entity, privilege_dict[privilege_string][1] 725 ) 726 ) 727 registry.write("\n") 728 registry.write( 729 "} // namespace redfish::privileges\n// clang-format on\n" 730 ) 731 732 733def to_pascal_case(text): 734 s = text.replace("_", " ") 735 s = s.split() 736 if len(text) == 0: 737 return text 738 return "".join(i.capitalize() for i in s[0:]) 739 740 741def main(): 742 dmtf_registries = ( 743 ("base", "1.19.0"), 744 ("composition", "1.1.2"), 745 ("environmental", "1.0.1"), 746 ("ethernet_fabric", "1.0.1"), 747 ("fabric", "1.0.2"), 748 ("heartbeat_event", "1.0.1"), 749 ("job_event", "1.0.1"), 750 ("license", "1.0.3"), 751 ("log_service", "1.0.1"), 752 ("network_device", "1.0.3"), 753 ("platform", "1.0.1"), 754 ("power", "1.0.1"), 755 ("resource_event", "1.3.0"), 756 ("sensor_event", "1.0.1"), 757 ("storage_device", "1.2.1"), 758 ("task_event", "1.0.3"), 759 ("telemetry", "1.0.0"), 760 ("update", "1.0.2"), 761 ) 762 763 parser = argparse.ArgumentParser() 764 parser.add_argument( 765 "--registries", 766 type=str, 767 default="privilege,openbmc," 768 + ",".join([dmtf[0] for dmtf in dmtf_registries]), 769 help="Comma delimited list of registries to update", 770 ) 771 772 args = parser.parse_args() 773 774 registries = set(args.registries.split(",")) 775 files = [] 776 777 for registry, version in dmtf_registries: 778 if registry in registries: 779 registry_pascal_case = to_pascal_case(registry) 780 files.append( 781 make_getter( 782 f"{registry_pascal_case}.{version}.json", 783 f"{registry}_message_registry.hpp", 784 registry, 785 ) 786 ) 787 if "openbmc" in registries: 788 files.append(openbmc_local_getter()) 789 790 update_registries(files) 791 792 create_error_registry( 793 files[0], dmtf_registries[0][1], "Base", "base", "error" 794 ) 795 create_error_registry( 796 files[5], 797 dmtf_registries[5][1], 798 "HeartbeatEvent", 799 "heartbeat_event", 800 "heartbeat", 801 ) 802 create_error_registry( 803 files[12], 804 dmtf_registries[12][1], 805 "ResourceEvent", 806 "resource_event", 807 "resource", 808 ) 809 create_error_registry( 810 files[15], dmtf_registries[15][1], "TaskEvent", "task_event", "task" 811 ) 812 813 if "privilege" in registries: 814 make_privilege_registry() 815 816 817if __name__ == "__main__": 818 main() 819