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