Exemple #1
0
    def __init__(self,
                 vg_name,
                 root_helper,
                 create_vg=False,
                 physical_volumes=None,
                 lvm_type='default',
                 executor=putils.execute,
                 lvm_conf=None,
                 suppress_fd_warn=False):
        """Initialize the LVM object.

        The LVM object is based on an LVM VolumeGroup, one instantiation
        for each VolumeGroup you have/use.

        :param vg_name: Name of existing VG or VG to create
        :param root_helper: Execution root_helper method to use
        :param create_vg: Indicates the VG doesn't exist
                          and we want to create it
        :param physical_volumes: List of PVs to build VG on
        :param lvm_type: VG and Volume type (default, or thin)
        :param executor: Execute method to use, None uses common/processutils
        :param suppress_fd_warn: Add suppress FD Warn to LVM env

        """
        super(LVM, self).__init__(execute=executor, root_helper=root_helper)
        self.vg_name = vg_name
        self.pv_list = []
        self.vg_size = 0.0
        self.vg_free_space = 0.0
        self.vg_lv_count = 0
        self.vg_uuid = None
        self.vg_thin_pool = None
        self.vg_thin_pool_size = 0.0
        self.vg_thin_pool_free_space = 0.0
        self._supports_snapshot_lv_activation = None
        self._supports_lvchange_ignoreskipactivation = None
        self.vg_provisioned_capacity = 0.0

        if lvm_type not in ['default', 'thin']:
            raise exception.Invalid('lvm_type must be "default" or "thin"')

        # Ensure LVM_SYSTEM_DIR has been added to LVM.LVM_CMD_PREFIX
        # before the first LVM command is executed, and use the directory
        # where the specified lvm_conf file is located as the value.

        # NOTE(jdg): We use the temp var here because LVM_CMD_PREFIX is a
        # class global and if you use append here, you'll literally just keep
        # appending values to the global.
        _lvm_cmd_prefix = ['env', 'LC_ALL=C']

        if lvm_conf and os.path.isfile(lvm_conf):
            lvm_sys_dir = os.path.dirname(lvm_conf)
            _lvm_cmd_prefix.append('LVM_SYSTEM_DIR=' + lvm_sys_dir)

        if suppress_fd_warn:
            _lvm_cmd_prefix.append('LVM_SUPPRESS_FD_WARNINGS=1')
        LVM.LVM_CMD_PREFIX = _lvm_cmd_prefix

        lvm_version = LVM.get_lvm_version(root_helper)
        if LVM.get_lvm_version(root_helper) < MINIMUM_LVM_VERSION:
            LOG.warning(
                "LVM version %(current)s is lower than the minimum "
                "supported version: %(supported)s", {
                    'current': lvm_version,
                    'supported': MINIMUM_LVM_VERSION
                })

        if create_vg and physical_volumes is not None:
            try:
                self._create_vg(physical_volumes)
            except putils.ProcessExecutionError as err:
                LOG.exception('Error creating Volume Group')
                LOG.error('Cmd     :%s', err.cmd)
                LOG.error('StdOut  :%s', err.stdout)
                LOG.error('StdErr  :%s', err.stderr)
                raise exception.VolumeGroupCreationFailed(vg_name=self.vg_name)

        if self._vg_exists() is False:
            LOG.error('Unable to locate Volume Group %s', vg_name)
            raise exception.VolumeGroupNotFound(vg_name=vg_name)

        # NOTE: we assume that the VG has been activated outside of Cinder

        if lvm_type == 'thin':
            pool_name = "%s-pool" % self.vg_name
            if self.get_volume(pool_name) is None:
                try:
                    self.create_thin_pool(pool_name)
                except putils.ProcessExecutionError:
                    # Maybe we just lost the race against another copy of
                    # this driver being in init in parallel - e.g.
                    # cinder-volume and cinder-backup starting in parallel
                    if self.get_volume(pool_name) is None:
                        raise

            self.vg_thin_pool = pool_name
            self.activate_lv(self.vg_thin_pool)
        self.pv_list = self.get_all_physical_volumes(root_helper, vg_name)
