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.1" 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 five, 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("</edmx:Edmx>\n") 137 138schema_files = {} 139for zip_filepath in zip_ref.namelist(): 140 if zip_filepath.startswith(os.path.join(VERSION, 'json-schema/')): 141 filename = os.path.basename(zip_filepath) 142 filenamesplit = filename.split(".") 143 if len(filenamesplit) == 3: 144 thisSchemaVersion = schema_files.get(filenamesplit[0], None) 145 if thisSchemaVersion is None: 146 schema_files[filenamesplit[0]] = filenamesplit[1] 147 else: 148 # need to see if we're a newer version. 149 if list(map(int, filenamesplit[1][1:].split("_"))) > list(map( 150 int, thisSchemaVersion[1:].split("_"))): 151 schema_files[filenamesplit[0]] = filenamesplit[1] 152 153 154for schema, version in schema_files.items(): 155 basename = schema + "." + version + ".json" 156 zip_filepath = os.path.join(VERSION, "json-schema", basename) 157 schemadir = os.path.join(json_schema_path, schema) 158 os.makedirs(schemadir) 159 location_json = OrderedDict() 160 location_json["Language"] = "en" 161 location_json["PublicationUri"] = ( 162 "http://redfish.dmtf.org/schemas/v1/" + schema + ".json") 163 location_json["Uri"] = ( 164 "/redfish/v1/JsonSchemas/" + schema + "/" + schema + ".json") 165 166 index_json = OrderedDict() 167 index_json["@odata.context"] = "/redfish/v1/$metadata#JsonSchemaFile.JsonSchemaFile" 168 index_json["@odata.id"] = "/redfish/v1/JsonSchemas/" + schema 169 index_json["@odata.type"] = "#JsonSchemaFile.v1_0_2.JsonSchemaFile" 170 index_json["Name"] = schema + " Schema File" 171 index_json["Schema"] = "#" + schema + "." + schema 172 index_json["Description"] = schema + " Schema File Location" 173 index_json["Id"] = schema 174 index_json["Languages"] = ["en"] 175 index_json["Languages@odata.count"] = 1 176 index_json["Location"] = [location_json] 177 index_json["Location@odata.count"] = 1 178 179 with open(os.path.join(schemadir, "index.json"), 'w') as schema_file: 180 json.dump(index_json, schema_file, indent=4) 181 with open(os.path.join(schemadir, schema + ".json"), 'wb') as schema_file: 182 schema_file.write(zip_ref.read(zip_filepath).replace(b'\r\n', b'\n')) 183 184with open(os.path.join(json_schema_path, "index.json"), 'w') as index_file: 185 members = [{"@odata.id": "/redfish/v1/JsonSchemas/" + schema} 186 for schema in schema_files] 187 188 members.sort(key=lambda x: x["@odata.id"]) 189 190 indexData = OrderedDict() 191 192 indexData["@odata.id"] = "/redfish/v1/JsonSchemas" 193 indexData["@odata.context"] = ("/redfish/v1/$metadata" 194 "#JsonSchemaFileCollection." 195 "JsonSchemaFileCollection") 196 indexData["@odata.type"] = ("#JsonSchemaFileCollection." 197 "JsonSchemaFileCollection") 198 indexData["Name"] = "JsonSchemaFile Collection" 199 indexData["Description"] = "Collection of JsonSchemaFiles" 200 indexData["Members@odata.count"] = len(schema_files) 201 indexData["Members"] = members 202 203 json.dump(indexData, index_file, indent=2) 204 205zip_ref.close() 206