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: Add a `Runtime` to the group either by host or as a `Runtime` object.
  
  Args:
      host: The host of the runtime. Defaults to None.
      runtime: The `Runtime` object to be added to the group. Defaults to None.
  
  Raises:
      ValueError: If the same host is already contained. Or if both host and runtime is given. We refuse
                  the temptation to guess. Also if no argument is supplied.
docstr_tok: ["Add","a","`","Runtime","`","to","the","group","either","by","host","or","as","a","`","Runtime","`","object",".","Args",":","host",":","The","host","of","the","runtime",".","Defaults","to","None",".","runtime",":","The","`","Runtime","`","object","to","be","added","to","the","group",".","Defaults","to","None",".","Raises",":","ValueError",":","If","the","same","host","is","already","contained",".","Or","if","both","host","and","runtime","is","given",".","We","refuse","the","temptation","to","guess",".","Also","if","no","argument","is","supplied","."]
code: def add_runtime(
      self,
      host: Optional[str] = None,
      runtime: Optional[Runtime] = None,
  ) -> None:
      """Add a `Runtime` to the group either by host or as a `Runtime` object.
  
      Args:
          host: The host of the runtime. Defaults to None.
          runtime: The `Runtime` object to be added to the group. Defaults to None.
  
      Raises:
          ValueError: If the same host is already contained. Or if both host and runtime is given. We refuse
                      the temptation to guess. Also if no argument is supplied.
      """
      if host and runtime:
          raise ValueError(
              "Only host or runtime must be supplied. We refuse the temptation to guess."
          )
      elif not host and not runtime:
          raise ValueError("Hostname or runtime must be supplied.")
      elif runtime and self.contains_runtime(runtime.host):
          raise ValueError(
              "Runtime with the same host is already contained in the group."
          )
      elif host and self.contains_runtime(host):
          raise ValueError(
              "Runtime with the same host is already contained in the group."
          )
      elif host:
          rt = Runtime(host)
      else:
          assert isinstance(runtime, Runtime)
          rt = runtime
      self._runtimes[rt.host] = rt
      self.log.info(
          rt.host + " added as " + rt.class_name + " to the group."
      )
  
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 14 for calling the RuntimeGroup obj's underlying member method code with example usage: obj.add_runtime(host, runtime) without return types