Exemple #1
0
  def getTopics(self):
    def topic_type(t, pub_topics):
        matches = [t_type for t_name, t_type in pub_topics if t_name == t]
        if matches:
            return matches[0]
        return 'unknown type'

    master = scriptutil.get_master()
    topic = None

    state = succeed(master.getSystemState('/rostopic'))
    pubs, subs, _ = state

    pub_topics = succeed(scriptutil.get_master().getPublishedTopics('/rostopic', '/'))    
    pubtopics = [t for t,_ in pubs]
    pubtopics.sort()

    subtopics = [t for t,_ in subs]
    subtopics.sort()

    nodes = []

    for s in state:
        for t, l in s:
            nodes.extend(l)

    nodes = set(nodes)
    nodes = list(nodes)
    nodes.sort()

    topics = (tuple(pubtopics), tuple(subtopics), tuple(nodes))

    return topics
Exemple #2
0
def get_node_names(namespace=None):
    """
    @param namespace: optional namespace to scope return values by. Namespace must already be resolved.
    @type  namespace: str
    @return: list of node caller IDs
    @rtype: [str]
    @raise ROSNodeIOException: if unable to communicate with master
    """
    master = scriptutil.get_master()
    try:
        state = _succeed(master.getSystemState(ID))
    except socket.error:
        raise ROSNodeIOException("Unable to communicate with master!")
    nodes = []
    import itertools
    if namespace:
        # canonicalize namespace with leading/trailing slash
        import roslib.names
        g_ns = roslib.names.make_global_ns(namespace)
        for s in state:
            for t, l in s:
                nodes.extend(
                    [n for n in l if n.startswith(g_ns) or n == namespace])
    else:
        for s in state:
            for t, l in s:
                nodes.extend(l)
    return list(set(nodes))
Exemple #3
0
def node_info(node):
  caller_id = make_caller_id('nodeutil-%s'%os.getpid())
  node_name = node #scriptutil.script_resolve_name(caller_id, node)
  master = scriptutil.get_master()

  # go through the master system state first
  try:
    state = _remote_call(master.getSystemState(caller_id))
  except socket.error:
    raise Exception("Unable to communicate with master!")
      
  pubs = [t for t, l in state[0] if node_name in l]
  subs = [t for t, l in state[1] if node_name in l]
  srvs = [t for t, l in state[2] if node_name in l]  

  results = {
    "publications": pubs,
    "subscriptions": subs,
    "services": srvs
  }
  node_api = get_api_uri(master, node_name, caller_id)
  if not node_api:
    results["error"] = "cannot contact [%s]: unknown node"%node_name

  return results
Exemple #4
0
def rosnode_ping_all(verbose=False):
    """
    Ping all running nodes
    @return [str], [str]: pinged nodes, un-pingable nodes
    @raise ROSNodeIOException: if unable to communicate with master
    """
    master = scriptutil.get_master()
    try:
        state = _succeed(master.getSystemState(ID))
    except socket.error:
        raise ROSNodeIOException("Unable to communicate with master!")

    nodes = []
    import itertools
    for s in state:
        for t, l in s:
            nodes.extend(l)
    nodes = list(set(nodes))  #uniq
    if verbose:
        print "Will ping the following nodes: \n" + ''.join(
            [" * %s\n" % n for n in nodes])
    pinged = []
    unpinged = []
    for node in nodes:
        if rosnode_ping(node, max_count=1, verbose=verbose):
            pinged.append(node)
        else:
            unpinged.append(node)
    return pinged, unpinged
Exemple #5
0
def _sub_rosnode_listnodes(namespace=None, list_uri=False, list_all=False):
    """
    Subroutine for rosnode_listnodes(). Composes list of strings to print to screen.
    
    @param namespace: (default None) namespace to scope list to. 
    @type  namespace: str
    @param list_uri: (default False) return uris of nodes instead of names. 
    @type  list_uri: bool
    @param list_all: (default False) return names and uris of nodes as combined strings
    @type  list_all: bool
    @return: new-line separated string containing list of all nodes
    @rtype: str
    """
    master = scriptutil.get_master()
    nodes = get_node_names(namespace)
    nodes.sort()
    if list_all:
        return '\n'.join([
            "%s \t%s" % (get_api_uri(master, n) or 'unknown address', n)
            for n in nodes
        ])
    elif list_uri:
        return '\n'.join([(get_api_uri(master, n) or 'unknown address')
                          for n in nodes])
    else:
        return '\n'.join(nodes)
