Exemple #1
0
def _pre_setup_checks(ssh_client, log):
    cmd = 'docker --version'
    msg, errmsg = _exec_ssh_cmd(cmd, ssh_client, log)
    if errmsg:
        raise CommandError("'%s' failed. Is docker installed? : %s" %
                           (cmd, errmsg))
    if 'Docker version' not in msg:
        raise CommandError("'%s' failed. Is docker installed? : %s" %
                           (cmd, msg))

    version = msg.split('version ')[1].split(',')[0]
    if StrictVersion(version) < StrictVersion(MIN_DOCKER_VERSION):
        raise CommandError('docker version (%s) below minimum (%s)' %
                           (version, msg))

    # docker is installed, now check if it is running
    cmd = 'docker info'
    _, errmsg = _exec_ssh_cmd(cmd, ssh_client, log)
    # docker info can return warning messages in stderr, ignore them
    if errmsg and 'WARNING' not in errmsg:
        raise CommandError("'%s' failed. Is docker running? : %s" %
                           (cmd, errmsg))

    # check for docker-py
    cmd = 'python -c "import docker"'
    msg, errmsg = _exec_ssh_cmd(cmd, ssh_client, log)
    if errmsg:
        raise CommandError('host check failed. ' + 'Is docker-py installed?')
Exemple #2
0
    def add_host(self, hostname, groupname=None):
        """add host

        if groupname is none, create a new host
        if group name is not none, add host to group
        """
        if groupname and groupname not in self._groups:
            raise CommandError('Group name (%s) does not exist' % groupname)

        if groupname and hostname not in self._hosts:
            raise CommandError('Host name (%s) does not exist' % hostname)

        if not groupname and not self.remote_mode and len(self._hosts) >= 1:
            raise CommandError('Cannot have more than one host when in ' +
                               'local deploy mode')

        # create new host if it doesn't exist
        host = Host(hostname)
        if hostname not in self.get_hostnames():
            # a new host is being added to the inventory
            self._hosts[hostname] = host

        # a host is to be added to an existing group
        elif groupname:
            group = self._groups[groupname]
            if hostname not in group.get_hostnames():
                group.add_host(host)
Exemple #3
0
    def __init__(self):
        super(KollaCli, self).__init__(
            description='Command-Line Client for OpenStack Kolla',
            version='0.1',
            command_manager=CommandManager('kolla.cli'),
        )

        # check that current user is in the kolla group
        inventory_path = os.path.join(get_kollacli_etc(), INVENTORY_PATH)
        errString = 'Required file %s does not exist.\n' + \
                    'Please re-install the kollacli to recreate the file.'
        if os.path.isfile(inventory_path) is False:
            raise CommandError(errString % inventory_path)

        inventory_file = None
        try:
            inventory_file = open(inventory_path, 'r+')
        except Exception:
            raise CommandError('Permission denied to run the kollacli.' +
                               '\nPlease add user to the kolla group and ' +
                               'then log out and back in.')
        finally:
            if inventory_file and inventory_file.close is False:
                inventory_file.close()

        self.rotating_log_dir = get_kolla_log_dir()
        self.max_bytes = get_kolla_log_file_size()
        self.backup_count = 4

        self.dump_stack_trace = False

        self.add_rotational_log()
Exemple #4
0
 def remove_group_from_service(self, groupname, servicename):
     if groupname not in self._groups:
         raise CommandError('Group (%s) not found.' % groupname)
     if servicename in self._services:
         service = self.get_service(servicename)
         service.remove_groupname(groupname)
     elif servicename in self._sub_services:
         sub_service = self.get_sub_service(servicename)
         sub_service.remove_groupname(groupname)
     else:
         raise CommandError('Service (%s) not found.' % servicename)
Exemple #5
0
    def get_yml_data(self, yml_path):
        if not os.path.isfile(yml_path):
            raise CommandError('No file exists at %s. ' % yml_path +
                               'An absolute file path is required.')

        with open(yml_path, 'r') as hosts_file:
            file_data = hosts_file.read()

        hosts_info = yaml.load(file_data)
        if not hosts_info:
            raise CommandError('%s is empty' % yml_path)
        return hosts_info
