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