openstack nova调用libvirt,跟踪libvirt源码实例详解(cpu_mode及live_migrate 错误解决)

感谢朋友支持本博客,欢迎共同探讨交流,由于能力和时间有限,错误之处在所难免,欢迎指正!

如有转载,请保留源作者博客信息。

Better Me的博客:blog.csdn.net/tantexian

如需交流,欢迎大家博客留言。



    本文中分两部分来讲解:

第一部分:讲解openstack中热迁移出现了CPU不兼容错误,nova错误定位方法

第二部分:讲解在nova中定位了是由于调用libvirt的迁移兼容函数判断为不兼容。因此从该处一路跟踪到libvirt源码 中去。顺带讲了 vim+ctags跟踪源码




第一部分:
"/usr/lib/python2.6/site-packages/eventlet/tpool.py", line 183, in doit
2014-11-12 18:14:33.353 31086 TRACE oslo.messaging.rpc.dispatcher result = proxy_call(self._autowrap, f, *args, **kwargs)
2014-11-12 18:14:33.353 31086 TRACE oslo.messaging.rpc.dispatcher File "/usr/lib/python2.6/site-packages/eventlet/tpool.py", line 141, in proxy_call
2014-11-12 18:14:33.353 31086 TRACE oslo.messaging.rpc.dispatcher rv = execute(f, *args, **kwargs)
2014-11-12 18:14:33.353 31086 TRACE oslo.messaging.rpc.dispatcher File "/usr/lib/python2.6/site-packages/eventlet/tpool.py", line 122, in execute
2014-11-12 18:14:33.353 31086 TRACE oslo.messaging.rpc.dispatcher six.reraise(c, e, tb)
2014-11-12 18:14:33.353 31086 TRACE oslo.messaging.rpc.dispatcher File "/usr/lib/python2.6/site-packages/eventlet/tpool.py", line 80, in tworker
2014-11-12 18:14:33.353 31086 TRACE oslo.messaging.rpc.dispatcher rv = meth(*args, **kwargs)
2014-11-12 18:14:33.353 31086 TRACE oslo.messaging.rpc.dispatcher File "/usr/lib64/python2.6/site-packages/libvirt.py", line 2878, in compareCPU
2014-11-12 18:14:33.353 31086 TRACE oslo.messaging.rpc.dispatcher if ret == -1: raise libvirtError ('virConnectCompareCPU() failed', conn=self)
2014-11-12 18:14:33.353 31086 TRACE oslo.messaging.rpc.dispatcher libvirtError: XML error: CPU feature `pdpe1gb' specified more than once


openstack nova调用libvirt,跟踪libvirt源码实例详解(cpu_mode及live_migrate 错误解决)_第1张图片


2014-11-12 18:14:33.300 31086 ERROR nova.virt.libvirt.driver [req-e68bce7c-4d44-4a73-abc4-541b0914f772 973eab9670774f589c476b1c4164272b 5e4d0a6d39a44b9c906a3173b448aa4a] 176------------source_cpu_info == {"vendor": "Intel", "model": "SandyBridge", "arch": "x86_64", "features": ["pdpe1gb", "osxsave", "dca", "pcid", "pdcm", "xtpr", "tm2", "est", "smx", "vmx", "ds_cpl", "monitor", "dtes64", "pbe", "tm", "ht", "ss", "acpi", "ds", "vme", "pdpe1gb", "osxsave", "dca", "pcid", "pdcm", "xtpr", "tm2", "est", "smx", "vmx", "ds_cpl", "monitor", "dtes64", "pbe", "tm", "ht", "ss", "acpi", "ds", "vme", "lahf_lm", "lm", "rdtscp", "nx", "syscall", "avx", "xsave", "aes", "tsc-deadline", "popcnt", "x2apic", "sse4.2", "sse4.1", "cx16", "ssse3", "pclmuldq", "pni", "sse2", "sse", "fxsr", "mmx", "clflush", "pse36", "pat", "cmov", "mca", "pge", "mtrr", "sep", "apic", "cx8", "mce", "pae", "msr", "tsc", "pse", "de", "fpu"], "topology": {"cores": 2, "threads": 1, "sockets": 1}} ---------------------------------------------
2014-11-12 18:14:33.307 31086 ERROR nova.virt.libvirt.driver [req-e68bce7c-4d44-4a73-abc4-541b0914f772 973eab9670774f589c476b1c4164272b 5e4d0a6d39a44b9c906a3173b448aa4a] CPU doesn't have compatibility.
XML error: CPU feature `pdpe1gb' specified more than once
明显可以看出pdpe1gb被加入到列表中两次。去重。

报secret_uuid错误则是所有ceph的secret_uuid必须一致,且nova.conf的rbd_secret_uuid = 8b45ead4-3cc9-4700-b85a-107050eeea8c也必须一致才能迁移。

