python调用libvirt API和装饰器应用

环境

内核及操作系统版本

cat /etc/redhat-release 
CentOS Linux release 7.6.1810 (Core) 
[root@localhost python]# uname -r
3.10.0-957.el7.x86_64

python版本

python -V
Python 2.7.5

安装libvirt-python

python调用libvirt需要libvirt模块,因此先安装这个模块。

yum -y install libvirt-python

安装该模块后查看增加的包。

[root@localhost python]# ll /usr/lib64/python2.7/site-packages/|grep libvirt
-rw-r--r--  1 root root   1738 11月  2 2018 libvirt_lxc.py
-rw-r--r--  2 root root   1680 11月  2 2018 libvirt_lxc.pyc
-rw-r--r--  2 root root   1680 11月  2 2018 libvirt_lxc.pyo
-rwxr-xr-x  1 root root  28496 11月  2 2018 libvirtmod_lxc.so
-rwxr-xr-x  1 root root  28760 11月  2 2018 libvirtmod_qemu.so
-rwxr-xr-x  1 root root 314712 11月  2 2018 libvirtmod.so
-rw-r--r--  1 root root 330338 11月 26 09:59 libvirt.py
-rw-r--r--  1 root root 366575 11月 26 10:16 libvirt.pyc
-rw-r--r--  1 root root 366575 11月  2 2018 libvirt.pyo
-rw-r--r--  1 root root   3213 11月  2 2018 libvirt_qemu.py
-rw-r--r--  2 root root   3226 11月  2 2018 libvirt_qemu.pyc
-rw-r--r--  2 root root   3226 11月  2 2018 libvirt_qemu.pyo

写代码调用libvirt的API

错误代码

cat /python/libvirt_python.py 
#!/usr/bin/python
#-*-coding:utf-8-*- 
import libvirt
import sys
 
def createConnection():
    conn = libvirt.openReadOnly(None)
    if conn == None:
        print '连接KVM失败'
        sys.exit(1)
    else:
        print '连接KVM成功'
        return conn
 
def closeConnection(conn):
    print ''
    try:
        conn.close()
    except:
        print '关闭KVM连接失败'
        return 1
    print 'KVM连接关闭'
 
def getDomInfoByName(conn, name):
    print ''
    print '通过KVM虚拟机名字获得虚拟机信息'
    try:
        domain = conn.lookupByName(name)
    except:
        print ("获取KVM域失败{}".format(name))
        return 1
         
    print "虚拟机ID: {}虚拟机名字: {}".format ( domain.ID(), domain.name())
    print "虚拟机状态: {}".format(domain.state(0))
    print "虚拟机信息: {}".format(domain.info())
    print "虚拟机最大内存:{} MB".format((domain.maxMemory()/1024))
    print "虚拟机内存状态:{}".format(domain.memoryStatus())
    print "虚拟机CPU核数:{}".format(domain.maxVcpus())
def getDomInfoByID(conn, id):
    print ''
    print '通过KVM虚拟机ID获得虚拟机信息'
    try:
        domain = conn.lookupByID(id)
    except:
        print 'Failed to find the Domain with ID "%"' % id
        return 1
         
    print "虚拟机ID: {}虚拟机名字: {}".format ( domain.ID(), domain.name())
    print "虚拟机状态: {}".format(domain.state(0))
    print "虚拟机信息: {}".format(domain.info())
    print "虚拟机最大内存:{} MB".format((domain.maxMemory()/1024))
    print "虚拟机内存状态:{}".format(domain.memoryStatus())
    print "虚拟机CPU核数:{}".format(domain.maxVcpus())
if __name__ == '__main__':
    name1 = sys.argv[2]
    #name2 = "notExist"
    id1 = int(sys.argv[1])
    #id2 = 9999
    print "获得域信息通过libvirt python API"
    conn = createConnection()
    getDomInfoByName(conn, name1)
    #getDomInfoByName(conn, name2)
    getDomInfoByID(conn, id1)
    #getDomInfoByID(conn, id2)
    closeConnection(conn)

执行代码前先用virsh查看虚拟机信息

virsh  list
 Id    名称                         状态
----------------------------------------------------
 3     CentOS7                        running

执行

[root@localhost python]# python libvirt_python.py 3 CentOS7
获得域信息通过libvirt python API
连接KVM成功

通过KVM虚拟机名字获得虚拟机信息
虚拟机ID: 3虚拟机名字: CentOS7
虚拟机状态: [1, 1]
虚拟机信息: [1, 1048576L, 1048576L, 1, 47080000000L]
虚拟机最大内存:1024 MB
Traceback (most recent call last):
  File "libvirt_python.py", line 61, in <module>
    getDomInfoByName(conn, name1)
  File "libvirt_python.py", line 37, in getDomInfoByName
    print "虚拟机内存状态:{}".format(domain.memoryStatus())
AttributeError: 'virDomain' object has no attribute 'memoryStatus'

报错解决

