def disconnect(self, connected_logic_ports, bidi=False):
        """Disconnect logical ports.

        :type connected_logic_ports: set[tuple[w2w_rome.helpers.port_entity.LogicalPort]]  # noqa
        :type bidi: bool
        """
        if bidi:
            connected_port_names = []
            num_ports = 0
            for src_logic_port, dst_logic_port in connected_logic_ports:
                src_logic_name = src_logic_port.original_logical_name
                dst_logic_name = dst_logic_port.original_logical_name
                # connect every E port to W in both directions
                num_ports += 2 * len(src_logic_port.rome_ports)
                connected_port_names.append((src_logic_name, dst_logic_name))
            # for every host disconnect logical ports
            param_map = {
                cli_service: [[cli_service, connected_port_names, num_ports],
                              {}]
                for cli_service in self._cli_services
            }
        else:
            host_connected_ports_map = defaultdict(list)
            for src_logic_port, dst_logic_port in connected_logic_ports:
                for e_port, w_port in src_logic_port.get_connected_sub_ports(
                        dst_logic_port):
                    cli_service = self._cli_services_map[e_port.port_resource]
                    host_connected_ports_map[cli_service].append(
                        (e_port.sub_port_name, w_port.sub_port_name))

            param_map = {
                cli: [
                    [
                        cli,
                        sorted(connected_port_names),
                        len(connected_port_names)
                    ],
                    {},
                ]
                for cli, connected_port_names in
                host_connected_ports_map.items()
            }

        if not self._is_run_in_parallel:
            params = param_map.values()[0]
            args, kwargs = params
            self._disconnect_and_wait(*args, **kwargs)
        else:
            run_in_threads(self._disconnect_and_wait, self._logger, param_map)
    def connect(self, src_logic_port, dst_logic_port, bidi=True):
        """Connect logical ports.

        :type src_logic_port: w2w_rome.helpers.port_entity.LogicalPort
        :type dst_logic_port: w2w_rome.helpers.port_entity.LogicalPort
        :type bidi: bool
        """
        if not bidi:
            if src_logic_port.is_q_port:
                raise NotSupportedError(
                    "Uni connections not supported for Q ports")
            if self._is_run_in_parallel:
                raise NotSupportedError(
                    "Not supported multiple host and map uni")
            e_port = src_logic_port.e_sub_ports[0].sub_port_name
            w_port = dst_logic_port.w_sub_ports[0].sub_port_name
            param_map = {
                cli_service: [[cli_service, e_port, w_port, 2], {}]
                for cli_service in self._cli_services
            }
        else:
            src_logic_name = src_logic_port.original_logical_name
            dst_logic_name = dst_logic_port.original_logical_name
            # connect every E port to W in both directions
            num_ports_to_connect = 2 * len(src_logic_port.rome_ports)
            param_map = {
                cli_service: [
                    [
                        cli_service, src_logic_name, dst_logic_name,
                        num_ports_to_connect
                    ],
                    {},
                ]
                for cli_service in self._cli_services
            }

        if not self._is_run_in_parallel:
            params = param_map.values()[0]
            args, kwargs = params
            self._connect_and_wait(*args, **kwargs)
        else:
            run_in_threads(self._connect_and_wait, self._logger, param_map)
    def get_port_table(self):
        """Get port table from hosts and concatenating it.

        :rtype: PortTable
        """
        if not self._is_run_in_parallel:
            port_table = self._get_port_table(self._cli_services[0])
        else:
            param_map = {
                cli_service: [[cli_service], {}]
                for cli_service in self._cli_services
            }
            results_map = run_in_threads(self._get_port_table, self._logger,
                                         param_map)
            port_table = reduce(PortTable.__add__, results_map.values())
        return port_table
    def get_board_tables_map(self):
        """Get board tables from hosts.

        :return: dict[cli_service, dict with board table info[
        :rtype: dict[cloudshell.cli.cli_service_impl.CliServiceImpl, dict]
        """
        if not self._is_run_in_parallel:
            results_map = {
                self._cli_services[0]: self._board_table(self._cli_services[0])
            }
        else:
            param_map = {
                cli_service: [[cli_service], {}]
                for cli_service in self._cli_services
            }
            results_map = run_in_threads(self._board_table, self._logger,
                                         param_map)
        return results_map