1#!/usr/bin/env python3 2import argparse 3import json 4import os 5 6import requests 7 8PRAGMA_ONCE = """#pragma once 9""" 10 11WARNING = """/**************************************************************** 12 * READ THIS WARNING FIRST 13 * This is an auto-generated header which contains definitions 14 * for Redfish DMTF defined messages. 15 * DO NOT modify this registry outside of running the 16 * parse_registries.py script. The definitions contained within 17 * this file are owned by DMTF. Any modifications to these files 18 * should be first pushed to the relevant registry in the DMTF 19 * github organization. 20 ***************************************************************/""" 21 22REGISTRY_HEADER = ( 23 PRAGMA_ONCE 24 + WARNING 25 + """ 26#include "registries.hpp" 27 28#include <array> 29 30// clang-format off 31 32namespace redfish::registries::{} 33{{ 34""" 35) 36 37SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__)) 38 39include_path = os.path.realpath( 40 os.path.join(SCRIPT_DIR, "..", "redfish-core", "include", "registries") 41) 42 43proxies = {"https": os.environ.get("https_proxy", None)} 44 45 46def make_getter(dmtf_name, header_name, type_name): 47 url = "https://redfish.dmtf.org/registries/{}".format(dmtf_name) 48 dmtf = requests.get(url, proxies=proxies) 49 dmtf.raise_for_status() 50 json_file = json.loads(dmtf.text) 51 path = os.path.join(include_path, header_name) 52 return (path, json_file, type_name, url) 53 54 55def openbmc_local_getter(): 56 url = "" 57 with open( 58 os.path.join( 59 SCRIPT_DIR, 60 "..", 61 "redfish-core", 62 "include", 63 "registries", 64 "openbmc.json", 65 ), 66 "rb", 67 ) as json_file: 68 json_file = json.load(json_file) 69 70 path = os.path.join(include_path, "openbmc_message_registry.hpp") 71 return (path, json_file, "openbmc", url) 72 73 74def update_registries(files): 75 # Remove the old files 76 for file, json_dict, namespace, url in files: 77 try: 78 os.remove(file) 79 except BaseException: 80 print("{} not found".format(file)) 81 82 with open(file, "w") as registry: 83 registry.write(REGISTRY_HEADER.format(namespace)) 84 # Parse the Registry header info 85 registry.write( 86 "const Header header = {{\n" 87 ' "{json_dict[@Redfish.Copyright]}",\n' 88 ' "{json_dict[@odata.type]}",\n' 89 ' "{json_dict[Id]}",\n' 90 ' "{json_dict[Name]}",\n' 91 ' "{json_dict[Language]}",\n' 92 ' "{json_dict[Description]}",\n' 93 ' "{json_dict[RegistryPrefix]}",\n' 94 ' "{json_dict[RegistryVersion]}",\n' 95 ' "{json_dict[OwningEntity]}",\n' 96 "}};\n" 97 "constexpr const char* url =\n" 98 ' "{url}";\n' 99 "\n" 100 "constexpr std::array registry =\n" 101 "{{\n".format( 102 json_dict=json_dict, 103 url=url, 104 ) 105 ) 106 107 messages_sorted = sorted(json_dict["Messages"].items()) 108 for messageId, message in messages_sorted: 109 registry.write( 110 " MessageEntry{{\n" 111 ' "{messageId}",\n' 112 " {{\n" 113 ' "{message[Description]}",\n' 114 ' "{message[Message]}",\n' 115 ' "{message[MessageSeverity]}",\n' 116 " {message[NumberOfArgs]},\n" 117 " {{".format( 118 messageId=messageId, message=message 119 ) 120 ) 121 paramTypes = message.get("ParamTypes") 122 if paramTypes: 123 for paramType in paramTypes: 124 registry.write( 125 '\n "{}",'.format(paramType) 126 ) 127 registry.write("\n },\n") 128 else: 129 registry.write("},\n") 130 registry.write( 131 ' "{message[Resolution]}",\n' 132 " }}}},\n".format(message=message) 133 ) 134 135 registry.write("\n};\n\nenum class Index\n{\n") 136 for index, (messageId, message) in enumerate(messages_sorted): 137 messageId = messageId[0].lower() + messageId[1:] 138 registry.write(" {} = {},\n".format(messageId, index)) 139 registry.write( 140 "}};\n}} // namespace redfish::registries::{}\n".format( 141 namespace 142 ) 143 ) 144 145 146def get_privilege_string_from_list(privilege_list): 147 privilege_string = "{{\n" 148 for privilege_json in privilege_list: 149 privileges = privilege_json["Privilege"] 150 privilege_string += " {" 151 for privilege in privileges: 152 if privilege == "NoAuth": 153 continue 154 privilege_string += '"' 155 privilege_string += privilege 156 privilege_string += '",\n' 157 if privilege != "NoAuth": 158 privilege_string = privilege_string[:-2] 159 privilege_string += "}" 160 privilege_string += ",\n" 161 privilege_string = privilege_string[:-2] 162 privilege_string += "\n}}" 163 return privilege_string 164 165 166def get_variable_name_for_privilege_set(privilege_list): 167 names = [] 168 for privilege_json in privilege_list: 169 privileges = privilege_json["Privilege"] 170 names.append("And".join(privileges)) 171 return "Or".join(names) 172 173 174PRIVILEGE_HEADER = ( 175 PRAGMA_ONCE 176 + WARNING 177 + """ 178#include "privileges.hpp" 179 180#include <array> 181 182// clang-format off 183 184namespace redfish::privileges 185{ 186""" 187) 188 189 190def make_privilege_registry(): 191 path, json_file, type_name, url = make_getter( 192 "Redfish_1.3.0_PrivilegeRegistry.json", 193 "privilege_registry.hpp", 194 "privilege", 195 ) 196 with open(path, "w") as registry: 197 registry.write(PRIVILEGE_HEADER) 198 199 privilege_dict = {} 200 for mapping in json_file["Mappings"]: 201 # first pass, identify all the unique privilege sets 202 for operation, privilege_list in mapping["OperationMap"].items(): 203 privilege_dict[ 204 get_privilege_string_from_list(privilege_list) 205 ] = (privilege_list,) 206 for index, key in enumerate(privilege_dict): 207 (privilege_list,) = privilege_dict[key] 208 name = get_variable_name_for_privilege_set(privilege_list) 209 registry.write( 210 "const std::array<Privileges, {length}> " 211 "privilegeSet{name} = {key};\n".format( 212 length=len(privilege_list), name=name, key=key 213 ) 214 ) 215 privilege_dict[key] = (privilege_list, name) 216 217 for mapping in json_file["Mappings"]: 218 entity = mapping["Entity"] 219 registry.write("// {}\n".format(entity)) 220 for operation, privilege_list in mapping["OperationMap"].items(): 221 privilege_string = get_privilege_string_from_list( 222 privilege_list 223 ) 224 operation = operation.lower() 225 226 registry.write( 227 "const static auto& {}{} = privilegeSet{};\n".format( 228 operation, entity, privilege_dict[privilege_string][1] 229 ) 230 ) 231 registry.write("\n") 232 registry.write( 233 "} // namespace redfish::privileges\n// clang-format on\n" 234 ) 235 236 237def main(): 238 parser = argparse.ArgumentParser() 239 parser.add_argument( 240 "--registries", 241 type=str, 242 default="base,task_event,resource_event,privilege,openbmc", 243 help="Comma delimited list of registries to update", 244 ) 245 246 args = parser.parse_args() 247 248 registries = set(args.registries.split(",")) 249 files = [] 250 251 if "base" in registries: 252 files.append( 253 make_getter( 254 "Base.1.16.0.json", "base_message_registry.hpp", "base" 255 ) 256 ) 257 if "task_event" in registries: 258 files.append( 259 make_getter( 260 "TaskEvent.1.0.3.json", 261 "task_event_message_registry.hpp", 262 "task_event", 263 ) 264 ) 265 if "resource_event" in registries: 266 files.append( 267 make_getter( 268 "ResourceEvent.1.3.0.json", 269 "resource_event_message_registry.hpp", 270 "resource_event", 271 ) 272 ) 273 if "openbmc" in registries: 274 files.append(openbmc_local_getter()) 275 276 update_registries(files) 277 278 if "privilege" in registries: 279 make_privilege_registry() 280 281 282if __name__ == "__main__": 283 main() 284