从报错上来看是没有memoryStatus这个函数,libvirt.py代码在/usr/lib64/python2.7/site-packages/目录下。grep过滤下这个函数名,发现真没有这个函数。

[root@localhost python]# grep memoryStatus /usr/lib64/python2.7/site-packages/libvirt.py
grep过滤下memory这个函数名,发现有memoryStats这个函数。改变libvirt_python代码中的memoryStatus函数为memoryStats函数。
[root@localhost python]# grep memory /usr/lib64/python2.7/site-packages/libvirt.py
        """This method will suspend a domain and save its memory contents to
        """Retrieve the maximum amount of physical memory allocated to a
        domain. If domain is None, then this get the amount of memory reserved
    def memoryParameters(self, flags=0):
        """Get the memory parameters """
    def memoryPeek(self, start, size, flags=0):
        """Read the contents of domain's memory """
    def memoryStats(self):
        """Extracts memory statistics for a domain """
                    repeatedly transferred memory pages during live migration. """
        transferred memory pages during live migration. It's supposed to be called
        Traditional pre-copy migration iteratively walks through guest memory
        memory pages.
        unpaused on destination. The source keeps sending all remaining memory pages
        guest tries to read a memory page which has not been migrated yet, the
             running on the destination host while some of its memory pages still
        this, any runtime changes, such as device hotplug or memory settings,
        """This method will suspend a domain and save its memory contents to
        """This method will suspend a domain and save its memory contents to
    def setMaxMemory(self, memory):
        """Dynamically change the maximum amount of physical memory allocated to a
        domain. If domain is None, then this change the amount of memory reserved
        ret = libvirtmod.virDomainSetMaxMemory(self._o, memory)
    def setMemory(self, memory):
        """Dynamically change the target amount of physical memory allocated to a
        domain. If domain is None, then this change the amount of memory reserved
        ret = libvirtmod.virDomainSetMemory(self._o, memory)
    def setMemoryFlags(self, memory, flags=0):
        """Dynamically change the target amount of physical memory allocated to a
        domain. If domain is None, then this change the amount of memory reserved
        If VIR_DOMAIN_MEM_MAXIMUM is set, the change affects domain's maximum memory
        size rather than current memory size.
        ret = libvirtmod.virDomainSetMemoryFlags(self._o, memory, flags)
        """Change the memory tunables """
        """Dynamically change the domain memory balloon driver statistics collection
        of the memory dump file, but reduces downtime of the guest while
        in the much rarer cases of running out of memory or disk space).
        to CPU resources and I/O but the memory used by the domain at the
        """Returns the available memory for a list of cells """
        """provides the free memory available on the Node
        Note: most libvirt APIs provide memory sizes in kibibytes, but in this
        """Extract hardware information about the Node. Note that the memory size is reported in MiB instead of KiB. """
        """Get the node memory parameters """
        """Extract node's memory statistics. """
        """Change the node memory tunables """
VIR_DOMAIN_JOB_MEMORY_BPS = "memory_bps"
VIR_DOMAIN_JOB_MEMORY_CONSTANT = "memory_constant"
VIR_DOMAIN_JOB_MEMORY_DIRTY_RATE = "memory_dirty_rate"
VIR_DOMAIN_JOB_MEMORY_ITERATION = "memory_iteration"
VIR_DOMAIN_JOB_MEMORY_NORMAL = "memory_normal"
VIR_DOMAIN_JOB_MEMORY_NORMAL_BYTES = "memory_normal_bytes"
VIR_DOMAIN_JOB_MEMORY_PAGE_SIZE = "memory_page_size"
VIR_DOMAIN_JOB_MEMORY_PROCESSED = "memory_processed"
VIR_DOMAIN_JOB_MEMORY_REMAINING = "memory_remaining"
VIR_DOMAIN_JOB_MEMORY_TOTAL = "memory_total"

正确代码

更改后的代码为

cat /python/libvirt_python.py 
#!/usr/bin/python
#-*-coding:utf-8-*- 
import libvirt
import sys
 
def createConnection():
    conn = libvirt.openReadOnly(None)
    if conn == None:
        print '连接KVM失败'
        sys.exit(1)
    else:
        print '连接KVM成功'
        return conn
 
def closeConnection(conn):
    print ''
    try:
        conn.close()
    except:
        print '关闭KVM连接失败'
        return 1
    print 'KVM连接关闭'
 
def getDomInfoByName(conn, name):
    print ''
    print '通过KVM虚拟机名字获得虚拟机信息'
    try:
        domain = conn.lookupByName(name)
    except:
        print ("获取KVM域失败{}".format(name))
        return 1
         
    print "虚拟机ID: {}虚拟机名字: {}".format ( domain.ID(), domain.name())
    print "虚拟机状态: {}".format(domain.state(0))
    print "虚拟机信息: {}".format(domain.info())
    print "虚拟机最大内存:{} MB".format((domain.maxMemory()/1024))
    print "虚拟机内存状态:{}".format(domain.memoryStats())
    print "虚拟机CPU核数:{}".format(domain.maxVcpus())