Exemple #6
0
    def setup_hosts(self, hosts_info):
        """setup multiple hosts

        hosts_info is a dict of format:
        {'hostname1': {
            'password': password
            'uname': user_name
            }
        }
        The uname entry is optional.
        """
        failed_hosts = {}
        for hostname, host_info in hosts_info.items():
            host = self.get_host(hostname)
            if not host:
                failed_hosts[hostname] = "Host doesn't exist"
                continue
            if not host_info or 'password' not in host_info:
                failed_hosts[hostname] = 'No password in yml file'
                continue
            passwd = host_info['password']
            uname = None
            if 'uname' in host_info:
                uname = host_info['uname']
            try:
                self.setup_host(hostname, passwd, uname)
            except Exception as e:
                failed_hosts[hostname] = '%s' % e
        if failed_hosts:
            summary = '\n'
            for hostname, err in failed_hosts.items():
                summary = summary + '- %s: %s\n' % (hostname, err)
            raise CommandError('Not all hosts were set up: %s' % summary)
        else:
            self.log.info('All hosts were successfully set up')
Exemple #7
0
def _post_setup_checks(net_addr, log):
    try:
        ssh_client = ssh_connect(net_addr, get_admin_user(), '')

    except Exception as e:
        raise CommandError("remote login failed : %s" % e)

    try:
        # a basic test
        ssh_client.exec_command('ls')

    except Exception as e:
        raise CommandError("remote command 'ls' failed : %s" % e)

    finally:
        _close_ssh_client(ssh_client)
Exemple #8
0
    def take_action(self, parsed_args):
        try:
            if parsed_args.hosts and parsed_args.groups:
                raise CommandError('Hosts and Groups arguments cannot both ' +
                                   'be present at the same time.')

            self._run_rules()

            playbook = AnsiblePlaybook()
            kolla_home = get_kolla_home()
            playbook.playbook_path = os.path.join(kolla_home,
                                                  'ansible/site.yml')
            if parsed_args.hosts:
                host_list = parsed_args.hosts.strip()
                host_list = convert_to_unicode(host_list)
                playbook.hosts = host_list.split(',')
            if parsed_args.groups:
                group_list = parsed_args.groups.strip()
                group_list = convert_to_unicode(group_list)
                playbook.groups = group_list.split(',')
            if parsed_args.services:
                tag_list = parsed_args.services.strip()
                tag_list = convert_to_unicode(tag_list)
                playbook.services = tag_list.split(',')
            if parsed_args.serial:
                playbook.serial = True

            playbook.verbose_level = self.app.options.verbose_level
            playbook.run()
        except CommandError as e:
            raise e
        except Exception:
            raise Exception(traceback.format_exc())
Exemple #9
0
    def set_deploy_mode(self, remote_flag):
        if not remote_flag and len(self._hosts) > 1:
            raise CommandError('Cannot set local deploy mode when multiple ' +
                               'hosts exist')
        self.remote_mode = remote_flag

        for group in self.get_groups():
            group.set_remote(remote_flag)
Exemple #10
0
def clear_password(pwd_key):
    """clear a password

    if the password exists, it will be removed from the passwords file
    """
    cmd = '%s -k %s -c' % (_get_cmd_prefix(), pwd_key)
    err_msg, output = utils.run_cmd(cmd, print_output=False)
    if err_msg:
        raise CommandError('%s %s' % (err_msg, output))
Exemple #11
0
def set_password(pwd_key, pwd_value):
    """set a password value

    If the password name exists, it will be changed.
    If it doesn't exist, a new password will be added.
    """
    cmd = '%s -k %s -v %s' % (_get_cmd_prefix(), pwd_key, pwd_value)
    err_msg, output = utils.run_cmd(cmd, print_output=False)
    if err_msg:
        raise CommandError('%s %s' % (err_msg, output))
Exemple #12
0
def get_password_names():
    """return a list of password names"""
    cmd = '%s -l' % (_get_cmd_prefix())
    err_msg, output = utils.run_cmd(cmd, print_output=False)
    if err_msg:
        raise CommandError('%s %s' % (err_msg, output))

    pwd_names = []
    if output and ',' in output:
        pwd_names = output.strip().split(',')
    return pwd_names
