1#!/usr/bin/env python3 2import json 3import os 4 5import requests 6import argparse 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 = PRAGMA_ONCE + WARNING + ''' 23#include "registries.hpp" 24 25#include <array> 26 27// clang-format off 28 29namespace redfish::registries::{} 30{{ 31''' 32 33SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__)) 34 35include_path = os.path.realpath( 36 os.path.join( 37 SCRIPT_DIR, 38 "..", 39 "redfish-core", 40 "include", 41 "registries")) 42 43proxies = { 44 'https': os.environ.get("https_proxy", None) 45} 46 47 48def make_getter(dmtf_name, header_name, type_name): 49 url = 'https://redfish.dmtf.org/registries/{}'.format(dmtf_name) 50 dmtf = requests.get(url, proxies=proxies) 51 dmtf.raise_for_status() 52 json_file = json.loads(dmtf.text) 53 path = os.path.join(include_path, header_name) 54 return (path, json_file, type_name, url) 55 56 57def update_registries(files): 58 # Remove the old files 59 for file, json_dict, namespace, url in files: 60 try: 61 os.remove(file) 62 except BaseException: 63 print("{} not found".format(file)) 64 65 with open(file, 'w') as registry: 66 registry.write(REGISTRY_HEADER.format(namespace)) 67 # Parse the Registry header info 68 registry.write( 69 "const Header header = {{\n" 70 " \"{json_dict[@Redfish.Copyright]}\",\n" 71 " \"{json_dict[@odata.type]}\",\n" 72 " \"{json_dict[Id]}\",\n" 73 " \"{json_dict[Name]}\",\n" 74 " \"{json_dict[Language]}\",\n" 75 " \"{json_dict[Description]}\",\n" 76 " \"{json_dict[RegistryPrefix]}\",\n" 77 " \"{json_dict[RegistryVersion]}\",\n" 78 " \"{json_dict[OwningEntity]}\",\n" 79 "}};\n" 80 "constexpr const char* url =\n" 81 " \"{url}\";\n" 82 "\n" 83 "constexpr std::array registry =\n" 84 "{{\n".format( 85 json_dict=json_dict, 86 url=url, 87 )) 88 89 messages_sorted = sorted(json_dict["Messages"].items()) 90 for messageId, message in messages_sorted: 91 registry.write( 92 " MessageEntry{{\n" 93 " \"{messageId}\",\n" 94 " {{\n" 95 " \"{message[Description]}\",\n" 96 " \"{message[Message]}\",\n" 97 " \"{message[MessageSeverity]}\",\n" 98 " {message[NumberOfArgs]},\n" 99 " {{".format( 100 messageId=messageId, 101 message=message 102 )) 103 paramTypes = message.get("ParamTypes") 104 if paramTypes: 105 for paramType in paramTypes: 106 registry.write( 107 "\n" 108 " \"{}\",".format(paramType) 109 ) 110 registry.write("\n },\n") 111 else: 112 registry.write("},\n") 113 registry.write( 114 " \"{message[Resolution]}\",\n" 115 " }}}},\n".format(message=message)) 116 117 registry.write( 118 "\n};\n" 119 "\n" 120 "enum class Index\n" 121 "{\n" 122 ) 123 for index, (messageId, message) in enumerate(messages_sorted): 124 messageId = messageId[0].lower() + messageId[1:] 125 registry.write( 126 " {} = {},\n".format(messageId, index)) 127 registry.write( 128 "}};\n" 129 "}} // namespace redfish::registries::{}\n" 130 .format(namespace)) 131 132 133def get_privilege_string_from_list(privilege_list): 134 privilege_string = "{{\n" 135 for privilege_json in privilege_list: 136 privileges = privilege_json["Privilege"] 137 privilege_string += " {" 138 for privilege in privileges: 139 if privilege == "NoAuth": 140 continue 141 privilege_string += "\"" 142 privilege_string += privilege 143 privilege_string += "\",\n" 144 if privilege != "NoAuth": 145 privilege_string = privilege_string[:-2] 146 privilege_string += "}" 147 privilege_string += ",\n" 148 privilege_string = privilege_string[:-2] 149 privilege_string += "\n}}" 150 return privilege_string 151 152 153def get_variable_name_for_privilege_set(privilege_list): 154 names = [] 155 for privilege_json in privilege_list: 156 privileges = privilege_json["Privilege"] 157 names.append("And".join(privileges)) 158 return "Or".join(names) 159 160 161PRIVILEGE_HEADER = PRAGMA_ONCE + WARNING + ''' 162#include "privileges.hpp" 163 164#include <array> 165 166// clang-format off 167 168namespace redfish::privileges 169{ 170''' 171 172 173def make_privilege_registry(): 174 path, json_file, type_name, url = \ 175 make_getter('Redfish_1.3.0_PrivilegeRegistry.json', 176 'privilege_registry.hpp', 'privilege') 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[get_privilege_string_from_list( 185 privilege_list)] = (privilege_list, ) 186 for index, key in enumerate(privilege_dict): 187 (privilege_list, ) = privilege_dict[key] 188 name = get_variable_name_for_privilege_set(privilege_list) 189 registry.write( 190 "const std::array<Privileges, {length}> " 191 "privilegeSet{name} = {key};\n" 192 .format(length=len(privilege_list), name=name, key=key) 193 ) 194 privilege_dict[key] = (privilege_list, name) 195 196 for mapping in json_file["Mappings"]: 197 entity = mapping["Entity"] 198 registry.write("// {}\n".format(entity)) 199 for operation, privilege_list in mapping["OperationMap"].items(): 200 privilege_string = get_privilege_string_from_list( 201 privilege_list) 202 operation = operation.lower() 203 204 registry.write( 205 "const static auto& {}{} = privilegeSet{};\n".format( 206 operation, 207 entity, 208 privilege_dict[privilege_string][1])) 209 registry.write("\n") 210 registry.write( 211 "} // namespace redfish::privileges\n" 212 "// clang-format on\n") 213 214 215def main(): 216 parser = argparse.ArgumentParser() 217 parser.add_argument( 218 '--registries', type=str, 219 default="base,task_event,resource_event,privilege", 220 help="Comma delimited list of registries to update") 221 222 args = parser.parse_args() 223 224 registries = set(args.registries.split(",")) 225 files = [] 226 227 if "base" in registries: 228 files.append(make_getter('Base.1.13.0.json', 229 'base_message_registry.hpp', 230 'base')) 231 if "task_event" in registries: 232 files.append(make_getter('TaskEvent.1.0.3.json', 233 'task_event_message_registry.hpp', 234 'task_event')) 235 if "resource_event" in registries: 236 files.append(make_getter('ResourceEvent.1.0.3.json', 237 'resource_event_message_registry.hpp', 238 'resource_event')) 239 240 update_registries(files) 241 242 if "privilege" in registries: 243 make_privilege_registry() 244 245 246if __name__ == "__main__": 247 main() 248