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)
Example #2
0
def detect_version(package):
    '''
    Try to detect the current version from git, installed VERSION/DATE files or package.xml
    '''
    global VERSION
    global DATE
    if VERSION != 'unknown':
        return VERSION, DATE
    version = 'unknown'
    date = 'unknown'
    try:
        pkg_path = roslib.packages.get_pkg_dir(package)
        if pkg_path is not None and os.path.isfile("%s/VERSION" % pkg_path):
            try:
                with open("%s/VERSION" % pkg_path) as f:
                    version = f.read()
                    version = version.strip()
                with open("%s/DATE" % pkg_path) as f:
                    datetag = f.read().split()
                    if datetag:
                        date = datetag[0]
            except Exception as err:
                print >> sys.stderr, "version detection error: %s" % err
        elif os.path.isdir("%s/../.git" % pkg_path):
            try:
                os.chdir(pkg_path)
                ps = SupervisedPopen([
                    'git', 'describe', '--tags', '--dirty', '--always',
                    '--abbrev=8'
                ],
                                     stdout=subprocess.PIPE,
                                     object_id='get git version')
                output = ps.stdout.read()
                version = output.strip()
                ps = SupervisedPopen(['git', 'show', '-s', '--format=%ci'],
                                     stdout=subprocess.PIPE,
                                     object_id='get git date')
                output = ps.stdout.read().split()
                if output:
                    date = output[0]
            except Exception as err:
                print >> sys.stderr, "version detection error: %s" % err
        else:
            ppath = roslib.packages.find_resource(package, 'package.xml')
            if ppath:
                doc = dom.parse(ppath[0])
                version_tags = doc.getElementsByTagName("version")
                if version_tags:
                    version = version_tags[0].firstChild.data
                    version = version
                else:
                    print >> sys.stderr, "version detection: no version tag in package.xml found!"
            else:
                print >> sys.stderr, "version detection: package.xml not found!"
    except Exception as err:
        print >> sys.stderr, "version detection error: %s" % err
    VERSION = version
    DATE = date
    return version, date
    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
    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 _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))
 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)
Example #10
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
Example #11
0
 def ssh_x11_exec(self, host, cmd, title=None, user=None):
     '''
     Executes a command on remote host using a terminal with X11 forwarding.
     @todo: establish connection using paramiko SSH library.
     @param host: the host
     @type host: C{str}
     @param cmd: the list with command and arguments
     @type cmd: C{[str,...]}
     @param title: the title of the new opened terminal, if it is None, no new terminal will be created
     @type title: C{str} or C{None}
     @param user: user name
     @return: the result of C{subprocess.Popen(command)}
     @see: U{http://docs.python.org/library/subprocess.html?highlight=subproces#subprocess}
     '''
     with self.mutex:
         try:
             # workaround: use ssh in a terminal with X11 forward
             user = nm.settings().host_user(host) if user is None else user
             if host in self.SSH_AUTH:
                 user = self.SSH_AUTH[host]
             # generate string for SSH command
             ssh_str = ' '.join([
                 '/usr/bin/ssh', '-aqtx', '-oClearAllForwardings=yes',
                 '-oConnectTimeout=5', '-oStrictHostKeyChecking=no',
                 '-oVerifyHostKeyDNS=no', '-oCheckHostIP=no',
                 ''.join([user, '@', host])
             ])
             if title is not None:
                 cmd_str = nm.settings().terminal_cmd(
                     [ssh_str, ' '.join(cmd)], title)
             else:
                 cmd_str = utf8(' '.join([ssh_str, ' '.join(cmd)]))
             rospy.loginfo("REMOTE x11 execute on %s: %s", host, cmd_str)
             return SupervisedPopen(
                 shlex.split(cmd_str),
                 object_id=utf8(title),
                 description="REMOTE x11 execute on %s: %s" %
                 (host, cmd_str))
         except Exception:
             raise
    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
                    })