예제 #1
0
 def _killall_roscore_wo(self,
                         host,
                         auto_pw_request=False,
                         user=None,
                         pw=None):
     rospy.loginfo("killall roscore on %s", host)
     cmd = ['killall', 'roscore']
     if nm.is_local(host):
         SupervisedPopen(cmd,
                         object_id="killall roscore",
                         description="killall roscore")
     else:
         # kill on a remote machine
         _, stdout, stderr, ok = nm.ssh().ssh_exec(host,
                                                   cmd,
                                                   user,
                                                   pw,
                                                   False,
                                                   close_stdin=True)
         if ok:
             output = stdout.read()
             error = stderr.read()
             stdout.close()
             stderr.close()
             if error:
                 rospy.logwarn("ERROR while killall roscore on %s: %s" %
                               (host, error))
                 raise StartException('The host "%s" reports:\n%s' %
                                      (host, error))
             if output:
                 rospy.logdebug("STDOUT while killall roscore on %s: %s" %
                                (host, output))
예제 #2
0
 def _kill_wo(self, host, pid, auto_pw_request=False, user=None, pw=None):
     rospy.loginfo("kill %s on %s", utf8(pid), host)
     if nm.is_local(host):
         os.kill(pid, signal.SIGKILL)
         rospy.loginfo("kill: %s", utf8(pid))
     else:
         # kill on a remote machine
         cmd = ['kill -9', str(pid)]
         _, stdout, stderr, ok = nm.ssh().ssh_exec(host,
                                                   cmd,
                                                   user,
                                                   pw,
                                                   False,
                                                   close_stdin=True)
         if ok:
             output = stdout.read()
             error = stderr.read()
             stdout.close()
             stderr.close()
             if error:
                 rospy.logwarn("ERROR while kill %s: %s", utf8(pid), error)
                 raise StartException(
                     utf8(''.join(
                         ['The host "', host, '" reports:\n', error])))
             if output:
                 rospy.logdebug("STDOUT while kill %s on %s: %s", utf8(pid),
                                host, output)
예제 #3
0
    def ntpdate(cls, host, cmd, user=None, pw=None):
        '''
        Opens the log file associated with the given node in a new terminal.

        :param str host: the host name or ip where the log file are
        :param str cmd: command to set the time
        :return: True, if a log file was found
        :rtype: bool
        :raise Exception: on errors while resolving host
        :see: :meth:`fkie_node_manager.is_local()`
        '''
        mesg = "synchronize time on '%s' using '%s'" % (utf8(host), cmd)
        rospy.loginfo(mesg)
        title_opt = "ntpdate on %s" % str(host)  # '%s on %s' % (cmd, host)
        if nm.is_local(host):
            cmd = nm.settings().terminal_cmd([cmd], title_opt, noclose=True)
            rospy.loginfo("EXEC: %s" % cmd)
            _ps = SupervisedPopen(shlex.split(cmd),
                                  object_id=cmd,
                                  description=mesg)
        else:
            _ps = nm.ssh().ssh_x11_exec(host, [
                cmd,
                ';echo "";echo "this terminal will be closed in 10 sec...";sleep 10'
            ], title_opt, user)
        return False
    def _bc_resolve_abs_paths(cls, value, host, auto_pw_request, user, pw):
        '''
        Replaces the local absolute path by remote absolute path. Only valid ROS
        package paths are resolved.

        :return: value, is absolute path, remote package found (ignore it on local host or if is not absolute path!), package name (if absolute path and remote package NOT found)
        '''
        if isstring(value) and value.startswith('/') and (os.path.isfile(value) or os.path.isdir(value)):
            if nm.is_local(host):
                return value, True, True, ''
            else:
                path = os.path.dirname(value) if os.path.isfile(value) else value
                package, package_path = package_name(path)
                if package:
                    _, stdout, _, ok = nm.ssh().ssh_exec(host, ['rospack', 'find', package], user, pw, auto_pw_request, close_stdin=True, close_stderr=True)
                    output = stdout.read()
                    stdout.close()
                    if ok:
                        if output:
                            value.replace(package_path, output)
                            return value.replace(package_path, output.strip()), True, True, package
                        else:
                            # package on remote host not found!
                            # TODO add error message
                            #      error = stderr.read()
                            pass
                return value, True, False, ''
        else:
            return value, False, False, ''
