[libvirt] [PATCHv2 2/3] vmx: convert to typesafe virConf accessors

2018-05-26 Thread Fabiano Fidêncio
From: Fabiano Fidêncio 

Signed-off-by: Fabiano Fidêncio 
---
 src/vmx/vmx.c | 196 ++
 1 file changed, 73 insertions(+), 123 deletions(-)

diff --git a/src/vmx/vmx.c b/src/vmx/vmx.c
index df6a58a474..54542c29a6 100644
--- a/src/vmx/vmx.c
+++ b/src/vmx/vmx.c
@@ -720,41 +720,36 @@ virVMXConvertToUTF8(const char *encoding, const char 
*string)
 }
 
 
-
 static int
-virVMXGetConfigString(virConfPtr conf, const char *name, char **string,
-  bool optional)
+virVMXGetConfigStringHelper(virConfPtr conf, const char *name, char **string,
+bool optional)
 {
-virConfValuePtr value;
-
+int result;
 *string = NULL;
-value = virConfGetValue(conf, name);
 
-if (value == NULL) {
-if (optional)
-return 0;
+result = virConfGetValueString(conf, name, string);
+if (result == 1 && *string != NULL)
+return 1;
 
-virReportError(VIR_ERR_INTERNAL_ERROR,
-   _("Missing essential config entry '%s'"), name);
-return -1;
-}
+if (optional)
+return 0;
 
-if (value->type != VIR_CONF_STRING) {
-virReportError(VIR_ERR_INTERNAL_ERROR,
-   _("Config entry '%s' must be a string"), name);
-return -1;
-}
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   _("Missing essential config entry '%s'"), name);
+return -1;
+}
 
-if (value->str == NULL) {
-if (optional)
-return 0;
 
-virReportError(VIR_ERR_INTERNAL_ERROR,
-   _("Missing essential config entry '%s'"), name);
+static int
+virVMXGetConfigString(virConfPtr conf, const char *name, char **string,
+  bool optional)
+{
+*string = NULL;
+
+if (virVMXGetConfigStringHelper(conf, name, string, optional) < 0)
 return -1;
-}
 
-return VIR_STRDUP(*string, value->str);
+return 0;
 }
 
 
@@ -763,43 +758,26 @@ static int
 virVMXGetConfigUUID(virConfPtr conf, const char *name, unsigned char *uuid,
 bool optional)
 {
-virConfValuePtr value;
+char *string = NULL;
+int result;
 
-value = virConfGetValue(conf, name);
+result = virVMXGetConfigStringHelper(conf, name, , optional);
+if (result <= 0)
+return result;
 
-if (value == NULL) {
-if (optional) {
-return 0;
-} else {
-virReportError(VIR_ERR_INTERNAL_ERROR,
-   _("Missing essential config entry '%s'"), name);
-return -1;
-}
-}
-
-if (value->type != VIR_CONF_STRING) {
+if (virUUIDParse(string, uuid) < 0) {
 virReportError(VIR_ERR_INTERNAL_ERROR,
-   _("Config entry '%s' must be a string"), name);
-return -1;
+   _("Could not parse UUID from string '%s'"), string);
+result = -1;
+goto cleanup;
 }
 
-if (value->str == NULL) {
-if (optional) {
-return 0;
-} else {
-virReportError(VIR_ERR_INTERNAL_ERROR,
-   _("Missing essential config entry '%s'"), name);
-return -1;
-}
-}
+result = 0;
 
-if (virUUIDParse(value->str, uuid) < 0) {
-virReportError(VIR_ERR_INTERNAL_ERROR,
-   _("Could not parse UUID from string '%s'"), value->str);
-return -1;
-}
+  cleanup:
+VIR_FREE(string);
 
-return 0;
+return result;
 }
 
 
