示例#1
0
    def _get_map(self):
        """
        Convert dm devices into their pool/rbd_image name. All gateway nodes
        should see the same rbds, and each rbd when mapped through device
        mapper will have the same name, so this gives us a common reference
        point.
        """

        dm_devices = glob.glob('/dev/mapper/[0-255]-*')

        if dm_devices:
            for dm_path in dm_devices:
                key = os.path.basename(dm_path)                     # e.g. 0-198baf12200854
                dm_id = os.path.realpath(dm_path).split('/')[-1]    # e.g. dm-4
                rbd_device = os.listdir('/sys/class/block/{}/slaves'.format(dm_id))[0]    # rbdX
                rbd_num = rbd_device[3:]                            # X
                pool = fread('/sys/devices/rbd/{}/pool'.format(rbd_num))
                image = fread('/sys/devices/rbd/{}/name'.format(rbd_num))

                self.map[key] = {"rbd_name": "{}.{}".format(pool, image),
                                 "rbd_dev": rbd_device}
示例#2
0
 def _get_size_bytes(self):
     """
     return the current size of the rbd from sysfs query
     :return:
     """
     rbd_bytes = 0
     if self.rbd_map:
         rbd_id = self.rbd_map.split('/')[-1]
         rbd_sysfs_path = "/sys/class/block/{}/size".format(rbd_id)
         # size is defined in 512b sectors
         rbd_bytes = int(fread(rbd_sysfs_path)) * 512
     return rbd_bytes
示例#3
0
def set_alua(lun, desired_state='standby'):
    """
    Sets the ALUA state of a LUN (active/standby)
    :param lun: LIO LUN object
    :param desired_state: active or standby state
    :return: None
    """

    alua_state_options = {
        "active": '0',
        "active/unoptimized": '1',
        "standby": '2'
    }
    configfs_path = lun.path
    lun_name = lun.name
    alua_access_state = 'alua/default_tg_pt_gp/alua_access_state'
    alua_access_type = 'alua/default_tg_pt_gp/alua_access_type'
    type_fullpath = os.path.join(configfs_path, alua_access_type)

    if fread(type_fullpath) != 'Implicit':
        logger.info(
            "(set_alua) Switching device alua access type to Implicit - i.e. active path set by gateways"
        )
        fwrite(type_fullpath, '1')
    else:
        logger.debug(
            "(set_alua) lun alua_access_type already set to Implicit - no change needed"
        )

    state_fullpath = os.path.join(configfs_path, alua_access_state)
    if fread(state_fullpath) != alua_state_options[desired_state]:
        logger.debug(
            "(set_alua) Updating alua_access_state for {} to {}".format(
                lun_name, desired_state))
        fwrite(state_fullpath, alua_state_options[desired_state])
    else:
        logger.debug(
            "(set_alua) Skipping alua update - already set to desired state '{}'"
            .format(desired_state))
示例#4
0
    def dm_device_name_from_rbd_map(map_device):
        """
        take a mapped device name /dev/rbdX to determine the /dev/mapper/X
        equivalent by reading the devices attribute files in sysfs
        :param map_device: device path of the form /dev/rbdX
        :return: device mapper name for the rbd device /dev/mapper/<pool>-<image-id>
        """

        rbd_bus_id = map_device[8:]
        dm_uid = None

        # TODO - could fread encounter an IOerror?
        rbd_path = os.path.join('/sys/bus/rbd/devices', rbd_bus_id)
        if os.path.exists(rbd_path):
            pool_id = fread(os.path.join(rbd_path, "pool_id"))
            image_id = fread(os.path.join(rbd_path, "image_id"))
            current_snap = fread(os.path.join(rbd_path, "current_snap"))

            dm_uid = "/dev/mapper/{}-{}".format(pool_id, image_id)
            if current_snap != "-":
                dm_uid += "-{}".format(fread(os.path.join(rbd_path,
                                                          "snap_id")))

        return dm_uid
示例#5
0
    def _get_lun_stats(self):
        iops = Metric("IOPS per LUN per client", "counter")
        read_bytes = Metric("read bytes per LUN per client", "counter")
        write_bytes = Metric("write bytes per LUN client", "counter")

        for node_acl in self._root.node_acls:
            for lun in node_acl.mapped_luns:
                lun_path = lun.path
                lun_name = lun.tpg_lun.storage_object.name
                perf_labels = {
                    "gw_name": self.gw_name,
                    "client_iqn": node_acl.node_wwn,
                    "lun_name": lun_name
                }

                lun_iops = int(
                    fread(
                        os.path.join(lun_path,
                                     "statistics/scsi_auth_intr/num_cmds")))
                mbytes_read = int(
                    fread(
                        os.path.join(lun_path,
                                     "statistics/scsi_auth_intr/read_mbytes")))
                mbytes_write = int(
                    fread(
                        os.path.join(
                            lun_path,
                            "statistics/scsi_auth_intr/write_mbytes")))

                iops.add(perf_labels, lun_iops)
                read_bytes.add(perf_labels, mbytes_read * (1024**2))
                write_bytes.add(perf_labels, mbytes_write * (1024**2))

        self.metrics["ceph_iscsi_lun_iops"] = iops
        self.metrics["ceph_iscsi_lun_read_bytes"] = read_bytes
        self.metrics["ceph_iscsi_lun_write_bytes"] = write_bytes
