xref: /openbmc/bmcweb/scripts/update_schemas.py (revision 262d7d4b)
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.4"
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