挂载卷到虚机逻辑(FC)

nova.compute.manager.do_attach_volume --> nova.compute.manager.ComputeManager#_attach_volume

bdm.attach(context, instance, self.volume_api, self.driver,
                       do_driver_attach=True)

调用nova.virt.block_device.DriverVolumeBlockDevice#attach,这是核心步骤

def attach(self, context, instance, volume_api, virt_driver,
           do_check_attach=True, do_driver_attach=False, **kwargs):
    volume = volume_api.get(context, self.volume_id)
    if do_check_attach:
        volume_api.check_attach(context, volume, instance=instance)

    volume_id = volume['id']
    context = context.elevated()

    connector = virt_driver.get_volume_connector(instance)

步骤:
一、 volume = volume_api.get(context, self.volume_id) 调cinder的restapi,得到卷信息
二、 volume_api.check_attach(context, volume, instance=instance) 确认是否已经挂载了虚机
三、 virt_driver.get_volume_connector(instance) 获取卷连接信息。
nova.virt.libvirt.driver.LibvirtDriver#get_volume_connector:

from os_brick.initiator import connector

def get_volume_connector(self, instance):
    root_helper = utils.get_root_helper()
    return connector.get_connector_properties(
        root_helper, CONF.my_block_storage_ip,
        CONF.libvirt.volume_use_multipath,
        enforce_multipath=True,
        host=CONF.host)

os_brick.initiator.connector.get_connector_properties 方法里,先是通过

    props = {}
    props['platform'] = platform.machine()
    props['os_type'] = sys.platform
    props['ip'] = my_ip
    props['host'] = host if host else socket.gethostname()

获取一些平台信息,然后遍历connector_list,创建连接对象connector。

for item in connector_list:
    connector = importutils.import_class(item)

connector_list是数组,存了不同协议的连接信息

# List of connectors to call when getting
# the connector properties for a host
connector_list = [
    'os_brick.initiator.connectors.base.BaseLinuxConnector',
    'os_brick.initiator.connectors.iscsi.ISCSIConnector',
    'os_brick.initiator.connectors.fibre_channel.FibreChannelConnector',
    <!--省略-->
]

如果前面获取的平台信息props['platform']、props['os_type']能和connector里信息匹配,就调用connector对象静态方法get_connector_properties()得到必要的信息并merge_dict 合并保存至字典里,最后一起返回。

if (utils.platform_matches(props['platform'], connector.platform) and
   utils.os_matches(props['os_type'], connector.os_type)):
    props = utils.merge_dict(props,
                             connector.get_connector_properties(
                                 root_helper,
                                 host=host,
                                 multipath=multipath,
                                 enforce_multipath=enforce_multipath,
                                 execute=execute))

拿FC举例,FC对应connector_list的'os_brick.initiator.connectors.fibre_channel.FibreChannelConnector'。FibreChannelConnector方法没有定义参数platform和os_type,这两个参数在父类InitiatorConnector作了初始化: # This object can be used on any platform (x86, S390)
platform = initiator.PLATFORM_ALL
# This object can be used on any os type (linux, windows)
os_type = initiator.OS_TYPE_ALL
PLATFORM_ALL = 'ALL',OS_TYPE_ALL = 'ALL',所以platform = 'ALL',os_type = 'ALL'。
我们看utils.platform_matches(props['platform'], connector.platform)这个方法里,

def platform_matches(current_platform, connector_platform):
    curr_p = current_platform.upper()
    conn_p = connector_platform.upper()
    if conn_p == 'ALL':
        return True

    # Add tests against families of platforms
    if curr_p == conn_p:
        return True

    return False

如果current_platform等于‘ALL’则匹配返回True。'os_brick.initiator.connectors.fibre_channel.FibreChannelConnector'符合条件,执行FibreChannelConnector.get_connector_properties。
FibreChannelConnector.get_connector_properties:

@staticmethod
def get_connector_properties(root_helper, *args, **kwargs):
    """The Fibre Channel connector properties."""
    props = {}
    fc = linuxfc.LinuxFibreChannel(root_helper,
                                   execute=kwargs.get('execute'))

    wwpns = fc.get_fc_wwpns()
    if wwpns:
        props['wwpns'] = wwpns
    wwnns = fc.get_fc_wwnns()
    if wwnns:
        props['wwnns'] = wwnns

    return props

获取系统wwpns存入props['wwpns']
来看fc.get_fc_wwpns()的逻辑:

    def get_fc_wwpns(self):
        """Get Fibre Channel WWPNs from the system, if any."""

        # Note(walter-boring) modern Linux kernels contain the FC HBA's in /sys
        # and are obtainable via the systool app
        hbas = self.get_fc_hbas()

        wwpns = []
        for hba in hbas:
            if hba['port_state'] == 'Online':
                wwpn = hba['port_name'].replace('0x', '')
                wwpns.append(wwpn)

        return wwpns
  1. 先获得hba信息:
    hbas = self.get_fc_hbas()对应os_brick.initiator.linuxfc.LinuxFibreChannel#get_fc_hbas
    def get_fc_hbas(self):
        """Get the Fibre Channel HBA information."""
        if not self.has_fc_support():
            return []
        out = None
        try:
            out, _err = self._execute('systool', '-c', 'fc_host', '-v',
                                      run_as_root=True,
                                      root_helper=self._root_helper)

逻辑简单的说就是:

  • 先判断'/sys/class/fc_host'是否存在
  • 如果存在,则用root权限执行systool -c fc_host -v去把'/sys/class/fc_host'记录的hba信息拿出来。
图片.png
  1. 如果hba['port_state'] HBA连接状态是online,则把port_name = "0x10008c7cff409e80" 替换修改成为"10008c7cff409e80"作为wwpns

再比如ISCSI,对应'os_brick.initiator.connectors.iscsi.ISCSIConnector',ISCSIConnector.get_connector_properties会去执行 cat /etc/iscsi/initiatorname.iscsi 来获得iscsi信息存入props['initiator']

def get_connector_properties(root_helper, *args, **kwargs):
    """The iSCSI connector properties."""
    props = {}
    iscsi = ISCSIConnector(root_helper=root_helper,
                           execute=kwargs.get('execute'))
    initiator = iscsi.get_initiator()
    if initiator:
        props['initiator'] = initiator

    return props

四、 获得连接信息后,就做连接初始化:

    connection_info = volume_api.initialize_connection(context,
                                                       volume_id,
                                                       connector)

调用cinder的restapi, POST http://172.24.9.198:8776/v2/406cd353135e44f0ade98f53d92d5d8b/volumes/b12d9043-895f-4f06-8e3c-b33094061cc8/action '{"os-initialize_connection": {"connector": {"platform": "x86_64", "host": "node11", "do_local_attach": false, "ip": "172.24.9.21", "os_type": "linux2", "multipath": false, "initiator": "iqn.1994-05.com.redhat:e08ae3b9ff2"}}}' ,把之前得到的连接信息作为请求参数一并传递给cinder。

如果cinder端出错,调用os-terminate_connection断开连接。cinder出错原因:比如nova想要连接FC,但是传递的connector里没有携带wwpns,会返回错误码500。在cinder-volume.log里可以看到 ERROR cinder.volume.manager KeyError: 'wwpns'。

五、 若cinder创建连接成功后,返回完整的连接信息(待补充),然后做卷连接:

volume_api.attach(context, volume_id, instance.uuid,
                                  self['mount_device'], mode=mode)

调用cinder的restapi, (待补充)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容