예제 #5
0
 def _connect(self, masteruri, screen_name, nodename, user=None):
     self._masteruri = masteruri
     if self.qfile is not None and self.qfile.isOpen():
         self.qfile.close()
         self.clear_signal.emit()
     host = get_hostname(masteruri)
     if nm.is_local(host):
         self._nodename = nodename
         if screen_name:
             screen_log = screen.get_logfile(node=nodename)
         else:
             screen_log = screen.get_ros_logfile(node=nodename)
         self.qfile = QFile(screen_log)
         self.setWindowTitle(nodename)
         if self.qfile.open(QIODevice.ReadOnly):
             self._first_fill = True
             self.qfile.seek(self.qfile.size() - 1)
             # self.lread()
             self._info = "END"
             self.thread = threading.Thread(target=self._read_log,
                                            kwargs={"filename": screen_log})
             self.thread.setDaemon(True)
             self.thread.start()
         else:
             self._valid = False
     else:
         self._connect_ssh(host, nodename, user)
     self.logger_handler = LoggerHandler(
         nodename,
         masteruri=masteruri,
         layout=self.scrollAreaWidgetContents.layout())
     self.logger_handler.update()
     return False
    def delete_log(cls, nodename, grpc_uri, auto_pw_request=False, user=None, pw=None):
        '''
        Deletes the log file associated with the given node.

        :param  str nodename: the name of the node (with name space)
        :param str grpc_uri: uri of the node manager daemon where to delete log
        :raise Exception: on errors while resolving host
        :see: :meth:`fkie_node_manager.is_local()`
        '''
        try:
            nm.nmd().screen.delete_log(grpc_uri, [nodename])
        except Exception as err:
            rospy.logwarn("delete log using SSH because of error: %s" % utf8(err))
            host = get_hostname(grpc_uri)
            if nm.is_local(host):
                screenLog = screen.get_logfile(node=nodename)
                pidFile = screen.get_pidfile(node=nodename)
                roslog = screen.get_ros_logfile(nodename)
                if os.path.isfile(screenLog):
                    os.remove(screenLog)
                if os.path.isfile(pidFile):
                    os.remove(pidFile)
                if os.path.isfile(roslog):
                    os.remove(roslog)
            else:
                try:
                    # output ignored: output, error, ok
                    _, stdout, _, ok = nm.ssh().ssh_exec(host, [nm.settings().start_remote_script, '--delete_logs', nodename], user, pw, auto_pw_request, close_stdin=True, close_stdout=False, close_stderr=True)
                    if ok:
                        stdout.readlines()
                        stdout.close()
                except nm.AuthenticationRequest as e:
                    raise nm.InteractionNeededError(e, cls.delete_log, {'nodename': nodename, 'grpc_uri': host, 'auto_pw_request': auto_pw_request, 'user': user, 'pw': pw})
 def open_terminal(self, host):
     if nm.is_local(host):
         cmd = nm.settings().terminal_cmd(['cd'], '')
         SupervisedPopen(shlex.split(cmd), object_id="Start local terminal", shell=True)
     else:
         cmd = nm.settings().terminal_cmd(["ssh -XC %s@%s" % (nm.settings().host_user(host), host)], '', noclose=True)
         SupervisedPopen(shlex.split(cmd), object_id="Start Terminal on %s" % host)
예제 #8
0
 def open_screen_terminal(cls,
                          masteruri,
                          screen_name,
                          nodename,
                          use_log_widget=False,
                          user=None):
     '''
     Open the screen output in a new terminal.
     :param str masteruri: the masteruri where the screen is running.
     :param str screen_name: the name of the screen to show
     :param str nodename: the name of the node is used for the title of the terminal
     :raise Exception: on errors while resolving host
     :see: L{fkie_node_manager.is_local()}
     '''
     # create a title of the terminal
     if use_log_widget:
         nm._MAIN_FORM.open_screen_dock(masteruri, screen_name, nodename,
                                        user)
         return
     host = get_hostname(masteruri)
     title_opt = 'SCREEN %s on %s' % (nodename, host)
     if nm.is_local(host):
         cmd = nm.settings().terminal_cmd(
             [screen.SCREEN, '-x', screen_name], title_opt)
         rospy.loginfo("Open screen terminal: %s", cmd)
         SupervisedPopen(shlex.split(cmd),
                         object_id=title_opt,
                         description="Open screen terminal: %s" % title_opt)
     else:
         rospy.loginfo("Open remote screen terminal for %s to %s" %
                       (nodename, host))
         _ps = nm.ssh().ssh_x11_exec(host,
                                     [screen.SCREEN, '-x', screen_name],
                                     title_opt, user)
 def _poweroff_wo(self, host, auto_pw_request=False, user=None, pw=None):
     if nm.is_local(host):
         rospy.logwarn("shutdown localhost localhost!")
         cmd = nm.settings().terminal_cmd(['sudo poweroff'], "poweroff")
         SupervisedPopen(shlex.split(cmd), object_id="poweroff", description="poweroff")
     else:
         rospy.loginfo("poweroff %s", host)
         # kill on a remote machine
         cmd = ['sudo poweroff']
         _ = nm.ssh().ssh_x11_exec(host, cmd, 'Shutdown %s' % host, user)
    def _prepareROSMaster(cls, masteruri):
        if masteruri is None:
            masteruri = masteruri_from_ros()
        # start roscore, if needed
        try:
            if not os.path.isdir(screen.LOG_PATH):
                os.makedirs(screen.LOG_PATH)
            socket.setdefaulttimeout(3)
            master = xmlrpcclient.ServerProxy(masteruri)
            master.getUri(rospy.get_name())
            # restart ROSCORE on different masteruri?, not now...
