支持 System z 上 Linux 的 ECKD 卷

https://blueprints.launchpad.net/cinder/+spec/linux-ficon-support

FICON(光纤连接)是一种光纤通道 FC-4 层协议。它在大型机上用于通过光纤通道连接 ECKD 卷。为了允许 Cinder 管理 Linux on System z 上的基于 FICON 的块存储,需要进行一些更改。

此外,需要为支持 ECKD(例如 IBM DS8000)的存储子系统的现有 Cinder 驱动程序添加支持。

Nova 中所需的支持由单独的蓝图描述,该蓝图列为以下依赖项。

问题描述

FICON 和 FCP 都是光纤通道 FC-4 层协议。FICON 使用与 FCP 不同的方案来寻址卷。

  • ECKD 卷通过控制单元和单元地址进行寻址,而不是 WWPN 和 LUN。

  • System z 使用与 System z 上 FCP 使用的文件路径类似的基于 ccw 的设备文件路径格式(而不是基于 pci 的格式)。

  • 在使用 ECKD 卷之前,需要将其设置为联机状态并进行格式化

用例

允许最终用户创建和管理基于连接到 FICON 的存储子系统的 Cinder 块设备,这些存储子系统支持 ECKD 协议。例如:创建、删除、镜像部署、快照等。

我们将扩展 IBM DS8000 的 Cinder 驱动程序。其他供应商,如 EMC、日立或 HP 也支持 ECKD。它们是潜在的候选者。

提议的变更

更改 os-brick 中的代码以解决这些问题,具体取决于驱动程序提供的新的协议类型“fibre_channel_eckd”。有关详细信息,请参阅 工作项目 部分。

备选方案

数据模型影响

REST API 影响

安全影响

通知影响

其他最终用户影响

性能影响

其他部署者影响

开发人员影响

支持 FICON/ECKD 的平台需要为其驱动程序实现此功能。

实现

负责人

主要负责人

stefan-amann

其他贡献者

arecknag maiera

工作项

os-brick/initiator/connector.py

  • 提供新的连接器 FibreChannelECKDConnector

  • connect_volume 需要为卷启用中断并将卷设置为联机状态。这是通过调用新的 configure_eckd_device() 函数完成的)

  • disconnect_volume 需要将卷设置为脱机状态。这是通过调用新的 deconfigure_eckd_device() 函数完成的

os-brick/initiator/linuxeckd.py

  • 用于将卷设置为联机状态、验证其格式是否正确以及在需要时对其进行格式化的实用程序函数

    def _is_online(self, device):
        """
        Return True if device is online, else return False
        :param device: device id
        """
        if os.access('/sys/bus/ccw/devices/%s/online' % device, os.R_OK):
            online_file = None
            try:
                online_file = open('/sys/bus/ccw/devices/%s/online' % device)
                value = online_file.readline()
                if value and value.strip() == '1':
                    return True
            finally:
                if online_file:
                    online_file.close()
        return False
    
    def _is_formatted(self, device):
        """
        Return True if device is online, else return False
        :param device: device id
        """
        if os.access('/sys/bus/ccw/devices/%s/status' % device, os.R_OK):
            formatted = None
            (out, _err) = self._execute('cat',
                                '/sys/bus/ccw/devices/%s/status' % device,
                                run_as_root=True,
                                root_helper=self._root_helper)
            if out and out.strip() == 'unformatted':
                return False
        return True
    
    def format_eckd_volume(self, path):
        """
        formats ECKD volume
        :param device: device path
        """
        name = os.path.realpath(path)
        if name.startswith("/dev/"):
            format_cmd = 'dasdfmt -y -b 4096 -d ldl ' + name
            (out, _err) = self._execute(format_cmd, run_as_root=True,
                                root_helper=self._root_helper)
            return True
        else:
            return False
    

os-brick/initiator/linuxfc.py

  • 新的类 LinuxFibreChannelECKD

def configure_eckd_device(self, device_number):
    """Add the eckd volume to the Linux configuration. """

    full_device_identifier = "0.0.%04x" % device_number
    eckd_device_command = ('cio_ignore', '-r',
        '%(dev_id)s' % {"dev_id": full_device_identifier})
    LOG.debug("issue cio_ignore for s390: %s", eckd_device_command)

    out, info = None, None
    try:
        out, info = self._execute('cio_ignore', '-r',
                '%(dev_id)s' % {"dev_id": full_device_identifier},
                run_as_root=True,
                root_helper=self._root_helper)
    except putils.ProcessExecutionError as exc:
        LOG.warning(_LW("cio_ignore call for s390 failed exit"
                        " %(code)s, stderr %(stderr)s"),
                    {'code': exc.exit_code, 'stderr': exc.stderr})

    eckd_device_command = ('chccwdev', '-e',
            '%(dev_id)s' % {"dev_id": full_device_identifier})
    LOG.debug("add ECKD command for s390: %s", eckd_device_command)
    out, info = None, None
    try:
        out, info = self._execute('chccwdev', '-e',
                '%(dev_id)s' % {"dev_id": full_device_identifier},
                run_as_root=True,
                root_helper=self._root_helper)
    except putils.ProcessExecutionError as exc:
        LOG.warning(_LW("add ECKD call for s390 failed exit"
                        " %(code)s, stderr %(stderr)s"),
                    {'code': exc.exit_code, 'stderr': exc.stderr})

def deconfigure_eckd_device(self, device_number):
    """Remove the eckd volume from the Linux configuration. """

    LOG.debug("Deconfigure ECKD volume: device_number=%(device_num)s ",
              {'device_num': device_number})

    full_device_identifier = "0.0.%04x" % device_number
    eckd_device_command = ('chccwdev', '-d',
            '%(dev_id)s' % {"dev_id": full_device_identifier})
    LOG.debug("remove ECKD command for s390: %s", eckd_device_command)
    out, info = None, None
    try:
        out, info = self._execute('chccwdev', '-d',
                '%(dev_id)s' % {"dev_id": full_device_identifier},
                run_as_root=True,
                root_helper=self._root_helper)
    except putils.ProcessExecutionError as exc:
        LOG.warning(_LW("remove ECKD call for s390 failed exit"
                        " %(code)s, stderr %(stderr)s"),
                    {'code': exc.exit_code, 'stderr': exc.stderr})

对 volume.filters 的调整,以允许发送新的命令

Cinder 驱动程序需要报告 ECKD 卷的控制单元地址和单元地址,并将 driver_volume_type 设置为“fibre_channel_eckd”。

希望支持 FICON 的任何驱动程序都需要针对连接到 FICON 的主机运行 CI 报告结果。

依赖项

Nova 蓝图,用于为 System z 上的 Linux 添加对 ECKD 的支持。该蓝图可以在这里找到:https://blueprints.launchpad.net/nova/+spec/linux-ficon-support

测试

单元测试

  • 将在 System z 以及基于 Intel 的机器上添加和执行单元测试。

CI 环境

  • 我们将为 DS8000 提供第三方 CI 环境。

文档影响

  • 我们将根据需要更新文档。

参考资料