Esempio n. 1
0
 def summary(self, local=False):
     """
     Get a human-readable string summary of the launch
     @param local bool: if True, only print local nodes
     @return: summary
     @rtype: str
     """
     summary = '\nSUMMARY\n========'
     if self.clear_params:
         summary += '\n\nCLEAR PARAMETERS\n' + '\n'.join(
             [' * %s' % p for p in self.clear_params])
     if self.params:
         summary += '\n\nPARAMETERS\n' + '\n'.join(
             [' * %s' % k for k in self.params])
     if not local:
         summary += '\n\nMACHINES\n' + '\n'.join(
             [' * %s' % k for k in self.machines if k])
     summary += '\n\nNODES\n'
     namespaces = {}
     if local:
         nodes = [n for n in self.nodes if is_machine_local(n.machine)]
     else:
         nodes = self.nodes
     for n in nodes:
         ns = n.namespace
         if ns not in namespaces:
             namespaces[ns] = [n]
         else:
             namespaces[ns].append(n)
     for k, v in namespaces.iteritems():
         summary += '  %s\n' % k + '\n'.join(
             ['    %s' % _summary_name(n) for n in v])
         summary += '\n'
     return summary
Esempio n. 2
0
 def summary(self, local=False):
     """
     Get a human-readable string summary of the launch
     @param local bool: if True, only print local nodes
     @return: summary
     @rtype: str
     """
     summary = '\nSUMMARY\n========'
     if self.clear_params:
         summary += '\n\nCLEAR PARAMETERS\n' + '\n'.join([' * %s'%p for p in self.clear_params])
     if self.params:
         summary += '\n\nPARAMETERS\n' + '\n'.join([' * %s'%k for k in self.params])
     if not local:
         summary += '\n\nMACHINES\n' + '\n'.join([' * %s'%k for k in self.machines if k])
     summary += '\n\nNODES\n'
     namespaces = {}
     if local:
         nodes = [n for n in self.nodes if is_machine_local(n.machine)]
     else:
         nodes = self.nodes
     for n in nodes:
         ns = n.namespace
         if ns not in namespaces:
             namespaces[ns] = [n]
         else:
             namespaces[ns].append(n)
     for k,v in namespaces.iteritems():
         summary += '  %s\n'%k + '\n'.join(['    %s'%_summary_name(n) for n in v])
         summary += '\n'
     return summary
Esempio n. 3
0
    def start_children(self):
        """
        Start the child roslaunch processes
        """
        server_node_uri = self.server.uri
        if not server_node_uri:
            raise RLException("server URI is not initialized")
        
        # TODOXXX: break out table building code into a separate
        # routine so we can unit test it _start_child() should not be
        # determining the process name

        # Build table of unique machines that we are going to launch on
        machines = {}
        for n in self.rosconfig.nodes:
            if not is_machine_local(n.machine):
                machines[n.machine.config_key()] = n.machine

        # Launch child roslaunch processes on remote machines
        counter = 0
        #  - keep a list of procs so we can check for those that failed to launch
        procs = []
        for m in machines:
            p = self._start_child(server_node_uri, machines[m], counter)
            procs.append(p)
            counter += 1
        
        # Wait for all children to call register() callback. The machines can have
        # non-uniform registration timeouts. We consider the failure to occur once
        # one of the machines has failed to meet it's timeout.
        start_t = time.time() 
        while True:
            pending = []
            for p in procs:
                if not p.is_alive():
                    raise RLException("remote roslaunch failed to launch: %s"%p.machine.name)
                elif not p.uri:
                    pending.append(p.machine)
            if not pending:
                break
            # timeout is the minimum of the remaining timeouts of the machines
            timeout_t = start_t + min([m.timeout for m in pending])
            if time.time() > timeout_t:
                break
            time.sleep(0.1)
        if pending:
            raise RLException(
                """The following roslaunch remote processes failed to register: 
%s

If this is a network latency issue, you may wish to consider setting 
  <machine timeout="NUMBER OF SECONDS" ... />
in your launch"""%'\n'.join([" * %s (timeout %ss)"%(m.name, m.timeout) for m in pending]))

        # convert machine dictionary to a list
        self.machine_list = machines.values()
        # save a list of the remote processes
        self.remote_processes = procs
