[libvirt] [PATCH 1/2] ESX: Add routines to interface driver

Laine Stump laine at laine.org
Mon Jul 23 19:43:24 UTC 2012


On 07/20/2012 05:20 PM, Ata E Husain Bohra wrote:
> Add following routines to esx_interface_driver:
>     esxNumOfInterfaces,
>     esxNumOfDefinedInterfaces,
>     esxListInterfaces,
>     esxListDefinedInterfaces,
>     esxInterfaceLookupByMACString,
>     esxInterfaceGetXMLDesc,
>     esxInterfaceUndefine,
>     esxInterfaceCreate,
>     esxInterfaceDestroy
>
> Signed-off-by: Ata E Husain Bohra <ata.husain at hotmail.com>
> ---
>  src/esx/esx_interface_driver.c |  506 +++++++++++++++++++++++++++++++++++++++-
>  src/esx/esx_vi.c               |  126 ++++++++++
>  src/esx/esx_vi.h               |   10 +
>  src/esx/esx_vi_generator.input |  227 ++++++++++++++++++
>  src/esx/esx_vi_generator.py    |   31 ++-
>  src/esx/esx_vi_types.c         |   18 +-
>  6 files changed, 913 insertions(+), 5 deletions(-)
>
> diff --git a/src/esx/esx_interface_driver.c b/src/esx/esx_interface_driver.c
> index 5713137..b1ba5e2 100644
> --- a/src/esx/esx_interface_driver.c
> +++ b/src/esx/esx_interface_driver.c
> @@ -23,6 +23,9 @@
>   */
>  
>  #include <config.h>
> +#include <sys/socket.h>
> +#include <netinet/in.h>
> +#include <arpa/inet.h>
>  
>  #include "internal.h"
>  #include "util.h"
> @@ -34,6 +37,7 @@
>  #include "esx_vi.h"
>  #include "esx_vi_methods.h"
>  #include "esx_util.h"
> +#include "interface_conf.h"
>  
>  #define VIR_FROM_THIS VIR_FROM_ESX
>  
> @@ -67,10 +71,508 @@ esxInterfaceClose(virConnectPtr conn)
>  
>  
>  
> +static int
> +esxNumOfInterfaces(virConnectPtr conn)
> +{
> +    esxPrivate *priv = conn->interfacePrivateData;
> +    esxVI_HostVirtualNic *virtualNicList = NULL;
> +    const esxVI_HostVirtualNic *virtualNic = NULL;


It's a bit disconcerting to see these called "virtual" NICs, when
virInterface is all about configuring interfaces on the *physical* host.
Being unfamiliar with the vmware API, I'm not sure which of these
functions are things you've added to libvirt and which are part of
vmware, but please rename any that are defined in libvirt to use
"physical" or "host" or "p/h" as appropriate, rather than "virtual"
and/or "v". We want to make sure nobody gets the wrong idea about these
functions.


> +    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;

Setting interfacePrivateData to NULL is equivalent to closing the
driver. I don't think you really want to do this. Possibly it was an
error in cut/paste from somewhere else (esxInterfaceClose()?).


> +
> +    // 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 = conn->privateData;
> +    *names = NULL;
> +
> +    /* keeps compiler happy */
> +    VIR_DEBUG("max interfaces: %d", maxnames);
> +
> +    // ESX interfaces are always active
> +    return 0;
> +}


As I'll be mentioning in PATCH 2/2, just do this right the first time,
rather than having a followup patch to fix code you've just added.


