def test_run_remote_util_arg_types(self): """Test that a remote utility runs properly with different argument types.""" result = remote_door.run_remote_util( self.session, "json", "dumps", ["foo", { "bar": ["baz", None, 1.0, 2] }], skipkeys=False, separators=None, # must be boolean but we want to test string allow_nan="string for yes") self.assertEqual(result, '["foo", {"bar": ["baz", null, 1.0, 2]}]') local_controls = glob.glob("tmp*.control") remote_controls = glob.glob( os.path.join(remote_door.REMOTE_CONTROL_DIR, "tmp*.control")) self.assertEqual(len(local_controls), len(remote_controls)) self.assertEqual(len(remote_controls), 1) self.assertEqual(os.path.basename(local_controls[0]), os.path.basename(remote_controls[0])) with open(remote_controls[0]) as handle: control_lines = handle.readlines() self.assertIn("import json\n", control_lines) self.assertIn( "result = json.dumps(['foo', {'bar': ['baz', None, 1.0, 2]}], " "allow_nan=r'string for yes', separators=None, skipkeys=False)\n", control_lines)
def test_run_remote_util(self): """Test that a remote utility can be run properly.""" remote_door.run_remote_util(self.session, "foo_util", "bar_func", 42, "spring", sing="zazz") # python 3.6 and above if hasattr(self.session.cmd, "assert_called_once"): self.session.cmd.assert_called_once() else: self.assertEqual(self.session.cmd.call_count, 1) command = self.session.cmd.call_args[0][0] self.assertTrue(re.match(r"python3 /tmp/tmp.+\.control", command), "A control file has to be generated and called on the peer") control = os.path.basename(command.lstrip("python3 ")) with open(control) as handle: control_lines = handle.readlines() self.assertIn("import foo_util\n", control_lines) self.assertIn("result = foo_util.bar_func(42, r'spring', sing=r'zazz')\n", control_lines)
def test_run_remote_util_object(self): """Test that a remote utility object can be run properly.""" util_object = "BarClass(val1, 'val2')" remote_door.run_remote_util(self.session, "foo_util", "%s.baz_func" % util_object, "Wonderland is fun", wanderer=None) # python 3.6 and above if hasattr(self.session.cmd, "assert_called_once"): self.session.cmd.assert_called_once() else: self.assertEqual(self.session.cmd.call_count, 1) command = self.session.cmd.call_args[0][0] self.assertTrue(re.match(r"python3 /tmp/tmp.+\.control", command), "A control file has to be generated and called on the peer") control = os.path.basename(command.lstrip("python3 ")) with open(control) as handle: control_lines = handle.readlines() self.assertIn("import foo_util\n", control_lines) self.assertIn("result = foo_util.BarClass(val1, 'val2').baz_func(" "r'Wonderland is fun', wanderer=None)\n", control_lines)
def test_run_remote_util(self): """Test that a remote utility runs properly.""" result = remote_door.run_remote_util(self.session, "math", "gcd", 2, 3) self.assertEqual(int(result), 1) local_controls = glob.glob("tmp*.control") remote_controls = glob.glob( os.path.join(remote_door.REMOTE_CONTROL_DIR, "tmp*.control")) self.assertEqual(len(local_controls), len(remote_controls)) self.assertEqual(len(remote_controls), 1) self.assertEqual(os.path.basename(local_controls[0]), os.path.basename(remote_controls[0])) with open(remote_controls[0]) as handle: control_lines = handle.readlines() self.assertIn("import math\n", control_lines) self.assertIn("result = math.gcd(2, 3)\n", control_lines)
def test_run_remote_util_object(self): """Test that a remote utility object runs properly.""" result = remote_door.run_remote_util(self.session, "collections", "OrderedDict().get", "akey") self.assertEqual(result, "None") local_controls = glob.glob("tmp*.control") remote_controls = glob.glob( os.path.join(remote_door.REMOTE_CONTROL_DIR, "tmp*.control")) self.assertEqual(len(local_controls), len(remote_controls)) self.assertEqual(len(remote_controls), 1) self.assertEqual(os.path.basename(local_controls[0]), os.path.basename(remote_controls[0])) with open(remote_controls[0]) as handle: control_lines = handle.readlines() self.assertIn("result = collections.OrderedDict().get(r'akey')\n", control_lines)
def run(test, params, env): """ Main test run. :param test: test object :type test: :py:class:`avocado_vt.test.VirtTest` :param params: extended dictionary of parameters :type params: :py:class:`virttest.utils_params.Params` :param env: environment object :type env: :py:class:`virttest.utils_env.Env` """ error_context.context("network configuration") vmnet = env.get_vmnet() vmnet.start_all_sessions() vms = vmnet.get_vms() server_vm = vms.server client_vm = vms.client vmnet.ping_all() # call to a function shared among tests sleep(3) error_context.context("misc commands on each vm") tmp_server = server_vm.session.cmd("ls " + server_vm.params["tmp_dir"]) tmp_client = client_vm.session.cmd("dir " + client_vm.params["tmp_dir"]) logging.info("Content of temporary server folder:\n%s", tmp_server) logging.info("Content of temporary client folder:\n%s", tmp_client) deployed_folders = ("data", "utils", "packages") for folder in deployed_folders: if folder not in tmp_server: raise exceptions.TestFail( "No deployed %s was found on the server" % folder) if folder not in tmp_client: raise exceptions.TestFail( "No deployed %s was found on the client" % folder) error_context.context("enhanced remote checks") if params.get_boolean("enhanced_remote_checks"): # Another way to run remote commands is through the host -> guest door, # which provides us with different functions to share code between # the host machine and a guest virtual machine (vm). if not DOOR_AVAILABLE: raise exceptions.TestSkipError( "The remote door of an upgraded aexpect package is not available" ) door.DUMP_CONTROL_DIR = test.logdir door.REMOTE_PYTHON_BINARY = "python3.4" # The most advanced remote methods require serialization backend. serialization_cmd = door.REMOTE_PYTHON_BINARY + " -c 'import Pyro4'" host_serialization = server_vm.session.cmd_status( serialization_cmd) == 0 try: import Pyro4 except ImportError: guest_serialization = False else: guest_serialization = True # The simplest remote execution we can perform is through a single call to # a utility or module. Under the hood, this is similar to running a # python script on the vm with just a few lines importing the module or # utility and calling its desired function. if params.get_boolean("remote_util_check"): door.run_remote_util( server_vm.session, "os", "listdir", server_vm.params["tmp_dir"].replace("\\", r"\\"), ) # Note that the usage of `shell=True` is here because `run_remote_util` # doesn't support array serialization. However, `shell=True` should be # avoided in real test scripts. door.run_remote_util( server_vm.session, "subprocess", "call", "dir " + client_vm.params["tmp_dir"].replace("\\", r"\\"), shell=True) # A bit more flexible way to run code on the vm is using a decorated # function with multiple locally written but remotely executed lines. if params.get_boolean("remote_decorator_check"): check_walk(server_vm.session, params) # One advanced but last resort method is to use a control file which is # a file where the remote code is written and deployed to the vm. This # is also used internally for both previous methods. if params.get_boolean("remote_control_check"): # With a bit of metaprogramming, we can set single parameters, lists, or # dicts for one time use by th control file. control_path = server_vm.params["control_file"] control_path = door.set_subcontrol_parameter( control_path, "EXTRA_SLEEP", 2) control_path = door.set_subcontrol_parameter( control_path, "ROOT_DIR", params["root_dir"]) control_path = door.set_subcontrol_parameter_list( control_path, "DETECT_DIRS", ["data", "utils"]) control_path = door.set_subcontrol_parameter_dict( control_path, "SIMPLE_PARAMS", { "client": server_vm.params["client"], "server": server_vm.params["server"] }) door.run_subcontrol(server_vm.session, control_path) # It becomes more intricate but possible to share the Cartesian # configuration between the host test and the control file and thus # allowing for return arguments from the control but we need a remote # object backend as additional satisfied dependency. if host_serialization and guest_serialization: logging.info( "Performing extra hostname check using shared parameters control" ) control_path = server_vm.params["control_file"].replace( "step_3", "step_3.2") control_path = door.set_subcontrol_parameter_object( control_path, server_vm.params) door.run_subcontrol(server_vm.session, control_path) failed_checks = server_vm.params["failed_checks"] if failed_checks > 0: raise exceptions.TestFail("%s hostname checks failed" % failed_checks) # The highest complexity but most permanent approach (supports multiple # calls switching back and forth from guest to host) is using a remote # object and serializing the calls in the background. This is the most # flexible approach and a bit less complex than using controls but might # require an additional dependency as a backend implementation for the # remote objects (we usually use pyro and pickle or serpent serializers). if params.get_boolean("remote_object_check"): if not guest_serialization or not host_serialization: raise exceptions.TestSkipError( "The remote door object backend (pyro) is not available") sysmisc = door.get_remote_object( "sample_utility", session=server_vm.wait_for_login(), host=server_vm.params["ip_" + server_vm.params["ro_nic"]], port=server_vm.params["ro_port"]) sysmisc.sleep(5) logging.info( "It would appear that the test terminated in a civilized manner.")