2023/10/30 16:12:20 - TG 1 - INFO - Sending: 'import time' 2023/10/30 16:12:20 - TG 1 - DEBUG - Got output: >>> import time >>> 2023/10/30 16:12:20 - TG 1 - INFO - Sending: 'class QuittableXMLRPCServer(SimpleXMLRPCServer): r"""Basic XML-RPC server. The server may be augmented by functions serializable by the marshal module. Example: :: def hello_world(): # to be sent to the XML-RPC server print("Hello World!") # start the XML-RPC server on the remote node # the example assumes you're already connect to a tg_node # this is done by starting a Python shell on the remote node from framework.remote_session import PythonShell session = tg_node.create_interactive_shell(PythonShell, timeout=5, privileged=True) # then importing the modules needed to run the server # and the modules for any functions later added to the server session.send_command("import xmlrpc") session.send_command("from xmlrpc.server import SimpleXMLRPCServer") # sending the source code of this class to the Python shell from xmlrpc.server import SimpleXMLRPCServer src = inspect.getsource(QuittableXMLRPCServer) src = "\n".join([l for l in src.splitlines() if not l.isspace() and l != ""]) spacing = "\n" * 4 session.send_command(spacing + src + spacing) # then starting the server with: command = "s = QuittableXMLRPCServer(('0.0.0.0', {listen_port}));s.serve_forever()" session.send_command(command, "XMLRPC OK") # now the server is running on the remote node and we can add functions to it # first connect to the server from the execution node import xmlrpc.client server_url = f"http://{tg_node.config.hostname}:8000" rpc_server_proxy = xmlrpc.client.ServerProxy(server_url) # get the function bytes to send import marshal function_bytes = marshal.dumps(hello_world.__code__) rpc_server_proxy.add_rpc_function(hello_world.__name__, function_bytes) # now we can execute the function on the server xmlrpc_binary_recv: xmlrpc.client.Binary = rpc_server_proxy.hello_world() print(str(xmlrpc_binary_recv)) """ def __init__(self, *args, **kwargs): """Extend the XML-RPC server initialization. Args: args: The positional arguments that will be passed to the superclass's constructor. kwargs: The keyword arguments that will be passed to the superclass's constructor. The `allow_none` argument will be set to ``True``. """ kwargs["allow_none"] = True super().__init__(*args, **kwargs) self.register_introspection_functions() self.register_function(self.quit) self.register_function(self.add_rpc_function) def quit(self) -> None: """Quit the server.""" self._BaseServer__shutdown_request = True return None def add_rpc_function(self, name: str, function_bytes: xmlrpc.client.Binary) -> None: """Add a function to the server. This is meant to be executed remotely. Args: name: The name of the function. function_bytes: The code of the function. """ function_code = marshal.loads(function_bytes.data) function = types.FunctionType(function_code, globals(), name) self.register_function(function) def serve_forever(self, poll_interval: float = 0.5) -> None: """Start the server.""" print("XMLRPC OK") super().serve_forever(poll_interval)' 2023/10/30 16:12:20 - TG 1 - DEBUG - Got output: >>> class QuittableXMLRPCServer(SimpleXMLRPCServer): 2023/10/30 16:12:20 - TG 1 - INFO - Sending: 'server = QuittableXMLRPCServer(('0.0.0.0', 8000));server.serve_forever()' 2023/10/30 16:12:20 - TG 1 - DEBUG - Got output: ... r"""Basic XML-RPC server. ... The server may be augmented by functions serializable by the marshal module. ... Example: ... :: ... def hello_world(): ... # to be sent to the XML-RPC server ... print("Hello World!") ... # start the XML-RPC server on the remote node ... # the example assumes you're already connect to a tg_node ... # this is done by starting a Python shell on the remote node ... from framework.remote_session import PythonShell ... session = tg_node.create_interactive_shell(PythonShell, timeout=5, privileged=True) ... # then importing the modules needed to run the server ... # and the modules for any functions later added to the server ... session.send_command("import xmlrpc") ... session.send_command("from xmlrpc.server import SimpleXMLRPCServer") ... # sending the source code of this class to the Python shell ... from xmlrpc.server import SimpleXMLRPCServer ... src = inspect.getsource(QuittableXMLRPCServer) ... src = "\n".join([l for l in src.splitlines() if not l.isspace() and l != ""]) ... spacing = "\n" * 4 ... session.send_command(spacing + src + spacing) ... # then starting the server with: ... command = "s = QuittableXMLRPCServer(('0.0.0.0', {listen_port}));s.serve_forever()" ... session.send_command(command, "XMLRPC OK") 2023/10/30 16:12:20 - DTSRunner - ERROR - Creation of node TG 1 failed. Traceback (most recent call last): File "/home/jlinkes/workspace/dpdk/dpdk/dts/framework/dts.py", line 81, in run_all tg_node = TGNode(execution.traffic_generator_node) File "/home/jlinkes/workspace/dpdk/dpdk/dts/framework/testbed_model/tg_node.py", line 48, in __init__ self.traffic_generator = create_traffic_generator( File "/home/jlinkes/workspace/dpdk/dpdk/dts/framework/testbed_model/traffic_generator/__init__.py", line 39, in create_traffic_generator return ScapyTrafficGenerator(tg_node, traffic_generator_config) File "/home/jlinkes/workspace/dpdk/dpdk/dts/framework/testbed_model/traffic_generator/scapy.py", line 281, in __init__ self.rpc_server_proxy.add_rpc_function(function.__name__, function_bytes) File "/home/jlinkes/.pyenv/versions/3.10.11/lib/python3.10/xmlrpc/client.py", line 1122, in __call__ return self.__send(self.__name, args) File "/home/jlinkes/.pyenv/versions/3.10.11/lib/python3.10/xmlrpc/client.py", line 1464, in __request response = self.__transport.request( File "/home/jlinkes/.pyenv/versions/3.10.11/lib/python3.10/xmlrpc/client.py", line 1166, in request return self.single_request(host, handler, request_body, verbose) File "/home/jlinkes/.pyenv/versions/3.10.11/lib/python3.10/xmlrpc/client.py", line 1178, in single_request http_conn = self.send_request(host, handler, request_body, verbose) File "/home/jlinkes/.pyenv/versions/3.10.11/lib/python3.10/xmlrpc/client.py", line 1291, in send_request self.send_content(connection, request_body) File "/home/jlinkes/.pyenv/versions/3.10.11/lib/python3.10/xmlrpc/client.py", line 1321, in send_content connection.endheaders(request_body) File "/home/jlinkes/.pyenv/versions/3.10.11/lib/python3.10/http/client.py", line 1278, in endheaders self._send_output(message_body, encode_chunked=encode_chunked) File "/home/jlinkes/.pyenv/versions/3.10.11/lib/python3.10/http/client.py", line 1038, in _send_output self.send(msg) File "/home/jlinkes/.pyenv/versions/3.10.11/lib/python3.10/http/client.py", line 976, in send self.connect() File "/home/jlinkes/.pyenv/versions/3.10.11/lib/python3.10/http/client.py", line 942, in connect self.sock = self._create_connection( File "/home/jlinkes/.pyenv/versions/3.10.11/lib/python3.10/socket.py", line 845, in create_connection raise err File "/home/jlinkes/.pyenv/versions/3.10.11/lib/python3.10/socket.py", line 833, in create_connection sock.connect(sa) ConnectionRefusedError: [Errno 111] Connection refused 2023/10/30 16:12:20 - DTSRunner - DEBUG - Summary of errors: 2023/10/30 16:12:20 - DTSRunner - DEBUG - ConnectionRefusedError(111, 'Connection refused') 2023/10/30 16:12:20 - DTSRunner - INFO - DTS execution has ended.