Exemplo n.º 1
0
   def test_playbook_hash_merge(self):
      # save default hash behavior so we can restore it in the end of the test
      saved_hash_behavior = C.DEFAULT_HASH_BEHAVIOUR
      C.DEFAULT_HASH_BEHAVIOUR = "merge"

      test_callbacks = TestCallbacks()
      playbook = ansible.playbook.PlayBook(
          playbook=os.path.join(self.test_dir, 'test_hash_behavior', 'playbook.yml'),
          host_list='test/ansible_hosts',
          stats=ans_callbacks.AggregateStats(),
          callbacks=test_callbacks,
          runner_callbacks=test_callbacks
      )
      playbook.run()

      filename = '/tmp/ansible_test_messages.out'
      expected_lines = [
        "goodbye: Goodbye World!",
        "hello: Hello World!"
      ]
      self._compare_file_output(filename, expected_lines)

      filename = '/tmp/ansible_test_role_messages.out'
      expected_lines = [
        "goodbye: Goodbye World!",
        "hello: Hello World!",
        "inside_a_role: Indeed!"
      ]
      self._compare_file_output(filename, expected_lines)

      # restore default hash behavior
      C.DEFAULT_HASH_BEHAVIOUR = saved_hash_behavior
Exemplo n.º 2
0
    def test_playbook_hash_merge(self):
        # save default hash behavior so we can restore it in the end of the test
        saved_hash_behavior = C.DEFAULT_HASH_BEHAVIOUR
        C.DEFAULT_HASH_BEHAVIOUR = "merge"

        test_callbacks = TestCallbacks()
        playbook = ansible.playbook.PlayBook(
            playbook=os.path.join(self.test_dir, 'test_hash_behavior',
                                  'playbook.yml'),
            host_list='test/ansible_hosts',
            stats=ans_callbacks.AggregateStats(),
            callbacks=test_callbacks,
            runner_callbacks=test_callbacks)
        playbook.run()

        filename = '/tmp/ansible_test_messages.out'
        expected_lines = ["goodbye: Goodbye World!", "hello: Hello World!"]
        self._compare_file_output(filename, expected_lines)

        filename = '/tmp/ansible_test_role_messages.out'
        expected_lines = [
            "goodbye: Goodbye World!", "hello: Hello World!",
            "inside_a_role: Indeed!"
        ]
        self._compare_file_output(filename, expected_lines)

        # restore default hash behavior
        C.DEFAULT_HASH_BEHAVIOUR = saved_hash_behavior
Exemplo n.º 3
0
 def test_playbook_vars(self):
     test_callbacks = TestCallbacks()
     playbook = ansible.playbook.PlayBook(
         playbook=os.path.join(self.test_dir, 'test_playbook_vars',
                               'playbook.yml'),
         host_list='test/test_playbook_vars/hosts',
         stats=ans_callbacks.AggregateStats(),
         callbacks=test_callbacks,
         runner_callbacks=test_callbacks)
     playbook.run()
Exemplo n.º 4
0
 def test_playbook_vars(self):
     test_callbacks = TestCallbacks()
     playbook = ansible.playbook.PlayBook(
         playbook=os.path.join(self.test_dir, 'test_playbook_vars', 'playbook.yml'),
         host_list='test/test_playbook_vars/hosts',
         stats=ans_callbacks.AggregateStats(),
         callbacks=test_callbacks,
         runner_callbacks=test_callbacks
     )
     playbook.run()
Exemplo n.º 5
0
 def test_playbook_vars(self):
     test_callbacks = TestCallbacks()
     playbook = ansible.playbook.PlayBook(
         playbook=os.path.join(self.test_dir, 'test_playbook_vars',
                               'playbook.yml'),
         host_list='test/test_playbook_vars/hosts',
         stats=ans_callbacks.AggregateStats(),
         callbacks=test_callbacks,
         runner_callbacks=test_callbacks)
     playbook.run()
     assert playbook.SETUP_CACHE['host1'] == {'attr2': 2, 'attr1': 1}
     assert playbook.SETUP_CACHE['host2'] == {'attr2': 2}
Exemplo n.º 6
0
 def test_playbook_vars(self): 
     test_callbacks = TestCallbacks()
     playbook = ansible.playbook.PlayBook(
         playbook=os.path.join(self.test_dir, 'test_playbook_vars', 'playbook.yml'),
         host_list='test/test_playbook_vars/hosts',
         stats=ans_callbacks.AggregateStats(),
         callbacks=test_callbacks,
         runner_callbacks=test_callbacks
     )
     playbook.run()
     assert playbook.SETUP_CACHE['host1'] == {'attr2': 2, 'attr1': 1}
     assert playbook.SETUP_CACHE['host2'] == {'attr2': 2}
    def run_playbook(self,
                     playbook,
                     host_list=None,
                     use_sudo=True,
                     local=False,
                     extra_vars={},
                     ans_remote_user=AnsibleConstants.DEFAULT_REMOTE_USER,
                     ans_remote_pass=AnsibleConstants.DEFAULT_REMOTE_PASS,
                     only_tags=None,
                     skip_tags=None):
        """Runs an ansible playbook

        From ansible doc:
        lib/ansible/__init__.py

        playbook:         path to a playbook file
        host_list:        path to a file like /etc/ansible/hosts
        module_path:      path to ansible modules, like /usr/share/ansible/
        forks:            desired level of paralellism
        timeout:          connection timeout
        remote_user:      run as this user if not specified in a particular play
        remote_pass:      use this remote password (for all plays) vs using SSH keys
        sudo_pass:        if sudo==True, and a password is required, this is the sudo password
        remote_port:      default remote port to use if not specified with the host or play
        transport:        how to connect to hosts that don't specify a transport (local, paramiko, etc)
        callbacks         output callbacks for the playbook
        runner_callbacks: more callbacks, this time for the runner API
        stats:            holds aggregate data about events occuring to each host
        sudo:             if not specified per play, requests all plays use sudo mode
        inventory:        can be specified instead of host_list to use a pre-existing inventory object
        check:            don't change anything, just try to detect some potential changes

        only_tags:        List of tags to include. Only run task of tasks in the include list.
        skip_tags:        List of tags to skip. Run all task but tagged in the skip list.
        """
        use_transport = AnsibleConstants.DEFAULT_TRANSPORT
        if local:
            use_transport = "local"
            host_list = []
            host_list.append("127.0.0.1")
        playbook = ansible.playbook.PlayBook(
            playbook=playbook,
            host_list=host_list if host_list != [] else self.__host_list,
            stats=ans_callbacks.AggregateStats(),
            callbacks=self.callbacks,
            runner_callbacks=self.callbacks,
            transport=use_transport,
            sudo=use_sudo,
            extra_vars=extra_vars,
            remote_user=ans_remote_user,
            remote_pass=ans_remote_pass,
            only_tags=only_tags,
            skip_tags=skip_tags)
        playbook.SETUP_CACHE.clear()
        result = playbook.run()
        # The result is a dict. I'm going to add
        # The "alienvault" key with our "internal"
        # values
        result['alienvault'] = {'lasterror': self.callbacks.lasterror}
        return result
Exemplo n.º 8
0
def run(validation, cancel_event):
    C.HOST_KEY_CHECKING = False
    stats = callbacks.AggregateStats()
    playbook_callbacks = SilentPlaybookCallbacks(cancel_event)
    runner_callbacks = callbacks.DefaultRunnerCallbacks()
    playbook = ansible.playbook.PlayBook(
        playbook=validation['playbook'],
        host_list='tripleo-ansible-inventory.py',
        stats=stats,
        callbacks=playbook_callbacks,
        runner_callbacks=runner_callbacks)
    try:
        result = playbook.run()
    except ValidationCancelled:
        result = {}
        for host in playbook.inventory.list_hosts():
            result[host] = {
                'failures': 1,
                'unreachable': 0,
                'description': "Validation was cancelled.",
            }

    for host, status in result.items():
        success = status['failures'] == 0 and status['unreachable'] == 0
        result[host]['success'] = success
    return result
Exemplo n.º 9
0
def run(validation, cancel_event):
    C.HOST_KEY_CHECKING = False
    stats = callbacks.AggregateStats()
    playbook_callbacks = SilentPlaybookCallbacks(cancel_event)
    runner_callbacks = callbacks.DefaultRunnerCallbacks()
    playbook = ansible.playbook.PlayBook(
        playbook=validation['playbook'],
        host_list='tripleo-ansible-inventory.py',
        stats=stats,
        callbacks=playbook_callbacks,
        runner_callbacks=runner_callbacks)
    try:
        result = playbook.run()
    except ValidationCancelled:
        result = {}
        for host in playbook.inventory.list_hosts():
            result[host] = {
                'failures': 1,
                'unreachable': 0,
                'description': "Validation was cancelled.",
            }

    for host, status in result.items():
        success = status['failures'] == 0 and status['unreachable'] == 0
        result[host]['success'] = success
    return result
Exemplo n.º 10
0
   def test_playbook_always_run(self):
      test_callbacks = TestCallbacks()
      playbook = ansible.playbook.PlayBook(
          playbook=os.path.join(self.test_dir, 'playbook-always-run.yml'),
          host_list='test/ansible_hosts',
          stats=ans_callbacks.AggregateStats(),
          callbacks=test_callbacks,
          runner_callbacks=test_callbacks,
          check=True
      )
      actual = playbook.run()

      # if different, this will output to screen
      print "**ACTUAL**"
      print utils.jsonify(actual, format=True)
      expected =  {
          "localhost": {
              "changed": 4,
              "failures": 0,
              "ok": 4,
              "skipped": 8,
              "unreachable": 0
          }
      }
      print "**EXPECTED**"
      print utils.jsonify(expected, format=True)

      assert utils.jsonify(expected, format=True) == utils.jsonify(actual,format=True)
Exemplo n.º 11
0
   def _test_playbook_undefined_vars(self, playbook, fail_on_undefined):
       # save DEFAULT_UNDEFINED_VAR_BEHAVIOR so we can restore it in the end of the test
       saved_undefined_var_behavior = C.DEFAULT_UNDEFINED_VAR_BEHAVIOR
       C.DEFAULT_UNDEFINED_VAR_BEHAVIOR = fail_on_undefined

       test_callbacks = TestCallbacks()
       playbook = ansible.playbook.PlayBook(
           playbook=os.path.join(self.test_dir, 'test_playbook_undefined_vars', playbook),
           host_list='test/test_playbook_undefined_vars/hosts',
           stats=ans_callbacks.AggregateStats(),
           callbacks=test_callbacks,
           runner_callbacks=test_callbacks
       )
       actual = playbook.run()

       C.DEFAULT_UNDEFINED_VAR_BEHAVIOR = saved_undefined_var_behavior

       # if different, this will output to screen
       print "**ACTUAL**"
       print utils.jsonify(actual, format=True)
       expected =  {
           "localhost": {
               "changed": 0,
               "failures": 0,
               "ok": int(not fail_on_undefined) + 1,
               "skipped": 0,
               "unreachable": int(fail_on_undefined)
           }
       }
       print "**EXPECTED**"
       print utils.jsonify(expected, format=True)

       assert utils.jsonify(expected, format=True) == utils.jsonify(actual, format=True)
Exemplo n.º 12
0
    def _test_playbook_undefined_vars(self, playbook, fail_on_undefined):
        # save DEFAULT_UNDEFINED_VAR_BEHAVIOR so we can restore it in the end of the test
        saved_undefined_var_behavior = C.DEFAULT_UNDEFINED_VAR_BEHAVIOR
        C.DEFAULT_UNDEFINED_VAR_BEHAVIOR = fail_on_undefined

        test_callbacks = TestCallbacks()
        playbook = ansible.playbook.PlayBook(
            playbook=os.path.join(self.test_dir,
                                  'test_playbook_undefined_vars', playbook),
            host_list='test/test_playbook_undefined_vars/hosts',
            stats=ans_callbacks.AggregateStats(),
            callbacks=test_callbacks,
            runner_callbacks=test_callbacks)
        actual = playbook.run()

        C.DEFAULT_UNDEFINED_VAR_BEHAVIOR = saved_undefined_var_behavior

        # if different, this will output to screen
        print "**ACTUAL**"
        print utils.jsonify(actual, format=True)
        expected = {
            "localhost": {
                "changed": 0,
                "failures": 0,
                "ok": int(not fail_on_undefined) + 1,
                "skipped": 0,
                "unreachable": int(fail_on_undefined)
            }
        }
        print "**EXPECTED**"
        print utils.jsonify(expected, format=True)

        assert utils.jsonify(expected,
                             format=True) == utils.jsonify(actual, format=True)
Exemplo n.º 13
0
    def test_playbook_always_run(self):
        test_callbacks = TestCallbacks()
        playbook = ansible.playbook.PlayBook(
            playbook=os.path.join(self.test_dir, 'playbook-always-run.yml'),
            host_list='test/ansible_hosts',
            stats=ans_callbacks.AggregateStats(),
            callbacks=test_callbacks,
            runner_callbacks=test_callbacks,
            check=True)
        actual = playbook.run()

        # if different, this will output to screen
        print "**ACTUAL**"
        print utils.jsonify(actual, format=True)
        expected = {
            "localhost": {
                "changed": 4,
                "failures": 0,
                "ok": 4,
                "skipped": 8,
                "unreachable": 0
            }
        }
        print "**EXPECTED**"
        print utils.jsonify(expected, format=True)

        assert utils.jsonify(expected,
                             format=True) == utils.jsonify(actual, format=True)
Exemplo n.º 14
0
def run_playbook(host, playbook, **kwargs):

    logger.info('running playbook {playbook} on host {hostname}'.format(
        playbook=playbook,
        hostname=host.hostname,
    ))

    inventory = ansible.inventory.Inventory(host_list=[host.hostname])

    stats = ansible.callbacks.AggregateStats()
    callbacks = ansible.callbacks.PlaybookCallbacks(verbose=ansible.utils.VERBOSITY)
    runner_callbacks = ansible.callbacks.PlaybookRunnerCallbacks(stats=stats, verbose=ansible.utils.VERBOSITY)

    playbook = ansible.playbook.PlayBook(
        inventory=inventory,
        playbook=playbook,
        remote_user=host.login,
        callbacks=callbacks,
        runner_callbacks=runner_callbacks,
        stats=stats,
        **kwargs
    )

    results = playbook.run()
    logger.info('results: {}'.format(results))

    return results
Exemplo n.º 15
0
def run(validation, cancel_event):
    C.HOST_KEY_CHECKING = False
    stats = callbacks.AggregateStats()
    playbook_callbacks = SilentPlaybookCallbacks(cancel_event)
    runner_callbacks = callbacks.DefaultRunnerCallbacks()
    playbook = ansible.playbook.PlayBook(
        playbook=validation['playbook'],
        # TODO we should use a dynamic inventory based on data coming from
        # tripleo-common/heat/ironic
        # http://docs.ansible.com/ansible/developing_api.html
        host_list='hosts',
        stats=stats,
        callbacks=playbook_callbacks,
        runner_callbacks=runner_callbacks)
    try:
        result = playbook.run()
    except ValidationCancelled:
        result = {}
        for host in playbook.inventory.list_hosts():
            result[host] = {
                'failures': 1,
                'unreachable': 0,
                'description': "Validation was cancelled.",
            }

    for host, status in result.items():
        success = status['failures'] == 0 and status['unreachable'] == 0
        result[host]['success'] = success
    return result
Exemplo n.º 16
0
    def run_playbook(self,
                     playbook,
                     host_list=None,
                     use_sudo=True,
                     local=False,
                     extra_vars={},
                     ans_remote_user=AnsibleConstants.DEFAULT_REMOTE_USER,
                     ans_remote_pass=AnsibleConstants.DEFAULT_REMOTE_PASS,
                     only_tags=None,
                     skip_tags=None):
        """Runs an ansible playbook

        From ansible doc:
        lib/ansible/__init__.py

        playbook:         path to a playbook file
        host_list:        path to a file like /etc/ansible/hosts
        module_path:      path to ansible modules, like /usr/share/ansible/
        forks:            desired level of paralellism
        timeout:          connection timeout
        remote_user:      run as this user if not specified in a particular play
        remote_pass:      use this remote password (for all plays) vs using SSH keys
        sudo_pass:        if sudo==True, and a password is required, this is the sudo password
        remote_port:      default remote port to use if not specified with the host or play
        transport:        how to connect to hosts that don't specify a transport (local, paramiko, etc)
        callbacks         output callbacks for the playbook
        runner_callbacks: more callbacks, this time for the runner API
        stats:            holds aggregate data about events occuring to each host
        sudo:             if not specified per play, requests all plays use sudo mode
        inventory:        can be specified instead of host_list to use a pre-existing inventory object
        check:            don't change anything, just try to detect some potential changes

        only_tags:        List of tags to include. Only run task of tasks in the include list.
        skip_tags:        List of tags to skip. Run all task but tagged in the skip list.
        """
        use_transport = AnsibleConstants.DEFAULT_TRANSPORT
        if local:
            use_transport = "local"
            host_list = []
            host_list.append("127.0.0.1")
        playbook = ansible.playbook.PlayBook(playbook=playbook,
                                             host_list=host_list if host_list != [] else self.__host_list,
                                             stats=ans_callbacks.AggregateStats(),
                                             callbacks=self.callbacks,
                                             runner_callbacks=self.callbacks,
                                             transport=use_transport,
                                             sudo=use_sudo,
                                             extra_vars=extra_vars,
                                             remote_user=ans_remote_user,
                                             remote_pass=ans_remote_pass,
                                             only_tags=only_tags,
                                             skip_tags=skip_tags)
        playbook.SETUP_CACHE.clear()
        result = playbook.run()
        # The result is a dict. I'm going to add
        # The "alienvault" key with our "internal"
        # values
        result['alienvault'] = {'lasterror': self.callbacks.lasterror}
        return result
def run_playbook(playbook_file=None,
                 inventory=ansible.inventory.Inventory([]),
                 verbose=psi_ops_config.ANSIBLE_VERBOSE_LEVEL,
                 email_stats=True):
    '''
        Runs a playbook file and returns the result
        playbook_file : Playbook file to open and run (String)
        inventory : Ansible inventory to run playbook against
        verbose : Output verbosity
    '''
    try:
        start_time = datetime.datetime.now()
        playbook_callbacks = ansible.callbacks.PlaybookCallbacks(
            verbose=verbose)
        stats = ansible.callbacks.AggregateStats()
        runner_callbacks = ansible.callbacks.PlaybookRunnerCallbacks(
            stats, verbose=verbose)

        playbook = ansible.playbook.PlayBook(playbook=playbook_file,
                                             callbacks=playbook_callbacks,
                                             runner_callbacks=runner_callbacks,
                                             stats=stats,
                                             inventory=inventory)

        res = playbook.run()
        end_time = datetime.datetime.now()
        print "Run completed at: %s\nTotal run time: %s" % (
            str(end_time), str(end_time - start_time))

        if email_stats is True:
            # stats.dark : (dict) number of hosts that could not be contacted
            # stats.failures : (dict) number of hosts that failed to complete the tasks
            (host_output, host_errs) = process_playbook_vars_cache(playbook)
            setup_cache = process_playbook_setup_cache(playbook)

            if 'apt_update' in playbook_file:
                print playbook_file
                host_output = process_playbook_apt_update_cache(
                    host_output, setup_cache)

            host_output = massage_responses(host_output)
            record = (str(start_time), str(end_time), playbook_file,
                      stats.processed, stats.dark, stats.failures,
                      stats.changed, stats.skipped, res, host_output,
                      host_errs, setup_cache)
            send_mail(record)

        return (stats, res)

    except Exception as e:
        raise e
Exemplo n.º 18
0
def ansible_book(pb, args, id):
    stats = callbacks.AggregateStats()
    playbook_cb = callbacks.PlaybookCallbacks(verbose=utils.VERBOSITY)
    runner_cb = callbacks.PlaybookRunnerCallbacks(stats,
                                                  verbose=utils.VERBOSITY)
    playbook = ansible.playbook.PlayBook(
        playbook=pb,  #要执行的剧本
        extra_vars=args,  #剧本中设置的变量传递
        stats=stats,  #必填参数
        callbacks=playbook_cb,  #必填参数
        runner_callbacks=runner_cb,  #必填参数
        #check=True                     #测试执行,设置为这个True的时候只会输出执行结果   但是不会在真实服务器上执行
        #inventory='/root/my_app/get_inventory.py'
        host_list='/root/my_app/app/host.py')
    result = playbook.run()
    result = json.dumps(result, indent=4)

    return result
Exemplo n.º 19
0
def run(validation, cancel_event):
    C.HOST_KEY_CHECKING = False
    stats = callbacks.AggregateStats()
    playbook_callbacks = SilentPlaybookCallbacks(cancel_event)
    runner_callbacks = CustomRunnerHandler()
    playbook = ansible.playbook.PlayBook(
        playbook=validation['playbook'],
        host_list='tripleo-ansible-inventory.py',
        stats=stats,
        forks=1,
        callbacks=playbook_callbacks,
        runner_callbacks=runner_callbacks)
    try:
        result = playbook.run()
    except ValidationCancelled:
        result = {}
        for host in playbook.inventory.list_hosts():
            result[host] = {
                'failures': 1,
                'unreachable': 0,
                'description': "Validation was cancelled.",
            }

    for host, captures in runner_callbacks.captured_results().items():
        result[host]['raw'] = captures
        result[host]['failure_messages'] = []
        result[host]['warning_messages'] = []
        for capture in captures:
            if capture.get('failed'):
                result[host]['failure_messages'].append(
                    capture.get('msg', 'Unknown failure'))
            if capture.get('rc', 0) != 0:
                msg = "Command '{}' exited with code {}. STDERR: {}".format(
                    capture.get('cmd'), capture.get('rc'),
                    capture.get('stderr'))
                result[host]['failure_messages'].append(msg)
            warnings = capture.get('warnings', [])
            for warning in warnings:
                result[host]['warning_messages'].append(warning)

    for host, status in result.items():
        success = status['failures'] == 0 and status['unreachable'] == 0
        result[host]['success'] = success
    return result
Exemplo n.º 20
0
    def RunPlaybook(
            self, playbook,
            hostlist):  #playbook,用来指定playbook的yaml文件, hostlist 指定hosts文件
        stats = callbacks.AggregateStats()  #收集playbook执行期间的状态信息,最后会进行汇总
        playbook_cb = callbacks.PlaybookCallbacks(
            verbose=utils.VERBOSITY)  #callbacks用来输出playbook执行的结果
        runner_cb = callbacks.PlaybookRunnerCallbacks(
            stats, verbose=utils.VERBOSITY)  #用来输出playbook执行期间的结果

        playbook = ansible.playbook.PlayBook(
            playbook=playbook,
            stats=stats,
            callbacks=playbook_cb,
            runner_callbacks=runner_cb,
            inventory=self.webInventory,
        )
        result = playbook.run()
        data = json.dumps(result, indent=4)
        return data
Exemplo n.º 21
0
def run_playbook(playbook_file=None, inventory=ansible.inventory.Inventory([]), 
                 verbose=psi_ops_config.ANSIBLE_VERBOSE_LEVEL, email_stats=True):
    '''
        Runs a playbook file and returns the result
        playbook_file : Playbook file to open and run (String)
        inventory : Ansible inventory to run playbook against
        verbose : Output verbosity
    '''
    try:
        start_time = datetime.datetime.now()
        playbook_callbacks = ansible.callbacks.PlaybookCallbacks(verbose=verbose)
        stats = ansible.callbacks.AggregateStats()
        runner_callbacks = ansible.callbacks.PlaybookRunnerCallbacks(stats, verbose=verbose)

        playbook = ansible.playbook.PlayBook(
            playbook=playbook_file, callbacks=playbook_callbacks,
            runner_callbacks=runner_callbacks,
            stats=stats, inventory=inventory)
        
        res = playbook.run()
        end_time = datetime.datetime.now()
        print "Run completed at: %s\nTotal run time: %s" % (str(end_time), str(end_time-start_time))
        
        if email_stats is True:
            # stats.dark : (dict) number of hosts that could not be contacted 
            # stats.failures : (dict) number of hosts that failed to complete the tasks
            (host_output, host_errs) = process_playbook_vars_cache(playbook)
            setup_cache = process_playbook_setup_cache(playbook)
            
            if 'apt_update' in playbook_file:
                print playbook_file
                host_output = process_playbook_apt_update_cache(host_output, setup_cache)
            
            host_output = massage_responses(host_output)
            record = (str(start_time), str(end_time), playbook_file, stats.processed, stats.dark, stats.failures, stats.changed, stats.skipped, res, host_output, host_errs, setup_cache)
            send_mail(record)
        
        return (stats, res)
    
    except Exception as e:
        raise e
Exemplo n.º 22
0
def run_playbook(owner,
                 cloud_id,
                 machine_id,
                 playbook_path,
                 extra_vars=None,
                 force_handlers=False,
                 debug=False):
    if not extra_vars:
        extra_vars = None
    ret_dict = {
        'success': False,
        'started_at': time(),
        'finished_at': 0,
        'stdout': '',
        'error_msg': '',
        'inventory': '',
        'stats': {},
    }
    inventory = mist.api.inventory.MistInventory(owner,
                                                 [(cloud_id, machine_id)])
    if len(inventory.hosts) != 1:
        log.error("Expected 1 host, found %s", inventory.hosts)
        ret_dict['error_msg'] = "Expected 1 host, found %s" % inventory.hosts
        ret_dict['finished_at'] = time()
        return ret_dict
    ret_dict['host'] = inventory.hosts.values()[0]['ansible_ssh_host']
    machine_name = inventory.hosts.keys()[0]
    log_prefix = "Running playbook '%s' on machine '%s'" % (playbook_path,
                                                            machine_name)
    files = inventory.export(include_localhost=False)
    ret_dict['inventory'] = files['inventory']
    tmp_dir = tempfile.mkdtemp()
    old_dir = os.getcwd()
    os.chdir(tmp_dir)
    try:
        log.debug("%s: Saving inventory files", log_prefix)
        os.mkdir('id_rsa')
        for name, data in files.items():
            with open(name, 'w') as f:
                f.write(data)
        for name in os.listdir('id_rsa'):
            os.chmod('id_rsa/%s' % name, 0600)
        log.debug("%s: Inventory files ready", log_prefix)

        playbook_path = '%s/%s' % (old_dir, playbook_path)
        ansible_hosts_path = 'inventory'
        # extra_vars['host_key_checking'] = False

        ansible.utils.VERBOSITY = 4 if debug else 0
        ansible.constants.HOST_KEY_CHECKING = False
        ansible.constants.ANSIBLE_NOCOWS = True
        stats = ansible.callbacks.AggregateStats()
        playbook_cb = ansible.callbacks.PlaybookCallbacks(
            verbose=ansible.utils.VERBOSITY)
        runner_cb = ansible.callbacks.PlaybookRunnerCallbacks(
            stats, verbose=ansible.utils.VERBOSITY)
        log.error(old_dir)
        log.error(tmp_dir)
        log.error(extra_vars)
        log.error(playbook_path)
        capture = StdStreamCapture()
        try:
            playbook = ansible.playbook.PlayBook(
                playbook=playbook_path,
                host_list=ansible_hosts_path,
                callbacks=playbook_cb,
                runner_callbacks=runner_cb,
                stats=stats,
                extra_vars=extra_vars,
                force_handlers=force_handlers,
            )
            result = playbook.run()
        except Exception as exc:
            log.error("%s: Error %r", log_prefix, exc)
            ret_dict['error_msg'] = repr(exc)
        finally:
            ret_dict['finished_at'] = time()
            ret_dict['stdout'] = capture.close()
        if ret_dict['error_msg']:
            return ret_dict
        log.debug("%s: Ansible result = %s", log_prefix, result)
        mresult = result[machine_name]
        ret_dict['stats'] = mresult
        if mresult['failures'] or mresult['unreachable']:
            log.error("%s: Ansible run failed: %s", log_prefix, mresult)
            return ret_dict
        log.info("%s: Ansible run succeeded: %s", log_prefix, mresult)
        ret_dict['success'] = True
        return ret_dict
    finally:
        os.chdir(old_dir)
        if not debug:
            shutil.rmtree(tmp_dir)