[PATCH] Add vms cli tool to the list of applications using libvirt

2022-11-16 Thread Cédric Bosdonnat
Just adds a tool to the applications list. This tool helps managing
multiple VMs at once using the python binding.

Signed-off-by: Cédric Bosdonnat 
---
 docs/apps.rst | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/docs/apps.rst b/docs/apps.rst
index 1a25c0a21e..57a3d00dca 100644
--- a/docs/apps.rst
+++ b/docs/apps.rst
@@ -70,6 +70,9 @@ virsh
Virt-Lightning uses libvirt, cloud-init and libguestfs to allow
anyone to quickly start a new VM. Very much like a container CLI, but
with a virtual machine.
+`vms <https://github.com/cbosdo/vms>`__
+   vms is a tool wrapping around the libvirt API to manage multiple virtual
+   machines at once with name patterns.
 
 Configuration Management
 
-- 
2.37.1



[PATCHv2] Fix format network dns doc

2021-01-26 Thread Cédric Bosdonnat
The code block on the srv name in the formatnetwork page is confusing
since the actual parameter is service. Moving the code block to the
service work makes it better.
---

Diff to v1:
 * remove the word 'name'

 docs/formatnetwork.html.in | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/formatnetwork.html.in b/docs/formatnetwork.html.in
index f5a48d9b92..b1b2391f43 100644
--- a/docs/formatnetwork.html.in
+++ b/docs/formatnetwork.html.in
@@ -1035,7 +1035,7 @@
   The dns element can have also 0 or more 
srv
 record elements. Each srv record element defines a 
DNS SRV record
 and has 2 mandatory and 5 optional attributes. The mandatory 
attributes
-are service name and protocol (tcp, udp)
+are service and protocol (tcp, udp)
 and the optional attributes are target,
 port, priority, weight and
 domain as defined in DNS server SRV RFC (RFC 2782).
-- 
2.29.2




[PATCH] Fix format network dns doc

2021-01-25 Thread Cédric Bosdonnat
The code block on the srv name in the formatnetwork page is confusing
since the actual parameter is service. Moving the code block to the
service work makes it better.
---
 docs/formatnetwork.html.in | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/formatnetwork.html.in b/docs/formatnetwork.html.in
index f5a48d9b92..06ac63eeb5 100644
--- a/docs/formatnetwork.html.in
+++ b/docs/formatnetwork.html.in
@@ -1035,7 +1035,7 @@
   The dns element can have also 0 or more 
srv
 record elements. Each srv record element defines a 
DNS SRV record
 and has 2 mandatory and 5 optional attributes. The mandatory 
attributes
-are service name and protocol (tcp, udp)
+are service name and protocol (tcp, udp)
 and the optional attributes are target,
 port, priority, weight and
 domain as defined in DNS server SRV RFC (RFC 2782).
-- 
2.29.2




[libvirt] [PATCH 2/3] lxc: factorize code for block stats

2018-03-05 Thread Cédric Bosdonnat
lxcDomainBlockStats and lxcDomainBlockStatsFlags were both using very
similar code. This commit factorizes them into a
lxcDomainBlockStatsInternal.
---
 src/lxc/lxc_driver.c | 131 ---
 1 file changed, 50 insertions(+), 81 deletions(-)

diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index fa6fc4643..a16dbcc96 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -2348,28 +2348,22 @@ lxcDomainMergeBlkioDevice(virBlkioDevicePtr *dest_array,
 return 0;
 }
 
