class_docstr: Abstract class for implementing the strategy for launching worker instances within a RuntimeGroup.
  
  In order to implement a new concrete `WorkerLauncher` subclass you need to implement the start method. Please
  consider the comments of the start method because some internal variables need to be set in the concrete
  implementation.
  
  Moreover, the `setup_worker_ssh_tunnels()` method can be used to setup ssh tunnels so that all entities can talk to
  each other.
class_docstr_tok: ["Abstract","class","for","implementing","the","strategy","for","launching","worker","instances","within","a","RuntimeGroup",".","In","order","to","implement","a","new","concrete","`","WorkerLauncher","`","subclass","you","need","to","implement","the","start","method",".","Please","consider","the","comments","of","the","start","method","because","some","internal","variables","need","to","be","set","in","the","concrete","implementation",".","Moreover",",","the","`","setup_worker_ssh_tunnels","(",")","`","method","can","be","used","to","setup","ssh","tunnels","so","that","all","entities","can","talk","to","each","other","."]
docstr: Set up ssh tunnel for workers such that all communication is routed over the local machine and all entities can talk to each other on localhost.
  
  Note:
      This method needs to be called if the communication between the worker instances is necessary, e.g. in case
      of DASK or Apache Flink, where data needs to be shuffled between the different entities.
  
  Raises:
      ValueError: If host is not contained.
      PortInUseError: If `group_port` is occupied on the local machine.
      NoPortsLeftError: If `group_ports` was given and none of the ports was free.
docstr_tok: ["Set","up","ssh","tunnel","for","workers","such","that","all","communication","is","routed","over","the","local","machine","and","all","entities","can","talk","to","each","other","on","localhost",".","Note",":","This","method","needs","to","be","called","if","the","communication","between","the","worker","instances","is","necessary",",","e.g",".","in","case","of","DASK","or","Apache","Flink",",","where","data","needs","to","be","shuffled","between","the","different","entities",".","Raises",":","ValueError",":","If","host","is","not","contained",".","PortInUseError",":","If","`","group_port","`","is","occupied","on","the","local","machine",".","NoPortsLeftError",":","If","`","group_ports","`","was","given","and","none","of","the","ports","was","free","."]
code: def setup_worker_ssh_tunnels(self) -> None:
      """Set up ssh tunnel for workers such that all communication is routed over the local machine and all entities can talk to each other on localhost.
  
      Note:
          This method needs to be called if the communication between the worker instances is necessary, e.g. in case
          of DASK or Apache Flink, where data needs to be shuffled between the different entities.
  
      Raises:
          ValueError: If host is not contained.
          PortInUseError: If `group_port` is occupied on the local machine.
          NoPortsLeftError: If `group_ports` was given and none of the ports was free.
      """
      self.log.info(
          "Setting up ssh tunnel for inter worker communication."
      )
      for host, ports in self.ports_per_host.items():
          for worker_port in ports:
              self._group.expose_port_from_runtime_to_group(
                  host, worker_port
              )
  
imports: import atexit
  import logging
  from subprocess import Popen
  from typing import Dict, List, Optional, Union
  from lazycluster.exceptions import LazyclusterError
  from lazycluster.runtime_mgmt import RuntimeGroup
label_desc: Use image node_id 5 for calling the WorkerLauncher obj's underlying member method code with example usage: obj.setup_worker_ssh_tunnels() without return types