1#!/usr/bin/env python 2# -*- coding: utf-8 -*- 3# Copyright (c) 2021 Huawei Device Co., Ltd. 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15 16import sys 17import re 18import os 19import json 20import argparse 21 22sys.path.append( 23 os.path.dirname( 24 os.path.dirname( 25 os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))) 26 27from third_party.PyYAML.lib import yaml # noqa: E402 28 29 30def format_validation(pattern, content): 31 regex = re.compile(pattern) 32 matched = regex.match(content) 33 if not matched: 34 print("error: %s match %s " % (content, pattern), "failed") 35 return matched 36 37 38def length_check(content, length_min, length_max): 39 length = len(content) 40 length_valid = [False, True][(length >= length_min) 41 and (length <= length_max)] 42 if not length_valid: 43 print("error: length of %s is incorrect," % (content), 44 "must be in range of [%d, %d]" % (length_min, length_max)) 45 return length_valid 46 47 48def check_char(content): 49 return format_validation('^[A-Z]{1}[A-Z0-9_]*$', content) 50 51 52def check_char_base(content): 53 return format_validation('[A-Za-z0-9_]*$', content) 54 55 56def check_char_desc(content): 57 return format_validation('[A-Za-z0-9_ ]*$', content) 58 59 60def check_char_tag(content): 61 return format_validation('[A-Za-z0-9]*$', content) 62 63 64def domain_name_check(content, length_min, length_max): 65 if not length_check(content, length_min, length_max): 66 sys.exit(1) 67 if not check_char(content): 68 if check_char_base(content): 69 print("warning: %s: %s" % (DOMAIN_NAME, content), 70 "is not all in A-Z, or not start with A-Z", 71 file=WARNING_TXT) 72 else: 73 sys.exit(1) 74 75 76def desc_check(content): 77 if ((not length_check(content, 3, 128)) or (not check_char_desc(content))): 78 sys.exit(1) 79 80 81def tag_check(tag_list): 82 if not length_check(tag_list, 1, 5): 83 sys.exit(1) 84 for each_tag in tag_list: 85 if ((not check_char_tag(each_tag)) 86 or (not length_check(each_tag, 1, 16))): 87 sys.exit(1) 88 89 90def check_domain_duplicate(domain, domain_value): 91 if domain in DOMAIN_DICT: 92 sys.exit(1) 93 else: 94 DOMAIN_DICT[domain] = domain_value 95 96 97def event_check(yaml_info, base_type, base_level, param_type): 98 for event_name, param_info in yaml_info.items(): 99 domain_name_check(event_name, 1, 32) 100 if "__BASE" in param_info: 101 if not param_info["__BASE"]["type"] in base_type: 102 print('error: __BASE type must be in %s' % base_type) 103 sys.exit(1) 104 if not param_info["__BASE"]["level"] in base_level: 105 print('error: __BASE level must be in %s' % base_level) 106 sys.exit(1) 107 if "desc" in param_info["__BASE"]: 108 desc_check(param_info["__BASE"]["desc"]) 109 else: 110 print("error: __BASE must have desc") 111 sys.exit(1) 112 if "tag" in param_info["__BASE"]: 113 param_tag_list = param_info["__BASE"]["tag"].split() 114 tag_check(param_tag_list) 115 else: 116 print("error: __BASE is not the key in ", param_info) 117 sys.exit(1) 118 if not length_check(param_info, 1, 129): 119 sys.exit(1) 120 for param_name, param_value in param_info.items(): 121 if param_name == "__BASE": 122 continue 123 domain_name_check(param_name, 1, 32) 124 if not param_value["type"] in param_type: 125 print('error:', param_name, 'type must in %s' % param_type) 126 sys.exit(1) 127 if "desc" in param_value: 128 desc_check(param_value["desc"]) 129 else: 130 print('error: ', param_value, 'must have desc') 131 sys.exit(1) 132 if "arrsize" in param_value: 133 if ((param_value["arrsize"] < 1) 134 or (param_value["arrsize"] > 100)): 135 print("error: ", param_name, 136 "array size must be in range [1, 100]") 137 sys.exit(1) 138 139 140def merge_hisysevent_config(yaml_list, output_path): 141 if (len(output_path) == 0): 142 present_path = os.path.dirname(os.path.abspath(__file__)) 143 output_path = present_path 144 if (len(yaml_list) == 0): 145 print("error: there is no yaml input") 146 sys.exit(1) 147 if not os.path.exists(output_path): 148 os.makedirs(output_path, exist_ok=True) 149 base_type = ["FAULT", "STATISTIC", "SECURITY", "BEHAVIOR"] 150 base_level = ["CRITICAL", "MINOR"] 151 param_type = [ 152 "BOOL", "INT8", "UINT8", "INT16", "UINT16", "INT32", "UINT32", "INT64", 153 "UINT64", "FLOAT", "DOUBLE", "STRING" 154 ] 155 global DOMAIN_DICT 156 DOMAIN_DICT = {} 157 dictionary_result = {} 158 global WARNING_TXT 159 hisysevent_warning_file = os.path.join(output_path, 160 'hisysevent_warning.txt') 161 WARNING_TXT = open(hisysevent_warning_file, 'w+') 162 for each_yaml in yaml_list: 163 yaml_file = open(each_yaml, 'r') 164 yaml_info = yaml.safe_load(yaml_file) 165 global DOMAIN_NAME 166 DOMAIN_NAME = yaml_info['domain'] 167 domain_name_check(DOMAIN_NAME, 1, 16) 168 check_domain_duplicate(DOMAIN_NAME, each_yaml) 169 del yaml_info['domain'] 170 if not length_check(yaml_info, 1, 4096): 171 print("error: events count should in the range of [1, 4096]") 172 sys.exit() 173 event_check(yaml_info, base_type, base_level, param_type) 174 dictionary_result[DOMAIN_NAME] = yaml_info 175 hisysevent_def_file = os.path.join(output_path, 'hisysevent.def') 176 with open(hisysevent_def_file, 'w') as j: 177 json.dump(dictionary_result, j, indent=4) 178 print( 179 "Verify the YAML files and pack them into {} hisysevent.def successful" 180 .format(hisysevent_def_file)) 181 return hisysevent_def_file 182 183 184def main(argv): 185 parser = argparse.ArgumentParser(description='yaml list') 186 parser.add_argument("--yaml-list", nargs='+', required=True) 187 parser.add_argument("--def-path", required=True) 188 args = parser.parse_args(argv) 189 hisysevent_def_file = merge_hisysevent_config(args.yaml_list, 190 args.def_path) 191 print(hisysevent_def_file) 192 return 0 193 194 195if __name__ == '__main__': 196 sys.exit(main(sys.argv[1:])) 197