xref: /openbmc/bmcweb/scripts/update_schemas.py (revision 118b1c71)
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
11
12import xml.etree.ElementTree as ET
13
14SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
15
16proxies = {
17    'https': os.environ.get("https_proxy", None)
18}
19
20r = requests.get('https://www.dmtf.org/sites/default/files/standards/documents/'
21                 'DSP8010_2018.1.zip', proxies=proxies)
22
23r.raise_for_status()
24
25static_path = os.path.realpath(os.path.join(SCRIPT_DIR, "..", "static",
26                                            "redfish", "v1"))
27
28schema_path = os.path.join(static_path, "schema")
29json_schema_path = os.path.join(static_path, "JsonSchemas")
30metadata_index_path = os.path.join(static_path, "$metadata", "index.xml")
31
32zipBytesIO = BytesIO(r.content)
33zip_ref = zipfile.ZipFile(zipBytesIO)
34
35# Remove the old files
36if os.path.exists(schema_path):
37    shutil.rmtree(schema_path)
38if os.path.exists(json_schema_path):
39    files = glob.glob(os.path.join(json_schema_path, '[!Oem]*'))
40    for f in files:
41        if (os.path.isfile(f)):
42            os.remove(f)
43        else:
44            shutil.rmtree(f)
45os.remove(metadata_index_path)
46
47if not os.path.exists(schema_path):
48    os.makedirs(schema_path)
49if not os.path.exists(json_schema_path):
50    os.makedirs(json_schema_path)
51
52with open(metadata_index_path, 'w') as metadata_index:
53
54    metadata_index.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
55    metadata_index.write(
56        "<edmx:Edmx xmlns:edmx=\"http://docs.oasis-open.org/odata/ns/edmx\" Version=\"4.0\">\n")
57
58    for zip_filepath in zip_ref.namelist():
59        if zip_filepath.startswith('metadata/'):
60            filename = os.path.basename(zip_filepath)
61            with open(os.path.join(schema_path, filename), 'wb') as schema_file:
62
63                metadata_index.write(
64                    "    <edmx:Reference Uri=\"/redfish/v1/schema/" + filename + "\">\n")
65
66                content = zip_ref.read(zip_filepath)
67                xml_root = ET.fromstring(content)
68
69                for edmx_child in xml_root:
70
71                    if edmx_child.tag == "{http://docs.oasis-open.org/odata/ns/edmx}DataServices":
72                        for data_child in edmx_child:
73                            if data_child.tag == "{http://docs.oasis-open.org/odata/ns/edm}Schema":
74                                namespace = data_child.attrib["Namespace"]
75                                if namespace.startswith("RedfishExtensions"):
76                                    metadata_index.write(
77                                        "        <edmx:Include Namespace=\"" + namespace + "\"  Alias=\"Redfish\"/>\n")
78
79                                else:
80                                    metadata_index.write(
81                                        "        <edmx:Include Namespace=\"" + namespace + "\"/>\n")
82                schema_file.write(content)
83                metadata_index.write("    </edmx:Reference>\n")
84
85    metadata_index.write("""    <edmx:DataServices>
86        <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="Service">
87            <EntityContainer Name="Service" Extends="ServiceRoot.v1_0_0.ServiceContainer"/>
88        </Schema>
89    </edmx:DataServices>
90""")
91    metadata_index.write("</edmx:Edmx>\n")
92
93schema_files = {}
94for zip_filepath in zip_ref.namelist():
95    if zip_filepath.startswith('json-schema/'):
96        filename = os.path.basename(zip_filepath)
97        filenamesplit = filename.split(".")
98        if len(filenamesplit) == 3:
99            thisSchemaVersion = schema_files.get(filenamesplit[0], None)
100            if thisSchemaVersion == None:
101                schema_files[filenamesplit[0]] = filenamesplit[1]
102            else:
103                # need to see if we're a newer version.
104                if list(map(int, filenamesplit[1][1:].split("_"))) > list(map(
105                        int, thisSchemaVersion[1:].split("_"))):
106                    schema_files[filenamesplit[0]] = filenamesplit[1]
107
108
109for schema, version in schema_files.items():
110    basename = schema + "." + version + ".json"
111    zip_filepath = os.path.join("json-schema", basename)
112    schemadir = os.path.join(json_schema_path, schema)
113    os.makedirs(schemadir)
114
115    index_json = {
116        "@odata.context": "/redfish/v1/$metadata#JsonSchemaFile.JsonSchemaFile",
117        "@odata.id": "/redfish/v1/JSONSchemas/" + schema,
118        "@odata.type": "#JsonSchemaFile.v1_0_2.JsonSchemaFile",
119        "Name": schema + " Schema File",
120        "Schema": "#" + schema + "." + schema,
121        "Description": schema + " Schema File Location",
122        "Id": schema,
123        "Languages": [
124            "en"
125        ],
126        "Languages@odata.count": 1,
127        "Location": [
128            {
129                "Language": "en",
130                "PublicationUri": "http://redfish.dmtf.org/schemas/v1/" + schema + ".json",
131                "Uri": "/redfish/v1/JSONSchemas/" + schema + "/" + schema + ".json"
132            }
133        ],
134        "Location@odata.count": 1,
135    }
136
137    with open(os.path.join(schemadir, "index.json"), 'w') as schema_file:
138        json.dump(index_json, schema_file, indent=4)
139    with open(os.path.join(schemadir, schema + ".json"), 'wb') as schema_file:
140        schema_file.write(zip_ref.read(zip_filepath))
141
142with open(os.path.join(json_schema_path, "index.json"), 'w') as index_file:
143    members = [{"@odata.id": "/redfish/v1/JsonSchemas/" + schema + "/"}
144               for schema in schema_files]
145
146    members.sort(key=lambda x: x["@odata.id"])
147
148    indexData = OrderedDict()
149
150    indexData["@odata.id"] = "/redfish/v1/JsonSchemas"
151    indexData["@odata.context"] = ("/redfish/v1/$metadata"
152                                   "#JsonSchemaFileCollection."
153                                   "JsonSchemaFileCollection")
154    indexData["@odata.type"] = ("#JsonSchemaFileCollection."
155                                "JsonSchemaFileCollection")
156    indexData["Name"] = "JsonSchemaFile Collection"
157    indexData["Description"] = "Collection of JsonSchemaFiles"
158    indexData["Members@odata.count"] = len(schema_files)
159    indexData["Members"] = members
160
161    json.dump(indexData, index_file, indent=2)
162
163zip_ref.close()
164