返回顶部
首页 > 资讯 > 后端开发 > Python >python实战系列之通过libvirt
  • 118
分享到

python实战系列之通过libvirt

实战系列之python 2023-01-31 06:01:39 118人浏览 薄情痞子

Python 官方文档:入门教程 => 点击学习

摘要

1. 概述    libvirt是基于KVM的上层封装,提供了操作KVM的生层接口,如虚拟机的生命周期(创建,删除,查看,管理)等,网络的管理和存储的管理。通过libvirt可以操作KVM,实现类似于virsh,virt-manager这些

1. 概述

    libvirt是基于KVM的上层封装,提供了操作KVM的生层接口,如虚拟机的生命周期(创建,删除,查看,管理)等,网络的管理和存储的管理。通过libvirt可以操作KVM,实现类似于virsh,virt-manager这些工具能够实现的功能,本文以查看当前hypervisor的所有instance为例,讲述通过libvirt模块,查看当前机器的虚拟机列表,关于libvirt的更多操作,如开机,关机,重启,网络管理,存储管理等操作,参考附件。


2. 实现代码

cat libvirt_vm.py       
#!/usr/bin/env python
#_*_ coding:utf8 _*_
#author:Happy
#blog aDDDress: Http://happylab.blog.51cto.com
#来自Happy实验室
import sys
try:
        import libvirt
        HAS_LIBVIRT = True
except Exception:
        HAS_LIBVIRT = False
def is_virtual():
        '''
        判断当前系统是否支持KVM虚拟化,不支持则退出
        '''
        if not HAS_LIBVIRT:
                sys.exit("current system are not support Virtualization")
        return 'virt' 
def get_conn():
        '''
        获取libvirt的连接句柄,用于提供操作libivrt的接口
        '''
        if is_virtual() == 'virt':
                try:
                        conn = libvirt.open('qemu:///system')
                except Exception as e:
                        sys.exit(e)
        return conn
def close_conn(conn):
        '''
        关闭libvirt的连接句柄
        '''
        return conn.close()
def list_active_vms():
        '''
        获取所有开机状态的instance,返回虚拟机的名字
        '''
        vms_list = []
        conn = get_conn()
        domain_list = conn.listDomainsID()
        for id in domain_list:
                vms_list.append(conn.lookupByID(id).name())
        close_conn(conn)
        return vms_list
def list_inactive_vms():
        '''
        获取关机状态的instance,返回虚拟机的名字
        '''
        vms_list = []
        conn = get_conn()
        for id in conn.listDefinedDomains():
                vms_list.append(id)
        close_conn(conn)
        return vms_list
def list_all_vms():
        '''
        获取所有的虚拟机
        '''
        vms = []
        vms.extend(list_active_vms())
        vms.extend(list_inactive_vms())
        return vms
def get_capability():
        '''
        得到hypervisor的容量信息,返回格式为XML
        '''
        conn = get_conn()
        capability = conn.getCapabilities()
        conn.close()
        return capability
def get_hostname():
        '''
        attain hypervisor's hostname
        '''
        conn = get_conn()
        hostname = conn.getHostname()
        conn.close()
        return hostname
def get_max_vcpus():
        '''
        获取hypervisor支持虚拟机的最大CPU数
        '''
        conn = get_conn()
        max_vcpus = conn.getMaxVcpus(None)
        conn.close()
        return max_vcpus
if __name__ == "__main__":
        print "当前主机%s的虚拟机列表:" % (get_hostname())
        for vms in list_active_vms():
                print vms

3. 测试

[root@ChuangYiYuan_10_16_2_19 ~]# Python libvirt_vm.py 
当前主机ChuangYiYuan_10_16_2_19的虚拟机列表:
instance-0000006b
instance-000001c1
instance-000000b9
instance-00000181
instance-000001f5
instance-000000cb
instance-0000007f
instance-000000eb
instance-00000145
instance-0000019b
instance-000001b9
instance-000000d7
instance-0000012b
instance-00000077
instance-00000165
instance-00000083

4. 总结

    通过libvirt能够实现KVM的管理,libvirt提供了大部分管理KVM的接口,通过改接口,可以实现openstack底层的操作。


5. 附录

    openstack关于libvirt底层的实现代码,供大家参考

"""
Supports KVM, LXC, QEMU, UML, and XEN.
"""
import errno
import eventlet
import functools
import glob
import mmap
import os
import shutil
import Socket
import sys
import tempfile
import threading
import time
import uuid