def getDomInfoByID(conn, id):
    print ''
    print '通过KVM虚拟机ID获得虚拟机信息'
    try:
        domain = conn.lookupByID(id)
    except:
        print 'Failed to find the Domain with ID "%"' % id
        return 1
         
    print "虚拟机ID: {}虚拟机名字: {}".format ( domain.ID(), domain.name())
    print "虚拟机状态: {}".format(domain.state(0))
    print "虚拟机信息: {}".format(domain.info())
    print "虚拟机最大内存:{} MB".format((domain.maxMemory()/1024))
    print "虚拟机内存状态:{}".format(domain.memoryStats())
    print "虚拟机CPU核数:{}".format(domain.maxVcpus())
if __name__ == '__main__':
    name1 = sys.argv[2]
    #name2 = "notExist"
    id1 = int(sys.argv[1])
    #id2 = 9999
    print "获得域信息通过libvirt python API"
    conn = createConnection()
    getDomInfoByName(conn, name1)
    #getDomInfoByName(conn, name2)
    getDomInfoByID(conn, id1)
    #getDomInfoByID(conn, id2)
    closeConnection(conn)

执行代码前先用virsh查看虚拟机信息

virsh  list
 Id    名称                         状态
----------------------------------------------------
 3     CentOS7                        running

执行

[root@localhost python]# python libvirt_python.py 3 CentOS7
获得域信息通过libvirt python API
连接KVM成功

通过KVM虚拟机名字获得虚拟机信息
虚拟机ID: 3虚拟机名字: CentOS7
虚拟机状态: [1, 1]
虚拟机信息: [1, 1048576L, 1048576L, 1, 45570000000L]
虚拟机最大内存:1024 MB
虚拟机内存状态:{
     'swap_out': 0L, 'available': 1015000L, 'actual': 1048576L, 'major_fault': 192L, 'swap_in': 0L, 'last_update': 1606358542L, 'unused': 918512L, 'minor_fault': 578127L, 'rss': 337104L}
虚拟机CPU核数:1

通过KVM虚拟机ID获得虚拟机信息
虚拟机ID: 3虚拟机名字: CentOS7
虚拟机状态: [1, 1]
虚拟机信息: [1, 1048576L, 1048576L, 1, 45570000000L]
虚拟机最大内存:1024 MB
虚拟机内存状态:{
     'swap_out': 0L, 'available': 1015000L, 'actual': 1048576L, 'major_fault': 192L, 'swap_in': 0L, 'last_update': 1606358542L, 'unused': 918512L, 'minor_fault': 578127L, 'rss': 337104L}
虚拟机CPU核数:1

KVM连接关闭

采用装饰器输出内存详细信息

从输出可以看到虚拟机内存状态输出的项很多,可不可以将其更加细化,输出一项呢。
首先往代码里加一行print “虚拟机内存状态输出的数据类型{}”.format(type(domain.memoryStats())),查看下内存状态输出的数据类型。

[root@localhost python]# cat /python/libvirt_python.py 
#!/usr/bin/python
#-*-coding:utf-8-*- 
import libvirt
import sys
 
def createConnection():
    conn = libvirt.openReadOnly(None)
    if conn == None:
        print '连接KVM失败'
        sys.exit(1)
    else:
        print '连接KVM成功'
        return conn
 
def closeConnection(conn):
    print ''
    try:
        conn.close()
    except:
        print '关闭KVM连接失败'
        return 1
    print 'KVM连接关闭'
 
def getDomInfoByName(conn, name):
    print ''
    print '通过KVM虚拟机名字获得虚拟机信息'
    try:
        domain = conn.lookupByName(name)
    except:
        print ("获取KVM域失败{}".format(name))
        return 1
         
    print "虚拟机ID: {}虚拟机名字: {}".format ( domain.ID(), domain.name())
    print "虚拟机状态: {}".format(domain.state(0))
    print "虚拟机信息: {}".format(domain.info())
    print "虚拟机最大内存:{} MB".format((domain.maxMemory()/1024))
    print "虚拟机内存状态:{}".format(domain.memoryStats())
    print "虚拟机CPU核数:{}".format(domain.maxVcpus())
    print "虚拟机内存状态输出的数据类型{}".format(type(domain.memoryStats()))
def getDomInfoByID(conn, id):
    print ''
    print '通过KVM虚拟机ID获得虚拟机信息'
    try:
        domain = conn.lookupByID(id)
    except:
        print 'Failed to find the Domain with ID "%"' % id
        return 1
         
    print "虚拟机ID: {}虚拟机名字: {}".format ( domain.ID(), domain.name())
    print "虚拟机状态: {}".format(domain.state(0))
    print "虚拟机信息: {}".format(domain.info())
    print "虚拟机最大内存:{} MB".format((domain.maxMemory()/1024))
    print "虚拟机内存状态:{}".format(domain.memoryStats())
    print "虚拟机CPU核数:{}".format(domain.maxVcpus())
    print "虚拟机内存状态输出的数据类型{}".format(type(domain.memoryStats()))
