[libvirt] [libvirt-test-API][PATCH] Add network_dhcp_leases test case
by jiahu
The network_dhcp_leases.py uses DHCPLeases() to validate new API
virNetworkGetDHCPLeases of libvirt.
---
repos/network/network_dhcp_leases.py | 277 +++++++++++++++++++++++++++++++++++
1 file changed, 277 insertions(+)
create mode 100644 repos/network/network_dhcp_leases.py
diff --git a/repos/network/network_dhcp_leases.py b/repos/network/network_dhcp_leases.py
new file mode 100644
index 0000000..29ee529
--- /dev/null
+++ b/repos/network/network_dhcp_leases.py
@@ -0,0 +1,277 @@
+#!/usr/bin/env python
+#test DHCPLeases() API for libvirt
+
+import os
+import time
+import libvirt
+from libvirt import libvirtError
+from utils import utils
+from src import sharedmod
+
+required_params = ('networkname',)
+optional_params = {'macaddr': ''}
+
+LEASE_FILE = "/var/lib/libvirt/dnsmasq/"
+
+def check_ip(ipaddr, logger):
+ """
+ return a string according to ip address type, return 'ipv4' for ipv4,
+ return 'ipv6' for ipv6, return False for others
+ """
+ addr4 = ipaddr.strip().split('.')
+ addr6 = ipaddr.strip().split(':')
+ if len(addr4) == 4:
+ iptype = "ipv4"
+ elif len(addr6) == 6:
+ iptype = "ipv6"
+ else:
+ return False
+ return iptype
+
+def get_network_type(ipaddr,logger):
+ """
+ return 0 or 1 for ipv4/ipv6, this function will be used in
+ check_ipv4_values()/check_ipv6_values()
+ """
+ if check_ip(ipaddr, logger) == "ipv4":
+ return 0
+ elif check_ip(ipaddr, logger) == "ipv6":
+ return 1
+
+def get_bridge_name(network,logger):
+ """
+ get bridge name under specified network from specified network conf
+ """
+ CONF_NETWORK = LEASE_FILE + network + ".conf"
+ GREP_BRIDGE = "grep \"^interface=\" %s | awk -F\"=\" '{print $2}'"
+ status, output = utils.exec_cmd(GREP_BRIDGE % CONF_NETWORK, shell=True)
+ if not status:
+ pass
+ else:
+ logger.error("\"" + GREP_BRIDGE + "\"" + "error")
+ logger.error(output)
+ return False
+ return output[0]
+
+def get_ip_prefix(network, iptype, logger):
+ """
+ get ip prefix according to IP type
+ """
+ br = get_bridge_name(network, logger)
+ PREFIX = "ip -4 -o ad show %s | awk '{print $4}'|awk -F\"/\" '{print $2}'"
+ PREFIX_6 = "ip -6 -o ad show %s|awk '{print $4}'|awk -F\"/\" '{print $2}'"
+ if iptype == "ipv4":
+ status, output = utils.exec_cmd(PREFIX % br, shell=True)
+ elif iptype == "ipv6":
+ status, output = utils.exec_cmd(PREFIX_6 % br, shell=True)
+ if not status:
+ pass
+ else:
+ logger.error("\"" + GREP_BRIDGE + "\"" + "error")
+ logger.error(output)
+ return False
+ return output[0]
+
+def get_info_from_dnsmasq(network,macaddr,logger):
+ """
+ generate dict for lease info from virtual network's lease file
+ """
+ title = ['expirytime','mac','ipaddr','hostname','clientid']
+ output_list = []
+ lease_dnsmasq = []
+ temp = []
+ remove_list = []
+ GREP_MAC = "grep -w %s" + " " + LEASE_FILE_DNSMASQ
+ CAT_FILE = "cat" + " " + LEASE_FILE_DNSMASQ
+
+ status, output = utils.exec_cmd(CAT_FILE, shell=True)
+ if not status:
+ for i in range(0, len(output)):
+ output_list = []
+ output_str = output[i]
+ for item in output_str.split(" "):
+ output_list.append(item)
+ lease_dnsmasq.append(dict(zip(title,output_list)))
+
+ #due to no mac field in IPv6 line, so do nothing here temporarily.
+ if macaddr != None:
+ pass
+
+ #remove bridge duid line
+ for i in range(0, len(lease_dnsmasq)):
+ if lease_dnsmasq[i]['expirytime'] == 'duid':
+ remove_list.append(lease_dnsmasq[i])
+
+ for i in range(0, len(remove_list)):
+ lease_dnsmasq.remove(remove_list[i])
+
+ #remove expiry leases
+ for i in range(0, len(lease_dnsmasq)):
+ temp = int(lease_dnsmasq[i]['expirytime'])
+ lease_dnsmasq[i]['expirytime'] = temp
+
+ remove_list = []
+ for i in range(0, len(lease_dnsmasq)):
+ if time.time() >= int(lease_dnsmasq[i]['expirytime']):
+ remove_list.append(lease_dnsmasq[i])
+
+ for i in range(0, len(remove_list)):
+ lease_dnsmasq.remove(remove_list[i])
+
+ #replace * to None
+ for i in range(0, len(lease_dnsmasq)):
+ if lease_dnsmasq[i]['hostname'] == "*":
+ lease_dnsmasq[i]['hostname'] = None
+ if lease_dnsmasq[i]['clientid'] == "*":
+ lease_dnsmasq[i]['clientid'] = None
+
+ return lease_dnsmasq
+ else:
+ logger.error("\"" + CAT_FILE + "\"" + "error")
+ logger.error(output)
+ return False
+
+def compare_values(op1, op2, network, iptype, logger):
+ """
+ check all printed values from API
+ """
+ dnsmasq = op1
+ api = op2
+ temp = int(api['expirytime'])
+ api['expirytime'] = temp
+
+ for j in range(0,len(dnsmasq)):
+ if dnsmasq[j]['hostname'] == api['hostname'] and \
+ dnsmasq[j]['expirytime'] == api['expirytime']:
+ if dnsmasq[j]['ipaddr'] == api['ipaddr'] and \
+ dnsmasq[j]['clientid'] == api['clientid']:
+
+ if iptype == "ipv4":
+ logger.debug("PASS: hostname: %s expirytime: %s ipaddr: %s" \
+ % (api['hostname'],api['expirytime'],api['ipaddr']))
+ logger.debug("Unsupported: clientid: %s in IPv4" \
+ % (api['clientid']))
+ elif iptype == "ipv6":
+ logger.debug("PASS: hostname: %s expirytime: %s ipaddr: %s \
+clientid: %s" % (api['hostname'],api['expirytime'],api['ipaddr'],\
+api['clientid']))
+
+ if iptype == "ipv4" and api['mac'] == dnsmasq[j]['mac']:
+ logger.debug("PASS: mac: %s" % api['mac'])
+ elif iptype == "ipv6" and api['iaid'] == dnsmasq[j]['mac']:
+ logger.debug("PASS: iaid: %s" % api['iaid'])
+ else:
+ logger.error("Fail: mac/iaid: %s/%s" % (api['mac'], \
+ api['iaid']))
+ return False
+
+ break
+ else:
+ if j == len(dnsmasq) - 1:
+ logger.debug("Last loop %d, FAIL: %s" % (j,api))
+ logger.debug("failed on ipaddr or clientid")
+ return False
+ else:
+ logger.debug("Skipped loop %d,Warning: ipaddr: %s \
+clientid: %s" % (j,api['ipaddr'],api['clientid']))
+ continue
+ else:
+ if j == len(dnsmasq) - 1:
+ logger.error("Fail: hostname: %s expirytime: %s ipaddr: %s \
+clientid: %s" % (api['hostname'],api['expirytime'],api['ipaddr'], \
+api['clientid']))
+ logger.error("Last loop %d, FAIL: %s" % (j,api))
+ return False
+ else:
+ logger.debug("Skipped loop %d,Warning: hostname: \
+%s expirytime: %s" % (j,api['hostname'],api['expirytime']))
+ continue
+ if not api['iface'] == get_bridge_name(network,logger):
+ logger.error("FAIL: iface: %s" % api['iface'])
+ return False
+ else:
+ logger.debug("PASS: iface: %s" % api['iface'])
+ if not api['type'] == get_network_type(api['ipaddr'],logger):
+ logger.error("FAIL: type: %s" % api['type'])
+ return False
+ else:
+ logger.debug("PASS: type: %s" % api['type'])
+
+ if not api['prefix'] == int(get_ip_prefix(network, iptype ,logger)):
+ logger.error("FAIL: prefix: %s" % api['prefix'])
+ logger.error("FAIL: %s" % api)
+ return False
+ else:
+ logger.debug("PASS: prefix: %s" % api['prefix'])
+ if iptype == "ipv4":
+ if not api['iaid'] == None:
+ logger.error("FAIL: iaid: %s" % api['iaid'])
+ return False
+ else:
+ logger.debug("Unsupported: iaid: %s in IPv4" % api['iaid'])
+ logger.debug("PASS: %s" % api)
+ elif iptype == "ipv6":
+ logger.debug("Ignoring mac checking on IPv6 line %s" % api['mac'])
+ logger.debug("PASS: %s" % api)
+
+ return True
+
+def check_values(op1, op2, network, logger):
+ """
+ check each line accorting to ip type, if ipv4 go to check_ipv4_values
+ if ipv6, go to check_ipv6_values.
+ """
+ networkname = network
+ dnsmasq = op1
+ api = op2
+
+ for i in range(0, len(api)):
+ if check_ip(api[i]['ipaddr'],logger) == "ipv4":
+ if not compare_values(dnsmasq,api[i],networkname,"ipv4",logger):
+ return False
+ elif check_ip(api[i]['ipaddr'],logger) == "ipv6":
+ if not compare_values(dnsmasq,api[i],networkname,"ipv6",logger):
+ return False
+ else:
+ logger.error("invalid list element for ipv4 and ipv6")
+ return False
+ return True
+
+def network_dhcp_leases(params):
+ """
+ test API for DHCPLeases in class virNetwork
+ """
+ global LEASE_FILE_DNSMASQ
+ logger = params['logger']
+ networkname = params['networkname']
+ LEASE_FILE_DNSMASQ = "/var/lib/libvirt/dnsmasq/" + networkname + ".leases"
+ mac_value = params.get('macaddr', None)
+ conn = sharedmod.libvirtobj['conn']
+ logger.info("The given mac is %s" % (mac_value))
+
+ if not os.path.exists(LEASE_FILE_DNSMASQ):
+ logger.error("leases file for %s is not exist" % networkname)
+ logger.error("%s" % LEASE_FILE_DNSMASQ)
+ return 1
+ dhcp_lease_dns = get_info_from_dnsmasq(networkname, mac_value, logger)
+ logger.info("From dnsmasq: %s" % (dhcp_lease_dns))
+ if not dhcp_lease_dns:
+ return 1
+
+ netobj = conn.networkLookupByName(networkname)
+
+ try:
+ dhcp_lease_api = netobj.DHCPLeases(mac_value,0)
+ if not dhcp_lease_api and dhcp_lease_dns:
+ logger.info("From API: %s" % (dhcp_lease_api))
+ return 1
+ logger.info("From API: %s" % (dhcp_lease_api))
+ if not check_values(dhcp_lease_dns,dhcp_lease_api,networkname,logger):
+ return 1
+
+ except libvirtError, e:
+ logger.error("API error message: %s, error code is %s" \
+ % (e.message, e.get_error_code()))
+ return 1
+
+ return 0
--
1.8.3.1
9 years, 9 months
[libvirt] [PATCH 0/2] try to use btrfs COW copy
by Chen Hanxiao
If VIR_STORAGE_VOL_CREATE_REFLINK is specified,
try to use btrfs COW copy;
If btrfs COW copy is not supported,
fall back to normal copy.
Chen Hanxiao (2):
introduce btrfsCloneFile for COW copy
storage: try to perform btrfs clone if possible
include/libvirt/libvirt-storage.h | 1 +
src/storage/storage_backend.c | 65 ++++++++++++++++++++++++++++++++++-----
src/storage/storage_backend_fs.c | 8 +++--
src/storage/storage_driver.c | 4 ++-
4 files changed, 68 insertions(+), 10 deletions(-)
--
1.9.3
9 years, 9 months
[libvirt] [PATCH 0/8] Refactoring driver registration
by Daniel P. Berrange
This series continues on my previous work to refactor the driver
registration process. With this patch series applied, there is
no probing of secondary drivers any more. Once the hypervisor
driver is chosen, the correct secondary drivers are immediately
known. This enables a bunch of hacks to be removed from the ESX,
HyperV and VirtualBox drivers.
The final remaining problem will be to address the circular
dependancy problems wrt to the secrets and storage drivers.
Daniel P. Berrange (8):
Remove use of secretPrivateData from secret driver
Remove use of nwfilterPrivateData from nwfilter driver
Remove use of storagePrivateData/networkPrivateData from vbox
Remove use of nodeDevicePrivateData from nodeDev driver
Remove use of interfacePrivateData from udev driver
Remove all secondary driver private data fields
don't disable state driver when libvirtd is not built
Removing probing of secondary drivers
daemon/libvirtd.c | 19 +-
src/Makefile.am | 69 +------
src/bhyve/bhyve_driver.c | 14 +-
src/check-driverimpls.pl | 3 +-
src/conf/domain_nwfilter.c | 5 +-
src/conf/domain_nwfilter.h | 6 +-
src/datatypes.c | 12 --
src/datatypes.h | 6 -
src/driver-hypervisor.h | 3 -
src/driver-interface.h | 9 -
src/driver-network.h | 11 +-
src/driver-nodedev.h | 8 +-
src/driver-nwfilter.h | 13 +-
src/driver-secret.h | 12 +-
src/driver-storage.h | 12 +-
src/driver.h | 60 +++---
src/esx/esx_device_monitor.c | 74 --------
src/esx/esx_device_monitor.h | 28 ---
src/esx/esx_driver.c | 25 +--
src/esx/esx_interface_driver.c | 37 +---
src/esx/esx_interface_driver.h | 4 +-
src/esx/esx_network_driver.c | 37 +---
src/esx/esx_network_driver.h | 4 +-
src/esx/esx_nwfilter_driver.c | 74 --------
src/esx/esx_nwfilter_driver.h | 28 ---
src/esx/esx_secret_driver.c | 72 -------
src/esx/esx_secret_driver.h | 27 ---
src/esx/esx_storage_driver.c | 37 +---
src/esx/esx_storage_driver.h | 4 +-
src/hyperv/hyperv_device_monitor.c | 71 -------
src/hyperv/hyperv_device_monitor.h | 28 ---
src/hyperv/hyperv_driver.c | 25 +--
src/hyperv/hyperv_interface_driver.c | 71 -------
src/hyperv/hyperv_interface_driver.h | 28 ---
src/hyperv/hyperv_network_driver.c | 71 -------
src/hyperv/hyperv_network_driver.h | 28 ---
src/hyperv/hyperv_nwfilter_driver.c | 71 -------
src/hyperv/hyperv_nwfilter_driver.h | 28 ---
src/hyperv/hyperv_secret_driver.c | 71 -------
src/hyperv/hyperv_secret_driver.h | 28 ---
src/hyperv/hyperv_storage_driver.c | 71 -------
src/hyperv/hyperv_storage_driver.h | 28 ---
src/interface/interface_backend_netcf.c | 26 +--
src/interface/interface_backend_udev.c | 120 ++++++------
src/libvirt.c | 327 ++++++++++++++------------------
src/libvirt_daemon.syms | 15 --
src/libvirt_internal.h | 2 -
src/libvirt_private.syms | 19 +-
src/libxl/libxl_driver.c | 10 +-
src/lxc/lxc_driver.c | 13 +-
src/lxc/lxc_process.c | 8 +-
src/lxc/lxc_process.h | 3 +-
src/network/bridge_driver.c | 25 +--
src/node_device/node_device_driver.c | 78 +++-----
src/node_device/node_device_driver.h | 6 +-
src/node_device/node_device_hal.c | 106 ++++-------
src/node_device/node_device_udev.c | 78 +++-----
src/nwfilter/nwfilter_driver.c | 132 +++++--------
src/openvz/openvz_driver.c | 12 +-
src/phyp/phyp_driver.c | 64 +------
src/qemu/qemu_command.c | 8 +-
src/qemu/qemu_command.h | 1 -
src/qemu/qemu_driver.c | 12 +-
src/qemu/qemu_hotplug.c | 12 +-
src/qemu/qemu_hotplug.h | 1 -
src/qemu/qemu_process.c | 10 +-
src/remote/remote_driver.c | 158 ++-------------
src/secret/secret_driver.c | 215 +++++++++------------
src/storage/storage_driver.c | 25 +--
src/test/test_driver.c | 156 ++-------------
src/uml/uml_conf.c | 9 +-
src/uml/uml_driver.c | 10 +-
src/vbox/vbox_common.c | 1 -
src/vbox/vbox_driver.c | 47 ++---
src/vbox/vbox_network.c | 32 ----
src/vbox/vbox_storage.c | 30 ---
src/vmware/vmware_driver.c | 12 +-
src/xen/xen_driver.c | 11 +-
src/xenapi/xenapi_driver.c | 10 +-
tests/qemuxml2argvtest.c | 17 --
tests/virdrivermoduletest.c | 18 +-
81 files changed, 648 insertions(+), 2523 deletions(-)
delete mode 100644 src/esx/esx_device_monitor.c
delete mode 100644 src/esx/esx_device_monitor.h
delete mode 100644 src/esx/esx_nwfilter_driver.c
delete mode 100644 src/esx/esx_nwfilter_driver.h
delete mode 100644 src/esx/esx_secret_driver.c
delete mode 100644 src/esx/esx_secret_driver.h
delete mode 100644 src/hyperv/hyperv_device_monitor.c
delete mode 100644 src/hyperv/hyperv_device_monitor.h
delete mode 100644 src/hyperv/hyperv_interface_driver.c
delete mode 100644 src/hyperv/hyperv_interface_driver.h
delete mode 100644 src/hyperv/hyperv_network_driver.c
delete mode 100644 src/hyperv/hyperv_network_driver.h
delete mode 100644 src/hyperv/hyperv_nwfilter_driver.c
delete mode 100644 src/hyperv/hyperv_nwfilter_driver.h
delete mode 100644 src/hyperv/hyperv_secret_driver.c
delete mode 100644 src/hyperv/hyperv_secret_driver.h
delete mode 100644 src/hyperv/hyperv_storage_driver.c
delete mode 100644 src/hyperv/hyperv_storage_driver.h
delete mode 100644 src/libvirt_daemon.syms
--
2.1.0
9 years, 9 months
[libvirt] [PATCH] qemu: format server interface without a listen address
by Ján Tomko
https://bugzilla.redhat.com/show_bug.cgi?id=1130390
The listen address is not mandatory for <interface type='server'>
but when it's not specified, we've been formatting it as:
-netdev socket,listen=(null):5558,id=hostnet0
which failed with:
Device 'socket' could not be initialized
Omit the address completely and only format the port in the listen
attribute.
---
docs/schemas/domaincommon.rng | 10 ++++++++++
src/qemu/qemu_command.c | 3 ++-
tests/qemuxml2argvdata/qemuxml2argv-net-vhostuser.args | 4 +++-
tests/qemuxml2argvdata/qemuxml2argv-net-vhostuser.xml | 5 +++++
4 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index c428ddf..9d6c1ee 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -2207,6 +2207,16 @@
<empty/>
</element>
</optional>
+ <optional>
+ <element name="model">
+ <attribute name="type">
+ <data type="string">
+ <param name='pattern'>[a-zA-Z0-9\-_]+</param>
+ </data>
+ </attribute>
+ <empty/>
+ </element>
+ </optional>
</interleave>
</group>
<group>
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index c041ee7..7e1f3d0 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -4576,7 +4576,8 @@ qemuBuildHostNetStr(virDomainNetDefPtr net,
case VIR_DOMAIN_NET_TYPE_SERVER:
virBufferAsprintf(&buf, "socket%clisten=%s:%d",
type_sep,
- net->data.socket.address,
+ net->data.socket.address ? net->data.socket.address
+ : "",
net->data.socket.port);
type_sep = ',';
break;
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-vhostuser.args b/tests/qemuxml2argvdata/qemuxml2argv-net-vhostuser.args
index 26daac3..ac43630 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-net-vhostuser.args
+++ b/tests/qemuxml2argvdata/qemuxml2argv-net-vhostuser.args
@@ -7,4 +7,6 @@ pc -m 214 -smp 1 -nographic -nodefaults -monitor unix:/tmp/test-monitor,server,n
-device virtio-net-pci,netdev=hostnet0,id=net0,mac=52:54:00:ee:96:6b,bus=pci.0,addr=0x3 \
-chardev socket,id=charnet1,path=/tmp/vhost1.sock \
-netdev type=vhost-user,id=hostnet1,chardev=charnet1 \
--device virtio-net-pci,netdev=hostnet1,id=net1,mac=52:54:00:ee:96:6c,bus=pci.0,addr=0x4
+-device virtio-net-pci,netdev=hostnet1,id=net1,mac=52:54:00:ee:96:6c,bus=pci.0,addr=0x4 \
+-netdev socket,listen=:2015,id=hostnet2 \
+-device rtl8139,netdev=hostnet2,id=net2,mac=52:54:00:95:db:c0,bus=pci.0,addr=0x5
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-vhostuser.xml b/tests/qemuxml2argvdata/qemuxml2argv-net-vhostuser.xml
index e5b6242..fa09157 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-net-vhostuser.xml
+++ b/tests/qemuxml2argvdata/qemuxml2argv-net-vhostuser.xml
@@ -33,6 +33,11 @@
<source type='unix' path='/tmp/vhost1.sock' mode='client'/>
<model type='virtio'/>
</interface>
+ <interface type='server'>
+ <mac address='52:54:00:95:db:c0'/>
+ <source port='2015'/>
+ <model type='rtl8139'/>
+ </interface>
<memballoon model='none'/>
</devices>
</domain>
--
2.0.4
9 years, 9 months
[libvirt] [PATCH] tests: fix xlconfigtest build failure
by Jim Fehlig
When libvirt is configured --without-xen, building the xlconfigtest
fails with
CCLD xlconfigtest
/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/crt1.o
In function `_start': (.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status
Introduced in commit 4ed5fb91 by too much copy and paste from
xmconfigtest.
Signed-off-by: Jim Fehlig <jfehlig(a)suse.com>
---
tests/Makefile.am | 17 ++++++++++++-----
tests/xlconfigtest.c | 4 ++--
2 files changed, 14 insertions(+), 7 deletions(-)
diff --git a/tests/Makefile.am b/tests/Makefile.am
index b16d3d5..1d838a5 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -483,11 +483,6 @@ sexpr2xmltest_SOURCES = \
testutils.c testutils.h
sexpr2xmltest_LDADD = $(xen_LDADDS)
-xlconfigtest_SOURCES = \
- xlconfigtest.c testutilsxen.c testutilsxen.h \
- testutils.c testutils.h
-xlconfigtest_LDADD =$(xen_LDADDS)
-
xmconfigtest_SOURCES = \
xmconfigtest.c testutilsxen.c testutilsxen.h \
testutils.c testutils.h
@@ -511,6 +506,18 @@ EXTRA_DIST += xml2sexprtest.c sexpr2xmltest.c xmconfigtest.c \
testutilsxen.c testutilsxen.h
endif ! WITH_XEN
+if WITH_LIBXL
+libxl_LDADDS = ../src/libvirt_driver_libxl_impl.la
+libxl_LDADDS += $(LDADDS)
+
+xlconfigtest_SOURCES = \
+ xlconfigtest.c testutilsxen.c testutilsxen.h \
+ testutils.c testutils.h
+xlconfigtest_LDADD =$(libxl_LDADDS)
+else ! WITH_LIBXL
+EXTRA_DIST += xlconfigtest.c
+endif ! WITH_LIBXL
+
QEMUMONITORTESTUTILS_SOURCES = \
qemumonitortestutils.c \
qemumonitortestutils.h \
diff --git a/tests/xlconfigtest.c b/tests/xlconfigtest.c
index c2763c0..8c4c82c 100644
--- a/tests/xlconfigtest.c
+++ b/tests/xlconfigtest.c
@@ -36,7 +36,7 @@
#include "virstring.h"
#include "testutils.h"
#include "testutilsxen.h"
-#include "xen/xen_driver.h"
+#include "libxl/libxl_conf.h"
#define VIR_FROM_THIS VIR_FROM_NONE
@@ -198,7 +198,7 @@ mymain(void)
if (!(caps = testXLInitCaps()))
return EXIT_FAILURE;
- if (!(xmlopt = xenDomainXMLConfInit()))
+ if (!(xmlopt = libxlCreateXMLConf()))
return EXIT_FAILURE;
#define DO_TEST(name, version) \
--
1.8.4.5
9 years, 9 months
[libvirt] [PATCH 0/3] Support for per-thread scheduling settings
by Martin Kletzander
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1178986
Martin Kletzander (3):
util: Add virProcessSetScheduler() function for scheduler settings
docs, schema, conf: Add support for setting scheduler parameters of
guest threads
qemu: Add support for setting vCPU and I/O thread scheduler setting
docs/formatdomain.html.in | 13 +++
docs/schemas/domaincommon.rng | 33 ++++++
src/conf/domain_conf.c | 137 +++++++++++++++++++++++-
src/conf/domain_conf.h | 24 +++++
src/libvirt_private.syms | 1 +
src/qemu/qemu_driver.c | 7 +-
src/qemu/qemu_process.c | 76 ++++++++++++-
src/qemu/qemu_process.h | 5 +-
src/util/virprocess.c | 46 +++++++-
src/util/virprocess.h | 6 +-
tests/qemuxml2argvdata/qemuxml2argv-cputune.xml | 4 +
11 files changed, 345 insertions(+), 7 deletions(-)
--
2.2.1
9 years, 9 months
[libvirt] Question about migration max downtime in domXML
by Jim Fehlig
Hi All,
I've had a few user requests to add migration max downtime to the domain
XML. IIRC, this was discussed on the list quite some time ago, but I'm
unable to find it in the archives. My recollection is that max downtime
is considered a tunable vs config and as such not included in the
domXML. But domXML does contain quite a few tunables, so perhaps my
memory is incorrect. Does anyone recall the details? I'd be happy to
work on this if folks find it acceptable.
Regards,
Jim
9 years, 9 months
[libvirt] [PATCH] qemu: Propagate storage errors on migration
by Michal Privoznik
There's one bug that got more visible with my patches that
automatically precreate storage on migration. The problem is, if
there's not enough disk space on destination, we successfully finish
the migration instead of failing.
Firstly, we instruct qemu to copy the storage. And as it copies the
data, one write() will return -ENOSPC, eventually, to which qemu
reacts by emitting BLOCK_JOB_ERROR. The event is successfully ignored
by us. Then, since the block job has finished, BLOCK_JOB_COMPLETED
event is emitted too.
Secondly, we are not checking for the block job completion as we
should. Currently, we do the check by issuing 'query-block-jobs' and
then looking in the command's output for the job we are interested in.
If course, we don't fail if the job is not there, in which case the
number of total bytes to be transferred and bytes already transferred,
well they equal both to zero. This is actually the line causing the
bug as it sees both numbers equal to each other and gives green light
to the actual migration.
The fix consist of two parts:
In the first, code handling BLOCK_JOB_ERROR is added. It's a monitor
event and we should have handler for that anyway.
In the second part, the code doing drive mirroring is rewritten so it
waits for the events instead of querying on the monitor repeatedly.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
src/conf/domain_conf.c | 3 ++-
src/conf/domain_conf.h | 1 +
src/qemu/qemu_migration.c | 25 +++++++------------------
src/qemu/qemu_monitor_json.c | 10 ++++++++++
src/qemu/qemu_process.c | 14 ++++++++++++++
5 files changed, 34 insertions(+), 19 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index d1a483a..751a9b5 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -787,7 +787,8 @@ VIR_ENUM_IMPL(virDomainDiskMirrorState, VIR_DOMAIN_DISK_MIRROR_STATE_LAST,
"none",
"yes",
"abort",
- "pivot")
+ "pivot",
+ "error")
VIR_ENUM_IMPL(virDomainLoader,
VIR_DOMAIN_LOADER_TYPE_LAST,
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index ac1f4f8..f18fa80 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -654,6 +654,7 @@ typedef enum {
VIR_DOMAIN_DISK_MIRROR_STATE_READY, /* Job in second phase */
VIR_DOMAIN_DISK_MIRROR_STATE_ABORT, /* Job aborted, waiting for event */
VIR_DOMAIN_DISK_MIRROR_STATE_PIVOT, /* Job pivoted, waiting for event */
+ VIR_DOMAIN_DISK_MIRROR_STATE_ERROR, /* Job failed */
VIR_DOMAIN_DISK_MIRROR_STATE_LAST
} virDomainDiskMirrorState;
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 77e0b35..e2309ea 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -1743,7 +1743,6 @@ qemuMigrationDriveMirror(virQEMUDriverPtr driver,
for (i = 0; i < vm->def->ndisks; i++) {
virDomainDiskDefPtr disk = vm->def->disks[i];
- virDomainBlockJobInfo info;
/* skip shared, RO and source-less disks */
if (disk->src->shared || disk->src->readonly ||
@@ -1768,6 +1767,7 @@ qemuMigrationDriveMirror(virQEMUDriverPtr driver,
if (mon_ret < 0)
goto error;
+ disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_COPY;
lastGood = i;
/* wait for completion */
@@ -1775,38 +1775,27 @@ qemuMigrationDriveMirror(virQEMUDriverPtr driver,
/* Poll every 500ms for progress & to allow cancellation */
struct timespec ts = { .tv_sec = 0, .tv_nsec = 500 * 1000 * 1000ull };
- memset(&info, 0, sizeof(info));
-
- if (qemuDomainObjEnterMonitorAsync(driver, vm,
- QEMU_ASYNC_JOB_MIGRATION_OUT) < 0)
- goto error;
if (priv->job.asyncAbort) {
/* explicitly do this *after* we entered the monitor,
* as this is a critical section so we are guaranteed
* priv->job.asyncAbort will not change */
- qemuDomainObjExitMonitor(driver, vm);
priv->job.current->type = VIR_DOMAIN_JOB_CANCELLED;
virReportError(VIR_ERR_OPERATION_ABORTED, _("%s: %s"),
qemuDomainAsyncJobTypeToString(priv->job.asyncJob),
_("canceled by client"));
goto error;
}
- mon_ret = qemuMonitorBlockJobInfo(priv->mon, diskAlias, &info,
- NULL);
- qemuDomainObjExitMonitor(driver, vm);
- if (mon_ret < 0)
- goto error;
-
- if (info.cur == info.end) {
+ if (disk->mirrorState == VIR_DOMAIN_DISK_MIRROR_STATE_READY) {
VIR_DEBUG("Drive mirroring of '%s' completed", diskAlias);
break;
+ } else if (disk->mirrorState == VIR_DOMAIN_DISK_MIRROR_STATE_ERROR) {
+ virReportError(VIR_ERR_OPERATION_ABORTED, _("%s: %s"),
+ qemuDomainAsyncJobTypeToString(priv->job.asyncJob),
+ _("canceled by destination"));
+ goto error;
}
- /* XXX Frankly speaking, we should listen to the events,
- * instead of doing this. But this works for now and we
- * are doing something similar in migration itself anyway */
-
virObjectUnlock(vm);
nanosleep(&ts, NULL);
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index e567aa7..5d6bbca 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -76,6 +76,7 @@ static void qemuMonitorJSONHandlePMWakeup(qemuMonitorPtr mon, virJSONValuePtr da
static void qemuMonitorJSONHandlePMSuspend(qemuMonitorPtr mon, virJSONValuePtr data);
static void qemuMonitorJSONHandleBlockJobCompleted(qemuMonitorPtr mon, virJSONValuePtr data);
static void qemuMonitorJSONHandleBlockJobCanceled(qemuMonitorPtr mon, virJSONValuePtr data);
+static void qemuMonitorJSONHandleBlockJobError(qemuMonitorPtr mon, virJSONValuePtr data);
static void qemuMonitorJSONHandleBlockJobReady(qemuMonitorPtr mon, virJSONValuePtr data);
static void qemuMonitorJSONHandleBalloonChange(qemuMonitorPtr mon, virJSONValuePtr data);
static void qemuMonitorJSONHandlePMSuspendDisk(qemuMonitorPtr mon, virJSONValuePtr data);
@@ -94,6 +95,7 @@ static qemuEventHandler eventHandlers[] = {
{ "BLOCK_IO_ERROR", qemuMonitorJSONHandleIOError, },
{ "BLOCK_JOB_CANCELLED", qemuMonitorJSONHandleBlockJobCanceled, },
{ "BLOCK_JOB_COMPLETED", qemuMonitorJSONHandleBlockJobCompleted, },
+ { "BLOCK_JOB_ERROR", qemuMonitorJSONHandleBlockJobError, },
{ "BLOCK_JOB_READY", qemuMonitorJSONHandleBlockJobReady, },
{ "DEVICE_DELETED", qemuMonitorJSONHandleDeviceDeleted, },
{ "DEVICE_TRAY_MOVED", qemuMonitorJSONHandleTrayChange, },
@@ -842,6 +844,14 @@ qemuMonitorJSONHandleBlockJobCanceled(qemuMonitorPtr mon,
}
static void
+qemuMonitorJSONHandleBlockJobError(qemuMonitorPtr mon,
+ virJSONValuePtr data)
+{
+ qemuMonitorJSONHandleBlockJobImpl(mon, data,
+ VIR_DOMAIN_BLOCK_JOB_FAILED);
+}
+
+static void
qemuMonitorJSONHandleBlockJobReady(qemuMonitorPtr mon,
virJSONValuePtr data)
{
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index c18204b..b29ecf1 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -1110,6 +1110,20 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN;
save = true;
}
+ } else if (disk->mirrorJob == VIR_DOMAIN_BLOCK_JOB_TYPE_COPY) {
+ switch ((virConnectDomainEventBlockJobStatus) status) {
+ case VIR_DOMAIN_BLOCK_JOB_READY:
+ case VIR_DOMAIN_BLOCK_JOB_COMPLETED:
+ disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_READY;
+ break;
+ case VIR_DOMAIN_BLOCK_JOB_CANCELED:
+ case VIR_DOMAIN_BLOCK_JOB_FAILED:
+ disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_ERROR;
+ break;
+ case VIR_DOMAIN_BLOCK_JOB_LAST:
+ VIR_DEBUG("should not get here");
+ break;
+ }
}
}
--
2.0.5
9 years, 9 months