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 23COPYRIGHT = """// SPDX-License-Identifier: Apache-2.0 24// SPDX-FileCopyrightText: Copyright OpenBMC Authors 25""" 26 27INCLUDES = """ 28#include "registries.hpp" 29 30#include <array> 31 32// clang-format off 33 34namespace redfish::registries::{} 35{{ 36""" 37 38REGISTRY_HEADER = f"{COPYRIGHT}{PRAGMA_ONCE}{WARNING}{INCLUDES}" 39 40SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__)) 41 42include_path = os.path.realpath( 43 os.path.join(SCRIPT_DIR, "..", "redfish-core", "include", "registries") 44) 45 46proxies = {"https": os.environ.get("https_proxy", None)} 47 48 49def make_getter(dmtf_name, header_name, type_name): 50 url = "https://redfish.dmtf.org/registries/{}".format(dmtf_name) 51 dmtf = requests.get(url, proxies=proxies) 52 dmtf.raise_for_status() 53 json_file = json.loads(dmtf.text, object_pairs_hook=OrderedDict) 54 path = os.path.join(include_path, header_name) 55 return (path, json_file, type_name, url) 56 57 58def openbmc_local_getter(): 59 url = "https://raw.githubusercontent.com/openbmc/bmcweb/refs/heads/master/redfish-core/include/registries/openbmc.json" 60 with open( 61 os.path.join( 62 SCRIPT_DIR, 63 "..", 64 "redfish-core", 65 "include", 66 "registries", 67 "openbmc.json", 68 ), 69 "rb", 70 ) as json_file: 71 json_file = json.load(json_file) 72 73 path = os.path.join(include_path, "openbmc_message_registry.hpp") 74 return (path, json_file, "openbmc", url) 75 76 77def update_registries(files): 78 # Remove the old files 79 for file, json_dict, namespace, url in files: 80 try: 81 os.remove(file) 82 except BaseException: 83 print("{} not found".format(file)) 84 85 with open(file, "w") as registry: 86 87 version_split = json_dict["RegistryVersion"].split(".") 88 89 registry.write(REGISTRY_HEADER.format(namespace)) 90 # Parse the Registry header info 91 registry.write( 92 "const Header header = {{\n" 93 ' "{json_dict[@Redfish.Copyright]}",\n' 94 ' "{json_dict[@odata.type]}",\n' 95 " {version_split[0]},\n" 96 " {version_split[1]},\n" 97 " {version_split[2]},\n" 98 ' "{json_dict[Name]}",\n' 99 ' "{json_dict[Language]}",\n' 100 ' "{json_dict[Description]}",\n' 101 ' "{json_dict[RegistryPrefix]}",\n' 102 ' "{json_dict[OwningEntity]}",\n' 103 "}};\n" 104 "constexpr const char* url =\n" 105 ' "{url}";\n' 106 "\n" 107 "constexpr std::array registry =\n" 108 "{{\n".format( 109 json_dict=json_dict, 110 url=url, 111 version_split=version_split, 112 ) 113 ) 114 115 messages_sorted = sorted(json_dict["Messages"].items()) 116 for messageId, message in messages_sorted: 117 registry.write( 118 " MessageEntry{{\n" 119 ' "{messageId}",\n' 120 " {{\n" 121 ' "{message[Description]}",\n' 122 ' "{message[Message]}",\n' 123 ' "{message[MessageSeverity]}",\n' 124 " {message[NumberOfArgs]},\n" 125 " {{".format( 126 messageId=messageId, message=message 127 ) 128 ) 129 paramTypes = message.get("ParamTypes") 130 if paramTypes: 131 for paramType in paramTypes: 132 registry.write( 133 '\n "{}",'.format(paramType) 134 ) 135 registry.write("\n },\n") 136 else: 137 registry.write("},\n") 138 registry.write( 139 ' "{message[Resolution]}",\n' 140 " }}}},\n".format(message=message) 141 ) 142 143 registry.write("\n};\n\nenum class Index\n{\n") 144 for index, (messageId, message) in enumerate(messages_sorted): 145 messageId = messageId[0].lower() + messageId[1:] 146 registry.write(" {} = {},\n".format(messageId, index)) 147 registry.write( 148 "}};\n}} // namespace redfish::registries::{}\n".format( 149 namespace 150 ) 151 ) 152 153 154def get_privilege_string_from_list(privilege_list): 155 privilege_string = "{{\n" 156 for privilege_json in privilege_list: 157 privileges = privilege_json["Privilege"] 158 privilege_string += " {" 159 for privilege in privileges: 160 if privilege == "NoAuth": 161 continue 162 privilege_string += '"' 163 privilege_string += privilege 164 privilege_string += '",\n' 165 if privilege != "NoAuth": 166 privilege_string = privilege_string[:-2] 167 privilege_string += "}" 168 privilege_string += ",\n" 169 privilege_string = privilege_string[:-2] 170 privilege_string += "\n}}" 171 return privilege_string 172 173 174def get_variable_name_for_privilege_set(privilege_list): 175 names = [] 176 for privilege_json in privilege_list: 177 privileges = privilege_json["Privilege"] 178 names.append("And".join(privileges)) 179 return "Or".join(names) 180 181 182PRIVILEGE_HEADER = ( 183 COPYRIGHT 184 + PRAGMA_ONCE 185 + WARNING 186 + """ 187#include "privileges.hpp" 188 189#include <array> 190 191// clang-format off 192 193namespace redfish::privileges 194{ 195""" 196) 197 198 199def get_response_code(entry_id, entry): 200 codes = { 201 "InternalError": "internal_server_error", 202 "OperationTimeout": "internal_server_error", 203 "PropertyValueResourceConflict": "conflict", 204 "ResourceInUse": "service_unavailable", 205 "ServiceTemporarilyUnavailable": "service_unavailable", 206 "ResourceCannotBeDeleted": "method_not_allowed", 207 "PropertyValueModified": "ok", 208 "InsufficientPrivilege": "forbidden", 209 "AccountForSessionNoLongerExists": "forbidden", 210 "ServiceDisabled": "service_unavailable", 211 "ServiceInUnknownState": "service_unavailable", 212 "EventSubscriptionLimitExceeded": "service_unavailable", 213 "ResourceAtUriUnauthorized": "unauthorized", 214 "SessionTerminated": "ok", 215 "SubscriptionTerminated": "ok", 216 "PropertyNotWritable": "forbidden", 217 "MaximumErrorsExceeded": "internal_server_error", 218 "GeneralError": "internal_server_error", 219 "PreconditionFailed": "precondition_failed", 220 "OperationFailed": "bad_gateway", 221 "ServiceShuttingDown": "service_unavailable", 222 "AccountRemoved": "ok", 223 "PropertyValueExternalConflict": "conflict", 224 "InsufficientStorage": "insufficient_storage", 225 "OperationNotAllowed": "method_not_allowed", 226 "ResourceNotFound": "not_found", 227 "CouldNotEstablishConnection": "not_found", 228 "AccessDenied": "forbidden", 229 "Success": None, 230 "Created": "created", 231 "NoValidSession": "forbidden", 232 "SessionLimitExceeded": "service_unavailable", 233 "ResourceExhaustion": "service_unavailable", 234 "AccountModified": "ok", 235 "PasswordChangeRequired": None, 236 "ResourceInStandby": "service_unavailable", 237 "GenerateSecretKeyRequired": "forbidden", 238 } 239 240 code = codes.get(entry_id, "NOCODE") 241 if code != "NOCODE": 242 return code 243 244 return "bad_request" 245 246 247def make_error_function( 248 entry_id, entry, is_header, registry_name, namespace_name 249): 250 arg_nonstring_types = { 251 "const boost::urls::url_view_base&": { 252 "AccessDenied": [1], 253 "CouldNotEstablishConnection": [1], 254 "GenerateSecretKeyRequired": [1], 255 "InvalidObject": [1], 256 "PasswordChangeRequired": [1], 257 "PropertyValueResourceConflict": [3], 258 "ResetRequired": [1], 259 "ResourceAtUriInUnknownFormat": [1], 260 "ResourceAtUriUnauthorized": [1], 261 "ResourceCreationConflict": [1], 262 "ResourceMissingAtURI": [1], 263 "SourceDoesNotSupportProtocol": [1], 264 }, 265 "const nlohmann::json&": { 266 "ActionParameterValueError": [1], 267 "ActionParameterValueFormatError": [1], 268 "ActionParameterValueTypeError": [1], 269 "PropertyValueExternalConflict": [2], 270 "PropertyValueFormatError": [1], 271 "PropertyValueIncorrect": [2], 272 "PropertyValueModified": [2], 273 "PropertyValueNotInList": [1], 274 "PropertyValueOutOfRange": [1], 275 "PropertyValueResourceConflict": [2], 276 "PropertyValueTypeError": [1], 277 "QueryParameterValueFormatError": [1], 278 "QueryParameterValueTypeError": [1], 279 }, 280 "uint64_t": { 281 "ArraySizeTooLong": [2], 282 "InvalidIndex": [1], 283 "StringValueTooLong": [2], 284 "TaskProgressChanged": [2], 285 }, 286 } 287 288 out = "" 289 args = [] 290 argtypes = [] 291 for arg_index, arg in enumerate(entry.get("ParamTypes", [])): 292 arg_index += 1 293 typename = "std::string_view" 294 for typestring, entries in arg_nonstring_types.items(): 295 if arg_index in entries.get(entry_id, []): 296 typename = typestring 297 298 argtypes.append(typename) 299 args.append(f"{typename} arg{arg_index}") 300 function_name = entry_id[0].lower() + entry_id[1:] 301 arg = ", ".join(args) 302 out += f"nlohmann::json {function_name}({arg})" 303 304 if is_header: 305 out += ";\n\n" 306 else: 307 out += "\n{\n" 308 to_array_type = "" 309 if argtypes: 310 outargs = [] 311 for index, typename in enumerate(argtypes): 312 index += 1 313 if typename == "const nlohmann::json&": 314 out += f"std::string arg{index}Str = arg{index}.dump(-1, ' ', true, nlohmann::json::error_handler_t::replace);\n" 315 elif typename == "uint64_t": 316 out += f"std::string arg{index}Str = std::to_string(arg{index});\n" 317 318 for index, typename in enumerate(argtypes): 319 index += 1 320 if typename == "const boost::urls::url_view_base&": 321 outargs.append(f"arg{index}.buffer()") 322 to_array_type = "<std::string_view>" 323 elif typename == "const nlohmann::json&": 324 outargs.append(f"arg{index}Str") 325 to_array_type = "<std::string_view>" 326 elif typename == "uint64_t": 327 outargs.append(f"arg{index}Str") 328 to_array_type = "<std::string_view>" 329 else: 330 outargs.append(f"arg{index}") 331 argstring = ", ".join(outargs) 332 333 if argtypes: 334 arg_param = f"std::to_array{to_array_type}({{{argstring}}})" 335 else: 336 arg_param = "{}" 337 out += f" return getLog(redfish::registries::{namespace_name}::Index::{function_name}, {arg_param});" 338 out += "\n}\n\n" 339 if registry_name == "Base": 340 args.insert(0, "crow::Response& res") 341 if entry_id == "InternalError": 342 if is_header: 343 args.append( 344 "std::source_location location = std::source_location::current()" 345 ) 346 else: 347 args.append("const std::source_location location") 348 arg = ", ".join(args) 349 out += f"void {function_name}({arg})" 350 if is_header: 351 out += ";\n" 352 else: 353 out += "\n{\n" 354 if entry_id == "InternalError": 355 out += """BMCWEB_LOG_CRITICAL("Internal Error {}({}:{}) `{}`: ", location.file_name(), 356 location.line(), location.column(), 357 location.function_name());\n""" 358 359 if entry_id == "ServiceTemporarilyUnavailable": 360 out += "res.addHeader(boost::beast::http::field::retry_after, arg1);" 361 362 res = get_response_code(entry_id, entry) 363 if res: 364 out += f" res.result(boost::beast::http::status::{res});\n" 365 args_out = ", ".join([f"arg{x+1}" for x in range(len(argtypes))]) 366 367 addMessageToJson = { 368 "PropertyDuplicate": 1, 369 "ResourceAlreadyExists": 2, 370 "CreateFailedMissingReqProperties": 1, 371 "PropertyValueFormatError": 2, 372 "PropertyValueNotInList": 2, 373 "PropertyValueTypeError": 2, 374 "PropertyValueError": 1, 375 "PropertyNotWritable": 1, 376 "PropertyValueModified": 1, 377 "PropertyMissing": 1, 378 } 379 380 addMessageToRoot = [ 381 "SessionTerminated", 382 "SubscriptionTerminated", 383 "AccountRemoved", 384 "Created", 385 "Success", 386 "PasswordChangeRequired", 387 ] 388 389 if entry_id in addMessageToJson: 390 out += f" addMessageToJson(res.jsonValue, {function_name}({args_out}), arg{addMessageToJson[entry_id]});\n" 391 elif entry_id in addMessageToRoot: 392 out += f" addMessageToJsonRoot(res.jsonValue, {function_name}({args_out}));\n" 393 else: 394 out += f" addMessageToErrorJson(res.jsonValue, {function_name}({args_out}));\n" 395 out += "}\n" 396 out += "\n" 397 return out 398 399 400def create_error_registry( 401 entry, registry_version, registry_name, namespace_name, filename 402): 403 file, json_dict, namespace, url = entry 404 base_filename = filename + "_messages" 405 406 error_messages_hpp = os.path.join( 407 SCRIPT_DIR, "..", "redfish-core", "include", f"{base_filename}.hpp" 408 ) 409 messages = json_dict["Messages"] 410 411 with open( 412 error_messages_hpp, 413 "w", 414 ) as out: 415 out.write(PRAGMA_ONCE) 416 out.write(WARNING) 417 out.write( 418 """ 419 420#include "http_response.hpp" 421 422#include <boost/url/url_view_base.hpp> 423#include <nlohmann/json.hpp> 424 425#include <source_location> 426#include <string_view> 427 428// IWYU pragma: no_forward_declare crow::Response 429 430namespace redfish 431{ 432 433namespace messages 434{ 435""" 436 ) 437 if registry_name == "Base": 438 out.write( 439 f'constexpr const char* messageVersionPrefix = "{registry_name}.{registry_version}.";' 440 ) 441 out.write( 442 """ 443 constexpr const char* messageAnnotation = "@Message.ExtendedInfo"; 444 445 /** 446 * @brief Moves all error messages from the |source| JSON to |target| 447 */ 448 void moveErrorsToErrorJson(nlohmann::json& target, nlohmann::json& source); 449 450 """ 451 ) 452 for entry_id, entry in messages.items(): 453 message = entry["Message"] 454 for index in range(1, 10): 455 message = message.replace(f"'%{index}'", f"<arg{index}>") 456 message = message.replace(f"%{index}", f"<arg{index}>") 457 458 if registry_name == "Base": 459 out.write("/**\n") 460 out.write(f"* @brief Formats {entry_id} message into JSON\n") 461 out.write(f'* Message body: "{message}"\n') 462 out.write("*\n") 463 arg_index = 0 464 for arg_index, arg in enumerate(entry.get("ParamTypes", [])): 465 arg_index += 1 466 467 out.write( 468 f"* @param[in] arg{arg_index} Parameter of message that will replace %{arg_index} in its body.\n" 469 ) 470 out.write("*\n") 471 out.write( 472 f"* @returns Message {entry_id} formatted to JSON */\n" 473 ) 474 475 out.write( 476 make_error_function( 477 entry_id, entry, True, registry_name, namespace_name 478 ) 479 ) 480 out.write(" }\n") 481 out.write("}\n") 482 483 error_messages_cpp = os.path.join( 484 SCRIPT_DIR, "..", "redfish-core", "src", f"{base_filename}.cpp" 485 ) 486 with open( 487 error_messages_cpp, 488 "w", 489 ) as out: 490 out.write(WARNING) 491 out.write(f'\n#include "{base_filename}.hpp"\n') 492 headers = [] 493 494 headers.append('"registries.hpp"') 495 if registry_name == "Base": 496 reg_name_lower = "base" 497 headers.append('"http_response.hpp"') 498 headers.append('"logging.hpp"') 499 headers.append("<boost/beast/http/field.hpp>") 500 headers.append("<boost/beast/http/status.hpp>") 501 headers.append("<boost/url/url_view_base.hpp>") 502 headers.append("<source_location>") 503 else: 504 reg_name_lower = namespace_name.lower() 505 headers.append(f'"registries/{reg_name_lower}_message_registry.hpp"') 506 507 headers.append("<nlohmann/json.hpp>") 508 headers.append("<array>") 509 headers.append("<cstddef>") 510 headers.append("<span>") 511 512 if registry_name not in ("ResourceEvent", "HeartbeatEvent"): 513 headers.append("<cstdint>") 514 headers.append("<string>") 515 headers.append("<string_view>") 516 517 for header in headers: 518 out.write(f"#include {header}\n") 519 520 out.write( 521 """ 522// Clang can't seem to decide whether this header needs to be included or not, 523// and is inconsistent. Include it for now 524// NOLINTNEXTLINE(misc-include-cleaner) 525#include <utility> 526 527namespace redfish 528{ 529 530namespace messages 531{ 532""" 533 ) 534 535 if registry_name == "Base": 536 out.write( 537 """ 538static void addMessageToErrorJson(nlohmann::json& target, 539 const nlohmann::json& message) 540{ 541 auto& error = target["error"]; 542 543 // If this is the first error message, fill in the information from the 544 // first error message to the top level struct 545 if (!error.is_object()) 546 { 547 auto messageIdIterator = message.find("MessageId"); 548 if (messageIdIterator == message.end()) 549 { 550 BMCWEB_LOG_CRITICAL( 551 "Attempt to add error message without MessageId"); 552 return; 553 } 554 555 auto messageFieldIterator = message.find("Message"); 556 if (messageFieldIterator == message.end()) 557 { 558 BMCWEB_LOG_CRITICAL("Attempt to add error message without Message"); 559 return; 560 } 561 error["code"] = *messageIdIterator; 562 error["message"] = *messageFieldIterator; 563 } 564 else 565 { 566 // More than 1 error occurred, so the message has to be generic 567 error["code"] = std::string(messageVersionPrefix) + "GeneralError"; 568 error["message"] = "A general error has occurred. See Resolution for " 569 "information on how to resolve the error."; 570 } 571 572 // This check could technically be done in the default construction 573 // branch above, but because we need the pointer to the extended info field 574 // anyway, it's more efficient to do it here. 575 auto& extendedInfo = error[messages::messageAnnotation]; 576 if (!extendedInfo.is_array()) 577 { 578 extendedInfo = nlohmann::json::array(); 579 } 580 581 extendedInfo.push_back(message); 582} 583 584void moveErrorsToErrorJson(nlohmann::json& target, nlohmann::json& source) 585{ 586 if (!source.is_object()) 587 { 588 return; 589 } 590 auto errorIt = source.find("error"); 591 if (errorIt == source.end()) 592 { 593 // caller puts error message in root 594 messages::addMessageToErrorJson(target, source); 595 source.clear(); 596 return; 597 } 598 auto extendedInfoIt = errorIt->find(messages::messageAnnotation); 599 if (extendedInfoIt == errorIt->end()) 600 { 601 return; 602 } 603 const nlohmann::json::array_t* extendedInfo = 604 (*extendedInfoIt).get_ptr<const nlohmann::json::array_t*>(); 605 if (extendedInfo == nullptr) 606 { 607 source.erase(errorIt); 608 return; 609 } 610 for (const nlohmann::json& message : *extendedInfo) 611 { 612 addMessageToErrorJson(target, message); 613 } 614 source.erase(errorIt); 615} 616 617static void addMessageToJsonRoot(nlohmann::json& target, 618 const nlohmann::json& message) 619{ 620 if (!target[messages::messageAnnotation].is_array()) 621 { 622 // Force object to be an array 623 target[messages::messageAnnotation] = nlohmann::json::array(); 624 } 625 626 target[messages::messageAnnotation].push_back(message); 627} 628 629static void addMessageToJson(nlohmann::json& target, 630 const nlohmann::json& message, 631 std::string_view fieldPath) 632{ 633 std::string extendedInfo(fieldPath); 634 extendedInfo += messages::messageAnnotation; 635 636 nlohmann::json& field = target[extendedInfo]; 637 if (!field.is_array()) 638 { 639 // Force object to be an array 640 field = nlohmann::json::array(); 641 } 642 643 // Object exists and it is an array so we can just push in the message 644 field.push_back(message); 645} 646""" 647 ) 648 out.write( 649 """ 650static nlohmann::json getLog(redfish::registries::{namespace_name}::Index name, 651 std::span<const std::string_view> args) 652{{ 653 size_t index = static_cast<size_t>(name); 654 if (index >= redfish::registries::{namespace_name}::registry.size()) 655 {{ 656 return {{}}; 657 }} 658 return getLogFromRegistry(redfish::registries::{namespace_name}::header, 659 redfish::registries::{namespace_name}::registry, index, args); 660}} 661 662""".format( 663 namespace_name=namespace_name 664 ) 665 ) 666 for entry_id, entry in messages.items(): 667 out.write( 668 f"""/** 669 * @internal 670 * @brief Formats {entry_id} message into JSON 671 * 672 * See header file for more information 673 * @endinternal 674 */ 675""" 676 ) 677 message = entry["Message"] 678 out.write( 679 make_error_function( 680 entry_id, entry, False, registry_name, namespace_name 681 ) 682 ) 683 684 out.write(" }\n") 685 out.write("}\n") 686 os.system(f"clang-format -i {error_messages_hpp} {error_messages_cpp}") 687 688 689def make_privilege_registry(): 690 path, json_file, type_name, url = make_getter( 691 "Redfish_1.5.0_PrivilegeRegistry.json", 692 "privilege_registry.hpp", 693 "privilege", 694 ) 695 with open(path, "w") as registry: 696 registry.write(PRIVILEGE_HEADER) 697 698 privilege_dict = {} 699 for mapping in json_file["Mappings"]: 700 # first pass, identify all the unique privilege sets 701 for operation, privilege_list in mapping["OperationMap"].items(): 702 privilege_dict[ 703 get_privilege_string_from_list(privilege_list) 704 ] = (privilege_list,) 705 for index, key in enumerate(privilege_dict): 706 (privilege_list,) = privilege_dict[key] 707 name = get_variable_name_for_privilege_set(privilege_list) 708 registry.write( 709 "const std::array<Privileges, {length}> " 710 "privilegeSet{name} = {key};\n".format( 711 length=len(privilege_list), name=name, key=key 712 ) 713 ) 714 privilege_dict[key] = (privilege_list, name) 715 716 for mapping in json_file["Mappings"]: 717 entity = mapping["Entity"] 718 registry.write("// {}\n".format(entity)) 719 for operation, privilege_list in mapping["OperationMap"].items(): 720 privilege_string = get_privilege_string_from_list( 721 privilege_list 722 ) 723 operation = operation.lower() 724 725 registry.write( 726 "const static auto& {}{} = privilegeSet{};\n".format( 727 operation, entity, privilege_dict[privilege_string][1] 728 ) 729 ) 730 registry.write("\n") 731 registry.write( 732 "} // namespace redfish::privileges\n// clang-format on\n" 733 ) 734 735 736def to_pascal_case(text): 737 s = text.replace("_", " ") 738 s = s.split() 739 if len(text) == 0: 740 return text 741 return "".join(i.capitalize() for i in s[0:]) 742 743 744def main(): 745 dmtf_registries = OrderedDict( 746 [ 747 ("base", "1.19.0"), 748 ("composition", "1.1.2"), 749 ("environmental", "1.0.1"), 750 ("ethernet_fabric", "1.0.1"), 751 ("fabric", "1.0.2"), 752 ("heartbeat_event", "1.0.1"), 753 ("job_event", "1.0.1"), 754 ("license", "1.0.3"), 755 ("log_service", "1.0.1"), 756 ("network_device", "1.0.3"), 757 ("platform", "1.0.1"), 758 ("power", "1.0.1"), 759 ("resource_event", "1.3.0"), 760 ("sensor_event", "1.0.1"), 761 ("storage_device", "1.2.1"), 762 ("task_event", "1.0.3"), 763 ("telemetry", "1.0.0"), 764 ("update", "1.0.2"), 765 ] 766 ) 767 768 parser = argparse.ArgumentParser() 769 parser.add_argument( 770 "--registries", 771 type=str, 772 default="privilege,openbmc," 773 + ",".join([dmtf for dmtf in dmtf_registries]), 774 help="Comma delimited list of registries to update", 775 ) 776 777 args = parser.parse_args() 778 779 registries = set(args.registries.split(",")) 780 files = [] 781 registries_map = OrderedDict() 782 783 for registry, version in dmtf_registries.items(): 784 if registry in registries: 785 registry_pascal_case = to_pascal_case(registry) 786 files.append( 787 make_getter( 788 f"{registry_pascal_case}.{version}.json", 789 f"{registry}_message_registry.hpp", 790 registry, 791 ) 792 ) 793 registries_map[registry] = files[-1] 794 if "openbmc" in registries: 795 files.append(openbmc_local_getter()) 796 797 update_registries(files) 798 799 if "base" in registries_map: 800 create_error_registry( 801 registries_map["base"], 802 dmtf_registries["base"], 803 "Base", 804 "base", 805 "error", 806 ) 807 if "heartbeat_event" in registries_map: 808 create_error_registry( 809 registries_map["heartbeat_event"], 810 dmtf_registries["heartbeat_event"], 811 "HeartbeatEvent", 812 "heartbeat_event", 813 "heartbeat", 814 ) 815 if "resource_event" in registries_map: 816 create_error_registry( 817 registries_map["resource_event"], 818 dmtf_registries["resource_event"], 819 "ResourceEvent", 820 "resource_event", 821 "resource", 822 ) 823 if "task_event" in registries_map: 824 create_error_registry( 825 registries_map["task_event"], 826 dmtf_registries["task_event"], 827 "TaskEvent", 828 "task_event", 829 "task", 830 ) 831 832 if "privilege" in registries: 833 make_privilege_registry() 834 835 836if __name__ == "__main__": 837 main() 838