Exemple #6
0
def rosnode_info(node_name):
    """
    Print information about node, including subscriptions and other debugging information. This will query the node over the network.
    
    @param node_name: name of ROS node
    @type  node_name: str
    @raise ROSNodeIOException: if unable to communicate with master
    """
    def topic_type(t, pub_topics):
        matches = [t_type for t_name, t_type in pub_topics if t_name == t]
        if matches:
            return matches[0]
        return 'unknown type'

    master = scriptutil.get_master()
    node_name = scriptutil.script_resolve_name('rosnode', node_name)

    print('-'*80)
    print(get_node_info_description(node_name))
        
    node_api = get_api_uri(master, node_name)
    if not node_api:
        print("cannot contact [%s]: unknown node"%node_name, file=sys.stderr)
        return
    
    print("\ncontacting node %s ..."%node_api)

    print(get_node_connection_info_description(node_api))
Exemple #7
0
def get_node_names(namespace=None):
    """
    @param namespace: optional namespace to scope return values by. Namespace must already be resolved.
    @type  namespace: str
    @return: list of node caller IDs
    @rtype: [str]
    @raise ROSNodeIOException: if unable to communicate with master
    """
    master = scriptutil.get_master()
    try:
        state = _succeed(master.getSystemState(ID))
    except socket.error:
        raise ROSNodeIOException("Unable to communicate with master!")
    nodes = []
    import itertools
    if namespace:
        # canonicalize namespace with leading/trailing slash
        import roslib.names
        g_ns = roslib.names.make_global_ns(namespace)
        for s in state:
            for t, l in s:
                nodes.extend([n for n in l if n.startswith(g_ns) or n == namespace])
    else:
        for s in state:
            for t, l in s:
                nodes.extend(l)
    return list(set(nodes))
Exemple #8
0
def topic_info(topic):
  caller_id = make_caller_id('nodeutil-%s'%os.getpid())
  master = scriptutil.get_master()

  # go through the master system state first
  try:
    state = _remote_call(master.getSystemState(caller_id))
  except socket.error:
    raise IOException("Unable to communicate with master!")
      
  pubs, subs, _ = state
  publists = [publist for t, publist in pubs if t == topic]
  sublists = [sublist for t, sublist in subs if t == topic]

  #pub_topics = _succeed(master.getPublishedTopics(caller_id, '/'))

  if publists == []:
    return {
      "error": "This topic does not appear to be published yet."
    }
  elif sublists == []: 
    return {  
        "publishers": publists[0], 
        "subscribers": [] 
    } 
  else:
    return {
      "publishers": publists[0],
      "subscribers": sublists[0]
    }
Exemple #9
0
def rosnode_info(node_name):
    """
    Print information about node, including subscriptions and other debugging information. This will query the node over the network.
    
    @param node_name: name of ROS node
    @type  node_name: str
    @raise ROSNodeIOException: if unable to communicate with master
    """
    def topic_type(t, pub_topics):
        matches = [t_type for t_name, t_type in pub_topics if t_name == t]
        if matches:
            return matches[0]
        return 'unknown type'

    master = scriptutil.get_master()
    node_name = scriptutil.script_resolve_name('rosnode', node_name)

    print '-' * 80
    print get_node_info_description(node_name)

    node_api = get_api_uri(master, node_name)
    if not node_api:
        print >> sys.stderr, "cannot contact [%s]: unknown node" % node_name
        return

    print "\ncontacting node %s ..." % node_api

    print get_node_connection_info_description(node_api)
Exemple #10
0
def is_node_running(node):
    """
    Return true if the given node is running.
    """
    master = scriptutil.get_master()
    node_info = master.lookupNode(rospy.get_name(), node)
    return node_info[0] == 1
Exemple #11
0
def rosnode_ping_all(verbose=False):
    """
    Ping all running nodes
    @return [str], [str]: pinged nodes, un-pingable nodes
    @raise ROSNodeIOException: if unable to communicate with master
    """
    master = scriptutil.get_master()
    try:
        state = _succeed(master.getSystemState(ID))
    except socket.error:
        raise ROSNodeIOException("Unable to communicate with master!")

    nodes = []
    import itertools
    for s in state:
        for t, l in s:
            nodes.extend(l)
    nodes = list(set(nodes)) #uniq
    if verbose:
        print("Will ping the following nodes: \n"+''.join([" * %s\n"%n for n in nodes]))
    pinged = []
    unpinged = []
    for node in nodes:
        if rosnode_ping(node, max_count=1, verbose=verbose):
            pinged.append(node)
        else:
            unpinged.append(node)
    return pinged, unpinged
