summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/generate_schema_enums.py163
-rwxr-xr-xscripts/update_schemas.py3
2 files changed, 166 insertions, 0 deletions
diff --git a/scripts/generate_schema_enums.py b/scripts/generate_schema_enums.py
new file mode 100755
index 0000000000..13fbefe40f
--- /dev/null
+++ b/scripts/generate_schema_enums.py
@@ -0,0 +1,163 @@
+#!/usr/bin/python3
+import os
+import xml.etree.ElementTree as ET
+from collections import defaultdict
+import shutil
+import re
+
+
+SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
+REDFISH_SCHEMA_DIR = os.path.realpath(
+ os.path.join(SCRIPT_DIR, "..", "static", "redfish", "v1", "schema")
+)
+
+OUTFOLDER = os.path.realpath(os.path.join(
+ SCRIPT_DIR,
+ "..",
+ "redfish-core",
+ "include",
+ "generated",
+ "enums"
+ )
+)
+
+# Odata string types
+EDMX = "{http://docs.oasis-open.org/odata/ns/edmx}"
+EDM = "{http://docs.oasis-open.org/odata/ns/edm}"
+
+
+class Enum:
+ def __init__(self, name, values, namespace, from_file):
+ self.name = name
+ self.values = values
+ self.namespace = namespace
+ self.from_file = from_file
+
+
+def parse_schema(element, filename):
+ EntityTypes = []
+ namespace = element.attrib["Namespace"]
+ for schema_element in element:
+ name = schema_element.attrib.get("Name", None)
+ if name is None:
+ continue
+ if schema_element.tag == EDM + "EnumType":
+ enums = []
+ for member in schema_element.findall(EDM + "Member"):
+ enums.append(member.attrib["Name"])
+ EntityTypes.append(Enum(name, enums, namespace, filename))
+ return EntityTypes
+
+
+def parse_file(filename):
+ tree = ET.parse(filename)
+ root = tree.getroot()
+ results = []
+ data_services = root.findall(EDMX + "DataServices")
+ for ds in data_services:
+ for element in ds:
+ if element.tag == EDM + "Schema":
+ results.extend(parse_schema(element, filename))
+
+ return results
+
+
+def camel_to_snake(name):
+ # snake casing PCIeDevice and PCIeFunction results in mediocre results
+ # given that the standard didn't camel case those in a way that the
+ # algorithm expects, so change the casing explicitly to generate sane
+ # snake case results.
+ name = name.replace("PCIe", "Pcie")
+ name = re.sub("(.)([A-Z][a-z]+)", r"\1_\2", name)
+ return re.sub("([a-z0-9])([A-Z])", r"\1_\2", name).lower()
+
+
+def write_enum_list(redfish_defs_file, enum_list, snake_case_namespace):
+ redfish_defs_file.write(
+ "#pragma once\n"
+ "#include <nlohmann/json.hpp>\n\n"
+ "namespace {}\n"
+ "{{\n"
+ "// clang-format off\n\n".format(snake_case_namespace)
+ )
+
+ for element in enum_list:
+ redfish_defs_file.write("enum class {}{{\n".format(element.name))
+ values = element.values
+ if "Invalid" not in values:
+ values.insert(0, "Invalid")
+
+ for value in values:
+ redfish_defs_file.write(" {},\n".format(value))
+
+ redfish_defs_file.write("};\n\n")
+
+ for element in enum_list:
+ values = element.values
+ if "Invalid" not in values:
+ values.insert(0, "Invalid")
+ # nlohmann::json aparently uses c style arrays in their enum
+ # implementation, and clang-tidy isn't smart enough to figure out that
+ # the C arrays are in their code not bmcwebs, so we have to explicitly
+ # ignore the error.
+ redfish_defs_file.write(
+ "NLOHMANN_JSON_SERIALIZE_ENUM({}, {{\n".format(
+ element.name
+ )
+ )
+ for value in values:
+ redfish_defs_file.write(
+ ' {{{}::{}, "{}"}},\n'.format(element.name, value, value)
+ )
+
+ redfish_defs_file.write("});\n\n")
+
+ print(element.name)
+
+ redfish_defs_file.write("}\n" "// clang-format on\n")
+
+
+def generate_enums(flat_list):
+ # clear out the old results if they exist
+ if os.path.exists(OUTFOLDER):
+ shutil.rmtree(OUTFOLDER)
+ os.makedirs(OUTFOLDER)
+
+ enum_by_namespace = defaultdict(list)
+
+ for element in flat_list:
+ if isinstance(element, Enum):
+ namespace_split = element.namespace.split(".")[0]
+ enum_by_namespace[namespace_split].append(element)
+
+ for namespace, enum_list in enum_by_namespace.items():
+ snake_case_namespace = camel_to_snake(namespace)
+ outfile = os.path.join(
+ OUTFOLDER, "{}.hpp".format(snake_case_namespace)
+ )
+
+ with open(outfile, "w") as redfish_defs:
+ write_enum_list(redfish_defs, enum_list, snake_case_namespace)
+
+
+def main():
+ print("Reading from {}".format(REDFISH_SCHEMA_DIR))
+ dir_list = os.listdir(REDFISH_SCHEMA_DIR)
+
+ filepaths = [
+ os.path.join(REDFISH_SCHEMA_DIR, filename) for filename in dir_list
+ ]
+
+ enum_list = []
+
+ for filepath in filepaths:
+ out = parse_file(filepath)
+ enum_list.extend(out)
+
+ print("Parsing done")
+
+ generate_enums(enum_list)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/update_schemas.py b/scripts/update_schemas.py
index 459d0457bd..f6eca42c78 100755
--- a/scripts/update_schemas.py
+++ b/scripts/update_schemas.py
@@ -8,6 +8,7 @@ from io import BytesIO
import requests
from packaging.version import parse
+import generate_schema_enums
VERSION = "DSP8010_2022.2"
@@ -390,3 +391,5 @@ with open(os.path.join(cpp_path, "schemas.hpp"), "w") as hpp_file:
hpp_file.write(" };\n}\n")
zip_ref.close()
+
+generate_schema_enums.main()