58fb4811] An error occurred while trying to launch a defined domain with xml: <domain type='qemu'>
  <name>instance-0000005e</name>
  <uuid>e72e98dc-567d-4c5e-aefe-3d755ad7c40b</uuid>
  <memory unit='KiB'>4194304</memory>
  <currentMemory unit='KiB'>4194304</currentMemory>
  <vcpu placement='static'>2</vcpu>
  <sysinfo type='smbios'>
    <system>
      <entry name='manufacturer'>Red Hat Inc.</entry>
      <entry name='product'>OpenStack Nova</entry>
      <entry name='version'>2014.1.1-3.el6</entry>
      <entry name='serial'>44454c4c-5000-1052-804d-b3c04f443358</entry>
      <entry name='uuid'>e72e98dc-567d-4c5e-aefe-3d755ad7c40b</entry>
    </system>
  </sysinfo>
  <os>
    <type arch='x86_64' machine='pc-i440fx-1.6'>hvm</type>
    <boot dev='hd'/>
    <smbios mode='sysinfo'/>
  </os>
  <features>
    <acpi/>
    <apic/>
  </features>
  <clock offset='utc'/>
  <on_poweroff>destroy</on_poweroff>
  <on_reboot>restart</on_reboot>
  <on_crash>destroy</on_crash>
  <devices>
    <emulator>/usr/bin/qemu-system-x86_64</emulator>
    <disk type='network' device='disk'>
      <driver name='qemu' type='raw' cache='none'/>
      <auth username='admin'>
        <secret type='ceph' uuid='026a17e8-ea8c-4997-a013-2622a1d9f9c0'/>
      </auth>
      <source protocol='rbd' name='nova/e72e98dc-567d-4c5e-aefe-3d755ad7c40b_disk'>
        <host name='192.168.10.186' port='6789'/>
        <host name='192.168.10.187' port='6789'/>
        <host name='192.168.10.188' port='6789'/>
        <host name='192.168.10.189' port='6789'/>
      </source>
      <target dev='hda' bus='ide'/>
      <address type='drive' controller='0' bus='0' target='0' unit='0'/>
    </disk>
    <controller type='usb' index='0'>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
    </controller>
    <controller type='pci' index='0' model='pci-root'/>
    <controller type='ide' index='0'>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
    </controller>
    <interface type='bridge'>
      <mac address='fa:16:3e:65:9c:5e'/>
      <source bridge='qbrfd16f3fc-3c'/>
      <target dev='tapfd16f3fc-3c'/>
      <model type='virtio'/>
      <driver name='qemu'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
    </interface>
    <serial type='file'>
      <source path='/var/lib/nova/instances/e72e98dc-567d-4c5e-aefe-3d755ad7c40b/console.log'/>
      <target port='0'/>
    </serial>
    <serial type='pty'>
      <target port='1'/>
    </serial>
    <console type='file'>
      <source path='/var/lib/nova/instances/e72e98dc-567d-4c5e-aefe-3d755ad7c40b/console.log'/>
      <target type='serial' port='0'/>
    </console>
    <input type='tablet' bus='usb'/>
    <input type='mouse' bus='ps2'/>
    <graphics type='spice' autoport='yes' listen='0.0.0.0' keymap='en-us'>
      <listen type='address' address='0.0.0.0'/>
    </graphics>
    <video>
      <model type='qxl' ram='65536' vram='65536' heads='1'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
    </video>
    <memballoon model='virtio'>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
    </memballoon>
  </devices>
