import lib.test_const as consts import re import lib._metric_resolvers as mr CANON_SB_VAULT_REGEX = re.compile(r"\w+=(value|file):[-\w]+:\w+") CANON_YAV_REGEX = re.compile(r"\w+=(value|file):sec-[a-z0-9]+:\w+") VALID_DNS_REQUIREMENTS = ("default", "local", "dns64") VALID_NETWORK_REQUIREMENTS = ("full", "restricted") def check_cpu(suite_cpu_requirements, test_size, is_kvm=False): min_cpu_requirements = consts.TestRequirementsConstants.MinCpu max_cpu_requirements = consts.TestSize.get_max_requirements(test_size).get(consts.TestRequirements.Cpu) if isinstance(suite_cpu_requirements, str): if all( consts.TestRequirementsConstants.is_all_cpu(req) for req in (max_cpu_requirements, suite_cpu_requirements) ): return None return "Wrong 'cpu' requirements: {}, should be in [{}..{}] for {}-size tests".format( suite_cpu_requirements, min_cpu_requirements, max_cpu_requirements, test_size ) if not isinstance(suite_cpu_requirements, int): return "Wrong 'cpu' requirements: {}, should be integer".format(suite_cpu_requirements) if ( suite_cpu_requirements < min_cpu_requirements or suite_cpu_requirements > consts.TestRequirementsConstants.get_cpu_value(max_cpu_requirements) ): return "Wrong 'cpu' requirement: {}, should be in [{}..{}] for {}-size tests".format( suite_cpu_requirements, min_cpu_requirements, max_cpu_requirements, test_size ) return None # TODO: Remove is_kvm param when there will be guarantees on RAM def check_ram(suite_ram_requirements, test_size, is_kvm=False): if not isinstance(suite_ram_requirements, int): return "Wrong 'ram' requirements: {}, should be integer".format(suite_ram_requirements) min_ram_requirements = consts.TestRequirementsConstants.MinRam max_ram_requirements = ( consts.MAX_RAM_REQUIREMENTS_FOR_KVM if is_kvm else consts.TestSize.get_max_requirements(test_size).get(consts.TestRequirements.Ram) ) if suite_ram_requirements < min_ram_requirements or suite_ram_requirements > max_ram_requirements: err_msg = "Wrong 'ram' requirements: {}, should be in [{}..{}] for {}-size tests".format( suite_ram_requirements, min_ram_requirements, max_ram_requirements, test_size ) if is_kvm: err_msg += ' with kvm requirements' return err_msg return None def check_ram_disk(suite_ram_disk, test_size, is_kvm=False): min_ram_disk = consts.TestRequirementsConstants.MinRamDisk max_ram_disk = consts.TestSize.get_max_requirements(test_size).get(consts.TestRequirements.RamDisk) if isinstance(suite_ram_disk, str): if all(consts.TestRequirementsConstants.is_all_ram_disk(req) for req in (max_ram_disk, suite_ram_disk)): return None return "Wrong 'ram_disk' requirements: {}, should be in [{}..{}] for {}-size tests".format( suite_ram_disk, 0, max_ram_disk, test_size ) if not isinstance(suite_ram_disk, int): return "Wrong 'ram_disk' requirements: {}, should be integer".format(suite_ram_disk) if suite_ram_disk < min_ram_disk or suite_ram_disk > consts.TestRequirementsConstants.get_ram_disk_value( max_ram_disk ): return "Wrong 'ram_disk' requirement: {}, should be in [{}..{}] for {}-size tests".format( suite_ram_disk, min_ram_disk, max_ram_disk, test_size ) return None def validate_sb_vault(name, value): if not CANON_SB_VAULT_REGEX.match(value): return "sb_vault value '{}' should follow pattern =::".format(value) def validate_yav_vault(name, value): if not CANON_YAV_REGEX.match(value): return "yav value '{}' should follow pattern =::".format(value) def validate_numerical_requirement(name, value): if mr.resolve_value(value) is None: return "Cannot convert [[imp]]{}[[rst]] to the proper [[imp]]{}[[rst]] requirement value".format(value, name) def validate_choice_requirement(name, val, valid): if val not in valid: return "Unknown [[imp]]{}[[rst]] requirement: [[imp]]{}[[rst]], choose from [[imp]]{}[[rst]]".format( name, val, ", ".join(valid) ) def validate_force_sandbox_requirement( name, value, test_size, is_force_sandbox, in_autocheck, is_fuzzing, is_kvm, is_ytexec_run, check_func ): if is_force_sandbox or not in_autocheck or is_fuzzing or is_ytexec_run: if value == 'all': return return validate_numerical_requirement(name, value) error_msg = validate_numerical_requirement(name, value) if error_msg: return error_msg return check_func(mr.resolve_value(value), test_size, is_kvm) def validate_ram_disk_requirement( name, value, test_size, is_force_sandbox, in_autocheck, is_fuzzing, is_kvm, is_ytexec_run, ram ): error_msg = validate_force_sandbox_requirement( name, value, test_size, is_force_sandbox, in_autocheck, is_fuzzing, is_kvm, is_ytexec_run, check_ram_disk ) if error_msg: return error_msg if is_force_sandbox or not in_autocheck or test_size == consts.TestSize.Large: return if int(value) > int(ram): return "Wrong 'ram_disk' value, 'ram_disk':{} should be no more than 'ram':{}".format(value, ram) return None # TODO: Remove is_kvm param when there will be guarantees on RAM def validate_requirement( req_name, value, test_size, is_force_sandbox, in_autocheck, is_fuzzing, is_kvm, is_ytexec_run, requirements ): req_checks = { 'container': validate_numerical_requirement, 'cpu': lambda n, v: validate_force_sandbox_requirement( n, v, test_size, is_force_sandbox, in_autocheck, is_fuzzing, is_kvm, is_ytexec_run, check_cpu ), 'disk_usage': validate_numerical_requirement, 'dns': lambda n, v: validate_choice_requirement(n, v, VALID_DNS_REQUIREMENTS), 'kvm': None, 'network': lambda n, v: validate_choice_requirement(n, v, VALID_NETWORK_REQUIREMENTS), 'ram': lambda n, v: validate_force_sandbox_requirement( n, v, test_size, is_force_sandbox, in_autocheck, is_fuzzing, is_kvm, is_ytexec_run, check_ram ), 'ram_disk': lambda n, v: validate_ram_disk_requirement( n, v, test_size, is_force_sandbox, in_autocheck, is_fuzzing, is_kvm, is_ytexec_run, requirements.get( 'ram', consts.TestSize.get_default_requirements(test_size).get(consts.TestRequirements.Ram) ), ), 'sb': None, 'sb_vault': validate_sb_vault, 'yav': validate_yav_vault, } if req_name not in req_checks: return "Unknown requirement: [[imp]]{}[[rst]], choose from [[imp]]{}[[rst]]".format( req_name, ", ".join(sorted(req_checks)) ) if req_name in ('container', 'disk') and not is_force_sandbox: return "Only [[imp]]LARGE[[rst]] tests without [[imp]]ya:force_distbuild[[rst]] tag can have [[imp]]{}[[rst]] requirement".format( req_name ) check_func = req_checks[req_name] if check_func: return check_func(req_name, value)