blob: 0c2e185b331b0a9b3b6a3abe0862421175590b3c [file] [log] [blame]
Bob King5cc01282019-12-17 18:11:57 +08001#!/usr/bin/env python
2
3import argparse
4import json
5import sys
6import jsonschema
7
8r"""
9Validates the phosphor-regulators configuration file. Checks it against a JSON
10schema as well as doing some extra checks that can't be encoded in the schema.
11"""
12
Bob King95b796a2020-01-15 14:45:06 +080013def handle_validation_error():
14 sys.exit("Validation failed.")
15
Bob King5b27a952020-01-20 18:04:15 +080016def check_duplicate_object_id(config_json):
17 r"""
18 Check that there aren't any JSON objects with the same 'id' property value.
19 config_json: Configuration file JSON
20 """
21
22 json_ids = check_duplicate_rule_id(config_json)+\
23 check_duplicate_device_id(config_json)+\
24 check_duplicate_rail_id(config_json)
25 unique_ids = set()
26 for id in json_ids:
27 if id in unique_ids:
28 sys.stderr.write("Error: Duplicate ID.\n"+\
29 "Found multiple objects with the ID "+id+'\n')
30 handle_validation_error()
31 else:
32 unique_ids.add(id)
33
Bob King95b796a2020-01-15 14:45:06 +080034def check_duplicate_rule_id(config_json):
35 r"""
36 Check that there aren't any "rule" elements with the same 'id' field.
37 config_json: Configuration file JSON
38 """
39 rule_ids = []
40 for rule in config_json.get('rules', {}):
41 rule_id = rule['id']
42 if rule_id in rule_ids:
43 sys.stderr.write("Error: Duplicate rule ID.\n"+\
44 "Found multiple rules with the ID "+rule_id+'\n')
45 handle_validation_error()
46 else:
47 rule_ids.append(rule_id)
Bob King5b27a952020-01-20 18:04:15 +080048 return rule_ids
Bob King95b796a2020-01-15 14:45:06 +080049
50def check_duplicate_chassis_number(config_json):
51 r"""
52 Check that there aren't any "chassis" elements with the same 'number' field.
53 config_json: Configuration file JSON
54 """
55 numbers = []
56 for chassis in config_json.get('chassis', {}):
57 number = chassis['number']
58 if number in numbers:
59 sys.stderr.write("Error: Duplicate chassis number.\n"+\
60 "Found multiple chassis with the number "+str(number)+'\n')
61 handle_validation_error()
62 else:
63 numbers.append(number)
64
65def check_duplicate_device_id(config_json):
66 r"""
67 Check that there aren't any "devices" with the same 'id' field.
68 config_json: Configuration file JSON
69 """
70 device_ids = []
71 for chassis in config_json.get('chassis', {}):
72 for device in chassis.get('devices', {}):
73 device_id = device['id']
74 if device_id in device_ids:
75 sys.stderr.write("Error: Duplicate device ID.\n"+\
76 "Found multiple devices with the ID "+device_id+'\n')
77 handle_validation_error()
78 else:
79 device_ids.append(device_id)
Bob King5b27a952020-01-20 18:04:15 +080080 return device_ids
Bob King95b796a2020-01-15 14:45:06 +080081
82def check_duplicate_rail_id(config_json):
83 r"""
84 Check that there aren't any "rails" with the same 'id' field.
85 config_json: Configuration file JSON
86 """
87 rail_ids = []
88 for chassis in config_json.get('chassis', {}):
89 for device in chassis.get('devices', {}):
90 for rail in device.get('rails', {}):
91 rail_id = rail['id']
92 if rail_id in rail_ids:
93 sys.stderr.write("Error: Duplicate rail ID.\n"+\
94 "Found multiple rails with the ID "+rail_id+'\n')
95 handle_validation_error()
96 else:
97 rail_ids.append(rail_id)
Bob King5b27a952020-01-20 18:04:15 +080098 return rail_ids
Bob King95b796a2020-01-15 14:45:06 +080099
100def check_for_duplicates(config_json):
101 r"""
102 Check for duplicate ID.
103 """
104 check_duplicate_rule_id(config_json)
105
106 check_duplicate_chassis_number(config_json)
107
108 check_duplicate_device_id(config_json)
109
110 check_duplicate_rail_id(config_json)
111
Bob King5b27a952020-01-20 18:04:15 +0800112 check_duplicate_object_id(config_json)
113
Bob King5cc01282019-12-17 18:11:57 +0800114def validate_schema(config, schema):
115 r"""
116 Validates the specified config file using the specified
117 schema file.
118
119 config: Path of the file containing the config JSON
120 schema: Path of the file containing the schema JSON
121 """
122
123 with open(config) as config_handle:
124 config_json = json.load(config_handle)
125
126 with open(schema) as schema_handle:
127 schema_json = json.load(schema_handle)
128
129 try:
130 jsonschema.validate(config_json, schema_json)
131 except jsonschema.ValidationError as e:
132 print(e)
Bob King95b796a2020-01-15 14:45:06 +0800133 handle_validation_error()
134
135 return config_json
Bob King5cc01282019-12-17 18:11:57 +0800136
137if __name__ == '__main__':
138
139 parser = argparse.ArgumentParser(
140 description='phosphor-regulators configuration file validator')
141
142 parser.add_argument('-s', '--schema-file', dest='schema_file',
143 help='The phosphor-regulators schema file')
144
145 parser.add_argument('-c', '--configuration-file', dest='configuration_file',
146 help='The phosphor-regulators configuration file')
147
148 args = parser.parse_args()
149
150 if not args.schema_file:
151 parser.print_help()
152 sys.exit("Error: Schema file is required.")
153 if not args.configuration_file:
154 parser.print_help()
155 sys.exit("Error: Configuration file is required.")
156
Bob King95b796a2020-01-15 14:45:06 +0800157 config_json = validate_schema(args.configuration_file, args.schema_file)
158 check_for_duplicates(config_json)