class_docstr: A `RuntimeGroup` is the representation of logically related `Runtimes`.
  
  The group provides convenient methods for managing those related `Runtimes`.
  Most methods are wrappers around their counterparts in the `Runtime` class.
  Typical usage examples are exposing a port (i.e. a service such as a DB) in
  the `RuntimeGroup`, transfer files, or execute  a `RuntimeTask` on the contained
  `Runtimes`. Additionally, all concrete RuntimeCluster (e.g. HyperoptCluster)
  implementations rely on `RuntimeGroups` for example.
  
  Examples:
  Execute a `RuntimeTask` in a `RuntimeGroup`
  
  ```python
  # Create instances
  group = RuntimeGroup([Runtime('host-1'), Runtime('host-2')])
  # group = RuntimeGroup(hosts=['host-1', 'host-2'])
  my_task = RuntimeTask('group-demo').run_command('echo Hello Group!')
  
  # Execute a RuntimeTask in a single Runtime
  single_task = group.execute_task(my_task)
  print(single_task.execution_log[0])
  
  # Execute a RuntimeTask in the whole RuntimeGroup
  task_list = group.execute_task(my_task, broadcast=True)
  
  # Execute a RuntimeTask on a single Runtime contained in the RuntimeGroup
  task = group.execute_task(my_task)
  ```
  
  A DB is running on localhost on port `local_port` and the DB is only accessible
  from localhost. But you also want to access the service on the other `Runtimes` on port
  `runtime_port`. Then you can use this method to expose the service which is running on the
  local machine to the remote machines.
  
  ```python
  # Expose a port to all Runtimes contained in the Runtime. If a port list is given the next free port is
  # chosen and returned.
  group_port = group.expose_port_to_runtimes(local_port=60000, runtime_port=list(range(60000,60010)))
  print('Local port 60000 is now exposed to port ' + str(group_port) + ' in the RuntimeGroup!')
  ```
  
  A DB is running on a remote host on port `runtime_port` and the DB is only accessible from the remote
  machine itself. But you also want to access the service to other `Runtimes` in the group. Then you can use
  this method to expose the service which is running on one `Runtime` to the whole group.
  
  ```python
  # Expose a port from a Runtime to all other ones in the RuntimeGroup. If a port list is given the next
  # free port is chosen and returned.
  group_port = group.expose_port_from_runtime_to_group(host='host-1', runtime_port=60000,
                                                          group_port=list(range(60000,60010)))
  print('Port 60000 of `host-1` is now exposed to port ' + str(group_port) + ' in the RuntimeGroup!')
  ```
