def killScreens(cls, host, node, user=None, parent=None): ''' Searches for the screen associated with the given node and kill this screens. @param host: the host name or ip where the screen is running @type host: C{str} @param node: the name of the node those screen output to show @type node: C{str} @param parent: the parent widget to show a message box, if a user input is required. @type parent: L{PySide.QtGui.QWidget} ''' if node is None or len(node) == 0: return False # get the available screens screens = cls.getActiveScreens(host, cls.createSessionName(node), user=user) #user=user, pwd=pwd if screens: from PySide import QtGui result = QtGui.QMessageBox.question(parent, "Kill SCREENs?", '\n'.join(screens), QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel, QtGui.QMessageBox.Ok) if result & QtGui.QMessageBox.Ok: for s in screens: pid, sep, name = s.partition('.') if pid: try: nm.starter().kill(host, int(pid)) except: import traceback rospy.logwarn("Error while kill screen (PID: %s) on host '%s': %s", str(pid), str(host), str(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: nm.ssh().ssh_exec(host, [cls.SCREEN, '-wipe'])
def openLog(cls, nodename, host, user=None): ''' Opens the log file associated with the given node in a new terminal. @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 @type host: C{str} @return: C{True}, if a log file was found @rtype: C{bool} @raise Exception: on errors while resolving host @see: L{node_manager_fkie.is_local()} ''' rospy.loginfo("show log for '%s' on '%s'", str(nodename), str(host)) title_opt = 'LOG %s on %s'%(nodename, host) if nm.is_local(host): found = False screenLog = nm.screen().getScreenLogFile(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), id="Open log", description="Open log for '%s' on '%s'"%(str(nodename), str(host))) found = True #open roslog file roslog = nm.screen().getROSLogFile(nodename) if os.path.isfile(roslog): 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), id="Open log", description="Open log for '%s' on '%s'"%(str(nodename), str(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) 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 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))
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))
def _on_display_anchorClicked(self, url, user=None, pw=None): try: ok = False if self.show_only_rate: self.ssh_input_file, self.ssh_output_file, self.ssh_error_file, ok = nm.ssh().ssh_exec(url.host(), ['rostopic hz %s'%(self.topic)], user, pw, auto_pw_request=True, get_pty=True) self.status_label.setText('connected to %s over SSH'%url.host()) else: self.combobox_displ_hz.setEnabled(False) nostr = '--nostr' if self.no_str_checkbox.isChecked() else '' noarr = '--noarr' if self.no_arr_checkbox.isChecked() else '' self.ssh_input_file, self.ssh_output_file, self.ssh_error_file, ok = nm.ssh().ssh_exec(url.host(), ['rostopic echo %s %s %s'%(nostr, noarr, self.topic)], user, pw, auto_pw_request=True, get_pty=True) if ok: self.display.clear() target = self._read_output_hz if self.show_only_rate else self._read_output thread = threading.Thread(target=target, args=((self.ssh_output_file,))) thread.setDaemon(True) thread.start() thread = threading.Thread(target=self._read_error, args=((self.ssh_error_file,))) thread.setDaemon(True) thread.start() elif self.ssh_output_file: self.ssh_output_file.close() self.ssh_error_file.close() except Exception as e: self._append_error_text('%s\n'%e)
def openLog(cls, nodename, host): ''' Opens the log file associated with the given node in a new terminal. @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 @type host: C{str} @return: C{True}, if a log file was found @rtype: C{bool} @raise Exception: on errors while resolving host @see: L{node_manager_fkie.is_local()} ''' title_opt = ' '.join(['"LOG', nodename, 'on', host, '"']) if nm.is_local(host): found = False screenLog = nm.screen().getScreenLogFile(node=nodename) if os.path.isfile(screenLog): cmd = nm.terminal_cmd([nm.LESS, screenLog], title_opt) rospy.loginfo("open log: %s", cmd) subprocess.Popen(shlex.split(cmd)) found = True #open roslog file roslog = nm.screen().getROSLogFile(nodename) if os.path.isfile(roslog): title_opt = title_opt.replace('LOG', 'ROSLOG') cmd = nm.terminal_cmd([nm.LESS, roslog], title_opt) rospy.loginfo("open ROS log: %s", cmd) subprocess.Popen(shlex.split(cmd)) found = True return found else: nm.ssh().ssh_x11_exec(host, [nm.STARTER_SCRIPT, '--show_screen_log', nodename], title_opt) nm.ssh().ssh_x11_exec(host, [nm.STARTER_SCRIPT, '--show_ros_log', nodename], title_opt.replace('LOG', 'ROSLOG')) return False
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: from node_manager_fkie.detailed_msg_box import MessageBox result = MessageBox.question(None, "Kill SCREENs?", '\n'.join(screens), buttons=MessageBox.Ok | MessageBox.Cancel) if result == MessageBox.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", utf8(pid), utf8(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))
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))
def openLog(cls, nodename, host): ''' Opens the log file associated with the given node in a new terminal. @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 @type host: C{str} @return: C{True}, if a log file was found @rtype: C{bool} @raise Exception: on errors while resolving host @see: L{node_manager_fkie.is_local()} ''' rospy.loginfo("show log for '%s' on '%s'", str(nodename), str(host)) title_opt = ' '.join(['"LOG', nodename, 'on', host, '"']) if nm.is_local(host): found = False screenLog = nm.screen().getScreenLogFile(node=nodename) if os.path.isfile(screenLog): cmd = nm.terminal_cmd([nm.LESS, screenLog], title_opt) rospy.loginfo("open log: %s", cmd) ps = subprocess.Popen(shlex.split(cmd)) # wait for process to avoid 'defunct' processes thread = threading.Thread(target=ps.wait) thread.setDaemon(True) thread.start() found = True #open roslog file roslog = nm.screen().getROSLogFile(nodename) if os.path.isfile(roslog): title_opt = title_opt.replace('LOG', 'ROSLOG') cmd = nm.terminal_cmd([nm.LESS, roslog], title_opt) rospy.loginfo("open ROS log: %s", cmd) ps = subprocess.Popen(shlex.split(cmd)) # wait for process to avoid 'defunct' processes thread = threading.Thread(target=ps.wait) thread.setDaemon(True) thread.start() found = True return found else: ps = nm.ssh().ssh_x11_exec( host, [nm.STARTER_SCRIPT, '--show_screen_log', nodename], title_opt) # wait for process to avoid 'defunct' processes thread = threading.Thread(target=ps.wait) thread.setDaemon(True) thread.start() ps = nm.ssh().ssh_x11_exec( host, [nm.STARTER_SCRIPT, '--show_ros_log', nodename], title_opt.replace('LOG', 'ROSLOG')) # wait for process to avoid 'defunct' processes thread = threading.Thread(target=ps.wait) thread.setDaemon(True) thread.start() return False
def openLog(cls, nodename, host, user=None): ''' Opens the log file associated with the given node in a new terminal. @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 @type host: C{str} @return: C{True}, if a log file was found @rtype: C{bool} @raise Exception: on errors while resolving host @see: L{node_manager_fkie.is_local()} ''' rospy.loginfo("show log for '%s' on '%s'", str(nodename), str(host)) title_opt = ' '.join(['"LOG', nodename, 'on', host, '"']) if nm.is_local(host): found = False screenLog = nm.screen().getScreenLogFile(node=nodename) if os.path.isfile(screenLog): cmd = nm.terminal_cmd([nm.LESS, screenLog], title_opt) rospy.loginfo("open log: %s", cmd) ps = subprocess.Popen(shlex.split(cmd)) # wait for process to avoid 'defunct' processes thread = threading.Thread(target=ps.wait) thread.setDaemon(True) thread.start() found = True #open roslog file roslog = nm.screen().getROSLogFile(nodename) if os.path.isfile(roslog): title_opt = title_opt.replace('LOG', 'ROSLOG') cmd = nm.terminal_cmd([nm.LESS, roslog], title_opt) rospy.loginfo("open ROS log: %s", cmd) ps = subprocess.Popen(shlex.split(cmd)) # wait for process to avoid 'defunct' processes thread = threading.Thread(target=ps.wait) thread.setDaemon(True) thread.start() found = True return found else: ps = nm.ssh().ssh_x11_exec(host, [nm.STARTER_SCRIPT, '--show_screen_log', nodename], title_opt, user) # wait for process to avoid 'defunct' processes thread = threading.Thread(target=ps.wait) thread.setDaemon(True) thread.start() ps = nm.ssh().ssh_x11_exec(host, [nm.STARTER_SCRIPT, '--show_ros_log', nodename], title_opt.replace('LOG', 'ROSLOG'), user) # wait for process to avoid 'defunct' processes thread = threading.Thread(target=ps.wait) thread.setDaemon(True) thread.start() return False
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))
def openLog(cls, nodename, host, user=None): ''' Opens the log file associated with the given node in a new terminal. @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 @type host: C{str} @return: C{True}, if a log file was found @rtype: C{bool} @raise Exception: on errors while resolving host @see: L{node_manager_fkie.is_local()} ''' rospy.loginfo("show log for '%s' on '%s'", str(nodename), str(host)) title_opt = 'LOG %s on %s' % (nodename, host) if nm.is_local(host): found = False screenLog = nm.screen().getScreenLogFile(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), id="Open log", description="Open log for '%s' on '%s'" % (str(nodename), str(host))) found = True #open roslog file roslog = nm.screen().getROSLogFile(nodename) if os.path.isfile(roslog): 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), id="Open log", description="Open log for '%s' on '%s'" % (str(nodename), str(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) 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 _resolve_abs_paths(cls, value, host, user, pw, auto_pw_request): ''' 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 isinstance(value, types.StringTypes) 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, ''
def getActiveScreens(cls, host, session='', 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()} ''' output = None result = [] if nm.is_local(host): out, out_err = cls.getLocalOutput([cls.SCREEN, '-ls']) output = out else: (stdin, stdout, stderr), ok = nm.ssh().ssh_exec(host, [cls.SCREEN, ' -ls']) if ok: stdin.close() # error = stderr.read() output = stdout.read() if not (output is None): splits = output.split() for i in splits: if i.count('.') > 0 and i.endswith(session): result.append(i) return result
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))
def _resolve_abs_paths(cls, value, host): ''' 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 isinstance(value, types.StringTypes) and value.startswith('/') and ( os.path.isfile(value) or os.path.isdir(value)): if nm.is_local(host): return value, True, True, '' else: # print "ABS PATH:", value, os.path.dirname(value) dir = os.path.dirname(value) if os.path.isfile( value) else value package, package_path = LaunchConfig.packageName(dir) if package: output, error, ok = nm.ssh().ssh_exec( host, ['rospack', 'find', package]) if ok: if output: # print " RESOLVED:", output # print " PACK_PATH:", package_path value.replace(package_path, output) # print " RENAMED:", value.replace(package_path, output.strip()) 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, ''
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()} ''' output = None result = [] if nm.is_local(host): output = cls.getLocalOutput([cls.SCREEN, '-ls']) else: _, stdout, _, _ = nm.ssh().ssh_exec(host, [cls.SCREEN, ' -ls'], user, pwd, auto_pw_request, close_stdin=True, close_stderr=True) output = stdout.read() stdout.close() if output: splits = output.split() for i in splits: if i.count('.') > 0 and i.endswith(session) and i.find('._') >= 0: result.append(i) return result
def openScreenTerminal(cls, host, screen_name, nodename, user=None): ''' Open the screen output in a new terminal. @param host: the host name or ip where the screen is running. @type host: C{str} @param screen_name: the name of the screen to show @type screen_name: C{str} @param nodename: the name of the node is used for the title of the terminal @type nodename: C{str} @raise Exception: on errors while resolving host @see: L{node_manager_fkie.is_local()} ''' #create a title of the terminal # pid, session_name = cls.splitSessionName(screen_name) title_opt = 'SCREEN %s on %s' % (nodename, host) if nm.is_local(host): cmd = nm.settings().terminal_cmd([cls.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: ps = nm.ssh().ssh_x11_exec(host, [cls.SCREEN, '-x', screen_name], title_opt, user) rospy.loginfo("Open remote screen terminal: %s", ps)
def kill(self, host, pid): ''' 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()} ''' if nm.is_local(host): import signal os.kill(pid, signal.SIGKILL) rospy.loginfo("kill: %s", str(pid)) else: # kill on a remote machine cmd = ['kill -9', str(pid)] rospy.loginfo("kill remote: %s", ' '.join(cmd)) (stdin, stdout, stderr), ok = nm.ssh().ssh_exec(host, cmd) if ok: stdin.close() error = stderr.read() if error: rospy.logwarn("ERROR while kill %s: %s", str(pid), error) raise nm.StartException( str(''.join( ['The host "', host, '" reports:\n', error]))) output = stdout.read() if output: rospy.logdebug("STDOUT while kill %s: %s", str(pid), output)
def _kill_wo(self, host, pid, auto_pw_request=False, user=None, pw=None): rospy.loginfo("kill %s on %s", str(pid), host) if nm.is_local(host): os.kill(pid, signal.SIGKILL) rospy.loginfo("kill: %s", str(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", str(pid), error) raise StartException( str(''.join( ['The host "', host, '" reports:\n', error]))) if output: rospy.logdebug("STDOUT while kill %s on %s: %s", str(pid), host, output)
def deleteLog(cls, nodename, host): ''' 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()} ''' 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: (stdin, stdout, stderr), ok = nm.ssh().ssh_exec( host, [nm.STARTER_SCRIPT, '--delete_logs', nodename]) if ok: stdin.close()
def openScreenTerminal(cls, host, screen_name, nodename, user=None): ''' Open the screen output in a new terminal. @param host: the host name or ip where the screen is running. @type host: C{str} @param screen_name: the name of the screen to show @type screen_name: C{str} @param nodename: the name of the node is used for the title of the terminal @type nodename: C{str} @raise Exception: on errors while resolving host @see: L{node_manager_fkie.is_local()} ''' #create a title of the terminal # pid, session_name = cls.splitSessionName(screen_name) title_opt = ' '.join(['"SCREEN', nodename, 'on', host, '"']) if nm.is_local(host): cmd = nm.terminal_cmd([cls.SCREEN, '-x', screen_name], title_opt) rospy.loginfo("Open screen terminal: %s", cmd) ps = subprocess.Popen(shlex.split(cmd)) # wait for process to avoid 'defunct' processes thread = threading.Thread(target=ps.wait) thread.setDaemon(True) thread.start() else: ps = nm.ssh().ssh_x11_exec(host, [cls.SCREEN, '-x', screen_name], title_opt) rospy.loginfo("Open remote screen terminal: %s", ps) # wait for process to avoid 'defunct' processes thread = threading.Thread(target=ps.wait) thread.setDaemon(True) thread.start()
def _on_request_interact(self, ident, descr, req): ''' If the interaction of the user is needed a message dialog must be exceuted in the main Qt thread. The requests are done by different request exceptinos. These are handled by this method. ''' if isinstance(req.request, nm.AuthenticationRequest): res, user, pw = nm.ssh()._requestPW(req.request.user, req.request.host) if not res: self._on_progress_canceled() return pt = ProgressThread(ident, descr, req.method, (req.args+(user, pw))) pt.finished_signal.connect(self._progress_thread_finished) pt.error_signal.connect(self._progress_thread_error) pt.request_interact_signal.connect(self._on_request_interact) pt.start() elif isinstance(req.request, nm.ScreenSelectionRequest): from select_dialog import SelectDialog items, _ = SelectDialog.getValue('Show screen', '', req.request.choices.keys(), False) if not items: self._progress_thread_finished(ident) return res = [req.request.choices[i] for i in items] pt = ProgressThread(ident, descr, req.method, (req.args+(res,))) pt.finished_signal.connect(self._progress_thread_finished) pt.error_signal.connect(self._progress_thread_error) pt.request_interact_signal.connect(self._on_request_interact) pt.start() elif isinstance(req.request, nm.BinarySelectionRequest): from select_dialog import SelectDialog items, _ = SelectDialog.getValue('Multiple executables', '', req.request.choices, True) if not items: self._progress_thread_finished(ident) return res = items[0] pt = ProgressThread(ident, descr, req.method, (req.args+(res,))) pt.finished_signal.connect(self._progress_thread_finished) pt.error_signal.connect(self._progress_thread_error) pt.request_interact_signal.connect(self._on_request_interact) pt.start() elif isinstance(req.request, nm.LaunchArgsSelectionRequest): from parameter_dialog import ParameterDialog inputDia = ParameterDialog(req.request.args_dict) inputDia.setFilterVisible(False) inputDia.setWindowTitle(''.join(['Enter the argv for ', req.request.launchfile])) if inputDia.exec_(): params = inputDia.getKeywords() argv = [] for p,v in params.items(): if v: argv.append(''.join([p, ':=', v])) res = argv pt = ProgressThread(ident, descr, req.method, (req.args+(argv,))) pt.finished_signal.connect(self._progress_thread_finished) pt.error_signal.connect(self._progress_thread_error) pt.request_interact_signal.connect(self._on_request_interact) pt.start() else: self._progress_thread_finished(ident) return
def openScreenTerminal(cls, host, screen_name, nodename, user=None): ''' Open the screen output in a new terminal. @param host: the host name or ip where the screen is running. @type host: C{str} @param screen_name: the name of the screen to show @type screen_name: C{str} @param nodename: the name of the node is used for the title of the terminal @type nodename: C{str} @raise Exception: on errors while resolving host @see: L{node_manager_fkie.is_local()} ''' #create a title of the terminal # pid, session_name = cls.splitSessionName(screen_name) title_opt = 'SCREEN %s on %s' % (nodename, host) if nm.is_local(host): cmd = nm.settings().terminal_cmd([cls.SCREEN, '-x', screen_name], title_opt) rospy.loginfo("Open screen terminal: %s", cmd) ps = subprocess.Popen(shlex.split(cmd)) # wait for process to avoid 'defunct' processes thread = threading.Thread(target=ps.wait) thread.setDaemon(True) thread.start() else: ps = nm.ssh().ssh_x11_exec(host, [cls.SCREEN, '-x', screen_name], title_opt, user) rospy.loginfo("Open remote screen terminal: %s", ps) # wait for process to avoid 'defunct' processes thread = threading.Thread(target=ps.wait) thread.setDaemon(True) thread.start()
def _resolve_abs_paths(cls, value, host): ''' 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 isinstance(value, types.StringTypes) and value.startswith('/') and (os.path.isfile(value) or os.path.isdir(value)): if nm.is_local(host): return value, True, True, '' else: # print "ABS PATH:", value, os.path.dirname(value) dir = os.path.dirname(value) if os.path.isfile(value) else value package, package_path = LaunchConfig.packageName(dir) if package: (stdin, stdout, stderr), ok = nm.ssh().ssh_exec(host, ['rospack', 'find', package]) if ok: stdin.close() output = stdout.read() if output: # print " RESOLVED:", output # print " PACK_PATH:", package_path value.replace(package_path, output) # print " RENAMED:", value.replace(package_path, output.strip()) 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, ''
def kill(self, host, pid): ''' 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()} ''' if nm.is_local(host): import signal os.kill(pid, signal.SIGKILL) rospy.loginfo("kill: %s", str(pid)) else: # kill on a remote machine cmd = ['kill -9', str(pid)] rospy.loginfo("kill remote on %s: %s", host, ' '.join(cmd)) (stdin, stdout, stderr), ok = nm.ssh().ssh_exec(host, cmd) if ok: stdin.close() error = stderr.read() if error: rospy.logwarn("ERROR while kill %s: %s", str(pid), error) raise nm.StartException(str(''.join(['The host "', host, '" reports:\n', error]))) output = stdout.read() if output: rospy.logdebug("STDOUT while kill %s on %s: %s", str(pid), host, output)
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_exec(host, cmd, 'Shutdown %s' % host, user)
def _rosclean_wo(self, host, auto_pw_request=False, user=None, pw=None): 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.loginfo("rosclean %s", host) # kill on a remote machine cmd = ['rosclean purge -y'] _ = nm.ssh().ssh_x11_exec(host, cmd, 'rosclean purge on %s' % host, 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 _on_display_anchorClicked(self, url, user=None, pw=None): try: ok = False if self.show_only_rate: self.ssh_input_file, self.ssh_output_file, self.ssh_error_file, ok = nm.ssh( ).ssh_exec(url.host(), ['rostopic hz %s' % (self.topic)], user, pw, auto_pw_request=True, get_pty=True) self.statusLabel.setText('connected to %s over SSH' % url.host()) else: nostr = '--nostr' if not self.showStringsCheckBox.isChecked( ) else '' noarr = '--noarr' if not self.showArraysCheckBox.isChecked( ) else '' self.ssh_input_file, self.ssh_output_file, self.ssh_error_file, ok = nm.ssh( ).ssh_exec( url.host(), ['rostopic echo %s %s %s' % (nostr, noarr, self.topic)], user, pw, auto_pw_request=True, get_pty=True) if ok: self.display.clear() target = self._read_output_hz if self.show_only_rate else self._read_output thread = threading.Thread(target=target, args=((self.ssh_output_file, ))) thread.setDaemon(True) thread.start() thread = threading.Thread(target=self._read_error, args=((self.ssh_error_file, ))) thread.setDaemon(True) thread.start() elif self.ssh_output_file: self.ssh_output_file.close() self.ssh_error_file.close() except Exception as e: self._append_error_text('%s\n' % e)
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))
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, path, auto_pw_request))
def _kill_wo(self, host, pid, auto_pw_request=False, user=None, pw=None): rospy.loginfo("kill %s on %s", str(pid), host) if nm.is_local(host): os.kill(pid, signal.SIGKILL) rospy.loginfo("kill: %s", str(pid)) else: # kill on a remote machine cmd = ['kill -9', str(pid)] output, error, ok = nm.ssh().ssh_exec(host, cmd, user, pw, False) if ok: if error: rospy.logwarn("ERROR while kill %s: %s", str(pid), error) raise StartException(str(''.join(['The host "', host, '" reports:\n', error]))) if output: rospy.logdebug("STDOUT while kill %s on %s: %s", str(pid), host, output)
def transfer_files(cls, host, file, 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(file)) if not pkg_name is None: # get the subpath of the file subfile_path = file.replace(pkg_path, '') # get the path of the package on the remote machine try: output = '' error = '' ok = True if CACHED_PKG_PATH.has_key(host) and CACHED_PKG_PATH[host].has_key(pkg_name): output = CACHED_PKG_PATH[host][pkg_name] else: if not CACHED_PKG_PATH.has_key(host): CACHED_PKG_PATH[host] = dict() output, error, ok = nm.ssh().ssh_exec(host, [nm.STARTER_SCRIPT, '--package', pkg_name], user, pw, auto_pw_request) if ok: if error: rospy.logwarn("ERROR while transfer %s to %s: %s", file, 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, file, 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, file, auto_pw_request))
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))
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 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)
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(utf8(''.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)
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)
def ntpdate(cls, host, cmd, user=None, pw=None): ''' Opens the log file associated with the given node in a new terminal. @param host: the host name or ip where the log file are @type host: C{str} @param cmd: command to set the time @type cmd: C{str} @return: C{True}, if a log file was found @rtype: C{bool} @raise Exception: on errors while resolving host @see: L{node_manager_fkie.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 openScreenTerminal(cls, host, screen_name, nodename, user=None): ''' Open the screen output in a new terminal. @param host: the host name or ip where the screen is running. @type host: C{str} @param screen_name: the name of the screen to show @type screen_name: C{str} @param nodename: the name of the node is used for the title of the terminal @type nodename: C{str} @raise Exception: on errors while resolving host @see: L{node_manager_fkie.is_local()} ''' #create a title of the terminal # pid, session_name = cls.splitSessionName(screen_name) title_opt = 'SCREEN %s on %s'%(nodename, host) if nm.is_local(host): cmd = nm.settings().terminal_cmd([cls.SCREEN, '-x', screen_name], title_opt) rospy.loginfo("Open screen terminal: %s", cmd) SupervisedPopen(shlex.split(cmd), id=title_opt, description="Open screen terminal: %s"%title_opt) else: ps = nm.ssh().ssh_x11_exec(host, [cls.SCREEN, '-x', screen_name], title_opt, user) rospy.loginfo("Open remote screen terminal: %s", ps)
def ntpdate(cls, host, cmd, user=None, pw=None): ''' Opens the log file associated with the given node in a new terminal. @param host: the host name or ip where the log file are @type host: C{str} @param cmd: command to set the time @type cmd: C{str} @return: C{True}, if a log file was found @rtype: C{bool} @raise Exception: on errors while resolving host @see: L{node_manager_fkie.is_local()} ''' mesg = "synchronize time on '%s' using '%s'" % (str(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 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, sep, name = 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), str(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']) except nm.AuthenticationRequest as e: raise nm.InteractionNeededError(e, cls.killScreens, (node, host, auto_ok_request))
def _on_request_interact(self, id, descr, req): if isinstance(req.request, nm.AuthenticationRequest): res, user, pw = nm.ssh()._requestPW(req.request.user, req.request.host) if not res: self._on_progress_canceled() return pt = ProgressThread(id, descr, req.method, (req.args+(user, pw))) pt.finished_signal.connect(self._progress_thread_finished) pt.error_signal.connect(self._progress_thread_error) pt.request_interact_signal.connect(self._on_request_interact) pt.start() elif isinstance(req.request, nm.ScreenSelectionRequest): from select_dialog import SelectDialog items = SelectDialog.getValue('Show screen', req.request.choices.keys(), False) if not items: self._progress_thread_finished(id) return res = [req.request.choices[i] for i in items] pt = ProgressThread(id, descr, req.method, (req.args+(res,))) pt.finished_signal.connect(self._progress_thread_finished) pt.error_signal.connect(self._progress_thread_error) pt.request_interact_signal.connect(self._on_request_interact) pt.start()
def deleteLog(cls, nodename, host): ''' 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()} ''' 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: (stdin, stdout, stderr), ok = nm.ssh().ssh_exec(host, [nm.STARTER_SCRIPT, '--delete_logs', nodename]) if ok: stdin.close()
def runNode(cls, node, launch_config, force2host=None, masteruri=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()} ''' 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) 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 nm.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 nm.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: # 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 nm.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 = [] 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))) (stdin, stdout, stderr), ok = nm.ssh().ssh_exec(host, startcmd) if ok: stdin.close() # stderr.close() # stdout.close() error = stderr.read() if error: rospy.logwarn("ERROR while start '%s': %s", node, error) raise nm.StartException(str(''.join(['The host "', host, '" reports:\n', error]))) output = stdout.read() 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 nm.StartException(str('\n'.join(['Some absolute paths are not renamed because following packages are not found on remote host:', packages])))
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))
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))
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 ])))
def _on_request_interact(self, ident, descr, req): ''' If the interaction of the user is needed a message dialog must be exceuted in the main Qt thread. The requests are done by different request exceptinos. These are handled by this method. ''' if isinstance(req.request, nm.AuthenticationRequest): res, user, pw = nm.ssh()._requestPW(req.request.user, req.request.host) if not res: self._on_progress_canceled() return if req.args and isinstance(req.args[0], nm.AdvRunCfg): req.args[0].user = user req.args[0].pw = pw else: req.args = req.args + (user, pw) pt = ProgressThread(ident, descr, req.method, (req.args)) pt.finished_signal.connect(self._progress_thread_finished) pt.error_signal.connect(self._progress_thread_error) pt.request_interact_signal.connect(self._on_request_interact) pt.start() elif isinstance(req.request, nm.ScreenSelectionRequest): from node_manager_fkie.select_dialog import SelectDialog items, _ = SelectDialog.getValue('Show screen', '', req.request.choices.keys(), False) if not items: self._progress_thread_finished(ident) return res = [req.request.choices[i] for i in items] pt = ProgressThread(ident, descr, req.method, (req.args + (res, ))) pt.finished_signal.connect(self._progress_thread_finished) pt.error_signal.connect(self._progress_thread_error) pt.request_interact_signal.connect(self._on_request_interact) pt.start() elif isinstance(req.request, nm.BinarySelectionRequest): from node_manager_fkie.select_dialog import SelectDialog items, _ = SelectDialog.getValue('Multiple executables', '', req.request.choices, True) if not items: self._progress_thread_finished(ident) return res = items[0] if req.args and isinstance(req.args[0], nm.AdvRunCfg): req.args[0].executable = res else: req.args = req.args + (res, ) pt = ProgressThread(ident, descr, req.method, (req.args)) pt.finished_signal.connect(self._progress_thread_finished) pt.error_signal.connect(self._progress_thread_error) pt.request_interact_signal.connect(self._on_request_interact) pt.start() elif isinstance(req.request, nm.LaunchArgsSelectionRequest): from node_manager_fkie.parameter_dialog import ParameterDialog input_dia = ParameterDialog(req.request.args_dict) input_dia.setFilterVisible(False) input_dia.setWindowTitle('Enter the argv for %s' % req.request.launchfile) if input_dia.exec_(): params = input_dia.getKeywords() argv = [] for prm, val in params.items(): if val: argv.append('%s:=%s' % (prm, val)) res = argv pt = ProgressThread(ident, descr, req.method, (req.args + (argv, ))) pt.finished_signal.connect(self._progress_thread_finished) pt.error_signal.connect(self._progress_thread_error) pt.request_interact_signal.connect(self._on_request_interact) pt.start() else: self._progress_thread_finished(ident) return
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 ])))
def runNode(cls, runcfg): ''' 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: L{node_manager_fkie.is_local()} ''' # 'print "RUN node", node, time.time() n = runcfg.roslaunch_config.getNode(runcfg.node) if n is None: raise StartException(''.join(["Node '", runcfg.node, "' not found!"])) env = list(n.env_args) # set logging options if runcfg.logging is not None: if not runcfg.logging.is_default('console_format'): env.append(('ROSCONSOLE_FORMAT', '%s' % runcfg.logging.console_format)) if n.respawn: # set the respawn environment variables respawn_params = cls._get_respawn_params(rospy.names.ns_join(n.namespace, n.name), runcfg.roslaunch_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 n.launch_prefix is not None else '' if prefix.lower() == 'screen' or prefix.lower().find('screen ') != -1: rospy.loginfo("SCREEN prefix removed before start!") prefix = '' args = ['__ns:=%s' % n.namespace.rstrip(rospy.names.SEP), '__name:=%s' % n.name] if n.cwd is not None: args.append('__cwd:=%s' % n.cwd) # add remaps for remap in n.remap_args: args.append(''.join([remap[0], ':=', remap[1]])) # get host of the node host = runcfg.roslaunch_config.hostname env_loader = '' if n.machine_name: machine = runcfg.roslaunch_config.Roscfg.machines[n.machine_name] if machine.address not in ['localhost', '127.0.0.1']: host = machine.address if runcfg.masteruri is None: runcfg.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 runcfg.force2host is not None: host = runcfg.force2host # set the ROS_MASTER_URI if runcfg.masteruri is None: runcfg.masteruri = masteruri_from_ros() env.append(('ROS_MASTER_URI', runcfg.masteruri)) ros_hostname = NameResolution.get_ros_hostname(runcfg.masteruri) if ros_hostname: env.append(('ROS_HOSTNAME', ros_hostname)) 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) # 'print "RUN prepared", node, time.time() if nm.is_local(host, wait=True): nm.screen().testScreen() if runcfg.executable: cmd_type = runcfg.executable else: try: cmd = roslib.packages.find_node(n.package, n.type) except (Exception, roslib.packages.ROSPkgException) as starterr: # multiple nodes, invalid package raise StartException("Can't find resource: %s" % starterr) # 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("%s in package [%s] not found!\n\nThe package " "was created?\nIs the binary executable?\n" % (n.type, n.package)) if len(cmd) > 1: if runcfg.auto_pw_request: # Open selection for executables, only if the method is called from the main GUI thread try: try: from python_qt_binding.QtGui import QInputDialog except: from python_qt_binding.QtWidgets import QInputDialog item, result = QInputDialog.getItem(None, 'Multiple executables %s in %s' % (n.type, 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, (runcfg,)) 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(runcfg.masteruri) node_cmd = [nm.settings().respawn_script if n.respawn else '', prefix, cmd_type] cmd_args = [nm.screen().getSceenCmd(runcfg.node)] cmd_args[len(cmd_args):] = node_cmd cmd_args.append(utf8(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'] = runcfg.masteruri ros_hostname = NameResolution.get_ros_hostname(runcfg.masteruri) if ros_hostname: new_env['ROS_HOSTNAME'] = ros_hostname # add the namespace environment parameter to handle some cases, # e.g. rqt_cpp plugins if n.namespace: new_env['ROS_NAMESPACE'] = n.namespace # set logging options if runcfg.logging is not None: if not runcfg.logging.is_default('loglevel'): env.append(('ROSCONSOLE_CONFIG_FILE', nm.settings().rosconsole_cfg_file(n.package))) for key, value in env: new_env[key] = value SupervisedPopen(shlex.split(utf8(' '.join(cmd_args))), cwd=cwd, env=new_env, object_id="Run node", description="Run node " "[%s]%s" % (utf8(n.package), utf8(n.type))) nm.filewatcher().add_binary(cmd_type, runcfg.node, runcfg.masteruri, runcfg.roslaunch_config.Filename) else: # 'print "RUN REMOTE", node, time.time() # start remote if runcfg.roslaunch_config.PackageName is None: raise StartException("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, runcfg.user, runcfg.pw, runcfg.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, (runcfg,)) startcmd = [env_command, nm.settings().start_remote_script, '--package', utf8(n.package), '--node_type', utf8(n.type), '--node_name', utf8(runcfg.node), '--node_respawn true' if n.respawn else ''] if runcfg.masteruri is not None: startcmd.append('--masteruri') startcmd.append(runcfg.masteruri) if prefix: startcmd[len(startcmd):] = ['--prefix', prefix] if runcfg.logging is not None: if not runcfg.logging.is_default('loglevel'): startcmd.append('--loglevel') startcmd.append(nm.settings().logging.loglevel) # 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, runcfg.user, runcfg.pw, runcfg.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, utf8(' '.join(startcmd))) # 'print "RUN CALL", node, time.time() _, stdout, stderr, ok = nm.ssh().ssh_exec(host, startcmd, runcfg.user, runcfg.pw, runcfg.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, (runcfg,)) if ok: if error: rospy.logwarn("ERROR while start '%s': %s", runcfg.node, error) raise StartException(utf8(''.join(['The host "', host, '" reports:\n', error]))) if output: rospy.loginfo("STDOUT while start '%s': %s", runcfg.node, 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])))
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, wait=True): 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 # import types if isinstance(cmd, types.StringTypes): cmd = [cmd] cmd_type = '' if cmd is None or len(cmd) == 0: raise StartException('%s in package [%s] not found!' % (binary, package)) if len(cmd) > 1: # Open selection for executables 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 = utf8(' '.join([nm.screen().getSceenCmd(fullname), cmd_type, ' '.join(args2)])) rospy.loginfo("Run without config: %s", cmd_str) 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 ros_hostname = NameResolution.get_ros_hostname(masteruri) if ros_hostname: new_env['ROS_HOSTNAME'] = ros_hostname SupervisedPopen(shlex.split(cmd_str), env=new_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: 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))
def runNodeWithoutConfig(cls, host, package, type, name, args=[]): ''' 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 fullname = ''.join(['/', name]) for a in args: if a.startswith('__ns:='): fullname = ''.join( ['/', a.replace('__ns:=', '').strip('/ '), fullname]) fullname = fullname.replace('//', '/') args2 = list(args) 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 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 nm.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: raise nm.StartException( 'Multiple executables with same name in package found!' ) 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) subprocess.Popen(shlex.split(cmd_str)) 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 rospy.loginfo("Run remote: %s", ' '.join(startcmd)) (stdin, stdout, stderr), ok = nm.ssh().ssh_exec(host, startcmd) if ok: stdin.close() error = stderr.read() if error: rospy.logwarn("ERROR while start '%s': %s", name, 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) output = stdout.read() if output: rospy.logdebug("STDOUT while start '%s': %s", name, output)
def runNode(cls, node, launch_config): ''' 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} @raise StartException: if the screen is not available on host. @raise Exception: on errors while resolving host @see: L{node_manager_fkie.is_local()} ''' 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 '' # thus the parameters while the transfer are not separated if prefix: prefix = ''.join(['"', 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 masteruri = nm.nameres().getUri(host=host) # set the ROS_MASTER_URI if masteruri is None: env.append(('ROS_MASTER_URI', nm.masteruri_from_ros())) # 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)) 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)) cls._load_parameters(masteruri, params, clear_params) 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 nm.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 nm.StartException( 'Multiple executables with same name in package found!' ) else: cmd_type = cmd[0] node_cmd = [prefix, cmd_type] cmd_args = [nm.screen().getSceenCmd(node)] cmd_args[len(cmd_args):] = node_cmd cmd_args.append(n.args) cmd_args[len(cmd_args):] = args rospy.loginfo("RUN: %s", ' '.join(cmd_args)) subprocess.Popen(shlex.split(str(' '.join(cmd_args)))) else: # start remote if launch_config.PackageName is None: raise StartException(''.join( ["Can't run remote without a valid package name!"])) # setup environment env_command = '' if env_loader: rospy.logwarn( "env_loader in machine tag currently not supported") raise nm.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) ] if prefix: startcmd[len(startcmd):] = ['--prefix', prefix] startcmd[len(startcmd):] = n.args startcmd[len(startcmd):] = args rospy.loginfo("Run remote: %s", ' '.join(startcmd)) (stdin, stdout, stderr), ok = nm.ssh().ssh_exec(host, startcmd) if ok: stdin.close() # stderr.close() # stdout.close() error = stderr.read() if error: rospy.logwarn("ERROR while start '%s': %s", node, error) raise nm.StartException( str(''.join( ['The host "', host, '" reports:\n', error]))) output = stdout.read() if output: rospy.logdebug("STDOUT while start '%s': %s", node, output)