xref: /openbmc/bmcweb/scripts/update_schemas.py (revision 09b9d45e)
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_2019.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                                   '/' +
69                                   VERSION +
70                                   '/csdl/') & (zip_filepath != VERSION +
71                                                "/csdl/") & (zip_filepath != VERSION +
72                                                             '/' +
73                                                             VERSION +
74                                                             "/csdl/"):
75            filename = os.path.basename(zip_filepath)
76            with open(os.path.join(schema_path, filename), 'wb') as schema_file:
77
78                metadata_index.write(
79                    "    <edmx:Reference Uri=\"/redfish/v1/schema/" +
80                    filename +
81                    "\">\n")
82
83                content = zip_ref.read(zip_filepath)
84                content = content.replace(b'\r\n', b'\n')
85                xml_root = ET.fromstring(content)
86
87                for edmx_child in xml_root:
88
89                    if edmx_child.tag == "{http://docs.oasis-open.org/odata/ns/edmx}DataServices":
90                        for data_child in edmx_child:
91                            if data_child.tag == "{http://docs.oasis-open.org/odata/ns/edm}Schema":
92                                namespace = data_child.attrib["Namespace"]
93                                if namespace.startswith("RedfishExtensions"):
94                                    metadata_index.write(
95                                        "        <edmx:Include Namespace=\"" + namespace + "\"  Alias=\"Redfish\"/>\n")
96
97                                else:
98                                    metadata_index.write(
99                                        "        <edmx:Include Namespace=\"" + namespace + "\"/>\n")
100                schema_file.write(content)
101                metadata_index.write("    </edmx:Reference>\n")
102
103    metadata_index.write("""    <edmx:DataServices>
104        <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="Service">
105            <EntityContainer Name="Service" Extends="ServiceRoot.v1_0_0.ServiceContainer"/>
106        </Schema>
107    </edmx:DataServices>
108""")
109    # TODO:Issue#32 There's a bug in the script that currently deletes this
110    # schema (because it's an OEM schema). Because it's the only five, and we
111    # don't update schemas very often, we just manually fix it. Need a
112    # permanent fix to the script.
113    metadata_index.write(
114        "    <edmx:Reference Uri=\"/redfish/v1/schema/OemManager_v1.xml\">\n")
115    metadata_index.write("        <edmx:Include Namespace=\"OemManager\"/>\n")
116    metadata_index.write("    </edmx:Reference>\n")
117
118    metadata_index.write(
119        "    <edmx:Reference Uri=\"/redfish/v1/schema/OemCrashdump_v1.xml\">\n")
120    metadata_index.write("        <edmx:Include Namespace=\"OemCrashdump.v1_0_0\"/>\n")
121    metadata_index.write("    </edmx:Reference>\n")
122
123    metadata_index.write(
124        "    <edmx:Reference Uri=\"/redfish/v1/schema/OemComputerSystem_v1.xml\">\n")
125    metadata_index.write("        <edmx:Include Namespace=\"OemComputerSystem\"/>\n")
126    metadata_index.write("    </edmx:Reference>\n")
127
128    metadata_index.write(
129        "    <edmx:Reference Uri=\"/redfish/v1/schema/OemVirtualMedia_v1.xml\">\n")
130    metadata_index.write("        <edmx:Include Namespace=\"OemVirtualMedia\"/>\n")
131    metadata_index.write("        <edmx:Include Namespace=\"OemVirtualMedia.v1_0_0\"/>\n")
132    metadata_index.write("    </edmx:Reference>\n")
133
134    metadata_index.write(
135        "    <edmx:Reference Uri=\"/redfish/v1/schema/OemAccountService_v1.xml\">\n")
136    metadata_index.write("        <edmx:Include Namespace=\"OemAccountService\"/>\n")
137    metadata_index.write("        <edmx:Include Namespace=\"OemAccountService.v1_0_0\"/>\n")
138    metadata_index.write("    </edmx:Reference>\n")
139
140    metadata_index.write("</edmx:Edmx>\n")
141
142schema_files = {}
143for zip_filepath in zip_ref.namelist():
144    if zip_filepath.startswith(os.path.join(VERSION, VERSION, 'json-schema/')):
145        filename = os.path.basename(zip_filepath)
146        filenamesplit = filename.split(".")
147        if len(filenamesplit) == 3:
148            thisSchemaVersion = schema_files.get(filenamesplit[0], None)
149            if thisSchemaVersion is None:
150                schema_files[filenamesplit[0]] = filenamesplit[1]
151            else:
152                # need to see if we're a newer version.
153                if list(map(int, filenamesplit[1][1:].split("_"))) > list(map(
154                        int, thisSchemaVersion[1:].split("_"))):
155                    schema_files[filenamesplit[0]] = filenamesplit[1]
156
157
158for schema, version in schema_files.items():
159    basename = schema + "." + version + ".json"
160    zip_filepath = os.path.join(VERSION, VERSION, "json-schema", basename)
161    schemadir = os.path.join(json_schema_path, schema)
162    os.makedirs(schemadir)
163    location_json = OrderedDict()
164    location_json["Language"] = "en"
165    location_json["PublicationUri"] = (
166        "http://redfish.dmtf.org/schemas/v1/" + schema + ".json")
167    location_json["Uri"] = (
168        "/redfish/v1/JsonSchemas/" + schema + "/" + schema + ".json")
169
170    index_json = OrderedDict()
171    index_json["@odata.context"] = "/redfish/v1/$metadata#JsonSchemaFile.JsonSchemaFile"
172    index_json["@odata.id"] = "/redfish/v1/JsonSchemas/" + schema
173    index_json["@odata.type"] = "#JsonSchemaFile.v1_0_2.JsonSchemaFile"
174    index_json["Name"] = schema + " Schema File"
175    index_json["Schema"] = "#" + schema + "." + schema
176    index_json["Description"] = schema + " Schema File Location"
177    index_json["Id"] = schema
178    index_json["Languages"] = ["en"]
179    index_json["Languages@odata.count"] = 1
180    index_json["Location"] = [location_json]
181    index_json["Location@odata.count"] = 1
182
183    with open(os.path.join(schemadir, "index.json"), 'w') as schema_file:
184        json.dump(index_json, schema_file, indent=4)
185    with open(os.path.join(schemadir, schema + ".json"), 'wb') as schema_file:
186        schema_file.write(zip_ref.read(zip_filepath).replace(b'\r\n', b'\n'))
187
188with open(os.path.join(json_schema_path, "index.json"), 'w') as index_file:
189    members = [{"@odata.id": "/redfish/v1/JsonSchemas/" + schema}
190               for schema in schema_files]
191
192    members.sort(key=lambda x: x["@odata.id"])
193
194    indexData = OrderedDict()
195
196    indexData["@odata.id"] = "/redfish/v1/JsonSchemas"
197    indexData["@odata.context"] = ("/redfish/v1/$metadata"
198                                   "#JsonSchemaFileCollection."
199                                   "JsonSchemaFileCollection")
200    indexData["@odata.type"] = ("#JsonSchemaFileCollection."
201                                "JsonSchemaFileCollection")
202    indexData["Name"] = "JsonSchemaFile Collection"
203    indexData["Description"] = "Collection of JsonSchemaFiles"
204    indexData["Members@odata.count"] = len(schema_files)
205    indexData["Members"] = members
206
207    json.dump(indexData, index_file, indent=2)
208
209zip_ref.close()
210