#      master_uri = master.getUri(rospy.get_name())
#      if masteruri != master_uri[2]:
#        # kill the local roscore...
#        raise
        except Exception:
            # run a roscore
            master_host = get_hostname(masteruri)
            if nm.is_local(master_host, True):
                master_port = get_port(masteruri)
                new_env = dict(os.environ)
                new_env['ROS_MASTER_URI'] = masteruri
                ros_hostname = nmdhost.get_ros_hostname(masteruri)
                if ros_hostname:
                    new_env['ROS_HOSTNAME'] = ros_hostname
                cmd_args = '%s roscore --port %d' % (screen.get_cmd('/roscore--%d' % master_port), master_port)
                for n in [1, 2, 3, 4]:
                    try:
                        if n == 1:
                            print("Launch ROS Master in screen  ... %s" % (cmd_args))
                            SupervisedPopen(shlex.split(cmd_args), env=new_env, object_id="ROSCORE", description="Start roscore")
                        elif n == 2:
                            print("ROS Master takes too long for start, wait for next 10 sec ...")
                        elif n == 3:
                            print("A really slow start, wait for last 10 sec ...")
                        # wait for roscore to avoid connection problems while init_node
                        result = -1
                        count = 1
                        while result == -1 and count < 11:
                            try:
                                master = xmlrpcclient.ServerProxy(masteruri)
                                result, _, _ = master.getUri(rospy.get_name())  # _:=uri, msg
                                return
                            except Exception:
                                time.sleep(1)
                                count += 1
                        if n == 4 and count >= 11:
                            raise StartException('Cannot connect to ROS-Master: %s\n--> please run "roscore" manually!' % utf8(masteruri))
                    except Exception as e:
                        raise Exception("Error while call '%s': %s" % (cmd_args, utf8(e)))
            else:
                raise Exception("ROS master '%s' is not reachable" % masteruri)
        finally:
            socket.setdefaulttimeout(None)
 def _rosclean_wo(self, grpc_uri, auto_pw_request=False, user=None, pw=None):
     try:
         nm.nmd().screen.rosclean(grpc_uri)
     except Exception as err:
         host = get_hostname(grpc_uri)
         if nm.is_local(host):
             rospy.loginfo("rosclean purge on localhost!")
             cmd = nm.settings().terminal_cmd(['rosclean purge -y'], "rosclean")
             SupervisedPopen(shlex.split(cmd), object_id="rosclean", description="rosclean")
         else:
             rospy.logwarn("use SSH to run 'rosclean' because of error: %s" % utf8(err))
             # kill on a remote machine
             cmd = ['rosclean purge -y']
             _ = nm.ssh().ssh_x11_exec(host, cmd, 'rosclean purge on %s' % host, user)
예제 #12
0
    def openLog(cls, nodename, host, user=None, only_screen=False):
        '''
        Opens the log file associated with the given node in a new terminal.

        :param str nodename: the name of the node (with name space)
        :param str host: the host name or ip where the log file are
        :return: True, if a log file was found
        :rtype: bool
        :raise Exception: on errors while resolving host
        :see: :meth:`fkie_node_manager.is_local()`
        '''
        rospy.loginfo("show log for '%s' on '%s'", utf8(nodename), utf8(host))
        title_opt = 'LOG %s on %s' % (nodename, host)
        if nm.is_local(host):
            found = False
            screenLog = screen.get_logfile(node=nodename)
            if os.path.isfile(screenLog):
                cmd = nm.settings().terminal_cmd(
                    [nm.settings().log_viewer, screenLog], title_opt)
                rospy.loginfo("open log: %s", cmd)
                SupervisedPopen(shlex.split(cmd),
                                object_id="Open log",
                                description="Open log for '%s' on '%s'" %
                                (utf8(nodename), utf8(host)))
                found = True
            # open roslog file
            roslog = screen.get_ros_logfile(nodename)
            if os.path.isfile(roslog) and not only_screen:
                title_opt = title_opt.replace('LOG', 'ROSLOG')
                cmd = nm.settings().terminal_cmd(
                    [nm.settings().log_viewer, roslog], title_opt)
                rospy.loginfo("open ROS log: %s", cmd)
                SupervisedPopen(shlex.split(cmd),
                                object_id="Open log",
                                description="Open log for '%s' on '%s'" %
                                (utf8(nodename), utf8(host)))
                found = True
            return found
        else:
            _ps = nm.ssh().ssh_x11_exec(host, [
                nm.settings().start_remote_script, '--show_screen_log',
                nodename
            ], title_opt, user)
            if not only_screen:
                _ps = nm.ssh().ssh_x11_exec(host, [
                    nm.settings().start_remote_script, '--show_ros_log',
                    nodename
                ], title_opt.replace('LOG', 'ROSLOG'), user)
        return False
예제 #13
0
 def __gt__(self, item):
     if isstring(item):
         local = False
         try:
             local = nm.is_local(get_hostname(nm.nameres().masteruri(item)))
         except Exception:
             pass
         if self.local and not local:  # local hosts are at the top
             return False
         return self.master.name.lower() > item.lower()
     elif not (item is None):
         if self.local and not item.local:  # local hosts are at the top
             return False
         return self.master.name.lower() > item.master.name.lower()
     return False
예제 #14
0
 def __gt__(self, item):
     if isinstance(item, str) or isinstance(item, unicode):
         local = False
         try:
             local = nm.is_local(item)
         except Exception:
             pass
         if self.local and not local:  # local hosts are at the top
             return False
         return self.master.name.lower() > item.lower()
     elif not (item is None):
         if self.local and not item.local:  # local hosts are at the top
             return False
         return self.master.name.lower() > item.master.name.lower()
     return False