class LibvirtDriver(driver.ComputeDriver):
    capabilities = {
        "has_p_w_picpathcache": True,
        "supports_recreate": True,
        }
    def __init__(self, virtapi, read_only=False):
        super(LibvirtDriver, self).__init__(virtapi)
        global libvirt
        if libvirt is None:
            libvirt = __import__('libvirt')
        self._host_state = None
        self._initiator = None
        self._fc_wwnns = None
        self._fc_wwpns = None
        self._wrapped_conn = None
        self._wrapped_conn_lock = threading.Lock()
        self._caps = None
        self._vcpu_total = 0
        self.read_only = read_only
        self.firewall_driver = firewall.load_driver(
            DEFAULT_FIREWALL_DRIVER,
            self.virtapi,
            get_connection=self._get_connection)
        vif_class = importutils.import_class(CONF.libvirt.vif_driver)
        self.vif_driver = vif_class(self._get_connection)
        self.volume_drivers = driver.driver_dict_from_config(
            CONF.libvirt.volume_drivers, self)
        self.dev_filter = pci_whitelist.get_pci_devices_filter()
        self._event_queue = None
        self._disk_cachemode = None
        self.p_w_picpath_cache_manager = p_w_picpathcache.ImageCacheManager()
        self.p_w_picpath_backend = p_w_picpathbackend.Backend(CONF.use_cow_p_w_picpaths)
        self.disk_cachemodes = {}
        self.valid_cachemodes = ["default",
                                 "none",
                                 "writethrough",
                                 "writeback",
                                 "directsync",
                                 "unsafe",
                                ]
        for mode_str in CONF.libvirt.disk_cachemodes:
            disk_type, sep, cache_mode = mode_str.partition('=')
            if cache_mode not in self.valid_cachemodes:
                LOG.warn(_('Invalid cachemode %(cache_mode)s specified '
                           'for disk type %(disk_type)s.'),
                         {'cache_mode': cache_mode, 'disk_type': disk_type})
                continue
            self.disk_cachemodes[disk_type] = cache_mode
        self._volume_api = volume.API()
 
    def _get_new_connection(self):
        # call with _wrapped_conn_lock held
        LOG.debug(_('Connecting to libvirt: %s'), self.uri())
        wrapped_conn = None
        try:
            wrapped_conn = self._connect(self.uri(), self.read_only)
        finally:
            # Enabling the compute service, in case it was disabled
            # since the connection was successful.
            disable_reason = DISABLE_REASON_UNDEFINED
            if not wrapped_conn:
                disable_reason = 'Failed to connect to libvirt'
            self._set_host_enabled(bool(wrapped_conn), disable_reason)
        self._wrapped_conn = wrapped_conn
        try:
            LOG.debug(_("ReGIStering for lifecycle events %s"), self)
            wrapped_conn.domainEventRegisterAny(
                None,
                libvirt.VIR_DOMAIN_EVENT_ID_LIFECYCLE,
                self._event_lifecycle_callback,
                self)
        except Exception as e:
            LOG.warn(_("URI %(uri)s does not support events: %(error)s"),
                     {'uri': self.uri(), 'error': e})
        try:
            LOG.debug(_("Registering for connection events: %s") %
                      str(self))
            wrapped_conn.registerCloseCallback(self._close_callback, None)
        except (TypeError, AttributeError) as e:
            # NOTE: The registerCloseCallback of python-libvirt 1.0.1+
            # is defined with 3 arguments, and the above registerClose-
            # Callback succeeds. However, the one of python-libvirt 1.0.0
            # is defined with 4 arguments and TypeError happens here.
            # Then python-libvirt 0.9 does not define a method register-
            # CloseCallback.
            LOG.debug(_("The version of python-libvirt does not support "
                        "registerCloseCallback or is too old: %s"), e)
        except libvirt.libvirtError as e:
            LOG.warn(_("URI %(uri)s does not support connection"
                       " events: %(error)s"),
                     {'uri': self.uri(), 'error': e})
        return wrapped_conn
   @staticmethod
    def uri():
        if CONF.libvirt.virt_type == 'uml':
            uri = CONF.libvirt.connection_uri or 'uml:///system'
        elif CONF.libvirt.virt_type == 'xen':
            uri = CONF.libvirt.connection_uri or 'xen:///'
        elif CONF.libvirt.virt_type == 'lxc':
            uri = CONF.libvirt.connection_uri or 'lxc:///'
        else:
            uri = CONF.libvirt.connection_uri or 'qemu:///system'
        return uri
    @staticmethod
    def _connect(uri, read_only):
        def _connect_auth_cb(creds, opaque):
            if len(creds) == 0:
                return 0
            LOG.warning(
                _("Can not handle authentication request for %d credentials")
                % len(creds))
            raise exception.NovaException(
                _("Can not handle authentication request for %d credentials")
                % len(creds))
        auth = [[libvirt.VIR_CRED_AUTHNAME,
                 libvirt.VIR_CRED_ECHOPROMPT,
                 libvirt.VIR_CRED_REALM,
                 libvirt.VIR_CRED_PASSPHRASE,
                 libvirt.VIR_CRED_NOECHOPROMPT,
                 libvirt.VIR_CRED_EXTERNAL],
                _connect_auth_cb,
                None]
        try:
            flags = 0
            if read_only:
                flags = libvirt.VIR_CONNECT_RO
            # tpool.proxy_call creates a native thread. Due to limitations
            # with eventlet locking we cannot use the logging API inside
            # the called function.
            return tpool.proxy_call(
                (libvirt.virDomain, libvirt.virConnect),
                libvirt.openAuth, uri, auth, flags)
        except libvirt.libvirtError as ex:
            LOG.exception(_("Connection to libvirt failed: %s"), ex)
            payload = dict(ip=LibvirtDriver.get_host_ip_addr(),
                           method='_connect',
                           reason=ex)
            rpc.get_notifier('compute').error(nova_context.get_admin_context(),
                                              'compute.libvirt.error',
                                              payload)
            raise exception.HypervisorUnavailable(host=CONF.host)
    '''
                返回instance的个数,conn.numOfDomains()用于显示active的vm个数,conn.numOfDefinedDomains()则显示inactive的vm个数
    '''
    def get_num_instances(self):
        """Efficient override of base instance_exists method."""
        return self._conn.numOfDomains()
    '''
            检查虚拟机是否存在,根据名字校验
    '''
    def instance_exists(self, instance_name):
        """Efficient override of base instance_exists method."""
        try:
            self._lookup_by_name(instance_name)
            return True
        except exception.NovaException:
            return False
    '''
                查看libvirt active虚拟机的id号码,conn.numOfDomains()用于显示active虚拟机的个数,conn.numOfDefinedDomains()则用于显示inactive的虚拟机个数
    '''
    # TODO(Shrews): Remove when libvirt Bugzilla bug # 836647 is fixed.
    def list_instance_ids(self):
        if self._conn.numOfDomains() == 0:
            return []
        return self._conn.listDomainsID()
    '''
                返回虚拟机列表的名字,调用list_instance_ids()函数,只是显示active虚拟机的名字,其中conn.lookupByID(ids).name()用于显示instance的名字
    '''
    def list_instances(self):
        names = []
        for domain_id in self.list_instance_ids():
            try:
                # We skip domains with ID 0 (hypervisors).
                if domain_id != 0:
                    domain = self._lookup_by_id(domain_id)
                    names.append(domain.name())
            except exception.InstanceNotFound:
                # Ignore deleted instance while listing
                continue
        # extend instance list to contain also defined domains
        names.extend([vm for vm in self._conn.listDefinedDomains()
                    if vm not in names])
        return names
    '''
                查看instance的UUID号码,显示active+inactive状态的虚拟机的UUID号码,其中conn.lookupByID(ids).UUIDString()用于返回active instance的UUID号码
                                                            conn.lookupByName('name').UUIDString()则返回inactive虚拟机的UUID号
    '''
    def list_instance_uuids(self):
        uuids = set()
        for domain_id in self.list_instance_ids():
            try:
                # We skip domains with ID 0 (hypervisors).
                if domain_id != 0:
                    domain = self._lookup_by_id(domain_id)
                    uuids.add(domain.UUIDString())
            except exception.InstanceNotFound:
                # Ignore deleted instance while listing
                continue
        # extend instance list to contain also defined domains
        for domain_name in self._conn.listDefinedDomains():
            try:
                uuids.add(self._lookup_by_name(domain_name).UUIDString())
            except exception.InstanceNotFound:
                # Ignore deleted instance while listing
                continue
        return list(uuids)
    def plug_vifs(self, instance, network_info):
        """Plug VIFs into networks."""
        for vif in network_info:
            self.vif_driver.plug(instance, vif)
    def unplug_vifs(self, instance, network_info, ignore_errors=False):
        """Unplug VIFs from networks."""
        for vif in network_info:
            try:
                self.vif_driver.unplug(instance, vif)
            except exception.NovaException:
                if not ignore_errors:
                    raise
    def _teardown_container(self, instance):
        inst_path = libvirt_utils.get_instance_path(instance)
        container_dir = os.path.join(inst_path, 'rootfs')
        container_root_device = instance.get('root_device_name')
        disk.teardown_container(container_dir, container_root_device)
   
    def _undefine_domain(self, instance):
        try:
            virt_dom = self._lookup_by_name(instance['name'])
        except exception.InstanceNotFound:
            virt_dom = None
        if virt_dom:
            try:
                try:
                    virt_dom.undefineFlags(
                        libvirt.VIR_DOMAIN_UNDEFINE_MANAGED_SAVE)
                except libvirt.libvirtError:
                    LOG.debug(_("Error from libvirt during undefineFlags."
                        " Retrying with undefine"), instance=instance)
                    virt_dom.undefine()
                except AttributeError:
                    # NOTE(vish): Older versions of libvirt don't support
                    #             undefine flags, so attempt to do the
                    #             right thing.
                    try:
                        if virt_dom.hasManagedSaveImage(0):
                            virt_dom.managedSaveRemove(0)
                    except AttributeError:
                        pass
                    virt_dom.undefine()
            except libvirt.libvirtError as e:
                with excutils.save_and_reraise_exception():
                    errcode = e.get_error_code()
                    LOG.error(_('Error from libvirt during undefine. '
                                'Code=%(errcode)s Error=%(e)s') %
                              {'errcode': errcode, 'e': e}, instance=instance)
  
    def _cleanup_rbd(self, instance):
        pool = CONF.libvirt.p_w_picpaths_rbd_pool
        volumes = libvirt_utils.list_rbd_volumes(pool)
        pattern = instance['uuid']
        def belongs_to_instance(disk):
            return disk.startswith(pattern)
        volumes = filter(belongs_to_instance, volumes)
        if volumes:
            libvirt_utils.remove_rbd_volumes(pool, *volumes)
    def _cleanup_lvm(self, instance):
        """Delete all LVM disks for given instance object."""
        disks = self._lvm_disks(instance)
        if disks:
            libvirt_utils.remove_logical_volumes(*disks)
   
    @staticmethod
    def _get_disk_xml(xml, device):
        """Returns the xml for the disk mounted at device."""
        try:
            doc = etree.fromstring(xml)
        except Exception:
            return None
        ret = doc.findall('./devices/disk')
        for node in ret:
            for child in node.getchildren():
                if child.tag == 'target':
                    if child.get('dev') == device:
                        return etree.tostring(node)
    def _get_existing_domain_xml(self, instance, network_info,
                                 block_device_info=None):
        try:
            virt_dom = self._lookup_by_name(instance['name'])
            xml = virt_dom.XMLDesc(0)
        except exception.InstanceNotFound:
            disk_info = blockinfo.get_disk_info(CONF.libvirt.virt_type,
                                                instance,
                                                block_device_info)
            xml = self.to_xml(nova_context.get_admin_context(),
                              instance, network_info, disk_info,
                              block_device_info=block_device_info)
        return xml

