Ejemplo n.º 1
0
 def openScreen(cls, node, host, auto_item_request=False, user=None, pw=None, items=[]):
     '''
     Searches for the screen associated with the given node and open the screen
     output in a new terminal.
     @param node: the name of the node those screen output to show
     @type node: C{str}
     @param host: the host name or ip where the screen is running
     @type host: C{str}
     @raise Exception: on errors while resolving host
     @see: L{openScreenTerminal()} or L{_getActiveScreens()}
     '''
     if node is None or len(node) == 0:
         return False
     try:
         if items:
             for item in items:
                 # open the selected screen
                 cls.openScreenTerminal(host, item, node, user)
         else:
             # get the available screens
             screens = cls._getActiveScreens(host, cls.createSessionName(node), auto_item_request, user, pw)
             if len(screens) == 1:
                 cls.openScreenTerminal(host, screens[0], node, user)
             else:
                 # create a list to let the user make a choice, which screen must be open
                 choices = {}
                 for s in screens:
                     pid, session_name = cls.splitSessionName(s)
                     choices[''.join([session_name, ' [', pid, ']'])] = s
                 # Open selection
                 if len(choices) > 0:
                     if len(choices) == 1:
                         cls.openScreenTerminal(host, choices[0], node, user)
                     elif auto_item_request:
                         from select_dialog import SelectDialog
                         items, _ = SelectDialog.getValue('Show screen', '', choices.keys(), False)
                         for item in items:
                             # open the selected screen
                             cls.openScreenTerminal(host, choices[item], node, user)
                     else:
                         raise ScreenSelectionRequest(choices, 'Show screen')
                 else:
                     raise DetailedError('Show screen', 'No screen for %s on %s found!\nSee log for details!' % (node, host))
             return len(screens) > 0
     except nm.AuthenticationRequest as e:
         raise nm.InteractionNeededError(e, cls.openScreen, (node, host, auto_item_request))
     except ScreenSelectionRequest as e:
         raise nm.InteractionNeededError(e, cls.openScreen, (node, host, auto_item_request, user, pw))
Ejemplo n.º 2
0
 def copylogPath2Clipboards(self,
                            host,
                            nodes=[],
                            auto_pw_request=True,
                            user=None,
                            pw=None):
     if nm.is_local(host):
         if len(nodes) == 1:
             return nm.screen().getScreenLogFile(node=nodes[0])
         else:
             return nm.screen().LOG_PATH
     else:
         request = '[]' if len(nodes) != 1 else nodes[0]
         try:
             output, error, ok = nm.ssh().ssh_exec(
                 host, [nm.STARTER_SCRIPT, '--ros_log_path', request], user,
                 pw, auto_pw_request)
             if ok:
                 return output
             else:
                 raise StartException(
                     str(''.join([
                         'Get log path from "', host, '" failed:\n', error
                     ])))
         except nm.AuthenticationRequest as e:
             raise nm.InteractionNeededError(
                 e, cls.deleteLog, (nodename, host, auto_pw_request))
