Spawn multi-environments on the nodes through SSH-connections.

        :param spawn_cmd:
            str or list, command(s) used to spawn the environment on each node.
            If *list*, it must contain one command for each node in
            :attr:`nodes`. If *str*, the same command is used for each node.

        :param ports:
            Optional. If not ``None``, must be a mapping from nodes
            (``(server, port)``-tuples) to ports which are used for the spawned
            multi-environments' master manager environments. If ``None``, then
            the same port is used to derive the master manager addresses as was
            used to initialize this distributed environment's managing
            environment (port in :attr:`addr`).

        :param ssh_kwargs:
            Any additional SSH-connection arguments, as specified by
            :meth:`asyncssh.connect`. See `asyncssh documentation
            <http://asyncssh.readthedocs.io/en/latest/api.html#connect>`_ for
            details.

        Nodes are spawned by creating a multiprocessing pool where each node
        has its own subprocess. These subprocesses then use SSH-connections
        to spawn the multi-environments on the nodes. The SSH-connections in
        the pool are kept alive until the nodes are stopped, i.e. this
        distributed environment is destroyed.

async def spawn_slaves(self, spawn_cmd, ports=None, **ssh_kwargs):
        """Spawn multi-environments on the nodes through SSH-connections.

        :param spawn_cmd:
            str or list, command(s) used to spawn the environment on each node.
            If *list*, it must contain one command for each node in
            :attr:`nodes`. If *str*, the same command is used for each node.

        :param ports:
            Optional. If not ``None``, must be a mapping from nodes
            (``(server, port)``-tuples) to ports which are used for the spawned
            multi-environments' master manager environments. If ``None``, then
            the same port is used to derive the master manager addresses as was
            used to initialize this distributed environment's managing
            environment (port in :attr:`addr`).

        :param ssh_kwargs:
            Any additional SSH-connection arguments, as specified by
            :meth:`asyncssh.connect`. See `asyncssh documentation
            <http://asyncssh.readthedocs.io/en/latest/api.html#connect>`_ for
            details.

        Nodes are spawned by creating a multiprocessing pool where each node
        has its own subprocess. These subprocesses then use SSH-connections
        to spawn the multi-environments on the nodes. The SSH-connections in
        the pool are kept alive until the nodes are stopped, i.e. this
        distributed environment is destroyed.
        """
        pool = multiprocessing.Pool(len(self.nodes))
        rets = []
        for i, node in enumerate(self.nodes):
            server, server_port = node
            port = ports[node] if ports is not None else self.port
            mgr_addr = "tcp://{}:{}/0".format(server, port)
            self._manager_addrs.append(mgr_addr)
            if type(spawn_cmd) in [list, tuple]:
                cmd = spawn_cmd[i]
            else:
                cmd = spawn_cmd
            args = [server, cmd]
            ssh_kwargs_cp = ssh_kwargs.copy()
            ssh_kwargs_cp['port'] = server_port
            ret = pool.apply_async(ssh_exec_in_new_loop,
                                   args=args,
                                   kwds=ssh_kwargs_cp,
                                   error_callback=logger.warning)
            rets.append(ret)
        self._pool = pool
        self._r = rets