Exemple #12
0
def kill_nodes(node_names):
    """
    Call shutdown on the specified nodes

    @return: list of nodes that shutdown was called on successfully and list of failures
    @rtype: ([str], [str])
    """
    master = scriptutil.get_master()
    
    success = []
    fail = []
    tocall = []
    try:
        # lookup all nodes keeping track of lookup failures for return value
        for n in node_names:
            try:
                uri = _succeed(master.lookupNode(ID, n))
                tocall.append([n, uri])
            except:
                fail.append(n)
    except socket.error:
        raise ROSNodeIOException("Unable to communicate with master!")

    for n, uri in tocall:
        # the shutdown call can sometimes fail to succeed if the node
        # tears down during the request handling, so we assume success
        try:
            p = xmlrpclib.ServerProxy(uri)
            _succeed(p.shutdown(ID, 'user request'))
        except:
            pass
        success.append(n)            

    return success, fail
Exemple #13
0
def kill_nodes(node_names):
    """
    Call shutdown on the specified nodes

    @return: list of nodes that shutdown was called on successfully and list of failures
    @rtype: ([str], [str])
    """
    master = scriptutil.get_master()

    success = []
    fail = []
    tocall = []
    try:
        # lookup all nodes keeping track of lookup failures for return value
        for n in node_names:
            try:
                uri = _succeed(master.lookupNode(ID, n))
                tocall.append([n, uri])
            except:
                fail.append(n)
    except socket.error:
        raise ROSNodeIOException("Unable to communicate with master!")

    for n, uri in tocall:
        # the shutdown call can sometimes fail to succeed if the node
        # tears down during the request handling, so we assume success
        try:
            p = xmlrpclib.ServerProxy(uri)
            _succeed(p.shutdown(ID, 'user request'))
        except:
            pass
        success.append(n)

    return success, fail
Exemple #14
0
def is_node_running(node):
    """
    Return true if the given node is running.
    Note that a socket is created to query the master.
    """
    master = scriptutil.get_master()
    node_info = master.lookupNode(rospy.get_name(), node)
    return node_info[0] == 1
Exemple #15
0
def get_node_info_description(node_name):
    def topic_type(t, pub_topics):
        matches = [t_type for t_name, t_type in pub_topics if t_name == t]
        if matches:
            return matches[0]
        return 'unknown type'

    master = scriptutil.get_master()

    # go through the master system state first
    try:
        state = _succeed(master.getSystemState(ID))
        pub_topics = _succeed(scriptutil.get_master().getPublishedTopics(
            ID, '/'))
    except socket.error:
        raise ROSNodeIOException("Unable to communicate with master!")
    pubs = [t for t, l in state[0] if node_name in l]
    subs = [t for t, l in state[1] if node_name in l]
    srvs = [t for t, l in state[2] if node_name in l]

    buff = "Node [%s]" % node_name
    if pubs:
        buff += "\nPublications: \n"
        buff += '\n'.join(
            [" * %s [%s]" % (l, topic_type(l, pub_topics))
             for l in pubs]) + '\n'
    else:
        buff += "\nPublications: None\n"
    if subs:
        buff += "\nSubscriptions: \n"
        buff += '\n'.join(
            [" * %s [%s]" % (l, topic_type(l, pub_topics))
             for l in subs]) + '\n'
    else:
        buff += "\nSubscriptions: None\n"
    if srvs:
        buff += "\nServices: \n"
        buff += '\n'.join([" * %s" % l for l in srvs]) + '\n'
    else:
        buff += "\nServices: None\n"

    return buff