Esempio n. 4
0
    def start_children(self):
        """
        Start the child roslaunch processes
        """
        server_node_uri = self.server.uri
        if not server_node_uri:
            raise RLException("server URI is not initialized")
        
        # TODOXXX: break out table building code into a separate
        # routine so we can unit test it _start_child() should not be
        # determining the process name

        # Build table of unique machines that we are going to launch on
        machines = {}
        for n in self.rosconfig.nodes:
            if not is_machine_local(n.machine):
                machines[n.machine.config_key()] = n.machine

        # Launch child roslaunch processes on remote machines
        counter = 0
        #  - keep a list of procs so we can check for those that failed to launch
        procs = []
        for m in machines:
            p = self._start_child(server_node_uri, machines[m], counter)
            procs.append(p)
            counter += 1
        
        # Wait for all children to call register() callback. The machines can have
        # non-uniform registration timeouts. We consider the failure to occur once
        # one of the machines has failed to meet it's timeout.
        start_t = time.time() 
        while True:
            pending = []
            for p in procs:
                if not p.is_alive():
                    raise RLException("remote roslaunch failed to launch: %s"%p.machine.name)
                elif not p.uri:
                    pending.append(p.machine)
            if not pending:
                break
            # timeout is the minimum of the remaining timeouts of the machines
            timeout_t = start_t + min([m.timeout for m in pending])
            if time.time() > timeout_t:
                break
            time.sleep(0.1)
        if pending:
            raise RLException(
                """The following roslaunch remote processes failed to register: 
%s

If this is a network latency issue, you may wish to consider setting 
  <machine timeout="NUMBER OF SECONDS" ... />
in your launch"""%'\n'.join([" * %s (timeout %ss)"%(m.name, m.timeout) for m in pending]))

        # convert machine dictionary to a list
        self.machine_list = machines.values()
        # save a list of the remote processes
        self.remote_processes = procs
Esempio n. 5
0
    def launch_remote_nodes(self):
        """
        Contact each child to launch remote nodes
        """
        succeeded = []
        failed = []

        # initialize remote_nodes. we use the machine config key as
        # the key for the dictionary so that we can bin the nodes.
        self.remote_nodes = {}
        for m in self.machine_list:
            self.remote_nodes[m.config_key()] = []

        # build list of nodes that will be launched by machine
        nodes = [
            x for x in self.rosconfig.nodes if not is_machine_local(x.machine)
        ]
        for n in nodes:
            self.remote_nodes[n.machine.config_key()].append(n)

        for child in self.remote_processes:
            nodes = self.remote_nodes[child.machine.config_key()]
            body = '\n'.join([n.to_remote_xml() for n in nodes])
            # force utf-8 encoding, #3799
            xml = '<?xml version="1.0" encoding="utf-8"?>\n<launch>\n%s</launch>' % body
            if 0:
                print xml

            api = child.getapi()
            # TODO: timeouts
            try:
                self.logger.debug("sending [%s] XML [\n%s\n]" %
                                  (child.uri, xml))
                code, msg, val = api.launch(xml)
                if code == 1:
                    c_succ, c_fail = val
                    succeeded.extend(c_succ)
                    failed.extend(c_fail)
                else:
                    printerrlog('error launching on [%s, uri %s]: %s' %
                                (child.name, child.uri, msg))
                    self._assume_failed(nodes, failed)
            except socket.error, (errno, msg):
                printerrlog('error launching on [%s, uri %s]: %s' %
                            (child.name, child.uri, str(msg)))
                self._assume_failed(nodes, failed)

            except socket.gaierror, (errno, msg):
                # usually errno == -2. See #815.
                child_host, _ = network.parse_http_host_and_port(child.uri)
                printerrlog(
                    "Unable to contact remote roslaunch at [%s]. This is most likely due to a network misconfiguration with host lookups. Please make sure that you can contact '%s' from this machine"
                    % (child.uri, child_host))
                self._assume_failed(nodes, failed)
