• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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