Exemple #16
0
def rosnode_ping(node_name, max_count=None, verbose=False):
    """
    Test connectivity to node by calling its XMLRPC API
    @param node_name: name of node to ping
    @type  node_name: str
    @param max_count: number of ping requests to make
    @type  max_count: int
    @param verbose: print ping information to screen
    @type  verbose: bool
    @return: True if node pinged
    @rtype: bool
    """
    master = scriptutil.get_master()
    node_api = get_api_uri(master, node_name)
    if not node_api:
        print >> sys.stderr, "cannot ping [%s]: unknown node" % node_name
        return False

    timeout = 3.

    if verbose:
        print "pinging %s with a timeout of %ss" % (node_name, timeout)
    socket.setdefaulttimeout(timeout)
    node = xmlrpclib.ServerProxy(node_api)
    lastcall = 0.
    count = 0
    acc = 0.
    try:
        while True:
            try:
                start = time.time()
                pid = _succeed(node.getPid(ID))
                end = time.time()

                dur = (end - start) * 1000.
                acc += dur
                count += 1

                if verbose:
                    print "xmlrpc reply from %s\ttime=%fms" % (node_api, dur)
                # 1s between pings
            except socket.error:
                print >> sys.stderr, "connection to [%s] timed out" % node_name
                return False
            if max_count and count >= max_count:
                break
            time.sleep(1.0)
    except KeyboardInterrupt:
        pass

    if verbose and count > 1:
        print "ping average: %fms" % (acc / count)
    return True
Exemple #17
0
def get_node_info_description(node_name):
    def topic_type(t, pub_topics):
        matches = [t_type for t_name, t_type in pub_topics if t_name == t]
        if matches:
            return matches[0]
        return 'unknown type'

    master = scriptutil.get_master()

    # go through the master system state first
    try:
        state = _succeed(master.getSystemState(ID))
        pub_topics = _succeed(scriptutil.get_master().getPublishedTopics(ID, '/'))
    except socket.error:
        raise ROSNodeIOException("Unable to communicate with master!")
    pubs = [t for t, l in state[0] if node_name in l]
    subs = [t for t, l in state[1] if node_name in l]
    srvs = [t for t, l in state[2] if node_name in l]  

    buff = "Node [%s]"%node_name
    if pubs:
        buff += "\nPublications: \n"
        buff += '\n'.join([" * %s [%s]"%(l, topic_type(l, pub_topics)) for l in pubs]) + '\n'
    else:
        buff += "\nPublications: None\n"
    if subs:
        buff += "\nSubscriptions: \n"
        buff += '\n'.join([" * %s [%s]"%(l, topic_type(l, pub_topics)) for l in subs]) + '\n'
    else:
        buff += "\nSubscriptions: None\n"        
    if srvs:
        buff += "\nServices: \n"
        buff += '\n'.join([" * %s"%l for l in srvs]) + '\n'
    else:
        buff += "\nServices: None\n"
        
    return buff
Exemple #18
0
def get_nodes_by_machine(machine):
    """
    Find nodes by machine name. This is a very costly procedure as it
    must do N lookups with the Master, where N is the number of nodes.
    
    @return: list of nodes on the specified machine
    @rtype: [str]
    @raise ROSNodeException: if machine name cannot be resolved to an address
    @raise ROSNodeIOException: if unable to communicate with master
    """
    import urlparse

    master = scriptutil.get_master()
    try:
        machine_actual = socket.gethostbyname(machine)
    except:
        raise ROSNodeException("cannot resolve machine name [%s] to address" %
                               machine)

    # get all the node names, lookup their uris, parse the hostname
    # from the uris, and then compare the resolved hostname against
    # the requested machine name.
    matches = [machine, machine_actual]
    not_matches = []  # cache lookups
    node_names = get_node_names()
    retval = []
    for n in node_names:
        try:
            code, msg, uri = master.lookupNode(ID, n)
            # it's possible that the state changes as we are doing lookups. this is a soft-fail
            if code != 1:
                continue

            h = urlparse.urlparse(uri).hostname
            if h in matches:
                retval.append(n)
            elif h in not_matches:
                continue
            else:
                r = socket.gethostbyname(h)
                if r == machine_actual:
                    matches.append(r)
                    retval.append(n)
                else:
                    not_matches.append(r)
        except socket.error:
            raise ROSNodeIOException("Unable to communicate with master!")
    return retval
Exemple #19
0
def get_nodes_by_machine(machine):
    """
    Find nodes by machine name. This is a very costly procedure as it
    must do N lookups with the Master, where N is the number of nodes.
    
    @return: list of nodes on the specified machine
    @rtype: [str]
    @raise ROSNodeException: if machine name cannot be resolved to an address
    @raise ROSNodeIOException: if unable to communicate with master
    """
    import urlparse
    
    master = scriptutil.get_master()
    try:
        machine_actual = socket.gethostbyname(machine)
    except:
        raise ROSNodeException("cannot resolve machine name [%s] to address"%machine)

    # get all the node names, lookup their uris, parse the hostname
    # from the uris, and then compare the resolved hostname against
    # the requested machine name.
    matches = [machine, machine_actual]
    not_matches = [] # cache lookups
    node_names = get_node_names()
    retval = []
    for n in node_names:
        try:
            code, msg, uri = master.lookupNode(ID, n)
            # it's possible that the state changes as we are doing lookups. this is a soft-fail
            if code != 1:
                continue

            h = urlparse.urlparse(uri).hostname
            if h in matches:
                retval.append(n)
            elif h in not_matches:
                continue
            else:
                r = socket.gethostbyname(h)
                if r == machine_actual:
                    matches.append(r)
                    retval.append(n)
                else:
                    not_matches.append(r)                        
        except socket.error:
            raise ROSNodeIOException("Unable to communicate with master!")    
    return retval
