[Azure]通过waagent代码找到临时磁盘的设备名

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qwertyupoiuytr/article/details/79403713

Azure的Linux虚拟机默认会有一个临时磁盘,正常情况下设备名是/dev/sdb,但是由于设备识别顺序是随机的,所以重启的时候,临时磁盘的设备名可能未必是/dev/sdb,那么waagent是如何将/dev/sdb挂在到/mnt/resource下的呢?

waagent相关代码都在/usr/lib/python2.7/site-packages/azurelinuxagent目录下(具体分析过程这里不再赘述)。

我们进入resourcedisk子目录,找到default.py文件,看一下activate_resource_disk方法,我们看到通过调用mount_resource_disk方法进行临时磁盘的挂载:
def activate_resource_disk(self):
    logger.info("Activate resource disk")
    try:
        mount_point = conf.get_resourcedisk_mountpoint()
        mount_point = self.mount_resource_disk(mount_point)
        warning_file = os.path.join(mount_point,
                                    DATALOSS_WARNING_FILE_NAME)
        try:
            fileutil.write_file(warning_file, DATA_LOSS_WARNING)
        except IOError as e:
            logger.warn("Failed to write data loss warning:{0}", e)
        return mount_point
    except ResourceDiskError as e:
        logger.error("Failed to mount resource disk {0}", e)
        add_event(name=AGENT_NAME, is_success=False, message=ustr(e),
                  op=WALAEventOperation.ActivateResourceDisk)

我们继续在这个文件中查看mount_resource_disk方法,可以看到是在device_for_ide_port这个方法中得到设备名的:
def mount_resource_disk(self, mount_point):
    device = self.osutil.device_for_ide_port(1)
    if device is None:
        raise ResourceDiskError("unable to detect disk topology")


    device = "/dev/{0}".format(device)
    partition = device + "1"
    mount_list = shellutil.run_get_output("mount")[1]
    existing = self.osutil.get_mount_point(mount_list, device)

    if existing:
        logger.info("Resource disk [{0}] is already mounted [{1}]",
                    partition,
                    existing)
        return existing

在文件开头引用了osutil命名空间中的方法:
from azurelinuxagent.common.osutil import get_osutil

并且在构造函数中制定了self.osutil属性:
def __init__(self):
    self.osutil = get_osutil()
    self.fs = conf.get_resourcedisk_filesystem()

接着我们到/usr/lib/python2.7/site-packages/azurelinuxagent/common/osutil中查看对应的源代码default.py文件,找到device_for_ide_port这个方法:
def device_for_ide_port(self, port_id):
    """
    Return device name attached to ide port 'n'.
    """
    if port_id > 3:
        return None
    g0 = "00000000"
    if port_id > 1:
        g0 = "00000001"
        port_id = port_id - 2
    device = None
    path = "/sys/bus/vmbus/devices/"
    if os.path.exists(path):
        for vmbus in os.listdir(path):
            deviceid = fileutil.read_file(os.path.join(path, vmbus, "device_id"))
            guid = deviceid.lstrip('{').split('-')
            if guid[0] == g0 and guid[1] == "000" + ustr(port_id):
                for root, dirs, files in os.walk(path + vmbus):
                    if root.endswith("/block"):
                        device = dirs[0]
                        break
                    else : #older distros
                        for d in dirs:
                            if ':' in d and "block" == d.split(':')[0]:
                                device = d.split(':')[1]
                                break
                break
    return device

看起来比较乱,我们看到逻辑中是找到guid以00000000开头的,并且guid第二部分是0001(注意前面参数里面port_id写的是1,所以根据guid[1] == "000" + ustr(port_id)判断条件是0001)的一个blockId,我们看一下/sys/bus/vmbus/devices/下面符合条件的blockId:

定位到是这个ID:

00000000-0001-8899-0000-000000000000

根据这个,我们将device_for_ide_port方法简化成下下面的脚本在这台机器上跑一下:

import os
path = "/sys/bus/vmbus/devices/"
vmbus = "00000000-0001-8899-0000-000000000000"
for root, dirs, files in os.walk(path + vmbus):
    if root.endswith("/block"):
        root
        dirs
        break

跑完得到结果:

可以看到,是从/sys/bus/vmbus/devices/00000000-0001-8899-0000-000000000000/host5/target5:0:1/5:0:1:0/block这个目录下读到了sdb这个目录,这个目录就是临时磁盘的设备名。

猜你喜欢

转载自blog.csdn.net/qwertyupoiuytr/article/details/79403713
今日推荐