if __name__ == '__main__':
    name1 = sys.argv[2]
    #name2 = "notExist"
    id1 = int(sys.argv[1])
    #id2 = 9999
    print "获得域信息通过libvirt python API"
    conn = createConnection()
    getDomInfoByName(conn, name1)
    #getDomInfoByName(conn, name2)
    getDomInfoByID(conn, id1)
    #getDomInfoByID(conn, id2)
    closeConnection(conn)

执行查看下内存状态输出的数据类型

python libvirt_python.py 3 CentOS7
获得域信息通过libvirt python API
连接KVM成功

通过KVM虚拟机名字获得虚拟机信息
虚拟机ID: 3虚拟机名字: CentOS7
虚拟机状态: [1, 1]
虚拟机信息: [1, 1048576L, 1048576L, 1, 55140000000L]
虚拟机最大内存:1024 MB
虚拟机内存状态:{
     'swap_out': 0L, 'available': 1015000L, 'actual': 1048576L, 'major_fault': 192L, 'swap_in': 0L, 'last_update': 1606358542L, 'unused': 918512L, 'minor_fault': 578127L, 'rss': 337088L}
虚拟机CPU核数:1
虚拟机内存状态输出的数据类型<type 'dict'>

通过KVM虚拟机ID获得虚拟机信息
虚拟机ID: 3虚拟机名字: CentOS7
虚拟机状态: [1, 1]
虚拟机信息: [1, 1048576L, 1048576L, 1, 55140000000L]
虚拟机最大内存:1024 MB
虚拟机内存状态:{
     'swap_out': 0L, 'available': 1015000L, 'actual': 1048576L, 'major_fault': 192L, 'swap_in': 0L, 'last_update': 1606358542L, 'unused': 918512L, 'minor_fault': 578127L, 'rss': 337088L}
虚拟机CPU核数:1
虚拟机内存状态输出的数据类型<type 'dict'>

KVM连接关闭

可以看到输出的数据类型为字典,故想要获得内存的详细输出信息,用字典方法即可。
另外这里的函数已经写好,在不改变原来函数的代码的时候,可以使用装饰器来修改函数的输出。

用装饰器装饰函数getDomInfoByName

cat /python/libvirt_python.py 
#!/usr/bin/python
#-*-coding:utf-8-*- 
import libvirt
import sys
 
def createConnection():
    conn = libvirt.openReadOnly(None)
    if conn == None:
        print '连接KVM失败'
        sys.exit(1)
    else:
        print '连接KVM成功'
        return conn
 
def closeConnection(conn):
    print ''
    try:
        conn.close()
    except:
        print '关闭KVM连接失败'
        return 1
    print 'KVM连接关闭'
 
def decorator(func):
   def innerfun(conn,name):
      try:
         print ''
         func(conn,name)
         print("采用字典方法,输出内存详细信息======================================")
         domain = conn.lookupByName(name)
         for k,v in domain.memoryStats().items():
            print(k,v)
         print("内存详细信息输出完毕================================================")
      except:
         print('装饰器输出内存详细信息有错误,请检查装饰器代码')
         print ''
   return innerfun
@decorator
def getDomInfoByName(conn, name):
    print ''
    print '通过KVM虚拟机名字获得虚拟机信息'
    try:
        domain = conn.lookupByName(name)
    except:
        print ("获取KVM域失败{}".format(name))
        return 1
         
    print "虚拟机ID: {}虚拟机名字: {}".format ( domain.ID(), domain.name())
    print "虚拟机状态: {}".format(domain.state(0))
    print "虚拟机信息: {}".format(domain.info())
    print "虚拟机最大内存:{} MB".format((domain.maxMemory()/1024))
    print "虚拟机内存状态:{}".format(domain.memoryStats())
    print "虚拟机CPU核数:{}".format(domain.maxVcpus())
    print "虚拟机内存状态输出的数据类型{}".format(type(domain.memoryStats()))

def getDomInfoByID(conn, id):
    print ''
    print '通过KVM虚拟机ID获得虚拟机信息'
    try:
        domain = conn.lookupByID(id)
    except:
        print 'Failed to find the Domain with ID "%"' % id
        return 1
         
    print "虚拟机ID: {}虚拟机名字: {}".format ( domain.ID(), domain.name())
    print "虚拟机状态: {}".format(domain.state(0))
    print "虚拟机信息: {}".format(domain.info())
    print "虚拟机最大内存:{} MB".format((domain.maxMemory()/1024))
    print "虚拟机内存状态:{}".format(domain.memoryStats())
    print "虚拟机CPU核数:{}".format(domain.maxVcpus())
    print "虚拟机内存状态输出的数据类型{}".format(type(domain.memoryStats()))

if __name__ == '__main__':
    name1 = sys.argv[2]
    #name2 = "notExist"
    id1 = int(sys.argv[1])
    #id2 = 9999
    print "获得域信息通过libvirt python API"
    conn = createConnection()
    getDomInfoByName(conn, name1)
    #getDomInfoByName(conn, name2)
    getDomInfoByID(conn, id1)
    #getDomInfoByID(conn, id2)
    closeConnection(conn)

