1*9c5db199SXin Li# Copyright 2019 The Chromium OS Authors. All rights reserved. 2*9c5db199SXin Li# Use of this source code is governed by a BSD-style license that can be 3*9c5db199SXin Li# found in the LICENSE file. 4*9c5db199SXin Li"""This module provides functions for loading side_effects_config.json. 5*9c5db199SXin Li""" 6*9c5db199SXin Li 7*9c5db199SXin Liimport errno 8*9c5db199SXin Liimport os 9*9c5db199SXin Li 10*9c5db199SXin Lifrom google.protobuf import json_format 11*9c5db199SXin Li 12*9c5db199SXin Liimport common 13*9c5db199SXin Lifrom autotest_lib.utils.side_effects.proto import config_pb2 14*9c5db199SXin Li 15*9c5db199SXin Li_SIDE_EFFECTS_CONFIG_FILE = 'side_effects_config.json' 16*9c5db199SXin Li 17*9c5db199SXin Li 18*9c5db199SXin Lidef load(results_dir): 19*9c5db199SXin Li """Load a side_effects_config.json file. 20*9c5db199SXin Li 21*9c5db199SXin Li @param results_dir: The path to the results directory containing the file. 22*9c5db199SXin Li 23*9c5db199SXin Li @returns: a side_effects.Config proto object if side_effects_config.json 24*9c5db199SXin Li exists, None otherwise. 25*9c5db199SXin Li 26*9c5db199SXin Li @raises: json_format.ParseError if the content of side_effects_config.json 27*9c5db199SXin Li is not valid JSON. 28*9c5db199SXin Li """ 29*9c5db199SXin Li config_path = os.path.join(results_dir, _SIDE_EFFECTS_CONFIG_FILE) 30*9c5db199SXin Li 31*9c5db199SXin Li if not os.path.exists(config_path): 32*9c5db199SXin Li return None 33*9c5db199SXin Li 34*9c5db199SXin Li with open(config_path, 'r') as config_file: 35*9c5db199SXin Li content = config_file.read() 36*9c5db199SXin Li config = config_pb2.Config() 37*9c5db199SXin Li return json_format.Parse(content, config, ignore_unknown_fields=True) 38*9c5db199SXin Li 39*9c5db199SXin Li 40*9c5db199SXin Lidef validate_tko(config): 41*9c5db199SXin Li """Validate the tko field of the side_effects.Config. 42*9c5db199SXin Li 43*9c5db199SXin Li @param config: A side_effects.Config proto. 44*9c5db199SXin Li 45*9c5db199SXin Li @raises: ValueError if the tko field does not contain all required fields. 46*9c5db199SXin Li OSError if one of the required files is missing. 47*9c5db199SXin Li """ 48*9c5db199SXin Li _check_empty_fields({ 49*9c5db199SXin Li 'TKO proxy socket': config.tko.proxy_socket, 50*9c5db199SXin Li 'TKO MySQL user': config.tko.mysql_user, 51*9c5db199SXin Li 'TKO MySQL password file': config.tko.mysql_password_file 52*9c5db199SXin Li }) 53*9c5db199SXin Li 54*9c5db199SXin Li _check_file_existence({ 55*9c5db199SXin Li 'TKO proxy socket': config.tko.proxy_socket, 56*9c5db199SXin Li 'TKO MySQL password file': config.tko.mysql_password_file 57*9c5db199SXin Li }) 58*9c5db199SXin Li 59*9c5db199SXin Li 60*9c5db199SXin Lidef validate_google_storage(config): 61*9c5db199SXin Li """Validate the google_storage field of the side_effects.Config. 62*9c5db199SXin Li 63*9c5db199SXin Li @param config: A side_effects.Config proto. 64*9c5db199SXin Li 65*9c5db199SXin Li @raises: ValueError if the tko field does not contain all required fields. 66*9c5db199SXin Li OSError if one of the required files is missing. 67*9c5db199SXin Li """ 68*9c5db199SXin Li _check_empty_fields({ 69*9c5db199SXin Li 'Google Storage bucket': config.google_storage.bucket, 70*9c5db199SXin Li 'Google Storage credentials file': 71*9c5db199SXin Li config.google_storage.credentials_file 72*9c5db199SXin Li }) 73*9c5db199SXin Li 74*9c5db199SXin Li _check_file_existence({ 75*9c5db199SXin Li 'Google Storage credentials file': 76*9c5db199SXin Li config.google_storage.credentials_file 77*9c5db199SXin Li }) 78*9c5db199SXin Li 79*9c5db199SXin Li 80*9c5db199SXin Lidef _check_empty_fields(fields): 81*9c5db199SXin Li """Return a list of missing required TKO-related fields. 82*9c5db199SXin Li 83*9c5db199SXin Li @param fields: A dict mapping string field descriptions to string field 84*9c5db199SXin Li values. 85*9c5db199SXin Li 86*9c5db199SXin Li @raises: ValueError if at least one of the field values is empty. 87*9c5db199SXin Li """ 88*9c5db199SXin Li empty_fields = [] 89*9c5db199SXin Li for description, value in fields.items(): 90*9c5db199SXin Li if not value: 91*9c5db199SXin Li empty_fields.append(description) 92*9c5db199SXin Li if empty_fields: 93*9c5db199SXin Li raise ValueError('Missing required fields: ' + ', '.join(empty_fields)) 94*9c5db199SXin Li 95*9c5db199SXin Li 96*9c5db199SXin Lidef _check_file_existence(files): 97*9c5db199SXin Li """Checks that all given files exist. 98*9c5db199SXin Li 99*9c5db199SXin Li @param files: A dict mapping string file descriptions to string file names. 100*9c5db199SXin Li 101*9c5db199SXin Li @raises: OSError if at least one of the files is missing. 102*9c5db199SXin Li """ 103*9c5db199SXin Li missing_files = [] 104*9c5db199SXin Li for description, path in files.items(): 105*9c5db199SXin Li if not os.path.exists(path): 106*9c5db199SXin Li missing_files.append(description + ': ' + path) 107*9c5db199SXin Li if missing_files: 108*9c5db199SXin Li raise OSError(errno.ENOENT, os.strerror(errno.ENOENT), 109*9c5db199SXin Li ', '.join(missing_files)) 110