diff --git a/compute_endpoint/globus_compute_endpoint/endpoint/taskqueue.py b/compute_endpoint/globus_compute_endpoint/endpoint/taskqueue.py index f7a93d62a..7f68fce01 100644 --- a/compute_endpoint/globus_compute_endpoint/endpoint/taskqueue.py +++ b/compute_endpoint/globus_compute_endpoint/endpoint/taskqueue.py @@ -91,6 +91,8 @@ def __init__( if linger is not None: self.zmq_socket.setsockopt(zmq.LINGER, linger) + self.zmq_socket.setsockopt(zmq.IPV6, True) + # all zmq setsockopt calls must be done before bind/connect is called if self.mode == "server": self.zmq_socket.bind(f"tcp://*:{port}") @@ -121,7 +123,7 @@ def setup_server_auth(self): # Start an authenticator for this context. self.auth = ThreadAuthenticator(self.context) self.auth.start() - self.auth.allow("127.0.0.1") + self.auth.allow("::1") # Tell the authenticator how to handle CURVE requests if not self.ironhouse: diff --git a/compute_endpoint/globus_compute_endpoint/engines/high_throughput/engine.py b/compute_endpoint/globus_compute_endpoint/engines/high_throughput/engine.py index 4bb281831..f99b383ad 100644 --- a/compute_endpoint/globus_compute_endpoint/engines/high_throughput/engine.py +++ b/compute_endpoint/globus_compute_endpoint/engines/high_throughput/engine.py @@ -10,6 +10,7 @@ import multiprocessing import os import queue +import socket import threading import time import typing as t @@ -299,14 +300,15 @@ def __init__( self.endpoint_id = endpoint_id self._task_counter = 0 - try: - ipaddress.ip_address(address=address) - except Exception: - log.critical( - f"Invalid address supplied: {address}. " - "Please use a valid IPv4 or IPv6 address" + if not HighThroughputEngine.is_hostname_or_ip(address): + err_msg = ( + # yes, suggesting `=` formatter, so it's clear which argument. + f"Invalid address: {address=}\n\n" + "Expecting an interface name, hostname, IPv4 address, or IPv6 address." ) - raise + log.critical(err_msg) + raise ValueError(err_msg) + self.address = address self.worker_ports = worker_ports self.worker_port_range = worker_port_range @@ -376,12 +378,8 @@ def start( self.run_dir = run_dir self.endpoint_id = endpoint_id - self.outgoing_q = zmq_pipes.TasksOutgoing( - "127.0.0.1", self.interchange_port_range - ) - self.incoming_q = zmq_pipes.ResultsIncoming( - "127.0.0.1", self.interchange_port_range - ) + self.outgoing_q = zmq_pipes.TasksOutgoing("127.0.0.1", self.interchange_port_range) + self.incoming_q = zmq_pipes.ResultsIncoming("127.0.0.1", self.interchange_port_range) self.command_client = zmq_pipes.CommandClient( "127.0.0.1", self.interchange_port_range ) @@ -419,6 +417,27 @@ def start( return self.outgoing_q.port, self.incoming_q.port, self.command_client.port + @staticmethod + def is_hostname_or_ip(hostname_or_ip: str) -> bool: + """ + Utility method to verify that the input is a valid hostname or + IP address. + """ + if not hostname_or_ip: + return False + else: + try: + socket.gethostbyname(hostname_or_ip) + return True + except socket.gaierror: + # Not a hostname, now check IP + pass + try: + ipaddress.ip_address(address=hostname_or_ip) + except ValueError: + return False + return True + def _start_local_interchange_process(self): """Starts the interchange process locally @@ -431,7 +450,7 @@ def _start_local_interchange_process(self): name="Engine-Interchange", args=(comm_q,), kwargs={ - "client_address": "127.0.0.1", # engine and ix are on the same node + "client_address": "127.0.0.1", # engine and ix are on same node "client_ports": ( self.outgoing_q.port, self.incoming_q.port, diff --git a/compute_endpoint/globus_compute_endpoint/engines/high_throughput/interchange.py b/compute_endpoint/globus_compute_endpoint/engines/high_throughput/interchange.py index c02b8c88c..338dd04e1 100644 --- a/compute_endpoint/globus_compute_endpoint/engines/high_throughput/interchange.py +++ b/compute_endpoint/globus_compute_endpoint/engines/high_throughput/interchange.py @@ -134,11 +134,11 @@ def __init__( client_address : str The ip address at which the parsl client can be reached. - Default: "127.0.0.1" + Default: "localhost" interchange_address : str The ip address at which the workers will be able to reach the Interchange. - Default: "127.0.0.1" + Default: "localhost" client_ports : tuple[int, int, int] The ports at which the client can be reached diff --git a/compute_endpoint/globus_compute_endpoint/engines/high_throughput/manager.py b/compute_endpoint/globus_compute_endpoint/engines/high_throughput/manager.py index 82f8da75a..bf51f243e 100755 --- a/compute_endpoint/globus_compute_endpoint/engines/high_throughput/manager.py +++ b/compute_endpoint/globus_compute_endpoint/engines/high_throughput/manager.py @@ -80,8 +80,8 @@ class Manager: def __init__( self, - task_q_url="tcp://127.0.0.1:50097", - result_q_url="tcp://127.0.0.1:50098", + task_q_url="tcp://localhost:50097", + result_q_url="tcp://localhost:50098", max_queue_size=10, cores_per_worker=1, available_accelerators: list[str] | None = None, @@ -171,6 +171,7 @@ def __init__( # Linger is set to 0, so that the manager can exit even when there might be # messages in the pipe self.task_incoming.setsockopt(zmq.LINGER, 0) + self.task_incoming.setsockopt(zmq.IPV6, True) self.task_incoming.connect(task_q_url) self.logdir = logdir @@ -179,6 +180,7 @@ def __init__( self.result_outgoing = self.context.socket(zmq.DEALER) self.result_outgoing.setsockopt(zmq.IDENTITY, uid.encode("utf-8")) self.result_outgoing.setsockopt(zmq.LINGER, 0) + self.result_outgoing.setsockopt(zmq.IPV6, True) self.result_outgoing.connect(result_q_url) log.info("Manager connected") @@ -213,7 +215,8 @@ def __init__( self.funcx_task_socket = self.context.socket(zmq.ROUTER) self.funcx_task_socket.set_hwm(0) - self.address = "127.0.0.1" + self.funcx_task_socket.setsockopt(zmq.IPV6, True) + self.address = "localhost" self.worker_port = self.funcx_task_socket.bind_to_random_port( "tcp://*", min_port=self.internal_worker_port_range[0], diff --git a/compute_endpoint/globus_compute_endpoint/engines/high_throughput/worker.py b/compute_endpoint/globus_compute_endpoint/engines/high_throughput/worker.py index 954e8e0e9..bd3a30abd 100644 --- a/compute_endpoint/globus_compute_endpoint/engines/high_throughput/worker.py +++ b/compute_endpoint/globus_compute_endpoint/engines/high_throughput/worker.py @@ -38,7 +38,8 @@ class Worker: Worker id string address : str - Address at which the manager might be reached. This is usually 127.0.0.1 + Address at which the manager might be reached. This is usually the ipv4 + or ipv6 loopback address 127.0.0.1 or ::1 port : int Port at which the manager can be reached @@ -79,6 +80,7 @@ def __init__( self.task_socket = self.context.socket(zmq.DEALER) self.task_socket.setsockopt(zmq.IDENTITY, self.identity) + self.task_socket.setsockopt(zmq.IPV6, True) log.info(f"Trying to connect to : tcp://{self.address}:{self.port}") self.task_socket.connect(f"tcp://{self.address}:{self.port}") diff --git a/compute_endpoint/globus_compute_endpoint/engines/high_throughput/zmq_pipes.py b/compute_endpoint/globus_compute_endpoint/engines/high_throughput/zmq_pipes.py index f41f3ecdc..aac200d55 100644 --- a/compute_endpoint/globus_compute_endpoint/engines/high_throughput/zmq_pipes.py +++ b/compute_endpoint/globus_compute_endpoint/engines/high_throughput/zmq_pipes.py @@ -1,5 +1,8 @@ #!/usr/bin/env python3 +from __future__ import annotations + +import ipaddress import logging import time @@ -10,6 +13,42 @@ log = logging.getLogger(__name__) +def _zmq_canonicalize_address(addr: str | int) -> str: + try: + ip = ipaddress.ip_address(addr) + except ValueError: + # Not a valid IPv4 or IPv6 address + if isinstance(addr, int): + # If it was an integer, then it's just plain invalid + raise + + # Otherwise, it was likely a hostname; let another layer deal with it + return addr + + if ip.version == 4: + return str(ip) # like "12.34.56.78" + elif ip.version == 6: + return f"[{ip}]" # like "[::1]" + + +def _zmq_create_socket_port(context: zmq.Context, ip_address: str | int, port_range): + """ + Utility method with logic shared by all the pipes + """ + sock = context.socket(zmq.DEALER) + sock.set_hwm(0) + # This option should work for both IPv4 and IPv6...? + # May not work until Parsl is updated? + sock.setsockopt(zmq.IPV6, True) + + port = sock.bind_to_random_port( + f"tcp://{_zmq_canonicalize_address(ip_address)}", + min_port=port_range[0], + max_port=port_range[1], + ) + return sock, port + + class CommandClient: """CommandClient""" @@ -24,13 +63,10 @@ def __init__(self, ip_address, port_range): Port range for the comms between client and interchange """ + self.context = zmq.Context() - self.zmq_socket = self.context.socket(zmq.DEALER) - self.zmq_socket.set_hwm(0) - self.port = self.zmq_socket.bind_to_random_port( - f"tcp://{ip_address}", - min_port=port_range[0], - max_port=port_range[1], + self.zmq_socket, self.port = _zmq_create_socket_port( + self.context, ip_address, port_range ) def run(self, message): @@ -66,12 +102,8 @@ def __init__(self, ip_address, port_range): """ self.context = zmq.Context() - self.zmq_socket = self.context.socket(zmq.DEALER) - self.zmq_socket.set_hwm(0) - self.port = self.zmq_socket.bind_to_random_port( - f"tcp://{ip_address}", - min_port=port_range[0], - max_port=port_range[1], + self.zmq_socket, self.port = _zmq_create_socket_port( + self.context, ip_address, port_range ) self.poller = zmq.Poller() self.poller.register(self.zmq_socket, zmq.POLLOUT) @@ -141,12 +173,8 @@ def __init__(self, ip_address, port_range): """ self.context = zmq.Context() - self.results_receiver = self.context.socket(zmq.DEALER) - self.results_receiver.set_hwm(0) - self.port = self.results_receiver.bind_to_random_port( - f"tcp://{ip_address}", - min_port=port_range[0], - max_port=port_range[1], + self.results_receiver, self.port = _zmq_create_socket_port( + self.context, ip_address, port_range ) def get(self, block=True, timeout=None): diff --git a/compute_endpoint/tests/conftest.py b/compute_endpoint/tests/conftest.py index 8677ca6b4..6c5776a09 100644 --- a/compute_endpoint/tests/conftest.py +++ b/compute_endpoint/tests/conftest.py @@ -139,7 +139,7 @@ def _runner(engine_type: t.Type[GlobusComputeEngineBase], **kwargs): k = dict(max_workers=2) elif engine_type is engines.GlobusComputeEngine: k = dict( - address="127.0.0.1", + address="::1", heartbeat_period=engine_heartbeat, heartbeat_threshold=2, job_status_kwargs=dict(max_idletime=0, strategy_period=0.1), @@ -153,7 +153,7 @@ def _runner(engine_type: t.Type[GlobusComputeEngineBase], **kwargs): """ k = dict( - address="127.0.0.1", + address="::1", heartbeat_period=engine_heartbeat, heartbeat_threshold=1, mpi_launcher="mpiexec", diff --git a/compute_endpoint/tests/integration/endpoint/endpoint/test_endpoint_manager.py b/compute_endpoint/tests/integration/endpoint/endpoint/test_endpoint_manager.py index cb8bfc7cd..fe53506c7 100644 --- a/compute_endpoint/tests/integration/endpoint/endpoint/test_endpoint_manager.py +++ b/compute_endpoint/tests/integration/endpoint/endpoint/test_endpoint_manager.py @@ -394,10 +394,10 @@ def test_with_funcx_config(self, mocker): mock_interchange.return_value.stop.return_value = None mock_optionals = {} - mock_optionals["interchange_address"] = "127.0.0.1" + mock_optionals["interchange_address"] = "::1" mock_funcx_config = {} - mock_funcx_config["endpoint_address"] = "127.0.0.1" + mock_funcx_config["endpoint_address"] = "::1" manager = Endpoint(funcx_dir=os.getcwd()) manager.name = "test" diff --git a/compute_endpoint/tests/integration/endpoint/endpoint/test_gcengine_strategy.py b/compute_endpoint/tests/integration/endpoint/endpoint/test_gcengine_strategy.py index f984c101f..d70cf45c7 100644 --- a/compute_endpoint/tests/integration/endpoint/endpoint/test_gcengine_strategy.py +++ b/compute_endpoint/tests/integration/endpoint/endpoint/test_gcengine_strategy.py @@ -16,7 +16,7 @@ def gc_engine_scaling(tmp_path): ep_id = uuid.uuid4() engine = GlobusComputeEngine( - address="127.0.0.1", + address="::1", heartbeat_period=1, heartbeat_threshold=2, provider=LocalProvider( @@ -37,7 +37,7 @@ def gc_engine_scaling(tmp_path): def gc_engine_non_scaling(tmp_path): ep_id = uuid.uuid4() engine = GlobusComputeEngine( - address="127.0.0.1", + address="::1", heartbeat_period=1, heartbeat_threshold=2, provider=LocalProvider( diff --git a/compute_endpoint/tests/integration/endpoint/executors/test_gcengine_retries.py b/compute_endpoint/tests/integration/endpoint/executors/test_gcengine_retries.py index 905b3c58b..914bca982 100644 --- a/compute_endpoint/tests/integration/endpoint/executors/test_gcengine_retries.py +++ b/compute_endpoint/tests/integration/endpoint/executors/test_gcengine_retries.py @@ -100,5 +100,5 @@ def test_repeated_fail(mock_gce, ez_pack_task): def test_default_retries_is_0(): - engine = GlobusComputeEngine(address="127.0.0.1") + engine = GlobusComputeEngine(address="localhost") assert engine.max_retries_on_system_failure == 0, "Users must knowingly opt-in" diff --git a/compute_endpoint/tests/unit/test_bad_endpoint_config.py b/compute_endpoint/tests/unit/test_bad_endpoint_config.py index ae73bcce6..3e68ea410 100644 --- a/compute_endpoint/tests/unit/test_bad_endpoint_config.py +++ b/compute_endpoint/tests/unit/test_bad_endpoint_config.py @@ -6,7 +6,7 @@ _MOCK_BASE = "globus_compute_endpoint.engines.high_throughput.engine." -@pytest.mark.parametrize("address", ("localhost", "login1.theta.alcf.anl.gov", "*")) +@pytest.mark.parametrize("address", ("example", "a.b.c.d.e", "*")) def test_invalid_address(address, htex_warns): with mock.patch(f"{_MOCK_BASE}log") as mock_log: with pytest.raises(ValueError): diff --git a/compute_endpoint/tests/unit/test_cli_behavior.py b/compute_endpoint/tests/unit/test_cli_behavior.py index d041e71b2..112d87c00 100644 --- a/compute_endpoint/tests/unit/test_cli_behavior.py +++ b/compute_endpoint/tests/unit/test_cli_behavior.py @@ -491,7 +491,7 @@ def test_config_yaml_display_none(run_line, mock_command_ensure, display_name): run_line(config_cmd) conf_dict = dict(yaml.safe_load(conf.read_text())) - conf_dict["engine"]["address"] = "127.0.0.1" # avoid unnecessary DNS lookup + conf_dict["engine"]["address"] = "::1" # avoid unnecessary DNS lookup conf = load_config_yaml(yaml.safe_dump(conf_dict)) assert conf.display_name is None, conf.display_name diff --git a/compute_endpoint/tests/unit/test_endpoint_config.py b/compute_endpoint/tests/unit/test_endpoint_config.py index c3b1e5631..384b06a09 100644 --- a/compute_endpoint/tests/unit/test_endpoint_config.py +++ b/compute_endpoint/tests/unit/test_endpoint_config.py @@ -20,7 +20,7 @@ @pytest.fixture def config_dict(): - return {"engine": {"type": "GlobusComputeEngine", "address": "127.0.0.1"}} + return {"engine": {"type": "GlobusComputeEngine", "address": "localhost"}} @pytest.fixture @@ -140,7 +140,9 @@ def test_conditional_engine_strategy( ): config_dict["engine"]["type"] = engine_type config_dict["engine"]["strategy"] = strategy - config_dict["engine"]["address"] = "127.0.0.1" + config_dict["engine"]["address"] = ( + "::1" if engine_type != "HighThroughputEngine" else "127.0.0.1" + ) if engine_type == "GlobusComputeEngine": if isinstance(strategy, str) or strategy is None: @@ -173,7 +175,7 @@ def test_provider_container_compatibility( ): config_dict["engine"]["container_uri"] = "docker://ubuntu" config_dict["engine"]["provider"] = {"type": provider_type} - config_dict["engine"]["address"] = "127.0.0.1" + config_dict["engine"]["address"] = "::1" if compatible: UserEndpointConfigModel(**config_dict) diff --git a/compute_endpoint/tests/unit/test_endpoint_unit.py b/compute_endpoint/tests/unit/test_endpoint_unit.py index 577c3f8f2..6097db0b8 100644 --- a/compute_endpoint/tests/unit/test_endpoint_unit.py +++ b/compute_endpoint/tests/unit/test_endpoint_unit.py @@ -530,7 +530,7 @@ def test_endpoint_get_metadata(mocker, engine_cls): k = {} if engine_cls is GlobusComputeEngine: - k["address"] = "127.0.0.1" + k["address"] = "::1" executors = [engine_cls(**k)] test_config = UserEndpointConfig(executors=executors) test_config.source_content = "foo: bar" @@ -720,7 +720,7 @@ def test_always_prints_endpoint_id_to_terminal(mocker, mock_ep_data, mock_reg_in def test_serialize_config_field_types(): fns = [str(uuid.uuid4()) for _ in range(5)] - ep_config = UserEndpointConfig(executors=[GlobusComputeEngine(address="127.0.0.1")]) + ep_config = UserEndpointConfig(executors=[GlobusComputeEngine(address="::1")]) ep_config._hidden_attr = "123" ep_config.rando_attr = "howdy" ep_config.allowed_functions = fns diff --git a/compute_endpoint/tests/unit/test_engines.py b/compute_endpoint/tests/unit/test_engines.py index 3641515b3..826287110 100644 --- a/compute_endpoint/tests/unit/test_engines.py +++ b/compute_endpoint/tests/unit/test_engines.py @@ -187,7 +187,8 @@ def test_gc_engine_system_failure(ez_pack_task, task_uuid, engine_runner): def test_serialized_engine_config_has_provider( engine_type: t.Type[GlobusComputeEngineBase], ): - ep_config = UserEndpointConfig(executors=[engine_type(address="127.0.0.1")]) + loopback = "127.7.0.1" if engine_type != "HighThroughputEngine" else "::1" + ep_config = UserEndpointConfig(executors=[engine_type(address=loopback)]) res = serialize_config(ep_config) executor = res["executors"][0].get("executor") or res["executors"][0] @@ -196,7 +197,7 @@ def test_serialized_engine_config_has_provider( def test_gcengine_compute_launch_cmd(): - engine = GlobusComputeEngine(address="127.0.0.1") + engine = GlobusComputeEngine(address="::1") assert engine.executor.launch_cmd.startswith( "globus-compute-endpoint python-exec" " parsl.executors.high_throughput.process_worker_pool" @@ -205,7 +206,7 @@ def test_gcengine_compute_launch_cmd(): def test_gcengine_compute_interchange_launch_cmd(): - engine = GlobusComputeEngine(address="127.0.0.1") + engine = GlobusComputeEngine(address="::1") assert engine.executor.interchange_launch_cmd[:3] == [ "globus-compute-endpoint", "python-exec", @@ -218,7 +219,7 @@ def test_gcengine_pass_through_to_executor(randomstring): args = ("arg1", 2) kwargs = { "label": "VroomEngine", - "address": "127.0.0.1", + "address": "::1", "encrypted": False, "max_workers_per_node": 1, "foo": "bar", @@ -291,12 +292,12 @@ def test_gcengine_encrypted(encrypted: bool, engine_runner): def test_gcengine_new_executor_not_exceptional(): - gce = GlobusComputeEngine(address="127.0.0.1") + gce = GlobusComputeEngine(address="::1") assert gce.executor_exception is None, "Expect no exception from fresh Executor" def test_gcengine_executor_exception_passthrough(randomstring): - gce = GlobusComputeEngine(address="127.0.0.1") + gce = GlobusComputeEngine(address="::1") exc_text = randomstring() gce.executor.set_bad_state_and_fail_all(ZeroDivisionError(exc_text)) assert isinstance(gce.executor_exception, ZeroDivisionError) @@ -304,7 +305,7 @@ def test_gcengine_executor_exception_passthrough(randomstring): def test_gcengine_bad_state_futures_failed_immediately(randomstring, task_uuid): - gce = GlobusComputeEngine(address="127.0.0.1") + gce = GlobusComputeEngine(address="::1") gce._engine_ready = True exc_text = randomstring() gce.executor.set_bad_state_and_fail_all(ZeroDivisionError(exc_text)) @@ -320,7 +321,7 @@ def test_gcengine_bad_state_futures_failed_immediately(randomstring, task_uuid): def test_gcengine_exception_report_from_bad_state(task_uuid): - gce = GlobusComputeEngine(address="127.0.0.1") + gce = GlobusComputeEngine(address="::1") gce._engine_ready = True gce.executor.set_bad_state_and_fail_all(ZeroDivisionError()) @@ -343,19 +344,19 @@ def test_gcengine_exception_report_from_bad_state(task_uuid): def test_gcengine_rejects_mpi_mode(randomstring): with pytest.raises(ValueError) as pyt_exc_1: - GlobusComputeEngine(enable_mpi_mode=True, address="127.0.0.1") + GlobusComputeEngine(enable_mpi_mode=True, address="::1") assert "is not supported" in str(pyt_exc_1) with pytest.raises(ValueError) as pyt_exc_2: - GlobusComputeEngine(mpi_launcher=randomstring(), address="127.0.0.1") + GlobusComputeEngine(mpi_launcher=randomstring(), address="::1") assert "is not supported" in str(pyt_exc_2) def test_gcengine_rejects_resource_specification(task_uuid): with pytest.raises(ValueError) as pyt_exc: - gce = GlobusComputeEngine(address="127.0.0.1") + gce = GlobusComputeEngine(address="::1") gce._engine_ready = True gce.submit( str(task_uuid), @@ -387,7 +388,7 @@ def test_gcmpiengine_accepts_resource_specification(task_uuid, randomstring): with mock.patch.object(GlobusMPIEngine, "_ExecutorClass") as mock_ex: mock_ex.__name__ = "ClassName" mock_ex.return_value = mock.Mock(launch_cmd="") - engine = GlobusMPIEngine(address="127.0.0.1") + engine = GlobusMPIEngine(address="::1") engine._engine_ready = True engine.submit(str(task_uuid), b"some task", resource_specification=spec) @@ -395,3 +396,23 @@ def test_gcmpiengine_accepts_resource_specification(task_uuid, randomstring): a, _k = engine.executor.submit.call_args assert spec in a + + +@pytest.mark.parametrize( + ("input", "is_valid"), + ( + [None, False], + ["", False], + ["localhost.1", False], + ["localhost", True], + ["1.2.3.4.5", False], + ["127.0.0.1", True], + ["example.com", True], + ["0:0:0:0:0:0:0:1", True], + ["11111:0:0:0:0:0:0:1", False], + ["::1", True], + ["abc", False], + ), +) +def test_hostname_or_ip_validation(input, is_valid): + assert HighThroughputEngine.is_hostname_or_ip(input) is is_valid diff --git a/compute_endpoint/tests/unit/test_gce_container.py b/compute_endpoint/tests/unit/test_gce_container.py index d8b9f1876..82394f710 100644 --- a/compute_endpoint/tests/unit/test_gce_container.py +++ b/compute_endpoint/tests/unit/test_gce_container.py @@ -19,7 +19,7 @@ def _kernel(**k): expect_uri = randomstring(length=random.randint(1, 20)) expect_opts = randomstring(length=random.randint(1, 20)) k = { - "address": "127.0.0.1", + "address": "::1", "max_workers_per_node": 1, "label": "GCE_TEST", "container_uri": expect_uri, @@ -66,7 +66,7 @@ def test_custom_missing_options(tmp_path): with pytest.raises(AssertionError) as pyt_e: with mock.patch(f"{_MOCK_BASE}ReportingThread"): GlobusComputeEngine( - address="127.0.0.1", + address="::1", max_workers_per_node=1, label="GCE_TEST", container_type="custom", @@ -88,4 +88,4 @@ def test_custom(gce_factory, randomstring): def test_bad_container(): with pytest.raises(AssertionError): - GlobusComputeEngine(address="127.0.0.1", container_type="BAD") + GlobusComputeEngine(address="::1", container_type="BAD") diff --git a/compute_endpoint/tests/unit/test_reporting_period.py b/compute_endpoint/tests/unit/test_reporting_period.py index 1b2adf4ac..cd9d0bc00 100644 --- a/compute_endpoint/tests/unit/test_reporting_period.py +++ b/compute_endpoint/tests/unit/test_reporting_period.py @@ -24,7 +24,7 @@ def test_default_period(): thread = thread_pool._status_report_thread assert thread.reporting_period == 30.0 - gce = GlobusComputeEngine(address="127.0.0.1", heartbeat_period=1) + gce = GlobusComputeEngine(address="::1", heartbeat_period=1) thread = gce._status_report_thread assert thread.reporting_period == 30.0 assert gce.executor.heartbeat_period == 1 diff --git a/compute_endpoint/tests/unit/test_worker.py b/compute_endpoint/tests/unit/test_worker.py index 62ed6f984..4347dbd6b 100644 --- a/compute_endpoint/tests/unit/test_worker.py +++ b/compute_endpoint/tests/unit/test_worker.py @@ -45,7 +45,7 @@ def test_worker(): # the worker will receive tasks and send messages on this mock socket mock_socket = mock.Mock() mock_context.return_value.socket.return_value = mock_socket - yield Worker("0", "127.0.0.1", 50001) + yield Worker("0", "::1", 50001) def test_register_and_kill(test_worker): diff --git a/compute_endpoint/tests/unit/test_working_dir.py b/compute_endpoint/tests/unit/test_working_dir.py index f345dd190..21b1edf6a 100644 --- a/compute_endpoint/tests/unit/test_working_dir.py +++ b/compute_endpoint/tests/unit/test_working_dir.py @@ -23,7 +23,7 @@ def reset_cwd(): @pytest.mark.parametrize( "engine", - (GlobusComputeEngine(address="127.0.0.1"), ThreadPoolEngine(), ProcessPoolEngine()), + (GlobusComputeEngine(address="::1"), ThreadPoolEngine(), ProcessPoolEngine()), ) def test_set_working_dir_default(engine, tmp_path): """Verify that working dir is set to tasks dir in the run_dir by default for all @@ -36,7 +36,7 @@ def test_set_working_dir_default(engine, tmp_path): @pytest.mark.parametrize( "engine", - (GlobusComputeEngine(address="127.0.0.1"), ThreadPoolEngine(), ProcessPoolEngine()), + (GlobusComputeEngine(address="::1"), ThreadPoolEngine(), ProcessPoolEngine()), ) def test_set_working_dir_called(engine, tmp_path, endpoint_uuid): """Verify that set_working_dir is called when engine.start() is called""" @@ -50,7 +50,7 @@ def test_set_working_dir_called(engine, tmp_path, endpoint_uuid): @pytest.mark.parametrize( "engine", - (GlobusComputeEngine(address="127.0.0.1"), ThreadPoolEngine(), ProcessPoolEngine()), + (GlobusComputeEngine(address="::1"), ThreadPoolEngine(), ProcessPoolEngine()), ) def test_set_working_dir_relative(engine, tmp_path): """Working_dir should be absolute and set relative to the endpoint run_dir""" @@ -64,7 +64,7 @@ def test_set_working_dir_relative(engine, tmp_path): def test_default_working_dir(tmp_path): """Test working_dir relative to run_dir""" gce = GlobusComputeEngine( - address="127.0.0.1", + address="::1", ) gce.executor.start = mock.MagicMock(spec=HighThroughputExecutor.start) gce.start(endpoint_id=uuid.uuid4(), run_dir=tmp_path) @@ -75,7 +75,7 @@ def test_default_working_dir(tmp_path): def test_relative_working_dir(tmp_path): """Test working_dir relative to run_dir""" gce = GlobusComputeEngine( - address="127.0.0.1", + address="::1", working_dir="relative_path", ) gce.executor.start = mock.MagicMock(spec=HighThroughputExecutor.start) @@ -87,7 +87,7 @@ def test_relative_working_dir(tmp_path): def test_absolute_working_dir(tmp_path): """Test absolute path for working_dir""" gce = GlobusComputeEngine( - address="127.0.0.1", + address="::1", working_dir="/absolute/path", ) gce.executor.start = mock.MagicMock(spec=HighThroughputExecutor.start) @@ -99,7 +99,7 @@ def test_absolute_working_dir(tmp_path): def test_submit_pass(tmp_path, task_uuid): """Test absolute path for working_dir""" gce = GlobusComputeEngine( - address="127.0.0.1", + address="::1", ) gce.executor.start = mock.Mock(spec=HighThroughputExecutor.start) gce.executor.submit = mock.Mock(spec=HighThroughputExecutor.submit) diff --git a/compute_sdk/tests/unit/test_login_manager.py b/compute_sdk/tests/unit/test_login_manager.py index 74e627997..a6ba3ed58 100644 --- a/compute_sdk/tests/unit/test_login_manager.py +++ b/compute_sdk/tests/unit/test_login_manager.py @@ -220,7 +220,7 @@ def test_requires_login_decorator(mocker, logman): class MockClient: login_manager = logman - web_service_address = "127.0.0.1" + web_service_address = "::1" upstream_call = requires_login(mock_method) mock_client = MockClient() diff --git a/docs/autobuild.sh b/docs/autobuild.sh index 49b769e93..1a78cb8a5 100755 --- a/docs/autobuild.sh +++ b/docs/autobuild.sh @@ -49,7 +49,7 @@ make clean html || exit 2 # quick and dirty display clean up from inaugural run; highlight python # 'http.server' message echo -en "\033[;H\033[J\033[40;92;1m" -(cd _build/html/; python3 -m http.server -b 127.0.0.1 $PORT) & +(cd _build/html/; python3 -m http.server -b localhost $PORT) & sleep 1 echo -en "\033[m"