예제 #15
0
    def _bc_get_active_screens(cls,
                               host,
                               nodename='',
                               auto_pw_request=True,
                               user=None,
                               pwd=None):
        '''
        Returns the list with all compatible screen names. If the session is set to
        an empty string all screens will be returned.

        :param str host: the host name or IP to search for the screen session.
        :param str nodename: the name of the node
        :return: dictionary of screen name and corresponding ROS node name
        :rtype: {str: str}
        :raise Exception: on errors while resolving host
        :see: fkie_node_manager.is_local()
        '''
        output = None
        result = {}
        if nm.is_local(host):
            ps = SupervisedPopen(shlex.split('%s -ls' % screen.SCREEN),
                                 stdout=subprocess.PIPE)
            output = ps.stdout.read()
            ps.stdout.close()
        else:
            _, stdout, _, _ = nm.ssh().ssh_exec(host, [screen.SCREEN, ' -ls'],
                                                user,
                                                pwd,
                                                auto_pw_request,
                                                close_stdin=True,
                                                close_stderr=True)
            output = stdout.read()
            stdout.close()
        if output:
            splits = output.split()
            session = utf8(nodename).replace(
                '/', '_') if nodename is not None else ''
            for i in splits:
                sname = i.replace('__', '_')
                if sname.count('.') > 0 and sname.endswith(
                        session) and sname.find('._') >= 0:
                    result[i] = nodename
        return result
예제 #16
0
 def get_log_path(cls,
                  host,
                  nodes=[],
                  auto_pw_request=False,
                  user=None,
                  pw=None):
     if nm.is_local(host):
         if len(nodes) == 1:
             return screen.get_logfile(node=nodes[0])
         else:
             return screen.LOG_PATH
     else:
         request = '[]' if len(nodes) != 1 else nodes[0]
         try:
             socket.setdefaulttimeout(3)
             _, stdout, _, ok = nm.ssh().ssh_exec(host, [
                 nm.settings().start_remote_script, '--ros_log_path',
                 request
             ],
                                                  user,
                                                  pw,
                                                  auto_pw_request,
                                                  close_stdin=True,
                                                  close_stderr=True)
             if ok:
                 output = stdout.read()
                 stdout.close()
                 return output.strip()
             else:
                 raise StartException(
                     utf8(''.join(['Get log path from "', host,
                                   '" failed'])))
         except nm.AuthenticationRequest as e:
             raise nm.InteractionNeededError(
                 e, cls.get_log_path, {
                     'host': host,
                     'nodes': nodes,
                     'auto_pw_request': auto_pw_request,
                     'user': user,
                     'pw': pw
                 })
         finally:
             socket.setdefaulttimeout(None)
 def transfer_files(cls, host, path, auto_pw_request=False, user=None, pw=None):
     '''
     Copies the given file to the remote host. Uses caching of remote paths.
     '''
     # get package of the file
     if nm.is_local(host):
         # it's local -> no copy needed
         return
     (pkg_name, pkg_path) = package_name(os.path.dirname(path))
     if pkg_name is not None:
         # get the subpath of the file
         subfile_path = path.replace(pkg_path, '')
         # get the path of the package on the remote machine
         try:
             output = ''
             error = ''
             ok = True
             if host in CACHED_PKG_PATH and pkg_name in CACHED_PKG_PATH[host]:
                 output = CACHED_PKG_PATH[host][pkg_name]
             else:
                 if host not in CACHED_PKG_PATH:
                     CACHED_PKG_PATH[host] = dict()
                 _, stdout, stderr, ok = nm.ssh().ssh_exec(host, [nm.settings().start_remote_script, '--package', pkg_name], user, pw, auto_pw_request, close_stdin=True)
                 output = stdout.read()
                 error = stderr.read()
                 stdout.close()
                 stderr.close()
             if ok:
                 if error:
                     rospy.logwarn("ERROR while transfer %s to %s: %s", path, host, error)
                     raise StartException(utf8(''.join(['The host "', host, '" reports:\n', error])))
                 if output:
                     CACHED_PKG_PATH[host][pkg_name] = output
                     nm.ssh().transfer(host, path, os.path.join(output.strip(), subfile_path.strip(os.sep)), user)
                 else:
                     raise StartException("Remote host no returned any answer. Is there the new version of node_manager installed?")
             else:
                 raise StartException("Can't get path from remote host. Is there the new version of node_manager installed?")
         except nm.AuthenticationRequest as e:
             raise nm.InteractionNeededError(e, cls.transfer_files, {'host': host, 'path': path, 'auto_pw_request': auto_pw_request, 'user': user, 'pw': pw})