Ejemplo n.º 3
0
 def deleteLog(cls, nodename, host, auto_pw_request=False, user=None, pw=None):
     '''
     Deletes the log file associated with the given node.
     @param nodename: the name of the node (with name space)
     @type nodename: C{str}
     @param host: the host name or ip where the log file are to delete
     @type host: C{str}
     @raise Exception: on errors while resolving host
     @see: L{node_manager_fkie.is_local()}
     '''
     rospy.loginfo("delete log for '%s' on '%s'", str(nodename), str(host))
     if nm.is_local(host):
         screenLog = nm.screen().getScreenLogFile(node=nodename)
         pidFile = nm.screen().getScreenPidFile(node=nodename)
         roslog = nm.screen().getROSLogFile(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
             nm.ssh().ssh_exec(host, [nm.settings().start_remote_script, '--delete_logs', nodename], user, pw, auto_pw_request, close_stdin=True, close_stdout=True, close_stderr=True)
         except nm.AuthenticationRequest as e:
             raise nm.InteractionNeededError(e, cls.deleteLog, (nodename, host, auto_pw_request))
Ejemplo n.º 4
0
 def killScreens(cls, node, host, auto_ok_request=True, user=None, pw=None):
     '''
     Searches for the screen associated with the given node and kill this screens.
     @param node: the name of the node those screen output to show
     @type node: C{str}
     @param host: the host name or ip where the screen is running
     @type host: C{str}
     '''
     if node is None or len(node) == 0:
         return False
     try:
         # get the available screens
         screens = cls._getActiveScreens(host,
                                         cls.createSessionName(node),
                                         auto_ok_request,
                                         user=user,
                                         pwd=pw)  # user=user, pwd=pwd
         if screens:
             do_kill = True
             if auto_ok_request:
                 try:
                     from python_qt_binding.QtGui import QMessageBox
                 except:
                     from python_qt_binding.QtWidgets import QMessageBox
                 result = QMessageBox.question(
                     None, "Kill SCREENs?", '\n'.join(screens),
                     QMessageBox.Ok | QMessageBox.Cancel, QMessageBox.Ok)
                 if result & QMessageBox.Ok:
                     do_kill = True
             if do_kill:
                 for s in screens:
                     pid, _, _ = s.partition('.')
                     if pid:
                         try:
                             nm.starter()._kill_wo(host, int(pid),
                                                   auto_ok_request, user,
                                                   pw)
                         except:
                             import traceback
                             rospy.logwarn(
                                 "Error while kill screen (PID: %s) on host '%s': %s",
                                 str(pid), str(host),
                                 traceback.format_exc(1))
                 if nm.is_local(host):
                     SupervisedPopen(
                         [cls.SCREEN, '-wipe'],
                         object_id='screen -wipe',
                         description="screen: clean up the socket with -wipe"
                     )
                 else:
                     nm.ssh().ssh_exec(host, [cls.SCREEN, '-wipe'],
                                       close_stdin=True,
                                       close_stdout=True,
                                       close_stderr=True)
     except nm.AuthenticationRequest as e:
         raise nm.InteractionNeededError(e, cls.killScreens,
                                         (node, host, auto_ok_request))
Ejemplo n.º 5
0
 def rosclean(self, host, auto_pw_request=False, user=None, pw=None):
     '''
     rosclean purge on given host.
     @param host: the name or address of the host, where rosclean is called.
     @type host: C{str}
     @raise StartException: on error
     @raise Exception: on errors while resolving host
     @see: L{node_manager_fkie.is_local()}
     '''
     try:
         self._rosclean_wo(host, auto_pw_request, user, pw)
     except nm.AuthenticationRequest as e:
         raise nm.InteractionNeededError(e, self.poweroff, (host, auto_pw_request))
Ejemplo n.º 6
0
 def killall_roscore(self, host, auto_pw_request=False, user=None, pw=None):
     '''
     Kills all roscore processes on given host.
     @param host: the name or address of the host, where the process must be killed.
     @type host: C{str}
     @raise StartException: on error
     @raise Exception: on errors while resolving host
     @see: L{node_manager_fkie.is_local()}
     '''
     try:
         self._killall_roscore_wo(host, auto_pw_request, user, pw)
     except nm.AuthenticationRequest as e:
         raise nm.InteractionNeededError(e, self.killall_roscore, (host, auto_pw_request))
Ejemplo n.º 7
0
 def killScreens(cls, node, host, auto_ok_request=True, user=None, pw=None):
     '''
 Searches for the screen associated with the given node and kill this screens. 
 @param node: the name of the node those screen output to show
 @type node: C{str}
 @param host: the host name or ip where the screen is running
 @type host: C{str}
 '''
     if node is None or len(node) == 0:
         return False
     try:
         # get the available screens
         screens = cls.getActiveScreens(host,
                                        cls.createSessionName(node),
                                        user=user)  #user=user, pwd=pwd
         if screens:
             do_kill = True
             if auto_ok_request:
                 from python_qt_binding import QtGui
                 result = QtGui.QMessageBox.question(
                     None, "Kill SCREENs?", '\n'.join(screens),
                     QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel,
                     QtGui.QMessageBox.Ok)
                 if result & QtGui.QMessageBox.Ok:
                     do_kill = True
             if do_kill:
                 for s in screens:
                     pid, _, _ = s.partition('.')
                     if pid:
                         try:
                             nm.starter()._kill_wo(host, int(pid),
                                                   auto_ok_request, user,
                                                   pw)
                         except:
                             import traceback
                             rospy.logwarn(
                                 "Error while kill screen (PID: %s) on host '%s': %s",
                                 str(pid), str(host),
                                 traceback.format_exc())
                 if nm.is_local(host):
                     ps = subprocess.Popen([cls.SCREEN, '-wipe'])
                     # wait for process to avoid 'defunct' processes
                     thread = threading.Thread(target=ps.wait)
                     thread.setDaemon(True)
                     thread.start()
                 else:
                     #            output, error, ok = nm.ssh().ssh_exec(host, [cls.SCREEN, '-wipe'])
                     nm.ssh().ssh_exec(host, [cls.SCREEN, '-wipe'])
     except nm.AuthenticationRequest as e:
         raise nm.InteractionNeededError(e, cls.killScreens,
                                         (node, host, auto_ok_request))
Ejemplo n.º 8
0
 def kill(self, host, pid, auto_pw_request=True, user=None, pw=None):
     '''
 Kills the process with given process id on given host.
 @param host: the name or address of the host, where the process must be killed.
 @type host: C{str}
 @param pid: the process id
 @type pid: C{int}
 @raise StartException: on error
 @raise Exception: on errors while resolving host
 @see: L{node_manager_fkie.is_local()}
 '''
     try:
         self._kill_wo(host, pid, auto_pw_request, user, pw)
     except nm.AuthenticationRequest as e:
         raise nm.InteractionNeededError(e, cls.deleteLog,
                                         (nodename, host, auto_pw_request))
Ejemplo n.º 9
0
 def getActiveScreens(cls, host, session='', 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 host: the host name or IP to search for the screen session.
     @type host: C{str}
     @param session: the name or the suffix of the screen session
     @type session: C{str} (Default: C{''})
     @return: the list with session names
     @rtype: C{[str(session name), ...]}
     @raise Exception: on errors while resolving host
     @see: L{node_manager_fkie.is_local()}
     '''
     try:
         return cls._getActiveScreens(host, session, auto_pw_request, user, pwd)
     except nm.AuthenticationRequest as e:
         raise nm.InteractionNeededError(e, cls.getActiveScreens, (host, session, auto_pw_request))
Ejemplo n.º 10
0
 def copylogPath2Clipboards(cls, host, nodes=[], auto_pw_request=False, user=None, pw=None):
   if nm.is_local(host):
     if len(nodes) == 1:
       return nm.screen().getScreenLogFile(node=nodes[0])
     else:
       return nm.screen().LOG_PATH
   else:
     request = '[]' if len(nodes) != 1 else nodes[0]
     try:
       socket.setdefaulttimeout(3)
       output, error, ok = nm.ssh().ssh_exec(host, [nm.settings().start_remote_script, '--ros_log_path', request], user, pw, auto_pw_request)
       if ok:
         return output
       else:
         raise StartException(str(''.join(['Get log path from "', host, '" failed:\n', error])))
     except nm.AuthenticationRequest as e:
       raise nm.InteractionNeededError(e, cls.copylogPath2Clipboards, (host, nodes, auto_pw_request))
     finally:
       socket.setdefaulttimeout(None)
Ejemplo n.º 11
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 nm.screen().getScreenLogFile(node=nodes[0])
         else:
             return nm.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(str(''.join(['Get log path from "', host, '" failed'])))
         except nm.AuthenticationRequest as e:
             raise nm.InteractionNeededError(e, cls.get_log_path, (host, nodes, auto_pw_request))
         finally:
             socket.setdefaulttimeout(None)
Ejemplo n.º 12
0
 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(str(''.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, path, auto_pw_request))
Ejemplo n.º 13
0
    def runNode(cls,
                node,
                launch_config,
                force2host=None,
                masteruri=None,
                auto_pw_request=False,
                user=None,
                pw=None,
                item=None):
        '''
    Start the node with given name from the given configuration.
    @param node: the name of the node (with name space)
    @type node: C{str}
    @param launch_config: the configuration containing the node
    @type launch_config: L{LaunchConfig} 
    @param force2host: start the node on given host.
    @type force2host: L{str} 
    @param masteruri: force the masteruri.
    @type masteruri: L{str} 
    @param auto_pw_request: opens question dialog directly, use True only if the method is called from the main GUI thread
    @type auto_pw_request: bool
    @raise StartException: if the screen is not available on host.
    @raise Exception: on errors while resolving host
    @see: L{node_manager_fkie.is_local()}
    '''
        #'print "RUN node", node, time.time()
        n = launch_config.getNode(node)
        if n is None:
            raise StartException(''.join(["Node '", node, "' not found!"]))

        env = list(n.env_args)
        if n.respawn:
            # set the respawn environment variables
            respawn_params = cls._get_respawn_params(
                rospy.names.ns_join(n.namespace, n.name),
                launch_config.Roscfg.params)
            if respawn_params['max'] > 0:
                env.append(('RESPAWN_MAX', '%d' % respawn_params['max']))
            if respawn_params['min_runtime'] > 0:
                env.append(('RESPAWN_MIN_RUNTIME',
                            '%d' % respawn_params['min_runtime']))
            if respawn_params['delay'] > 0:
                env.append(('RESPAWN_DELAY', '%d' % respawn_params['delay']))
        prefix = n.launch_prefix if not n.launch_prefix is None else ''
        if prefix.lower() == 'screen' or prefix.lower().find('screen ') != -1:
            rospy.loginfo("SCREEN prefix removed before start!")
            prefix = ''
        args = [
            ''.join(['__ns:=', n.namespace.rstrip(rospy.names.SEP)]),
            ''.join(['__name:=', n.name])
        ]
        if not (n.cwd is None):
            args.append(''.join(['__cwd:=', n.cwd]))

        # add remaps
        for remap in n.remap_args:
            args.append(''.join([remap[0], ':=', remap[1]]))

        # get host of the node
        host = launch_config.hostname
        env_loader = ''
        if n.machine_name:
            machine = launch_config.Roscfg.machines[n.machine_name]
            if not machine.address in ['localhost', '127.0.0.1']:
                host = machine.address
                if masteruri is None:
                    masteruri = nm.nameres().masteruri(n.machine_name)
            #TODO: env-loader support?
#      if hasattr(machine, "env_loader") and machine.env_loader:
#        env_loader = machine.env_loader
# set the host to the given host
        if not force2host is None:
            host = force2host

        # set the ROS_MASTER_URI
        if masteruri is None:
            masteruri = masteruri_from_ros()
            env.append(('ROS_MASTER_URI', masteruri))

        abs_paths = list()  # tuples of (parameter name, old value, new value)
        not_found_packages = list()  # package names
        # set the global parameter
        if not masteruri is None and not masteruri in launch_config.global_param_done:
            global_node_names = cls.getGlobalParams(launch_config.Roscfg)
            rospy.loginfo(
                "Register global parameter:\n  %s", '\n  '.join(
                    "%s%s" % (str(v)[:80], '...' if len(str(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(
                    masteruri, global_node_names, [], user, pw,
                    auto_pw_request)
            launch_config.global_param_done.append(masteruri)

        # add params
        if not masteruri is None:
            nodens = ''.join([n.namespace, n.name, rospy.names.SEP])
            params = dict()
            for param, value in launch_config.Roscfg.params.items():
                if param.startswith(nodens):
                    params[param] = value
            clear_params = []
            for cparam in launch_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" % (str(v)[:80], '...' if len(str(v)) > 80 else '')
                    for v in params.values()))
            abs_paths[len(abs_paths):], not_found_packages[
                len(not_found_packages):] = cls._load_parameters(
                    masteruri, params, clear_params, user, pw, auto_pw_request)
        #'print "RUN prepared", node, time.time()

        if nm.is_local(host):
            nm.screen().testScreen()
            if item:
                cmd_type = item
            else:
                try:
                    cmd = roslib.packages.find_node(n.package, n.type)
                except (Exception, roslib.packages.ROSPkgException) as e:
                    # multiple nodes, invalid package
                    raise StartException(''.join(
                        ["Can't find resource: ",
                         str(e)]))
                # handle diferent result types str or array of string
                if isinstance(cmd, types.StringTypes):
                    cmd = [cmd]
                cmd_type = ''
                if cmd is None or len(cmd) == 0:
                    raise StartException(' '.join([
                        n.type, 'in package [', n.package,
                        '] not found!\n\nThe package was created?\nIs the binary executable?\n'
                    ]))
                if len(cmd) > 1:
                    if auto_pw_request:
                        # Open selection for executables, only if the method is called from the main GUI thread
                        try:
                            from python_qt_binding import QtGui
                            item, result = QtGui.QInputDialog.getItem(
                                None, ' '.join([
                                    'Multiple executables', n.type, 'in',
                                    n.package
                                ]), 'Select an executable', cmd, 0, False)
                            if result:
                                #open the selected screen
                                cmd_type = item
                            else:
                                return
                        except:
                            raise StartException(
                                'Multiple executables with same name in package found!'
                            )
                    else:
                        err = BinarySelectionRequest(cmd,
                                                     'Multiple executables')
                        raise nm.InteractionNeededError(
                            err, cls.runNode,
                            (node, launch_config, force2host, masteruri,
                             auto_pw_request, user, pw))
                else:
                    cmd_type = cmd[0]
            # determine the current working path, Default: the package of the node
            cwd = get_ros_home()
            if not (n.cwd is None):
                if n.cwd == 'ROS_HOME':
                    cwd = get_ros_home()
                elif n.cwd == 'node':
                    cwd = os.path.dirname(cmd_type)
            cls._prepareROSMaster(masteruri)
            node_cmd = [
                nm.settings().respawn_script if n.respawn else '', prefix,
                cmd_type
            ]
            cmd_args = [nm.screen().getSceenCmd(node)]
            cmd_args[len(cmd_args):] = node_cmd
            cmd_args.append(str(n.args))
            cmd_args[len(cmd_args):] = args
            rospy.loginfo("RUN: %s", ' '.join(cmd_args))
            new_env = dict(os.environ)
            new_env['ROS_MASTER_URI'] = masteruri
            # add the namespace environment parameter to handle some cases, e.g. rqt_cpp plugins
            if n.namespace:
                new_env['ROS_NAMESPACE'] = n.namespace
            for k, v in env:
                new_env[k] = v
            SupervisedPopen(shlex.split(str(' '.join(cmd_args))),
                            cwd=cwd,
                            env=new_env,
                            id="Run node",
                            description="Run node [%s]%s" %
                            (str(n.package), str(n.type)))
        else:
            #'print "RUN REMOTE", node, time.time()
            # start remote
            if launch_config.PackageName is None:
                raise StartException(''.join(
                    ["Can't run remote without a valid package name!"]))
            # thus the prefix parameters while the transfer are not separated
            if prefix:
                prefix = ''.join(['"', prefix, '"'])
            # setup environment
            env_command = ''
            if env_loader:
                rospy.logwarn(
                    "env_loader in machine tag currently not supported")
                raise StartException(
                    "env_loader in machine tag currently not supported")
            if env:
                new_env = dict()
                try:
                    for (k, v) in env:
                        v_value, is_abs_path, found, package = cls._resolve_abs_paths(
                            v, host, user, pw, auto_pw_request)
                        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.runNode, (node, launch_config, force2host,
                                         masteruri, auto_pw_request))

            startcmd = [
                env_command,
                nm.settings().start_remote_script, '--package',
                str(n.package), '--node_type',
                str(n.type), '--node_name',
                str(node), '--node_respawn true' if n.respawn else ''
            ]
            if not masteruri is None:
                startcmd.append('--masteruri')
                startcmd.append(masteruri)
            if prefix:
                startcmd[len(startcmd):] = ['--prefix', prefix]

            #rename the absolute paths in the args of the node
            node_args = []
            try:
                for a in n.args.split():
                    a_value, is_abs_path, found, package = cls._resolve_abs_paths(
                        a, host, user, pw, auto_pw_request)
                    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", host,
                              str(' '.join(startcmd)))
                #'print "RUN CALL", node, time.time()
                _, stdout, stderr, ok = nm.ssh().ssh_exec(host,
                                                          startcmd,
                                                          user,
                                                          pw,
                                                          auto_pw_request,
                                                          close_stdin=True)
                output = stdout.read()
                error = stderr.read()
                stdout.close()
                stderr.close()
                #'print "RUN CALLOK", node, time.time()
            except nm.AuthenticationRequest as e:
                raise nm.InteractionNeededError(
                    e, cls.runNode, (node, launch_config, force2host,
                                     masteruri, auto_pw_request))

            if ok:
                if error:
                    rospy.logwarn("ERROR while start '%s': %s", node, error)
                    raise StartException(
                        str(''.join(
                            ['The host "', host, '" reports:\n', error])))
                if output:
                    rospy.loginfo("STDOUT while start '%s': %s", node, output)
            # inform about absolute paths in parameter value
            if len(abs_paths) > 0:
                rospy.loginfo(
                    "Absolute paths found while start:\n%s",
                    str('\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(
                    str('\n'.join([
                        'Some absolute paths are not renamed because following packages are not found on remote host:',
                        packages
                    ])))
Ejemplo n.º 14
0
    def runNodeWithoutConfig(cls,
                             host,
                             package,
                             binary,
                             name,
                             args=[],
                             masteruri=None,
                             auto_pw_request=False,
                             user=None,
                             pw=None):
        '''
    Start a node with using a launch configuration.
    @param host: the host or ip to run the node
    @type host: C{str} 
    @param package: the ROS package containing the binary
    @type package: C{str} 
    @param binary: the binary of the node to execute
    @type binary: C{str} 
    @param name: the ROS name of the node (with name space)
    @type name: C{str} 
    @param args: the list with arguments passed to the binary
    @type args: C{[str, ...]} 
    @param auto_pw_request: opens question dialog directly, use True only if the method is called from the main GUI thread
    @type auto_pw_request: bool
    @raise Exception: on errors while resolving host
    @see: L{node_manager_fkie.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):
            try:
                cmd = roslib.packages.find_node(package, binary)
            except roslib.packages.ROSPkgException as e:
                # multiple nodes, invalid package
                raise StartException(str(e))
            # handle different result types str or array of string
#      import types
            if isinstance(cmd, types.StringTypes):
                cmd = [cmd]
            cmd_type = ''
            if cmd is None or len(cmd) == 0:
                raise StartException(' '.join(
                    [binary, 'in package [', package, '] not found!']))
            if len(cmd) > 1:
                # Open selection for executables
                #        try:
                #          from python_qt_binding import QtGui
                #          item, result = QtGui.QInputDialog.getItem(None, ' '.join(['Multiple executables', type, 'in', package]),
                #                                            'Select an executable',
                #                                            cmd, 0, False)
                #          if result:
                #            #open the selected screen
                #            cmd_type = item
                #          else:
                #            return
                #        except:
                err = [
                    ''.join([
                        'Multiple executables with same name in package [',
                        package, ']  found:'
                    ])
                ]
                err.extend(cmd)
                raise StartException('\n'.join(err))
            else:
                cmd_type = cmd[0]
            cmd_str = str(' '.join(
                [nm.screen().getSceenCmd(fullname), cmd_type,
                 ' '.join(args2)]))
            rospy.loginfo("Run without config: %s", cmd_str)
            ps = None
            new_env = dict(os.environ)
            if namespace:
                new_env['ROS_NAMESPACE'] = namespace
            if not masteruri is None:
                cls._prepareROSMaster(masteruri)
                new_env['ROS_MASTER_URI'] = masteruri
            SupervisedPopen(shlex.split(cmd_str),
                            env=new_env,
                            id="Run without config",
                            description="Run without config [%s]%s" %
                            (str(package), str(binary)))
        else:
            # run on a remote machine
            startcmd = [
                nm.settings().start_remote_script, '--package',
                str(package), '--node_type',
                str(binary), '--node_name',
                str(fullname)
            ]
            startcmd[len(startcmd):] = args2
            if not masteruri is 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]))

    #          from python_qt_binding import QtGui
    #          QtGui.QMessageBox.warning(None, 'Error while remote start %s'%str(name),
    #                                      str(''.join(['The host "', host, '" reports:\n', error])),
    #                                      QtGui.QMessageBox.Ok)
                    if output:
                        rospy.logdebug("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, package, binary, name, args, masteruri,
                     auto_pw_request))
