• openstack 使用cloud init 和 console-log, nbd或者libguestfs 获取VM中的硬件信息。


    以获取PCI的信息为例。

    基本代码:

    pci.py

    import base64
    import guestfs
    from functools import partial
    import os
    import six
    import stat
    import subprocess
    import tempfile
    import time
    import xml.etree.ElementTree as ET
    
    from oslo_utils import encodeutils
    from tempest import config
    from tempest_lib.common.utils import data_utils
    
    def shell_command(cmd, log=False):
        # cmd = ['sudo', 'ip', 'netns', 'exec', ns, 'ssh', "%s@%s" %(name, ip),
        # "'%s;ifconfig eth1 %s/24'" % (name ip)]
        p = subprocess.Popen(
            cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        out, err = p.communicate()
        if log:
            print out
            print err
            if len(err):
                return False
        return out
    
    
    VM_MOUNT_POINT = "/mnt"
    PCI_PATH = "/pci.info"
    RC_LOCAL = "/etc/rc.local"
    USER_DATA = ['#!/bin/sh -e',
                 '# mount -a',
                 'mount /dev/vdb %s' % VM_MOUNT_POINT,
                 'touch %s%s' % (VM_MOUNT_POINT, PCI_PATH),
                 'lspci > %s%s' % (VM_MOUNT_POINT, PCI_PATH),
                 '# umount /mnt/'
                 'exit 0']
    
    
    PCIINFO_DELIMITER = "*" * 40 + "%s" + "*" * 40
    PCIINFO_DELIMITER_BEGIN = PCIINFO_DELIMITER % "PCI INFO BEGIN"
    PCIINFO_DELIMITER_END = PCIINFO_DELIMITER % "PCI INFO END"
    
    CONSOLE_DATA = ['#!/bin/sh -e',
                    'sudo echo "%s"' % PCIINFO_DELIMITER_BEGIN,
                    'sudo lspci',
                    'sudo echo "%s"'  % PCIINFO_DELIMITER_END,
                    'exit 0']
    
    def gen_rc_local_file(pci_path=PCI_PATH):
        """please remove the file: os.remove(p)
           print gen_rc_local()
        """
        l, p = tempfile.mkstemp("local", "rc")
        f = open(p, 'w+b')
        f.writelines(['#!/bin/sh -e
    ',
                      'mount -a
    ',
                      'touch %s%s
    ' % (VM_MOUNT_POINT, pci_path),
                      'lspci > %s%s
    ' % (VM_MOUNT_POINT, pci_path),
                      'umount /mnt/
    '
                      'exit 0
    '])
        os.chmod(p, stat.S_IRWXU + stat.S_IXGRP + stat.S_IXOTH)
        f.close()
        return p, pci_path
    
    
    def gen_rc_local_dict(pci_path=PCI_PATH):
        """
        usage: personality = {}
               personality.append({
                   'path': filepath,
                   'contents': cont,
               })
    
        """
        data = ['#!/bin/sh -e',
                'mount -a',
                'touch %s%s' % (VM_MOUNT_POINT, pci_path),
                'lspci > %s%s' % (VM_MOUNT_POINT, pci_path),
                'cd ~',
                'umount /mnt/',
                'exit 0']
        data = "
    ".join(data)
        if six.PY3 and isinstance(data, str):
            data = data.encode('utf-8')
        cont = base64.b64encode(data).decode('utf-8')
        return cont
    
    
    def gen_user_data(userdata=USER_DATA):
        if hasattr(userdata, 'read'):
            userdata = userdata.read()
        # NOTE(melwitt): Text file data is converted to bytes prior to
        # base64 encoding. The utf-8 encoding will fail for binary files.
        if six.PY3:
            try:
                userdata = userdata.encode("utf-8")
            except AttributeError:
                # In python 3, 'bytes' object has no attribute 'encode'
                pass
        else:
            try:
                userdata = encodeutils.safe_encode(userdata)
            except UnicodeDecodeError:
                pass
    
        userdata_b64 = base64.b64encode(userdata).decode('utf-8')
        return userdata_b64
    
    
    def gen_etc_fstab():
        """
        usage: personality = {}
               personality.append({
                   'path': filepath,
                   'contents': cont,
               })
    
        """
        data = ["/dev/root  /         auto     rw,noauto                 0 1",
                "proc       /proc     proc     defaults                  0 0",
                "devpts     /dev/pts  devpts   defaults,gid=5,mode=620   0 0",
                "tmpfs      /dev/shm  tmpfs    mode=0777                 0 0",
                "sysfs      /sys      sysfs    defaults                  0 0",
                "tmpfs      /run      tmpfs    rw,nosuid,relatime,size=200k,mode=755 0 0",
                "/dev/vdb    /mnt/ auto    defaults                0 0"]
    
        data = "
    ".join(data)
        if six.PY3 and isinstance(data, str):
            data = data.encode('utf-8')
        cont = base64.b64encode(data).decode('utf-8')
        return cont
    
    def get_pci_info(disk, pci_path=PCI_PATH):
        """please remove the dir: os.rmdir(p)
        mount the disk by guestfs and get the pci info.
        need:
        $ sudo chmod g+rw /boot/vmlinuz-/boot/vmlinuz-`uname -r`
        $ sudo usermod -a -G root jenkins
        need to install these 2 packages
        $ sudo apt-get install libguestfs-tools
        $ sudo apt-get install python-guestfs
        need to add use to kvm group
        $ sudo usermod -a -G kvm jenkins
        or
        $ sudo chmod 0666 /dev/kvm
        ref http://libguestfs.org/guestfs-python.3.html
        for debug:
        $ export LIBGUESTFS_DEBUG=1
        $ export LIBGUESTFS_TRACE=1
        ref http://libguestfs.org/guestfs-faq.1.html#debugging-libguestfs
        """
        p = tempfile.mkdtemp("guestfs", "mount")
        g = guestfs.GuestFS(python_return_dict=True)
        # g.add_drive_opts(disk, format="qcow2", readonly=1)
        g.add_drive_opts(disk, readonly=1)
        g.launch()
        g.mount('/dev/sda', '/')
        return g.read_lines(pci_path)
    
    
    def nbd_mount(f, disk, path=PCI_PATH):
        """please remove the dir: os.rmdir(p)
        mount the disk by guestfs and get the pci info.
        need:
        $ sudo rmmod nbd
        $ sudo modprobe nbd max_part=16
        ref https://en.wikibooks.org/wiki/QEMU/Images
        ref https://blogs.gnome.org/muelli/2010/03/mounting-qemu-qcow2-image-using-nbd/
        """
        mount_point = "/mnt/nbd"
        cmd = ["sudo", "modinfo", "nbd"]
        out = shell_command(cmd)
        if "modinfo: ERROR:" in out:
            cmd = ["sudo", "modprobe", "nbd", "max_part=16"]
            shell_command(cmd)
    
        if not os.path.exists(mount_point):
            cmd = ["sudo", "mkdir", mount_point]
            shell_command(cmd)
    
        if os.path.ismount(mount_point):
            cmd = ["sudo", "umount", mount_point]
            shell_command(cmd)
    
        cmd = ["sudo", "qemu-nbd", "-d", "/dev/nbd0"]
        shell_command(cmd)
    
        cmd = ["sudo", "killall", "qemu-nbd"]
        shell_command(cmd)
    
        # cmd = ["sudo", "qemu-nbd", "-r", "-c", "/dev/nbd0", disk]
        cmd = ["sudo", "qemu-nbd", "-c", "/dev/nbd0", disk]
        shell_command(cmd)
    
        cmd = ["sudo", "mount", "/dev/nbd0", mount_point]
        shell_command(cmd)
    
        if not os.path.ismount(mount_point):
            cmd = ["sudo", "qemu-nbd", "-d", "/dev/nbd0"]
            shell_command(cmd)
            raise Exception("Can't mount the VM disk!")
    
        out = f(mount_point, path)
    
        cmd = ["sudo", "umount", mount_point]
        shell_command(cmd)
    
        cmd = ["sudo", "qemu-nbd", "-d", "/dev/nbd0"]
        shell_command(cmd)
        return out
    
    
    def cat_file(mount, pci_path):
        cmd = ["sudo", "cat", mount + pci_path]
        pci_info = shell_command(cmd, True)
        if pci_info is False:
            return pci_info
        return pci_info.splitlines()
    
    
    get_pci_info_by_nbd = partial(nbd_mount, cat_file)
    
    
    def x_file(mount, rc_path):
        cmd = ["sudo", "chmod", "a+x", mount + rc_path]
        out = shell_command(cmd)
        return out
    
    rc_local_add_x = partial(nbd_mount, x_file)
    
    
    def get_vda_path(xml):
        # tree = ET.parse('/etc/libvirt/qemu/instance-0000001f.xml')
        # root = tree.getroot()
        root = ET.fromstring(xml)
        disks = root.findall("./devices/disk[@device='disk'][@type='file']")
        for d in disks:
            t = d.find("target")
            if t.attrib.get("dev") == "vda":
                return d.find("./source").get("file")
    
    def get_config_drive_path(xml):
        # tree = ET.parse('/etc/libvirt/qemu/instance-0000001f.xml')
        # root = tree.getroot()
        root = ET.fromstring(xml)
        disks = root.findall("./devices/disk[@device='disk'][@type='file']")
        for d in disks:
            f = d.find("./source").get("file")
            if "disk.config" in f:
                return f
    
    
    def get_pci_output(get_console_output, server_id):
        output = get_console_output(server_id, -1)['output']
        lines = output.split('
    ')
        if (len(lines) > 0 and lines.count(PCIINFO_DELIMITER_BEGIN) > 0
            and lines.count(PCIINFO_DELIMITER_END)):
            begin = lines.index(PCIINFO_DELIMITER_BEGIN) + 1
            end = lines.index(PCIINFO_DELIMITER_END)
            return lines[begin : end]
    
    
    def retry_get_pci_output(get_console_output, server_id, retry=20):
        while retry > 0:
            out = get_pci_output(get_console_output, server_id)
            if out is None:
                retry = retry - 1
                time.sleep(1)
            else:
                return out
        raise Exception("Can't get the pci.info from VM!")
                                                          
    View Code

    使用cloud-init 和console-log获取硬件信息的代码的片段。

                personality = []
    
                user_data = pci.gen_user_data("
    ".join(pci.CONSOLE_DATA))
    
                server_with_pci = (self.create_test_server(
                                          wait_until='ACTIVE',
                                          adminPass=admin_pass,
                                          user_data=user_data,
                                          personality=personality,
                                          flavor=flavor_with_pci_id))
                #print self.client.get_server_metadata_item(server_with_pci['id'],"addresses")
                addresses = self.client.show_server(server_with_pci['id'])['server']
                password = 'cubswin:)'
    
                print "cirros@" + addresses["addresses"]["private"][0]["addr"]
                print password
                pci_info = pci.retry_get_pci_output(
                    self.client.get_console_output, server_with_pci["id"])
    
                # pci_info = pci.get_pci_info(disk)
                # pci_flag = linux_client.get_pci(pciid)
                expect_pci = filter(lambda x: pciid in x, pci_info)
    
                # self.assertTrue(pci_flag is not None)
                self.assertTrue(not not expect_pci)
    
                # pci_count = linux_client.get_pci_count(pciid)
                pci_count = len(expect_pci)
    
                # pci_count = pci_count.strip()
                self.assertEqual(1, pci_count)
    View Code

    使用 使用cloud-init 和 nbd获取时候,需要mount config.drive的磁盘。

    使用 file inject 和nbd获取的时候,需要开关机器。

  • 相关阅读:
    强化学习_PolicyGradient(策略梯度)_代码解析
    leetcode_1053. Previous Permutation With One Swap
    leetcode_1052. Grumpy Bookstore Owner
    Tensorflow_入门学习_2_一个神经网络栗子
    通过批处理快速设置IP
    汇编、编译、反汇编、反编译的简单概念介绍
    Logistic回归
    基于概率论的分类方法:朴素贝叶斯
    决策树 预测隐形眼镜类型
    k-近邻算法2(kNN)手写识别系统
  • 原文地址:https://www.cnblogs.com/shaohef/p/5316104.html
Copyright © 2020-2023  润新知