예제 #18
0
    def updateMaster(self, master):
        '''
        Updates the information of the ros master. If the ROS master not exists, it
        will be added.

        @param master: the ROS master to update
        @type master: U{fkie_master_discovery.msg.ROSMaster<http://docs.ros.org/api/fkie_multimaster_msgs/html/msg/ROSMaster.html>}
        '''
        # remove master, if his name was changed but not the ROS master URI
        root = self.invisibleRootItem()
        for i in reversed(range(root.rowCount())):
            masterItem = root.child(i)
            if masterItem.master.uri == master.uri and masterItem.master.name != master.name:
                root.removeRow(i)
                try:
                    del self.pyqt_workaround[masterItem.master.name]
                except Exception:
                    pass
                break

        # update or add a the item
        root = self.invisibleRootItem()
        doAddItem = True
        is_local = nm.is_local(get_hostname(master.uri))
        for index in range(root.rowCount()):
            masterItem = root.child(index, self.COL_NAME)
            if (masterItem == master.name):
                # update item
                masterItem.master = master
                masterItem.updateMasterView(root)
                doAddItem = False
                break
            elif (masterItem > master.name):
                self.addRow(master, is_local, root, index)
                doAddItem = False
                break
        if doAddItem:
            self.addRow(master, is_local, root, -1)
예제 #19
0
    def updateTypeView(cls, service, item):
        '''
        Updates the representation of the column contains the type of the service.

        :param service: the service data
        :type service: fkie_master_discovery.ServiceInfo<http://docs.ros.org/kinetic/api/fkie_master_discovery/html/modules.html#fkie_master_discovery.master_info.ServiceInfo>
        :param item: corresponding item in the model
        :type item: :class:`ServiceItem`
        '''
        try:
            if service.isLocal and service.type:
                service_class = service.get_service_class(
                    nm.is_local(get_hostname(service.uri)))
                item.setText(service_class._type)
            elif service.type:
                item.setText(service.type)
            else:
                item.setText('unknown type')
            # removed tooltip for clarity !!!
#      tooltip = ''
#      tooltip = ''.join([tooltip, '<h4>', service_class._type, '</h4>'])
#      tooltip = ''.join([tooltip, '<b><u>', 'Request', ':</u></b>'])
#      tooltip = ''.join([tooltip, '<dl><dt>', utf8(service_class._request_class.__slots__), '</dt></dl>'])
#
#      tooltip = ''.join([tooltip, '<b><u>', 'Response', ':</u></b>'])
#      tooltip = ''.join([tooltip, '<dl><dt>', utf8(service_class._response_class.__slots__), '</dt></dl>'])
#
#      item.setToolTip(''.join(['<div>', tooltip, '</div>']))
            item.setToolTip('')
        except Exception:
            if not service.isLocal:
                tooltip = ''.join([
                    '<h4>',
                    'Service type is not available due to he running on another host.',
                    '</h4>'
                ])
                item.setToolTip(''.join(['<div>', tooltip, '</div>']))
예제 #20
0
    def bc_run_node(cls,
                    name,
                    grpc_path='grpc://localhost:12321',
                    masteruri='',
                    reload_global_param=False,
                    loglevel='',
                    logformat='',
                    auto_pw_request=False,
                    user=None,
                    pw=None):
        '''
        Start the node with given name from the given configuration.

        :param runcfg: the configuration containing the start parameter
        :type runcfg: AdvRunCfg
        :raise StartException: if the screen is not available on host.
        :raise Exception: on errors while resolving host
        :see: :meth:`fkie_node_manager.is_local()`
        '''
        startcfg = nm.nmd().launch.get_start_cfg(
            name,
            grpc_path,
            masteruri,
            reload_global_param=reload_global_param,
            loglevel=loglevel,
            logformat=logformat)
        new_env = dict(startcfg.env)
        # set logging options
        if startcfg.namespace:
            new_env['ROS_NAMESPACE'] = startcfg.namespace
        # set logging
        if startcfg.logformat:
            new_env['ROSCONSOLE_FORMAT'] = '%s' % startcfg.logformat