Exemple #13
0
    def take_action(self, parsed_args):
        try:
            if not parsed_args.hostname and not parsed_args.file:
                raise CommandError('Hostname or hosts info file path ' +
                                   'is required')
            if parsed_args.hostname and parsed_args.file:
                raise CommandError('Hostname and hosts info file path ' +
                                   'cannot both be present')
            inventory = Inventory.load()

            if parsed_args.file:
                # multi-host setup via xml file
                hosts_data = self.get_yml_data(parsed_args.file.strip())
                inventory.setup_hosts(hosts_data)
            else:
                # single host setup
                hostname = parsed_args.hostname.strip()
                hostname = utils.convert_to_unicode(hostname)
                if not inventory.get_host(hostname):
                    _host_not_found(self.log, hostname)

                check_ok = inventory.check_host(hostname, True)
                if check_ok:
                    self.log.info(
                        'Skipping setup of host (%s) as check is ok' %
                        hostname)
                    return True

                if parsed_args.insecure:
                    password = parsed_args.insecure.strip()
                else:
                    setup_user = get_setup_user()
                    password = getpass.getpass('%s password for %s: ' %
                                               (setup_user, hostname))
                password = utils.convert_to_unicode(password)
                inventory.setup_host(hostname, password)

        except CommandError as e:
            raise e
        except Exception as e:
            raise Exception(traceback.format_exc())
Exemple #14
0
    def save(inventory):
        """Save the inventory in a pickle file"""
        inventory_path = os.path.join(utils.get_kollacli_etc(), INVENTORY_PATH)
        try:
            # multiple trips thru json to render a readable inventory file
            data = jsonpickle.encode(inventory)
            data_str = json.loads(data)
            pretty_data = json.dumps(data_str, indent=4)
            utils.sync_write_file(inventory_path, pretty_data)

        except Exception as e:
            raise CommandError('saving inventory failed: %s' % e)
Exemple #15
0
    def remove_group(self, groupname):
        if groupname in PROTECTED_GROUPS:
            raise CommandError('Cannot remove %s group. ' % groupname +
                               'It is required by kolla.')

        # remove group from services & subservices
        for service in self._services.values():
            service.remove_groupname(groupname)

        for subservice in self._sub_services.values():
            subservice.remove_groupname(groupname)

        if groupname in self._groups:
            del self._groups[groupname]
Exemple #16
0
    def add_group(self, groupname):

        # Group names cannot overlap with service names:
        if groupname in self._services or groupname in self._sub_services:
            raise CommandError('Invalid group name. A service name '
                               'cannot be used for a group name.')

        if groupname not in self._groups:
            self._groups[groupname] = HostGroup(groupname)

        group = self._groups[groupname]

        group.set_remote(self.remote_mode)

        return group
Exemple #17
0
 def take_action(self, parsed_args):
     try:
         mode = parsed_args.mode.strip()
         remote_flag = False
         if mode == 'remote':
             remote_flag = True
         elif mode != 'local':
             raise CommandError('Invalid deploy mode. Mode must be ' +
                                'either "local" or "remote"')
         inventory = Inventory.load()
         inventory.set_deploy_mode(remote_flag)
         Inventory.save(inventory)
     except CommandError as e:
         raise e
     except Exception:
         raise Exception(traceback.format_exc())
Exemple #18
0
 def _run_rules(self):
     # check that ring files are in /etc/kolla/config/swift if
     # swift is enabled
     expected_files = ['account.ring.gz',
                       'container.ring.gz',
                       'object.ring.gz']
     properties = AnsibleProperties()
     is_enabled = properties.get_property('enable_swift')
     if is_enabled == 'yes':
         path_pre = os.path.join(get_kolla_etc(), 'config', 'swift')
         for expected_file in expected_files:
             path = os.path.join(path_pre, expected_file)
             if not os.path.isfile(path):
                 msg = ('Deploy failed. ' +
                        'Swift is enabled but ring buffers have ' +
                        'not yet been set up. Please see the ' +
                        'documentation for swift configuration ' +
                        'instructions.')
                 raise CommandError(msg)
