[libvirt] [PATCH] build: fix PROBE() usage of intptr_t
by Eric Blake
Otherwise, in locations like virobject.c where PROBE is used,
for certain configure options, the compiler warns:
util/virobject.c:110:1: error: 'intptr_t' undeclared (first use in this function)
As long as we are making this header always available, we can
clean up several other files.
* src/internal.h (includes): Pull in <stdint.h>.
* src/conf/nwfilter_conf.h: Rely on internal.h.
* src/storage/storage_backend.c: Likewise.
* src/storage/storage_backend.h: Likewise.
* src/util/cgroup.c: Likewise.
* src/util/sexpr.h: Likewise.
* src/util/virhashcode.h: Likewise.
* src/util/virnetdevvportprofile.h: Likewise.
* src/util/virnetlink.h: Likewise.
* src/util/virrandom.h: Likewise.
* src/vbox/vbox_driver.c: Likewise.
* src/xenapi/xenapi_driver.c: Likewise.
* src/xenapi/xenapi_utils.c: Likewise.
* src/xenapi/xenapi_utils.h: Likewise.
* src/xenxs/xenxs_private.h: Likewise.
* tests/storagebackendsheepdogtest.c: Likewise.
Reported by Matthias Bolte.
---
Almost qualifies for the build-breaker rule, except that I didn't
reproduce the particular configure settings that Matthias was
experiencing on IRC.
src/conf/nwfilter_conf.h | 5 +----
src/internal.h | 1 +
src/storage/storage_backend.c | 1 -
src/storage/storage_backend.h | 3 +--
src/util/cgroup.c | 1 -
src/util/sexpr.h | 8 ++------
src/util/virhashcode.h | 1 -
src/util/virnetdevvportprofile.h | 4 +---
src/util/virnetlink.h | 2 --
src/util/virrandom.h | 1 -
src/vbox/vbox_driver.c | 4 +---
src/xenapi/xenapi_driver.c | 1 -
src/xenapi/xenapi_utils.c | 1 -
src/xenapi/xenapi_utils.h | 2 +-
src/xenxs/xenxs_private.h | 3 +--
tests/storagebackendsheepdogtest.c | 2 --
16 files changed, 9 insertions(+), 31 deletions(-)
diff --git a/src/conf/nwfilter_conf.h b/src/conf/nwfilter_conf.h
index 8b05d04..ca6bd16 100644
--- a/src/conf/nwfilter_conf.h
+++ b/src/conf/nwfilter_conf.h
@@ -2,7 +2,7 @@
* nwfilter_conf.h: network filter XML processing
* (derived from storage_conf.h)
*
- * Copyright (C) 2006-2010 Red Hat, Inc.
+ * Copyright (C) 2006-2010, 2012 Red Hat, Inc.
* Copyright (C) 2006-2008 Daniel P. Berrange
*
* Copyright (C) 2010 IBM Corporation
@@ -26,9 +26,6 @@
#ifndef NWFILTER_CONF_H
# define NWFILTER_CONF_H
-# include <stdint.h>
-# include <stddef.h>
-
# include "internal.h"
# include "util.h"
diff --git a/src/internal.h b/src/internal.h
index fd8d190..300de3a 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -9,6 +9,7 @@
# include <limits.h>
# include <verify.h>
# include <stdbool.h>
+# include <stdint.h>
# if STATIC_ANALYSIS
# undef NDEBUG /* Don't let a prior NDEBUG definition cause trouble. */
diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c
index 4a2109e..df3833a 100644
--- a/src/storage/storage_backend.c
+++ b/src/storage/storage_backend.c
@@ -32,7 +32,6 @@
#include <sys/wait.h>
#include <unistd.h>
#include <fcntl.h>
-#include <stdint.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <dirent.h>
diff --git a/src/storage/storage_backend.h b/src/storage/storage_backend.h
index bafd6b6..5352f5d 100644
--- a/src/storage/storage_backend.h
+++ b/src/storage/storage_backend.h
@@ -1,7 +1,7 @@
/*
* storage_backend.h: internal storage driver backend contract
*
- * Copyright (C) 2007-2010 Red Hat, Inc.
+ * Copyright (C) 2007-2010, 2012 Red Hat, Inc.
* Copyright (C) 2007-2008 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
@@ -24,7 +24,6 @@
#ifndef __VIR_STORAGE_BACKEND_H__
# define __VIR_STORAGE_BACKEND_H__
-# include <stdint.h>
# include "internal.h"
# include "storage_conf.h"
# include "command.h"
diff --git a/src/util/cgroup.c b/src/util/cgroup.c
index 6c29c87..2256c23 100644
--- a/src/util/cgroup.c
+++ b/src/util/cgroup.c
@@ -24,7 +24,6 @@
#include <config.h>
#include <stdio.h>
-#include <stdint.h>
#if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
# include <mntent.h>
#endif
diff --git a/src/util/sexpr.h b/src/util/sexpr.h
index 8dfd89a..b4b41ed 100644
--- a/src/util/sexpr.h
+++ b/src/util/sexpr.h
@@ -1,9 +1,8 @@
/*
* sexpr.h : S-Expression interfaces needed to communicate with the Xen Daemon
*
- * Copyright (C) 2005
- *
- * Anthony Liguori <aliguori(a)us.ibm.com>
+ * Copyright (C) 2012 Red Hat, Inc.
+ * Copyright (C) 2005 Anthony Liguori <aliguori(a)us.ibm.com>
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License. See the file COPYING.LIB in the main directory of this
@@ -16,9 +15,6 @@
# include "internal.h"
# include "buf.h"
-# include <sys/types.h>
-# include <stdint.h>
-
enum sexpr_type {
SEXPR_NIL,
SEXPR_CONS,
diff --git a/src/util/virhashcode.h b/src/util/virhashcode.h
index 2fb7a95..34254b6 100644
--- a/src/util/virhashcode.h
+++ b/src/util/virhashcode.h
@@ -29,7 +29,6 @@
# define __VIR_HASH_CODE_H__
# include "internal.h"
-# include <stdint.h>
extern uint32_t virHashCodeGen(const void *key, size_t len, uint32_t seed);
diff --git a/src/util/virnetdevvportprofile.h b/src/util/virnetdevvportprofile.h
index 6cce1bb..f33da18 100644
--- a/src/util/virnetdevvportprofile.h
+++ b/src/util/virnetdevvportprofile.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2011 Red Hat, Inc.
+ * Copyright (C) 2009-2012 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -23,8 +23,6 @@
#ifndef __VIR_NETDEV_VPORT_PROFILE_H__
# define __VIR_NETDEV_VPORT_PROFILE_H__
-# include <stdint.h>
-
# include "internal.h"
# include "uuid.h"
# include "util.h"
diff --git a/src/util/virnetlink.h b/src/util/virnetlink.h
index 1997c8d..5d8337d 100644
--- a/src/util/virnetlink.h
+++ b/src/util/virnetlink.h
@@ -24,8 +24,6 @@
# include "internal.h"
# include "virmacaddr.h"
-# include <stdint.h>
-
# if defined(__linux__) && defined(HAVE_LIBNL)
# include <netlink/msg.h>
diff --git a/src/util/virrandom.h b/src/util/virrandom.h
index 8d3cad7..29a055d 100644
--- a/src/util/virrandom.h
+++ b/src/util/virrandom.h
@@ -23,7 +23,6 @@
# define __VIR_RANDOM_H__
# include "internal.h"
-# include <stdint.h>
uint64_t virRandomBits(int nbits);
int virRandomGenerateWWN(char **wwn, const char *virt_type);
diff --git a/src/vbox/vbox_driver.c b/src/vbox/vbox_driver.c
index b340b7c..c4037f8 100644
--- a/src/vbox/vbox_driver.c
+++ b/src/vbox/vbox_driver.c
@@ -3,7 +3,7 @@
*/
/*
- * Copyright (C) 2010-2011 Red Hat, Inc.
+ * Copyright (C) 2010-2012 Red Hat, Inc.
* Copyright (C) 2008-2009 Sun Microsystems, Inc.
*
* This file is part of a free software library; you can redistribute
@@ -29,9 +29,7 @@
#include <config.h>
-#include <stdint.h>
#include <unistd.h>
-#include <sys/types.h>
#include "internal.h"
diff --git a/src/xenapi/xenapi_driver.c b/src/xenapi/xenapi_driver.c
index 5608de8..f57449e 100644
--- a/src/xenapi/xenapi_driver.c
+++ b/src/xenapi/xenapi_driver.c
@@ -23,7 +23,6 @@
#include <config.h>
#include <limits.h>
-#include <stdint.h>
#include <string.h>
#include <curl/curl.h>
#include <xen/api/xen_all.h>
diff --git a/src/xenapi/xenapi_utils.c b/src/xenapi/xenapi_utils.c
index 3031a17..d62192a 100644
--- a/src/xenapi/xenapi_utils.c
+++ b/src/xenapi/xenapi_utils.c
@@ -24,7 +24,6 @@
#include <stdio.h>
#include <string.h>
-#include <stdint.h>
#include <xen/api/xen_all.h>
#include "internal.h"
#include "domain_conf.h"
diff --git a/src/xenapi/xenapi_utils.h b/src/xenapi/xenapi_utils.h
index 5912446..86af07c 100644
--- a/src/xenapi/xenapi_utils.h
+++ b/src/xenapi/xenapi_utils.h
@@ -1,5 +1,6 @@
/*
* xenapi_utils.h: Xen API driver -- utils header
+ * Copyright (C) 2012, Red Hat, Inc.
* Copyright (C) 2009, 2010 Citrix Ltd.
*
* This library is free software; you can redistribute it and/or
@@ -22,7 +23,6 @@
#ifndef __VIR_XENAPI_UTILS__
# define __VIR_XENAPI_UTILS__
-# include <stdint.h>
# include <xen/api/xen_all.h>
# include "internal.h"
# include "viruri.h"
diff --git a/src/xenxs/xenxs_private.h b/src/xenxs/xenxs_private.h
index d0ba59a..17b481b 100644
--- a/src/xenxs/xenxs_private.h
+++ b/src/xenxs/xenxs_private.h
@@ -1,8 +1,8 @@
/*
* xenxs_private.h: Private definitions for Xen parsing
*
+ * Copyright (C) 2007, 2010, 2012 Red Hat, Inc.
* Copyright (C) 2011 Univention GmbH
- * Copyright (C) 2007, 2010 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -27,7 +27,6 @@
# include "internal.h"
-# include <stdint.h>
# include <xen/xen.h>
# include "xen_sxpr.h"
diff --git a/tests/storagebackendsheepdogtest.c b/tests/storagebackendsheepdogtest.c
index b7b3b35..ba5bc36 100644
--- a/tests/storagebackendsheepdogtest.c
+++ b/tests/storagebackendsheepdogtest.c
@@ -25,10 +25,8 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
-#include <stdint.h>
#include <string.h>
-#include <sys/types.h>
#include <fcntl.h>
#include "internal.h"
--
1.7.11.2
12 years, 8 months
[libvirt] [PATCH] esx: Implement network driver
by Matthias Bolte
An ESX server has one or more PhysicalNics that represent the actual
hardware NICs. Those can be listed via the interface driver.
A libvirt virtual network is mapped to a HostVirtualSwitch. On the
physical side a HostVirtualSwitch can be connected to PhysicalNics.
On the virtual side a HostVirtualSwitch has HostPortGroups that are
mapped to libvirt virtual network's portgroups. Typically there is
HostPortGroups named 'VM Network' that is used to connect virtual
machines to a HostVirtualSwitch. A second HostPortGroup typically
named 'Management Network' is used to connect the hypervisor itself
to the HostVirtualSwitch. This one is not mapped to a libvirt virtual
network's portgroup. There can be more HostPortGroups than those
typical two on a HostVirtualSwitch.
+---------------+-------------------+
...---| | | +-------------+
| HostPortGroup | |---| PhysicalNic |
| VM Network | | | vmnic0 |
...---| | | +-------------+
+---------------+ HostVirtualSwitch |
| vSwitch0 |
+---------------+ |
| HostPortGroup | |
...---| Management | |
| Network | |
+---------------+-------------------+
The virtual counterparts of the PhysicalNic is the HostVirtualNic for
the hypervisor and the VirtualEthernetCard for the virtual machines
that are grouped into HostPortGroups.
+---------------------+ +---------------+---...
| VirtualEthernetCard |---| |
+---------------------+ | HostPortGroup |
+---------------------+ | VM Network |
| VirtualEthernetCard |---| |
+---------------------+ +---------------+
|
+---------------+
+---------------------+ | HostPortGroup |
| HostVirtualNic |---| Management |
+---------------------+ | Network |
+---------------+---...
The currently implemented network driver can list, define and undefine
HostVirtualSwitches including HostPortGroups for virtual machines.
Existing HostVirtualSwitches cannot be edited yet. This will be added
in a followup patch.
---
po/POTFILES.in | 1 +
src/conf/network_conf.c | 3 +-
src/conf/network_conf.h | 3 +
src/esx/esx_network_driver.c | 867 +++++++++++++++++++++++++++++++++++++++-
src/esx/esx_vi.c | 171 ++++++++
src/esx/esx_vi.h | 14 +
src/esx/esx_vi_generator.input | 151 +++++++
src/esx/esx_vi_generator.py | 5 +
8 files changed, 1212 insertions(+), 3 deletions(-)
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 37a00ee..e617952 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -27,6 +27,7 @@ src/cpu/cpu_x86.c
src/datatypes.c
src/driver.c
src/esx/esx_driver.c
+src/esx/esx_network_driver.c
src/esx/esx_storage_driver.c
src/esx/esx_util.c
src/esx/esx_vi.c
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index eb92d93..a3714d9 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -47,8 +47,6 @@
#define MAX_BRIDGE_ID 256
#define VIR_FROM_THIS VIR_FROM_NETWORK
-VIR_ENUM_DECL(virNetworkForward)
-
VIR_ENUM_IMPL(virNetworkForward,
VIR_NETWORK_FORWARD_LAST,
"none", "nat", "route", "bridge", "private", "vepa", "passthrough" )
@@ -967,6 +965,7 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
goto error;
}
VIR_FREE(tmp);
+ def->uuid_specified = true;
}
/* Parse network domain information */
diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h
index 1c640a9..a95b382 100644
--- a/src/conf/network_conf.h
+++ b/src/conf/network_conf.h
@@ -148,6 +148,7 @@ typedef struct _virNetworkDef virNetworkDef;
typedef virNetworkDef *virNetworkDefPtr;
struct _virNetworkDef {
unsigned char uuid[VIR_UUID_BUFLEN];
+ bool uuid_specified;
char *name;
char *bridge; /* Name of bridge device */
@@ -289,4 +290,6 @@ int virNetworkObjIsDuplicate(virNetworkObjListPtr doms,
void virNetworkObjLock(virNetworkObjPtr obj);
void virNetworkObjUnlock(virNetworkObjPtr obj);
+VIR_ENUM_DECL(virNetworkForward)
+
#endif /* __NETWORK_CONF_H__ */
diff --git a/src/esx/esx_network_driver.c b/src/esx/esx_network_driver.c
index 2e0e40b..b42f1d8 100644
--- a/src/esx/esx_network_driver.c
+++ b/src/esx/esx_network_driver.c
@@ -4,7 +4,7 @@
* host networks
*
* Copyright (C) 2010-2011 Red Hat, Inc.
- * Copyright (C) 2010 Matthias Bolte <matthias.bolte(a)googlemail.com>
+ * Copyright (C) 2010-2012 Matthias Bolte <matthias.bolte(a)googlemail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -24,11 +24,13 @@
#include <config.h>
+#include "md5.h"
#include "internal.h"
#include "util.h"
#include "memory.h"
#include "logging.h"
#include "uuid.h"
+#include "network_conf.h"
#include "esx_private.h"
#include "esx_network_driver.h"
#include "esx_vi.h"
@@ -37,6 +39,12 @@
#define VIR_FROM_THIS VIR_FROM_ESX
+/*
+ * The UUID of a network is the MD5 sum of it's key. Therefore, verify that
+ * UUID and MD5 sum match in size, because we rely on that.
+ */
+verify(MD5_DIGEST_SIZE == VIR_UUID_BUFLEN);
+
static virDrvOpenStatus
@@ -67,10 +75,867 @@ esxNetworkClose(virConnectPtr conn)
+static int
+esxNumberOfNetworks(virConnectPtr conn)
+{
+ esxPrivate *priv = conn->networkPrivateData;
+ esxVI_HostVirtualSwitch *hostVirtualSwitchList = NULL;
+ esxVI_HostVirtualSwitch *hostVirtualSwitch = NULL;
+ int count = 0;
+
+ if (esxVI_EnsureSession(priv->primary) < 0 ||
+ esxVI_LookupHostVirtualSwitchList(priv->primary,
+ &hostVirtualSwitchList) < 0) {
+ return -1;
+ }
+
+ for (hostVirtualSwitch = hostVirtualSwitchList; hostVirtualSwitch != NULL;
+ hostVirtualSwitch = hostVirtualSwitch->_next) {
+ ++count;
+ }
+
+ esxVI_HostVirtualSwitch_Free(&hostVirtualSwitchList);
+
+ return count;
+}
+
+
+
+static int
+esxListNetworks(virConnectPtr conn, char **const names, int maxnames)
+{
+ bool success = false;
+ esxPrivate *priv = conn->networkPrivateData;
+ esxVI_HostVirtualSwitch *hostVirtualSwitchList = NULL;
+ esxVI_HostVirtualSwitch *hostVirtualSwitch = NULL;
+ int count = 0;
+ int i;
+
+ if (maxnames == 0) {
+ return 0;
+ }
+
+ if (esxVI_EnsureSession(priv->primary) < 0 ||
+ esxVI_LookupHostVirtualSwitchList(priv->primary,
+ &hostVirtualSwitchList) < 0) {
+ return -1;
+ }
+
+ for (hostVirtualSwitch = hostVirtualSwitchList; hostVirtualSwitch != NULL;
+ hostVirtualSwitch = hostVirtualSwitch->_next) {
+ names[count] = strdup(hostVirtualSwitch->name);
+
+ if (names[count] == NULL) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ ++count;
+ }
+
+ success = true;
+
+ cleanup:
+ if (! success) {
+ for (i = 0; i < count; ++i) {
+ VIR_FREE(names[i]);
+ }
+
+ count = -1;
+ }
+
+ esxVI_HostVirtualSwitch_Free(&hostVirtualSwitchList);
+
+ return count;
+}
+
+
+
+static int
+esxNumberOfDefinedNetworks(virConnectPtr conn ATTRIBUTE_UNUSED)
+{
+ /* ESX networks are always active */
+ return 0;
+}
+
+
+
+static int
+esxListDefinedNetworks(virConnectPtr conn ATTRIBUTE_UNUSED,
+ char **const names ATTRIBUTE_UNUSED,
+ int maxnames ATTRIBUTE_UNUSED)
+{
+ /* ESX networks are always active */
+ return 0;
+}
+
+
+
+static virNetworkPtr
+esxNetworkLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
+{
+ virNetworkPtr network = NULL;
+ esxPrivate *priv = conn->networkPrivateData;
+ esxVI_HostVirtualSwitch *hostVirtualSwitchList = NULL;
+ esxVI_HostVirtualSwitch *hostVirtualSwitch = NULL;
+ unsigned char md5[MD5_DIGEST_SIZE]; /* MD5_DIGEST_SIZE = VIR_UUID_BUFLEN = 16 */
+ char uuid_string[VIR_UUID_STRING_BUFLEN] = "";
+
+ if (esxVI_EnsureSession(priv->primary) < 0 ||
+ esxVI_LookupHostVirtualSwitchList(priv->primary,
+ &hostVirtualSwitchList) < 0) {
+ return NULL;
+ }
+
+ for (hostVirtualSwitch = hostVirtualSwitchList; hostVirtualSwitch != NULL;
+ hostVirtualSwitch = hostVirtualSwitch->_next) {
+ md5_buffer(hostVirtualSwitch->key, strlen(hostVirtualSwitch->key), md5);
+
+ if (memcmp(uuid, md5, VIR_UUID_BUFLEN) == 0) {
+ break;
+ }
+ }
+
+ if (hostVirtualSwitch == NULL) {
+ virUUIDFormat(uuid, uuid_string);
+
+ virReportError(VIR_ERR_NO_NETWORK,
+ _("Could not find HostVirtualSwitch with UUID '%s'"),
+ uuid_string);
+
+ goto cleanup;
+ }
+
+ network = virGetNetwork(conn, hostVirtualSwitch->name, uuid);
+
+ cleanup:
+ esxVI_HostVirtualSwitch_Free(&hostVirtualSwitchList);
+
+ return network;
+}
+
+
+
+static virNetworkPtr
+esxNetworkLookupByName(virConnectPtr conn, const char *name)
+{
+ virNetworkPtr network = NULL;
+ esxPrivate *priv = conn->networkPrivateData;
+ esxVI_HostVirtualSwitch *hostVirtualSwitch = NULL;
+ unsigned char md5[MD5_DIGEST_SIZE]; /* MD5_DIGEST_SIZE = VIR_UUID_BUFLEN = 16 */
+
+ if (esxVI_EnsureSession(priv->primary) < 0 ||
+ esxVI_LookupHostVirtualSwitchByName(priv->primary, name,
+ &hostVirtualSwitch,
+ esxVI_Occurrence_RequiredItem) < 0) {
+ return NULL;
+ }
+
+ /*
+ * HostVirtualSwitch doesn't have a UUID, but we can use the key property
+ * as source for a UUID. The key is unique per host and cannot change
+ * during the lifetime of the HostVirtualSwitch.
+ *
+ * The MD5 sum of the key can be used as UUID, assuming MD5 is considered
+ * to be collision-free enough for this use case.
+ */
+ md5_buffer(hostVirtualSwitch->key, strlen(hostVirtualSwitch->key), md5);
+
+ network = virGetNetwork(conn, hostVirtualSwitch->name, md5);
+
+ esxVI_HostVirtualSwitch_Free(&hostVirtualSwitch);
+
+ return network;
+}
+
+
+
+static int
+esxBandwidthToShapingPolicy(virNetDevBandwidthPtr bandwidth,
+ esxVI_HostNetworkTrafficShapingPolicy **shapingPolicy)
+{
+ int result = -1;
+
+ if (shapingPolicy == NULL || *shapingPolicy != NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
+ return -1;
+ }
+
+ if (bandwidth->in == NULL || bandwidth->out == NULL ||
+ bandwidth->in->average != bandwidth->out->average ||
+ bandwidth->in->peak != bandwidth->out->peak ||
+ bandwidth->in->burst != bandwidth->out->burst) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Different inbound and outbound bandwidth is unsupported"));
+ return -1;
+ }
+
+ if (bandwidth->in->average == 0 && bandwidth->in->peak == 0 &&
+ bandwidth->in->burst == 0) {
+ return 0;
+ }
+
+ if (esxVI_HostNetworkTrafficShapingPolicy_Alloc(shapingPolicy) < 0) {
+ goto cleanup;
+ }
+
+ (*shapingPolicy)->enabled = esxVI_Boolean_True;
+
+ if (bandwidth->in->average > 0) {
+ if (esxVI_Long_Alloc(&(*shapingPolicy)->averageBandwidth) < 0) {
+ goto cleanup;
+ }
+
+ /* Scale kilobytes per second to bits per second */
+ (*shapingPolicy)->averageBandwidth->value = bandwidth->in->average * 8 * 1000;
+ }
+
+ if (bandwidth->in->peak > 0) {
+ if (esxVI_Long_Alloc(&(*shapingPolicy)->peakBandwidth) < 0) {
+ goto cleanup;
+ }
+
+ /* Scale kilobytes per second to bits per second */
+ (*shapingPolicy)->peakBandwidth->value = bandwidth->in->peak * 8 * 1000;
+ }
+
+ if (bandwidth->in->burst > 0) {
+ if (esxVI_Long_Alloc(&(*shapingPolicy)->burstSize) < 0) {
+ goto cleanup;
+ }
+
+ /* Scale kilobytes to bytes */
+ (*shapingPolicy)->burstSize->value = bandwidth->in->burst * 1024;
+ }
+
+ result = 0;
+
+ cleanup:
+ if (result < 0) {
+ esxVI_HostNetworkTrafficShapingPolicy_Free(shapingPolicy);
+ }
+
+ return result;
+}
+
+
+
+static virNetworkPtr
+esxNetworkDefineXML(virConnectPtr conn, const char *xml)
+{
+ virNetworkPtr network = NULL;
+ esxPrivate *priv = conn->networkPrivateData;
+ virNetworkDefPtr def = NULL;
+ esxVI_HostVirtualSwitch *hostVirtualSwitch = NULL;
+ esxVI_HostPortGroup *hostPortGroupList = NULL;
+ esxVI_HostPortGroup *hostPortGroup = NULL;
+ esxVI_HostVirtualSwitchSpec *hostVirtualSwitchSpec = NULL;
+ esxVI_HostVirtualSwitchBondBridge *hostVirtualSwitchBondBridge = NULL;
+ esxVI_PhysicalNic *physicalNicList = NULL;
+ esxVI_PhysicalNic *physicalNic = NULL;
+ esxVI_HostPortGroupSpec *hostPortGroupSpec = NULL;
+ int i;
+
+ unsigned char md5[MD5_DIGEST_SIZE]; /* MD5_DIGEST_SIZE = VIR_UUID_BUFLEN = 16 */
+
+ if (esxVI_EnsureSession(priv->primary) < 0) {
+ return NULL;
+ }
+
+ /* Parse network XML */
+ def = virNetworkDefParseString(xml);
+
+ if (def == NULL) {
+ return NULL;
+ }
+
+ /* Check if an existing HostVirtualSwitch should be edited */
+ if (esxVI_LookupHostVirtualSwitchByName(priv->primary, def->name,
+ &hostVirtualSwitch,
+ esxVI_Occurrence_OptionalItem) < 0) {
+ goto cleanup;
+ }
+
+ if (hostVirtualSwitch != NULL) {
+ /* FIXME */
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("HostVirtualSwitch already exists, editing existing "
+ "ones is not supported yet"));
+ goto cleanup;
+ }
+
+ /* UUID is derived from the HostVirtualSwitch's key and cannot be specified */
+ if (def->uuid_specified) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Cannot use predefined UUID"));
+ goto cleanup;
+ }
+
+ /* FIXME: Add support for NAT */
+ if (def->forwardType != VIR_NETWORK_FORWARD_NONE &&
+ def->forwardType != VIR_NETWORK_FORWARD_BRIDGE) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Unsupported forward mode '%s'"),
+ virNetworkForwardTypeToString(def->forwardType));
+ goto cleanup;
+ }
+
+ /* Verify that specified HostPortGroups don't exist already */
+ if (def->nPortGroups > 0) {
+ if (esxVI_LookupHostPortGroupList(priv->primary, &hostPortGroupList) < 0) {
+ goto cleanup;
+ }
+
+ for (i = 0; i < def->nPortGroups; ++i) {
+ for (hostPortGroup = hostPortGroupList; hostPortGroup != NULL;
+ hostPortGroup = hostPortGroup->_next) {
+ if (STREQ(def->portGroups[i].name, hostPortGroup->spec->name)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("HostPortGroup with name '%s' exists already"),
+ def->portGroups[i].name);
+ goto cleanup;
+ }
+ }
+ }
+ }
+
+ /* Create HostVirtualSwitch */
+ if (esxVI_HostVirtualSwitchSpec_Alloc(&hostVirtualSwitchSpec) < 0 ||
+ esxVI_Int_Alloc(&hostVirtualSwitchSpec->numPorts) < 0) {
+ goto cleanup;
+ }
+
+ if (def->forwardType != VIR_NETWORK_FORWARD_NONE && def->nForwardIfs > 0) {
+ if (esxVI_HostVirtualSwitchBondBridge_Alloc
+ (&hostVirtualSwitchBondBridge) < 0) {
+ goto cleanup;
+ }
+
+ hostVirtualSwitchSpec->bridge =
+ (esxVI_HostVirtualSwitchBridge *)hostVirtualSwitchBondBridge;
+
+ /* Lookup PhysicalNic list and match by name to get key */
+ if (esxVI_LookupPhysicalNicList(priv->primary, &physicalNicList) < 0) {
+ goto cleanup;
+ }
+
+ for (i = 0; i < def->nForwardIfs; ++i) {
+ bool found = false;
+
+ for (physicalNic = physicalNicList; physicalNic != NULL;
+ physicalNic = physicalNic->_next) {
+ if (STREQ(def->forwardIfs[i].dev, physicalNic->device)) {
+ if (esxVI_String_AppendValueToList
+ (&hostVirtualSwitchBondBridge->nicDevice,
+ physicalNic->key) < 0) {
+ goto cleanup;
+ }
+
+ found = true;
+ break;
+ }
+ }
+
+ if (! found) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not find PhysicalNic with name '%s'"),
+ def->forwardIfs[i].dev);
+ goto cleanup;
+ }
+ }
+ }
+
+ hostVirtualSwitchSpec->numPorts->value = 128;
+
+ if (def->bandwidth != NULL) {
+ if (esxVI_HostNetworkPolicy_Alloc(&hostVirtualSwitchSpec->policy) < 0) {
+ goto cleanup;
+ }
+
+ if (esxBandwidthToShapingPolicy
+ (def->bandwidth,
+ &hostVirtualSwitchSpec->policy->shapingPolicy) < 0) {
+ goto cleanup;
+ }
+ }
+
+ if (esxVI_AddVirtualSwitch
+ (priv->primary,
+ priv->primary->hostSystem->configManager->networkSystem,
+ def->name, hostVirtualSwitchSpec) < 0) {
+ goto cleanup;
+ }
+
+ /* Create HostPortGroup(s) */
+ for (i = 0; i < def->nPortGroups; ++i) {
+ esxVI_HostPortGroupSpec_Free(&hostPortGroupSpec);
+
+ if (esxVI_HostPortGroupSpec_Alloc(&hostPortGroupSpec) < 0 ||
+ esxVI_HostNetworkPolicy_Alloc(&hostPortGroupSpec->policy) < 0 ||
+ esxVI_Int_Alloc(&hostPortGroupSpec->vlanId) < 0 ||
+ esxVI_String_DeepCopyValue(&hostPortGroupSpec->name,
+ def->portGroups[i].name) < 0 ||
+ esxVI_String_DeepCopyValue(&hostPortGroupSpec->vswitchName,
+ def->name) < 0) {
+ goto cleanup;
+ }
+
+ hostPortGroupSpec->vlanId->value = 0;
+
+ if (def->portGroups[i].bandwidth != NULL) {
+ if (esxBandwidthToShapingPolicy
+ (def->portGroups[i].bandwidth,
+ &hostPortGroupSpec->policy->shapingPolicy) < 0) {
+ goto cleanup;
+ }
+ }
+
+ if (esxVI_AddPortGroup
+ (priv->primary,
+ priv->primary->hostSystem->configManager->networkSystem,
+ hostPortGroupSpec) < 0) {
+ goto cleanup;
+ }
+ }
+
+ /* Lookup created HostVirtualSwitch to get the UUID */
+ if (esxVI_LookupHostVirtualSwitchByName(priv->primary, def->name,
+ &hostVirtualSwitch,
+ esxVI_Occurrence_RequiredItem) < 0) {
+ goto cleanup;
+ }
+
+ md5_buffer(hostVirtualSwitch->key, strlen(hostVirtualSwitch->key), md5);
+
+ network = virGetNetwork(conn, hostVirtualSwitch->name, md5);
+
+ cleanup:
+ virNetworkDefFree(def);
+ esxVI_HostVirtualSwitch_Free(&hostVirtualSwitch);
+ esxVI_HostPortGroup_Free(&hostPortGroupList);
+ esxVI_HostVirtualSwitchSpec_Free(&hostVirtualSwitchSpec);
+ esxVI_PhysicalNic_Free(&physicalNicList);
+ esxVI_HostPortGroupSpec_Free(&hostPortGroupSpec);
+
+ return network;
+}
+
+
+
+static int
+esxNetworkUndefine(virNetworkPtr network)
+{
+ int result = -1;
+ esxPrivate *priv = network->conn->networkPrivateData;
+ esxVI_HostVirtualSwitch *hostVirtualSwitch = NULL;
+ esxVI_HostPortGroup *hostPortGroupList = NULL;
+ esxVI_String *hostPortGroupKey = NULL;
+ esxVI_HostPortGroup *hostPortGroup = NULL;
+ esxVI_HostPortGroupPort *hostPortGroupPort = NULL;
+
+ if (esxVI_EnsureSession(priv->primary) < 0) {
+ return -1;
+ }
+
+ /* Lookup HostVirtualSwitch and HostPortGroup list*/
+ if (esxVI_LookupHostVirtualSwitchByName(priv->primary, network->name,
+ &hostVirtualSwitch,
+ esxVI_Occurrence_RequiredItem) < 0 ||
+ esxVI_LookupHostPortGroupList(priv->primary, &hostPortGroupList) < 0) {
+ goto cleanup;
+ }
+
+ /* Verify that the HostVirtualSwitch is connected to virtual machines only */
+ for (hostPortGroupKey = hostVirtualSwitch->portgroup;
+ hostPortGroupKey != NULL; hostPortGroupKey = hostPortGroupKey->_next) {
+ bool found = false;
+
+ for (hostPortGroup = hostPortGroupList; hostPortGroup != NULL;
+ hostPortGroup = hostPortGroup->_next) {
+ if (STREQ(hostPortGroupKey->value, hostPortGroup->key)) {
+ for (hostPortGroupPort = hostPortGroup->port;
+ hostPortGroupPort != NULL;
+ hostPortGroupPort = hostPortGroupPort->_next) {
+ if (STRNEQ(hostPortGroupPort->type, "virtualMachine")) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ _("Cannot undefine HostVirtualSwitch that has a '%s' port"),
+ hostPortGroupPort->type);
+ goto cleanup;
+ }
+ }
+
+ found = true;
+ break;
+ }
+ }
+
+ if (! found) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not find HostPortGroup for key '%s'"),
+ hostPortGroupKey->value);
+ goto cleanup;
+ }
+ }
+
+ /* Remove all HostPortGroups from the HostVirtualSwitch */
+ for (hostPortGroupKey = hostVirtualSwitch->portgroup;
+ hostPortGroupKey != NULL; hostPortGroupKey = hostPortGroupKey->_next) {
+ bool found = false;
+
+ for (hostPortGroup = hostPortGroupList; hostPortGroup != NULL;
+ hostPortGroup = hostPortGroup->_next) {
+ if (STREQ(hostPortGroupKey->value, hostPortGroup->key)) {
+ if (esxVI_RemovePortGroup
+ (priv->primary,
+ priv->primary->hostSystem->configManager->networkSystem,
+ hostPortGroup->spec->name) < 0) {
+ goto cleanup;
+ }
+
+ found = true;
+ break;
+ }
+ }
+
+ if (! found) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not find HostPortGroup for key '%s'"),
+ hostPortGroupKey->value);
+ goto cleanup;
+ }
+ }
+
+ /* Finally, remove HostVirtualSwitch itself */
+ if (esxVI_RemoveVirtualSwitch
+ (priv->primary,
+ priv->primary->hostSystem->configManager->networkSystem,
+ network->name) < 0) {
+ goto cleanup;
+ }
+
+ result = 0;
+
+ cleanup:
+ esxVI_HostVirtualSwitch_Free(&hostVirtualSwitch);
+ esxVI_HostPortGroup_Free(&hostPortGroupList);
+
+ return result;
+}
+
+
+
+static int
+esxShapingPolicyToBandwidth(esxVI_HostNetworkTrafficShapingPolicy *shapingPolicy,
+ virNetDevBandwidthPtr *bandwidth)
+{
+ if (bandwidth == NULL || *bandwidth != NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
+ return -1;
+ }
+
+ if (shapingPolicy == NULL || shapingPolicy->enabled != esxVI_Boolean_True) {
+ return 0;
+ }
+
+ if (VIR_ALLOC(*bandwidth) < 0 ||
+ VIR_ALLOC((*bandwidth)->in) < 0 ||
+ VIR_ALLOC((*bandwidth)->out) < 0) {
+ virReportOOMError();
+ return -1;
+ }
+
+ if (shapingPolicy->averageBandwidth != NULL) {
+ /* Scale bits per second to kilobytes per second */
+ (*bandwidth)->in->average = shapingPolicy->averageBandwidth->value / 8 / 1000;
+ (*bandwidth)->out->average = shapingPolicy->averageBandwidth->value / 8 / 1000;
+ }
+
+ if (shapingPolicy->peakBandwidth != NULL) {
+ /* Scale bits per second to kilobytes per second */
+ (*bandwidth)->in->peak = shapingPolicy->peakBandwidth->value / 8 / 1000;
+ (*bandwidth)->out->peak = shapingPolicy->peakBandwidth->value / 8 / 1000;
+ }
+
+ if (shapingPolicy->burstSize != NULL) {
+ /* Scale bytes to kilobytes */
+ (*bandwidth)->in->burst = shapingPolicy->burstSize->value / 1024;
+ (*bandwidth)->out->burst = shapingPolicy->burstSize->value / 1024;
+ }
+
+ return 0;
+}
+
+
+
+static char *
+esxNetworkGetXMLDesc(virNetworkPtr network_, unsigned int flags)
+{
+ char *xml = NULL;
+ esxPrivate *priv = network_->conn->networkPrivateData;
+ esxVI_HostVirtualSwitch *hostVirtualSwitch = NULL;
+ int count = 0;
+ esxVI_PhysicalNic *physicalNicList = NULL;
+ esxVI_PhysicalNic *physicalNic = NULL;
+ esxVI_String *physicalNicKey = NULL;
+ esxVI_HostPortGroup *hostPortGroupList = NULL;
+ esxVI_HostPortGroup *hostPortGroup = NULL;
+ esxVI_String *propertyNameList = NULL;
+ esxVI_ObjectContent *networkList = NULL;
+ esxVI_ObjectContent *network = NULL;
+ esxVI_String *networkNameList = NULL;
+ esxVI_String *hostPortGroupKey = NULL;
+ esxVI_String *networkName = NULL;
+ virNetworkDefPtr def;
+
+ if (esxVI_EnsureSession(priv->primary) < 0) {
+ return NULL;
+ }
+
+ if (VIR_ALLOC(def) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ /* Lookup HostVirtualSwitch */
+ if (esxVI_LookupHostVirtualSwitchByName(priv->primary, network_->name,
+ &hostVirtualSwitch,
+ esxVI_Occurrence_RequiredItem) < 0) {
+ goto cleanup;
+ }
+
+ md5_buffer(hostVirtualSwitch->key, strlen(hostVirtualSwitch->key), def->uuid);
+
+ def->name = strdup(hostVirtualSwitch->name);
+
+ if (def->name == NULL) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ def->forwardType = VIR_NETWORK_FORWARD_NONE;
+
+ /* Count PhysicalNics on HostVirtualSwitch */
+ count = 0;
+
+ for (physicalNicKey = hostVirtualSwitch->pnic;
+ physicalNicKey != NULL; physicalNicKey = physicalNicKey->_next) {
+ ++count;
+ }
+
+ if (count > 0) {
+ def->forwardType = VIR_NETWORK_FORWARD_BRIDGE;
+
+ if (VIR_ALLOC_N(def->forwardIfs, count) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ /* Find PhysicalNic by key */
+ if (esxVI_LookupPhysicalNicList(priv->primary, &physicalNicList) < 0) {
+ goto cleanup;
+ }
+
+ for (physicalNicKey = hostVirtualSwitch->pnic;
+ physicalNicKey != NULL; physicalNicKey = physicalNicKey->_next) {
+ bool found = false;
+
+ for (physicalNic = physicalNicList; physicalNic != NULL;
+ physicalNic = physicalNic->_next) {
+ if (STREQ(physicalNicKey->value, physicalNic->key)) {
+ def->forwardIfs[def->nForwardIfs].dev = strdup(physicalNic->device);
+
+ if (def->forwardIfs[def->nForwardIfs].dev == NULL) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ ++def->nForwardIfs;
+
+ found = true;
+ break;
+ }
+ }
+
+ if (! found) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not find PhysicalNic with key '%s'"),
+ physicalNicKey->value);
+ goto cleanup;
+ }
+ }
+ }
+
+ /* Count HostPortGroups on HostVirtualSwitch */
+ count = 0;
+
+ for (hostPortGroupKey = hostVirtualSwitch->portgroup;
+ hostPortGroupKey != NULL; hostPortGroupKey = hostPortGroupKey->_next) {
+ ++count;
+ }
+
+ if (count > 0) {
+ if (VIR_ALLOC_N(def->portGroups, count) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ /* Lookup Network list and create name list */
+ if (esxVI_String_AppendValueToList(&propertyNameList, "name") < 0 ||
+ esxVI_LookupNetworkList(priv->primary, propertyNameList,
+ &networkList) < 0) {
+ goto cleanup;
+ }
+
+ for (network = networkList; network != NULL; network = network->_next) {
+ char *tmp = NULL;
+
+ if (esxVI_GetStringValue(network, "name", &tmp,
+ esxVI_Occurrence_RequiredItem) < 0 ||
+ esxVI_String_AppendValueToList(&networkNameList, tmp) < 0) {
+ goto cleanup;
+ }
+ }
+
+ /* Find HostPortGroup by key */
+ if (esxVI_LookupHostPortGroupList(priv->primary, &hostPortGroupList) < 0) {
+ goto cleanup;
+ }
+
+ for (hostPortGroupKey = hostVirtualSwitch->portgroup;
+ hostPortGroupKey != NULL; hostPortGroupKey = hostPortGroupKey->_next) {
+ bool found = false;
+
+ for (hostPortGroup = hostPortGroupList; hostPortGroup != NULL;
+ hostPortGroup = hostPortGroup->_next) {
+ if (STREQ(hostPortGroupKey->value, hostPortGroup->key)) {
+ /* Find Network for HostPortGroup, there might be none */
+ for (networkName = networkNameList; networkName != NULL;
+ networkName = networkName->_next) {
+ if (STREQ(networkName->value, hostPortGroup->spec->name)) {
+ def->portGroups[def->nPortGroups].name = strdup(networkName->value);
+
+ if (def->portGroups[def->nPortGroups].name == NULL) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (hostPortGroup->spec->policy != NULL) {
+ if (esxShapingPolicyToBandwidth
+ (hostPortGroup->spec->policy->shapingPolicy,
+ &def->portGroups[def->nPortGroups].bandwidth) < 0) {
+ ++def->nPortGroups;
+ goto cleanup;
+ }
+ }
+
+ ++def->nPortGroups;
+ break;
+ }
+ }
+
+ found = true;
+ break;
+ }
+ }
+
+ if (! found) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not find HostPortGroup with key '%s'"),
+ hostPortGroupKey->value);
+ goto cleanup;
+ }
+ }
+ }
+
+ if (hostVirtualSwitch->spec->policy != NULL) {
+ if (esxShapingPolicyToBandwidth
+ (hostVirtualSwitch->spec->policy->shapingPolicy,
+ &def->bandwidth) < 0) {
+ goto cleanup;
+ }
+ }
+
+ xml = virNetworkDefFormat(def, flags);
+
+ cleanup:
+ esxVI_HostVirtualSwitch_Free(&hostVirtualSwitch);
+ esxVI_PhysicalNic_Free(&physicalNicList);
+ esxVI_HostPortGroup_Free(&hostPortGroupList);
+ esxVI_String_Free(&propertyNameList);
+ esxVI_ObjectContent_Free(&networkList);
+ esxVI_String_Free(&networkNameList);
+ virNetworkDefFree(def);
+
+ return xml;
+}
+
+
+
+static int
+esxNetworkGetAutostart(virNetworkPtr network ATTRIBUTE_UNUSED,
+ int *autostart)
+{
+ /* ESX networks are always active */
+ *autostart = 1;
+
+ return 0;
+}
+
+
+
+static int
+esxNetworkSetAutostart(virNetworkPtr network ATTRIBUTE_UNUSED,
+ int autostart)
+{
+ /* Just accept autostart activation, but fail on autostart deactivation */
+ autostart = (autostart != 0);
+
+ if (! autostart) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Cannot deactivate network autostart"));
+ return -1;
+ }
+
+ return 0;
+}
+
+
+
+static int
+esxNetworkIsActive(virNetworkPtr network ATTRIBUTE_UNUSED)
+{
+ /* ESX networks are always active */
+ return 1;
+}
+
+
+
+static int
+esxNetworkIsPersistent(virNetworkPtr network ATTRIBUTE_UNUSED)
+{
+ /* ESX has no concept of transient networks, so all of them are persistent */
+ return 1;
+}
+
+
+
static virNetworkDriver esxNetworkDriver = {
.name = "ESX",
.open = esxNetworkOpen, /* 0.7.6 */
.close = esxNetworkClose, /* 0.7.6 */
+ .numOfNetworks = esxNumberOfNetworks, /* 0.10.0 */
+ .listNetworks = esxListNetworks, /* 0.10.0 */
+ .numOfDefinedNetworks = esxNumberOfDefinedNetworks, /* 0.10.0 */
+ .listDefinedNetworks = esxListDefinedNetworks, /* 0.10.0 */
+ .networkLookupByUUID = esxNetworkLookupByUUID, /* 0.10.0 */
+ .networkLookupByName = esxNetworkLookupByName, /* 0.10.0 */
+ .networkDefineXML = esxNetworkDefineXML, /* 0.10.0 */
+ .networkUndefine = esxNetworkUndefine, /* 0.10.0 */
+ .networkGetXMLDesc = esxNetworkGetXMLDesc, /* 0.10.0 */
+ .networkGetAutostart = esxNetworkGetAutostart, /* 0.10.0 */
+ .networkSetAutostart = esxNetworkSetAutostart, /* 0.10.0 */
+ .networkIsActive = esxNetworkIsActive, /* 0.10.0 */
+ .networkIsPersistent = esxNetworkIsPersistent, /* 0.10.0 */
};
diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c
index f3a9e91..65e1d9a 100644
--- a/src/esx/esx_vi.c
+++ b/src/esx/esx_vi.c
@@ -783,6 +783,7 @@ ESX_VI__TEMPLATE__FREE(Context,
esxVI_SelectionSpec_Free(&item->selectSet_hostSystemToDatastore);
esxVI_SelectionSpec_Free(&item->selectSet_computeResourceToHost);
esxVI_SelectionSpec_Free(&item->selectSet_computeResourceToParentToParent);
+ esxVI_SelectionSpec_Free(&item->selectSet_datacenterToNetwork);
})
int
@@ -1927,6 +1928,13 @@ esxVI_BuildSelectSetCollection(esxVI_Context *ctx)
return -1;
}
+ /* Datacenter -> network (Network) */
+ if (esxVI_BuildSelectSet(&ctx->selectSet_datacenterToNetwork,
+ "datacenterToNetwork",
+ "Datacenter", "network", NULL) < 0) {
+ return -1;
+ }
+
return 0;
}
@@ -2094,6 +2102,15 @@ esxVI_LookupObjectContentByType(esxVI_Context *ctx,
type, root->type);
goto cleanup;
}
+ } else if (STREQ(root->type, "Datacenter")) {
+ if (STREQ(type, "Network")) {
+ objectSpec->selectSet = ctx->selectSet_datacenterToNetwork;
+ } else {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Invalid lookup of '%s' from '%s'"),
+ type, root->type);
+ goto cleanup;
+ }
} else {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Invalid lookup from '%s'"), root->type);
@@ -4091,6 +4108,160 @@ esxVI_LookupPhysicalNicByMACAddress(esxVI_Context *ctx, const char *mac,
int
+esxVI_LookupHostVirtualSwitchList(esxVI_Context *ctx,
+ esxVI_HostVirtualSwitch **hostVirtualSwitchList)
+{
+ int result = -1;
+ esxVI_String *propertyNameList = NULL;
+ esxVI_ObjectContent *hostSystem = NULL;
+ esxVI_DynamicProperty *dynamicProperty = NULL;
+
+ if (hostVirtualSwitchList == NULL || *hostVirtualSwitchList != NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
+ return -1;
+ }
+
+ if (esxVI_String_AppendValueToList(&propertyNameList,
+ "config.network.vswitch") < 0 ||
+ esxVI_LookupHostSystemProperties(ctx, propertyNameList,
+ &hostSystem) < 0) {
+ goto cleanup;
+ }
+
+ for (dynamicProperty = hostSystem->propSet; dynamicProperty != NULL;
+ dynamicProperty = dynamicProperty->_next) {
+ if (STREQ(dynamicProperty->name, "config.network.vswitch")) {
+ if (esxVI_HostVirtualSwitch_CastListFromAnyType
+ (dynamicProperty->val, hostVirtualSwitchList) < 0) {
+ goto cleanup;
+ }
+ } else {
+ VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
+ }
+ }
+
+ result = 0;
+
+ cleanup:
+ esxVI_String_Free(&propertyNameList);
+ esxVI_ObjectContent_Free(&hostSystem);
+
+ return result;
+}
+
+
+
+int
+esxVI_LookupHostVirtualSwitchByName(esxVI_Context *ctx, const char *name,
+ esxVI_HostVirtualSwitch **hostVirtualSwitch,
+ esxVI_Occurrence occurrence)
+{
+ int result = -1;
+ esxVI_HostVirtualSwitch *hostVirtualSwitchList = NULL;
+ esxVI_HostVirtualSwitch *candidate = NULL;
+
+ if (hostVirtualSwitch == NULL || *hostVirtualSwitch != NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
+ return -1;
+ }
+
+ if (esxVI_LookupHostVirtualSwitchList(ctx, &hostVirtualSwitchList) < 0) {
+ goto cleanup;
+ }
+
+ /* Search for a matching HostVirtualSwitch */
+ for (candidate = hostVirtualSwitchList; candidate != NULL;
+ candidate = candidate->_next) {
+ if (STREQ(candidate->name, name)) {
+ if (esxVI_HostVirtualSwitch_DeepCopy(hostVirtualSwitch,
+ candidate) < 0) {
+ goto cleanup;
+ }
+
+ /* Found HostVirtualSwitch with matching name */
+ result = 0;
+
+ goto cleanup;
+ }
+ }
+
+ if (*hostVirtualSwitch == NULL &&
+ occurrence != esxVI_Occurrence_OptionalItem) {
+ virReportError(VIR_ERR_NO_NETWORK,
+ _("Could not find HostVirtualSwitch with name '%s'"),
+ name);
+ goto cleanup;
+ }
+
+ result = 0;
+
+ cleanup:
+ esxVI_HostVirtualSwitch_Free(&hostVirtualSwitchList);
+
+ return result;
+}
+
+
+
+int
+esxVI_LookupHostPortGroupList(esxVI_Context *ctx,
+ esxVI_HostPortGroup **hostPortGroupList)
+{
+ int result = -1;
+ esxVI_String *propertyNameList = NULL;
+ esxVI_ObjectContent *hostSystem = NULL;
+ esxVI_DynamicProperty *dynamicProperty = NULL;
+
+ if (hostPortGroupList == NULL || *hostPortGroupList != NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
+ return -1;
+ }
+
+ if (esxVI_String_AppendValueToList(&propertyNameList,
+ "config.network.portgroup") < 0 ||
+ esxVI_LookupHostSystemProperties(ctx, propertyNameList,
+ &hostSystem) < 0) {
+ goto cleanup;
+ }
+
+ for (dynamicProperty = hostSystem->propSet; dynamicProperty != NULL;
+ dynamicProperty = dynamicProperty->_next) {
+ if (STREQ(dynamicProperty->name, "config.network.portgroup")) {
+ if (esxVI_HostPortGroup_CastListFromAnyType
+ (dynamicProperty->val, hostPortGroupList) < 0) {
+ goto cleanup;
+ }
+
+ break;
+ } else {
+ VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
+ }
+ }
+
+ result = 0;
+
+ cleanup:
+ esxVI_String_Free(&propertyNameList);
+ esxVI_ObjectContent_Free(&hostSystem);
+
+ return result;
+}
+
+
+
+int
+esxVI_LookupNetworkList(esxVI_Context *ctx, esxVI_String *propertyNameList,
+ esxVI_ObjectContent **networkList)
+{
+ return esxVI_LookupObjectContentByType(ctx, ctx->datacenter->_reference,
+ "Network", propertyNameList,
+ networkList,
+ esxVI_Occurrence_OptionalList);
+}
+
+
+
+int
esxVI_HandleVirtualMachineQuestion
(esxVI_Context *ctx, esxVI_ManagedObjectReference *virtualMachine,
esxVI_VirtualMachineQuestionInfo *questionInfo, bool autoAnswer,
diff --git a/src/esx/esx_vi.h b/src/esx/esx_vi.h
index 597013c..12394e7 100644
--- a/src/esx/esx_vi.h
+++ b/src/esx/esx_vi.h
@@ -227,6 +227,7 @@ struct _esxVI_Context {
esxVI_SelectionSpec *selectSet_hostSystemToDatastore;
esxVI_SelectionSpec *selectSet_computeResourceToHost;
esxVI_SelectionSpec *selectSet_computeResourceToParentToParent;
+ esxVI_SelectionSpec *selectSet_datacenterToNetwork;
bool hasQueryVirtualDiskUuid;
bool hasSessionIsActive;
};
@@ -492,6 +493,19 @@ int esxVI_LookupPhysicalNicByMACAddress(esxVI_Context *ctx, const char *mac,
esxVI_PhysicalNic **physicalNic,
esxVI_Occurrence occurrence);
+int esxVI_LookupHostVirtualSwitchList
+ (esxVI_Context *ctx, esxVI_HostVirtualSwitch **hostVirtualSwitchList);
+
+int esxVI_LookupHostVirtualSwitchByName(esxVI_Context *ctx, const char *name,
+ esxVI_HostVirtualSwitch **hostVirtualSwitch,
+ esxVI_Occurrence occurrence);
+
+int esxVI_LookupHostPortGroupList(esxVI_Context *ctx,
+ esxVI_HostPortGroup **hostPortGroupList);
+
+int esxVI_LookupNetworkList(esxVI_Context *ctx, esxVI_String *propertyNameList,
+ esxVI_ObjectContent **networkList);
+
int esxVI_HandleVirtualMachineQuestion
(esxVI_Context *ctx, esxVI_ManagedObjectReference *virtualMachine,
esxVI_VirtualMachineQuestionInfo *questionInfo, bool autoAnswer,
diff --git a/src/esx/esx_vi_generator.input b/src/esx/esx_vi_generator.input
index 5572b36..c4a3e56 100644
--- a/src/esx/esx_vi_generator.input
+++ b/src/esx/esx_vi_generator.input
@@ -338,12 +338,138 @@ object HostNasVolume extends HostFileSystemVolume
end
+object HostNetOffloadCapabilities
+ Boolean csumOffload o
+ Boolean tcpSegmentation o
+ Boolean zeroCopyXmit o
+end
+
+
+object HostNetworkPolicy
+ HostNetworkSecurityPolicy security o
+ HostNicTeamingPolicy nicTeaming o
+ HostNetOffloadCapabilities offloadPolicy o
+ HostNetworkTrafficShapingPolicy shapingPolicy o
+end
+
+
+object HostNetworkSecurityPolicy
+ Boolean allowPromiscuous o
+ Boolean macChanges o
+ Boolean forgedTransmits o
+end
+
+
+object HostNetworkTrafficShapingPolicy
+ Boolean enabled o
+ Long averageBandwidth o
+ Long peakBandwidth o
+ Long burstSize o
+end
+
+
+object HostNicFailureCriteria
+ String checkSpeed o
+ Int speed o
+ Boolean checkDuplex o
+ Boolean fullDuplex o
+ Boolean checkErrorPercent o
+ Int percentage o
+ Boolean checkBeacon o
+end
+
+
+object HostNicOrderPolicy
+ String activeNic ol
+ String standbyNic ol
+end
+
+
+object HostNicTeamingPolicy
+ String policy o
+ Boolean reversePolicy o
+ Boolean notifySwitches o
+ Boolean rollingOrder o
+ HostNicFailureCriteria failureCriteria o
+ HostNicOrderPolicy nicOrder o
+end
+
+
+object HostPortGroup
+ String key o
+ HostPortGroupPort port ol
+ String vswitch o
+ HostNetworkPolicy computedPolicy r
+ HostPortGroupSpec spec r
+end
+
+
+object HostPortGroupPort
+ String key o
+ String mac ol
+ String type r
+end
+
+
+object HostPortGroupSpec
+ String name r
+ Int vlanId r
+ String vswitchName r
+ HostNetworkPolicy policy r
+end
+
+
object HostScsiDiskPartition
String diskName r
Int partition r
end
+object HostVirtualSwitch
+ String name r
+ String key r
+ Int numPorts r
+ Int numPortsAvailable r
+ Int mtu o
+ String portgroup ol
+ String pnic ol
+ HostVirtualSwitchSpec spec r
+end
+
+
+object HostVirtualSwitchAutoBridge extends HostVirtualSwitchBridge
+ String excludedNicDevice ol
+end
+
+
+object HostVirtualSwitchBeaconConfig
+ Int interval r
+end
+
+
+object HostVirtualSwitchBondBridge extends HostVirtualSwitchBridge
+ String nicDevice rl
+ HostVirtualSwitchBeaconConfig beacon o
+end
+
+
+object HostVirtualSwitchBridge
+end
+
+
+object HostVirtualSwitchSimpleBridge extends HostVirtualSwitchBridge
+ String nicDevice r
+end
+
+
+object HostVirtualSwitchSpec
+ Int numPorts r
+ HostVirtualSwitchBridge bridge o
+ HostNetworkPolicy policy o
+ Int mtu o
+end
+
+
object HostVmfsVolume extends HostFileSystemVolume
Int blockSizeMb r
Int maxBlocks r
@@ -805,6 +931,19 @@ end
# Methods
#
+method AddPortGroup
+ ManagedObjectReference _this r
+ HostPortGroupSpec portgrp r
+end
+
+
+method AddVirtualSwitch
+ ManagedObjectReference _this r
+ String vswitchName r
+ HostVirtualSwitchSpec spec o
+end
+
+
method AnswerVM
ManagedObjectReference _this r
String questionId r
@@ -981,12 +1120,24 @@ method RegisterVM_Task returns ManagedObjectReference r
end
+method RemovePortGroup
+ ManagedObjectReference _this r
+ String pgName r
+end
+
+
method RemoveSnapshot_Task returns ManagedObjectReference r
ManagedObjectReference _this r
Boolean removeChildren r
end
+method RemoveVirtualSwitch
+ ManagedObjectReference _this r
+ String vswitchName r
+end
+
+
method RetrieveProperties returns ObjectContent ol
ManagedObjectReference _this:propertyCollector r
PropertyFilterSpec specSet rl
diff --git a/src/esx/esx_vi_generator.py b/src/esx/esx_vi_generator.py
index 596bd16..b49db70 100755
--- a/src/esx/esx_vi_generator.py
+++ b/src/esx/esx_vi_generator.py
@@ -1520,6 +1520,11 @@ additional_object_features = { "AutoStartDefaults" : Object.FEATURE__AN
Object.FEATURE__ANY_TYPE,
"HostDatastoreBrowserSearchResults" : Object.FEATURE__LIST |
Object.FEATURE__ANY_TYPE,
+ "HostPortGroup" : Object.FEATURE__LIST |
+ Object.FEATURE__ANY_TYPE,
+ "HostVirtualSwitch" : Object.FEATURE__DEEP_COPY |
+ Object.FEATURE__LIST |
+ Object.FEATURE__ANY_TYPE,
"ManagedObjectReference" : Object.FEATURE__ANY_TYPE,
"ObjectContent" : Object.FEATURE__DEEP_COPY,
"PhysicalNic" : Object.FEATURE__DEEP_COPY |
--
1.7.4.1
12 years, 8 months
[libvirt] [PATCH] esx: Implement interface driver
by Matthias Bolte
Lists available PhysicalNic devices. A PhysicalNic is always active
and can neither be defined nor undefined.
A PhysicalNic is used to bridge a HostVirtualSwitch to the physical
network.
---
This implementation differs from Ata's. It just lists PhysicalNics
instead of listing HostVirtualNics as bridges.
src/esx/esx_interface_driver.c | 239 +++++++++++++++++++++++++++++++++++++++-
src/esx/esx_vi.c | 144 ++++++++++++++++++++++++-
src/esx/esx_vi.h | 13 ++-
src/esx/esx_vi_generator.input | 34 ++++++-
src/esx/esx_vi_generator.py | 5 +-
5 files changed, 430 insertions(+), 5 deletions(-)
diff --git a/src/esx/esx_interface_driver.c b/src/esx/esx_interface_driver.c
index 501409a..a78a744 100644
--- a/src/esx/esx_interface_driver.c
+++ b/src/esx/esx_interface_driver.c
@@ -4,7 +4,7 @@
* host interfaces
*
* Copyright (C) 2010-2011 Red Hat, Inc.
- * Copyright (C) 2010 Matthias Bolte <matthias.bolte(a)googlemail.com>
+ * Copyright (C) 2010-2012 Matthias Bolte <matthias.bolte(a)googlemail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -29,6 +29,8 @@
#include "memory.h"
#include "logging.h"
#include "uuid.h"
+#include "interface_conf.h"
+#include "virsocketaddr.h"
#include "esx_private.h"
#include "esx_interface_driver.h"
#include "esx_vi.h"
@@ -67,10 +69,245 @@ esxInterfaceClose(virConnectPtr conn)
+static int
+esxNumberOfInterfaces(virConnectPtr conn)
+{
+ esxPrivate *priv = conn->interfacePrivateData;
+ esxVI_PhysicalNic *physicalNicList = NULL;
+ esxVI_PhysicalNic *physicalNic = NULL;
+ int count = 0;
+
+ if (esxVI_EnsureSession(priv->primary) < 0 ||
+ esxVI_LookupPhysicalNicList(priv->primary, &physicalNicList) < 0) {
+ return -1;
+ }
+
+ for (physicalNic = physicalNicList; physicalNic != NULL;
+ physicalNic = physicalNic->_next) {
+ ++count;
+ }
+
+ esxVI_PhysicalNic_Free(&physicalNicList);
+
+ return count;
+}
+
+
+
+static int
+esxListInterfaces(virConnectPtr conn, char **const names, int maxnames)
+{
+ bool success = false;
+ esxPrivate *priv = conn->interfacePrivateData;
+ esxVI_PhysicalNic *physicalNicList = NULL;
+ esxVI_PhysicalNic *physicalNic = NULL;
+ int count = 0;
+ int i;
+
+ if (maxnames == 0) {
+ return 0;
+ }
+
+ if (esxVI_EnsureSession(priv->primary) < 0 ||
+ esxVI_LookupPhysicalNicList(priv->primary, &physicalNicList) < 0) {
+ return -1;
+ }
+
+ for (physicalNic = physicalNicList; physicalNic != NULL;
+ physicalNic = physicalNic->_next) {
+ names[count] = strdup(physicalNic->device);
+
+ if (names[count] == NULL) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ ++count;
+ }
+
+ success = true;
+
+ cleanup:
+ if (! success) {
+ for (i = 0; i < count; ++i) {
+ VIR_FREE(names[i]);
+ }
+
+ count = -1;
+ }
+
+ esxVI_PhysicalNic_Free(&physicalNicList);
+
+ return count;
+}
+
+
+
+static int
+esxNumberOfDefinedInterfaces(virConnectPtr conn ATTRIBUTE_UNUSED)
+{
+ /* ESX interfaces are always active */
+ return 0;
+}
+
+
+
+static int
+esxListDefinedInterfaces(virConnectPtr conn ATTRIBUTE_UNUSED,
+ char **const names ATTRIBUTE_UNUSED,
+ int maxnames ATTRIBUTE_UNUSED)
+{
+ /* ESX interfaces are always active */
+ return 0;
+}
+
+
+
+static virInterfacePtr
+esxInterfaceLookupByName(virConnectPtr conn, const char *name)
+{
+ virInterfacePtr iface = NULL;
+ esxPrivate *priv = conn->interfacePrivateData;
+ esxVI_PhysicalNic *physicalNic = NULL;
+
+ if (esxVI_EnsureSession(priv->primary) < 0 ||
+ esxVI_LookupPhysicalNicByMACAddress(priv->primary, name, &physicalNic,
+ esxVI_Occurrence_RequiredItem) < 0) {
+ return NULL;
+ }
+
+ iface = virGetInterface(conn, physicalNic->device, physicalNic->mac);
+
+ esxVI_PhysicalNic_Free(&physicalNic);
+
+ return iface;
+}
+
+
+
+static virInterfacePtr
+esxInterfaceLookupByMACString(virConnectPtr conn, const char *mac)
+{
+ virInterfacePtr iface = NULL;
+ esxPrivate *priv = conn->interfacePrivateData;
+ esxVI_PhysicalNic *physicalNic = NULL;
+
+ if (esxVI_EnsureSession(priv->primary) < 0 ||
+ esxVI_LookupPhysicalNicByMACAddress(priv->primary, mac, &physicalNic,
+ esxVI_Occurrence_RequiredItem) < 0) {
+ return NULL;
+ }
+
+ iface = virGetInterface(conn, physicalNic->device, physicalNic->mac);
+
+ esxVI_PhysicalNic_Free(&physicalNic);
+
+ return iface;
+}
+
+
+
+static char *
+esxInterfaceGetXMLDesc(virInterfacePtr iface, unsigned int flags)
+{
+ char *xml = NULL;
+ esxPrivate *priv = iface->conn->interfacePrivateData;
+ esxVI_PhysicalNic *physicalNic = NULL;
+ virInterfaceDef def;
+ bool hasAddress = false;
+ virInterfaceProtocolDefPtr protocols;
+ virInterfaceProtocolDef protocol;
+ virSocketAddr socketAddress;
+ virInterfaceIpDefPtr ips;
+ virInterfaceIpDef ip;
+
+ virCheckFlags(VIR_INTERFACE_XML_INACTIVE, NULL);
+
+ memset(&def, 0, sizeof(def));
+ memset(&protocol, 0, sizeof(protocol));
+ memset(&socketAddress, 0, sizeof(socketAddress));
+ memset(&ip, 0, sizeof(ip));
+
+ if (esxVI_EnsureSession(priv->primary) < 0 ||
+ esxVI_LookupPhysicalNicByMACAddress(priv->primary, iface->mac,
+ &physicalNic,
+ esxVI_Occurrence_RequiredItem) < 0) {
+ return NULL;
+ }
+
+ def.type = VIR_INTERFACE_TYPE_ETHERNET;
+ def.name = physicalNic->device;
+ def.mac = physicalNic->mac;
+ def.startmode = VIR_INTERFACE_START_ONBOOT;
+
+ /* FIXME: Add support for IPv6, requires to use vSphere API 4.0 */
+ if (physicalNic->spec->ip != NULL) {
+ protocol.family = (char *)"ipv4";
+
+ if (physicalNic->spec->ip->dhcp == esxVI_Boolean_True) {
+ protocol.dhcp = 1;
+ }
+
+ if (physicalNic->spec->ip->ipAddress != NULL &&
+ physicalNic->spec->ip->subnetMask != NULL &&
+ strlen(physicalNic->spec->ip->ipAddress) > 0 &&
+ strlen(physicalNic->spec->ip->subnetMask) > 0) {
+ hasAddress = true;
+ }
+
+ if (protocol.dhcp || hasAddress) {
+ protocols = &protocol;
+ def.nprotos = 1;
+ def.protos = &protocols;
+ }
+
+ if (hasAddress &&
+ !(protocol.dhcp && (flags & VIR_INTERFACE_XML_INACTIVE))) {
+ ips = &ip;
+ protocol.nips = 1;
+ protocol.ips = &ips;
+
+ if (virSocketAddrParseIPv4(&socketAddress,
+ physicalNic->spec->ip->subnetMask) < 0) {
+ goto cleanup;
+ }
+
+ ip.address = physicalNic->spec->ip->ipAddress;
+ ip.prefix = virSocketAddrGetNumNetmaskBits(&socketAddress);
+ }
+ }
+
+ xml = virInterfaceDefFormat(&def);
+
+ cleanup:
+ esxVI_PhysicalNic_Free(&physicalNic);
+
+ return xml;
+}
+
+
+
+static int
+esxInterfaceIsActive(virInterfacePtr iface ATTRIBUTE_UNUSED)
+{
+ /* ESX interfaces are always active */
+ return 1;
+}
+
+
+
static virInterfaceDriver esxInterfaceDriver = {
.name = "ESX",
.open = esxInterfaceOpen, /* 0.7.6 */
.close = esxInterfaceClose, /* 0.7.6 */
+ .numOfInterfaces = esxNumberOfInterfaces, /* 0.10.0 */
+ .listInterfaces = esxListInterfaces, /* 0.10.0 */
+ .numOfDefinedInterfaces = esxNumberOfDefinedInterfaces, /* 0.10.0 */
+ .listDefinedInterfaces = esxListDefinedInterfaces, /* 0.10.0 */
+ .interfaceLookupByName = esxInterfaceLookupByName, /* 0.10.0 */
+ .interfaceLookupByMACString = esxInterfaceLookupByMACString, /* 0.10.0 */
+ .interfaceGetXMLDesc = esxInterfaceGetXMLDesc, /* 0.10.0 */
+ .interfaceIsActive = esxInterfaceIsActive, /* 0.10.0 */
};
diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c
index 2c789e1..c4217c9 100644
--- a/src/esx/esx_vi.c
+++ b/src/esx/esx_vi.c
@@ -3,7 +3,7 @@
* esx_vi.c: client for the VMware VI API 2.5 to manage ESX hosts
*
* Copyright (C) 2010-2011 Red Hat, Inc.
- * Copyright (C) 2009-2011 Matthias Bolte <matthias.bolte(a)googlemail.com>
+ * Copyright (C) 2009-2012 Matthias Bolte <matthias.bolte(a)googlemail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -3949,6 +3949,148 @@ esxVI_LookupAutoStartPowerInfoList(esxVI_Context *ctx,
int
+esxVI_LookupPhysicalNicList(esxVI_Context *ctx,
+ esxVI_PhysicalNic **physicalNicList)
+{
+ int result = -1;
+ esxVI_String *propertyNameList = NULL;
+ esxVI_ObjectContent *hostSystem = NULL;
+ esxVI_DynamicProperty *dynamicProperty = NULL;
+
+ if (physicalNicList == NULL || *physicalNicList != NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
+ return -1;
+ }
+
+ if (esxVI_String_AppendValueToList(&propertyNameList,
+ "config.network.pnic") < 0 ||
+ esxVI_LookupHostSystemProperties(ctx, propertyNameList,
+ &hostSystem) < 0) {
+ goto cleanup;
+ }
+
+ for (dynamicProperty = hostSystem->propSet; dynamicProperty != NULL;
+ dynamicProperty = dynamicProperty->_next) {
+ if (STREQ(dynamicProperty->name, "config.network.pnic")) {
+ if (esxVI_PhysicalNic_CastListFromAnyType(dynamicProperty->val,
+ physicalNicList) < 0) {
+ goto cleanup;
+ }
+ } else {
+ VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
+ }
+ }
+
+ result = 0;
+
+ cleanup:
+ esxVI_String_Free(&propertyNameList);
+ esxVI_ObjectContent_Free(&hostSystem);
+
+ return result;
+}
+
+
+
+int
+esxVI_LookupPhysicalNicByName(esxVI_Context *ctx, const char *name,
+ esxVI_PhysicalNic **physicalNic,
+ esxVI_Occurrence occurrence)
+{
+ int result = -1;
+ esxVI_PhysicalNic *physicalNicList = NULL;
+ esxVI_PhysicalNic *candidate = NULL;
+
+ if (physicalNic == NULL || *physicalNic != NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
+ return -1;
+ }
+
+ if (esxVI_LookupPhysicalNicList(ctx, &physicalNicList) < 0) {
+ goto cleanup;
+ }
+
+ /* Search for a matching physical NIC */
+ for (candidate = physicalNicList; candidate != NULL;
+ candidate = candidate->_next) {
+ if (STRCASEEQ(candidate->device, name)) {
+ if (esxVI_PhysicalNic_DeepCopy(physicalNic, candidate) < 0) {
+ goto cleanup;
+ }
+
+ /* Found physical NIC with matching name */
+ result = 0;
+
+ goto cleanup;
+ }
+ }
+
+ if (*physicalNic == NULL && occurrence != esxVI_Occurrence_OptionalItem) {
+ virReportError(VIR_ERR_NO_INTERFACE,
+ _("Could not find physical NIC with name '%s'"), name);
+ goto cleanup;
+ }
+
+ result = 0;
+
+ cleanup:
+ esxVI_PhysicalNic_Free(&physicalNicList);
+
+ return result;
+}
+
+
+
+int
+esxVI_LookupPhysicalNicByMACAddress(esxVI_Context *ctx, const char *mac,
+ esxVI_PhysicalNic **physicalNic,
+ esxVI_Occurrence occurrence)
+{
+ int result = -1;
+ esxVI_PhysicalNic *physicalNicList = NULL;
+ esxVI_PhysicalNic *candidate = NULL;
+
+ if (physicalNic == NULL || *physicalNic != NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
+ return -1;
+ }
+
+ if (esxVI_LookupPhysicalNicList(ctx, &physicalNicList) < 0) {
+ goto cleanup;
+ }
+
+ /* Search for a matching physical NIC */
+ for (candidate = physicalNicList; candidate != NULL;
+ candidate = candidate->_next) {
+ if (STRCASEEQ(candidate->mac, mac)) {
+ if (esxVI_PhysicalNic_DeepCopy(physicalNic, candidate) < 0) {
+ goto cleanup;
+ }
+
+ /* Found physical NIC with matching MAC address */
+ result = 0;
+
+ goto cleanup;
+ }
+ }
+
+ if (*physicalNic == NULL && occurrence != esxVI_Occurrence_OptionalItem) {
+ virReportError(VIR_ERR_NO_INTERFACE,
+ _("Could not find physical NIC with MAC address '%s'"), mac);
+ goto cleanup;
+ }
+
+ result = 0;
+
+ cleanup:
+ esxVI_PhysicalNic_Free(&physicalNicList);
+
+ return result;
+}
+
+
+
+int
esxVI_HandleVirtualMachineQuestion
(esxVI_Context *ctx, esxVI_ManagedObjectReference *virtualMachine,
esxVI_VirtualMachineQuestionInfo *questionInfo, bool autoAnswer,
diff --git a/src/esx/esx_vi.h b/src/esx/esx_vi.h
index 4b84be8..597013c 100644
--- a/src/esx/esx_vi.h
+++ b/src/esx/esx_vi.h
@@ -3,7 +3,7 @@
* esx_vi.h: client for the VMware VI API 2.5 to manage ESX hosts
*
* Copyright (C) 2011 Red Hat, Inc.
- * Copyright (C) 2009-2010 Matthias Bolte <matthias.bolte(a)googlemail.com>
+ * Copyright (C) 2009-2012 Matthias Bolte <matthias.bolte(a)googlemail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -481,6 +481,17 @@ int esxVI_LookupAutoStartDefaults(esxVI_Context *ctx,
int esxVI_LookupAutoStartPowerInfoList(esxVI_Context *ctx,
esxVI_AutoStartPowerInfo **powerInfoList);
+int esxVI_LookupPhysicalNicList(esxVI_Context *ctx,
+ esxVI_PhysicalNic **physicalNicList);
+
+int esxVI_LookupPhysicalNicByName(esxVI_Context *ctx, const char *name,
+ esxVI_PhysicalNic **physicalNic,
+ esxVI_Occurrence occurrence);
+
+int esxVI_LookupPhysicalNicByMACAddress(esxVI_Context *ctx, const char *mac,
+ esxVI_PhysicalNic **physicalNic,
+ esxVI_Occurrence occurrence);
+
int esxVI_HandleVirtualMachineQuestion
(esxVI_Context *ctx, esxVI_ManagedObjectReference *virtualMachine,
esxVI_VirtualMachineQuestionInfo *questionInfo, bool autoAnswer,
diff --git a/src/esx/esx_vi_generator.input b/src/esx/esx_vi_generator.input
index 1a67a8c..5572b36 100644
--- a/src/esx/esx_vi_generator.input
+++ b/src/esx/esx_vi_generator.input
@@ -317,6 +317,13 @@ object HostFileSystemVolume
end
+object HostIpConfig
+ Boolean dhcp r
+ String ipAddress o
+ String subnetMask o
+end
+
+
object HostMountInfo
String path o
String accessMode r
@@ -455,6 +462,31 @@ object PerfSampleInfo
end
+object PhysicalNic
+ String key o
+ String device r
+ String pci r
+ String driver o
+ PhysicalNicLinkInfo linkSpeed o
+ PhysicalNicLinkInfo validLinkSpecification ol
+ PhysicalNicSpec spec r
+ Boolean wakeOnLanSupported r
+ String mac r
+end
+
+
+object PhysicalNicLinkInfo
+ Int speedMb r
+ Boolean duplex r
+end
+
+
+object PhysicalNicSpec
+ HostIpConfig ip o
+ PhysicalNicLinkInfo linkSpeed o
+end
+
+
object PropertyChange
String name r
PropertyChangeOp op r
@@ -569,7 +601,7 @@ object TemplateConfigFileQuery extends VmConfigFileQuery
end
-object TraversalSpec extends SelectionSpec
+object TraversalSpec extends SelectionSpec
String type r
String path r
Boolean skip o
diff --git a/src/esx/esx_vi_generator.py b/src/esx/esx_vi_generator.py
index af2d57e..596bd16 100755
--- a/src/esx/esx_vi_generator.py
+++ b/src/esx/esx_vi_generator.py
@@ -3,7 +3,7 @@
#
# esx_vi_generator.py: generates most of the SOAP type mapping code
#
-# Copyright (C) 2010-2011 Matthias Bolte <matthias.bolte(a)googlemail.com>
+# Copyright (C) 2010-2012 Matthias Bolte <matthias.bolte(a)googlemail.com>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
@@ -1522,6 +1522,9 @@ additional_object_features = { "AutoStartDefaults" : Object.FEATURE__AN
Object.FEATURE__ANY_TYPE,
"ManagedObjectReference" : Object.FEATURE__ANY_TYPE,
"ObjectContent" : Object.FEATURE__DEEP_COPY,
+ "PhysicalNic" : Object.FEATURE__DEEP_COPY |
+ Object.FEATURE__LIST |
+ Object.FEATURE__ANY_TYPE,
"ResourcePoolResourceUsage" : Object.FEATURE__ANY_TYPE,
"ServiceContent" : Object.FEATURE__DESERIALIZE,
"SharesInfo" : Object.FEATURE__ANY_TYPE,
--
1.7.4.1
12 years, 8 months
[libvirt] [PATCH] esx: Remove redundant checks for esxVI_LookupHostSystemProperties result
by Matthias Bolte
esxVI_LookupHostSystemProperties guarantees that hostSystem is non-NULL.
Remove redundant NULL checks from callers.
Also prefer esxVI_GetStringValue over open-coding the logic.
---
src/esx/esx_driver.c | 82 +++++++++---------------------------------------
src/esx/esx_vi.c | 4 +-
src/esx/esx_vi_types.c | 3 +-
3 files changed, 19 insertions(+), 70 deletions(-)
diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c
index 47957cc..72a7acc 100644
--- a/src/esx/esx_driver.c
+++ b/src/esx/esx_driver.c
@@ -3,7 +3,7 @@
* esx_driver.c: core driver functions for managing VMware ESX hosts
*
* Copyright (C) 2010-2012 Red Hat, Inc.
- * Copyright (C) 2009-2011 Matthias Bolte <matthias.bolte(a)googlemail.com>
+ * Copyright (C) 2009-2012 Matthias Bolte <matthias.bolte(a)googlemail.com>
* Copyright (C) 2009 Maximilian Wilhelm <max(a)rfc2324.org>
*
* This library is free software; you can redistribute it and/or
@@ -467,12 +467,6 @@ esxSupportsLongMode(esxPrivate *priv)
goto cleanup;
}
- if (hostSystem == NULL) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("Could not retrieve the HostSystem object"));
- goto cleanup;
- }
-
for (dynamicProperty = hostSystem->propSet; dynamicProperty != NULL;
dynamicProperty = dynamicProperty->_next) {
if (STREQ(dynamicProperty->name, "hardware.cpuFeature")) {
@@ -534,7 +528,7 @@ esxLookupHostSystemBiosUuid(esxPrivate *priv, unsigned char *uuid)
int result = -1;
esxVI_String *propertyNameList = NULL;
esxVI_ObjectContent *hostSystem = NULL;
- esxVI_DynamicProperty *dynamicProperty = NULL;
+ char *uuid_string = NULL;
if (esxVI_EnsureSession(priv->primary) < 0) {
return -1;
@@ -543,41 +537,22 @@ esxLookupHostSystemBiosUuid(esxPrivate *priv, unsigned char *uuid)
if (esxVI_String_AppendValueToList(&propertyNameList,
"hardware.systemInfo.uuid") < 0 ||
esxVI_LookupHostSystemProperties(priv->primary, propertyNameList,
- &hostSystem) < 0) {
- goto cleanup;
- }
-
- if (hostSystem == NULL) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("Could not retrieve the HostSystem object"));
+ &hostSystem) < 0 ||
+ esxVI_GetStringValue(hostSystem, "hardware.systemInfo.uuid",
+ &uuid_string, esxVI_Occurrence_RequiredItem) < 0) {
goto cleanup;
}
- for (dynamicProperty = hostSystem->propSet; dynamicProperty != NULL;
- dynamicProperty = dynamicProperty->_next) {
- if (STREQ(dynamicProperty->name, "hardware.systemInfo.uuid")) {
- if (esxVI_AnyType_ExpectType(dynamicProperty->val,
- esxVI_Type_String) < 0) {
- goto cleanup;
- }
-
- if (strlen(dynamicProperty->val->string) > 0) {
- if (virUUIDParse(dynamicProperty->val->string, uuid) < 0) {
- VIR_WARN("Could not parse host UUID from string '%s'",
- dynamicProperty->val->string);
+ if (strlen(uuid_string) > 0) {
+ if (virUUIDParse(uuid_string, uuid) < 0) {
+ VIR_WARN("Could not parse host UUID from string '%s'", uuid_string);
- /* HostSystem has an invalid UUID, ignore it */
- memset(uuid, 0, VIR_UUID_BUFLEN);
- }
- } else {
- /* HostSystem has an empty UUID */
- memset(uuid, 0, VIR_UUID_BUFLEN);
- }
-
- break;
- } else {
- VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
+ /* HostSystem has an invalid UUID, ignore it */
+ memset(uuid, 0, VIR_UUID_BUFLEN);
}
+ } else {
+ /* HostSystem has an empty UUID */
+ memset(uuid, 0, VIR_UUID_BUFLEN);
}
result = 0;
@@ -1176,17 +1151,8 @@ esxSupportsVMotion(esxPrivate *priv)
if (esxVI_String_AppendValueToList(&propertyNameList,
"capability.vmotionSupported") < 0 ||
esxVI_LookupHostSystemProperties(priv->primary, propertyNameList,
- &hostSystem) < 0) {
- goto cleanup;
- }
-
- if (hostSystem == NULL) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("Could not retrieve the HostSystem object"));
- goto cleanup;
- }
-
- if (esxVI_GetBoolean(hostSystem, "capability.vmotionSupported",
+ &hostSystem) < 0 ||
+ esxVI_GetBoolean(hostSystem, "capability.vmotionSupported",
&priv->supportsVMotion,
esxVI_Occurrence_RequiredItem) < 0) {
goto cleanup;
@@ -1281,12 +1247,6 @@ esxGetHostname(virConnectPtr conn)
goto cleanup;
}
- if (hostSystem == NULL) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("Could not retrieve the HostSystem object"));
- goto cleanup;
- }
-
for (dynamicProperty = hostSystem->propSet; dynamicProperty != NULL;
dynamicProperty = dynamicProperty->_next) {
if (STREQ(dynamicProperty->name,
@@ -1379,12 +1339,6 @@ esxNodeGetInfo(virConnectPtr conn, virNodeInfoPtr nodeinfo)
goto cleanup;
}
- if (hostSystem == NULL) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("Could not retrieve the HostSystem object"));
- goto cleanup;
- }
-
for (dynamicProperty = hostSystem->propSet; dynamicProperty != NULL;
dynamicProperty = dynamicProperty->_next) {
if (STREQ(dynamicProperty->name, "hardware.cpuInfo.hz")) {
@@ -2702,12 +2656,6 @@ esxDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags)
goto cleanup;
}
- if (hostSystem == NULL) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("Could not retrieve the HostSystem object"));
- goto cleanup;
- }
-
for (dynamicProperty = hostSystem->propSet; dynamicProperty != NULL;
dynamicProperty = dynamicProperty->_next) {
if (STREQ(dynamicProperty->name, "capability.maxSupportedVcpus")) {
diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c
index c4217c9..f3a9e91 100644
--- a/src/esx/esx_vi.c
+++ b/src/esx/esx_vi.c
@@ -4570,8 +4570,8 @@ esxVI_ProductVersionToDefaultVirtualHWVersion(esxVI_ProductVersion productVersio
esxVI_DynamicProperty *dynamicProperty = NULL; \
\
if (ptrptr == NULL || *ptrptr != NULL) { \
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s", \
- _("Invalid argument")); \
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", \
+ _("Invalid argument")); \
return -1; \
} \
\
diff --git a/src/esx/esx_vi_types.c b/src/esx/esx_vi_types.c
index 36f3196..2236751 100644
--- a/src/esx/esx_vi_types.c
+++ b/src/esx/esx_vi_types.c
@@ -296,7 +296,8 @@
childNode = childNode->next) { \
if (childNode->type != XML_ELEMENT_NODE) { \
virReportError(VIR_ERR_INTERNAL_ERROR, \
- _("Wrong XML element type %d"), childNode->type); \
+ _("Wrong XML element type %d"), \
+ childNode->type); \
goto failure; \
} \
\
--
1.7.4.1
12 years, 8 months
[libvirt] [PATCH] esx: Fix dynamic deep copy
by Matthias Bolte
The static deep copy allocates storage for the copy. The dynamic
version injected the dynamic dispatch after the allocation. This
triggered the invalid argument check in the dynamically dispatched
deep copy call. The deep copy function expects its dest parameter
to be a pointer to a NULL-pointer. This expectation wasn't met due
to the dispatching deep copy doing the allocation before the call.
Fix this by dynamically dispatching to the correct type before the
allocation.
---
src/esx/esx_vi_types.c | 35 ++++++++++++++++++++++++++++++-----
1 files changed, 30 insertions(+), 5 deletions(-)
diff --git a/src/esx/esx_vi_types.c b/src/esx/esx_vi_types.c
index 8750554..36f3196 100644
--- a/src/esx/esx_vi_types.c
+++ b/src/esx/esx_vi_types.c
@@ -621,11 +621,36 @@
#define ESX_VI__TEMPLATE__DYNAMIC_DEEP_COPY(__type, _dispatch, _deep_copy) \
- ESX_VI__TEMPLATE__DEEP_COPY(__type, \
- ESX_VI__TEMPLATE__DISPATCH(src->_type, \
- esxVI_Type_ToString(src->_type), \
- __type, _dispatch, -1) \
- _deep_copy)
+ int \
+ esxVI_##__type##_DeepCopy(esxVI_##__type **dest, esxVI_##__type *src) \
+ { \
+ if (dest == NULL || *dest != NULL) { \
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", \
+ _("Invalid argument")); \
+ return -1; \
+ } \
+ \
+ if (src == NULL) { \
+ return 0; \
+ } \
+ \
+ ESX_VI__TEMPLATE__DISPATCH(src->_type, \
+ esxVI_Type_ToString(src->_type), \
+ __type, _dispatch, -1) \
+ \
+ if (esxVI_##__type##_Alloc(dest) < 0) { \
+ goto failure; \
+ } \
+ \
+ _deep_copy \
+ \
+ return 0; \
+ \
+ failure: \
+ esxVI_##__type##_Free(dest); \
+ \
+ return -1; \
+ }
--
1.7.4.1
12 years, 8 months
[libvirt] [PATCH] nwfilter: remove target table before renaming it
by Stefan Berger
Remove the target table before renaming a table to it, i.e.,
remove table B before renaming A to B. This makes the
renaming more robust against unconnected left-over tables.
---
src/nwfilter/nwfilter_ebiptables_driver.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
Index: libvirt-firewalld/src/nwfilter/nwfilter_ebiptables_driver.c
===================================================================
--- libvirt-firewalld.orig/src/nwfilter/nwfilter_ebiptables_driver.c
+++ libvirt-firewalld/src/nwfilter/nwfilter_ebiptables_driver.c
@@ -125,12 +125,18 @@ static const char ebiptables_script_func
"}\n";
static const char ebiptables_script_func_rename_chains[] =
+ "rename_chain()\n"
+ "{\n"
+ " $EBT -t nat -F $2\n"
+ " $EBT -t nat -X $2\n"
+ " $EBT -t nat -E $1 $2\n"
+ "}\n"
"rename_chains()\n"
"{\n"
" for tmp in $*; do\n"
" case $tmp in\n"
- " %c*) $EBT -t nat -E $tmp %c${tmp#?} ;;\n"
- " %c*) $EBT -t nat -E $tmp %c${tmp#?} ;;\n"
+ " %c*) rename_chain $tmp %c${tmp#?} ;;\n"
+ " %c*) rename_chain $tmp %c${tmp#?} ;;\n"
" esac\n"
" done\n"
"}\n";
12 years, 8 months
[libvirt] PF interface brought down if guest using a VF in hostdev mode under 802.1Qbh
by Nishank Trivedi (nistrive)
Hi,
In 802.1Qbh case where exists a SR-IOV capable network device, if any of
the virtual functions of this device is used in hostdev mode for the
guest, port-profile disassociate will also cause physical function
interface to go down. This appears to be a bug, but wanted to find if this
was done intentionally for some reasons.
To be more specific, if a network device supports SRIOV and its VF is
being used in pci passthrough mode, when the guest is shutdown or
destroyed following happens -
qemuProcessStop
\_ qemuDomainReAttachHostdevDevices(hostdevs)
\_ qemuDomainHostdevNetConfigRestore(hostdev)
\_ virNetDevPortProfileDisassociate(linkdev)
\_ virNetDevSetOnline(linkdev, false)
In above, qemuDomainHostdevNetConfigRestore() finds out the PF for
provided hostdev (which is VF) and passes it to
virNetDevPortProfileDisassociate() as linkdev. Later, linkdev gets passed
to virNetDevSetOnline() where the interface is brought down by clearing
IFF_UP flag.
However, in macvtap emulation mode,
virNetDevMacVLanDeleteWithVPortProfile() passes VF as linkdev (and -1 as
vf) to virNetDevPortProfileDisassociate(), hence, not affecting PF at all.
Bringing down a PF, when only VF is being brought down is not expected
behavior (unless, I'm missing something here). A way to get around it
would be to check if there exists vf (>=0) in
virNetDevPortProfileDisassociate(), and if so, it should only pass the
interface name of this VF rather than PF itself to virNetDevSetOnline().
If it sounds reasonable, I'll send out a fix.
Thanks,
Nishank
12 years, 8 months
[libvirt] virDomainMemoryStats call
by Parakkal, Navin S
Hi,
Is the array mstats returned by virDomainMemoryStats call cummulative or snapshot of the counter at that particular time ? I was of the opinion that is cummulative like the /proc counters but this counter seems to go backwards ie next snapshot value is less than the current one which makes me think these are snapshot values . I'm using RHEL 6.3 libvirt version 0.9.10.
Regards,
Navin
12 years, 8 months
[libvirt] [PATCH 5/5] Add qemu-agent-command command to virsh
by MATSUDA, Daiki
Add qemu-agent-command command to virsh to support virDomainQemuAgentCommand().
virsh-host.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 70 insertions(+)
diff --git a/tools/virsh-host.c b/tools/virsh-host.c
index d9d09b4..b9180f3 100644
--- a/tools/virsh-host.c
+++ b/tools/virsh-host.c
@@ -633,6 +633,74 @@ cleanup:
}
/*
+ * "qemu-agent-command" command
+ */
+static const vshCmdInfo info_qemu_agent_command[] = {
+ {"help", N_("Qemu Guest Agent Command")},
+ {"desc", N_("Qemu Guest Agent Command")},
+ {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_qemu_agent_command[] = {
+ {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
+ {"timeout", VSH_OT_INT, VSH_OFLAG_REQ_OPT, N_("timeout")},
+ {"cmd", VSH_OT_ARGV, VSH_OFLAG_REQ, N_("command")},
+ {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdQemuAgentCommand(vshControl *ctl, const vshCmd *cmd)
+{
+ virDomainPtr dom = NULL;
+ bool ret = false;
+ char *guest_agent_cmd = NULL;
+ char *result = NULL;
+ int timeout = 0;
+ unsigned int flags = 0;
+ const vshCmdOpt *opt = NULL;
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+ bool pad = false;
+
+ if (!vshConnectionUsability(ctl, ctl->conn))
+ goto cleanup;
+
+ dom = vshCommandOptDomain(ctl, cmd, NULL);
+ if (dom == NULL)
+ goto cleanup;
+
+ while ((opt = vshCommandOptArgv(cmd, opt))) {
+ if (pad)
+ virBufferAddChar(&buf, ' ');
+ pad = true;
+ virBufferAdd(&buf, opt->data, -1);
+ }
+ if (virBufferError(&buf)) {
+ vshPrint(ctl, "%s", _("Failed to collect command"));
+ goto cleanup;
+ }
+ guest_agent_cmd = virBufferContentAndReset(&buf);
+
+ if (vshCommandOptInt(cmd, "timeout", &timeout) < 0) {
+ timeout = 0;
+ }
+
+ if (virDomainQemuAgentCommand(dom, guest_agent_cmd, &result,
+ timeout, flags) < 0)
+ goto cleanup;
+
+ printf("%s\n", result);
+
+ ret = true;
+
+cleanup:
+ VIR_FREE(result);
+ VIR_FREE(guest_agent_cmd);
+ if (dom)
+ virDomainFree(dom);
+
+ return ret;
+}
+/*
* "sysinfo" command
*/
static const vshCmdInfo info_sysinfo[] = {
@@ -832,6 +900,8 @@ static const vshCmdDef hostAndHypervisorCmds[] = {
{"qemu-attach", cmdQemuAttach, opts_qemu_attach, info_qemu_attach, 0},
{"qemu-monitor-command", cmdQemuMonitorCommand, opts_qemu_monitor_command,
info_qemu_monitor_command, 0},
+ {"qemu-agent-command", cmdQemuAgentCommand, opts_qemu_agent_command,
+ info_qemu_agent_command, 0},
{"sysinfo", cmdSysinfo, NULL, info_sysinfo, 0},
{"uri", cmdURI, NULL, info_uri, 0},
{"version", cmdVersion, opts_version, info_version, 0},
12 years, 8 months
[libvirt] [PATCH 4/5] Add virDomainQemuAgentCommand() support function to python module
by MATSUDA, Daiki
Add virDomainQemuAgentCommand() support function to python module.
generator.py | 1 +
libvirt-qemu-override-api.xml | 8 ++++++++
libvirt-qemu-override.c | 31 +++++++++++++++++++++++++++++++
3 files changed, 40 insertions(+)
diff --git a/python/generator.py b/python/generator.py
index 6559ece..3cec12b 100755
--- a/python/generator.py
+++ b/python/generator.py
@@ -431,6 +431,7 @@ skip_impl = (
qemu_skip_impl = (
'virDomainQemuMonitorCommand',
+ 'virDomainQemuAgentCommand',
)
diff --git a/python/libvirt-qemu-override-api.xml b/python/libvirt-qemu-override-api.xml
index d69acea..37759d0 100644
--- a/python/libvirt-qemu-override-api.xml
+++ b/python/libvirt-qemu-override-api.xml
@@ -8,5 +8,13 @@
<arg name='cmd' type='const char *' info='the command which will be passed to QEMU monitor'/>
<arg name='flags' type='unsigned int' info='an OR'ed set of virDomainQemuMonitorCommandFlags'/>
</function>
+ <function name='virDomainQemuAgentCommand' file='python-qemu'>
+ <info>Send a Guest Agent command to domain</info>
+ <return type='str *' info='the command output or None in case of error'/>
+ <arg name='domain' type='virDomainPtr' info='pointer to the domain'/>
+ <arg name='cmd' type='const char *' info='guest agent command on domain'/>
+ <arg name='timeout' type='int' info='timeout seconds'/>
+ <arg name='flags' type='unsigned int' info='execution flags'/>
+ </function>
</symbols>
</api>
diff --git a/python/libvirt-qemu-override.c b/python/libvirt-qemu-override.c
index e532416..195aadc 100644
--- a/python/libvirt-qemu-override.c
+++ b/python/libvirt-qemu-override.c
@@ -82,6 +82,36 @@ libvirt_qemu_virDomainQemuMonitorCommand(PyObject *self ATTRIBUTE_UNUSED,
return py_retval;
}
+static PyObject *
+libvirt_qemu_virDomainQemuAgentCommand(PyObject *self ATTRIBUTE_UNUSED,
+ PyObject *args)
+{
+ PyObject *py_retval;
+ char *result = NULL;
+ virDomainPtr domain;
+ PyObject *pyobj_domain;
+ int timeout;
+ unsigned int flags;
+ char *cmd;
+ int c_retval;
+
+ if (!PyArg_ParseTuple(args, (char *)"Ozii:virDomainQemuAgentCommand",
+ &pyobj_domain, &cmd, &timeout, &flags))
+ return NULL;
+ domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain);
+
+ if (domain == NULL)
+ return VIR_PY_NONE;
+ LIBVIRT_BEGIN_ALLOW_THREADS;
+ c_retval = virDomainQemuAgentCommand(domain, cmd, &result, timeout, flags);
+ LIBVIRT_END_ALLOW_THREADS;
+
+ if (c_retval < 0)
+ return VIR_PY_NONE;
+
+ py_retval = PyString_FromString(result);
+ return py_retval;
+}
/************************************************************************
* *
* The registration stuff *
@@ -90,6 +120,7 @@ libvirt_qemu_virDomainQemuMonitorCommand(PyObject *self ATTRIBUTE_UNUSED,
static PyMethodDef libvirtQemuMethods[] = {
#include "libvirt-qemu-export.c"
{(char *) "virDomainQemuMonitorCommand", libvirt_qemu_virDomainQemuMonitorCommand, METH_VARARGS, NULL},
+ {(char *) "virDomainQemuAgentCommand", libvirt_qemu_virDomainQemuAgentCommand, METH_VARARGS, NULL},
{NULL, NULL, 0, NULL}
};
12 years, 8 months