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 <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{ 434""" 435 ) 436 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"; 443 444 /** 445 * @brief Moves all error messages from the |source| JSON to |target| 446 */ 447 void moveErrorsToErrorJson(nlohmann::json& target, nlohmann::json& source); 448 449 """ 450 ) 451 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 457 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 465 466 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") 470 out.write( 471 f"* @returns Message {entry_id} formatted to JSON */\n" 472 ) 473 474 out.write( 475 make_error_function( 476 entry_id, entry, True, registry_name, namespace_name 477 ) 478 ) 479 out.write(" }\n") 480 out.write("}\n") 481 482 error_messages_cpp = os.path.join( 483 SCRIPT_DIR, "..", "redfish-core", "src", f"{base_filename}.cpp" 484 ) 485 with open( 486 error_messages_cpp, 487 "w", 488 ) as out: 489 out.write(WARNING) 490 out.write(f'\n#include "{base_filename}.hpp"\n') 491 headers = [] 492 493 headers.append('"registries.hpp"') 494 if registry_name == "Base": 495 reg_name_lower = "base" 496 headers.append('"http_response.hpp"') 497 headers.append('"logging.hpp"') 498 headers.append("<boost/beast/http/field.hpp>") 499 headers.append("<boost/beast/http/status.hpp>") 500 headers.append("<boost/url/url_view_base.hpp>") 501 headers.append("<source_location>") 502 else: 503 reg_name_lower = namespace_name.lower() 504 headers.append(f'"registries/{reg_name_lower}_message_registry.hpp"') 505 506 headers.append("<nlohmann/json.hpp>") 507 headers.append("<array>") 508 headers.append("<cstddef>") 509 headers.append("<span>") 510 511 if registry_name != "ResourceEvent": 512 headers.append("<cstdint>") 513 headers.append("<string>") 514 headers.append("<string_view>") 515 516 for header in headers: 517 out.write(f"#include {header}\n") 518 519 out.write( 520 """ 521// Clang can't seem to decide whether this header needs to be included or not, 522// and is inconsistent. Include it for now 523// NOLINTNEXTLINE(misc-include-cleaner) 524#include <utility> 525 526namespace redfish 527{ 528 529namespace messages 530{ 531""" 532 ) 533 534 if registry_name == "Base": 535 out.write( 536 """ 537static void addMessageToErrorJson(nlohmann::json& target, 538 const nlohmann::json& message) 539{ 540 auto& error = target["error"]; 541 542 // If this is the first error message, fill in the information from the 543 // first error message to the top level struct 544 if (!error.is_object()) 545 { 546 auto messageIdIterator = message.find("MessageId"); 547 if (messageIdIterator == message.end()) 548 { 549 BMCWEB_LOG_CRITICAL( 550 "Attempt to add error message without MessageId"); 551 return; 552 } 553 554 auto messageFieldIterator = message.find("Message"); 555 if (messageFieldIterator == message.end()) 556 { 557 BMCWEB_LOG_CRITICAL("Attempt to add error message without Message"); 558 return; 559 } 560 error["code"] = *messageIdIterator; 561 error["message"] = *messageFieldIterator; 562 } 563 else 564 { 565 // More than 1 error occurred, so the message has to be generic 566 error["code"] = std::string(messageVersionPrefix) + "GeneralError"; 567 error["message"] = "A general error has occurred. See Resolution for " 568 "information on how to resolve the error."; 569 } 570 571 // This check could technically be done in the default construction 572 // branch above, but because we need the pointer to the extended info field 573 // anyway, it's more efficient to do it here. 574 auto& extendedInfo = error[messages::messageAnnotation]; 575 if (!extendedInfo.is_array()) 576 { 577 extendedInfo = nlohmann::json::array(); 578 } 579 580 extendedInfo.push_back(message); 581} 582 583void moveErrorsToErrorJson(nlohmann::json& target, nlohmann::json& source) 584{ 585 if (!source.is_object()) 586 { 587 return; 588 } 589 auto errorIt = source.find("error"); 590 if (errorIt == source.end()) 591 { 592 // caller puts error message in root 593 messages::addMessageToErrorJson(target, source); 594 source.clear(); 595 return; 596 } 597 auto extendedInfoIt = errorIt->find(messages::messageAnnotation); 598 if (extendedInfoIt == errorIt->end()) 599 { 600 return; 601 } 602 const nlohmann::json::array_t* extendedInfo = 603 (*extendedInfoIt).get_ptr<const nlohmann::json::array_t*>(); 604 if (extendedInfo == nullptr) 605 { 606 source.erase(errorIt); 607 return; 608 } 609 for (const nlohmann::json& message : *extendedInfo) 610 { 611 addMessageToErrorJson(target, message); 612 } 613 source.erase(errorIt); 614} 615 616static void addMessageToJsonRoot(nlohmann::json& target, 617 const nlohmann::json& message) 618{ 619 if (!target[messages::messageAnnotation].is_array()) 620 { 621 // Force object to be an array 622 target[messages::messageAnnotation] = nlohmann::json::array(); 623 } 624 625 target[messages::messageAnnotation].push_back(message); 626} 627 628static void addMessageToJson(nlohmann::json& target, 629 const nlohmann::json& message, 630 std::string_view fieldPath) 631{ 632 std::string extendedInfo(fieldPath); 633 extendedInfo += messages::messageAnnotation; 634 635 nlohmann::json& field = target[extendedInfo]; 636 if (!field.is_array()) 637 { 638 // Force object to be an array 639 field = nlohmann::json::array(); 640 } 641 642 // Object exists and it is an array so we can just push in the message 643 field.push_back(message); 644} 645""" 646 ) 647 out.write( 648 """ 649static nlohmann::json getLog(redfish::registries::{namespace_name}::Index name, 650 std::span<const std::string_view> args) 651{{ 652 size_t index = static_cast<size_t>(name); 653 if (index >= redfish::registries::{namespace_name}::registry.size()) 654 {{ 655 return {{}}; 656 }} 657 return getLogFromRegistry(redfish::registries::{namespace_name}::header, 658 redfish::registries::{namespace_name}::registry, index, args); 659}} 660 661""".format( 662 namespace_name=namespace_name 663 ) 664 ) 665 for entry_id, entry in messages.items(): 666 out.write( 667 f"""/** 668 * @internal 669 * @brief Formats {entry_id} message into JSON 670 * 671 * See header file for more information 672 * @endinternal 673 */ 674""" 675 ) 676 message = entry["Message"] 677 out.write( 678 make_error_function( 679 entry_id, entry, False, registry_name, namespace_name 680 ) 681 ) 682 683 out.write(" }\n") 684 out.write("}\n") 685 os.system(f"clang-format -i {error_messages_hpp} {error_messages_cpp}") 686 687 688def make_privilege_registry(): 689 path, json_file, type_name, url = make_getter( 690 "Redfish_1.5.0_PrivilegeRegistry.json", 691 "privilege_registry.hpp", 692 "privilege", 693 ) 694 with open(path, "w") as registry: 695 registry.write(PRIVILEGE_HEADER) 696 697 privilege_dict = {} 698 for mapping in json_file["Mappings"]: 699 # first pass, identify all the unique privilege sets 700 for operation, privilege_list in mapping["OperationMap"].items(): 701 privilege_dict[ 702 get_privilege_string_from_list(privilege_list) 703 ] = (privilege_list,) 704 for index, key in enumerate(privilege_dict): 705 (privilege_list,) = privilege_dict[key] 706 name = get_variable_name_for_privilege_set(privilege_list) 707 registry.write( 708 "const std::array<Privileges, {length}> " 709 "privilegeSet{name} = {key};\n".format( 710 length=len(privilege_list), name=name, key=key 711 ) 712 ) 713 privilege_dict[key] = (privilege_list, name) 714 715 for mapping in json_file["Mappings"]: 716 entity = mapping["Entity"] 717 registry.write("// {}\n".format(entity)) 718 for operation, privilege_list in mapping["OperationMap"].items(): 719 privilege_string = get_privilege_string_from_list( 720 privilege_list 721 ) 722 operation = operation.lower() 723 724 registry.write( 725 "const static auto& {}{} = privilegeSet{};\n".format( 726 operation, entity, privilege_dict[privilege_string][1] 727 ) 728 ) 729 registry.write("\n") 730 registry.write( 731 "} // namespace redfish::privileges\n// clang-format on\n" 732 ) 733 734 735def to_pascal_case(text): 736 s = text.replace("_", " ") 737 s = s.split() 738 if len(text) == 0: 739 return text 740 return "".join(i.capitalize() for i in s[0:]) 741 742 743def main(): 744 dmtf_registries = ( 745 ("base", "1.19.0"), 746 ("composition", "1.1.2"), 747 ("environmental", "1.0.1"), 748 ("ethernet_fabric", "1.0.1"), 749 ("fabric", "1.0.2"), 750 ("heartbeat_event", "1.0.1"), 751 ("job_event", "1.0.1"), 752 ("license", "1.0.3"), 753 ("log_service", "1.0.1"), 754 ("network_device", "1.0.3"), 755 ("platform", "1.0.1"), 756 ("power", "1.0.1"), 757 ("resource_event", "1.3.0"), 758 ("sensor_event", "1.0.1"), 759 ("storage_device", "1.2.1"), 760 ("task_event", "1.0.3"), 761 ("telemetry", "1.0.0"), 762 ("update", "1.0.2"), 763 ) 764 765 parser = argparse.ArgumentParser() 766 parser.add_argument( 767 "--registries", 768 type=str, 769 default="privilege,openbmc," 770 + ",".join([dmtf[0] for dmtf in dmtf_registries]), 771 help="Comma delimited list of registries to update", 772 ) 773 774 args = parser.parse_args() 775 776 registries = set(args.registries.split(",")) 777 files = [] 778 779 for registry, version in dmtf_registries: 780 if registry in registries: 781 registry_pascal_case = to_pascal_case(registry) 782 files.append( 783 make_getter( 784 f"{registry_pascal_case}.{version}.json", 785 f"{registry}_message_registry.hpp", 786 registry, 787 ) 788 ) 789 if "openbmc" in registries: 790 files.append(openbmc_local_getter()) 791 792 update_registries(files) 793 794 create_error_registry( 795 files[0], dmtf_registries[0][1], "Base", "base", "error" 796 ) 797 create_error_registry( 798 files[12], 799 dmtf_registries[12][1], 800 "ResourceEvent", 801 "resource_event", 802 "resource", 803 ) 804 create_error_registry( 805 files[15], dmtf_registries[15][1], "TaskEvent", "task_event", "task" 806 ) 807 808 if "privilege" in registries: 809 make_privilege_registry() 810 811 812if __name__ == "__main__": 813 main() 814