</domain>
2014-11-12 22:22:37.770 21166 ERROR nova.compute.manager [req-8c6906c1-9a58-4de7-a78b-1b1097fa551f 973eab9670774f589c476b1c4164272b 84e02e81eb934b7a957e63c058fb4811] [instance: e72e98dc-567d-4c5e-aefe-3d755ad7c40b] Failed to deallocate network for instance.
2014-11-12 22:22:37.925 21166 ERROR root [-] Original exception being dropped: ['Traceback (most recent call last):\n', ' File "/usr/lib/python2.6/site-packages/nova/compute/manager.py", line 1390, in _reschedule_or_error\n bdms, requested_networks)\n', ' File "/usr/lib/python2.6/site-packages/nova/compute/manager.py", line 2116, in _shutdown_instance\n self._try_deallocate_network(context, instance, requested_networks)\n', ' File "/usr/lib/python2.6/site-packages/nova/compute/manager.py", line 2080, in _try_deallocate_network\n self._set_instance_error_state(context, instance[\'uuid\'])\n', ' File "/usr/lib/python2.6/site-packages/nova/openstack/common/excutils.py", line 68, in __exit__\n six.reraise(self.type_, self.value, self.tb)\n', ' File "/usr/lib/python2.6/site-packages/nova/compute/manager.py", line 2075, in _try_deallocate_network\n self._deallocate_network(context, instance, requested_networks)\n', ' File "/usr/lib/python2.6/site-packages/nova/compute/manager.py", line 1769, in _deallocate_network\n context, instance, requested_networks=requested_networks)\n', ' File "/usr/lib/python2.6/site-packages/nova/network/neutronv2/api.py", line 410, in deallocate_for_instance\n data = neutron.list_ports(**search_opts)\n', ' File "/usr/lib/python2.6/site-packages/neutronclient/v2_0/client.py", line 111, in with_params\n ret = self.function(instance, *args, **kwargs)\n', ' File "/usr/lib/python2.6/site-packages/neutronclient/v2_0/client.py", line 306, in list_ports\n **_params)\n', ' File "/usr/lib/python2.6/site-packages/neutronclient/v2_0/client.py", line 1250, in list\n for r in self._pagination(collection, path, **params):\n', ' File "/usr/lib/python2.6/site-packages/neutronclient/v2_0/client.py", line 1263, in _pagination\n res = self.get(path, params=params)\n', ' File "/usr/lib/python2.6/site-packages/neutronclient/v2_0/client.py", line 1236, in get\n headers=headers, params=params)\n', ' File "/usr/lib/python2.6/site-packages/neutronclient/v2_0/client.py", line 1221, in retry_request\n headers=headers, params=params)\n', ' File "/usr/lib/python2.6/site-packages/neutronclient/v2_0/client.py", line 1156, in do_request\n resp, replybody = self.httpclient.do_request(action, method, body=body)\n', ' File "/usr/lib/python2.6/site-packages/neutronclient/client.py", line 195, in do_request\n self.authenticate()\n', ' File "/usr/lib/python2.6/site-packages/neutronclient/client.py", line 231, in authenticate\n token_url = self.auth_url + "/tokens"\n', "TypeError: unsupported operand type(s) for +: 'NoneType' and 'str'\n"]
2014-11-12 22:22:38.429 21166 ERROR oslo.messaging.rpc.dispatcher [-] Exception during message handling: 'ascii' codec can't decode byte 0xe8 in position 49: ordinal not in range(128)
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher Traceback (most recent call last):
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher File "/usr/lib/python2.6/site-packages/oslo/messaging/rpc/dispatcher.py", line 133, in _dispatch_and_reply
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher incoming.message))
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher File "/usr/lib/python2.6/site-packages/oslo/messaging/rpc/dispatcher.py", line 176, in _dispatch
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher return self._do_dispatch(endpoint, method, ctxt, args)
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher File "/usr/lib/python2.6/site-packages/oslo/messaging/rpc/dispatcher.py", line 122, in _do_dispatch
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher result = getattr(endpoint, method)(ctxt, **new_args)
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher File "/usr/lib/python2.6/site-packages/oslo/messaging/rpc/server.py", line 139, in inner
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher return func(*args, **kwargs)
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher File "/usr/lib/python2.6/site-packages/nova/exception.py", line 88, in wrapped
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher payload)
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher File "/usr/lib/python2.6/site-packages/nova/openstack/common/excutils.py", line 68, in __exit__
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher six.reraise(self.type_, self.value, self.tb)
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher File "/usr/lib/python2.6/site-packages/nova/exception.py", line 71, in wrapped
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher return f(self, context, *args, **kw)
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher File "/usr/lib/python2.6/site-packages/nova/compute/manager.py", line 274, in decorated_function
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher pass
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher File "/usr/lib/python2.6/site-packages/nova/openstack/common/excutils.py", line 68, in __exit__
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher six.reraise(self.type_, self.value, self.tb)
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher File "/usr/lib/python2.6/site-packages/nova/compute/manager.py", line 260, in decorated_function
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher return function(self, context, *args, **kwargs)
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher File "/usr/lib/python2.6/site-packages/nova/compute/manager.py", line 327, in decorated_function
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher function(self, context, *args, **kwargs)
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher File "/usr/lib/python2.6/site-packages/nova/compute/manager.py", line 303, in decorated_function
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher e, sys.exc_info())
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher File "/usr/lib/python2.6/site-packages/nova/openstack/common/excutils.py", line 68, in __exit__
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher six.reraise(self.type_, self.value, self.tb)
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher File "/usr/lib/python2.6/site-packages/nova/compute/manager.py", line 290, in decorated_function
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher return function(self, context, *args, **kwargs)
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher File "/usr/lib/python2.6/site-packages/nova/compute/manager.py", line 2069, in run_instance
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher do_run_instance()
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher File "/usr/lib/python2.6/site-packages/nova/openstack/common/lockutils.py", line 249, in inner
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher return f(*args, **kwargs)
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher File "/usr/lib/python2.6/site-packages/nova/compute/manager.py", line 2068, in do_run_instance
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher legacy_bdm_in_spec)
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher File "/usr/lib/python2.6/site-packages/nova/compute/manager.py", line 1201, in _run_instance
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher notify("error", fault=e) # notify that build failed
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher File "/usr/lib/python2.6/site-packages/nova/openstack/common/excutils.py", line 68, in __exit__
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher six.reraise(self.type_, self.value, self.tb)
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher File "/usr/lib/python2.6/site-packages/nova/compute/manager.py", line 1185, in _run_instance
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher instance, image_meta, legacy_bdm_in_spec)
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher File "/usr/lib/python2.6/site-packages/nova/compute/manager.py", line 1349, in _build_instance
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher filter_properties, bdms, legacy_bdm_in_spec)
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher File "/usr/lib/python2.6/site-packages/nova/compute/manager.py", line 1395, in _reschedule_or_error
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher self._log_original_error(exc_info, instance_uuid)
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher File "/usr/lib/python2.6/site-packages/nova/compute/manager.py", line 1364, in _log_original_error
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher LOG.error(_('Error: %s') % exc_info[1], instance_uuid=instance_uuid,
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher UnicodeDecodeError: 'ascii' codec can't decode byte 0xe8 in position 49: ordinal not in range(128)
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher
tils.py", line 68, in __exit__
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher six.reraise(self.type_, self.value, self.tb)
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher File "/usr/lib/python2.6/site-packages/nova/compute/manager.py", line 1185, in _run_instance
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher instance, image_meta, legacy_bdm_in_spec)
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher File "/usr/lib/python2.6/site-packages/nova/compute/manager.py", line 1349, in _build_instance
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher filter_properties, bdms, legacy_bdm_in_spec)
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher File "/usr/lib/python2.6/site-packages/nova/compute/manager.py", line 1395, in _reschedule_or_error
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher self._log_original_error(exc_info, instance_uuid)
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher File "/usr/lib/python2.6/site-packages/nova/compute/manager.py", line 1364, in _log_original_error
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher LOG.error(_('Error: %s') % exc_info[1], instance_uuid=instance_uuid,
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher UnicodeDecodeError: 'ascii' codec can't decode byte 0xe8 in position 49: ordinal not in range(128)
2014-11-12 22:22:38.429 21166 TRACE oslo.messaging.rpc.dispatcher
2014-11-12 22:22:38.432 21166 ERROR oslo.messaging._drivers.common [-] Returning exception 'ascii' codec can't decode byte 0xe8 in position 49: ordinal not in range(128) to caller
2014-11-12 22:22:38.432 21166 ERROR oslo.messaging._drivers.common [-] ['Traceback (most recent call last):\n', ' File "/usr/lib/python2.6/site-packages/oslo/messaging/rpc/dispatcher.py", line 133, in _dispatch_and_reply\n incoming.message))\n', ' File "/usr/lib/python2.6/site-packages/oslo/messaging/rpc/dispatcher.py", line 176, in _dispatch\n return self._do_dispatch(endpoint, method, ctxt, args)\n', ' File "/usr/lib/python2.6/site-packages/oslo/messaging/rpc/dispatcher.py", line 122, in _do_dispatch\n result = getattr(endpoint, method)(ctxt, **new_args)\n', ' File "/usr/lib/python2.6/site-packages/oslo/messaging/rpc/server.py", line 139, in inner\n return func(*args, **kwargs)\n', ' File "/usr/lib/python2.6/site-packages/nova/exception.py", line 88, in wrapped\n payload)\n', ' File "/usr/lib/python2.6/site-packages/nova/openstack/common/excutils.py", line 68, in __exit__\n six.reraise(self.type_, self.value, self.tb)\n', ' File "/usr/lib/python2.6/site-packages/nova/exception.py", line 71, in wrapped\n return f(self, context, *args, **kw)\n', ' File "/usr/lib/python2.6/site-packages/nova/compute/manager.py", line 274, in decorated_function\n pass\n', ' File "/usr/lib/python2.6/site-packages/nova/openstack/common/excutils.py", line 68, in __exit__\n six.reraise(self.type_, self.value, self.tb)\n', ' File "/usr/lib/python2.6/site-packages/nova/compute/manager.py", line 260, in decorated_function\n return function(self, context, *args, **kwargs)\n', ' File "/usr/lib/python2.6/site-packages/nova/compute/manager.py", line 327, in decorated_function\n function(self, context, *args, **kwargs)\n', ' File "/usr/lib/python2.6/site-packages/nova/compute/manager.py", line 303, in decorated_function\n e, sys.exc_info())\n', ' File "/usr/lib/python2.6/site-packages/nova/openstack/common/excutils.py", line 68, in __exit__\n six.reraise(self.type_, self.value, self.tb)\n', ' File "/usr/lib/python2.6/site-packages/nova/compute/manager.py", line 290, in decorated_function\n return function(self, context, *args, **kwargs)\n', ' File "/usr/lib/python2.6/site-packages/nova/compute/manager.py", line 2069, in run_instance\n do_run_instance()\n', ' File "/usr/lib/python2.6/site-packages/nova/openstack/common/lockutils.py", line 249, in inner\n return f(*args, **kwargs)\n', ' File "/usr/lib/python2.6/site-packages/nova/compute/manager.py", line 2068, in do_run_instance\n legacy_bdm_in_spec)\n', ' File "/usr/lib/python2.6/site-packages/nova/compute/manager.py", line 1201, in _run_instance\n notify("error", fault=e) # notify that build failed\n', ' File "/usr/lib/python2.6/site-packages/nova/openstack/common/excutils.py", line 68, in __exit__\n six.reraise(self.type_, self.value, self.tb)\n', ' File "/usr/lib/python2.6/site-packages/nova/compute/manager.py", line 1185, in _run_instance\n instance, image_meta, legacy_bdm_in_spec)\n', ' File "/usr/lib/python2.6/site-packages/nova/compute/manager.py", line 1349, in _build_instance\n filter_properties, bdms, legacy_bdm_in_spec)\n', ' File "/usr/lib/python2.6/site-packages/nova/compute/manager.py", line 1395, in _reschedule_or_error\n self._log_original_error(exc_info, instance_uuid)\n', ' File "/usr/lib/python2.6/site-packages/nova/compute/manager.py", line 1364, in _log_original_error\n LOG.error(_(\'Error: %s\') % exc_info[1], instance_uuid=instance_uuid,\n', "UnicodeDecodeError: 'ascii' codec can't decode byte 0xe8 in position 49: ordinal not in range(128)\n"]
上述错误就是nova。conf的uuid与virsh secret-list不一致,导致。

错误:
2014-11-18 19:39:20.559 11921 WARNING nova.compute.manager [-] Found 4 in the database and 3 on the hypervisor.
2014-11-18 19:39:46.968 11921 ERROR nova.virt.libvirt.driver [-] [instance: cb91421e-5dfa-4d2b-8d8a-c6b0f51b2bf6] Live Migration failure: unsupported configuration: Unable to find security driver for label selinux

解决办法:
vim /usr/local/libvirt/etc/libvirt/qemu.conf
将selinux修改为none


错误:

Refer to http://libvirt.org/html/libvirt-libvirt.html#virCPUCompareResult 
2014-11-25 13:06:00.744 12150 TRACE oslo.messaging.rpc.dispatcher Traceback (most recent call last): 
2014-11-25 13:06:00.744 12150 TRACE oslo.messaging.rpc.dispatcher File "/usr/lib/python2.6/site-packages/oslo/messaging/rpc/dispatcher.py", line 133, in _dispatch_and_reply 
2014-11-25 13:06:00.744 12150 TRACE oslo.messaging.rpc.dispatcher incoming.message)) 
2014-11-25 13:06:00.744 12150 TRACE oslo.messaging.rpc.dispatcher File "/usr/lib/python2.6/site-packages/oslo/messaging/rpc/dispatcher.py", line 176, in _dispatch 
2014-11-25 13:06:00.744 12150 TRACE oslo.messaging.rpc.dispatcher return self._do_dispatch(endpoint, method, ctxt, args) 
2014-11-25 13:06:00.744 12150 TRACE oslo.messaging.rpc.dispatcher File "/usr/lib/python2.6/site-packages/oslo/messaging/rpc/dispatcher.py", line 122, in _do_dispatch 
2014-11-25 13:06:00.744 12150 TRACE oslo.messaging.rpc.dispatcher result = getattr(endpoint, method)(ctxt, **new_args) 
2014-11-25 13:06:00.744 12150 TRACE oslo.messaging.rpc.dispatcher File "/usr/lib/python2.6/site-packages/nova/exception.py", line 88, in wrapped 
2014-11-25 13:06:00.744 12150 TRACE oslo.messaging.rpc.dispatcher payload) 
2014-11-25 13:06:00.744 12150 TRACE oslo.messaging.rpc.dispatcher File "/usr/lib/python2.6/site-packages/nova/openstack/common/excutils.py", line 68, in __exit__ 
2014-11-25 13:06:00.744 12150 TRACE oslo.messaging.rpc.dispatcher six.reraise(self.type_, self.value, self.tb) 
2014-11-25 13:06:00.744 12150 TRACE oslo.messaging.rpc.dispatcher File "/usr/lib/python2.6/site-packages/nova/exception.py", line 71, in wrapped 
2014-11-25 13:06:00.744 12150 TRACE oslo.messaging.rpc.dispatcher return f(self, context, *args, **kw) 
2014-11-25 13:06:00.744 12150 TRACE oslo.messaging.rpc.dispatcher File "/usr/lib/python2.6/site-packages/nova/compute/manager.py", line 303, in decorated_function 
2014-11-25 13:06:00.744 12150 TRACE oslo.messaging.rpc.dispatcher e, sys.exc_info()) 
2014-11-25 13:06:00.744 12150 TRACE oslo.messaging.rpc.dispatcher File "/usr/lib/python2.6/site-packages/nova/openstack/common/excutils.py", line 68, in __exit__ 
2014-11-25 13:06:00.744 12150 TRACE oslo.messaging.rpc.dispatcher six.reraise(self.type_, self.value, self.tb) 
2014-11-25 13:06:00.744 12150 TRACE oslo.messaging.rpc.dispatcher File "/usr/lib/python2.6/site-packages/nova/compute/manager.py", line 290, in decorated_function 
2014-11-25 13:06:00.744 12150 TRACE oslo.messaging.rpc.dispatcher return function(self, context, *args, **kwargs) 
2014-11-25 13:06:00.744 12150 TRACE oslo.messaging.rpc.dispatcher File "/usr/lib/python2.6/site-packages/nova/compute/manager.py", line 4406, in check_can_live_migrate_destination 
2014-11-25 13:06:00.744 12150 TRACE oslo.messaging.rpc.dispatcher block_migration, disk_over_commit) 
2014-11-25 13:06:00.744 12150 TRACE oslo.messaging.rpc.dispatcher File "/usr/lib/python2.6/site-packages/nova/virt/libvirt/driver.py", line 4201, in check_can_live_migrate_destination 
2014-11-25 13:06:00.744 12150 TRACE oslo.messaging.rpc.dispatcher self._compare_cpu(source_cpu_info) 
2014-11-25 13:06:00.744 12150 TRACE oslo.messaging.rpc.dispatcher File "/usr/lib/python2.6/site-packages/nova/virt/libvirt/driver.py", line 4381, in _compare_cpu 
2014-11-25 13:06:00.744 12150 TRACE oslo.messaging.rpc.dispatcher raise exception.InvalidCPUInfo(reason=m % {'ret': ret, 'u': u}) 
2014-11-25 13:06:00.744 12150 TRACE oslo.messaging.rpc.dispatcher InvalidCPUInfo: Unacceptable CPU info: CPU doesn't have compatibility. 
2014-11-25 13:06:00.744 12150 TRACE oslo.messaging.rpc.dispatcher 
2014-11-25 13:06:00.744 12150 TRACE oslo.messaging.rpc.dispatcher 0 
2014-11-25 13:06:00.744 12150 TRACE oslo.messaging.rpc.dispatcher 
2014-11-25 13:06:00.744 12150 TRACE oslo.messaging.rpc.dispatcher Refer to http://libvirt.org/html/libvirt-libvirt.html#virCPUCompareResult 
2014-11-25 13:06:00.744 12150 TRACE oslo.messaging.rpc.dispatcher 
2014-11-25 13:06:00.746 12150 ERROR oslo.messaging._drivers.common [-] Returning exception Unacceptable CPU info: CPU doesn't have compatibility.