def rosnode_ping(node_name):
    max_count = 1

    master = scriptutil.get_master()

    node_api = get_api_uri(master, node_name)
    if not node_api:
        #print >> sys.stderr, "cannot ping [%s]: unknown node"%node_name
        #print 'NODE IS DOWN'
        return False

    timeout = 3.

    #print "pinging %s with a timeout of %ss"%(node_name, timeout)

    socket.setdefaulttimeout(timeout)
    node = xmlrpclib.ServerProxy(node_api)
    lastcall = 0.
    acc = 0.
    count = 0
    try:
        while True:
            try:
                start = time.time()
                pid = _succeed(node.getPid(ID))
                end = time.time()

                dur = (end - start) * 1000.
                acc += dur
                count += 1

                #print 'NODE IS UP'
                #print "xmlrpc reply from %s\ttime=%fms"%(node_api, dur)
                # 1s between pings
            except socket.error:
                #print 'NODE IS DOWN'
                #print >> sys.stderr, "connection to [%s] timed out"%node_name
                return False
            if max_count and count >= max_count:
                break
            #time.sleep(1.0)
    except KeyboardInterrupt:
        pass

    return True
Exemple #21
0
def stop_node(node):
    """
    Stop the given node. Return true on success.
    """
    master = scriptutil.get_master()
    node_info = master.lookupNode(rospy.get_name(), node)
    [code, msg, uri] = master.lookupNode(rospy.get_name(), node)
    if code != 1:
        if msg.startswith('unknown node'):
            rospy.loginfo('Unknown node "%s"; ignored stop request.', node)
            return True
        else:
            rospy.logwarn('Couldn\'t stop "%s", problem retrieving information: %s', node, msg)
            return False
    try:
        proxy = xmlrpclib.ServerProxy(uri)
        result = proxy.shutdown(rospy.get_name(), 'pal_common')
    except Exception, e:
        rospy.logwarn('Couldn\'t stop "%s": %s', node, str(e))
        return False
Exemple #22
0
def node_info(node):
    caller_id = make_caller_id('nodeutil-%s' % os.getpid())
    node_name = node  #scriptutil.script_resolve_name(caller_id, node)
    master = scriptutil.get_master()

    # go through the master system state first
    try:
        state = _remote_call(master.getSystemState(caller_id))
    except socket.error:
        raise Exception("Unable to communicate with master!")

    pubs = [t for t, l in state[0] if node_name in l]
    subs = [t for t, l in state[1] if node_name in l]
    srvs = [t for t, l in state[2] if node_name in l]

    results = {"publications": pubs, "subscriptions": subs, "services": srvs}
    node_api = get_api_uri(master, node_name, caller_id)
    if not node_api:
        results["error"] = "cannot contact [%s]: unknown node" % node_name

    return results
Exemple #23
0
def topic_info(topic):
    caller_id = make_caller_id('nodeutil-%s' % os.getpid())
    master = scriptutil.get_master()

    # go through the master system state first
    try:
        state = _remote_call(master.getSystemState(caller_id))
    except socket.error:
        raise IOException("Unable to communicate with master!")

    pubs, subs, _ = state
    publists = [publist for t, publist in pubs if t == topic]
    sublists = [sublist for t, sublist in subs if t == topic]

    #pub_topics = _succeed(master.getPublishedTopics(caller_id, '/'))

    if publists == []:
        return {"error": "This topic does not appear to be published yet."}
    elif sublists == []:
        return {"publishers": publists[0], "subscribers": []}
    else:
        return {"publishers": publists[0], "subscribers": sublists[0]}