Esempio n. 6
0
    def launch_remote_nodes(self):
        """
        Contact each child to launch remote nodes
        """
        succeeded = []
        failed = []
        
        # initialize remote_nodes. we use the machine config key as
        # the key for the dictionary so that we can bin the nodes.
        self.remote_nodes = {}
        for m in self.machine_list:
            self.remote_nodes[m.config_key()] = []
            
        # build list of nodes that will be launched by machine
        nodes = [x for x in self.rosconfig.nodes if not is_machine_local(x.machine)]
        for n in nodes:
            self.remote_nodes[n.machine.config_key()].append(n)
            
        for child in self.remote_processes:
            nodes = self.remote_nodes[child.machine.config_key()]
            body = '\n'.join([n.to_remote_xml() for n in nodes])
            # #3799: force utf-8 encoding 
            xml = '<?xml version="1.0" encoding="utf-8"?>\n<launch>\n%s</launch>'%body 
                
            api = child.getapi()
            # TODO: timeouts
            try:
                self.logger.debug("sending [%s] XML [\n%s\n]"%(child.uri, xml))
                code, msg, val = api.launch(xml)
                if code == 1:
                    c_succ, c_fail = val
                    succeeded.extend(c_succ)
                    failed.extend(c_fail)
                else:
                    printerrlog('error launching on [%s, uri %s]: %s'%(child.name, child.uri, msg))
                    self._assume_failed(nodes, failed)
            except socket.error as e:
                errno, msg = e
                printerrlog('error launching on [%s, uri %s]: %s'%(child.name, child.uri, str(msg)))
                self._assume_failed(nodes, failed)

            except socket.gaierror as e:
                errno, msg = e
                # usually errno == -2. See #815. 
                child_host, _ = network.parse_http_host_and_port(child.uri)
                printerrlog("Unable to contact remote roslaunch at [%s]. This is most likely due to a network misconfiguration with host lookups. Please make sure that you can contact '%s' from this machine"%(child.uri, child_host))
                self._assume_failed(nodes, failed)

            except Exception as e:
                printerrlog('error launching on [%s, uri %s]: %s'%(child.name, child.uri, str(e)))
                self._assume_failed(nodes, failed)

        return succeeded, failed
Esempio n. 7
0
    def assign_machines(self):
        """
        Assign nodes to machines and determine whether or not there are any remote machines
        """
        # don't repeat machine assignment
        if self._assign_machines_complete:
            return

        machine_unify_dict = {}

        self._assign_machines_complete = True
        # #653: current have to set all core nodes to local launch
        local_machine = self.machines['']
        for n in self.nodes_core:
            n.machine = local_machine

        #for n in self.nodes_core + self.nodes + self.tests:
        for n in self.nodes + self.tests:
            m = self._select_machine(n)

            # if machines have the same config keys it means that they are identical except
            # for their name. we unify the machine assignments so that we don't use
            # extra resources.
            config_key = m.config_key()
            if config_key in machine_unify_dict:
                new_m = machine_unify_dict[config_key]
                if m != new_m:
                    self.logger.info(
                        "... changing machine assignment from [%s] to [%s] as they are equivalent",
                        m.name, new_m.name)
                    m = new_m
            else:
                machine_unify_dict[config_key] = m
            n.machine = m
            self.logger.info(
                "... selected machine [%s] for node of type [%s/%s]", m.name,
                n.package, n.type)

        # determine whether or not there are any machines we will need
        # to setup remote roslaunch clients for
        self._remote_nodes_present = False
        if [
                m for m in machine_unify_dict.itervalues()
                if not is_machine_local(m)
        ]:
            self._remote_nodes_present = True
Esempio n. 8
0
    def assign_machines(self):
        """
        Assign nodes to machines and determine whether or not there are any remote machines
        """
        # don't repeat machine assignment
        if self._assign_machines_complete:
            return
        
        machine_unify_dict = {}
        
        self._assign_machines_complete = True
        # #653: current have to set all core nodes to local launch
        local_machine = self.machines['']
        for n in self.nodes_core:
            n.machine = local_machine

        #for n in self.nodes_core + self.nodes + self.tests:
        for n in self.nodes + self.tests:
            m = self._select_machine(n)
            
            # if machines have the same config keys it means that they are identical except
            # for their name. we unify the machine assignments so that we don't use
            # extra resources.
            config_key = m.config_key()
            if config_key in machine_unify_dict:
                new_m = machine_unify_dict[config_key]
                if m != new_m:
                    self.logger.info("... changing machine assignment from [%s] to [%s] as they are equivalent", m.name, new_m.name)
                    m = new_m
            else:
                machine_unify_dict[config_key] = m
            n.machine = m
            self.logger.info("... selected machine [%s] for node of type [%s/%s]", m.name, n.package, n.type)

        # determine whether or not there are any machines we will need
        # to setup remote roslaunch clients for
        self._remote_nodes_present = False 
        if [m for m in machine_unify_dict.itervalues() if not is_machine_local(m)]:
            self._remote_nodes_present = True