1#!/usr/bin/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 12 13import xml.etree.ElementTree as ET 14 15VERSION = "DSP8010_2020.3" 16 17SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__)) 18 19proxies = { 20 'https': os.environ.get("https_proxy", None) 21} 22 23r = requests.get( 24 'https://www.dmtf.org/sites/default/files/standards/documents/' + 25 VERSION + 26 '.zip', 27 proxies=proxies) 28 29r.raise_for_status() 30 31static_path = os.path.realpath(os.path.join(SCRIPT_DIR, "..", "static", 32 "redfish", "v1")) 33 34schema_path = os.path.join(static_path, "schema") 35json_schema_path = os.path.join(static_path, "JsonSchemas") 36metadata_index_path = os.path.join(static_path, "$metadata", "index.xml") 37 38zipBytesIO = BytesIO(r.content) 39zip_ref = zipfile.ZipFile(zipBytesIO) 40 41# Remove the old files 42if os.path.exists(schema_path): 43 files = glob.glob(os.path.join(schema_path, '[!Oem]*')) 44 for f in files: 45 os.remove(f) 46if os.path.exists(json_schema_path): 47 files = glob.glob(os.path.join(json_schema_path, '[!Oem]*')) 48 for f in files: 49 if (os.path.isfile(f)): 50 os.remove(f) 51 else: 52 shutil.rmtree(f) 53os.remove(metadata_index_path) 54 55if not os.path.exists(schema_path): 56 os.makedirs(schema_path) 57if not os.path.exists(json_schema_path): 58 os.makedirs(json_schema_path) 59 60with open(metadata_index_path, 'w') as metadata_index: 61 62 metadata_index.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n") 63 metadata_index.write( 64 "<edmx:Edmx xmlns:edmx=\"http://docs.oasis-open.org/odata/ns/edmx\" Version=\"4.0\">\n") 65 66 for zip_filepath in zip_ref.namelist(): 67 if zip_filepath.startswith(VERSION + 68 '/csdl/') & (zip_filepath != VERSION + 69 "/csdl/") & (zip_filepath != VERSION + 70 "/csdl/"): 71 filename = os.path.basename(zip_filepath) 72 with open(os.path.join(schema_path, filename), 'wb') as schema_file: 73 74 metadata_index.write( 75 " <edmx:Reference Uri=\"/redfish/v1/schema/" + 76 filename + 77 "\">\n") 78 79 content = zip_ref.read(zip_filepath) 80 content = content.replace(b'\r\n', b'\n') 81 xml_root = ET.fromstring(content) 82 83 for edmx_child in xml_root: 84 85 if edmx_child.tag == "{http://docs.oasis-open.org/odata/ns/edmx}DataServices": 86 for data_child in edmx_child: 87 if data_child.tag == "{http://docs.oasis-open.org/odata/ns/edm}Schema": 88 namespace = data_child.attrib["Namespace"] 89 if namespace.startswith("RedfishExtensions"): 90 metadata_index.write( 91 " <edmx:Include Namespace=\"" + namespace + "\" Alias=\"Redfish\"/>\n") 92 93 else: 94 metadata_index.write( 95 " <edmx:Include Namespace=\"" + namespace + "\"/>\n") 96 schema_file.write(content) 97 metadata_index.write(" </edmx:Reference>\n") 98 99 metadata_index.write(""" <edmx:DataServices> 100 <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="Service"> 101 <EntityContainer Name="Service" Extends="ServiceRoot.v1_0_0.ServiceContainer"/> 102 </Schema> 103 </edmx:DataServices> 104""") 105 # TODO:Issue#32 There's a bug in the script that currently deletes this 106 # schema (because it's an OEM schema). Because it's the only six, and we 107 # don't update schemas very often, we just manually fix it. Need a 108 # permanent fix to the script. 109 metadata_index.write( 110 " <edmx:Reference Uri=\"/redfish/v1/schema/OemManager_v1.xml\">\n") 111 metadata_index.write(" <edmx:Include Namespace=\"OemManager\"/>\n") 112 metadata_index.write(" </edmx:Reference>\n") 113 114 metadata_index.write( 115 " <edmx:Reference Uri=\"/redfish/v1/schema/OemCrashdump_v1.xml\">\n") 116 metadata_index.write(" <edmx:Include Namespace=\"OemCrashdump.v1_0_0\"/>\n") 117 metadata_index.write(" </edmx:Reference>\n") 118 119 metadata_index.write( 120 " <edmx:Reference Uri=\"/redfish/v1/schema/OemComputerSystem_v1.xml\">\n") 121 metadata_index.write(" <edmx:Include Namespace=\"OemComputerSystem\"/>\n") 122 metadata_index.write(" </edmx:Reference>\n") 123 124 metadata_index.write( 125 " <edmx:Reference Uri=\"/redfish/v1/schema/OemVirtualMedia_v1.xml\">\n") 126 metadata_index.write(" <edmx:Include Namespace=\"OemVirtualMedia\"/>\n") 127 metadata_index.write(" <edmx:Include Namespace=\"OemVirtualMedia.v1_0_0\"/>\n") 128 metadata_index.write(" </edmx:Reference>\n") 129 130 metadata_index.write( 131 " <edmx:Reference Uri=\"/redfish/v1/schema/OemAccountService_v1.xml\">\n") 132 metadata_index.write(" <edmx:Include Namespace=\"OemAccountService\"/>\n") 133 metadata_index.write(" <edmx:Include Namespace=\"OemAccountService.v1_0_0\"/>\n") 134 metadata_index.write(" </edmx:Reference>\n") 135 136 metadata_index.write( 137 " <edmx:Reference Uri=\"/redfish/v1/schema/OemSession_v1.xml\">\n") 138 metadata_index.write(" <edmx:Include Namespace=\"OemSession\"/>\n") 139 metadata_index.write(" <edmx:Include Namespace=\"OemSession.v1_0_0\"/>\n") 140 metadata_index.write(" </edmx:Reference>\n") 141 142 metadata_index.write("</edmx:Edmx>\n") 143 144schema_files = {} 145for zip_filepath in zip_ref.namelist(): 146 if zip_filepath.startswith(os.path.join(VERSION, 'json-schema/')): 147 filename = os.path.basename(zip_filepath) 148 filenamesplit = filename.split(".") 149 if len(filenamesplit) == 3: 150 thisSchemaVersion = schema_files.get(filenamesplit[0], None) 151 if thisSchemaVersion is None: 152 schema_files[filenamesplit[0]] = filenamesplit[1] 153 else: 154 # need to see if we're a newer version. 155 if list(map(int, filenamesplit[1][1:].split("_"))) > list(map( 156 int, thisSchemaVersion[1:].split("_"))): 157 schema_files[filenamesplit[0]] = filenamesplit[1] 158 159 160for schema, version in schema_files.items(): 161 basename = schema + "." + version + ".json" 162 zip_filepath = os.path.join(VERSION, "json-schema", basename) 163 schemadir = os.path.join(json_schema_path, schema) 164 os.makedirs(schemadir) 165 location_json = OrderedDict() 166 location_json["Language"] = "en" 167 location_json["PublicationUri"] = ( 168 "http://redfish.dmtf.org/schemas/v1/" + schema + ".json") 169 location_json["Uri"] = ( 170 "/redfish/v1/JsonSchemas/" + schema + "/" + schema + ".json") 171 172 index_json = OrderedDict() 173 index_json["@odata.context"] = "/redfish/v1/$metadata#JsonSchemaFile.JsonSchemaFile" 174 index_json["@odata.id"] = "/redfish/v1/JsonSchemas/" + schema 175 index_json["@odata.type"] = "#JsonSchemaFile.v1_0_2.JsonSchemaFile" 176 index_json["Name"] = schema + " Schema File" 177 index_json["Schema"] = "#" + schema + "." + schema 178 index_json["Description"] = schema + " Schema File Location" 179 index_json["Id"] = schema 180 index_json["Languages"] = ["en"] 181 index_json["Languages@odata.count"] = 1 182 index_json["Location"] = [location_json] 183 index_json["Location@odata.count"] = 1 184 185 with open(os.path.join(schemadir, "index.json"), 'w') as schema_file: 186 json.dump(index_json, schema_file, indent=4) 187 with open(os.path.join(schemadir, schema + ".json"), 'wb') as schema_file: 188 schema_file.write(zip_ref.read(zip_filepath).replace(b'\r\n', b'\n')) 189 190with open(os.path.join(json_schema_path, "index.json"), 'w') as index_file: 191 members = [{"@odata.id": "/redfish/v1/JsonSchemas/" + schema} 192 for schema in schema_files] 193 194 members.sort(key=lambda x: x["@odata.id"]) 195 196 indexData = OrderedDict() 197 198 indexData["@odata.id"] = "/redfish/v1/JsonSchemas" 199 indexData["@odata.context"] = ("/redfish/v1/$metadata" 200 "#JsonSchemaFileCollection." 201 "JsonSchemaFileCollection") 202 indexData["@odata.type"] = ("#JsonSchemaFileCollection." 203 "JsonSchemaFileCollection") 204 indexData["Name"] = "JsonSchemaFile Collection" 205 indexData["Description"] = "Collection of JsonSchemaFiles" 206 indexData["Members@odata.count"] = len(schema_files) 207 indexData["Members"] = members 208 209 json.dump(indexData, index_file, indent=2) 210 211zip_ref.close() 212