[libvirt] [PATCH v2] qemu: Set swap_hard_limit before hard_limit
by Osier Yang
Setting hard_limit larger than previous swap_hard_limit must fail,
it's not that good if one wants to change the swap_hard_limit
and hard_limit together. E.g.
% virsh memtune rhel6
hard_limit : 1000000
soft_limit : 1000000
swap_hard_limit: 1000000
% virsh memtune rhel6 --hard-limit 1000020 --soft-limit 1000020 \
--swap-hard-limit 1000020 --live
This patch reoder the limits setting to set the swap_hard_limit
first, hard_limit then, and soft_limit last if it's greater than
current swap_hard_limit. And soft_limit first, hard_limit then,
swap_hard_limit last, if not.
---
src/qemu/qemu_driver.c | 59 +++++++++++++++++++++++++++++++++++++++++------
1 files changed, 51 insertions(+), 8 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 80cfa84..a26d3cd 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -6651,11 +6651,18 @@ qemuDomainSetMemoryParameters(virDomainPtr dom,
virDomainDefPtr persistentDef = NULL;
virCgroupPtr group = NULL;
virDomainObjPtr vm = NULL;
+ virTypedParameterPtr hard_limit = NULL;
+ virTypedParameterPtr soft_limit = NULL;
+ virTypedParameterPtr swap_hard_limit = NULL;
+ virTypedParameterPtr sorted_params[nparams];
+ unsigned long long val = 0;
+
int ret = -1;
int rc;
virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
VIR_DOMAIN_AFFECT_CONFIG, -1);
+
if (virTypedParameterArrayValidate(params, nparams,
VIR_DOMAIN_MEMORY_HARD_LIMIT,
VIR_TYPED_PARAM_ULLONG,
@@ -6694,13 +6701,49 @@ qemuDomainSetMemoryParameters(virDomainPtr dom,
}
}
+ for (i = 0; i < nparams; i++) {
+ if (STREQ(params[i].field, VIR_DOMAIN_MEMORY_HARD_LIMIT))
+ hard_limit = ¶ms[i];
+ else if (STREQ(params[i].field, VIR_DOMAIN_MEMORY_SOFT_LIMIT))
+ soft_limit = ¶ms[i];
+ else if (STREQ(params[i].field, VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT))
+ swap_hard_limit = ¶ms[i];
+ }
+
+ /* It will fail if hard limit greater than swap hard limit anyway */
+ if (swap_hard_limit &&
+ hard_limit &&
+ (hard_limit->value.ul > swap_hard_limit->value.ul)) {
+ virReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("hard limit must be lower than swap hard limit"));
+ goto cleanup;
+ }
+
+ /* Get current swap hard limit */
+ rc = virCgroupGetMemSwapHardLimit(group, &val);
+ if (rc != 0) {
+ virReportSystemError(-rc, "%s",
+ _("unable to get swap hard limit"));
+ goto cleanup;
+ }
+
+ if (swap_hard_limit->value.ul > val) {
+ sorted_params[0] = swap_hard_limit;
+ sorted_params[1] = hard_limit;
+ sorted_params[2] = soft_limit;
+ } else {
+ sorted_params[0] = soft_limit;
+ sorted_params[1] = hard_limit;
+ sorted_params[2] = swap_hard_limit;
+ }
+
ret = 0;
for (i = 0; i < nparams; i++) {
- virTypedParameterPtr param = ¶ms[i];
+ virTypedParameterPtr param = sorted_params[i];
if (STREQ(param->field, VIR_DOMAIN_MEMORY_HARD_LIMIT)) {
if (flags & VIR_DOMAIN_AFFECT_LIVE) {
- rc = virCgroupSetMemoryHardLimit(group, params[i].value.ul);
+ rc = virCgroupSetMemoryHardLimit(group, sorted_params[i]->value.ul);
if (rc != 0) {
virReportSystemError(-rc, "%s",
_("unable to set memory hard_limit tunable"));
@@ -6709,11 +6752,11 @@ qemuDomainSetMemoryParameters(virDomainPtr dom,
}
if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
- persistentDef->mem.hard_limit = params[i].value.ul;
+ persistentDef->mem.hard_limit = sorted_params[i]->value.ul;
}
} else if (STREQ(param->field, VIR_DOMAIN_MEMORY_SOFT_LIMIT)) {
if (flags & VIR_DOMAIN_AFFECT_LIVE) {
- rc = virCgroupSetMemorySoftLimit(group, params[i].value.ul);
+ rc = virCgroupSetMemorySoftLimit(group, sorted_params[i]->value.ul);
if (rc != 0) {
virReportSystemError(-rc, "%s",
_("unable to set memory soft_limit tunable"));
@@ -6722,11 +6765,11 @@ qemuDomainSetMemoryParameters(virDomainPtr dom,
}
if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
- persistentDef->mem.soft_limit = params[i].value.ul;
+ persistentDef->mem.soft_limit = sorted_params[i]->value.ul;
}
} else if (STREQ(param->field, VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT)) {
if (flags & VIR_DOMAIN_AFFECT_LIVE) {
- rc = virCgroupSetMemSwapHardLimit(group, params[i].value.ul);
+ rc = virCgroupSetMemSwapHardLimit(group, sorted_params[i]->value.ul);
if (rc != 0) {
virReportSystemError(-rc, "%s",
_("unable to set swap_hard_limit tunable"));
@@ -6734,7 +6777,7 @@ qemuDomainSetMemoryParameters(virDomainPtr dom,
}
}
if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
- persistentDef->mem.swap_hard_limit = params[i].value.ul;
+ persistentDef->mem.swap_hard_limit = sorted_params[i]->value.ul;
}
}
}
@@ -7011,7 +7054,7 @@ qemuDomainSetNumaParameters(virDomainPtr dom,
continue;
}
- /* Ensure the cpuset string is formated before passing to cgroup */
+ /* Ensure the cpuset string is formatted before passing to cgroup */
if (!(nodeset_str = virDomainCpuSetFormat(nodeset,
VIR_DOMAIN_CPUMASK_LEN))) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
--
1.7.7.3
12 years, 3 months
[libvirt] [PATCH] qemu: Ensure the cpuset is formated as expected before passing to cgroup
by Osier Yang
The parameter value for cpuset could be in special format like
"0-10,^7", which is not recongnized by cgroup. This patch is to
ensure the cpuset is formated as expected before passing it to
cgroup. As a side effect, after the patch, it parses the cpuset
early before cgroup setting, to avoid the rollback if cpuset
parsing fails afterwards.
---
src/qemu/qemu_driver.c | 77 +++++++++++++++++++++++++----------------------
1 files changed, 41 insertions(+), 36 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 369e8ed..fc412a1 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -6952,8 +6952,23 @@ qemuDomainSetNumaParameters(virDomainPtr dom,
}
} else if (STREQ(param->field, VIR_DOMAIN_NUMA_NODESET)) {
int rc;
- bool savedmask;
- char oldnodemask[VIR_DOMAIN_CPUMASK_LEN];
+ char *nodeset = NULL;
+ char *nodeset_str = NULL;
+
+ if (VIR_ALLOC_N(nodeset, VIR_DOMAIN_CPUMASK_LEN) < 0) {
+ virReportOOMError();
+ ret = -1;
+ goto cleanup;
+ };
+
+ if (virDomainCpuSetParse(params[i].value.s,
+ 0, nodeset,
+ VIR_DOMAIN_CPUMASK_LEN) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Failed to parse nodeset"));
+ ret = -1;
+ continue;
+ }
if (flags & VIR_DOMAIN_AFFECT_LIVE) {
if (vm->def->numatune.memory.mode !=
@@ -6961,72 +6976,62 @@ qemuDomainSetNumaParameters(virDomainPtr dom,
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
_("change of nodeset for running domain "
"requires strict numa mode"));
+ VIR_FREE(nodeset);
ret = -1;
continue;
}
- rc = virCgroupSetCpusetMems(group, params[i].value.s);
- if (rc != 0) {
+
+ /* Ensure the cpuset string is formated before passing to cgroup */
+ if (!(nodeset_str = virDomainCpuSetFormat(nodeset,
+ VIR_DOMAIN_CPUMASK_LEN))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Failed to format nodeset"));
+ VIR_FREE(nodeset);
+ ret = -1;
+ continue;
+ }
+
+ if ((rc = virCgroupSetCpusetMems(group, nodeset_str) != 0)) {
virReportSystemError(-rc, "%s",
_("unable to set numa tunable"));
+ VIR_FREE(nodeset);
+ VIR_FREE(nodeset_str);
ret = -1;
continue;
}
+ VIR_FREE(nodeset_str);
/* update vm->def here so that dumpxml can read the new
* values from vm->def. */
- savedmask = false;
if (!vm->def->numatune.memory.nodemask) {
if (VIR_ALLOC_N(vm->def->numatune.memory.nodemask,
VIR_DOMAIN_CPUMASK_LEN) < 0) {
virReportOOMError();
+ VIR_FREE(nodeset);
ret = -1;
goto cleanup;
}
} else {
- memcpy(oldnodemask, vm->def->numatune.memory.nodemask,
- VIR_DOMAIN_CPUMASK_LEN);
- savedmask = true;
- }
- if (virDomainCpuSetParse(params[i].value.s,
- 0,
- vm->def->numatune.memory.nodemask,
- VIR_DOMAIN_CPUMASK_LEN) < 0) {
- if (savedmask)
- memcpy(vm->def->numatune.memory.nodemask,
- oldnodemask, VIR_DOMAIN_CPUMASK_LEN);
- else
- VIR_FREE(vm->def->numatune.memory.nodemask);
- ret = -1;
- continue;
+ VIR_FREE(vm->def->numatune.memory.nodemask);
}
+
+ vm->def->numatune.memory.nodemask = nodeset;
}
if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
- savedmask = false;
if (!persistentDef->numatune.memory.nodemask) {
if (VIR_ALLOC_N(persistentDef->numatune.memory.nodemask,
VIR_DOMAIN_CPUMASK_LEN) < 0) {
virReportOOMError();
+ VIR_FREE(nodeset);
ret = -1;
goto cleanup;
}
} else {
- memcpy(oldnodemask, persistentDef->numatune.memory.nodemask,
- VIR_DOMAIN_CPUMASK_LEN);
- savedmask = true;
- }
- if (virDomainCpuSetParse(params[i].value.s,
- 0,
- persistentDef->numatune.memory.nodemask,
- VIR_DOMAIN_CPUMASK_LEN) < 0) {
- if (savedmask)
- memcpy(persistentDef->numatune.memory.nodemask,
- oldnodemask, VIR_DOMAIN_CPUMASK_LEN);
- else
- VIR_FREE(persistentDef->numatune.memory.nodemask);
- ret = -1;
- continue;
+ VIR_FREE(persistentDef->numatune.memory.nodemask);
}
+
+ persistentDef->numatune.memory.nodemask = nodeset;
}
}
}
--
1.7.7.3
12 years, 3 months
[libvirt] [PATCHv2] build: avoid warnings on older gcc
by Eric Blake
The previous patch pulled in a newer version of stat-time.h from
gnulib, which tries to suppress some stupid gcc warnings (see
<http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54113>) by exploiting
a feature of newer gcc. But we still aim to compile on RHEL 6.3,
with gcc 4.4.6 (not to mention even older devel platforms like
RHEL 5), which fails to build thanks to our development -Werror.
It took me a while to figure out how to make our set of warnings
smaller on older gcc without losing the benefit of the warnings
when using newer gcc (such as the one on Fedora 17), but this
should do the trick.
* m4/virt-compile-warnings.m4 (LIBVIRT_COMPILE_WARNINGS): Avoid
warnings that gnulib can't silence on older gcc.
---
v2: Use AC_CACHE_CHECK, add -Werror, and test further.
Pushing under the build-breaker rule.
m4/virt-compile-warnings.m4 | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/m4/virt-compile-warnings.m4 b/m4/virt-compile-warnings.m4
index 9dee000..26f6134 100644
--- a/m4/virt-compile-warnings.m4
+++ b/m4/virt-compile-warnings.m4
@@ -58,6 +58,24 @@ AC_DEFUN([LIBVIRT_COMPILE_WARNINGS],[
# Gnulib's stat-time.h violates this
dontwarn="$dontwarn -Waggregate-return"
+ # Gnulib uses '#pragma GCC diagnostic push' to silence some
+ # warnings, but older gcc doesn't support this.
+ AC_CACHE_CHECK([whether pragma GCC diagnostic push works],
+ [lv_cv_gcc_pragma_push_works], [
+ save_CFLAGS=$CFLAGS
+ CFLAGS='-Wunknown-pragmas -Werror'
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic pop
+ ]])],
+ [lv_cv_gcc_pragma_push_works=yes],
+ [lv_cv_gcc_pragma_push_works=no])
+ CFLAGS=$save_CFLAGS])
+ if test $lv_cv_gcc_pragma_push_works = no; then
+ dontwarn="$dontwarn -Wmissing-prototypes"
+ dontwarn="$dontwarn -Wmissing-declarations"
+ fi
+
# We might fundamentally need some of these disabled forever, but
# ideally we'd turn many of them on
dontwarn="$dontwarn -Wfloat-equal"
--
1.7.11.2
12 years, 3 months
[libvirt] [PATCH v3 0/5] Per-guest configurable user/group for QEMU processes
by Marcelo Cerri
This is a v3 patch series that updates the libvirt's security driver mechanism to support per-guest configurable user and group for QEMU processes running together with other security drivers, such as SELinux and AppArmor.
Comments and feedbacks are welcome.
Marcelo Cerri (5):
Internal refactory of data structures
Multiple security drivers in XML data
Update security layer to handle many security labels
Support for multiple default security drivers in QEMU config
Update the remote API
daemon/remote.c | 63 ++++
docs/formatdomain.html.in | 11 +-
docs/schemas/capability.rng | 18 +-
docs/schemas/domaincommon.rng | 30 ++-
include/libvirt/libvirt.h.in | 2 +
python/generator.py | 1 +
src/conf/capabilities.c | 17 +-
src/conf/capabilities.h | 6 +-
src/conf/domain_audit.c | 14 +-
src/conf/domain_conf.c | 342 +++++++++++++++-----
src/conf/domain_conf.h | 18 +-
src/driver.h | 4 +
src/libvirt.c | 47 +++
src/libvirt_private.syms | 5 +
src/libvirt_public.syms | 5 +
src/lxc/lxc_conf.c | 8 +-
src/lxc/lxc_controller.c | 8 +-
src/lxc/lxc_driver.c | 11 +-
src/lxc/lxc_process.c | 23 +-
src/qemu/qemu_conf.c | 38 ++-
src/qemu/qemu_conf.h | 2 +-
src/qemu/qemu_driver.c | 218 +++++++++++---
src/qemu/qemu_process.c | 50 ++-
src/remote/remote_driver.c | 46 +++
src/remote/remote_protocol.x | 17 +-
src/remote_protocol-structs | 1 +
src/security/security_apparmor.c | 118 +++++--
src/security/security_dac.c | 324 +++++++++++++++++--
src/security/security_manager.c | 101 +++++--
src/security/security_manager.h | 8 +-
src/security/security_selinux.c | 256 ++++++++++-----
src/security/security_stack.c | 237 +++++++++-----
src/security/security_stack.h | 13 +
src/test/test_driver.c | 11 +-
.../qemuxml2argv-seclabel-dynamic-override.xml | 4 +-
.../qemuxml2argv-seclabel-dynamic.xml | 2 +-
36 files changed, 1634 insertions(+), 445 deletions(-)
12 years, 3 months
[libvirt] RFC: a <uuid> for every <interface> in each domain
by Laine Stump
A couple of situations have come up recently that could be solved by
every interface in every domain always having a unique identifier
associated with it:
1) In order to properly track information as a guest is disconnected and
reconnected to an Open vSwitch bridge, the initial Open vSwitch support
added an "interfaceid" parameter to virtualport. If the interfaceid
isn't specified by the user when the interface is defined, one is
automatically generated and placed into the persistent definition.
But if the guest interface is just <interface type='network'>, it isn't
known at the time of definition whether this interface will be using an
Open vSwitch connection, or something else. Then, by the time we get
into the network driver and decide that we're going to use Open vSwitch,
it's too late to conveniently/cleanly generate an interfaceid and plug
it back into the <virtualport> of the interface's persistent config. The
result is that each time the guest is restarted, Open vSwitch gets a new
interfaceid for it, and can't properly track things.
If every interface had a uuid, the code that connects to an Open vSwitch
network could just use the interface's uuid if interfaceid wasn't specified.
2) I'm about to write some patches that will allow enacting config
changes to a network without needing to destroy/re-start the network.
One thing that came up while I was mulling over what could and couldn't
be modified without a restart is that it will be possible to allow
removing physical interfaces from a network's interface pool (used for
macvtap and hostdev modes), but only if that physical interface isn't
currently in use. There is a use counter on each interface so we can
easily tell when that situation occurs, but once we know of the failure,
we have no way of pointing to which guest is causing the problem. If
each interface had a uuid, we could save a list of the uuid's of all
interfaces currently connected to a particular physical interface, and
report that in the failure message. It would then be a fairly mechanical
task to find that uuid in the guests' config.
Does this sound like a reasonable idea? Any reasons *not* to do it?
Problems we'll need to take care of if we add it (for example, existing
guest interfaces will all need to get a uuid during the upgrade process,
similar to the way we add a mac address to all existing networks that
don't have one). Any other things you can think of doing with uuid if we
add one?
12 years, 3 months
[libvirt] [PATCHv2 0/4] support <vlan> element for interfaces and networks
by Laine Stump
danpb raised a (valid) objection about the XML format in the first
version of these patches, so I've redone it to be like this:
<vlan trunk='yes'>
<tag id='42'/>
<tag id='30'/>
</vlan>
The downside is that for a single vlan tag, it's more verbose:
<vlan>
<tag id='42'/>
</vlan>
On the other hand, it's more consistent.
The rest of the patches in the series were unchanged (and even the
data definition is unchanged).
===
The purpose of these patches is to define a data type that can
properly describe an interface's vlan configuration (including
multiple vlans for trunking), provide XML parser and formatter to
translate to and from the new data type, add the new <vlan> element to
both domain <interface> and to <network> in appropriate places, and to
provide the new vlan data to the hypervisor driver.
Once these 4 patches are applied, all that will be left to support
vlan configuration for any network connection that supports it, is to
request the vlan data for the interface with
virDomainNetGetActualVlan(netdef). If that function returns NULL,
there is no vlan config for this interface; if it's non-zero, it is a
pointer to virNetDevVlan, and you can grab the data from there.
Since I currently know of only two types of network connection we will
be able to easily support this for (sr-iov VFs using PCI passthrough,
and openvswitch), any type other than those will refuse to start if a
vlan has been requested (see PATCH 4/4). This covers validation for
the qemu and lxc drivers (since they use common code), but I'm not
sure about xen, esx, or any other driver - they will likely require
extra code to either implement transparent vlan configuration, or log
an error if it's requested (my guess is that, in spite of our best
efforts, *many* people will misunderstand the limitations of this
functionality, and try to put all sorts of interfaces on vlans; it
will be much friendlier to inform them of the problem rather than
simply ignore the vlan config.
12 years, 3 months
[libvirt] [PATCHv2 0/9] network: properly support openvswitch in <network>
by Laine Stump
This is mainly a refresh of the initial version of the patch to
rebase, but there have also been a couple of small bugs fixed. In
particular, if not <virtualport/> is specified in the domain's
interface element, connection of the interface to an ovs switch won't
fail because of a missing interfaceid (see
http://www.redhat.com/archives/libvir-list/2012-August/msg00874.html
and it's parents)
Many of these patches are trivial or mechanical.
======
Although it's been possible (ever since openvswitch was added to
libvirt in 0.9.11) for a libvirt network to use an openvswitch bridge
(by adding <virtualport type='openvswitch'>), the virtualport in the
network would always have a default random interfaceid included, which
would be re-used for all interfaces using that network, which doesn't
really work at all. The alternative was to not specify openvswitch in
the <network> definition, but to do it in the guest's <interface>
definition instead - this of course goes against the principle of not
having host-specific config embedded in guest config.
This patch series enhances the functionality of <virtualport>
elements, to allow omitting some attributes (and even the type), and
to merge the interface, network, and portgroup virtualports rather
than simply picking one. This not only makes openvswitch <network>s
more practical (because the network can specify type='openvswitch'
without also specifying an interfaceid), but also makes <virtualport>
in networks and portgroups more useful in general - for example, an
interface can specify an interfaceid (used only by openvswitch) *and*
an instanceid (used only by 802.1Qbh), while the network's virtualport
specifies only the type, and the portgroups specify the managerid,
typeid, profileid, or whatever is appropriate for the type of switch
used by the network.
The result is that the guest config can be completely devoid of
knowledge about the type of switch being used on the hardware, but can
still enjoy full configurability for whatever switch ends up being
used.
12 years, 3 months
[libvirt] [PATCH] build: avoid warnings on older gcc
by Eric Blake
The previous patch pulled in a newer version of stat-time.h from
gnulib, which tries to suppress some stupid gcc warnings (see
<http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54113>) by exploiting
a feature of newer gcc. But we still aim to compile on RHEL 6.3,
with gcc 4.4.6 (not to mention even older devel platforms like
RHEL 5), which fails to build thanks to our development -Werror.
It took me a while to figure out how to make our set of warnings
smaller on older gcc without losing the benefit of the warnings
when using newer gcc (such as the one on Fedora 17), but this
should do the trick.
* m4/virt-compile-warnings.m4 (LIBVIRT_COMPILE_WARNINGS): Avoid
warnings that gnulib can't silence on older gcc.
---
If I don't get a review by tomorrow, I will go ahead and push this
under the build-breaker rule.
m4/virt-compile-warnings.m4 | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/m4/virt-compile-warnings.m4 b/m4/virt-compile-warnings.m4
index 9dee000..702506d 100644
--- a/m4/virt-compile-warnings.m4
+++ b/m4/virt-compile-warnings.m4
@@ -58,6 +58,23 @@ AC_DEFUN([LIBVIRT_COMPILE_WARNINGS],[
# Gnulib's stat-time.h violates this
dontwarn="$dontwarn -Waggregate-return"
+ # Gnulib uses '#pragma GCC diagnostic push' to silence some
+ # warnings, but older gcc doesn't support this.
+ AC_CACHE_VAL([lv_cv_gcc_pragma_push_works], [
+ save_CFLAGS=$CFLAGS
+ CFLAGS=-Wunknown-pragmas
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic pop
+ ]])],
+ [lv_cv_gcc_pragma_push_works=yes],
+ [lv_cv_gcc_pragma_push_works=no])
+ CFLAGS=$save_CFLAGS])
+ if test $lv_cv_gcc_pragma_push_works = no; then
+ dontwarn="$dontwarn -Wmissing-prototypes"
+ dontwarn="$dontwarn -Wmissing-declarations"
+ fi
+
# We might fundamentally need some of these disabled forever, but
# ideally we'd turn many of them on
dontwarn="$dontwarn -Wfloat-equal"
--
1.7.11.2
12 years, 3 months
[libvirt] [firewalld PATCHv3] firewalld PATCH v3
by Thomas Woerner
* configura.ac, spec file: firewalld now defaults to enabled, depends on
dbus
* fixed comment for with_firewalld define
* bridge_driver, nwfilter_driver: new dbus filters to get FirewallD1.Reloaded
signal and DBus.NameOwnerChanged on org.fedoraproject.FirewallD1
* iptables, ebtables, nwfilter_ebiptables_driver: use firewall-cmd direct
passthrough interface
* spec file changed as requested
---
configure.ac | 17 ++++++++++++++++
libvirt.spec.in | 11 +++++++++++
src/Makefile.am | 4 ++--
src/network/bridge_driver.c | 47 +++++++++++++++++++++++++++++++++++++++++++++
src/util/ebtables.c | 35 +++++++++++++++++++++++++++++++++
src/util/iptables.c | 21 ++++++++++++++++++--
6 files changed, 131 insertions(+), 4 deletions(-)
diff --git a/configure.ac b/configure.ac
index 8a04d91..c742d2f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1282,6 +1282,22 @@ AM_CONDITIONAL([HAVE_POLKIT1], [test "x$with_polkit1" = "xyes"])
AC_SUBST([POLKIT_CFLAGS])
AC_SUBST([POLKIT_LIBS])
+dnl firewalld
+AC_ARG_WITH([firewalld],
+ AC_HELP_STRING([--with-firewalld], [enable firewalld support @<:@default=check@:>@]),
+ [],
+ [with_firewalld=check])
+if test "x$with_firewalld" = "xcheck" ; then
+ with_firewalld=$with_dbus
+fi
+if test "x$with_firewalld" == "xyes" ; then
+ if test "x$with_dbus" != "xyes" ; then
+ AC_MSG_ERROR([You must have dbus enabled for firewalld support])
+ fi
+ AC_DEFINE_UNQUOTED([HAVE_FIREWALLD], [1], [whether firewalld support is enabled])
+fi
+AM_CONDITIONAL([HAVE_FIREWALLD], [test "x$with_firewalld" != "xno"])
+
dnl Avahi library
AC_ARG_WITH([avahi],
AC_HELP_STRING([--with-avahi], [use avahi to advertise remote daemon @<:@default=check@:>@]),
@@ -2989,6 +3005,7 @@ AC_MSG_NOTICE([ sanlock: $SANLOCK_CFLAGS $SANLOCK_LIBS])
else
AC_MSG_NOTICE([ sanlock: no])
fi
+AC_MSG_NOTICE([firewalld: $with_firewalld])
if test "$with_avahi" = "yes" ; then
AC_MSG_NOTICE([ avahi: $AVAHI_CFLAGS $AVAHI_LIBS])
else
diff --git a/libvirt.spec.in b/libvirt.spec.in
index 67b955a..ea2fd88 100644
--- a/libvirt.spec.in
+++ b/libvirt.spec.in
@@ -106,6 +106,7 @@
%define with_sanlock 0%{!?_without_sanlock:0}
%define with_systemd 0%{!?_without_systemd:0}
%define with_numad 0%{!?_without_numad:0}
+%define with_firewalld 0%{!?_without_firewalld:0}
# Non-server/HV driver defaults which are always enabled
%define with_python 0%{!?_without_python:1}
@@ -146,6 +147,11 @@
%define with_systemd 1
%endif
+# Fedora 18 / RHEL-7 are first where firewalld support is enabled
+%if 0%{?fedora} >= 17 || 0%{?rhel} >= 7
+%define with_firewalld 1
+%endif
+
# RHEL-5 has restricted QEMU to x86_64 only and is too old for LXC
%if 0%{?rhel} == 5
%define with_qemu_tcg 0
@@ -1182,6 +1188,10 @@ of recent versions of Linux (and other OSes).
%define _without_driver_modules --without-driver-modules
%endif
+%if %{with_firewalld}
+%define _with_firewalld --with-firewalld
+%endif
+
%define when %(date +"%%F-%%T")
%define where %(hostname)
%define who %{?packager}%{!?packager:Unknown}
@@ -1240,6 +1250,7 @@ autoreconf -if
%{?_without_audit} \
%{?_without_dtrace} \
%{?_without_driver_modules} \
+ %{?_with_firewalld} \
%{with_packager} \
%{with_packager_version} \
--with-qemu-user=%{qemu_user} \
diff --git a/src/Makefile.am b/src/Makefile.am
index 79b4e59..76570db 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -989,7 +989,7 @@ libvirt_driver_network_la_SOURCES =
libvirt_driver_network_la_LIBADD = libvirt_driver_network_impl.la
if WITH_DRIVER_MODULES
mod_LTLIBRARIES += libvirt_driver_network.la
-libvirt_driver_network_la_LIBADD += ../gnulib/lib/libgnu.la $(LIBNL_LIBS)
+libvirt_driver_network_la_LIBADD += ../gnulib/lib/libgnu.la $(LIBNL_LIBS) $(DBUS_LIBS)
libvirt_driver_network_la_LDFLAGS = -module -avoid-version $(AM_LDFLAGS)
else
noinst_LTLIBRARIES += libvirt_driver_network.la
@@ -999,7 +999,7 @@ endif
libvirt_driver_network_impl_la_CFLAGS = \
$(LIBNL_CFLAGS) \
- -I$(top_srcdir)/src/conf $(AM_CFLAGS)
+ -I$(top_srcdir)/src/conf $(AM_CFLAGS) $(DBUS_CFLAGS)
libvirt_driver_network_impl_la_SOURCES = $(NETWORK_DRIVER_SOURCES)
endif
EXTRA_DIST += network/default.xml
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index a5046f1..39c0449 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -61,6 +61,7 @@
#include "virnetdev.h"
#include "virnetdevbridge.h"
#include "virnetdevtap.h"
+#include "virdbus.h"
#define NETWORK_PID_DIR LOCALSTATEDIR "/run/libvirt/network"
#define NETWORK_STATE_DIR LOCALSTATEDIR "/lib/libvirt/network"
@@ -248,6 +249,25 @@ networkAutostartConfigs(struct network_driver *driver) {
}
}
+#if HAVE_FIREWALLD
+static DBusHandlerResult
+firewalld_dbus_filter_bridge(DBusConnection *connection ATTRIBUTE_UNUSED,
+ DBusMessage *message, void *user_data) {
+ struct network_driver *_driverState = user_data;
+
+ if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS,
+ "NameOwnerChanged") ||
+ dbus_message_is_signal(message, "org.fedoraproject.FirewallD1",
+ "Reloaded"))
+ {
+ VIR_DEBUG("Reload in bridge_driver because of firewalld.");
+ networkReloadIptablesRules(_driverState);
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+#endif
+
/**
* networkStartup:
*
@@ -256,6 +276,9 @@ networkAutostartConfigs(struct network_driver *driver) {
static int
networkStartup(int privileged) {
char *base = NULL;
+#ifdef HAVE_FIREWALLD
+ DBusConnection *sysbus = NULL;
+#endif
if (VIR_ALLOC(driverState) < 0)
goto error;
@@ -322,6 +345,30 @@ networkStartup(int privileged) {
networkDriverUnlock(driverState);
+#ifdef HAVE_FIREWALLD
+ if (!(sysbus = virDBusGetSystemBus())) {
+ virErrorPtr err = virGetLastError();
+ VIR_WARN("DBus not available, disabling firewalld support in bridge_driver: %s", err->message);
+ } else {
+ /* add matches for
+ * NameOwnerChanged on org.freedesktop.DBus for firewalld start/stop
+ * Reloaded on org.fedoraproject.FirewallD1 for firewalld reload
+ */
+ dbus_bus_add_match(sysbus,
+ "type='signal'"
+ ",interface='"DBUS_INTERFACE_DBUS"'"
+ ",member='NameOwnerChanged'"
+ ",arg0='org.fedoraproject.FirewallD1'",
+ NULL);
+ dbus_bus_add_match(sysbus,
+ "type='signal'"
+ ",interface='org.fedoraproject.FirewallD1'"
+ ",member='Reloaded'",
+ NULL);
+ dbus_connection_add_filter(sysbus, firewalld_dbus_filter_bridge, driverState, NULL);
+ }
+#endif
+
return 0;
out_of_memory:
diff --git a/src/util/ebtables.c b/src/util/ebtables.c
index ca056b1..6f4d151 100644
--- a/src/util/ebtables.c
+++ b/src/util/ebtables.c
@@ -176,11 +176,34 @@ ebtablesAddRemoveRule(ebtRules *rules, int action, const char *arg, ...)
const char *s;
int n, command_idx;
+#if HAVE_FIREWALLD
+ int ret;
+ char *firewall_cmd_path = NULL;
+ virCommandPtr cmd = NULL;
+
+ firewall_cmd_path = virFindFileInPath("firewall-cmd");
+ if (firewall_cmd_path) {
+ cmd = virCommandNew(firewall_cmd_path);
+ virCommandAddArgList(cmd, "--state", NULL);
+ ret = virCommandRun(cmd, NULL);
+ if (ret != 0) {
+ VIR_FREE(firewall_cmd_path);
+ firewall_cmd_path = NULL;
+ }
+ virCommandFree(cmd);
+ }
+#endif
+
n = 1 + /* /sbin/ebtables */
2 + /* --table foo */
2 + /* --insert bar */
1; /* arg */
+#if HAVE_FIREWALLD
+ if (firewall_cmd_path)
+ n += 3; /* --direct --passthrough eb */
+#endif
+
va_start(args, arg);
while (va_arg(args, const char *))
n++;
@@ -192,6 +215,18 @@ ebtablesAddRemoveRule(ebtRules *rules, int action, const char *arg, ...)
n = 0;
+#if HAVE_FIREWALLD
+ if (firewall_cmd_path) {
+ if (!(argv[n++] = strdup(firewall_cmd_path)))
+ goto error;
+ if (!(argv[n++] = strdup("--direct")))
+ goto error;
+ if (!(argv[n++] = strdup("--passthrough")))
+ goto error;
+ if (!(argv[n++] = strdup("eb")))
+ goto error;
+ } else
+#endif
if (!(argv[n++] = strdup(EBTABLES_PATH)))
goto error;
diff --git a/src/util/iptables.c b/src/util/iptables.c
index b23aca9..1378575 100644
--- a/src/util/iptables.c
+++ b/src/util/iptables.c
@@ -101,9 +101,26 @@ iptablesAddRemoveRule(iptRules *rules, int family, int action,
{
va_list args;
int ret;
- virCommandPtr cmd;
+ virCommandPtr cmd = NULL;
const char *s;
-
+#if HAVE_FIREWALLD
+ char *firewall_cmd_path = NULL;
+
+ firewall_cmd_path = virFindFileInPath("firewall-cmd");
+ if (firewall_cmd_path) {
+ cmd = virCommandNew(firewall_cmd_path);
+ virCommandAddArgList(cmd, "--state", NULL);
+ ret = virCommandRun(cmd, NULL);
+ if (ret == 0) {
+ cmd = virCommandNew(firewall_cmd_path);
+ virCommandAddArgList(cmd, "--direct", "--passthrough",
+ (family == AF_INET6) ? "ipv6" : "ipv4", NULL);
+ } else
+ cmd = NULL;
+ VIR_FREE(firewall_cmd_path);
+ }
+ if (!cmd)
+#endif
cmd = virCommandNew((family == AF_INET6)
? IP6TABLES_PATH : IPTABLES_PATH);
--
1.7.11.2
12 years, 3 months
[libvirt] [PATCH 1/4] Fix man page file paths to real paths
by Doug Goldstein
Currently the man page has paths that start with @sysconfdir@,
@localstatedir@ and @remote_pid_file@. The sed command attempts to
replace these during the build but unfortunately pod2man gets to the
files first and escapes the @ character resulting in the sed not
working. This removes the @ character and makes the paths correct.
---
daemon/Makefile.am | 6 +++---
daemon/libvirtd.pod.in | 18 +++++++++---------
2 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 928aeaf..c15c785 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -85,9 +85,9 @@ CLEANFILES += test_libvirtd.aug
libvirtd.8: $(srcdir)/libvirtd.8.in
sed \
- -e 's![@]sysconfdir[@]!$(sysconfdir)!g' \
- -e 's![@]localstatedir[@]!$(localstatedir)!g' \
- -e 's![@]remote_pid_file[@]!$(REMOTE_PID_FILE)!g' \
+ -e 's!SYSCONFDIR!$(sysconfdir)!g' \
+ -e 's!LOCALSTATEDIR!$(localstatedir)!g' \
+ -e 's!REMOTE_PID_FILE!$(REMOTE_PID_FILE)!g' \
< $< > $@-t
mv $@-t $@
diff --git a/daemon/libvirtd.pod.in b/daemon/libvirtd.pod.in
index 57a3b27..7dc8d83 100644
--- a/daemon/libvirtd.pod.in
+++ b/daemon/libvirtd.pod.in
@@ -77,14 +77,14 @@ On receipt of B<SIGHUP> libvirtd will reload its configuration.
=over
-=item F<@sysconfdir(a)/libvirtd.conf>
+=item F<SYSCONFDIR/libvirtd.conf>
The default configuration file used by libvirtd, unless overridden on the
command line using the B<-f>|B<--config> option.
-=item F<@localstatedir@/run/libvirt/libvirt-sock>
+=item F<LOCALSTATEDIR/run/libvirt/libvirt-sock>
-=item F<@localstatedir@/run/libvirt/libvirt-sock-ro>
+=item F<LOCALSTATEDIR/run/libvirt/libvirt-sock-ro>
The sockets libvirtd will use when B<run as root>.
@@ -92,19 +92,19 @@ The sockets libvirtd will use when B<run as root>.
The socket libvirtd will use when run as a B<non-root> user.
-=item F<@sysconfdir(a)/pki/CA/cacert.pem>
+=item F<SYSCONFDIR/pki/CA/cacert.pem>
The TLS B<Certificate Authority> certificate libvirtd will use.
-=item F<@sysconfdir(a)/pki/libvirt/servercert.pem>
+=item F<SYSCONFDIR/pki/libvirt/servercert.pem>
The TLS B<Server> certificate libvirtd will use.
-=item F<@sysconfdir(a)/pki/libvirt/private/serverkey.pem>
+=item F<SYSCONFDIR/pki/libvirt/private/serverkey.pem>
The TLS B<Server> private key libvirtd will use.
-=item F<@remote_pid_file@>
+=item F<REMOTE_PID_FILE>
The PID file to use, unless overridden by the B<-p>|B<--pid-file> option.
@@ -121,8 +121,8 @@ To retrieve the version of libvirtd:
To start libvirtd, instructing it to daemonize and create a PID file:
# libvirtd -d
- # ls -la @remote_pid_file@
- -rw-r--r-- 1 root root 6 Jul 9 02:40 @remote_pid_file@
+ # ls -la REMOTE_PID_FILE
+ -rw-r--r-- 1 root root 6 Jul 9 02:40 REMOTE_PID_FILE
#
=head1 BUGS
--
1.7.8.6
12 years, 3 months