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