运行

python libvirt_python.py 3 CentOS7
获得域信息通过libvirt python API
连接KVM成功


通过KVM虚拟机名字获得虚拟机信息
虚拟机ID: 3虚拟机名字: CentOS7
虚拟机状态: [1, 1]
虚拟机信息: [1, 1048576L, 1048576L, 1, 60950000000L]
虚拟机最大内存:1024 MB
虚拟机内存状态:{
     'swap_out': 0L, 'available': 1015000L, 'actual': 1048576L, 'major_fault': 192L, 'swap_in': 0L, 'last_update': 1606358542L, 'unused': 918512L, 'minor_fault': 578127L, 'rss': 337104L}
虚拟机CPU核数:1
虚拟机内存状态输出的数据类型<type 'dict'>
采用字典方法,输出内存详细信息======================================
('swap_out', 0L)
('available', 1015000L)
('actual', 1048576L)
('major_fault', 192L)
('swap_in', 0L)
('last_update', 1606358542L)
('unused', 918512L)
('minor_fault', 578127L)
('rss', 337104L)
内存详细信息输出完毕================================================

通过KVM虚拟机ID获得虚拟机信息
虚拟机ID: 3虚拟机名字: CentOS7
虚拟机状态: [1, 1]
虚拟机信息: [1, 1048576L, 1048576L, 1, 60960000000L]
虚拟机最大内存:1024 MB
虚拟机内存状态:{
     'swap_out': 0L, 'available': 1015000L, 'actual': 1048576L, 'major_fault': 192L, 'swap_in': 0L, 'last_update': 1606358542L, 'unused': 918512L, 'minor_fault': 578127L, 'rss': 337104L}
虚拟机CPU核数:1
虚拟机内存状态输出的数据类型<type 'dict'>

KVM连接关闭

注意:想装饰哪个函数就把装饰器定义在哪个函数的前面,并且在被装饰函数之前@装饰器,这样操作后仅仅是@装饰器后边的第一个函数会被装饰,如果想装饰其他函数,直接在函数前边@装饰器。

用装饰器装饰另外一个函数getDomInfoByID

cat /python/libvirt_python.py 
#!/usr/bin/python
#-*-coding:utf-8-*- 
import libvirt
import sys
 
def createConnection():
    conn = libvirt.openReadOnly(None)
    if conn == None:
        print '连接KVM失败'
        sys.exit(1)
    else:
        print '连接KVM成功'
        return conn
 
def closeConnection(conn):
    print ''
    try:
        conn.close()
    except:
        print '关闭KVM连接失败'
        return 1
    print 'KVM连接关闭'
 
def decorator(func):
   def innerfun(conn,name):
      try:
         print ''
         func(conn,name)
         print("采用字典方法,输出内存详细信息======================================")
         domain = conn.lookupByName(name)
         for k,v in domain.memoryStats().items():
            print(k,v)
         print("内存详细信息输出完毕================================================")
      except:
         print('装饰器输出内存详细信息有错误,请检查装饰器代码')
         print ''
   return innerfun
@decorator
def getDomInfoByName(conn, name):
    print ''
    print '通过KVM虚拟机名字获得虚拟机信息'
    try:
        domain = conn.lookupByName(name)
    except:
        print ("获取KVM域失败{}".format(name))
        return 1
         
    print "虚拟机ID: {}虚拟机名字: {}".format ( domain.ID(), domain.name())
    print "虚拟机状态: {}".format(domain.state(0))
    print "虚拟机信息: {}".format(domain.info())
    print "虚拟机最大内存:{} MB".format((domain.maxMemory()/1024))
    print "虚拟机内存状态:{}".format(domain.memoryStats())
    print "虚拟机CPU核数:{}".format(domain.maxVcpus())
    print "虚拟机内存状态输出的数据类型{}".format(type(domain.memoryStats()))

@decorator
def getDomInfoByID(conn, id):
    print ''
    print '通过KVM虚拟机ID获得虚拟机信息'
    try:
        domain = conn.lookupByID(id)
    except:
        print 'Failed to find the Domain with ID "%"' % id
        return 1
         
    print "虚拟机ID: {}虚拟机名字: {}".format ( domain.ID(), domain.name())
    print "虚拟机状态: {}".format(domain.state(0))
    print "虚拟机信息: {}".format(domain.info())
    print "虚拟机最大内存:{} MB".format((domain.maxMemory()/1024))
    print "虚拟机内存状态:{}".format(domain.memoryStats())
    print "虚拟机CPU核数:{}".format(domain.maxVcpus())
    print "虚拟机内存状态输出的数据类型{}".format(type(domain.memoryStats()))

if __name__ == '__main__':
    name1 = sys.argv[2]
    #name2 = "notExist"
    id1 = int(sys.argv[1])
    #id2 = 9999
    print "获得域信息通过libvirt python API"
    conn = createConnection()
    getDomInfoByName(conn, name1)
    #getDomInfoByName(conn, name2)
    getDomInfoByID(conn, id1)
    #getDomInfoByID(conn, id2)
    closeConnection(conn)