Ejemplo n.º 15
0
    def runNode(cls,
                node,
                launch_config,
                force2host=None,
                masteruri=None,
                auto_pw_request=False,
                user=None,
                pw=None):
        '''
    Start the node with given name from the given configuration.
    @param node: the name of the node (with name space)
    @type node: C{str}
    @param launch_config: the configuration containing the node
    @type launch_config: L{LaunchConfig} 
    @param force2host: start the node on given host.
    @type force2host: L{str} 
    @param masteruri: force the masteruri.
    @type masteruri: L{str} 
    @raise StartException: if the screen is not available on host.
    @raise Exception: on errors while resolving host
    @see: L{node_manager_fkie.is_local()}
    '''
        #'print "RUN node", node, time.time()
        n = launch_config.getNode(node)
        if n is None:
            raise StartException(''.join(["Node '", node, "' not found!"]))

        env = list(n.env_args)
        prefix = n.launch_prefix if not n.launch_prefix is None else ''
        if prefix.lower() == 'screen' or prefix.lower().find('screen ') != -1:
            rospy.loginfo("SCREEN prefix removed before start!")
            prefix = ''
        args = [
            ''.join(['__ns:=', n.namespace]), ''.join(['__name:=', n.name])
        ]
        if not (n.cwd is None):
            args.append(''.join(['__cwd:=', n.cwd]))

        # add remaps
        for remap in n.remap_args:
            args.append(''.join([remap[0], ':=', remap[1]]))

        # get host of the node
        host = launch_config.hostname
        env_loader = ''
        if n.machine_name:
            machine = launch_config.Roscfg.machines[n.machine_name]
            host = machine.address
            #TODO: env-loader support?