Exemple #24
0
def _sub_rosnode_listnodes(namespace=None, list_uri=False, list_all=False):
    """
    Subroutine for rosnode_listnodes(). Composes list of strings to print to screen.
    
    @param namespace: (default None) namespace to scope list to. 
    @type  namespace: str
    @param list_uri: (default False) return uris of nodes instead of names. 
    @type  list_uri: bool
    @param list_all: (default False) return names and uris of nodes as combined strings
    @type  list_all: bool
    @return: new-line separated string containing list of all nodes
    @rtype: str
    """
    master = scriptutil.get_master()    
    nodes = get_node_names(namespace)
    nodes.sort()
    if list_all:
        return '\n'.join(["%s \t%s"%(get_api_uri(master, n) or 'unknown address', n) for n in nodes])
    elif list_uri:
        return '\n'.join([(get_api_uri(master, n) or 'unknown address') for n in nodes])
    else:
        return '\n'.join(nodes)
Exemple #25
0
def rosnode_cleanup():
    """
    This is a semi-hidden routine for cleaning up stale node
    registration information on the ROS Master. The intent is to
    remove this method once Master TTLs are properly implemented.
    """
    pinged, unpinged = rosnode_ping_all()
    if unpinged:
        master = scriptutil.get_master()
        print("Unable to contact the following nodes:")
        print('\n'.join(' * %s'%n for n in unpinged))
        print("cleanup will purge all information about these nodes from the master")
        print("Please type y or n to continue")
        input = sys.stdin.readline()
        while not input.strip() in ['y', 'n']:
            input = sys.stdin.readline()
        if input.strip() == 'n':
            print('aborting')
            return
        
        cleanup_master_blacklist(master, unpinged)

        print("done")
Exemple #26
0
def rosnode_cleanup():
    """
    This is a semi-hidden routine for cleaning up stale node
    registration information on the ROS Master. The intent is to
    remove this method once Master TTLs are properly implemented.
    """
    pinged, unpinged = rosnode_ping_all()
    if unpinged:
        master = scriptutil.get_master()
        print "Unable to contact the following nodes:"
        print '\n'.join(' * %s' % n for n in unpinged)
        print "cleanup will purge all information about these nodes from the master"
        print "Please type y or n to continue"
        input = sys.stdin.readline()
        while not input.strip() in ['y', 'n']:
            input = sys.stdin.readline()
        if input.strip() == 'n':
            print 'aborting'
            return

        cleanup_master_blacklist(master, unpinged)

        print "done"
Exemple #27
0
def rosnode_ping(node_name, max_count=None, verbose=False):
    """
    Test connectivity to node by calling its XMLRPC API
    @param node_name: name of node to ping
    @type  node_name: str
    @param max_count: number of ping requests to make
    @type  max_count: int
    @param verbose: print ping information to screen
    @type  verbose: bool
    @return: True if node pinged
    @rtype: bool
    """
    master = scriptutil.get_master()
    node_api = get_api_uri(master,node_name)
    if not node_api:
        print("cannot ping [%s]: unknown node"%node_name, file=sys.stderr)
        return False

    timeout = 3.

    if verbose:
        print("pinging %s with a timeout of %ss"%(node_name, timeout))
    socket.setdefaulttimeout(timeout)
    node = xmlrpclib.ServerProxy(node_api)
    lastcall = 0.
    count = 0
    acc = 0.
    try:
        while True:
            try:
                start = time.time()
                pid = _succeed(node.getPid(ID))
                end = time.time()

                dur = (end-start)*1000.
                acc += dur
                count += 1

                if verbose:
                    print("xmlrpc reply from %s\ttime=%fms"%(node_api, dur))
                # 1s between pings
            except socket.error as e:
                # 3786: catch ValueError on unpack as socket.error is not always a tuple
                try:
                    # #3659
                    errnum, msg = e
                    if errnum == -2: #name/service unknown
                        p = urlparse.urlparse(node_api)
                        print("ERROR: Unknown host [%s] for node [%s]"%(p.hostname, node_name), file=sys.stderr)
                    elif errnum == errno.ECONNREFUSED:
                        p = urlparse.urlparse(node_api)
                        print("ERROR: connection refused to [%s]"%(node_api), file=sys.stderr)
                    else:
                        print("connection to [%s] timed out"%node_name, file=sys.stderr)
                    return False
                except ValueError:
                    print("unknown network error contacting node: %s"%(str(e)))
            if max_count and count >= max_count:
                break
            time.sleep(1.0)
    except KeyboardInterrupt:
        pass
            
    if verbose and count > 1:
        print("ping average: %fms"%(acc/count))
    return True