解决办法:
openstack nova调用libvirt,跟踪libvirt源码实例详解(cpu_mode及live_migrate 错误解决)_第2张图片

打印出cpu.toxml()
2014-11-25 14:16:48.572 19451 ERROR nova.virt.libvirt.driver [req-4f072e10-a19a-4f39-ad37-275b81d13482 973eab9670774f589c476b1c4164272b 5e4d0a6d39a44b9c906a3173b448aa4a] 1--------------cpu==<cpu>
  <arch>x86_64</arch>
  <model>Westmere</model>
  <vendor>Intel</vendor>
  <topology sockets="1" cores="48" threads="1"/>
  <feature name="rdtscp"/>
  <feature name="pdpe1gb"/>
  <feature name="x2apic"/>
  <feature name="dca"/>
  <feature name="pcid"/>
  <feature name="pdcm"/>
  <feature name="xtpr"/>
  <feature name="tm2"/>
  <feature name="est"/>
  <feature name="smx"/>
  <feature name="vmx"/>
  <feature name="ds_cpl"/>
  <feature name="monitor"/>
  <feature name="dtes64"/>
  <feature name="pclmuldq"/>
  <feature name="pbe"/>
  <feature name="tm"/>
  <feature name="ht"/>
  <feature name="ss"/>
  <feature name="acpi"/>
  <feature name="ds"/>
  <feature name="vme"/>