Exemple #19
0
    def remove_host(self, hostname, groupname=None):
        """remove host

        if groupname is none, delete host
        if group name is not none, remove host from group
        """
        if groupname and groupname not in self._groups:
            raise CommandError('Group name (%s) does not exist' % groupname)

        if hostname not in self._hosts:
            return

        host = self._hosts[hostname]
        groups = self.get_groups(host)
        for group in groups:
            if not groupname or groupname == group.name:
                group.remove_host(host)

        if not groupname:
            del self._hosts[hostname]
Exemple #20
0
    def load():
        """load the inventory from a pickle file"""
        inventory_path = os.path.join(utils.get_kollacli_etc(), INVENTORY_PATH)
        data = ''
        try:
            if os.path.exists(inventory_path):
                data = utils.sync_read_file(inventory_path)

            if data.strip():
                inventory = jsonpickle.decode(data)

                # upgrade version handling
                if inventory.version != inventory.class_version:
                    inventory.upgrade()
            else:
                inventory = Inventory()
        except Exception:
            raise CommandError('loading inventory failed: %s' %
                               traceback.format_exc())
        return inventory
Exemple #21
0
def _host_not_found(log, hostname):
    raise CommandError('Host (%s) not found. ' % hostname +
                       'Please add it with "host add"')
Exemple #22
0
    def run(self):
        globals_string = None
        password_string = None
        inventory_path = None
        cmd = ''
        try:
            flag = ''
            # verbose levels: 1=not verbose, 2=more verbose
            if self.verbose_level > 1:
                flag = '-vvv'

            admin_user = get_admin_user()
            command_string = ('/usr/bin/sudo -u %s ansible-playbook %s' %
                              (admin_user, flag))
            inventory = Inventory.load()
            inventory_filter = {}
            if self.hosts:
                for hostname in self.hosts:
                    host = inventory.get_host(hostname)
                    if not host:
                        raise CommandError('Host (%s) not found. ' % hostname)
                inventory_filter['deploy_hosts'] = self.hosts
            elif self.groups:
                for groupname in self.groups:
                    group = inventory.get_group(groupname)
                    if not group:
                        raise CommandError('Group (%s) not found. ' %
                                           groupname)
                inventory_filter['deploy_groups'] = self.groups

            inventory_path = inventory.create_json_gen_file(inventory_filter)
            inventory_string = '-i ' + inventory_path
            cmd = (command_string + ' ' + inventory_string)

            if self.include_globals:
                globals_string = self._get_globals_path()
                cmd = (cmd + ' ' + globals_string)

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

            cmd = (cmd + ' ' + 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 = (cmd + ' --extra-vars \"' + extra_vars + '\"')

            if self.services:
                service_string = ''
                first = True
                for service in self.services:
                    valid_service = inventory.get_service(service)
                    if not valid_service:
                        raise CommandError('Service (%s) not found. ' %
                                           service)
                    if not first:
                        service_string = service_string + ','
                    else:
                        first = False
                    service_string = service_string + service
                cmd = (cmd + ' --tags ' + service_string)

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

            if self.verbose_level > 1:
                # log the ansible command
                self.log.debug('cmd:' + cmd)

                if self.verbose_level > 2:
                    # log the inventory
                    dbg_gen = inventory_path
                    (inv, _) = \
                        subprocess.Popen(dbg_gen.split(' '),
                                         stdout=subprocess.PIPE,
                                         stderr=subprocess.PIPE).communicate()
                    self.log.debug(inv)

            err_msg, output = run_cmd(cmd, self.print_output)
            if err_msg:
                if not self.print_output:
                    # since the user didn't see the output, include it in
                    # the error message
                    err_msg = '%s %s' % (err_msg, output)
                raise CommandError(err_msg)

            self.log.info('Success')
        except CommandError as e:
            raise e
        except Exception:
            raise Exception(traceback.format_exc())
        finally:
            if inventory_path:
                os.remove(inventory_path)