执行

python libvirt_python.py 3 CentOS7
获得域信息通过libvirt python API
连接KVM成功


通过KVM虚拟机名字获得虚拟机信息
虚拟机ID: 3虚拟机名字: CentOS7
虚拟机状态: [1, 1]
虚拟机信息: [1, 1048576L, 1048576L, 1, 61940000000L]
虚拟机最大内存:1024 MB
虚拟机内存状态:{
     'swap_out': 0L, 'available': 1015000L, 'actual': 1048576L, 'major_fault': 192L, 'swap_in': 0L, 'last_update': 1606358542L, 'unused': 918512L, 'minor_fault': 578127L, 'rss': 337088L}
虚拟机CPU核数:1
虚拟机内存状态输出的数据类型<type 'dict'>
采用字典方法,输出内存详细信息======================================
('swap_out', 0L)
('available', 1015000L)
('actual', 1048576L)
('major_fault', 192L)
('swap_in', 0L)
('last_update', 1606358542L)
('unused', 918512L)
('minor_fault', 578127L)
('rss', 337088L)
内存详细信息输出完毕================================================


通过KVM虚拟机ID获得虚拟机信息
虚拟机ID: 3虚拟机名字: CentOS7
虚拟机状态: [1, 1]
虚拟机信息: [1, 1048576L, 1048576L, 1, 61950000000L]
虚拟机最大内存:1024 MB
虚拟机内存状态:{
     'swap_out': 0L, 'available': 1015000L, 'actual': 1048576L, 'major_fault': 192L, 'swap_in': 0L, 'last_update': 1606358542L, 'unused': 918512L, 'minor_fault': 578127L, 'rss': 337088L}
虚拟机CPU核数:1
虚拟机内存状态输出的数据类型<type 'dict'>
采用字典方法,输出内存详细信息======================================
装饰器输出内存详细信息有错误,请检查装饰器代码


KVM连接关闭

可以看到装饰第二个函数失败,这是因为第二个函数里面获取内存的那个方法和第一个函数不一样,第一个函数是conn.lookupByName(),而第二个函数是conn.lookupByID(),这里改进一下,判断下输入的函数名是哪个,然后就调用相应的方法即可。
要动态地获取函数名字并不是简单的事,容易犯的错误为直接func==‘函数名’,下面来演示下这样会不会成功

cat /python/libvirt_python.py 
#!/usr/bin/python
#-*-coding:utf-8-*- 
import libvirt
import sys
 
def createConnection():
    conn = libvirt.openReadOnly(None)
    if conn == None:
        print '连接KVM失败'
        sys.exit(1)
    else:
        print '连接KVM成功'
        return conn
 
def closeConnection(conn):
    print ''
    try:
        conn.close()
    except:
        print '关闭KVM连接失败'
        return 1
    print 'KVM连接关闭'
 
def decorator(func):
   def innerfun(conn,name):
      try:
         print ''
         func(conn,name)
         print("采用字典方法,输出内存详细信息======================================")
         if func=='getDomInfoByName':
            domain = conn.lookupByName(name)
            for k,v in domain.memoryStats().items():
               print(k,v)
         elif func=='getDomInfoByID':
            domain = conn.lookupByID(name)
            for k,v in domain.memoryStats().items():
               print(k,v)
         else:
            print '没有获取到函数名'
         print("内存详细信息输出完毕================================================")
      except:
         print('装饰器输出内存详细信息有错误,请检查装饰器代码')
         print ''
   return innerfun
@decorator
def getDomInfoByName(conn, name):
    print ''
    print '通过KVM虚拟机名字获得虚拟机信息'
    try:
        domain = conn.lookupByName(name)
    except:
        print ("获取KVM域失败{}".format(name))
        return 1
         
    print "虚拟机ID: {}虚拟机名字: {}".format ( domain.ID(), domain.name())
    print "虚拟机状态: {}".format(domain.state(0))
    print "虚拟机信息: {}".format(domain.info())
    print "虚拟机最大内存:{} MB".format((domain.maxMemory()/1024))
    print "虚拟机内存状态:{}".format(domain.memoryStats())
    print "虚拟机CPU核数:{}".format(domain.maxVcpus())
    print "虚拟机内存状态输出的数据类型{}".format(type(domain.memoryStats()))

@decorator
def getDomInfoByID(conn, id):
    print ''
    print '通过KVM虚拟机ID获得虚拟机信息'
    try:
        domain = conn.lookupByID(id)
    except:
        print 'Failed to find the Domain with ID "%"' % id
        return 1
         
    print "虚拟机ID: {}虚拟机名字: {}".format ( domain.ID(), domain.name())
    print "虚拟机状态: {}".format(domain.state(0))
    print "虚拟机信息: {}".format(domain.info())
    print "虚拟机最大内存:{} MB".format((domain.maxMemory()/1024))
    print "虚拟机内存状态:{}".format(domain.memoryStats())
    print "虚拟机CPU核数:{}".format(domain.maxVcpus())
    print "虚拟机内存状态输出的数据类型{}".format(type(domain.memoryStats()))