--结束END--

本文标题: python实战系列之通过libvirt

本文链接: https://lsjlt.com/news/190028.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • python实战系列之通过libvirt
    1. 概述    libvirt是基于KVM的上层封装,提供了操作KVM的生层接口,如虚拟机的生命周期(创建,删除,查看,管理)等,网络的管理和存储的管理。通过libvirt可以操作KVM,实现类似于virsh,virt-manager这些...
    99+
    2023-01-31
    实战 系列之 python
  • Spider-Python实战之通过Py
    1.1 开发工具 Python 3.6 Pycharm Pro 2017.3.2 Text文本 1.2 Python库 requests re urllib 如果没有这些Python库,使用以下方法 pip install 需...
    99+
    2023-01-30
    实战 Spider Python
  • python实战系列之ip地址排序问题(
    1. 背景说明   从openstack的nova list中获取了虚拟机的ip地址,但这些ip都没有排序和分组,为了进一步增强可读性,对ip地址执行排序操作,在shell下,可以通过sort命令,执行排序操作,具体操作如下:[root@c...
    99+
    2023-01-31
    实战 地址 系列之
  • SpringBoot开发实战系列之定时器
    前言 定时器功能在项目里面往往会用到,比如定时发送邮件、定时释放数据库资源;这里记录一下springboot对定时器的支持的简单实例 cron表达式 开始之前要先介绍一下cron表...
    99+
    2024-04-02
  • Python算法应用实战之队列详解
    队列(queue) 队列是先进先出(FIFO, First-In-First-Out)的线性表,在具体应用中通常用链表或者数组来实现,队列只允许在后端(称为rear)进行插入操作,在前端(称为front)进...
    99+
    2022-06-04
    队列 算法 详解
  • Python通过队列实现进程间通信详情
    目录一、前言二、队列简介三、多进程队列的使用四、使用队列在进程间通信一、前言 在多进程中,每个进程之间是什么关系呢?其实每个进程都有自己的地址空间、内存、数据栈以及其他记录其运行状态...
    99+
    2024-04-02
  • Python如何通过队列实现进程间通信
    本篇内容主要讲解“Python如何通过队列实现进程间通信”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Python如何通过队列实现进程间通信”吧!一、前言在多进程中,每个进程之间是什么关系呢?其...
    99+
    2023-07-02
  • 项目实战软件测试系列之Python3 S
    项目实战软件测试系列之Python3 Selenium自动化实践系列视频课程,测试用例设计视频教程21套高级软件测试,性能测试,功能测试,自动化测试,接口测试,移动端测试,手机测试,WEB测试,***测试,测试用例设计,黑盒测试,白盒测试,...
    99+
    2023-01-31
    实战 测试 项目
  • 永恒之蓝实战教程之Mac通过Metasploit攻击Server2008的详细过程
    目录导读开发环境基础知识永恒之蓝Metasploitmeterpreter准备工作虚拟机安装Server2008Mac上安装MetasploitMac上安装远程桌面客户端Micros...
    99+
    2024-04-02
  • python练习之通过python pe
    #!/usr/bin/evn python import re,sys,os,pexpect from pexpect import * #coding=utf-8 #create environment if os.path.exists...
    99+
    2023-01-31
    python pe
  • Java实战之用Swing实现通讯录管理系统
    一、系统介绍  1.系统功能 登录系统 查询信息 新增信息 修改信息 删除信息 2.环境配置 JDK版本:1.8 Mysql:8...
    99+
    2024-04-02
  • Python实战之IQ测试系统的实现
    目录导语一、运行环境二、资料素材三、代码展示四、效果展示1)智商测试限时版本​2)木子测试导语 智商测试 通常,智商测试测验一个人在数字、空间、逻辑、词汇、创造、记忆等方面的能力。 ...
    99+
    2024-04-02
  • SpringBoot开发实战系列之动态定时任务
    目录前言代码编写效果演示  启动修改停止后记前言 定时器是我们项目中经常会用到的,SpringBoot使用@Scheduled注解可以快速启用一个简单的定时器(详情请看我们之前的博客...
    99+
    2024-04-02
  • Python全栈之路系列之Python
    The Python interpreter has a number of functions and types built into it that are always available. They are listed her...
    99+
    2023-01-31
    之路 系列之 Python
  • Python实战之天气预报系统的实现
    目录前言一、前期准备二、代码展示三、效果展示前言 鼎鼎大名的南方城市长沙很早就入冬了,街上各种大衣,毛衣,棉衣齐齐出动。 这段时间全国各地大风呜呜地吹,很多地方断崖式降温。 虽然前几...
    99+
    2022-12-19
    Python天气预报系统 Python天气预报
  • redis系列:通过队列案例学习list命令
    前言这一篇文章将讲述Redis中的list类型命令,同样也是通过demo来讲述,其他部分这里就不在赘述了。项目Github地址:https://github.com/rainbowda/learnWay/tree/master/learnR...
    99+
    2023-06-04
  • python之字符串系列
    python字符串1.序列的操作可通过len()函数验证长度,并通过索引操作得到各个元素例如: S=’abcd’ 字符串赋值给变量S 偏移量a对应0,以此类推Len(S) 验证长度4S[0] 索引(有正向和反向)‘a’S...
    99+
    2023-01-31
    字符串 系列 python
  • Python之函数系列(一)
    每个编程语言中(诸如:Java、C++、C)等都有函数的,Python也不例外函数的主要作用有哪些呢?1、将程序的功能进行模块化,功能模块清晰2、减少重复代码的工作量3、便于阅读及维护、调试等一、函数的结束及返回值# -*- coding:...
    99+
    2023-01-31
    函数 系列 Python
  • loadrunner12.6快速实战之通过抓包来获取app测试脚本
    除了上篇我们讲到的可以通过传统录制方式录制app脚本外(http://www.xqtesting.com/blog/loadrunner-app-346.html),loadrunner12.6还提供了分析流量包的功能,是不是感觉很高大上。...
    99+
    2023-06-05
  • Java毕业设计实战之校园一卡通系统的实现
    一、项目简述(+需求文档+PPT) 功能:卡管理,卡消费,卡充值,图书借阅,消费,记录,注销等等功能。 二、项目运行 环境配置: Jdk1.8 + Tomcat8.5 + mysql...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作