blob: c77144d113464070a86f0ca39a94c552d01d5a54 [file] [log] [blame]
Nan Zhou313c1b72022-03-25 11:47:55 -07001#!/usr/bin/env python3
Ed Tanous683f7272018-07-26 12:47:19 -07002import os
Ed Tanous683f7272018-07-26 12:47:19 -07003import shutil
Ed Tanous118b1c72018-09-13 13:45:51 -07004import xml.etree.ElementTree as ET
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -06005import zipfile
6from collections import OrderedDict, defaultdict
7from io import BytesIO
8
Ed Tanous0ec8b832022-03-14 14:56:47 -07009import generate_schema_enums
Patrick Williamsfd06b302022-12-12 10:39:42 -060010import requests
Carson Labrado9e031402022-07-08 20:56:52 +000011from generate_schema_collections import generate_top_collections
Ed Tanous118b1c72018-09-13 13:45:51 -070012
Ed Tanouse9cc1bc2023-09-21 11:15:30 -070013VERSION = "DSP8010_2023.2"
Ed Tanouscb103132019-10-08 11:34:22 -070014
Ed Tanous27747912022-09-23 12:50:08 -070015WARNING = """/****************************************************************
Ed Tanous81d523a2022-05-25 12:00:51 -070016 * READ THIS WARNING FIRST
17 * This is an auto-generated header which contains definitions
18 * for Redfish DMTF defined schemas.
19 * DO NOT modify this registry outside of running the
20 * update_schemas.py script. The definitions contained within
21 * this file are owned by DMTF. Any modifications to these files
22 * should be first pushed to the relevant registry in the DMTF
23 * github organization.
Ed Tanous27747912022-09-23 12:50:08 -070024 ***************************************************************/"""
Ed Tanous81d523a2022-05-25 12:00:51 -070025
Gunnar Mills349a2ac2021-01-20 22:29:16 -060026# To use a new schema, add to list and rerun tool
27include_list = [
Ed Tanous27747912022-09-23 12:50:08 -070028 "AccountService",
29 "ActionInfo",
Ed Tanous6c068982023-02-07 15:44:38 -080030 "AggregationService",
Carson Labrado8b2521a2023-02-18 02:33:14 +000031 "AggregationSource",
Carson Labrado5315c1b2023-02-18 01:02:18 +000032 "AggregationSourceCollection",
Ed Tanous27747912022-09-23 12:50:08 -070033 "Assembly",
34 "AttributeRegistry",
35 "Bios",
36 "Cable",
37 "CableCollection",
38 "Certificate",
39 "CertificateCollection",
40 "CertificateLocations",
41 "CertificateService",
42 "Chassis",
43 "ChassisCollection",
44 "ComputerSystem",
45 "ComputerSystemCollection",
Ed Tanous23203b42023-03-16 16:58:46 -070046 "ComponentIntegrity",
47 "ComponentIntegrityCollection",
Ed Tanous27747912022-09-23 12:50:08 -070048 "Drive",
49 "DriveCollection",
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -060050 "EnvironmentMetrics",
Ed Tanous27747912022-09-23 12:50:08 -070051 "EthernetInterface",
52 "EthernetInterfaceCollection",
53 "Event",
54 "EventDestination",
55 "EventDestinationCollection",
56 "EventService",
Lakshmi Yadlapati71abefe2023-01-10 22:22:09 -060057 "FabricAdapter",
58 "FabricAdapterCollection",
George Liu1a7b3772022-09-29 09:29:18 +080059 "Fan",
60 "FanCollection",
Ed Tanous27747912022-09-23 12:50:08 -070061 "IPAddresses",
62 "JsonSchemaFile",
63 "JsonSchemaFileCollection", # redfish/v1/JsonSchemas
64 "LogEntry",
65 "LogEntryCollection",
66 "LogService",
67 "LogServiceCollection",
68 "Manager",
69 "ManagerAccount",
70 "ManagerAccountCollection",
71 "ManagerCollection",
72 "ManagerDiagnosticData",
73 "ManagerNetworkProtocol",
74 "Memory",
75 "MemoryCollection",
76 "Message",
77 "MessageRegistry",
78 "MessageRegistryCollection",
79 "MessageRegistryFile",
80 "MessageRegistryFileCollection",
81 "MetricDefinition",
82 "MetricDefinitionCollection",
83 "MetricReport",
84 "MetricReportCollection",
85 "MetricReportDefinition",
86 "MetricReportDefinitionCollection",
87 "OperatingConfig",
88 "OperatingConfigCollection",
89 "PCIeDevice",
90 "PCIeDeviceCollection",
91 "PCIeFunction",
92 "PCIeFunctionCollection",
93 "PhysicalContext",
94 "PCIeSlots",
George Liu7da1c582023-02-21 14:38:49 +080095 "Port",
96 "PortCollection",
Ed Tanous27747912022-09-23 12:50:08 -070097 "Power",
Chicago Duanfe9bd2d2022-09-30 18:03:05 +080098 "PowerSubsystem",
99 "PowerSupply",
100 "PowerSupplyCollection",
Ed Tanous27747912022-09-23 12:50:08 -0700101 "Privileges", # Used in Role
102 "Processor",
103 "ProcessorCollection",
104 "RedfishError",
105 "RedfishExtensions",
106 "Redundancy",
107 "Resource",
108 "Role",
109 "RoleCollection",
110 "Sensor",
111 "SensorCollection",
112 "ServiceRoot",
113 "Session",
114 "SessionCollection",
115 "SessionService",
116 "Settings",
117 "SoftwareInventory",
118 "SoftwareInventoryCollection",
119 "Storage",
120 "StorageCollection",
121 "StorageController",
122 "StorageControllerCollection",
123 "Task",
124 "TaskCollection",
125 "TaskService",
126 "TelemetryService",
127 "Thermal",
George Liuf1240b42022-10-28 17:26:15 +0800128 "ThermalMetrics",
Ed Tanous27747912022-09-23 12:50:08 -0700129 "ThermalSubsystem",
130 "Triggers",
131 "TriggersCollection",
132 "UpdateService",
Ed Tanous27747912022-09-23 12:50:08 -0700133 "VirtualMedia",
134 "VirtualMediaCollection",
135 "odata",
136 "odata-v4",
137 "redfish-error",
138 "redfish-payload-annotations",
139 "redfish-schema",
140 "redfish-schema-v1",
Gunnar Mills349a2ac2021-01-20 22:29:16 -0600141]
142
Myung Bae480662d2023-10-04 07:19:38 -0700143# OEM schemas
144oem_schema_names = [
145 "OemManager",
146 "OemComputerSystem",
147 "OemVirtualMedia",
148 "OpenBMCAccountService",
149]
150
Ed Tanous683f7272018-07-26 12:47:19 -0700151SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
152
Ed Tanous27747912022-09-23 12:50:08 -0700153proxies = {"https": os.environ.get("https_proxy", None)}
Ed Tanous683f7272018-07-26 12:47:19 -0700154
Ed Tanouscb103132019-10-08 11:34:22 -0700155r = requests.get(
Ed Tanous27747912022-09-23 12:50:08 -0700156 "https://www.dmtf.org/sites/default/files/standards/documents/"
157 + VERSION
158 + ".zip",
159 proxies=proxies,
160)
Ed Tanous683f7272018-07-26 12:47:19 -0700161
162r.raise_for_status()
163
Ed Tanous81d523a2022-05-25 12:00:51 -0700164
Ed Tanous27747912022-09-23 12:50:08 -0700165static_path = os.path.realpath(
166 os.path.join(SCRIPT_DIR, "..", "static", "redfish", "v1")
167)
Ed Tanous683f7272018-07-26 12:47:19 -0700168
Ed Tanous81d523a2022-05-25 12:00:51 -0700169
Ed Tanous27747912022-09-23 12:50:08 -0700170cpp_path = os.path.realpath(
171 os.path.join(SCRIPT_DIR, "..", "redfish-core", "include")
172)
Ed Tanous81d523a2022-05-25 12:00:51 -0700173
174
Ed Tanous683f7272018-07-26 12:47:19 -0700175schema_path = os.path.join(static_path, "schema")
176json_schema_path = os.path.join(static_path, "JsonSchemas")
Ed Tanous118b1c72018-09-13 13:45:51 -0700177metadata_index_path = os.path.join(static_path, "$metadata", "index.xml")
Ed Tanous683f7272018-07-26 12:47:19 -0700178
179zipBytesIO = BytesIO(r.content)
180zip_ref = zipfile.ZipFile(zipBytesIO)
181
Ed Tanous8b564552022-09-23 12:03:18 -0700182
Ed Tanous204c3762022-12-12 09:50:09 -0800183class SchemaVersion:
Patrick Williamsfd06b302022-12-12 10:39:42 -0600184 """
Ed Tanous204c3762022-12-12 09:50:09 -0800185 A Python class for sorting Redfish schema versions. Allows sorting Redfish
186 versions in the way humans expect, by comparing version strings as lists
187 (ie 0_2_0 comes before 0_10_0) in the way humans expect. It does case
188 insensitive schema name comparisons
Patrick Williamsfd06b302022-12-12 10:39:42 -0600189 """
Ed Tanous8b564552022-09-23 12:03:18 -0700190
Ed Tanous204c3762022-12-12 09:50:09 -0800191 def __init__(self, key):
192 key = str.casefold(key)
Ed Tanous8b564552022-09-23 12:03:18 -0700193
Ed Tanous204c3762022-12-12 09:50:09 -0800194 split_tup = key.split(".")
195 self.version_pieces = [split_tup[0]]
196 if len(split_tup) < 2:
197 return
198 version = split_tup[1]
Ed Tanous8b564552022-09-23 12:03:18 -0700199
Ed Tanous204c3762022-12-12 09:50:09 -0800200 if version.startswith("v"):
201 version = version[1:]
202 if any(char.isdigit() for char in version):
Patrick Williamsfd06b302022-12-12 10:39:42 -0600203 self.version_pieces.extend([int(x) for x in version.split("_")])
Ed Tanous8b564552022-09-23 12:03:18 -0700204
Ed Tanous204c3762022-12-12 09:50:09 -0800205 def __lt__(self, other):
206 return self.version_pieces < other.version_pieces
Ed Tanous8b564552022-09-23 12:03:18 -0700207
208
Ed Tanous683f7272018-07-26 12:47:19 -0700209# Remove the old files
Ed Tanous5b5574a2022-09-26 19:53:36 -0700210skip_prefixes = ["Oem", "OpenBMC"]
Ed Tanous683f7272018-07-26 12:47:19 -0700211if os.path.exists(schema_path):
Ed Tanous27747912022-09-23 12:50:08 -0700212 files = [
213 os.path.join(schema_path, f)
214 for f in os.listdir(schema_path)
Ed Tanous5b5574a2022-09-26 19:53:36 -0700215 if not any([f.startswith(prefix) for prefix in skip_prefixes])
Ed Tanous27747912022-09-23 12:50:08 -0700216 ]
James Feistaee8d842018-09-10 16:07:40 -0700217 for f in files:
218 os.remove(f)
Ed Tanous683f7272018-07-26 12:47:19 -0700219if os.path.exists(json_schema_path):
Ed Tanous27747912022-09-23 12:50:08 -0700220 files = [
221 os.path.join(json_schema_path, f)
222 for f in os.listdir(json_schema_path)
Ed Tanous5b5574a2022-09-26 19:53:36 -0700223 if not any([f.startswith(prefix) for prefix in skip_prefixes])
Ed Tanous27747912022-09-23 12:50:08 -0700224 ]
Ed Tanous118b1c72018-09-13 13:45:51 -0700225 for f in files:
Ed Tanous27747912022-09-23 12:50:08 -0700226 if os.path.isfile(f):
Ed Tanous118b1c72018-09-13 13:45:51 -0700227 os.remove(f)
228 else:
229 shutil.rmtree(f)
Ed Tanous8b564552022-09-23 12:03:18 -0700230try:
231 os.remove(metadata_index_path)
232except FileNotFoundError:
233 pass
Ed Tanous683f7272018-07-26 12:47:19 -0700234
Ed Tanous118b1c72018-09-13 13:45:51 -0700235if not os.path.exists(schema_path):
236 os.makedirs(schema_path)
237if not os.path.exists(json_schema_path):
238 os.makedirs(json_schema_path)
Ed Tanous683f7272018-07-26 12:47:19 -0700239
Ed Tanous8b564552022-09-23 12:03:18 -0700240csdl_filenames = []
241json_schema_files = defaultdict(list)
242
Ed Tanous204c3762022-12-12 09:50:09 -0800243for zip_file in zip_ref.infolist():
244 if zip_file.is_dir():
245 continue
246 if zip_file.filename.startswith("csdl/"):
247 csdl_filenames.append(os.path.basename(zip_file.filename))
248 elif zip_file.filename.startswith("json-schema/"):
249 filename = os.path.basename(zip_file.filename)
Ed Tanous8b564552022-09-23 12:03:18 -0700250 filenamesplit = filename.split(".")
251 # exclude schemas again to save flash space
252 if filenamesplit[0] not in include_list:
253 continue
254 json_schema_files[filenamesplit[0]].append(filename)
Ed Tanous204c3762022-12-12 09:50:09 -0800255 elif zip_file.filename.startswith("openapi/"):
Ed Tanous8b564552022-09-23 12:03:18 -0700256 pass
Ed Tanous204c3762022-12-12 09:50:09 -0800257 elif zip_file.filename.startswith("dictionaries/"):
Ed Tanous8b564552022-09-23 12:03:18 -0700258 pass
259
260# sort the json files by version
261for key, value in json_schema_files.items():
Ed Tanous204c3762022-12-12 09:50:09 -0800262 value.sort(key=SchemaVersion, reverse=True)
Ed Tanous8b564552022-09-23 12:03:18 -0700263
264# Create a dictionary ordered by schema name
265json_schema_files = OrderedDict(
Ed Tanous204c3762022-12-12 09:50:09 -0800266 sorted(json_schema_files.items(), key=lambda x: SchemaVersion(x[0]))
Ed Tanous8b564552022-09-23 12:03:18 -0700267)
268
Ed Tanous204c3762022-12-12 09:50:09 -0800269csdl_filenames.sort(key=SchemaVersion)
Myung Bae480662d2023-10-04 07:19:38 -0700270
271# Create oem filenames - from oem json names
272oem_csdl_filenames = []
273for filename in oem_schema_names:
274 oem_csdl_filenames.append(filename + "_v1.xml")
275
276# Append Oem csdl files
277csdl_filenames += oem_csdl_filenames
278
Ed Tanous27747912022-09-23 12:50:08 -0700279with open(metadata_index_path, "w") as metadata_index:
Ed Tanous27747912022-09-23 12:50:08 -0700280 metadata_index.write('<?xml version="1.0" encoding="UTF-8"?>\n')
Ed Tanous118b1c72018-09-13 13:45:51 -0700281 metadata_index.write(
Ed Tanousf395daa2021-08-02 08:56:24 -0700282 "<edmx:Edmx xmlns:edmx="
Ed Tanous27747912022-09-23 12:50:08 -0700283 '"http://docs.oasis-open.org/odata/ns/edmx"'
284 ' Version="4.0">\n'
285 )
Ed Tanous118b1c72018-09-13 13:45:51 -0700286
Ed Tanous8b564552022-09-23 12:03:18 -0700287 for filename in csdl_filenames:
288 # filename looks like Zone_v1.xml
Myung Bae480662d2023-10-04 07:19:38 -0700289 if filename in oem_csdl_filenames:
290 with open(
291 os.path.join(schema_path, filename), "rb"
292 ) as oem_csdl_in:
293 content = oem_csdl_in.read()
294 content = content.replace(b"\r\n", b"\n")
295 else:
296 with open(os.path.join(schema_path, filename), "wb") as schema_out:
297 content = zip_ref.read(os.path.join("csdl", filename))
298 content = content.replace(b"\r\n", b"\n")
299 schema_out.write(content)
300 filenamesplit = filename.split("_")
301 if filenamesplit[0] not in include_list:
302 continue
Ed Tanous853c0dc2022-12-21 13:21:52 -0800303
Myung Bae480662d2023-10-04 07:19:38 -0700304 metadata_index.write(
305 ' <edmx:Reference Uri="/redfish/v1/schema/' + filename + '">\n'
306 )
Ed Tanous853c0dc2022-12-21 13:21:52 -0800307
Myung Bae480662d2023-10-04 07:19:38 -0700308 xml_root = ET.fromstring(content)
309 edmx = "{http://docs.oasis-open.org/odata/ns/edmx}"
310 edm = "{http://docs.oasis-open.org/odata/ns/edm}"
311 for edmx_child in xml_root:
312 if edmx_child.tag == edmx + "DataServices":
313 for data_child in edmx_child:
314 if data_child.tag == edm + "Schema":
315 namespace = data_child.attrib["Namespace"]
316 if namespace.startswith("RedfishExtensions"):
317 metadata_index.write(
318 ' <edmx:Include Namespace="'
319 + namespace
320 + '" Alias="Redfish"/>\n'
321 )
Ed Tanous118b1c72018-09-13 13:45:51 -0700322
Myung Bae480662d2023-10-04 07:19:38 -0700323 else:
324 metadata_index.write(
325 ' <edmx:Include Namespace="'
326 + namespace
327 + '"/>\n'
328 )
329 metadata_index.write(" </edmx:Reference>\n")
Ed Tanous118b1c72018-09-13 13:45:51 -0700330
Ed Tanous27747912022-09-23 12:50:08 -0700331 metadata_index.write(
332 " <edmx:DataServices>\n"
333 " <Schema "
334 'xmlns="http://docs.oasis-open.org/odata/ns/edm" '
335 'Namespace="Service">\n'
336 ' <EntityContainer Name="Service" '
337 'Extends="ServiceRoot.v1_0_0.ServiceContainer"/>\n'
338 " </Schema>\n"
339 " </edmx:DataServices>\n"
340 )
Ed Tanous118b1c72018-09-13 13:45:51 -0700341 metadata_index.write("</edmx:Edmx>\n")
Ed Tanous683f7272018-07-26 12:47:19 -0700342
Gunnar Mills349a2ac2021-01-20 22:29:16 -0600343
Ed Tanous8b564552022-09-23 12:03:18 -0700344for schema, version in json_schema_files.items():
345 zip_filepath = os.path.join("json-schema", version[0])
Ed Tanous683f7272018-07-26 12:47:19 -0700346 schemadir = os.path.join(json_schema_path, schema)
347 os.makedirs(schemadir)
Ed Tanous118b1c72018-09-13 13:45:51 -0700348
Ed Tanous27747912022-09-23 12:50:08 -0700349 with open(os.path.join(schemadir, schema + ".json"), "wb") as schema_file:
350 schema_file.write(zip_ref.read(zip_filepath).replace(b"\r\n", b"\n"))
Ed Tanous683f7272018-07-26 12:47:19 -0700351
Ed Tanous27747912022-09-23 12:50:08 -0700352with open(os.path.join(cpp_path, "schemas.hpp"), "w") as hpp_file:
Ed Tanous81d523a2022-05-25 12:00:51 -0700353 hpp_file.write(
354 "#pragma once\n"
355 "{WARNING}\n"
356 "// clang-format off\n"
Ed Tanous3d69fed2022-09-26 20:10:42 -0700357 "#include <array>\n"
Ed Tanous81d523a2022-05-25 12:00:51 -0700358 "\n"
359 "namespace redfish\n"
360 "{{\n"
Ed Tanous27747912022-09-23 12:50:08 -0700361 " constexpr std::array schemas {{\n".format(WARNING=WARNING)
Ed Tanous81d523a2022-05-25 12:00:51 -0700362 )
Ed Tanous8b564552022-09-23 12:03:18 -0700363 for schema_file in json_schema_files:
Ed Tanous27747912022-09-23 12:50:08 -0700364 hpp_file.write(' "{}",\n'.format(schema_file))
365
Myung Bae480662d2023-10-04 07:19:38 -0700366 for schema_file in oem_schema_names:
367 hpp_file.write(' "{}",\n'.format(schema_file))
368
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600369 hpp_file.write(" };\n}\n")
Ed Tanous683f7272018-07-26 12:47:19 -0700370
371zip_ref.close()
Ed Tanous0ec8b832022-03-14 14:56:47 -0700372
373generate_schema_enums.main()
Carson Labrado9e031402022-07-08 20:56:52 +0000374generate_top_collections()
Ed Tanous853c0dc2022-12-21 13:21:52 -0800375
376# Now delete the xml schema files we aren't supporting
377if os.path.exists(schema_path):
378 files = [
379 os.path.join(schema_path, f)
380 for f in os.listdir(schema_path)
Ed Tanous5b5574a2022-09-26 19:53:36 -0700381 if not any([f.startswith(prefix) for prefix in skip_prefixes])
Ed Tanous853c0dc2022-12-21 13:21:52 -0800382 ]
383 for filename in files:
384 # filename will include the absolute path
385 filenamesplit = filename.split("/")
386 name = filenamesplit.pop()
387 namesplit = name.split("_")
388 if namesplit[0] not in include_list:
389 print("excluding schema: " + filename)
390 os.remove(filename)