nova底层虚拟管理与libvirt

源码版本:H版

  nova通过nova/virt/driver.py中的ComputeDriver对底层虚拟化技术进行抽象,不同的虚拟化技术在nova/virt下有不同的目录,里面均有driver.py文件,通过继承ComputeDriver类来实现自己的Driver类。nova可以通过对Driver类进行统一接口的调用实现底层虚拟技术的管理。下面具体谈谈nova对libvirt的使用:

一、libvirt基础

1、libvirt基本知识:

http://www.ibm.com/developerworks/cn/linux/l-libvirt/

http://libvirt.org/

2、libvirt配置

http://smilejay.com/2013/03/libvirt-configuration-and-usage/

3、libvirt日志信息

http://www.chenyudong.com/archives/qemu-vm-log-and-libvirtd-log.html

4、libvirt创建instance的xml配置

http://libvirt.org/formatdomain.html

5、libvirt的简单使用

http://blog.163.com/soloman_hao/blog/static/209653155201291652337198/

6、libvirt的Python绑定编程

http://libvirt.org/python.html

http://www.ibm.com/developerworks/cn/opensource/os-python-kvm-scripting1/

二、nova对libvirt的使用架构

  说明:其中libvirt-python仅仅是对libvirt的Python绑定,并没有改变功能,对API的改动也不大。

三、nova创建虚拟机时对libvirt的调度

nova/virt/libvirt/driver.py

LibvirtDriver类:
def spawn(self, context, instance, image_meta, injected_files,
              admin_password, network_info=None, block_device_info=None):
    """获取disk相关信息"""
    disk_info = blockinfo.get_disk_info(CONF.libvirt_type,
                                        instance,
                                        block_device_info,
                                        image_meta)
    """主要是镜像的处理,见下文第1节"""
    self._create_image(context, instance,
                       disk_info[‘mapping‘],
                       network_info=network_info,
                       block_device_info=block_device_info,
                       files=injected_files,
                       admin_pass=admin_password)
    """将当前的参数配置转成创建虚拟机需要用到的xml文件"""
    xml = self.to_xml(context, instance, network_info,
                      disk_info, image_meta,
                      block_device_info=block_device_info,
                      write_to_disk=True)
    """调用libvirt创建并启动虚拟机,见下文第2节"""
    self._create_domain_and_network(context, xml, instance, network_info,
                                    block_device_info)
    ...

1、处理镜像

def _create_image(self, context, instance,
                      disk_mapping, suffix=‘‘,
                      disk_images=None, network_info=None,
                      block_device_info=None, files=None,
                      admin_pass=None, inject_files=True):
        ...
        """此处返回的对象为Qcow2对象"""
        def image(fname, image_type=CONF.libvirt_images_type):
            return self.image_backend.image(instance,
                                            fname + suffix, image_type)
        ...
        """
        首先试图获取存储在_base目录中的base镜像文件,由于创建虚拟机时建立的镜像为qcow2格式,所以需要base镜像,
        镜像格式参考:
        http://docs.openstack.org/image-guide/content/ch_introduction.html
        """
        if not booted_from_volume:
            root_fname = imagecache.get_cache_fname(disk_images, ‘image_id‘)
            size = instance[‘root_gb‘] * 1024 * 1024 * 1024

            if size == 0 or suffix == ‘.rescue‘:
                size = None

            image(‘disk‘).cache(fetch_func=libvirt_utils.fetch_image,
                                context=context,
                                filename=root_fname,
                                size=size,
                                image_id=disk_images[‘image_id‘],
                                user_id=instance[‘user_id‘],
                                project_id=instance[‘project_id‘])

        ...
        """配置驱动"""
        if configdrive.required_by(instance):
            LOG.info(_(‘Using config drive‘), instance=instance)
            extra_md = {}
            ...

        """文件注入"""
        elif inject_files and CONF.libvirt_inject_partition != -2:
            target_partition = None
            ...

nova/virt/libvirt/imagebackend.py

Image类:
def cache(self, fetch_func, filename, size=None, *args, **kwargs):
    @utils.synchronized(filename, external=True, lock_path=self.lock_path)
    def call_if_not_exists(target, *args, **kwargs):
        if not os.path.exists(target):
            fetch_func(target=target, *args, **kwargs)
        elif CONF.libvirt_images_type == "lvm" and                 ‘ephemeral_size‘ in kwargs:
            fetch_func(target=target, *args, **kwargs)
    ...

    if not self.check_image_exists() or not os.path.exists(base):
        self.create_image(call_if_not_exists, base, size,
                          *args, **kwargs)
    ...