if __name__ == '__main__':
    name1 = sys.argv[2]
    #name2 = "notExist"
    id1 = int(sys.argv[1])
    #id2 = 9999
    print "获得域信息通过libvirt python API"
    conn = createConnection()
    getDomInfoByName(conn, name1)
    #getDomInfoByName(conn, name2)
    getDomInfoByID(conn, id1)
    #getDomInfoByID(conn, id2)
    closeConnection(conn)

由执行结果可知,并没有成功,这是因为func其实是一个函数的内存地址信息,并不是函数的名字,要获取函数名字有个方法__name__

python3.5 libvirt_python.py 3 CentOS7
获得域信息通过libvirt python API
连接KVM成功


通过KVM虚拟机名字获得虚拟机信息
虚拟机ID: 3虚拟机名字: CentOS7
虚拟机状态: [1, 1]
虚拟机信息: [1, 1048576L, 1048576L, 1, 68200000000L]
虚拟机最大内存:1024 MB
虚拟机内存状态:{
     'swap_out': 0L, 'available': 1015000L, 'actual': 1048576L, 'major_fault': 192L, 'swap_in': 0L, 'last_update': 1606358542L, 'unused': 918512L, 'minor_fault': 578127L, 'rss': 337088L}
虚拟机CPU核数:1
虚拟机内存状态输出的数据类型<type 'dict'>
采用字典方法,输出内存详细信息======================================
没有获取到函数名
内存详细信息输出完毕================================================


通过KVM虚拟机ID获得虚拟机信息
虚拟机ID: 3虚拟机名字: CentOS7
虚拟机状态: [1, 1]
虚拟机信息: [1, 1048576L, 1048576L, 1, 68200000000L]
虚拟机最大内存:1024 MB
虚拟机内存状态:{
     'swap_out': 0L, 'available': 1015000L, 'actual': 1048576L, 'major_fault': 192L, 'swap_in': 0L, 'last_update': 1606358542L, 'unused': 918512L, 'minor_fault': 578127L, 'rss': 337088L}
虚拟机CPU核数:1
虚拟机内存状态输出的数据类型<type 'dict'>
采用字典方法,输出内存详细信息======================================
没有获取到函数名
内存详细信息输出完毕================================================

KVM连接关闭

用__name__方法获取函数名装饰两个函数

cat /python/libvirt_python.py 
#!/usr/bin/python
#-*-coding:utf-8-*- 
import libvirt
import sys
 
def createConnection():
    conn = libvirt.openReadOnly(None)
    if conn == None:
        print '连接KVM失败'
        sys.exit(1)
    else:
        print '连接KVM成功'
        return conn
 
def closeConnection(conn):
    print ''
    try:
        conn.close()
    except:
        print '关闭KVM连接失败'
        return 1
    print 'KVM连接关闭'
 
def decorator(func):
   def innerfun(conn,name):
      try:
         print ''
         func(conn,name)
         print("采用字典方法,输出内存详细信息======================================")
         if func.__name__=='getDomInfoByName':
            domain = conn.lookupByName(name)
            for k,v in domain.memoryStats().items():
               print(k,v)
         elif func.__name__=='getDomInfoByID':
            domain = conn.lookupByID(name)
            for k,v in domain.memoryStats().items():
               print(k,v)
         else:
            print '没有获取到函数名'
         print("内存详细信息输出完毕================================================")
      except:
         print('装饰器输出内存详细信息有错误,请检查装饰器代码')
         print ''
   return innerfun
@decorator
def getDomInfoByName(conn, name):
    print ''
    print '通过KVM虚拟机名字获得虚拟机信息'
    try:
        domain = conn.lookupByName(name)
    except:
        print ("获取KVM域失败{}".format(name))
        return 1
         
    print "虚拟机ID: {}虚拟机名字: {}".format ( domain.ID(), domain.name())
    print "虚拟机状态: {}".format(domain.state(0))
    print "虚拟机信息: {}".format(domain.info())
    print "虚拟机最大内存:{} MB".format((domain.maxMemory()/1024))
    print "虚拟机内存状态:{}".format(domain.memoryStats())
    print "虚拟机CPU核数:{}".format(domain.maxVcpus())
    print "虚拟机内存状态输出的数据类型{}".format(type(domain.memoryStats()))

@decorator
def getDomInfoByID(conn, id):
    print ''
    print '通过KVM虚拟机ID获得虚拟机信息'
    try:
        domain = conn.lookupByID(id)
    except:
        print 'Failed to find the Domain with ID "%"' % id
        return 1
         
    print "虚拟机ID: {}虚拟机名字: {}".format ( domain.ID(), domain.name())
    print "虚拟机状态: {}".format(domain.state(0))
    print "虚拟机信息: {}".format(domain.info())
    print "虚拟机最大内存:{} MB".format((domain.maxMemory()/1024))
    print "虚拟机内存状态:{}".format(domain.memoryStats())
    print "虚拟机CPU核数:{}".format(domain.maxVcpus())
    print "虚拟机内存状态输出的数据类型{}".format(type(domain.memoryStats()))