#         if startcfg.loglevel:
#             new_env['ROSCONSOLE_CONFIG_FILE'] = launcher._rosconsole_cfg_file(startcfg.package, startcfg.loglevel)
        args = []
        # set name and namespace of the node
        if startcfg.name:
            args.append("__name:=%s" % startcfg.name)
        if startcfg.namespace:
            args.append("__ns:=%s" % startcfg.namespace)
        # add remap arguments
        for key, val in startcfg.remaps.items():
            args.append("%s:=%s" % (key, val))
        # handle respawn
        if startcfg.respawn:
            if startcfg.respawn_delay > 0:
                new_env['RESPAWN_DELAY'] = '%d' % startcfg.respawn_delay
            respawn_params = launcher._get_respawn_params(
                startcfg.fullname, startcfg.params)
            if respawn_params['max'] > 0:
                new_env['RESPAWN_MAX'] = '%d' % respawn_params['max']
            if respawn_params['min_runtime'] > 0:
                new_env['RESPAWN_MIN_RUNTIME'] = '%d' % respawn_params[
                    'min_runtime']
        if startcfg.cwd:
            cwd = get_cwd(startcfg.cwd, startcfg.binary_path)
            if cwd:
                args.append('__cwd:=%s' % cwd)
        # check for masteruri
        masteruri = startcfg.masteruri
        on_hostname = startcfg.hostname
        if masteruri is None:
            masteruri = masteruri_from_ros()
        if masteruri is not None:
            new_env['ROS_MASTER_URI'] = masteruri
            if 'ROS_HOSTNAME' in os.environ:
                # set only ROS_HOSTNAME if node manager have also one
                ros_hostname = nmdhost.get_ros_hostname(masteruri, on_hostname)
                if ros_hostname:
                    new_env['ROS_HOSTNAME'] = ros_hostname
            # load params to ROS master
            launcher._load_parameters(masteruri, startcfg.params,
                                      startcfg.clear_params)

        abs_paths = list()  # tuples of (parameter name, old value, new value)
        not_found_packages = list()  # package names
        #         # set the global parameter
        #         if runcfg.masteruri is not None and runcfg.masteruri not in runcfg.roslaunch_config.global_param_done:
        #             global_node_names = cls.getGlobalParams(runcfg.roslaunch_config.Roscfg)
        #             rospy.loginfo("Register global parameter:\n  %s", '\n  '.join("%s%s" % (utf8(v)[:80], '...' if len(utf8(v)) > 80 else'') for v in global_node_names.values()))
        #             abs_paths[len(abs_paths):], not_found_packages[len(not_found_packages):] = cls._load_parameters(runcfg.masteruri, global_node_names, [], runcfg.user, runcfg.pw, runcfg.auto_pw_request)
        #             runcfg.roslaunch_config.global_param_done.append(runcfg.masteruri)
        #
        #         # add params
        #         if runcfg.masteruri is not None:
        #             nodens = ''.join([n.namespace, n.name, rospy.names.SEP])
        #             params = dict()
        #             for param, value in runcfg.roslaunch_config.Roscfg.params.items():
        #                 if param.startswith(nodens):
        #                     params[param] = value
        #             clear_params = []
        #             for cparam in runcfg.roslaunch_config.Roscfg.clear_params:
        #                 if cparam.startswith(nodens):
        #                     clear_params.append(cparam)
        #             rospy.loginfo("Delete parameter:\n  %s", '\n  '.join(clear_params))
        #             rospy.loginfo("Register parameter:\n  %s", '\n  '.join("%s%s" % (utf8(v)[:80], '...' if len(utf8(v)) > 80 else'') for v in params.values()))
        #             abs_paths[len(abs_paths):], not_found_packages[len(not_found_packages):] = cls._load_parameters(runcfg.masteruri, params, clear_params, runcfg.user, runcfg.pw, runcfg.auto_pw_request)
        if not nm.is_local(on_hostname, wait=True):
            # start remote
            if not startcfg.package:
                raise StartException(
                    "Can't run remote without a valid package name!")
            # setup environment
            env_command = ''
            if new_env:
                try:
                    for k, v in new_env.items():
                        v_value, is_abs_path, found, package = cls._bc_resolve_abs_paths(
                            v, on_hostname, auto_pw_request, user, pw)
                        new_env[k] = v_value
                        if is_abs_path:
                            abs_paths.append(('ENV', "%s=%s" % (k, v),
                                              "%s=%s" % (k, v_value)))
                            if not found and package:
                                not_found_packages.append(package)
                    env_command = "env " + ' '.join(
                        ["%s=\'%s\'" % (k, v) for (k, v) in new_env.items()])
                except nm.AuthenticationRequest as e:
                    raise nm.InteractionNeededError(
                        e, cls.bc_run_node, {
                            'name': name,
                            'grpc_path': grpc_path,
                            'masteruri': masteruri,
                            'reload_global_param': reload_global_param,
                            'loglevel': loglevel,
                            'logformat': logformat,
                            'auto_pw_request': auto_pw_request,
                            'user': user,
                            'pw': pw
                        })
            startcmd = [
                env_command,
                nm.settings().start_remote_script, '--package',
                utf8(startcfg.package), '--node_type',
                utf8(startcfg.binary), '--node_name',
                utf8(startcfg.fullname),
                '--node_respawn true' if startcfg.respawn else ''
            ]
            if startcfg.masteruri is not None:
                startcmd.append('--masteruri')
                startcmd.append(startcfg.masteruri)
            if startcfg.prefix:
                startcmd[len(startcmd):] = ['--prefix', startcfg.prefix]
            if startcfg.loglevel:
                startcmd.append('--loglevel')
                startcmd.append(startcfg.loglevel)

            # rename the absolute paths in the args of the node
            node_args = []
            error = ''
            output = ''
            try:
                for a in startcfg.args:
                    a_value, is_abs_path, found, package = cls._bc_resolve_abs_paths(
                        a, on_hostname, auto_pw_request, user, pw)
                    node_args.append(a_value)
                    if is_abs_path:
                        abs_paths.append(('ARGS', a, a_value))
                        if not found and package:
                            not_found_packages.append(package)

                startcmd[len(startcmd):] = node_args
                startcmd[len(startcmd):] = args
                rospy.loginfo("Run remote on %s: %s", on_hostname,
                              utf8(' '.join(startcmd)))
                _, stdout, stderr, ok = nm.ssh().ssh_exec(on_hostname,
                                                          startcmd,
                                                          user,
                                                          pw,
                                                          auto_pw_request,
                                                          close_stdin=True)
                output = stdout.read()
                error = stderr.read()
                stdout.close()
                stderr.close()
            except nm.AuthenticationRequest as e:
                raise nm.InteractionNeededError(
                    e, cls.bc_run_node, {
                        'name': name,
                        'grpc_path': grpc_path,
                        'masteruri': masteruri,
                        'reload_global_param': reload_global_param,
                        'loglevel': loglevel,
                        'logformat': logformat,
                        'auto_pw_request': auto_pw_request,
                        'user': user,
                        'pw': pw
                    })
            if ok:
                if error:
                    rospy.logwarn("ERROR while start '%s': %s",
                                  startcfg.fullname, error)
                    raise StartException(
                        utf8(''.join(
                            ['The host "', on_hostname, '" reports:\n',
                             error])))
                if output:
                    rospy.logdebug("STDOUT while start '%s': %s",
                                   startcfg.fullname, output)
            # inform about absolute paths in parameter value
            if len(abs_paths) > 0:
                rospy.loginfo(
                    "Absolute paths found while start:\n%s",
                    utf8('\n'.join([
                        ''.join([p, '\n  OLD: ', ov, '\n  NEW: ', nv])
                        for p, ov, nv in abs_paths
                    ])))

            if len(not_found_packages) > 0:
                packages = '\n'.join(not_found_packages)
                raise StartException(
                    utf8('\n'.join([
                        'Some absolute paths are not renamed because following packages are not found on remote host:',
                        packages
                    ])))
