Exemplo n.º 1
0
def run_command(command, hosts, max_threads=DFLT_MAX_THREADS, analyse=None):
    ''' Run a command over a set of hosts using threading.
        A working SSH agent is needed for authentication.
        
        @param command: the command to be executed on the specified hosts.
        @type command: string

        @param hosts: the hosts on which the command is to be executed
        @type hosts: list

        @param max_threads: the number of concurrent threads used to
        interact with nodes
        @type max_threads: int

        @param analyse: a function which can be called to analyse the
        results of the execution of the command for each host. Argument
        of the function should be a L{NodeResult} variable.
        @type analyse: function

        @return: a L{NodeResultSet} with results for all hosts
        @rtype: NodeResultSet
    '''

    agent = Agent()
    queue = Queue.Queue()
    threads = {}

    # fork enough (but not too many) threads
    for i in range(min(max_threads, len(hosts))):
        threads[i] = NodeCommandThread(queue, command, agent, analyse=analyse)
        threads[i].setDaemon(True)
        threads[i].start()

    # add all hosts to the work queue
    for host in hosts:
        queue.put(host)

    # wait for threads to be done
    queue.join()

    # fix for some threading problems
    time.sleep(1)

    # gather results
    result = NodeResultSet()
    for i in range(min(max_threads, len(hosts))):
        result.append(threads[i].get_result())

    return result
Exemplo n.º 2
0
    def __init__(self, queue, command, agent, timeout=DFLT_SSH_TIMEOUT, analyse=None):
        """ Create a new NodeCommandThread object.

            @param queue: a list of nodes on which the commands is to be executed
            @type queue: list of strings
            
            @param command: the command to be executed
            @type command: string
        
            @param agent: a I{paramiko.Agent} SSH-agent object.
            @type agent: I{paramiko.Agent} object

            @param timeout: the SSH timeout in seconds
            @type timeout: integer

            @param analyse: callback analyse function. This function is called after
            the command has been executed. Argument for the function is a L{NodeResult} object.
            @type analyse: function
        """
        self.queue = queue
        self.command = command
        self.agent = agent
        self.timeout = timeout
        self.result = NodeResultSet()
        self.analyse = analyse
        threading.Thread.__init__(self)
Exemplo n.º 3
0
class NodeCommandThread(threading.Thread):
    ''' a thread for processing commands to a node via SSH
    '''

    def __init__(self, queue, command, agent, timeout=DFLT_SSH_TIMEOUT, analyse=None):
        """ Create a new NodeCommandThread object.

            @param queue: a list of nodes on which the commands is to be executed
            @type queue: list of strings
            
            @param command: the command to be executed
            @type command: string
        
            @param agent: a I{paramiko.Agent} SSH-agent object.
            @type agent: I{paramiko.Agent} object

            @param timeout: the SSH timeout in seconds
            @type timeout: integer

            @param analyse: callback analyse function. This function is called after
            the command has been executed. Argument for the function is a L{NodeResult} object.
            @type analyse: function
        """
        self.queue = queue
        self.command = command
        self.agent = agent
        self.timeout = timeout
        self.result = NodeResultSet()
        self.analyse = analyse
        threading.Thread.__init__(self)


    def run(self):
        """ Execution of the thread.
        """
        # read default SSH config
        ssh = SSHClient()
        conf = SSHConfig()
        
        # use the local SSH configuration for keys, known hosts, etc
        conf.parse(open(os.path.join(os.environ['HOME'], '.ssh', 'config'), 'r'))
        ssh.set_missing_host_key_policy(AutoAddPolicy())
        ssh.load_system_host_keys()

        # continue to process hosts until the queue is empty
        while True:
            try:
                starttime = time.time()
                # pick the next available host
                host = self.queue.get()
                result = NodeResult(host)
                node = RingNode(host)
                try:
                    # some template replacements
                    cmd = self.command.replace("%%HOST%%", host)
                    result = node.run_command(cmd)
                except RingException, e:
                    result.set_ssh_result(NodeResult.SSH_ERROR)
                    result.set_ssh_errormsg(e.__str__())
                finally:
                    node.close()
                    if self.analyse:
                        self.analyse(result)

                result.add_value('runtime', time.time() - starttime)
                self.result.append(result)

            except Queue.Empty:
                # we're done!
                pass
            finally: