예제 #1
0
    def test_json_generator(self):
        self.run_cli_cmd('setdeploy local')

        host1 = 'host_test1'
        self.run_cli_cmd('host add %s' % host1)

        inventory = Inventory.load()

        path = inventory.create_json_gen_file()
        (retval, msg) = self.run_command(path)
        inventory.remove_json_gen_file(path)
        self.assertEqual(0, retval, 'json generator command failed: %s' % msg)

        self.assertNotEqual('', msg,
                            'json generator returned no data: %s' % msg)

        self.assertIn(host1, msg,
                      '%s not in json_gen output: %s' % (host1, msg))

        ansible_inventory = AnsibleInventory()
        services = ansible_inventory.services
        for servicename, service in services.items():
            self.assertIn(servicename, msg,
                          '%s not in json_gen output: %s' % (servicename, msg))

        # verify that json output is valid. This will throw if invalid json
        try:
            json.loads(msg)
        except Exception:
            self.assertTrue(False, 'invalid json: %s' % msg)
        remote_msg = '"ansible_ssh_user": "******"'
        local_msg = '"ansible_connection": "local"'

        # verify that setdeploy local worked:
        self.assertIn(local_msg, msg,
                      '%s not in local json_gen output: %s' % (local_msg, msg))
        self.assertNotIn(remote_msg, msg,
                         '%s in local json_gen output: %s' % (remote_msg, msg))

        # verify that setdeploy remote worked:
        CLIENT.set_deploy_mode(remote_mode=True)
        inventory = Inventory.load()
        path = inventory.create_json_gen_file()
        (retval, msg) = self.run_command(path)
        inventory.remove_json_gen_file(path)
        self.assertEqual(0, retval, 'json generator command failed: %s' % msg)

        self.assertIn(
            remote_msg, msg,
            '%s not in remote json_gen output: %s' % (remote_msg, msg))
        self.assertNotIn(local_msg, msg,
                         '%s in remote json_gen output: %s' % (local_msg, msg))
예제 #2
0
    def group_remove(self, groupnames):
        # type: (List[str]) -> None
        """Remove groups from the inventory

        :param groupnames: names of the groups to remove from the inventory
        :type groupnames: list of strings
        """
        check_arg(groupnames, u._('Group names'), list)
        groupnames = safe_decode(groupnames)

        inventory = Inventory.load()
        for groupname in groupnames:
            inventory.remove_group(groupname)
        Inventory.save(inventory)
예제 #3
0
    def group_add(self, groupnames):
        # type: (List[str]) -> None
        """Add groups to the inventory

        :param groupnames: names of the groups to add to the inventory
        :type groupnames: list of strings

        """
        check_arg(groupnames, u._('Group names'), list)
        groupnames = safe_decode(groupnames)

        inventory = Inventory.load()
        for groupname in groupnames:
            inventory.add_group(groupname)
        Inventory.save(inventory)
예제 #4
0
def _add_cmd_info(tar):
    # run all the kollacli list commands
    cmds = [
        'kolla-cli --version', 'kolla-cli service listgroups',
        'kolla-cli service list', 'kolla-cli group listservices',
        'kolla-cli group listhosts', 'kolla-cli host list',
        'kolla-cli property list', 'kolla-cli password list'
    ]

    # collect the json inventory output
    inventory = Inventory.load()
    inv_path = inventory.create_json_gen_file()
    cmds.append(inv_path)

    try:
        fd, path = tempfile.mkstemp(suffix='.tmp')
        os.close(fd)
        with open(path, 'w') as tmp_file:
            for cmd in cmds:
                err_msg, output = run_cmd(cmd, False)
                tmp_file.write('\n\n$ %s\n' % cmd)
                if err_msg:
                    tmp_file.write('Error message: %s\n' % err_msg)
                for line in output.split('\n'):
                    tmp_file.write(line + '\n')

        tar.add(path, arcname=os.path.join('kolla', 'cmds_output'))
    except Exception as e:
        raise e
    finally:
        if path:
            os.remove(path)
        inventory.remove_json_gen_file(inv_path)
    return
예제 #5
0
    def _get_services(self, servicenames, get_all=False):
        # type: (List[str], bool) -> List[Service]
        services = []
        inventory = Inventory.load()

        if get_all:
            inv_services = inventory.get_services(client_filter=True)
            for inv_service in inv_services:
                service = Service(inv_service.name,
                                  inv_service.get_parentnames(),
                                  inv_service.get_childnames(),
                                  inv_service.get_groupnames())
                services.append(service)
        else:
            inventory.validate_servicenames(servicenames, client_filter=True)

            for servicename in servicenames:
                inv_service = inventory.get_service(servicename,
                                                    client_filter=True)
                if inv_service:
                    service = Service(inv_service.name,
                                      inv_service.get_parentnames(),
                                      inv_service.get_childnames(),
                                      inv_service.get_groupnames())
                services.append(service)
        return services
예제 #6
0
    def config_import_inventory(self, file_path):
        # type: (str) -> None
        """Config Import Inventory

        Import groups and child associations from the provided
        inventory file. This currently does not import hosts, group
        vars, or host vars that may also exist in the inventory file.

        :param file_path: path to inventory file to import
        :type file_path: string
        """
        check_arg(file_path, u._('File path'), str)
        if not os.path.isfile(file_path):
            raise InvalidArgument(
                u._('File {path} is not valid.').format(path=file_path))
        inventory = Inventory(file_path)
        Inventory.save(inventory)
예제 #7
0
    def host_remove(hostnames):
        # type: (List[str]) -> None
        """Remove hosts from the inventory

        :param hostnames: list of strings
        """
        check_arg(hostnames, u._('Host names'), list)
        hostnames = safe_decode(hostnames)

        inventory = Inventory.load()
        any_changed = False
        for hostname in hostnames:
            changed = inventory.remove_host(hostname)
            if changed:
                any_changed = True
        if any_changed:
            Inventory.save(inventory)
예제 #8
0
    def set_deploy_mode(remote_mode):
        # type: (bool) -> None
        """Set deploy mode.

        Set deploy mode to either local or remote. Local indicates
        that the openstack deployment will be to the local host.
        Remote means that the deployment is executed via ssh.

        NOTE: local mode is not supported and should never be used
        in production environments.

        :param remote_mode: if remote mode is True deployment is done via ssh
        :type remote_mode: bool
        """
        check_arg(remote_mode, u._('Remote mode'), bool)
        inventory = Inventory.load()
        inventory.set_deploy_mode(remote_mode)
        Inventory.save(inventory)
예제 #9
0
def get_logs(servicenames, hostname, dirname):
    inventory = Inventory.load()
    inventory.validate_hostnames([hostname])
    inventory.validate_servicenames(servicenames, client_filter=True)

    logs = HostLogs(hostname, inventory, servicenames)
    logs.load_container_info()
    logs.filter_services()
    logs.write_logs(dirname)
예제 #10
0
    def add_service(self, servicename):
        # type: (str) -> None
        """Add service to group

        :param servicename: name of the service to add to the group
        :type servicename: string
        """
        check_arg(servicename, u._('Service name'), str)
        servicename = safe_decode(servicename)
        inventory = Inventory.load()
        inventory.validate_servicenames([servicename], client_filter=True)

        group_services = inventory.get_group_services()
        self._servicenames = group_services[self.name]
        if servicename not in self._servicenames:
            # service not associated with group, add it
            inventory.add_group_to_service(self.name, servicename)
            self._servicenames.append(servicename)
            Inventory.save(inventory)
예제 #11
0
 def test_ceph(self):
     # ceph has an odd structure in the upstream all-in-one file.
     # It was changed in 3.0.1 of kolla. This test is to check that
     # the kolla change was not overwritten by a kolla update from upstream.
     # If the upstream file is used, ceph will default to having no
     # groups.
     inventory = Inventory.load()
     ceph = inventory.get_service('ceph')
     groups = ceph.get_groupnames()
     self.assertIsNot(groups, 'ceph has no groups, could be due to '
                      'using an unpatched upstream all-in-one file.')
예제 #12
0
    def remove_host(self, hostname):
        # type: (str) -> None
        """Remove host from group

        :param hostname: name of the host to remove from the group
        :type hostname: string

        """
        check_arg(hostname, u._('Host name'), str)
        hostname = safe_decode(hostname)
        inventory = Inventory.load()
        inventory.validate_hostnames([hostname])

        group = inventory.get_group(self.name)
        self._hostnames = group.get_hostnames()
        if hostname in self._hostnames:
            # host is associated with group, remove it
            inventory.remove_host(hostname, self.name)
            self._hostnames.remove(hostname)
            Inventory.save(inventory)
예제 #13
0
    def add_host(self, hostname):
        # type: (str) -> None
        """Add host to group

        :param hostname: name of the host to add to the group
        :type hostname: string

        """
        check_arg(hostname, u._('Host name'), str)
        hostname = safe_decode(hostname)
        inventory = Inventory.load()
        inventory.validate_hostnames([hostname])

        group = inventory.get_group(self.name)
        self._hostnames = group.get_hostnames()
        if hostname not in self._hostnames:
            # host not associated with group, add it
            inventory.add_host(hostname, self.name)
            self._hostnames.append(hostname)
            Inventory.save(inventory)
예제 #14
0
파일: utils.py 프로젝트: run4life/kolla-cli
def check_kolla_args(hostnames=[], servicenames=[]):

    if not any([hostnames, servicenames]):
        return

    inventory = Inventory.load()
    if hostnames:
        inventory.validate_hostnames(hostnames)

    if servicenames:
        inventory.validate_servicenames(servicenames)
예제 #15
0
    def remove_service(self, servicename):
        # type: (str) -> None
        """Remove service from group

        :param servicename: name of the service to remove from the group
        :type servicename: string

        """
        check_arg(servicename, u._('Service name'), str)
        servicename = safe_decode(servicename)
        inventory = Inventory.load()
        inventory.validate_servicenames([servicename], client_filter=True)

        group_services = inventory.get_group_services()
        self._servicenames = group_services[self.name]
        if servicename in self._servicenames:
            # service is associated with group, remove it
            inventory.remove_group_from_service(self.name, servicename)
            self._servicenames.remove(servicename)
            Inventory.save(inventory)
예제 #16
0
    def run(self):
        try:
            if self.local_only:
                # Create a temporary local inventory with only localhost
                self.inventory = Inventory()
                self.inventory.set_deploy_mode(False)
                self.inventory.add_host('localhost')
            else:
                self.inventory = Inventory.load()
            inventory_path = self._make_temp_inventory()
            cmd = self._get_playbook_cmd(inventory_path)
            self._log_ansible_cmd(cmd, inventory_path)

            # create and run the job
            job = AnsibleJob(cmd, self.deploy_id, self.print_output,
                             inventory_path)
            job._ignore_error_strings = self.ignore_error_strings
            job.run()
            return job

        except Exception:
            raise Exception(traceback.format_exc())
예제 #17
0
    def host_get_all():
        # type: () -> List[Host]
        """Get all hosts in the inventory

        :return: Hosts
        :rtype: list of Host objects
        """
        inventory = Inventory.load()
        hosts = []
        host_groups = inventory.get_host_groups()
        for hostname, groupnames in host_groups.items():
            hosts.append(Host(hostname, groupnames))
        return hosts
예제 #18
0
    def test_json_filtering(self):

        hosts = ['host_test1', 'host_test2', 'host_test3']
        groups = ['control', 'network', 'storage']

        for host in hosts:
            self.run_cli_cmd('host add %s' % host)
            for groupname in groups:
                group = CLIENT.group_get([groupname])[0]
                group.add_host(host)

        inventory = Inventory.load()

        # filter by host- include all hosts
        inv_filter = {'deploy_hosts': hosts}
        path = inventory.create_json_gen_file(inv_filter)
        self.log.info('run command: %s' % path)
        (retval, msg) = self.run_command(path)
        inventory.remove_json_gen_file(path)
        self.assertEqual(0, retval, 'json generator command failed: %s' % msg)

        self.check_json(msg, groups, hosts, groups, hosts)

        # filter by host- to first host
        included_host = hosts[0]
        inv_filter = {'deploy_hosts': [included_host]}
        path = inventory.create_json_gen_file(inv_filter)
        self.log.info('run command: %s' % path)
        (retval, msg) = self.run_command(path)
        inventory.remove_json_gen_file(path)
        self.assertEqual(0, retval, 'json generator command failed: %s' % msg)
        self.check_json(msg, groups, hosts, groups, [included_host])

        # filter by group- include all groups
        inv_filter = {'deploy_groups': groups}
        path = inventory.create_json_gen_file(inv_filter)
        self.log.info('run command: %s' % path)
        (retval, msg) = self.run_command(path)
        inventory.remove_json_gen_file(path)
        self.assertEqual(0, retval, 'json generator command failed: %s' % msg)
        self.check_json(msg, groups, hosts, groups, hosts)

        # filter by group- to first group
        included_group = groups[0]
        inv_filter = {'deploy_groups': [included_group]}
        path = inventory.create_json_gen_file(inv_filter)
        self.log.info('run command: %s' % path)
        (retval, msg) = self.run_command(path)
        inventory.remove_json_gen_file(path)
        self.assertEqual(0, retval, 'json generator command failed: %s' % msg)
        self.check_json(msg, groups, hosts, [included_group], hosts)
예제 #19
0
    def get_deploy_mode():
        """Get deploy mode from either local or remote.

        Local indicates that the openstack deployment will be
        to the local host. Remote means that the deployment is
        executed via ssh.

        NOTE: local mode is not supported and should never be used
        in production environments.
        """
        inventory = Inventory.load()
        remote_mode = inventory.remote_mode
        deploy_mode = 'remote' if remote_mode else 'local'
        return deploy_mode
예제 #20
0
    def run(self):
        try:
            self.inventory = Inventory.load()
            inventory_path = self._make_temp_inventory()
            cmd = self._get_playbook_cmd(inventory_path)
            self._log_ansible_cmd(cmd, inventory_path)

            # create and run the job
            job = AnsibleJob(cmd, self.deploy_id, self.print_output,
                             inventory_path)
            job._ignore_error_strings = self.ignore_error_strings
            job.run()
            return job

        except Exception:
            raise Exception(traceback.format_exc())
예제 #21
0
    def _get_groups(self, groupnames, get_all=False):
        # type: (List[str], bool) -> List[Group]
        groups = []
        inventory = Inventory.load()
        if get_all:
            groupnames = inventory.get_groupnames()
        else:
            inventory.validate_groupnames(groupnames)

        group_services = inventory.get_group_services()
        for groupname in groupnames:
            inv_group = inventory.get_group(groupname)
            group = Group(groupname, group_services[groupname],
                          inv_group.get_hostnames())
            groups.append(group)
        return groups
예제 #22
0
    def host_get(hostnames):
        # type: (List[str]) -> List[Host]
        """Get selected hosts in the inventory

        :param hostnames: list of strings
        :return: hosts
        :rtype: list of Host objects
        """
        check_arg(hostnames, u._('Host names'), list)
        hostnames = safe_decode(hostnames)
        inventory = Inventory.load()
        inventory.validate_hostnames(hostnames)

        hosts = []
        host_groups = inventory.get_host_groups()
        for hostname in hostnames:
            hosts.append(Host(hostname, host_groups[hostname]))
        return hosts
예제 #23
0
    def _run_deploy_rules(self, playbook):
        properties = AnsibleProperties()
        inventory = Inventory.load()

        # cannot have both groups and hosts
        if playbook.hosts and playbook.groups:
            raise InvalidArgument(
                u._('Hosts and Groups arguments cannot '
                    'both be present at the same time.'))

        # verify that all services exists
        if playbook.services:
            for service in playbook.services:
                valid_service = inventory.get_service(service)
                if not valid_service:
                    raise NotInInventory(u._('Service'), service)

        # check that every group with enabled services
        # has hosts associated to it
        group_services = inventory.get_group_services()
        failed_groups = []
        failed_services = []
        if group_services:
            for (groupname, servicenames) in group_services.items():
                group = inventory.get_group(groupname)
                hosts = group.get_hostnames()

                group_needs_host = False
                if not hosts:
                    for servicename in servicenames:
                        if self._is_service_enabled(servicename, inventory,
                                                    properties):
                            group_needs_host = True
                            failed_services.append(servicename)
                    if group_needs_host:
                        failed_groups.append(groupname)

            if len(failed_groups) > 0:
                raise InvalidConfiguration(
                    u._('Deploy failed. '
                        'Groups: {groups} with enabled '
                        'services : {services} '
                        'have no associated hosts').format(
                            groups=failed_groups, services=failed_services))
예제 #24
0
    def host_setup(hosts_info):
        # type: (Dict[str,Dict[str,object]]) -> None
        """Setup multiple hosts for ssh access

        hosts_info is a dictionary of form:
            - {hostname': {
              'password': password
              'uname': user_name},
              ...
              }

        The uname entry is optional.

        :param hosts_info: dictionary
        """
        check_arg(hosts_info, u._('Hosts info'), dict)
        inventory = Inventory.load()
        inventory.validate_hostnames(hosts_info.keys())
        inventory.setup_hosts(hosts_info)
예제 #25
0
    def host_destroy(hostnames,
                     destroy_type,
                     verbose_level=1,
                     include_data=False,
                     remove_images=False):
        # type: (List[str], str, int, bool, bool) -> Job
        """Destroy Hosts.

        Stops and removes all kolla related docker containers on the
        specified hosts.

        :param hostnames: host names
        :type hostnames: list
        :param destroy_type: either 'kill' or 'stop'
        :type destroy_type: string
        :param verbose_level: the higher the number, the more verbose
        :type verbose_level: integer
        :param include_data: if true, destroy data containers too.
        :type include_data: boolean
        :param remove_images: if true, destroy will remove the docker images
        :type remove_images: boolean
        :return: Job object
        :rtype: Job
        """
        check_arg(hostnames, u._('Host names'), list)
        check_arg(destroy_type, u._('Destroy type'), str)
        check_arg(verbose_level, u._('Verbose level'), int)
        check_arg(include_data, u._('Include data'), bool)
        check_arg(remove_images, u._('Remove images'), bool)
        if destroy_type not in ['stop', 'kill']:
            raise InvalidArgument(
                u._('Invalid destroy type ({type}). Must be either '
                    '"stop" or "kill".').format(type=destroy_type))

        hostnames = safe_decode(hostnames)
        inventory = Inventory.load()
        inventory.validate_hostnames(hostnames)

        action = KollaAction(verbose_level=verbose_level,
                             playbook_name='destroy.yml')
        ansible_job = action.destroy_hosts(hostnames, destroy_type,
                                           include_data, remove_images)
        return Job(ansible_job)
예제 #26
0
    def host_ssh_check(hostnames):
        # type: (List[str]) -> Dict[str,Dict[str,object]]
        """Check hosts for ssh connectivity

        Check status is a dictionary of form:
            - {hostname: {
              'success':<True|False>,
              'msg':message_string},
              ...
              }

        :param hostnames: list of strings
        :return: check status
        :rtype: dictionary
        """
        check_arg(hostnames, u._('Host names'), list)
        inventory = Inventory.load()
        hostnames = safe_decode(hostnames)
        inventory.validate_hostnames(hostnames)
        summary = inventory.ssh_check_hosts(hostnames)
        return summary
예제 #27
0
    def host_precheck(hostnames, verbose_level=1):
        # type: (List[str], int) -> Job
        """Check pre-deployment configuration of hosts.

        Check if host is ready for a new deployment. This will fail if
        any of the hosts are not configured correctly or if they have
        already been deployed to.
        :param hostnames: host names
        :type hostnames: list
        :param verbose_level: the higher the number, the more verbose
        :type verbose_level: integer
        :return: Job object
        :rtype: Job
        """
        check_arg(hostnames, u._('Host names'), list)
        check_arg(verbose_level, u._('Verbose level'), int)
        hostnames = safe_decode(hostnames)
        inventory = Inventory.load()
        inventory.validate_hostnames(hostnames)

        ansible_job = actions.precheck(hostnames, verbose_level)
        return Job(ansible_job)
예제 #28
0
    def host_stop(hostnames, verbose_level=1):
        # type: (List[str], int) -> Job
        """Stop Hosts.

        Stops all kolla related docker containers on the specified hosts.

        :param hostnames: host names
        :type hostnames: list
        :param verbose_level: the higher the number, the more verbose
        :type verbose_level: integer
        :return: Job object
        :rtype: Job
        """
        check_arg(hostnames, u._('Host names'), list)
        check_arg(verbose_level, u._('Verbose level'), int)

        hostnames = safe_decode(hostnames)
        inventory = Inventory.load()
        inventory.validate_hostnames(hostnames)

        ansible_job = actions.stop_hosts(hostnames, verbose_level)
        return Job(ansible_job)
예제 #29
0
    def test_service_add_group(self):
        servicename = 'cinder'
        new_group = 'network'

        inventory = Inventory.load()
        service = inventory.get_service(servicename)
        groupnames = service.get_groupnames()

        # add new group to a service
        self.run_cli_cmd('service addgroup %s %s' % (servicename, new_group))

        msg = self.run_cli_cmd('service listgroups -f json')
        cli_services = json.loads(msg)
        cli_service = ''
        for svc in cli_services:
            if svc['Service'] == servicename:
                cli_service = svc
                break
        self.assertNotEqual(cli_service, '',
                            'service: %s, ' % servicename +
                            'not found in cli_services: \n%s'
                            % cli_service)
        cli_groups = cli_service['Groups']
        groupnames.append(new_group)
        self.assertEqual(groupnames, cli_groups,
                         'service: %s, ' % service +
                         'expected groups: %s, ' % groupnames +
                         'cli_groups: %s' % cli_groups)

        # remove that group
        self.run_cli_cmd('service removegroup %s %s' % (servicename,
                                                        new_group))
        groupnames.remove(new_group)

        msg = self.run_cli_cmd('service listgroups -f json')
        cli_services = json.loads(msg)
        for svc in cli_services:
            if svc['Service'] == servicename:
                cli_service = svc
                break
        self.assertNotEqual(cli_service, '',
                            'service: %s, ' % servicename +
                            'not found in cli_services: \n%s'
                            % cli_service)
        cli_groups = cli_service['Groups']
        expected_groups = groupnames
        self.assertEqual(expected_groups, cli_groups,
                         'service: %s, ' % service +
                         'expected groups: %s, ' % expected_groups +
                         'cli_groups: %s' % cli_groups)

        # add new group to a service which has a parent
        servicename = 'glance-api'
        new_group = 'control'
        self.run_cli_cmd('service addgroup %s %s' % (servicename, new_group))

        msg = self.run_cli_cmd('service listgroups -f json')
        cli_services = json.loads(msg)
        for svc in cli_services:
            if svc['Service'] == servicename:
                cli_service = svc
                break
        self.assertNotEqual(cli_service, '',
                            'service: %s, ' % servicename +
                            'not found in cli_services: \n%s'
                            % cli_service)
        cli_groups = cli_service['Groups']
        expected_groups = ['%s' % new_group]
        self.assertEqual(expected_groups, cli_groups,
                         'service: %s, ' % service +
                         'expected groups: %s, ' % expected_groups +
                         'cli_groups: %s' % cli_groups)

        # remove that group
        self.run_cli_cmd('service removegroup %s %s' % (servicename,
                                                        new_group))

        msg = self.run_cli_cmd('service listgroups -f json')
        cli_services = json.loads(msg)
        for svc in cli_services:
            if svc['Service'] == servicename:
                cli_service = svc
                break
        self.assertNotEqual(cli_service, '',
                            'service: %s, ' % service +
                            'not found in cli_services: \n%s'
                            % cli_service)
        cli_groups = cli_service['Groups']
        expected_groups = []
        self.assertEqual(expected_groups, cli_groups,
                         'service: %s, ' % servicename +
                         'expected groups: %s, ' % expected_groups +
                         'cli_groups: %s' % cli_groups)

        test_group = 'testgroup'
        self.run_cli_cmd('group add %s' % test_group)
        self.run_cli_cmd('service addgroup cinder %s' % test_group)
        self.run_cli_cmd('group remove %s' % test_group)
        msg = self.run_cli_cmd('service listgroups -f json')
        self.assertNotIn(test_group, msg,
                         'Group: %s, still listed in services: %s'
                         % (test_group, msg))
예제 #30
0
class AnsiblePlaybook(object):
    playbook_path = ''
    extra_vars = ''
    include_passwords = True
    flush_cache = True
    print_output = True
    verbose_level = 0
    hosts = None  # type: List[str]
    groups = None  # type: List[str]
    services = None  # type: List[str]
    ignore_error_strings = None  # type: List[str]
    serial = False
    deploy_id = None  # type: str
    inventory = None  # type: Inventory
    local_only = False
    become_user = None  # type: str

    def run(self):
        try:
            if self.local_only:
                # Create a temporary local inventory with only localhost
                self.inventory = Inventory()
                self.inventory.set_deploy_mode(False)
                self.inventory.add_host('localhost')
            else:
                self.inventory = Inventory.load()
            inventory_path = self._make_temp_inventory()
            cmd = self._get_playbook_cmd(inventory_path)
            self._log_ansible_cmd(cmd, inventory_path)

            # create and run the job
            job = AnsibleJob(cmd, self.deploy_id, self.print_output,
                             inventory_path)
            job._ignore_error_strings = self.ignore_error_strings
            job.run()
            return job

        except Exception:
            raise Exception(traceback.format_exc())

    def _get_playbook_cmd(self, inventory_path):
        flag = ''
        # verbose levels: 1=not verbose, 2=more verbose
        if self.verbose_level > 1:
            flag = '-'
            for x in range(1, self.verbose_level):
                flag += 'v'

        ansible_cmd = get_ansible_command(playbook=True)
        cmd = '%s %s' % (ansible_cmd, flag)

        cmd += ' -i %s' % inventory_path

        if self.include_passwords:
            cmd += ' %s' % self._get_password_path()

        cmd += ' %s' % self.playbook_path

        if self.extra_vars or self.serial:
            extra_vars = ''
            if self.extra_vars:
                extra_vars = self.extra_vars
                if self.serial:
                    extra_vars += ' '
            if self.serial:
                extra_vars += 'serial_var=1'

            cmd += ' --extra-vars \"%s\"' % extra_vars

        if self.services:
            service_string = ''
            first = True
            for service in self.services:
                if not first:
                    service_string += ','
                else:
                    first = False
                service_string = service_string + service
            cmd += ' --tags %s' % service_string

        if self.hosts:
            host_string = ''
            first = True
            for host in self.hosts:
                if not first:
                    host_string += ','
                else:
                    first = False
                host_string = host_string + host
            cmd += ' --limit %s' % host_string

        if self.flush_cache:
            cmd += ' --flush-cache'

        if self.become_user:
            cmd += ' --become-user %s' % self.become_user

        return cmd

    def _make_temp_inventory(self):
        """Create temporary inventory file

        A temporary inventory is created so that a
        unique id can be assigned to the deployment.
        """
        inventory_filter = {}
        inventory_path = \
            self.inventory.create_json_gen_file(inventory_filter)

        # inv path = /tmp/kolla_UUID/temp_inventory.py
        deploy_id = os.path.dirname(inventory_path)
        self.deploy_id = deploy_id.split('kolla_')[1]

        return inventory_path

    def _get_password_path(self):
        kolla_etc = get_kolla_etc()
        return ('-e @' + os.path.join(kolla_etc, 'passwords.yml '))

    def _log_ansible_cmd(self, cmd, inventory_path):
        if self.verbose_level > 2:
            # log the ansible command
            LOG.debug('cmd:\n%s' % cmd)

            if self.verbose_level > 3:
                # log the inventory
                with open(inventory_path, 'r') as inv_file:
                    inv = inv_file.read()
                LOG.debug('\ninventory: \n%s' % inv)