예제 #21
0
    def runNodeWithoutConfig(cls,
                             host,
                             package,
                             binary,
                             name,
                             args=[],
                             masteruri=None,
                             use_nmd=True,
                             auto_pw_request=False,
                             user=None,
                             pw=None,
                             path=''):
        '''
        Start a node with using a launch configuration.

        :param str hosturi: the host or ip to run the node
        :param str package: the ROS package containing the binary
        :param str binary: the binary of the node to execute
        :param str name: the ROS name of the node (with name space)
        :param args: the list with arguments passed to the binary
        :type args: [str]
        :param bool use_nmd: start the node using node manager daemon
        :param bool auto_pw_request: opens question dialog directly, use True only if the method is called from the main GUI thread
        :raise Exception: on errors while resolving host
        :see: :meth:`fkie_node_manager.is_local()`
        '''
        # create the name with namespace
        args2 = list(args)
        fullname = roslib.names.ns_join(roslib.names.SEP, name)
        namespace = ''
        for a in args:
            if a.startswith('__ns:='):
                namespace = a.replace('__ns:=', '')
                fullname = roslib.names.ns_join(namespace, name)
        args2.append(''.join(['__name:=', name]))
        # run on local host
        if nm.is_local(host, wait=True):
            if not use_nmd:
                if path:
                    cmd = [path]
                else:
                    try:
                        cmd = roslib.packages.find_node(package, binary)
                    except roslib.packages.ROSPkgException as e:
                        # multiple nodes, invalid package
                        raise StartException(utf8(e))
                    # handle different result types str or array of string
                    if isstring(cmd):
                        cmd = [cmd]
                cmd_type = ''
                if cmd is None or len(cmd) == 0:
                    raise StartException('%s in package [%s] not found!' %
                                         (binary, package))
                # compatibility for python scripts installed with catkin_install_python()
                # avoid ask for select a binary
                cmd = cls._remove_src_binary(cmd)
                if len(cmd) > 1:
                    # Open selection for executables
                    err = 'Multiple executables with same name in package [%s] found' % package
                    bsel = nm.BinarySelectionRequest(cmd, err)
                    raise nm.InteractionNeededError(
                        bsel, cls.runNodeWithoutConfig, {
                            'host': host,
                            'package': package,
                            'binary': binary,
                            'name': name,
                            'args': args,
                            'masteruri': masteruri,
                            'use_nmd': use_nmd,
                            'auto_pw_request': auto_pw_request,
                            'user': user,
                            'pw': pw,
                            'path': path
                        })
                else:
                    cmd_type = cmd[0]
            new_env = {}  # dict(os.environ)
            if namespace:
                new_env['ROS_NAMESPACE'] = namespace
            if masteruri is not None:
                cls._prepareROSMaster(masteruri)
                new_env['ROS_MASTER_URI'] = masteruri
                if 'ROS_HOSTNAME' in os.environ:
                    # set ROS_HOSTNAME only if node_manager has also one
                    ros_hostname = nmdhost.get_ros_hostname(masteruri, host)
                    if ros_hostname:
                        new_env['ROS_HOSTNAME'] = ros_hostname
            if use_nmd:
                nm.nmd().launch.start_standalone_node(nmdurl.nmduri(), package,
                                                      binary, name, namespace,
                                                      args, new_env, masteruri,
                                                      host)
            else:
                local_env = dict(os.environ)
                local_env.update(new_env)
                cmd_str = utf8(' '.join([
                    screen.get_cmd(fullname, local_env), cmd_type,
                    ' '.join(args2)
                ]))
                rospy.loginfo("Run without config: %s",
                              fullname if use_nmd else cmd_str)
                SupervisedPopen(shlex.split(cmd_str),
                                env=local_env,
                                object_id="Run without config",
                                description="Run without config [%s]%s" %
                                (utf8(package), utf8(binary)))
        else:
            # run on a remote machine
            startcmd = [
                nm.settings().start_remote_script, '--package',
                utf8(package), '--node_type',
                utf8(binary), '--node_name',
                utf8(fullname)
            ]
            startcmd[len(startcmd):] = args2
            if masteruri is not None:
                startcmd.append('--masteruri')
                startcmd.append(masteruri)
            rospy.loginfo("Run remote on %s: %s", host, ' '.join(startcmd))
            try:
                _, stdout, stderr, ok = nm.ssh().ssh_exec(host,
                                                          startcmd,
                                                          user,
                                                          pw,
                                                          auto_pw_request,
                                                          close_stdin=True)
                if ok:
                    output = stdout.read()
                    error = stderr.read()
                    stdout.close()
                    stderr.close()
                    if error:
                        rospy.logwarn("ERROR while start '%s': %s", name,
                                      error)
                        raise StartException(''.join(
                            ['The host "', host, '" reports:\n', error]))
                    if output:
                        if output.find("dn't") != -1:
                            rospy.logwarn("Warning while start '%s': %s", name,
                                          output)
                        else:
                            rospy.loginfo("STDOUT while start '%s': %s", name,
                                          output)
                else:
                    if error:
                        rospy.logwarn("ERROR while start '%s': %s", name,
                                      error)
                        raise StartException(''.join(
                            ['The host "', host, '" reports:\n', error]))
            except nm.AuthenticationRequest as e:
                raise nm.InteractionNeededError(
                    e, cls.runNodeWithoutConfig, {
                        'host': host,
                        'package': package,
                        'binary': binary,
                        'name': name,
                        'args': args,
                        'masteruri': masteruri,
                        'use_nmd': use_nmd,
                        'auto_pw_request': auto_pw_request,
                        'user': user,
                        'pw': pw,
                        'path': path
                    })