class_docstr_tok: ["A","`","RuntimeGroup","`","is","the","representation","of","logically","related","`","Runtimes","`",".","The","group","provides","convenient","methods","for","managing","those","related","`","Runtimes","`",".","Most","methods","are","wrappers","around","their","counterparts","in","the","`","Runtime","`","class",".","Typical","usage","examples","are","exposing","a","port","(","i.e",".","a","service","such","as","a","DB",")","in","the","`","RuntimeGroup","`",",","transfer","files",",","or","execute","a","`","RuntimeTask","`","on","the","contained","`","Runtimes","`",".","Additionally",",","all","concrete","RuntimeCluster","(","e.g",".","HyperoptCluster",")","implementations","rely","on","`","RuntimeGroups","`","for","example",".","Examples",":","Execute","a","`","RuntimeTask","`","in","a","`","RuntimeGroup","`","``","`","python","#","Create","instances","group","=","RuntimeGroup","(","[","Runtime","(","'host-1","'",")",",","Runtime","(","'host-2","'",")","]",")","#","group","=","RuntimeGroup","(","hosts=","[","'host-1","'",",","'host-2","'","]",")","my_task","=","RuntimeTask","(","'group-demo","'",")",".run_command","(","'echo","Hello","Group","!","'",")","#","Execute","a","RuntimeTask","in","a","single","Runtime","single_task","=","group.execute_task","(","my_task",")","print","(","single_task.execution_log","[","0","]",")","#","Execute","a","RuntimeTask","in","the","whole","RuntimeGroup","task_list","=","group.execute_task","(","my_task",",","broadcast=True",")","#","Execute","a","RuntimeTask","on","a","single","Runtime","contained","in","the","RuntimeGroup","task","=","group.execute_task","(","my_task",")","``","`","A","DB","is","running","on","localhost","on","port","`","local_port","`","and","the","DB","is","only","accessible","from","localhost",".","But","you","also","want","to","access","the","service","on","the","other","`","Runtimes","`","on","port","`","runtime_port","`",".","Then","you","can","use","this","method","to","expose","the","service","which","is","running","on","the","local","machine","to","the","remote","machines",".","``","`","python","#","Expose","a","port","to","all","Runtimes","contained","in","the","Runtime",".","If","a","port","list","is","given","the","next","free","port","is","#","chosen","and","returned",".","group_port","=","group.expose_port_to_runtimes","(","local_port=60000",",","runtime_port=list","(","range","(","60000,60010",")",")",")","print","(","'Local","port","60000","is","now","exposed","to","port","'","+","str","(","group_port",")","+","'","in","the","RuntimeGroup","!","'",")","``","`","A","DB","is","running","on","a","remote","host","on","port","`","runtime_port","`","and","the","DB","is","only","accessible","from","the","remote","machine","itself",".","But","you","also","want","to","access","the","service","to","other","`","Runtimes","`","in","the","group",".","Then","you","can","use","this","method","to","expose","the","service","which","is","running","on","one","`","Runtime","`","to","the","whole","group",".","``","`","python","#","Expose","a","port","from","a","Runtime","to","all","other","ones","in","the","RuntimeGroup",".","If","a","port","list","is","given","the","next","#","free","port","is","chosen","and","returned",".","group_port","=","group.expose_port_from_runtime_to_group","(","host='host-1","'",",","runtime_port=60000",",","group_port=list","(","range","(","60000,60010",")",")",")","print","(","'Port","60000","of","`","host-1","`","is","now","exposed","to","port","'","+","str","(","group_port",")","+","'","in","the","RuntimeGroup","!","'",")","``","`"]
docstr: Execute a `RuntimeTask` in the whole group or in a single `Runtime`.
  
  Note:
      When broadcasting a `RuntimeTask` in the group then actually deep copies of the RuntimeTask are created (by using
      its custom __deepcopy__ implementation), since each RuntimeTask holds state related to its own execution. Thus,
      multiple `RuntimeTasks` will be returned in this case.
  
  Args:
      task: The RuntimeTask to be executed.
      host: If `RuntimeTask` should be executed in one Runtime. Optionally, the host could be set in order to ensure
            the execution in a specific Runtime. Defaults to None. Consequently, the least busy `Runtime` will be
            chosen.
      broadcast: True, if the `RuntimeTask` will be executed on all `Runtimes`. Defaults to False.
      execute_async: True, if execution will take place async. Defaults to True.
      omit_on_join: If True, then a call to join() won't wait for the termination of the corresponding process.
                    Defaults to False. This parameter has no effect in case of synchronous execution.
      debug : If `True`, stdout/stderr from the remote host will be printed to stdout. If, `False`
              then the stdout/stderr will be written to execution log files. Defaults to `False`.
  
  Returns:
      RuntimeTask or List[RuntimeTask]: Either a single `RuntimeTask` object in case the execution took place
                                        in a single `Runtime` or a list of `RuntimeTasks` if executed in all.
  
  Raises:
      ValueError: If `host` is given and not contained as `Runtime` in the group.
      TaskExecutionError: If an executed `RuntimeTask` step can't be executed successfully.