#      if hasattr(machine, "env_loader") and machine.env_loader:
#        env_loader = machine.env_loader
# set the host to the given host
        if not force2host is None:
            host = force2host

        if masteruri is None:
            masteruri = nm.nameres().masteruri(n.machine_name)
        # set the ROS_MASTER_URI
        if masteruri is None:
            masteruri = nm.masteruri_from_ros()
            env.append(('ROS_MASTER_URI', masteruri))

        abs_paths = list()  # tuples of (parameter name, old value, new value)
        not_found_packages = list()  # package names
        # set the global parameter
        if not masteruri is None and not masteruri in launch_config.global_param_done:
            global_node_names = cls.getGlobalParams(launch_config.Roscfg)
            rospy.loginfo("Register global parameter:\n%s",
                          '\n'.join(global_node_names))
            abs_paths[len(abs_paths):], not_found_packages[
                len(not_found_packages):] = cls._load_parameters(
                    masteruri, global_node_names, [])
            launch_config.global_param_done.append(masteruri)

        # add params
        if not masteruri is None:
            nodens = ''.join([n.namespace, n.name, '/'])
            params = dict()
            for param, value in launch_config.Roscfg.params.items():
                if param.startswith(nodens):
                    params[param] = value
            clear_params = []
            for cparam in launch_config.Roscfg.clear_params:
                if cparam.startswith(nodens):
                    clear_params.append(param)
            rospy.loginfo("Register parameter:\n%s", '\n'.join(params))
            abs_paths[len(abs_paths):], not_found_packages[
                len(not_found_packages):] = cls._load_parameters(
                    masteruri, params, clear_params)
        #'print "RUN prepared", node, time.time()

        if nm.is_local(host):
            nm.screen().testScreen()
            try:
                cmd = roslib.packages.find_node(n.package, n.type)
            except (Exception, roslib.packages.ROSPkgException) as e:
                # multiple nodes, invalid package
                raise StartException(''.join(["Can't find resource: ",
                                              str(e)]))
            # handle diferent result types str or array of string
            import types
            if isinstance(cmd, types.StringTypes):
                cmd = [cmd]
            cmd_type = ''
            if cmd is None or len(cmd) == 0:
                raise StartException(' '.join([
                    n.type, 'in package [', n.package,
                    '] not found!\n\nThe package was created?\nIs the binary executable?\n'
                ]))
            if len(cmd) > 1:
                # Open selection for executables
                try:
                    from PySide import QtGui
                    item, result = QtGui.QInputDialog.getItem(
                        None, ' '.join(
                            ['Multiple executables', n.type, 'in', n.package]),
                        'Select an executable', cmd, 0, False)
                    if result:
                        #open the selected screen
                        cmd_type = item
                    else:
                        return
                except:
                    raise StartException(
                        'Multiple executables with same name in package found!'
                    )
            else:
                cmd_type = cmd[0]
            # determine the current working path, Default: the package of the node
            cwd = nm.get_ros_home()
            if not (n.cwd is None):
                if n.cwd == 'ROS_HOME':
                    cwd = nm.get_ros_home()
                elif n.cwd == 'node':
                    cwd = os.path.dirname(cmd_type)