@@ -808,47 +786,35 @@ static int
 virVMXGetConfigLong(virConfPtr conf, const char *name, long long *number,
 long long default_, bool optional)
 {
-virConfValuePtr value;
+char *string = NULL;
+int result;
 
 *number = default_;
-value = virConfGetValue(conf, name);
 
-if (value == NULL) {
-if (optional) {
-return 0;
-} else {
-virReportError(VIR_ERR_INTERNAL_ERROR,
-   _("Missing essential config entry '%s'"), name);
-return -1;
-}
-}
+result = virVMXGetConfigStringHelper(conf, name, , optional);
+if (result <= 0)
+return result;
 
-if (value->type == VIR_CONF_STRING) {
-if (value->str == NULL) {
-if (optional) {
-return 0;
-} else {
-virReportError(VIR_ERR_INTERNAL_ERROR,
-   _("Missing essential config entry '%s'"), name);
-return -1;
-}
-}
+if (STRCASEEQ(string, "unlimited")) {
+*number = -1;
+result = 0;
+goto cleanup;
+}
 
-if (STRCASEEQ(value->str, "unlimited")) {
-*number = -1;
-} else if (virStrToLong_ll(value->str, NULL, 10, number) < 0) {
-virReportError(VIR_ERR_INTERNAL_ERROR,
-   _("Config 

[libvirt] [PATCHv2 3/3] xen_common: convert to typesafe virConf accessors

2018-05-26 Thread Fabiano Fidêncio
From: Fabiano Fidêncio 

There are still some places using virConfGetValue() and then checking
the specific type of the pointers and so on.

Those place are not going to be changed as:
- Directly using virConfGetValue*() would trigger virReportError() on
their current code
- Expanding virConfGetValue*() to support strings as other types (as
boolean or long) doesn't seem to be the safest path to take.

Signed-off-by: Fabiano Fidêncio 
---
 src/xenconfig/xen_common.c | 637 ++---
 1 file changed, 307 insertions(+), 330 deletions(-)

diff --git a/src/xenconfig/xen_common.c b/src/xenconfig/xen_common.c
index a2b0708ee3..2e8e95f720 100644
--- a/src/xenconfig/xen_common.c
+++ b/src/xenconfig/xen_common.c
@@ -145,31 +145,18 @@ xenConfigCopyStringInternal(virConfPtr conf,
 char **value,
 int allowMissing)
 {
-virConfValuePtr val;
+int result;
 
 *value = NULL;
-if (!(val = virConfGetValue(conf, name))) {
-if (allowMissing)
-return 0;
-virReportError(VIR_ERR_INTERNAL_ERROR,
-   _("config value %s was missing"), name);
-return -1;
-}
 
-if (val->type != VIR_CONF_STRING) {
-virReportError(VIR_ERR_INTERNAL_ERROR,
-   _("config value %s was not a string"), name);
-return -1;
-}
-if (!val->str) {
-if (allowMissing)
-return 0;
-virReportError(VIR_ERR_INTERNAL_ERROR,
-   _("config value %s was missing"), name);
-return -1;
-}
+result = virConfGetValueString(conf, name, value);
+if (result == 1 && *value != NULL)
+return 0;
+
+if (allowMissing)
+return 0;
 
-return VIR_STRDUP(*value, val->str);
+return -1;
 }
 
 
@@ -193,7 +180,8 @@ xenConfigCopyStringOpt(virConfPtr conf, const char *name, 
char **value)
 static int
 xenConfigGetUUID(virConfPtr conf, const char *name, unsigned char *uuid)
 {
-virConfValuePtr val;
+char *string = NULL;
+int result;
 
 if (!uuid || !name || !conf) {
 virReportError(VIR_ERR_INVALID_ARG, "%s",
@@ -201,35 +189,35 @@ xenConfigGetUUID(virConfPtr conf, const char *name, 
unsigned char *uuid)
 return -1;
 }
 
-if (!(val = virConfGetValue(conf, name))) {
-if (virUUIDGenerate(uuid) < 0) {
-virReportError(VIR_ERR_INTERNAL_ERROR,
-   "%s", _("Failed to generate UUID"));
-return -1;
-} else {
-return 0;
-}
-}
-
-if (val->type != VIR_CONF_STRING) {
-virReportError(VIR_ERR_CONF_SYNTAX,
-   _("config value %s not a string"), name);
+if (virConfGetValueString(conf, name, ) < 0)
 return -1;
-}
 
-if (!val->str) {
+if (!string) {
 virReportError(VIR_ERR_CONF_SYNTAX,
_("%s can't be empty"), name);
 return -1;
 }
 
-if (virUUIDParse(val->str, uuid) < 0) {
+if (virUUIDGenerate(uuid) < 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   "%s", _("Failed to generate UUID"));
+result = -1;
+goto cleanup;
+}
+
+if (virUUIDParse(string, uuid) < 0) {
 virReportError(VIR_ERR_CONF_SYNTAX,
-   _("%s not parseable"), val->str);
-return -1;
+   _("%s not parseable"), string);
+result = -1;
+goto cleanup;
 }
 
-return 0;
+result = 1;
+
+ cleanup:
+VIR_FREE(string);
+
+return result;
 }
 
 
@@ -242,23 +230,15 @@ xenConfigGetString(virConfPtr conf,
const char **value,
const char *def)
 {
-virConfValuePtr val;
+char *string = NULL;
 
-*value = NULL;
-if (!(val = virConfGetValue(conf, name))) {
+if (virConfGetValueString(conf, name, ) < 0) {
 *value = def;
-return 0;
-}
-
-if (val->type != VIR_CONF_STRING) {
-virReportError(VIR_ERR_INTERNAL_ERROR,
-   _("config value %s was malformed"), name);
 return -1;
 }
-if (!val->str)
-*value = def;
-else
-*value = val->str;
+
+*value = string != NULL ? string : def;
+
 return 0;
 }
 
@@ -392,93 +372,92 @@ xenParseEventsActions(virConfPtr conf, virDomainDefPtr 
def)
 static int
 xenParsePCI(virConfPtr conf, virDomainDefPtr def)
 {
-virConfValuePtr list = virConfGetValue(conf, "pci");
 virDomainHostdevDefPtr hostdev = NULL;
+char **pcis = NULL, **entries;
 
-if (list && list->type == VIR_CONF_LIST) {
-list = list->list;
-while (list) {
-char domain[5];
-char bus[3];
-char slot[3];
-char func[2];
-char *key, *nextkey;
-int domainID;
-int busID;
-int slotID;
-int funcID;
-
-   

[libvirt] [PATCHv2 0/3] Finish the conversion to virConfGetValue* functions

2018-05-26 Thread Fabiano Fidêncio
This patchset finishes the conversion to virConfGetValue* functions,
started by Daniel Berrange a few months ago.

Please, mind that although we could make virConfGetValue* functions more
generic in order to support numbers and booleans as strings, that
doesn't seem the safest path to take. The side-effect of this is that we
will have to live with some specific code doing that as part of vmx and
xen_common.

Once this patchset gets merged,
https://wiki.libvirt.org/page/BiteSizedTasks#Finish_conversion_to_virConfGetValue.2A_functions
can be removed.

- Changes since v1:
  All the "values" from virConfGetValueString() are freed

Fabiano Fidêncio (3):
  xen_vm: convert to typesafe virConf accessors
  vmx: convert to typesafe virConf accessors
  xen_common: convert to typesafe virConf accessors

 src/vmx/vmx.c  | 196 ++
 src/xenconfig/xen_common.c | 637 ++---
 src/xenconfig/xen_xm.c | 268 ++-
 3 files changed, 512 insertions(+), 589 deletions(-)

-- 
2.14.3

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

[libvirt] [PATCHv2 1/3] xen_vm: convert to typesafe virConf accessors

2018-05-26 Thread Fabiano Fidêncio
From: Fabiano Fidêncio 

Signed-off-by: Fabiano Fidêncio 
---
 src/xenconfig/xen_xm.c | 268 -
 1 file changed, 132 insertions(+), 136 deletions(-)

diff --git a/src/xenconfig/xen_xm.c b/src/xenconfig/xen_xm.c
index 4becb40b4c..fc88ac8238 100644
--- a/src/xenconfig/xen_xm.c
+++ b/src/xenconfig/xen_xm.c
@@ -112,172 +112,168 @@ xenParseXMDisk(virConfPtr conf, virDomainDefPtr def)
 {
 virDomainDiskDefPtr disk = NULL;
 int hvm = def->os.type == VIR_DOMAIN_OSTYPE_HVM;
-virConfValuePtr list = virConfGetValue(conf, "disk");
+char **disks = NULL, **entries;
 
-if (list && list->type == VIR_CONF_LIST) {
-list = list->list;
-while (list) {
-char *head;
-char *offset;
-char *tmp;
-const char *src;
+if (virConfGetValueStringList(conf, "disk", false, ) < 0)
+goto cleanup;
 
-if ((list->type != VIR_CONF_STRING) || (list->str == NULL))
-goto skipdisk;
+for (entries = disks; *entries; entries++) {
+char *head = *entries;
+char *offset;
+char *tmp;
+const char *src;
 
-head = list->str;
-if (!(disk = virDomainDiskDefNew(NULL)))
-return -1;
+if (!(disk = virDomainDiskDefNew(NULL)))
+return -1;
+
+/*
+ * Disks have 3 components, SOURCE,DEST-DEVICE,MODE
+ * eg, phy:/dev/HostVG/XenGuest1,xvda,w
+ * The SOURCE is usually prefixed with a driver type,
+ * and optionally driver sub-type
+ * The DEST-DEVICE is optionally post-fixed with disk type
+ */
+
+/* Extract the source file path*/
+if (!(offset = strchr(head, ',')))
+goto skipdisk;
+
+if (offset == head) {
+/* No source file given, eg CDROM with no media */
+ignore_value(virDomainDiskSetSource(disk, NULL));
+} else {
+if (VIR_STRNDUP(tmp, head, offset - head) < 0)
+goto cleanup;
+
+if (virDomainDiskSetSource(disk, tmp) < 0) {
+VIR_FREE(tmp);
+goto cleanup;
+}
+VIR_FREE(tmp);
+}
 
-/*
- * Disks have 3 components, SOURCE,DEST-DEVICE,MODE
- * eg, phy:/dev/HostVG/XenGuest1,xvda,w
- * The SOURCE is usually prefixed with a driver type,
- * and optionally driver sub-type
- * The DEST-DEVICE is optionally post-fixed with disk type
- */
-
-/* Extract the source file path*/
-if (!(offset = strchr(head, ',')))
-goto skipdisk;
-
-if (offset == head) {
-/* No source file given, eg CDROM with no media */
-ignore_value(virDomainDiskSetSource(disk, NULL));
-} else {
-if (VIR_STRNDUP(tmp, head, offset - head) < 0)
+head = offset + 1;
+/* Remove legacy ioemu: junk */
+if (STRPREFIX(head, "ioemu:"))
+head = head + 6;
+
+/* Extract the dest device name */
+if (!(offset = strchr(head, ',')))
+goto skipdisk;
+
+if (VIR_ALLOC_N(disk->dst, (offset - head) + 1) < 0)
+goto cleanup;
+
+if (virStrncpy(disk->dst, head, offset - head,
+   (offset - head) + 1) == NULL) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   _("Dest file %s too big for destination"), head);
+goto cleanup;
+}
+
+head = offset + 1;
+/* Extract source driver type */
+src = virDomainDiskGetSource(disk);
+if (src) {
+size_t len;
+/* The main type  phy:, file:, tap: ... */
+if ((tmp = strchr(src, ':')) != NULL) {
+len = tmp - src;
+if (VIR_STRNDUP(tmp, src, len) < 0)
 goto cleanup;
 
-if (virDomainDiskSetSource(disk, tmp) < 0) {
+if (virDomainDiskSetDriver(disk, tmp) < 0) {
 VIR_FREE(tmp);
 goto cleanup;
 }
 VIR_FREE(tmp);
-}
-
-head = offset + 1;
-/* Remove legacy ioemu: junk */
-if (STRPREFIX(head, "ioemu:"))
-head = head + 6;
-
-/* Extract the dest device name */
-if (!(offset = strchr(head, ',')))
-goto skipdisk;
 
-if (VIR_ALLOC_N(disk->dst, (offset - head) + 1) < 0)
-goto cleanup;
+/* Strip the prefix we found off the source file name */
+if (virDomainDiskSetSource(disk, src + len + 1) < 0)
+goto cleanup;
 
-if (virStrncpy(disk->dst, head, offset - head,
-   (offset - head) + 1) == NULL) {
-

Re: [libvirt] [PATCH v2 12/12] news: Document new API introduction

2018-05-26 Thread Ján Tomko

On Thu, May 24, 2018 at 01:13:39PM +0200, Michal Privoznik wrote:

Signed-off-by: Michal Privoznik 
---
docs/news.xml | 8 
1 file changed, 8 insertions(+)



Reviewed-by: Ján Tomko 

Jano


signature.asc
Description: Digital signature
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCH v2 11/12] qemu: Implement virDomainDetachDeviceAlias

2018-05-26 Thread Ján Tomko

On Thu, May 24, 2018 at 01:13:38PM +0200, Michal Privoznik wrote:

Signed-off-by: Michal Privoznik 
---
src/qemu/qemu_driver.c | 108 +
1 file changed, 108 insertions(+)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 81a9833b39..6f0a3d0cda 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -8750,6 +8750,77 @@ qemuDomainDetachDeviceLiveAndConfig(virQEMUDriverPtr 
driver,
return ret;
}

+
+static int
+qemuDomainDetachDeviceAliasLiveAndConfig(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ const char *alias,
+ unsigned int flags)
+{
+virCapsPtr caps = NULL;
+virQEMUDriverConfigPtr cfg = NULL;
+virDomainDefPtr def = NULL;
+virDomainDefPtr persistentDef = NULL;
+virDomainDefPtr vmdef = NULL;
+unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE;


Why on earth would we need parse_flags to detach a device?


+int ret = -1;
+
+virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+  VIR_DOMAIN_AFFECT_CONFIG, -1);
+
+if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
+goto cleanup;
+
+cfg = virQEMUDriverGetConfig(driver);
+
+if ((flags & VIR_DOMAIN_AFFECT_CONFIG) &&
+!(flags & VIR_DOMAIN_AFFECT_LIVE))
+parse_flags |= VIR_DOMAIN_DEF_PARSE_INACTIVE;
+
+if (virDomainObjGetDefs(vm, flags, , ) < 0)
+goto cleanup;
+
+if (persistentDef) {
+virDomainDeviceDef dev;
+
+vmdef = virDomainObjCopyPersistentDef(vm, caps, driver->xmlopt);
+if (!vmdef)
+goto cleanup;
+
+if (virDomainDefFindDevice(persistentDef, alias, , true) < 0)
+goto cleanup;
+
+if (qemuDomainDetachDeviceConfig(persistentDef, , caps,
+ parse_flags, driver->xmlopt) < 0)


Oh, somebody thought it would be a good idea to call postParse even
though no parsing has happened

Reviewed-by: Ján Tomko 

Jano


signature.asc
Description: Digital signature
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCH v2 10/12] qemu_hotplug: Allow asynchronous detach

2018-05-26 Thread Ján Tomko

On Thu, May 24, 2018 at 01:13:37PM +0200, Michal Privoznik wrote:

The virDomainDetachDeviceAlias API is designed so that it only
sends detach request to qemu. It's user's responsibility to wait


s/user/the user/


for DEVICE_DELETED event, not libvirt's. Add @async flag to
qemuDomainDetach*Device() functions so that caller can chose if
detach is semi-synchronous (old virDomainDetachDeviceFlags()) or
fully asynchronous (new virDomainDetachDeviceFlags()).

Signed-off-by: Michal Privoznik 
---
src/qemu/qemu_driver.c  |  32 +++
src/qemu/qemu_hotplug.c | 231 
src/qemu/qemu_hotplug.h |  33 ---
tests/qemuhotplugtest.c |  13 +--
4 files changed, 203 insertions(+), 106 deletions(-)

@@ -4769,18 +4771,24 @@ qemuDomainDetachVirtioDiskDevice(virQEMUDriverPtr 
driver,
if (qemuDomainObjExitMonitor(driver, vm) < 0)
goto cleanup;

-if ((ret = qemuDomainWaitForDeviceRemoval(vm)) == 1)
-ret = qemuDomainRemoveDiskDevice(driver, vm, detach);
+if (async) {
+ret = 0;
+} else {
+if ((ret = qemuDomainWaitForDeviceRemoval(vm)) == 1)
+ret = qemuDomainRemoveDiskDevice(driver, vm, detach);
+}


I'm sure the ret assignments could be reduced here, but that's out of
scope of this series...

Also, most of the code is executed if (!async). It might be nicer to
come up with a variable that can be used in a positive condition,
but it would be less precise, because only the new async API is
reasonably defined - even if (wait) does not seem to outweigh
the loss of clarity.



 cleanup:
-qemuDomainResetDeviceRemoval(vm);
+if (!async)
+qemuDomainResetDeviceRemoval(vm);
return ret;
}

static int
qemuDomainDetachDiskDevice(virQEMUDriverPtr driver,
   virDomainObjPtr vm,
-   virDomainDiskDefPtr detach)
+   virDomainDiskDefPtr detach,
+   bool async)
{
int ret = -1;
qemuDomainObjPrivatePtr priv = vm->privateData;
@@ -5336,7 +5375,8 @@ qemuDomainDetachWatchdog(virQEMUDriverPtr driver,
return -1;
}

-qemuDomainMarkDeviceForRemoval(vm, >info);
+if (!async)
+qemuDomainMarkDeviceForRemoval(vm, >info);

qemuDomainObjEnterMonitor(driver, vm);
if (qemuMonitorDelDevice(priv->mon, watchdog->info.alias) < 0) {


Missing condition around qemuDomainWaitForDeviceRemoval here in
qemuDomainDetachWatchdog. It should only be called if (!async).

With that fixed:

Reviewed-by: Ján Tomko 

Jano


signature.asc
Description: Digital signature
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH 2/1] nwfilter: Fix IP address learning

2018-05-26 Thread John Ferlan
In a previous commit:

   commit d4bf8f415074759baf051644559e04fe7f8b
   Author: Daniel P. Berrangé 
   Date:   Wed Feb 14 09:43:59 2018 +

 nwfilter: handle missing switch enum cases

 Ensure all enum cases are listed in switch statements, or cast away
 enum type in places where we don't wish to cover all cases.

 Reviewed-by: John Ferlan 
 Signed-off-by: Daniel P. Berrangé 

we changed a switch in the nwfilter learning thread so that it had
explict cases for all enum entries. Unfortunately the parameters in the
method had been declared with incorrect type. The "howDetect" parameter
does *not* accept "enum howDetect" values, rather it accepts a bitmask
of "enum howDetect" values, so it should have been an "int" type.

The caller always passes DETECT_STATIC|DETECT_DHCP, so essentially the
IP addressing learning was completely broken by the above change, as it
never matched any switch case, hitting the default leading to EINVAL.

Rather than treat the howDetect as a numerical enum, let's treat it
as a bitmask/flag since that's the way it's used. Thus, the switch
changes to a simple if bit is set keeping the original intention that
if @howDetect == DETECT_DHCP, then use applyDHCPOnlyRules; otherwise,
use applyBasicRules to determine the IP Address.

Proposed-by: Daniel P. Berrangé 
Signed-off-by: John Ferlan 
---

 Here's to hoping I've used the correct magic incantation to get this
 to reply to Daniel's poll series as this should be pushed in
 conjunction with that (and thus would need review). This should be
 done before the 4.4.0 release.

 BTW: This also fixes a strange phenomena I was seeing in my testing
  environment where domain startups would periodically fail with:

  error: Failed to start domain f23
  error: Machine 'qemu-6-f23' already exists

  but could be started with enough retry attempts. What causes me
  to believe there's a relationship with this series is that if
  running libvirtd debug, I see the following as output:


  Detaching after fork from child process 22442.
  2018-05-25 20:37:24.966+: 25923: error :
  virSystemdCreateMachine:361 : Machine 'qemu-6-f23' already exists
  2018-05-25 20:37:24.988+: 22440: error :
  learnIPAddressThread:668   : encountered an error on interface
  vnet0 index 150: Invalid argument
  [Thread 0x7fffacdb7700 (LWP 22440) exited]

  With these two patches in place, no more errors.

 src/nwfilter/nwfilter_learnipaddr.c | 27 +--
 src/nwfilter/nwfilter_learnipaddr.h | 10 +-
 2 files changed, 18 insertions(+), 19 deletions(-)

diff --git a/src/nwfilter/nwfilter_learnipaddr.c 
b/src/nwfilter/nwfilter_learnipaddr.c
index 506b98fd07..ab2697274c 100644
--- a/src/nwfilter/nwfilter_learnipaddr.c
+++ b/src/nwfilter/nwfilter_learnipaddr.c
@@ -145,7 +145,7 @@ struct _virNWFilterIPAddrLearnReq {
 char *filtername;
 virHashTablePtr filterparams;
 virNWFilterDriverStatePtr driver;
-enum howDetect howDetect;
+virNWFilterLearnIPHowDetectFlags howDetect;
 
 int status;
 volatile bool terminate;
@@ -344,7 +344,7 @@ virNWFilterDeregisterLearnReq(int ifindex)
 static void
 procDHCPOpts(struct dhcp *dhcp, int dhcp_opts_len,
  uint32_t *vmaddr, uint32_t *bcastaddr,
- enum howDetect *howDetected)
+ virNWFilterLearnIPHowDetectFlags *howDetected)
 {
 struct dhcp_option *dhcpopt = >options[0];
 
@@ -413,7 +413,7 @@ learnIPAddressThread(void *arg)
 char *filter = NULL;
 uint16_t etherType;
 bool showError = true;
-enum howDetect howDetected = 0;
+virNWFilterLearnIPHowDetectFlags howDetected = 0;
 virNWFilterTechDriverPtr techdriver = req->techdriver;
 struct pollfd fds[1];
 
@@ -442,28 +442,27 @@ learnIPAddressThread(void *arg)
 
 virMacAddrFormat(>macaddr, macaddr);
 
-switch (req->howDetect) {
-case DETECT_DHCP:
+if (req->howDetect == DETECT_DHCP) {
 if (techdriver->applyDHCPOnlyRules(req->ifname,
>macaddr,
NULL, false) < 0) {
+VIR_DEBUG("Unable to apply DHCP only rules");
 req->status = EINVAL;
 goto done;
 }
 virBufferAddLit(, "src port 67 and dst port 68");
-break;
-case DETECT_STATIC:
+} else {
+/* howDetect == DETECT_DHCP ||
+ * howDetect == (DETECT_DHCP | DETECT_STATIC)
+ */
 if (techdriver->applyBasicRules(req->ifname,
 >macaddr) < 0) {
+VIR_DEBUG("Unable to apply basic rules");
 req->status = EINVAL;
 goto done;
 }
 virBufferAsprintf(, "ether host %s or ether dst ff:ff:ff:ff:ff:ff",
   

Re: [libvirt] [PATCH] nwfilter: fix IP address learning

2018-05-26 Thread John Ferlan


On 05/18/2018 07:59 AM, Daniel P. Berrangé wrote:
> In a previous commit:
> 
>   commit d4bf8f415074759baf051644559e04fe7f8b
>   Author: Daniel P. Berrangé 
>   Date:   Wed Feb 14 09:43:59 2018 +
> 
> nwfilter: handle missing switch enum cases
> 
> Ensure all enum cases are listed in switch statements, or cast away
> enum type in places where we don't wish to cover all cases.
> 
> Reviewed-by: John Ferlan 
> Signed-off-by: Daniel P. Berrangé 
> 
> we changed a switch in the nwfilter learning thread so that it had
> explict cases for all enum entries. Unfortunately the parameters in the
> method had been declared with incorrect type. The "howDetect" parameter
> does *not* accept "enum howDetect" values, rather it accepts a bitmask
> of "enum howDetect" values, so it should have been an "int" type.
> 
> The caller always passes DETECT_STATIC|DETECT_DHCP, so essentially the
> IP addressing learning was completely broken by the above change, as it
> never matched any switch case, hitting the default leading to EINVAL.
> 
> Signed-off-by: Daniel P. Berrangé 
> ---
>  src/nwfilter/nwfilter_learnipaddr.c | 13 ++---
>  src/nwfilter/nwfilter_learnipaddr.h |  2 +-
>  2 files changed, 7 insertions(+), 8 deletions(-)
> 

This is a companion patch to:

https://www.redhat.com/archives/libvir-list/2018-May/msg01484.html

Still, perhaps to avoid future issues the howDetect related code should
adopt a bitmask model...

Since  Daniel is away and it'd be good to get this into this release
(before he returns) I'll propose an alternative...

John


> diff --git a/src/nwfilter/nwfilter_learnipaddr.c 
> b/src/nwfilter/nwfilter_learnipaddr.c
> index cc3bfd971c..061b39d72b 100644
> --- a/src/nwfilter/nwfilter_learnipaddr.c
> +++ b/src/nwfilter/nwfilter_learnipaddr.c
> @@ -144,7 +144,7 @@ struct _virNWFilterIPAddrLearnReq {
>  char *filtername;
>  virHashTablePtr filterparams;
>  virNWFilterDriverStatePtr driver;
> -enum howDetect howDetect;
> +int howDetect; /* bitmask of enum howDetect */
>  
>  int status;
>  volatile bool terminate;
> @@ -442,23 +442,22 @@ learnIPAddressThread(void *arg)
>  if (techdriver->applyDHCPOnlyRules(req->ifname,
> >macaddr,
> NULL, false) < 0) {
> +VIR_DEBUG("Unable to apply DHCP only rules");
>  req->status = EINVAL;
>  goto done;
>  }
>  virBufferAddLit(, "src port 67 and dst port 68");
>  break;
> -case DETECT_STATIC:
> +default:
>  if (techdriver->applyBasicRules(req->ifname,
>  >macaddr) < 0) {
> +VIR_DEBUG("Unable to apply basic rules");
>  req->status = EINVAL;
>  goto done;
>  }
>  virBufferAsprintf(, "ether host %s or ether dst 
> ff:ff:ff:ff:ff:ff",
>macaddr);
>  break;
> -default:
> -req->status = EINVAL;
> -goto done;
>  }
>  
>  if (virBufferError()) {
> @@ -693,7 +692,7 @@ learnIPAddressThread(void *arg)
>   *   once its IP address has been detected
>   * @driver : the network filter driver
>   * @howDetect : the method on how the thread is supposed to detect the
> - *  IP address; must choose any of the available flags
> + *  IP address; bitmask of "enum howDetect" flags.
>   *
>   * Instruct to learn the IP address being used on a given interface (ifname).
>   * Unless there already is a thread attempting to learn the IP address
> @@ -711,7 +710,7 @@ virNWFilterLearnIPAddress(virNWFilterTechDriverPtr 
> techdriver,
>const char *filtername,
>virHashTablePtr filterparams,
>virNWFilterDriverStatePtr driver,
> -  enum howDetect howDetect)
> +  int howDetect)
>  {
>  int rc;
>  virThread thread;
> diff --git a/src/nwfilter/nwfilter_learnipaddr.h 
> b/src/nwfilter/nwfilter_learnipaddr.h
> index 06fea5bff8..753aabc594 100644
> --- a/src/nwfilter/nwfilter_learnipaddr.h
> +++ b/src/nwfilter/nwfilter_learnipaddr.h
> @@ -43,7 +43,7 @@ int virNWFilterLearnIPAddress(virNWFilterTechDriverPtr 
> techdriver,
>const char *filtername,
>virHashTablePtr filterparams,
>virNWFilterDriverStatePtr driver,
> -  enum howDetect howDetect);
> +  int howDetect);
>  
>  bool virNWFilterHasLearnReq(int ifindex);
>  int virNWFilterTerminateLearnReq(const char *ifname);
> 

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

Re: [libvirt] [PATCH] nwfilter: directly use poll to wait for packets instead of pcap_next

2018-05-26 Thread John Ferlan


On 05/21/2018 08:15 AM, Daniel P. Berrangé wrote:
> When a QEMU VM shuts down its TAP device gets deleted while nwfilter
> IP address learning thread is still capturing packets. It is seen that
> with TPACKET_V3 support in libcap, the pcap_next() call will not always
> exit its poll() when the NIC is removed. This prevents the learning
> thread from exiting which blocks the rest of libvirtd waiting on mutex
> acquisition. By switching to do poll() in libvirt code, we can ensure
> that we always exit the poll() at a time that is right for libvirt.
> 
> Signed-off-by: Daniel P. Berrangé 
> ---
>  src/nwfilter/nwfilter_learnipaddr.c | 37 +++--
>  1 file changed, 35 insertions(+), 2 deletions(-)
> 

FWIW: This patch is related to:

https://www.redhat.com/archives/libvir-list/2018-May/msg01440.html

Reviewed-by: John Ferlan 

I think this needs to be pushed before the release! Since Daniel is
away, I can take care of that.  I will wait for Monday though to ensure
there's no objection...

There's also a companion patch:

https://www.redhat.com/archives/libvir-list/2018-May/msg01429.html

but I have some issues with that and will post an alternative that would
also need to be pushed before the release.

John

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

Re: [libvirt] [PATCH v2 09/12] qemuDomainDetachDeviceLiveAndConfig: Avoid overwriting @ret

2018-05-26 Thread Ján Tomko

On Thu, May 24, 2018 at 01:13:36PM +0200, Michal Privoznik wrote:

The fact that we are overwriting @ret multiple times is very
confusing to see what is actually happening here.


-EPARSE
s/is very confusing/makes it difficult to see/


Follow our
traditional pattern where @ret is initialized to -1, and set to 0
only in case we know we succeeded.

Signed-off-by: Michal Privoznik 
---
src/qemu/qemu_driver.c | 24 
1 file changed, 12 insertions(+), 12 deletions(-)



Reviewed-by: Ján Tomko 

Jano


signature.asc
Description: Digital signature
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCH v2 08/12] qemuDomainDetachDeviceLiveAndConfig: Don't use driver->caps directly

2018-05-26 Thread Ján Tomko

On Thu, May 24, 2018 at 01:13:35PM +0200, Michal Privoznik wrote:

Funny, we obtain driver caps at the beginning of the function,
but then for unknown reason access driver->caps directly.

Signed-off-by: Michal Privoznik 
---
src/qemu/qemu_driver.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)



Reviewed-by: Ján Tomko 

Jano


signature.asc
Description: Digital signature
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCH v2 07/12] qemu_hotplug: Use more gotos in qemuDomainDetach*Device

2018-05-26 Thread Ján Tomko

On Thu, May 24, 2018 at 01:13:34PM +0200, Michal Privoznik wrote:

We are overwriting @ret a lot. It makes hard to see what is
actually going on. Use more gotos. Two functions are fixed here:
qemuDomainDetachShmemDevice() and qemuDomainDetachWatchdog().

Signed-off-by: Michal Privoznik 
---
src/qemu/qemu_hotplug.c | 42 ++
1 file changed, 22 insertions(+), 20 deletions(-)



Reviewed-by: Ján Tomko 

Jano


signature.asc
Description: Digital signature
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCH v2 06/12] qemuDomainDetachWatchdog: Don't release watchdog address twice

2018-05-26 Thread Ján Tomko

On Thu, May 24, 2018 at 01:13:33PM +0200, Michal Privoznik wrote:

On watchdog unplug, when qemu doesn't support DEVICE_DELETED event
(or couple of other reasons) we do two things:

1) release watchdog device address,
2) call qemuDomainRemoveWatchdog() which does 1) again.

This is potentially dangerous.

Signed-off-by: Michal Privoznik 
---
src/qemu/qemu_hotplug.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)



Reviewed-by: Ján Tomko 

Jano


signature.asc
Description: Digital signature
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCH v2 05/12] qemuDomainDetachShmemDevice: Don't release shmem address twice

2018-05-26 Thread Ján Tomko

On Thu, May 24, 2018 at 01:13:32PM +0200, Michal Privoznik wrote:

On shmem unplug, when qemu doesn't support DEVICE_DELETED event
(or couple of other reasons) we do two things:

1) release shmem device address,
2) call qemuDomainRemoveShmemDevice() which does 1) again.

This is potentially dangerous.

Signed-off-by: Michal Privoznik 
---
src/qemu/qemu_hotplug.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)



Reviewed-by: Ján Tomko 

Jano


signature.asc
Description: Digital signature
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCH v2 04/12] qemuDomainRemoveChrDevice: Release device address

2018-05-26 Thread Ján Tomko

On Thu, May 24, 2018 at 01:13:31PM +0200, Michal Privoznik wrote:

Instead of releasing address only sometimes in
qemuDomainDetachChrDevice() let's release it whenever the device
is actually removed from the domain definition.

Signed-off-by: Michal Privoznik 
---
src/qemu/qemu_hotplug.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)



Reviewed-by: Ján Tomko 

Jano


signature.asc
Description: Digital signature
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCH v2 03/12] virsh: Expose virDomainDetachDeviceAlias

2018-05-26 Thread Ján Tomko

On Thu, May 24, 2018 at 01:13:30PM +0200, Michal Privoznik wrote:

Signed-off-by: Michal Privoznik 
---
tools/virsh-domain.c | 72 
tools/virsh.pod  | 12 +
2 files changed, 84 insertions(+)

diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index cfbbf5a7bc..26f7983540 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -11878,6 +11878,72 @@ cmdDetachDevice(vshControl *ctl, const vshCmd *cmd)
return funcRet;
}

+
+/*
+ * "detach-device-alias" command
+ */
+static const vshCmdInfo info_detach_device_alias[] = {
+{.name = "help",
+ .data = N_("detach device from an alias")
+},
+{.name = "desc",
+ .data = N_("Detach device from domain using given alias to identify 
device")


"from a domain" feels better. Or even:
Detach device identified by the given alias from a domain


+},
+{.name = NULL}
+};
+


[...]


+static bool
+cmdDetachDeviceAlias(vshControl *ctl, const vshCmd *cmd)
+{
+virDomainPtr dom = NULL;
+const char *alias = NULL;
+bool current = vshCommandOptBool(cmd, "current");
+bool config = vshCommandOptBool(cmd, "config");
+bool live = vshCommandOptBool(cmd, "live");
+unsigned int flags = VIR_DOMAIN_AFFECT_CURRENT;
+bool ret = false;
+
+VSH_EXCLUSIVE_OPTIONS_VAR(current, live);
+VSH_EXCLUSIVE_OPTIONS_VAR(current, config);
+
+if (config)
+flags |= VIR_DOMAIN_AFFECT_CONFIG;
+if (live)
+flags |= VIR_DOMAIN_AFFECT_LIVE;
+
+if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
+return false;
+
+if (vshCommandOptStringReq(ctl, cmd, "alias", ) < 0)
+goto cleanup;
+
+if (virDomainDetachDeviceAlias(dom, alias, flags) < 0) {
+vshError(ctl, _("Failed to detach device with alias %s"), alias);
+goto cleanup;
+}
+
+vshPrintExtra(ctl, "%s", _("Device detached successfully\n"));


Or, to match the semantics of the API more closely:
"Device detach request sent successfully\n"


+ret = true;
+
+ cleanup:
+virshDomainFree(dom);
+return ret;
+}
+
+
/*
 * "update-device" command
 */
@@ -13999,6 +14065,12 @@ const vshCmdDef domManagementCmds[] = {
 .info = info_detach_device,
 .flags = 0
},
+{.name = "detach-device-alias",
+ .handler = cmdDetachDeviceAlias,
+ .opts = opts_detach_device_alias,
+ .info = info_detach_device_alias,
+ .flags = 0
+},
{.name = "detach-disk",
 .handler = cmdDetachDisk,
 .opts = opts_detach_disk,
diff --git a/tools/virsh.pod b/tools/virsh.pod
index 929958a953..45c1a3f271 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -3112,6 +3112,18 @@ an offline domain, and like I<--live> I<--config> for a 
running domain.
Note that older versions of virsh used I<--config> as an alias for
I<--persistent>.

+=item B I I
+[[[I<--live>] [I<--config>] | [I<--current>]] | [I<--persistent>]]
+
+Detach a device with given I from the I.
+
+If I<--live> is specified, affect a running domain.
+If I<--config> is specified, affect the next startup of a persistent domain.
+If I<--current> is specified, affect the current domain state.
+Both I<--live> and I<--config> flags may be given, but I<--current> is
+exclusive.



When no flag is specified legacy API is used whose behavior depends
+on the hypervisor driver.
+


Drop this sentence, it is not relevant for the new API.

Reviewed-by: Ján Tomko 

Jano


signature.asc
Description: Digital signature
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCH v2 02/12] remote: Implement virDomainDetachDeviceAlias

2018-05-26 Thread Ján Tomko

On Thu, May 24, 2018 at 01:13:29PM +0200, Michal Privoznik wrote:

Signed-off-by: Michal Privoznik 
---
src/remote/remote_driver.c   |  1 +
src/remote/remote_protocol.x | 16 +++-
src/remote_protocol-structs  |  6 ++
3 files changed, 22 insertions(+), 1 deletion(-)



Reviewed-by: Ján Tomko 

Jano


signature.asc
Description: Digital signature
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCH v2 01/12] Introduce virDomainDetachDeviceAlias API

2018-05-26 Thread Ján Tomko

On Thu, May 24, 2018 at 01:13:28PM +0200, Michal Privoznik wrote:

When detaching a device it can be uniquely identified by its
alias. Instead of misusing virDomainDetachDeviceFlags which has
the same signature introduce new function.


s/new/a new/



Signed-off-by: Michal Privoznik 
---
include/libvirt/libvirt-domain.h |  3 +++
src/driver-hypervisor.h  |  6 +
src/libvirt-domain.c | 53 
src/libvirt_public.syms  |  5 
4 files changed, 67 insertions(+)

diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c
index 2d86e48979..e536781e38 100644
--- a/src/libvirt-domain.c
+++ b/src/libvirt-domain.c
@@ -8349,6 +8349,59 @@ virDomainUpdateDeviceFlags(virDomainPtr domain,
}


+/**
+ * virDomainDetachDeviceAlias:
+ * @domain: pointer to domain object


s/domain/a domain/

or even

d/pointer to /


+ * @alias: device alias
+ * @flags: bitwise-OR of virDomainDeviceModifyFlags
+ *
+ * Detach a virtual device from a domain, using the alias to
+ * specify device. The value of @flags should be either


s/device/the device/


+ * VIR_DOMAIN_AFFECT_CURRENT, or a bitwise-or of values from
+ * VIR_DOMAIN_AFFECT_LIVE and VIR_DOMAIN_AFFECT_CURRENT, although
+ * hypervisors vary in which flags are supported.
+ *
+ * In contrast to virDomainDetachDeviceFlags() this API only send
+ * request to the hypervisor and returns immediately.


this API is asynchronous - it returns immediately after sending
the detach request to the hypervisor.


It's
+ * caller's responsibility to wait for


s/caller/the caller/


+ * VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED event to signal actual
+ * device removal.
+ *
+ * Returns 0 in case of success, -1 in case of failure.
+ */
+int
+virDomainDetachDeviceAlias(virDomainPtr domain,
+   const char *alias,
+   unsigned int flags)


Reviewed-by: Ján Tomko 

Jano


signature.asc
Description: Digital signature
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list