if __name__ == '__main__':
    name1 = sys.argv[2]
    #name2 = "notExist"
    id1 = int(sys.argv[1])
    #id2 = 9999
    print "获得域信息通过libvirt python API"
    conn = createConnection()
    getDomInfoByName(conn, name1)
    #getDomInfoByName(conn, name2)
    getDomInfoByID(conn, id1)
    #getDomInfoByID(conn, id2)
    closeConnection(conn)

[root@localhost python]# python3.5 libvirt_python.py 3 CentOS7
获得域信息通过libvirt python API
连接KVM成功
通过KVM虚拟机名字获得虚拟机信息
虚拟机ID: 3虚拟机名字: CentOS7
虚拟机状态: [1, 1]
虚拟机信息: [1, 1048576L, 1048576L, 1, 69200000000L]
虚拟机最大内存:1024 MB
虚拟机内存状态:{
     'swap_out': 0L, 'available': 1015000L, 'actual': 1048576L, 'major_fault': 192L, 'swap_in': 0L, 'last_update': 1606358542L, 'unused': 918512L, 'minor_fault': 578127L, 'rss': 337088L}
虚拟机CPU核数:1
虚拟机内存状态输出的数据类型<type 'dict'>
采用字典方法,输出内存详细信息======================================
('swap_out', 0L)
('available', 1015000L)
('actual', 1048576L)
('major_fault', 192L)
('swap_in', 0L)
('last_update', 1606358542L)
('unused', 918512L)
('minor_fault', 578127L)
('rss', 337088L)
内存详细信息输出完毕================================================


通过KVM虚拟机ID获得虚拟机信息
虚拟机ID: 3虚拟机名字: CentOS7
虚拟机状态: [1, 1]
虚拟机信息: [1, 1048576L, 1048576L, 1, 69210000000L]
虚拟机最大内存:1024 MB
虚拟机内存状态:{
     'swap_out': 0L, 'available': 1015000L, 'actual': 1048576L, 'major_fault': 192L, 'swap_in': 0L, 'last_update': 1606358542L, 'unused': 918512L, 'minor_fault': 578127L, 'rss': 337088L}
虚拟机CPU核数:1
虚拟机内存状态输出的数据类型<type 'dict'>
采用字典方法,输出内存详细信息======================================
('swap_out', 0L)
('available', 1015000L)
('actual', 1048576L)
('major_fault', 192L)
('swap_in', 0L)
('last_update', 1606358542L)
('unused', 918512L)
('minor_fault', 578127L)
('rss', 337088L)
内存详细信息输出完毕================================================

KVM连接关闭

libvirtd.py其他函数的使用方法

cat /python/test.py 
#!/usr/bin/python
#-*-coding:utf-8-*- 
import libvirt
import sys
 
def createConnection():
    conn = libvirt.openReadOnly(None)
    if conn == None:
        print '连接KVM失败'
        sys.exit(1)
    else:
        print '连接KVM成功'
        return conn
 
def closeConnection(conn):
    print ''
    try:
        conn.close()
    except:
        print '关闭KVM连接失败'
        return 1
    print 'KVM连接关闭'
    
def test(conn):
   print "域网卡(virsh net-list获取的网卡){}".format(conn.listNetworks())
   print "宿主机主机名{}".format(conn.getHostname())
   print "域不活跃的网卡(virsh net-list --all获取的不活跃的网卡){}".format(conn.listDefinedNetworks())
   print "宿主机内存剩余{}".format(conn.getFreeMemory()/1024/1024/1024)
   print "宿主机信息{}".format(conn.getInfo())
   print "宿主机信息数据类型{}".format(type(conn.getInfo()))
   print "连接域的uri{}".format(conn.getURI())
   print "虚拟化类型{}".format(conn.getType())
   print "虚拟机id{}".format(conn.listDomainsID())
   print "宿主机原生的网卡{}".format(conn.listInterfaces())
   print "域活跃的网卡数{}".format(conn.numOfNetworks())
   
if __name__ == '__main__':
    conn = createConnection()
    test(conn)
    closeConnection(conn)
[root@kvm python]# python test.py 
连接KVM成功
域网卡(virsh net-list获取的网卡)['default']
宿主机主机名kvm
域不活跃的网卡(virsh net-list --all获取的不活跃的网卡)['CentOS7-net']
宿主机内存剩余1
宿主机信息['x86_64', 4095L, 2, 3691, 1, 1, 2, 1]
宿主机信息数据类型<type 'list'>
连接域的uriqemu:///system
虚拟化类型QEMU
虚拟机id[6]
宿主机原生的网卡['br0', 'lo']
域活跃的网卡数1

KVM连接关闭

你可能感兴趣的:(Python,python)