blob: bf395799e3ae6a23d9b1ebcc5f03d7bfcf753f6a [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
Gunnar Mills2ae81db2024-01-31 14:25:11 -060013VERSION = "DSP8010_2023.3"
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",
Patrick Williams1c79f932024-02-26 18:57:26 -0600104 "Protocol",
Ed Tanous27747912022-09-23 12:50:08 -0700105 "RedfishError",
106 "RedfishExtensions",
107 "Redundancy",
108 "Resource",
109 "Role",
110 "RoleCollection",
111 "Sensor",
112 "SensorCollection",
113 "ServiceRoot",
114 "Session",
115 "SessionCollection",
116 "SessionService",
117 "Settings",
118 "SoftwareInventory",
119 "SoftwareInventoryCollection",
120 "Storage",
121 "StorageCollection",
122 "StorageController",
123 "StorageControllerCollection",
124 "Task",
125 "TaskCollection",
126 "TaskService",
127 "TelemetryService",
128 "Thermal",
George Liuf1240b42022-10-28 17:26:15 +0800129 "ThermalMetrics",
Ed Tanous27747912022-09-23 12:50:08 -0700130 "ThermalSubsystem",
131 "Triggers",
132 "TriggersCollection",
133 "UpdateService",
Ed Tanous27747912022-09-23 12:50:08 -0700134 "VirtualMedia",
135 "VirtualMediaCollection",
136 "odata",
137 "odata-v4",
138 "redfish-error",
139 "redfish-payload-annotations",
140 "redfish-schema",
141 "redfish-schema-v1",
Gunnar Mills349a2ac2021-01-20 22:29:16 -0600142]
143
Myung Bae480662d2023-10-04 07:19:38 -0700144# OEM schemas
145oem_schema_names = [
146 "OemManager",
147 "OemComputerSystem",
148 "OemVirtualMedia",
149 "OpenBMCAccountService",
150]
151
Ed Tanous683f7272018-07-26 12:47:19 -0700152SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
153
Ed Tanous27747912022-09-23 12:50:08 -0700154proxies = {"https": os.environ.get("https_proxy", None)}
Ed Tanous683f7272018-07-26 12:47:19 -0700155
Ed Tanouscb103132019-10-08 11:34:22 -0700156r = requests.get(
Ed Tanous27747912022-09-23 12:50:08 -0700157 "https://www.dmtf.org/sites/default/files/standards/documents/"
158 + VERSION
159 + ".zip",
160 proxies=proxies,
161)
Ed Tanous683f7272018-07-26 12:47:19 -0700162
163r.raise_for_status()
164
Ed Tanous81d523a2022-05-25 12:00:51 -0700165
Ed Tanous27747912022-09-23 12:50:08 -0700166static_path = os.path.realpath(
167 os.path.join(SCRIPT_DIR, "..", "static", "redfish", "v1")
168)
Ed Tanous683f7272018-07-26 12:47:19 -0700169
Ed Tanous81d523a2022-05-25 12:00:51 -0700170
Ed Tanous27747912022-09-23 12:50:08 -0700171cpp_path = os.path.realpath(
172 os.path.join(SCRIPT_DIR, "..", "redfish-core", "include")
173)
Ed Tanous81d523a2022-05-25 12:00:51 -0700174
175
Ed Tanous683f7272018-07-26 12:47:19 -0700176schema_path = os.path.join(static_path, "schema")
177json_schema_path = os.path.join(static_path, "JsonSchemas")
Ed Tanous118b1c72018-09-13 13:45:51 -0700178metadata_index_path = os.path.join(static_path, "$metadata", "index.xml")
Ed Tanous683f7272018-07-26 12:47:19 -0700179
180zipBytesIO = BytesIO(r.content)
181zip_ref = zipfile.ZipFile(zipBytesIO)
182
Ed Tanous8b564552022-09-23 12:03:18 -0700183
Ed Tanous204c3762022-12-12 09:50:09 -0800184class SchemaVersion:
Patrick Williamsfd06b302022-12-12 10:39:42 -0600185 """
Ed Tanous204c3762022-12-12 09:50:09 -0800186 A Python class for sorting Redfish schema versions. Allows sorting Redfish
187 versions in the way humans expect, by comparing version strings as lists
188 (ie 0_2_0 comes before 0_10_0) in the way humans expect. It does case
189 insensitive schema name comparisons
Patrick Williamsfd06b302022-12-12 10:39:42 -0600190 """
Ed Tanous8b564552022-09-23 12:03:18 -0700191
Ed Tanous204c3762022-12-12 09:50:09 -0800192 def __init__(self, key):
193 key = str.casefold(key)
Ed Tanous8b564552022-09-23 12:03:18 -0700194
Ed Tanous204c3762022-12-12 09:50:09 -0800195 split_tup = key.split(".")
196 self.version_pieces = [split_tup[0]]
197 if len(split_tup) < 2:
198 return
199 version = split_tup[1]
Ed Tanous8b564552022-09-23 12:03:18 -0700200
Ed Tanous204c3762022-12-12 09:50:09 -0800201 if version.startswith("v"):
202 version = version[1:]
203 if any(char.isdigit() for char in version):
Patrick Williamsfd06b302022-12-12 10:39:42 -0600204 self.version_pieces.extend([int(x) for x in version.split("_")])
Ed Tanous8b564552022-09-23 12:03:18 -0700205
Ed Tanous204c3762022-12-12 09:50:09 -0800206 def __lt__(self, other):
207 return self.version_pieces < other.version_pieces
Ed Tanous8b564552022-09-23 12:03:18 -0700208
209
Ed Tanous683f7272018-07-26 12:47:19 -0700210# Remove the old files
Ed Tanous5b5574a2022-09-26 19:53:36 -0700211skip_prefixes = ["Oem", "OpenBMC"]
Ed Tanous683f7272018-07-26 12:47:19 -0700212if os.path.exists(schema_path):
Ed Tanous27747912022-09-23 12:50:08 -0700213 files = [
214 os.path.join(schema_path, f)
215 for f in os.listdir(schema_path)
Ed Tanous5b5574a2022-09-26 19:53:36 -0700216 if not any([f.startswith(prefix) for prefix in skip_prefixes])
Ed Tanous27747912022-09-23 12:50:08 -0700217 ]
James Feistaee8d842018-09-10 16:07:40 -0700218 for f in files:
219 os.remove(f)
Ed Tanous683f7272018-07-26 12:47:19 -0700220if os.path.exists(json_schema_path):
Ed Tanous27747912022-09-23 12:50:08 -0700221 files = [
222 os.path.join(json_schema_path, f)
223 for f in os.listdir(json_schema_path)
Ed Tanous5b5574a2022-09-26 19:53:36 -0700224 if not any([f.startswith(prefix) for prefix in skip_prefixes])
Ed Tanous27747912022-09-23 12:50:08 -0700225 ]
Ed Tanous118b1c72018-09-13 13:45:51 -0700226 for f in files:
Ed Tanous27747912022-09-23 12:50:08 -0700227 if os.path.isfile(f):
Ed Tanous118b1c72018-09-13 13:45:51 -0700228 os.remove(f)
229 else:
230 shutil.rmtree(f)
Ed Tanous8b564552022-09-23 12:03:18 -0700231try:
232 os.remove(metadata_index_path)
233except FileNotFoundError:
234 pass
Ed Tanous683f7272018-07-26 12:47:19 -0700235
Ed Tanous118b1c72018-09-13 13:45:51 -0700236if not os.path.exists(schema_path):
237 os.makedirs(schema_path)
238if not os.path.exists(json_schema_path):
239 os.makedirs(json_schema_path)
Ed Tanous683f7272018-07-26 12:47:19 -0700240
Ed Tanous8b564552022-09-23 12:03:18 -0700241csdl_filenames = []
242json_schema_files = defaultdict(list)
243
Ed Tanous204c3762022-12-12 09:50:09 -0800244for zip_file in zip_ref.infolist():
245 if zip_file.is_dir():
246 continue
247 if zip_file.filename.startswith("csdl/"):
248 csdl_filenames.append(os.path.basename(zip_file.filename))
249 elif zip_file.filename.startswith("json-schema/"):
250 filename = os.path.basename(zip_file.filename)
Ed Tanous8b564552022-09-23 12:03:18 -0700251 filenamesplit = filename.split(".")
252 # exclude schemas again to save flash space
253 if filenamesplit[0] not in include_list:
254 continue
255 json_schema_files[filenamesplit[0]].append(filename)
Ed Tanous204c3762022-12-12 09:50:09 -0800256 elif zip_file.filename.startswith("openapi/"):
Ed Tanous8b564552022-09-23 12:03:18 -0700257 pass
Ed Tanous204c3762022-12-12 09:50:09 -0800258 elif zip_file.filename.startswith("dictionaries/"):
Ed Tanous8b564552022-09-23 12:03:18 -0700259 pass
260
261# sort the json files by version
262for key, value in json_schema_files.items():
Ed Tanous204c3762022-12-12 09:50:09 -0800263 value.sort(key=SchemaVersion, reverse=True)
Ed Tanous8b564552022-09-23 12:03:18 -0700264
265# Create a dictionary ordered by schema name
266json_schema_files = OrderedDict(
Ed Tanous204c3762022-12-12 09:50:09 -0800267 sorted(json_schema_files.items(), key=lambda x: SchemaVersion(x[0]))
Ed Tanous8b564552022-09-23 12:03:18 -0700268)
269
Ed Tanous204c3762022-12-12 09:50:09 -0800270csdl_filenames.sort(key=SchemaVersion)
Myung Bae480662d2023-10-04 07:19:38 -0700271
272# Create oem filenames - from oem json names
273oem_csdl_filenames = []
274for filename in oem_schema_names:
275 oem_csdl_filenames.append(filename + "_v1.xml")
276
277# Append Oem csdl files
278csdl_filenames += oem_csdl_filenames
279
Ed Tanous27747912022-09-23 12:50:08 -0700280with open(metadata_index_path, "w") as metadata_index:
Ed Tanous27747912022-09-23 12:50:08 -0700281 metadata_index.write('<?xml version="1.0" encoding="UTF-8"?>\n')
Ed Tanous118b1c72018-09-13 13:45:51 -0700282 metadata_index.write(
Ed Tanousf395daa2021-08-02 08:56:24 -0700283 "<edmx:Edmx xmlns:edmx="
Ed Tanous27747912022-09-23 12:50:08 -0700284 '"http://docs.oasis-open.org/odata/ns/edmx"'
285 ' Version="4.0">\n'
286 )
Ed Tanous118b1c72018-09-13 13:45:51 -0700287
Ed Tanous8b564552022-09-23 12:03:18 -0700288 for filename in csdl_filenames:
289 # filename looks like Zone_v1.xml
Myung Bae480662d2023-10-04 07:19:38 -0700290 if filename in oem_csdl_filenames:
291 with open(
292 os.path.join(schema_path, filename), "rb"
293 ) as oem_csdl_in:
294 content = oem_csdl_in.read()
295 content = content.replace(b"\r\n", b"\n")
296 else:
297 with open(os.path.join(schema_path, filename), "wb") as schema_out:
298 content = zip_ref.read(os.path.join("csdl", filename))
299 content = content.replace(b"\r\n", b"\n")
300 schema_out.write(content)
301 filenamesplit = filename.split("_")
302 if filenamesplit[0] not in include_list:
303 continue
Ed Tanous853c0dc2022-12-21 13:21:52 -0800304
Myung Bae480662d2023-10-04 07:19:38 -0700305 metadata_index.write(
306 ' <edmx:Reference Uri="/redfish/v1/schema/' + filename + '">\n'
307 )
Ed Tanous853c0dc2022-12-21 13:21:52 -0800308
Myung Bae480662d2023-10-04 07:19:38 -0700309 xml_root = ET.fromstring(content)
310 edmx = "{http://docs.oasis-open.org/odata/ns/edmx}"
311 edm = "{http://docs.oasis-open.org/odata/ns/edm}"
312 for edmx_child in xml_root:
313 if edmx_child.tag == edmx + "DataServices":
314 for data_child in edmx_child:
315 if data_child.tag == edm + "Schema":
316 namespace = data_child.attrib["Namespace"]
317 if namespace.startswith("RedfishExtensions"):
318 metadata_index.write(
319 ' <edmx:Include Namespace="'
320 + namespace
321 + '" Alias="Redfish"/>\n'
322 )
Ed Tanous118b1c72018-09-13 13:45:51 -0700323
Myung Bae480662d2023-10-04 07:19:38 -0700324 else:
325 metadata_index.write(
326 ' <edmx:Include Namespace="'
327 + namespace
328 + '"/>\n'
329 )
330 metadata_index.write(" </edmx:Reference>\n")
Ed Tanous118b1c72018-09-13 13:45:51 -0700331
Ed Tanous27747912022-09-23 12:50:08 -0700332 metadata_index.write(
333 " <edmx:DataServices>\n"
334 " <Schema "
335 'xmlns="http://docs.oasis-open.org/odata/ns/edm" '
336 'Namespace="Service">\n'
337 ' <EntityContainer Name="Service" '
338 'Extends="ServiceRoot.v1_0_0.ServiceContainer"/>\n'
339 " </Schema>\n"
340 " </edmx:DataServices>\n"
341 )
Ed Tanous118b1c72018-09-13 13:45:51 -0700342 metadata_index.write("</edmx:Edmx>\n")
Ed Tanous683f7272018-07-26 12:47:19 -0700343
Gunnar Mills349a2ac2021-01-20 22:29:16 -0600344
Ed Tanous8b564552022-09-23 12:03:18 -0700345for schema, version in json_schema_files.items():
346 zip_filepath = os.path.join("json-schema", version[0])
Ed Tanous683f7272018-07-26 12:47:19 -0700347 schemadir = os.path.join(json_schema_path, schema)
348 os.makedirs(schemadir)
Ed Tanous118b1c72018-09-13 13:45:51 -0700349
Ed Tanous27747912022-09-23 12:50:08 -0700350 with open(os.path.join(schemadir, schema + ".json"), "wb") as schema_file:
351 schema_file.write(zip_ref.read(zip_filepath).replace(b"\r\n", b"\n"))
Ed Tanous683f7272018-07-26 12:47:19 -0700352
Ed Tanous27747912022-09-23 12:50:08 -0700353with open(os.path.join(cpp_path, "schemas.hpp"), "w") as hpp_file:
Ed Tanous81d523a2022-05-25 12:00:51 -0700354 hpp_file.write(
355 "#pragma once\n"
356 "{WARNING}\n"
357 "// clang-format off\n"
Ed Tanous3d69fed2022-09-26 20:10:42 -0700358 "#include <array>\n"
Ed Tanous81d523a2022-05-25 12:00:51 -0700359 "\n"
360 "namespace redfish\n"
361 "{{\n"
Ed Tanous27747912022-09-23 12:50:08 -0700362 " constexpr std::array schemas {{\n".format(WARNING=WARNING)
Ed Tanous81d523a2022-05-25 12:00:51 -0700363 )
Ed Tanous8b564552022-09-23 12:03:18 -0700364 for schema_file in json_schema_files:
Ed Tanous27747912022-09-23 12:50:08 -0700365 hpp_file.write(' "{}",\n'.format(schema_file))
366
Myung Bae480662d2023-10-04 07:19:38 -0700367 for schema_file in oem_schema_names:
368 hpp_file.write(' "{}",\n'.format(schema_file))
369
Patrick Williamsdfa3fdc2022-12-07 07:14:21 -0600370 hpp_file.write(" };\n}\n")
Ed Tanous683f7272018-07-26 12:47:19 -0700371
372zip_ref.close()
Ed Tanous0ec8b832022-03-14 14:56:47 -0700373
374generate_schema_enums.main()
Carson Labrado9e031402022-07-08 20:56:52 +0000375generate_top_collections()
Ed Tanous853c0dc2022-12-21 13:21:52 -0800376
377# Now delete the xml schema files we aren't supporting
378if os.path.exists(schema_path):
379 files = [
380 os.path.join(schema_path, f)
381 for f in os.listdir(schema_path)
Ed Tanous5b5574a2022-09-26 19:53:36 -0700382 if not any([f.startswith(prefix) for prefix in skip_prefixes])
Ed Tanous853c0dc2022-12-21 13:21:52 -0800383 ]
384 for filename in files:
385 # filename will include the absolute path
386 filenamesplit = filename.split("/")
387 name = filenamesplit.pop()
388 namesplit = name.split("_")
389 if namesplit[0] not in include_list:
390 print("excluding schema: " + filename)
391 os.remove(filename)