docstr_tok: ["Execute","a","`","RuntimeTask","`","in","the","whole","group","or","in","a","single","`","Runtime","`",".","Note",":","When","broadcasting","a","`","RuntimeTask","`","in","the","group","then","actually","deep","copies","of","the","RuntimeTask","are","created","(","by","using","its","custom","__deepcopy__","implementation",")",",","since","each","RuntimeTask","holds","state","related","to","its","own","execution",".","Thus",",","multiple","`","RuntimeTasks","`","will","be","returned","in","this","case",".","Args",":","task",":","The","RuntimeTask","to","be","executed",".","host",":","If","`","RuntimeTask","`","should","be","executed","in","one","Runtime",".","Optionally",",","the","host","could","be","set","in","order","to","ensure","the","execution","in","a","specific","Runtime",".","Defaults","to","None",".","Consequently",",","the","least","busy","`","Runtime","`","will","be","chosen",".","broadcast",":","True",",","if","the","`","RuntimeTask","`","will","be","executed","on","all","`","Runtimes","`",".","Defaults","to","False",".","execute_async",":","True",",","if","execution","will","take","place","async",".","Defaults","to","True",".","omit_on_join",":","If","True",",","then","a","call","to","join","(",")","wo","n't","wait","for","the","termination","of","the","corresponding","process",".","Defaults","to","False",".","This","parameter","has","no","effect","in","case","of","synchronous","execution",".","debug",":","If","`","True","`",",","stdout\/stderr","from","the","remote","host","will","be","printed","to","stdout",".","If",",","`","False","`","then","the","stdout\/stderr","will","be","written","to","execution","log","files",".","Defaults","to","`","False","`",".","Returns",":","RuntimeTask","or","List","[","RuntimeTask","]",":","Either","a","single","`","RuntimeTask","`","object","in","case","the","execution","took","place","in","a","single","`","Runtime","`","or","a","list","of","`","RuntimeTasks","`","if","executed","in","all",".","Raises",":","ValueError",":","If","`","host","`","is","given","and","not","contained","as","`","Runtime","`","in","the","group",".","TaskExecutionError",":","If","an","executed","`","RuntimeTask","`","step","ca","n't","be","executed","successfully","."]
code: def execute_task(
      self,
      task: RuntimeTask,
      host: Optional[str] = None,
      broadcast: bool = False,
      execute_async: bool = True,
      omit_on_join: bool = False,
      debug: bool = False,
  ) -> Union[RuntimeTask, List[RuntimeTask]]:
      """Execute a `RuntimeTask` in the whole group or in a single `Runtime`.
  
      Note:
          When broadcasting a `RuntimeTask` in the group then actually deep copies of the RuntimeTask are created (by using
          its custom __deepcopy__ implementation), since each RuntimeTask holds state related to its own execution. Thus,
          multiple `RuntimeTasks` will be returned in this case.
  
      Args:
          task: The RuntimeTask to be executed.
          host: If `RuntimeTask` should be executed in one Runtime. Optionally, the host could be set in order to ensure
                the execution in a specific Runtime. Defaults to None. Consequently, the least busy `Runtime` will be
                chosen.
          broadcast: True, if the `RuntimeTask` will be executed on all `Runtimes`. Defaults to False.
          execute_async: True, if execution will take place async. Defaults to True.
          omit_on_join: If True, then a call to join() won't wait for the termination of the corresponding process.
                        Defaults to False. This parameter has no effect in case of synchronous execution.
          debug : If `True`, stdout/stderr from the remote host will be printed to stdout. If, `False`
                  then the stdout/stderr will be written to execution log files. Defaults to `False`.
  
      Returns:
          RuntimeTask or List[RuntimeTask]: Either a single `RuntimeTask` object in case the execution took place
                                            in a single `Runtime` or a list of `RuntimeTasks` if executed in all.
  
      Raises:
          ValueError: If `host` is given and not contained as `Runtime` in the group.
          TaskExecutionError: If an executed `RuntimeTask` step can't be executed successfully.
      """
      if not broadcast:
          self.log.debug(
              f"Start executing RuntimeTask {task.name} in RuntimeGroup (no broadcasting)."
          )
      else:
          self.log.debug(
              f"Start broadcasting RuntimeTask {task.name} in RuntimeGroup."
          )
  
      task.omit_on_join = omit_on_join
  
      if broadcast:
          tasks = []
          needs_to_create_copy = False
  
          for (
              runtime
          ) in self.get_runtimes().values():  # Raises ValueError
              if not needs_to_create_copy:
                  current_task = task
              else:
                  # Create a deep copy to prevent reference errors especially for the task log.
                  # Each task will contain its own log produced on its executing host.
                  current_task = deepcopy(task)
  
              runtime.execute_task(current_task, execute_async, debug)
  
              tasks.append(current_task)
              self._tasks.append(current_task)
  
          return tasks
  
      else:
          if host:
              if host not in self._runtimes:
                  raise ValueError(
                      "The host " + host + " is not a valid runtime."
                  )
              self.get_runtime(host).execute_task(
                  task, execute_async, debug
              )
          else:
              self._get_least_busy_runtime().execute_task(
                  task, execute_async, debug
              )
          self._tasks.append(task)
          return task
  
imports: import atexit
  import logging
  import warnings
  from copy import deepcopy
  from multiprocessing import Pool, Process
  from typing import Dict, Generator, List, Optional, Union
  from storm import Storm
  from lazycluster import _utils
  from lazycluster.exceptions import InvalidRuntimeError, NoPortsLeftError, NoRuntimesDetectedError, PortInUseError
  from lazycluster.runtimes import Runtime, RuntimeTask
label_desc: Use image node_id 18 for calling the RuntimeGroup obj's underlying member method code with example usage: obj.execute_task(task, host, broadcast, execute_async, omit_on_join, debug) and returns: tasks, task