Exemple #2
0
    def update_volume_group_info(self):
        """Update VG info for this instantiation.

        Used to update member fields of object and
        provide a dict of info for caller.

        :returns: Dictionaries of VG info

        """
        vg_list = self.get_all_volume_groups(self._root_helper, self.vg_name)

        if len(vg_list) != 1:
            LOG.error('Unable to find VG: %s', self.vg_name)
            raise exception.VolumeGroupNotFound(vg_name=self.vg_name)

        self.vg_size = float(vg_list[0]['size'])
        self.vg_free_space = float(vg_list[0]['available'])
        self.vg_lv_count = int(vg_list[0]['lv_count'])
        self.vg_uuid = vg_list[0]['uuid']

        total_vols_size = 0.0
        if self.vg_thin_pool is not None:
            # NOTE(xyang): If providing only self.vg_name,
            # get_lv_info will output info on the thin pool and all
            # individual volumes.
            # get_lv_info(self._root_helper, 'stack-vg')
            # sudo lvs --noheadings --unit=g -o vg_name,name,size
            # --nosuffix stack-vg
            # stack-vg stack-pool               9.51
            # stack-vg volume-13380d16-54c3-4979-9d22-172082dbc1a1  1.00
            # stack-vg volume-629e13ab-7759-46a5-b155-ee1eb20ca892  1.00
            # stack-vg volume-e3e6281c-51ee-464c-b1a7-db6c0854622c  1.00
            #
            # If providing both self.vg_name and self.vg_thin_pool,
            # get_lv_info will output only info on the thin pool, but not
            # individual volumes.
            # get_lv_info(self._root_helper, 'stack-vg', 'stack-pool')
            # sudo lvs --noheadings --unit=g -o vg_name,name,size
            # --nosuffix stack-vg/stack-pool
            # stack-vg stack-pool               9.51
            #
            # We need info on both the thin pool and the volumes,
            # therefore we should provide only self.vg_name, but not
            # self.vg_thin_pool here.
            for lv in self.get_lv_info(self._root_helper, self.vg_name):
                lvsize = lv['size']
                # get_lv_info runs "lvs" command with "--nosuffix".
                # This removes "g" from "1.00g" and only outputs "1.00".
                # Running "lvs" command without "--nosuffix" will output
                # "1.00g" if "g" is the unit.
                # Remove the unit if it is in lv['size'].
                if not lv['size'][-1].isdigit():
                    lvsize = lvsize[:-1]
                if lv['name'] == self.vg_thin_pool:
                    self.vg_thin_pool_size = float(lvsize)
                    tpfs = self._get_thin_pool_free_space(
                        self.vg_name, self.vg_thin_pool)
                    self.vg_thin_pool_free_space = tpfs
                else:
                    total_vols_size = total_vols_size + float(lvsize)
            total_vols_size = round(total_vols_size, 2)

        self.vg_provisioned_capacity = total_vols_size
Exemple #3
0
    def __init__(self, vg_name, root_helper, create_vg=False,
                 physical_volumes=None, lvm_type='default',
                 executor=putils.execute, lvm_conf=None):

        """Initialize the LVM object.

        The LVM object is based on an LVM VolumeGroup, one instantiation
        for each VolumeGroup you have/use.

        :param vg_name: Name of existing VG or VG to create
        :param root_helper: Execution root_helper method to use
        :param create_vg: Indicates the VG doesn't exist
                          and we want to create it
        :param physical_volumes: List of PVs to build VG on
        :param lvm_type: VG and Volume type (default, or thin)
        :param executor: Execute method to use, None uses common/processutils

        """
        super(LVM, self).__init__(execute=executor, root_helper=root_helper)
        self.vg_name = vg_name
        self.pv_list = []
        self.vg_size = 0.0
        self.vg_free_space = 0.0
        self.vg_lv_count = 0
        self.vg_uuid = None
        self.vg_thin_pool = None
        self.vg_thin_pool_size = 0.0
        self.vg_thin_pool_free_space = 0.0
        self._supports_snapshot_lv_activation = None
        self._supports_lvchange_ignoreskipactivation = None
        self.vg_provisioned_capacity = 0.0

        # Ensure LVM_SYSTEM_DIR has been added to LVM.LVM_CMD_PREFIX
        # before the first LVM command is executed, and use the directory
        # where the specified lvm_conf file is located as the value.
        if lvm_conf and os.path.isfile(lvm_conf):
            lvm_sys_dir = os.path.dirname(lvm_conf)
            LVM.LVM_CMD_PREFIX = ['env',
                                  'LC_ALL=C',
                                  'LVM_SYSTEM_DIR=' + lvm_sys_dir]

        if create_vg and physical_volumes is not None:
            self.pv_list = physical_volumes

            try:
                self._create_vg(physical_volumes)
            except putils.ProcessExecutionError as err:
                LOG.exception(_LE('Error creating Volume Group'))
                LOG.error(_LE('Cmd     :%s'), err.cmd)
                LOG.error(_LE('StdOut  :%s'), err.stdout)
                LOG.error(_LE('StdErr  :%s'), err.stderr)
                raise exception.VolumeGroupCreationFailed(vg_name=self.vg_name)

        if self._vg_exists() is False:
            LOG.error(_LE('Unable to locate Volume Group %s'), vg_name)
            raise exception.VolumeGroupNotFound(vg_name=vg_name)

        # NOTE: we assume that the VG has been activated outside of Cinder

        if lvm_type == 'thin':
            pool_name = "%s-pool" % self.vg_name
            if self.get_volume(pool_name) is None:
                try:
                    self.create_thin_pool(pool_name)
                except putils.ProcessExecutionError:
                    # Maybe we just lost the race against another copy of
                    # this driver being in init in parallel - e.g.
                    # cinder-volume and cinder-backup starting in parallel
                    if self.get_volume(pool_name) is None:
                        raise

            self.vg_thin_pool = pool_name
            self.activate_lv(self.vg_thin_pool)
        self.pv_list = self.get_all_physical_volumes(root_helper, vg_name)