-
-static int
-lxcDomainBlockStats(virDomainPtr dom,
-const char *path,
-virDomainBlockStatsPtr stats)
+static int lxcDomainBlockStatsInternal(virLXCDriverPtr driver,
+   virDomainObjPtr vm,
+   const char *path,
+   long long *rd_bytes,
+   long long *wr_bytes,
+   long long *rd_req,
+   long long *wr_req)
 {
-virLXCDriverPtr driver = dom->conn->privateData;
 int ret = -1;
-virDomainObjPtr vm;
 virDomainDiskDefPtr disk = NULL;
 virLXCDomainObjPrivatePtr priv;
 
-if (!(vm = lxcDomObjFromDomain(dom)))
-return ret;
-
 priv = vm->privateData;
 
-if (virDomainBlockStatsEnsureACL(dom->conn, vm->def) < 0)
-goto cleanup;
-
if (virLXCDomainObjBeginJob(driver, vm, LXC_JOB_QUERY) < 0)
-goto cleanup;
+return -1;
 
 if (!virDomainObjIsActive(vm)) {
 virReportError(VIR_ERR_OPERATION_INVALID,
@@ -2386,10 +2380,10 @@ lxcDomainBlockStats(virDomainPtr dom,
 if (!*path) {
 /* empty path - return entire domain blkstats instead */
 ret = virCgroupGetBlkioIoServiced(priv->cgroup,
-  >rd_bytes,
-  >wr_bytes,
-  >rd_req,
-  >wr_req);
+  rd_bytes,
+  wr_bytes,
+  rd_req,
+  wr_req);
 goto endjob;
 }
 
@@ -2407,13 +2401,36 @@ lxcDomainBlockStats(virDomainPtr dom,
 
 ret = virCgroupGetBlkioIoDeviceServiced(priv->cgroup,
 disk->info.alias,
->rd_bytes,
->wr_bytes,
->rd_req,
->wr_req);
+rd_bytes,
+wr_bytes,
+rd_req,
+wr_req);
 
  endjob:
 virLXCDomainObjEndJob(driver, vm);
+return ret;
+}
+
+static int
+lxcDomainBlockStats(virDomainPtr dom,
+const char *path,
+virDomainBlockStatsPtr stats)
+{
+virLXCDriverPtr driver = dom->conn->privateData;
+virDomainObjPtr vm;
+int ret = -1;
+
+if (!(vm = lxcDomObjFromDomain(dom)))
+return -1;
+
+if (virDomainBlockStatsEnsureACL(dom->conn, vm->def) < 0)
+goto cleanup;
+
+ret = lxcDomainBlockStatsInternal(driver, vm, path,
+  >rd_bytes,
+  >wr_bytes,
+  >rd_req,
+  >wr_req);
 
  cleanup:
 virDomainObjEndAPI();
@@ -2431,8 +2448,6 @@ lxcDomainBlockStatsFlags(virDomainPtr dom,
 virLXCDriverPtr driver = dom->conn->privateData;
 int tmp, ret = -1;
 virDomainObjPtr vm;
-virDomainDiskDefPtr disk = NULL;
-virLXCDomainObjPrivatePtr priv;
 long long rd_req, rd_bytes, wr_req, wr_bytes;
 virTypedParameterPtr param;
 
@@ -2449,60 +2464,17 @@ lxcDomainBlockStatsFlags(virDomainPtr dom,
 if (!(vm = lxcDomObjFromDomain(dom)))
 return ret;
 
-priv = vm->privateData;
-
 if (virDomainBlockStatsFlagsEnsureACL(dom->conn, vm->def) < 0)
 goto cleanup;
 
-if (virLXCDomainObjBeginJob(driver, vm, LXC_JOB_QUERY) < 0)
+if (lxcDomainBlockStatsInternal(driver, vm, path,
+_bytes,
+_bytes,
+_req,
+_req) < 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   "%s", _("domain stats query failed"));
 goto cleanup;
-
-if (!virDomainObjIsActive(vm)) {
-virReportError(VIR_ERR_OPERATION_INVALID,
-   "%s", _("domain is not running"));
-goto endjob;
-}
-
-if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_BLKIO)) {
-

[libvirt] [PATCH 1/3] Extract stats functions from the qemu driver

2018-03-05 Thread Cédric Bosdonnat
Some of the qemu functions getting statistics can easily be reused in
other drivers. Create a conf/domain_stats.[ch] pair to host some of
them.
---
 src/Makefile.am  |   1 +
 src/conf/domain_stats.c  | 139 +
 src/conf/domain_stats.h  |  64 +++
 src/libvirt_private.syms |   4 ++
 src/qemu/qemu_driver.c   | 158 +++
 src/util/vircgroup.c |  46 ++
 src/util/vircgroup.h |   4 ++
 7 files changed, 265 insertions(+), 151 deletions(-)
 create mode 100644 src/conf/domain_stats.c
 create mode 100644 src/conf/domain_stats.h

diff --git a/src/Makefile.am b/src/Makefile.am
index 3bf2da543..3952a6d2c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -441,6 +441,7 @@ DOMAIN_CONF_SOURCES = \
conf/domain_conf.c conf/domain_conf.h \
conf/domain_audit.c conf/domain_audit.h \
conf/domain_nwfilter.c conf/domain_nwfilter.h \
+   conf/domain_stats.c conf/domain_stats.h \
conf/virsavecookie.c conf/virsavecookie.h \
conf/snapshot_conf.c conf/snapshot_conf.h \
conf/numa_conf.c conf/numa_conf.h \
diff --git a/src/conf/domain_stats.c b/src/conf/domain_stats.c
new file mode 100644
index 0..beb3c09d5
--- /dev/null
+++ b/src/conf/domain_stats.c
@@ -0,0 +1,139 @@
+/*
+ * domain_stats.c: domain stats extraction helpers
+ *
+ * Copyright (C) 2006-2016 Red Hat, Inc.
+ * Copyright (C) 2006-2008 Daniel P. Berrange
+ * Copyright (c) 2018 SUSE LINUX Products GmbH, Nuernberg, Germany.
+ *
+ * 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
+ * .
+ *
+ * Author: Daniel P. Berrange 
+ */
+
+#include 
+
+#include 
+
+#include "virlog.h"
+#include "domain_stats.h"
+#include "virtypedparam.h"
+#include "virnetdevtap.h"
+#include "virnetdevopenvswitch.h"
+
+#define VIR_FROM_THIS VIR_FROM_DOMAIN
+
+VIR_LOG_INIT("conf.domain_stats");
+
+int
+virDomainStatsGetState(virDomainObjPtr dom,
+   virDomainStatsRecordPtr record,
+   int *maxparams)
+{
+if (virTypedParamsAddInt(>params,
+ >nparams,
+ maxparams,
+ "state.state",
+ dom->state.state) < 0)
+return -1;
+
+if (virTypedParamsAddInt(>params,
+ >nparams,
+ maxparams,
+ "state.reason",
+ dom->state.reason) < 0)
+return -1;
+
+return 0;
+}
+
+#define STATS_ADD_NET_PARAM(record, maxparams, num, name, value) \
+do { \
+char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \
+snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, \
+ "net.%zu.%s", num, name); \
+if (value >= 0 && virTypedParamsAddULLong(&(record)->params, \
+  &(record)->nparams, \
+  maxparams, \
+  param_name, \
+  value) < 0) \
+return -1; \
+} while (0)
+
+int
+virDomainStatsGetInterface(virDomainObjPtr dom,
+   virDomainStatsRecordPtr record,
+   int *maxparams)
+{
+size_t i;
+struct _virDomainInterfaceStats tmp;
+int ret = -1;
+
+if (!virDomainObjIsActive(dom))
+return 0;
+
+VIR_DOMAIN_STATS_ADD_COUNT_PARAM(record, maxparams, "net", 
dom->def->nnets);
+
+/* Check the path is one of the domain's network interfaces. */
+for (i = 0; i < dom->def->nnets; i++) {
+virDomainNetDefPtr net = dom->def->nets[i];
+virDomainNetType actualType;
+
+if (!net->ifname)
+continue;
+
+memset(, 0, sizeof(tmp));
+
+actualType = virDomainNetGetActualType(net);
+
+VIR_DOMAIN_STATS_ADD_NAME_PARAM(record, maxparams,
+"net", "name", i, net->ifname);
+
+if (actualType == VIR_DOMAIN_NET_TYPE_VHOSTUSER) {
+if (virNetDevOpenvswitchInterfaceStats(net->ifname, ) < 0) {
+virResetLastError();
+continue;
+}
+} else {
+if (virNetDevTapInterfaceStats(net->ifname, ,

[libvirt] [PATCH 3/3] lxc: implement connectGetAllDomainStats

2018-03-05 Thread Cédric Bosdonnat
LXC containers can also provide some statistics. Allow users to fetch
them using the existing API.
---
 src/lxc/lxc_driver.c | 203 +++
 1 file changed, 203 insertions(+)

diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index a16dbcc96..c357df927 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -80,6 +80,7 @@
 #include "viraccessapichecklxc.h"
 #include "virhostdev.h"
 #include "netdev_bandwidth_conf.h"
+#include "domain_stats.h"
 
 #define VIR_FROM_THIS VIR_FROM_LXC
 
@@ -5483,6 +5484,207 @@ lxcDomainHasManagedSaveImage(virDomainPtr dom, unsigned 
int flags)
 return ret;
 }
 
+static int
+lxcDomainGetStatsState(virLXCDriverPtr driver ATTRIBUTE_UNUSED,
+   virDomainObjPtr dom,
+   virDomainStatsRecordPtr record,
+   int *maxparams)
+{
+return virDomainStatsGetState(dom, record, maxparams);
+}
+
+static int
+lxcDomainGetStatsCpu(virLXCDriverPtr driver ATTRIBUTE_UNUSED,
+ virDomainObjPtr dom,
+ virDomainStatsRecordPtr record,
+ int *maxparams)
+{
+virLXCDomainObjPrivatePtr priv = dom->privateData;
+return virCgroupGetStatsCpu(priv->cgroup, record, maxparams);
+}
+
+static int
+lxcDomainGetStatsInterface(virLXCDriverPtr driver ATTRIBUTE_UNUSED,
+   virDomainObjPtr dom,
+   virDomainStatsRecordPtr record,
+   int *maxparams)
+{
+return virDomainStatsGetInterface(dom, record, maxparams);
+}
+
+/* expects a LL, but typed parameter must be ULL */
+#define LXC_ADD_BLOCK_PARAM_LL(record, maxparams, name, value) \
+do { \
+char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \
+snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, \
+ "block.cgroup.%s", name); \
+if (virTypedParamsAddULLong(&(record)->params, \
+&(record)->nparams, \
+maxparams, \
+param_name, \
+value) < 0) \
+goto cleanup; \
+} while (0)
+
+static int
+lxcDomainGetStatsBlock(virLXCDriverPtr driver,
+   virDomainObjPtr dom,
+   virDomainStatsRecordPtr record,
+   int *maxparams)
+{
+long long rd_req, rd_bytes, wr_req, wr_bytes;
+
+int ret = lxcDomainBlockStatsInternal(driver, dom, "",
+  _bytes,
+  _bytes,
+  _req,
+  _req);
+
+LXC_ADD_BLOCK_PARAM_LL(record, maxparams,
+"rd.reqs", rd_req);
+LXC_ADD_BLOCK_PARAM_LL(record, maxparams,
+"rd.bytes", rd_bytes);
+LXC_ADD_BLOCK_PARAM_LL(record, maxparams,
+"wr.reqs", wr_req);
+LXC_ADD_BLOCK_PARAM_LL(record, maxparams,
+"wr.bytes", wr_bytes);
+
+ cleanup:
+return ret;
+}
+
+#undef LXC_ADD_BLOCK_PARAM_ULL
+
+typedef int
+(*lxcDomainGetStatsFunc)(virLXCDriverPtr driver,
+ virDomainObjPtr dom,
+ virDomainStatsRecordPtr record,
+ int *maxparams);
+
+struct lxcDomainGetStatsWorker {
+lxcDomainGetStatsFunc func;
+unsigned int stats;
+};
+
+static struct lxcDomainGetStatsWorker lxcDomainGetStatsWorkers[] = {
+{ lxcDomainGetStatsState, VIR_DOMAIN_STATS_STATE },
+{ lxcDomainGetStatsCpu, VIR_DOMAIN_STATS_CPU_TOTAL },
+{ lxcDomainGetStatsInterface, VIR_DOMAIN_STATS_INTERFACE },
+{ lxcDomainGetStatsBlock, VIR_DOMAIN_STATS_BLOCK },
+{ NULL, 0 }
+};
+
+static int
+lxcDomainGetStats(virConnectPtr conn,
+  virDomainObjPtr dom,
+  unsigned int stats,
+  virDomainStatsRecordPtr *record)
+{
+virLXCDriverPtr driver = conn->privateData;
+int maxparams = 0;
+virDomainStatsRecordPtr tmp;
+size_t i;
+int ret = -1;
+
+if (VIR_ALLOC(tmp) < 0)
+goto cleanup;
+
+for (i = 0; lxcDomainGetStatsWorkers[i].func; i++) {
+if (stats & lxcDomainGetStatsWorkers[i].stats) {
+if (lxcDomainGetStatsWorkers[i].func(driver, dom, tmp, ) 
< 0)
+goto cleanup;
+}
+}
+
+if (!(tmp->dom = virGetDomain(conn, dom->def->name,
+  dom->def->uuid, dom->def->id)))
+goto cleanup;
+
+*record = tmp;
+tmp = NULL;
+ret = 0;
+
+ cleanup:
+if (tmp) {
+virTypedParamsFree(tmp->params, tmp->nparams);
+VIR_FREE(tmp);
+}
+
+return ret;
+}
+
+static int
+lxcConnectGetAllDomainStats(virConnectPtr conn,
+virDomainPtr *doms,
+unsigned int ndoms,
+unsigned int stats,
+

[libvirt] [PATCH] apparmor: fix virt-aa-helper profile

2018-01-03 Thread Cédric Bosdonnat
Fix rule introduced by commit 0f33025a:
  * to handle /var/run not being a symlink to /run
  * to be properly parsed: missing comma at the end.
---
 examples/apparmor/usr.lib.libvirt.virt-aa-helper | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/examples/apparmor/usr.lib.libvirt.virt-aa-helper 
b/examples/apparmor/usr.lib.libvirt.virt-aa-helper
index 9c822b644..105f09e43 100644
--- a/examples/apparmor/usr.lib.libvirt.virt-aa-helper
+++ b/examples/apparmor/usr.lib.libvirt.virt-aa-helper
@@ -51,7 +51,7 @@ profile virt-aa-helper 
/usr/{lib,lib64}/libvirt/virt-aa-helper {
   /var/lib/libvirt/images/** r,
   /{media,mnt,opt,srv}/** r,
   # For virt-sandbox
-  /run/libvirt/**/[sv]d[a-z] r
+  /{,var/}run/libvirt/**/[sv]d[a-z] r,
 
   /**.img r,
   /**.raw r,
-- 
2.15.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH] netserver: close clients before stopping all drivers

2017-12-21 Thread Cédric Bosdonnat
So far clients were closed when disposing the daemon, after the state
driver cleanup. This was leading to libvirtd crashing at shutdown due
to missing driver.

Moving the client close in virNetServerClose() fixes the problem.
---
 src/rpc/virnetserver.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/src/rpc/virnetserver.c b/src/rpc/virnetserver.c
index 2b76daab5..43f889e2a 100644
--- a/src/rpc/virnetserver.c
+++ b/src/rpc/virnetserver.c
@@ -774,10 +774,8 @@ void virNetServerDispose(void *obj)
 virObjectUnref(srv->programs[i]);
 VIR_FREE(srv->programs);
 
-for (i = 0; i < srv->nclients; i++) {
-virNetServerClientClose(srv->clients[i]);
+for (i = 0; i < srv->nclients; i++)
 virObjectUnref(srv->clients[i]);
-}
 VIR_FREE(srv->clients);
 
 VIR_FREE(srv->mdnsGroupName);
@@ -796,6 +794,9 @@ void virNetServerClose(virNetServerPtr srv)
 for (i = 0; i < srv->nservices; i++)
 virNetServerServiceClose(srv->services[i]);
 
+for (i = 0; i < srv->nclients; i++)
+virNetServerClientClose(srv->clients[i]);
+
 virObjectUnlock(srv);
 }
 
-- 
2.15.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH 1/2] Add virStringFilterChars() string utility

2017-12-18 Thread Cédric Bosdonnat
Add a function to filter a string based on a list of valid characters.
---
 src/libvirt_private.syms |  1 +
 src/util/virstring.c | 24 
 src/util/virstring.h |  1 +
 tests/virstringtest.c| 46 ++
 4 files changed, 72 insertions(+)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index d5c3b9abb..31adaf324 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2753,6 +2753,7 @@ virStrcpy;
 virStrdup;
 virStringBufferIsPrintable;
 virStringEncodeBase64;
+virStringFilterChars;
 virStringHasChars;
 virStringHasControlChars;
 virStringIsEmpty;
diff --git a/src/util/virstring.c b/src/util/virstring.c
index b2ebce27f..b808aff2c 100644
--- a/src/util/virstring.c
+++ b/src/util/virstring.c
@@ -1293,6 +1293,30 @@ virStringStripControlChars(char *str)
 str[j] = '\0';
 }
 
+/**
+ * virStringFilterChars:
+ * @str: the string to strip
+ * @valid: the valid characters for the string
+ *
+ * Modify the string in-place to remove the characters that aren't
+ * in the list of valid ones.
+ */
+void
+virStringFilterChars(char *str, const char *valid)
+{
+size_t len, i, j;
+
+if (!str)
+return;
+
+len = strlen(str);
+for (i = 0, j = 0; i < len; i++) {
+if (strchr(valid, str[i]))
+str[j++] = str[i];
+}
+str[j] = '\0';
+}
+
 /**
  * virStringToUpper:
  * @str: string to capitalize
diff --git a/src/util/virstring.h b/src/util/virstring.h
index b19abaf9f..8af054bce 100644
--- a/src/util/virstring.h
+++ b/src/util/virstring.h
@@ -293,6 +293,7 @@ bool virStringHasChars(const char *str,
const char *chars);
 bool virStringHasControlChars(const char *str);
 void virStringStripControlChars(char *str);
+void virStringFilterChars(char *str, const char *valid);
 
 bool virStringIsPrintable(const char *str);
 bool virStringBufferIsPrintable(const uint8_t *buf, size_t buflen);
diff --git a/tests/virstringtest.c b/tests/virstringtest.c
index 320f7a398..e8518ede1 100644
--- a/tests/virstringtest.c
+++ b/tests/virstringtest.c
@@ -767,6 +767,36 @@ static int testStripControlChars(const void *args)
 return ret;
 }
 
+struct testFilterData {
+const char *string;
+const char *valid;
+const char *result;
+};
+
+static int testFilterChars(const void *args)
+{
+const struct testFilterData *data = args;
+int ret = -1;
+char *res = NULL;
+
+if (VIR_STRDUP(res, data->string) < 0)
+goto cleanup;
+
+virStringFilterChars(res, data->valid);
+
+if (STRNEQ_NULLABLE(res, data->result)) {
+fprintf(stderr, "Returned '%s', expected '%s'\n",
+NULLSTR(res), NULLSTR(data->result));
+goto cleanup;
+}
+
+ret = 0;
+
+ cleanup:
+VIR_FREE(res);
+return ret;
+}
+
 static int
 mymain(void)
 {
@@ -1085,6 +1115,22 @@ mymain(void)
 TEST_STRIP_CONTROL_CHARS("\x01H\x02" "E\x03L\x04L\x05O", "HELLO");
 TEST_STRIP_CONTROL_CHARS("\x01\x02\x03\x04HELL\x05O", "HELLO");
 TEST_STRIP_CONTROL_CHARS("\nhello \x01\x07hello\t", "\nhello hello\t");
+
+#define TEST_FILTER_CHARS(str, filter, res) \
+do { \
+struct testFilterData filterData = { \
+.string = str,  \
+.valid = filter, \
+.result = res,  \
+}; \
+if (virTestRun("Filter chars from " #str, \
+   testFilterChars, ) < 0) \
+ret = -1; \
+} while (0)
+
+TEST_FILTER_CHARS(NULL, NULL, NULL);
+TEST_FILTER_CHARS("hello 123 hello", "helo", "hellohello");
+
 return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
 }
 
-- 
2.15.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH 2/2] lxc: set a hostname based on the container name

2017-12-18 Thread Cédric Bosdonnat
Set a transient hostname on containers. The hostname is computed from
the container name, only keeping the valid characters [a-zA-Z0-9-] in it.
This filtering is based on RFC 1123 and allows a digit to start the
hostname.
---
 src/lxc/lxc_container.c | 35 +++
 1 file changed, 35 insertions(+)

diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index b7216d6ee..96fceaf1b 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -2159,6 +2159,37 @@ static int lxcContainerSetUserGroup(virCommandPtr cmd,
 return 0;
 }
 
+static const char hostname_validchars[] =
+"abcdefghijklmnopqrstuvwxyz"
+"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+"0123456789-";
+
+static int lxcContainerSetHostname(virDomainDefPtr def)
+{
+int ret = -1;
+char *name = NULL;
+char *hostname = NULL;
+
+/* Filter the VM name to get a valid hostname */
+if (VIR_STRDUP(name, def->name) < 0)
+goto cleanup;
+
+/* RFC 1123 allows 0-9 digits as a first character in hostname */
+virStringFilterChars(name, hostname_validchars);
+hostname = name;
+if (strlen(name) > 0 && name[0] == '-')
+hostname = name + 1;
+
+if (sethostname(hostname, strlen(hostname)) < 0) {
+virReportSystemError(errno, "%s", _("Failed to set hostname"));
+goto cleanup;
+}
+ret = 0;
+
+ cleanup:
+VIR_FREE(name);
+return ret;
+}
 
 /**
  * lxcContainerChild:
@@ -2269,6 +2300,10 @@ static int lxcContainerChild(void *data)
 goto cleanup;
 }
 
+if (lxcContainerSetHostname(vmDef) < 0)
+goto cleanup;
+
+
 /* drop a set of root capabilities */
 if (lxcContainerDropCapabilities(vmDef, !!hasReboot) < 0)
 goto cleanup;
-- 
2.15.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH 0/2] Set hostname in lxc containers

2017-12-18 Thread Cédric Bosdonnat
Hey there,

Here are two commits to set a transient hostname on lxc containers based
on the guest name.

Cédric Bosdonnat (2):
  Add virStringFilterChars() string utility
  lxc: set a hostname based on the container name

 src/libvirt_private.syms |  1 +
 src/lxc/lxc_container.c  | 35 +++
 src/util/virstring.c | 24 
 src/util/virstring.h |  1 +
 tests/virstringtest.c| 46 ++
 5 files changed, 107 insertions(+)

-- 
2.15.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH] virt-aa-helper: handle more disk images

2017-12-11 Thread Cédric Bosdonnat
virt-aa-helper needs read access to the disk image to resolve symlinks
and add the proper rules to the profile. Its profile whitelists a few
common paths, but users can place their images anywhere.

This commit helps users allowing access to their images by adding their
own rules in apparmor.d/local/usr.lib.libvirt.virt-aa-helper.

This commit also adds rules to allow reading files named:
  - *.raw as this is a rather common disk image extension
  - /run/libvirt/**[vd]d[a-z] as these are used by virt-sandbox
---
 examples/Makefile.am | 24 ++--
 examples/apparmor/usr.lib.libvirt.virt-aa-helper |  4 
 2 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/examples/Makefile.am b/examples/Makefile.am
index ef2f79db3..8a1d6919a 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -67,6 +67,9 @@ admin_client_info_SOURCES = admin/client_info.c
 admin_client_close_SOURCES = admin/client_close.c
 admin_logging_SOURCES = admin/logging.c
 
+INSTALL_DATA_LOCAL =
+UNINSTALL_LOCAL =
+
 if WITH_APPARMOR_PROFILES
 apparmordir = $(sysconfdir)/apparmor.d/
 apparmor_DATA = \
@@ -85,20 +88,37 @@ templates_DATA = \
apparmor/TEMPLATE.qemu \
apparmor/TEMPLATE.lxc \
$(NULL)
+
+APPARMOR_LOCAL_DIR = "$(DESTDIR)$(apparmordir)/local"
+install-apparmor-local:
+   $(MKDIR_P) "$(APPARMOR_LOCAL_DIR)"
+   echo "# Site-specific additions and overrides for \
+'usr.lib.libvirt.virt-aa-helper'" \
+>$(APPARMOR_LOCAL_DIR)/usr.lib.libvirt.virt-aa-helper
+
+INSTALL_DATA_LOCAL += install-apparmor-local
+UNINSTALL_LOCAL += uninstall-apparmor-local
 endif WITH_APPARMOR_PROFILES
 
 if WITH_NWFILTER
 NWFILTER_DIR = "$(DESTDIR)$(sysconfdir)/libvirt/nwfilter"
 
-install-data-local:
+install-nwfilter-local:
$(MKDIR_P) "$(NWFILTER_DIR)"
for f in $(FILTERS); do \
$(INSTALL_DATA) $$f "$(NWFILTER_DIR)"; \
done
 
-uninstall-local::
+uninstall-nwfilter-local::
for f in $(FILTERS); do \
rm -f "$(NWFILTER_DIR)/`basename $$f`"; \
done
-test -z "$(shell ls $(NWFILTER_DIR))" || rmdir $(NWFILTER_DIR)
+
+INSTALL_DATA_LOCAL += install-nwfilter-local
+UNINSTALL_LOCAL += uninstall-nwfilter-local
 endif WITH_NWFILTER
+
+install-data-local: $(INSTALL_DATA_LOCAL)
+
+uninstall-local: $(UNINSTALL_LOCAL)
diff --git a/examples/apparmor/usr.lib.libvirt.virt-aa-helper 
b/examples/apparmor/usr.lib.libvirt.virt-aa-helper
index bd6181d00..f3069d369 100644
--- a/examples/apparmor/usr.lib.libvirt.virt-aa-helper
+++ b/examples/apparmor/usr.lib.libvirt.virt-aa-helper
@@ -3,6 +3,7 @@
 
 profile virt-aa-helper /usr/{lib,lib64}/libvirt/virt-aa-helper {
   #include 
+  #include 
 
   # needed for searching directories
   capability dac_override,
@@ -50,8 +51,11 @@ profile virt-aa-helper 
/usr/{lib,lib64}/libvirt/virt-aa-helper {
   /var/lib/libvirt/images/ r,
   /var/lib/libvirt/images/** r,
   /{media,mnt,opt,srv}/** r,
+  # For virt-sandbox
+  /run/libvirt/**/[sv]d[a-z] r
 
   /**.img r,
+  /**.raw r,
   /**.qcow{,2} r,
   /**.qed r,
   /**.vmdk r,
-- 
2.15.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [sandbox 3/6] Add tests .log and .trs files to gitignore

2017-12-05 Thread Cédric Bosdonnat
---
 .gitignore | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/.gitignore b/.gitignore
index 83831bb..c4e2217 100644
--- a/.gitignore
+++ b/.gitignore
@@ -58,3 +58,5 @@ bin/virt-sandbox
 bin/virt-sandbox-service-util
 build/
 bin/*.1
+*.log
+*.trs
-- 
2.15.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [sandbox 6/6] Don't hardcode interpreter path

2017-12-05 Thread Cédric Bosdonnat
This is particularly useful on operating systems that don't ship
Python as part of the base system (eg. FreeBSD) while still working
just as well as it did before on Linux.
---
 bin/virt-sandbox-image   | 2 +-
 bin/virt-sandbox-service | 2 +-
 examples/demo.py | 2 +-
 examples/shell.py| 2 +-
 examples/virt-sandbox-mkinitrd.py| 2 +-
 examples/virt-sandbox.py | 2 +-
 libvirt-sandbox/image/cli.py | 2 +-
 libvirt-sandbox/image/sources/base.py| 1 -
 libvirt-sandbox/image/sources/docker.py  | 1 -
 libvirt-sandbox/image/sources/virtbuilder.py | 1 -
 10 files changed, 7 insertions(+), 10 deletions(-)

diff --git a/bin/virt-sandbox-image b/bin/virt-sandbox-image
index 7e0d76b..61346ef 100755
--- a/bin/virt-sandbox-image
+++ b/bin/virt-sandbox-image
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 # -*- coding: utf-8 -*-
 
 from libvirt_sandbox.image import cli
diff --git a/bin/virt-sandbox-service b/bin/virt-sandbox-service
index e78defb..b06f304 100755
--- a/bin/virt-sandbox-service
+++ b/bin/virt-sandbox-service
@@ -1,4 +1,4 @@
-#!/usr/bin/python -Es
+#!/usr/bin/env python3
 #
 # Authors: Dan Walsh 
 #
diff --git a/examples/demo.py b/examples/demo.py
index 6252194..c61b091 100755
--- a/examples/demo.py
+++ b/examples/demo.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 
 from gi.repository import LibvirtGObject
 from gi.repository import LibvirtSandbox
diff --git a/examples/shell.py b/examples/shell.py
index 317d13e..86b2159 100755
--- a/examples/shell.py
+++ b/examples/shell.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 
 from gi.repository import LibvirtGObject
 from gi.repository import LibvirtSandbox
diff --git a/examples/virt-sandbox-mkinitrd.py 
b/examples/virt-sandbox-mkinitrd.py
index 76df925..74d1b00 100755
--- a/examples/virt-sandbox-mkinitrd.py
+++ b/examples/virt-sandbox-mkinitrd.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 
 from gi.repository import LibvirtGObject
 from gi.repository import LibvirtSandbox
diff --git a/examples/virt-sandbox.py b/examples/virt-sandbox.py
index 922ad00..e4ed6e7 100755
--- a/examples/virt-sandbox.py
+++ b/examples/virt-sandbox.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 
 from gi.repository import LibvirtGObject
 from gi.repository import LibvirtSandbox
diff --git a/libvirt-sandbox/image/cli.py b/libvirt-sandbox/image/cli.py
index fa3cace..490c5e0 100644
--- a/libvirt-sandbox/image/cli.py
+++ b/libvirt-sandbox/image/cli.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python -Es
+#!/usr/bin/env python3
 # -*- coding: utf-8 -*-
 # Authors: Daniel P. Berrange 
 #  Eren Yagdiran 
diff --git a/libvirt-sandbox/image/sources/base.py 
b/libvirt-sandbox/image/sources/base.py
index e4e4e41..0fc9243 100644
--- a/libvirt-sandbox/image/sources/base.py
+++ b/libvirt-sandbox/image/sources/base.py
@@ -1,4 +1,3 @@
-#!/usr/bin/python
 # -*- coding: utf-8 -*-
 #
 # Copyright (C) 2015 Universitat Politècnica de Catalunya.
diff --git a/libvirt-sandbox/image/sources/docker.py 
b/libvirt-sandbox/image/sources/docker.py
index e979054..eaf41fc 100755
--- a/libvirt-sandbox/image/sources/docker.py
+++ b/libvirt-sandbox/image/sources/docker.py
@@ -1,4 +1,3 @@
-#!/usr/bin/python
 # -*- coding: utf-8 -*-
 #
 # Copyright (C) 2015 Universitat Politècnica de Catalunya.
diff --git a/libvirt-sandbox/image/sources/virtbuilder.py 
b/libvirt-sandbox/image/sources/virtbuilder.py
index 6bd9695..1b32083 100755
--- a/libvirt-sandbox/image/sources/virtbuilder.py
+++ b/libvirt-sandbox/image/sources/virtbuilder.py
@@ -1,4 +1,3 @@
-#!/usr/bin/python
 #
 # Copyright (C) 2015 SUSE LLC
 #
-- 
2.15.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [sandbox 1/6] Pass debug and verbose values to init

2017-12-05 Thread Cédric Bosdonnat
libvirt-sandbox-init-common is expecting -d and -v parameters to
set it in debug or verbose mode... but those will never be passed
by the launcher program.

Writing the core.debug and core.verbose parameters in the sandbox
configuration makes those values actually usable from the init.
---
 bin/virt-sandbox.c|  3 ++
 libvirt-sandbox/libvirt-sandbox-config.c  | 75 +++
 libvirt-sandbox/libvirt-sandbox-config.h  |  6 +++
 libvirt-sandbox/libvirt-sandbox-init-common.c |  3 ++
 libvirt-sandbox/libvirt-sandbox.sym   |  4 ++
 5 files changed, 91 insertions(+)

diff --git a/bin/virt-sandbox.c b/bin/virt-sandbox.c
index 3058013..6032562 100644
--- a/bin/virt-sandbox.c
+++ b/bin/virt-sandbox.c
@@ -273,6 +273,9 @@ int main(int argc, char **argv) {
 if (shell)
 gvir_sandbox_config_set_shell(cfg, TRUE);
 
+gvir_sandbox_config_set_debug(cfg, debug);
+gvir_sandbox_config_set_verbose(cfg, verbose);
+
 if (isatty(STDIN_FILENO))
 gvir_sandbox_config_interactive_set_tty(icfg, TRUE);
 
diff --git a/libvirt-sandbox/libvirt-sandbox-config.c 
b/libvirt-sandbox/libvirt-sandbox-config.c
index 8709736..73a0fa4 100644
--- a/libvirt-sandbox/libvirt-sandbox-config.c
+++ b/libvirt-sandbox/libvirt-sandbox-config.c
@@ -68,6 +68,9 @@ struct _GVirSandboxConfigPrivate
 
 gchar *secLabel;
 gboolean secDynamic;
+
+gboolean debug;
+gboolean verbose;
 };
 
 G_DEFINE_ABSTRACT_TYPE(GVirSandboxConfig, gvir_sandbox_config, G_TYPE_OBJECT);
@@ -1926,6 +1929,59 @@ gboolean 
gvir_sandbox_config_set_security_opts(GVirSandboxConfig *config,
 return ret;
 }
 
+/**
+ * gvir_sandbox_config_set_debug:
+ * @config: (transfer none): the sandbox config
+ * @debug: true if the container init should print debugging messages
+ *
+ * Set whether the container init should print debugging messages.
+ */
+void gvir_sandbox_config_set_debug(GVirSandboxConfig *config, gboolean debug)
+{
+GVirSandboxConfigPrivate *priv = config->priv;
+priv->debug = debug;
+}
+
+/**
+ * gvir_sandbox_config_get_debug:
+ * @config: (transfer none): the sandbox config
+ *
+ * Retrieves the sandbox debug flag
+ *
+ * Returns: the debug flag
+ */
+gboolean gvir_sandbox_config_get_debug(GVirSandboxConfig *config)
+{
+GVirSandboxConfigPrivate *priv = config->priv;
+return priv->debug;
+}
+
+/**
+ * gvir_sandbox_config_set_verbose:
+ * @config: (transfer none): the sandbox config
+ * @verbose: true if the container init should be verbose
+ *
+ * Set whether the container init should be verbose.
+ */
+void gvir_sandbox_config_set_verbose(GVirSandboxConfig *config, gboolean 
verbose)
+{
+GVirSandboxConfigPrivate *priv = config->priv;
+priv->verbose = verbose;
+}
+
+/**
+ * gvir_sandbox_config_get_verbose:
+ * @config: (transfer none): the sandbox config
+ *
+ * Retrieves the sandbox verbose flag
+ *
+ * Returns: the verbose flag
+ */
+gboolean gvir_sandbox_config_get_verbose(GVirSandboxConfig *config)
+{
+GVirSandboxConfigPrivate *priv = config->priv;
+return priv->verbose;
+}
 
 static GVirSandboxConfigMount *gvir_sandbox_config_load_config_mount(GKeyFile 
*file,
  guint i,
@@ -2415,6 +2471,22 @@ static gboolean 
gvir_sandbox_config_load_config(GVirSandboxConfig *config,
 priv->secDynamic = b;
 }
 
+b = g_key_file_get_boolean(file, "core", "debug", );
+if (e) {
+g_error_free(e);
+e = NULL;
+} else {
+priv->debug = b;
+}
+
+b = g_key_file_get_boolean(file, "core", "verbose", );
+if (e) {
+g_error_free(e);
+e = NULL;
+} else {
+priv->verbose = b;
+}
+
 ret = TRUE;
  cleanup:
 return ret;
@@ -2677,6 +2749,9 @@ static void 
gvir_sandbox_config_save_config(GVirSandboxConfig *config,
 if (priv->secLabel)
 g_key_file_set_string(file, "security", "label", priv->secLabel);
 g_key_file_set_boolean(file, "security", "dynamic", priv->secDynamic);
+
+g_key_file_set_boolean(file, "core", "debug", priv->debug);
+g_key_file_set_boolean(file, "core", "verbose", priv->verbose);
 }
 
 
diff --git a/libvirt-sandbox/libvirt-sandbox-config.h 
b/libvirt-sandbox/libvirt-sandbox-config.h
index e5e53f7..8950e25 100644
--- a/libvirt-sandbox/libvirt-sandbox-config.h
+++ b/libvirt-sandbox/libvirt-sandbox-config.h
@@ -180,6 +180,12 @@ gboolean 
gvir_sandbox_config_set_security_opts(GVirSandboxConfig *config,
const gchar *optstr,
GError**error);
 
+void gvir_sandbox_config_set_debug(GVirSandboxConfig *config, gboolean debug);
+gboolean gvir_sandbox_config_get_debug(GVirSandboxConfig *config);
+
+void gvir_sandbox_config_set_verbose(GVirSandboxConfig *config, gboolean 
verbose);
+gboolean gvir_sandbox_config_get_verbose(GVirSandboxConfig *config);
+
 gchar 

[libvirt] [sandbox 5/6] Convert to python3

2017-12-05 Thread Cédric Bosdonnat
Python2 is going to die soon, convert to python3.
---
 bin/virt-sandbox-service| 68 ++---
 libvirt-sandbox/image/cli.py| 18 -
 libvirt-sandbox/image/sources/docker.py | 41 ++--
 libvirt-sandbox/image/template.py   |  8 ++--
 4 files changed, 71 insertions(+), 64 deletions(-)

diff --git a/bin/virt-sandbox-service b/bin/virt-sandbox-service
index c34c6f3..e78defb 100755
--- a/bin/virt-sandbox-service
+++ b/bin/virt-sandbox-service
@@ -30,7 +30,6 @@ from gi.repository import GLib
 import gi
 import re
 import os, sys, shutil, errno, stat
-import exceptions
 import rpm
 from subprocess import Popen, PIPE, STDOUT
 import gettext
@@ -49,7 +48,6 @@ gettext.textdomain("libvirt-sandbox")
 try:
 gettext.install("libvirt-sandbox",
 localedir="/usr/share/locale",
-unicode=False,
 codeset = 'utf-8')
 except IOError:
 import __builtin__
@@ -235,7 +233,7 @@ class Container:
 path = "%s%s" % (self.dest, f)
 os.chown(path, s.st_uid, s.st_gid)
 os.chmod(path, s.st_mode)
-except OSError, e:
+except OSError as e:
 if not e.errno == errno.ENOENT:
 raise
 
@@ -253,7 +251,7 @@ class Container:
 try:
 path = "%s%s" % (self.dest, d)
 os.makedirs(path)
-except OSError, e:
+except OSError as e:
 if not e.errno == errno.EEXIST:
 raise
 
@@ -263,7 +261,7 @@ class Container:
 path = "%s%s" % (self.dest, f)
 fd=open(path, "w")
 fd.close()
-except OSError, e:
+except OSError as e:
 if not e.errno == errno.EEXIST:
 raise
 
@@ -404,10 +402,10 @@ class GenericContainer(Container):
 def create(self):
 try:
 self.create_generic()
-except Exception, e:
+except Exception as e:
 try:
 self.delete()
-except Exception, e2:
+except Exception as e2:
 pass
 raise e
 
@@ -418,6 +416,18 @@ class GenericContainer(Container):
 def is_template_unit(unit):
 return '@' in unit
 
+# Python 2 / 3 compability helpers
+def get_next(obj):
+if hasattr(obj, 'next'):
+return obj.next()
+else:
+return next(obj)
+
+def string(obj):
+if isinstance(obj, bytes):
+return str(obj, encoding='utf-8')
+return obj
+
 class SystemdContainer(Container):
 IGNORE_DIRS= [ "/var/run/", "/etc/logrotate.d/", "/etc/pam.d" ]
 DEFAULT_DIRS   = [ "/etc", "/var" ]
@@ -581,8 +591,8 @@ WantedBy=multi-user.target
 def get_rpm_for_unit(self, unitfile):
 mi = self.ts.dbMatch(rpm.RPMTAG_BASENAMES, unitfile)
 try:
-h = mi.next();
-except exceptions.StopIteration:
+h = get_next(mi);
+except StopIteration:
 return None
 return h['name']
 
@@ -590,8 +600,8 @@ WantedBy=multi-user.target
 def extract_rpm(self, rpm_name):
 mi = self.ts.dbMatch('name', rpm_name)
 try:
-h = mi.next();
-except exceptions.StopIteration:
+h = get_next(mi);
+except StopIteration:
 raise ValueError([_("Cannot find package named %s") % rpm_name])
 
 for fentry in h.fiFromHeader():
@@ -602,16 +612,16 @@ WantedBy=multi-user.target
 if os.path.isfile(fname):
 self.add_file(fname)
 
-srcrpm = h[rpm.RPMTAG_SOURCERPM]
+srcrpm = string(h[rpm.RPMTAG_SOURCERPM])
 srcrpmbits = self.split_filename(srcrpm)
 
-if srcrpmbits[0] == h[rpm.RPMTAG_NAME]:
+if srcrpmbits[0] == string(h[rpm.RPMTAG_NAME]):
 return
 
 mi = self.ts.dbMatch(rpm.RPMTAG_NAME, srcrpmbits[0])
 try:
-h = mi.next();
-except exceptions.StopIteration:
+h = get_next(mi);
+except StopIteration:
 raise ValueError([_("Cannot find base package %s") % 
srcrpmbits[0]])
 
 for fentry in h.fiFromHeader():
@@ -771,7 +781,7 @@ PrivateNetwork=false
 fd.write("[Unit]\n")
 fd.write("Description=Sandbox multi-user target\n")
 fd.close()
-except OSError, e:
+except OSError as e:
 if not e.errno == errno.EEXIST:
 raise
 
@@ -789,7 +799,7 @@ PrivateNetwork=false
 jpath = "/var/log/journal/" + uuid
 if os.path.lexists(jpath):
 os.remove(jpath)
-except Exception, e:
+except Exception as e:
 sys.stderr.write("%s: %s\n" % (sys.argv[0], e))
 sys.stderr.flush()
 
@@ -825,10 +835,10 @@ PrivateNetwork=false
 
 try:
 self.create_systemd()
-except Exception, e:
+except Exception as e:
 try:
 

[libvirt] [sandbox 0/6] Misc patches

2017-12-05 Thread Cédric Bosdonnat
Hi all,

Here are a few patches I found sitting on my local copy. I also added a
few patches to convert to python3.

Cédric Bosdonnat (6):
  Pass debug and verbose values to init
  machine: use squash security mode  for non-root virt-sandbox mounts
  Add tests .log and .trs files to gitignore
  service: fix bad ConfigMountHostImage constructor call
  Convert to python3
  Don't hardcode interpreter path

 .gitignore|  2 +
 bin/virt-sandbox-image|  2 +-
 bin/virt-sandbox-service  | 75 +--
 bin/virt-sandbox.c|  3 +
 examples/demo.py  |  2 +-
 examples/shell.py |  2 +-
 examples/virt-sandbox-mkinitrd.py |  2 +-
 examples/virt-sandbox.py  |  2 +-
 libvirt-sandbox/image/cli.py  | 20 +++---
 libvirt-sandbox/image/sources/base.py |  1 -
 libvirt-sandbox/image/sources/docker.py   | 42 ++---
 libvirt-sandbox/image/sources/virtbuilder.py  |  1 -
 libvirt-sandbox/image/template.py |  8 +--
 libvirt-sandbox/libvirt-sandbox-builder-machine.c |  5 +-
 libvirt-sandbox/libvirt-sandbox-config.c  | 75 +++
 libvirt-sandbox/libvirt-sandbox-config.h  |  6 ++
 libvirt-sandbox/libvirt-sandbox-init-common.c |  3 +
 libvirt-sandbox/libvirt-sandbox.sym   |  4 ++
 18 files changed, 179 insertions(+), 76 deletions(-)

-- 
2.15.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [sandbox 2/6] machine: use squash security mode for non-root virt-sandbox mounts

2017-12-05 Thread Cédric Bosdonnat
When running virt-sandbox as a user with host-bind mount, the user
can't write in the mounted folder. If run as root, use passthrough
security mode, otherwise use squashed one to fix this.
---
 libvirt-sandbox/libvirt-sandbox-builder-machine.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/libvirt-sandbox/libvirt-sandbox-builder-machine.c 
b/libvirt-sandbox/libvirt-sandbox-builder-machine.c
index 7204f71..b6f2218 100644
--- a/libvirt-sandbox/libvirt-sandbox-builder-machine.c
+++ b/libvirt-sandbox/libvirt-sandbox-builder-machine.c
@@ -589,7 +589,10 @@ static gboolean 
gvir_sandbox_builder_machine_construct_devices(GVirSandboxBuilde
 
 fs = gvir_config_domain_filesys_new();
 gvir_config_domain_filesys_set_type(fs, 
GVIR_CONFIG_DOMAIN_FILESYS_MOUNT);
-gvir_config_domain_filesys_set_access_type(fs, 
GVIR_CONFIG_DOMAIN_FILESYS_ACCESS_PASSTHROUGH);
+if (getuid() == 0)
+gvir_config_domain_filesys_set_access_type(fs, 
GVIR_CONFIG_DOMAIN_FILESYS_ACCESS_PASSTHROUGH);
+else
+gvir_config_domain_filesys_set_access_type(fs, 
GVIR_CONFIG_DOMAIN_FILESYS_ACCESS_SQUASH);
 gvir_config_domain_filesys_set_source(fs,
   
gvir_sandbox_config_mount_file_get_source(mfile));
 gvir_config_domain_filesys_set_target(fs, target);
-- 
2.15.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [sandbox 4/6] service: fix bad ConfigMountHostImage constructor call

2017-12-05 Thread Cédric Bosdonnat
Since commit 68406aff8 ConfigMountHostImage needs a format parameter,
virt-sandbox-service needs to fit the new API.
---
 bin/virt-sandbox-service | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/bin/virt-sandbox-service b/bin/virt-sandbox-service
index 45f4517..c34c6f3 100755
--- a/bin/virt-sandbox-service
+++ b/bin/virt-sandbox-service
@@ -20,6 +20,8 @@
 #
 
 import gi
+gi.require_version('LibvirtGConfig', '1.0')
+from gi.repository import LibvirtGConfig
 gi.require_version('LibvirtGObject', '1.0')
 from gi.repository import LibvirtGObject
 gi.require_version('LibvirtSandbox', '1.0')
@@ -223,7 +225,8 @@ class Container:
 def gen_filesystems(self):
 if self.use_image:
 self.image = self.DEFAULT_IMAGE % self.get_name()
-mount = LibvirtSandbox.ConfigMountHostImage.new(self.image, 
self.dest)
+mount = LibvirtSandbox.ConfigMountHostImage.new(self.image, 
self.dest,
+
LibvirtGConfig.DomainDiskFormat.RAW)
 self.config.add_mount(mount)
 
 def fix_stat(self, f):
-- 
2.15.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [libvirt-python][PATCH] Don't hardcode interpreter path

2017-11-29 Thread Cédric Bosdonnat
This is particularly useful on operating systems that don't ship
Python as part of the base system (eg. FreeBSD) while still working
just as well as it did before on Linux.
---
 examples/event-test.py | 2 +-
 generator.py   | 2 +-
 sanitytest.py  | 2 +-
 setup.py   | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/examples/event-test.py b/examples/event-test.py
index 4eb7142..2587226 100755
--- a/examples/event-test.py
+++ b/examples/event-test.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python -u
+#!/usr/bin/env python
 #
 #
 #
diff --git a/generator.py b/generator.py
index 59e7531..74150b7 100755
--- a/generator.py
+++ b/generator.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python -u
+#!/usr/bin/env python
 #
 # generate python wrappers from the XML API description
 #
diff --git a/sanitytest.py b/sanitytest.py
index a5cb01b..1d65e8d 100644
--- a/sanitytest.py
+++ b/sanitytest.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
 
 import sys
 import lxml
diff --git a/setup.py b/setup.py
index 3cdfcbf..05a981e 100755
--- a/setup.py
+++ b/setup.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
 
 from distutils.core import setup, Extension, Command
 from distutils.command.build import build
-- 
2.15.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH] apparmor: add network netlink raw rule

2017-11-09 Thread Cédric Bosdonnat
The rule 'network netlink raw' fixes these denials on libvirtd start:

apparmor="DENIED" operation="create" profile="/usr/sbin/libvirtd" pid=12969
comm="libvirtd" family="netlink" sock_type="raw" protocol=0
requested_mask="create" denied_mask="create"
---
 examples/apparmor/usr.sbin.libvirtd | 1 +
 1 file changed, 1 insertion(+)

diff --git a/examples/apparmor/usr.sbin.libvirtd 
b/examples/apparmor/usr.sbin.libvirtd
index 819068ffc..8ac5233cc 100644
--- a/examples/apparmor/usr.sbin.libvirtd
+++ b/examples/apparmor/usr.sbin.libvirtd
@@ -36,6 +36,7 @@
   network inet6 dgram,
   network packet dgram,
   network packet raw,
+  network netlink raw,
 
   ptrace (trace) peer=unconfined,
   ptrace (trace) peer=/usr/sbin/libvirtd,
-- 
2.14.3

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v3 3/4] lxc: allow user to specify command working directory

2017-06-26 Thread Cédric Bosdonnat
Some containers may want the application to run in a special directory.
Add  element in the domain configuration to handle this case
and use it in the lxc driver.
---
 docs/formatdomain.html.in|  5 +
 docs/schemas/domaincommon.rng|  5 +
 src/conf/domain_conf.c   |  5 +
 src/conf/domain_conf.h   |  1 +
 src/lxc/lxc_container.c  |  2 ++
 tests/lxcxml2xmldata/lxc-initdir.xml | 30 ++
 tests/lxcxml2xmltest.c   |  1 +
 7 files changed, 49 insertions(+)
 create mode 100644 tests/lxcxml2xmldata/lxc-initdir.xml

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index d2db5a4f9..e79a9d5be 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -330,6 +330,10 @@
   To set environment variables, use the initenv element, one
   for each variable.
 
+
+  To set a custom work directory for the init, use the initdir
+  element.
+
 
 
 os
@@ -338,6 +342,7 @@
   initarg--unit/initarg
   initargemergency.service/initarg
   initenv name='MYENV'some value/initenv
+  initdir/my/custom/cwd/initdir
 /os
 
 
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 1e9fccc9e..06fe62305 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -395,6 +395,11 @@
 
   
 
+
+  
+
+  
+
   
 
   
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 868aa522e..7835852f1 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -2870,6 +2870,7 @@ void virDomainDefFree(virDomainDefPtr def)
 VIR_FREE(def->os.initargv);
 for (i = 0; def->os.initenv && def->os.initenv[i]; i++)
 VIR_FREE(def->os.initenv[i]);
+VIR_FREE(def->os.initdir);
 VIR_FREE(def->os.initenv);
 VIR_FREE(def->os.kernel);
 VIR_FREE(def->os.initrd);
@@ -17021,6 +17022,7 @@ virDomainDefParseBootOptions(virDomainDefPtr def,
 if (def->os.type == VIR_DOMAIN_OSTYPE_EXE) {
 def->os.init = virXPathString("string(./os/init[1])", ctxt);
 def->os.cmdline = virXPathString("string(./os/cmdline[1])", ctxt);
+def->os.initdir = virXPathString("string(./os/initdir[1])", ctxt);
 
 if ((n = virXPathNodeSet("./os/initarg", ctxt, )) < 0)
 goto error;
@@ -24902,6 +24904,9 @@ virDomainDefFormatInternal(virDomainDefPtr def,
 for (i = 0; def->os.initenv && def->os.initenv[i]; i++)
 virBufferAsprintf(buf, "%s\n",
   def->os.initenv[i]->name, def->os.initenv[i]->value);
+if (def->os.initdir)
+virBufferEscapeString(buf, "%s\n",
+  def->os.initdir);
 if (def->os.loader)
 virDomainLoaderDefFormat(buf, def->os.loader);
 virBufferEscapeString(buf, "%s\n",
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 5e47e2e97..4d41de2a4 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1852,6 +1852,7 @@ struct _virDomainOSDef {
 char *init;
 char **initargv;
 virDomainOSEnvPtr *initenv;
+char *initdir;
 char *kernel;
 char *initrd;
 char *cmdline;
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index ffafc39d7..8d8e1a735 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -245,6 +245,8 @@ static virCommandPtr 
lxcContainerBuildInitCmd(virDomainDefPtr vmDef,
 virCommandAddEnvPair(cmd, "LIBVIRT_LXC_NAME", vmDef->name);
 if (vmDef->os.cmdline)
 virCommandAddEnvPair(cmd, "LIBVIRT_LXC_CMDLINE", vmDef->os.cmdline);
+if (vmDef->os.initdir)
+virCommandSetWorkingDirectory(cmd, vmDef->os.initdir);
 
 for (i = 0; vmDef->os.initenv[i]; i++) {
 virCommandAddEnvPair(cmd, vmDef->os.initenv[i]->name,
diff --git a/tests/lxcxml2xmldata/lxc-initdir.xml 
b/tests/lxcxml2xmldata/lxc-initdir.xml
new file mode 100644
index 0..2940bda91
--- /dev/null
+++ b/tests/lxcxml2xmldata/lxc-initdir.xml
@@ -0,0 +1,30 @@
+
+  jessie
+  e21987a5-e98e-9c99-0e35-803e4d9ad1fe
+  1048576
+  1048576
+  1
+  
+/machine
+  
+  
+exe
+/sbin/sh
+/path/to/pwd
+  
+  
+  destroy
+  restart
+  restart
+  
+/usr/libexec/libvirt_lxc
+
+  
+  
+
+
+  
+
+  
+  
+
diff --git a/tests/lxcxml2xmltest.c b/tests/lxcxml2xmltest.c
index 2a24b60b3..c81b0eace 100644
--- a/tests/lxcxml2xmltest.c
+++ b/tests/lxcxml2xmltest.c
@@ -99,6 +99,7 @@ mymain(void)
 DO_TEST_FULL("filesystem-root", 0, false,
  VIR_DOMAIN_DEF_PARSE_SKIP_OSTYPE_CHECKS);
 DO_TEST("initenv");
+DO_TEST("initdir");
 
 virObjectUnref(caps);
 virObjectUnref(xmlopt);
-- 
2.12.2

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v3 0/4] lxc improvements

2017-06-26 Thread Cédric Bosdonnat
Hi all,

Here is a series grouping several small patches I sent
independently to the mailing list.

Main change since v2:
  *  and  have been changed to hold either a uid or
name as text child, rather than in an attribute.
  * Moved the uid/gid setting to after the pivot_root to allow getting
the uid/gid from name.

Cédric Bosdonnat (4):
  lxc: allow defining environment variables
  util: share code between virExec and virCommandExec
  lxc: allow user to specify command working directory
  lxc: add possibility to define init uid/gid

 docs/formatdomain.html.in | 17 +
 docs/schemas/domaincommon.rng | 29 +++
 src/conf/domain_conf.c| 52 ++
 src/conf/domain_conf.h| 11 ++
 src/lxc/lxc_container.c   | 59 ++
 src/util/vircommand.c | 69 ---
 tests/lxcxml2xmldata/lxc-initdir.xml  | 30 +++
 tests/lxcxml2xmldata/lxc-initenv.xml  | 30 +++
 tests/lxcxml2xmldata/lxc-inituser.xml | 31 
 tests/lxcxml2xmltest.c|  3 ++
 10 files changed, 302 insertions(+), 29 deletions(-)
 create mode 100644 tests/lxcxml2xmldata/lxc-initdir.xml
 create mode 100644 tests/lxcxml2xmldata/lxc-initenv.xml
 create mode 100644 tests/lxcxml2xmldata/lxc-inituser.xml

-- 
2.12.2

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH v3 2/4] util: share code between virExec and virCommandExec

2017-06-26 Thread Cédric Bosdonnat
virCommand is a version of virExec that doesn't fork, however it is
just calling execve and doesn't honors setting uid/gid and pwd.

This commit extrac those pieces from virExec() to a virExecCommon()
function that is called from both virExec() and virCommandExec().
---
 src/util/vircommand.c | 69 +--
 1 file changed, 40 insertions(+), 29 deletions(-)

diff --git a/src/util/vircommand.c b/src/util/vircommand.c
index e1bbc0526..60c1121da 100644
--- a/src/util/vircommand.c
+++ b/src/util/vircommand.c
@@ -464,6 +464,41 @@ virCommandHandshakeChild(virCommandPtr cmd)
 return 0;
 }
 
+static int
+virExecCommon(virCommandPtr cmd)
+{
+gid_t *groups = NULL;
+int ngroups;
+int ret = -1;
+
+if ((ngroups = virGetGroupList(cmd->uid, cmd->gid, )) < 0)
+goto cleanup;
+
+if (cmd->uid != (uid_t)-1 || cmd->gid != (gid_t)-1 ||
+cmd->capabilities || (cmd->flags & VIR_EXEC_CLEAR_CAPS)) {
+VIR_DEBUG("Setting child uid:gid to %d:%d with caps %llx",
+  (int)cmd->uid, (int)cmd->gid, cmd->capabilities);
+if (virSetUIDGIDWithCaps(cmd->uid, cmd->gid, groups, ngroups,
+ cmd->capabilities,
+ !!(cmd->flags & VIR_EXEC_CLEAR_CAPS)) < 0)
+goto cleanup;
+}
+
+if (cmd->pwd) {
+VIR_DEBUG("Running child in %s", cmd->pwd);
+if (chdir(cmd->pwd) < 0) {
+virReportSystemError(errno,
+ _("Unable to change to %s"), cmd->pwd);
+goto cleanup;
+}
+}
+ret = 0;
+
+ cleanup:
+VIR_FREE(groups);
+return ret;
+}
+
 /*
  * virExec:
  * @cmd virCommandPtr containing all information about the program to
@@ -484,8 +519,6 @@ virExec(virCommandPtr cmd)
 const char *binary = NULL;
 int ret;
 struct sigaction waxon, waxoff;
-gid_t *groups = NULL;
-int ngroups;
 
 if (cmd->args[0][0] != '/') {
 if (!(binary = binarystr = virFindFileInPath(cmd->args[0]))) {
@@ -556,9 +589,6 @@ virExec(virCommandPtr cmd)
 childerr = null;
 }
 
-if ((ngroups = virGetGroupList(cmd->uid, cmd->gid, )) < 0)
-goto cleanup;
-
 pid = virFork();
 
 if (pid < 0)
@@ -578,7 +608,6 @@ virExec(virCommandPtr cmd)
 cmd->pid = pid;
 
 VIR_FREE(binarystr);
-VIR_FREE(groups);
 
 return 0;
 }
@@ -727,28 +756,8 @@ virExec(virCommandPtr cmd)
 }
 # endif
 
-/* The steps above may need to do something privileged, so we delay
- * setuid and clearing capabilities until the last minute.
- */
-if (cmd->uid != (uid_t)-1 || cmd->gid != (gid_t)-1 ||
-cmd->capabilities || (cmd->flags & VIR_EXEC_CLEAR_CAPS)) {
-VIR_DEBUG("Setting child uid:gid to %d:%d with caps %llx",
-  (int)cmd->uid, (int)cmd->gid, cmd->capabilities);
-if (virSetUIDGIDWithCaps(cmd->uid, cmd->gid, groups, ngroups,
- cmd->capabilities,
- !!(cmd->flags & VIR_EXEC_CLEAR_CAPS)) < 0) {
-goto fork_error;
-}
-}
-
-if (cmd->pwd) {
-VIR_DEBUG("Running child in %s", cmd->pwd);
-if (chdir(cmd->pwd) < 0) {
-virReportSystemError(errno,
- _("Unable to change to %s"), cmd->pwd);
-goto fork_error;
-}
-}
+if (virExecCommon(cmd) < 0)
+goto fork_error;
 
 if (virCommandHandshakeChild(cmd) < 0)
goto fork_error;
@@ -789,7 +798,6 @@ virExec(virCommandPtr cmd)
 /* This is cleanup of parent process only - child
should never jump here on error */
 
-VIR_FREE(groups);
 VIR_FREE(binarystr);
 
 /* NB we don't virReportError() on any failures here
@@ -2166,6 +2174,9 @@ int virCommandExec(virCommandPtr cmd)
 return -1;
 }
 
+if (virExecCommon(cmd) < 0)
+return -1;
+
 execve(cmd->args[0], cmd->args, cmd->env);
 
 virReportSystemError(errno,
-- 
2.12.2

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v3 4/4] lxc: add possibility to define init uid/gid

2017-06-26 Thread Cédric Bosdonnat
Users may want to run the init command of a container as a special
user / group. This is achieved by adding  and 
elements. Note that the user can either provide a name or an ID to
specify the user / group to be used.

This commit also fixes a side effect of being able to run the command
as a non-root user: the user needs rights on the tty to allow shell
job control.
---
 docs/formatdomain.html.in |  7 +
 docs/schemas/domaincommon.rng | 14 ++
 src/conf/domain_conf.c|  9 ++
 src/conf/domain_conf.h|  2 ++
 src/lxc/lxc_container.c   | 52 +++
 tests/lxcxml2xmldata/lxc-inituser.xml | 31 +
 tests/lxcxml2xmltest.c|  1 +
 7 files changed, 116 insertions(+)
 create mode 100644 tests/lxcxml2xmldata/lxc-inituser.xml

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index e79a9d5be..f9a5177e0 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -334,6 +334,11 @@
   To set a custom work directory for the init, use the initdir
   element.
 
+
+  To run the init command as a given user or group, use the 
inituser
+  or initgroup elements respectively. Both elements can be 
provided
+  either a user (resp. group) id or a name.
+
 
 
 os
@@ -343,6 +348,8 @@
   initargemergency.service/initarg
   initenv name='MYENV'some value/initenv
   initdir/my/custom/cwd/initdir
+  initusertester/inituser
+  initgroup1000/initgroup
 /os
 
 
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 06fe62305..0b8294a9d 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -400,6 +400,20 @@
 
   
 
+
+  
+
+  
+  
+
+  
+  
+
+  
+  
+
+  
+
   
 
   
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 7835852f1..82c413e98 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -2871,6 +2871,8 @@ void virDomainDefFree(virDomainDefPtr def)
 for (i = 0; def->os.initenv && def->os.initenv[i]; i++)
 VIR_FREE(def->os.initenv[i]);
 VIR_FREE(def->os.initdir);
+VIR_FREE(def->os.inituser);
+VIR_FREE(def->os.initgroup);
 VIR_FREE(def->os.initenv);
 VIR_FREE(def->os.kernel);
 VIR_FREE(def->os.initrd);
@@ -17023,6 +17025,8 @@ virDomainDefParseBootOptions(virDomainDefPtr def,
 def->os.init = virXPathString("string(./os/init[1])", ctxt);
 def->os.cmdline = virXPathString("string(./os/cmdline[1])", ctxt);
 def->os.initdir = virXPathString("string(./os/initdir[1])", ctxt);
+def->os.inituser = virXPathString("string(./os/inituser[1])", ctxt);
+def->os.initgroup = virXPathString("string(./os/initgroup[1])", ctxt);
 
 if ((n = virXPathNodeSet("./os/initarg", ctxt, )) < 0)
 goto error;
@@ -24907,6 +24911,11 @@ virDomainDefFormatInternal(virDomainDefPtr def,
 if (def->os.initdir)
 virBufferEscapeString(buf, "%s\n",
   def->os.initdir);
+if (def->os.inituser)
+virBufferAsprintf(buf, "%s\n", def->os.inituser);
+if (def->os.initgroup)
+virBufferAsprintf(buf, "%s\n", 
def->os.initgroup);
+
 if (def->os.loader)
 virDomainLoaderDefFormat(buf, def->os.loader);
 virBufferEscapeString(buf, "%s\n",
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 4d41de2a4..bbffcda61 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1853,6 +1853,8 @@ struct _virDomainOSDef {
 char **initargv;
 virDomainOSEnvPtr *initenv;
 char *initdir;
+char *inituser;
+char *initgroup;
 char *kernel;
 char *initrd;
 char *cmdline;
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index 8d8e1a735..6309abe4b 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -2110,6 +2110,55 @@ static int lxcAttachNS(int *ns_fd)
 return 0;
 }
 
+/**
+ * lxcContainerSetUserGroup:
+ * @cmd: command to update
+ * @vmDef: domain definition for the container
+ * @ttyPath: guest path to the tty
+ *
+ * Set the command UID and GID. As this function attempts at
+ * converting the user/group name into uid/gid, it needs to
+ * be called after the pivot root is done.
+ *
+ * The owner of the tty is also changed to the given user.
+ */
+static int lxcContainerSetUserGroup(virCommandPtr cmd,
+virDomainDefPtr vmDef,
+const char *ttyPath)
+{
+uid_t uid;
+gid_t gid;
+
+if (vmDef->os.inituser) {
+if (virGetUserID(vmDef->os.inituser, ) < 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR, _("User %s doesn't exist"),
+   vmDef->os.inituser);
+return -1;

[libvirt] [PATCH v3 1/4] lxc: allow defining environment variables

2017-06-26 Thread Cédric Bosdonnat
When running an application container, setting environment variables
could be important.

The newly introduced  tag in domain configuration will allow
setting environment variables to the init program.
---
 docs/formatdomain.html.in|  5 +
 docs/schemas/domaincommon.rng| 10 ++
 src/conf/domain_conf.c   | 38 
 src/conf/domain_conf.h   |  8 
 src/lxc/lxc_container.c  |  5 +
 tests/lxcxml2xmldata/lxc-initenv.xml | 30 
 tests/lxcxml2xmltest.c   |  1 +
 7 files changed, 97 insertions(+)
 create mode 100644 tests/lxcxml2xmldata/lxc-initenv.xml

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index a55a9e139..d2db5a4f9 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -326,6 +326,10 @@
   element, if set will be used to provide an equivalent to 
/proc/cmdline
   but will not affect init argv.
 
+
+  To set environment variables, use the initenv element, one
+  for each variable.
+
 
 
 os
@@ -333,6 +337,7 @@
   init/bin/systemd/init
   initarg--unit/initarg
   initargemergency.service/initarg
+  initenv name='MYENV'some value/initenv
 /os
 
 
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index e259e3ee2..1e9fccc9e 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -385,6 +385,16 @@
 
   
 
+
+  
+
+  
+[a-zA-Z_]+[a-zA-Z0-9_]*
+  
+
+
+  
+
   
 
   
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index fdf85d5dd..868aa522e 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -2868,6 +2868,9 @@ void virDomainDefFree(virDomainDefPtr def)
 for (i = 0; def->os.initargv && def->os.initargv[i]; i++)
 VIR_FREE(def->os.initargv[i]);
 VIR_FREE(def->os.initargv);
+for (i = 0; def->os.initenv && def->os.initenv[i]; i++)
+VIR_FREE(def->os.initenv[i]);
+VIR_FREE(def->os.initenv);
 VIR_FREE(def->os.kernel);
 VIR_FREE(def->os.initrd);
 VIR_FREE(def->os.cmdline);
@@ -17001,6 +17004,7 @@ virDomainDefParseBootOptions(virDomainDefPtr def,
 xmlNodePtr *nodes = NULL;
 xmlNodePtr oldnode;
 char *tmp = NULL;
+char *name = NULL;
 int ret = -1;
 size_t i;
 int n;
@@ -17036,6 +17040,37 @@ virDomainDefParseBootOptions(virDomainDefPtr def,
 }
 def->os.initargv[n] = NULL;
 VIR_FREE(nodes);
+
+if ((n = virXPathNodeSet("./os/initenv", ctxt, )) < 0)
+goto error;
+
+if (VIR_ALLOC_N(def->os.initenv, n+1) < 0)
+goto error;
+for (i = 0; i < n; i++) {
+if (!(name = virXMLPropString(nodes[i], "name"))) {
+virReportError(VIR_ERR_XML_ERROR, "%s",
+_("No name supplied for  element"));
+goto error;
+}
+
+if (!nodes[i]->children ||
+!nodes[i]->children->content) {
+virReportError(VIR_ERR_XML_ERROR,
+   _("No value supplied for  
element"),
+   name);
+goto error;
+}
+
+if (VIR_ALLOC(def->os.initenv[i]) < 0)
+goto error;
+
+def->os.initenv[i]->name = name;
+if (VIR_STRDUP(def->os.initenv[i]->value,
+   (const char*) nodes[i]->children->content) < 0)
+goto error;
+}
+def->os.initenv[n] = NULL;
+VIR_FREE(nodes);
 }
 
 if (def->os.type == VIR_DOMAIN_OSTYPE_XEN ||
@@ -24864,6 +24899,9 @@ virDomainDefFormatInternal(virDomainDefPtr def,
 for (i = 0; def->os.initargv && def->os.initargv[i]; i++)
 virBufferEscapeString(buf, "%s\n",
   def->os.initargv[i]);
+for (i = 0; def->os.initenv && def->os.initenv[i]; i++)
+virBufferAsprintf(buf, "%s\n",
+  def->os.initenv[i]->name, def->os.initenv[i]->value);
 if (def->os.loader)
 virDomainLoaderDefFormat(buf, def->os.loader);
 virBufferEscapeString(buf, "%s\n",
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 6d9ee9787..5e47e2e97 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1831,6 +1831,13 @@ typedef enum {
 VIR_ENUM_DECL(virDomainIOAPIC);
 
 /* Operating system configuration data & machine / arch */
+typedef struct _virDomainOSEnv virDomainOSEnv;
+typedef virDomainOSEnv *virDomainOSEnvPtr;
+struct _virDomainOSEnv {
+char *name;
+char *value;
+};
+
 typedef struct _virDomainOSDef virDomainOSDef;
 typedef virDomainOSDef *virDomainOSDefPtr;
 struct _virDomainOSDef {
@@ -1844,6 +1851,7 @@ struct _virDomainOSDef {
 bool bm_timeout_set;
 char 

[libvirt] [sandbox 2/2] machine: use squash security mode for non-root virt-sandbox mounts

2017-06-08 Thread Cédric Bosdonnat
When running virt-sandbox as a user with host-bind mount, the user
can't write in the mounted folder. If run as root, use passthrough
security mode, otherwise use squashed one to fix this.
---
 libvirt-sandbox/libvirt-sandbox-builder-machine.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/libvirt-sandbox/libvirt-sandbox-builder-machine.c 
b/libvirt-sandbox/libvirt-sandbox-builder-machine.c
index 7204f71..b6f2218 100644
--- a/libvirt-sandbox/libvirt-sandbox-builder-machine.c
+++ b/libvirt-sandbox/libvirt-sandbox-builder-machine.c
@@ -589,7 +589,10 @@ static gboolean 
gvir_sandbox_builder_machine_construct_devices(GVirSandboxBuilde
 
 fs = gvir_config_domain_filesys_new();
 gvir_config_domain_filesys_set_type(fs, 
GVIR_CONFIG_DOMAIN_FILESYS_MOUNT);
-gvir_config_domain_filesys_set_access_type(fs, 
GVIR_CONFIG_DOMAIN_FILESYS_ACCESS_PASSTHROUGH);
+if (getuid() == 0)
+gvir_config_domain_filesys_set_access_type(fs, 
GVIR_CONFIG_DOMAIN_FILESYS_ACCESS_PASSTHROUGH);
+else
+gvir_config_domain_filesys_set_access_type(fs, 
GVIR_CONFIG_DOMAIN_FILESYS_ACCESS_SQUASH);
 gvir_config_domain_filesys_set_source(fs,
   
gvir_sandbox_config_mount_file_get_source(mfile));
 gvir_config_domain_filesys_set_target(fs, target);
-- 
2.12.2

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [sandbox 0/2] misc fixes

2017-06-08 Thread Cédric Bosdonnat
Hi all,

Here are a two fixes for virt-sandbox. One to actually use -d and -v flags
in the init program, and the other to get host-bound mounts writable as
non-root user.

Cédric Bosdonnat (2):
  Pass debug and verbose values to init
  machine: use squash security mode  for non-root virt-sandbox mounts

 bin/virt-sandbox.c|  3 +
 libvirt-sandbox/libvirt-sandbox-builder-machine.c |  5 +-
 libvirt-sandbox/libvirt-sandbox-config.c  | 75 +++
 libvirt-sandbox/libvirt-sandbox-config.h  |  6 ++
 libvirt-sandbox/libvirt-sandbox-init-common.c |  3 +
 libvirt-sandbox/libvirt-sandbox.sym   |  4 ++
 6 files changed, 95 insertions(+), 1 deletion(-)

-- 
2.12.2

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [sandbox 1/2] Pass debug and verbose values to init

2017-06-08 Thread Cédric Bosdonnat
libvirt-sandbox-init-common is expecting -d and -v parameters to
set it in debug or verbose mode... but those will never be passed
by the launcher program.

Writing the core.debug and core.verbose parameters in the sandbox
configuration makes those values actually usable from the init.
---
 bin/virt-sandbox.c|  3 ++
 libvirt-sandbox/libvirt-sandbox-config.c  | 75 +++
 libvirt-sandbox/libvirt-sandbox-config.h  |  6 +++
 libvirt-sandbox/libvirt-sandbox-init-common.c |  3 ++
 libvirt-sandbox/libvirt-sandbox.sym   |  4 ++
 5 files changed, 91 insertions(+)

diff --git a/bin/virt-sandbox.c b/bin/virt-sandbox.c
index 3058013..6032562 100644
--- a/bin/virt-sandbox.c
+++ b/bin/virt-sandbox.c
@@ -273,6 +273,9 @@ int main(int argc, char **argv) {
 if (shell)
 gvir_sandbox_config_set_shell(cfg, TRUE);
 
+gvir_sandbox_config_set_debug(cfg, debug);
+gvir_sandbox_config_set_verbose(cfg, verbose);
+
 if (isatty(STDIN_FILENO))
 gvir_sandbox_config_interactive_set_tty(icfg, TRUE);
 
diff --git a/libvirt-sandbox/libvirt-sandbox-config.c 
b/libvirt-sandbox/libvirt-sandbox-config.c
index 8709736..73a0fa4 100644
--- a/libvirt-sandbox/libvirt-sandbox-config.c
+++ b/libvirt-sandbox/libvirt-sandbox-config.c
@@ -68,6 +68,9 @@ struct _GVirSandboxConfigPrivate
 
 gchar *secLabel;
 gboolean secDynamic;
+
+gboolean debug;
+gboolean verbose;
 };
 
 G_DEFINE_ABSTRACT_TYPE(GVirSandboxConfig, gvir_sandbox_config, G_TYPE_OBJECT);
@@ -1926,6 +1929,59 @@ gboolean 
gvir_sandbox_config_set_security_opts(GVirSandboxConfig *config,
 return ret;
 }
 
+/**
+ * gvir_sandbox_config_set_debug:
+ * @config: (transfer none): the sandbox config
+ * @debug: true if the container init should print debugging messages
+ *
+ * Set whether the container init should print debugging messages.
+ */
+void gvir_sandbox_config_set_debug(GVirSandboxConfig *config, gboolean debug)
+{
+GVirSandboxConfigPrivate *priv = config->priv;
+priv->debug = debug;
+}
+
+/**
+ * gvir_sandbox_config_get_debug:
+ * @config: (transfer none): the sandbox config
+ *
+ * Retrieves the sandbox debug flag
+ *
+ * Returns: the debug flag
+ */
+gboolean gvir_sandbox_config_get_debug(GVirSandboxConfig *config)
+{
+GVirSandboxConfigPrivate *priv = config->priv;
+return priv->debug;
+}
+
+/**
+ * gvir_sandbox_config_set_verbose:
+ * @config: (transfer none): the sandbox config
+ * @verbose: true if the container init should be verbose
+ *
+ * Set whether the container init should be verbose.
+ */
+void gvir_sandbox_config_set_verbose(GVirSandboxConfig *config, gboolean 
verbose)
+{
+GVirSandboxConfigPrivate *priv = config->priv;
+priv->verbose = verbose;
+}
+
+/**
+ * gvir_sandbox_config_get_verbose:
+ * @config: (transfer none): the sandbox config
+ *
+ * Retrieves the sandbox verbose flag
+ *
+ * Returns: the verbose flag
+ */
+gboolean gvir_sandbox_config_get_verbose(GVirSandboxConfig *config)
+{
+GVirSandboxConfigPrivate *priv = config->priv;
+return priv->verbose;
+}
 
 static GVirSandboxConfigMount *gvir_sandbox_config_load_config_mount(GKeyFile 
*file,
  guint i,
@@ -2415,6 +2471,22 @@ static gboolean 
gvir_sandbox_config_load_config(GVirSandboxConfig *config,
 priv->secDynamic = b;
 }
 
+b = g_key_file_get_boolean(file, "core", "debug", );
+if (e) {
+g_error_free(e);
+e = NULL;
+} else {
+priv->debug = b;
+}
+
+b = g_key_file_get_boolean(file, "core", "verbose", );
+if (e) {
+g_error_free(e);
+e = NULL;
+} else {
+priv->verbose = b;
+}
+
 ret = TRUE;
  cleanup:
 return ret;
@@ -2677,6 +2749,9 @@ static void 
gvir_sandbox_config_save_config(GVirSandboxConfig *config,
 if (priv->secLabel)
 g_key_file_set_string(file, "security", "label", priv->secLabel);
 g_key_file_set_boolean(file, "security", "dynamic", priv->secDynamic);
+
+g_key_file_set_boolean(file, "core", "debug", priv->debug);
+g_key_file_set_boolean(file, "core", "verbose", priv->verbose);
 }
 
 
diff --git a/libvirt-sandbox/libvirt-sandbox-config.h 
b/libvirt-sandbox/libvirt-sandbox-config.h
index e5e53f7..8950e25 100644
--- a/libvirt-sandbox/libvirt-sandbox-config.h
+++ b/libvirt-sandbox/libvirt-sandbox-config.h
@@ -180,6 +180,12 @@ gboolean 
gvir_sandbox_config_set_security_opts(GVirSandboxConfig *config,
const gchar *optstr,
GError**error);
 
+void gvir_sandbox_config_set_debug(GVirSandboxConfig *config, gboolean debug);
+gboolean gvir_sandbox_config_get_debug(GVirSandboxConfig *config);
+
+void gvir_sandbox_config_set_verbose(GVirSandboxConfig *config, gboolean 
verbose);
+gboolean gvir_sandbox_config_get_verbose(GVirSandboxConfig *config);
+
 gchar 

[libvirt] [PATCH 1/2] util: share code between virExec and virCommandExec

2017-06-06 Thread Cédric Bosdonnat
virCommand is a version of virExec that doesn't fork, however it is
just calling execve and doesn't honors setting uid/gid and pwd.

This commit extrac those pieces from virExec() to a virExecCommon()
function that is called from both virExec() and virCommandExec().
---
 src/util/vircommand.c | 69 +--
 1 file changed, 40 insertions(+), 29 deletions(-)

diff --git a/src/util/vircommand.c b/src/util/vircommand.c
index e1bbc0526..60c1121da 100644
--- a/src/util/vircommand.c
+++ b/src/util/vircommand.c
@@ -464,6 +464,41 @@ virCommandHandshakeChild(virCommandPtr cmd)
 return 0;
 }
 
+static int
+virExecCommon(virCommandPtr cmd)
+{
+gid_t *groups = NULL;
+int ngroups;
+int ret = -1;
+
+if ((ngroups = virGetGroupList(cmd->uid, cmd->gid, )) < 0)
+goto cleanup;
+
+if (cmd->uid != (uid_t)-1 || cmd->gid != (gid_t)-1 ||
+cmd->capabilities || (cmd->flags & VIR_EXEC_CLEAR_CAPS)) {
+VIR_DEBUG("Setting child uid:gid to %d:%d with caps %llx",
+  (int)cmd->uid, (int)cmd->gid, cmd->capabilities);
+if (virSetUIDGIDWithCaps(cmd->uid, cmd->gid, groups, ngroups,
+ cmd->capabilities,
+ !!(cmd->flags & VIR_EXEC_CLEAR_CAPS)) < 0)
+goto cleanup;
+}
+
+if (cmd->pwd) {
+VIR_DEBUG("Running child in %s", cmd->pwd);
+if (chdir(cmd->pwd) < 0) {
+virReportSystemError(errno,
+ _("Unable to change to %s"), cmd->pwd);
+goto cleanup;
+}
+}
+ret = 0;
+
+ cleanup:
+VIR_FREE(groups);
+return ret;
+}
+
 /*
  * virExec:
  * @cmd virCommandPtr containing all information about the program to
@@ -484,8 +519,6 @@ virExec(virCommandPtr cmd)
 const char *binary = NULL;
 int ret;
 struct sigaction waxon, waxoff;
-gid_t *groups = NULL;
-int ngroups;
 
 if (cmd->args[0][0] != '/') {
 if (!(binary = binarystr = virFindFileInPath(cmd->args[0]))) {
@@ -556,9 +589,6 @@ virExec(virCommandPtr cmd)
 childerr = null;
 }
 
-if ((ngroups = virGetGroupList(cmd->uid, cmd->gid, )) < 0)
-goto cleanup;
-
 pid = virFork();
 
 if (pid < 0)
@@ -578,7 +608,6 @@ virExec(virCommandPtr cmd)
 cmd->pid = pid;
 
 VIR_FREE(binarystr);
-VIR_FREE(groups);
 
 return 0;
 }
@@ -727,28 +756,8 @@ virExec(virCommandPtr cmd)
 }
 # endif
 
-/* The steps above may need to do something privileged, so we delay
- * setuid and clearing capabilities until the last minute.
- */
-if (cmd->uid != (uid_t)-1 || cmd->gid != (gid_t)-1 ||
-cmd->capabilities || (cmd->flags & VIR_EXEC_CLEAR_CAPS)) {
-VIR_DEBUG("Setting child uid:gid to %d:%d with caps %llx",
-  (int)cmd->uid, (int)cmd->gid, cmd->capabilities);
-if (virSetUIDGIDWithCaps(cmd->uid, cmd->gid, groups, ngroups,
- cmd->capabilities,
- !!(cmd->flags & VIR_EXEC_CLEAR_CAPS)) < 0) {
-goto fork_error;
-}
-}
-
-if (cmd->pwd) {
-VIR_DEBUG("Running child in %s", cmd->pwd);
-if (chdir(cmd->pwd) < 0) {
-virReportSystemError(errno,
- _("Unable to change to %s"), cmd->pwd);
-goto fork_error;
-}
-}
+if (virExecCommon(cmd) < 0)
+goto fork_error;
 
 if (virCommandHandshakeChild(cmd) < 0)
goto fork_error;
@@ -789,7 +798,6 @@ virExec(virCommandPtr cmd)
 /* This is cleanup of parent process only - child
should never jump here on error */
 
-VIR_FREE(groups);
 VIR_FREE(binarystr);
 
 /* NB we don't virReportError() on any failures here
@@ -2166,6 +2174,9 @@ int virCommandExec(virCommandPtr cmd)
 return -1;
 }
 
+if (virExecCommon(cmd) < 0)
+return -1;
+
 execve(cmd->args[0], cmd->args, cmd->env);
 
 virReportSystemError(errno,
-- 
2.12.2

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH] lxc: add possibility to define init uid/gid

2017-06-06 Thread Cédric Bosdonnat
Users may want to run the init command of a container as a special
user / group. Allow doing it using  and  elements.
---
 docs/formatdomain.html.in |  6 ++
 docs/schemas/domaincommon.rng | 12 
 src/conf/domain_conf.c| 19 +++
 src/conf/domain_conf.h|  2 ++
 src/lxc/lxc_container.c   | 13 +
 tests/lxcxml2xmldata/lxc-inituser.xml | 31 +++
 tests/lxcxml2xmltest.c|  1 +
 7 files changed, 84 insertions(+)
 create mode 100644 tests/lxcxml2xmldata/lxc-inituser.xml

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 7627fd0d0..85d5f4539 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -334,6 +334,10 @@
   To set a custom work directory for the init, use the initdir
   element.
 
+
+  To run the init command as a given user or group, use the 
inituser
+  or initgroup elements respectively.
+
 
 
 os
@@ -343,6 +347,8 @@
   initargemergency.service/initarg
   initenv name='MYENV'some value/initenv
   initdir/my/custom/cwd/initdir
+  inituser uid="1000"/
+  initgroup gid="1000"/
 /os
 
 
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 5a4c4ecf1..385e937e9 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -400,6 +400,18 @@
 
   
 
+
+  
+
+  
+
+  
+  
+
+  
+
+  
+
   
 
   
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 3c2a81f52..21bb104a9 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -16806,6 +16806,18 @@ virDomainDefParseBootOptions(virDomainDefPtr def,
 def->os.cmdline = virXPathString("string(./os/cmdline[1])", ctxt);
 def->os.initdir = virXPathString("string(./os/initdir[1])", ctxt);
 
+if (virXPathUInt("string(./os/inituser[1]/@uid)", ctxt, 
>os.inituid) == -2) {
+virReportError(VIR_ERR_XML_ERROR, "%s",
+   _("Failed to parse inituser uid"));
+goto error;
+}
+
+if (virXPathUInt("string(./os/initgroup[1]/@gid)", ctxt, 
>os.initgid) == -2) {
+virReportError(VIR_ERR_XML_ERROR, "%s",
+   _("Failed to parse initgroup gid"));
+goto error;
+}
+
 if ((n = virXPathNodeSet("./os/initarg", ctxt, )) < 0)
 goto error;
 
@@ -24593,6 +24605,13 @@ virDomainDefFormatInternal(virDomainDefPtr def,
 if (def->os.initdir)
 virBufferEscapeString(buf, "%s\n",
   def->os.initdir);
+if (def->os.inituid)
+virBufferAsprintf(buf, "\n",
+  def->os.inituid);
+if (def->os.initgid)
+virBufferAsprintf(buf, "\n",
+  def->os.initgid);
+
 if (def->os.loader)
 virDomainLoaderDefFormat(buf, def->os.loader);
 virBufferEscapeString(buf, "%s\n",
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index d6b8429c3..6e1997324 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1842,6 +1842,8 @@ struct _virDomainOSDef {
 char **initargv;
 virDomainOSEnvPtr *initenv;
 char *initdir;
+uid_t inituid;
+gid_t initgid;
 char *kernel;
 char *initrd;
 char *cmdline;
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index 8d8e1a735..42bcd25c4 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -247,6 +247,10 @@ static virCommandPtr 
lxcContainerBuildInitCmd(virDomainDefPtr vmDef,
 virCommandAddEnvPair(cmd, "LIBVIRT_LXC_CMDLINE", vmDef->os.cmdline);
 if (vmDef->os.initdir)
 virCommandSetWorkingDirectory(cmd, vmDef->os.initdir);
+if (vmDef->os.inituid)
+virCommandSetUID(cmd, vmDef->os.inituid);
+if (vmDef->os.initgid)
+virCommandSetGID(cmd, vmDef->os.initgid);
 
 for (i = 0; vmDef->os.initenv[i]; i++) {
 virCommandAddEnvPair(cmd, vmDef->os.initenv[i]->name,
@@ -2192,6 +2196,15 @@ static int lxcContainerChild(void *data)
 goto cleanup;
 }
 
+/* Change the newly created tty owner to the inituid for
+ * shells to have job control */
+if (vmDef->os.inituid && chown(ttyPath, vmDef->os.inituid, -1) < 0) {
+virReportSystemError(errno,
+ _("Failed to change ownership of tty %s"),
+ ttyPath);
+goto cleanup;
+}
+
 if (lxcContainerResolveAllSymlinks(vmDef) < 0)
 goto cleanup;
 
diff --git a/tests/lxcxml2xmldata/lxc-inituser.xml 
b/tests/lxcxml2xmldata/lxc-inituser.xml
new file mode 100644
index 0..61b5db4af
--- /dev/null
+++ b/tests/lxcxml2xmldata/lxc-inituser.xml
@@ -0,0 +1,31 @@
+
+  jessie
+  e21987a5-e98e-9c99-0e35-803e4d9ad1fe
+  

[libvirt] [PATCH 2/2] lxc: allow user to specify command working directory

2017-06-06 Thread Cédric Bosdonnat
Some containers may want the application to run in a special directory.
Add  element in the domain configuration to handle this case
and use it in the lxc driver.
---
 docs/formatdomain.html.in|  5 +
 docs/schemas/domaincommon.rng|  5 +
 src/conf/domain_conf.c   |  5 +
 src/conf/domain_conf.h   |  1 +
 src/lxc/lxc_container.c  |  2 ++
 tests/lxcxml2xmldata/lxc-initdir.xml | 30 ++
 tests/lxcxml2xmltest.c   |  1 +
 7 files changed, 49 insertions(+)
 create mode 100644 tests/lxcxml2xmldata/lxc-initdir.xml

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 8da50875b..7627fd0d0 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -330,6 +330,10 @@
   To set environment variables, use the initenv element, one
   for each variable.
 
+
+  To set a custom work directory for the init, use the initdir
+  element.
+
 
 
 os
@@ -338,6 +342,7 @@
   initarg--unit/initarg
   initargemergency.service/initarg
   initenv name='MYENV'some value/initenv
+  initdir/my/custom/cwd/initdir
 /os
 
 
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 695214816..5a4c4ecf1 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -395,6 +395,11 @@
 
   
 
+
+  
+
+  
+
   
 
   
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 37ed1a732..3c2a81f52 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -2808,6 +2808,7 @@ void virDomainDefFree(virDomainDefPtr def)
 VIR_FREE(def->os.initargv);
 for (i = 0; def->os.initenv && def->os.initenv[i]; i++)
 VIR_FREE(def->os.initenv[i]);
+VIR_FREE(def->os.initdir);
 VIR_FREE(def->os.initenv);
 VIR_FREE(def->os.kernel);
 VIR_FREE(def->os.initrd);
@@ -16803,6 +16804,7 @@ virDomainDefParseBootOptions(virDomainDefPtr def,
 if (def->os.type == VIR_DOMAIN_OSTYPE_EXE) {
 def->os.init = virXPathString("string(./os/init[1])", ctxt);
 def->os.cmdline = virXPathString("string(./os/cmdline[1])", ctxt);
+def->os.initdir = virXPathString("string(./os/initdir[1])", ctxt);
 
 if ((n = virXPathNodeSet("./os/initarg", ctxt, )) < 0)
 goto error;
@@ -24588,6 +24590,9 @@ virDomainDefFormatInternal(virDomainDefPtr def,
 for (i = 0; def->os.initenv && def->os.initenv[i]; i++)
 virBufferAsprintf(buf, "%s\n",
   def->os.initenv[i]->name, def->os.initenv[i]->value);
+if (def->os.initdir)
+virBufferEscapeString(buf, "%s\n",
+  def->os.initdir);
 if (def->os.loader)
 virDomainLoaderDefFormat(buf, def->os.loader);
 virBufferEscapeString(buf, "%s\n",
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 4d86a1e16..d6b8429c3 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1841,6 +1841,7 @@ struct _virDomainOSDef {
 char *init;
 char **initargv;
 virDomainOSEnvPtr *initenv;
+char *initdir;
 char *kernel;
 char *initrd;
 char *cmdline;
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index ffafc39d7..8d8e1a735 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -245,6 +245,8 @@ static virCommandPtr 
lxcContainerBuildInitCmd(virDomainDefPtr vmDef,
 virCommandAddEnvPair(cmd, "LIBVIRT_LXC_NAME", vmDef->name);
 if (vmDef->os.cmdline)
 virCommandAddEnvPair(cmd, "LIBVIRT_LXC_CMDLINE", vmDef->os.cmdline);
+if (vmDef->os.initdir)
+virCommandSetWorkingDirectory(cmd, vmDef->os.initdir);
 
 for (i = 0; vmDef->os.initenv[i]; i++) {
 virCommandAddEnvPair(cmd, vmDef->os.initenv[i]->name,
diff --git a/tests/lxcxml2xmldata/lxc-initdir.xml 
b/tests/lxcxml2xmldata/lxc-initdir.xml
new file mode 100644
index 0..2940bda91
--- /dev/null
+++ b/tests/lxcxml2xmldata/lxc-initdir.xml
@@ -0,0 +1,30 @@
+
+  jessie
+  e21987a5-e98e-9c99-0e35-803e4d9ad1fe
+  1048576
+  1048576
+  1
+  
+/machine
+  
+  
+exe
+/sbin/sh
+/path/to/pwd
+  
+  
+  destroy
+  restart
+  restart
+  
+/usr/libexec/libvirt_lxc
+
+  
+  
+
+
+  
+
+  
+  
+
diff --git a/tests/lxcxml2xmltest.c b/tests/lxcxml2xmltest.c
index 2a24b60b3..c81b0eace 100644
--- a/tests/lxcxml2xmltest.c
+++ b/tests/lxcxml2xmltest.c
@@ -99,6 +99,7 @@ mymain(void)
 DO_TEST_FULL("filesystem-root", 0, false,
  VIR_DOMAIN_DEF_PARSE_SKIP_OSTYPE_CHECKS);
 DO_TEST("initenv");
+DO_TEST("initdir");
 
 virObjectUnref(caps);
 virObjectUnref(xmlopt);
-- 
2.12.2

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH 0/2] Set lxc container working directory

2017-06-06 Thread Cédric Bosdonnat
Hi all,

Here is a resubmit with:
  * virExec() call orders preserved while still sharing code with
virCommandExec()
  * Cleanup in the last patch

Cédric Bosdonnat (2):
  util: share code between virExec and virCommandExec
  lxc: allow user to specify command working directory

 docs/formatdomain.html.in|  5 +++
 docs/schemas/domaincommon.rng|  5 +++
 src/conf/domain_conf.c   |  5 +++
 src/conf/domain_conf.h   |  1 +
 src/lxc/lxc_container.c  |  2 ++
 src/util/vircommand.c| 69 +---
 tests/lxcxml2xmldata/lxc-initdir.xml | 30 
 tests/lxcxml2xmltest.c   |  1 +
 8 files changed, 89 insertions(+), 29 deletions(-)
 create mode 100644 tests/lxcxml2xmldata/lxc-initdir.xml

-- 
2.12.2

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH 1/2] util: share code between virExec and virCommandExec

2017-06-01 Thread Cédric Bosdonnat
virCommand is a version of virExec that doesn't fork, however it is
just calling execve and doesn't honors setting uid/gid and pwd.

This commit moves those pieces from virExec to virCommandExec and
makes virExec use virCommandExec to avoid code duplication.
---
 src/util/vircommand.c | 92 ---
 1 file changed, 43 insertions(+), 49 deletions(-)

diff --git a/src/util/vircommand.c b/src/util/vircommand.c
index e1bbc0526..aa97a5a10 100644
--- a/src/util/vircommand.c
+++ b/src/util/vircommand.c
@@ -481,21 +481,18 @@ virExec(virCommandPtr cmd)
 int childerr = -1;
 int tmpfd;
 char *binarystr = NULL;
-const char *binary = NULL;
 int ret;
 struct sigaction waxon, waxoff;
-gid_t *groups = NULL;
-int ngroups;
 
 if (cmd->args[0][0] != '/') {
-if (!(binary = binarystr = virFindFileInPath(cmd->args[0]))) {
+if (!(binarystr = virFindFileInPath(cmd->args[0]))) {
 virReportSystemError(ENOENT,
  _("Cannot find '%s' in path"),
  cmd->args[0]);
 return -1;
 }
-} else {
-binary = cmd->args[0];
+VIR_FREE(cmd->args[0]);
+cmd->args[0] = binarystr;
 }
 
 if (childin < 0) {
@@ -556,9 +553,6 @@ virExec(virCommandPtr cmd)
 childerr = null;
 }
 
-if ((ngroups = virGetGroupList(cmd->uid, cmd->gid, )) < 0)
-goto cleanup;
-
 pid = virFork();
 
 if (pid < 0)
@@ -577,9 +571,6 @@ virExec(virCommandPtr cmd)
 
 cmd->pid = pid;
 
-VIR_FREE(binarystr);
-VIR_FREE(groups);
-
 return 0;
 }
 
@@ -727,29 +718,6 @@ virExec(virCommandPtr cmd)
 }
 # endif
 
-/* The steps above may need to do something privileged, so we delay
- * setuid and clearing capabilities until the last minute.
- */
-if (cmd->uid != (uid_t)-1 || cmd->gid != (gid_t)-1 ||
-cmd->capabilities || (cmd->flags & VIR_EXEC_CLEAR_CAPS)) {
-VIR_DEBUG("Setting child uid:gid to %d:%d with caps %llx",
-  (int)cmd->uid, (int)cmd->gid, cmd->capabilities);
-if (virSetUIDGIDWithCaps(cmd->uid, cmd->gid, groups, ngroups,
- cmd->capabilities,
- !!(cmd->flags & VIR_EXEC_CLEAR_CAPS)) < 0) {
-goto fork_error;
-}
-}
-
-if (cmd->pwd) {
-VIR_DEBUG("Running child in %s", cmd->pwd);
-if (chdir(cmd->pwd) < 0) {
-virReportSystemError(errno,
- _("Unable to change to %s"), cmd->pwd);
-goto fork_error;
-}
-}
-
 if (virCommandHandshakeChild(cmd) < 0)
goto fork_error;
 
@@ -771,15 +739,10 @@ virExec(virCommandPtr cmd)
 /* Close logging again to ensure no FDs leak to child */
 virLogReset();
 
-if (cmd->env)
-execve(binary, cmd->args, cmd->env);
-else
-execv(binary, cmd->args);
+if (virCommandExec(cmd) == -2)
+goto fork_error;
 
 ret = errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE;
-virReportSystemError(errno,
- _("cannot execute binary %s"),
- cmd->args[0]);
 
  fork_error:
 virDispatchError(NULL);
@@ -789,9 +752,6 @@ virExec(virCommandPtr cmd)
 /* This is cleanup of parent process only - child
should never jump here on error */
 
-VIR_FREE(groups);
-VIR_FREE(binarystr);
-
 /* NB we don't virReportError() on any failures here
because the code which jumped here already raised
an error condition which we must not overwrite */
@@ -2150,23 +2110,57 @@ virCommandProcessIO(virCommandPtr cmd)
  * in the hook after already forking / cloning, so does not attempt to
  * daemonize or preserve any FDs.
  *
- * Returns -1 on any error executing the command.
+ * Returns -1 on any error executing the command, -2 if the error happen
+ * before running the command.
+ *
  * Will not return on success.
  */
 #ifndef WIN32
 int virCommandExec(virCommandPtr cmd)
 {
+gid_t *groups = NULL;
+int ngroups;
+
 if (!cmd ||cmd->has_error == ENOMEM) {
 virReportOOMError();
-return -1;
+return -2;
 }
 if (cmd->has_error) {
 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("invalid use of command API"));
-return -1;
+return -2;
 }
 
-execve(cmd->args[0], cmd->args, cmd->env);
+if ((ngroups = virGetGroupList(cmd->uid, cmd->gid, )) < 0) {
+VIR_FREE(groups);
+return -2;
+}
+
+if (cmd->uid != (uid_t)-1 || cmd->gid != (gid_t)-1 ||
+cmd->capabilities || (cmd->flags & VIR_EXEC_CLEAR_CAPS)) {
+VIR_DEBUG("Setting child uid:gid to %d:%d with caps %llx",
+  (int)cmd->uid, (int)cmd->gid, cmd->capabilities);
+if (virSetUIDGIDWithCaps(cmd->uid, cmd->gid, groups, ngroups,
+ 

[libvirt] [PATCH 0/2] Set lxc container working directory

2017-06-01 Thread Cédric Bosdonnat
Hi all,

To get lxc containers set the workng directory I had to refactor
virExec and virCommandExec to share some more code.

Cédric Bosdonnat (2):
  util: share code between virExec and virCommandExec
  lxc: allow user to specify command working directory

 docs/formatdomain.html.in|  5 ++
 docs/schemas/domaincommon.rng|  5 ++
 src/conf/domain_conf.c   |  5 ++
 src/conf/domain_conf.h   |  1 +
 src/lxc/lxc_container.c  |  4 +-
 src/util/vircommand.c| 92 +---
 tests/lxcxml2xmldata/lxc-initdir.xml | 30 
 tests/lxcxml2xmltest.c   |  1 +
 8 files changed, 93 insertions(+), 50 deletions(-)
 create mode 100644 tests/lxcxml2xmldata/lxc-initdir.xml

-- 
2.12.2

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH 2/2] lxc: allow user to specify command working directory

2017-06-01 Thread Cédric Bosdonnat
Some containers may want the application to run in a special directory.
Add  element in the domain configuration to handle this case
and use it in the lxc driver.
---
 docs/formatdomain.html.in|  5 +
 docs/schemas/domaincommon.rng|  5 +
 src/conf/domain_conf.c   |  5 +
 src/conf/domain_conf.h   |  1 +
 src/lxc/lxc_container.c  |  4 +++-
 tests/lxcxml2xmldata/lxc-initdir.xml | 30 ++
 tests/lxcxml2xmltest.c   |  1 +
 7 files changed, 50 insertions(+), 1 deletion(-)
 create mode 100644 tests/lxcxml2xmldata/lxc-initdir.xml

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 8da50875b..7627fd0d0 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -330,6 +330,10 @@
   To set environment variables, use the initenv element, one
   for each variable.
 
+
+  To set a custom work directory for the init, use the initdir
+  element.
+
 
 
 os
@@ -338,6 +342,7 @@
   initarg--unit/initarg
   initargemergency.service/initarg
   initenv name='MYENV'some value/initenv
+  initdir/my/custom/cwd/initdir
 /os
 
 
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 695214816..5a4c4ecf1 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -395,6 +395,11 @@
 
   
 
+
+  
+
+  
+
   
 
   
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 89c803047..bf530fc52 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -2801,6 +2801,7 @@ void virDomainDefFree(virDomainDefPtr def)
 VIR_FREE(def->os.initargv);
 for (i = 0; def->os.initenv && def->os.initenv[i]; i++)
 VIR_FREE(def->os.initenv[i]);
+VIR_FREE(def->os.initdir);
 VIR_FREE(def->os.initenv);
 VIR_FREE(def->os.kernel);
 VIR_FREE(def->os.initrd);
@@ -16796,6 +16797,7 @@ virDomainDefParseBootOptions(virDomainDefPtr def,
 if (def->os.type == VIR_DOMAIN_OSTYPE_EXE) {
 def->os.init = virXPathString("string(./os/init[1])", ctxt);
 def->os.cmdline = virXPathString("string(./os/cmdline[1])", ctxt);
+def->os.initdir = virXPathString("string(./os/initdir[1])", ctxt);
 
 if ((n = virXPathNodeSet("./os/initarg", ctxt, )) < 0)
 goto error;
@@ -24562,6 +24564,9 @@ virDomainDefFormatInternal(virDomainDefPtr def,
 for (i = 0; def->os.initenv && def->os.initenv[i]; i++)
 virBufferAsprintf(buf, "%s\n",
   def->os.initenv[i]->name, def->os.initenv[i]->value);
+if (def->os.initdir)
+virBufferEscapeString(buf, "%s\n",
+  def->os.initdir);
 if (def->os.loader)
 virDomainLoaderDefFormat(buf, def->os.loader);
 virBufferEscapeString(buf, "%s\n",
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 03153b972..105f0b7a6 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1841,6 +1841,7 @@ struct _virDomainOSDef {
 char *init;
 char **initargv;
 virDomainOSEnvPtr *initenv;
+char *initdir;
 char *kernel;
 char *initrd;
 char *cmdline;
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index ffafc39d7..c122a588e 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -237,7 +237,7 @@ static virCommandPtr 
lxcContainerBuildInitCmd(virDomainDefPtr vmDef,
 virCommandAddEnvString(cmd, "PATH=/bin:/sbin");
 virCommandAddEnvString(cmd, "TERM=linux");
 virCommandAddEnvString(cmd, "container=lxc-libvirt");
-virCommandAddEnvString(cmd, "HOME=/");
+/*virCommandAddEnvString(cmd, "HOME=/"); */
 virCommandAddEnvPair(cmd, "container_uuid", uuidstr);
 if (nttyPaths > 1)
 virCommandAddEnvPair(cmd, "container_ttys", 
virBufferCurrentContent());
@@ -245,6 +245,8 @@ static virCommandPtr 
lxcContainerBuildInitCmd(virDomainDefPtr vmDef,
 virCommandAddEnvPair(cmd, "LIBVIRT_LXC_NAME", vmDef->name);
 if (vmDef->os.cmdline)
 virCommandAddEnvPair(cmd, "LIBVIRT_LXC_CMDLINE", vmDef->os.cmdline);
+if (vmDef->os.initdir)
+virCommandSetWorkingDirectory(cmd, vmDef->os.initdir);
 
 for (i = 0; vmDef->os.initenv[i]; i++) {
 virCommandAddEnvPair(cmd, vmDef->os.initenv[i]->name,
diff --git a/tests/lxcxml2xmldata/lxc-initdir.xml 
b/tests/lxcxml2xmldata/lxc-initdir.xml
new file mode 100644
index 0..2940bda91
--- /dev/null
+++ b/tests/lxcxml2xmldata/lxc-initdir.xml
@@ -0,0 +1,30 @@
+
+  jessie
+  e21987a5-e98e-9c99-0e35-803e4d9ad1fe
+  1048576
+  1048576
+  1
+  
+/machine
+  
+  
+exe
+/sbin/sh
+/path/to/pwd
+  
+  
+  destroy
+  restart
+  restart
+  
+/usr/libexec/libvirt_lxc
+
+  
+  
+
+
+  
+
+  
+  
+
diff --git a/tests/lxcxml2xmltest.c b/tests/lxcxml2xmltest.c
index 2a24b60b3..c81b0eace 100644
--- 

[libvirt] [PATCH] lxc: allow defining environment variables

2017-05-30 Thread Cédric Bosdonnat
When running an application container, setting environment variables
could be important.

The newly introduced  tag in domain configuration will allow
setting environment variables to the init program.
---
 docs/formatdomain.html.in|  5 +
 docs/schemas/domaincommon.rng| 10 ++
 src/conf/domain_conf.c   | 38 
 src/conf/domain_conf.h   |  8 
 src/lxc/lxc_container.c  |  5 +
 tests/lxcxml2xmldata/lxc-initenv.xml | 30 
 tests/lxcxml2xmltest.c   |  1 +
 7 files changed, 97 insertions(+)
 create mode 100644 tests/lxcxml2xmldata/lxc-initenv.xml

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 07208eef8..8da50875b 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -326,6 +326,10 @@
   element, if set will be used to provide an equivalent to 
/proc/cmdline
   but will not affect init argv.
 
+
+  To set environment variables, use the initenv element, one
+  for each variable.
+
 
 
 os
@@ -333,6 +337,7 @@
   init/bin/systemd/init
   initarg--unit/initarg
   initargemergency.service/initarg
+  initenv name='MYENV'some value/initenv
 /os
 
 
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 4d9f8d1a2..695214816 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -385,6 +385,16 @@
 
   
 
+
+  
+
+  
+[a-zA-Z_]+[a-zA-Z0-9_]*
+  
+
+
+  
+
   
 
   
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index c7e20b8ba..89c803047 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -2799,6 +2799,9 @@ void virDomainDefFree(virDomainDefPtr def)
 for (i = 0; def->os.initargv && def->os.initargv[i]; i++)
 VIR_FREE(def->os.initargv[i]);
 VIR_FREE(def->os.initargv);
+for (i = 0; def->os.initenv && def->os.initenv[i]; i++)
+VIR_FREE(def->os.initenv[i]);
+VIR_FREE(def->os.initenv);
 VIR_FREE(def->os.kernel);
 VIR_FREE(def->os.initrd);
 VIR_FREE(def->os.cmdline);
@@ -16776,6 +16779,7 @@ virDomainDefParseBootOptions(virDomainDefPtr def,
 xmlNodePtr *nodes = NULL;
 xmlNodePtr oldnode;
 char *tmp = NULL;
+char *name = NULL;
 int ret = -1;
 size_t i;
 int n;
@@ -16811,6 +16815,37 @@ virDomainDefParseBootOptions(virDomainDefPtr def,
 }
 def->os.initargv[n] = NULL;
 VIR_FREE(nodes);
+
+if ((n = virXPathNodeSet("./os/initenv", ctxt, )) < 0)
+goto error;
+
+if (VIR_ALLOC_N(def->os.initenv, n+1) < 0)
+goto error;
+for (i = 0; i < n; i++) {
+if (!(name = virXMLPropString(nodes[i], "name"))) {
+virReportError(VIR_ERR_XML_ERROR, "%s",
+_("No name supplied for  element"));
+goto error;
+}
+
+if (!nodes[i]->children ||
+!nodes[i]->children->content) {
+virReportError(VIR_ERR_XML_ERROR,
+   _("No value supplied for  
element"),
+   name);
+goto error;
+}
+
+if (VIR_ALLOC(def->os.initenv[i]) < 0)
+goto error;
+
+def->os.initenv[i]->name = name;
+if (VIR_STRDUP(def->os.initenv[i]->value,
+   (const char*) nodes[i]->children->content) < 0)
+goto error;
+}
+def->os.initenv[n] = NULL;
+VIR_FREE(nodes);
 }
 
 if (def->os.type == VIR_DOMAIN_OSTYPE_XEN ||
@@ -24524,6 +24559,9 @@ virDomainDefFormatInternal(virDomainDefPtr def,
 for (i = 0; def->os.initargv && def->os.initargv[i]; i++)
 virBufferEscapeString(buf, "%s\n",
   def->os.initargv[i]);
+for (i = 0; def->os.initenv && def->os.initenv[i]; i++)
+virBufferAsprintf(buf, "%s\n",
+  def->os.initenv[i]->name, def->os.initenv[i]->value);
 if (def->os.loader)
 virDomainLoaderDefFormat(buf, def->os.loader);
 virBufferEscapeString(buf, "%s\n",
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 83e067269..03153b972 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1820,6 +1820,13 @@ typedef enum {
 VIR_ENUM_DECL(virDomainIOAPIC);
 
 /* Operating system configuration data & machine / arch */
+typedef struct _virDomainOSEnv virDomainOSEnv;
+typedef virDomainOSEnv *virDomainOSEnvPtr;
+struct _virDomainOSEnv {
+char *name;
+char *value;
+};
+
 typedef struct _virDomainOSDef virDomainOSDef;
 typedef virDomainOSDef *virDomainOSDefPtr;
 struct _virDomainOSDef {
@@ -1833,6 +1840,7 @@ struct _virDomainOSDef {
 bool bm_timeout_set;
 char 

[libvirt] [PATCH] IPv6 route check: list devices only once

2017-04-26 Thread Cédric Bosdonnat
If several RA routes are found for the same device, only list that
device once in the error message.
---
 src/util/virnetdevip.c | 10 +-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/src/util/virnetdevip.c b/src/util/virnetdevip.c
index 09925e1d7..bf98ed8a5 100644
--- a/src/util/virnetdevip.c
+++ b/src/util/virnetdevip.c
@@ -551,6 +551,8 @@ virNetDevIPCheckIPv6ForwardingCallback(const struct 
nlmsghdr *resp,
 int ret = 0;
 int len = RTM_PAYLOAD(resp);
 int oif = -1;
+size_t i;
+bool hasDevice;
 
 /* Ignore messages other than route ones */
 if (resp->nlmsg_type != RTM_NEWROUTE)
@@ -587,7 +589,13 @@ virNetDevIPCheckIPv6ForwardingCallback(const struct 
nlmsghdr *resp,
 accept_ra = virNetDevIPGetAcceptRA(ifname);
 VIR_DEBUG("Checking route for device %s, accept_ra: %d", ifname, 
accept_ra);
 
-if (accept_ra != 2 && VIR_APPEND_ELEMENT(data->devices, data->ndevices, 
ifname) < 0)
+hasDevice = false;
+for (i = 0; i < data->ndevices && !hasDevice; i++) {
+if (STREQ(data->devices[i], ifname))
+hasDevice = true;
+}
+if (accept_ra != 2 && !hasDevice &&
+VIR_APPEND_ELEMENT(data->devices, data->ndevices, ifname) < 0)
 goto error;
 
  cleanup:
-- 
2.12.2

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v2] virNetDevIPCheckIPv6ForwardingCallback fixes

2017-03-28 Thread Cédric Bosdonnat
Add check for more than one RTA_OIF, even though this is rather
unlikely.

Get rid of the buggy switch / break as this code won't need to
handle more attributes.

Use VIR_WARNINGS_NO_CAST_ALIGN to fix impossible to fix
util/virnetdevip.c:560:17: error: cast increases required alignment of target 
type [-Werror=cast-align]
---
 Diff to v1:
   * Add error message
   * Use VIR_WARNINGS_NO_CAST_ALIGN
 src/util/virnetdevip.c | 17 +
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/src/util/virnetdevip.c b/src/util/virnetdevip.c
index c9ac6baf7..726fa6c3e 100644
--- a/src/util/virnetdevip.c
+++ b/src/util/virnetdevip.c
@@ -556,15 +556,24 @@ virNetDevIPCheckIPv6ForwardingCallback(const struct 
nlmsghdr *resp,
 if (resp->nlmsg_type != RTM_NEWROUTE)
 return ret;
 
-/* Extract a few attributes */
+/* Extract a device ID attribute */
+VIR_WARNINGS_NO_CAST_ALIGN
 for (rta = RTM_RTA(rtmsg); RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) {
-switch (rta->rta_type) {
-case RTA_OIF:
+VIR_WARNINGS_RESET
+if (rta->rta_type == RTA_OIF) {
 oif = *(int *)RTA_DATA(rta);
 
+/* Should never happen: netlink message would be broken */
+if (ifname) {
+char *ifname2 = virNetDevGetName(oif);
+VIR_WARN("Single route has unexpected 2nd interface "
+ "- '%s' and '%s'", ifname, ifname2);
+VIR_FREE(ifname2);
+break;
+}
+
 if (!(ifname = virNetDevGetName(oif)))
 goto error;
-break;
 }
 }
 
-- 
2.12.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH] Coverity fix for virNetDevIPCheckIPv6ForwardingCallback

2017-03-24 Thread Cédric Bosdonnat
Add check for more than one RTA_OIF, even though this is rather
unlikely and get rid of the buggy switch / break.
---
 src/util/virnetdevip.c | 10 ++
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/src/util/virnetdevip.c b/src/util/virnetdevip.c
index c9ac6baf7..f5662413a 100644
--- a/src/util/virnetdevip.c
+++ b/src/util/virnetdevip.c
@@ -556,15 +556,17 @@ virNetDevIPCheckIPv6ForwardingCallback(const struct 
nlmsghdr *resp,
 if (resp->nlmsg_type != RTM_NEWROUTE)
 return ret;
 
-/* Extract a few attributes */
+/* Extract a device ID attribute */
 for (rta = RTM_RTA(rtmsg); RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) {
-switch (rta->rta_type) {
-case RTA_OIF:
+if (rta->rta_type == RTA_OIF) {
 oif = *(int *)RTA_DATA(rta);
 
+/* Should never happen: netlink message would be broken */
+if (ifname)
+goto error;
+
 if (!(ifname = virNetDevGetName(oif)))
 goto error;
-break;
 }
 }
 
-- 
2.12.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v2 5/5] network: check accept_ra before enabling ipv6 forwarding

2017-03-15 Thread Cédric Bosdonnat
When enabling IPv6 on all interfaces, we may get the host Router
Advertisement routes discarded. To avoid this, the user needs to set
accept_ra to 2 for the interfaces with such routes.

See https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt
on this topic.

To avoid user mistakenly losing routes on their hosts, check
accept_ra values before enabling IPv6 forwarding. If a RA route is
detected, but neither the corresponding device nor global accept_ra
is set to 2, the network will fail to start.
---
 src/libvirt_private.syms|   1 +
 src/network/bridge_driver.c |  16 +++--
 src/util/virnetdevip.c  | 158 
 src/util/virnetdevip.h  |   1 +
 4 files changed, 171 insertions(+), 5 deletions(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 0fe88c3fa..ec6553520 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2056,6 +2056,7 @@ virNetDevBridgeSetVlanFiltering;
 virNetDevIPAddrAdd;
 virNetDevIPAddrDel;
 virNetDevIPAddrGet;
+virNetDevIPCheckIPv6Forwarding;
 virNetDevIPInfoAddToDev;
 virNetDevIPInfoClear;
 virNetDevIPRouteAdd;
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 3f6561055..d02cd19f9 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -61,6 +61,7 @@
 #include "virlog.h"
 #include "virdnsmasq.h"
 #include "configmake.h"
+#include "virnetlink.h"
 #include "virnetdev.h"
 #include "virnetdevip.h"
 #include "virnetdevbridge.h"
@@ -2377,11 +2378,16 @@ networkStartNetworkVirtual(virNetworkDriverStatePtr 
driver,
 }
 
 /* If forward.type != NONE, turn on global IP forwarding */
-if (network->def->forward.type != VIR_NETWORK_FORWARD_NONE &&
-networkEnableIPForwarding(v4present, v6present) < 0) {
-virReportSystemError(errno, "%s",
- _("failed to enable IP forwarding"));
-goto err3;
+if (network->def->forward.type != VIR_NETWORK_FORWARD_NONE) {
+if (!virNetDevIPCheckIPv6Forwarding())
+goto err3; /* Precise error message already provided */
+
+
+if (networkEnableIPForwarding(v4present, v6present) < 0) {
+virReportSystemError(errno, "%s",
+ _("failed to enable IP forwarding"));
+goto err3;
+}
 }
 
 
diff --git a/src/util/virnetdevip.c b/src/util/virnetdevip.c
index 42fbba1eb..a4d382427 100644
--- a/src/util/virnetdevip.c
+++ b/src/util/virnetdevip.c
@@ -508,6 +508,158 @@ virNetDevIPWaitDadFinish(virSocketAddrPtr *addrs, size_t 
count)
 return ret;
 }
 
+static int
+virNetDevIPGetAcceptRA(const char *ifname)
+{
+char *path = NULL;
+char *buf = NULL;
+char *suffix;
+int accept_ra = -1;
+
+if (virAsprintf(, "/proc/sys/net/ipv6/conf/%s/accept_ra",
+ifname ? ifname : "all") < 0)
+goto cleanup;
+
+if ((virFileReadAll(path, 512, ) < 0) ||
+(virStrToLong_i(buf, , 10, _ra) < 0))
+goto cleanup;
+
+ cleanup:
+VIR_FREE(path);
+VIR_FREE(buf);
+
+return accept_ra;
+}
+
+struct virNetDevIPCheckIPv6ForwardingData {
+bool hasRARoutes;
+
+/* Devices with conflicting accept_ra */
+char **devices;
+size_t ndevices;
+};
+
+static int
+virNetDevIPCheckIPv6ForwardingCallback(const struct nlmsghdr *resp,
+   void *opaque)
+{
+struct rtmsg *rtmsg = NLMSG_DATA(resp);
+int accept_ra = -1;
+struct rtattr *rta;
+char *ifname = NULL;
+struct virNetDevIPCheckIPv6ForwardingData *data = opaque;
+int ret = 0;
+int len = RTM_PAYLOAD(resp);
+int oif = -1;
+
+/* Ignore messages other than route ones */
+if (resp->nlmsg_type != RTM_NEWROUTE)
+return ret;
+
+/* Extract a few attributes */
+for (rta = RTM_RTA(rtmsg); RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) {
+switch (rta->rta_type) {
+case RTA_OIF:
+oif = *(int *)RTA_DATA(rta);
+
+if (!(ifname = virNetDevGetName(oif)))
+goto error;
+break;
+}
+}
+
+/* No need to do anything else for non RA routes */
+if (rtmsg->rtm_protocol != RTPROT_RA)
+goto cleanup;
+
+data->hasRARoutes = true;
+
+/* Check the accept_ra value for the interface */
+accept_ra = virNetDevIPGetAcceptRA(ifname);
+VIR_DEBUG("Checking route for device %s, accept_ra: %d", ifname, 
accept_ra);
+
+if (accept_ra != 2 && VIR_APPEND_ELEMENT(data->devices, data->ndevices, 
ifname) < 0)
+goto error;
+
+ cleanup:
+VIR_FREE(ifname);
+return ret;
+
+ error:
+ret = -1;
+goto cleanup;
+}
+
+bool
+virNetDevIPCheckIPv6Forwarding(void)
+{
+struct nl_msg *nlmsg = NULL;
+bool valid = false;
+struct rtgenmsg genmsg;
+size_t i;
+struct virNetDevIPCheckIPv6ForwardingData data = {
+.hasRARoutes = false,
+.devices = NULL,
+.ndevices = 0
+};
+
+
+/* Prepare 

[libvirt] [PATCH v2 0/5] Prevent losing IPv6 routes due to forwarding

2017-03-15 Thread Cédric Bosdonnat
Hi Laine, all,

Here is the v2 of my series. The changes are:

 * Add a commit to create a virNetDevGetName() function
 * Fix Laine's comments

Cédric Bosdonnat (5):
  util: extract the request sending code from virNetlinkCommand()
  util: add virNetlinkDumpCommand()
  bridge_driver.c: more uses of SYSCTL_PATH
  util: add virNetDevGetName() function
  network: check accept_ra before enabling ipv6 forwarding

 src/libvirt_private.syms|   3 +
 src/network/bridge_driver.c |  25 ---
 src/util/virnetdev.c|  19 ++
 src/util/virnetdev.h|   2 +
 src/util/virnetdevip.c  | 158 
 src/util/virnetdevip.h  |   1 +
 src/util/virnetlink.c   | 145 ++--
 src/util/virnetlink.h   |   9 +++
 8 files changed, 319 insertions(+), 43 deletions(-)

-- 
2.11.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH v2 2/5] util: add virNetlinkDumpCommand()

2017-03-15 Thread Cédric Bosdonnat
virNetlinkCommand() processes only one response message, while some
netlink commands like routes dumping need to process several ones.
Add virNetlinkDumpCommand() as a virNetlinkCommand() sister.
---
 src/libvirt_private.syms |  1 +
 src/util/virnetlink.c| 58 
 src/util/virnetlink.h|  9 
 3 files changed, 68 insertions(+)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 4efea0098..1f25e42d8 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2127,6 +2127,7 @@ virNetDevVPortProfileOpTypeToString;
 # util/virnetlink.h
 virNetlinkCommand;
 virNetlinkDelLink;
+virNetlinkDumpCommand;
 virNetlinkDumpLink;
 virNetlinkEventAddClient;
 virNetlinkEventRemoveClient;
diff --git a/src/util/virnetlink.c b/src/util/virnetlink.c
index be00351db..9bc1f0f2b 100644
--- a/src/util/virnetlink.c
+++ b/src/util/virnetlink.c
@@ -335,6 +335,52 @@ int virNetlinkCommand(struct nl_msg *nl_msg,
 return ret;
 }
 
+int
+virNetlinkDumpCommand(struct nl_msg *nl_msg,
+  virNetlinkDumpCallback callback,
+  uint32_t src_pid, uint32_t dst_pid,
+  unsigned int protocol, unsigned int groups,
+  void *opaque)
+{
+int ret = -1;
+bool end = false;
+int len = 0;
+struct nlmsghdr *resp = NULL;
+struct nlmsghdr *msg = NULL;
+
+struct sockaddr_nl nladdr = {
+.nl_family = AF_NETLINK,
+.nl_pid= dst_pid,
+.nl_groups = 0,
+};
+virNetlinkHandle *nlhandle = NULL;
+
+if (!(nlhandle = virNetlinkSendRequest(nl_msg, src_pid, nladdr,
+   protocol, groups)))
+goto cleanup;
+
+while (!end) {
+len = nl_recv(nlhandle, , (unsigned char **), NULL);
+
+for (msg = resp; NLMSG_OK(msg, len); msg = NLMSG_NEXT(msg, len)) {
+if (msg->nlmsg_type == NLMSG_DONE)
+end = true;
+
+if (virNetlinkGetErrorCode(msg, len) < 0)
+goto cleanup;
+
+if (callback(msg, opaque) < 0)
+goto cleanup;
+}
+}
+
+ret = 0;
+
+ cleanup:
+virNetlinkFree(nlhandle);
+return ret;
+}
+
 /**
  * virNetlinkDumpLink:
  *
@@ -1061,6 +1107,18 @@ int virNetlinkCommand(struct nl_msg *nl_msg 
ATTRIBUTE_UNUSED,
 return -1;
 }
 
+int
+virNetlinkDumpCommand(struct nl_msg *nl_msg ATTRIBUTE_UNUSED,
+  virNetlinkDumpCallback callback ATTRIBUTE_UNUSED,
+  uint32_t src_pid ATTRIBUTE_UNUSED,
+  uint32_t dst_pid ATTRIBUTE_UNUSED,
+  unsigned int protocol ATTRIBUTE_UNUSED,
+  unsigned int groups ATTRIBUTE_UNUSED,
+  void *opaque ATTRIBUTE_UNUSED)
+{
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _(unsupported));
+return -1;
+}
 
 int
 virNetlinkDumpLink(const char *ifname ATTRIBUTE_UNUSED,
diff --git a/src/util/virnetlink.h b/src/util/virnetlink.h
index 11e817c82..088b01343 100644
--- a/src/util/virnetlink.h
+++ b/src/util/virnetlink.h
@@ -52,6 +52,15 @@ int virNetlinkCommand(struct nl_msg *nl_msg,
   uint32_t src_pid, uint32_t dst_pid,
   unsigned int protocol, unsigned int groups);
 
+typedef int (*virNetlinkDumpCallback)(const struct nlmsghdr *resp,
+  void *data);
+
+int virNetlinkDumpCommand(struct nl_msg *nl_msg,
+  virNetlinkDumpCallback callback,
+  uint32_t src_pid, uint32_t dst_pid,
+  unsigned int protocol, unsigned int groups,
+  void *opaque);
+
 typedef int (*virNetlinkDelLinkFallback)(const char *ifname);
 
 int virNetlinkDelLink(const char *ifname, virNetlinkDelLinkFallback fallback);
-- 
2.11.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v2 1/5] util: extract the request sending code from virNetlinkCommand()

2017-03-15 Thread Cédric Bosdonnat
Allow to reuse as much as possible from virNetlinkCommand(). This
comment prepares for the introduction of virNetlindDumpCommand()
only differing by how it handles the responses.
---
 src/util/virnetlink.c | 89 +++
 1 file changed, 54 insertions(+), 35 deletions(-)

diff --git a/src/util/virnetlink.c b/src/util/virnetlink.c
index a5d10fa8e..be00351db 100644
--- a/src/util/virnetlink.c
+++ b/src/util/virnetlink.c
@@ -209,61 +209,38 @@ virNetlinkCreateSocket(int protocol)
 goto cleanup;
 }
 
-
-/**
- * virNetlinkCommand:
- * @nlmsg: pointer to netlink message
- * @respbuf: pointer to pointer where response buffer will be allocated
- * @respbuflen: pointer to integer holding the size of the response buffer
- *  on return of the function.
- * @src_pid: the pid of the process to send a message
- * @dst_pid: the pid of the process to talk to, i.e., pid = 0 for kernel
- * @protocol: netlink protocol
- * @groups: the group identifier
- *
- * Send the given message to the netlink layer and receive response.
- * Returns 0 on success, -1 on error. In case of error, no response
- * buffer will be returned.
- */
-int virNetlinkCommand(struct nl_msg *nl_msg,
-  struct nlmsghdr **resp, unsigned int *respbuflen,
-  uint32_t src_pid, uint32_t dst_pid,
+static virNetlinkHandle *
+virNetlinkSendRequest(struct nl_msg *nl_msg, uint32_t src_pid,
+  struct sockaddr_nl nladdr,
   unsigned int protocol, unsigned int groups)
 {
-int ret = -1;
-struct sockaddr_nl nladdr = {
-.nl_family = AF_NETLINK,
-.nl_pid= dst_pid,
-.nl_groups = 0,
-};
 ssize_t nbytes;
-struct pollfd fds[1];
 int fd;
 int n;
-struct nlmsghdr *nlmsg = nlmsg_hdr(nl_msg);
 virNetlinkHandle *nlhandle = NULL;
-int len = 0;
+struct pollfd fds[1];
+struct nlmsghdr *nlmsg = nlmsg_hdr(nl_msg);
 
 if (protocol >= MAX_LINKS) {
 virReportSystemError(EINVAL,
  _("invalid protocol argument: %d"), protocol);
-goto cleanup;
+goto error;
 }
 
 if (!(nlhandle = virNetlinkCreateSocket(protocol)))
-goto cleanup;
+goto error;
 
 fd = nl_socket_get_fd(nlhandle);
 if (fd < 0) {
 virReportSystemError(errno,
  "%s", _("cannot get netlink socket fd"));
-goto cleanup;
+goto error;
 }
 
 if (groups && nl_socket_add_membership(nlhandle, groups) < 0) {
 virReportSystemError(errno,
  "%s", _("cannot add netlink membership"));
-goto cleanup;
+goto error;
 }
 
 nlmsg_set_dst(nl_msg, );
@@ -274,10 +251,11 @@ int virNetlinkCommand(struct nl_msg *nl_msg,
 if (nbytes < 0) {
 virReportSystemError(errno,
  "%s", _("cannot send to netlink socket"));
-goto cleanup;
+goto error;
 }
 
 memset(fds, 0, sizeof(fds));
+
 fds[0].fd = fd;
 fds[0].events = POLLIN;
 
@@ -289,9 +267,51 @@ int virNetlinkCommand(struct nl_msg *nl_msg,
 if (n == 0)
 virReportSystemError(ETIMEDOUT, "%s",
  _("no valid netlink response was received"));
-goto cleanup;
 }
 
+return nlhandle;
+
+ error:
+virNetlinkFree(nlhandle);
+return NULL;
+}
+
+/**
+ * virNetlinkCommand:
+ * @nlmsg: pointer to netlink message
+ * @respbuf: pointer to pointer where response buffer will be allocated
+ * @respbuflen: pointer to integer holding the size of the response buffer
+ *  on return of the function.
+ * @src_pid: the pid of the process to send a message
+ * @dst_pid: the pid of the process to talk to, i.e., pid = 0 for kernel
+ * @protocol: netlink protocol
+ * @groups: the group identifier
+ *
+ * Send the given message to the netlink layer and receive response.
+ * Returns 0 on success, -1 on error. In case of error, no response
+ * buffer will be returned.
+ */
+int virNetlinkCommand(struct nl_msg *nl_msg,
+  struct nlmsghdr **resp, unsigned int *respbuflen,
+  uint32_t src_pid, uint32_t dst_pid,
+  unsigned int protocol, unsigned int groups)
+{
+int ret = -1;
+struct sockaddr_nl nladdr = {
+.nl_family = AF_NETLINK,
+.nl_pid= dst_pid,
+.nl_groups = 0,
+};
+struct pollfd fds[1];
+virNetlinkHandle *nlhandle = NULL;
+int len = 0;
+
+memset(fds, 0, sizeof(fds));
+
+if (!(nlhandle = virNetlinkSendRequest(nl_msg, src_pid, nladdr,
+   protocol, groups)))
+goto cleanup;
+
 len = nl_recv(nlhandle, , (unsigned char **)resp, NULL);
 if (len == 0) {
 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@@ -315,7 +335,6 @@ int virNetlinkCommand(struct nl_msg *nl_msg,
 return ret;
 }
 
-
 /**
  

[libvirt] [PATCH v2 4/5] util: add virNetDevGetName() function

2017-03-15 Thread Cédric Bosdonnat
Add a function getting the name of a network interface out of its index.
---
 src/libvirt_private.syms |  1 +
 src/util/virnetdev.c | 19 +++
 src/util/virnetdev.h |  2 ++
 3 files changed, 22 insertions(+)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 1f25e42d8..0fe88c3fa 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1982,6 +1982,7 @@ virNetDevFeatureTypeToString;
 virNetDevGetFeatures;
 virNetDevGetIndex;
 virNetDevGetLinkInfo;
+virNetDevGetName;
 virNetDevGetMAC;
 virNetDevGetMTU;
 virNetDevGetOnline;
diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c
index d12324878..91a5274aa 100644
--- a/src/util/virnetdev.c
+++ b/src/util/virnetdev.c
@@ -899,6 +899,25 @@ virNetDevGetRcvAllMulti(const char *ifname,
 return virNetDevGetIFFlag(ifname, VIR_IFF_ALLMULTI, receive);
 }
 
+char *virNetDevGetName(int ifindex)
+{
+char name[IFNAMSIZ];
+char *ifname = NULL;
+
+memset(, 0, sizeof(name));
+
+if (!if_indextoname(ifindex, name)) {
+virReportSystemError(errno,
+ _("Failed to convert interface index %d to a 
name"),
+ ifindex);
+goto cleanup;
+}
+
+   ignore_value(VIR_STRDUP(ifname, name));
+
+ cleanup:
+ return ifname;
+}
 
 /**
  * virNetDevGetIndex:
diff --git a/src/util/virnetdev.h b/src/util/virnetdev.h
index 236cf83ef..01e9c5b95 100644
--- a/src/util/virnetdev.h
+++ b/src/util/virnetdev.h
@@ -157,6 +157,8 @@ int virNetDevSetNamespace(const char *ifname, pid_t pidInNs)
 int virNetDevSetName(const char *ifname, const char *newifname)
 ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
 
+char *virNetDevGetName(int ifindex)
+ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
 int virNetDevGetIndex(const char *ifname, int *ifindex)
 ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
 
-- 
2.11.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v2 3/5] bridge_driver.c: more uses of SYSCTL_PATH

2017-03-15 Thread Cédric Bosdonnat
Replace a few occurences of /proc/sys by the corresponding macro
defined a few lines after: SYSCTL_PATH
---
 src/network/bridge_driver.c | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index c5ec2823d..3f6561055 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -85,6 +85,8 @@
  */
 #define VIR_NETWORK_DHCP_LEASE_FILE_SIZE_MAX (32 * 1024 * 1024)
 
+#define SYSCTL_PATH "/proc/sys"
+
 VIR_LOG_INIT("network.bridge_driver");
 
 static virNetworkDriverStatePtr network_driver;
@@ -2080,15 +2082,14 @@ networkEnableIPForwarding(bool enableIPv4, bool 
enableIPv6)
, sizeof(enabled));
 #else
 if (enableIPv4)
-ret = virFileWriteStr("/proc/sys/net/ipv4/ip_forward", "1\n", 0);
+ret = virFileWriteStr(SYSCTL_PATH "/net/ipv4/ip_forward", "1\n", 0);
 if (enableIPv6 && ret == 0)
-ret = virFileWriteStr("/proc/sys/net/ipv6/conf/all/forwarding", "1\n", 
0);
+ret = virFileWriteStr(SYSCTL_PATH "/net/ipv6/conf/all/forwarding", 
"1\n", 0);
+
 #endif
 return ret;
 }
 
-#define SYSCTL_PATH "/proc/sys"
-
 static int
 networkSetIPv6Sysctls(virNetworkObjPtr network)
 {
-- 
2.11.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH 4/4] network: check accept_ra before enabling ipv6 forwarding

2017-03-03 Thread Cédric Bosdonnat
When enabling IPv6 on all interfaces, we may get the host Router
Advertisement routes discarded. To avoid this, the user needs to set
accept_ra to 2 for the interfaces with such routes.

See https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt
on this topic.

To avoid user mistakenly loosing routes on their hosts, check
accept_ra values before enabling IPv6 forwarding. If a RA route is
detected, but neither the corresponding device nor global accept_ra
is set to 2, the network will fail to start.
---
 src/network/bridge_driver.c | 178 ++--
 1 file changed, 173 insertions(+), 5 deletions(-)

diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 3f6561055..1ac837f7f 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -61,6 +61,7 @@
 #include "virlog.h"
 #include "virdnsmasq.h"
 #include "configmake.h"
+#include "virnetlink.h"
 #include "virnetdev.h"
 #include "virnetdevip.h"
 #include "virnetdevbridge.h"
@@ -2067,6 +2068,168 @@ networkReloadFirewallRules(virNetworkDriverStatePtr 
driver)
  NULL);
 }
 
+static int
+networkGetAcceptRA(const char *ifname)
+{
+char *path = NULL;
+char *buf = NULL;
+char *suffix;
+int accept_ra = -1;
+
+if (virAsprintf(, SYSCTL_PATH "/net/ipv6/conf/%s/accept_ra",
+ifname ? ifname : "all") < 0)
+goto cleanup;
+
+if ((virFileReadAll(path, 512, ) < 0) ||
+(virStrToLong_i(buf, , 10, _ra) < 0))
+goto cleanup;
+
+ cleanup:
+VIR_FREE(path);
+VIR_FREE(buf);
+
+return accept_ra;
+}
+
+#if defined(__linux__) && defined(HAVE_LIBNL)
+struct networkIPv6CheckData {
+bool hasRARoutes;
+
+/* Devices with conflicting accept_ra */
+char **devices;
+size_t ndevices;
+};
+
+static int
+networkCheckIPv6ForwardingCallback(const struct nlmsghdr *resp,
+   void *opaque)
+{
+struct rtmsg *rtmsg = NLMSG_DATA(resp);
+int accept_ra = -1;
+struct rtattr *rta;
+char *ifname = NULL;
+char name[IFNAMSIZ];
+struct networkIPv6CheckData *data = opaque;
+int ret = 0;
+int len = RTM_PAYLOAD(resp);
+int oif = -1;
+
+/* Ignore messages other than route ones */
+if (resp->nlmsg_type != RTM_NEWROUTE)
+return ret;
+
+memset(, 0, sizeof(name));
+
+/* Extract a few attributes */
+for (rta = RTM_RTA(rtmsg); RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) {
+switch (rta->rta_type) {
+case RTA_OIF:
+oif = *(int *)RTA_DATA(rta);
+if (!if_indextoname(oif, name) || VIR_STRDUP(ifname, name) < 0)
+VIR_DEBUG("Failed to convert OIF to a device name");
+break;
+}
+}
+
+/* No need to do anything else for non RA routes */
+if (rtmsg->rtm_protocol != RTPROT_RA)
+goto cleanup;
+
+data->hasRARoutes = true;
+
+/* Check the accept_ra value for the interface */
+accept_ra = networkGetAcceptRA(ifname);
+VIR_DEBUG("Checking route for device %s, accept_ra: %d", ifname, 
accept_ra);
+
+if (accept_ra != 2 && VIR_APPEND_ELEMENT(data->devices, data->ndevices, 
ifname) < 0)
+ret = -1;
+
+ cleanup:
+VIR_FREE(ifname);
+return ret;
+}
+
+static bool
+networkCheckIPv6Forwarding(void)
+{
+struct nl_msg *nlmsg = NULL;
+bool valid = false;
+struct rtgenmsg genmsg;
+size_t i;
+struct networkIPv6CheckData data = {
+.hasRARoutes = false,
+.devices = NULL,
+.ndevices = 0
+};
+
+
+/* Prepare the request message */
+if (!(nlmsg = nlmsg_alloc_simple(RTM_GETROUTE,
+ NLM_F_REQUEST | NLM_F_DUMP))) {
+virReportOOMError();
+goto cleanup;
+}
+
+memset(, 0, sizeof(genmsg));
+genmsg.rtgen_family = AF_INET6;
+
+if (nlmsg_append(nlmsg, , sizeof(genmsg), NLMSG_ALIGNTO) < 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("allocated netlink buffer is too small"));
+goto cleanup;
+}
+
+/* Send the request and loop over the responses */
+if (virNetlinkDumpCommand(nlmsg, networkCheckIPv6ForwardingCallback, 0, 0,
+  NETLINK_ROUTE, 0, ) < 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("Failed to loop over routes"));
+goto cleanup;
+}
+
+valid = !data.hasRARoutes || data.ndevices == 0;
+
+/* Check the global accept_ra if at least one isn't set on a
+   per-device basis */
+if (!valid && data.hasRARoutes) {
+int accept_ra = networkGetAcceptRA(NULL);
+valid = accept_ra == 2;
+VIR_DEBUG("Checked global accept_ra: %d", accept_ra);
+}
+
+if (!valid) {
+virBuffer buf = VIR_BUFFER_INITIALIZER;
+for (i = 0; i < data.ndevices; i++) {
+virBufferAdd(, data.devices[i], -1);
+if (i < data.ndevices - 1)
+   

[libvirt] [PATCH 1/4] util: extract the request sending code from virNetlinkCommand()

2017-03-03 Thread Cédric Bosdonnat
Allow to reuse as much as possible from virNetlinkCommand(). This
comment prepares for the introduction of virNetlindDumpCommand()
only differing by how it handles the responses.
---
 src/util/virnetlink.c | 90 +++
 1 file changed, 55 insertions(+), 35 deletions(-)

diff --git a/src/util/virnetlink.c b/src/util/virnetlink.c
index a5d10fa8e..5fb49251c 100644
--- a/src/util/virnetlink.c
+++ b/src/util/virnetlink.c
@@ -209,61 +209,38 @@ virNetlinkCreateSocket(int protocol)
 goto cleanup;
 }
 
-
-/**
- * virNetlinkCommand:
- * @nlmsg: pointer to netlink message
- * @respbuf: pointer to pointer where response buffer will be allocated
- * @respbuflen: pointer to integer holding the size of the response buffer
- *  on return of the function.
- * @src_pid: the pid of the process to send a message
- * @dst_pid: the pid of the process to talk to, i.e., pid = 0 for kernel
- * @protocol: netlink protocol
- * @groups: the group identifier
- *
- * Send the given message to the netlink layer and receive response.
- * Returns 0 on success, -1 on error. In case of error, no response
- * buffer will be returned.
- */
-int virNetlinkCommand(struct nl_msg *nl_msg,
-  struct nlmsghdr **resp, unsigned int *respbuflen,
-  uint32_t src_pid, uint32_t dst_pid,
-  unsigned int protocol, unsigned int groups)
+static virNetlinkHandle *
+virNetlinkDoCommand(struct nl_msg *nl_msg, uint32_t src_pid,
+struct sockaddr_nl nladdr,
+unsigned int protocol, unsigned int groups)
 {
-int ret = -1;
-struct sockaddr_nl nladdr = {
-.nl_family = AF_NETLINK,
-.nl_pid= dst_pid,
-.nl_groups = 0,
-};
 ssize_t nbytes;
-struct pollfd fds[1];
 int fd;
 int n;
-struct nlmsghdr *nlmsg = nlmsg_hdr(nl_msg);
 virNetlinkHandle *nlhandle = NULL;
-int len = 0;
+struct pollfd fds[1];
+struct nlmsghdr *nlmsg = nlmsg_hdr(nl_msg);
 
 if (protocol >= MAX_LINKS) {
 virReportSystemError(EINVAL,
  _("invalid protocol argument: %d"), protocol);
-goto cleanup;
+goto error;
 }
 
 if (!(nlhandle = virNetlinkCreateSocket(protocol)))
-goto cleanup;
+goto error;
 
 fd = nl_socket_get_fd(nlhandle);
 if (fd < 0) {
 virReportSystemError(errno,
  "%s", _("cannot get netlink socket fd"));
-goto cleanup;
+goto error;
 }
 
 if (groups && nl_socket_add_membership(nlhandle, groups) < 0) {
 virReportSystemError(errno,
  "%s", _("cannot add netlink membership"));
-goto cleanup;
+goto error;
 }
 
 nlmsg_set_dst(nl_msg, );
@@ -274,10 +251,11 @@ int virNetlinkCommand(struct nl_msg *nl_msg,
 if (nbytes < 0) {
 virReportSystemError(errno,
  "%s", _("cannot send to netlink socket"));
-goto cleanup;
+goto error;
 }
 
 memset(fds, 0, sizeof(fds));
+
 fds[0].fd = fd;
 fds[0].events = POLLIN;
 
@@ -289,9 +267,51 @@ int virNetlinkCommand(struct nl_msg *nl_msg,
 if (n == 0)
 virReportSystemError(ETIMEDOUT, "%s",
  _("no valid netlink response was received"));
-goto cleanup;
 }
 
+return nlhandle;
+
+ error:
+virNetlinkFree(nlhandle);
+return NULL;
+}
+
+/**
+ * virNetlinkCommand:
+ * @nlmsg: pointer to netlink message
+ * @respbuf: pointer to pointer where response buffer will be allocated
+ * @respbuflen: pointer to integer holding the size of the response buffer
+ *  on return of the function.
+ * @src_pid: the pid of the process to send a message
+ * @dst_pid: the pid of the process to talk to, i.e., pid = 0 for kernel
+ * @protocol: netlink protocol
+ * @groups: the group identifier
+ *
+ * Send the given message to the netlink layer and receive response.
+ * Returns 0 on success, -1 on error. In case of error, no response
+ * buffer will be returned.
+ */
+int virNetlinkCommand(struct nl_msg *nl_msg,
+  struct nlmsghdr **resp, unsigned int *respbuflen,
+  uint32_t src_pid, uint32_t dst_pid,
+  unsigned int protocol, unsigned int groups)
+{
+int ret = -1;
+struct sockaddr_nl nladdr = {
+.nl_family = AF_NETLINK,
+.nl_pid= dst_pid,
+.nl_groups = 0,
+};
+struct pollfd fds[1];
+virNetlinkHandle *nlhandle = NULL;
+int len = 0;
+
+memset(fds, 0, sizeof(fds));
+
+if (!(nlhandle = virNetlinkDoCommand(nl_msg, src_pid, nladdr,
+ protocol, groups)))
+goto cleanup;
+
 len = nl_recv(nlhandle, , (unsigned char **)resp, NULL);
 if (len == 0) {
 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-- 
2.11.0

--
libvir-list mailing list

[libvirt] [PATCH 2/4] util: add virNetlinkDumpCommand()

2017-03-03 Thread Cédric Bosdonnat
virNetlinkCommand() processes only one response message, while some
netlink commands like routes dumping need to process several ones.
Add virNetlinkDumpCommand() as a virNetlinkCommand() sister.
---
 src/libvirt_private.syms |  1 +
 src/util/virnetlink.c| 55 
 src/util/virnetlink.h|  9 
 3 files changed, 65 insertions(+)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index bce0487ab..71143851c 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2117,6 +2117,7 @@ virNetDevVPortProfileOpTypeToString;
 # util/virnetlink.h
 virNetlinkCommand;
 virNetlinkDelLink;
+virNetlinkDumpCommand;
 virNetlinkDumpLink;
 virNetlinkEventAddClient;
 virNetlinkEventRemoveClient;
diff --git a/src/util/virnetlink.c b/src/util/virnetlink.c
index 5fb49251c..4747ba5a4 100644
--- a/src/util/virnetlink.c
+++ b/src/util/virnetlink.c
@@ -335,6 +335,49 @@ int virNetlinkCommand(struct nl_msg *nl_msg,
 return ret;
 }
 
+int
+virNetlinkDumpCommand(struct nl_msg *nl_msg,
+  virNetlinkDumpCallback callback,
+  uint32_t src_pid, uint32_t dst_pid,
+  unsigned int protocol, unsigned int groups,
+  void *opaque)
+{
+int ret = -1;
+bool end = false;
+int len = 0;
+struct nlmsghdr *resp = NULL;
+struct nlmsghdr *msg = NULL;
+
+struct sockaddr_nl nladdr = {
+.nl_family = AF_NETLINK,
+.nl_pid= dst_pid,
+.nl_groups = 0,
+};
+virNetlinkHandle *nlhandle = NULL;
+
+if (!(nlhandle = virNetlinkDoCommand(nl_msg, src_pid, nladdr,
+ protocol, groups)))
+goto cleanup;
+
+while (!end) {
+len = nl_recv(nlhandle, , (unsigned char **), NULL);
+
+for (msg = resp; NLMSG_OK(msg, len); msg = NLMSG_NEXT(msg, len)) {
+if (msg->nlmsg_type == NLMSG_DONE)
+end = true;
+
+if (callback(msg, opaque) < 0)
+goto cleanup;
+}
+}
+
+ret = 0;
+
+ cleanup:
+virNetlinkFree(nlhandle);
+return ret;
+}
+
 
 /**
  * virNetlinkDumpLink:
@@ -1062,6 +1105,18 @@ int virNetlinkCommand(struct nl_msg *nl_msg 
ATTRIBUTE_UNUSED,
 return -1;
 }
 
+int
+virNetlinkDumpCommand(struct nl_msg *nl_msg ATTRIBUTE_UNUSED,
+  virNetlinkDumpCallback callback ATTRIBUTE_UNUSED,
+  uint32_t src_pid ATTRIBUTE_UNUSED,
+  uint32_t dst_pid ATTRIBUTE_UNUSED,
+  unsigned int protocol ATTRIBUTE_UNUSED,
+  unsigned int groups ATTRIBUTE_UNUSED,
+  void *opaque ATTRIBUTE_UNUSED)
+{
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _(unsupported));
+return -1;
+}
 
 int
 virNetlinkDumpLink(const char *ifname ATTRIBUTE_UNUSED,
diff --git a/src/util/virnetlink.h b/src/util/virnetlink.h
index 11e817c82..088b01343 100644
--- a/src/util/virnetlink.h
+++ b/src/util/virnetlink.h
@@ -52,6 +52,15 @@ int virNetlinkCommand(struct nl_msg *nl_msg,
   uint32_t src_pid, uint32_t dst_pid,
   unsigned int protocol, unsigned int groups);
 
+typedef int (*virNetlinkDumpCallback)(const struct nlmsghdr *resp,
+  void *data);
+
+int virNetlinkDumpCommand(struct nl_msg *nl_msg,
+  virNetlinkDumpCallback callback,
+  uint32_t src_pid, uint32_t dst_pid,
+  unsigned int protocol, unsigned int groups,
+  void *opaque);
+
 typedef int (*virNetlinkDelLinkFallback)(const char *ifname);
 
 int virNetlinkDelLink(const char *ifname, virNetlinkDelLinkFallback fallback);
-- 
2.11.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH 3/4] bridge_driver.c: more uses of SYSCTL_PATH

2017-03-03 Thread Cédric Bosdonnat
Replace a few occurences of /proc/sys by the corresponding macro
defined a few lines after: SYSCTL_PATH
---
 src/network/bridge_driver.c | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index c5ec2823d..3f6561055 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -85,6 +85,8 @@
  */
 #define VIR_NETWORK_DHCP_LEASE_FILE_SIZE_MAX (32 * 1024 * 1024)
 
+#define SYSCTL_PATH "/proc/sys"
+
 VIR_LOG_INIT("network.bridge_driver");
 
 static virNetworkDriverStatePtr network_driver;
@@ -2080,15 +2082,14 @@ networkEnableIPForwarding(bool enableIPv4, bool 
enableIPv6)
, sizeof(enabled));
 #else
 if (enableIPv4)
-ret = virFileWriteStr("/proc/sys/net/ipv4/ip_forward", "1\n", 0);
+ret = virFileWriteStr(SYSCTL_PATH "/net/ipv4/ip_forward", "1\n", 0);
 if (enableIPv6 && ret == 0)
-ret = virFileWriteStr("/proc/sys/net/ipv6/conf/all/forwarding", "1\n", 
0);
+ret = virFileWriteStr(SYSCTL_PATH "/net/ipv6/conf/all/forwarding", 
"1\n", 0);
+
 #endif
 return ret;
 }
 
-#define SYSCTL_PATH "/proc/sys"
-
 static int
 networkSetIPv6Sysctls(virNetworkObjPtr network)
 {
-- 
2.11.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH 0/4] Prevent loosing IPv6 routes due to forwarding

2017-03-03 Thread Cédric Bosdonnat
Hi all,

When enabling IPv6 forwarding on hosts getting Router Advertised routes,
the host looses the RA routes. To prevent this, check if the host has
such routes. In case there are some, check that the accept_ra is set
to 2 before bringing the network up.

Cédric Bosdonnat (4):
  util: extract the request sending code from virNetlinkCommand()
  util: add virNetlinkDumpCommand()
  bridge_driver.c: more uses of SYSCTL_PATH
  network: check accept_ra before enabling ipv6 forwarding

 src/libvirt_private.syms|   1 +
 src/network/bridge_driver.c | 187 +---
 src/util/virnetlink.c   | 145 +-
 src/util/virnetlink.h   |   9 +++
 4 files changed, 298 insertions(+), 44 deletions(-)

-- 
2.11.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH v2] libxl: fix usb inputs loop error

2017-01-11 Thread Cédric Bosdonnat
List indexes where mixed up in the code looping over the USB
input devices.
---
 * v2: Increment nusbdevice if LIBXL_HAVE_BUILDINFO_USBDEVICE_LIST is
   not defined.
 src/libxl/libxl_conf.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c
index ac83b51c7..a24f9e052 100644
--- a/src/libxl/libxl_conf.c
+++ b/src/libxl/libxl_conf.c
@@ -479,7 +479,8 @@ libxlMakeDomBuildInfo(virDomainDefPtr def,
 if (VIR_EXPAND_N(b_info->u.hvm.usbdevice_list, nusbdevice, 1) < 0)
 return -1;
 #else
-if (i > 1) {
+nusbdevice++;
+if (nusbdevice > 1) {
 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
 _("libxenlight supports only one input device"));
 return -1;
@@ -487,7 +488,7 @@ libxlMakeDomBuildInfo(virDomainDefPtr def,
 #endif
 
 #ifdef LIBXL_HAVE_BUILDINFO_USBDEVICE_LIST
-usbdevice = _info->u.hvm.usbdevice_list[i];
+usbdevice = _info->u.hvm.usbdevice_list[nusbdevice - 1];
 #else
 usbdevice = _info->u.hvm.usbdevice;
 #endif
-- 
2.11.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH] libxl: fix usb inputs loop error

2017-01-10 Thread Cédric Bosdonnat
List indexes where mixed up in the code looping over the USB
input devices.
---
 src/libxl/libxl_conf.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c
index ac83b51c7..1053e60a1 100644
--- a/src/libxl/libxl_conf.c
+++ b/src/libxl/libxl_conf.c
@@ -479,7 +479,7 @@ libxlMakeDomBuildInfo(virDomainDefPtr def,
 if (VIR_EXPAND_N(b_info->u.hvm.usbdevice_list, nusbdevice, 1) < 0)
 return -1;
 #else
-if (i > 1) {
+if (nusbdevice > 1) {
 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
 _("libxenlight supports only one input device"));
 return -1;
@@ -487,7 +487,7 @@ libxlMakeDomBuildInfo(virDomainDefPtr def,
 #endif
 
 #ifdef LIBXL_HAVE_BUILDINFO_USBDEVICE_LIST
-usbdevice = _info->u.hvm.usbdevice_list[i];
+usbdevice = _info->u.hvm.usbdevice_list[nusbdevice - 1];
 #else
 usbdevice = _info->u.hvm.usbdevice;
 #endif
-- 
2.11.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v4] libxl: define a per-domain logger.

2017-01-10 Thread Cédric Bosdonnat
bxlDriverConfig {
 unsigned int version;
 
 /* log stream for driver-wide libxl ctx */
-FILE *logger_file;
-xentoollog_logger *logger;
+libxlLoggerPtr logger;
 /* libxl ctx for driver wide ops; getVersion, getNodeInfo, ... */
 libxl_ctx *ctx;
 
diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c
index 5cde576ef..fbe7ee5ff 100644
--- a/src/libxl/libxl_domain.c
+++ b/src/libxl/libxl_domain.c
@@ -809,6 +809,8 @@ libxlDomainCleanup(libxlDriverPrivatePtr driver,
 VIR_FREE(xml);
 }
 
+libxlLoggerCloseFile(cfg->logger, vm->def->id);
+
 virDomainObjRemoveTransientDef(vm);
 virObjectUnref(cfg);
 }
@@ -1127,6 +1129,7 @@ libxlDomainStart(libxlDriverPrivatePtr driver,
 libxl_asyncprogress_how aop_console_how;
 libxl_domain_restore_params params;
 unsigned int hostdev_flags = VIR_HOSTDEV_SP_PCI;
+char *config_json = NULL;
 
 #ifdef LIBXL_HAVE_PVUSB
 hostdev_flags |= VIR_HOSTDEV_SP_USB;
@@ -1290,6 +1293,9 @@ libxlDomainStart(libxlDriverPrivatePtr driver,
  * be cleaned up if there are any subsequent failures.
  */
 vm->def->id = domid;
+config_json = libxl_domain_config_to_json(cfg->ctx, _config);
+
+libxlLoggerOpenFile(cfg->logger, domid, vm->def->name, config_json);
 
 /* Always enable domain death events */
 if (libxl_evenable_domain_death(cfg->ctx, vm->def->id, 0, >deathW))
@@ -1366,6 +1372,7 @@ libxlDomainStart(libxlDriverPrivatePtr driver,
 
  cleanup:
 libxl_domain_config_dispose(_config);
+VIR_FREE(config_json);
 VIR_FREE(dom_xml);
 VIR_FREE(managed_save_path);
 virDomainDefFree(def);
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
index 7e5d9b69e..325636c9a 100644
--- a/src/libxl/libxl_driver.c
+++ b/src/libxl/libxl_driver.c
@@ -406,6 +406,8 @@ libxlReconnectDomain(virDomainObjPtr vm,
 /* Update domid in case it changed (e.g. reboot) while we were gone? */
 vm->def->id = d_info.domid;
 
+libxlLoggerOpenFile(cfg->logger, vm->def->id, vm->def->name, NULL);
+
 /* Update hostdev state */
 if (virHostdevUpdateActiveDomainDevices(hostdev_mgr, LIBXL_DRIVER_NAME,
 vm->def, hostdev_flags) < 0)
diff --git a/src/libxl/libxl_logger.c b/src/libxl/libxl_logger.c
new file mode 100644
index 0..437dbb34b
--- /dev/null
+++ b/src/libxl/libxl_logger.c
@@ -0,0 +1,257 @@
+/*
+ * libxl_logger.c: libxl logger implementation
+ *
+ * Copyright (c) 2016 SUSE LINUX Products GmbH, Nuernberg, Germany.
+ *
+ * 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:
+ * Cédric Bosdonnat <cbosdon...@suse.com>
+ */
+#include 
+
+#include 
+#include 
+
+#include "internal.h"
+#include "libxl_logger.h"
+#include "util/viralloc.h"
+#include "util/virerror.h"
+#include "util/virfile.h"
+#include "util/virhash.h"
+#include "util/virstring.h"
+#include "util/virtime.h"
+
+#define VIR_FROM_THIS VIR_FROM_LIBXL
+
+VIR_LOG_INIT("libxl.libxl_logger");
+
+typedef struct xentoollog_logger_libvirt xentoollog_logger_libvirt;
+
+typedef struct {
+FILE *handle;
+char *path;
+} libxlLoggerFile;
+
+struct xentoollog_logger_libvirt {
+xentoollog_logger vtable;
+xentoollog_level minLevel;
+const char *logDir;
+
+/* map storing the opened fds: "domid" -> FILE* */
+virHashTablePtr files;
+FILE *defaultLogFile;
+};
+
+static void
+libxlLoggerFileFree(void *payload, const void *key ATTRIBUTE_UNUSED)
+{
+libxlLoggerFile *file = payload;
+if (file->handle) {
+VIR_FORCE_FCLOSE(file->handle);
+file->handle = NULL;
+}
+VIR_FREE(file->path);
+}
+
+static int
+libxlLoggerFileOpen(libxlLoggerFile *file) {
+int ret = 0;
+char ebuf[1024];
+
+if (!file->handle && !(file->handle = fopen(file->path, "a"))) {
+VIR_WARN("Failed to open log file %s: %s",
+ file->path, virStrerror(errno, ebuf, sizeof(ebuf)));
+ret = -1;
+}
+
+return ret;
+}
+
+ATTRIBUTE_FMT_PRINTF(5, 0) static void
+libvirt_vmessage(xentoollog_logger *logger_in,
+ xentoollog_level level,
+ int err

[libvirt] [PATCH v3] libxl: define a per-domain logger.

2017-01-09 Thread Cédric Bosdonnat
   /* log stream for driver-wide libxl ctx */
-FILE *logger_file;
-xentoollog_logger *logger;
+libxlLoggerPtr logger;
 /* libxl ctx for driver wide ops; getVersion, getNodeInfo, ... */
 libxl_ctx *ctx;
 
diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c
index 5cde576ef..fbe7ee5ff 100644
--- a/src/libxl/libxl_domain.c
+++ b/src/libxl/libxl_domain.c
@@ -809,6 +809,8 @@ libxlDomainCleanup(libxlDriverPrivatePtr driver,
 VIR_FREE(xml);
 }
 
+libxlLoggerCloseFile(cfg->logger, vm->def->id);
+
 virDomainObjRemoveTransientDef(vm);
 virObjectUnref(cfg);
 }
@@ -1127,6 +1129,7 @@ libxlDomainStart(libxlDriverPrivatePtr driver,
 libxl_asyncprogress_how aop_console_how;
 libxl_domain_restore_params params;
 unsigned int hostdev_flags = VIR_HOSTDEV_SP_PCI;
+char *config_json = NULL;
 
 #ifdef LIBXL_HAVE_PVUSB
 hostdev_flags |= VIR_HOSTDEV_SP_USB;
@@ -1290,6 +1293,9 @@ libxlDomainStart(libxlDriverPrivatePtr driver,
  * be cleaned up if there are any subsequent failures.
  */
 vm->def->id = domid;
+config_json = libxl_domain_config_to_json(cfg->ctx, _config);
+
+libxlLoggerOpenFile(cfg->logger, domid, vm->def->name, config_json);
 
 /* Always enable domain death events */
 if (libxl_evenable_domain_death(cfg->ctx, vm->def->id, 0, >deathW))
@@ -1366,6 +1372,7 @@ libxlDomainStart(libxlDriverPrivatePtr driver,
 
  cleanup:
 libxl_domain_config_dispose(_config);
+VIR_FREE(config_json);
 VIR_FREE(dom_xml);
 VIR_FREE(managed_save_path);
 virDomainDefFree(def);
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
index 7e5d9b69e..325636c9a 100644
--- a/src/libxl/libxl_driver.c
+++ b/src/libxl/libxl_driver.c
@@ -406,6 +406,8 @@ libxlReconnectDomain(virDomainObjPtr vm,
 /* Update domid in case it changed (e.g. reboot) while we were gone? */
 vm->def->id = d_info.domid;
 
+libxlLoggerOpenFile(cfg->logger, vm->def->id, vm->def->name, NULL);
+
 /* Update hostdev state */
 if (virHostdevUpdateActiveDomainDevices(hostdev_mgr, LIBXL_DRIVER_NAME,
 vm->def, hostdev_flags) < 0)
diff --git a/src/libxl/libxl_logger.c b/src/libxl/libxl_logger.c
new file mode 100644
index 0..9ca745a93
--- /dev/null
+++ b/src/libxl/libxl_logger.c
@@ -0,0 +1,231 @@
+/*
+ * libxl_logger.c: libxl logger implementation
+ *
+ * Copyright (c) 2016 SUSE LINUX Products GmbH, Nuernberg, Germany.
+ *
+ * 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:
+ * Cédric Bosdonnat <cbosdon...@suse.com>
+ */
+#include 
+
+#include 
+#include 
+
+#include "internal.h"
+#include "libxl_logger.h"
+#include "util/viralloc.h"
+#include "util/virerror.h"
+#include "util/virfile.h"
+#include "util/virhash.h"
+#include "util/virstring.h"
+#include "util/virtime.h"
+
+#define VIR_FROM_THIS VIR_FROM_LIBXL
+
+VIR_LOG_INIT("libxl.libxl_logger");
+
+typedef struct xentoollog_logger_libvirt xentoollog_logger_libvirt;
+
+struct xentoollog_logger_libvirt {
+xentoollog_logger vtable;
+xentoollog_level minLevel;
+const char *logDir;
+
+/* map storing the opened fds: "domid" -> FILE* */
+virHashTablePtr files;
+FILE *defaultLogFile;
+};
+
+static void
+libxlLoggerFileFree(void *payload, const void *key ATTRIBUTE_UNUSED)
+{
+FILE *file = payload;
+VIR_FORCE_FCLOSE(file);
+file = NULL;
+}
+
+ATTRIBUTE_FMT_PRINTF(5, 0) static void
+libvirt_vmessage(xentoollog_logger *logger_in,
+ xentoollog_level level,
+ int errnoval,
+ const char *context,
+ const char *format,
+ va_list args)
+{
+xentoollog_logger_libvirt *lg = (xentoollog_logger_libvirt *)logger_in;
+FILE *logFile = lg->defaultLogFile;
+char timestamp[VIR_TIME_STRING_BUFLEN];
+char *message = NULL;
+char *start, *end;
+char ebuf[1024];
+
+VIR_DEBUG("libvirt_vmessage: context='%s' format='%s'", context, format);
+
+if (level < lg->minLevel)
+return;
+
+if (virVasprintf(, format, args) < 0)
+return;
+
+/* Should we print to a d

[libvirt] [PATCH v2] libxl: define a per-domain logger.

2017-01-04 Thread Cédric Bosdonnat
LoggerPtr logger;
 /* libxl ctx for driver wide ops; getVersion, getNodeInfo, ... */
 libxl_ctx *ctx;
 
diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c
index 5cde576ef..3bc468f61 100644
--- a/src/libxl/libxl_domain.c
+++ b/src/libxl/libxl_domain.c
@@ -809,6 +809,8 @@ libxlDomainCleanup(libxlDriverPrivatePtr driver,
 VIR_FREE(xml);
 }
 
+libxlLoggerCloseFile(cfg->logger, vm->def->id);
+
 virDomainObjRemoveTransientDef(vm);
 virObjectUnref(cfg);
 }
@@ -1291,6 +1293,8 @@ libxlDomainStart(libxlDriverPrivatePtr driver,
  */
 vm->def->id = domid;
 
+libxlLoggerOpenFile(cfg->logger, domid, vm->def->name);
+
 /* Always enable domain death events */
 if (libxl_evenable_domain_death(cfg->ctx, vm->def->id, 0, >deathW))
 goto destroy_dom;
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
index 7e5d9b69e..6a4ecddef 100644
--- a/src/libxl/libxl_driver.c
+++ b/src/libxl/libxl_driver.c
@@ -406,6 +406,8 @@ libxlReconnectDomain(virDomainObjPtr vm,
 /* Update domid in case it changed (e.g. reboot) while we were gone? */
 vm->def->id = d_info.domid;
 
+libxlLoggerOpenFile(cfg->logger, vm->def->id, vm->def->name);
+
 /* Update hostdev state */
 if (virHostdevUpdateActiveDomainDevices(hostdev_mgr, LIBXL_DRIVER_NAME,
 vm->def, hostdev_flags) < 0)
diff --git a/src/libxl/libxl_logger.c b/src/libxl/libxl_logger.c
new file mode 100644
index 0..d8ccdd852
--- /dev/null
+++ b/src/libxl/libxl_logger.c
@@ -0,0 +1,223 @@
+/*
+ * libxl_logger.c: libxl logger implementation
+ *
+ * Copyright (c) 2016 SUSE LINUX Products GmbH, Nuernberg, Germany.
+ *
+ * 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:
+ * Cédric Bosdonnat <cbosdon...@suse.com>
+ */
+#include 
+
+#include 
+#include 
+
+#include "internal.h"
+#include "libxl_logger.h"
+#include "util/viralloc.h"
+#include "util/virerror.h"
+#include "util/virfile.h"
+#include "util/virhash.h"
+#include "util/virstring.h"
+#include "util/virtime.h"
+
+#define VIR_FROM_THIS VIR_FROM_LIBXL
+
+VIR_LOG_INIT("libxl.libxl_logger");
+
+typedef struct xentoollog_logger_libvirt xentoollog_logger_libvirt;
+
+struct xentoollog_logger_libvirt {
+xentoollog_logger vtable;
+xentoollog_level minLevel;
+const char *logDir;
+
+/* map storing the opened fds: "domid" -> FILE* */
+virHashTablePtr files;
+FILE *defaultLogFile;
+};
+
+static void
+libxlLoggerFileFree(void *payload, const void *key ATTRIBUTE_UNUSED)
+{
+FILE *file = payload;
+VIR_FORCE_FCLOSE(file);
+file = NULL;
+}
+
+ATTRIBUTE_FMT_PRINTF(5, 0) static void
+libvirt_vmessage(xentoollog_logger *logger_in,
+ xentoollog_level level,
+ int errnoval,
+ const char *context,
+ const char *format,
+ va_list args)
+{
+xentoollog_logger_libvirt *lg = (xentoollog_logger_libvirt *)logger_in;
+FILE *logFile = lg->defaultLogFile;
+char timestamp[VIR_TIME_STRING_BUFLEN];
+char *message = NULL;
+char *start, *end;
+char ebuf[1024];
+
+VIR_DEBUG("libvirt_vmessage: context='%s' format='%s'", context, format);
+
+if (level < lg->minLevel)
+return;
+
+if (virVasprintf(, format, args) < 0)
+return;
+
+/* Should we print to a domain-specific log file? */
+if ((start = strstr(message, ": Domain ")) &&
+(end = strstr(start + 9, ":"))) {
+FILE *domainLogFile;
+
+VIR_DEBUG("Found domain log message");
+
+start = start + 9;
+*end = '\0';
+
+domainLogFile = virHashLookup(lg->files, start);
+if (domainLogFile)
+logFile = domainLogFile;
+
+*end = ':';
+}
+
+/* Do the actual print to the log file */
+if (virTimeStringNowRaw(timestamp) < 0)
+timestamp[0] = '\0';
+
+fprintf(logFile, "%s: ", timestamp);
+if (context)
+fprintf(logFile, "%s: ", context);
+
+fprintf(logFile, "%s", message);
+
+if (errnoval >= 0)
+fpr

[libvirt] [PATCH] libxl: define a per-domain logger.

2016-12-20 Thread Cédric Bosdonnat
de ops; getVersion, getNodeInfo, ... */
 libxl_ctx *ctx;
 
diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c
index 5cde576ef..3bc468f61 100644
--- a/src/libxl/libxl_domain.c
+++ b/src/libxl/libxl_domain.c
@@ -809,6 +809,8 @@ libxlDomainCleanup(libxlDriverPrivatePtr driver,
 VIR_FREE(xml);
 }
 
+libxlLoggerCloseFile(cfg->logger, vm->def->id);
+
 virDomainObjRemoveTransientDef(vm);
 virObjectUnref(cfg);
 }
@@ -1291,6 +1293,8 @@ libxlDomainStart(libxlDriverPrivatePtr driver,
  */
 vm->def->id = domid;
 
+libxlLoggerOpenFile(cfg->logger, domid, vm->def->name);
+
 /* Always enable domain death events */
 if (libxl_evenable_domain_death(cfg->ctx, vm->def->id, 0, >deathW))
 goto destroy_dom;
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
index 7e5d9b69e..6a4ecddef 100644
--- a/src/libxl/libxl_driver.c
+++ b/src/libxl/libxl_driver.c
@@ -406,6 +406,8 @@ libxlReconnectDomain(virDomainObjPtr vm,
 /* Update domid in case it changed (e.g. reboot) while we were gone? */
 vm->def->id = d_info.domid;
 
+libxlLoggerOpenFile(cfg->logger, vm->def->id, vm->def->name);
+
 /* Update hostdev state */
 if (virHostdevUpdateActiveDomainDevices(hostdev_mgr, LIBXL_DRIVER_NAME,
 vm->def, hostdev_flags) < 0)
diff --git a/src/libxl/libxl_logger.c b/src/libxl/libxl_logger.c
new file mode 100644
index 0..31110d0fd
--- /dev/null
+++ b/src/libxl/libxl_logger.c
@@ -0,0 +1,217 @@
+/*
+ * libxl_logger.c: libxl logger implementation
+ *
+ * Copyright (c) 2016 SUSE LINUX Products GmbH, Nuernberg, Germany.
+ *
+ * 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:
+ * Cédric Bosdonnat <cbosdon...@suse.com>
+ */
+#include 
+
+#include 
+#include 
+
+#include "internal.h"
+#include "libxl_logger.h"
+#include "util/viralloc.h"
+#include "util/virerror.h"
+#include "util/virfile.h"
+#include "util/virhash.h"
+#include "util/virstring.h"
+#include "util/virtime.h"
+
+#define VIR_FROM_THIS VIR_FROM_LIBXL
+
+VIR_LOG_INIT("libxl.libxl_logger");
+
+typedef struct xentoollog_logger_libvirt xentoollog_logger_libvirt;
+
+struct xentoollog_logger_libvirt {
+xentoollog_logger vtable;
+xentoollog_level minLevel;
+const char *logDir;
+
+/* map storing the opened fds: "domid" -> FILE* */
+virHashTablePtr files;
+FILE *defaultLogFile;
+};
+
+static void
+libxlLoggerFileFree(void *payload, const void *key ATTRIBUTE_UNUSED)
+{
+FILE *file = payload;
+VIR_FORCE_FCLOSE(file);
+file = NULL;
+}
+
+ATTRIBUTE_FMT_PRINTF(5, 0) static void
+libvirt_vmessage(xentoollog_logger *logger_in,
+ xentoollog_level level,
+ int errnoval,
+ const char *context,
+ const char *format,
+ va_list args)
+{
+xentoollog_logger_libvirt *lg = (void*)logger_in;
+FILE *logFile = lg->defaultLogFile;
+char timestamp[VIR_TIME_STRING_BUFLEN];
+char *message = NULL;
+char *start, *end;
+char ebuf[1024];
+
+VIR_DEBUG("libvirt_vmessage: context='%s' format='%s'", context, format);
+
+if (level < lg->minLevel)
+return;
+
+if (virVasprintf(, format, args) < 0)
+return;
+
+/* Should we print to a domain-specific log file? */
+if ((start = strstr(message, ": Domain ")) &&
+(end = strstr(start + 9, ":"))) {
+FILE *domainLogFile;
+
+VIR_DEBUG("Found domain log message");
+
+start = start + 9;
+*end = '\0';
+
+domainLogFile = virHashLookup(lg->files, start);
+if (domainLogFile)
+logFile = domainLogFile;
+
+*end = ':';
+}
+
+/* Do the actual print to the log file */
+if (virTimeStringNowRaw(timestamp) < 0)
+timestamp[0] = '\0';
+
+fprintf(logFile, "%s: ", timestamp);
+if (context)
+fprintf(logFile, "%s: ", context);
+
+fprintf(logFile, "%s", message);
+
+if (errnoval >= 0)
+fprintf(logFile, ": %s", virStrerror(errnoval, ebuf, sizeof(ebu

[libvirt] [PATCH v2] xen: add QED format test

2016-12-19 Thread Cédric Bosdonnat
Follow up of commit 340bb6b7 to add unit tests for the QED format
support. Also add missing QED case in xenFormatXLDisk()
---
 v2:
   * Separated the QED test files into another set ti make this
 test conditionnal
   * Removed useless #ifdef
 src/xenconfig/xen_xl.c   |  3 +++
 tests/xlconfigdata/test-disk-qed.cfg | 25 
 tests/xlconfigdata/test-disk-qed.xml | 45 
 tests/xlconfigtest.c |  3 +++
 4 files changed, 76 insertions(+)
 create mode 100644 tests/xlconfigdata/test-disk-qed.cfg
 create mode 100644 tests/xlconfigdata/test-disk-qed.xml

diff --git a/src/xenconfig/xen_xl.c b/src/xenconfig/xen_xl.c
index 048ecd579..18d9fe369 100644
--- a/src/xenconfig/xen_xl.c
+++ b/src/xenconfig/xen_xl.c
@@ -1050,6 +1050,9 @@ xenFormatXLDisk(virConfValuePtr list, virDomainDiskDefPtr 
disk)
 case VIR_STORAGE_FILE_QCOW2:
 virBufferAddLit(, "qcow2");
 break;
+case VIR_STORAGE_FILE_QED:
+virBufferAddLit(, "qed");
+break;
   /* set default */
 default:
 virBufferAddLit(, "raw");
diff --git a/tests/xlconfigdata/test-disk-qed.cfg 
b/tests/xlconfigdata/test-disk-qed.cfg
new file mode 100644
index 0..2a2c4fa84
--- /dev/null
+++ b/tests/xlconfigdata/test-disk-qed.cfg
@@ -0,0 +1,25 @@
+name = "XenGuest2"
+uuid = "c7a5fdb2-cdaf-9455-926a-d65c16db1809"
+maxmem = 579
+memory = 394
+vcpus = 1
+pae = 1
+acpi = 1
+apic = 1
+viridian = 0
+rtc_timeoffset = 0
+localtime = 0
+on_poweroff = "destroy"
+on_reboot = "restart"
+on_crash = "restart"
+device_model = "/usr/lib/xen/bin/qemu-system-i386"
+sdl = 0
+vnc = 1
+vncunused = 1
+vnclisten = "127.0.0.1"
+vif = [ "mac=00:16:3e:66:92:9c,bridge=xenbr1,script=vif-bridge,model=e1000" ]
+parallel = "none"
+serial = "none"
+builder = "hvm"
+boot = "d"
+disk = [ "/var/lib/libvirt/images/XenGuest2,qed,hda,rw", ]
diff --git a/tests/xlconfigdata/test-disk-qed.xml 
b/tests/xlconfigdata/test-disk-qed.xml
new file mode 100644
index 0..230382dd5
--- /dev/null
+++ b/tests/xlconfigdata/test-disk-qed.xml
@@ -0,0 +1,45 @@
+
+  XenGuest2
+  c7a5fdb2-cdaf-9455-926a-d65c16db1809
+  592896
+  403456
+  1
+  
+hvm
+/usr/lib/xen/boot/hvmloader
+
+  
+  
+
+
+
+  
+  
+  destroy
+  restart
+  restart
+  
+/usr/lib/xen/bin/qemu-system-i386
+
+  
+  
+  
+  
+
+
+
+  
+  
+  
+  
+
+
+
+
+  
+
+
+  
+
+  
+
diff --git a/tests/xlconfigtest.c b/tests/xlconfigtest.c
index 31892da69..cab0c0d47 100644
--- a/tests/xlconfigtest.c
+++ b/tests/xlconfigtest.c
@@ -258,6 +258,9 @@ mymain(void)
 DO_TEST("new-disk");
 DO_TEST_FORMAT("disk-positional-parms-full", false);
 DO_TEST_FORMAT("disk-positional-parms-partial", false);
+#ifdef LIBXL_HAVE_QED
+DO_TEST_FORMAT("disk-qed", false);
+#endif
 DO_TEST("spice");
 DO_TEST("spice-features");
 DO_TEST("vif-rate");
-- 
2.11.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH] xen: add QED format test

2016-12-19 Thread Cédric Bosdonnat
Follow up of commit 340bb6b7 to add unit tests for the QED format
support. Also add missing QED case in xenFormatXLDisk()
---
 src/xenconfig/xen_xl.c | 5 +
 tests/xlconfigdata/test-disk-positional-parms-full.cfg | 2 +-
 tests/xlconfigdata/test-disk-positional-parms-full.xml | 6 ++
 3 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/src/xenconfig/xen_xl.c b/src/xenconfig/xen_xl.c
index 048ecd579..65d8ffc63 100644
--- a/src/xenconfig/xen_xl.c
+++ b/src/xenconfig/xen_xl.c
@@ -1050,6 +1050,11 @@ xenFormatXLDisk(virConfValuePtr list, 
virDomainDiskDefPtr disk)
 case VIR_STORAGE_FILE_QCOW2:
 virBufferAddLit(, "qcow2");
 break;
+#ifdef LIBXL_HAVE_QED
+case VIR_STORAGE_FILE_QED:
+virBufferAddLit(, "qed");
+break;
+#endif
   /* set default */
 default:
 virBufferAddLit(, "raw");
diff --git a/tests/xlconfigdata/test-disk-positional-parms-full.cfg 
b/tests/xlconfigdata/test-disk-positional-parms-full.cfg
index 217d4dccf..20421ffc1 100644
--- a/tests/xlconfigdata/test-disk-positional-parms-full.cfg
+++ b/tests/xlconfigdata/test-disk-positional-parms-full.cfg
@@ -22,4 +22,4 @@ parallel = "none"
 serial = "none"
 builder = "hvm"
 boot = "d"
-disk = [ "/dev/HostVG/XenGuest2,raw,hda,rw,backendtype=phy", 
"/var/lib/libvirt/images/XenGuest2-home,qcow2,hdb,rw", 
"/root/boot.iso,raw,hdc,ro,devtype=cdrom" ]
+disk = [ "/dev/HostVG/XenGuest2,raw,hda,rw,backendtype=phy", 
"/var/lib/libvirt/images/XenGuest2-home,qcow2,hdb,rw", 
"/root/boot.iso,raw,hdc,ro,devtype=cdrom", 
"/var/lib/libvirt/images/XenGuest2-qed,qed,hdd,rw", ]
diff --git a/tests/xlconfigdata/test-disk-positional-parms-full.xml 
b/tests/xlconfigdata/test-disk-positional-parms-full.xml
index 1bc5b436e..9c2fb41b7 100644
--- a/tests/xlconfigdata/test-disk-positional-parms-full.xml
+++ b/tests/xlconfigdata/test-disk-positional-parms-full.xml
@@ -39,6 +39,12 @@
   
   
 
+
+  
+  
+  
+  
+
 
 
   
-- 
2.11.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v2 0/2] libxl QED support

2016-12-14 Thread Cédric Bosdonnat
Hi all,

Just added on patch before the QED one to add default: cases
in xenParseXLDisk to avoid build failures when building on more
uptodate xen.

Cédric Bosdonnat (2):
  xenconfig: add default in xenParseXLDisk()'s switches
  libxl: add QED disk format support

 src/libxl/libxl_conf.c | 11 +++
 src/xenconfig/xen_xl.c | 15 +++
 2 files changed, 26 insertions(+)

-- 
2.11.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH v2 2/2] libxl: add QED disk format support

2016-12-14 Thread Cédric Bosdonnat
If libxl has QED disk format support, then pass the feature
over to the user.
---
 src/libxl/libxl_conf.c | 11 +++
 src/xenconfig/xen_xl.c |  6 ++
 2 files changed, 17 insertions(+)

diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c
index 288712f65..02945ae1a 100644
--- a/src/libxl/libxl_conf.c
+++ b/src/libxl/libxl_conf.c
@@ -745,6 +745,12 @@ libxlMakeDisk(virDomainDiskDefPtr l_disk, 
libxl_device_disk *x_disk)
 x_disk->format = LIBXL_DISK_FORMAT_RAW;
 x_disk->backend = LIBXL_DISK_BACKEND_TAP;
 break;
+#ifdef LIBXL_HAVE_QED
+case VIR_STORAGE_FILE_QED:
+x_disk->format = LIBXL_DISK_FORMAT_QED;
+x_disk->backend = LIBXL_DISK_BACKEND_QDISK;
+break;
+#endif
 default:
 virReportError(VIR_ERR_INTERNAL_ERROR,
_("libxenlight does not support disk format %s "
@@ -762,6 +768,11 @@ libxlMakeDisk(virDomainDiskDefPtr l_disk, 
libxl_device_disk *x_disk)
 case VIR_STORAGE_FILE_QCOW2:
 x_disk->format = LIBXL_DISK_FORMAT_QCOW2;
 break;
+#ifdef LIBXL_HAVE_QED
+case VIR_STORAGE_FILE_QED:
+x_disk->format = LIBXL_DISK_FORMAT_QED;
+break;
+#endif
 case VIR_STORAGE_FILE_VHD:
 x_disk->format = LIBXL_DISK_FORMAT_VHD;
 break;
diff --git a/src/xenconfig/xen_xl.c b/src/xenconfig/xen_xl.c
index f197267bb..edaa8764d 100644
--- a/src/xenconfig/xen_xl.c
+++ b/src/xenconfig/xen_xl.c
@@ -394,6 +394,12 @@ xenParseXLDisk(virConfPtr conf, virDomainDefPtr def)
 case LIBXL_DISK_FORMAT_EMPTY:
 break;
 
+#ifdef LIBXL_HAVE_QED
+case LIBXL_DISK_FORMAT_QED:
+disk->src->format = VIR_STORAGE_FILE_QED;
+break;
+#endif
+
 default:
 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("disk image format not supported: %s"),
-- 
2.11.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v2 1/2] xenconfig: add default in xenParseXLDisk()'s switches

2016-12-14 Thread Cédric Bosdonnat
Without a default: case in the switches in xenParseXLDisk(), build
would fail with every new disk backend or image format added in libxl,
as this is the case in this error:

http://logs.test-lab.xenproject.org/osstest/logs/103325/build-amd64-libvirt/5.ts-libvirt-build.log
---
 src/xenconfig/xen_xl.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/src/xenconfig/xen_xl.c b/src/xenconfig/xen_xl.c
index bcdd35527..f197267bb 100644
--- a/src/xenconfig/xen_xl.c
+++ b/src/xenconfig/xen_xl.c
@@ -393,6 +393,11 @@ xenParseXLDisk(virConfPtr conf, virDomainDefPtr def)
 
 case LIBXL_DISK_FORMAT_EMPTY:
 break;
+
+default:
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+   _("disk image format not supported: %s"),
+   
libxl_disk_format_to_string(libxldisk->format));
 }
 
 switch (libxldisk->backend) {
@@ -415,6 +420,10 @@ xenParseXLDisk(virConfPtr conf, virDomainDefPtr def)
 goto fail;
 virDomainDiskSetType(disk, VIR_STORAGE_TYPE_BLOCK);
 break;
+default:
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+   _("disk backend not supported: %s"),
+   
libxl_disk_backend_to_string(libxldisk->backend));
 }
 }
 
-- 
2.11.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH] libxl: add QED disk format support

2016-12-14 Thread Cédric Bosdonnat
If libxl has QED disk format support, then pass the feature
over to the user.
---
 src/libxl/libxl_conf.c | 11 +++
 src/xenconfig/xen_xl.c |  6 ++
 2 files changed, 17 insertions(+)

diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c
index 288712f65..02945ae1a 100644
--- a/src/libxl/libxl_conf.c
+++ b/src/libxl/libxl_conf.c
@@ -745,6 +745,12 @@ libxlMakeDisk(virDomainDiskDefPtr l_disk, 
libxl_device_disk *x_disk)
 x_disk->format = LIBXL_DISK_FORMAT_RAW;
 x_disk->backend = LIBXL_DISK_BACKEND_TAP;
 break;
+#ifdef LIBXL_HAVE_QED
+case VIR_STORAGE_FILE_QED:
+x_disk->format = LIBXL_DISK_FORMAT_QED;
+x_disk->backend = LIBXL_DISK_BACKEND_QDISK;
+break;
+#endif
 default:
 virReportError(VIR_ERR_INTERNAL_ERROR,
_("libxenlight does not support disk format %s "
@@ -762,6 +768,11 @@ libxlMakeDisk(virDomainDiskDefPtr l_disk, 
libxl_device_disk *x_disk)
 case VIR_STORAGE_FILE_QCOW2:
 x_disk->format = LIBXL_DISK_FORMAT_QCOW2;
 break;
+#ifdef LIBXL_HAVE_QED
+case VIR_STORAGE_FILE_QED:
+x_disk->format = LIBXL_DISK_FORMAT_QED;
+break;
+#endif
 case VIR_STORAGE_FILE_VHD:
 x_disk->format = LIBXL_DISK_FORMAT_VHD;
 break;
diff --git a/src/xenconfig/xen_xl.c b/src/xenconfig/xen_xl.c
index bcdd35527..98436982a 100644
--- a/src/xenconfig/xen_xl.c
+++ b/src/xenconfig/xen_xl.c
@@ -393,6 +393,12 @@ xenParseXLDisk(virConfPtr conf, virDomainDefPtr def)
 
 case LIBXL_DISK_FORMAT_EMPTY:
 break;
+
+#ifdef LIBXL_HAVE_QED
+case LIBXL_DISK_FORMAT_QED:
+disk->src->format = VIR_STORAGE_FILE_QED;
+break;
+#endif
 }
 
 switch (libxldisk->backend) {
-- 
2.11.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v2] lxc: monitor now holds a reference to the domain

2016-12-08 Thread Cédric Bosdonnat
If the monitor doesn't hold a reference to the domain object
the object may be destroyed before the monitor actually stops.
---
 v2: Moved vm ref upper, removed vm unref in error case.

 src/lxc/lxc_monitor.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/lxc/lxc_monitor.c b/src/lxc/lxc_monitor.c
index d828d528a..9cab6c203 100644
--- a/src/lxc/lxc_monitor.c
+++ b/src/lxc/lxc_monitor.c
@@ -175,7 +175,7 @@ virLXCMonitorPtr virLXCMonitorNew(virDomainObjPtr vm,
mon->program) < 0)
 goto error;
 
-mon->vm = vm;
+mon->vm = virObjectRef(vm);
 memcpy(>cb, cb, sizeof(mon->cb));
 
 virObjectRef(mon);
@@ -201,6 +201,7 @@ static void virLXCMonitorDispose(void *opaque)
 if (mon->cb.destroy)
 (mon->cb.destroy)(mon, mon->vm);
 virObjectUnref(mon->program);
+virObjectUnref(mon->vm);
 }
 
 
-- 
2.11.0

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH] lxc: monitor now holds a reference to the domain

2016-12-06 Thread Cédric Bosdonnat
If the monitor doesn't hold a reference to the domain object
the object may be destroyed before the monitor actually stops.
---
 src/lxc/lxc_monitor.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/lxc/lxc_monitor.c b/src/lxc/lxc_monitor.c
index d828d52..de63f9e 100644
--- a/src/lxc/lxc_monitor.c
+++ b/src/lxc/lxc_monitor.c
@@ -179,6 +179,7 @@ virLXCMonitorPtr virLXCMonitorNew(virDomainObjPtr vm,
 memcpy(>cb, cb, sizeof(mon->cb));
 
 virObjectRef(mon);
+virObjectRef(vm);
 virNetClientSetCloseCallback(mon->client, virLXCMonitorEOFNotify, mon,
  virLXCMonitorCloseFreeCallback);
 
@@ -188,6 +189,7 @@ virLXCMonitorPtr virLXCMonitorNew(virDomainObjPtr vm,
 
  error:
 virObjectUnref(mon);
+virObjectUnref(vm);
 mon = NULL;
 goto cleanup;
 }
@@ -201,6 +203,7 @@ static void virLXCMonitorDispose(void *opaque)
 if (mon->cb.destroy)
 (mon->cb.destroy)(mon, mon->vm);
 virObjectUnref(mon->program);
+virObjectUnref(mon->vm);
 }
 
 
-- 
2.10.2

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH] xl: don't output (null) target in domxml-to-native

2016-10-19 Thread Cédric Bosdonnat
When converting a domain xml containing a CDROM device without
any attached source, don't add a target=(null) to the libxl config
disk definition: xen doesn't like it at all and would fail to start
the domain.
---
 src/xenconfig/xen_xl.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/xenconfig/xen_xl.c b/src/xenconfig/xen_xl.c
index a06983e..db8cbf1 100644
--- a/src/xenconfig/xen_xl.c
+++ b/src/xenconfig/xen_xl.c
@@ -1068,7 +1068,7 @@ xenFormatXLDisk(virConfValuePtr list, virDomainDiskDefPtr 
disk)
 
 /* devtype */
 if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM)
-virBufferAddLit(, "devtype=cdrom,");
+virBufferAddLit(, "devtype=cdrom");
 
 /*
  * target
@@ -1081,7 +1081,9 @@ xenFormatXLDisk(virConfValuePtr list, virDomainDiskDefPtr 
disk)
 if (xenFormatXLDiskSrc(disk->src, ) < 0)
 goto cleanup;
 
-virBufferAsprintf(, "target=%s", target);
+if (target) {
+virBufferAsprintf(, ",target=%s", target);
+}
 
 if (virBufferCheckError() < 0)
 goto cleanup;
-- 
2.10.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH] libxl: increase usbdevice list only when finding such an input device

2016-09-23 Thread Cédric Bosdonnat
If passing an empty usbdevice_list to libxl, qemu will always get an
-usb parameter for HVM guests with only non-USB input devices. This
causes qemu to crash when passing pvusb device on HVM guests.

The solution is to allocate the list only when an item to put in it
is found.
---
 src/libxl/libxl_conf.c | 58 --
 1 file changed, 33 insertions(+), 25 deletions(-)

diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c
index 306e441..f85f005 100644
--- a/src/libxl/libxl_conf.c
+++ b/src/libxl/libxl_conf.c
@@ -298,6 +298,7 @@ libxlMakeDomBuildInfo(virDomainDefPtr def,
 libxl_domain_build_info *b_info = _config->b_info;
 int hvm = def->os.type == VIR_DOMAIN_OSTYPE_HVM;
 size_t i;
+size_t nusbdevice = 0;
 
 libxl_domain_build_info_init(b_info);
 
@@ -469,47 +470,54 @@ libxlMakeDomBuildInfo(virDomainDefPtr def,
 libxl_defbool_set(_info->u.hvm.vnc.enable, 0);
 libxl_defbool_set(_info->u.hvm.sdl.enable, 0);
 
-if (def->ninputs) {
+for (i = 0; i < def->ninputs; i++) {
+char **usbdevice;
+
+if (def->inputs[i]->bus != VIR_DOMAIN_INPUT_BUS_USB)
+continue;
+
 #ifdef LIBXL_HAVE_BUILDINFO_USBDEVICE_LIST
-if (VIR_ALLOC_N(b_info->u.hvm.usbdevice_list, def->ninputs+1) < 0)
+if (VIR_EXPAND_N(b_info->u.hvm.usbdevice_list, nusbdevice, 1) < 0)
 return -1;
 #else
-if (def->ninputs > 1) {
+if (i > 1) {
 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
 _("libxenlight supports only one input device"));
 return -1;
 }
 #endif
-for (i = 0; i < def->ninputs; i++) {
-char **usbdevice;
-
-if (def->inputs[i]->bus != VIR_DOMAIN_INPUT_BUS_USB)
-continue;
 
 #ifdef LIBXL_HAVE_BUILDINFO_USBDEVICE_LIST
-usbdevice = _info->u.hvm.usbdevice_list[i];
+usbdevice = _info->u.hvm.usbdevice_list[i];
 #else
-usbdevice = _info->u.hvm.usbdevice;
+usbdevice = _info->u.hvm.usbdevice;
 #endif
-switch (def->inputs[i]->type) {
-case VIR_DOMAIN_INPUT_TYPE_MOUSE:
-VIR_FREE(*usbdevice);
-if (VIR_STRDUP(*usbdevice, "mouse") < 0)
-return -1;
-break;
-case VIR_DOMAIN_INPUT_TYPE_TABLET:
-VIR_FREE(*usbdevice);
-if (VIR_STRDUP(*usbdevice, "tablet") < 0)
-return -1;
-break;
-default:
-virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-_("Unknown input device type"));
+switch (def->inputs[i]->type) {
+case VIR_DOMAIN_INPUT_TYPE_MOUSE:
+VIR_FREE(*usbdevice);
+if (VIR_STRDUP(*usbdevice, "mouse") < 0)
 return -1;
-}
+break;
+case VIR_DOMAIN_INPUT_TYPE_TABLET:
+VIR_FREE(*usbdevice);
+if (VIR_STRDUP(*usbdevice, "tablet") < 0)
+return -1;
+break;
+default:
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+_("Unknown input device type"));
+return -1;
 }
 }
 
+#ifdef LIBXL_HAVE_BUILDINFO_USBDEVICE_LIST
+if (nusbdevice > 0 &&
+VIR_EXPAND_N(b_info->u.hvm.usbdevice_list, nusbdevice, 1) < 0) {
+VIR_DISPOSE_N(b_info->u.hvm.usbdevice_list, nusbdevice);
+return -1;
+}
+#endif
+
 /* Allow libxl to calculate shadow memory requirements */
 b_info->shadow_memkb =
 libxl_get_required_shadow_memory(b_info->max_memkb,
-- 
2.9.3

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH] apparmor: move qemu-bridge-helper to libvirtd profile

2016-08-05 Thread Cédric Bosdonnat
qemu-bridge-helper is only called from libvirtd, it has to be moved
from the qemu domain abstraction to the usr.sbin.libvirtd profile.
---
 examples/apparmor/libvirt-qemu  | 19 ---
 examples/apparmor/usr.sbin.libvirtd | 18 ++
 2 files changed, 18 insertions(+), 19 deletions(-)

diff --git a/examples/apparmor/libvirt-qemu b/examples/apparmor/libvirt-qemu
index efb4873..11381d4 100644
--- a/examples/apparmor/libvirt-qemu
+++ b/examples/apparmor/libvirt-qemu
@@ -148,22 +148,3 @@
   /etc/udev/udev.conf r,
   /sys/bus/ r,
   /sys/class/ r,
-
-  /usr/{lib,libexec}/qemu-bridge-helper Cx -> qemu_bridge_helper,
-  # child profile for bridge helper process
-  profile qemu_bridge_helper {
-   #include 
-
-   capability setuid,
-   capability setgid,
-   capability setpcap,
-   capability net_admin,
-
-   network inet stream,
-
-   /dev/net/tun rw,
-   /etc/qemu/** r,
-   owner @{PROC}/*/status r,
-
-   /usr/{lib,libexec}/qemu-bridge-helper rmix,
-  }
diff --git a/examples/apparmor/usr.sbin.libvirtd 
b/examples/apparmor/usr.sbin.libvirtd
index 23f70f5..48651b2 100644
--- a/examples/apparmor/usr.sbin.libvirtd
+++ b/examples/apparmor/usr.sbin.libvirtd
@@ -67,4 +67,22 @@
   # allow changing to our UUID-based named profiles
   change_profile -> 
@{LIBVIRT}-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*,
 
+  /usr/{lib,libexec}/qemu-bridge-helper Cx -> qemu_bridge_helper,
+  # child profile for bridge helper process
+  profile qemu_bridge_helper {
+   #include 
+
+   capability setuid,
+   capability setgid,
+   capability setpcap,
+   capability net_admin,
+
+   network inet stream,
+
+   /dev/net/tun rw,
+   /etc/qemu/** r,
+   owner @{PROC}/*/status r,
+
+   /usr/{lib,libexec}/qemu-bridge-helper rmix,
+  }
 }
-- 
2.6.6

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH 2/2] libxl: allow vendor/product addressing for USB hostdevs

2016-08-05 Thread Cédric Bosdonnat
libxl only has API to address the host USB devices by bus/device.
Find the bus/device if the user only provided the vendor/product
of the USB device.
---
 src/libxl/libxl_conf.c | 25 +
 1 file changed, 17 insertions(+), 8 deletions(-)

diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c
index 5202ca1..4b758f1 100644
--- a/src/libxl/libxl_conf.c
+++ b/src/libxl/libxl_conf.c
@@ -1559,23 +1559,32 @@ int
 libxlMakeUSB(virDomainHostdevDefPtr hostdev, libxl_device_usbdev *usbdev)
 {
 virDomainHostdevSubsysUSBPtr usbsrc = >source.subsys.u.usb;
+virUSBDevicePtr usb;
+int ret = -1;
 
 if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
-return -1;
+goto cleanup;
 if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)
-return -1;
+goto cleanup;
 
-if (usbsrc->bus <= 0 || usbsrc->device <= 0) {
-virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-   _("libxenlight supports only USB device "
- "specified by busnum:devnum"));
-return -1;
+if ((usbsrc->bus <= 0 || usbsrc->device <= 0) &&
+(virHostdevFindUSBDevice(hostdev, true, ) < 0)) {
+virReportError(VIR_ERR_OPERATION_FAILED,
+   _("failed to find USB device busnum:devnum "
+ "for %x:%x"),
+   usbsrc->vendor, usbsrc->product);
+goto cleanup;
 }
 
 usbdev->u.hostdev.hostbus = usbsrc->bus;
 usbdev->u.hostdev.hostaddr = usbsrc->device;
 
-return 0;
+ret = 0;
+
+ cleanup:
+virUSBDeviceFree(usb);
+
+return ret;
 }
 
 static int
-- 
2.6.6

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH 0/2] libxl USB vendor/product support

2016-08-05 Thread Cédric Bosdonnat
Hi all,

Libxl API only allows providing bus/dev for USB hostdevs. If libvirt 
libxl driver users provide vendor/product they get an error, instead
search for the corresponding bus/dev pair and feed them to libxl.


Cédric Bosdonnat (2):
  Add virHostdevFindUSBDevice to private symbols
  libxl: allow vendor/product addressing for USB hostdevs

 src/libvirt_private.syms |  1 +
 src/libxl/libxl_conf.c   | 25 +
 src/util/virhostdev.c|  2 +-
 src/util/virhostdev.h|  6 ++
 4 files changed, 25 insertions(+), 9 deletions(-)

-- 
2.6.6

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH 1/2] Add virHostdevFindUSBDevice to private symbols

2016-08-05 Thread Cédric Bosdonnat
Finding an USB device from the vendor/device values will be needed
by libxl driver to convert from vendor/device to bus/dev addresses.
---
 src/libvirt_private.syms | 1 +
 src/util/virhostdev.c| 2 +-
 src/util/virhostdev.h| 6 ++
 3 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 419c33d..de8b1fe 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1646,6 +1646,7 @@ virHookPresent;
 
 
 # util/virhostdev.h
+virHostdevFindUSBDevice;
 virHostdevManagerGetDefault;
 virHostdevPCINodeDeviceDetach;
 virHostdevPCINodeDeviceReAttach;
diff --git a/src/util/virhostdev.c b/src/util/virhostdev.c
index 9b5ca6f..9c2262e 100644
--- a/src/util/virhostdev.c
+++ b/src/util/virhostdev.c
@@ -1178,7 +1178,7 @@ virHostdevMarkUSBDevices(virHostdevManagerPtr mgr,
 }
 
 
-static int
+int
 virHostdevFindUSBDevice(virDomainHostdevDefPtr hostdev,
 bool mandatory,
 virUSBDevicePtr *usb)
diff --git a/src/util/virhostdev.h b/src/util/virhostdev.h
index c451981..9bb582b 100644
--- a/src/util/virhostdev.h
+++ b/src/util/virhostdev.h
@@ -66,6 +66,12 @@ virHostdevPreparePCIDevices(virHostdevManagerPtr hostdev_mgr,
 unsigned int flags)
 ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
 ATTRIBUTE_NONNULL(4);
+
+int
+virHostdevFindUSBDevice(virDomainHostdevDefPtr hostdev,
+bool mandatory,
+virUSBDevicePtr *usb)
+ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
 int
 virHostdevPrepareUSBDevices(virHostdevManagerPtr hostdev_mgr,
 const char *drv_name,
-- 
2.6.6

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v2 3/3] libxl: add hooks support

2016-07-28 Thread Cédric Bosdonnat
Introduce libxl hook and use it for start, prepare, started,
stop, stopped, migrate events.
---
 docs/hooks.html.in  | 53 ++--
 src/libxl/libxl_domain.c| 74 +
 src/libxl/libxl_driver.c| 22 ++
 src/libxl/libxl_migration.c | 57 ++
 src/util/virhook.c  | 16 +-
 src/util/virhook.h  | 13 
 6 files changed, 232 insertions(+), 3 deletions(-)

diff --git a/docs/hooks.html.in b/docs/hooks.html.in
index d4f4ac3..11073cb 100644
--- a/docs/hooks.html.in
+++ b/docs/hooks.html.in
@@ -17,8 +17,10 @@
   (since 0.8.0)
   A QEMU guest is started or stopped
  (since 0.8.0)
- An LXC guest is started or stopped
+  An LXC guest is started or stopped
  (since 0.8.0)
+  A libxl-handled Xen guest is started or stopped
+ (since 2.1.0)
   A network is started or stopped or an interface is
   plugged/unplugged to/from the network
   (since 1.2.2)
@@ -41,7 +43,7 @@
 
 
 Script names
-At present, there are three hook scripts that can be called:
+At present, there are five hook scripts that can be called:
 
   /etc/libvirt/hooks/daemon
   Executed when the libvirt daemon is started, stopped, or reloads
@@ -50,6 +52,9 @@
   Executed when a QEMU guest is started, stopped, or 
migrated
   /etc/libvirt/hooks/lxc
   Executed when an LXC guest is started or stopped
+  /etc/libvirt/hooks/libxl
+  Executed when a libxl-handled Xen guest is started, stopped, or
+  migrated
   /etc/libvirt/hooks/network
   Executed when a network is started or stopped or an
   interface is plugged/unplugged to/from the network
@@ -235,6 +240,50 @@
   
 
 
+/etc/libvirt/hooks/libxl
+
+  Before a Xen guest is started using libxl driver, the libxl hook
+script is called in three locations; if any location fails, the guest
+is not started.  The first location, since
+2.1.0, is before libvirt performs any resource
+labeling, and the hook can allocate resources not managed by
+libvirt.  This is called as:
+/etc/libvirt/hooks/libxl guest_name prepare begin -
+The second location, available Since
+2.1.0, occurs after libvirt has finished labeling
+all resources, but has not yet started the guest, called as:
+/etc/libvirt/hooks/libxl guest_name start begin -
+The third location, 2.1.0,
+occurs after the domain has successfully started up:
+/etc/libvirt/hooks/libxl guest_name started begin -
+  
+  When a libxl-handled Xen guest is stopped, the libxl hook script
+is called in two locations, to match the startup.
+First, since 2.1.0, the hook is
+called before libvirt restores any labels:
+/etc/libvirt/hooks/libxl guest_name stopped end -
+Then, after libvirt has released all resources, the hook is
+called again, since 2.1.0, to allow
+any additional resource cleanup:
+/etc/libvirt/hooks/libxl guest_name release end -
+  Since 2.1.0, the libxl hook script
+is also called at the beginning of incoming migration. It is called
+as: /etc/libvirt/hooks/libxl guest_name migrate begin -
+with domain XML sent to standard input of the script. In this case,
+the script acts as a filter and is supposed to modify the domain
+XML and print it out on its standard output. Empty output is
+identical to copying the input XML without changing it. In case the
+script returns failure or the output XML is not valid, incoming
+migration will be canceled. This hook may be used, e.g., to change
+location of disk images for incoming domains.
+  Since 2.1.0, the libxl hook script
+is also called when the libvirtd daemon restarts and reconnects
+to previously running Xen domains. If the script fails, the
+existing Xen domains will be killed off. It is called as:
+/etc/libvirt/hooks/libxl guest_name reconnect begin -
+  
+
+
 /etc/libvirt/hooks/network
 
   Since 1.2.2, before a network is started,
diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c
index 886b40f..d99f903 100644
--- a/src/libxl/libxl_domain.c
+++ b/src/libxl/libxl_domain.c
@@ -32,6 +32,7 @@
 #include "viratomic.h"
 #include "virfile.h"
 #include "virerror.h"
+#include "virhook.h"
 #include "virlog.h"
 #include "virstring.h"
 #include "virtime.h"
@@ -737,6 +738,17 @@ libxlDomainCleanup(libxlDriverPrivatePtr driver,
 hostdev_flags |= VIR_HOSTDEV_SP_USB;
 #endif
 
+/* now that we know it's stopped call the hook if present */
+if (virHookPresent(VIR_HOOK_DRIVER_LIBXL)) {
+char *xml = virDomainDefFormat(vm->def, cfg->caps, 0);
+
+/* we can't stop the 

[libvirt] [PATCH v2 0/3] libxl hooks

2016-07-28 Thread Cédric Bosdonnat
Hey there!

Diffs to v1:
  * move the ret = 0 to the proper patch
  * fix typos as pointed by Joao
  * use ignore_value where needed

Cédric Bosdonnat (3):
  libxl: add a flag to mark guests as tainted by a hook
  libxl: fix segfault in libxlReconnectDomain
  libxl: add hooks support

 docs/hooks.html.in  | 53 ++--
 src/libxl/libxl_domain.c| 84 +
 src/libxl/libxl_domain.h|  2 ++
 src/libxl/libxl_driver.c| 52 +---
 src/libxl/libxl_migration.c | 57 ++
 src/util/virhook.c  | 16 -
 src/util/virhook.h  | 13 +++
 7 files changed, 262 insertions(+), 15 deletions(-)

-- 
2.6.6

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH v2 2/3] libxl: fix segfault in libxlReconnectDomain

2016-07-28 Thread Cédric Bosdonnat
In case of error, libxlReconnectDomain may call
virDomainObjListRemoveLocked. However it has no local reference on
the domain object, leading to segfault. Get a reference to the domain
object at the start of the function and release it at the end to avoid
problems.

This commit also factorizes code between the error and normal ends.
---
 src/libxl/libxl_driver.c | 30 ++
 1 file changed, 18 insertions(+), 12 deletions(-)

diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
index cb501cf..823bc1a 100644
--- a/src/libxl/libxl_driver.c
+++ b/src/libxl/libxl_driver.c
@@ -373,11 +373,13 @@ libxlReconnectDomain(virDomainObjPtr vm,
 uint8_t *data = NULL;
 virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
 unsigned int hostdev_flags = VIR_HOSTDEV_SP_PCI;
+int ret = -1;
 
 #ifdef LIBXL_HAVE_PVUSB
 hostdev_flags |= VIR_HOSTDEV_SP_USB;
 #endif
 
+virObjectRef(vm);
 virObjectLock(vm);
 
 libxl_dominfo_init(_info);
@@ -385,18 +387,18 @@ libxlReconnectDomain(virDomainObjPtr vm,
 /* Does domain still exist? */
 rc = libxl_domain_info(cfg->ctx, _info, vm->def->id);
 if (rc == ERROR_INVAL) {
-goto out;
+goto error;
 } else if (rc != 0) {
 VIR_DEBUG("libxl_domain_info failed (code %d), ignoring domain %d",
   rc, vm->def->id);
-goto out;
+goto error;
 }
 
 /* Is this a domain that was under libvirt control? */
 if (libxl_userdata_retrieve(cfg->ctx, vm->def->id,
 "libvirt-xml", , )) {
 VIR_DEBUG("libxl_userdata_retrieve failed, ignoring domain %d", 
vm->def->id);
-goto out;
+goto error;
 }
 
 /* Update domid in case it changed (e.g. reboot) while we were gone? */
@@ -405,7 +407,7 @@ libxlReconnectDomain(virDomainObjPtr vm,
 /* Update hostdev state */
 if (virHostdevUpdateActiveDomainDevices(hostdev_mgr, LIBXL_DRIVER_NAME,
 vm->def, hostdev_flags) < 0)
-goto out;
+goto error;
 
 if (virAtomicIntInc(>nactive) == 1 && driver->inhibitCallback)
 driver->inhibitCallback(true, driver->inhibitOpaque);
@@ -413,21 +415,25 @@ libxlReconnectDomain(virDomainObjPtr vm,
 /* Enable domain death events */
 libxl_evenable_domain_death(cfg->ctx, vm->def->id, 0, >deathW);
 
+ret = 0;
+
+ cleanup:
 libxl_dominfo_dispose(_info);
 virObjectUnlock(vm);
+virObjectUnref(vm);
 virObjectUnref(cfg);
-return 0;
+return ret;
 
- out:
-libxl_dominfo_dispose(_info);
+ error:
 libxlDomainCleanup(driver, vm);
-if (!vm->persistent)
+if (!vm->persistent) {
 virDomainObjListRemoveLocked(driver->domains, vm);
-else
-virObjectUnlock(vm);
-virObjectUnref(cfg);
 
-return -1;
+/* virDomainObjListRemoveLocked leaves the object unlocked,
+ * lock it again to factorize more code. */
+virObjectLock(vm);
+}
+goto cleanup;
 }
 
 static void
-- 
2.6.6

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v2 1/3] libxl: add a flag to mark guests as tainted by a hook

2016-07-28 Thread Cédric Bosdonnat
The migrate hook will affect the migrated guest definition. Allow
these domains be marked as tainted in the libxl driver.
---
 src/libxl/libxl_domain.c | 10 ++
 src/libxl/libxl_domain.h |  2 ++
 2 files changed, 12 insertions(+)

diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c
index 0e26b91..886b40f 100644
--- a/src/libxl/libxl_domain.c
+++ b/src/libxl/libxl_domain.c
@@ -1135,6 +1135,16 @@ libxlDomainStart(libxlDriverPrivatePtr driver,
vm->def, hostdev_flags) < 0)
 goto cleanup_dom;
 
+if (priv->hookRun) {
+char uuidstr[VIR_UUID_STRING_BUFLEN];
+virUUIDFormat(vm->def->uuid, uuidstr);
+
+VIR_WARN("Domain id='%d' name='%s' uuid='%s' is tainted: hook",
+ vm->def->id,
+ vm->def->name,
+ uuidstr);
+}
+
 /* Unlock virDomainObj while creating the domain */
 virObjectUnlock(vm);
 
diff --git a/src/libxl/libxl_domain.h b/src/libxl/libxl_domain.h
index af11a2c..3a3890b 100644
--- a/src/libxl/libxl_domain.h
+++ b/src/libxl/libxl_domain.h
@@ -69,6 +69,8 @@ struct _libxlDomainObjPrivate {
 char *lockState;
 
 struct libxlDomainJobObj job;
+
+bool hookRun;  /* true if there was a hook run over this domain */
 };
 
 
-- 
2.6.6

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH 3/3] libxl: add hooks support

2016-07-27 Thread Cédric Bosdonnat
Introduce libxl hook and use it for start, prepare, started,
stop, stopped, migrate events.
---
 docs/hooks.html.in  | 53 ++--
 src/libxl/libxl_domain.c| 75 +
 src/libxl/libxl_driver.c| 24 +++
 src/libxl/libxl_migration.c | 58 +++
 src/util/virhook.c  | 16 +-
 src/util/virhook.h  | 13 
 6 files changed, 236 insertions(+), 3 deletions(-)

diff --git a/docs/hooks.html.in b/docs/hooks.html.in
index d4f4ac3..11073cb 100644
--- a/docs/hooks.html.in
+++ b/docs/hooks.html.in
@@ -17,8 +17,10 @@
   (since 0.8.0)
   A QEMU guest is started or stopped
  (since 0.8.0)
- An LXC guest is started or stopped
+  An LXC guest is started or stopped
  (since 0.8.0)
+  A libxl-handled Xen guest is started or stopped
+ (since 2.1.0)
   A network is started or stopped or an interface is
   plugged/unplugged to/from the network
   (since 1.2.2)
@@ -41,7 +43,7 @@
 
 
 Script names
-At present, there are three hook scripts that can be called:
+At present, there are five hook scripts that can be called:
 
   /etc/libvirt/hooks/daemon
   Executed when the libvirt daemon is started, stopped, or reloads
@@ -50,6 +52,9 @@
   Executed when a QEMU guest is started, stopped, or 
migrated
   /etc/libvirt/hooks/lxc
   Executed when an LXC guest is started or stopped
+  /etc/libvirt/hooks/libxl
+  Executed when a libxl-handled Xen guest is started, stopped, or
+  migrated
   /etc/libvirt/hooks/network
   Executed when a network is started or stopped or an
   interface is plugged/unplugged to/from the network
@@ -235,6 +240,50 @@
   
 
 
+/etc/libvirt/hooks/libxl
+
+  Before a Xen guest is started using libxl driver, the libxl hook
+script is called in three locations; if any location fails, the guest
+is not started.  The first location, since
+2.1.0, is before libvirt performs any resource
+labeling, and the hook can allocate resources not managed by
+libvirt.  This is called as:
+/etc/libvirt/hooks/libxl guest_name prepare begin -
+The second location, available Since
+2.1.0, occurs after libvirt has finished labeling
+all resources, but has not yet started the guest, called as:
+/etc/libvirt/hooks/libxl guest_name start begin -
+The third location, 2.1.0,
+occurs after the domain has successfully started up:
+/etc/libvirt/hooks/libxl guest_name started begin -
+  
+  When a libxl-handled Xen guest is stopped, the libxl hook script
+is called in two locations, to match the startup.
+First, since 2.1.0, the hook is
+called before libvirt restores any labels:
+/etc/libvirt/hooks/libxl guest_name stopped end -
+Then, after libvirt has released all resources, the hook is
+called again, since 2.1.0, to allow
+any additional resource cleanup:
+/etc/libvirt/hooks/libxl guest_name release end -
+  Since 2.1.0, the libxl hook script
+is also called at the beginning of incoming migration. It is called
+as: /etc/libvirt/hooks/libxl guest_name migrate begin -
+with domain XML sent to standard input of the script. In this case,
+the script acts as a filter and is supposed to modify the domain
+XML and print it out on its standard output. Empty output is
+identical to copying the input XML without changing it. In case the
+script returns failure or the output XML is not valid, incoming
+migration will be canceled. This hook may be used, e.g., to change
+location of disk images for incoming domains.
+  Since 2.1.0, the libxl hook script
+is also called when the libvirtd daemon restarts and reconnects
+to previously running Xen domains. If the script fails, the
+existing Xen domains will be killed off. It is called as:
+/etc/libvirt/hooks/libxl guest_name reconnect begin -
+  
+
+
 /etc/libvirt/hooks/network
 
   Since 1.2.2, before a network is started,
diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c
index 886b40f..d04dc5e 100644
--- a/src/libxl/libxl_domain.c
+++ b/src/libxl/libxl_domain.c
@@ -32,6 +32,7 @@
 #include "viratomic.h"
 #include "virfile.h"
 #include "virerror.h"
+#include "virhook.h"
 #include "virlog.h"
 #include "virstring.h"
 #include "virtime.h"
@@ -737,6 +738,17 @@ libxlDomainCleanup(libxlDriverPrivatePtr driver,
 hostdev_flags |= VIR_HOSTDEV_SP_USB;
 #endif
 
+/* now that we know it's stopped call the hook if present */
+if (virHookPresent(VIR_HOOK_DRIVER_LIBXL)) {
+char *xml = virDomainDefFormat(vm->def, cfg->caps, 0);
+
+/* we can't stop the 

[libvirt] [PATCH 0/3] libxl hooks

2016-07-27 Thread Cédric Bosdonnat
Hi there!

Here is small patchset adding hooks support to the libxl driver.

Cédric Bosdonnat (3):
  libxl: add a flag to mark guests as tainted by a hook
  libxl: fix segfault in libxlReconnectDomain
  libxl: add hooks support

 docs/hooks.html.in  | 53 ++--
 src/libxl/libxl_domain.c| 85 +
 src/libxl/libxl_domain.h|  2 ++
 src/libxl/libxl_driver.c| 52 ---
 src/libxl/libxl_migration.c | 58 +++
 src/util/virhook.c  | 16 -
 src/util/virhook.h  | 13 +++
 7 files changed, 264 insertions(+), 15 deletions(-)

-- 
2.6.6

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH 1/3] libxl: add a flag to mark guests as tainted by a hook

2016-07-27 Thread Cédric Bosdonnat
The migrate hook will affect the migrated guest definition. Allow
these domains be marked as tainted in the libxl driver.
---
 src/libxl/libxl_domain.c | 10 ++
 src/libxl/libxl_domain.h |  2 ++
 2 files changed, 12 insertions(+)

diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c
index 0e26b91..886b40f 100644
--- a/src/libxl/libxl_domain.c
+++ b/src/libxl/libxl_domain.c
@@ -1135,6 +1135,16 @@ libxlDomainStart(libxlDriverPrivatePtr driver,
vm->def, hostdev_flags) < 0)
 goto cleanup_dom;
 
+if (priv->hookRun) {
+char uuidstr[VIR_UUID_STRING_BUFLEN];
+virUUIDFormat(vm->def->uuid, uuidstr);
+
+VIR_WARN("Domain id='%d' name='%s' uuid='%s' is tainted: hook",
+ vm->def->id,
+ vm->def->name,
+ uuidstr);
+}
+
 /* Unlock virDomainObj while creating the domain */
 virObjectUnlock(vm);
 
diff --git a/src/libxl/libxl_domain.h b/src/libxl/libxl_domain.h
index af11a2c..3a3890b 100644
--- a/src/libxl/libxl_domain.h
+++ b/src/libxl/libxl_domain.h
@@ -69,6 +69,8 @@ struct _libxlDomainObjPrivate {
 char *lockState;
 
 struct libxlDomainJobObj job;
+
+bool hookRun;  /* true if there was a hook run over this domain */
 };
 
 
-- 
2.6.6

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH 2/3] libxl: fix segfault in libxlReconnectDomain

2016-07-27 Thread Cédric Bosdonnat
In case of error, libxlReconnectDomain may call
virDomainObjListRemoveLocked. However it has no local reference on
the domain object, leading to segfault. Get a reference to the domain
object at the start of the function and release it at the end to avoid
problems.

This commit also factorizes code between the error and normal ends.
---
 src/libxl/libxl_driver.c | 28 
 1 file changed, 16 insertions(+), 12 deletions(-)

diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
index cb501cf..5008c00 100644
--- a/src/libxl/libxl_driver.c
+++ b/src/libxl/libxl_driver.c
@@ -373,11 +373,13 @@ libxlReconnectDomain(virDomainObjPtr vm,
 uint8_t *data = NULL;
 virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
 unsigned int hostdev_flags = VIR_HOSTDEV_SP_PCI;
+int ret = -1;
 
 #ifdef LIBXL_HAVE_PVUSB
 hostdev_flags |= VIR_HOSTDEV_SP_USB;
 #endif
 
+virObjectRef(vm);
 virObjectLock(vm);
 
 libxl_dominfo_init(_info);
@@ -385,18 +387,18 @@ libxlReconnectDomain(virDomainObjPtr vm,
 /* Does domain still exist? */
 rc = libxl_domain_info(cfg->ctx, _info, vm->def->id);
 if (rc == ERROR_INVAL) {
-goto out;
+goto error;
 } else if (rc != 0) {
 VIR_DEBUG("libxl_domain_info failed (code %d), ignoring domain %d",
   rc, vm->def->id);
-goto out;
+goto error;
 }
 
 /* Is this a domain that was under libvirt control? */
 if (libxl_userdata_retrieve(cfg->ctx, vm->def->id,
 "libvirt-xml", , )) {
 VIR_DEBUG("libxl_userdata_retrieve failed, ignoring domain %d", 
vm->def->id);
-goto out;
+goto error;
 }
 
 /* Update domid in case it changed (e.g. reboot) while we were gone? */
@@ -405,7 +407,7 @@ libxlReconnectDomain(virDomainObjPtr vm,
 /* Update hostdev state */
 if (virHostdevUpdateActiveDomainDevices(hostdev_mgr, LIBXL_DRIVER_NAME,
 vm->def, hostdev_flags) < 0)
-goto out;
+goto error;
 
 if (virAtomicIntInc(>nactive) == 1 && driver->inhibitCallback)
 driver->inhibitCallback(true, driver->inhibitOpaque);
@@ -413,21 +415,23 @@ libxlReconnectDomain(virDomainObjPtr vm,
 /* Enable domain death events */
 libxl_evenable_domain_death(cfg->ctx, vm->def->id, 0, >deathW);
 
+ cleanup:
 libxl_dominfo_dispose(_info);
 virObjectUnlock(vm);
+virObjectUnref(vm);
 virObjectUnref(cfg);
-return 0;
+return ret;
 
- out:
-libxl_dominfo_dispose(_info);
+ error:
 libxlDomainCleanup(driver, vm);
-if (!vm->persistent)
+if (!vm->persistent) {
 virDomainObjListRemoveLocked(driver->domains, vm);
-else
-virObjectUnlock(vm);
-virObjectUnref(cfg);
 
-return -1;
+/* virDomainObjListRemoveLocked leaves the object unlocked,
+ * lock it again to factorize more code. */
+virObjectLock(vm);
+}
+goto cleanup;
 }
 
 static void
-- 
2.6.6

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH] lxc: errors after the handshake won't be reported

2016-07-19 Thread Cédric Bosdonnat
Any error happening after the hand shake in the lxc controller
will not result in a failure as errors are checked during the handshake.
Move the handshake after the last possible error.
---
 src/lxc/lxc_controller.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
index f55aadc..825b4d4 100644
--- a/src/lxc/lxc_controller.c
+++ b/src/lxc/lxc_controller.c
@@ -2444,13 +2444,13 @@ virLXCControllerRun(virLXCControllerPtr ctrl)
 if (lxcControllerClearCapabilities() < 0)
 goto cleanup;
 
-if (virLXCControllerDaemonHandshake(ctrl) < 0)
-goto cleanup;
-
 for (i = 0; i < ctrl->nconsoles; i++)
 if (virLXCControllerConsoleSetNonblocking(&(ctrl->consoles[i])) < 0)
 goto cleanup;
 
+if (virLXCControllerDaemonHandshake(ctrl) < 0)
+goto cleanup;
+
 /* We must not hold open a dbus connection for life
  * of LXC instance, since dbus-daemon is limited to
  * only a few 100 connections by default
-- 
2.6.6

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH] Adapt augeas profile to handle negative int values.

2016-04-15 Thread Cédric Bosdonnat
Introducing keepalive_interval = -1 breaks to augeas lens. Fix the lens
by allowing signed ints in the regular expression.
---
 daemon/libvirtd.aug | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/daemon/libvirtd.aug b/daemon/libvirtd.aug
index a70aa1d..4d40ee2 100644
--- a/daemon/libvirtd.aug
+++ b/daemon/libvirtd.aug
@@ -13,7 +13,7 @@ module Libvirtd =
 
let str_val = del /\"/ "\"" . store /[^\"]*/ . del /\"/ "\""
let bool_val = store /0|1/
-   let int_val = store /[0-9]+/
+   let int_val = store /-?[0-9]+/
let str_array_element = [ seq "el" . str_val ] . del /[ \t\n]*/ ""
let str_array_val = counter "el" . array_start . ( str_array_element . ( 
array_sep . str_array_element ) * ) ? . array_end
 
-- 
2.6.6

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH] libxl: add support for mounts in HVM guests

2015-12-01 Thread Cédric Bosdonnat
Xen HVM guests are running a QEMU, libxl allows passing QEMU parameters
in the d_config.b_info.extra list. Take advantage of that to implement
support for 9pfs mounts. For this to work, xen's qemu needs to be built
with virtfs enabled, or an upstream qemu needs to be used.
---
 Note that two functions have been picked from the qemu driver's code.

 src/libxl/libxl_conf.c | 174 +
 1 file changed, 174 insertions(+)

diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c
index 4eed5ca..4437e8f 100644
--- a/src/libxl/libxl_conf.c
+++ b/src/libxl/libxl_conf.c
@@ -55,6 +55,7 @@ VIR_LOG_INIT("libxl.libxl_conf");
 /* see xen-unstable.hg/xen/include/asm-x86/cpufeature.h */
 #define LIBXL_X86_FEATURE_PAE_MASK 0x40
 
+#define LIBXL_FSDEV_HOST_PREFIX "fsdev-"
 
 struct guest_arch {
 virArch arch;
@@ -84,6 +85,15 @@ static int libxlConfigOnceInit(void)
 
 VIR_ONCE_GLOBAL_INIT(libxlConfig)
 
+VIR_ENUM_DECL(libxlDomainFSDriver)
+VIR_ENUM_IMPL(libxlDomainFSDriver, VIR_DOMAIN_FS_DRIVER_TYPE_LAST,
+  "local",
+  "local",
+  "handle",
+  NULL,
+  NULL,
+  NULL);
+
 static void
 libxlDriverConfigDispose(void *obj)
 {
@@ -1854,6 +1864,167 @@ libxlMakeCapabilities(libxl_ctx *ctx)
 return NULL;
 }
 
+static char *
+libxlBuildQemuFSStr(virDomainFSDefPtr fs)
+{
+virBuffer opt = VIR_BUFFER_INITIALIZER;
+const char *driver = libxlDomainFSDriverTypeToString(fs->fsdriver);
+const char *wrpolicy = virDomainFSWrpolicyTypeToString(fs->wrpolicy);
+
+if (fs->type != VIR_DOMAIN_FS_TYPE_MOUNT) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+   _("only supports mount filesystem type"));
+goto error;
+}
+
+if (!driver) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+   _("Filesystem driver type not supported"));
+goto error;
+}
+virBufferAdd(, driver, -1);
+
+if (fs->fsdriver == VIR_DOMAIN_FS_DRIVER_TYPE_PATH ||
+fs->fsdriver == VIR_DOMAIN_FS_DRIVER_TYPE_DEFAULT) {
+if (fs->accessmode == VIR_DOMAIN_FS_ACCESSMODE_MAPPED) {
+virBufferAddLit(, ",security_model=mapped");
+} else if (fs->accessmode == VIR_DOMAIN_FS_ACCESSMODE_PASSTHROUGH) {
+virBufferAddLit(, ",security_model=passthrough");
+} else if (fs->accessmode == VIR_DOMAIN_FS_ACCESSMODE_SQUASH) {
+virBufferAddLit(, ",security_model=none");
+}
+} else {
+/* For other fs drivers, default(passthru) should always
+ * be supported */
+if (fs->accessmode != VIR_DOMAIN_FS_ACCESSMODE_PASSTHROUGH) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+   _("only supports passthrough accessmode"));
+goto error;
+}
+}
+
+if (fs->wrpolicy)
+virBufferAsprintf(, ",writeout=%s", wrpolicy);
+
+virBufferAsprintf(, ",id=%s%s", LIBXL_FSDEV_HOST_PREFIX, 
fs->info.alias);
+virBufferAsprintf(, ",path=%s", fs->src);
+
+if (fs->readonly)
+virBufferAddLit(, ",readonly");
+
+if (virBufferCheckError() < 0)
+goto error;
+
+return virBufferContentAndReset();
+
+ error:
+virBufferFreeAndReset();
+return NULL;
+}
+
+
+static char *
+libxlBuildQemuFSDevStr(virDomainFSDefPtr fs)
+{
+virBuffer opt = VIR_BUFFER_INITIALIZER;
+
+if (fs->type != VIR_DOMAIN_FS_TYPE_MOUNT) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+   _("can only passthrough directories"));
+goto error;
+}
+
+if (fs->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW)
+virBufferAddLit(, "virtio-9p-ccw");
+else
+virBufferAddLit(, "virtio-9p-pci");
+
+virBufferAsprintf(, ",id=%s", fs->info.alias);
+virBufferAsprintf(, ",fsdev=%s%s", LIBXL_FSDEV_HOST_PREFIX, 
fs->info.alias);
+virBufferAsprintf(, ",mount_tag=%s", fs->dst);
+
+if (virBufferCheckError() < 0)
+goto error;
+
+return virBufferContentAndReset();
+
+ error:
+virBufferFreeAndReset();
+return NULL;
+}
+
+static int
+libxlMakeMountList(virDomainDefPtr def,
+   libxl_domain_config *d_config)
+{
+int ret = -1;
+size_t i;
+size_t nextra = 0;
+char *fsstr = NULL;
+char *fsdevstr = NULL;
+char *fsdevargstr = NULL;
+char *deviceargstr = NULL;
+
+if (def->nfss > 0 && def->os.type != VIR_DOMAIN_OSTYPE_HVM) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+   _("only HVM guests supports mounts"));
+return ret;
+}
+
+/* Make sure we have an allocated array, not ending with NULL */
+if (!d_config->b_info.extra) {
+if (VIR_ALLOC(d_config->b_info.extra) < 0)
+return ret;
+nextra = 0;
+} else {
+nextra = virStringListLength(d_config->b_info.extra) + 1;
+if (VIR_DELETE_ELEMENT(d_config->b_info.extra, 

[libvirt] [PATCH] Wait for udev events to be handled after removing veth

2015-11-26 Thread Cédric Bosdonnat
As per http://www.redhat.com/archives/libvir-list/2013-July/msg01279.html,
wait for udev events to be handled after removing a virtual NIC.
Any udev rule associated to NIC destroy could happen to run with a new
device with the same name that is being created.
---
 src/util/virnetdevveth.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/util/virnetdevveth.c b/src/util/virnetdevveth.c
index 6905168..c8a38fb 100644
--- a/src/util/virnetdevveth.c
+++ b/src/util/virnetdevveth.c
@@ -225,5 +225,8 @@ int virNetDevVethDelete(const char *veth)
 ret = 0;
  cleanup:
 virCommandFree(cmd);
+/* Make sure the device is properly down: creating a new one
+ * with the same name could lead to troubles */
+virFileWaitForDevices();
 return ret;
 }
-- 
2.1.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v2] Allow building lxc without virt-login-shell

2015-11-25 Thread Cédric Bosdonnat
Add a configure option to disable virt-login-shell build even if lxc is
enabled.
---
Diff to V1:

 * moved the configure.ac code into m4/virt-login-shell.m4
 * allow building virt-login-shell without lxc
 * Introduce WITH_SETUID_RPC_CLIENT to have it built if
   either lxc or virt-login-shell is built.

 configure.ac   |  9 +
 m4/virt-login-shell.m4 | 27 +++
 src/Makefile.am|  4 ++--
 tools/Makefile.am  | 12 ++--
 4 files changed, 44 insertions(+), 8 deletions(-)
 create mode 100644 m4/virt-login-shell.m4

diff --git a/configure.ac b/configure.ac
index f481c50..6fef728 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1075,6 +1075,14 @@ fi
 AM_CONDITIONAL([WITH_LXC], [test "$with_lxc" = "yes"])
 
 dnl
+dnl Check for virt-login-shell
+dnl
+
+LIBVIRT_CHECK_LOGIN_SHELL
+
+AM_CONDITIONAL([WITH_SETUID_RPC_CLIENT], [test "$with_lxc$with_login_shell" != 
"nono"])
+
+dnl
 dnl Checks for the Parallels driver
 dnl
 
@@ -2974,6 +2982,7 @@ AC_MSG_NOTICE([  Init script: $with_init_script])
 AC_MSG_NOTICE([Char device locks: $with_chrdev_lock_files])
 AC_MSG_NOTICE([   Default Editor: $DEFAULT_EDITOR])
 AC_MSG_NOTICE([ Loader/NVRAM: $with_loader_nvram])
+AC_MSG_NOTICE([ virt-login-shell: $with_login_shell])
 AC_MSG_NOTICE([])
 AC_MSG_NOTICE([Developer Tools])
 AC_MSG_NOTICE([])
diff --git a/m4/virt-login-shell.m4 b/m4/virt-login-shell.m4
new file mode 100644
index 000..0701054
--- /dev/null
+++ b/m4/virt-login-shell.m4
@@ -0,0 +1,27 @@
+dnl Copyright (c) 2015 SUSE LINUX Products GmbH, Nuernberg, Germany.
+dnl
+dnl This library is free software; you can redistribute it and/or
+dnl modify it under the terms of the GNU Lesser General Public
+dnl License as published by the Free Software Foundation; either
+dnl version 2.1 of the License, or (at your option) any later version.
+dnl
+dnl This library is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+dnl Lesser General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU Lesser General Public
+dnl License along with this library.  If not, see
+dnl .
+
+AC_DEFUN([LIBVIRT_CHECK_LOGIN_SHELL], [
+  AC_ARG_WITH([login_shell],
+[AS_HELP_STRING([--with-login-shell],
+  [build virt-login-shell @<:@default=yes@:>@])])
+  m4_divert_text([DEFAULTS], [with_login_shell=yes])
+
+  if test "$with_login_shell" ; then
+  AC_DEFINE_UNQUOTED([WITH_LOGIN_SHELL], 1, [whether virt-login-shell is 
built])
+  fi
+  AM_CONDITIONAL([WITH_LOGIN_SHELL], [test "$with_login_shell" = "yes"])
+])
diff --git a/src/Makefile.am b/src/Makefile.am
index 99b4993..2f40910 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -2225,7 +2225,7 @@ libvirt_lxc_la_LIBADD = libvirt.la $(CYGWIN_EXTRA_LIBADD)
 # have a RPC client for local UNIX socket access only. We use
 # the ../config-post.h header to disable all external deps that
 # we don't want
-if WITH_LXC
+if WITH_SETUID_RPC_CLIENT
 noinst_LTLIBRARIES += libvirt-setuid-rpc-client.la
 
 libvirt_setuid_rpc_client_la_SOURCES = \
@@ -2302,7 +2302,7 @@ libvirt_setuid_rpc_client_la_CFLAGS = \
$(SECDRIVER_CFLAGS) \
$(XDR_CFLAGS)   \
$(NULL)
-endif WITH_LXC
+endif WITH_SETUID_RPC_CLIENT
 
 lockdriverdir = $(libdir)/libvirt/lock-driver
 lockdriver_LTLIBRARIES =
diff --git a/tools/Makefile.am b/tools/Makefile.am
index d5638d9..d005035 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -71,12 +71,12 @@ sbin_SCRIPTS = virt-sanlock-cleanup
 DISTCLEANFILES += virt-sanlock-cleanup
 endif WITH_SANLOCK
 
-if WITH_LXC
+if WITH_LOGIN_SHELL
 conf_DATA += virt-login-shell.conf
 bin_PROGRAMS += virt-login-shell
-else ! WITH_LXC
+else ! WITH_LOGIN_SHELL
 EXTRA_DIST += virt-login-shell.conf
-endif ! WITH_LXC
+endif ! WITH_LOGIN_SHELL
 
 
 dist_man1_MANS = \
@@ -84,11 +84,11 @@ dist_man1_MANS = \
virt-pki-validate.1 \
virt-xml-validate.1 \
virsh.1
-if WITH_LXC
+if WITH_LOGIN_SHELL
 dist_man1_MANS += virt-login-shell.1
-else ! WITH_LXC
+else ! WITH_LOGIN_SHELL
 EXTRA_DIST += virt-login-shell.1
-endif ! WITH_LXC
+endif ! WITH_LOGIN_SHELL
 if WITH_SANLOCK
 dist_man8_MANS = virt-sanlock-cleanup.8
 endif WITH_SANLOCK
-- 
2.1.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH] lxc: drop sys_admin caps by default

2015-11-25 Thread Cédric Bosdonnat
To make sure the container user doesn't play with mounts, like
changing them from ro to rw, drop the sys_admin capability by default.
If user really needs to play with those, it can be enabled in the
configuration.
---
 Note: it seems that patch 3/3 or my last series never reached the list.
 Here it is.

 src/lxc/lxc_container.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index c5a70a1..d6d6fba 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -2083,6 +2083,7 @@ static int lxcContainerDropCapabilities(virDomainDefPtr 
def,
 case VIR_DOMAIN_CAPS_FEATURE_MKNOD: /* No creating device nodes */
 case VIR_DOMAIN_CAPS_FEATURE_AUDIT_CONTROL: /* No messing with 
auditing status */
 case VIR_DOMAIN_CAPS_FEATURE_MAC_ADMIN: /* No messing with LSM 
config */
+case VIR_DOMAIN_CAPS_FEATURE_SYS_ADMIN: /* No messing with mounts 
*/
 toDrop = (state != VIR_TRISTATE_SWITCH_ON);
 break;
 default: /* User specified capabilities to drop */
-- 
2.1.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH 2/3] virt-aa-helper: don't deny writes to readonly mounts

2015-11-17 Thread Cédric Bosdonnat
There is no need to deny writes on a readonly mount: write still
won't be accepted, even if the user remounts the folder as RW in
the guest as qemu sets the 9p mount as ro.

This deny rule was leading to problems for example with readonly /:
The qemu process had to write to a bunch of files in / like logs,
sockets, etc. This deny rule was also preventing auditing of these
denials, making it harder to debug.
---
 src/security/virt-aa-helper.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c
index 5de56e5..a2d7226 100644
--- a/src/security/virt-aa-helper.c
+++ b/src/security/virt-aa-helper.c
@@ -1127,7 +1127,10 @@ get_files(vahControl * ctl)
 ctl->def->fss[i]->src) {
 virDomainFSDefPtr fs = ctl->def->fss[i];
 
-if (vah_add_path(, fs->src, fs->readonly ? "r" : "rw", true) 
!= 0)
+/* We don't need to add deny rw rules for readonly mounts,
+ * this can only lead to troubles when mounting / readonly.
+ */
+if (vah_add_path(, fs->src, "rw", true) != 0)
 goto cleanup;
 }
 }
-- 
2.1.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH 1/3] Allow building lxc without virt-login-shell

2015-11-17 Thread Cédric Bosdonnat
Add a configure option to disable virt-login-shell build even if lxc is
enabled.
---
 configure.ac  | 14 ++
 tools/Makefile.am | 12 ++--
 2 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/configure.ac b/configure.ac
index f481c50..c766351 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1074,6 +1074,19 @@ if test "$with_lxc" = "yes" ; then
 fi
 AM_CONDITIONAL([WITH_LXC], [test "$with_lxc" = "yes"])
 
+AC_ARG_WITH([login_shell],
+  [AS_HELP_STRING([--with-login-shell],
+[build virt-login-shell @<:@default=yes@:>@])])
+m4_divert_text([DEFAULTS], [with_login_shell=yes])
+
+if test "$with_lxc" != "yes" ; then
+with_login_shell="no"
+fi
+if test "$with_login_shell" ; then
+AC_DEFINE_UNQUOTED([WITH_LOGIN_SHELL], 1, [whether virt-login-shell is 
built])
+fi
+AM_CONDITIONAL([WITH_LOGIN_SHELL], [test "$with_login_shell" = "yes"])
+
 dnl
 dnl Checks for the Parallels driver
 dnl
@@ -2974,6 +2987,7 @@ AC_MSG_NOTICE([  Init script: $with_init_script])
 AC_MSG_NOTICE([Char device locks: $with_chrdev_lock_files])
 AC_MSG_NOTICE([   Default Editor: $DEFAULT_EDITOR])
 AC_MSG_NOTICE([ Loader/NVRAM: $with_loader_nvram])
+AC_MSG_NOTICE([ virt-login-shell: $with_login_shell])
 AC_MSG_NOTICE([])
 AC_MSG_NOTICE([Developer Tools])
 AC_MSG_NOTICE([])
diff --git a/tools/Makefile.am b/tools/Makefile.am
index d5638d9..d005035 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -71,12 +71,12 @@ sbin_SCRIPTS = virt-sanlock-cleanup
 DISTCLEANFILES += virt-sanlock-cleanup
 endif WITH_SANLOCK
 
-if WITH_LXC
+if WITH_LOGIN_SHELL
 conf_DATA += virt-login-shell.conf
 bin_PROGRAMS += virt-login-shell
-else ! WITH_LXC
+else ! WITH_LOGIN_SHELL
 EXTRA_DIST += virt-login-shell.conf
-endif ! WITH_LXC
+endif ! WITH_LOGIN_SHELL
 
 
 dist_man1_MANS = \
@@ -84,11 +84,11 @@ dist_man1_MANS = \
virt-pki-validate.1 \
virt-xml-validate.1 \
virsh.1
-if WITH_LXC
+if WITH_LOGIN_SHELL
 dist_man1_MANS += virt-login-shell.1
-else ! WITH_LXC
+else ! WITH_LOGIN_SHELL
 EXTRA_DIST += virt-login-shell.1
-endif ! WITH_LXC
+endif ! WITH_LOGIN_SHELL
 if WITH_SANLOCK
 dist_man8_MANS = virt-sanlock-cleanup.8
 endif WITH_SANLOCK
-- 
2.1.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH 0/3] Misc fixes

2015-11-17 Thread Cédric Bosdonnat
Hi all,

Here are a few patches without strong connection together. The first one
only allows us not to package virt-login-shell even with lxc driver
enabled. The other ones are related to mounts security.

I'm wondering if changing the default dropped capabilities in the lxc
driver is acceptable... dropping sys_admin makes sense, but it can
introduce incompatibilities for users needing it as they will need to
explicitely enable it.

Cédric Bosdonnat (3):
  Allow building lxc without virt-login-shell
  virt-aa-helper: don't deny writes to readonly mounts
  lxc: drop sys_admin caps by default

 configure.ac  | 14 ++
 src/lxc/lxc_container.c   |  1 +
 src/security/virt-aa-helper.c |  5 -
 tools/Makefile.am | 12 ++--
 4 files changed, 25 insertions(+), 7 deletions(-)

-- 
2.1.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH] Allow building lxc without virt-login-shell

2015-11-09 Thread Cédric Bosdonnat
Add a configure option to disable virt-login-shell build even if lxc is
enabled.
---
 configure.ac  | 14 ++
 tools/Makefile.am | 12 ++--
 2 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/configure.ac b/configure.ac
index f481c50..c766351 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1074,6 +1074,19 @@ if test "$with_lxc" = "yes" ; then
 fi
 AM_CONDITIONAL([WITH_LXC], [test "$with_lxc" = "yes"])
 
+AC_ARG_WITH([login_shell],
+  [AS_HELP_STRING([--with-login-shell],
+[build virt-login-shell @<:@default=yes@:>@])])
+m4_divert_text([DEFAULTS], [with_login_shell=yes])
+
+if test "$with_lxc" != "yes" ; then
+with_login_shell="no"
+fi
+if test "$with_login_shell" ; then
+AC_DEFINE_UNQUOTED([WITH_LOGIN_SHELL], 1, [whether virt-login-shell is 
built])
+fi
+AM_CONDITIONAL([WITH_LOGIN_SHELL], [test "$with_login_shell" = "yes"])
+
 dnl
 dnl Checks for the Parallels driver
 dnl
@@ -2974,6 +2987,7 @@ AC_MSG_NOTICE([  Init script: $with_init_script])
 AC_MSG_NOTICE([Char device locks: $with_chrdev_lock_files])
 AC_MSG_NOTICE([   Default Editor: $DEFAULT_EDITOR])
 AC_MSG_NOTICE([ Loader/NVRAM: $with_loader_nvram])
+AC_MSG_NOTICE([ virt-login-shell: $with_login_shell])
 AC_MSG_NOTICE([])
 AC_MSG_NOTICE([Developer Tools])
 AC_MSG_NOTICE([])
diff --git a/tools/Makefile.am b/tools/Makefile.am
index d5638d9..d005035 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -71,12 +71,12 @@ sbin_SCRIPTS = virt-sanlock-cleanup
 DISTCLEANFILES += virt-sanlock-cleanup
 endif WITH_SANLOCK
 
-if WITH_LXC
+if WITH_LOGIN_SHELL
 conf_DATA += virt-login-shell.conf
 bin_PROGRAMS += virt-login-shell
-else ! WITH_LXC
+else ! WITH_LOGIN_SHELL
 EXTRA_DIST += virt-login-shell.conf
-endif ! WITH_LXC
+endif ! WITH_LOGIN_SHELL
 
 
 dist_man1_MANS = \
@@ -84,11 +84,11 @@ dist_man1_MANS = \
virt-pki-validate.1 \
virt-xml-validate.1 \
virsh.1
-if WITH_LXC
+if WITH_LOGIN_SHELL
 dist_man1_MANS += virt-login-shell.1
-else ! WITH_LXC
+else ! WITH_LOGIN_SHELL
 EXTRA_DIST += virt-login-shell.1
-endif ! WITH_LXC
+endif ! WITH_LOGIN_SHELL
 if WITH_SANLOCK
 dist_man8_MANS = virt-sanlock-cleanup.8
 endif WITH_SANLOCK
-- 
2.1.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [sandbox 0/2] virt-sandbox-config minor fixes

2015-11-07 Thread Cédric Bosdonnat
Hi all,

Here are two really trivial patches, one adding image format guess
to -m host-image in the same way we do it for --disk, and one fixing some
code formatting issue.

Cédric Bosdonnat (2):
  Try guessing host-image image format
  Code formatting fix

 libvirt-sandbox/libvirt-sandbox-config.c | 9 -
 1 file changed, 4 insertions(+), 5 deletions(-)

-- 
2.1.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [sandbox 2/2] Code formatting fix

2015-11-07 Thread Cédric Bosdonnat
---
 libvirt-sandbox/libvirt-sandbox-config.c | 7 ++-
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/libvirt-sandbox/libvirt-sandbox-config.c 
b/libvirt-sandbox/libvirt-sandbox-config.c
index 55ee291..0ade178 100644
--- a/libvirt-sandbox/libvirt-sandbox-config.c
+++ b/libvirt-sandbox/libvirt-sandbox-config.c
@@ -1381,11 +1381,8 @@ gboolean 
gvir_sandbox_config_add_disk_opts(GVirSandboxConfig *config,
 _("Unknown disk image format: '%s'"), formatStr + 
7);
 return FALSE;
 }
-}
-else {
-if ((format = gvir_sandbox_util_guess_image_format(source, error)) < 
0) {
-   format = GVIR_CONFIG_DOMAIN_DISK_FORMAT_RAW;
-}
+} else if ((format = gvir_sandbox_util_guess_image_format(source, error)) 
< 0) {
+format = GVIR_CONFIG_DOMAIN_DISK_FORMAT_RAW;
 }
 
 
-- 
2.1.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [sandbox 1/2] Try guessing host-image image format

2015-11-07 Thread Cédric Bosdonnat
---
 libvirt-sandbox/libvirt-sandbox-config.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/libvirt-sandbox/libvirt-sandbox-config.c 
b/libvirt-sandbox/libvirt-sandbox-config.c
index 5a4aacb..55ee291 100644
--- a/libvirt-sandbox/libvirt-sandbox-config.c
+++ b/libvirt-sandbox/libvirt-sandbox-config.c
@@ -1621,6 +1621,8 @@ gboolean 
gvir_sandbox_config_add_mount_opts(GVirSandboxConfig *config,
 g_type_class_unref(enum_class);
 format = enum_value->value;
 }
+} else if ((format = gvir_sandbox_util_guess_image_format(source, 
error)) < 0) {
+format = GVIR_CONFIG_DOMAIN_DISK_FORMAT_RAW;
 }
 
 mnt = GVIR_SANDBOX_CONFIG_MOUNT(g_object_new(type,
-- 
2.1.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [sandbox] virt-sandbox-image: separate templates from the different sources

2015-10-07 Thread Cédric Bosdonnat
Put templates files in a folder for the corresponding source to avoid
potential name conflicts.
---
 libvirt-sandbox/image/cli.py | 19 ---
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/libvirt-sandbox/image/cli.py b/libvirt-sandbox/image/cli.py
index d449a7b..9b9c00b 100755
--- a/libvirt-sandbox/image/cli.py
+++ b/libvirt-sandbox/image/cli.py
@@ -64,17 +64,21 @@ def debug(msg):
 def info(msg):
 sys.stdout.write(msg)
 
+def get_template_dir(args):
+tmpl = template.Template.from_uri(args.template)
+return "%s/%s" % (args.template_dir, tmpl.source)
+
 def delete(args):
 tmpl = template.Template.from_uri(args.template)
 source = tmpl.get_source_impl()
 source.delete_template(template=tmpl,
-   templatedir=args.template_dir)
+   templatedir=get_template_dir(args))
 
 def create(args):
 tmpl = template.Template.from_uri(args.template)
 source = tmpl.get_source_impl()
 source.create_template(template=tmpl,
-   templatedir=args.template_dir,
+   templatedir=get_template_dir(args),
connect=args.connect)
 
 def run(args):
@@ -83,9 +87,10 @@ def run(args):
 
 tmpl = template.Template.from_uri(args.template)
 source = tmpl.get_source_impl()
+template_dir = get_template_dir(args)
 
 # Create the template image if needed
-if not source.has_template(tmpl, args.template_dir):
+if not source.has_template(tmpl, template_dir):
 create(args)
 
 name = args.name
@@ -94,11 +99,11 @@ def run(args):
 name = tmpl.path[1:] + ":" + randomid
 
 diskfile = source.get_disk(template=tmpl,
-   templatedir=args.template_dir,
+   templatedir=template_dir,
imagedir=args.image_dir,
sandboxname=name)
 
-commandToRun = source.get_command(tmpl, args.template_dir, args.args)
+commandToRun = source.get_command(tmpl, template_dir, args.args)
 if len(commandToRun) == 0:
 commandToRun = ["/bin/sh"]
 cmd = ['virt-sandbox', '--name', name]
@@ -112,7 +117,7 @@ def run(args):
 params.append('-N')
 params.append(networkArgs)
 
-allEnvs = source.get_env(tmpl, args.template_dir)
+allEnvs = source.get_env(tmpl, template_dir)
 envArgs = args.env
 if envArgs is not None:
 allEnvs = allEnvs + envArgs
@@ -128,7 +133,7 @@ def run(args):
 cmd = cmd + params + ['--'] + commandToRun
 subprocess.call(cmd)
 os.unlink(diskfile)
-source.post_run(tmpl, args.template_dir, name)
+source.post_run(tmpl, template_dir, name)
 
 def requires_template(parser):
 parser.add_argument("template",
-- 
2.1.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH] apparmor: differentiate between error and unconfined profiles

2015-10-06 Thread Cédric Bosdonnat
profile_status function was not making any difference between error
cases and unconfined profiles. The problem with this approach is that
dominfo was throwing an error on unconfined domains.
---
 src/security/security_apparmor.c | 30 +-
 1 file changed, 21 insertions(+), 9 deletions(-)

diff --git a/src/security/security_apparmor.c b/src/security/security_apparmor.c
index 16b8f87..2cf333d 100644
--- a/src/security/security_apparmor.c
+++ b/src/security/security_apparmor.c
@@ -66,10 +66,11 @@ struct SDPDOP {
 };
 
 /*
- * profile_status returns '-1' on error, '0' if loaded
+ * profile_status returns '-2' on error, '-1' if not loaded, '0' if loaded
  *
- * If check_enforcing is set to '1', then returns '-1' on error, '0' if
- * loaded in complain mode, and '1' if loaded in enforcing mode.
+ * If check_enforcing is set to '1', then returns '-2' on error, '-1' if
+ * not loaded, '0' if loaded in complain mode, and '1' if loaded in
+ * enforcing mode.
  */
 static int
 profile_status(const char *str, const int check_enforcing)
@@ -77,7 +78,7 @@ profile_status(const char *str, const int check_enforcing)
 char *content = NULL;
 char *tmp = NULL;
 char *etmp = NULL;
-int rc = -1;
+int rc = -2;
 
 /* create string that is ' \0' for accurate matching */
 if (virAsprintf(, "%s ", str) == -1)
@@ -100,6 +101,8 @@ profile_status(const char *str, const int check_enforcing)
 
 if (strstr(content, tmp) != NULL)
 rc = 0;
+else
+rc = -1; /* return -1 if not loaded */
 if (check_enforcing != 0) {
 if (rc == 0 && strstr(content, etmp) != NULL)
 rc = 1; /* return '1' if loaded and enforcing */
@@ -262,6 +265,9 @@ use_apparmor(void)
 goto cleanup;
 
 rc = profile_status(libvirt_daemon, 1);
+/* Error or unconfined should all result in -1*/
+if (rc < 0)
+rc = -1;
 
  cleanup:
 VIR_FREE(libvirt_daemon);
@@ -517,23 +523,29 @@ AppArmorGetSecurityProcessLabel(virSecurityManagerPtr mgr 
ATTRIBUTE_UNUSED,
 virSecurityLabelPtr sec)
 {
 int rc = -1;
+int status;
 char *profile_name = NULL;
 
 if ((profile_name = get_profile_name(def)) == NULL)
 return rc;
 
-if (virStrcpy(sec->label, profile_name,
-VIR_SECURITY_LABEL_BUFLEN) == NULL) {
+status = profile_status(profile_name, 1);
+if (status < -1) {
 virReportError(VIR_ERR_INTERNAL_ERROR,
-   "%s", _("error copying profile name"));
+   "%s", _("error getting profile status"));
 goto cleanup;
+} else if (status == -1) {
+profile_name[0] = '\0';
 }
 
-if ((sec->enforcing = profile_status(profile_name, 1)) < 0) {
+if (virStrcpy(sec->label, profile_name,
+VIR_SECURITY_LABEL_BUFLEN) == NULL) {
 virReportError(VIR_ERR_INTERNAL_ERROR,
-   "%s", _("error calling profile_status()"));
+   "%s", _("error copying profile name"));
 goto cleanup;
 }
+
+sec->enforcing = status == 1;
 rc = 0;
 
  cleanup:
-- 
2.1.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [sandbox v2 2/5] virt-image-sandbox: tarball extracting function to be reusable

2015-10-05 Thread Cédric Bosdonnat
The virt-builder source will need this function too, let's move it to
the Source abstraction for reusability. Note that the function now
checks for tarball filename to end with ".gz" to add the proper
tar option.
---
 libvirt-sandbox/image/sources/DockerSource.py | 25 +
 libvirt-sandbox/image/sources/Source.py   | 20 
 2 files changed, 25 insertions(+), 20 deletions(-)

diff --git a/libvirt-sandbox/image/sources/DockerSource.py 
b/libvirt-sandbox/image/sources/DockerSource.py
index 93d7f17..0d76717 100644
--- a/libvirt-sandbox/image/sources/DockerSource.py
+++ b/libvirt-sandbox/image/sources/DockerSource.py
@@ -266,7 +266,11 @@ class DockerSource(Source):
 if parentImage is None:
 self.format_disk(templateImage,format,connect)
 
-self._extract_tarballs(templatedir + "/" + imagetagid + 
"/template.",format,connect)
+path = templatedir + "/" + imagetagid + "/template."
+self.extract_tarball(path + "qcow2",
+ format,
+ path + "tar.gz",
+ connect)
 parentImage = templateImage
 
 
@@ -302,25 +306,6 @@ class DockerSource(Source):
 imagetagid = parent
 return imagelist
 
-def _extract_tarballs(self,directory,format,connect):
-tarfile = directory + "tar.gz"
-diskfile = directory + "qcow2"
-cmd = ['virt-sandbox']
-if connect is not None:
-cmd.append("-c")
-cmd.append(connect)
-cmd.append("-p")
-params = ['-m',
-  'host-image:/mnt=%s,format=%s' %(diskfile,format),
-  '--',
-  '/bin/tar',
-  'zxf',
-  '%s' %tarfile,
-  '-C',
-  '/mnt']
-cmd = cmd + params
-subprocess.call(cmd)
-
 def delete_template(self, template, templatedir):
 imageusage = {}
 imageparent = {}
diff --git a/libvirt-sandbox/image/sources/Source.py 
b/libvirt-sandbox/image/sources/Source.py
index 708f2aa..15737c1 100644
--- a/libvirt-sandbox/image/sources/Source.py
+++ b/libvirt-sandbox/image/sources/Source.py
@@ -119,3 +119,23 @@ class Source():
   '/dev/disk/by-tag/disk_image']
 cmd = cmd + params
 subprocess.call(cmd)
+
+def extract_tarball(self, diskfile, format, tarfile, connect):
+cmd = ['virt-sandbox']
+if connect is not None:
+cmd.append("-c")
+cmd.append(connect)
+cmd.append("-p")
+compression = ""
+if tarfile.endswith(".gz"):
+compression = "z"
+params = ['-m',
+  'host-image:/mnt=%s,format=%s' % (diskfile, format),
+  '--',
+  '/bin/tar',
+  'xf%s' % compression,
+  '%s' % tarfile,
+  '-C',
+  '/mnt']
+cmd = cmd + params
+subprocess.call(cmd)
-- 
2.1.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [sandbox v2 3/5] virt-sandbox-image: remove the format parameter

2015-10-05 Thread Cédric Bosdonnat
The format parameter isn't used so far and would only be misleading
users. Removing it for the while, but may be reintroduced later when
adding storage backend support.
---
 libvirt-sandbox/image/cli.py  |  9 ++---
 libvirt-sandbox/image/sources/DockerSource.py | 18 --
 libvirt-sandbox/image/sources/Source.py   |  3 +--
 3 files changed, 7 insertions(+), 23 deletions(-)

diff --git a/libvirt-sandbox/image/cli.py b/libvirt-sandbox/image/cli.py
index 4500713..f067347 100755
--- a/libvirt-sandbox/image/cli.py
+++ b/libvirt-sandbox/image/cli.py
@@ -75,8 +75,7 @@ def create(args):
 source = tmpl.get_source_impl()
 source.create_template(template=tmpl,
templatedir=args.template_dir,
-   connect=args.connect,
-   format=args.format)
+   connect=args.connect)
 
 def run(args):
 if args.connect is not None:
@@ -95,7 +94,6 @@ def run(args):
imagedir=args.image_dir,
sandboxname=name)
 
-format = "qcow2"
 commandToRun = source.get_command(tmpl, args.template_dir, args.args)
 if len(commandToRun) == 0:
 commandToRun = ["/bin/sh"]
@@ -103,7 +101,7 @@ def run(args):
 if args.connect is not None:
 cmd.append("-c")
 cmd.append(args.connect)
-params = ['-m','host-image:/=%s,format=%s' %(diskfile,format)]
+params = ['-m','host-image:/=%s,format=qcow2' % diskfile]
 
 networkArgs = args.network
 if networkArgs is not None:
@@ -185,9 +183,6 @@ def gen_create_args(subparser):
 requires_template(parser)
 requires_connect(parser)
 requires_template_dir(parser)
-parser.add_argument("-f","--format",
-default="qcow2",
-help=_("format format for image"))
 parser.set_defaults(func=create)
 
 def gen_run_args(subparser):
diff --git a/libvirt-sandbox/image/sources/DockerSource.py 
b/libvirt-sandbox/image/sources/DockerSource.py
index 0d76717..1f6f94f 100644
--- a/libvirt-sandbox/image/sources/DockerSource.py
+++ b/libvirt-sandbox/image/sources/DockerSource.py
@@ -241,11 +241,7 @@ class DockerSource(Source):
 debug("FAIL %s\n" % str(e))
 raise
 
-def create_template(self, template, templatedir, connect=None, 
format=None):
-if format is None:
-format = "qcow2"
-self._check_disk_format(format)
-
+def create_template(self, template, templatedir, connect=None):
 self.download_template(template, templatedir)
 
 imagelist = self._get_image_list(template, templatedir)
@@ -253,7 +249,7 @@ class DockerSource(Source):
 
 parentImage = None
 for imagetagid in imagelist:
-templateImage = templatedir + "/" + imagetagid + "/template." + 
format
+templateImage = templatedir + "/" + imagetagid + "/template.qcow2"
 cmd = ["qemu-img","create","-f","qcow2"]
 if parentImage is not None:
 cmd.append("-o")
@@ -264,21 +260,15 @@ class DockerSource(Source):
 subprocess.call(cmd)
 
 if parentImage is None:
-self.format_disk(templateImage,format,connect)
+self.format_disk(templateImage, "qcow2", connect)
 
 path = templatedir + "/" + imagetagid + "/template."
 self.extract_tarball(path + "qcow2",
- format,
+ "qcow2",
  path + "tar.gz",
  connect)
 parentImage = templateImage
 
-
-def _check_disk_format(self,format):
-supportedFormats = ['qcow2']
-if not format in supportedFormats:
-raise ValueError(["Unsupported image format %s" % format])
-
 def _get_image_list(self, template, destdir):
 imageparent = {}
 imagenames = {}
diff --git a/libvirt-sandbox/image/sources/Source.py 
b/libvirt-sandbox/image/sources/Source.py
index 15737c1..a31bab8 100644
--- a/libvirt-sandbox/image/sources/Source.py
+++ b/libvirt-sandbox/image/sources/Source.py
@@ -36,12 +36,11 @@ class Source():
 
 @abstractmethod
 def create_template(self, template, templatedir,
-connect=None, format=None):
+connect=None):
 """
 :param template: libvirt_sandbox.template.Template object
 :param templatedir: local directory path in which to store the template
 :param connect: libvirt connection URI
-:param format: disk image format
 
 Create a set of local disk images populated with the content
 of a template. The images creation process will be isolated
-- 
2.1.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [sandbox v2 5/5] virt-sandbox-image: add a virt-builder source

2015-10-05 Thread Cédric Bosdonnat
Allow virt-sandbox-image to pull templates from virt-builder and run
sandboxes on top of them.
---
 libvirt-sandbox.spec.in|  1 +
 libvirt-sandbox/image/cli.py   |  1 +
 libvirt-sandbox/image/sources/Makefile.am  |  1 +
 libvirt-sandbox/image/sources/VirtBuilderSource.py | 84 ++
 libvirt-sandbox/image/template.py  |  2 +
 5 files changed, 89 insertions(+)
 create mode 100644 libvirt-sandbox/image/sources/VirtBuilderSource.py

diff --git a/libvirt-sandbox.spec.in b/libvirt-sandbox.spec.in
index 54fde55..f84eabc 100644
--- a/libvirt-sandbox.spec.in
+++ b/libvirt-sandbox.spec.in
@@ -36,6 +36,7 @@ Requires: systemd >= 198
 Requires: pygobject3-base
 Requires: libselinux-python
 Requires: %{name}-libs = %{version}-%{release}
+Requires: %{_bindir}/virt-builder
 
 %package libs
 Group: Development/Libraries
diff --git a/libvirt-sandbox/image/cli.py b/libvirt-sandbox/image/cli.py
index 05d593a..f7fa8ee 100755
--- a/libvirt-sandbox/image/cli.py
+++ b/libvirt-sandbox/image/cli.py
@@ -172,6 +172,7 @@ Example supported URI formats:
   docker:///ubuntu?tag=15.04
   docker://username:passw...@index.docker.io/private/image
   docker://registry.access.redhat.com/rhel6
+  virt-builder:///fedora-20
 """)
 return parser
 
diff --git a/libvirt-sandbox/image/sources/Makefile.am 
b/libvirt-sandbox/image/sources/Makefile.am
index 069557d..52e9a7e 100644
--- a/libvirt-sandbox/image/sources/Makefile.am
+++ b/libvirt-sandbox/image/sources/Makefile.am
@@ -4,6 +4,7 @@ pythonimage_DATA = \
__init__.py \
Source.py \
DockerSource.py \
+   VirtBuilderSource.py \
$(NULL)
 
 EXTRA_DIST = $(pythonimage_DATA)
diff --git a/libvirt-sandbox/image/sources/VirtBuilderSource.py 
b/libvirt-sandbox/image/sources/VirtBuilderSource.py
new file mode 100644
index 000..3ce1867
--- /dev/null
+++ b/libvirt-sandbox/image/sources/VirtBuilderSource.py
@@ -0,0 +1,84 @@
+#!/usr/bin/python
+#
+# Copyright (C) 2015 SUSE LLC
+#
+# 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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  
USA
+#
+# Author: Cedric Bosdonnat 
+#
+
+from Source import Source
+import os
+import os.path
+import subprocess
+
+class VirtBuilderSource(Source):
+
+def _get_template_name(self, template):
+# We shouldn't have '/' in the names, but let's make sure
+# nobody can try to alter the folders structure later.
+return template.path[1:].replace('/', '_')
+
+def has_template(self, template, templatedir):
+imagepath = "%s/%s.qcow2" % (templatedir, template.path)
+return os.path.exists(imagepath)
+
+def create_template(self, template, templatedir, connect=None):
+if not os.path.exists(templatedir):
+os.makedirs(templatedir)
+
+# Get the image using virt-builder
+templatename = self._get_template_name(template)
+imagepath_original = "%s/%s-original.qcow2" % (templatedir, 
templatename)
+imagepath = "%s/%s.qcow2" % (templatedir, templatename)
+cmd = ["virt-builder", templatename,
+   "-o", imagepath_original, "--format", "qcow2"]
+subprocess.call(cmd)
+
+# We need to convert this image into a single partition one.
+tarfile = "%s/%s.tar" % (templatedir, templatename)
+cmd = ["virt-tar-out", "-a", imagepath_original, "/", tarfile]
+subprocess.call(cmd)
+
+os.unlink(imagepath_original)
+
+cmd = ["qemu-img", "create", "-q", "-f", "qcow2", imagepath, "10G"]
+subprocess.call(cmd)
+
+self.format_disk(imagepath, "qcow2", connect)
+self.extract_tarball(imagepath, "qcow2", tarfile, connect)
+os.unlink(tarfile)
+
+
+def delete_template(self, template, templatedir):
+os.unlink("%s/%s.qcow2" % (templatedir, 
self._get_template_name(template)))
+
+def get_command(self, template, templatedir, userargs):
+return userargs
+
+def get_disk(self,template, templatedir, imagedir, sandboxname):
+diskfile = "%s/%s.qcow2" % (templatedir, 
self._get_template_name(template))
+tempfile = imagedir + "/" + sandboxname + ".qcow2"
+if not os.path.exists(imagedir):
+os.makedirs(imagedir)
+cmd = ["qemu-img", "create", "-q",
+  

[libvirt] [sandbox v2 0/5] virt-builder source for virt-sandbox-image

2015-10-05 Thread Cédric Bosdonnat
Hi all,

Here is the new version of the virt-builder source with the download command
removed and the format parameter too.

Cédric Bosdonnat (5):
  virt-sandbox-image: remove the download command
  virt-image-sandbox: tarball extracting function to be reusable
  virt-sandbox-image: remove the format parameter
  virt-sandbox-image: automatically call create if needed
  virt-sandbox-image: add a virt-builder source

 libvirt-sandbox.spec.in|  1 +
 libvirt-sandbox/image/cli.py   | 29 +++-
 libvirt-sandbox/image/sources/DockerSource.py  | 61 
 libvirt-sandbox/image/sources/Makefile.am  |  1 +
 libvirt-sandbox/image/sources/Source.py| 29 ++--
 libvirt-sandbox/image/sources/VirtBuilderSource.py | 84 ++
 libvirt-sandbox/image/template.py  |  2 +
 7 files changed, 149 insertions(+), 58 deletions(-)
 create mode 100644 libvirt-sandbox/image/sources/VirtBuilderSource.py

-- 
2.1.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [sandbox v2 4/5] virt-sandbox-image: automatically call create if needed

2015-10-05 Thread Cédric Bosdonnat
To provide a smooth user experience, run automatically calls create if
needed.
---
 libvirt-sandbox/image/cli.py  |  5 +
 libvirt-sandbox/image/sources/DockerSource.py | 19 +++
 libvirt-sandbox/image/sources/Source.py   | 11 +++
 3 files changed, 35 insertions(+)

diff --git a/libvirt-sandbox/image/cli.py b/libvirt-sandbox/image/cli.py
index f067347..05d593a 100755
--- a/libvirt-sandbox/image/cli.py
+++ b/libvirt-sandbox/image/cli.py
@@ -42,6 +42,7 @@ if os.geteuid() == 0:
 else:
 default_template_dir = os.environ['HOME'] + 
"/.local/share/libvirt/templates"
 default_image_dir = os.environ['HOME'] + "/.local/share/libvirt/images"
+default_format = "qcow2"
 
 debug = False
 verbose = False
@@ -84,6 +85,10 @@ def run(args):
 tmpl = template.Template.from_uri(args.template)
 source = tmpl.get_source_impl()
 
+# Create the template image if needed
+if not source.has_template(tmpl, args.template_dir):
+create(args)
+
 name = args.name
 if name is None:
 randomid = ''.join(random.choice(string.lowercase) for i in range(10))
diff --git a/libvirt-sandbox/image/sources/DockerSource.py 
b/libvirt-sandbox/image/sources/DockerSource.py
index 1f6f94f..fb21bda 100644
--- a/libvirt-sandbox/image/sources/DockerSource.py
+++ b/libvirt-sandbox/image/sources/DockerSource.py
@@ -59,6 +59,22 @@ class DockerSource(Source):
 if  (major == 2 and sys.hexversion < py2_7_9_hexversion) or (major == 
3 and sys.hexversion < py3_4_3_hexversion):
 sys.stderr.write(SSL_WARNING)
 
+def _was_downloaded(self, template, templatedir):
+try:
+self._get_image_list(template, templatedir)
+return True
+except Exception:
+return False
+
+
+def has_template(self, template, templatedir):
+try:
+configfile, diskfile = self._get_template_data(template, 
templatedir)
+return os.path.exists(diskfile)
+except Exception:
+return False
+
+
 def download_template(self, template, templatedir):
 self._check_cert_validate()
 
@@ -244,6 +260,9 @@ class DockerSource(Source):
 def create_template(self, template, templatedir, connect=None):
 self.download_template(template, templatedir)
 
+if not self._was_downloaded(template, templatedir):
+self.download_template(template, templatedir)
+
 imagelist = self._get_image_list(template, templatedir)
 imagelist.reverse()
 
diff --git a/libvirt-sandbox/image/sources/Source.py 
b/libvirt-sandbox/image/sources/Source.py
index a31bab8..8f6ccba 100644
--- a/libvirt-sandbox/image/sources/Source.py
+++ b/libvirt-sandbox/image/sources/Source.py
@@ -34,6 +34,17 @@ class Source():
 def __init__(self):
 pass
 
+
+@abstractmethod
+def has_template(self, template, templatedir):
+"""
+:param template: libvirt_sandbox.template.Template object
+:param templatedir: local directory path in which to store the template
+
+Check if a template has already been created.
+"""
+pass
+
 @abstractmethod
 def create_template(self, template, templatedir,
 connect=None):
-- 
2.1.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [sandbox v2 1/5] virt-sandbox-image: remove the download command

2015-10-05 Thread Cédric Bosdonnat
The download command is now merged with the create one. There is no
real reason to keep those two separate.
---
 libvirt-sandbox/image/cli.py  | 14 --
 libvirt-sandbox/image/sources/DockerSource.py |  3 +++
 libvirt-sandbox/image/sources/Source.py   | 11 ---
 3 files changed, 3 insertions(+), 25 deletions(-)

diff --git a/libvirt-sandbox/image/cli.py b/libvirt-sandbox/image/cli.py
index a43da62..4500713 100755
--- a/libvirt-sandbox/image/cli.py
+++ b/libvirt-sandbox/image/cli.py
@@ -64,12 +64,6 @@ def debug(msg):
 def info(msg):
 sys.stdout.write(msg)
 
-def download(args):
-tmpl = template.Template.from_uri(args.template)
-source = tmpl.get_source_impl()
-source.download_template(template=tmpl,
- templatedir=args.template_dir)
-
 def delete(args):
 tmpl = template.Template.from_uri(args.template)
 source = tmpl.get_source_impl()
@@ -178,13 +172,6 @@ Example supported URI formats:
 """)
 return parser
 
-def gen_download_args(subparser):
-parser = gen_command_parser(subparser, "download",
-_("Download template data"))
-requires_template(parser)
-requires_template_dir(parser)
-parser.set_defaults(func=download)
-
 def gen_delete_args(subparser):
 parser = gen_command_parser(subparser, "delete",
 _("Delete template data"))
@@ -225,7 +212,6 @@ def main():
 parser = argparse.ArgumentParser(description="Sandbox Container Image 
Tool")
 
 subparser = parser.add_subparsers(help=_("commands"))
-gen_download_args(subparser)
 gen_delete_args(subparser)
 gen_create_args(subparser)
 gen_run_args(subparser)
diff --git a/libvirt-sandbox/image/sources/DockerSource.py 
b/libvirt-sandbox/image/sources/DockerSource.py
index 41df7a7..93d7f17 100644
--- a/libvirt-sandbox/image/sources/DockerSource.py
+++ b/libvirt-sandbox/image/sources/DockerSource.py
@@ -245,6 +245,9 @@ class DockerSource(Source):
 if format is None:
 format = "qcow2"
 self._check_disk_format(format)
+
+self.download_template(template, templatedir)
+
 imagelist = self._get_image_list(template, templatedir)
 imagelist.reverse()
 
diff --git a/libvirt-sandbox/image/sources/Source.py 
b/libvirt-sandbox/image/sources/Source.py
index 444baa3..708f2aa 100644
--- a/libvirt-sandbox/image/sources/Source.py
+++ b/libvirt-sandbox/image/sources/Source.py
@@ -35,17 +35,6 @@ class Source():
 pass
 
 @abstractmethod
-def download_template(self, template, templatedir):
-"""
-:param template: libvirt_sandbox.template.Template object
-:param templatedir: local directory path in which to store the template
-
-Download a template from the registry, storing it in the local
-filesystem
-"""
-pass
-
-@abstractmethod
 def create_template(self, template, templatedir,
 connect=None, format=None):
 """
-- 
2.1.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


  1   2   3   4   5   6   >