1#!/usr/bin/env python 2# -*- coding: utf-8 -*- 3# Copyright (c) 2023 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 argparse 17import sys 18import json 19import re 20import os 21 22 23def get_features(features): 24 feats = {} 25 for feat in features: 26 if not feat: 27 continue 28 match = feat.index("=") 29 if match <= 0: 30 print("Warning: invalid feature [{}]".format(feat)) 31 continue 32 key = feat[:match].strip() 33 val = feat[match + 1:].strip().strip('"') 34 if val == 'true': 35 feats[key] = True 36 elif val == 'false': 37 feats[key] = False 38 elif re.match(r'[0-9]+', val): 39 feats[key] = int(val) 40 else: 41 feats[key] = val.replace('\"', '"') 42 43 pairs = dict() 44 pairs['features'] = feats 45 return pairs 46 47 48def get_syscap(syscap): 49 feats = {} 50 for feat in syscap: 51 if not feat: 52 continue 53 if '=' not in feat: 54 raise Exception("Error: invalid syscap [{}]".format(feat)) 55 match = feat.index("=") 56 key = feat[:match].strip() 57 val = feat[match + 1:].strip().strip('"') 58 if val == 'true': 59 feats[key] = True 60 elif val == 'false': 61 feats[key] = False 62 elif re.match(r'[0-9]+', val): 63 feats[key] = int(val) 64 else: 65 feats[key] = val.replace('\"', '"') 66 67 pairs = dict() 68 pairs['syscap'] = feats 69 return pairs 70 71 72def get_exclusion_modules(exclusions): 73 pairs = dict() 74 pairs['exclusions'] = exclusions 75 return pairs 76 77 78def from_ss_to_parts(subsystems): 79 parts = dict() 80 for subsystem in subsystems: 81 ss_name = subsystem.get('subsystem') 82 components = subsystem.get('components') 83 if components: 84 for com in components: 85 com_name = com.get('component') 86 features = com.get('features') 87 syscap = com.get('syscap') 88 exclusions = com.get('exclusions') 89 if features: 90 pairs = get_features(features) 91 parts['{}:{}'.format(ss_name, com_name)] = pairs 92 else: 93 parts['{}:{}'.format(ss_name, com_name)] = dict() 94 if syscap: 95 pairs = get_syscap(syscap) 96 parts.get('{}:{}'.format(ss_name, com_name)).update(pairs) 97 if exclusions: 98 pairs = get_exclusion_modules(exclusions) 99 parts.get('{}:{}'.format(ss_name, com_name)).update(pairs) 100 # Copy other key-values 101 for key, val in com.items(): 102 if key in ['component', 'features', 'syscap', 'exclusions']: 103 continue 104 parts['{}:{}'.format(ss_name, com_name)][key] = val 105 return parts 106 107 108def transform(config): 109 subsystems = config.get('subsystems') 110 if subsystems: 111 config.pop('subsystems') 112 parts = from_ss_to_parts(subsystems) 113 config['parts'] = parts 114 return config 115 116 117def save_transformed_config(config, output_file): 118 new_config = json.dumps(config, indent=2, sort_keys=True) 119 with open(output_file, 'wt') as fout: 120 fout.write(new_config) 121 122 123def get_product_config(config_dir, product_name, company): 124 company_path = os.path.join(config_dir, company) 125 if not os.path.isdir(company_path): 126 raise Exception(f'Error: {company_path} is not a directory') 127 128 for product in os.listdir(company_path): 129 product_path = os.path.join(company_path, product) 130 config_json = os.path.join(product_path, 'config.json') 131 132 if os.path.isfile(config_json): 133 with open(config_json, 'rb') as fin: 134 config = json.load(fin) 135 if product_name == config.get('product_name'): 136 return config 137 raise Exception(f'Error: failed to get product config for {product_name}') 138 139 140def get_vendor_parts_list(config): 141 return transform(config).get('parts') 142 143 144def main(): 145 parser = argparse.ArgumentParser() 146 parser.add_argument('--product-name', required=True) 147 parser.add_argument('--company', required=True) 148 parser.add_argument('--config-dir', required=True) 149 options = parser.parse_args() 150 config = get_product_config(options.config_dir, options.product_name, 151 options.company) 152 get_vendor_parts_list(config) 153 154 155if __name__ == '__main__': 156 sys.exit(main()) 157