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