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