</cpu>

2014-11-25 13:06:00.523 12150 ERROR nova.virt.libvirt.driver [req-b97847d1-22a0-4b77-8531-622a5b033818 973eab9670774f589c476b1c4164272b 5e4d0a6d39a44b9c906a3173b448aa4a] 1--------------cpu=={'ns_prefix': None, 'vendor': u'Intel', 'features': [<nova.virt.libvirt.config.LibvirtConfigCPUFeature object at 0x39b7810>, <nova.virt.libvirt.config.LibvirtConfigCPUFeature object at 0x39b77d0>, <nova.virt.libvirt.config.LibvirtConfigCPUFeature object at 0x39b7710>, <nova.virt.libvirt.config.LibvirtConfigCPUFeature object at 0x39b7890>, <nova.virt.libvirt.config.LibvirtConfigCPUFeature object at 0x39b7950>, <nova.virt.libvirt.config.LibvirtConfigCPUFeature object at 0x39b78d0>, <nova.virt.libvirt.config.LibvirtConfigCPUFeature object at 0x39b7a10>, <nova.virt.libvirt.config.LibvirtConfigCPUFeature object at 0x39b7910>, <nova.virt.libvirt.config.LibvirtConfigCPUFeature object at 0x39b7650>, <nova.virt.libvirt.config.LibvirtConfigCPUFeature object at 0x39b7850>, <nova.virt.libvirt.config.LibvirtConfigCPUFeature object at 0x39b7750>, <nova.virt.libvirt.config.LibvirtConfigCPUFeature object at 0x39b79d0>, <nova.virt.libvirt.config.LibvirtConfigCPUFeature object at 0x39b7790>, <nova.virt.libvirt.config.LibvirtConfigCPUFeature object at 0x39b75d0>, <nova.virt.libvirt.config.LibvirtConfigCPUFeature object at 0x39b7990>, <nova.virt.libvirt.config.LibvirtConfigCPUFeature object at 0x39d0750>, <nova.virt.libvirt.config.LibvirtConfigCPUFeature object at 0x39d0450>, <nova.virt.libvirt.config.LibvirtConfigCPUFeature object at 0x39d0790>, <nova.virt.libvirt.config.LibvirtConfigCPUFeature object at 0x39d0910>, <nova.virt.libvirt.config.LibvirtConfigCPUFeature object at 0x39d08d0>, <nova.virt.libvirt.config.LibvirtConfigCPUFeature object at 0x39d0950>, <nova.virt.libvirt.config.LibvirtConfigCPUFeature object at 0x39d0990>], 'threads': 1, 'root_name': 'cpu', 'ns_uri': None, 'cores': 48, 'model': u'Westmere', 'arch': u'x86_64', 'sockets': 1}
2014-11-25 13:06:00.527 12150 ERROR nova.virt.libvirt.driver [req-b97847d1-22a0-4b77-8531-622a5b033818 973eab9670774f589c476b1c4164272b 5e4d0a6d39a44b9c906a3173b448aa4a] ttx-----------------------------
2014-11-25 13:06:00.527 12150 ERROR nova.virt.libvirt.driver [req-b97847d1-22a0-4b77-8531-622a5b033818 973eab9670774f589c476b1c4164272b 5e4d0a6d39a44b9c906a3173b448aa4a] CPU doesn't have compatibility.

PowerKVM 上 libvirt API 的 CPU 选项

如果 PowerKVM 访客的 CPU 功能与主机系统不同,那么您可以更改 libvirt API 的 CPU 设置。