#      else:
#        cwd = LaunchConfig.packageName(os.path.dirname(cmd_type))
            cls._prepareROSMaster(masteruri)
            node_cmd = [
                nm.RESPAWN_SCRIPT if n.respawn else '', prefix, cmd_type
            ]
            cmd_args = [nm.screen().getSceenCmd(node)]
            cmd_args[len(cmd_args):] = node_cmd
            cmd_args.append(str(n.args))
            cmd_args[len(cmd_args):] = args
            rospy.loginfo("RUN: %s", ' '.join(cmd_args))
            if not masteruri is None:
                new_env = dict(os.environ)
                new_env['ROS_MASTER_URI'] = masteruri
                ps = subprocess.Popen(shlex.split(str(' '.join(cmd_args))),
                                      cwd=cwd,
                                      env=new_env)
            else:
                ps = subprocess.Popen(shlex.split(str(' '.join(cmd_args))),
                                      cwd=cwd)
            # wait for process to avoid 'defunct' processes
            thread = threading.Thread(target=ps.wait)
            thread.setDaemon(True)
            thread.start()
        else:
            #'print "RUN REMOTE", node, time.time()
            # start remote
            if launch_config.PackageName is None:
                raise StartException(''.join(
                    ["Can't run remote without a valid package name!"]))
            # thus the prefix parameters while the transfer are not separated
            if prefix:
                prefix = ''.join(['"', prefix, '"'])
            # setup environment
            env_command = ''
            if env_loader:
                rospy.logwarn(
                    "env_loader in machine tag currently not supported")
                raise StartException(
                    "env_loader in machine tag currently not supported")
            if env:
                env_command = "env " + ' '.join(
                    ["%s=%s" % (k, v) for (k, v) in env])

            startcmd = [
                env_command, nm.STARTER_SCRIPT, '--package',
                str(n.package), '--node_type',
                str(n.type), '--node_name',
                str(node), '--node_respawn true' if n.respawn else ''
            ]
            if not masteruri is None:
                startcmd.append('--masteruri')
                startcmd.append(masteruri)
            if prefix:
                startcmd[len(startcmd):] = ['--prefix', prefix]

            #rename the absolute paths in the args of the node
            node_args = []
            try:
                for a in n.args.split():
                    a_value, is_abs_path, found, package = cls._resolve_abs_paths(
                        a, host)
                    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", host,
                              str(' '.join(startcmd)))
                #'print "RUN CALL", node, time.time()
                output, error, ok = nm.ssh().ssh_exec(host, startcmd, user, pw,
                                                      auto_pw_request)
                #'print "RUN CALLOK", node, time.time()
            except nm.AuthenticationRequest as e:
                raise nm.InteractionNeededError(
                    e, cls.runNode, (node, launch_config, force2host,
                                     masteruri, auto_pw_request))

            if ok:
                if error:
                    rospy.logwarn("ERROR while start '%s': %s", node, error)
                    raise StartException(
                        str(''.join(
                            ['The host "', host, '" reports:\n', error])))
                if output:
                    rospy.loginfo("STDOUT while start '%s': %s", node, output)
            # inform about absolute paths in parameter value
            if len(abs_paths) > 0:
                rospy.loginfo(
                    "Absolute paths found while start:\n%s",
                    str('\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(
                    str('\n'.join([
                        'Some absolute paths are not renamed because following packages are not found on remote host:',
                        packages
                    ])))
Ejemplo n.º 16
0
    def runNodeWithoutConfig(cls,
                             host,
                             package,
                             type,
                             name,
                             args=[],
                             masteruri=None,
                             auto_pw_request=True,
                             user=None,
                             pw=None):
        '''
    Start a node with using a launch configuration.
    @param host: the host or ip to run the node
    @type host: C{str} 
    @param package: the ROS package containing the binary
    @type package: C{str} 
    @param type: the binary of the node to execute
    @type type: C{str} 
    @param name: the ROS name of the node (with name space)
    @type name: C{str} 
    @param args: the list with arguments passed to the binary
    @type args: C{[str, ...]} 
    @raise Exception: on errors while resolving host
    @see: L{node_manager_fkie.is_local()}
    '''
        # create the name with namespace
        args2 = list(args)
        fullname = roslib.names.ns_join(roslib.names.SEP, name)
        for a in args:
            if a.startswith('__ns:='):
                fullname = roslib.names.ns_join(a.replace('__ns:=', ''), name)
        args2.append(''.join(['__name:=', name]))
        # run on local host
        if nm.is_local(host):
            try:
                cmd = roslib.packages.find_node(package, type)
            except roslib.packages.ROSPkgException as e:
                # multiple nodes, invalid package
                raise StartException(str(e))
            # handle different result types str or array of string
            import types
            if isinstance(cmd, types.StringTypes):
                cmd = [cmd]
            cmd_type = ''
            if cmd is None or len(cmd) == 0:
                raise StartException(' '.join(
                    [type, 'in package [', package, '] not found!']))
            if len(cmd) > 1:
                # Open selection for executables
                #        try:
                #          from PySide import QtGui
                #          item, result = QtGui.QInputDialog.getItem(None, ' '.join(['Multiple executables', type, 'in', package]),
                #                                            'Select an executable',
                #                                            cmd, 0, False)
                #          if result:
                #            #open the selected screen
                #            cmd_type = item
                #          else:
                #            return
                #        except:
                err = [
                    ''.join([
                        'Multiple executables with same name in package [',
                        package, ']  found:'
                    ])
                ]
                err.extend(cmd)
                raise StartException('\n'.join(err))
            else:
                cmd_type = cmd[0]
            cmd_str = str(' '.join(
                [nm.screen().getSceenCmd(fullname), cmd_type,
                 ' '.join(args2)]))
            rospy.loginfo("Run without config: %s", cmd_str)
            ps = None
            if not masteruri is None:
                cls._prepareROSMaster(masteruri)
                new_env = dict(os.environ)
                new_env['ROS_MASTER_URI'] = masteruri
                ps = subprocess.Popen(shlex.split(cmd_str), env=new_env)
            else:
                ps = subprocess.Popen(shlex.split(cmd_str))
            # wait for process to avoid 'defunct' processes
            thread = threading.Thread(target=ps.wait)
            thread.setDaemon(True)
            thread.start()
        else:
            # run on a remote machine
            startcmd = [
                nm.STARTER_SCRIPT, '--package',
                str(package), '--node_type',
                str(type), '--node_name',
                str(fullname)
            ]
            startcmd[len(startcmd):] = args2
            if not masteruri is None:
                startcmd.append('--masteruri')
                startcmd.append(masteruri)
            rospy.loginfo("Run remote on %s: %s", host, ' '.join(startcmd))
            try:
                output, error, ok = nm.ssh().ssh_exec(host, startcmd, user, pw,
                                                      auto_pw_request)
                if ok:
                    if error:
                        rospy.logwarn("ERROR while start '%s': %s", name,
                                      error)
                        raise StartException(''.join(
                            ['The host "', host, '" reports:\n', error]))

    #          from PySide import QtGui
    #          QtGui.QMessageBox.warning(None, 'Error while remote start %s'%str(name),
    #                                      str(''.join(['The host "', host, '" reports:\n', error])),
    #                                      QtGui.QMessageBox.Ok)
                    if output:
                        rospy.logdebug("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, package, type, name, args, masteruri,
                     auto_pw_request))