示例#6
0
    def dm_size_ok(self, rbd_object):
        """
        Check that the dm device matches the request. if the size request is lower than
        current size, just return since resizing down is not support and problematic
        for client filesystems anyway
        :return boolean indicating whether the size matches
        """

        target_bytes = convert_2_bytes(self.size)
        if rbd_object.size_bytes > target_bytes:
            return True

        tmr = 0
        size_ok = False
        rbd_size_ok = False
        dm_path_found = False

        # we have to wait for the rbd size to match, since the rbd could have been
        # resized on another gateway host when this is called from Ansible
        while tmr < settings.config.time_out:
            if rbd_object.size_bytes == target_bytes:
                rbd_size_ok = True
                break
            sleep(settings.config.loop_delay)
            tmr += settings.config.loop_delay

        # since the size matches underneath device mapper, now we ensure the size
        # matches with device mapper - if not issue a resize map request
        if rbd_size_ok:

            # find the dm-X device
            dm_devices = glob.glob('/sys/class/block/dm-*/')
            # convert the full dm_device path to just the name (last component of path
            dm_name = os.path.basename(self.dm_device)

            for dm_dev in dm_devices:
                if fread(os.path.join(dm_dev, 'dm/name')) == dm_name:
                    dm_path_found = True
                    break

            if dm_path_found:

                # size is in sectors, so read it and * 512 = bytes
                dm_size_bytes = int(fread(os.path.join(dm_dev, 'size'))) * 512
                if dm_size_bytes != target_bytes:

                    self.logger.info(
                        "Issuing a resize map for {}".format(dm_name))
                    response = shellcommand(
                        'multipathd resize map {}'.format(dm_name))

                    self.logger.debug("resize result : {}".format(response))
                    dm_size_bytes = int(fread(os.path.join(dm_dev,
                                                           'size'))) * 512

                    if response.lower().startswith(
                            'ok') and dm_size_bytes == target_bytes:
                        size_ok = True
                    else:
                        self.logger.critical(
                            "multipathd resize map for {} failed".format(
                                dm_name))
                else:
                    # size matches
                    size_ok = True
            else:
                self.logger.critical(
                    "Unable to locate a dm-X device for this rbd image - {}".
                    format(self.image))

        return size_ok
示例#7
0
 def _get_preferred(self):
     self._check_self()
     path = "%s/preferred" % self.path
     return int(fread(path))
示例#8
0
 def _get_alua_access_type(self):
     self._check_self()
     path = "%s/alua_access_type" % self.path
     return int(fread(path))
示例#9
0
 def _get_nonop_delay_msecs(self):
     self._check_self()
     path = "%s/nonop_delay_msecs" % self.path
     return int(fread(path))
示例#10
0
 def _get_tpg_id(self):
     self._check_self()
     path = "%s/tg_pt_gp_id" % self.path
     return int(fread(path))
示例#11
0
 def _get_alua_support_standby(self):
     self._check_self()
     path = "%s/alua_support_standby" % self.path
     return int(fread(path))
示例#12
0
 def _get_alua_support_unavailable(self):
     self._check_self()
     path = "%s/alua_support_unavailable" % self.path
     return int(fread(path))
示例#13
0
 def _get_alua_support_offline(self):
     self._check_self()
     path = "%s/alua_support_offline" % self.path
     return int(fread(path))
示例#14
0
 def _get_alua_support_active_optimized(self):
     self._check_self()
     path = "%s/alua_support_active_optimized" % self.path
     return int(fread(path))
示例#15
0
def get_lio_devices():
    """
    LIO uses the kernel's configfs feature to store and manage configuration
    data, so use rtslib to get a list of the devices

    :return: dict of dicts describing the rbd devices mapped to LIO
    """

    device_data = {}
    pools = {}

    lio_root = root.RTSRoot()
    # iterate over all luns - this will pick up the same lun mapped to
    # multiple tpgs - so we look out for that
    for lun in lio_root.luns:

        # plugin will show user or block
        lun_type = lun.storage_object.plugin

        if lun_type == 'block':
            dm_id = os.path.basename(lun.storage_object.udev_path)
            dm_num = dm_id.split('-')[0]

            dev_path = lun.storage_object.path
            # '/sys/kernel/config/target/core/iblock_0/ansible3'
            iblock_name = dev_path.split('/')[-2]
            rbd_name = 'rbd{}'.format(iblock_name.split('_')[1])

            if dm_num in pools:
                pool_name = pools[dm_num]
            else:
                pools[dm_num] = get_pool_name(pool_id=int(dm_num))
                pool_name = pools[dm_num]

            storage_type = 'rbd'

        elif lun_type == 'user':
            rbd_name = ''
            rbd_info = fread(os.path.join(lun.storage_object.path, 'info'))
            cfg_ptr = rbd_info.find('Config:')

            # cfg_data looks something like
            # rbd/iscsiTest/gprfc095-iscsiTest-20[;option1=value1]
            cfg_data = rbd_info[cfg_ptr:].split()[1]
            storage_type, pool_name, image_name = cfg_data.split('/')
            image_name = image_name.split(';')[0]

        else:
            raise ValueError("Unknown LUN type encountered with "
                             "{}".format(lun.storage_object.name))

        image_name = lun.storage_object.name
        image_size = lun.storage_object.size
        wwn = lun.storage_object.wwn

        # Each image name is assumed to be unique
        if image_name not in device_data:

            device_data[image_name] = {
                "size": image_size,
                "wwn": wwn,
                "rbd_name": rbd_name,
                "pool": pool_name,
                "image_name": image_name,
                "stg_type": storage_type,
                "lun_type": lun_type
            }

    return device_data