Qcow2类:
def create_image(self, prepare_template, base, size, *args, **kwargs):
    @utils.synchronized(base, external=True, lock_path=self.lock_path)
    def copy_qcow2_image(base, target, size):
        libvirt_utils.create_cow_image(base, target)
        if size:
            disk.extend(target, size, use_cow=True)

    """没有base镜像的话先下载base镜像,见1.1"""
    if not os.path.exists(base):
        prepare_template(target=base, max_size=size, *args, **kwargs)
    else:
        self.verify_base_size(base, size)

    ...
    """
    有base镜像后创建qcow2镜像,从上面的代码可以看出copy_qcow2_image函数的核心是create_cow_image,见1.2
    """
    if not os.path.exists(self.path):
        with fileutils.remove_path_on_error(self.path):
            copy_qcow2_image(base, self.path, size) 

1.1、下载base镜像(即分析prepare_template)

  从上面可以看出,prepare_template函数即为cache函数中传入的call_if_not_exists函数,call_if_not_exists函数里面接着调用fetch_func(target=target, *args, **kwargs),而fetch_func在_create_image函数中表明fetch_func=libvirt_utils.fetch_image,所以继续如下分析:

nova/virt/libvirt/utils.py

def fetch_image(context, target, image_id, user_id, project_id, max_size=0):
    """images为nova/virt/images.py"""
    images.fetch_to_raw(context, image_id, target, user_id, project_id,
                        max_size=max_size)

nova/virt/images.py

def fetch_to_raw(context, image_href, path, user_id, project_id, max_size=0):
    path_tmp = "%s.part" % path
    fetch(context, image_href, path_tmp, user_id, project_id,
          max_size=max_size)
    ...

def fetch(context, image_href, path, _user_id, _project_id, max_size=0):
    """其中glance为nova/image/glance.py模块"""
    (image_service, image_id) = glance.get_remote_image_service(context,
                                                                image_href)
    with fileutils.remove_path_on_error(path):
        image_service.download(context, image_id, dst_path=path)

nova/image/glance.py

GlanceImageService类:
def download(self, context, image_id, data=None, dst_path=None):
    ...
    try:
        """使用glanceclient获取镜像数据"""
        image_chunks = self._client.call(context, 1, ‘data‘, image_id)
    except Exception:
        _reraise_translated_image_exception(image_id)
    ...

1.2、创建qcow2镜像(即分析create_cow_image)

  注意这里创建的qcow2镜像是直接供虚拟机所用的。分析如下:

nova/virt/libvirt/utils.py

def create_cow_image(backing_file, path, size=None):
    """构建命令创建cow镜像"""
    base_cmd = [‘qemu-img‘, ‘create‘, ‘-f‘, ‘qcow2‘]
    cow_opts = []
    if backing_file:
        cow_opts += [‘backing_file=%s‘ % backing_file]
        base_details = images.qemu_img_info(backing_file)
    else:
        base_details = None
    if base_details and base_details.cluster_size is not None:
        cow_opts += [‘cluster_size=%s‘ % base_details.cluster_size]
    if base_details and base_details.encryption:
        cow_opts += [‘encryption=%s‘ % base_details.encryption]
    if size is not None:
        cow_opts += [‘size=%s‘ % size]
    if cow_opts:
        csv_opts = ",".join(cow_opts)
        cow_opts = [‘-o‘, csv_opts]
    cmd = base_cmd + cow_opts + [path]
    execute(*cmd)

2、创建并启动虚拟机

  继续分析spawn函数的内容,如下:

nova/virt/libvirt/driver.py

LibvirtDriver类:
def _create_domain_and_network(self, xml, instance, network_info,
                                   block_device_info=None, power_on=True,
                                   context=None, reboot=False):
    ...
    self.plug_vifs(instance, network_info)
    self.firewall_driver.setup_basic_filtering(instance, network_info)
    self.firewall_driver.prepare_instance_filter(instance, network_info)
    domain = self._create_domain(xml, instance=instance, power_on=power_on)
    self.firewall_driver.apply_instance_filter(instance, network_info)
    return domain

def _create_domain(self, xml=None, domain=None,
                       instance=None, launch_flags=0, power_on=True):
    ...
    if xml:
        try:
            """self._conn为libvirt.virConnect,所以这里实际上是调用libvirt定义XML"""
            domain = self._conn.defineXML(xml)
        except Exception as e:
            LOG.error(_("An error occurred while trying to define a domain"
                        " with xml: %s") % xml)
            raise e

    if power_on:
        try:
            """调用libvirt启动虚拟机"""
            domain.createWithFlags(launch_flags)
        except Exception as e:
            with excutils.save_and_reraise_exception():
                LOG.error(_("An error occurred while trying to launch a "
                            "defined domain with xml: %s") %
                          domain.XMLDesc(0))
    ...
    return domain
时间: 2024-12-12 16:52:10

nova底层虚拟管理与libvirt的相关文章

KVM虚拟机管理配置——libvirt

