1#!/usr/bin/env python3 2import os 3import shutil 4import zipfile 5from collections import OrderedDict, defaultdict 6from io import BytesIO 7 8import generate_schema_enums 9import requests 10from generate_schema_collections import generate_top_collections 11 12VERSION = "DSP8010_2023.3" 13 14WARNING = """/**************************************************************** 15 * READ THIS WARNING FIRST 16 * This is an auto-generated header which contains definitions 17 * for Redfish DMTF defined schemas. 18 * DO NOT modify this registry outside of running the 19 * update_schemas.py script. The definitions contained within 20 * this file are owned by DMTF. Any modifications to these files 21 * should be first pushed to the relevant registry in the DMTF 22 * github organization. 23 ***************************************************************/""" 24 25SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__)) 26 27proxies = {"https": os.environ.get("https_proxy", None)} 28 29r = requests.get( 30 "https://www.dmtf.org/sites/default/files/standards/documents/" 31 + VERSION 32 + ".zip", 33 proxies=proxies, 34) 35 36r.raise_for_status() 37 38 39static_path = os.path.realpath( 40 os.path.join(SCRIPT_DIR, "..", "static", "redfish", "v1") 41) 42 43 44cpp_path = os.path.realpath( 45 os.path.join(SCRIPT_DIR, "..", "redfish-core", "include") 46) 47 48 49schema_path = os.path.join( 50 SCRIPT_DIR, "..", "redfish-core", "schema", "dmtf", "csdl" 51) 52json_schema_path = os.path.join( 53 SCRIPT_DIR, "..", "redfish-core", "schema", "dmtf", "json-schema" 54) 55 56zipBytesIO = BytesIO(r.content) 57zip_ref = zipfile.ZipFile(zipBytesIO) 58 59 60class SchemaVersion: 61 """ 62 A Python class for sorting Redfish schema versions. Allows sorting Redfish 63 versions in the way humans expect, by comparing version strings as lists 64 (ie 0_2_0 comes before 0_10_0) in the way humans expect. It does case 65 insensitive schema name comparisons 66 """ 67 68 def __init__(self, key): 69 key = str.casefold(key) 70 71 split_tup = key.split(".") 72 self.version_pieces = [split_tup[0]] 73 if len(split_tup) < 2: 74 return 75 version = split_tup[1] 76 77 if version.startswith("v"): 78 version = version[1:] 79 if any(char.isdigit() for char in version): 80 self.version_pieces.extend([int(x) for x in version.split("_")]) 81 82 def __lt__(self, other): 83 return self.version_pieces < other.version_pieces 84 85 86# Remove the old files 87skip_prefixes = ["Oem", "OpenBMC"] 88if os.path.exists(schema_path): 89 files = [ 90 os.path.join(schema_path, f) 91 for f in os.listdir(schema_path) 92 if not any([f.startswith(prefix) for prefix in skip_prefixes]) 93 ] 94 for f in files: 95 os.remove(f) 96if os.path.exists(json_schema_path): 97 files = [ 98 os.path.join(json_schema_path, f) 99 for f in os.listdir(json_schema_path) 100 if not any([f.startswith(prefix) for prefix in skip_prefixes]) 101 ] 102 for f in files: 103 if os.path.isfile(f): 104 os.remove(f) 105 else: 106 shutil.rmtree(f) 107 108if not os.path.exists(schema_path): 109 os.makedirs(schema_path) 110if not os.path.exists(json_schema_path): 111 os.makedirs(json_schema_path) 112 113csdl_filenames = [] 114json_schema_files = defaultdict(list) 115 116for zip_file in zip_ref.infolist(): 117 if zip_file.is_dir(): 118 continue 119 if zip_file.filename.startswith("csdl/"): 120 csdl_filenames.append(os.path.basename(zip_file.filename)) 121 elif zip_file.filename.startswith("json-schema/"): 122 filename = os.path.basename(zip_file.filename) 123 filenamesplit = filename.split(".") 124 json_schema_files[filenamesplit[0]].append(filename) 125 elif zip_file.filename.startswith("openapi/"): 126 pass 127 elif zip_file.filename.startswith("dictionaries/"): 128 pass 129 130# sort the json files by version 131for key, value in json_schema_files.items(): 132 value.sort(key=SchemaVersion, reverse=True) 133 134# Create a dictionary ordered by schema name 135json_schema_files = OrderedDict( 136 sorted(json_schema_files.items(), key=lambda x: SchemaVersion(x[0])) 137) 138for csdl_file in csdl_filenames: 139 with open(os.path.join(schema_path, csdl_file), "wb") as schema_out: 140 content = zip_ref.read(os.path.join("csdl", csdl_file)) 141 content = content.replace(b"\r\n", b"\n") 142 schema_out.write(content) 143 144for schema, version in json_schema_files.items(): 145 zip_filepath = os.path.join("json-schema", version[0]) 146 147 with open(os.path.join(json_schema_path, version[0]), "wb") as schema_file: 148 schema_file.write(zip_ref.read(zip_filepath).replace(b"\r\n", b"\n")) 149 150with open(os.path.join(cpp_path, "schemas.hpp"), "w") as hpp_file: 151 schemas = [] 152 for root, dirs, files in os.walk( 153 os.path.join(SCRIPT_DIR, "..", "static", "redfish", "v1", "schema") 154 ): 155 for csdl_file in sorted(files, key=SchemaVersion): 156 if csdl_file.endswith(".xml"): 157 schemas.append(csdl_file.replace("_v1.xml", "")) 158 hpp_file.write( 159 "#pragma once\n" 160 "{WARNING}\n" 161 "// clang-format off\n" 162 "#include <array>\n" 163 "#include <string_view>\n" 164 "\n" 165 "namespace redfish\n" 166 "{{\n" 167 " constexpr std::array<std::string_view,{SIZE}> schemas {{\n".format( 168 WARNING=WARNING, 169 SIZE=len(schemas), 170 ) 171 ) 172 for schema in schemas: 173 hpp_file.write(' "{}",\n'.format(schema)) 174 175 hpp_file.write(" };\n}\n") 176 177zip_ref.close() 178 179generate_schema_enums.main() 180generate_top_collections() 181