Thanks Daniel for sharing the link. I got the idea and will try to adhere to the
standards.
One observation I want to share about "make check", with a fresh branch I see
one failure:
-----
.....!!!!!!...!!!!!!!!!!!!!!!!!!!!!!!!! 39 FAIL
FAIL: libvirtdconftest
TEST: capabilityschematest
.
.
.
=======================================
1 of 63 tests failed
Please report to libvir-list(a)redhat.com
=======================================
make[2]: *** [check-TESTS] Error 1
make[2]: Leaving directory `/home/abohra/libvirt_untouched/libvirt/tests'
make[1]: *** [check-am] Error 2
make[1]: Leaving directory `/home/abohra/libvirt_untouched/libvirt/tests'
make: *** [check-recursive] Error 1
---------------------
The branch with my patch also reports the same result, I have a feeling that this failure
may not be because of my commit, but I will double check everything (so far in my test bed
I can see new added functions working properly).
About the make syntax-check, I will update with the modifications.
Thanks!
Ata
Date: Mon, 9 Jul 2012 11:21:04 +0800
From: veillard(a)redhat.com
To: ata.husain(a)hotmail.com
CC: libvir-list(a)redhat.com
Subject: Re: [libvirt] [PATCH] ESX: Add routines to interface driver
On Sun, Jul 08, 2012 at 11:36:47AM -0700, Ata Bohra wrote:
> From: Ata E Husain <ata.husain(a)hotmail.com>
>
> Includes most of the dirver routines except DefineXML, I am working on it and will
update patch for it soon.
typo s/dirver/driver/
I guess you didn't really understand the reason why Doug asked you to
go though git-send-email
That part of the message is what will be recorded permanently in the
git patch database and is supposed to explain why that patch is needed
and how it does it. Comment about future patches are not supposed to
go there, but explanation of why that patch is there, its function.
I would suggest reading some of the rants from the kernel guys
about why they get grumpy when receiving patches, this can be
educational and even fun at times :-) For example James Bottomley
https://events.linuxfoundation.org/images/stories/pdf/lcjp2012_bottomley.pdf
around page 17 or one of the presentations from Greg Kroah-Hartman
(but it's better to watch them than read them ;-)
> diff --git a/src/esx/esx_interface_driver.c b/src/esx/esx_interface_driver.c
> index 5713137..4feadc2 100644
> --- a/src/esx/esx_interface_driver.c
> +++ b/src/esx/esx_interface_driver.c
> @@ -23,6 +23,10 @@
> */
>
> #include <config.h>
> +#include <sys/socket.h>
> +#include <netinet/in.h>
> +#include <arpa/inet.h>
> +#include <libxml/parser.h>
>
> #include "internal.h"
> #include "util.h"
> @@ -34,10 +38,10 @@
> #include "esx_vi.h"
> #include "esx_vi_methods.h"
> #include "esx_util.h"
> +#include "interface_conf.h"
>
> #define VIR_FROM_THIS VIR_FROM_ESX
> -
> -
> +#define XML_CAST (const xmlChar*)
>
> static virDrvOpenStatus
> esxInterfaceOpen(virConnectPtr conn,
> @@ -67,10 +71,565 @@ esxInterfaceClose(virConnectPtr conn)
>
>
>
> +static int
> +esxNumOfInterfaces(virConnectPtr conn)
> +{
> + esxPrivate *priv = conn->interfacePrivateData;
> + esxVI_HostVirtualNic *virtualNicList = NULL;
> + const esxVI_HostVirtualNic *virtualNic = NULL;
> + int count = 0;
> +
> + if (esxVI_EnsureSession(priv->primary) < 0 ||
> + esxVI_LookupVirtualNicList(priv->primary, &virtualNicList) < 0)
{
> + goto cleanup;
> + }
> +
> + if (virtualNicList == NULL) {
> + ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("Could not retrieve vNic List"));
> +
> + goto cleanup;
> + }
> +
> + for (virtualNic = virtualNicList;
> + virtualNic != NULL;
> + virtualNic = virtualNic->_next) {
> + count++;
> + }
> +
> +cleanup:
> + esxVI_HostVirtualNic_Free(&virtualNicList);
> +
> + return count;
> +}
> +
> +
> +
> +static int
> +esxNumOfDefinedInterfaces(virConnectPtr conn)
> +{
> + conn->interfacePrivateData = NULL;
> +
> + // ESX interfaces are always active
> + return 0;
> +}
> +
> +
> +
> +static int
> +esxListInterfaces(virConnectPtr conn, char **names, int maxnames)
> +{
> + esxPrivate *priv = conn->interfacePrivateData;
> + esxVI_HostVirtualNic *virtualNicList = NULL;
> + const esxVI_HostVirtualNic *virtualNic = NULL;
> + int result = -1;
> + int i = 0;
> +
> + if (esxVI_EnsureSession(priv->primary) < 0 ||
> + esxVI_LookupVirtualNicList(priv->primary,
> + &virtualNicList) < 0) {
> + goto cleanup;
> + }
> +
> + if (virtualNicList == NULL) {
> + ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("Could not retrieve vNIC List"));
> + goto cleanup;
> + }
> +
> + for (i= 0, virtualNic = virtualNicList;
> + virtualNic != NULL && i < maxnames;
> + ++i, virtualNic = virtualNic->_next) {
> + names[i] = strdup(virtualNic->device);
> +
> + if (names[i] == NULL) {
> + for(;i >=0;--i) {
> + VIR_FREE(names[i]);
> + }
> + virReportOOMError();
> + goto cleanup;
> + }
> + }
> +
> + result = i;
> + cleanup:
> + esxVI_HostVirtualNic_Free(&virtualNicList);
> +
> + return result;
> +}
> +
> +
> +
> +static int
> +esxListDefinedInterfaces(virConnectPtr conn, char **names, int maxnames)
> +{
> + conn->interfacePrivateData = NULL;
> + *names = NULL;
> +
> + /* keeps compiler happy */
> + VIR_DEBUG("Max Interfaces: %d", maxnames);
> + /* ESX interfaces are always active */
> + return 0;
> +}
> +
> +
> +
> +static virInterfacePtr
> +esxInterfaceLookupByName(virConnectPtr conn, const char *name)
> +{
> + esxPrivate *priv = conn->interfacePrivateData;
> + esxVI_HostVirtualNic *virtualNicList = NULL;
> + const esxVI_HostVirtualNic *virtualNic = NULL;
> + virInterfacePtr ret = NULL;
> +
> + if (esxVI_EnsureSession(priv->primary) < 0 ||
> + esxVI_LookupVirtualNicList(priv->primary,
> + &virtualNicList) < 0) {
> + goto cleanup;
> + }
> +
> + if (virtualNicList == 0) {
> + ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("Could not retrieve vNIC List"));
> + goto cleanup;
> + }
> +
> +
> + for(virtualNic = virtualNicList;
> + virtualNic != NULL;
> + virtualNic = virtualNic->_next) {
> + if (STREQ(virtualNic->device, name)) {
> + if (virtualNic->spec == NULL ||
> + virtualNic->spec->mac == NULL) {
> + ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("Malformed HostVirtualNicSpec"));
> + goto cleanup;
> + }
> +
> + ret = virGetInterface(conn, virtualNic->device,
virtualNic->spec->mac);
> + break;
> + }
> + }
> +
> + cleanup:
> + esxVI_HostVirtualNic_Free(&virtualNicList);
> +
> + return ret;
> +}
> +
> +
> +
> +static virInterfacePtr
> +esxInterfaceLookupByMACString(virConnectPtr conn, const char *mac)
> +{
> + esxPrivate *priv = conn->interfacePrivateData;
> + esxVI_HostVirtualNic *virtualNicList = NULL;
> + const esxVI_HostVirtualNic *virtualNic = NULL;
> + virInterfacePtr ret = NULL;
> +
> + if (esxVI_EnsureSession(priv->primary) < 0 ||
> + esxVI_LookupVirtualNicList(priv->primary,
> + &virtualNicList) < 0) {
> + goto cleanup;
> + }
> +
> + if (virtualNicList == 0) {
> + ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("Could not retrieve vNIC List"));
> + goto cleanup;
> + }
> +
> +
> + for(virtualNic = virtualNicList;
> + virtualNic != NULL;
> + virtualNic = virtualNic->_next) {
> + if (virtualNic->spec == NULL ||
> + virtualNic->spec->mac == NULL) {
> + ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("Malformed HostVirtualNicSpec"));
> + goto cleanup;
> + }
> +
> + if (STREQ(virtualNic->spec->mac, mac)) {
> + ret =
> + virGetInterface(conn, virtualNic->device,
virtualNic->spec->mac);
> + break;
> + }
> + }
> +
> + cleanup:
> + esxVI_HostVirtualNic_Free(&virtualNicList);
> +
> + return ret;
> +}
> +
> +
> +/**
> + * Generates native XML descritpor for a given interface.
> + * For instance:
> + * <interface type="bridge" name="%s">
> + * <start mode="onboot"/>"
> + * <mtu size="%d"/>"
> + * <mac address="%s"/>
> + * <protocol family="ipv4">
> + * <dhcp/>
> + * <ip address="%s" prefix="%d"/>
> + * <route gateway="%s"/>
> + * </protocol>
> + * <bridge stp="off">
> + * <interface type="ethernet" name="%s">
> + * <mac address="%s"/>
> + * </interface>
> + * </bridge>
> + * </interface>
> + */
> +static char*
> +esxGetNativeInterfaceXMLDesc(const esxVI_HostVirtualNic *virtualNic,
> + const esxVI_HostIpRouteConfig *ipRouteConfig,
> + const esxVI_PhysicalNic *physicalNicList,
> + const unsigned int flags)
> +{
> + const esxVI_PhysicalNic *physicalNic = NULL;
> + xmlDocPtr doc = NULL;
> + xmlNodePtr root = NULL;
> + xmlNodePtr startNode = NULL;
> + xmlNodePtr mtuNode = NULL;
> + xmlNodePtr protocolNode = NULL;
> + xmlNodePtr bridgeNode = NULL;
> + xmlNodePtr dhcpNode = NULL;
> + xmlChar *xmlbuff = NULL;
> + int use_static = 0;
> + struct in_addr addr;
> + uint32_t host_addr = 0;
> + int zero_count = 0;
> + int masklen = 0;
> + int i = 0;
> + virBuffer item = VIR_BUFFER_INITIALIZER;
> + int bufferSize = 0;
> + char *ret = NULL;
> +
> + if (VIR_INTERFACE_XML_INACTIVE & flags) {
> + use_static = 1;
> + }
> +
> + doc = xmlNewDoc(XML_CAST "1.0");
> + root = xmlNewDocNode(doc, NULL, XML_CAST "interface", NULL);
> +
> + xmlNewProp(root, XML_CAST "type", XML_CAST "bridge");
> + xmlNewProp(root, XML_CAST "name", XML_CAST virtualNic->device);
> + xmlDocSetRootElement(doc, root);
> +
> + /* define boot start mode */
> + startNode = xmlNewChild(root, NULL, XML_CAST "start", NULL);
> + xmlNewProp(startNode, XML_CAST "mode", XML_CAST "onboot");
> +
> + /* append mtu value */
> + mtuNode = xmlNewChild(root, NULL, XML_CAST "mtu", NULL);
> + virBufferAsprintf(&item, "%d",virtualNic->spec->mtu
&&
> + virtualNic->spec->mtu->value ?
> + virtualNic->spec->mtu->value :
> + 1500);
> + const char *mtustr = virBufferContentAndReset(&item);
> + if (mtustr == NULL) {
> + virReportOOMError();
> + goto cleanup;
> + }
> + xmlNewProp(mtuNode, XML_CAST "size", XML_CAST mtustr);
> +
> + /* append mac address field */
> + if (!use_static && virtualNic->spec->mac) {
> + xmlNodePtr mac_node = xmlNewChild(root, NULL, XML_CAST "mac",
NULL);
> + xmlNewProp(mac_node, XML_CAST "address",
> + XML_CAST virtualNic->spec->mac);
> + }
> +
> + /* TODO - Handle VLAN (via portgroup?) */
> + if (virtualNic->spec->ip->subnetMask &&
> + *virtualNic->spec->ip->subnetMask &&
> + inet_aton(virtualNic->spec->ip->subnetMask, &addr) == 0) {
> + ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("Error parsing netmask"));
> + goto cleanup;
> + }
> +
> + host_addr = ntohl(addr.s_addr);
> + /* Calculate masklen */
> + for (i = 0; i < 32; ++i) {
> + if (host_addr & 0x01) {
> + break;
> + }
> + zero_count++;
> + host_addr >>= 1;
> + }
> + masklen = 32 - zero_count;
> +
> + /* append protocol field */
> + /* TODO - Add IPv6 Support */
> + protocolNode = xmlNewChild(root, NULL, XML_CAST "protocol", NULL);
> + xmlNewProp(protocolNode, XML_CAST "family", XML_CAST
"ipv4");
> + if (virtualNic->spec->ip->dhcp == 1) {
> + dhcpNode = xmlNewChild(protocolNode, NULL, XML_CAST "dhcp",
NULL);
> + /* avoids compiler warning */
> + VIR_DEBUG("dhcpNode name: %s", (char *)dhcpNode->name);
> + }
> +
> + if (virtualNic->spec->ip->dhcp != 1 || !use_static) {
> + if (virtualNic->spec->ip->ipAddress &&
> + *virtualNic->spec->ip->ipAddress) {
> + xmlNodePtr ipAddrNode =
> + xmlNewChild(protocolNode, NULL, XML_CAST "ip", NULL);
> + xmlNewProp(ipAddrNode, XML_CAST "address", XML_CAST
> + virtualNic->spec->ip->ipAddress);
> +
> + virBufferAsprintf(&item, "%d", masklen);
> + const char *maskstr = virBufferContentAndReset(&item);
> + if (maskstr == NULL) {
> + virReportOOMError();
> + goto cleanup;
> + }
> + xmlNewProp(ipAddrNode, XML_CAST "prefix", XML_CAST maskstr);
> +
> + xmlNodePtr routeNode =
> + xmlNewChild(protocolNode, NULL, XML_CAST "route", NULL);
> + xmlNewProp(routeNode, XML_CAST "gateway",
> + XML_CAST ipRouteConfig->defaultGateway);
> + }
> + }
> +
> + /* Add bridge information */
> + bridgeNode = xmlNewChild(root, NULL, XML_CAST "bridge", NULL);
> + xmlNewProp(bridgeNode, XML_CAST "stp", XML_CAST "off");
> +
> + for (physicalNic = physicalNicList;
> + physicalNic != NULL;
> + physicalNic = physicalNic->_next) {
> + xmlNodePtr bridgeIfaceNode =
> + xmlNewChild(bridgeNode, NULL, XML_CAST "interface", NULL);
> + xmlNewProp(bridgeIfaceNode, XML_CAST "type", XML_CAST
"ethernet");
> + xmlNewProp(bridgeIfaceNode, XML_CAST "name",
> + XML_CAST physicalNic->device);
> +
> + xmlNodePtr bridgeIfaceMacNode =
> + xmlNewChild(bridgeIfaceNode, NULL, XML_CAST "mac", NULL);
> + xmlNewProp(bridgeIfaceMacNode, XML_CAST "address",
> + XML_CAST physicalNic->mac);
> + }
> +
> + xmlDocDumpFormatMemory(doc, &xmlbuff, &bufferSize, 1);
> + if (xmlbuff == NULL) {
> + virReportOOMError();
> + goto cleanup;
> + }
> +
> + ret = strdup((char *)xmlbuff);
> + if (ret == NULL) {
> + virReportOOMError();
> + goto cleanup;
> + }
> +
> + cleanup:
> + VIR_FREE(mtustr);
> + if (xmlbuff != NULL) {
> + xmlFree(xmlbuff);
> + }
That should not pass "make syntax-check" did you run that on your
tree ? xmlFree will check for NULL no need to double the test.
also none of the xmlNew... function are checked for return error,
that should probably be added, they are allocating memory and they
can fail.
> + xmlFreeDoc(doc);
> +
> + return ret;
> +}
> +
> +
> +
> +static char*
> +esxInterfaceGetXMLDesc(virInterfacePtr iface, unsigned int flags)
> +{
> + esxPrivate *priv = iface->conn->interfacePrivateData;
> + esxVI_HostVirtualNic *virtualNicList = NULL;
> + esxVI_HostVirtualNic *virtualNic = NULL;
> + esxVI_PhysicalNic *physicalNicList = NULL;
> + esxVI_PhysicalNic *matchingPhysicalNicList = NULL;
> + esxVI_HostIpRouteConfig *ipRouteConfig = NULL;
> + esxVI_HostPortGroup *portGroupList = NULL;
> + esxVI_HostVirtualSwitch *virtualSwitchList = NULL;
> + esxVI_String *propertyNameList = NULL;
> + esxVI_ObjectContent *hostSystem = NULL;
> + esxVI_DynamicProperty *dynamicProperty = NULL;
> + virInterfaceDefPtr def = NULL;
> + char *xmlstr = NULL;
> + char *ret = NULL;
> +
> + if (esxVI_EnsureSession(priv->primary) < 0 ||
> + esxVI_String_AppendValueListToList(&propertyNameList,
> + "config.network.vnic\0"
> + "config.network.ipRouteConfig\0"
> + "config.network.vswitch\0"
> + "config.network.pnic\0"
> + "config.network.portgroup\0") < 0 ||
> + esxVI_LookupHostSystemProperties(priv->primary, propertyNameList,
> + &hostSystem) < 0) {
> + goto cleanup;
> + }
> +
> + for (dynamicProperty = hostSystem->propSet; dynamicProperty != NULL;
> + dynamicProperty = dynamicProperty->_next) {
> + if (STREQ(dynamicProperty->name, "config.network.vnic")) {
> + if (esxVI_HostVirtualNic_CastListFromAnyType(dynamicProperty->val,
> + &virtualNicList)
> + < 0) {
> + goto cleanup;
> + }
> + } else if (STREQ(dynamicProperty->name,
"config.network.ipRouteConfig")) {
> + if (esxVI_HostIpRouteConfig_CastFromAnyType(dynamicProperty->val,
> + &ipRouteConfig)) {
> + goto cleanup;
> + }
> + } else if (STREQ(dynamicProperty->name,
"config.network.vswitch")) {
> + if (esxVI_HostVirtualSwitch_CastListFromAnyType
> + (dynamicProperty->val, &virtualSwitchList) < 0) {
> + goto cleanup;
> + }
> + } else if (STREQ(dynamicProperty->name,
"config.network.pnic")) {
> + if (esxVI_PhysicalNic_CastListFromAnyType(dynamicProperty->val,
> + &physicalNicList)
> + < 0) {
> + goto cleanup;
> + }
> + } else if (STREQ(dynamicProperty->name,
"config.network.portgroup")) {
> + if (esxVI_HostPortGroup_CastListFromAnyType(dynamicProperty->val,
> + &portGroupList)
> + < 0) {
> + goto cleanup;
> + }
> + } else {
> + VIR_WARN("Unexpected '%s' property",
dynamicProperty->name);
> + }
> + }
> +
> + if (!virtualNicList ||
> + !ipRouteConfig ||
> + !virtualSwitchList ||
> + !portGroupList) {
> + ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("Unable to retrieve network parameters"));
> +
> + goto cleanup;
> + }
> +
> + for (virtualNic = virtualNicList;
> + virtualNic != NULL;
> + virtualNic = virtualNic->_next) {
> + if (STREQ(virtualNic->device, iface->name)) {
> + break;
> + }
> + }
> +
> + if (virtualNic == NULL) {
> + ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("Could not find Interface"));
> + goto cleanup;
> + }
> +
> + if (esxVI_LookupPhysicalNicFromPortGroup(virtualNic->portgroup,
> + portGroupList,
> + virtualSwitchList,
> + physicalNicList,
> + &matchingPhysicalNicList) < 0)
{
> + ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("No Physical NIC found matching Virtual NIC's
portgroup"));
> + goto cleanup;
> + }
> +
> + /* create a xml descriptor and parse it using virInterfaceDefParseString */
> + xmlstr = esxGetNativeInterfaceXMLDesc(virtualNic,
> + ipRouteConfig,
> + matchingPhysicalNicList,
> + flags);
> + if (xmlstr == NULL) {
> + goto cleanup;
> + }
> +
> + def = virInterfaceDefParseString(xmlstr);
> + if (!def) {
> + goto cleanup;
> + }
> +
> + ret = virInterfaceDefFormat(def);
> + if (!ret) {
> + goto cleanup;
> + }
> +
> + cleanup:
> + esxVI_HostVirtualNic_Free(&virtualNicList);
> + esxVI_PhysicalNic_Free(&physicalNicList);
> + esxVI_PhysicalNic_Free(&matchingPhysicalNicList);
> + esxVI_HostPortGroup_Free(&portGroupList);
> + esxVI_HostVirtualSwitch_Free(&virtualSwitchList);
> + esxVI_HostIpRouteConfig_Free(&ipRouteConfig);
> + esxVI_ObjectContent_Free(&hostSystem);
> + esxVI_String_Free(&propertyNameList);
> + virInterfaceDefFree(def);
> + VIR_FREE(xmlstr);
> +
> + return ret;
> +}
> +
> +
> +
> +static int
> +esxInterfaceUndefine(virInterfacePtr iface)
> +{
> + esxPrivate *priv = iface->conn->interfacePrivateData;
> +
> + if (esxVI_RemoveVirtualNic(
> + priv->primary,
> + priv->primary->hostSystem->configManager->networkSystem,
> + iface->name) < 0) {
> + ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("Error deleting interface"));
> + return -1;
> + }
> +
> + return 0;
> +}
> +
> +
> +
> +static int
> +esxInterfaceCreate(virInterfacePtr iface, unsigned int flags)
> +{
> + iface->conn->interfacePrivateData = NULL;
> +
> + virCheckFlags(0, -1);
> +
> + /* ESX interfaces are always active */
> + return 0;
> +}
> +
> +
> +static int
> +esxInterfaceDestroy(virInterfacePtr iface, unsigned int flags)
> +{
> + iface->conn->privateData = NULL;
> +
> + virCheckFlags(0, -1);
> +
> + /* ESX does not support deactivating interfaces */
> + return 1;
> +}
> +
> static virInterfaceDriver esxInterfaceDriver = {
> .name = "ESX",
> - .open = esxInterfaceOpen, /* 0.7.6 */
> - .close = esxInterfaceClose, /* 0.7.6 */
> + .open = esxInterfaceOpen, /* 0.7.6 */
> + .close = esxInterfaceClose, /* 0.7.6 */
> + .numOfInterfaces = esxNumOfInterfaces, /* 0.9.x */
> + .numOfDefinedInterfaces = esxNumOfDefinedInterfaces, /* 0.9.x */
> + .listInterfaces = esxListInterfaces, /* 0.9.x */
> + .listDefinedInterfaces = esxListDefinedInterfaces, /* 0.9.x */
> + .interfaceLookupByName = esxInterfaceLookupByName, /* 0.9.x */
> + .interfaceLookupByMACString = esxInterfaceLookupByMACString, /* 0.9.x */
> + .interfaceGetXMLDesc = esxInterfaceGetXMLDesc, /* 0.9.x */
> + .interfaceUndefine = esxInterfaceUndefine, /* 0.9.x */
> + .interfaceCreate = esxInterfaceCreate, /* 0.9.x */
> + .interfaceDestroy = esxInterfaceDestroy, /* 0.9.x */
> };
>
>
> diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c
> index 5b5ab69..df9f8df 100644
> --- a/src/esx/esx_vi.c
> +++ b/src/esx/esx_vi.c
> @@ -4414,4 +4414,134 @@ esxVI_LookupManagedObjectHelper(esxVI_Context *ctx,
>
>
>
> +int
> +esxVI_LookupVirtualNicList(esxVI_Context* ctx,
> + esxVI_HostVirtualNic** virtualNicList)
> +{
> + int result = -1;
> + esxVI_String *propertyNameList = NULL;
> + esxVI_DynamicProperty *dynamicProperty = NULL;
> + esxVI_ObjectContent* hostSystem = NULL;
> +
> + if (esxVI_String_AppendValueListToList(
> + &propertyNameList, "config.network.vnic\0") < 0 ||
> + esxVI_LookupHostSystemProperties(ctx, propertyNameList, &hostSystem)
< 0) {
> + goto cleanup;
> + }
> +
> + if (hostSystem == NULL) {
> + ESX_VI_ERROR(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, "config.network.vnic")) {
> + if (esxVI_HostVirtualNic_CastListFromAnyType(dynamicProperty->val,
> + virtualNicList) < 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_LookupPhysicalNicFromPortGroup(
> + const char *portgroup,
> + const esxVI_HostPortGroup *portGroupList,
> + const esxVI_HostVirtualSwitch *virtualSwitchList,
> + const esxVI_PhysicalNic *physicalNicList,
> + esxVI_PhysicalNic **ret_physicalNicList)
> +{
> + int result = -1;
> + const esxVI_HostPortGroup *portGroup = NULL;
> + const esxVI_HostVirtualSwitch *virtualSwitch = NULL;
> + esxVI_PhysicalNic *matchingPhysicalNicList = NULL;
> + const esxVI_PhysicalNic *physicalNic = NULL;
> + esxVI_PhysicalNic *tempPhysicalNic = NULL;
> + const esxVI_String *pnicKey = NULL;
> +
> + if (portgroup == NULL) {
> + ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("No Portgroup found!"));
> + goto cleanup;
> + }
> +
> + /* Go through all the port groups to find the one that matches. */
> + for (portGroup = portGroupList;
> + portGroup != NULL;
> + portGroup = portGroup->_next) {
> + if (STREQ(portGroup->spec->name, portgroup)) {
> + break;
> + }
> + }
> +
> + if (portGroup == NULL) {
> + ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("Could not find Host port group"));
> + goto cleanup;
> + }
> +
> + /* Go through all the virtual switches to find the one that matches */
> + for (virtualSwitch = virtualSwitchList;
> + virtualSwitch != NULL;
> + virtualSwitch = virtualSwitch->_next) {
> + if (STREQ(portGroup->spec->vswitchName, virtualSwitch->name)) {
> + break;
> + }
> + }
> +
> + if (virtualSwitch == NULL) {
> + ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("Could not find Virtual Switch"));
> + goto cleanup;
> + }
> +
> + /* Go through all physical nics */
> + for (pnicKey = virtualSwitch->pnic;
> + pnicKey != NULL;
> + pnicKey = pnicKey->_next) {
> + /* O(n^2), but probably faster than a hash due to small N */
> + for (physicalNic = physicalNicList;
> + physicalNic != NULL;
> + physicalNic = physicalNic->_next) {
> +
> + if (STREQ(pnicKey->value, physicalNic->key)) {
> + if (esxVI_PhysicalNic_DeepCopy(&tempPhysicalNic,
> + (esxVI_PhysicalNic *)physicalNic) < 0 ||
> + esxVI_PhysicalNic_AppendToList(&matchingPhysicalNicList,
> + tempPhysicalNic) < 0) {
> + goto cleanup;
> + }
> + tempPhysicalNic = NULL;
> + }
> + }
> + }
> +
> + *ret_physicalNicList = matchingPhysicalNicList;
> + matchingPhysicalNicList = NULL; /* no cleanup needed */
> + tempPhysicalNic = NULL; /* no cleanup needed */
> + result = 0;
> + cleanup:
> + esxVI_PhysicalNic_Free(&matchingPhysicalNicList);
> + esxVI_PhysicalNic_Free(&tempPhysicalNic);
> + return result;
> +}
> +
> #include "esx_vi.generated.c"
> diff --git a/src/esx/esx_vi.h b/src/esx/esx_vi.h
> index 78d3986..11bc52e 100644
> --- a/src/esx/esx_vi.h
> +++ b/src/esx/esx_vi.h
> @@ -487,6 +487,16 @@ int esxVI_ParseHostCpuIdInfo(esxVI_ParsedHostCpuIdInfo
*parsedHostCpuIdInfo,
>
> int esxVI_ProductVersionToDefaultVirtualHWVersion(esxVI_ProductVersion
productVersion);
>
> +int esxVI_LookupVirtualNicList(esxVI_Context* ctx,
> + esxVI_HostVirtualNic** virtualNicList);
> +
> +int esxVI_LookupPhysicalNicFromPortGroup(
> + const char *portgroup,
> + const esxVI_HostPortGroup *portGroupList,
> + const esxVI_HostVirtualSwitch *virtualSwitchList,
> + const esxVI_PhysicalNic *physicalNicList,
> + esxVI_PhysicalNic **ret_physicalNicList);
> +
> # include "esx_vi.generated.h"
>
> #endif /* __ESX_VI_H__ */
> diff --git a/src/esx/esx_vi_generator.input b/src/esx/esx_vi_generator.input
> index 1a67a8c..b99fee6 100644
> --- a/src/esx/esx_vi_generator.input
> +++ b/src/esx/esx_vi_generator.input
> @@ -57,6 +57,29 @@ enum AutoStartWaitHeartbeatSetting
> systemDefault
> end
>
> +enum HostConfigChangeOperation
> + add
> + edit
> + remove
> +end
> +
> +enum HostIpConfigIpV6AdressStatus
> + deprecated
> + duplicate
> + inaccessible
> + invalid
> + preferred
> + tentative
> + unknown
> +end
> +
> +enum HostIpConfigV6AdressConfigType
> + dhcp
> + linklayer
> + manual
> + other
> + random
> +end
>
> enum ManagedEntityStatus
> gray
> @@ -89,6 +112,12 @@ enum PerfSummaryType
> none
> end
>
> +enum PortGroupConnecteeType
> + host
> + systemManagement
> + unknown
> + virtualMachine
> +end
>
> enum PropertyChangeOp
> add
> @@ -197,6 +226,12 @@ object DeviceBackedVirtualDiskSpec extends VirtualDiskSpec
> String device r
> end
>
> +object DistributedVirtualSwitchPortConnection
> + Int connectionCookie o
> + String portgroupKey o
> + String portKey o
> + String switchUuid r
> +end
>
> object DynamicProperty
> String name r
> @@ -316,6 +351,34 @@ object HostFileSystemVolume
> Long capacity r
> end
>
> +object HostIpConfig
> + Boolean dhcp r
> + String ipAddress o
> + HostIpConfigIpV6AddressConfiguration ipV6Config o
> + String subnetMask o
> +end
> +
> +object HostIpConfigIpV6Address
> + String dadState o
> + String ipAddress r
> + DateTime lifetime o
> + String operation o
> + String origin o
> + Int prefixLength r
> +end
> +
> +object HostIpConfigIpV6AddressConfiguration
> + Boolean autoConfigurationEnabled o
> + Boolean dhcpV6Enabled o
> + HostIpConfigIpV6Address ipV6Address ol
> +end
> +
> +object HostIpRouteConfig
> + String defaultGateway o
> + String gatewayDevice o
> + String ipV6DefaultGateway o
> + String ipV6GatewayDevice o
> +end
>
> object HostMountInfo
> String path o
> @@ -331,11 +394,134 @@ object HostNasVolume extends
HostFileSystemVolume
> end
>
>
> +object HostNicTeamingPolicy
> + HostNicFailureCriteria failureCriteria o
> + HostNicOrderPolicy nicOrder o
> + Boolean notifySwitches o
> + String policy o
> + Boolean reversePolicy o
> + Boolean rollingOrder o
> +end
> +
> +object HostNetOffloadCapabilities
> + Boolean csumOffload o
> + Boolean tcpSegmentation o
> + Boolean zeroCopyXmit o
> +end
> +
> +object HostNetworkSecurityPolicy
> + Boolean allowPromiscuous o
> + Boolean forgedTransmits o
> + Boolean macChanges o
> +end
> +
> +object HostNetworkPolicy
> + HostNicTeamingPolicy nicTeaming o
> + HostNetOffloadCapabilities offloadPolicy o
> + HostNetworkSecurityPolicy security o
> + HostNetworkTrafficShapingPolicy shapingPolicy o
> +end
> +
> +object HostNetworkTrafficShapingPolicy
> + Long averageBandwidth o
> + Long burstLong o
> + Boolean enabled o
> + Long peakBandwidth 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 HostPortGroup
> + String key r
> + HostPortGroupPort port ol
> + String vswitch r
> + HostNetworkPolicy computedPolicy r
> + HostPortGroupSpec spec r
> +end
> +
> +object HostPortGroupPort
> + String key o
> + String mac ol
> + String type r
> +end
> +
> +object HostPortGroupSpec
> + String name r
> + HostNetworkPolicy policy r
> + Int vlanId r
> + String vswitchName r
> +end
> +
> object HostScsiDiskPartition
> String diskName r
> Int partition r
> end
>
> +object HostVirtualNic
> + String device r
> + String key r
> + String port o
> + String portgroup r
> + HostVirtualNicSpec spec r
> +end
> +
> +object HostVirtualNicSpec
> + DistributedVirtualSwitchPortConnection distributedVirtualPort o
> + HostIpConfig ip o
> + String mac o
> + Int mtu o
> + String portgroup o
> + Boolean tsoEnabled o
> +end
> +
> +
> +object HostVirtualSwitch
> + String key r
> + Int mtu o
> + String name r
> + Int numPorts r
> + Int numPortsAvailable r
> + String pnic ol
> + String portgroup ol
> + HostVirtualSwitchSpec spec r
> +end
> +
> +object HostVirtualSwitchBridge
> +end
> +
> +object HostVirtualSwitchAutoBridge extends HostVirtualSwitchBridge
> + String excludedNicDevice ol
> +end
> +
> +object HostVirtualSwitchBeaconBridge extends HostVirtualSwitchBridge
> + Int interval r
> +end
> +
> +object HostVirtualSwitchBondBridge extends HostVirtualSwitchBridge
> + HostVirtualSwitchBeaconBridge beacon o
> + LinkDiscoveryProtocolConfig linkDiscoveryProtocolConfig o
> + String nicDevice rl
> +end
> +
> +object HostVirtualSwitchSpec
> + HostVirtualSwitchBridge bridge o
> + Int mtu o
> + Int numPorts r
> + HostNetworkPolicy policy o
> +end
>
> object HostVmfsVolume extends HostFileSystemVolume
> Int blockSizeMb r
> @@ -355,6 +541,10 @@ end
> object IsoImageFileQuery extends FileQuery
> end
>
> +object LinkDiscoveryProtocolConfig
> + String operation r
> + String protocol r
> +end
>
> object LocalDatastoreInfo extends DatastoreInfo
> String path o
> @@ -398,6 +588,10 @@ object OptionType
> Boolean valueIsReadonly o
> end
>
> +object OptionValue
> + String key r
> + AnyType value r
> +end
>
> object PerfCounterInfo
> Int key r
> @@ -454,6 +648,27 @@ object PerfSampleInfo
> Int interval r
> end
>
> +object PhysicalNic
> + String device r
> + String driver o
> + String key o
> + PhysicalNicInfo linkSpeed o
> + String mac r
> + String pci r
> + PhysicalNicSpec spec r
> + PhysicalNicInfo validLinkSpecification ol
> + Boolean wakeOnLanSupported r
> +end
> +
> +object PhysicalNicInfo
> + Boolean duplex r
> + Int speedMb r
> +end
> +
> +object PhysicalNicSpec
> + HostIpConfig ip o
> + PhysicalNicInfo linkSpeed o
> +end
>
> object PropertyChange
> String name r
> @@ -490,7 +705,6 @@ object ResourceAllocationInfo
> Long overheadLimit o
> end
>
> -
> object ResourcePoolResourceUsage
> Long reservationUsed r
> Long reservationUsedForVm r
> @@ -954,6 +1168,10 @@ method RemoveSnapshot_Task returns
ManagedObjectReference r
> Boolean removeChildren r
> end
>
> +method RemoveVirtualNic
> + ManagedObjectReference _this r
> + String device r
> +end
>
> method RetrieveProperties returns ObjectContent ol
> ManagedObjectReference _this:propertyCollector r
> @@ -1002,6 +1220,16 @@ method UnregisterVM
> ManagedObjectReference _this r
> end
>
> +method UpdateIpRouteConfig
> + ManagedObjectReference _this r
> + HostIpRouteConfig config r
> +end
> +
> +method UpdateVirtualNic
> + ManagedObjectReference _this r
> + String device r
> + HostVirtualNicSpec nic r
> +end
>
> method WaitForUpdates returns UpdateSet r
> ManagedObjectReference _this:propertyCollector r
> diff --git a/src/esx/esx_vi_generator.py b/src/esx/esx_vi_generator.py
> index 8a128df..787a28c 100755
> --- a/src/esx/esx_vi_generator.py
> +++ b/src/esx/esx_vi_generator.py
> @@ -371,8 +371,12 @@ class Property(Member):
> % self.name
> elif self.occurrence in [OCCURRENCE__REQUIRED_LIST,
> OCCURRENCE__OPTIONAL_LIST]:
> - return " ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_LIST(%s,
%s)\n" \
> - % (self.type, self.name)
> + if self.type == "String":
> + return "
ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_STRING_LIST(%s, %s)\n" \
> + % (self.type, self.name)
> + else:
> + return " ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_LIST(%s,
%s)\n" \
> + % (self.type, self.name)
> elif self.type == "String":
> return " ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String,
%s)\n" \
> % self.name
> @@ -1505,7 +1509,10 @@ predefined_objects = ["AnyType",
>
> additional_enum_features = { "ManagedEntityStatus" :
Enum.FEATURE__ANY_TYPE,
> "TaskInfoState" :
Enum.FEATURE__ANY_TYPE,
> - "VirtualMachinePowerState" :
Enum.FEATURE__ANY_TYPE }
> + "VirtualMachinePowerState" :
Enum.FEATURE__ANY_TYPE ,
> + "HostIpConfigIpV6AdressStatus" :
Enum.FEATURE__ANY_TYPE,
> + "HostIpConfigV6AdressConfigType" :
Enum.FEATURE__ANY_TYPE,
> + "PortGroupConnecteeType" :
Enum.FEATURE__ANY_TYPE }
>
> additional_object_features = { "AutoStartDefaults" :
Object.FEATURE__ANY_TYPE,
> "AutoStartPowerInfo" :
Object.FEATURE__ANY_TYPE,
> @@ -1519,8 +1526,31 @@ additional_object_features = { "AutoStartDefaults"
: Object.FEATURE__AN
>
Object.FEATURE__ANY_TYPE,
> "HostDatastoreBrowserSearchResults" :
Object.FEATURE__LIST |
>
Object.FEATURE__ANY_TYPE,
> + "HostIpConfig" :
Object.FEATURE__DEEP_COPY,
> + "HostIpRouteConfig" :
Object.FEATURE__ANY_TYPE,
> + "HostIpConfigIpV6Address" :
Object.FEATURE__LIST |
> +
Object.FEATURE__ANY_TYPE |
> +
Object.FEATURE__DEEP_COPY,
> + "HostIpConfigIpV6AddressConfiguration" :
Object.FEATURE__DEEP_COPY,
> + "HostPortGroup" :
Object.FEATURE__LIST |
> +
Object.FEATURE__ANY_TYPE,
> + "HostVirtualNic" :
Object.FEATURE__ANY_TYPE |
> +
Object.FEATURE__LIST,
> + "HostVirtualSwitch" :
Object.FEATURE__ANY_TYPE |
> +
Object.FEATURE__LIST,
> + "KeyValue" :
Object.FEATURE__ANY_TYPE,
> "ManagedObjectReference" :
Object.FEATURE__ANY_TYPE,
> + "PhysicalNic" :
Object.FEATURE__LIST |
> +
Object.FEATURE__ANY_TYPE |
> +
Object.FEATURE__DEEP_COPY,
> "ObjectContent" :
Object.FEATURE__DEEP_COPY,
> + "OptionValue" :
Object.FEATURE__ANY_TYPE |
> +
Object.FEATURE__LIST,
> + "PhysicalNic" :
Object.FEATURE__LIST |
> +
Object.FEATURE__ANY_TYPE |
> +
Object.FEATURE__DEEP_COPY,
> + "PhysicalNicSpec" :
Object.FEATURE__DEEP_COPY,
> + "PhysicalNicLinkInfo" :
Object.FEATURE__LIST,
> "ResourcePoolResourceUsage" :
Object.FEATURE__ANY_TYPE,
> "ServiceContent" :
Object.FEATURE__DESERIALIZE,
> "SharesInfo" :
Object.FEATURE__ANY_TYPE,
> diff --git a/src/esx/esx_vi_types.c b/src/esx/esx_vi_types.c
> index bcc310f..f23af8d 100644
> --- a/src/esx/esx_vi_types.c
> +++ b/src/esx/esx_vi_types.c
> @@ -475,7 +475,23 @@
> continue; \
> }
>
> -
> +#define ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_STRING_LIST(_type, _name) \
> + if (xmlStrEqual(childNode->name, BAD_CAST #_name)) { \
> + char *value = NULL; \
> + \
> + if (esxVI_String_DeserializeValue(childNode, &value) < 0 ||
\
> + value == NULL) { \
> + goto failure; \
> + } \
> + \
> + if (esxVI_##_type##_AppendValueToList(&(*ptrptr)->_name,
\
> + value) < 0) { \
> + VIR_FREE(value); \
> + goto failure; \
> + } \
> + \
> + continue; \
> + }
>
> /*
> * A required property must be != 0 (NULL for pointers, "undefined" == 0
for
> --
> 1.7.9.5
I think one more pass is needed at this, please make sure you
run make check and make syntax-check on the tree before submitting
your patch,
thanks !
Daniel
--
Daniel Veillard | libxml Gnome XML XSLT toolkit
http://xmlsoft.org/
daniel(a)veillard.com | Rpmfind RPM search engine
http://rpmfind.net/
http://veillard.com/ | virtualization library
http://libvirt.org/