一.关于libvirt 1)libvirt简介 Libvirt是目前使用最广泛的虚拟机管理工具和应用程序接口(API),常用的虚拟机管理工具(virsh.virt-install.virt-manager)和云计算架构平台(如:OpenStack.OpenNubula)等在底层都使用libvirt的应用程序接口. Libvirt是一套开源的支持linux下虚拟化工具的函数库,为安全有效的管理各域,libvirt提供的一个公共的稳定软件层. Libvirt由三个部分组成:应用程序接口(API).一

OpenStack Nova计算服务管理(四)

作者:李晓辉 联系方式: [email protected] 环境介绍 类型 控制节点和计算节点等在一起,形成all-in-one 内存 8G 硬盘 200G 网卡 2块 计算服务概览 使用OpenStack计算服务来托管和管理云计算系统.OpenStack计算服务是基础设施即服务(IaaS)系统的主要部分,模块主要由Python实现. OpenStack计算组件请求OpenStack Identity服务进行认证:请求OpenStack Image服务提供磁盘镜像:为OpenStack das

KVM 介绍(6):Nova 通过 libvirt 管理 QEMU/KVM 虚机 [Nova Libvirt QEMU/KVM Domain]

学习 KVM 的系列文章: (1)介绍和安装 (2)CPU 和 内存虚拟化 (3)I/O QEMU 全虚拟化和准虚拟化(Para-virtulizaiton) (4)I/O PCI/PCIe设备直接分配和 SR-IOV (5)libvirt 介绍 (6)Nova 通过 libvirt 管理 QEMU/KVM 虚机 1. Libvirt 在 OpenStack 架构中的位置 在 Nova Compute 节点上运行的 nova-compute 服务调用 Hypervisor API 去管理运行在该

KVM(六)Nova 通过 libvirt 管理 QEMU/KVM 虚机

1. Libvirt 在 OpenStack 架构中的位置 在 Nova Compute 节点上运行的 nova-compute 服务调用 Hypervisor API 去管理运行在该 Hypervisor 的虚机.Nova 使用 libvirt 管理 QEMU/KVM 虚机,还使用别的 API 去管理别的虚机.        libvirt 的实现代码在 /nova/virt/libvirt/driver.py 文件中. 这里是 OpenStack Hypervisor Matrix. 这里是

KVM 介绍(8):使用 libvirt 迁移 QEMU/KVM 虚机和 Nova 虚机 [Nova Libvirt QEMU/KVM Live Migration]

学习 KVM 的系列文章: (1)介绍和安装 (2)CPU 和 内存虚拟化 (3)I/O QEMU 全虚拟化和准虚拟化(Para-virtulizaiton) (4)I/O PCI/PCIe设备直接分配和 SR-IOV (5)libvirt 介绍 (6)Nova 通过 libvirt 管理 QEMU/KVM 虚机 (7)快照 (snapshot) (8)迁移 (migration) 1. QEMU/KVM 迁移的概念 迁移(migration)包括系统整体的迁移和某个工作负载的迁移.系统整理迁移

使用libvirt工具栈管理kvm虚拟机

libvirt介绍 Libvirt是一个软件集合,便于使用者管理虚拟机和其他虚拟化功能,比如存储和网络接口管理等等.Libvirt概括起来包括一个API库.一个 daemon(libvirtd)和一个命令行工具(virsh).支持的虚拟化技术:KVM, XEN, VMWARE, Qemu, LXC, OpenVZ等libvirt中的术语: node:指物理节点 hypervisor: domain: vm instances 虚拟机实例Libvirt的主要目标是:提供一种单一的方式管理多种不同的

openstack nova 基础知识——Quota(配额管理)

一.什么是配额(quota)管理 简单的讲就是控制用户资源的数量.在openstack里,管理员为每一个工程(project)分配的资源都是有一定限制的,这些资源包括实例(instance).cpu.内存.存储空间等等,不能让一个工程无限制的使用资源,所以配额管理针对的单位是工程(project).先来个感性的认识,看一下dashboard里的一个工程的overview: 管理员给这个工程的资源配额是最多创建10个实例,最多使用20个vcpu,最多使用5G的内存==,只要达到某一个资源的使用上限

OpenStack(i版)之Keystone,Glance,Nova,Neutron,Horizon

一.前期准备 1.1.linux-node1端: [[email protected]1 ~]# egrep '(vmx|svm)' /proc/cpuinfo ##有输出就支持虚拟化 [[email protected] ~]# cat /etc/redhat-release CentOS release 6.8 (Final) [[email protected] ~]# uname -r 2.6.32-642.el6.x86_64 [[email protected] ~]# getenf

libvirt 部分API 介绍

感谢朋友支持本博客.欢迎共同探讨交流,因为能力和时间有限,错误之处在所难免,欢迎指正! 假设转载,请保留作者信息. 博客地址:http://blog.csdn.net/qq_21398167 原博文地址:http://blog.csdn.net/qq_21398167/article/details/46422583 http://libvirt.org/html/index.html  官网包括全部的api API 概述 高级 libvirt API 可划分为 5 个 API 部分:虚拟机监控