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 update_registries(files): 56 # Remove the old files 57 for file, json_dict, namespace, url in files: 58 try: 59 os.remove(file) 60 except BaseException: 61 print("{} not found".format(file)) 62 63 with open(file, "w") as registry: 64 registry.write(REGISTRY_HEADER.format(namespace)) 65 # Parse the Registry header info 66 registry.write( 67 "const Header header = {{\n" 68 ' "{json_dict[@Redfish.Copyright]}",\n' 69 ' "{json_dict[@odata.type]}",\n' 70 ' "{json_dict[Id]}",\n' 71 ' "{json_dict[Name]}",\n' 72 ' "{json_dict[Language]}",\n' 73 ' "{json_dict[Description]}",\n' 74 ' "{json_dict[RegistryPrefix]}",\n' 75 ' "{json_dict[RegistryVersion]}",\n' 76 ' "{json_dict[OwningEntity]}",\n' 77 "}};\n" 78 "constexpr const char* url =\n" 79 ' "{url}";\n' 80 "\n" 81 "constexpr std::array registry =\n" 82 "{{\n".format( 83 json_dict=json_dict, 84 url=url, 85 ) 86 ) 87 88 messages_sorted = sorted(json_dict["Messages"].items()) 89 for messageId, message in messages_sorted: 90 registry.write( 91 " MessageEntry{{\n" 92 ' "{messageId}",\n' 93 " {{\n" 94 ' "{message[Description]}",\n' 95 ' "{message[Message]}",\n' 96 ' "{message[MessageSeverity]}",\n' 97 " {message[NumberOfArgs]},\n" 98 " {{".format( 99 messageId=messageId, message=message 100 ) 101 ) 102 paramTypes = message.get("ParamTypes") 103 if paramTypes: 104 for paramType in paramTypes: 105 registry.write( 106 '\n "{}",'.format(paramType) 107 ) 108 registry.write("\n },\n") 109 else: 110 registry.write("},\n") 111 registry.write( 112 ' "{message[Resolution]}",\n' 113 " }}}},\n".format(message=message) 114 ) 115 116 registry.write("\n};\n\nenum class Index\n{\n") 117 for index, (messageId, message) in enumerate(messages_sorted): 118 messageId = messageId[0].lower() + messageId[1:] 119 registry.write(" {} = {},\n".format(messageId, index)) 120 registry.write( 121 "}};\n}} // namespace redfish::registries::{}\n".format( 122 namespace 123 ) 124 ) 125 126 127def get_privilege_string_from_list(privilege_list): 128 privilege_string = "{{\n" 129 for privilege_json in privilege_list: 130 privileges = privilege_json["Privilege"] 131 privilege_string += " {" 132 for privilege in privileges: 133 if privilege == "NoAuth": 134 continue 135 privilege_string += '"' 136 privilege_string += privilege 137 privilege_string += '",\n' 138 if privilege != "NoAuth": 139 privilege_string = privilege_string[:-2] 140 privilege_string += "}" 141 privilege_string += ",\n" 142 privilege_string = privilege_string[:-2] 143 privilege_string += "\n}}" 144 return privilege_string 145 146 147def get_variable_name_for_privilege_set(privilege_list): 148 names = [] 149 for privilege_json in privilege_list: 150 privileges = privilege_json["Privilege"] 151 names.append("And".join(privileges)) 152 return "Or".join(names) 153 154 155PRIVILEGE_HEADER = ( 156 PRAGMA_ONCE 157 + WARNING 158 + """ 159#include "privileges.hpp" 160 161#include <array> 162 163// clang-format off 164 165namespace redfish::privileges 166{ 167""" 168) 169 170 171def make_privilege_registry(): 172 path, json_file, type_name, url = make_getter( 173 "Redfish_1.3.0_PrivilegeRegistry.json", 174 "privilege_registry.hpp", 175 "privilege", 176 ) 177 with open(path, "w") as registry: 178 registry.write(PRIVILEGE_HEADER) 179 180 privilege_dict = {} 181 for mapping in json_file["Mappings"]: 182 # first pass, identify all the unique privilege sets 183 for operation, privilege_list in mapping["OperationMap"].items(): 184 privilege_dict[ 185 get_privilege_string_from_list(privilege_list) 186 ] = (privilege_list,) 187 for index, key in enumerate(privilege_dict): 188 (privilege_list,) = privilege_dict[key] 189 name = get_variable_name_for_privilege_set(privilege_list) 190 registry.write( 191 "const std::array<Privileges, {length}> " 192 "privilegeSet{name} = {key};\n".format( 193 length=len(privilege_list), name=name, key=key 194 ) 195 ) 196 privilege_dict[key] = (privilege_list, name) 197 198 for mapping in json_file["Mappings"]: 199 entity = mapping["Entity"] 200 registry.write("// {}\n".format(entity)) 201 for operation, privilege_list in mapping["OperationMap"].items(): 202 privilege_string = get_privilege_string_from_list( 203 privilege_list 204 ) 205 operation = operation.lower() 206 207 registry.write( 208 "const static auto& {}{} = privilegeSet{};\n".format( 209 operation, entity, privilege_dict[privilege_string][1] 210 ) 211 ) 212 registry.write("\n") 213 registry.write( 214 "} // namespace redfish::privileges\n// clang-format on\n" 215 ) 216 217 218def main(): 219 parser = argparse.ArgumentParser() 220 parser.add_argument( 221 "--registries", 222 type=str, 223 default="base,task_event,resource_event,privilege", 224 help="Comma delimited list of registries to update", 225 ) 226 227 args = parser.parse_args() 228 229 registries = set(args.registries.split(",")) 230 files = [] 231 232 if "base" in registries: 233 files.append( 234 make_getter( 235 "Base.1.16.0.json", "base_message_registry.hpp", "base" 236 ) 237 ) 238 if "task_event" in registries: 239 files.append( 240 make_getter( 241 "TaskEvent.1.0.3.json", 242 "task_event_message_registry.hpp", 243 "task_event", 244 ) 245 ) 246 if "resource_event" in registries: 247 files.append( 248 make_getter( 249 "ResourceEvent.1.3.0.json", 250 "resource_event_message_registry.hpp", 251 "resource_event", 252 ) 253 ) 254 255 update_registries(files) 256 257 if "privilege" in registries: 258 make_privilege_registry() 259 260 261if __name__ == "__main__": 262 main() 263