在大多数情况下,不需要指定 CPU 方式。libvirt API 将自动选择相应的设置。例外的情况是,您要从 Power® 处理器的先前版本迁移至运行 PowerKVM 的 POWER8™ 系统。

libvirt API 上 CPU 方式设置的选项如下所示:
custom
在此方式下,CPU 元素描述应为访客提供的 CPU。在此方式下,持久访客将看到相同硬件,无论在哪一个主机上引导访客都是如此。在运行 PowerKVM 的系统上,此方式仅支持 power6  power7 兼容性。在以下 libvirt XML 示例中,以兼容性方式显式启动访客:
 <cpu mode='custom'> <model>power7</model> <vendor>IBM</vendor> </cpu
 <cpu mode='custom'> <model>power6</model> <vendor>IBM</vendor> </cpu
host-model
此方式提供用于复制主机 CPU 定义的快捷方式。如果您指定此方式,那么只会对主机 CPU 模型提供访客,即使访客不支持主机 CPU 模型也是如此。
host-passthrough
通过此方式,对访客可视的 CPU 必须与主机 CPU 完全相同。如果您指定此方式,那么只会对主机 CPU 模型提供访客,即使访客不支持主机 CPU 模型也是如此。

host-passthrough 和 host-model 选项与在 PowerKVM 系统上的行为相同。


none
custom 自己定义
host-model 根据物理CPU的特性,选择一个最靠近的标准CPU型号,xml配置文件为: 
<cpu mode='host-model'>
<model fallback='forbid'/>
<topology sockets='1' cores='2' threads='1'/>
</cpu>

host-passthrough 直接将物理CPU 暴露给虚拟机使用,在虚拟机上完全可以看到的就是物理CPU的型号;xml配置文件为:
<cpu mode='host-passthrough'/>

openstack nova调用libvirt,跟踪libvirt源码实例详解(cpu_mode及live_migrate 错误解决)_第3张图片


hi Yaguang:
I have the same problem and have do some reserch.
I use inter cpu as example:
this is inter cpu model:
Conroe<Penryn<Nehalem<Westmere<SandyBridge<Haswell

in openstack, if you migrating vm from Haswell to SandyBridge, it is OK. but if you migrating vm from SandyBridge
to Haswell, it failed. because different cpu have different core cmd. Haswell core cmd include SandyBridge core cmd.
so it can migrate.

if we want to migrate between different cpu mode, we can use the same cpu mode. libvirt support the cpu model lable.
like this:
<cpu>
         <model>SandyBridge</model>
<cpu>

if you want migrate from SandyBridge to Haswell, you can set the lable, model is SandyBridge. because Haswell is also compatible with SandyBridge.

but openstack don't support set the mode cpu, so we can modify the code.

if we disable the check, it will get some unknown error. because the vm run the different core cmd.

thanks




第二部分:
以下开始介绍如何从nova的libvirt驱动调用libvirt:
1、/nova/virt/libvirt/driver.py
打印出nova调用libvirt的参数值:
openstack nova调用libvirt,跟踪libvirt源码实例详解(cpu_mode及live_migrate 错误解决)_第4张图片



上述打印结果,可知,self._conn==libvirt.virConnect


2、在当前python环境中,找到libvirt模块路径:
openstack nova调用libvirt,跟踪libvirt源码实例详解(cpu_mode及live_migrate 错误解决)_第5张图片

3、vim /usr/lib64/python2.6/site-packages/libvirt.py


openstack nova调用libvirt,跟踪libvirt源码实例详解(cpu_mode及live_migrate 错误解决)_第6张图片


openstack nova调用libvirt,跟踪libvirt源码实例详解(cpu_mode及live_migrate 错误解决)_第7张图片

上图可知, libvirt.py链接到libvirtmod.so文件

ldd  /usr/lib64/python2.6/site-packages/libvirtmod.so 

openstack nova调用libvirt,跟踪libvirt源码实例详解(cpu_mode及live_migrate 错误解决)_第8张图片

上述libvirtmod.so文件由libvirt源码编译出来的共享文件,因此后续需要跟踪到libvirt源码中去。


4、libvirt1.1.2源码: http://pan.baidu.com/s/1qW19XQO
本示例中libvirt源码包为libvirt-1.1.2.tar.gz,解压后:
openstack nova调用libvirt,跟踪libvirt源码实例详解(cpu_mode及live_migrate 错误解决)_第9张图片


5、找出源码包中的virConnectCompareCPU函数:
grep -rn "virConnectCompareCPU" ./src/

源码中搜索出来virConnectCompareCPU比较多,每一个跟进去看,其实virConnectCompareCPU的定义只有一个在./src/libvirt.c中。

6、vim ./src/libvirt.c
 * @conn: virConnect connection
 * @xmlDesc: XML describing the CPU to compare with host CPU
 * @flags: extra flags; not used yet, so callers should always pass 0
 * #将传入的cpu描述与本机host cpu参数比较
 * Compares the given CPU description with the host CPU
 *
 * Returns comparison result according to enum virCPUCompareResult
 */
int
virConnectCompareCPU(virConnectPtr conn,
                     const char *xmlDesc,
                     unsigned int flags)
{
    VIR_DEBUG("conn=%p, xmlDesc=%s, flags=%x", conn, xmlDesc, flags);
    virResetLastError();
    if (!VIR_IS_CONNECT(conn)) {
        virLibConnError(VIR_ERR_INVALID_CONN, __FUNCTION__);
        virDispatchError(NULL);
        return VIR_CPU_COMPARE_ERROR;
    }
    virCheckNonNullArgGoto(xmlDesc, error);
    if (conn->driver->connectCompareCPU) {
        int ret;
       #跟进到步骤7
        ret = conn->driver->connectCompareCPU(conn, xmlDesc, flags);
        if (ret == VIR_CPU_COMPARE_ERROR)
            goto error;
        return ret;
    }
    virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
error:
    virDispatchError(conn);
    return VIR_CPU_COMPARE_ERROR;
}

7、
grep -rn "connectCompareCPU" ./src/
从上图查询结果可以看出,6中的conn->driver->connectCompareCPU,为./src/qemu/qemu_driver.c:15985:    .connectCompareCPU = qemuConnectCompareCPU, /* 0.7.5 */,

8、 vim ./src/qemu/qemu_driver.c
openstack nova调用libvirt,跟踪libvirt源码实例详解(cpu_mode及live_migrate 错误解决)_第10张图片