예제 #22
0
    def on_save_profile(self, masteruri='', path=None):
        '''
        Saves the current environment to a node manager profile.

        :param str masteruri: If not empty, save the profile only for given master
        :param str path: the path of file to save. If None :meth:`get_profile_file` is called to get a path.
        '''
        try:
            if path is None:
                path = self.get_profile_file()
                if path is None:
                    return
            rospy.loginfo("Save profile %s" % path)
            content = {}
            for muri, master in self._main_window.masters.items():
                if not masteruri or masteruri == muri:
                    running_nodes = master.get_nodes_runningIfLocal()
                    configs = {}
                    md_param = {}
                    ms_param = {}
                    zc_param = {}
                    nmd_param = {}
                    smuri = muri
                    addr = nm.nameres().address(smuri)
                    hostname = get_hostname(smuri)
                    mastername = ''
                    if nm.is_local(addr):
                        smuri = smuri.replace(hostname, '$LOCAL$')
                        addr = '$LOCAL$'
                    else:
                        mastername = nm.nameres().mastername(
                            smuri,
                            nm.nameres().address(smuri))
                    for node_name in running_nodes.keys():
                        node_items = master.getNode(node_name)
                        for node in node_items:
                            if node.is_running(
                            ) and node.launched_cfg is not None:  # node.has_launch_cfgs(node.cfgs):
                                # it is a loaded launch file, get the filename
                                cfg = to_pkg(node.launched_cfg)
                                if cfg not in configs:
                                    configs[cfg] = {'nodes': []}
                                configs[cfg]['nodes'].append(node_name)
                            elif node_name.endswith('master_discovery'):
                                md_param = get_rosparam(
                                    'master_discovery', muri)
                            elif node_name.endswith('master_sync'):
                                ms_param = get_rosparam('master_sync', muri)
                            elif node_name.endswith('zeroconf'):
                                zc_param = get_rosparam('zeroconf', muri)
                            elif node_name.endswith('node_manager_daemon'):
                                nmd_param = get_rosparam(
                                    'node_manager_daemon', muri)
                    # store arguments for launchfiles
                    for a, b in master.launchfiles.items():
                        resolved_a = to_pkg(a)
                        if resolved_a not in configs:
                            configs[resolved_a] = {}
                            configs[resolved_a]['default'] = False
                        configs[resolved_a]['args'] = b.args
                    # fill the configuration content for yaml as dictionary
                    content[smuri] = {
                        'mastername': mastername,
                        'address': addr,
                        'configs': configs
                    }
                    if md_param:
                        content[smuri]['master_discovery'] = md_param
                    if ms_param:
                        content[smuri]['master_sync'] = ms_param
                    if zc_param:
                        content[smuri]['zeroconf'] = zc_param
                    if nmd_param:
                        content[smuri]['node_manager_daemon'] = nmd_param
            buf = ruamel.yaml.compat.StringIO()
            ruamel.yaml.dump(content, buf, Dumper=ruamel.yaml.RoundTripDumper)
            with open(path, 'w+') as f:
                f.write(buf.getvalue())
        except Exception as e:
            import traceback
            print(utf8(traceback.format_exc(3)))
            MessageBox.warning(self, "Save profile Error",
                               'Error while save profile', utf8(e))