> +
> +
> +
> +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;
> +}
> +
> +
> +
> +static char*
> +esxInterfaceGetXMLDesc(virInterfacePtr iface, unsigned int flags)
> +{
> +    esxPrivate *priv = iface->conn->interfacePrivateData;
> +    esxVI_HostVirtualNic *virtualNicList = NULL;
> +    const esxVI_HostVirtualNic *virtualNic = NULL;
> +    esxVI_PhysicalNic *physicalNicList = NULL;
> +    const esxVI_PhysicalNic *physicalNic = 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;
> +    int use_static = 0;
> +    struct in_addr addr;
> +    uint32_t host_addr = 0;
> +    int zero_count = 0;
> +    int masklen = 0;
> +    int i = 0;
> +    char *ret = NULL;
> +
> +    if (VIR_INTERFACE_XML_INACTIVE & flags) {
> +        use_static = 1;
> +    }
> +
> +    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;
> +    }
> +
> +    /*
> +     * populate virInterfaceDef object to obtain
> +     * libvirt interface domain xml.
> +     */
> +    if (VIR_ALLOC(def) < 0) {
> +        virReportOOMError();
> +        goto cleanup;
> +    }
> +
> +    def->type = VIR_INTERFACE_TYPE_BRIDGE;
> +    def->name = strdup(virtualNic->device);
> +    if (virtualNic->spec->mtu && virtualNic->spec->mtu->value) {
> +        def->mtu = virtualNic->spec->mtu->value;
> +    } else {
> +        def->mtu = 1500;
> +    }
> +
> +    def->startmode = VIR_INTERFACE_START_ONBOOT;
> +
> +    if (!use_static && virtualNic->spec->mac) {
> +        def->mac = strdup(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 */
> +    def->nprotos = 1;
> +    if (VIR_ALLOC_N(def->protos, def->nprotos) < 0) {
> +        virReportOOMError();
> +        goto cleanup;
> +    }
> +
> +    /* TODO - Add IPv6 Support */
> +    for (i = 0; i < def->nprotos; ++i) {
> +        if (VIR_ALLOC(def->protos[i]) < 0) {
> +            goto cleanup;
> +        }
> +
> +        def->protos[i]->family = strdup("ipv4");
> +        if (virtualNic->spec->ip->dhcp == 1) {
> +            def->protos[i]->dhcp = 1;
> +        }
> +        def->protos[i]->nips = 1;
> +        if (virtualNic->spec->ip->dhcp != 1 || !use_static) {
> +            if (virtualNic->spec->ip->ipAddress &&
> +              *virtualNic->spec->ip->ipAddress) {
> +                int j =0;
> +                if (VIR_ALLOC_N(def->protos[i]->ips, def->protos[i]->nips)
> +                  < 0) {
> +                    virReportOOMError();
> +                    goto cleanup;
> +                }
> +
> +                for (j=0; j < def->protos[i]->nips; ++j) {
> +                    if (VIR_ALLOC(def->protos[i]->ips[j]) < 0) {
> +                        virReportOOMError();
> +                        goto cleanup;
> +                    }
> +                    def->protos[i]->ips[0]->address =
> +                        strdup(virtualNic->spec->ip->ipAddress);
> +                    def->protos[i]->ips[0]->prefix = masklen;
> +                    def->protos[i]->gateway =
> +                        strdup(ipRouteConfig->defaultGateway);
> +                }
> +            }
> +        }
> +    }
> +
> +    /* Add bridge information */
> +    def->data.bridge.stp = 0; /* off */
> +
> +    /**
> +     * traversing physical nic list twice, first to get total
> +     * interfaces and second to populate interface items.
> +     * Total Complexity ~= O(N); also total physical nics
> +     * cannot be that large number
> +     */
> +    for (physicalNic = matchingPhysicalNicList, i = 0; physicalNic != NULL;
> +         physicalNic = physicalNic->_next, ++i) {
> +    }
> +
> +    if ( i > 0) {
> +        if (VIR_ALLOC_N(def->data.bridge.itf, i) < 0) {
> +            virReportOOMError();
> +            goto cleanup;
> +        }
> +        def->data.bridge.nbItf = i;
> +        for (physicalNic = matchingPhysicalNicList, i = 0; physicalNic != NULL;
> +             physicalNic = physicalNic->_next, ++i) {
> +            virInterfaceDefPtr itf = NULL;
> +            if (VIR_ALLOC(itf) < 0) {
> +                virReportOOMError();
> +                goto cleanup;
> +            }
> +            itf->type = VIR_INTERFACE_TYPE_ETHERNET;
> +            itf->name = strdup(physicalNic->device);
> +            itf->mac = strdup(physicalNic->mac);
> +
> +            def->data.bridge.itf[i] = itf;
> +        }
> +    }
> +
> +    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);
> +
> +    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;

Again - you don't want to NULL this out - it's the same as closing the
driver.

> +
> +    virCheckFlags(0, -1);
> +
> +    /* ESX interfaces are always active */
> +    return 0;
> +}
> +
> +
> +
> +static int
> +esxInterfaceDestroy(virInterfacePtr iface, unsigned int flags)
> +{
> +    iface->conn->interfacePrivateData = NULL;

And again - don't NULL this.

> +
> +    virCheckFlags(0, -1);
> +
> +    /* ESX interfaces can not be deactivated */
> +    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 48718b6..80ddb76 100644
> --- a/src/esx/esx_vi.c
> +++ b/src/esx/esx_vi.c
> @@ -4523,6 +4523,132 @@ esxVI_LookupManagedObjectHelper(esxVI_Context *ctx,
>      return result;
>  }
>  
> +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 9560bd2..9b694b5 100644
> --- a/src/esx/esx_vi.h
> +++ b/src/esx/esx_vi.h
> @@ -505,6 +505,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..64f8389 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
> @@ -197,6 +220,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 +345,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 +388,131 @@ object HostNasVolume                 extends HostFileSystemVolume
>  end
>  
>  
> +object HostNicTeamingPolicy
> +    String                                   policy                         o
> +    Boolean                                  reversePolicy                  o
> +    Boolean                                  notifySwitches                 o
> +    Boolean                                  rollingOrder                   o
> +    HostNicFailureCriteria                   failureCriteria                o
> +    HostNicOrderPolicy                       nicOrder                       o
> +end
> +
> +object HostNetOffloadCapabilities
> +    Boolean                                  csumOffload                    o
> +    Boolean                                  tcpSegmentation                o
> +    Boolean                                  zeroCopyXmit                   o
> +end
> +
> +object HostNetworkSecurityPolicy
> +    Boolean                                  allowPromiscuous               o
> +    Boolean                                  macChanges                     o
> +    Boolean                                  forgedTransmits                o
> +end
> +
> +object HostNetworkPolicy
> +    HostNetworkSecurityPolicy                security                       o
> +    HostNicTeamingPolicy                     nicTeaming                     o
> +    HostNetOffloadCapabilities               offloadPolicy                  o
> +    HostNetworkTrafficShapingPolicy          shapingPolicy                  o
> +end
> +
> +object HostNetworkTrafficShapingPolicy
> +    Boolean                                  enabled                        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
> +    Int                                      vlanId                         r
> +    String                                   vswitchName                    r
> +    HostNetworkPolicy                        policy                         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 +532,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 +579,10 @@ object OptionType
>      Boolean                                  valueIsReadonly                o
>  end
>  
> +object OptionValue
> +    String                                   key                            r
> +    AnyType                                  value                          r
> +end
>  
>  object PerfCounterInfo
>      Int                                      key                            r
> @@ -454,6 +639,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
> @@ -773,6 +979,13 @@ end
>  # Methods
>  #
>  
> +method AddVirtualNic                 returns String                         r
> +    ManagedObjectReference                   _this                          r
> +    String                                   portgroup                      r
> +    HostVirtualNicSpec                       nic                            r
> +end
> +
> +
>  method AnswerVM
>      ManagedObjectReference                   _this                          r
>      String                                   questionId                     r
> @@ -954,6 +1167,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 +1219,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..f4e4a11 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
> @@ -1519,8 +1523,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

A general comment - I didn't see any kind of mutexes in here. Is this
code really threadsafe? (it looks like the toplevel functions just call
into your utility functions to get a snapshot of the current state of
interfaces in vmware, then work with that snapshot during the rest of
the call; I didn't look into the utility functions in detail, because
the chance of me understanding them is fairly low anyway :-)




More information about the libvir-list mailing list