9、跟进到qemuConnectCompareCPU函数(在 ./src/qemu/qemu_driver.c中):

static int
qemuConnectCompareCPU(virConnectPtr conn,
                      const char *xmlDesc,
                      unsigned int flags)
{
    virQEMUDriverPtr driver = conn->privateData;
    int ret = VIR_CPU_COMPARE_ERROR;
    virCapsPtr caps = NULL;
    virCheckFlags(0, VIR_CPU_COMPARE_ERROR);
    if (virConnectCompareCPUEnsureACL(conn) < 0)
        goto cleanup;
    #获取caps
    if (!(caps =  virQEMUDriverGetCapabilities (driver, false)))  #跟进到9-1
        goto cleanup;
    if (!caps->host.cpu ||  #判断host.cpu、model为空则警告,返回不兼容
        !caps->host.cpu->model) {
        VIR_WARN("cannot get host CPU capabilities");
        ret = VIR_CPU_COMPARE_INCOMPATIBLE;
    } else {
        ret = cpuCompareXML(caps->host.cpu, xmlDesc); #跟进到10
    }
cleanup:
    virObjectUnref(caps);
    return ret;
}

此处顺便介绍下linux下源码阅读工具vim+ctags
yum install  vim ctags
安装完毕,执行命令生成ctags索引:
ctags -R  源码目录 

vim ./src/qemu/qemu_driver.c
openstack nova调用libvirt,跟踪libvirt源码实例详解(cpu_mode及live_migrate 错误解决)_第11张图片

光标在virQEMUDriverGetCapabilities函数上,快捷键“ctrl+]”跳转到函数定义:
openstack nova调用libvirt,跟踪libvirt源码实例详解(cpu_mode及live_migrate 错误解决)_第12张图片

再次"ctrl+o“跳转回来。

更多ctags使用,请网上自行查找。



9-1、virQEMUDriverGetCapabilities源码:
/**
 * virQEMUDriverGetCapabilities:
 *
 * Get a reference to the virCapsPtr instance for the
 * driver. If @refresh is true, the capabilities will be
 * rebuilt first
 *      
 * The caller must release the reference with virObjetUnref
 *  
 * Returns: a reference to a virCapsPtr instance or NULL
 */
virCapsPtr virQEMUDriverGetCapabilities(virQEMUDriverPtr driver,
                                        bool refresh)
{
    virCapsPtr ret = NULL;
    if (refresh) {                      
        virCapsPtr caps = NULL;
        if ((caps = virQEMUDriverCreateCapabilities(driver)) == NULL)
            return NULL;
        qemuDriverLock(driver);
        virObjectUnref(driver->caps);
        driver->caps = caps;
    } else {          
        qemuDriverLock(driver);
    }
    ret = virObjectRef(driver->caps);
    qemuDriverUnlock(driver);
    return ret;
}

10:./src/qemu/qemu_driver.c
virCPUCompareResult
cpuCompareXML(virCPUDefPtr host,
              const char *xml)
{
    xmlDocPtr doc = NULL;
    xmlXPathContextPtr ctxt = NULL;
    virCPUDefPtr cpu = NULL;
    virCPUCompareResult ret = VIR_CPU_COMPARE_ERROR;
    VIR_DEBUG("host=%p, xml=%s", host, NULLSTR(xml));
    if (!(doc = virXMLParseStringCtxt(xml, _("(CPU_definition)"), &ctxt)))
        goto cleanup;
    cpu = virCPUDefParseXML(ctxt->node, ctxt, VIR_CPU_TYPE_AUTO);
    if (cpu == NULL)
        goto cleanup;
    if (!cpu->model) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("no CPU model specified"));
        goto cleanup;
    }
    ret = cpuCompare(host, cpu);  #跟进到11
cleanup:
    virCPUDefFree(cpu);
    xmlXPathFreeContext(ctxt);
    xmlFreeDoc(doc);
    return ret;
}

11:./src/qemu/qemu_driver.c
virCPUCompareResult 
cpuCompare(virCPUDefPtr host,
           virCPUDefPtr cpu)
{
    struct cpuArchDriver *driver;
    VIR_DEBUG("host=%p, cpu=%p", host, cpu);
    if ((driver = cpuGetSubDriver(host->arch)) == NULL)  #如果host arch为空报错
        return VIR_CPU_COMPARE_ERROR;
    if (driver->compare == NULL) {
        virReportError(VIR_ERR_NO_SUPPORT,
                       _("cannot compare CPUs of %s architecture"),
                       virArchToString(host->arch));
        return VIR_CPU_COMPARE_ERROR;
    }
    return driver->compare(host, cpu);  #跟进到12???:
}

12:
grep -rn "cpuArchDriver" ./src/
没弄明白那个多个 cpuArchDriver定义,为啥要选择cpu.c 40行里面那个????。

13、
vim ./src/cpu/cpu.c
#define NR_DRIVERS ARRAY_CARDINALITY(drivers)
#define VIR_FROM_THIS VIR_FROM_CPU
static struct cpuArchDriver *drivers[] = {
    &cpuDriverX86,  //跟进到14
    &cpuDriverPowerPC,
    &cpuDriverS390,
    &cpuDriverArm,
    /* generic driver must always be the last one */
    &cpuDriverGeneric
};

14、
openstack nova调用libvirt,跟踪libvirt源码实例详解(cpu_mode及live_migrate 错误解决)_第13张图片

openstack nova调用libvirt,跟踪libvirt源码实例详解(cpu_mode及live_migrate 错误解决)_第14张图片

找到上图的x86Compute定义:

15:为了解释代码,此处先贴出cpu特性(virsh capabilities):
  <cpu>
      <arch>x86_64</arch>
      <model>Westmere</model>
      <vendor>Intel</vendor>
      <topology sockets='1' cores='1' threads='1'/>
      <feature name='erms'/>
      <feature name='smep'/>
      <feature name='fsgsbase'/>
      <feature name='rdtscp'/>
      <feature name='pdpe1gb'/>
      <feature name='hypervisor'/>
      <feature name='rdrand'/>
      <feature name='f16c'/>
      <feature name='avx'/>
      <feature name='osxsave'/>
      <feature name='xsave'/>
      <feature name='movbe'/>
      <feature name='x2apic'/>
      <feature name='pcid'/>
      <feature name='fma'/>
      <feature name='pclmuldq'/>
      <feature name='ss'/>
      <feature name='ds'/>
      <feature name='vme'/>
    </cpu>

