Re: [libvirt] [PATCH] qemu: don't attempt undefined QMP commands
On 30.11.2012 01:40, Eric Blake wrote: https://bugzilla.redhat.com/show_bug.cgi?id=872292 Libvirt should not attempt to call a QMP command that has not been documented in qemu.git - if future qemu introduces a command by the same name but with subtly different semantics, then libvirt will be broken when trying to use that command. See also this attempt to convert the three snapshot commands to QMP: https://lists.gnu.org/archive/html/qemu-devel/2012-07/msg01597.html although it looks like that will still not happen before qemu 1.3. That thread eventually decided that qemu would use the name 'save-vm' rather than 'savevm', which mitigates the fact that libvirt's attempt to use a QMP 'savevm' would be broken, but we might not be as lucky on the other commands. * src/qemu/qemu_monitor_json.c (qemuMonitorJSONSetCPU) (qemuMonitorJSONAddDrive, qemuMonitorJSONDriveDel) (qemuMonitorJSONCreateSnapshot, qemuMonitorJSONLoadSnapshot) (qemuMonitorJSONDeleteSnapshot): Use only HMP fallback for now. (qemuMonitorJSONAddHostNetwork, qemuMonitorJSONRemoveHostNetwork) (qemuMonitorJSONAttachDrive, qemuMonitorJSONGetGuestDriveAddress): Delete; QMP implies QEMU_CAPS_DEVICE, which prefers AddNetdev, RemoveNetdev, and AddDrive anyways. * src/qemu/qemu_monitor.c (qemuMonitorAddHostNetwork) (qemuMonitorRemoveHostNetwork, qemuMonitorAttachDrive): Reflect deleted commands. * src/qemu/qemu_monitor_json.h (qemuMonitorJSONAddHostNetwork) (qemuMonitorJSONRemoveHostNetwork, qemuMonitorJSONAttachDrive): Likewise. --- src/qemu/qemu_monitor.c |9 +- src/qemu/qemu_monitor_json.c | 311 -- src/qemu/qemu_monitor_json.h | 12 -- 3 files changed, 31 insertions(+), 301 deletions(-) diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index aef5044..43e45ef 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -2387,7 +2387,8 @@ int qemuMonitorAddHostNetwork(qemuMonitorPtr mon, } if (mon-json) -ret = qemuMonitorJSONAddHostNetwork(mon, netstr); +virReportError(VIR_ERR_CONFIG_UNSUPPORTED, %s, + _(JSON monitor should be using netdev_add)); else ret = qemuMonitorTextAddHostNetwork(mon, netstr); I might be not getting something, but netdev_add seems documented for me: http://git.qemu.org/?p=qemu.git;a=blob;f=qapi-schema.json;h=5dfa0523915e1b3ea88d674492c3eb3ffb81a24f;hb=HEAD#l2297 The command is there since v1.2.0-rc0~314^2~2 (at least that's what 'git describe --tags --contains 928059a3' says). And if qemu developers are changing its semantic then they should not. I haven't checked the other commands you are removing. Michal -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] qemu: don't attempt undefined QMP commands
On Thu, Nov 29, 2012 at 05:40:20PM -0700, Eric Blake wrote: https://bugzilla.redhat.com/show_bug.cgi?id=872292 Libvirt should not attempt to call a QMP command that has not been documented in qemu.git - if future qemu introduces a command by the same name but with subtly different semantics, then libvirt will be broken when trying to use that command. The reason these were added was that back in the first days of QMP the intention was that every HMP command would have an identical QMP command. This plan changed before it was ever completed, hence the situation we're in now. diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index aef5044..43e45ef 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -2387,7 +2387,8 @@ int qemuMonitorAddHostNetwork(qemuMonitorPtr mon, } if (mon-json) -ret = qemuMonitorJSONAddHostNetwork(mon, netstr); +virReportError(VIR_ERR_CONFIG_UNSUPPORTED, %s, + _(JSON monitor should be using netdev_add)); else ret = qemuMonitorTextAddHostNetwork(mon, netstr); @@ -2418,7 +2419,8 @@ int qemuMonitorRemoveHostNetwork(qemuMonitorPtr mon, } if (mon-json) -ret = qemuMonitorJSONRemoveHostNetwork(mon, vlan, netname); +virReportError(VIR_ERR_CONFIG_UNSUPPORTED, %s, + _(JSON monitor should be using netdev_del)); In these two you recommend different commands else ret = qemuMonitorTextRemoveHostNetwork(mon, vlan, netname); return ret; @@ -2548,7 +2550,8 @@ int qemuMonitorAttachDrive(qemuMonitorPtr mon, } if (mon-json) -ret = qemuMonitorJSONAttachDrive(mon, drivestr, controllerAddr, driveAddr); +virReportError(VIR_ERR_CONFIG_UNSUPPORTED, %s, + _(JSON monitor should be using AddDrive)); while this one recommends a different method ACK you standardize on one. Daniel -- |: http://berrange.com -o-http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] qemu: don't attempt undefined QMP commands
On Fri, Nov 30, 2012 at 09:01:47AM +0100, Michal Privoznik wrote: On 30.11.2012 01:40, Eric Blake wrote: https://bugzilla.redhat.com/show_bug.cgi?id=872292 Libvirt should not attempt to call a QMP command that has not been documented in qemu.git - if future qemu introduces a command by the same name but with subtly different semantics, then libvirt will be broken when trying to use that command. See also this attempt to convert the three snapshot commands to QMP: https://lists.gnu.org/archive/html/qemu-devel/2012-07/msg01597.html although it looks like that will still not happen before qemu 1.3. That thread eventually decided that qemu would use the name 'save-vm' rather than 'savevm', which mitigates the fact that libvirt's attempt to use a QMP 'savevm' would be broken, but we might not be as lucky on the other commands. * src/qemu/qemu_monitor_json.c (qemuMonitorJSONSetCPU) (qemuMonitorJSONAddDrive, qemuMonitorJSONDriveDel) (qemuMonitorJSONCreateSnapshot, qemuMonitorJSONLoadSnapshot) (qemuMonitorJSONDeleteSnapshot): Use only HMP fallback for now. (qemuMonitorJSONAddHostNetwork, qemuMonitorJSONRemoveHostNetwork) (qemuMonitorJSONAttachDrive, qemuMonitorJSONGetGuestDriveAddress): Delete; QMP implies QEMU_CAPS_DEVICE, which prefers AddNetdev, RemoveNetdev, and AddDrive anyways. * src/qemu/qemu_monitor.c (qemuMonitorAddHostNetwork) (qemuMonitorRemoveHostNetwork, qemuMonitorAttachDrive): Reflect deleted commands. * src/qemu/qemu_monitor_json.h (qemuMonitorJSONAddHostNetwork) (qemuMonitorJSONRemoveHostNetwork, qemuMonitorJSONAttachDrive): Likewise. --- src/qemu/qemu_monitor.c |9 +- src/qemu/qemu_monitor_json.c | 311 -- src/qemu/qemu_monitor_json.h | 12 -- 3 files changed, 31 insertions(+), 301 deletions(-) diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index aef5044..43e45ef 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -2387,7 +2387,8 @@ int qemuMonitorAddHostNetwork(qemuMonitorPtr mon, } if (mon-json) -ret = qemuMonitorJSONAddHostNetwork(mon, netstr); +virReportError(VIR_ERR_CONFIG_UNSUPPORTED, %s, + _(JSON monitor should be using netdev_add)); else ret = qemuMonitorTextAddHostNetwork(mon, netstr); I might be not getting something, but netdev_add seems documented for me: You're mis-reading the patch - check the mesage again :-) Daniel -- |: http://berrange.com -o-http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [test-API][PATCH v4] Add test case of set vcpus with flags
v2: break down the case to small cases with separate flags * Use setVcpusFlags API to set domain vcpus with flags * 3 cases added, each only deal with one set flag value as in config, live or maximum * cases are independent on domain states, API will report error if not suitable for certain states * the sample conf is only one scenario of hotplug domain vcpus v3: merge config and maximum case to config * maximum flag can only work when domain is shutoff, merge it to config case to simplify code v4: make both vcpu and maxvcpu as optional param in config case * depend on the given params to select flags and setting Signed-off-by: Wayne Sun g...@redhat.com --- cases/set_vcpus_flags.conf | 67 repos/setVcpus/set_vcpus_config.py | 99 repos/setVcpus/set_vcpus_live.py | 96 ++ 3 files changed, 262 insertions(+), 0 deletions(-) create mode 100644 cases/set_vcpus_flags.conf create mode 100644 repos/setVcpus/__init__.py create mode 100644 repos/setVcpus/set_vcpus_config.py create mode 100644 repos/setVcpus/set_vcpus_live.py diff --git a/cases/set_vcpus_flags.conf b/cases/set_vcpus_flags.conf new file mode 100644 index 000..6cf595f --- /dev/null +++ b/cases/set_vcpus_flags.conf @@ -0,0 +1,67 @@ +domain:install_linux_cdrom +guestname +$defaultname +guestos +$defaultos +guestarch +$defaultarch +vcpu +$defaultvcpu +memory +$defaultmem +hddriver +$defaulthd +nicdriver +$defaultnic +imageformat +qcow2 + +domain:destroy +guestname +$defaultname + +setVcpus:set_vcpus_config +guestname +$defaultname +vcpu +1 +maxvcpu +8 + +domain:start +guestname +$defaultname + +setVcpus:set_vcpus_live +guestname +$defaultname +vcpu +3 +username +$username +password +$password + +setVcpus:set_vcpus_config +guestname +$defaultname +vcpu +5 + +domain:destroy +guestname +$defaultname + +domain:start +guestname +$defaultname + +domain:destroy +guestname +$defaultname + +domain:undefine +guestname +$defaultname + +options cleanup=enable diff --git a/repos/setVcpus/__init__.py b/repos/setVcpus/__init__.py new file mode 100644 index 000..e69de29 diff --git a/repos/setVcpus/set_vcpus_config.py b/repos/setVcpus/set_vcpus_config.py new file mode 100644 index 000..289dad1 --- /dev/null +++ b/repos/setVcpus/set_vcpus_config.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python +# Test set domain vcpu with flag VIR_DOMAIN_AFFECT_CONFIG or +# VIR_DOMAIN_VCPU_MAXIMUM, depend on which optional param is +# given. + +from xml.dom import minidom + +import libvirt +from libvirt import libvirtError + +from src import sharedmod + +required_params = ('guestname', ) +optional_params = {'vcpu': 1, + 'maxvcpu': 8, + } + +def get_vcpu_number(domobj): +dump domain config xml description to get vcpu number, return + current vcpu and maximum vcpu number + +try: +guestxml = domobj.XMLDesc(2) +logger.debug(domain %s xml is :\n%s %(domobj.name(), guestxml)) +xml = minidom.parseString(guestxml) +vcpu = xml.getElementsByTagName('vcpu')[0] +maxvcpu = int(vcpu.childNodes[0].data) +logger.info(domain max vcpu number is: %s % maxvcpu) + +if vcpu.hasAttribute('current'): +attr = vcpu.getAttributeNode('current') +current = int(attr.nodeValue) +else: +logger.info(no 'current' atrribute for element vcpu) +current = int(vcpu.childNodes[0].data) + +logger.info(domain current vcpu number is: %s % current) + +except libvirtError, e: +logger.error(libvirt call failed: + str(e)) +return False + +return current, maxvcpu + +def set_vcpus_config(params): +set domain vcpu with config flag and check, also set and check + max vcpu with maximum flag if optional param maxvcpu is given + +global logger +logger = params['logger'] +params.pop('logger') +guestname = params['guestname'] +vcpu = params.get('vcpu', None) +maxvcpu = params.get('maxvcpu', None) + +logger.info(the name of virtual machine is %s % guestname) +if vcpu == None and maxvcpu == None: +logger.error(at least one of vcpu or maxvcpu should be provided) +return 1 + +conn = sharedmod.libvirtobj['conn'] + +try: +domobj = conn.lookupByName(guestname) +if vcpu: +logger.info(the given vcpu number is %s % vcpu) +logger.info(set domain vcpu as %s with flag: %s % +(vcpu, libvirt.VIR_DOMAIN_AFFECT_CONFIG)) +domobj.setVcpusFlags(int(vcpu), libvirt.VIR_DOMAIN_AFFECT_CONFIG) +logger.info(set
Re: [libvirt] [test-API][PATCH v4] Add test case of set vcpus with flags
On 11/30/2012 04:25 PM, Wayne Sun wrote: v2: break down the case to small cases with separate flags * Use setVcpusFlags API to set domain vcpus with flags * 3 cases added, each only deal with one set flag value as in config, live or maximum * cases are independent on domain states, API will report error if not suitable for certain states * the sample conf is only one scenario of hotplug domain vcpus v3: merge config and maximum case to config * maximum flag can only work when domain is shutoff, merge it to config case to simplify code v4: make both vcpu and maxvcpu as optional param in config case * depend on the given params to select flags and setting Signed-off-by: Wayne Sun g...@redhat.com --- cases/set_vcpus_flags.conf | 67 repos/setVcpus/set_vcpus_config.py | 99 repos/setVcpus/set_vcpus_live.py | 96 ++ 3 files changed, 262 insertions(+), 0 deletions(-) create mode 100644 cases/set_vcpus_flags.conf create mode 100644 repos/setVcpus/__init__.py create mode 100644 repos/setVcpus/set_vcpus_config.py create mode 100644 repos/setVcpus/set_vcpus_live.py diff --git a/cases/set_vcpus_flags.conf b/cases/set_vcpus_flags.conf new file mode 100644 index 000..6cf595f --- /dev/null +++ b/cases/set_vcpus_flags.conf @@ -0,0 +1,67 @@ +domain:install_linux_cdrom +guestname +$defaultname +guestos +$defaultos +guestarch +$defaultarch +vcpu +$defaultvcpu +memory +$defaultmem +hddriver +$defaulthd +nicdriver +$defaultnic +imageformat +qcow2 + +domain:destroy +guestname +$defaultname + +setVcpus:set_vcpus_config +guestname +$defaultname +vcpu +1 +maxvcpu +8 + +domain:start +guestname +$defaultname + +setVcpus:set_vcpus_live +guestname +$defaultname +vcpu +3 +username +$username +password +$password + +setVcpus:set_vcpus_config +guestname +$defaultname +vcpu +5 + +domain:destroy +guestname +$defaultname + +domain:start +guestname +$defaultname + +domain:destroy +guestname +$defaultname + +domain:undefine +guestname +$defaultname + +options cleanup=enable diff --git a/repos/setVcpus/__init__.py b/repos/setVcpus/__init__.py new file mode 100644 index 000..e69de29 diff --git a/repos/setVcpus/set_vcpus_config.py b/repos/setVcpus/set_vcpus_config.py new file mode 100644 index 000..289dad1 --- /dev/null +++ b/repos/setVcpus/set_vcpus_config.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python +# Test set domain vcpu with flag VIR_DOMAIN_AFFECT_CONFIG or +# VIR_DOMAIN_VCPU_MAXIMUM, depend on which optional param is +# given. + +from xml.dom import minidom + +import libvirt +from libvirt import libvirtError + +from src import sharedmod + +required_params = ('guestname', ) +optional_params = {'vcpu': 1, + 'maxvcpu': 8, + } + +def get_vcpu_number(domobj): +dump domain config xml description to get vcpu number, return + current vcpu and maximum vcpu number + +try: +guestxml = domobj.XMLDesc(2) +logger.debug(domain %s xml is :\n%s %(domobj.name(), guestxml)) +xml = minidom.parseString(guestxml) +vcpu = xml.getElementsByTagName('vcpu')[0] +maxvcpu = int(vcpu.childNodes[0].data) +logger.info(domain max vcpu number is: %s % maxvcpu) + +if vcpu.hasAttribute('current'): +attr = vcpu.getAttributeNode('current') +current = int(attr.nodeValue) +else: +logger.info(no 'current' atrribute for element vcpu) +current = int(vcpu.childNodes[0].data) + +logger.info(domain current vcpu number is: %s % current) + +except libvirtError, e: +logger.error(libvirt call failed: + str(e)) +return False + +return current, maxvcpu + +def set_vcpus_config(params): +set domain vcpu with config flag and check, also set and check + max vcpu with maximum flag if optional param maxvcpu is given + +global logger +logger = params['logger'] +params.pop('logger') +guestname = params['guestname'] +vcpu = params.get('vcpu', None) +maxvcpu = params.get('maxvcpu', None) + +logger.info(the name of virtual machine is %s % guestname) +if vcpu == None and maxvcpu == None: +logger.error(at least one of vcpu or maxvcpu should be provided) +return 1 + +conn = sharedmod.libvirtobj['conn'] + +try: +domobj = conn.lookupByName(guestname) +if vcpu: +logger.info(the given vcpu number is %s % vcpu) +logger.info(set domain vcpu as %s with flag: %s % +(vcpu, libvirt.VIR_DOMAIN_AFFECT_CONFIG)) +domobj.setVcpusFlags(int(vcpu),
Re: [libvirt] [PATCHv2 1/2] nwfilter: utility function virNWFilterVarValueEqual
On 29.11.2012 19:30, Laine Stump wrote: From: Stefan Berger stef...@us.ibm.com To detect if an interface's nwfilter has changed, we need to also compare the filterparams, which is a hashtable of virNWFilterVarValue. virHashEqual can do this nicely, but requires a pointer to a function that will compare two of the items being stored in the hashes. --- src/conf/nwfilter_params.c | 31 +++ src/conf/nwfilter_params.h | 2 ++ src/libvirt_private.syms | 1 + 3 files changed, 34 insertions(+) diff --git a/src/conf/nwfilter_params.c b/src/conf/nwfilter_params.c index 6dc4baa..3ac1303 100644 --- a/src/conf/nwfilter_params.c +++ b/src/conf/nwfilter_params.c @@ -189,6 +189,37 @@ virNWFilterVarValueGetCardinality(const virNWFilterVarValuePtr val) return 0; } +bool +virNWFilterVarValueEqual(const virNWFilterVarValuePtr a, + const virNWFilterVarValuePtr b) +{ +unsigned int card, i, j; +const char *s; + +if (!a || !b) +return false; + +card = virNWFilterVarValueGetCardinality(a); +if (card != virNWFilterVarValueGetCardinality(b)) +return false; + +/* brute force O(n^2) comparison */ +for (i = 0; i card; i++) { +bool eq = false; + +s = virNWFilterVarValueGetNthValue(a, i); +for (j = 0; j card; j++) { +if (STREQ_NULLABLE(s, virNWFilterVarValueGetNthValue(b, j))) { + eq = true; + break; +} +} +if (!eq) +return false; +} +return true; +} + Seems reasonable. The quadratic time complexity could be avoided if @a and @b items are sorted. And since this is just a callback to virHashEqual() we shouldn't be doing anything here but comparing. int virNWFilterVarValueAddValue(virNWFilterVarValuePtr val, char *value) { diff --git a/src/conf/nwfilter_params.h b/src/conf/nwfilter_params.h index cedf9cd..96d3033 100644 --- a/src/conf/nwfilter_params.h +++ b/src/conf/nwfilter_params.h @@ -57,6 +57,8 @@ const char *virNWFilterVarValueGetSimple(const virNWFilterVarValuePtr val); const char *virNWFilterVarValueGetNthValue(virNWFilterVarValuePtr val, unsigned int idx); unsigned int virNWFilterVarValueGetCardinality(const virNWFilterVarValuePtr); +bool virNWFilterVarValueEqual(const virNWFilterVarValuePtr a, + const virNWFilterVarValuePtr b); int virNWFilterVarValueAddValue(virNWFilterVarValuePtr val, char *value); int virNWFilterVarValueDelValue(virNWFilterVarValuePtr val, const char *value); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 2573b8a..ada73fb 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -968,6 +968,7 @@ virNWFilterVarValueCopy; virNWFilterVarValueCreateSimple; virNWFilterVarValueCreateSimpleCopyValue; virNWFilterVarValueDelValue; +virNWFilterVarValueEqual; virNWFilterVarValueFree; virNWFilterVarValueGetCardinality; virNWFilterVarValueGetNthValue; ACK Michal -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] problems with current libvirt and qemu-kvm
On Thu, Nov 29, 2012 at 03:48:52PM -0500, Gene Czarcinski wrote: When I rebased my DHCPv6, etc. patches, I did that not only on to of Laine Stump's dnsmasq-capabiliotes/bind-dynamic updates but I also rebased to current git master. Well, the problem with the large number/frequent RTR-ADVERT syslog messages from dnsmasq that I had previously seen were fixed ... they stopped and dnsmasq produced expected results. But, starting virt-manager hung and there were new error messages in syslog about internal error cannot find suitable emulator for X86_64. Until I pushed the patches from Victor yesterday, libvirt GIT was broken when used against QEMU GIT. The effect was that libvirt could not detect any QEMU binaries. So if you're using latest QEMU GIT that might be what you've hit. Daniel -- |: http://berrange.com -o-http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCHv2 2/2] qemu: support live update of an interface's filter
On 29.11.2012 19:30, Laine Stump wrote: Since we can't (currently) rely on the ability to provide blanket support for all possible network changes by calling the toplevel netdev hostside disconnect/connect functions (due to qemu only supporting a lockstep between initialization of host side and guest side of devices), in order to support live change of an interface's nwfilter we need to make a special purpose function to only call the nwfilter teardown and setup functions if the filter for an interface (or its parameters) changes. The pattern is nearly identical to that used to change the bridge that an interface is connected to. This patch was inspired by a request from Guido Winkelmann gu...@sagersystems.de, who tested an earlier version. --- src/conf/nwfilter_params.c | 21 ++ src/conf/nwfilter_params.h | 4 +++- src/libvirt_private.syms | 1 + src/qemu/qemu_hotplug.c| 55 +++--- 4 files changed, 77 insertions(+), 4 deletions(-) diff --git a/src/conf/nwfilter_params.c b/src/conf/nwfilter_params.c index 3ac1303..7254519 100644 --- a/src/conf/nwfilter_params.c +++ b/src/conf/nwfilter_params.c @@ -795,6 +795,27 @@ err_exit: return -1; } +/* The general purpose function virNWFilterVarValueEqual returns a + * bool, but the comparison callback for virHashEqual (called below) + * needs to return an int of 0 for == and non-0 for != + */ +static int +virNWFilterVarValueCompare(const void *a, const void *b) +{ +return virNWFilterVarValueEqual((const virNWFilterVarValuePtr) a, +(const virNWFilterVarValuePtr) b) ? 0 : 1; +} + +bool +virNWFilterHashTableEqual(virNWFilterHashTablePtr a, + virNWFilterHashTablePtr b) +{ +if (!(a || b)) +return true; +if (!(a b)) +return false; +return virHashEqual(a-hashTable, b-hashTable, virNWFilterVarValueCompare); +} static bool isValidVarName(const char *var) diff --git a/src/conf/nwfilter_params.h b/src/conf/nwfilter_params.h index 96d3033..6c3ce54 100644 --- a/src/conf/nwfilter_params.h +++ b/src/conf/nwfilter_params.h @@ -1,7 +1,7 @@ /* * nwfilter_params.h: parsing and data maintenance of filter parameters * - * Copyright (C) 2011 Red Hat, Inc. + * Copyright (C) 2011-2012 Red Hat, Inc. * Copyright (C) 2010 IBM Corporation * * This library is free software; you can redistribute it and/or @@ -87,6 +87,8 @@ void *virNWFilterHashTableRemoveEntry(virNWFilterHashTablePtr table, const char *name); int virNWFilterHashTablePutAll(virNWFilterHashTablePtr src, virNWFilterHashTablePtr dest); +bool virNWFilterHashTableEqual(virNWFilterHashTablePtr a, + virNWFilterHashTablePtr b); # define VALID_VARNAME \ abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index ada73fb..5598682 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -952,6 +952,7 @@ virNWFilterIPAddrMapShutdown; # nwfilter_params.h virNWFilterHashTableCreate; +virNWFilterHashTableEqual; virNWFilterHashTableFree; virNWFilterHashTablePut; virNWFilterHashTablePutAll; diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 0bc2259..5058198 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1330,6 +1330,43 @@ cleanup: return ret; } +static int +qemuDomainChangeNetFilter(virConnectPtr conn, + virDomainObjPtr vm, + virDomainNetDefPtr olddev, + virDomainNetDefPtr newdev) +{ +/* make sure this type of device supports filters. */ +switch (virDomainNetGetActualType(newdev)) { +case VIR_DOMAIN_NET_TYPE_ETHERNET: +case VIR_DOMAIN_NET_TYPE_BRIDGE: +case VIR_DOMAIN_NET_TYPE_NETWORK: +break; +default: +virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _(filters not supported on interfaces of type %s), + virDomainNetTypeToString(virDomainNetGetActualType(newdev))); +return -1; +} + +virDomainConfNWFilterTeardown(olddev); + +if (virDomainConfNWFilterInstantiate(conn, vm-def-uuid, newdev) 0) { +virErrorPtr errobj; + +virReportError(VIR_ERR_OPERATION_FAILED, + _(failed to add new filter rules to '%s' + - attempting to restore old rules), + olddev-ifname); +errobj = virSaveLastError(); +ignore_value(virDomainConfNWFilterInstantiate(conn, vm-def-uuid, olddev)); +virSetError(errobj); +virFreeError(errobj); +return -1; +} +return 0; +} + int qemuDomainChangeNetLinkState(struct
[libvirt] [PATCH] implement managedsave in libvirt xen legacy driver
Implement the domainManagedSave, domainHasManagedSaveImage, and domainManagedSaveRemove functions in the libvirt legacy xen driver. domainHasManagedSaveImage check the managedsave image from filesystem everytime. This is different from qemu and libxl driver. In qemu or libxl driver, there is a hasManagesSave flags in virDomainObjPtr which is not used in xen legacy driver. This flag could not add into xen driver ptr either, because the driver ptr will be release at the end of every libvirt api calls. Meanwhile, AFAIK, xen store all the flags in xen not in libvirt xen driver. There is no need to add this flags in xen. --- i have test the following case for this patch: 1), virsh managedsave save domain to /var/lib/xen/save/domain_name.save. call xenUnifiedDomainManagedSave. 2), virsh start: if managedsave image is exist, it should be boot from managed save image. call xenUnifiedDomainHasManagedSaveImage. 3), virsh start --force-boot: fresh boot, delete the managed save image if exists. call xenUnifiedDomainHasManagedSaveImage, xenUnifiedDomainManagedSaveRemove. 4), virsh managedsave-remove: remove managed save image. call xenUnifiedDomainManagedSaveRemove 5), virsh undefine: undefine the domain, it will fail if mananed save image exist. call xenUnifiedDomainHasManagedSaveImage. 6), virsh undefine --managed-save: undefine the domain, and remove mananed save image. call xenUnifiedDomainHasManagedSaveImage and xenUnifiedDomainManagedSaveRemove. 7), virsh list --all --with-managed-save. list domain if managed save image exist. got nothing if non-exists. call xenUnifiedDomainHasManagedSaveImage. 8), virsh list --all --without-managed-save. do not list the domain if managed save image exist. call xenUnifiedDomainHasManagedSaveImage. src/xen/xen_driver.c | 109 ++- src/xen/xen_driver.h | 2 + 2 files changed, 110 insertions(+), 1 deletion(-) diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c index 5a40757..0b2418d 100644 --- a/src/xen/xen_driver.c +++ b/src/xen/xen_driver.c @@ -67,6 +67,7 @@ #include nodeinfo.h #define VIR_FROM_THIS VIR_FROM_XEN +#define XEN_SAVE_DIR LOCALSTATEDIR /lib/libvirt/xen/save static int xenUnifiedNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info); @@ -267,6 +268,7 @@ xenUnifiedOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags) { int i, ret = VIR_DRV_OPEN_DECLINED; xenUnifiedPrivatePtr priv; +char ebuf[1024]; #ifdef __sun /* @@ -406,6 +408,17 @@ xenUnifiedOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags) } #endif +if (virAsprintf(priv-saveDir, %s, XEN_SAVE_DIR) == -1) { +virReportOOMError(); +goto fail; +} + +if (virFileMakePath(priv-saveDir) 0) { +VIR_ERROR(_(Failed to create save dir '%s': %s), priv-saveDir, + virStrerror(errno, ebuf, sizeof(ebuf))); +goto fail; +} + return VIR_DRV_OPEN_SUCCESS; fail: @@ -437,6 +450,7 @@ xenUnifiedClose(virConnectPtr conn) if (priv-opened[i]) drivers[i]-xenClose(conn); +VIR_FREE(priv-saveDir); virMutexDestroy(priv-lock); VIR_FREE(conn-privateData); @@ -1080,6 +1094,79 @@ xenUnifiedDomainSave(virDomainPtr dom, const char *to) return xenUnifiedDomainSaveFlags(dom, to, NULL, 0); } +static char * +xenUnifiedDomainManagedSavePath(xenUnifiedPrivatePtr priv, virDomainPtr dom) +{ +char *ret; + +if (virAsprintf(ret, %s/%s.save, priv-saveDir, dom-name) 0) { +virReportOOMError(); +return NULL; +} + +VIR_DEBUG(managed save image: %s, ret); +return ret; +} + +static int +xenUnifiedDomainManagedSave(virDomainPtr dom, unsigned int flags) +{ +GET_PRIVATE(dom-conn); +char *name; +int ret = -1; + +virCheckFlags(0, -1); + +name = xenUnifiedDomainManagedSavePath(priv, dom); +if (!name) +goto cleanup; + +if (priv-opened[XEN_UNIFIED_XEND_OFFSET]) +ret = xenDaemonDomainSave(dom, name); + +cleanup: +VIR_FREE(name); +return ret; +} + +static int +xenUnifiedDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags) +{ +GET_PRIVATE(dom-conn); +char *name; +int ret = -1; + +virCheckFlags(0, -1); + +name = xenUnifiedDomainManagedSavePath(priv, dom); +if (!name) +return ret; + +ret = virFileExists(name); +VIR_FREE(name); +return ret; +} + +static int +xenUnifiedDomainManagedSaveRemove(virDomainPtr dom, unsigned int flags) +{ +GET_PRIVATE(dom-conn); +char *name; +int ret = -1; + +virCheckFlags(0, -1); + +name = xenUnifiedDomainManagedSavePath(priv, dom); +if (!name) +goto cleanup; + +ret = unlink(name); +VIR_FREE(name); + +cleanup: +return ret; +} + static int xenUnifiedDomainRestoreFlags(virConnectPtr conn, const char *from, const char *dxml, unsigned int flags) @@ -1504,16 +1591,33 @@ static int
[libvirt] [PATCH 0/2] Last two coverity patches
tools/virsh-pool.c: CHECKED_RETURN src/nwfilter/nwfilter_driver.c: UNREACHABLE Ján Tomko (2): virsh: check the return value of virStoragePoolGetAutostart nwfilter: fix error handling src/nwfilter/nwfilter_driver.c | 11 +-- tools/virsh-pool.c |5 + 2 files changed, 6 insertions(+), 10 deletions(-) -- 1.7.8.6 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 1/2] virsh: check the return value of virStoragePoolGetAutostart
On error, virStoragePoolGetAutostart would return -1 leaving autostart untouched. Removed the misleading debug message as well. Error: CHECKED_RETURN (CWE-252): libvirt-0.10.2/tools/virsh-pool.c:1386: unchecked_value: No check of the return value of virStoragePoolGetAutostart(pool, autostart). --- tools/virsh-pool.c |5 + 1 files changed, 1 insertions(+), 4 deletions(-) diff --git a/tools/virsh-pool.c b/tools/virsh-pool.c index c08cce6..5fee2cd 100644 --- a/tools/virsh-pool.c +++ b/tools/virsh-pool.c @@ -1383,10 +1383,7 @@ cmdPoolInfo(vshControl *ctl, const vshCmd *cmd) vshPrint(ctl, %-15s %s\n, _(Persistent:), persistent ? _(yes) : _(no)); /* Check and display whether the pool is autostarted or not */ -virStoragePoolGetAutostart(pool, autostart); -vshDebug(ctl, VSH_ERR_DEBUG, Pool autostart flag value: %d\n, - autostart); -if (autostart 0) +if (virStoragePoolGetAutostart(pool, autostart) 0) vshPrint(ctl, %-15s %s\n, _(Autostart:), _(no autostart)); else vshPrint(ctl, %-15s %s\n, _(Autostart:), autostart ? _(yes) : _(no)); -- 1.7.8.6 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 2/2] nwfilter: fix error handling
Commit 4efde75f introduced a return in the cleanup path and removed virNWFilterConfLayerShutdown. Found by coverity: Error: UNREACHABLE (CWE-561): libvirt-0.10.2/src/nwfilter/nwfilter_driver.c:259: unreachable: This code cannot be reached: nwfilterDriverUnlock(driver --- I wonder if the if (!privileged) check should be moved before driverState allocation? --- src/nwfilter/nwfilter_driver.c | 11 +-- 1 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/nwfilter/nwfilter_driver.c b/src/nwfilter/nwfilter_driver.c index a0ee4f1..cd185e2 100644 --- a/src/nwfilter/nwfilter_driver.c +++ b/src/nwfilter/nwfilter_driver.c @@ -174,8 +174,10 @@ nwfilterDriverStartup(bool privileged) sysbus = virDBusGetSystemBus(); #endif /* HAVE_DBUS */ -if (VIR_ALLOC(driverState) 0) -goto alloc_err_exit; +if (VIR_ALLOC(driverState) 0) { +virReportOOMError(); +return -1; +} if (virMutexInit(driverState-lock) 0) goto err_free_driverstate; @@ -247,10 +249,7 @@ error: nwfilterDriverUnlock(driverState); nwfilterDriverShutdown(); -alloc_err_exit: -return -1; - -nwfilterDriverUnlock(driverState); +virNWFilterConfLayerShutdown(); err_techdrivers_shutdown: virNWFilterTechDriversShutdown(); -- 1.7.8.6 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v1 01/11] bandwidth: add new 'floor' attribute
On 11/19/2012 11:51 AM, Michal Privoznik wrote: This is however supported only on domain interfaces with type='network'. Moreover, target network needs to have at least inbound QoS set. This is required by hierarchical traffic shaping. From now on, the required attribute for inbound/ is either 'average' (old) or 'floor' (new). This new attribute can be used just for interfaces type of network (interface type='network'/) currently. --- docs/formatdomain.html.in| 20 -- docs/schemas/networkcommon.rng |5 +++ src/conf/domain_conf.c |6 +++- src/conf/netdev_bandwidth_conf.c | 54 +- src/conf/netdev_bandwidth_conf.h |3 +- src/conf/network_conf.c |4 +- src/util/virnetdevbandwidth.h|1 + 7 files changed, 78 insertions(+), 15 deletions(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index c8da33d..da8184a 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -3047,7 +3047,7 @@ qemu-kvm -net nic,model=? /dev/null lt;source network='default'/gt; lt;target dev='vnet0'/gt; blt;bandwidthgt; -lt;inbound average='1000' peak='5000' burst='1024'/gt; +lt;inbound average='1000' peak='5000' floor='200' burst='1024'/gt; lt;outbound average='128' peak='256' burst='256'/gt; lt;/bandwidthgt;/b lt;/interfacegt; @@ -3062,14 +3062,28 @@ qemu-kvm -net nic,model=? /dev/null children element out result in no QoS applied on that traffic direction. So, when you want to shape only domain's incoming traffic, use codeinbound/code only, and vice versa. Each of these elements have one - mandatory attribute codeaverage/code. It specifies average bit rate on + mandatory attribute codeaverage/code (or codefloor/code as + described below). It specifies average bit rate on s|It|codeaverage/code| interface being shaped. Then there are two optional attributes: *the* interface being shaped codepeak/code, which specifies maximum rate at which interface can send data, and codeburst/code, amount of bytes that can be burst at codepeak/code speed. Accepted values for attributes are integer numbers. The units for codeaverage/code and codepeak/code attributes are kilobytes per second, and for the codeburst/code just kilobytes. - span class=sinceSince 0.9.4/span + span class=sinceSince 0.9.4/span The codeinbound/code can + optionally have codefloor/code attribute. This is there for + guaranteeing minimal throughput for shaped interfaces. This, however, + requires that all traffic goes through one point where QoS decisions can + take place. That's why this attribute works only for virtual networks for + now (that is codelt;interface type='network'/gt;/code. with a forward type of route, nat, or no forward at all (i.e. forward type can't be 'bridge' or 'hostdev') Moreover, the + virtual network the interface is connected to is required to have at least + inbound Qos set (codeaverage/code at least). Moreover, with + codefloorcode attribute users don't need to specify + codeaverage/code. However, codepeak/code and codeburst/code + attributes still require codeaverage/code. Currently, linux kernel + doesn't allow egress qdiscs to have any classes therefore + codefloor/code can be applied only on codeinbound/code and not + /codeoutbound/code. span class=sinceSince 1.0.1/span /p h5a name=elementVlanTagSetting VLAN tag (on supported network types only)/a/h5 diff --git a/docs/schemas/networkcommon.rng b/docs/schemas/networkcommon.rng index c7749e7..51ff759 100644 --- a/docs/schemas/networkcommon.rng +++ b/docs/schemas/networkcommon.rng @@ -149,6 +149,11 @@ /attribute /optional optional + attribute name=floor +ref name=speed/ + /attribute +/optional +optional attribute name='burst' ref name=BurstSize/ /attribute diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 99f03a9..bf23b77 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -4742,7 +4742,8 @@ virDomainActualNetDefParseXML(xmlNodePtr node, bandwidth_node = virXPathNode(./bandwidth, ctxt); if (bandwidth_node -!(actual-bandwidth = virNetDevBandwidthParse(bandwidth_node))) +!(actual-bandwidth = virNetDevBandwidthParse(bandwidth_node, + actual-type))) goto error; vlanNode = virXPathNode(./vlan, ctxt); @@ -4930,7 +4931,8 @@ virDomainNetDefParseXML(virCapsPtr caps, goto error; } } else if (xmlStrEqual(cur-name, BAD_CAST bandwidth)) { -if (!(def-bandwidth =
Re: [libvirt] [PATCH 1/2] virsh: check the return value of virStoragePoolGetAutostart
On 11/30/12 13:09, Ján Tomko wrote: On error, virStoragePoolGetAutostart would return -1 leaving autostart untouched. Removed the misleading debug message as well. Error: CHECKED_RETURN (CWE-252): libvirt-0.10.2/tools/virsh-pool.c:1386: unchecked_value: No check of the return value of virStoragePoolGetAutostart(pool, autostart). --- tools/virsh-pool.c |5 + 1 files changed, 1 insertions(+), 4 deletions(-) ACK. Peter -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 2/2] nwfilter: fix error handling
On 11/30/12 13:09, Ján Tomko wrote: Commit 4efde75f introduced a return in the cleanup path and removed virNWFilterConfLayerShutdown. Found by coverity: Error: UNREACHABLE (CWE-561): libvirt-0.10.2/src/nwfilter/nwfilter_driver.c:259: unreachable: This code cannot be reached: nwfilterDriverUnlock(driver --- I wonder if the if (!privileged) check should be moved before driverState allocation? --- src/nwfilter/nwfilter_driver.c | 11 +-- 1 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/nwfilter/nwfilter_driver.c b/src/nwfilter/nwfilter_driver.c index a0ee4f1..cd185e2 100644 --- a/src/nwfilter/nwfilter_driver.c +++ b/src/nwfilter/nwfilter_driver.c @@ -174,8 +174,10 @@ nwfilterDriverStartup(bool privileged) sysbus = virDBusGetSystemBus(); #endif /* HAVE_DBUS */ -if (VIR_ALLOC(driverState) 0) -goto alloc_err_exit; +if (VIR_ALLOC(driverState) 0) { +virReportOOMError(); +return -1; +} if (virMutexInit(driverState-lock) 0) goto err_free_driverstate; @@ -247,10 +249,7 @@ error: nwfilterDriverUnlock(driverState); nwfilterDriverShutdown(); -alloc_err_exit: -return -1; When you remove this hunk you cause any jump to the error label to fall through all of the following labeled error cleanup sections. Those sections are also called in nwfilterDriverShutdown(). I'm wondering if the functions are safe to call even if the driver wasn't initialized completely. In that case we might be just calling nwfilterDriverShutdown() and get rid of the cleanup labels. If we're not allowed to do that, the return statement has to stay there. - -nwfilterDriverUnlock(driverState); +virNWFilterConfLayerShutdown(); err_techdrivers_shutdown: virNWFilterTechDriversShutdown(); -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v1 01/11] bandwidth: add new 'floor' attribute
On 11/19/2012 11:51 AM, Michal Privoznik wrote: This is however supported only on domain interfaces with type='network'. Moreover, target network needs to have at least inbound QoS set. This is required by hierarchical traffic shaping. From now on, the required attribute for inbound/ is either 'average' (old) or 'floor' (new). This new attribute can be used just for interfaces type of network (interface type='network'/) currently. Another thing that I just thought of - this patch needs to update virNetdevBandwidthEqual to check floor, otherwise qemuNetChange won't properly detect when bandwidth is changed (btw, a small patch to do the right thing when that happens (similar to the patch I recently sent to support changing filters) would be really nice :-) -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 2/2] nwfilter: fix error handling
On 11/30/12 13:51, Peter Krempa wrote: On 11/30/12 13:09, Ján Tomko wrote: Commit 4efde75f introduced a return in the cleanup path and removed virNWFilterConfLayerShutdown. Found by coverity: Error: UNREACHABLE (CWE-561): libvirt-0.10.2/src/nwfilter/nwfilter_driver.c:259: unreachable: This code cannot be reached: nwfilterDriverUnlock(driver --- I wonder if the if (!privileged) check should be moved before driverState allocation? --- src/nwfilter/nwfilter_driver.c | 11 +-- 1 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/nwfilter/nwfilter_driver.c b/src/nwfilter/nwfilter_driver.c index a0ee4f1..cd185e2 100644 --- a/src/nwfilter/nwfilter_driver.c +++ b/src/nwfilter/nwfilter_driver.c @@ -174,8 +174,10 @@ nwfilterDriverStartup(bool privileged) sysbus = virDBusGetSystemBus(); #endif /* HAVE_DBUS */ -if (VIR_ALLOC(driverState) 0) -goto alloc_err_exit; +if (VIR_ALLOC(driverState) 0) { +virReportOOMError(); +return -1; +} if (virMutexInit(driverState-lock) 0) goto err_free_driverstate; @@ -247,10 +249,7 @@ error: nwfilterDriverUnlock(driverState); nwfilterDriverShutdown(); -alloc_err_exit: -return -1; When you remove this hunk you cause any jump to the error label to fall through all of the following labeled error cleanup sections. Those sections are also called in nwfilterDriverShutdown(). I'm wondering if the functions are safe to call even if the driver wasn't initialized completely. In that case we might be just calling nwfilterDriverShutdown() and get rid of the cleanup labels. If we're not allowed to do that, the return statement has to stay there. virNWFilterDHCPSnoopShutdown(void) doesn't look that it can be called without being initialized first, so you will need to either have to fix virNWFilterDHCPSnoopShutdown and make sure that other are callable even when not initialized, or you need to exit from the function at the point the label was before. - -nwfilterDriverUnlock(driverState); +virNWFilterConfLayerShutdown(); err_techdrivers_shutdown: virNWFilterTechDriversShutdown(); -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] storage: fix scsi detach regression with cgroup ACLs
On Thu, Nov 29, 2012 at 14:48:41 -0700, Eric Blake wrote: https://bugzilla.redhat.com/show_bug.cgi?id=876828 Commit 38c4a9cc introduced a regression in hot unplugging of disks from qemu, where cgroup device ACLs were no longer being revoked (thankfully not a security hole: cgroup ACLs only prevent open() of the disk; so reverting the ACL prevents future abuse but doesn't stop abuse from an fd that was already opened before the ACL change). Commit 1b2ebf95 overlooked that there were two spots affected. * src/qemu/qemu_hotplug.c (qemuDomainDetachDiskDevice): Transfer backing chain before deletion. * src/qemu/qemu_driver.c (qemuDomainDetachDeviceDiskLive): Fix spacing (partly to ensure a different-looking patch). --- I blame git for letting me find this - I did a 'pull --rebase' on top of libvirt.git, and noticed that my working patch was still on the tree - it turns out that the hunk for qemu_hotplug.c is _identical_ except for the context of the function name needing a fix. I still wish git would be more vocal when it finds an alternate place to apply a patch when function names don't match. ACK Jirka -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] problems with current libvirt and qemu-kvm
On 11/30/2012 03:24 AM, Daniel P. Berrange wrote: On Thu, Nov 29, 2012 at 03:48:52PM -0500, Gene Czarcinski wrote: When I rebased my DHCPv6, etc. patches, I did that not only on to of Laine Stump's dnsmasq-capabiliotes/bind-dynamic updates but I also rebased to current git master. Well, the problem with the large number/frequent RTR-ADVERT syslog messages from dnsmasq that I had previously seen were fixed ... they stopped and dnsmasq produced expected results. But, starting virt-manager hung and there were new error messages in syslog about internal error cannot find suitable emulator for X86_64. Until I pushed the patches from Victor yesterday, libvirt GIT was broken when used against QEMU GIT. The effect was that libvirt could not detect any QEMU binaries. So if you're using latest QEMU GIT that might be what you've hit. No, not the latest ... qemu-1.0.1-2.fc17. But, this problem is getting more than a bit strange. I have two systems which are pretty near identical (one id AMD-6-core and the other is AMD-8-core). They have the same kernel, the same libvirt, qemu, virt-manager, kernel, dnsmasq. The problem system only has the RTR-ADVERT problem with one network definition! [IPv4 with DHCP and IPv6 with SLAAC]. Destroy that network and start another with different addresses but the same specification and no problems. The is one difference I need to check ... the problem network is autostarted. I just installed the libvirt version that has a problem with qemu. I did not bother trying virt-manage since I just noticed a bunch of really strange syslog messages from libvirtd unknown OS type hvm so I downgraded back to something that works. The last update I have listed in the git-log is b7aba48bcaf315c27430a7d0edf8ff702d293527 and that one changed src/conf/domain_conf.c. I am going to give two things a try: 1. Back off the top few commits that hist domain stuff and 2. Try do a pull to update my copy of libvirt's git. About the only thing I am sure of is I believe that the three patches I submitted and Laine's three patches for bind-dynamic are not the problem ... they are also applied to the version that works and only deal with network stuff. Gene -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 1/3] Add APIs for talking to init via /dev/initctl
On Thu, Nov 29, 2012 at 01:16:09PM -0500, Eric Blake wrote: To be able todo controlled shutdown/reboot of containers an s/todo/to do/ API to talk to init via /dev/initctl is required. Fortunately this is quite straightforward to implement, and is supported by both sysvinit and systemd. Upstart support for /dev/initctl is unclear. +++ b/src/util/virinitctl.c @@ -0,0 +1,161 @@ + +/* These constants struct definitions are taken from + * systemd, under terms of LGPLv2+ + * + * initreq.hInterface to talk to init through /dev/initctl. + * + * Copyright (C) 1995-2004 Miquel van Smoorenburg + */ Thankfully, compatible with our usage. + +#if defined(__FreeBSD_kernel__) +# define VIR_INITCTL_FIFO /etc/.initctl +#else +# define VIR_INITCTL_FIFO /dev/initctl +#endif + +#define VIR_INITCTL_MAGIC 0x03091969 Wonder if the original author of this code picked a birthdate. Gotta love the Easter eggs present in open source software :) + +/* + * Because of legacy interfaces, runlevel and sleeptime + * aren't in a separate struct in the union. + * + * The weird sizes are because init expects the whole + * struct to be 384 bytes. + */ +struct virInitctlRequest { +int magic; /* Magic number */ 'int' is not necessarily 4 bytes; I would feel slightly more comfortable had upstream used int32_t. I know you are just copying code from an existing header (so don't change the struct itself), but wonder if we should at least add our own sanity checking: verify(sizeof(virInitctlRequest)) == 384); I'm just adding the verify, since I think that's the more important thing todo. + +if ((fd = open(path, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) 0) O_NDELAY is non-standard. I would spell it according to POSIX as O_NONBLOCK. Yep, good point. +typedef enum virInitctlRunLevel virInitctlRunLevel; +enum virInitctlRunLevel { +VIR_INITCTL_RUNLEVEL_POWEROFF = 0, +VIR_INITCTL_RUNLEVEL_1 = 1, +VIR_INITCTL_RUNLEVEL_2 = 2, +VIR_INITCTL_RUNLEVEL_3 = 3, +VIR_INITCTL_RUNLEVEL_4 = 4, +VIR_INITCTL_RUNLEVEL_5 = 5, +VIR_INITCTL_RUNLEVEL_REBOOT = 6, Should you add VIR_INITCTL_RUNLEVEL_LAST, in case we ever expand this list? Unlikely, but doesn't hurt to have a sentinal Daniel -- |: http://berrange.com -o-http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 2/3] Introduce two new methods for triggering controlled shutdown/reboot
On Thu, Nov 29, 2012 at 01:27:26PM -0500, Eric Blake wrote: The virDomainShutdownFlags and virDomainReboot APIs allow the caller to request the operation is implemented via either acpi button press or a guest agent. For containers, a couple of other methods make sense, a message to /dev/initctl, and direct kill(SIGTERM|HUP) of the container init process. Indeed - this is a nice way to tie in your earlier patches. Signed-off-by: Daniel P. Berrange berra...@redhat.com --- include/libvirt/libvirt.h.in | 4 tools/virsh-domain.c | 18 ++ 2 files changed, 18 insertions(+), 4 deletions(-) Alas, you are missing documentation of the new flags in src/libvirt.c (not that the existing flags were documented there yet), Well the docs refer to the corresponding enum, whcih will be included in the docs with its descriptions. So isn't that better than duplicating the enum descriptions again. as well as missing an update to this portion of libvirt.c:virDomainShutdownFlags() (and its reboot counterpart): /* At most one of these two flags should be set. */ if ((flags VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN) (flags VIR_DOMAIN_SHUTDOWN_GUEST_AGENT)) { virReportInvalidArg(flags, %s, _(flags for acpi power button and guest agent are mutually exclusive)); goto error; } That should be updated to check that now at most one of the four flags are present. IMHO that is a bogus check that should be deleted. Though the QEMU driver might not implement it, it seems perfectly valid to ask the driver to try multiple methods - after all it is able todo that by default. Sure you can't specify ordering, but that's fine. Daniel -- |: http://berrange.com -o-http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 3/3] Add support for shutdown / reboot APIs in LXC driver
On Thu, Nov 29, 2012 at 01:39:34PM -0500, Eric Blake wrote: Add support for doing controlled shutdown / reboot in the LXC driver. The default behaviour is to try talking to /dev/initctl inside the container's virtual root (/proc/$INITPID/root). This works with sysvinit or systemd. If that file does not exist then send SIGTERM (for shutdown) or SIGHUP (for reboot). These signals are not any kind of particular standard for shutdown or reboot, just something apps can choose to handle. The new virDomainSendProcessSignal allows for sending custom signals. We might allow the choice of SIGTERM/HUP to be configured for LXC containers via the XML in the future. Maybe even via new attributes or sub-elements of the existing on_reboot XML. + +if (flags == 0 || +(flags VIR_DOMAIN_SHUTDOWN_INITCTL)) { +if ((rc = virInitctlSetRunLevel(VIR_INITCTL_RUNLEVEL_POWEROFF, +vroot)) 0) { +goto cleanup; +} +if (rc == 0 flags != 0 Based on libvirt.c (well, if you follow my advice in 2/3 about enforcing the mutual exclusion between the four explicit shutdown methods), if 'flags != 0', then we are guaranteed that 'flags == VIR_DOMAIN_SHUTDOWN_INITCTL)' at this point... +((flags ~VIR_DOMAIN_SHUTDOWN_INITCTL) == 0)) { ...which means this leg of the conditional is always true. Or is your intent to allow the user to specify multiple flags rather than enforcing mutual exclusion between the flags? And if so, you need to fix libvirt.c to drop the mutual exclusion, as well as to document that when multiple flags are specified, it is up to the hypervisor which method is attempted first. Yep, I think allowing multiple flags is fine at the API level. I'd do that as a followup commit since it doesn't affect this, only the existing QEMU code. Daniel -- |: http://berrange.com -o-http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH] Move reboot/shutdown flags combination check into QEMU driver
From: Daniel P. Berrange berra...@redhat.com The fact that only the guest agent, or ACPI flag can be used when requesting reboot/shutdown is merely a limitation of the QEMU driver impl at this time. Thus it should not be in libvirt.c code Signed-off-by: Daniel P. Berrange berra...@redhat.com --- src/libvirt.c | 16 src/qemu/qemu_driver.c | 16 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/libvirt.c b/src/libvirt.c index 757bfa8..d5310ed 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -3260,14 +3260,6 @@ virDomainShutdownFlags(virDomainPtr domain, unsigned int flags) goto error; } -/* At most one of these two flags should be set. */ -if ((flags VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN) -(flags VIR_DOMAIN_SHUTDOWN_GUEST_AGENT)) { -virReportInvalidArg(flags, %s, -_(flags for acpi power button and guest agent are mutually exclusive)); -goto error; -} - conn = domain-conn; if (conn-driver-domainShutdownFlags) { @@ -3322,14 +3314,6 @@ virDomainReboot(virDomainPtr domain, unsigned int flags) goto error; } -/* At most one of these two flags should be set. */ -if ((flags VIR_DOMAIN_REBOOT_ACPI_POWER_BTN) -(flags VIR_DOMAIN_REBOOT_GUEST_AGENT)) { -virReportInvalidArg(flags, %s, -_(flags for acpi power button and guest agent are mutually exclusive)); -goto error; -} - conn = domain-conn; if (conn-driver-domainReboot) { diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index c37bdb9..6a8a333 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -1814,6 +1814,14 @@ static int qemuDomainShutdownFlags(virDomainPtr dom, unsigned int flags) { virCheckFlags(VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN | VIR_DOMAIN_SHUTDOWN_GUEST_AGENT, -1); +/* At most one of these two flags should be set. */ +if ((flags VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN) +(flags VIR_DOMAIN_SHUTDOWN_GUEST_AGENT)) { +virReportInvalidArg(flags, %s, +_(flags for acpi power button and guest agent are mutually exclusive)); +return -1; +} + qemuDriverLock(driver); vm = virDomainFindByUUID(driver-domains, dom-uuid); qemuDriverUnlock(driver); @@ -1896,6 +1904,14 @@ qemuDomainReboot(virDomainPtr dom, unsigned int flags) virCheckFlags(VIR_DOMAIN_REBOOT_ACPI_POWER_BTN | VIR_DOMAIN_REBOOT_GUEST_AGENT , -1); +/* At most one of these two flags should be set. */ +if ((flags VIR_DOMAIN_REBOOT_ACPI_POWER_BTN) +(flags VIR_DOMAIN_REBOOT_GUEST_AGENT)) { +virReportInvalidArg(flags, %s, +_(flags for acpi power button and guest agent are mutually exclusive)); +return -1; +} + qemuDriverLock(driver); vm = virDomainFindByUUID(driver-domains, dom-uuid); qemuDriverUnlock(driver); -- 1.7.11.7 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH] nwfilter: report an error on OOM
Also removed some unreachable code found by coverity: libvirt-0.10.2/src/nwfilter/nwfilter_driver.c:259: unreachable: This code cannot be reached: nwfilterDriverUnlock(driver --- diff to v1: don't break everything src/nwfilter/nwfilter_driver.c |9 - 1 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/nwfilter/nwfilter_driver.c b/src/nwfilter/nwfilter_driver.c index a0ee4f1..cff384e 100644 --- a/src/nwfilter/nwfilter_driver.c +++ b/src/nwfilter/nwfilter_driver.c @@ -174,8 +174,10 @@ nwfilterDriverStartup(bool privileged) sysbus = virDBusGetSystemBus(); #endif /* HAVE_DBUS */ -if (VIR_ALLOC(driverState) 0) -goto alloc_err_exit; +if (VIR_ALLOC(driverState) 0) { +virReportOOMError(); +return -1; +} if (virMutexInit(driverState-lock) 0) goto err_free_driverstate; @@ -247,11 +249,8 @@ error: nwfilterDriverUnlock(driverState); nwfilterDriverShutdown(); -alloc_err_exit: return -1; -nwfilterDriverUnlock(driverState); - err_techdrivers_shutdown: virNWFilterTechDriversShutdown(); virNWFilterDHCPSnoopShutdown(); -- 1.7.8.6 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] Move reboot/shutdown flags combination check into QEMU driver
The fact that only the guest agent, or ACPI flag can be used when requesting reboot/shutdown is merely a limitation of the QEMU driver impl at this time. Thus it should not be in libvirt.c code Signed-off-by: Daniel P. Berrange berra...@redhat.com --- src/libvirt.c | 16 src/qemu/qemu_driver.c | 16 2 files changed, 16 insertions(+), 16 deletions(-) ACK. Problem. Now our virsh command doesn't have full expression of the possible API usage. You need to modify 'virsh shutdown --mode=...' so that --mode can now take a comma-separated list of modes to combine, rather than only being able to select a single mode, if you want to be able to stress-test the full power of the API. -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] Move reboot/shutdown flags combination check into QEMU driver
On Fri, Nov 30, 2012 at 09:12:44AM -0500, Eric Blake wrote: The fact that only the guest agent, or ACPI flag can be used when requesting reboot/shutdown is merely a limitation of the QEMU driver impl at this time. Thus it should not be in libvirt.c code Signed-off-by: Daniel P. Berrange berra...@redhat.com --- src/libvirt.c | 16 src/qemu/qemu_driver.c | 16 2 files changed, 16 insertions(+), 16 deletions(-) ACK. Problem. Now our virsh command doesn't have full expression of the possible API usage. You need to modify 'virsh shutdown --mode=...' so that --mode can now take a comma-separated list of modes to combine, rather than only being able to select a single mode, if you want to be able to stress-test the full power of the API. Ok, will send another patch todo that too Daniel -- |: http://berrange.com -o-http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] Move reboot/shutdown flags combination check into QEMU driver
The fact that only the guest agent, or ACPI flag can be used when requesting reboot/shutdown is merely a limitation of the QEMU driver impl at this time. Thus it should not be in libvirt.c code Signed-off-by: Daniel P. Berrange berra...@redhat.com --- src/libvirt.c | 16 src/qemu/qemu_driver.c | 16 2 files changed, 16 insertions(+), 16 deletions(-) ACK. -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] problems with current libvirt and qemu-kvm
On 11/30/2012 08:19 AM, Gene Czarcinski wrote: On 11/30/2012 03:24 AM, Daniel P. Berrange wrote: On Thu, Nov 29, 2012 at 03:48:52PM -0500, Gene Czarcinski wrote: When I rebased my DHCPv6, etc. patches, I did that not only on to of Laine Stump's dnsmasq-capabiliotes/bind-dynamic updates but I also rebased to current git master. Well, the problem with the large number/frequent RTR-ADVERT syslog messages from dnsmasq that I had previously seen were fixed ... they stopped and dnsmasq produced expected results. But, starting virt-manager hung and there were new error messages in syslog about internal error cannot find suitable emulator for X86_64. Until I pushed the patches from Victor yesterday, libvirt GIT was broken when used against QEMU GIT. The effect was that libvirt could not detect any QEMU binaries. So if you're using latest QEMU GIT that might be what you've hit. No, not the latest ... qemu-1.0.1-2.fc17. But, this problem is getting more than a bit strange. I have two systems which are pretty near identical (one id AMD-6-core and the other is AMD-8-core). They have the same kernel, the same libvirt, qemu, virt-manager, kernel, dnsmasq. The problem system only has the RTR-ADVERT problem with one network definition! [IPv4 with DHCP and IPv6 with SLAAC]. Destroy that network and start another with different addresses but the same specification and no problems. The is one difference I need to check ... the problem network is autostarted. I just installed the libvirt version that has a problem with qemu. I did not bother trying virt-manage since I just noticed a bunch of really strange syslog messages from libvirtd unknown OS type hvm so I downgraded back to something that works. The last update I have listed in the git-log is b7aba48bcaf315c27430a7d0edf8ff702d293527 and that one changed src/conf/domain_conf.c. I am going to give two things a try: 1. Back off the top few commits that hist domain stuff and 2. Try do a pull to update my copy of libvirt's git. About the only thing I am sure of is I believe that the three patches I submitted and Laine's three patches for bind-dynamic are not the problem ... they are also applied to the version that works and only deal with network stuff. Gene That was fun. Good news! I did a pull to get my clone up to date, saw that Laine's updates had been pushed, rebased my updates, created a tarball and used it to build a set of libvirt rpms. Installed the updated rpms and ... everything seems to work again! I must have caught something in the middle when I did my last pull because it is fine now. And, the RTR-ADVERT messages (and associated issuing of RA packets) is back to normal ... an initial flurry and then slowing to one every none/ten minutes. However, I have noticed one thing. Simon Kelley had me add a little instrumentation to dnsmasq trying to pursue this large number of RTR-ADVERT messages. I am going to do a little more instrumentation. What I have noticed is that there seems to be a broadcast of something whenever a network is started so that all dnsmasq instances (one per started network) go into flurry mode with issuing RA packets and syslog messages. Does anyone know if something in libvirt is doing that? BTW, I will shortly be sending in a small rebase of my patches based on today's git. Gene -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] nwfilter: report an error on OOM
On 11/30/12 15:07, Ján Tomko wrote: Also removed some unreachable code found by coverity: libvirt-0.10.2/src/nwfilter/nwfilter_driver.c:259: unreachable: This code cannot be reached: nwfilterDriverUnlock(driver --- diff to v1: don't break everything src/nwfilter/nwfilter_driver.c |9 - 1 files changed, 4 insertions(+), 5 deletions(-) ACK. Peter -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 0/2] Last two coverity patches
On 11/30/12 13:09, Ján Tomko wrote: tools/virsh-pool.c: CHECKED_RETURN src/nwfilter/nwfilter_driver.c: UNREACHABLE Ján Tomko (2): virsh: check the return value of virStoragePoolGetAutostart nwfilter: fix error handling src/nwfilter/nwfilter_driver.c | 11 +-- tools/virsh-pool.c |5 + 2 files changed, 6 insertions(+), 10 deletions(-) Series pushed. Peter -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] Next release planning
Reminder, we are shooting for 1.0.1 release by mid December. I will be away next week and probably out of reach, and it looks unlikely i will have the bandwidth to start the freeze before Monday 10 possibly Tuesday 11. So there is a bit more than a week to push API and features for 1.0.1. Then 1.0.2 will occur at the end of January. Daniel -- Daniel Veillard | Open Source and Standards, Red Hat veill...@redhat.com | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ http://veillard.com/ | virtualization library http://libvirt.org/ -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCHv2 1/3] v1: allow guest to guest IPv6 without gateway definition
This patch adds the capability for virtual guests to do IPv6 communication via a virtual network interface with no IPv6 (gateway) addresses specified. This capability currently exists for IPv4. This patch allows creation of a completely isolated IPv6 network. Note that virtual guests cannot communication with the virtualization host via this interface. Also note that: net.ipv6.conf.interface_name.disable_ipv6 = 1 Also not that starting libvirtd has set the following: net.bridge.bridge-nf-call-arptables = 1 net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 although /etc/syslog.conf has them all set to 0. Note: If it is desired to control this behavior by having something like ipv6='yes' on the network statement, then this should also be done for ipv4. --- docs/formatnetwork.html.in | 18 ++ src/network/bridge_driver.c | 22 ++ 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/docs/formatnetwork.html.in b/docs/formatnetwork.html.in index 49206dd..7b3b25c 100644 --- a/docs/formatnetwork.html.in +++ b/docs/formatnetwork.html.in @@ -773,5 +773,23 @@ lt;/forwardgt; lt;/networkgt;/pre +h3a name=examplesNoGatewayNetwork config with no gateway addresses/a/h3 + +p +A valid network definition can contain no IPv4 or IPv6 addresses. Such a definition +can be used for a very private or very isolated network since it will not be +possible to communicate with the virtualization host via this network. However, +this virtual network interface can be used for communication between virtual guest +systems. This works for IPv4 and span class=since(Since 1.0.1)/span IPv6. +/p + +pre + lt;networkgt; +lt;namegt;nogwlt;/namegt; +lt;uuidgt;7a3b7497-1ec7-8aef-6d5c-38dff9109e93lt;/uuidgt; +lt;bridge name=virbr2 stp=on delay=0 /gt; +lt;mac address='00:16:3E:5D:C7:9E'/gt; + lt;/networkgt;/pre + /body /html diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 75f3c3a..0fdb635 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -1617,15 +1617,16 @@ networkRemoveRoutingIptablesRules(struct network_driver *driver, } } -/* Add all once/network rules required for IPv6 (if any IPv6 addresses are defined) */ +/* Add all once/network rules required for IPv6. + * Even if no IPv6 addresses are defined, allow IPv6 commuinications + * between virtual systems. If any IPv6 addresses are defined, then + * add the rules for regular operation. + */ static int networkAddGeneralIp6tablesRules(struct network_driver *driver, virNetworkObjPtr network) { -if (!virNetworkDefGetIpByIndex(network-def, AF_INET6, 0)) -return 0; - /* Catch all rules to block forwarding to/from bridges */ if (iptablesAddForwardRejectOut(driver-iptables, AF_INET6, @@ -1653,6 +1654,10 @@ networkAddGeneralIp6tablesRules(struct network_driver *driver, goto err3; } +/* if no IPv6 addresses are defined, we are done. */ +if (!virNetworkDefGetIpByIndex(network-def, AF_INET6, 0)) +return 0; + /* allow DNS over IPv6 */ if (iptablesAddTcpInput(driver-iptables, AF_INET6, network-def-bridge, 53) 0) { @@ -1689,11 +1694,12 @@ static void networkRemoveGeneralIp6tablesRules(struct network_driver *driver, virNetworkObjPtr network) { -if (!virNetworkDefGetIpByIndex(network-def, AF_INET6, 0)) -return; +if (virNetworkDefGetIpByIndex(network-def, AF_INET6, 0)) { +iptablesRemoveUdpInput(driver-iptables, AF_INET6, network-def-bridge, 53); +iptablesRemoveTcpInput(driver-iptables, AF_INET6, network-def-bridge, 53); +} -iptablesRemoveUdpInput(driver-iptables, AF_INET6, network-def-bridge, 53); -iptablesRemoveTcpInput(driver-iptables, AF_INET6, network-def-bridge, 53); +/* the following rules are there even if no IPv6 address has been defined */ iptablesRemoveForwardAllowCross(driver-iptables, AF_INET6, network-def-bridge); iptablesRemoveForwardRejectIn(driver-iptables, AF_INET6, network-def-bridge); iptablesRemoveForwardRejectOut(driver-iptables, AF_INET6, network-def-bridge); -- 1.7.11.7 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCHv2 3/3] v7.9: put dnsmasq parameters into conf-file
This patch changes how parameters are passed to dnsmasq. Instead of being on the command line, the parameters are put into a file (one parameter per line) and a commandline --conf-file= specifies the location of the file. The file is located in the same directory as the leases file. This also adds the dnsmasq parameter interface=net-name Putting the dnsmasq parameters into a configuration file allows them to be examined and more easily understood than examining the command lines displayed by ps ax. This is especially true when a number of networks have been started. I suspect that when the use of dnsmasq was originally done, the command line was simple but has gotten more complicated over time and will likely become even more complicated in the future. I believe that if use of dnsmasq was done today with the current requirements for dnsmasq, a configuration file would have been used. Many (most?) daemons use configuration files as oppose to large number of command line parameters. One potential addition to dnsmasq parameters is to specify the reverse-lookup queries which are not to be passed on up the chain. For IPv4, such queries are rather simple and take the form: ipv4_address.in-addr.arpa but ipv6 queries involve a lot longer specification. The IPv6 query will be of the form: ipv6_address.ip6.arpa where the above query expands to a 44 character string which is specified by --local=/ipv6_address.ip6.arpa/ which is certainly a lot of clutter to add to the command line. --- src/network/bridge_driver.c| 190 + src/network/bridge_driver.h| 7 +- tests/networkxml2argvdata/dhcp6-nat-network.argv | 29 ++-- tests/networkxml2argvdata/dhcp6-network.argv | 29 ++-- .../dhcp6host-routed-network.argv | 25 ++- tests/networkxml2argvdata/isolated-network.argv| 31 ++-- .../networkxml2argvdata/nat-network-dns-hosts.argv | 19 +-- .../nat-network-dns-srv-record-minimal.argv| 37 ++-- .../nat-network-dns-srv-record.argv| 27 ++- .../nat-network-dns-txt-record.argv| 26 +-- tests/networkxml2argvdata/nat-network.argv | 29 ++-- tests/networkxml2argvdata/netboot-network.argv | 37 ++-- .../networkxml2argvdata/netboot-proxy-network.argv | 33 ++-- tests/networkxml2argvdata/routed-network.argv | 15 +- tests/networkxml2argvtest.c| 40 + 15 files changed, 286 insertions(+), 288 deletions(-) diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 0128fba..a8f6d8e 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -142,6 +142,16 @@ networkDnsmasqLeaseFileNameFunc networkDnsmasqLeaseFileName = networkDnsmasqLeaseFileNameDefault; static char * +networkDnsmasqConfigFileName(const char *netname) +{ +char *conffile; + +ignore_value(virAsprintf(conffile, DNSMASQ_STATE_DIR /%s.conf, + netname)); +return conffile; +} + +static char * networkRadvdPidfileBasename(const char *netname) { /* this is simple but we want to be sure it's consistently done */ @@ -168,6 +178,7 @@ networkRemoveInactive(struct network_driver *driver, { char *leasefile = NULL; char *radvdconfigfile = NULL; +char *configfile = NULL; char *radvdpidbase = NULL; dnsmasqContext *dctx = NULL; virNetworkDefPtr def = virNetworkObjGetPersistentDef(net); @@ -187,9 +198,13 @@ networkRemoveInactive(struct network_driver *driver, if (!(radvdpidbase = networkRadvdPidfileBasename(def-name))) goto no_memory; +if (!(configfile = networkDnsmasqConfigFileName(def-name))) +goto no_memory; + /* dnsmasq */ dnsmasqDelete(dctx); unlink(leasefile); +unlink(configfile); /* radvd */ unlink(radvdconfigfile); @@ -202,6 +217,7 @@ networkRemoveInactive(struct network_driver *driver, cleanup: VIR_FREE(leasefile); +VIR_FREE(configfile); VIR_FREE(radvdconfigfile); VIR_FREE(radvdpidbase); dnsmasqContextFree(dctx); @@ -635,12 +651,13 @@ networkBuildDnsmasqHostsList(dnsmasqContext *dctx, static int -networkBuildDnsmasqArgv(virNetworkObjPtr network, +networkDnsmasqConfContents(virNetworkObjPtr network, const char *pidfile, -virCommandPtr cmd, +char **configstr, dnsmasqContext *dctx, dnsmasqCapsPtr caps ATTRIBUTE_UNUSED) { +virBuffer configbuf = VIR_BUFFER_INITIALIZER; int r, ret = -1; int nbleases = 0; int ii; @@ -651,46 +668,43 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network, virNetworkIpDefPtr tmpipdef, ipdef, ipv4def, ipv6def; bool dhcp4flag, dhcp6flag, ipv6SLAAC; +*configstr = NULL; + /* - * NB, be careful about syntax for dnsmasq options in long format. - * - * If the flag has a
[libvirt] [PATCHv2 0/3] IPv6 enhancements; put dnsmasq parameters in conf-file
Rebased 30 Nov 2012 These three patch files are packaged together because they serially depend on each other. These files have been rebased to v3 of the dnsmasq capabilities and bind-dynamic patches. The DHCPv6 support checks dnsmasq's version and requires a minimum of 2.64. Also, using dnsmasq for providing the RA service is checked against the dnsmasq version and is currently 2.64. As with IPv4, IPv6 DHCP is only one subnetwork on an interface. Additionally, if other IPv6 addresses are defined, a warning message is issued since the Router Advertisement service will support only state-full (DHCP) or state-less (SLAAC) addressing on a network interface (not both). Thus, the additional subnetworks will need to be manually configured to properly function. If dnsmasq provides the RA service, it also points to itself as a RDNSS (Recursive DNS Server) as part of the information is supplies. If IPv6 DHCP is not being run, then SLAAC addressing is supported for any IPv6 addresses specified. Gene Czarcinski (3): v1: allow guest to guest IPv6 without gateway definition v8.1 add support for DHCPv6 v7.9: put dnsmasq parameters into conf-file docs/formatnetwork.html.in | 126 - docs/schemas/network.rng | 12 +- src/conf/network_conf.c| 100 ++-- src/network/bridge_driver.c| 590 ++--- src/network/bridge_driver.h| 7 +- src/util/dnsmasq.c | 9 +- tests/networkxml2argvdata/dhcp6-nat-network.argv | 14 + tests/networkxml2argvdata/dhcp6-nat-network.xml| 24 + tests/networkxml2argvdata/dhcp6-network.argv | 14 + tests/networkxml2argvdata/dhcp6-network.xml| 14 + .../dhcp6host-routed-network.argv | 12 + .../dhcp6host-routed-network.xml | 19 + tests/networkxml2argvdata/isolated-network.argv| 25 +- .../networkxml2argvdata/nat-network-dns-hosts.argv | 14 +- .../nat-network-dns-srv-record-minimal.argv| 34 +- .../nat-network-dns-srv-record.argv| 24 +- .../nat-network-dns-txt-record.argv| 22 +- tests/networkxml2argvdata/nat-network.argv | 22 +- tests/networkxml2argvdata/netboot-network.argv | 28 +- .../networkxml2argvdata/netboot-proxy-network.argv | 26 +- tests/networkxml2argvdata/routed-network.argv | 11 +- tests/networkxml2argvtest.c| 47 +- 22 files changed, 838 insertions(+), 356 deletions(-) create mode 100644 tests/networkxml2argvdata/dhcp6-nat-network.argv create mode 100644 tests/networkxml2argvdata/dhcp6-nat-network.xml create mode 100644 tests/networkxml2argvdata/dhcp6-network.argv create mode 100644 tests/networkxml2argvdata/dhcp6-network.xml create mode 100644 tests/networkxml2argvdata/dhcp6host-routed-network.argv create mode 100644 tests/networkxml2argvdata/dhcp6host-routed-network.xml -- 1.7.11.7 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] problems with current libvirt and qemu-kvm
On 11/30/2012 09:31 AM, Gene Czarcinski wrote: However, I have noticed one thing. Simon Kelley had me add a little instrumentation to dnsmasq trying to pursue this large number of RTR-ADVERT messages. I am going to do a little more instrumentation. What I have noticed is that there seems to be a broadcast of something whenever a network is started so that all dnsmasq instances (one per started network) go into flurry mode with issuing RA packets and syslog messages. Does anyone know if something in libvirt is doing that? libvirt itself doesn't do anything directly that would cause that; I'm guessing it's a side effect of creating the bridge, or adding an IP address - perhaps either the bridge module or the IP stack is sending around some sort of notification that the topology has changed. -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 2/3] Introduce two new methods for triggering controlled shutdown/reboot
Alas, you are missing documentation of the new flags in src/libvirt.c (not that the existing flags were documented there yet), Well the docs refer to the corresponding enum, whcih will be included in the docs with its descriptions. So isn't that better than duplicating the enum descriptions again. I suppose that's okay, if you think the enum itself has enough details about what each flag means. http://libvirt.org/html/libvirt-libvirt.html#virDomainShutdownFlagValues But there's still the question of semantics, on whether we have properly captured the fact that you can now specify more than one flag, and if so, it is hypervisor choice on which order to attempt the flags. At any rate, ACK to this patch, now that you've done a separate patch for moving the mutual exclusion of flags into the qemu driver. -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 3/3] Add support for shutdown / reboot APIs in LXC driver
Or is your intent to allow the user to specify multiple flags rather than enforcing mutual exclusion between the flags? And if so, you need to fix libvirt.c to drop the mutual exclusion, as well as to document that when multiple flags are specified, it is up to the hypervisor which method is attempted first. Yep, I think allowing multiple flags is fine at the API level. I'd do that as a followup commit since it doesn't affect this, only the existing QEMU code. In which case, I think this patch is okay as-is (unless you wanted to follow my other suggestion of refactoring the common grunt code into a helper method, to reduce code duplication). ACK. -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH] Introduce APIs for splitting/joining strings
From: Daniel P. Berrange berra...@redhat.com This introduces a few new APIs for dealing with strings. One to split a char * into a char **, another to join a char ** into a char *, and finally one to free a char ** There is a simple test suite to validate the edge cases too. No more need to use the horrible strtok_r() API, or hand-written code for splitting strings. Signed-off-by: Daniel P. Berrange berra...@redhat.com --- src/Makefile.am | 1 + src/libvirt_private.syms | 6 ++ src/util/virstring.c | 129 + src/util/virstring.h | 36 +++ tests/Makefile.am| 6 ++ tests/virstringtest.c| 164 +++ 6 files changed, 342 insertions(+) create mode 100644 src/util/virstring.c create mode 100644 src/util/virstring.h create mode 100644 tests/virstringtest.c diff --git a/src/Makefile.am b/src/Makefile.am index 6401dec..b5c20c8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -112,6 +112,7 @@ UTIL_SOURCES = \ util/virnetlink.c util/virnetlink.h \ util/virrandom.h util/virrandom.c \ util/virsocketaddr.h util/virsocketaddr.c \ + util/virstring.h util/virstring.c \ util/virtime.h util/virtime.c \ util/viruri.h util/viruri.c diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 93a21cc..08974d0 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1812,6 +1812,12 @@ virSetErrorLogPriorityFunc; virStrerror; +# virstring.h +virStringSplit; +virStringJoin; +virStringFreeList; + + # virtime.h virTimeFieldsNow; virTimeFieldsNowRaw; diff --git a/src/util/virstring.c b/src/util/virstring.c new file mode 100644 index 000..97dddac --- /dev/null +++ b/src/util/virstring.c @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2007-2012 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * http://www.gnu.org/licenses/. + * + * Authors: + * Daniel P. Berrange berra...@redhat.com + */ + +#include config.h + +#include virstring.h +#include memory.h +#include virterror_internal.h + +#define VIR_FROM_THIS VIR_FROM_NONE + +char **virStringSplit(const char *string, + const char *delim, + size_t max_tokens) +{ +char **tokens = NULL; +size_t ntokens = 0; +size_t maxtokens = 0; +const char *remainder = string; +char *tmp; +size_t i; + +if (max_tokens 1) +max_tokens = INT_MAX; + +tmp = strstr(remainder, delim); +if (tmp) { +size_t delimlen = strlen(delim); + +while (--max_tokens tmp) { +size_t len = tmp - remainder; + +if (VIR_RESIZE_N(tokens, maxtokens, ntokens, 1) 0) +goto no_memory; + +if (!(tokens[ntokens] = strndup(remainder, len))) +goto no_memory; +ntokens++; +remainder = tmp + delimlen; +tmp = strstr(remainder, delim); +} +} +if (*string) { +if (VIR_RESIZE_N(tokens, maxtokens, ntokens, 1) 0) +goto no_memory; + +if (!(tokens[ntokens] = strdup(remainder))) +goto no_memory; +ntokens++; +} + +if (VIR_RESIZE_N(tokens, maxtokens, ntokens, 1) 0) +goto no_memory; +tokens[ntokens++] = NULL; + +return tokens; + +no_memory: +virReportOOMError(); +for (i = 0 ; i ntokens ; i++) { +VIR_FREE(tokens[i]); +} +VIR_FREE(tokens); +return NULL; +} + + +char *virStringJoin(const char **strings, +const char *delim) +{ +size_t len = 0; +size_t delimlen = strlen(delim); +const char **tmp = strings; +char *string; +char *offset; + +while (tmp *tmp) { +len += strlen(*tmp); +len += delimlen; +tmp++; +} + +if (VIR_ALLOC_N(string, len + 1) 0) { +virReportOOMError(); +return NULL; +} + +tmp = strings; +offset = string; +while (tmp *tmp) { +offset = stpcpy(offset, *tmp); +if (*(tmp+1)) +offset = stpcpy(offset, delim); +len += strlen(*tmp); +len += delimlen; +tmp++; +} + +return string; +} + + +void virStringFreeList(char
[libvirt] [PATCH] Allow comma separated list of shutdown/reboot modes with virsh
From: Daniel P. Berrange berra...@redhat.com The shutdown and reboot commands in virsh allow a comma separated list of mode values Signed-off-by: Daniel P. Berrange berra...@redhat.com --- tools/virsh-domain.c | 25 +++-- tools/virsh.pod | 16 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index a7ffd2b..3ca246b 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -48,6 +48,7 @@ #include virfile.h #include virkeycode.h #include virmacaddr.h +#include virstring.h #include virsh-domain-monitor.h #include virterror_internal.h #include virtypedparam.h @@ -4035,13 +4036,21 @@ cmdShutdown(vshControl *ctl, const vshCmd *cmd) const char *mode = NULL; int flags = 0; int rv; +char **modes, **tmp; if (vshCommandOptString(cmd, mode, mode) 0) { vshError(ctl, %s, _(Invalid type)); return false; } -if (mode) { +if (!(modes = virStringSplit(mode, ,, 0))) { +vshError(ctl, %s, _(Cannot parse mode string)); +return false; +} + +tmp = modes; +while (*tmp) { +mode = *tmp; if (STREQ(mode, acpi)) { flags |= VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN; } else if (STREQ(mode, agent)) { @@ -4055,7 +4064,9 @@ cmdShutdown(vshControl *ctl, const vshCmd *cmd) 'acpi', 'agent', 'initctl' or 'signal'), mode); return false; } +tmp++; } +virStringFreeList(modes); if (!(dom = vshCommandOptDomain(ctl, cmd, name))) return false; @@ -4098,13 +4109,21 @@ cmdReboot(vshControl *ctl, const vshCmd *cmd) const char *name; const char *mode = NULL; int flags = 0; +char **modes, **tmp; if (vshCommandOptString(cmd, mode, mode) 0) { vshError(ctl, %s, _(Invalid type)); return false; } -if (mode) { +if (!(modes = virStringSplit(mode, ,, 0))) { +vshError(ctl, %s, _(Cannot parse mode string)); +return false; +} + +tmp = modes; +while (*tmp) { +mode = *tmp; if (STREQ(mode, acpi)) { flags |= VIR_DOMAIN_REBOOT_ACPI_POWER_BTN; } else if (STREQ(mode, agent)) { @@ -4118,7 +4137,9 @@ cmdReboot(vshControl *ctl, const vshCmd *cmd) 'acpi', 'agent', 'initctl' or 'signal'), mode); return false; } +tmp++; } +virStringFreeList(modes); if (!(dom = vshCommandOptDomain(ctl, cmd, name))) return false; diff --git a/tools/virsh.pod b/tools/virsh.pod index c901b11..7dde3df 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -1137,7 +1137,7 @@ If I--live is specified, set scheduler information of a running guest. If I--config is specified, affect the next boot of a persistent guest. If I--current is specified, affect the current guest state. -=item Breboot Idomain [I--mode acpi|agent] +=item Breboot Idomain [I--mode MODE-LIST] Reboot a domain. This acts just as if the domain had the Breboot command run from the console. The command returns as soon as it has @@ -1149,7 +1149,11 @@ Ion_reboot parameter in the domain's XML definition. By default the hypervisor will try to pick a suitable shutdown method. To specify an alternative method, the I--mode parameter -can specify Cacpi or Cagent. +can specify a comma separated list which includes Cacpi, Cagent, +Cinitctl and Csignal. The order in which drivers will try each +mode is undefined, and not related to the order specified to virsh. +For strict control over ordering, use a single mode at a time and +repeat the command. =item Breset Idomain @@ -1567,7 +1571,7 @@ The I--maximum flag controls the maximum number of virtual cpus that can be hot-plugged the next time the domain is booted. As such, it must only be used with the I--config flag, and not with the I--live flag. -=item Bshutdown Idomain [I--mode acpi|agent] +=item Bshutdown Idomain [I--mode MODE-LIST] Gracefully shuts down a domain. This coordinates with the domain OS to perform graceful shutdown, so there is no guarantee that it will @@ -1584,7 +1588,11 @@ snapshot metadata with Bsnapshot-create. By default the hypervisor will try to pick a suitable shutdown method. To specify an alternative method, the I--mode parameter -can specify Cacpi or Cagent. +can specify a comma separated list which includes Cacpi, Cagent, +Cinitctl and Csignal. The order in which drivers will try each +mode is undefined, and not related to the order specified to virsh. +For strict control over ordering, use a single mode at a time and +repeat the command. =item Bstart Idomain-name-or-uuid [I--console] [I--paused] [I--autodestroy] [I--bypass-cache] [I--force-boot] -- 1.7.11.7 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] Introduce APIs for splitting/joining strings
On Fri, Nov 30, 2012 at 03:34:36PM +, Daniel P. Berrange wrote: From: Daniel P. Berrange berra...@redhat.com This introduces a few new APIs for dealing with strings. One to split a char * into a char **, another to join a char ** into a char *, and finally one to free a char ** There is a simple test suite to validate the edge cases too. No more need to use the horrible strtok_r() API, or hand-written code for splitting strings. Signed-off-by: Daniel P. Berrange berra...@redhat.com --- src/Makefile.am | 1 + src/libvirt_private.syms | 6 ++ src/util/virstring.c | 129 + src/util/virstring.h | 36 +++ tests/Makefile.am| 6 ++ tests/virstringtest.c| 164 +++ 6 files changed, 342 insertions(+) create mode 100644 src/util/virstring.c create mode 100644 src/util/virstring.h create mode 100644 tests/virstringtest.c Opps, the virstring.c file should have this patch spliced in diff --git a/src/util/virstring.c b/src/util/virstring.c index 97dddac..fda378a 100644 --- a/src/util/virstring.c +++ b/src/util/virstring.c @@ -27,6 +27,35 @@ #define VIR_FROM_THIS VIR_FROM_NONE +/* + * The following virStringSplit virStringJoin methods + * are derived from g_strsplit / g_strjoin in glib2, + * also available under the LGPLv2+ license terms + */ + +/** + * virStringSplit: + * @string: a string to split + * @delim: a string which specifies the places at which to split + * the string. The delimiter is not included in any of the resulting + * strings, unless @max_tokens is reached. + * @max_tokens: the maximum number of pieces to split @string into. + * If this is less than 1, the string is split completely. + * + * Splits a string into a maximum of @max_tokens pieces, using the given + * @delim. If @max_tokens is reached, the remainder of @string is + * appended to the last token. + * + * As a special case, the result of splitting the empty string is an empty + * vector, not a vector containing a single string. The reason for this + * special case is that being able to represent a empty vector is typically + * more useful than consistent handling of empty elements. If you do need + * to represent empty elements, you'll need to check for the empty string + * before calling virStringSplit(). + * + * Return value: a newly-allocated NULL-terminated array of strings. Use + *virStringFreeList() to free it. + */ char **virStringSplit(const char *string, const char *delim, size_t max_tokens) @@ -83,6 +112,18 @@ no_memory: } +/** + * virStringJoin: + * @strings: a NULL-terminated array of strings to join + * @delim: a string to insert between each of the strings + * + * Joins a number of strings together to form one long string, with the + * @delim inserted between each of them. The returned string + * should be freed with VIR_FREE(). + * + * Returns: a newly-allocated string containing all of the strings joined + * together, with @delim between them + */ char *virStringJoin(const char **strings, const char *delim) { @@ -118,6 +159,13 @@ char *virStringJoin(const char **strings, } +/** + * virStringFreeList: + * @str_array: a NULL-terminated array of strings to free + * + * Frees a NULL-terminated array of strings, and the array itself. + * If called on a NULL value, virStringFreeList() simply returns. + */ void virStringFreeList(char **strings) { char **tmp = strings; diff --git a/src/Makefile.am b/src/Makefile.am index 6401dec..b5c20c8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -112,6 +112,7 @@ UTIL_SOURCES = \ util/virnetlink.c util/virnetlink.h \ util/virrandom.h util/virrandom.c \ util/virsocketaddr.h util/virsocketaddr.c \ + util/virstring.h util/virstring.c \ util/virtime.h util/virtime.c \ util/viruri.h util/viruri.c diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 93a21cc..08974d0 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1812,6 +1812,12 @@ virSetErrorLogPriorityFunc; virStrerror; +# virstring.h +virStringSplit; +virStringJoin; +virStringFreeList; + + # virtime.h virTimeFieldsNow; virTimeFieldsNowRaw; diff --git a/src/util/virstring.c b/src/util/virstring.c new file mode 100644 index 000..97dddac --- /dev/null +++ b/src/util/virstring.c @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2007-2012 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + *
Re: [libvirt] [PATCH] Introduce APIs for splitting/joining strings
This introduces a few new APIs for dealing with strings. One to split a char * into a char **, another to join a char ** into a char *, and finally one to free a char ** Do we also want to migrate virsh.c:vshStringToArray() to this file, with its additional magic of supporting ',,' as an escape sequence for literal comma in one of the strings being split? There is a simple test suite to validate the edge cases too. No more need to use the horrible strtok_r() API, or hand-written code for splitting strings. Signed-off-by: Daniel P. Berrange berra...@redhat.com --- src/Makefile.am | 1 + src/libvirt_private.syms | 6 ++ src/util/virstring.c | 129 + src/util/virstring.h | 36 +++ tests/Makefile.am| 6 ++ tests/virstringtest.c| 164 +++ 6 files changed, 342 insertions(+) create mode 100644 src/util/virstring.c create mode 100644 src/util/virstring.h create mode 100644 tests/virstringtest.c + +char **virStringSplit(const char *string, + const char *delim, + size_t max_tokens) +{ +char **tokens = NULL; +size_t ntokens = 0; +size_t maxtokens = 0; +const char *remainder = string; +char *tmp; +size_t i; + +if (max_tokens 1) Effectively 'if (!max_tokens)' + +char *virStringJoin(const char **strings, +const char *delim) +{ Should this function have a third argument that says how many elements are in strings (and leave it 0 if strings is NULL-terminated)? Otherwise, callers will have to ensure that there is a trailing NULL element in strings, instead of being able to specifically request the joining of an exact amount of strings. +size_t len = 0; +size_t delimlen = strlen(delim); +const char **tmp = strings; +char *string; +char *offset; + +while (tmp *tmp) { +len += strlen(*tmp); +len += delimlen; +tmp++; +} Would it be any easier to write this function in terms of virBuffer, instead of rolling it by hand? Untested: char *virStringJoin(const char **strings, const char *delim) { virBuffer buf = VIR_BUFFER_INITIALIZER; if (strings *strings) { virBufferAdd(buf, *strings, 0); while (*++strings) { virBufferAdd(buf, delim, 0); virBufferAdd(*strings); } } return virBufferContentAndReset(buf); } +void virStringFreeList(char **strings) Another function that might benefit from a length argument, rather than forcing the user to pass in a NULL-terminated list; in which case, it would then be usable in the no_memory label of the split function, rather than your current hand-rolled cleanup loop (since that label is a case of not having a NULL terminator). + +char **virStringSplit(const char *string, + const char *delim, + size_t max_tokens); Worth marking ATTRIBUTE_NONNULL(2)? It looks like you intend to allow NULL for arg 1 though (in which case the return is also NULL). + +char *virStringJoin(const char **strings, +const char *delim); Worth marking ATTRIBUTE_NONNULL(2)? +++ b/tests/Makefile.am @@ -95,6 +95,7 @@ test_programs = virshtest sockettest \ virauthconfigtest \ virbitmaptest \ virlockspacetest \ + virstringtest \ Does .gitignore need to be updated for this binary? +++ b/tests/virstringtest.c @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2011 Red Hat, Inc. 2012 +static int +mymain(void) +{ +int ret = 0; + +signal(SIGPIPE, SIG_IGN); Isn't this already taken care of in the top-level main() before calling into mymain()? -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] Allow comma separated list of shutdown/reboot modes with virsh
The shutdown and reboot commands in virsh allow a comma separated list of mode values Signed-off-by: Daniel P. Berrange berra...@redhat.com --- tools/virsh-domain.c | 25 +++-- tools/virsh.pod | 16 2 files changed, 35 insertions(+), 6 deletions(-) -if (mode) { +if (!(modes = virStringSplit(mode, ,, 0))) { Any reason you can't use vshStringToArray to do the split? +vshError(ctl, %s, _(Cannot parse mode string)); +return false; +} + +tmp = modes; +while (*tmp) { +mode = *tmp; if (STREQ(mode, acpi)) { flags |= VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN; } else if (STREQ(mode, agent)) { @@ -4055,7 +4064,9 @@ cmdShutdown(vshControl *ctl, const vshCmd *cmd) 'acpi', 'agent', 'initctl' or 'signal'), mode); return false; Memory leak... } +tmp++; } +virStringFreeList(modes); ...You need a cleanup label to cover this in all error paths. @@ -4118,7 +4137,9 @@ cmdReboot(vshControl *ctl, const vshCmd *cmd) 'acpi', 'agent', 'initctl' or 'signal'), mode); return false; } +tmp++; } +virStringFreeList(modes); Another leak. -=item Breboot Idomain [I--mode acpi|agent] +=item Breboot Idomain [I--mode MODE-LIST] Reboot a domain. This acts just as if the domain had the Breboot command run from the console. The command returns as soon as it has @@ -1149,7 +1149,11 @@ Ion_reboot parameter in the domain's XML definition. By default the hypervisor will try to pick a suitable shutdown method. To specify an alternative method, the I--mode parameter -can specify Cacpi or Cagent. +can specify a comma separated list which includes Cacpi, Cagent, +Cinitctl and Csignal. The order in which drivers will try each +mode is undefined, and not related to the order specified to virsh. +For strict control over ordering, use a single mode at a time and +repeat the command. This portion looks good, though :) -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] Introduce APIs for splitting/joining strings
This introduces a few new APIs for dealing with strings. One to split a char * into a char **, another to join a char ** into a char *, and finally one to free a char ** Opps, the virstring.c file should have this patch spliced in Oh, you're copying code. Which means my suggestion of letting the user specify a length rather than forcing them to NULL-terminate their array would mean you are no longer matching the version that you copied from (not necessarily a bad thing). +/** + * virStringSplit: + * @string: a string to split + * @delim: a string which specifies the places at which to split + * the string. The delimiter is not included in any of the resulting + * strings, unless @max_tokens is reached. + * @max_tokens: the maximum number of pieces to split @string into. + * If this is less than 1, the string is split completely. less than 1 means exactly 0, since it is an unsigned param. -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] storage: fix scsi detach regression with cgroup ACLs
https://bugzilla.redhat.com/show_bug.cgi?id=876828 Commit 38c4a9cc introduced a regression in hot unplugging of disks from qemu, where cgroup device ACLs were no longer being revoked (thankfully not a security hole: cgroup ACLs only prevent open() of the disk; so reverting the ACL prevents future abuse but doesn't stop abuse from an fd that was already opened before the ACL change). Commit 1b2ebf95 overlooked that there were two spots affected. ACK Thanks; pushed. -- Eric Blake ebl...@redhat.com+1-919-301-3266 Libvirt virtualization library http://libvirt.org -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] qemu: don't attempt undefined QMP commands
https://bugzilla.redhat.com/show_bug.cgi?id=872292 Libvirt should not attempt to call a QMP command that has not been documented in qemu.git - if future qemu introduces a command by the same name but with subtly different semantics, then libvirt will be broken when trying to use that command. The reason these were added was that back in the first days of QMP the intention was that every HMP command would have an identical QMP command. This plan changed before it was ever completed, hence the situation we're in now. Yep :) +virReportError(VIR_ERR_CONFIG_UNSUPPORTED, %s, + _(JSON monitor should be using netdev_del)); In these two you recommend different commands +virReportError(VIR_ERR_CONFIG_UNSUPPORTED, %s, + _(JSON monitor should be using AddDrive)); while this one recommends a different method ACK you standardize on one. I standardized on the method name, improved the commit message to give more details about the commands being deleted from QMP support (since they were dead code based on qemu_hotplug.c usage patterns), and pushed. -- Eric Blake ebl...@redhat.com+1-919-301-3266 Libvirt virtualization library http://libvirt.org -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v1 02/11] bandwidth: Create hierarchical shaping classes
On 11/19/2012 11:51 AM, Michal Privoznik wrote: These classes can borrow unused bandwidth. Basically, only egress qdsics can have classes, therefore we can do this kind of traffic shaping only on host's outgoing, that is domain's incoming traffic. --- src/lxc/lxc_process.c |3 ++- src/network/bridge_driver.c |3 ++- src/qemu/qemu_command.c |3 ++- src/qemu/qemu_driver.c|2 +- src/util/virnetdevbandwidth.c | 33 +++-- src/util/virnetdevbandwidth.h |4 +++- src/util/virnetdevmacvlan.c |2 +- 7 files changed, 38 insertions(+), 12 deletions(-) diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c index 079bc3a..91ce2d3 100644 --- a/src/lxc/lxc_process.c +++ b/src/lxc/lxc_process.c @@ -335,7 +335,8 @@ static int virLXCProcessSetupInterfaceBridged(virConnectPtr conn, goto cleanup; if (virNetDevBandwidthSet(net-ifname, - virDomainNetGetActualBandwidth(net)) 0) { + virDomainNetGetActualBandwidth(net), + false) 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _(cannot set bandwidth limits on %s), net-ifname); diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index c153d36..256b601 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -2240,7 +2240,8 @@ networkStartNetworkVirtual(struct network_driver *driver, VIR_FORCE_CLOSE(tapfd); } -if (virNetDevBandwidthSet(network-def-bridge, network-def-bandwidth) 0) { +if (virNetDevBandwidthSet(network-def-bridge, + network-def-bandwidth, true) 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _(cannot set bandwidth limits on %s), network-def-bridge); diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 22bb209..c1f8680 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -292,7 +292,8 @@ qemuNetworkIfaceConnect(virDomainDefPtr def, if (tapfd = 0 virNetDevBandwidthSet(net-ifname, - virDomainNetGetActualBandwidth(net)) 0) { + virDomainNetGetActualBandwidth(net), + false) 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _(cannot set bandwidth limits on %s), net-ifname); diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 595c452..9ae0c1b 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -8960,7 +8960,7 @@ qemuDomainSetInterfaceParameters(virDomainPtr dom, sizeof(*newBandwidth-out)); } -if (virNetDevBandwidthSet(net-ifname, newBandwidth) 0) { +if (virNetDevBandwidthSet(net-ifname, newBandwidth, false) 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _(cannot set bandwidth limits on %s), device); diff --git a/src/util/virnetdevbandwidth.c b/src/util/virnetdevbandwidth.c index bddb788..fcc6b56 100644 --- a/src/util/virnetdevbandwidth.c +++ b/src/util/virnetdevbandwidth.c @@ -45,17 +45,21 @@ virNetDevBandwidthFree(virNetDevBandwidthPtr def) * virNetDevBandwidthSet: * @ifname: on which interface * @bandwidth: rates to set (may be NULL) + * @hierarchical_class: whether to create hierarchical class * * This function enables QoS on specified interface * and set given traffic limits for both, incoming * and outgoing traffic. Any previous setting get - * overwritten. + * overwritten. If @hierarchical_class is TRUE, create + * hierarchical class. It is used to guarantee minimal + * throughput ('floor' attribute in NIC). * * Return 0 on success, -1 otherwise. */ int virNetDevBandwidthSet(const char *ifname, - virNetDevBandwidthPtr bandwidth) + virNetDevBandwidthPtr bandwidth, + bool hierarchical_class) { int ret = -1; virCommandPtr cmd = NULL; @@ -71,7 +75,7 @@ virNetDevBandwidthSet(const char *ifname, virNetDevBandwidthClear(ifname); -if (bandwidth-in) { +if (bandwidth-in bandwidth-in-average) { if (virAsprintf(average, %llukbps, bandwidth-in-average) 0) goto cleanup; if (bandwidth-in-peak @@ -83,15 +87,32 @@ virNetDevBandwidthSet(const char *ifname, cmd = virCommandNew(TC); virCommandAddArgList(cmd, qdisc, add, dev, ifname, root, - handle, 1:, htb, default, 1, NULL); + handle, 1:, htb, default, + hierarchical_class ? 2 : 1, NULL); Don't you really only need to do this if floor has been set? If you create
[libvirt] [PATCH] qemu: Fix up the default machine type for QMP probing
The default machine type must be stored in the first element of the caps-machineTypes array. This was done for help output parsing but not for QMP probing. Added a helper function qemuSetDefaultMachine to apply the same fix up for both probing methods. Further, it was necessary to set caps-nmachineTypes after QMP probing. Signed-off-by: Viktor Mihajlovski mihaj...@linux.vnet.ibm.com --- src/qemu/qemu_capabilities.c | 38 ++ 1 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index d6affb9..6e34cdf 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -292,6 +292,23 @@ qemuCapsProbeCommand(const char *qemu, } +static void +qemuSetDefaultMachine(qemuCapsPtr caps, + size_t defIdx) +{ +char *name = caps-machineTypes[defIdx]; +char *alias = caps-machineAliases[defIdx]; + +memmove(caps-machineTypes + 1, +caps-machineTypes, +sizeof(caps-machineTypes[0]) * defIdx); +memmove(caps-machineAliases + 1, +caps-machineAliases, +sizeof(caps-machineAliases[0]) * defIdx); +caps-machineTypes[0] = name; +caps-machineAliases[0] = alias; +} + /* Format is: * machine desc [(default)|(alias of canonical)] */ @@ -352,18 +369,8 @@ qemuCapsParseMachineTypesStr(const char *output, } while ((p = next)); -if (defIdx != 0) { -char *name = caps-machineTypes[defIdx]; -char *alias = caps-machineAliases[defIdx]; -memmove(caps-machineTypes + 1, -caps-machineTypes, -sizeof(caps-machineTypes[0]) * defIdx); -memmove(caps-machineAliases + 1, -caps-machineAliases, -sizeof(caps-machineAliases[0]) * defIdx); -caps-machineTypes[0] = name; -caps-machineAliases[0] = alias; -} +if (defIdx) +qemuSetDefaultMachine(caps, defIdx); return 0; @@ -2020,6 +2027,7 @@ qemuCapsProbeQMPMachineTypes(qemuCapsPtr caps, int nmachines = 0; int ret = -1; size_t i; +size_t defIdx = 0; if ((nmachines = qemuMonitorGetMachines(mon, machines)) 0) goto cleanup; @@ -2049,7 +2057,13 @@ qemuCapsProbeQMPMachineTypes(qemuCapsPtr caps, goto cleanup; } } +if (machines[i]-isDefault) +defIdx = i; } +caps-nmachineTypes = nmachines; + +if (defIdx) +qemuSetDefaultMachine(caps, defIdx); ret = 0; -- 1.7.0.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] fwd: RA support in dnsmasq
I am sort-of cross posting this to the libvir-list because the bind-dynamic fix may have introduced an undesirable new feature. I will be troubleshooting this. One thing I want to try is to build a dnsmasq with a fake version so that bind-interface is forced into use. Since this is occurring with a SLAAC address, I do not need DHCPv6 for this testing. Wait, since Laine put a lot of effort into parsing dnsmasq --help, I will just remove the bind-dynamic rather than changing the version. Gene Original Message Subject:Re: [Dnsmasq-discuss] RA support in dnsmasq Date: Fri, 30 Nov 2012 12:20:36 -0500 From: Gene Czarcinski g...@czarc.net To: dnsmasq-disc...@thekelleys.org.uk On 11/30/2012 11:32 AM, Simon Kelley wrote: On 30/11/12 15:54, Gene Czarcinski wrote: On 11/29/2012 04:18 PM, Simon Kelley wrote: On 29/11/12 20:31, Gene Czarcinski wrote: I spoke too quickly. The cause of the problem is libvirt related but I am not sure what just yet. I was running a libvirt that had a lot of stuff on it but seemed to work OK. Then, earlier today I update to a point that appears to be somewhat beyond the leading edge and, although I was not getting any RTR-ADVERT messages, it turned out that there were/are big-time problems running qemu-kvm. So, back off/downgrade to the previous version. Qemu-kvm now works but the RTR-ADVERT messages are back. This may be a bit time-consuming to debug! Are you seeing the new log message in netlink.c? The good news is that libvirt is working again (I must have done a git-pull in the middle of an update). Thus, I am not seeing the large numbers of RTR-ADVERT. Yes, I am seeing the new log message and I have a question about that. Every time a new virtual network interface is started, something must be doing some type of broadcast because all of the dnsmasq instances (the new one and all the old ones) suddenly wake up and issue a flurry of RA packets and related syslog messages. To kick the flurry off, there one of the new unsolicited syslog messages from each dnsmasq instance. Is this something you would expect? Is this normal? The libvirt folks they are not doing it. I'd expect it. The code you instrumented gets run whenever a new address event happens, which is whenever an address is added to an interface. Every time a new virtual network interface is started is a good proxy for that. The dnsmasq code isn't very discriminating, it updates it's idea of which interfaces hace which addresses, and then does a minute of fast advertisements on all of them. It might be possible to only do the fast advertisements on new interfaces, but implementing that isn't totally trivial. Yes, I doubt very much if it would be trivial. However, I do not believe that this is the basic problem. When the problem occurs, one of the networks suddenly attempts to work with the real NIC rather than the virtual one defined in its config file. I slightly changed the IPv4 and IPv6 addresses defined for this network and the problem went away. I have also just seen the problem happen on another system which also had that virtual address defined. BTW, these configurations all use interface= and bind-dynamic rather than the old bind-interface with listen-address= specified for each specified IPv4 and IPv6 address. I had not noticed the problem previously. Why it occurs at all with just this specific address is puzzling. The configuration in which causes problems is: -- # dnsmasq conf file created by libvirt strict-order domain-needed domain=net6 expand-hosts local=/net6/ pid-file=/var/run/libvirt/network/net6.pid bind-dynamic interface=virbr11 dhcp-range=192.168.6.128,192.168.6.254 dhcp-no-override dhcp-leasefile=/var/lib/libvirt/dnsmasq/net6.leases dhcp-lease-max=127 dhcp-hostsfile=/var/lib/libvirt/dnsmasq/net6.hostsfile addn-hosts=/var/lib/libvirt/dnsmasq/net6.addnhosts dhcp-range=fd00:beef:10:6::1,ra-only - When I changed all the 6 to 160, the problem, disappeared. And there is another network defined almost the same with 8 instead of 6 and I have had no problems with it. The real NIC is configured as a DHCP client for both IPv4 and IPv6. It is assigned nailed addresses of 192.168.17.2/24 and fd00:dead:beef:17::2. And I just discovered why crazy stuff is happening (but I do not know what causes it) ... the P33p1 NIC has: inet6 fd00:beef:10:6:3285:a9ff:fe8f:e982/64 scope global dynamic And the reason why may be related to that NetworkManager goes through a verly long dance to bring up an interface. With dnsmasq autostarted for net6, it may have gotten there first ... but it should have not responded to p33p1 in any case. I am getting a little suspicious of dnsmasq with bind-dynamic! Gene ___ Dnsmasq-discuss mailing list dnsmasq-disc...@lists.thekelleys.org.uk
Re: [libvirt] [PATCH v1 03/11] bandwidth: Create (un)plug functions
On 11/19/2012 11:51 AM, Michal Privoznik wrote: These set bridge part of QoS when bringing domain's interface up. Long story short, if there's a 'floor' set, a new QoS class is created. ClassID MUST be unique within the bridge and should be kept for unplug phase. --- po/POTFILES.in|1 + src/util/virnetdevbandwidth.c | 178 + src/util/virnetdevbandwidth.h | 14 +++ 3 files changed, 193 insertions(+), 0 deletions(-) diff --git a/po/POTFILES.in b/po/POTFILES.in index 9768528..f51e2c7 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -154,6 +154,7 @@ src/util/virhash.c src/util/virkeyfile.c src/util/virlockspace.c src/util/virnetdev.c +src/util/virnetdevbandwidth.c src/util/virnetdevbridge.c src/util/virnetdevmacvlan.c src/util/virnetdevopenvswitch.c diff --git a/src/util/virnetdevbandwidth.c b/src/util/virnetdevbandwidth.c index fcc6b56..9597dcd 100644 --- a/src/util/virnetdevbandwidth.c +++ b/src/util/virnetdevbandwidth.c @@ -285,3 +285,181 @@ virNetDevBandwidthEqual(virNetDevBandwidthPtr a, return true; } + +/* + * virNetDevBandwidthPlug: + * @brname: name of the bridge + * @net_bandwidth: QoS settings on @brname + * @ifname: interface being plugged into @brname + * @ifmac: MAC of @ifname + * @bandwidth: QoS settings for @ifname + * @id: unique ID (MUST be greater than 2) * If it must be 2, then you need to check for that at the top of the function. + * + * Set bridge part of interface QoS settings, e.g. guaranteed + * bandwidth. @id is an unique ID (among @brname) from which + * other identifiers for class, qdisc and filter are derived. + * However, two classes were already set up (by + * virNetDevBandwidthSet). That's why this @id MUST be greater + * than 2. You may want to keep passed @id, as it is used later + * by virNetDevBandwidthUnplug. + * + * Returns: + * 1 if there is nothing to set + * 0 if QoS set successfully + * -1 otherwise. + */ +int +virNetDevBandwidthPlug(const char *brname, + virNetDevBandwidthPtr net_bandwidth, + const char *ifname, + const virMacAddrPtr ifmac_ptr, + virNetDevBandwidthPtr bandwidth, + unsigned int id) +{ +int ret = -1; +virCommandPtr cmd = NULL; +char *class_id = NULL; +char *qdisc_id = NULL; +char *filter_id = NULL; +char *floor = NULL; +char *ceil = NULL; +unsigned char ifmac[VIR_MAC_BUFLEN]; +char *mac[2]; + +if (!bandwidth || !bandwidth-in || !bandwidth-in-floor) { +/* nothing to set */ +return 1; +} + +if (!net_bandwidth || !net_bandwidth-in) { +virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _(Bridge '%s' has no QoS set, therefore + unable to set 'floor' on '%s'), + brname, ifname); +return -1; +} + +virMacAddrGetRaw(ifmac_ptr, ifmac); + +if (virAsprintf(class_id, 1:%x, id) 0 || +virAsprintf(qdisc_id, %x:, id) 0 || +virAsprintf(filter_id, %u, id) 0 || +virAsprintf(mac[0], 0x%02x%02x%02x%02x, ifmac[2], +ifmac[3], ifmac[4], ifmac[5]) 0 || +virAsprintf(mac[1], 0x%02x%02x, ifmac[0], ifmac[1]) 0 || +virAsprintf(floor, %llukbps, bandwidth-in-floor) 0 || +virAsprintf(ceil, %llukbps, net_bandwidth-in-peak ? +net_bandwidth-in-peak : +net_bandwidth-in-average) 0) { +virReportOOMError(); +goto cleanup; +} + +cmd = virCommandNew(TC); +virCommandAddArgList(cmd, class, add, dev, brname, parent, 1:1, + classid, class_id, htb, rate, floor, + ceil, ceil, NULL); + +if (virCommandRun(cmd, NULL) 0) +goto cleanup; + +virCommandFree(cmd); +cmd = virCommandNew(TC); +virCommandAddArgList(cmd, qdisc, add, dev, brname, parent, + class_id, handle, qdisc_id, sfq, perturb, + 10, NULL); + +if (virCommandRun(cmd, NULL) 0) +goto cleanup; + +virCommandFree(cmd); +cmd = virCommandNew(TC); +/* Okay, this not nice. But since libvirt does not know anything about + * interface IP address(es), and tc fw filter simply refuse to use ebtables + * marks, we need to use u32 selector to match MAC address. + * If libvirt will ever know something, remove this FIXME Heck, maybe not even then - don't forget about IPv6, along with the fact that I'm not convinced the host can ever know all the IP addresses used by an untrusted guest with 100% certainty (unless we filter for them I suppose). + */ +virCommandAddArgList(cmd, filter, add, dev, brname, protocol, ip, + prio, filter_id, u32, +
Re: [libvirt] [PATCH v1 04/11] bandwidth: Create rate update function
On 11/19/2012 11:51 AM, Michal Privoznik wrote: This will be used whenever a NIC with guaranteed throughput is to be plugged into a bridge. It will adjust the average throughput of non guaranteed NICs (classid 1:2) to meet new requirements. --- src/util/virnetdevbandwidth.c | 49 + src/util/virnetdevbandwidth.h |6 + 2 files changed, 55 insertions(+), 0 deletions(-) diff --git a/src/util/virnetdevbandwidth.c b/src/util/virnetdevbandwidth.c index 9597dcd..3abe7e2 100644 --- a/src/util/virnetdevbandwidth.c +++ b/src/util/virnetdevbandwidth.c @@ -463,3 +463,52 @@ cleanup: virCommandFree(cmd); return ret; } + +/** + * virNetDevBandwidthUpdateRate: + * @ifname: interface name + * @classid: ID of class to update + * @new_rate: new rate + * + * This function updates the 'rate' attribute of HTB class. + * It can be used whenever a new interface is plugged to a + * bridge to adjust average throughput of non guaranteed + * NICs. So it's changing the average for that NIC to something other than what was configured? Is a record of this kept anywhere? (or maybe it's not necessary). + * + * Returns 0 on success, -1 otherwise. + */ +int +virNetDevBandwidthUpdateRate(const char *ifname, + const char *class_id, + virNetDevBandwidthPtr bandwidth, + unsigned long long new_rate) +{ +int ret = -1; +virCommandPtr cmd = NULL; +char *rate = NULL; +char *ceil = NULL; + +if (virAsprintf(rate, %llukbps, new_rate) 0 || +virAsprintf(ceil, %llukbps, bandwidth-in-peak ? +bandwidth-in-peak : +bandwidth-in-average) 0) { +virReportOOMError(); +goto cleanup; +} + +cmd = virCommandNew(TC); +virCommandAddArgList(cmd, class, change, dev, ifname, + classid, class_id, htb, rate, rate, + ceil, ceil, NULL); + +if (virCommandRun(cmd, NULL) 0) +goto cleanup; + +ret = 0; + +cleanup: +virCommandFree(cmd); +VIR_FREE(rate); +VIR_FREE(ceil); +return ret; +} diff --git a/src/util/virnetdevbandwidth.h b/src/util/virnetdevbandwidth.h index 19eb418..a5d595e 100644 --- a/src/util/virnetdevbandwidth.h +++ b/src/util/virnetdevbandwidth.h @@ -67,4 +67,10 @@ int virNetDevBandwidthUnplug(const char *brname, unsigned int id) ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK; +int virNetDevBandwidthUpdateRate(const char *ifname, + const char *class_id, + virNetDevBandwidthPtr bandwidth, + unsigned long long new_rate) +ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) +ATTRIBUTE_RETURN_CHECK; #endif /* __VIR_NETDEV_BANDWIDTH_H__ */ ACK. -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH] Fix uninitialized variables
detecet by http://honk.sigxcpu.org:8001/job/libvirt-build/348/console --- Probably o.k. to push under the build breaker rule but I'd better check. Cheers, -- Guido src/qemu/qemu_monitor.c |4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index c1f7c41..f85bb76 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -2408,7 +2408,7 @@ int qemuMonitorRemoveHostNetwork(qemuMonitorPtr mon, int vlan, const char *netname) { -int ret; +int ret = -1; VIR_DEBUG(mon=%p netname=%s, mon, netname); @@ -2541,7 +2541,7 @@ int qemuMonitorAttachDrive(qemuMonitorPtr mon, mon, drivestr, controllerAddr-domain, controllerAddr-bus, controllerAddr-slot, controllerAddr-function); -int ret; +int ret = 1; if (!mon) { virReportError(VIR_ERR_INVALID_ARG, %s, -- 1.7.10.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] Fix uninitialized variables
On Fri, Nov 30, 2012 at 07:13:01PM +0100, Guido Günther wrote: detecet by http://honk.sigxcpu.org:8001/job/libvirt-build/348/console --- Probably o.k. to push under the build breaker rule but I'd better check. Cheers, -- Guido src/qemu/qemu_monitor.c |4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index c1f7c41..f85bb76 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -2408,7 +2408,7 @@ int qemuMonitorRemoveHostNetwork(qemuMonitorPtr mon, int vlan, const char *netname) { -int ret; +int ret = -1; VIR_DEBUG(mon=%p netname=%s, mon, netname); @@ -2541,7 +2541,7 @@ int qemuMonitorAttachDrive(qemuMonitorPtr mon, mon, drivestr, controllerAddr-domain, controllerAddr-bus, controllerAddr-slot, controllerAddr-function); -int ret; +int ret = 1; if (!mon) { virReportError(VIR_ERR_INVALID_ARG, %s, ACK Daniel -- |: http://berrange.com -o-http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v1 05/11] bandwidth: Create network (un)plug functions
On 11/19/2012 11:51 AM, Michal Privoznik wrote: Network should be notified if we plug in or unplug an interface, so it can perform some action, e.g. set/unset network part of QoS. --- src/Makefile.am |7 ++- src/conf/domain_conf.h |1 + src/conf/network_conf.c |1 + src/conf/network_conf.h |3 + src/libvirt_network.syms|8 ++ src/network/bridge_driver.c | 165 +++ src/network/bridge_driver.h | 10 ++- src/qemu/qemu_command.c | 32 ++--- src/qemu/qemu_process.c | 12 +++ 9 files changed, 225 insertions(+), 14 deletions(-) create mode 100644 src/libvirt_network.syms diff --git a/src/Makefile.am b/src/Makefile.am index 1f32263..9b14ef8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1366,6 +1366,10 @@ if WITH_ATOMIC_OPS_PTHREAD USED_SYM_FILES += libvirt_atomic.syms endif +if WITH_NETWORK +USED_SYM_FILES += libvirt_network.syms +endif + EXTRA_DIST += \ libvirt_public.syms\ libvirt_private.syms \ @@ -1379,7 +1383,8 @@ EXTRA_DIST += \ libvirt_sasl.syms \ libvirt_vmx.syms \ libvirt_xenxs.syms \ - libvirt_libssh2.syms + libvirt_libssh2.syms \ + libvirt_network.syms GENERATED_SYM_FILES = libvirt.syms libvirt.def libvirt_qemu.def diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 091879e..09c705a 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -862,6 +862,7 @@ struct _virDomainNetDef { virNetDevBandwidthPtr bandwidth; virNetDevVlan vlan; int linkstate; +unsigned int class_id; /* Class ID for 'floor' */ }; /* Used for prefix of ifname of any network name generated dynamically diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c index 41831e0..80189e6 100644 --- a/src/conf/network_conf.c +++ b/src/conf/network_conf.c @@ -318,6 +318,7 @@ virNetworkAssignDef(virNetworkObjListPtr nets, } virNetworkObjLock(network); network-def = def; +network-class_id = 3; /* next free class id */ I don't really like the magic number characteristic of the 3 here. Can we give this a #define or something? nets-objs[nets-count] = network; nets-count++; diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h index 3e46304..8a8d1e4 100644 --- a/src/conf/network_conf.h +++ b/src/conf/network_conf.h @@ -221,6 +221,9 @@ struct _virNetworkObj { virNetworkDefPtr def; /* The current definition */ virNetworkDefPtr newDef; /* New definition to activate at shutdown */ + +unsigned int class_id; /* next class ID for QoS */ Okay, so this is just a monotonically increasing counter so that each interface gets a new and different class_id. Maybe you should call it nextFreeClassID or something like that, so that everyone understands it's not a class id used by the network. Or you might want to do this with a bitmap so you can re-use id's of interfaces that are disconnected. (can virBitmaps being dynamically expanded?) +unsigned long long floor_sum; /* sum of all 'floor'-s of attached NICs */ And you keep track of the sum of all floors here. So, what happens if libvirtd is restarted? It looks like they both go back to their initial values. And what about hotplug? This is a similar problem to the pool of interfaces used by macvtap/hostdev modes - a network with an interface pool needs to have the inuse counters of each interface refreshed whenever libvirtd restarts. So the necessary hooks are already in place: networkAllocateActualDevice - called any time an interface with type='network' is initially allocated and connected. networkNotifyActualDevice - called for each type='network' interface of each active domain any time libvirtd restarts networkReleaseActualDevice - called for every type='network' interface as it is being disconnected and destroyed. These are called for *all* type='network' interfaces, not just those that need to allocate a physical netdev from a pool. Rather than adding your own new hooks (and figuring out all the places they need to be called), I think it would be better to use the existing hooks (perhaps calling a reduced/renamed version of your functions, which can possibly be moved over to ). That will have two advantages: 1) It will assure that the bandwidth functions are called at all the right times, including hotplug/unplug, and libvirtd restart 2) It will continue the process of consolidating all network-related functionality need for these three events into 3 functions which may some day be moved into their own daemom with a public (within libvirt anyway) API accessible via RPC (thus allowing non-privileged libvirts to have full networking functionality). Note that you will probably want to save the interface class_id in the iface-actual (as a matter of fact, in
Re: [libvirt] [PATCH] Allow comma separated list of shutdown/reboot modes with virsh
On Fri, Nov 30, 2012 at 11:05:25AM -0500, Eric Blake wrote: The shutdown and reboot commands in virsh allow a comma separated list of mode values Signed-off-by: Daniel P. Berrange berra...@redhat.com --- tools/virsh-domain.c | 25 +++-- tools/virsh.pod | 16 2 files changed, 35 insertions(+), 6 deletions(-) -if (mode) { +if (!(modes = virStringSplit(mode, ,, 0))) { Any reason you can't use vshStringToArray to do the split? I didn't know it existed - utility functions like that shouldn't be in virsh code anyway. Now I know it exists, I'll kill it off in favour of virStringSplit everywhere. Daniel -- |: http://berrange.com -o-http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] Fix uninitialized variables
On Fri, Nov 30, 2012 at 07:13:01PM +0100, Guido Günther wrote: detecet by s/detecet/detected/ [oh well, pushed already] -- Eric Blake ebl...@redhat.com+1-919-301-3266 Libvirt virtualization library http://libvirt.org -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] Introduce APIs for splitting/joining strings
On Fri, Nov 30, 2012 at 11:02:40AM -0500, Eric Blake wrote: This introduces a few new APIs for dealing with strings. One to split a char * into a char **, another to join a char ** into a char *, and finally one to free a char ** Do we also want to migrate virsh.c:vshStringToArray() to this file, with its additional magic of supporting ',,' as an escape sequence for literal comma in one of the strings being split? I don't really like that magic escape behaviour for a general purpose string splitting function. IMHO if the thing being split needs to use ',' then the delimitor should be changed. +char *virStringJoin(const char **strings, +const char *delim) +{ Should this function have a third argument that says how many elements are in strings (and leave it 0 if strings is NULL-terminated)? Otherwise, callers will have to ensure that there is a trailing NULL element in strings, instead of being able to specifically request the joining of an exact amount of strings. I don't much like the idea of having one API that deals with two different ways of representing the array bounds. If we want explicited sized arrays, I think it'd be nicer to have a parallel set of APIs todo that (albeit sharing internal impl where appropriate) +size_t len = 0; +size_t delimlen = strlen(delim); +const char **tmp = strings; +char *string; +char *offset; + +while (tmp *tmp) { +len += strlen(*tmp); +len += delimlen; +tmp++; +} Would it be any easier to write this function in terms of virBuffer, instead of rolling it by hand? Untested: char *virStringJoin(const char **strings, const char *delim) { virBuffer buf = VIR_BUFFER_INITIALIZER; if (strings *strings) { virBufferAdd(buf, *strings, 0); while (*++strings) { virBufferAdd(buf, delim, 0); virBufferAdd(*strings); } } return virBufferContentAndReset(buf); } I guess there's not much difference in efficiency there it is shorter, so why not. +char **virStringSplit(const char *string, + const char *delim, + size_t max_tokens); Worth marking ATTRIBUTE_NONNULL(2)? It looks like you intend to allow NULL for arg 1 though (in which case the return is also NULL). We shouldn't allow NULL for arg 1, since then a NULL return value can be either an error or valid, depending on the parameters, which has unpleasant semantics. Daniel -- |: http://berrange.com -o-http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] Fix uninitialized variables
On Fri, Nov 30, 2012 at 06:38:31PM +, Daniel P. Berrange wrote: On Fri, Nov 30, 2012 at 07:13:01PM +0100, Guido Günther wrote: detecet by http://honk.sigxcpu.org:8001/job/libvirt-build/348/console --- Probably o.k. to push under the build breaker rule but I'd better check. Cheers, -- Guido src/qemu/qemu_monitor.c |4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index c1f7c41..f85bb76 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -2408,7 +2408,7 @@ int qemuMonitorRemoveHostNetwork(qemuMonitorPtr mon, int vlan, const char *netname) { -int ret; +int ret = -1; VIR_DEBUG(mon=%p netname=%s, mon, netname); @@ -2541,7 +2541,7 @@ int qemuMonitorAttachDrive(qemuMonitorPtr mon, mon, drivestr, controllerAddr-domain, controllerAddr-bus, controllerAddr-slot, controllerAddr-function); -int ret; +int ret = 1; if (!mon) { virReportError(VIR_ERR_INVALID_ARG, %s, ACK Build back to green. Thanks, -- Guido Daniel -- |: http://berrange.com -o-http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v1 06/11] network: Create real network status files
On 11/19/2012 11:51 AM, Michal Privoznik wrote: Currently, we are only keeping a inactive XML configuration in status dir. This is no longer enough as we need to keep this class_id attribute so we don't overwrite old entries when the daemon restarts. Aha! So you're looking at solving the problem in a different way - save everything to the status file rather than recomputing it as you restart. While I like the idea of having the network status file hold this information, I think its reliability is suspect. What if a guest's process is terminated while libvirtd isn't running? Or what if libvirtd exits unexpectedly after the commands to setup bandwidth have been executed, but before the new network state file has been written (or vice versa, depending on the code). Also, networks aren't properly shut down when the host is being shutdown (there's no equivalent to the libvirt-guests service, although at least one person a month or two ago requested it). If everybody agrees that saving this info to a file and re-reading it on start up is reliable, though, then we might as well do the same thing with the device pool (although it's currently a bit different - the inuse count is stored in the virNetworkDef rather than Obj, and is reported during net-dumpxml) However, since there has already been a libvirt release *a* libvirt release? :-) which has just network/ as root element, and we want to keep things compatible, detect that loaded status file is older one, and don't scream about it. --- src/conf/network_conf.c | 199 ++- src/conf/network_conf.h |2 + src/libvirt_private.syms|1 + src/network/bridge_driver.c |9 +-- 4 files changed, 165 insertions(+), 46 deletions(-) diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c index 80189e6..9c2e4d4 100644 --- a/src/conf/network_conf.c +++ b/src/conf/network_conf.c @@ -1645,6 +1645,78 @@ cleanup: return def; } +int +virNetworkObjUpdateParseFile(const char *filename, + virNetworkObjPtr net) +{ +int ret = -1; +xmlDocPtr xml = NULL; +xmlNodePtr node = NULL; +virNetworkDefPtr tmp = NULL; +xmlXPathContextPtr ctxt = NULL; + +xml = virXMLParse(filename, NULL, _((network status))); +if (!xml) +return -1; + +ctxt = xmlXPathNewContext(xml); +if (ctxt == NULL) { +virReportOOMError(); +goto cleanup; +} + +node = xmlDocGetRootElement(xml); +if (xmlStrEqual(node-name, BAD_CAST networkstatus)) { +/* Newer network status file. Contains useful + * info which are not to be found in bare config XML */ +char *class_id = NULL; +char *floor_sum = NULL; + +ctxt-node = node; +class_id = virXPathString(string(./class_id[1]/@next), ctxt); +if (class_id +virStrToLong_ui(class_id, NULL, 10, net-class_id) 0) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _(Malformed 'class_id' attribute: %s), + class_id); +VIR_FREE(class_id); +goto cleanup; +} +VIR_FREE(class_id); + +floor_sum = virXPathString(string(./floor[1]/@sum), ctxt); +if (floor_sum +virStrToLong_ull(floor_sum, NULL, 10, net-floor_sum) 0) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _(Malformed 'floor_sum' attribute: %s), + floor_sum); +VIR_FREE(floor_sum); +} +VIR_FREE(floor_sum); +} + +node = virXPathNode(//network, ctxt); +if (!node) { +virReportError(VIR_ERR_INTERNAL_ERROR, %s, + _(Could not find any 'network' element)); +goto cleanup; +} + +ctxt-node = node; +tmp = virNetworkDefParseXML(ctxt); + +if (tmp) { +net-newDef = net-def; +net-def = tmp; +} + +ret = 0; + +cleanup: +xmlXPathFreeContext(ctxt); +return ret; +} + static int virNetworkDNSDefFormat(virBufferPtr buf, virNetworkDNSDefPtr def) @@ -1823,24 +1895,26 @@ virPortGroupDefFormat(virBufferPtr buf, return 0; } -char *virNetworkDefFormat(const virNetworkDefPtr def, unsigned int flags) +static int +virNetworkDefFormatInternal(virBufferPtr buf, +const virNetworkDefPtr def, +unsigned int flags) { -virBuffer buf = VIR_BUFFER_INITIALIZER; unsigned char *uuid; char uuidstr[VIR_UUID_STRING_BUFLEN]; int ii; -virBufferAddLit(buf, network); +virBufferAddLit(buf, network); if (!(flags VIR_NETWORK_XML_INACTIVE) (def-connections 0)) { -virBufferAsprintf(buf, connections='%d', def-connections); +virBufferAsprintf(buf, connections='%d', def-connections);
Re: [libvirt] [PATCH] Allow comma separated list of shutdown/reboot modes with virsh
On Fri, Nov 30, 2012 at 02:01:53PM -0500, Eric Blake wrote: +if (!(modes = virStringSplit(mode, ,, 0))) { Any reason you can't use vshStringToArray to do the split? I didn't know it existed - utility functions like that shouldn't be in virsh code anyway. Now I know it exists, I'll kill it off in favour of virStringSplit everywhere. Except that vshStingToArray _also_ does ',,' unescaping, so that: a,b,,c,d is split into a, b,c, d, rather than a, b, , c, d so we'd still need a post-processing path after virStringSplit. Well, which users of vshStringToArray actually need that feature ? IIUC, the only ones are those which accept arbitrary user strings, which is only 1/2 users in virsh. The rest can use the new API with no practical loss in functionality, since they use fixed strings where ',' is not used. Daniel -- |: http://berrange.com -o-http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] Allow comma separated list of shutdown/reboot modes with virsh
+if (!(modes = virStringSplit(mode, ,, 0))) { Any reason you can't use vshStringToArray to do the split? I didn't know it existed - utility functions like that shouldn't be in virsh code anyway. Now I know it exists, I'll kill it off in favour of virStringSplit everywhere. Except that vshStingToArray _also_ does ',,' unescaping, so that: a,b,,c,d is split into a, b,c, d, rather than a, b, , c, d so we'd still need a post-processing path after virStringSplit. -- Eric Blake ebl...@redhat.com+1-919-301-3266 Libvirt virtualization library http://libvirt.org -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] qemu: Fix up the default machine type for QMP probing
The default machine type must be stored in the first element of the caps-machineTypes array. This was done for help output parsing but not for QMP probing. Added a helper function qemuSetDefaultMachine to apply the same fix up for both probing methods. Further, it was necessary to set caps-nmachineTypes after QMP probing. Signed-off-by: Viktor Mihajlovski mihaj...@linux.vnet.ibm.com --- src/qemu/qemu_capabilities.c | 38 ++ 1 files changed, 26 insertions(+), 12 deletions(-) ACK and pushed. -- Eric Blake ebl...@redhat.com+1-919-301-3266 Libvirt virtualization library http://libvirt.org -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH] Quote client identity in SASL whitelist log message
From: Daniel P. Berrange berra...@redhat.com When seeing a message virNetSASLContextCheckIdentity:146 : SASL client admin not allowed in whitelist it isn't immediately obvious that 'admin' is the identity being checked. Quote the string to make it more obvious Pushed under trivial rule --- src/rpc/virnetsaslcontext.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rpc/virnetsaslcontext.c b/src/rpc/virnetsaslcontext.c index 3001871..b6b68d5 100644 --- a/src/rpc/virnetsaslcontext.c +++ b/src/rpc/virnetsaslcontext.c @@ -163,7 +163,7 @@ int virNetSASLContextCheckIdentity(virNetSASLContextPtr ctxt, } /* Denied */ -VIR_ERROR(_(SASL client %s not allowed in whitelist), identity); +VIR_ERROR(_(SASL client identity '%s' not allowed in whitelist), identity); /* This is the most common error: make it informative. */ virReportError(VIR_ERR_SYSTEM_ERROR, %s, -- 1.7.11.7 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH] Ensure virDomainShutdownFlags logs flags parameter
From: Daniel P. Berrange berra...@redhat.com Pushed under trivial rule Signed-off-by: Daniel P. Berrange berra...@redhat.com --- src/libvirt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libvirt.c b/src/libvirt.c index 757bfa8..955e761 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -3246,7 +3246,7 @@ virDomainShutdownFlags(virDomainPtr domain, unsigned int flags) { virConnectPtr conn; -VIR_DOMAIN_DEBUG(domain); +VIR_DOMAIN_DEBUG(domain, flags=%u, flags); virResetLastError(); -- 1.7.11.7 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH] Allow duration=0 for virsh nodesuspend
From: Daniel P. Berrange berra...@redhat.com The virNodeSuspend API allows for a duration of 0, to mean no timed wakup. virsh needlessly forbids this though Signed-off-by: Daniel P. Berrange berra...@redhat.com --- tools/virsh-domain.c | 34 -- tools/virsh-host.c | 2 +- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index 3ca246b..9f1a3d4 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -4030,8 +4030,8 @@ static const vshCmdOptDef opts_shutdown[] = { static bool cmdShutdown(vshControl *ctl, const vshCmd *cmd) { -virDomainPtr dom; -bool ret = true; +virDomainPtr dom = NULL; +bool ret = false; const char *name; const char *mode = NULL; int flags = 0; @@ -4062,14 +4062,13 @@ cmdShutdown(vshControl *ctl, const vshCmd *cmd) } else { vshError(ctl, _(Unknown mode %s value, expecting 'acpi', 'agent', 'initctl' or 'signal'), mode); -return false; +goto cleanup; } tmp++; } -virStringFreeList(modes); if (!(dom = vshCommandOptDomain(ctl, cmd, name))) -return false; +goto cleanup; if (flags) rv = virDomainShutdownFlags(dom, flags); @@ -4079,10 +4078,14 @@ cmdShutdown(vshControl *ctl, const vshCmd *cmd) vshPrint(ctl, _(Domain %s is being shutdown\n), name); } else { vshError(ctl, _(Failed to shutdown domain %s), name); -ret = false; +goto cleanup; } -virDomainFree(dom); +ret = true; +cleanup: +if (dom) +virDomainFree(dom); +virStringFreeList(modes); return ret; } @@ -4104,8 +4107,8 @@ static const vshCmdOptDef opts_reboot[] = { static bool cmdReboot(vshControl *ctl, const vshCmd *cmd) { -virDomainPtr dom; -bool ret = true; +virDomainPtr dom = NULL; +bool ret = false; const char *name; const char *mode = NULL; int flags = 0; @@ -4135,23 +4138,26 @@ cmdReboot(vshControl *ctl, const vshCmd *cmd) } else { vshError(ctl, _(Unknown mode %s value, expecting 'acpi', 'agent', 'initctl' or 'signal'), mode); -return false; +goto cleanup; } tmp++; } -virStringFreeList(modes); if (!(dom = vshCommandOptDomain(ctl, cmd, name))) -return false; +goto cleanup; if (virDomainReboot(dom, flags) == 0) { vshPrint(ctl, _(Domain %s is being rebooted\n), name); } else { vshError(ctl, _(Failed to reboot domain %s), name); -ret = false; +goto cleanup; } -virDomainFree(dom); +ret = true; +cleanup: +if (dom) +virDomainFree(dom); +virStringFreeList(modes); return ret; } diff --git a/tools/virsh-host.c b/tools/virsh-host.c index 3701f56..3d13e01 100644 --- a/tools/virsh-host.c +++ b/tools/virsh-host.c @@ -537,7 +537,7 @@ cmdNodeSuspend(vshControl *ctl, const vshCmd *cmd) return false; } -if (duration = 0) { +if (duration 0) { vshError(ctl, %s, _(Invalid duration)); return false; } -- 1.7.11.7 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] Allow duration=0 for virsh nodesuspend
From: Daniel P. Berrange berra...@redhat.com The virNodeSuspend API allows for a duration of 0, to mean no timed wakup. virsh needlessly forbids this though Signed-off-by: Daniel P. Berrange berra...@redhat.com --- tools/virsh-domain.c | 34 -- tools/virsh-host.c | 2 +- 2 files changed, 21 insertions(+), 15 deletions(-) Looks like you mixed two commits: diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index 3ca246b..9f1a3d4 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -4030,8 +4030,8 @@ static const vshCmdOptDef opts_shutdown[] = { static bool cmdShutdown(vshControl *ctl, const vshCmd *cmd) { -virDomainPtr dom; -bool ret = true; +virDomainPtr dom = NULL; +bool ret = false; One for improving reboot/shutdown mode handling... diff --git a/tools/virsh-host.c b/tools/virsh-host.c index 3701f56..3d13e01 100644 --- a/tools/virsh-host.c +++ b/tools/virsh-host.c @@ -537,7 +537,7 @@ cmdNodeSuspend(vshControl *ctl, const vshCmd *cmd) return false; } -if (duration = 0) { +if (duration 0) { ...and the actual intended commit. ACK to just this hunk, and save the rest for your mode handling improvements. -- Eric Blake ebl...@redhat.com+1-919-301-3266 Libvirt virtualization library http://libvirt.org -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v2] Introduce APIs for splitting/joining strings
From: Daniel P. Berrange berra...@redhat.com This introduces a few new APIs for dealing with strings. One to split a char * into a char **, another to join a char ** into a char *, and finally one to free a char ** There is a simple test suite to validate the edge cases too. No more need to use the horrible strtok_r() API, or hand-written code for splitting strings. Signed-off-by: Daniel P. Berrange berra...@redhat.com --- .gitignore | 1 + src/Makefile.am | 1 + src/libvirt_private.syms | 6 ++ src/util/virstring.c | 168 +++ src/util/virstring.h | 38 +++ tests/Makefile.am| 6 ++ tests/virstringtest.c| 162 + 7 files changed, 382 insertions(+) create mode 100644 src/util/virstring.c create mode 100644 src/util/virstring.h create mode 100644 tests/virstringtest.c diff --git a/.gitignore b/.gitignore index 12fbe0e..0dadd21 100644 --- a/.gitignore +++ b/.gitignore @@ -170,6 +170,7 @@ /tests/virlockspacetest /tests/virnet*test /tests/virshtest +/tests/virstringtest /tests/virtimetest /tests/viruritest /tests/vmx2xmltest diff --git a/src/Makefile.am b/src/Makefile.am index 6401dec..b5c20c8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -112,6 +112,7 @@ UTIL_SOURCES = \ util/virnetlink.c util/virnetlink.h \ util/virrandom.h util/virrandom.c \ util/virsocketaddr.h util/virsocketaddr.c \ + util/virstring.h util/virstring.c \ util/virtime.h util/virtime.c \ util/viruri.h util/viruri.c diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 93a21cc..08974d0 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1812,6 +1812,12 @@ virSetErrorLogPriorityFunc; virStrerror; +# virstring.h +virStringSplit; +virStringJoin; +virStringFreeList; + + # virtime.h virTimeFieldsNow; virTimeFieldsNowRaw; diff --git a/src/util/virstring.c b/src/util/virstring.c new file mode 100644 index 000..1917e9a --- /dev/null +++ b/src/util/virstring.c @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2012 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * http://www.gnu.org/licenses/. + * + * Authors: + * Daniel P. Berrange berra...@redhat.com + */ + +#include config.h + +#include virstring.h +#include memory.h +#include buf.h +#include virterror_internal.h + +#define VIR_FROM_THIS VIR_FROM_NONE + +/* + * The following virStringSplit virStringJoin methods + * are derived from g_strsplit / g_strjoin in glib2, + * also available under the LGPLv2+ license terms + */ + +/** + * virStringSplit: + * @string: a string to split + * @delim: a string which specifies the places at which to split + * the string. The delimiter is not included in any of the resulting + * strings, unless @max_tokens is reached. + * @max_tokens: the maximum number of pieces to split @string into. + * If this is 0, the string is split completely. + * + * Splits a string into a maximum of @max_tokens pieces, using the given + * @delim. If @max_tokens is reached, the remainder of @string is + * appended to the last token. + * + * As a special case, the result of splitting the empty string is an empty + * vector, not a vector containing a single string. The reason for this + * special case is that being able to represent a empty vector is typically + * more useful than consistent handling of empty elements. If you do need + * to represent empty elements, you'll need to check for the empty string + * before calling virStringSplit(). + * + * Return value: a newly-allocated NULL-terminated array of strings. Use + *virStringFreeList() to free it. + */ +char **virStringSplit(const char *string, + const char *delim, + size_t max_tokens) +{ +char **tokens = NULL; +size_t ntokens = 0; +size_t maxtokens = 0; +const char *remainder = string; +char *tmp; +size_t i; + +if (max_tokens == 0) +max_tokens = INT_MAX; + +tmp = strstr(remainder, delim); +if (tmp) { +size_t delimlen = strlen(delim); + +while (--max_tokens tmp) { +size_t len = tmp - remainder; + +if
Re: [libvirt] [PATCH] Allow comma separated list of shutdown/reboot modes with virsh
so we'd still need a post-processing path after virStringSplit. Well, which users of vshStringToArray actually need that feature ? Commit 9d91a18 merged ,, into vshStringToArray out of a single caller, vshParseSnapshotDiskspec; then commit 2cd4d8e added another caller vshParseSnapshotMemspec. All other callers don't need it. IIUC, the only ones are those which accept arbitrary user strings, which is only 1/2 users in virsh. The rest can use the new API with no practical loss in functionality, since they use fixed strings where ',' is not used. That works for me. -- Eric Blake ebl...@redhat.com+1-919-301-3266 Libvirt virtualization library http://libvirt.org -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v2] Introduce APIs for splitting/joining strings
This introduces a few new APIs for dealing with strings. One to split a char * into a char **, another to join a char ** into a char *, and finally one to free a char ** There is a simple test suite to validate the edge cases too. No more need to use the horrible strtok_r() API, or hand-written code for splitting strings. Signed-off-by: Daniel P. Berrange berra...@redhat.com --- ACK; you addressed my findings from v1. -- Eric Blake ebl...@redhat.com+1-919-301-3266 Libvirt virtualization library http://libvirt.org -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v2] Allow comma separated list of shutdown/reboot modes with virsh
From: Daniel P. Berrange berra...@redhat.com The shutdown and reboot commands in virsh allow a comma separated list of mode values Signed-off-by: Daniel P. Berrange berra...@redhat.com --- tools/virsh-domain.c | 25 +++-- tools/virsh.pod | 16 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index a7ffd2b..3ca246b 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -48,6 +48,7 @@ #include virfile.h #include virkeycode.h #include virmacaddr.h +#include virstring.h #include virsh-domain-monitor.h #include virterror_internal.h #include virtypedparam.h @@ -4035,13 +4036,21 @@ cmdShutdown(vshControl *ctl, const vshCmd *cmd) const char *mode = NULL; int flags = 0; int rv; +char **modes, **tmp; if (vshCommandOptString(cmd, mode, mode) 0) { vshError(ctl, %s, _(Invalid type)); return false; } -if (mode) { +if (!(modes = virStringSplit(mode, ,, 0))) { +vshError(ctl, %s, _(Cannot parse mode string)); +return false; +} + +tmp = modes; +while (*tmp) { +mode = *tmp; if (STREQ(mode, acpi)) { flags |= VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN; } else if (STREQ(mode, agent)) { @@ -4055,7 +4064,9 @@ cmdShutdown(vshControl *ctl, const vshCmd *cmd) 'acpi', 'agent', 'initctl' or 'signal'), mode); return false; } +tmp++; } +virStringFreeList(modes); if (!(dom = vshCommandOptDomain(ctl, cmd, name))) return false; @@ -4098,13 +4109,21 @@ cmdReboot(vshControl *ctl, const vshCmd *cmd) const char *name; const char *mode = NULL; int flags = 0; +char **modes, **tmp; if (vshCommandOptString(cmd, mode, mode) 0) { vshError(ctl, %s, _(Invalid type)); return false; } -if (mode) { +if (!(modes = virStringSplit(mode, ,, 0))) { +vshError(ctl, %s, _(Cannot parse mode string)); +return false; +} + +tmp = modes; +while (*tmp) { +mode = *tmp; if (STREQ(mode, acpi)) { flags |= VIR_DOMAIN_REBOOT_ACPI_POWER_BTN; } else if (STREQ(mode, agent)) { @@ -4118,7 +4137,9 @@ cmdReboot(vshControl *ctl, const vshCmd *cmd) 'acpi', 'agent', 'initctl' or 'signal'), mode); return false; } +tmp++; } +virStringFreeList(modes); if (!(dom = vshCommandOptDomain(ctl, cmd, name))) return false; diff --git a/tools/virsh.pod b/tools/virsh.pod index c901b11..7dde3df 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -1137,7 +1137,7 @@ If I--live is specified, set scheduler information of a running guest. If I--config is specified, affect the next boot of a persistent guest. If I--current is specified, affect the current guest state. -=item Breboot Idomain [I--mode acpi|agent] +=item Breboot Idomain [I--mode MODE-LIST] Reboot a domain. This acts just as if the domain had the Breboot command run from the console. The command returns as soon as it has @@ -1149,7 +1149,11 @@ Ion_reboot parameter in the domain's XML definition. By default the hypervisor will try to pick a suitable shutdown method. To specify an alternative method, the I--mode parameter -can specify Cacpi or Cagent. +can specify a comma separated list which includes Cacpi, Cagent, +Cinitctl and Csignal. The order in which drivers will try each +mode is undefined, and not related to the order specified to virsh. +For strict control over ordering, use a single mode at a time and +repeat the command. =item Breset Idomain @@ -1567,7 +1571,7 @@ The I--maximum flag controls the maximum number of virtual cpus that can be hot-plugged the next time the domain is booted. As such, it must only be used with the I--config flag, and not with the I--live flag. -=item Bshutdown Idomain [I--mode acpi|agent] +=item Bshutdown Idomain [I--mode MODE-LIST] Gracefully shuts down a domain. This coordinates with the domain OS to perform graceful shutdown, so there is no guarantee that it will @@ -1584,7 +1588,11 @@ snapshot metadata with Bsnapshot-create. By default the hypervisor will try to pick a suitable shutdown method. To specify an alternative method, the I--mode parameter -can specify Cacpi or Cagent. +can specify a comma separated list which includes Cacpi, Cagent, +Cinitctl and Csignal. The order in which drivers will try each +mode is undefined, and not related to the order specified to virsh. +For strict control over ordering, use a single mode at a time and +repeat the command. =item Bstart Idomain-name-or-uuid [I--console] [I--paused] [I--autodestroy] [I--bypass-cache] [I--force-boot] -- 1.7.11.7 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v2] Allow comma separated list of shutdown/reboot modes with virsh
From: Daniel P. Berrange berra...@redhat.com The shutdown and reboot commands in virsh allow a comma separated list of mode values Signed-off-by: Daniel P. Berrange berra...@redhat.com --- tools/virsh-domain.c | 25 +++-- tools/virsh.pod | 16 2 files changed, 35 insertions(+), 6 deletions(-) Conditional ACK, if you squash in the hunk that got misplaced in your duration==0 patch. -- Eric Blake ebl...@redhat.com+1-919-301-3266 Libvirt virtualization library http://libvirt.org -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] implement managedsave in libvirt xen legacy driver
Bamvor Jian Zhang wrote: Implement the domainManagedSave, domainHasManagedSaveImage, and domainManagedSaveRemove functions in the libvirt legacy xen driver. Cool, thanks for the patch! In case others are interested, one motivation for adding this functionality in the legacy xen driver is to avoid xen-only hacks in the nova libvirt driver. domainHasManagedSaveImage check the managedsave image from filesystem everytime. This is different from qemu and libxl driver. In qemu or libxl driver, there is a hasManagesSave flags in virDomainObjPtr which is not used in xen legacy driver. This flag could not add into xen driver ptr either, because the driver ptr will be release at the end of every libvirt api calls. Meanwhile, AFAIK, xen store all the flags in xen not in libvirt xen driver. There is no need to add this flags in xen. I think checking the filesystem is the only way to go since xend doesn't have the notion of managedsave. Do others see any issues with this approach? --- i have test the following case for this patch: 1), virsh managedsave save domain to /var/lib/xen/save/domain_name.save. call xenUnifiedDomainManagedSave. 2), virsh start: if managedsave image is exist, it should be boot from managed save image. call xenUnifiedDomainHasManagedSaveImage. 3), virsh start --force-boot: fresh boot, delete the managed save image if exists. call xenUnifiedDomainHasManagedSaveImage, xenUnifiedDomainManagedSaveRemove. 4), virsh managedsave-remove: remove managed save image. call xenUnifiedDomainManagedSaveRemove 5), virsh undefine: undefine the domain, it will fail if mananed save image exist. call xenUnifiedDomainHasManagedSaveImage. 6), virsh undefine --managed-save: undefine the domain, and remove mananed save image. call xenUnifiedDomainHasManagedSaveImage and xenUnifiedDomainManagedSaveRemove. 7), virsh list --all --with-managed-save. list domain if managed save image exist. got nothing if non-exists. call xenUnifiedDomainHasManagedSaveImage. 8), virsh list --all --without-managed-save. do not list the domain if managed save image exist. call xenUnifiedDomainHasManagedSaveImage. Thanks for including your test cases. I've tried these on your patch as well and looks good! src/xen/xen_driver.c | 109 ++- src/xen/xen_driver.h | 2 + 2 files changed, 110 insertions(+), 1 deletion(-) diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c index 5a40757..0b2418d 100644 --- a/src/xen/xen_driver.c +++ b/src/xen/xen_driver.c @@ -67,6 +67,7 @@ #include nodeinfo.h #define VIR_FROM_THIS VIR_FROM_XEN +#define XEN_SAVE_DIR LOCALSTATEDIR /lib/libvirt/xen/save #include configmake.h is needed for LOCALSTATEDIR static int xenUnifiedNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info); @@ -267,6 +268,7 @@ xenUnifiedOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags) { int i, ret = VIR_DRV_OPEN_DECLINED; xenUnifiedPrivatePtr priv; +char ebuf[1024]; #ifdef __sun /* @@ -406,6 +408,17 @@ xenUnifiedOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags) } #endif +if (virAsprintf(priv-saveDir, %s, XEN_SAVE_DIR) == -1) { +virReportOOMError(); +goto fail; +} + +if (virFileMakePath(priv-saveDir) 0) { +VIR_ERROR(_(Failed to create save dir '%s': %s), priv-saveDir, + virStrerror(errno, ebuf, sizeof(ebuf))); +goto fail; +} + return VIR_DRV_OPEN_SUCCESS; fail: @@ -437,6 +450,7 @@ xenUnifiedClose(virConnectPtr conn) if (priv-opened[i]) drivers[i]-xenClose(conn); +VIR_FREE(priv-saveDir); virMutexDestroy(priv-lock); VIR_FREE(conn-privateData); @@ -1080,6 +1094,79 @@ xenUnifiedDomainSave(virDomainPtr dom, const char *to) return xenUnifiedDomainSaveFlags(dom, to, NULL, 0); } +static char * +xenUnifiedDomainManagedSavePath(xenUnifiedPrivatePtr priv, virDomainPtr dom) +{ +char *ret; + +if (virAsprintf(ret, %s/%s.save, priv-saveDir, dom-name) 0) { +virReportOOMError(); +return NULL; +} + +VIR_DEBUG(managed save image: %s, ret); +return ret; +} + +static int +xenUnifiedDomainManagedSave(virDomainPtr dom, unsigned int flags) +{ +GET_PRIVATE(dom-conn); +char *name; +int ret = -1; + +virCheckFlags(0, -1); + +name = xenUnifiedDomainManagedSavePath(priv, dom); +if (!name) +goto cleanup; + +if (priv-opened[XEN_UNIFIED_XEND_OFFSET]) +ret = xenDaemonDomainSave(dom, name); + +cleanup: +VIR_FREE(name); +return ret; +} + +static int +xenUnifiedDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags) +{ +GET_PRIVATE(dom-conn); +char *name; +int ret = -1; + +virCheckFlags(0, -1); + +name = xenUnifiedDomainManagedSavePath(priv, dom); +if
Re: [libvirt] [PATCH] qemu: Fix up the default machine type for QMP probing
On 11/30/2012 07:58 PM, Eric Blake wrote: The default machine type must be stored in the first element of the caps-machineTypes array. This was done for help output parsing but not for QMP probing. Added a helper function qemuSetDefaultMachine to apply the same fix up for both probing methods. Further, it was necessary to set caps-nmachineTypes after QMP probing. Signed-off-by: Viktor Mihajlovski mihaj...@linux.vnet.ibm.com --- src/qemu/qemu_capabilities.c | 38 ++ 1 files changed, 26 insertions(+), 12 deletions(-) ACK and pushed. Thanks... -- Mit freundlichen Grüßen/Kind Regards Viktor Mihajlovski IBM Deutschland Research Development GmbH Vorsitzender des Aufsichtsrats: Martin Jetter Geschäftsführung: Dirk Wittkopp Sitz der Gesellschaft: Böblingen Registergericht: Amtsgericht Stuttgart, HRB 243294 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v1 07/11] domain: Keep assigned class_id in domstatus XML
On 11/19/2012 11:51 AM, Michal Privoznik wrote: Interfaces keeps a class_id, which is an ID from which bridge part of QoS settings is derived. We need to store class_id in domain status file, so we can later pass it to virNetDevBandwidthUnplug. Interesting use of alias to find the original interface matching the class_id. But we already have a status-only subelement in every type='network' interface, so it will be much simpler to just store it there (conveniently in the bandwidth object, as I suggested in an earlier patch). (if actual wasn't already saved within interface, I might have considered doing it this way, but that ship has already sailed.) --- src/conf/domain_conf.c |4 +- src/qemu/qemu_domain.c | 66 --- 2 files changed, 63 insertions(+), 7 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index bf23b77..37a8875 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -10242,7 +10242,7 @@ static virDomainObjPtr virDomainObjParseXML(virCapsPtr caps, VIR_FREE(nodes); if (caps-privateDataXMLParse -((caps-privateDataXMLParse)(ctxt, obj-privateData)) 0) +((caps-privateDataXMLParse)(ctxt, obj)) 0) goto error; return obj; @@ -14212,7 +14212,7 @@ static char *virDomainObjFormat(virCapsPtr caps, } if (caps-privateDataXMLFormat -((caps-privateDataXMLFormat)(buf, obj-privateData)) 0) +((caps-privateDataXMLFormat)(buf, obj)) 0) goto error; virBufferAdjustIndent(buf, 2); diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index e0d6951..5312946 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -258,9 +258,12 @@ static void qemuDomainObjPrivateFree(void *data) static int qemuDomainObjPrivateXMLFormat(virBufferPtr buf, void *data) { -qemuDomainObjPrivatePtr priv = data; +virDomainObjPtr vm = data; +qemuDomainObjPrivatePtr priv = vm-privateData; const char *monitorpath; enum qemuDomainJob job; +bool do_class_id = false; +int i; /* priv-monitor_chr is set only for qemu */ if (priv-monConfig) { @@ -283,7 +286,6 @@ static int qemuDomainObjPrivateXMLFormat(virBufferPtr buf, void *data) if (priv-nvcpupids) { -int i; virBufferAddLit(buf, vcpus\n); for (i = 0 ; i priv-nvcpupids ; i++) { virBufferAsprintf(buf, vcpu pid='%d'/\n, priv-vcpupids[i]); @@ -292,7 +294,6 @@ static int qemuDomainObjPrivateXMLFormat(virBufferPtr buf, void *data) } if (priv-caps) { -int i; virBufferAddLit(buf, qemuCaps\n); for (i = 0 ; i QEMU_CAPS_LAST ; i++) { if (qemuCapsGet(priv-caps, i)) { @@ -326,15 +327,36 @@ static int qemuDomainObjPrivateXMLFormat(virBufferPtr buf, void *data) if (priv-fakeReboot) virBufferAsprintf(buf, fakereboot/\n); +for (i = 0; i vm-def-nnets; i++) { +if (vm-def-nets[i]-class_id) { +do_class_id = true; +break; +} +} + +if (do_class_id) { +virBufferAddLit(buf, class_id\n); +for (; i vm-def-nnets; i++) { +virDomainNetDefPtr iface = vm-def-nets[i]; +if (iface-class_id) { +virBufferAsprintf(buf, interface alias='%s' + class_id='%u'/\n, + iface-info.alias, iface-class_id); +} +} +virBufferAddLit(buf, /class_id\n); +} + return 0; } static int qemuDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt, void *data) { -qemuDomainObjPrivatePtr priv = data; +virDomainObjPtr vm = data; +qemuDomainObjPrivatePtr priv = vm-privateData; char *monitorpath; char *tmp; -int n, i; +int n, i, ii; xmlNodePtr *nodes = NULL; qemuCapsPtr caps = NULL; @@ -471,6 +493,40 @@ static int qemuDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt, void *data) priv-fakeReboot = virXPathBoolean(boolean(./fakereboot), ctxt) == 1; +if ((n = virXPathNodeSet(./class_id/interface, ctxt, nodes)) 0) +goto error; + +for (i = 0; i n; i++) { +char *alias = virXMLPropString(nodes[i], alias); +char *class_id = virXMLPropString(nodes[i], class_id); +virDomainNetDefPtr iface = NULL; +if (alias class_id) { +for (ii = 0; ii vm-def-nnets; ii++) { +if (STREQ(vm-def-nets[ii]-info.alias, alias)) { +iface = vm-def-nets[ii]; +break; +} +} + +if (!iface) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _(No such interface '%s'), + alias); +VIR_FREE(alias);
Re: [libvirt] [PATCH v2] Allow comma separated list of shutdown/reboot modes with virsh
On Fri, Nov 30, 2012 at 02:28:53PM -0500, Eric Blake wrote: From: Daniel P. Berrange berra...@redhat.com The shutdown and reboot commands in virsh allow a comma separated list of mode values Signed-off-by: Daniel P. Berrange berra...@redhat.com --- tools/virsh-domain.c | 25 +++-- tools/virsh.pod | 16 2 files changed, 35 insertions(+), 6 deletions(-) Conditional ACK, if you squash in the hunk that got misplaced in your duration==0 patch. Opps, yes, rebase mistake. Will fix when pushing Daniel -- |: http://berrange.com -o-http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v1 08/11] network: Update status file on (un)plug
On 11/19/2012 11:51 AM, Michal Privoznik wrote: Status file keeps track of class_id and floor_sum. It's better to keep it updated in case libvirtd is killed. I'm not sure why you're doing this type of iterative improvement in separate patches. Since you would want this functionality in any working version of the code, and you haven't already pushed the earlier versions, why not just do it in the original patch that introduces these functions? Likewise, doing part of the functionality, then a bit of infrastructure to allow the new functionality to work better, and then another patch to improve the new functionality makes it a bit of a treasure hunt to review; I like to make my patchsets so that the first patches contain all the improvements/changes to existing infrastructure that will be needed, then the following patches introduce the new code, fully functioning from the beginning. --- src/network/bridge_driver.c | 14 ++ 1 files changed, 14 insertions(+), 0 deletions(-) diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 8dc9d19..5a0f43f 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -4300,6 +4300,15 @@ networkNotifyPlug(virNetworkPtr network, net-class_id++; /* update sum of 'floor'-s of attached NICs */ net-floor_sum += iface-bandwidth-in-floor; +/* update status file */ +if (virNetworkSaveStatus(NETWORK_STATE_DIR, net) 0) { +net-class_id--; +net-floor_sum -= iface-bandwidth-in-floor; +iface-class_id = 0; +ignore_value(virNetDevBandwidthUnplug(net-def-bridge, + net-class_id)); +goto cleanup; +} /* update rate for non guaranteed NICs */ new_rate -= net-floor_sum; if (virNetDevBandwidthUpdateRate(net-def-bridge, 1:2, @@ -4339,6 +4348,11 @@ networkNotifyUnplug(virDomainNetDefPtr iface) goto cleanup; /* update sum of 'floor'-s of attached NICs */ net-floor_sum -= iface-bandwidth-in-floor; +/* update status file */ +if (virNetworkSaveStatus(NETWORK_STATE_DIR, net) 0) { +net-floor_sum += iface-bandwidth-in-floor; +goto cleanup; +} /* update rate for non guaranteed NICs */ new_rate -= net-floor_sum; if (virNetDevBandwidthUpdateRate(net-def-bridge, 1:2, -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH] logging: more API needing to log flags
Commit a21f5112 fixed one API, but missed two others that also failed to log their 'flags' argument. * src/libvirt.c (virNodeSuspendForDuration, virDomainGetHostname): Log flags parameter. --- Pushing under the trivial rule. src/libvirt.c |5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libvirt.c b/src/libvirt.c index a5e2cc7..cdb63e7 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -6713,7 +6713,8 @@ virNodeSuspendForDuration(virConnectPtr conn, unsigned int flags) { -VIR_DEBUG(conn=%p, target=%d, duration=%lld, conn, target, duration); +VIR_DEBUG(conn=%p, target=%d, duration=%lld, flags=%x, + conn, target, duration, flags); virResetLastError(); @@ -20233,7 +20234,7 @@ virDomainGetHostname(virDomainPtr domain, unsigned int flags) { virConnectPtr conn; -VIR_DOMAIN_DEBUG(domain); +VIR_DOMAIN_DEBUG(domain, flags=%x, flags); virResetLastError(); -- 1.7.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 00/23] Improve device support for LXC
This series makes some major improvements to the device support for LXC - USB, block and char device passthrough - Hotplug/unplug support for disk, nic, usb, block and char devices -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 02/23] Refactor virDomainHostdevFind method
From: Daniel P. Berrange berra...@redhat.com Move the code for matching hostdev instances out of virDomainHostdevFind and into virDomainHostdevMatch method, which in turn calls out to other helper methods depending on the type of hostdev. Signed-off-by: Daniel P. Berrange berra...@redhat.com --- src/conf/domain_conf.c | 108 + 1 file changed, 65 insertions(+), 43 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index ed31431..dd0e841 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -7830,6 +7830,69 @@ virDomainHostdevRemove(virDomainDefPtr def, size_t i) return hostdev; } + +static int +virDomainHostdevMatchSubsysUSB(virDomainHostdevDefPtr a, + virDomainHostdevDefPtr b) +{ +if (b-source.subsys.u.usb.bus b-source.subsys.u.usb.device) { +/* specified by bus location on host */ +if (a-source.subsys.u.usb.bus == b-source.subsys.u.usb.bus +a-source.subsys.u.usb.device == b-source.subsys.u.usb.device) +return 1; +} else { +/* specified by product vendor id */ +if (a-source.subsys.u.usb.product == b-source.subsys.u.usb.product +a-source.subsys.u.usb.vendor == b-source.subsys.u.usb.vendor) +return 1; +} +return 0; +} + +static int +virDomainHostdevMatchSubsysPCI(virDomainHostdevDefPtr a, + virDomainHostdevDefPtr b) +{ +if (a-source.subsys.u.pci.domain == b-source.subsys.u.pci.domain +a-source.subsys.u.pci.bus == b-source.subsys.u.pci.bus +a-source.subsys.u.pci.slot == b-source.subsys.u.pci.slot +a-source.subsys.u.pci.function == b-source.subsys.u.pci.function) +return 1; +return 0; +} + + +static int +virDomainHostdevMatchSubsys(virDomainHostdevDefPtr a, +virDomainHostdevDefPtr b) +{ +if (a-source.subsys.type != b-source.subsys.type) +return 0; + +switch (a-source.subsys.type) { +case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: +return virDomainHostdevMatchSubsysPCI(a, b); +case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: +return virDomainHostdevMatchSubsysUSB(a, b); +} +return 0; +} + + +static int +virDomainHostdevMatch(virDomainHostdevDefPtr a, + virDomainHostdevDefPtr b) +{ +if (a-mode != b-mode) +return 0; + +switch (a-mode) { +case VIR_DOMAIN_HOSTDEV_MODE_SUBSYS: +return virDomainHostdevMatchSubsys(a, b); +} +return 0; +} + /* Find an entry in hostdevs that matches the source spec in * @match. return pointer to the entry in @found (if found is * non-NULL). Returns index (within hostdevs) of matched entry, or -1 @@ -7841,58 +7904,17 @@ virDomainHostdevFind(virDomainDefPtr def, virDomainHostdevDefPtr *found) { virDomainHostdevDefPtr local_found; -virDomainHostdevSubsysPtr m_subsys = match-source.subsys; int i; if (!found) found = local_found; *found = NULL; -/* There is no code that uses _MODE_CAPABILITIES, and nothing to - * compare if it did, so don't allow it. - */ -if (match-mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) -return -1; - for (i = 0 ; i def-nhostdevs ; i++) { -virDomainHostdevDefPtr compare = def-hostdevs[i]; -virDomainHostdevSubsysPtr c_subsys = compare-source.subsys; - -if (compare-mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS || -c_subsys-type != m_subsys-type) { -continue; -} - -switch (m_subsys-type) -{ -case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: -if (c_subsys-u.pci.domain == m_subsys-u.pci.domain -c_subsys-u.pci.bus == m_subsys-u.pci.bus -c_subsys-u.pci.slot == m_subsys-u.pci.slot -c_subsys-u.pci.function == m_subsys-u.pci.function) { -*found = compare; -} -break; -case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: -if (m_subsys-u.usb.bus m_subsys-u.usb.device) { -/* specified by bus location on host */ -if (c_subsys-u.usb.bus == m_subsys-u.usb.bus -c_subsys-u.usb.device == m_subsys-u.usb.device) { -*found = compare; -} -} else { -/* specified by product vendor id */ -if (c_subsys-u.usb.product == m_subsys-u.usb.product -c_subsys-u.usb.vendor == m_subsys-u.usb.vendor) { -*found = compare; -} -} -break; -default: +if (virDomainHostdevMatch(match, def-hostdevs[i])) { +*found = def-hostdevs[i]; break; } -if (*found) -break; } return *found ? i : -1; } -- 1.8.0.1 -- libvir-list mailing list
[libvirt] [PATCH 11/23] Add support for storage host device passthrough with LXC
From: Daniel P. Berrange berra...@redhat.com This extends support for host device passthrough with LXC to cover storage devices. In this case all we need todo is a mknod in the container's /dev and whitelist the device in cgroups Signed-off-by: Daniel P. Berrange berra...@redhat.com --- src/lxc/lxc_cgroup.c| 46 ++-- src/lxc/lxc_container.c | 80 + 2 files changed, 111 insertions(+), 15 deletions(-) diff --git a/src/lxc/lxc_cgroup.c b/src/lxc/lxc_cgroup.c index 14c840a..0c3d5dd 100644 --- a/src/lxc/lxc_cgroup.c +++ b/src/lxc/lxc_cgroup.c @@ -414,21 +414,37 @@ static int virLXCCgroupSetupDeviceACL(virDomainDefPtr def, virDomainHostdevDefPtr hostdev = def-hostdevs[i]; usbDevice *usb; -if (hostdev-mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) -continue; -if (hostdev-source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) -continue; -if (hostdev-missing) -continue; - -if ((usb = usbGetDevice(hostdev-source.subsys.u.usb.bus, -hostdev-source.subsys.u.usb.device, -NULL)) == NULL) -goto cleanup; - -if (usbDeviceFileIterate(usb, virLXCSetupHostUsbDeviceCgroup, - cgroup) 0) -goto cleanup; +switch (hostdev-mode) { +case VIR_DOMAIN_HOSTDEV_MODE_SUBSYS: +if (hostdev-source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) +continue; +if (hostdev-missing) +continue; + +if ((usb = usbGetDevice(hostdev-source.subsys.u.usb.bus, +hostdev-source.subsys.u.usb.device, +NULL)) == NULL) +goto cleanup; + +if (usbDeviceFileIterate(usb, virLXCSetupHostUsbDeviceCgroup, + cgroup) 0) +goto cleanup; +break; +case VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES: +switch (hostdev-source.caps.type) { +case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_STORAGE: +if (virCgroupAllowDevicePath(cgroup, + hostdev-source.caps.u.storage.block, + VIR_CGROUP_DEVICE_RW | + VIR_CGROUP_DEVICE_MKNOD) 0) +goto cleanup; +break; +default: +break; +} +default: +break; +} } rc = virCgroupAllowDeviceMajor(cgroup, 'c', LXC_DEV_MAJ_PTY, diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c index 0a407bf..19c5702 100644 --- a/src/lxc/lxc_container.c +++ b/src/lxc/lxc_container.c @@ -1384,6 +1384,64 @@ cleanup: } +static int lxcContainerSetupHostdevCapsStorage(virDomainDefPtr vmDef ATTRIBUTE_UNUSED, + virDomainHostdevDefPtr def ATTRIBUTE_UNUSED, + const char *dstprefix ATTRIBUTE_UNUSED, + virSecurityManagerPtr securityDriver ATTRIBUTE_UNUSED) +{ +char *src = NULL; +int ret = -1; +struct stat sb; +mode_t mode; + +if (def-source.caps.u.storage.block == NULL) { +virReportError(VIR_ERR_CONFIG_UNSUPPORTED, %s, + _(Missing storage host block path)); +goto cleanup; +} + +if (virAsprintf(src, %s/%s, dstprefix, def-source.caps.u.storage.block) 0) { +virReportOOMError(); +goto cleanup; +} + +if (stat(src, sb) 0) { +virReportSystemError(errno, + _(Unable to access %s), + src); +goto cleanup; +} + +if (!S_ISBLK(sb.st_mode)) { +virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _(Storage source %s must be a block device), + def-source.caps.u.storage.block); +goto cleanup; +} + +mode = 0700 | S_IFBLK; + +VIR_DEBUG(Creating dev %s (%d,%d), + def-source.caps.u.storage.block, + major(sb.st_rdev), minor(sb.st_rdev)); +if (mknod(def-source.caps.u.storage.block, mode, sb.st_rdev) 0) { +virReportSystemError(errno, + _(Unable to create device %s), + def-source.caps.u.storage.block); +goto cleanup; +} + +if (virSecurityManagerSetHostdevLabel(securityDriver, vmDef, def, NULL) 0) +goto cleanup; + +ret = 0; + +cleanup: +VIR_FREE(src); +return ret; +} + + static int lxcContainerSetupHostdevSubsys(virDomainDefPtr vmDef, virDomainHostdevDefPtr def, const char *dstprefix, @@ -1402,6
[libvirt] [PATCH 12/23] Add support for misc host device passthrough with LXC
From: Daniel P. Berrange berra...@redhat.com This extends support for host device passthrough with LXC to cover misc devices. In this case all we need todo is a mknod in the container's /dev and whitelist the device in cgroups Signed-off-by: Daniel P. Berrange berra...@redhat.com --- src/lxc/lxc_cgroup.c| 7 ++ src/lxc/lxc_container.c | 61 + 2 files changed, 68 insertions(+) diff --git a/src/lxc/lxc_cgroup.c b/src/lxc/lxc_cgroup.c index 0c3d5dd..4fe23c1 100644 --- a/src/lxc/lxc_cgroup.c +++ b/src/lxc/lxc_cgroup.c @@ -439,6 +439,13 @@ static int virLXCCgroupSetupDeviceACL(virDomainDefPtr def, VIR_CGROUP_DEVICE_MKNOD) 0) goto cleanup; break; +case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_MISC: +if (virCgroupAllowDevicePath(cgroup, + hostdev-source.caps.u.misc.chardev, + VIR_CGROUP_DEVICE_RW | + VIR_CGROUP_DEVICE_MKNOD) 0) +goto cleanup; +break; default: break; } diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c index 19c5702..25a3ab5 100644 --- a/src/lxc/lxc_container.c +++ b/src/lxc/lxc_container.c @@ -1442,6 +1442,64 @@ cleanup: } +static int lxcContainerSetupHostdevCapsMisc(virDomainDefPtr vmDef ATTRIBUTE_UNUSED, +virDomainHostdevDefPtr def ATTRIBUTE_UNUSED, +const char *dstprefix ATTRIBUTE_UNUSED, +virSecurityManagerPtr securityDriver ATTRIBUTE_UNUSED) +{ +char *src = NULL; +int ret = -1; +struct stat sb; +mode_t mode; + +if (def-source.caps.u.misc.chardev == NULL) { +virReportError(VIR_ERR_CONFIG_UNSUPPORTED, %s, + _(Missing storage host block path)); +goto cleanup; +} + +if (virAsprintf(src, %s/%s, dstprefix, def-source.caps.u.misc.chardev) 0) { +virReportOOMError(); +goto cleanup; +} + +if (stat(src, sb) 0) { +virReportSystemError(errno, + _(Unable to access %s), + src); +goto cleanup; +} + +if (!S_ISCHR(sb.st_mode)) { +virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _(Storage source %s must be a character device), + def-source.caps.u.misc.chardev); +goto cleanup; +} + +mode = 0700 | S_IFCHR; + +VIR_DEBUG(Creating dev %s (%d,%d), + def-source.caps.u.misc.chardev, + major(sb.st_rdev), minor(sb.st_rdev)); +if (mknod(def-source.caps.u.misc.chardev, mode, sb.st_rdev) 0) { +virReportSystemError(errno, + _(Unable to create device %s), + def-source.caps.u.misc.chardev); +goto cleanup; +} + +if (virSecurityManagerSetHostdevLabel(securityDriver, vmDef, def, NULL) 0) +goto cleanup; + +ret = 0; + +cleanup: +VIR_FREE(src); +return ret; +} + + static int lxcContainerSetupHostdevSubsys(virDomainDefPtr vmDef, virDomainHostdevDefPtr def, const char *dstprefix, @@ -1469,6 +1527,9 @@ static int lxcContainerSetupHostdevCaps(virDomainDefPtr vmDef, case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_STORAGE: return lxcContainerSetupHostdevCapsStorage(vmDef, def, dstprefix, securityDriver); +case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_MISC: +return lxcContainerSetupHostdevCapsMisc(vmDef, def, dstprefix, securityDriver); + default: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _(Unsupported host device mode %s), -- 1.8.0.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 10/23] Add support for USB host device passthrough with LXC
From: Daniel P. Berrange berra...@redhat.com This adds support for host device passthrough with the LXC driver. Since there is only a single kernel image, it doesn't make sense to pass through PCI devices, but USB devices are fine. For the latter we merely need to make the /dev/bus/usb/NNN/MMM character device exist in the container's /dev Signed-off-by: Daniel P. Berrange berra...@redhat.com --- src/Makefile.am | 1 + src/lxc/lxc_cgroup.c| 64 src/lxc/lxc_cgroup.h| 12 ++ src/lxc/lxc_conf.h | 3 + src/lxc/lxc_container.c | 124 ++- src/lxc/lxc_driver.c| 6 + src/lxc/lxc_hostdev.c | 390 src/lxc/lxc_hostdev.h | 43 ++ src/lxc/lxc_process.c | 11 ++ 9 files changed, 653 insertions(+), 1 deletion(-) create mode 100644 src/lxc/lxc_hostdev.c create mode 100644 src/lxc/lxc_hostdev.h diff --git a/src/Makefile.am b/src/Makefile.am index 627dbb5..c3459a5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -411,6 +411,7 @@ LXC_DRIVER_SOURCES = \ lxc/lxc_container.c lxc/lxc_container.h \ lxc/lxc_cgroup.c lxc/lxc_cgroup.h \ lxc/lxc_domain.c lxc/lxc_domain.h \ + lxc/lxc_hostdev.c lxc/lxc_hostdev.h \ lxc/lxc_monitor.c lxc/lxc_monitor.h \ lxc/lxc_process.c lxc/lxc_process.h \ lxc/lxc_fuse.c lxc/lxc_fuse.h \ diff --git a/src/lxc/lxc_cgroup.c b/src/lxc/lxc_cgroup.c index 0636869..14c840a 100644 --- a/src/lxc/lxc_cgroup.c +++ b/src/lxc/lxc_cgroup.c @@ -291,6 +291,49 @@ struct _virLXCCgroupDevicePolicy { }; +int +virLXCSetupHostUsbDeviceCgroup(usbDevice *dev ATTRIBUTE_UNUSED, + const char *path, + void *opaque) +{ +virCgroupPtr cgroup = opaque; +int rc; + +VIR_DEBUG(Process path '%s' for USB device, path); +rc = virCgroupAllowDevicePath(cgroup, path, + VIR_CGROUP_DEVICE_RW); +if (rc 0) { +virReportSystemError(-rc, + _(Unable to allow device %s), + path); +return -1; +} + +return 0; +} + + +int +virLXCTeardownHostUsbDeviceCgroup(usbDevice *dev ATTRIBUTE_UNUSED, + const char *path, + void *opaque) +{ +virCgroupPtr cgroup = opaque; +int rc; + +VIR_DEBUG(Process path '%s' for USB device, path); +rc = virCgroupDenyDevicePath(cgroup, path, + VIR_CGROUP_DEVICE_RW); +if (rc 0) { +virReportSystemError(-rc, + _(Unable to deny device %s), + path); +return -1; +} + +return 0; +} + static int virLXCCgroupSetupDeviceACL(virDomainDefPtr def, virCgroupPtr cgroup) @@ -367,6 +410,27 @@ static int virLXCCgroupSetupDeviceACL(virDomainDefPtr def, } } +for (i = 0; i def-nhostdevs; i++) { +virDomainHostdevDefPtr hostdev = def-hostdevs[i]; +usbDevice *usb; + +if (hostdev-mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) +continue; +if (hostdev-source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) +continue; +if (hostdev-missing) +continue; + +if ((usb = usbGetDevice(hostdev-source.subsys.u.usb.bus, +hostdev-source.subsys.u.usb.device, +NULL)) == NULL) +goto cleanup; + +if (usbDeviceFileIterate(usb, virLXCSetupHostUsbDeviceCgroup, + cgroup) 0) +goto cleanup; +} + rc = virCgroupAllowDeviceMajor(cgroup, 'c', LXC_DEV_MAJ_PTY, VIR_CGROUP_DEVICE_RWM); if (rc != 0) { diff --git a/src/lxc/lxc_cgroup.h b/src/lxc/lxc_cgroup.h index 6961943..c1d4551 100644 --- a/src/lxc/lxc_cgroup.h +++ b/src/lxc/lxc_cgroup.h @@ -24,7 +24,19 @@ # include domain_conf.h # include lxc_fuse.h +# include hostusb.h int virLXCCgroupSetup(virDomainDefPtr def); int virLXCCgroupGetMeminfo(virLXCMeminfoPtr meminfo); + +int +virLXCSetupHostUsbDeviceCgroup(usbDevice *dev, + const char *path, + void *opaque); + +int +virLXCTeardownHostUsbDeviceCgroup(usbDevice *dev, + const char *path, + void *opaque); + #endif /* __VIR_LXC_CGROUP_H__ */ diff --git a/src/lxc/lxc_conf.h b/src/lxc/lxc_conf.h index 4ae0c5e..a6872ea 100644 --- a/src/lxc/lxc_conf.h +++ b/src/lxc/lxc_conf.h @@ -35,6 +35,7 @@ # include cgroup.h # include security/security_manager.h # include configmake.h +# include hostusb.h
[libvirt] [PATCH 16/23] Add support for attach/detach/update hostdev devices in config for LXC
From: Daniel P. Berrange berra...@redhat.com Wire up the attach/detach/update device APIs to support changing of hostdevs in the persistent config file Signed-off-by: Daniel P. Berrange berra...@redhat.com --- src/lxc/lxc_driver.c | 30 ++ 1 file changed, 30 insertions(+) diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 9a56643..daf32c7 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -2776,6 +2776,7 @@ lxcDomainAttachDeviceConfig(virDomainDefPtr vmdef, int ret = -1; virDomainDiskDefPtr disk; virDomainNetDefPtr net; +virDomainHostdevDefPtr hostdev; switch (dev-type) { case VIR_DOMAIN_DEVICE_DISK: @@ -2804,6 +2805,21 @@ lxcDomainAttachDeviceConfig(virDomainDefPtr vmdef, ret = 0; break; +case VIR_DOMAIN_DEVICE_HOSTDEV: +hostdev = dev-data.hostdev; +if (virDomainHostdevFind(vmdef, hostdev, NULL) = 0) { +virReportError(VIR_ERR_INVALID_ARG, %s, + _(device is already in the domain configuration)); +return -1; +} +if (virDomainHostdevInsert(vmdef, hostdev) 0) { +virReportOOMError(); +return -1; +} +dev-data.hostdev = NULL; +ret = 0; +break; + default: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, %s, _(persistent attach of device is not supported)); @@ -2868,6 +2884,7 @@ lxcDomainDetachDeviceConfig(virDomainDefPtr vmdef, int ret = -1; virDomainDiskDefPtr disk, det_disk; virDomainNetDefPtr net; +virDomainHostdevDefPtr hostdev, det_hostdev; int idx; char mac[VIR_MAC_STRING_BUFLEN]; @@ -2901,6 +2918,19 @@ lxcDomainDetachDeviceConfig(virDomainDefPtr vmdef, ret = 0; break; +case VIR_DOMAIN_DEVICE_HOSTDEV: { +hostdev = dev-data.hostdev; +if ((idx = virDomainHostdevFind(vmdef, hostdev, det_hostdev)) 0) { +virReportError(VIR_ERR_INVALID_ARG, %s, + _(device not present in domain configuration)); +return -1; +} +virDomainHostdevRemove(vmdef, idx); +virDomainHostdevDefFree(det_hostdev); +ret = 0; +break; +} + default: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, %s, _(persistent detach of device is not supported)); -- 1.8.0.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 13/23] Add basic driver API framework for device attach/detach support in LXC
From: Daniel P. Berrange berra...@redhat.com This wires up the LXC driver to support the domain device attach/ detach/update APIs, following the same code design as used in the QEMU driver. No actual changes are possible with this commit, it is only providing the framework Signed-off-by: Daniel P. Berrange berra...@redhat.com --- src/lxc/lxc_driver.c | 290 +++ 1 file changed, 290 insertions(+) diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 1c6ec8c..38d5d87 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -2768,6 +2768,291 @@ lxcListAllDomains(virConnectPtr conn, return ret; } + +static int +lxcDomainAttachDeviceConfig(virDomainDefPtr vmdef ATTRIBUTE_UNUSED, +virDomainDeviceDefPtr dev) +{ +int ret = -1; + +switch (dev-type) { +default: + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, %s, +_(persistent attach of device is not supported)); + break; +} + +return ret; +} + + +static int +lxcDomainUpdateDeviceConfig(virDomainDefPtr vmdef ATTRIBUTE_UNUSED, +virDomainDeviceDefPtr dev) +{ +int ret = -1; + +switch (dev-type) { +default: +virReportError(VIR_ERR_CONFIG_UNSUPPORTED, %s, + _(persistent update of device is not supported)); +break; +} + +return ret; +} + + +static int +lxcDomainDetachDeviceConfig(virDomainDefPtr vmDef ATTRIBUTE_UNUSED, +virDomainDeviceDefPtr dev) +{ +int ret = -1; + +switch (dev-type) { +default: +virReportError(VIR_ERR_CONFIG_UNSUPPORTED, %s, + _(persistent detach of device is not supported)); +break; +} + +return ret; +} + + +static int +lxcDomainAttachDeviceLive(virLXCDriverPtr driver ATTRIBUTE_UNUSED, + virDomainObjPtr vm ATTRIBUTE_UNUSED, + virDomainDeviceDefPtr dev) +{ +int ret = -1; + +switch (dev-type) { +default: +virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _(device type '%s' cannot be attached), + virDomainDeviceTypeToString(dev-type)); +break; +} + +return ret; +} + + +static int +lxcDomainDetachDeviceLive(virLXCDriverPtr driver ATTRIBUTE_UNUSED, + virDomainObjPtr vm ATTRIBUTE_UNUSED, + virDomainDeviceDefPtr dev) +{ +int ret = -1; + +switch (dev-type) { +default: +virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _(device type '%s' cannot be detached), + virDomainDeviceTypeToString(dev-type)); +break; +} + +return ret; +} + + +/* Actions for lxcDomainModifyDeviceFlags */ +enum { +LXC_DEVICE_ATTACH, +LXC_DEVICE_UPDATE, +LXC_DEVICE_DETACH, +}; + + +static int +lxcDomainModifyDeviceFlags(virDomainPtr dom, const char *xml, + unsigned int flags, int action) +{ +virLXCDriverPtr driver = dom-conn-privateData; +virDomainObjPtr vm = NULL; +virDomainDefPtr vmdef = NULL; +virDomainDeviceDefPtr dev = NULL, dev_copy = NULL; +int ret = -1; +unsigned int affect; + +virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | + VIR_DOMAIN_AFFECT_CONFIG | + (action == LXC_DEVICE_UPDATE ? + VIR_DOMAIN_DEVICE_MODIFY_FORCE : 0), -1); + +affect = flags (VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG); + +lxcDriverLock(driver); +vm = virDomainFindByUUID(driver-domains, dom-uuid); +if (!vm) { +char uuidstr[VIR_UUID_STRING_BUFLEN]; +virUUIDFormat(dom-uuid, uuidstr); +virReportError(VIR_ERR_NO_DOMAIN, + _(no domain with matching uuid '%s'), uuidstr); +goto cleanup; +} + +if (virDomainObjIsActive(vm)) { +if (affect == VIR_DOMAIN_AFFECT_CURRENT) +flags |= VIR_DOMAIN_AFFECT_LIVE; +} else { +if (affect == VIR_DOMAIN_AFFECT_CURRENT) +flags |= VIR_DOMAIN_AFFECT_CONFIG; +/* check consistency between flags and the vm state */ +if (flags VIR_DOMAIN_AFFECT_LIVE) { +virReportError(VIR_ERR_OPERATION_INVALID, %s, + _(cannot do live update a device on + inactive domain)); +goto cleanup; +} +} + +if ((flags VIR_DOMAIN_AFFECT_CONFIG) !vm-persistent) { + virReportError(VIR_ERR_OPERATION_INVALID, %s, +_(cannot modify device on transient domain)); + goto cleanup; +} + +dev = dev_copy = virDomainDeviceDefParse(driver-caps, vm-def, xml, + VIR_DOMAIN_XML_INACTIVE); +if (dev == NULL) +goto cleanup; + +if (flags VIR_DOMAIN_AFFECT_CONFIG +flags VIR_DOMAIN_AFFECT_LIVE) { +/* If we
[libvirt] [PATCH 18/23] Add support for hotplug/unplug of NIC devices in LXC
From: Daniel P. Berrange berra...@redhat.com Wire up the attach/detach device drivers in LXC to support the hotplug/unplug of NICs. Signed-off-by: Daniel P. Berrange berra...@redhat.com --- src/lxc/lxc_driver.c | 219 +-- 1 file changed, 214 insertions(+), 5 deletions(-) diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index a2bb497..08ac70d 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -3073,9 +3073,141 @@ cleanup: } +/* XXX conn required for network - bridge resolution */ static int -lxcDomainAttachDeviceLive(virLXCDriverPtr driver ATTRIBUTE_UNUSED, - virDomainObjPtr vm ATTRIBUTE_UNUSED, +lxcDomainAttachDeviceNetLive(virConnectPtr conn, + virDomainObjPtr vm, + virDomainNetDefPtr net) +{ +virLXCDomainObjPrivatePtr priv = vm-privateData; +int ret = -1; +int actualType; +char *veth = NULL; + +if (!priv-initpid) { +virReportError(VIR_ERR_OPERATION_INVALID, %s, + _(Cannot attach disk until init PID is known)); +goto cleanup; +} + +/* preallocate new slot for device */ +if (VIR_REALLOC_N(vm-def-nets, vm-def-nnets+1) 0) { +virReportOOMError(); +return -1; +} + +/* If appropriate, grab a physical device from the configured + * network's pool of devices, or resolve bridge device name + * to the one defined in the network definition. + */ +if (networkAllocateActualDevice(net) 0) +return -1; + +actualType = virDomainNetGetActualType(net); + +switch (actualType) { +case VIR_DOMAIN_NET_TYPE_BRIDGE: { +const char *brname = virDomainNetGetActualBridgeName(net); +if (!brname) { +virReportError(VIR_ERR_INTERNAL_ERROR, %s, + _(No bridge name specified)); +goto cleanup; +} +if (!(veth = virLXCProcessSetupInterfaceBridged(conn, +vm-def, +net, +brname))) +goto cleanup; +} break; +case VIR_DOMAIN_NET_TYPE_NETWORK: { +virNetworkPtr network; +char *brname = NULL; +bool fail = false; +int active; +virErrorPtr errobj; + +if (!(network = virNetworkLookupByName(conn, + net-data.network.name))) +goto cleanup; + +active = virNetworkIsActive(network); +if (active != 1) { +fail = true; +if (active == 0) +virReportError(VIR_ERR_INTERNAL_ERROR, + _(Network '%s' is not active.), + net-data.network.name); +} + +if (!fail) { +brname = virNetworkGetBridgeName(network); +if (brname == NULL) +fail = true; +} + +/* Make sure any above failure is preserved */ +errobj = virSaveLastError(); +virNetworkFree(network); +virSetError(errobj); +virFreeError(errobj); + +if (fail) +goto cleanup; + +if (!(veth = virLXCProcessSetupInterfaceBridged(conn, +vm-def, +net, +brname))) { +VIR_FREE(brname); +goto cleanup; +} +VIR_FREE(brname); +} break; +case VIR_DOMAIN_NET_TYPE_DIRECT: { +if (!(veth = virLXCProcessSetupInterfaceDirect(conn, + vm-def, + net))) +goto cleanup; +} break; +default: +virReportError(VIR_ERR_CONFIG_UNSUPPORTED, %s, + _(Network device type is not supported)); +goto cleanup; +} + +if (virNetDevSetNamespace(veth, priv-initpid) 0) { +virDomainAuditNet(vm, NULL, net, attach, false); +goto cleanup; +} + +virDomainAuditNet(vm, NULL, net, attach, true); + +ret = 0; + +cleanup: +if (!ret) { +vm-def-nets[vm-def-nnets++] = net; +} else if (veth) { +switch (actualType) { +case VIR_DOMAIN_NET_TYPE_BRIDGE: +case VIR_DOMAIN_NET_TYPE_NETWORK: +ignore_value(virNetDevVethDelete(veth)); +break; + +case VIR_DOMAIN_NET_TYPE_DIRECT: +ignore_value(virNetDevMacVLanDelete(veth)); +break; +} +} + +return ret; +} + + +static int +lxcDomainAttachDeviceLive(virConnectPtr conn, + virLXCDriverPtr driver, + virDomainObjPtr vm, virDomainDeviceDefPtr dev) {
[libvirt] [PATCH 03/23] Add support for hostdev mode=capabilities
From: Daniel P. Berrange berra...@redhat.com The hostdev device type has long had a redundant mode attribute, which has always been subsys. This finally introduces a new mode capabilities, which will be used by the LXC driver for device assignment. Since container based virtualization uses a single kernel, the idea of assigning physical PCI devices doesn't make sense. It is still reasonable to assign USB devices, but for assinging arbitrary nodes in /dev, the new 'capabilities' mode is to be used. The first capability support is 'storage', which is for assignment of block devices. Functionally this is really pretty similar to the disk support. The only difference is the device node name is identical in both host and container namespaces. hostdev mode='capabilities' type='storage' source block/dev/sdf1/block /source /hostdev The second capability support is 'misc', which is for assignment of character devices. There is no existing parallel to this. Again the device node is the same inside outside the container. hostdev mode='capabilities' type='misc' source char/dev/sdf1/char /source /hostdev The reason for keeping the char storage devices separate in the domain XML, is to mirror the split in the node device XML. NB the node device XML does not yet report character devices, but that's another new patch to come Signed-off-by: Daniel P. Berrange berra...@redhat.com --- docs/schemas/domaincommon.rng| 128 + src/conf/domain_audit.c | 80 +++- src/conf/domain_conf.c | 175 ++- src/conf/domain_conf.h | 31 +-- src/libvirt_private.syms | 1 + tests/lxcxml2xmldata/lxc-hostdev.xml | 34 +++ tests/lxcxml2xmltest.c | 1 + 7 files changed, 375 insertions(+), 75 deletions(-) create mode 100644 tests/lxcxml2xmldata/lxc-hostdev.xml diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 0e85739..072e5cc 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -2812,63 +2812,109 @@ /zeroOrMore /element /define + define name=hostdev element name=hostdev + choice +group + ref name=hostdevsubsys/ +/group +group + ref name=hostdevcaps/ +/group + /choice optional -attribute name=mode - choice -valuesubsystem/value -valuecapabilities/value - /choice -/attribute - /optional - attribute name=type -choice - valueusb/value - valuepci/value -/choice - /attribute - optional -attribute name=managed - choice -valueyes/value -valueno/value - /choice -/attribute +ref name=alias/ /optional - group -element name=source - optional -ref name=startupPolicy/ - /optional - choice -group - ref name=usbproduct/ - optional -ref name=usbaddress/ - /optional -/group -ref name=usbaddress/ -element name=address - ref name=pciaddress/ -/element - /choice -/element - /group optional ref name=deviceBoot/ /optional optional -ref name=alias/ +ref name=rom/ /optional optional ref name=address/ /optional +/element + /define + + define name=hostdevsubsys +optional + attribute name=mode +valuesubsystem/value + /attribute +/optional +optional + attribute name=managed +choice + valueyes/value + valueno/value +/choice + /attribute +/optional +choice + ref name=hostdevsubsyspci/ + ref name=hostdevsubsysusb/ +/choice + /define + + define name=hostdevcaps +attribute name=mode + valuecapabilities/value +/attribute +choice + group +ref name=hostdevcapsstorage/ + /group +/choice + /define + + + define name=hostdevsubsyspci +attribute name=type + valuepci/value +/attribute +element name=source + optional +ref name=startupPolicy/ + /optional + element name=address +ref name=pciaddress/ + /element +/element + /define + + define name=hostdevsubsysusb +attribute name=type + valueusb/value +/attribute +element name=source optional -ref name=rom/ +ref name=startupPolicy/ /optional + choice +group + ref name=usbproduct/ + optional +ref name=usbaddress/ + /optional +/group +ref name=usbaddress/ + /choice /element /define + + define
Re: [libvirt] fwd: RA support in dnsmasq
On 11/30/2012 12:31 PM, Gene Czarcinski wrote: I am sort-of cross posting this to the libvir-list because the bind-dynamic fix may have introduced an undesirable new feature. I will be troubleshooting this. One thing I want to try is to build a dnsmasq with a fake version so that bind-interface is forced into use. Since this is occurring with a SLAAC address, I do not need DHCPv6 for this testing. Wait, since Laine put a lot of effort into parsing dnsmasq --help, I will just remove the bind-dynamic rather than changing the version. Cancel that. I did some grepping of syslogs and this problem started around 8 Nov (or at least that is the earliest one I found). That is well before the bind-dynamic stuff was integrated in. Original Message Subject: Re: [Dnsmasq-discuss] RA support in dnsmasq Date: Fri, 30 Nov 2012 12:20:36 -0500 From: Gene Czarcinski g...@czarc.net To: dnsmasq-disc...@thekelleys.org.uk On 11/30/2012 11:32 AM, Simon Kelley wrote: On 30/11/12 15:54, Gene Czarcinski wrote: On 11/29/2012 04:18 PM, Simon Kelley wrote: On 29/11/12 20:31, Gene Czarcinski wrote: I spoke too quickly. The cause of the problem is libvirt related but I am not sure what just yet. I was running a libvirt that had a lot of stuff on it but seemed to work OK. Then, earlier today I update to a point that appears to be somewhat beyond the leading edge and, although I was not getting any RTR-ADVERT messages, it turned out that there were/are big-time problems running qemu-kvm. So, back off/downgrade to the previous version. Qemu-kvm now works but the RTR-ADVERT messages are back. This may be a bit time-consuming to debug! Are you seeing the new log message in netlink.c? The good news is that libvirt is working again (I must have done a git-pull in the middle of an update). Thus, I am not seeing the large numbers of RTR-ADVERT. Yes, I am seeing the new log message and I have a question about that. Every time a new virtual network interface is started, something must be doing some type of broadcast because all of the dnsmasq instances (the new one and all the old ones) suddenly wake up and issue a flurry of RA packets and related syslog messages. To kick the flurry off, there one of the new unsolicited syslog messages from each dnsmasq instance. Is this something you would expect? Is this normal? The libvirt folks they are not doing it. I'd expect it. The code you instrumented gets run whenever a new address event happens, which is whenever an address is added to an interface. Every time a new virtual network interface is started is a good proxy for that. The dnsmasq code isn't very discriminating, it updates it's idea of which interfaces hace which addresses, and then does a minute of fast advertisements on all of them. It might be possible to only do the fast advertisements on new interfaces, but implementing that isn't totally trivial. Yes, I doubt very much if it would be trivial. However, I do not believe that this is the basic problem. When the problem occurs, one of the networks suddenly attempts to work with the real NIC rather than the virtual one defined in its config file. I slightly changed the IPv4 and IPv6 addresses defined for this network and the problem went away. I have also just seen the problem happen on another system which also had that virtual address defined. BTW, these configurations all use interface= and bind-dynamic rather than the old bind-interface with listen-address= specified for each specified IPv4 and IPv6 address. I had not noticed the problem previously. Why it occurs at all with just this specific address is puzzling. The configuration in which causes problems is: -- # dnsmasq conf file created by libvirt strict-order domain-needed domain=net6 expand-hosts local=/net6/ pid-file=/var/run/libvirt/network/net6.pid bind-dynamic interface=virbr11 dhcp-range=192.168.6.128,192.168.6.254 dhcp-no-override dhcp-leasefile=/var/lib/libvirt/dnsmasq/net6.leases dhcp-lease-max=127 dhcp-hostsfile=/var/lib/libvirt/dnsmasq/net6.hostsfile addn-hosts=/var/lib/libvirt/dnsmasq/net6.addnhosts dhcp-range=fd00:beef:10:6::1,ra-only - When I changed all the 6 to 160, the problem, disappeared. And there is another network defined almost the same with 8 instead of 6 and I have had no problems with it. The real NIC is configured as a DHCP client for both IPv4 and IPv6. It is assigned nailed addresses of 192.168.17.2/24 and fd00:dead:beef:17::2. And I just discovered why crazy stuff is happening (but I do not know what causes it) ... the P33p1 NIC has: inet6 fd00:beef:10:6:3285:a9ff:fe8f:e982/64 scope global dynamic And the reason why may be related to that NetworkManager goes through a verly long dance to bring up an interface. With dnsmasq autostarted for net6, it may have gotten there first ... but it should have not responded to
[libvirt] [PATCH 14/23] Add support for attach/detach/update net devices in config for LXC
From: Daniel P. Berrange berra...@redhat.com Wire up the attach/detach/update device APIs to support changing of network interfaces in the persistent config file Signed-off-by: Daniel P. Berrange berra...@redhat.com --- src/lxc/lxc_driver.c | 69 +--- 1 file changed, 66 insertions(+), 3 deletions(-) diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 38d5d87..ecd7cb8 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -2770,52 +2770,115 @@ lxcListAllDomains(virConnectPtr conn, static int -lxcDomainAttachDeviceConfig(virDomainDefPtr vmdef ATTRIBUTE_UNUSED, +lxcDomainAttachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev) { int ret = -1; +virDomainNetDefPtr net; switch (dev-type) { +case VIR_DOMAIN_DEVICE_NET: +net = dev-data.net; +if (virDomainNetInsert(vmdef, net) 0) { +virReportOOMError(); +goto cleanup; +} +dev-data.net = NULL; +ret = 0; +break; + default: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, %s, _(persistent attach of device is not supported)); break; } +cleanup: return ret; } static int -lxcDomainUpdateDeviceConfig(virDomainDefPtr vmdef ATTRIBUTE_UNUSED, +lxcDomainUpdateDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev) { int ret = -1; +virDomainNetDefPtr net; +int pos; +char mac[VIR_MAC_STRING_BUFLEN]; switch (dev-type) { +case VIR_DOMAIN_DEVICE_NET: +net = dev-data.net; +pos = virDomainNetFindIdx(vmdef, net); +if (pos == -2) { +virMacAddrFormat(net-mac, mac); +virReportError(VIR_ERR_OPERATION_FAILED, + _(couldn't find matching device + with mac address %s), mac); +goto cleanup; +} else if (pos 0) { +virMacAddrFormat(net-mac, mac); +virReportError(VIR_ERR_OPERATION_FAILED, + _(couldn't find matching device + with mac address %s), mac); +goto cleanup; +} + +virDomainNetDefFree(vmdef-nets[pos]); + +vmdef-nets[pos] = net; +dev-data.net = NULL; +ret = 0; + +break; + default: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, %s, _(persistent update of device is not supported)); break; } +cleanup: return ret; } static int -lxcDomainDetachDeviceConfig(virDomainDefPtr vmDef ATTRIBUTE_UNUSED, +lxcDomainDetachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev) { int ret = -1; +virDomainNetDefPtr net; +int idx; +char mac[VIR_MAC_STRING_BUFLEN]; switch (dev-type) { +case VIR_DOMAIN_DEVICE_NET: +net = dev-data.net; +idx = virDomainNetFindIdx(vmdef, net); +if (idx == -2) { +virReportError(VIR_ERR_OPERATION_FAILED, + _(multiple devices matching mac address %s found), + virMacAddrFormat(net-mac, mac)); +goto cleanup; +} else if (idx 0) { +virReportError(VIR_ERR_OPERATION_FAILED, %s, + _(no matching network device was found)); +goto cleanup; +} +/* this is guaranteed to succeed */ +virDomainNetDefFree(virDomainNetRemove(vmdef, idx)); +ret = 0; +break; + default: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, %s, _(persistent detach of device is not supported)); break; } +cleanup: return ret; } -- 1.8.0.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 04/23] Refactor LXC NIC creation to allow reuse by hotplug code
From: Daniel P. Berrange berra...@redhat.com The code for creating veth/macvlan devices is part of the LXC process startup code. Refactor this a little and export the methods to the rest of the LXC driver. This allows them to be reused for NIC hotplug code Signed-off-by: Daniel P. Berrange berra...@redhat.com --- src/lxc/lxc_process.c | 102 +- src/lxc/lxc_process.h | 8 2 files changed, 50 insertions(+), 60 deletions(-) diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c index 8b9d02f..72e1be3 100644 --- a/src/lxc/lxc_process.c +++ b/src/lxc/lxc_process.c @@ -293,14 +293,12 @@ static void virLXCProcessCleanup(virLXCDriverPtr driver, } -static int virLXCProcessSetupInterfaceBridged(virConnectPtr conn, - virDomainDefPtr vm, - virDomainNetDefPtr net, - const char *brname, - unsigned int *nveths, - char ***veths) +char *virLXCProcessSetupInterfaceBridged(virConnectPtr conn, + virDomainDefPtr vm, + virDomainNetDefPtr net, + const char *brname) { -int ret = -1; +char *ret = NULL; char *parentVeth; char *containerVeth = NULL; const virNetDevVPortProfilePtr vport = virDomainNetGetActualVirtPortProfile(net); @@ -314,24 +312,17 @@ static int virLXCProcessSetupInterfaceBridged(virConnectPtr conn, if (net-ifname == NULL) net-ifname = parentVeth; -if (VIR_REALLOC_N(*veths, (*nveths)+1) 0) { -virReportOOMError(); -VIR_FREE(containerVeth); -goto cleanup; -} -(*veths)[(*nveths)] = containerVeth; -(*nveths)++; - if (virNetDevSetMAC(containerVeth, net-mac) 0) goto cleanup; -if (vport vport-virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH) -ret = virNetDevOpenvswitchAddPort(brname, parentVeth, net-mac, - vm-uuid, vport, virDomainNetGetActualVlan(net)); -else -ret = virNetDevBridgeAddPort(brname, parentVeth); -if (ret 0) -goto cleanup; +if (vport vport-virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH) { +if (virNetDevOpenvswitchAddPort(brname, parentVeth, net-mac, +vm-uuid, vport, virDomainNetGetActualVlan(net)) 0) +goto cleanup; +} else { +if (virNetDevBridgeAddPort(brname, parentVeth) 0) +goto cleanup; +} if (virNetDevSetOnline(parentVeth, true) 0) goto cleanup; @@ -348,20 +339,18 @@ static int virLXCProcessSetupInterfaceBridged(virConnectPtr conn, virDomainConfNWFilterInstantiate(conn, vm-uuid, net) 0) goto cleanup; -ret = 0; +ret = containerVeth; cleanup: return ret; } -static int virLXCProcessSetupInterfaceDirect(virConnectPtr conn, - virDomainDefPtr def, - virDomainNetDefPtr net, - unsigned int *nveths, - char ***veths) +char *virLXCProcessSetupInterfaceDirect(virConnectPtr conn, +virDomainDefPtr def, +virDomainNetDefPtr net) { -int ret = -1; +char *ret = NULL; char *res_ifname = NULL; virLXCDriverPtr driver = conn-privateData; virNetDevBandwidthPtr bw; @@ -376,7 +365,7 @@ static int virLXCProcessSetupInterfaceDirect(virConnectPtr conn, if (bw) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, %s, _(Unable to set network bandwidth on direct interfaces)); -return -1; +return NULL; } /* XXX how todo port profiles ? @@ -390,15 +379,9 @@ static int virLXCProcessSetupInterfaceDirect(virConnectPtr conn, if (prof) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, %s, _(Unable to set port profile on direct interfaces)); -return -1; +return NULL; } -if (VIR_REALLOC_N(*veths, (*nveths)+1) 0) { -virReportOOMError(); -return -1; -} -(*veths)[(*nveths)] = NULL; - if (virNetDevMacVLanCreateWithVPortProfile( net-ifname, net-mac, virDomainNetGetActualDirectDev(net), @@ -411,10 +394,7 @@ static int virLXCProcessSetupInterfaceDirect(virConnectPtr conn, virDomainNetGetActualBandwidth(net)) 0) goto cleanup; -(*veths)[(*nveths)] = res_ifname; -(*nveths)++; - -ret = 0; +ret = res_ifname; cleanup: return ret; @@ -436,13 +416,14 @@ cleanup: */ static int
[libvirt] [PATCH 20/23] Add support for hotplug/unplug of host storage devices in LXC
From: Daniel P. Berrange berra...@redhat.com Wire up the attach/detach device drivers in LXC to support the hotplug/unplug of host storage devices. Signed-off-by: Daniel P. Berrange berra...@redhat.com --- src/lxc/lxc_driver.c | 237 +++ 1 file changed, 237 insertions(+) diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 50050cf..27ee3d7 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -3224,6 +3224,12 @@ lxcDomainAttachDeviceHostdevSubsysUSBLive(virLXCDriverPtr driver, usbDevice *usb = NULL; virCgroupPtr group = NULL; +if (virDomainHostdevFind(vm-def, def, NULL) = 0) { +virReportError(VIR_ERR_OPERATION_FAILED, %s, + _(host USB device already exists)); +return -1; +} + if (virAsprintf(vroot, /proc/%llu/root, (unsigned long long)priv-initpid) 0) { virReportOOMError(); @@ -3351,6 +3357,123 @@ cleanup: static int +lxcDomainAttachDeviceHostdevStorageLive(virLXCDriverPtr driver, +virDomainObjPtr vm, +virDomainDeviceDefPtr dev) +{ +virLXCDomainObjPrivatePtr priv = vm-privateData; +virDomainHostdevDefPtr def = dev-data.hostdev; +virCgroupPtr group = NULL; +int ret = -1; +char *dst; +char *vroot; +struct stat sb; +bool created = false; +mode_t mode = 0; + +if (!priv-initpid) { +virReportError(VIR_ERR_OPERATION_INVALID, %s, + _(Cannot attach disk until init PID is known)); +goto cleanup; +} + +if (!def-source.caps.u.storage.block) { +virReportError(VIR_ERR_CONFIG_UNSUPPORTED, %s, + _(Missing storage block path)); +goto cleanup; +} + +if (virDomainHostdevFind(vm-def, def, NULL) = 0) { +virReportError(VIR_ERR_OPERATION_FAILED, %s, + _(host device already exists)); +return -1; +} + +if (stat(def-source.caps.u.storage.block, sb) 0) { +virReportSystemError(errno, + _(Unable to access %s), + def-source.caps.u.storage.block); +goto cleanup; +} + +if (!S_ISBLK(sb.st_mode)) { +virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _(Hostdev source %s must be a block device), + def-source.caps.u.storage.block); +goto cleanup; +} + +if (virAsprintf(vroot, /proc/%llu/root, +(unsigned long long)priv-initpid) 0) { +virReportOOMError(); +goto cleanup; +} + +if (virAsprintf(dst, %s/%s, +vroot, +def-source.caps.u.storage.block) 0) { +virReportOOMError(); +goto cleanup; +} + +if (VIR_REALLOC_N(vm-def-hostdevs, vm-def-nhostdevs+1) 0) { +virReportOOMError(); +goto cleanup; +} + +mode = 0700 | S_IFBLK; + +VIR_DEBUG(Creating dev %s (%d,%d), + def-source.caps.u.storage.block, + major(sb.st_rdev), minor(sb.st_rdev)); +if (mknod(dst, mode, sb.st_rdev) 0) { +virReportSystemError(errno, + _(Unable to create device %s), + dst); +goto cleanup; +} +created = true; + +if (virSecurityManagerSetHostdevLabel(driver-securityManager, + vm-def, def, vroot) 0) +goto cleanup; + +if (!lxcCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) { +virReportError(VIR_ERR_OPERATION_INVALID, %s, + _(devices cgroup isn't mounted)); +goto cleanup; +} + +if (virCgroupForDomain(driver-cgroup, vm-def-name, group, 0) != 0) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _(cannot find cgroup for domain %s), vm-def-name); +goto cleanup; +} + +if (virCgroupAllowDevicePath(group, def-source.caps.u.storage.block, + VIR_CGROUP_DEVICE_RW | + VIR_CGROUP_DEVICE_MKNOD) != 0) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _(cannot allow device %s for domain %s), + def-source.caps.u.storage.block, vm-def-name); +goto cleanup; +} + +vm-def-hostdevs[vm-def-nhostdevs++] = def; + +ret = 0; + +cleanup: +virDomainAuditHostdev(vm, def, attach, ret == 0); +if (group) +virCgroupFree(group); +if (dst created ret 0) +unlink(dst); +return ret; +} + + +static int lxcDomainAttachDeviceHostdevSubsysLive(virLXCDriverPtr driver, virDomainObjPtr vm, virDomainDeviceDefPtr dev) @@ -3369,6 +3492,24 @@ lxcDomainAttachDeviceHostdevSubsysLive(virLXCDriverPtr driver, static int
[libvirt] [PATCH 07/23] Refactor SELinux security driver hostdev labelling
From: Daniel P. Berrange berra...@redhat.com Prepare to support different types of hostdevs by refactoring the current SELinux security driver code Signed-off-by: Daniel P. Berrange berra...@redhat.com --- src/security/security_selinux.c | 89 +++-- 1 file changed, 59 insertions(+), 30 deletions(-) diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c index 9070ff9..ad13490 100644 --- a/src/security/security_selinux.c +++ b/src/security/security_selinux.c @@ -1118,26 +1118,15 @@ virSecuritySELinuxSetSecurityUSBLabel(usbDevice *dev ATTRIBUTE_UNUSED, return virSecuritySELinuxSetFilecon(file, secdef-imagelabel); } + static int -virSecuritySELinuxSetSecurityHostdevLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, - virDomainDefPtr def, - virDomainHostdevDefPtr dev, - const char *vroot) +virSecuritySELinuxSetSecurityHostdevSubsysLabel(virDomainDefPtr def, +virDomainHostdevDefPtr dev, +const char *vroot) { -virSecurityLabelDefPtr secdef; int ret = -1; -secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME); -if (secdef == NULL) -return -1; - -if (secdef-norelabel) -return 0; - -if (dev-mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) -return 0; - switch (dev-source.subsys.type) { case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: { usbDevice *usb; @@ -1182,6 +1171,32 @@ done: static int +virSecuritySELinuxSetSecurityHostdevLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, + virDomainDefPtr def, + virDomainHostdevDefPtr dev, + const char *vroot) + +{ +virSecurityLabelDefPtr secdef; + +secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME); +if (secdef == NULL) +return -1; + +if (secdef-norelabel) +return 0; + +switch (dev-mode) { +case VIR_DOMAIN_HOSTDEV_MODE_SUBSYS: +return virSecuritySELinuxSetSecurityHostdevSubsysLabel(def, dev, vroot); + +default: +return 0; +} +} + + +static int virSecuritySELinuxRestoreSecurityPCILabel(pciDevice *dev ATTRIBUTE_UNUSED, const char *file, void *opaque ATTRIBUTE_UNUSED) @@ -1197,26 +1212,14 @@ virSecuritySELinuxRestoreSecurityUSBLabel(usbDevice *dev ATTRIBUTE_UNUSED, return virSecuritySELinuxRestoreSecurityFileLabel(file); } + static int -virSecuritySELinuxRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, - virDomainDefPtr def, - virDomainHostdevDefPtr dev, - const char *vroot) +virSecuritySELinuxRestoreSecurityHostdevSubsysLabel(virDomainHostdevDefPtr dev, +const char *vroot) { -virSecurityLabelDefPtr secdef; int ret = -1; -secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME); -if (secdef == NULL) -return -1; - -if (secdef-norelabel) -return 0; - -if (dev-mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) -return 0; - switch (dev-source.subsys.type) { case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: { usbDevice *usb; @@ -1262,6 +1265,32 @@ done: static int +virSecuritySELinuxRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, + virDomainDefPtr def, + virDomainHostdevDefPtr dev, + const char *vroot) + +{ +virSecurityLabelDefPtr secdef; + +secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME); +if (secdef == NULL) +return -1; + +if (secdef-norelabel) +return 0; + +switch (dev-mode) { +case VIR_DOMAIN_HOSTDEV_MODE_SUBSYS: +return virSecuritySELinuxRestoreSecurityHostdevSubsysLabel(dev, vroot); + +default: +return 0; +} +} + + +static int virSecuritySELinuxSetSecurityChardevLabel(virDomainDefPtr def, virDomainChrDefPtr dev, virDomainChrSourceDefPtr dev_source) -- 1.8.0.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 08/23] Add support for SELinux labelling of hostdev storage/misc devices
From: Daniel P. Berrange berra...@redhat.com The SELinux security driver needs to learn to label storage/misc hostdev devices for LXC Signed-off-by: Daniel P. Berrange berra...@redhat.com --- src/security/security_selinux.c | 118 1 file changed, 118 insertions(+) diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c index ad13490..6f0cd4d 100644 --- a/src/security/security_selinux.c +++ b/src/security/security_selinux.c @@ -1171,6 +1171,65 @@ done: static int +virSecuritySELinuxSetSecurityHostdevCapsLabel(virDomainDefPtr def, + virDomainHostdevDefPtr dev, + const char *vroot) +{ +int ret = -1; +virSecurityLabelDefPtr secdef; +char *path; + +secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME); +if (secdef == NULL) +return -1; + +switch (dev-source.caps.type) { +case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_STORAGE: { +if (vroot) { +if (virAsprintf(path, %s/%s, vroot, +dev-source.caps.u.storage.block) 0) { +virReportOOMError(); +return -1; +} +} else { +if (!(path = strdup(dev-source.caps.u.storage.block))) { +virReportOOMError(); +return -1; +} +} +ret = virSecuritySELinuxSetFilecon(path, secdef-imagelabel); +VIR_FREE(path); +break; +} + +case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_MISC: { +if (vroot) { +if (virAsprintf(path, %s/%s, vroot, +dev-source.caps.u.misc.chardev) 0) { +virReportOOMError(); +return -1; +} +} else { +if (!(path = strdup(dev-source.caps.u.misc.chardev))) { +virReportOOMError(); +return -1; +} +} +ret = virSecuritySELinuxSetFilecon(path, secdef-imagelabel); +VIR_FREE(path); +break; +} + +default: +ret = 0; +break; +} + +return ret; +} + + +static int virSecuritySELinuxSetSecurityHostdevLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, virDomainDefPtr def, virDomainHostdevDefPtr dev, @@ -1190,6 +1249,9 @@ virSecuritySELinuxSetSecurityHostdevLabel(virSecurityManagerPtr mgr ATTRIBUTE_UN case VIR_DOMAIN_HOSTDEV_MODE_SUBSYS: return virSecuritySELinuxSetSecurityHostdevSubsysLabel(def, dev, vroot); +case VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES: +return virSecuritySELinuxSetSecurityHostdevCapsLabel(def, dev, vroot); + default: return 0; } @@ -1265,6 +1327,59 @@ done: static int +virSecuritySELinuxRestoreSecurityHostdevCapsLabel(virDomainHostdevDefPtr dev, + const char *vroot) +{ +int ret = -1; +char *path; + +switch (dev-source.caps.type) { +case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_STORAGE: { +if (vroot) { +if (virAsprintf(path, %s/%s, vroot, +dev-source.caps.u.storage.block) 0) { +virReportOOMError(); +return -1; +} +} else { +if (!(path = strdup(dev-source.caps.u.storage.block))) { +virReportOOMError(); +return -1; +} +} +ret = virSecuritySELinuxRestoreSecurityFileLabel(path); +VIR_FREE(path); +break; +} + +case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_MISC: { +if (vroot) { +if (virAsprintf(path, %s/%s, vroot, +dev-source.caps.u.misc.chardev) 0) { +virReportOOMError(); +return -1; +} +} else { +if (!(path = strdup(dev-source.caps.u.misc.chardev))) { +virReportOOMError(); +return -1; +} +} +ret = virSecuritySELinuxRestoreSecurityFileLabel(path); +VIR_FREE(path); +break; +} + +default: +ret = 0; +break; +} + +return ret; +} + + +static int virSecuritySELinuxRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, virDomainDefPtr def, virDomainHostdevDefPtr dev, @@ -1284,6 +1399,9 @@ virSecuritySELinuxRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr ATTRIBUT case VIR_DOMAIN_HOSTDEV_MODE_SUBSYS: return virSecuritySELinuxRestoreSecurityHostdevSubsysLabel(dev, vroot); +case VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES: +return virSecuritySELinuxRestoreSecurityHostdevCapsLabel(dev, vroot); + default: return 0; } -- 1.8.0.1 -- libvir-list mailing
[libvirt] [PATCH 15/23] Add support for attach/detach/update disk devices in config for LXC
From: Daniel P. Berrange berra...@redhat.com Wire up the attach/detach/update device APIs to support changing of disks in the persistent config file Signed-off-by: Daniel P. Berrange berra...@redhat.com --- src/lxc/lxc_driver.c | 29 + 1 file changed, 29 insertions(+) diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index ecd7cb8..9a56643 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -2774,9 +2774,26 @@ lxcDomainAttachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev) { int ret = -1; +virDomainDiskDefPtr disk; virDomainNetDefPtr net; switch (dev-type) { +case VIR_DOMAIN_DEVICE_DISK: +disk = dev-data.disk; +if (virDomainDiskIndexByName(vmdef, disk-dst, true) = 0) { +virReportError(VIR_ERR_INVALID_ARG, + _(target %s already exists.), disk-dst); +return -1; +} +if (virDomainDiskInsert(vmdef, disk)) { +virReportOOMError(); +return -1; +} +/* vmdef has the pointer. Generic codes for vmdef will do all jobs */ +dev-data.disk = NULL; +ret = 0; +break; + case VIR_DOMAIN_DEVICE_NET: net = dev-data.net; if (virDomainNetInsert(vmdef, net) 0) { @@ -2849,11 +2866,23 @@ lxcDomainDetachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev) { int ret = -1; +virDomainDiskDefPtr disk, det_disk; virDomainNetDefPtr net; int idx; char mac[VIR_MAC_STRING_BUFLEN]; switch (dev-type) { +case VIR_DOMAIN_DEVICE_DISK: +disk = dev-data.disk; +if (!(det_disk = virDomainDiskRemoveByName(vmdef, disk-dst))) { +virReportError(VIR_ERR_INVALID_ARG, + _(no target device %s), disk-dst); +return -1; +} +virDomainDiskDefFree(det_disk); +ret = 0; +break; + case VIR_DOMAIN_DEVICE_NET: net = dev-data.net; idx = virDomainNetFindIdx(vmdef, net); -- 1.8.0.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 22/23] Don't force existance of a USB controller for containers
From: Daniel P. Berrange berra...@redhat.com The virDomainDefCompatibleDevice method checks if the domain has a USB controller for any USB devices. This is not required when using containers, so skip that check Signed-off-by: Daniel P. Berrange berra...@redhat.com --- src/conf/domain_conf.c | 14 -- 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index d97bbc8..43336d7 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -14530,12 +14530,14 @@ int virDomainDefCompatibleDevice(virDomainDefPtr def, virDomainDeviceDefPtr dev) { -if (!virDomainDefHasUSB(def) -virDomainDeviceIsUSB(dev)) { -virReportError(VIR_ERR_CONFIG_UNSUPPORTED, %s, - _(Device configuration is not compatible: - Domain has no USB bus support)); -return -1; +if (virDomainDeviceIsUSB(dev)) { +if (STRNEQ(def-os.type, exe) +!virDomainDefHasUSB(def)) { +virReportError(VIR_ERR_CONFIG_UNSUPPORTED, %s, + _(Device configuration is not compatible: + Domain has no USB bus support)); +return -1; +} } return 0; -- 1.8.0.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 06/23] Allow passing a vroot into security manager hostdev labelling
From: Daniel P. Berrange berra...@redhat.com When LXC labels USB devices during hotplug, it is running in host context, so it needs to pass in a vroot path to the container root. Signed-off-by: Daniel P. Berrange berra...@redhat.com --- src/qemu/qemu_cgroup.c | 3 ++- src/qemu/qemu_hostdev.c | 11 +++ src/qemu/qemu_hotplug.c | 11 ++- src/security/security_apparmor.c | 10 ++ src/security/security_dac.c | 20 +--- src/security/security_driver.h | 6 -- src/security/security_manager.c | 10 ++ src/security/security_manager.h | 6 -- src/security/security_nop.c | 6 -- src/security/security_selinux.c | 20 +--- src/security/security_stack.c| 16 src/util/hostusb.c | 17 + src/util/hostusb.h | 6 +- 13 files changed, 95 insertions(+), 47 deletions(-) diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c index 30cd1d6..084d89d 100644 --- a/src/qemu/qemu_cgroup.c +++ b/src/qemu/qemu_cgroup.c @@ -290,7 +290,8 @@ int qemuSetupCgroup(virQEMUDriverPtr driver, continue; if ((usb = usbGetDevice(hostdev-source.subsys.u.usb.bus, -hostdev-source.subsys.u.usb.device)) == NULL) +hostdev-source.subsys.u.usb.device, +NULL)) == NULL) goto cleanup; if (usbDeviceFileIterate(usb, qemuSetupHostUsbDeviceCgroup, diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index ab0f173..6d706a6 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -179,7 +179,8 @@ qemuUpdateActiveUsbHostdevs(virQEMUDriverPtr driver, continue; usb = usbGetDevice(hostdev-source.subsys.u.usb.bus, - hostdev-source.subsys.u.usb.device); + hostdev-source.subsys.u.usb.device, + NULL); if (!usb) { VIR_WARN(Unable to reattach USB device %03d.%03d on domain %s, hostdev-source.subsys.u.usb.bus, @@ -657,6 +658,7 @@ qemuFindHostdevUSBDevice(virDomainHostdevDefPtr hostdev, if (vendor bus) { rc = usbFindDevice(vendor, product, bus, device, + NULL, autoAddress ? false : mandatory, usb); if (rc 0) { @@ -677,7 +679,7 @@ qemuFindHostdevUSBDevice(virDomainHostdevDefPtr hostdev, if (vendor) { usbDeviceList *devs; -rc = usbFindDeviceByVendor(vendor, product, mandatory, devs); +rc = usbFindDeviceByVendor(vendor, product, NULL, mandatory, devs); if (rc 0) return -1; @@ -717,7 +719,7 @@ qemuFindHostdevUSBDevice(virDomainHostdevDefPtr hostdev, bus, device); } } else if (!vendor bus) { -if (usbFindDeviceByBus(bus, device, mandatory, usb) 0) +if (usbFindDeviceByBus(bus, device, NULL, mandatory, usb) 0) return -1; } @@ -936,7 +938,8 @@ qemuDomainReAttachHostUsbDevices(virQEMUDriverPtr driver, continue; usb = usbGetDevice(hostdev-source.subsys.u.usb.bus, - hostdev-source.subsys.u.usb.device); + hostdev-source.subsys.u.usb.device, + NULL); if (!usb) { VIR_WARN(Unable to reattach USB device %03d.%03d on domain %s, diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index cfeae68..36022e4 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1105,7 +1105,8 @@ int qemuDomainAttachHostUsbDevice(virQEMUDriverPtr driver, } if ((usb = usbGetDevice(hostdev-source.subsys.u.usb.bus, -hostdev-source.subsys.u.usb.device)) == NULL) +hostdev-source.subsys.u.usb.device, +NULL)) == NULL) goto error; data.vm = vm; @@ -1173,7 +1174,7 @@ int qemuDomainAttachHostDevice(virQEMUDriverPtr driver, } if (virSecurityManagerSetHostdevLabel(driver-securityManager, - vm-def, hostdev) 0) + vm-def, hostdev, NULL) 0) goto cleanup; switch (hostdev-source.subsys.type) { @@ -1201,7 +1202,7 @@ int qemuDomainAttachHostDevice(virQEMUDriverPtr driver, error: if (virSecurityManagerRestoreHostdevLabel(driver-securityManager, - vm-def, hostdev) 0) + vm-def, hostdev, NULL) 0) VIR_WARN(Unable to restore host device labelling on hotplug fail); cleanup: @@ -2337,7 +2338,7 @@ qemuDomainDetachHostUsbDevice(virQEMUDriverPtr driver, if (ret 0)
[libvirt] [PATCH 17/23] Add support for hotplug/unplug of disk devices in LXC
From: Daniel P. Berrange berra...@redhat.com Wire up the attach/detach device drivers in LXC to support the hotplug/unplug of disks. Signed-off-by: Daniel P. Berrange berra...@redhat.com --- src/lxc/lxc_driver.c | 212 +++ 1 file changed, 212 insertions(+) diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index daf32c7..a2bb497 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -30,6 +30,7 @@ #include string.h #include sys/types.h #include sys/socket.h +#include sys/stat.h #include sys/un.h #include sys/poll.h #include unistd.h @@ -2943,6 +2944,136 @@ cleanup: static int +lxcDomainAttachDeviceDiskLive(virLXCDriverPtr driver, + virDomainObjPtr vm, + virDomainDeviceDefPtr dev) +{ +virLXCDomainObjPrivatePtr priv = vm-privateData; +virDomainDiskDefPtr def = dev-data.disk; +virCgroupPtr group = NULL; +int ret = -1; +char *dst; +struct stat sb; +bool created = false; +mode_t mode = 0; +char *tmpsrc = def-src; + +if (!priv-initpid) { +virReportError(VIR_ERR_OPERATION_INVALID, %s, + _(Cannot attach disk until init PID is known)); +goto cleanup; +} + +if (def-type != VIR_DOMAIN_DISK_TYPE_BLOCK) { +virReportError(VIR_ERR_CONFIG_UNSUPPORTED, %s, + _(Can't setup disk for non-block device)); +goto cleanup; +} +if (def-src == NULL) { +virReportError(VIR_ERR_CONFIG_UNSUPPORTED, %s, + _(Can't setup disk without media)); +goto cleanup; +} + +if (virDomainDiskIndexByName(vm-def, def-dst, true) = 0) { +virReportError(VIR_ERR_OPERATION_FAILED, + _(target %s already exists), def-dst); +goto cleanup; +} + +if (stat(def-src, sb) 0) { +virReportSystemError(errno, + _(Unable to access %s), def-src); +goto cleanup; +} + +if (!S_ISCHR(sb.st_mode) !S_ISBLK(sb.st_mode)) { +virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _(Disk source %s must be a character/block device), + def-src); +goto cleanup; +} + +if (virAsprintf(dst, /proc/%llu/root/dev/%s, +(unsigned long long)priv-initpid, def-dst) 0) { +virReportOOMError(); +goto cleanup; +} + +if (VIR_REALLOC_N(vm-def-disks, vm-def-ndisks+1) 0) { +virReportOOMError(); +goto cleanup; +} + +mode = 0700; +if (S_ISCHR(sb.st_mode)) +mode |= S_IFCHR; +else +mode |= S_IFBLK; + +/* Yes, the device name we're creating may not + * actually correspond to the major:minor number + * we're using, but we've no other option at this + * time. Just have to hope that containerized apps + * don't get upset that the major:minor is different + * to that normally implied by the device name + */ +VIR_DEBUG(Creating dev %s (%d,%d) from %s, + dst, major(sb.st_rdev), minor(sb.st_rdev), def-src); +if (mknod(dst, mode, sb.st_rdev) 0) { +virReportSystemError(errno, + _(Unable to create device %s), + dst); +goto cleanup; +} +created = true; + +/* Labelling normally operates on src, but we need + * to actally label the dst here, so hack the config */ +def-src = dst; +if (virSecurityManagerSetImageLabel(driver-securityManager, +vm-def, def) 0) +goto cleanup; + +if (!lxcCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) { +virReportError(VIR_ERR_OPERATION_INVALID, %s, + _(devices cgroup isn't mounted)); +goto cleanup; +} + +if (virCgroupForDomain(driver-cgroup, vm-def-name, group, 0) != 0) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _(cannot find cgroup for domain %s), vm-def-name); +goto cleanup; +} + +if (virCgroupAllowDevicePath(group, def-src, + (def-readonly ? + VIR_CGROUP_DEVICE_READ : + VIR_CGROUP_DEVICE_RW) | + VIR_CGROUP_DEVICE_MKNOD) != 0) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _(cannot allow device %s for domain %s), + def-src, vm-def-name); +goto cleanup; +} + +virDomainDiskInsertPreAlloced(vm-def, def); + +ret = 0; + +cleanup: +def-src = tmpsrc; +virDomainAuditDisk(vm, NULL, def-src, attach, ret == 0); +if (group) +virCgroupFree(group); +if (dst created ret 0) +unlink(dst); +return ret; +} + + +static int lxcDomainAttachDeviceLive(virLXCDriverPtr driver ATTRIBUTE_UNUSED,
[libvirt] [PATCH 05/23] Skip bulk relabelling of resources in SELinux driver when used with LXC
From: Daniel P. Berrange berra...@redhat.com The virSecurityManager{Set,Restore}AllLabel methods are invoked at domain startup/shutdown to relabel resources associated with a domain. This works fine with QEMU, but with LXC they are in fact both currently no-ops since LXC does not support disks, hostdevs, or kernel/initrd files. Worse, when LXC gains support for disks/hostdevs, they will do the wrong thing, since they run in host context, not container context. Thus this patch turns then into a formal no-op when used with LXC. The LXC controller will call out to specific security manager labelling APIs as required during startup. Signed-off-by: Daniel P. Berrange berra...@redhat.com --- src/security/security_selinux.c | 12 +--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c index 5409e32..ddf3da3 100644 --- a/src/security/security_selinux.c +++ b/src/security/security_selinux.c @@ -61,6 +61,7 @@ struct _virSecuritySELinuxData { char *file_context; char *content_context; virHashTablePtr mcs; +bool skipAllLabel; }; struct _virSecuritySELinuxCallbackData { @@ -363,6 +364,8 @@ virSecuritySELinuxLXCInitialize(virSecurityManagerPtr mgr) virConfPtr selinux_conf; virSecuritySELinuxDataPtr data = virSecurityManagerGetPrivateData(mgr); +data-skipAllLabel = true; + selinux_conf = virConfReadFile(selinux_lxc_contexts_path(), 0); if (!selinux_conf) { virReportSystemError(errno, @@ -438,6 +441,8 @@ virSecuritySELinuxQEMUInitialize(virSecurityManagerPtr mgr) char *ptr; virSecuritySELinuxDataPtr data = virSecurityManagerGetPrivateData(mgr); +data-skipAllLabel = false; + if (virFileReadAll(selinux_virtual_domain_context_path(), MAX_CONTEXT, (data-domain_context)) 0) { virReportSystemError(errno, _(cannot read SELinux virtual domain context file '%s'), @@ -1438,11 +1443,12 @@ virSecuritySELinuxRestoreSecuritySmartcardCallback(virDomainDefPtr def, static int -virSecuritySELinuxRestoreSecurityAllLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, +virSecuritySELinuxRestoreSecurityAllLabel(virSecurityManagerPtr mgr, virDomainDefPtr def, int migrated ATTRIBUTE_UNUSED) { virSecurityLabelDefPtr secdef; +virSecuritySELinuxDataPtr data = virSecurityManagerGetPrivateData(mgr); int i; int rc = 0; @@ -1452,7 +1458,7 @@ virSecuritySELinuxRestoreSecurityAllLabel(virSecurityManagerPtr mgr ATTRIBUTE_UN if (secdef == NULL) return -1; -if (secdef-norelabel) +if (secdef-norelabel || data-skipAllLabel) return 0; for (i = 0 ; i def-nhostdevs ; i++) { @@ -1810,7 +1816,7 @@ virSecuritySELinuxSetSecurityAllLabel(virSecurityManagerPtr mgr, if (secdef == NULL) return -1; -if (secdef-norelabel) +if (secdef-norelabel || data-skipAllLabel) return 0; for (i = 0 ; i def-ndisks ; i++) { -- 1.8.0.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH 01/23] Slightly refactor hostdev parsing / formating
From: Daniel P. Berrange berra...@redhat.com Rename virDomainHostdevPartsParse to virDomainHostdevDefParseSubsys to reflect the fact that it only deals with hostdevs uing the traditional mode=subsystem, and not mode=capabilities Rename virDomainHostSourceFormat to virDomainHostdevDefFormatSubsys for the same reason. Signed-off-by: Daniel P. Berrange berra...@redhat.com --- src/conf/domain_conf.c | 101 - 1 file changed, 58 insertions(+), 43 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 814859a..ed31431 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -2949,31 +2949,16 @@ out: } static int -virDomainHostdevPartsParse(xmlNodePtr node, - xmlXPathContextPtr ctxt, - const char *mode, - const char *type, - virDomainHostdevDefPtr def, - unsigned int flags) +virDomainHostdevDefParseXMLSubsys(xmlNodePtr node, + xmlXPathContextPtr ctxt, + const char *type, + virDomainHostdevDefPtr def, + unsigned int flags) { xmlNodePtr sourcenode; char *managed = NULL; int ret = -1; -/* @mode is passed in separately from the caller, since an - * 'intelligent hostdev' has no place for 'mode' in the XML (it is - * always 'subsys'). - */ -if (mode) { -if ((def-mode=virDomainHostdevModeTypeFromString(mode)) 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, -_(unknown hostdev mode '%s'), mode); -goto error; -} -} else { -def-mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS; -} - /* @managed can be read from the xml document - it is always an * attribute of the toplevel element, no matter what type of * element that might be (pure hostdev, or higher level device @@ -4773,8 +4758,9 @@ virDomainActualNetDefParseXML(xmlNodePtr node, virReportOOMError(); goto error; } -if (virDomainHostdevPartsParse(node, ctxt, NULL, addrtype, - hostdev, flags) 0) { +hostdev-mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS; +if (virDomainHostdevDefParseXMLSubsys(node, ctxt, addrtype, + hostdev, flags) 0) { goto error; } } @@ -5150,8 +5136,9 @@ virDomainNetDefParseXML(virCapsPtr caps, virReportOOMError(); goto error; } -if (virDomainHostdevPartsParse(node, ctxt, NULL, addrtype, - hostdev, flags) 0) { +hostdev-mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS; +if (virDomainHostdevDefParseXMLSubsys(node, ctxt, addrtype, + hostdev, flags) 0) { goto error; } break; @@ -7320,9 +7307,27 @@ virDomainHostdevDefParseXML(const xmlNodePtr node, if (!(def = virDomainHostdevDefAlloc())) goto error; -/* parse managed/mode/type, and the source element */ -if (virDomainHostdevPartsParse(node, ctxt, mode, type, def, flags) 0) +if (mode) { +if ((def-mode = virDomainHostdevModeTypeFromString(mode)) 0) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _(unknown hostdev mode '%s'), mode); +goto error; +} +} else { +def-mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS; +} + +switch (def-mode) { +case VIR_DOMAIN_HOSTDEV_MODE_SUBSYS: +/* parse managed/mode/type, and the source element */ +if (virDomainHostdevDefParseXMLSubsys(node, ctxt, type, def, flags) 0) +goto error; +break; +default: +virReportError(VIR_ERR_INTERNAL_ERROR, + _(Unexpected hostdev mode %d), def-mode); goto error; +} if (def-info-type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) { if (virDomainDeviceInfoParseXML(node, bootMap, def-info, @@ -12337,10 +12342,10 @@ virDomainFSDefFormat(virBufferPtr buf, } static int -virDomainHostdevSourceFormat(virBufferPtr buf, - virDomainHostdevDefPtr def, - unsigned int flags, - bool includeTypeInAddr) +virDomainHostdevDefFormatSubsys(virBufferPtr buf, +virDomainHostdevDefPtr def, +unsigned int flags, +bool includeTypeInAddr) { virBufferAddLit(buf, source); if (def-startupPolicy) { @@ -12458,8 +12463,8 @@ virDomainActualNetDefFormat(virBufferPtr buf, break; case VIR_DOMAIN_NET_TYPE_HOSTDEV: -if (virDomainHostdevSourceFormat(buf, def-data.hostdev.def, -
[libvirt] [PATCH 19/23] Add support for hotplug/unplug of USB host devices in LXC
From: Daniel P. Berrange berra...@redhat.com Wire up the attach/detach device drivers in LXC to support the hotplug/unplug of USB host devices. Signed-off-by: Daniel P. Berrange berra...@redhat.com --- src/lxc/lxc_driver.c | 332 +++ 1 file changed, 332 insertions(+) diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 08ac70d..50050cf 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -39,6 +39,7 @@ #include virterror_internal.h #include logging.h #include datatypes.h +#include lxc_cgroup.h #include lxc_conf.h #include lxc_container.h #include lxc_domain.h @@ -3205,6 +3206,195 @@ cleanup: static int +lxcDomainAttachDeviceHostdevSubsysUSBLive(virLXCDriverPtr driver, + virDomainObjPtr vm, + virDomainDeviceDefPtr dev) +{ +virLXCDomainObjPrivatePtr priv = vm-privateData; +virDomainHostdevDefPtr def = dev-data.hostdev; +int ret = -1; +char *vroot = NULL; +char *src = NULL; +char *dstdir = NULL; +char *dstfile = NULL; +struct stat sb; +mode_t mode; +bool created = false; +usbDeviceList *list = NULL; +usbDevice *usb = NULL; +virCgroupPtr group = NULL; + +if (virAsprintf(vroot, /proc/%llu/root, +(unsigned long long)priv-initpid) 0) { +virReportOOMError(); +goto cleanup; +} + +if (virAsprintf(dstdir, %s/dev/bus/usb/%03d, +vroot, +def-source.subsys.u.usb.bus) 0) { +virReportOOMError(); +goto cleanup; +} + +if (virAsprintf(dstfile, %s/%03d, +dstdir, +def-source.subsys.u.usb.device) 0) { +virReportOOMError(); +goto cleanup; +} + +if (virAsprintf(src, /dev/bus/usb/%03d/%03d, +def-source.subsys.u.usb.bus, +def-source.subsys.u.usb.device) 0) { +virReportOOMError(); +goto cleanup; +} + +if (!lxcCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) { +virReportError(VIR_ERR_OPERATION_INVALID, %s, + _(devices cgroup isn't mounted)); +goto cleanup; +} + +if (virCgroupForDomain(driver-cgroup, vm-def-name, group, 0) != 0) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _(cannot find cgroup for domain %s), vm-def-name); +goto cleanup; +} + +if (VIR_REALLOC_N(vm-def-hostdevs, vm-def-nhostdevs+1) 0) { +virReportOOMError(); +goto cleanup; +} + +if (!(usb = usbGetDevice(def-source.subsys.u.usb.bus, + def-source.subsys.u.usb.device, vroot))) +goto cleanup; + +if (!(list = usbDeviceListNew())) +goto cleanup; + +if (usbDeviceListAdd(list, usb) 0) { +usbFreeDevice(usb); +usb = NULL; +goto cleanup; +} + +if (virLXCPrepareHostdevUSBDevices(driver, vm-def-name, list) 0) { +usb = NULL; +goto cleanup; +} + +usbDeviceListSteal(list, usb); + +if (stat(src, sb) 0) { +virReportSystemError(errno, + _(Unable to access %s), src); +goto cleanup; +} + +if (!S_ISCHR(sb.st_mode)) { +virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _(USB source %s was not a character device), + src); +goto cleanup; +} + +mode = 0700 | S_IFCHR; + +if (virFileMakePath(dstdir) 0) { +virReportSystemError(errno, + _(Unable to create %s), dstdir); +goto cleanup; +} + +VIR_DEBUG(Creating dev %s (%d,%d), + dstfile, major(sb.st_rdev), minor(sb.st_rdev)); +if (mknod(dstfile, mode, sb.st_rdev) 0) { +virReportSystemError(errno, + _(Unable to create device %s), + dstfile); +goto cleanup; +} +created = true; + +if (virSecurityManagerSetHostdevLabel(driver-securityManager, + vm-def, def, vroot) 0) +goto cleanup; + +if (usbDeviceFileIterate(usb, + virLXCSetupHostUsbDeviceCgroup, + group) 0) +goto cleanup; + +vm-def-hostdevs[vm-def-nhostdevs++] = def; + +ret = 0; + +cleanup: +virDomainAuditHostdev(vm, def, attach, ret == 0); +if (ret 0 created) +unlink(dstfile); + +usbDeviceListFree(list); +if (ret 0 usb) +usbDeviceListSteal(driver-activeUsbHostdevs, usb); + +virCgroupFree(group); +VIR_FREE(src); +VIR_FREE(dstfile); +VIR_FREE(dstdir); +VIR_FREE(vroot); +return ret; +} + + +static int +lxcDomainAttachDeviceHostdevSubsysLive(virLXCDriverPtr driver, + virDomainObjPtr vm, +
[libvirt] [PATCH 21/23] Add support for hotplug/unplug of host misc devices in LXC
From: Daniel P. Berrange berra...@redhat.com Wire up the attach/detach device drivers in LXC to support the hotplug/unplug of host misc devices. Signed-off-by: Daniel P. Berrange berra...@redhat.com --- src/lxc/lxc_driver.c | 194 +++ 1 file changed, 194 insertions(+) diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 27ee3d7..17445a7 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -3474,6 +3474,123 @@ cleanup: static int +lxcDomainAttachDeviceHostdevMiscLive(virLXCDriverPtr driver, + virDomainObjPtr vm, + virDomainDeviceDefPtr dev) +{ +virLXCDomainObjPrivatePtr priv = vm-privateData; +virDomainHostdevDefPtr def = dev-data.hostdev; +virCgroupPtr group = NULL; +int ret = -1; +char *dst; +char *vroot; +struct stat sb; +bool created = false; +mode_t mode = 0; + +if (!priv-initpid) { +virReportError(VIR_ERR_OPERATION_INVALID, %s, + _(Cannot attach disk until init PID is known)); +goto cleanup; +} + +if (!def-source.caps.u.misc.chardev) { +virReportError(VIR_ERR_CONFIG_UNSUPPORTED, %s, + _(Missing storage block path)); +goto cleanup; +} + +if (virDomainHostdevFind(vm-def, def, NULL) = 0) { +virReportError(VIR_ERR_OPERATION_FAILED, %s, + _(host device already exists)); +return -1; +} + +if (stat(def-source.caps.u.misc.chardev, sb) 0) { +virReportSystemError(errno, + _(Unable to access %s), + def-source.caps.u.misc.chardev); +goto cleanup; +} + +if (!S_ISCHR(sb.st_mode)) { +virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _(Hostdev source %s must be a block device), + def-source.caps.u.misc.chardev); +goto cleanup; +} + +if (virAsprintf(vroot, /proc/%llu/root, +(unsigned long long)priv-initpid) 0) { +virReportOOMError(); +goto cleanup; +} + +if (virAsprintf(dst, %s/%s, +vroot, +def-source.caps.u.misc.chardev) 0) { +virReportOOMError(); +goto cleanup; +} + +if (VIR_REALLOC_N(vm-def-hostdevs, vm-def-nhostdevs+1) 0) { +virReportOOMError(); +goto cleanup; +} + +mode = 0700 | S_IFCHR; + +VIR_DEBUG(Creating dev %s (%d,%d), + def-source.caps.u.misc.chardev, + major(sb.st_rdev), minor(sb.st_rdev)); +if (mknod(dst, mode, sb.st_rdev) 0) { +virReportSystemError(errno, + _(Unable to create device %s), + dst); +goto cleanup; +} +created = true; + +if (virSecurityManagerSetHostdevLabel(driver-securityManager, + vm-def, def, vroot) 0) +goto cleanup; + +if (!lxcCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) { +virReportError(VIR_ERR_OPERATION_INVALID, %s, + _(devices cgroup isn't mounted)); +goto cleanup; +} + +if (virCgroupForDomain(driver-cgroup, vm-def-name, group, 0) != 0) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _(cannot find cgroup for domain %s), vm-def-name); +goto cleanup; +} + +if (virCgroupAllowDevicePath(group, def-source.caps.u.misc.chardev, + VIR_CGROUP_DEVICE_RW | + VIR_CGROUP_DEVICE_MKNOD) != 0) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _(cannot allow device %s for domain %s), + def-source.caps.u.misc.chardev, vm-def-name); +goto cleanup; +} + +vm-def-hostdevs[vm-def-nhostdevs++] = def; + +ret = 0; + +cleanup: +virDomainAuditHostdev(vm, def, attach, ret == 0); +if (group) +virCgroupFree(group); +if (dst created ret 0) +unlink(dst); +return ret; +} + + +static int lxcDomainAttachDeviceHostdevSubsysLive(virLXCDriverPtr driver, virDomainObjPtr vm, virDomainDeviceDefPtr dev) @@ -3500,6 +3617,9 @@ lxcDomainAttachDeviceHostdevCapsLive(virLXCDriverPtr driver, case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_STORAGE: return lxcDomainAttachDeviceHostdevStorageLive(driver, vm, dev); +case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_MISC: +return lxcDomainAttachDeviceHostdevMiscLive(driver, vm, dev); + default: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _(Unsupported host device type %s), @@ -3875,6 +3995,77 @@ cleanup: static int +lxcDomainDetachDeviceHostdevMiscLive(virLXCDriverPtr driver, + virDomainObjPtr vm, +
Re: [libvirt] [PATCH v2] Allow comma separated list of shutdown/reboot modes with virsh
On Fri, Nov 30, 2012 at 02:28:53PM -0500, Eric Blake wrote: From: Daniel P. Berrange berra...@redhat.com The shutdown and reboot commands in virsh allow a comma separated list of mode values Signed-off-by: Daniel P. Berrange berra...@redhat.com --- tools/virsh-domain.c | 25 +++-- tools/virsh.pod | 16 2 files changed, 35 insertions(+), 6 deletions(-) Conditional ACK, if you squash in the hunk that got misplaced in your duration==0 patch. Opps, yes, rebase mistake. Will fix when pushing Well, we still have some sort of rebase mistake; 'git bisect' pointed to this commit as the culprit. ./virsh-undefine: line 62: 24499 Segmentation fault (core dumped) $abs_top_builddir/tools/virsh -q -c test:///default 'shutdown test; undefine test; dominfo test' out 21 --- expout 2012-11-30 13:43:00.894996356 -0700 +++ out 2012-11-30 13:43:00.747996489 -0700 @@ -1,4 +0,0 @@ -Domain test is being shutdown -Domain test has been undefined -error: failed to get domain 'test' -error: Domain not found FAIL: virsh-undefine I'm still looking into it. -- Eric Blake ebl...@redhat.com+1-919-301-3266 Libvirt virtualization library http://libvirt.org -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list