def parse(self, filepath=None, all_sections=False, paths=[], **kwargs): assert filepath, "File Path must be provided" root = None if "::" in filepath: [filepath, root] = filepath.split("::", 2) if not isinstance(paths, list) and isinstance(paths, str): paths = [paths] filepath = utils.find_file(filepath, paths) text = "\n".join(utils.read_lines(filepath)) tmpl = Environment().from_string(text) if root: block = tmpl.blocks[root] text = "\n".join(block(tmpl.new_context(kwargs))) return json.fix(text, "Invalid json file supplied", True, object_pairs_hook=SpyTestDict) if not all_sections or not tmpl.blocks: text = Environment().from_string(text).render(**kwargs) return json.fix(text, "Invalid json file supplied", True, object_pairs_hook=SpyTestDict) retval = SpyTestDict() for root in tmpl.blocks: block = tmpl.blocks[root] text = "\n".join(block(tmpl.new_context(**kwargs))) retval[root] = json.fix(text, "Invalid json file supplied", True, object_pairs_hook=SpyTestDict) return retval
def _read_pid(wa): file_prefix = os.getenv("SPYTEST_FILE_PREFIX", "results") for slave in wa.slaves.values(): filepath = os.path.join(wa.logs_path, slave.name, "{}_pid.txt".format(file_prefix)) try: slave.pid = utils.read_lines(filepath)[0] except: pass
def ansible_playbook(playbook, host_list, username, password, logs_path=None): ansible_cfg = os.path.join(os.path.dirname(__file__), '..', "ansible", "ansible.cfg") ansible_cfg = os.path.abspath(ansible_cfg) ansible_dir = os.path.dirname(sys.executable) ansible_exe = os.path.join(ansible_dir, "ansible-playbook") if logs_path: os.environ["ANSIBLE_LOCAL_TEMP"] = logs_path os.environ["ANSIBLE_CONFIG"] = ansible_cfg # added the SSH_ARGS as environment variable to supress host checking as the nodes # in the case would be dut's with dynamic inventory. os.environ[ "ANSIBLE_SSH_ARGS"] = "-o ControlMaster=auto -o ControlPersist=60s -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" fp = tempfile.NamedTemporaryFile(delete=False) _fp_write(fp, "[hosts]\n") for host in host_list: _fp_write(fp, "{}\n".format(host)) _fp_write(fp, "[hosts:vars]\n") _fp_write(fp, "ansible_user={}\n".format(username)) _fp_write(fp, "ansible_password={}\n".format(password)) fp.close() configs = "\n".join(utils.read_lines(fp.name)) cmd = "{} -i {} {}".format(ansible_exe, fp.name, playbook) #print("Executing", cmd) proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) out, err = proc.communicate() proc.wait() os.unlink(fp.name) if proc.returncode != 0: msg = [ "Error: Failed to execute ansible playbook '{}'".format(playbook) ] msg.append("errcode: {} error: ('{}')".format(proc.returncode, err.strip())) msg.append("output: {}".format(out)) msg.append("config: {}".format(configs)) return "\n".join(msg) for line in out.splitlines(): print(line) return out
def _parse_args(pre_parse=False): # pytest hack to let it wotk with absolute paths for testbed and tclist parser = argparse.ArgumentParser(description='Process SpyTest arguments.', add_help=False) if pre_parse: parser.add_argument("--args-file", action="store", default=None, help="spytest arguments from file path") parser.add_argument("--testbed-file", action="store", default=None, help="testbed file path -- default: ./testbed.yaml") parser.add_argument("--test-suite", action="append", default=[], help="test suites") parser.add_argument("--tclist-file", action="append", default=None, help="test case list file path") parser.add_argument("--logs-path", action="store", default=None, help="logs folder -- default: .") parser.add_argument("--logs-level", action="store", default="info", help="logs level -- default: info") parser.add_argument("--log-level", action="store", dest="logs_level", default="info", help="logs level -- default: info") parser.add_argument("--results-prefix", action="store", default=None, help="Prefix to be used for results.") parser.add_argument("--file-mode", action="store_true", default=False, help="Execute in file mode -- default: false") parser.add_argument("-n", "--numprocesses", action="store", default=None, type=int, help="number of preocessese") parser.add_argument("--tclist-bucket", action="append", default=None, help="use test cases from buckets") for bucket in range(1, 9): parser.add_argument( "--bucket-{}".format(bucket), action="store", default=None, nargs="*", help="needed topology for bucket-{}.".format(bucket)) parser.add_argument("--env", action="append", default=[], nargs=2, help="environment variables") parser.add_argument("--exclude-devices", action="store", default=None, help="exclude given duts from testbed") parser.add_argument("--include-devices", action="store", default=None, help="include given duts from testbed") parser.add_argument( "--open-config-api", action="store", default='GNMI', help="specified open-config request API type -- default: gNMI") parser.add_argument( "--noop", action="store_true", default=False, help="No operation, to be used while using optional arguments") parser.add_argument("--augment-modules-csv", action="append", default=[], nargs="*", help="Add additional lines to modules.csv") args, unknown = parser.parse_known_args() # parse the bucket options argsdict = vars(args) tclist_bucket = ",".join(argsdict["tclist_bucket"] or "") bucket_list = [] for bucket in range(1, 9): value = argsdict["bucket_{}".format(bucket)] if value is None: continue bucket_list.append(str(bucket)) tclist_bucket = ",".join(bucket_list) if not value: continue os.environ["SPYTEST_TOPO_{}".format(bucket)] = " ".join(value) # update sys.argv with arguments from suite args if args.test_suite: addl_args = parse_suite_files(args.test_suite) print("\nSuite Arguments {}\n".format(" ".join(addl_args))) index = sys.argv.index("--test-suite") new_argv = [] new_argv.extend(sys.argv[:index]) new_argv.extend(addl_args) new_argv.extend(sys.argv[index + 2:]) sys.argv = new_argv #print("\nSuite Arguments {}\n".format(" ".join(sys.argv))) os.environ["SPYTEST_SUITE_ARGS"] = " ".join(addl_args) return _parse_args(pre_parse=pre_parse) if pre_parse and args.args_file: # read arguments from file user_root = env.get("SPYTEST_USER_ROOT") if user_root and not os.path.isabs(args.args_file): filepath = os.path.join(user_root, args.args_file) else: filepath = args.args_file file_args = [] for line in utils.read_lines(filepath): file_args.extend(utils.split_with_quoted_strings(line)) # update sys.argv with arguments from file index = sys.argv.index("--args-file") new_argv = [] new_argv.extend(sys.argv[:index]) new_argv.extend(file_args) new_argv.extend(sys.argv[index + 2:]) sys.argv = new_argv # update SPYTEST_CMDLINE_ARGS with arguments from file app_cmdline = env.get("SPYTEST_CMDLINE_ARGS", "") app_args = utils.split_with_quoted_strings(app_cmdline) index = app_args.index("--args-file") app_new_args = [] app_new_args.extend(app_args[:index]) for arg in file_args: app_new_args.append("'{}'".format(arg) if " " in arg else arg) app_new_args.extend(app_args[index + 2:]) os.environ["SPYTEST_CMDLINE_ARGS"] = " ".join(app_new_args) return _parse_args() sys.argv = [sys.argv[0]] sys.argv.extend(unknown) for name, value in args.env: print("setting environment {} = {}".format(name, value)) os.environ[name] = value if args.exclude_devices: os.environ["SPYTEST_TESTBED_EXCLUDE_DEVICES"] = args.exclude_devices sys.argv.extend(["--exclude-devices", args.exclude_devices]) if args.include_devices: os.environ["SPYTEST_TESTBED_INCLUDE_DEVICES"] = args.include_devices sys.argv.extend(["--include-devices", args.include_devices]) if args.testbed_file: os.environ["SPYTEST_TESTBED_FILE"] = args.testbed_file if args.tclist_file: os.environ["SPYTEST_TCLIST_FILE"] = ",".join(args.tclist_file) if args.logs_path: os.environ["SPYTEST_LOGS_PATH"] = args.logs_path os.environ["SPYTEST_LOGS_LEVEL"] = args.logs_level if args.open_config_api: os.environ["SPYTEST_OPENCONFIG_API"] = args.open_config_api prefix = "" prefix = "results" if args.results_prefix: file_prefix = args.results_prefix elif args.file_mode and prefix: file_prefix = prefix elif tclist_bucket: file_prefix = prefix elif prefix: file_prefix = "{}_{}".format(prefix, time.strftime("%Y_%m_%d_%H_%M_%S")) else: file_prefix = "{}".format(time.strftime("%Y_%m_%d_%H_%M_%S")) os.environ["SPYTEST_FILE_PREFIX"] = file_prefix # filemode is needed in more places if args.file_mode: os.environ["SPYTEST_FILE_MODE"] = "1" sys.argv.append("--file-mode") addl_args = parse_batch_args(args.numprocesses, tclist_bucket, args.augment_modules_csv) sys.argv.extend(addl_args) seed = utils.get_random_seed() print("SPYTEST_RAMDOM_SEED used = {}".format(seed)) return args
def pytest_runtestloop(self): def search_nodeid(entries, nodeid): for ent in entries: if nodeid == ent.nodeid: return ent return None def finish_test(item): getattr(conn.root, "finish_test")(item.nodeid) def get_test(entries): while 1: nodeid = getattr(conn.root, "get_test")() if not nodeid: break item = search_nodeid(entries, nodeid) if item: return item return None # connect to batch server conn = None for _ in range(0, 10): try: filename = os.path.join(self.logs_path, "..", "batch.server") lines = utils.read_lines(filename) port = int(lines[0]) conn = rpyc.connect("127.0.0.1", port) if conn and conn.root: break time.sleep(2) except Exception as exp: print("connect to batch server", exp, filename, port) time.sleep(2) try: item_list = [] # wait for master ready is_ready = getattr(conn.root, "is_ready") while not is_ready(os.getpid()): trace("slave: waiting for master") time.sleep(2) # get first item item = get_test(self.items) if item: item_list.append(item) while 1: # check if there is some thing to do if not item_list: break # get next item item = get_test(self.items) if item: item_list.append(item) # get the item and next for the current execution [item, nextitem] = [item_list.pop(0), None] if item_list: nextitem = item_list[-1] debug("slave: pytest_runtestloop", item, nextitem) self.config.hook.pytest_runtest_protocol(item=item, nextitem=nextitem) finish_test(item) except KeyboardInterrupt: trace("slave: interrupted") conn.close() trace("") os._exit(0)
def ansible_playbook(playbook, host_list, username, password, logs_path=None, trace=False, verbose="", **kwargs): ansible_root = os.path.join(os.path.dirname(__file__), '..', "ansible") ansible_cfg = os.path.join(ansible_root, "ansible.cfg") ansible_cfg = os.path.abspath(ansible_cfg) ansible_dir = os.path.dirname(sys.executable) ansible_exe = os.path.join(ansible_dir, "ansible-playbook") # check if playbook is present if not os.path.exists(playbook): msgs = ["Playbook file {} is not present".format(playbook)] msgs.append("Trying replative to ansible config") playbook = os.path.join(ansible_root, playbook) if not os.path.exists(playbook): msgs.append("Playbook file {} is not present".format(playbook)) retval = "\n".join(msgs) if trace: print("ERR: {}".format(retval)) return retval if logs_path: os.environ["ANSIBLE_LOCAL_TEMP"] = logs_path os.environ["ANSIBLE_CONFIG"] = ansible_cfg # added the SSH_ARGS as environment variable to supress host checking as the nodes # in the case would be dut's with dynamic inventory. ssh_args = ["-o ControlMaster=auto"] ssh_args.append("-o ControlPersist=60s") ssh_args.append("-o UserKnownHostsFile=/dev/null") ssh_args.append("-o StrictHostKeyChecking=no") os.environ["ANSIBLE_SSH_ARGS"] = " ".join(ssh_args) fp = tempfile.NamedTemporaryFile(delete=False) _fp_write(fp, "[hosts]\n") for host in host_list: _fp_write(fp, "{}\n".format(host)) _fp_write(fp, "[hosts:vars]\n") _fp_write(fp, "ansible_user={}\n".format(username)) _fp_write(fp, "ansible_password={}\n".format(password)) _fp_write(fp, "ansible_become_password={}\n".format(password)) for key, value in kwargs.items(): _fp_write(fp, "{}={}\n".format(key, value)) fp.close() configs = "\n".join(utils.read_lines(fp.name)) cmd = "{} {} -i {} {}".format(ansible_exe, verbose, fp.name, playbook) if trace: print("Executing", cmd) proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) out, err = proc.communicate() proc.wait() os.unlink(fp.name) if proc.returncode != 0: msg = [ "Error: Failed to execute ansible playbook '{}'".format(playbook) ] msg.append("errcode: {} error: ('{}')".format(proc.returncode, err.strip())) msg.append("output: {}".format(out)) msg.append("config:\n{}".format(configs)) return "\n".join(msg) for line in out.splitlines(): if trace: print("OUT: {}".format(line)) for line in err.splitlines(): if trace: print("ERR: {}".format(line)) return out
def _parse_args(pre_parse=False): # pytest hack to let it wotk with absolute paths for testbed and tclist parser = argparse.ArgumentParser(description='Process SpyTest arguments.', add_help=False) if pre_parse: parser.add_argument("--args-file", action="store", default=None, help="spytest arguments from file path") parser.add_argument("--testbed-file", action="store", default=None, help="testbed file path -- default: ./testbed.yaml") parser.add_argument("--tclist-file", action="store", default=None, help="test case list file path") parser.add_argument("--logs-path", action="store", default=None, help="logs folder -- default: .") parser.add_argument("--logs-level", action="store", default="info", help="logs level -- default: info") parser.add_argument("--log-level", action="store", dest="logs_level", default="info", help="logs level -- default: info") parser.add_argument("--results-prefix", action="store", default=None, help="Prefix to be used for results.") parser.add_argument("--file-mode", action="store_true", default=False, help="Execute in file mode -- default: false") parser.add_argument("-n", "--numprocesses", action="store", default=None, type=int, help="number of preocessese") parser.add_argument("--tclist-bucket", action="append", default=None, help="use test cases from buckets") parser.add_argument("--env", action="append", default=[], nargs=2, help="environment variables") args, unknown = parser.parse_known_args() if pre_parse and args.args_file: # read arguments from file user_root = os.getenv("SPYTEST_USER_ROOT") if user_root and not os.path.isabs(args.args_file): filepath = os.path.join(user_root, args.args_file) else: filepath = args.args_file file_args = [] for line in utils.read_lines(filepath): file_args.extend(utils.split_with_quoted_strings(line)) # update sys.argv with arguments from file index = sys.argv.index("--args-file") new_argv = [] new_argv.extend(sys.argv[:index]) new_argv.extend(file_args) new_argv.extend(sys.argv[index + 2:]) sys.argv = new_argv # update SPYTEST_CMDLINE_ARGS with arguments from file app_cmdline = os.getenv("SPYTEST_CMDLINE_ARGS", "") app_args = utils.split_with_quoted_strings(app_cmdline) index = app_args.index("--args-file") app_new_args = [] app_new_args.extend(app_args[:index]) for arg in file_args: app_new_args.append("'{}'".format(arg) if " " in arg else arg) app_new_args.extend(app_args[index + 2:]) os.environ["SPYTEST_CMDLINE_ARGS"] = " ".join(app_new_args) return _parse_args() sys.argv = [sys.argv[0]] sys.argv.extend(unknown) for name, value in args.env: print("setting environment {} = {}".format(name, value)) os.environ[name] = value if args.testbed_file: os.environ["SPYTEST_TESTBED_FILE"] = args.testbed_file if args.tclist_file: os.environ["SPYTEST_TCLIST_FILE"] = args.tclist_file if args.logs_path: os.environ["SPYTEST_LOGS_PATH"] = args.logs_path os.environ["SPYTEST_LOGS_LEVEL"] = args.logs_level prefix = "results" if args.results_prefix: file_prefix = args.results_prefix os.environ["SPYTEST_RESULTS_PREFIX"] = file_prefix else: file_prefix = "{0}_{1}".format(prefix, time.strftime("%Y_%m_%d_%H_%M")) os.environ["SPYTEST_FILE_PREFIX"] = file_prefix # filemode is needed in more places if args.file_mode: os.environ["SPYTEST_FILE_MODE"] = "1" sys.argv.append("--file-mode") addl_args = parse_batch_args(args.numprocesses, args.tclist_bucket) sys.argv.extend(addl_args) os.environ["SPYTEST_RAMDOM_SEED"] = str(random.randint(10000, 20000))