解释 x86Compute代码:
static virCPUCompareResult
x86Compute(virCPUDefPtr host,
           virCPUDefPtr cpu,
           virCPUDataPtr *guest,
           char **message)
{
    struct x86_map *map = NULL;
    struct x86_model *host_model = NULL;
    struct x86_model *cpu_force = NULL;
    struct x86_model *cpu_require = NULL;
    struct x86_model *cpu_optional = NULL;
    struct x86_model *cpu_disable = NULL;
    struct x86_model *cpu_forbid = NULL;
    struct x86_model *diff = NULL;
    struct x86_model *guest_model = NULL;
    virCPUCompareResult ret;
    enum compare_result result;
    virArch arch;
    size_t i;
    if (cpu->arch != VIR_ARCH_NONE) {
        bool found = false;
        for (i = 0; i < ARRAY_CARDINALITY(archs); i++) {
            if (archs[i] == cpu->arch) {  #此处判断如果arch相同则found 设置为true
                found = true;
                break;
            }
        }
        if (!found) {  #如果arch不匹配,返回不兼容
            VIR_DEBUG("CPU arch %s does not match host arch",
                      virArchToString(cpu->arch));
            if (message &&
                virAsprintf(message,
                            _("CPU arch %s does not match host arch"),
                            virArchToString(cpu->arch)) < 0)
                goto error;
            return VIR_CPU_COMPARE_INCOMPATIBLE;
        }
        arch = cpu->arch;
    } else {
        arch = host->arch;
    }
     #如果本机host vendor 为空,或者传入vendor 与本机vendor 不等,返回不兼容
    if (cpu->vendor && 
        (!host->vendor || STRNEQ(cpu->vendor, host->vendor))) {
        VIR_DEBUG("host CPU vendor does not match required CPU vendor %s",
                  cpu->vendor);
        if (message &&
            virAsprintf(message,
                        _("host CPU vendor does not match required "
                          "CPU vendor %s"),
                        cpu->vendor) < 0)
            goto error;
        return VIR_CPU_COMPARE_INCOMPATIBLE;
    }
    //后续流程比较繁杂,则不一一分析,有兴趣者,请自行分析
    if (!(map = x86LoadMap()) ||
        !(host_model = x86ModelFromCPU(host, map, VIR_CPU_FEATURE_REQUIRE)) ||
        !(cpu_force = x86ModelFromCPU(cpu, map, VIR_CPU_FEATURE_FORCE)) ||
        !(cpu_require = x86ModelFromCPU(cpu, map, VIR_CPU_FEATURE_REQUIRE)) ||
        !(cpu_optional = x86ModelFromCPU(cpu, map, VIR_CPU_FEATURE_OPTIONAL)) ||
        !(cpu_disable = x86ModelFromCPU(cpu, map, VIR_CPU_FEATURE_DISABLE)) ||
        !(cpu_forbid = x86ModelFromCPU(cpu, map, VIR_CPU_FEATURE_FORBID)))
        goto error;
    x86DataIntersect(cpu_forbid->data, host_model->data);
    if (!x86DataIsEmpty(cpu_forbid->data)) {
        virX86CpuIncompatible(N_("Host CPU provides forbidden features"),
                              cpu_forbid->data);
        goto out;
    }
    /* first remove features that were inherited from the CPU model and were
     * explicitly forced, disabled, or made optional
     */
    x86DataSubtract(cpu_require->data, cpu_force->data);
    x86DataSubtract(cpu_require->data, cpu_optional->data);
    x86DataSubtract(cpu_require->data, cpu_disable->data);
    result = x86ModelCompare(host_model, cpu_require);
    if (result == SUBSET || result == UNRELATED) {
        x86DataSubtract(cpu_require->data, host_model->data);
        virX86CpuIncompatible(N_("Host CPU does not provide required "
                                 "features"),
                              cpu_require->data);
        goto out;
    }
    ret = VIR_CPU_COMPARE_IDENTICAL;
    if ((diff = x86ModelCopy(host_model)) == NULL)
        goto error;
    x86DataSubtract(diff->data, cpu_optional->data);
    x86DataSubtract(diff->data, cpu_require->data);
    x86DataSubtract(diff->data, cpu_disable->data);
    x86DataSubtract(diff->data, cpu_force->data);
    if (!x86DataIsEmpty(diff->data))
        ret = VIR_CPU_COMPARE_SUPERSET;
    if (ret == VIR_CPU_COMPARE_SUPERSET
        && cpu->type == VIR_CPU_TYPE_GUEST
        && cpu->match == VIR_CPU_MATCH_STRICT) {
        virX86CpuIncompatible(N_("Host CPU does not strictly match guest CPU: "
                                 "Extra features"),
                              diff->data);
        goto out;
    }
    if (guest != NULL) {
        struct cpuX86Data *guestData;
        if ((guest_model = x86ModelCopy(host_model)) == NULL)
            goto error;
        if (cpu->type == VIR_CPU_TYPE_GUEST
            && cpu->match == VIR_CPU_MATCH_EXACT)
            x86DataSubtract(guest_model->data, diff->data);
        if (x86DataAdd(guest_model->data, cpu_force->data))
            goto error;
        x86DataSubtract(guest_model->data, cpu_disable->data);
        if (!(guestData = x86DataCopy(guest_model->data)) ||
            !(*guest = x86MakeCPUData(arch, &guestData))) {
            x86DataFree(guestData);
            goto error;
        }
    }
out:
    x86MapFree(map);
    x86ModelFree(host_model);
    x86ModelFree(diff);
    x86ModelFree(cpu_force);
    x86ModelFree(cpu_require);
    x86ModelFree(cpu_optional);
    x86ModelFree(cpu_disable);
    x86ModelFree(cpu_forbid);
    x86ModelFree(guest_model);
    return ret;
error:
    ret = VIR_CPU_COMPARE_ERROR;
    goto out;
}
上述即nova调用的两台主机迁移前判断兼容与否qemu最底层函数。由于时间关系,分析暂且到此。

总结:如果nova中没有使用与硬件相关的cpu特性,正常来说,直接迁移即可,不需要做兼容性判断。
兼容性判断场景是用来检测使用了cpu特性的迁移。

你可能感兴趣的:(openstack nova调用libvirt,跟踪libvirt源码实例详解(cpu_mode及live_migrate 错误解决))