[libvirt] [PATCH v5] ESX: Add routines to interface driver

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@hotmail.com> --- src/esx/esx_interface_driver.c | 551 +++++++++++++++++++++++++++++++++++++++- src/esx/esx_vi.c | 125 +++++++++ src/esx/esx_vi.h | 10 + src/esx/esx_vi_generator.input | 227 +++++++++++++++++ src/esx/esx_vi_generator.py | 23 ++ src/esx/esx_vi_types.c | 2 - 6 files changed, 934 insertions(+), 4 deletions(-) diff --git a/src/esx/esx_interface_driver.c b/src/esx/esx_interface_driver.c index 501409a..e9f0d4a 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,553 @@ esxInterfaceClose(virConnectPtr conn) +static int +esxNumOfInterfaces(virConnectPtr conn) +{ + bool success = false; + esxPrivate *priv = conn->interfacePrivateData; + esxVI_HostVirtualNic *hostVirtualNicList = NULL; + const esxVI_HostVirtualNic *hostVirtualNic = NULL; + int count = 0; + + if (esxVI_EnsureSession(priv->primary) < 0 || + esxVI_LookupHostVirtualNicList(priv->primary, + &hostVirtualNicList) < 0) { + goto cleanup; + } + + if (hostVirtualNicList == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Could not retrieve HostVirtualNic List")); + + goto cleanup; + } + + for (hostVirtualNic = hostVirtualNicList; + hostVirtualNic != NULL; + hostVirtualNic = hostVirtualNic->_next) { + count++; + } + + success = true; + +cleanup: + + esxVI_HostVirtualNic_Free(&hostVirtualNicList); + + return success ? count : -1; + +} + + + +static int +esxNumOfDefinedInterfaces(virConnectPtr conn ATTRIBUTE_UNUSED) +{ + // ESX interfaces are always active + return 0; + +} + + + +static int +esxListInterfaces(virConnectPtr conn, char **names, int maxnames) +{ + int result = -1; + esxPrivate *priv = conn->interfacePrivateData; + esxVI_HostVirtualNic *hostVirtualNicList = NULL; + const esxVI_HostVirtualNic *hostVirtualNic = NULL; + int i = 0; + + if (esxVI_EnsureSession(priv->primary) < 0 || + esxVI_LookupHostVirtualNicList(priv->primary, + &hostVirtualNicList) < 0) { + goto cleanup; + } + + if (hostVirtualNicList == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Could not retrieve vNIC List")); + goto cleanup; + } + + for (i= 0, hostVirtualNic = hostVirtualNicList; + hostVirtualNic != NULL && i < maxnames; + ++i, hostVirtualNic = hostVirtualNic->_next) { + names[i] = strdup(hostVirtualNic->device); + + if (names[i] == NULL) { + for(;i >=0;--i) { + VIR_FREE(names[i]); + } + virReportOOMError(); + goto cleanup; + } + } + + result = i; + + cleanup: + + esxVI_HostVirtualNic_Free(&hostVirtualNicList); + + return result; + +} + + + +static int +esxListDefinedInterfaces(virConnectPtr conn ATTRIBUTE_UNUSED, + char **names ATTRIBUTE_UNUSED, + int maxnames ATTRIBUTE_UNUSED) +{ + // ESX interfaces are always active + return 0; + +} + + + +static virInterfacePtr +esxInterfaceLookupByName(virConnectPtr conn, const char *name) +{ + virInterfacePtr ret = NULL; + esxPrivate *priv = conn->interfacePrivateData; + esxVI_HostVirtualNic *hostVirtualNicList = NULL; + const esxVI_HostVirtualNic *hostVirtualNic = NULL; + + if (esxVI_EnsureSession(priv->primary) < 0 || + esxVI_LookupHostVirtualNicList(priv->primary, + &hostVirtualNicList) < 0) { + goto cleanup; + } + + if (hostVirtualNicList == 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Could not retrieve HostVirtualNic List")); + goto cleanup; + } + + + for(hostVirtualNic = hostVirtualNicList; + hostVirtualNic != NULL; + hostVirtualNic = hostVirtualNic->_next) { + if (STREQ(hostVirtualNic->device, name)) { + if (hostVirtualNic->spec == NULL || + hostVirtualNic->spec->mac == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Malformed HostVirtualNicSpec")); + goto cleanup; + } + + ret = virGetInterface(conn, hostVirtualNic->device, + hostVirtualNic->spec->mac); + break; + } + } + + cleanup: + + esxVI_HostVirtualNic_Free(&hostVirtualNicList); + + return ret; + +} + + + +static virInterfacePtr +esxInterfaceLookupByMACString(virConnectPtr conn, const char *mac) +{ + virInterfacePtr ret = NULL; + esxPrivate *priv = conn->interfacePrivateData; + esxVI_HostVirtualNic *hostVirtualNicList = NULL; + const esxVI_HostVirtualNic *hostVirtualNic = NULL; + + if (esxVI_EnsureSession(priv->primary) < 0 || + esxVI_LookupHostVirtualNicList(priv->primary, + &hostVirtualNicList) < 0) { + goto cleanup; + } + + if (hostVirtualNicList == 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Could not retrieve HostVirtualNic List")); + goto cleanup; + } + + + for(hostVirtualNic = hostVirtualNicList; + hostVirtualNic != NULL; + hostVirtualNic = hostVirtualNic->_next) { + if (hostVirtualNic->spec == NULL || + hostVirtualNic->spec->mac == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Malformed HostVirtualNicSpec")); + goto cleanup; + } + + if (STREQ(hostVirtualNic->spec->mac, mac)) { + ret = virGetInterface(conn, hostVirtualNic->device, + hostVirtualNic->spec->mac); + break; + } + } + + cleanup: + + esxVI_HostVirtualNic_Free(&hostVirtualNicList); + + return ret; + +} + + + +static char* +esxInterfaceGetXMLDesc(virInterfacePtr iface, unsigned int flags) +{ + char *ret = NULL; + esxPrivate *priv = iface->conn->interfacePrivateData; + esxVI_HostVirtualNic *hostVirtualNicList = NULL; + const esxVI_HostVirtualNic *hostVirtualNic = NULL; + esxVI_PhysicalNic *physicalNicList = NULL; + const esxVI_PhysicalNic *physicalNic = NULL; + esxVI_PhysicalNic *matchingPhysicalNicList = NULL; + esxVI_HostIpRouteConfig *ipRouteConfig = NULL; + esxVI_HostPortGroup *hostPortGroupList = NULL; + esxVI_HostVirtualSwitch *hostVirtualSwitchList = NULL; + esxVI_String *propertyNameList = NULL; + esxVI_ObjectContent *hostSystem = NULL; + esxVI_DynamicProperty *dynamicProperty = NULL; + virInterfaceDefPtr def = NULL; + virInterfaceDefPtr itf = NULL; + int use_static = 0; + struct in_addr addr; + uint32_t host_addr = 0; + int zero_count = 0; + int masklen = 0; + int i = 0; + + 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, &hostVirtualNicList) < 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, &hostVirtualSwitchList) < 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, &hostPortGroupList) < 0) { + goto cleanup; + } + } else { + VIR_WARN("Unexpected '%s' property", dynamicProperty->name); + } + } + + if (!hostVirtualNicList || + !ipRouteConfig || + !hostVirtualSwitchList || + !hostPortGroupList) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to retrieve network parameters")); + + goto cleanup; + } + + for (hostVirtualNic = hostVirtualNicList; + hostVirtualNic != NULL; + hostVirtualNic = hostVirtualNic->_next) { + if (STREQ(hostVirtualNic->device, iface->name)) { + break; + } + } + + if (hostVirtualNic == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Could not find HostVirtual Nic")); + goto cleanup; + } + + if (esxVI_LookupPhysicalNicFromHostPortGroup( + hostVirtualNic->portgroup, hostPortGroupList, + hostVirtualSwitchList, physicalNicList, + &matchingPhysicalNicList) < 0) { + 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(hostVirtualNic->device); + if (def->name == NULL) { + virReportOOMError(); + goto cleanup; + } + + if (hostVirtualNic->spec->mtu && hostVirtualNic->spec->mtu->value) { + def->mtu = hostVirtualNic->spec->mtu->value; + } else { + def->mtu = 1500; + } + + def->startmode = VIR_INTERFACE_START_ONBOOT; + + if (!use_static && hostVirtualNic->spec->mac) { + def->mac = strdup(hostVirtualNic->spec->mac); + if (def->mac == NULL) { + virReportOOMError(); + goto cleanup; + } + } + + /* TODO - Handle VLAN (via portgroup?) */ + if (hostVirtualNic->spec->ip->subnetMask && + *hostVirtualNic->spec->ip->subnetMask && + inet_aton(hostVirtualNic->spec->ip->subnetMask, &addr) == 0) { + virReportError(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 (def->protos[i]->family == NULL) { + virReportOOMError(); + goto cleanup; + } + + if (hostVirtualNic->spec->ip->dhcp == 1) { + def->protos[i]->dhcp = 1; + } + + def->protos[i]->nips = 1; + if (hostVirtualNic->spec->ip->dhcp != 1 || !use_static) { + if (hostVirtualNic->spec->ip->ipAddress && + *hostVirtualNic->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(hostVirtualNic->spec->ip->ipAddress); + if (def->protos[i]->ips[0] == NULL) { + virReportOOMError(); + goto cleanup; + } + + def->protos[i]->ips[0]->prefix = masklen; + + def->protos[i]->gateway = + strdup(ipRouteConfig->defaultGateway); + if (def->protos[i]->gateway == NULL) { + virReportOOMError(); + goto cleanup; + } + } + } + } + } + + /* 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); N should not be a 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) { + virInterfaceDefFree(itf); + if (VIR_ALLOC(itf) < 0) { + virReportOOMError(); + goto cleanup; + } + + itf->type = VIR_INTERFACE_TYPE_ETHERNET; + itf->name = strdup(physicalNic->device); + if (itf->name == NULL) { + virReportOOMError(); + goto cleanup; + } + + itf->mac = strdup(physicalNic->mac); + if (itf->mac == NULL) { + virReportOOMError(); + goto cleanup; + } + + def->data.bridge.itf[i] = itf; + itf = NULL; /* avoid double free */ + } + } + + ret = virInterfaceDefFormat(def); + + cleanup: + + esxVI_HostVirtualNic_Free(&hostVirtualNicList); + esxVI_PhysicalNic_Free(&physicalNicList); + esxVI_PhysicalNic_Free(&matchingPhysicalNicList); + esxVI_HostPortGroup_Free(&hostPortGroupList); + esxVI_HostVirtualSwitch_Free(&hostVirtualSwitchList); + esxVI_HostIpRouteConfig_Free(&ipRouteConfig); + esxVI_ObjectContent_Free(&hostSystem); + esxVI_String_Free(&propertyNameList); + virInterfaceDefFree(def); + virInterfaceDefFree(itf); + + 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) { + return -1; + } + + return 0; + +} + + + +static int +esxInterfaceCreate(virInterfacePtr iface ATTRIBUTE_UNUSED, + unsigned int flags) +{ + virCheckFlags(0, -1); + + /* ESX interfaces are always active */ + return 0; + +} + + + +static int +esxInterfaceDestroy(virInterfacePtr iface ATTRIBUTE_UNUSED, + unsigned int flags) +{ + 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 2c789e1..962c9c2 100644 --- a/src/esx/esx_vi.c +++ b/src/esx/esx_vi.c @@ -4569,6 +4569,131 @@ esxVI_LookupManagedObjectHelper(esxVI_Context *ctx, return result; } +int +esxVI_LookupHostVirtualNicList(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) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Could not retrieve the HostSystem object")); + + goto cleanup; + } + + for (dynamicProperty = hostSystem->propSet; + dynamicProperty != NULL; + dynamicProperty = dynamicProperty->_next) { + if (STREQ(dynamicProperty->name, "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_LookupPhysicalNicFromHostPortGroup( + const char *portgroup, + const esxVI_HostPortGroup *hostPortGroupList, + const esxVI_HostVirtualSwitch *hostVirtualSwitchList, + const esxVI_PhysicalNic *physicalNicList, + esxVI_PhysicalNic **ret_physicalNicList) +{ + int result = -1; + const esxVI_HostPortGroup *hostPortGroup = NULL; + const esxVI_HostVirtualSwitch *hostVirtualSwitch = NULL; + const esxVI_PhysicalNic *physicalNic = NULL; + esxVI_PhysicalNic *tempPhysicalNic = NULL; + const esxVI_String *pnicKey = NULL; + if (portgroup == NULL) { + goto cleanup; + } + + /* Go through all the port groups to find the one that matches. */ + for (hostPortGroup = hostPortGroupList; + hostPortGroup != NULL; + hostPortGroup = hostPortGroup->_next) { + if (STREQ(hostPortGroup->spec->name, portgroup)) { + break; + } + } + + if (hostPortGroup == NULL) { + virReportError(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 (hostVirtualSwitch = hostVirtualSwitchList; + hostVirtualSwitch != NULL; + hostVirtualSwitch = hostVirtualSwitch->_next) { + if (STREQ(hostPortGroup->spec->vswitchName, hostVirtualSwitch->name)) { + break; + } + } + + if (hostVirtualSwitch == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Could not find Virtual Switch")); + goto cleanup; + } + + /* Go through all physical nics */ + for (pnicKey = hostVirtualSwitch->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) { + + esxVI_PhysicalNic_Free(&tempPhysicalNic); + + if (STREQ(pnicKey->value, physicalNic->key)) { + if (esxVI_PhysicalNic_DeepCopy( + &tempPhysicalNic, (esxVI_PhysicalNic *)physicalNic) < 0 || + esxVI_PhysicalNic_AppendToList( + ret_physicalNicList, tempPhysicalNic) < 0) { + goto cleanup; + } + tempPhysicalNic = NULL; + } + } + } + + result = 0; + + cleanup: + + 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 4b84be8..0eb9a99 100644 --- a/src/esx/esx_vi.h +++ b/src/esx/esx_vi.h @@ -499,6 +499,16 @@ int esxVI_ParseHostCpuIdInfo(esxVI_ParsedHostCpuIdInfo *parsedHostCpuIdInfo, int esxVI_ProductVersionToDefaultVirtualHWVersion(esxVI_ProductVersion productVersion); +int esxVI_LookupHostVirtualNicList(esxVI_Context* ctx, + esxVI_HostVirtualNic** virtualNicList); + +int esxVI_LookupPhysicalNicFromHostPortGroup( + 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 910478c..26ae62e 100755 --- a/src/esx/esx_vi_generator.py +++ b/src/esx/esx_vi_generator.py @@ -1519,8 +1519,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 708aeda..d074e69 100644 --- a/src/esx/esx_vi_types.c +++ b/src/esx/esx_vi_types.c @@ -475,8 +475,6 @@ continue; \ } - - /* * A required property must be != 0 (NULL for pointers, "undefined" == 0 for * enumeration values). -- 1.7.9.5

2012/8/2 Ata E Husain Bohra <ata.husain@hotmail.com>:
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@hotmail.com>
Okay, I finally had time to take a detailed look at the interface driver and the related network driver and your proposed implementation for the interface driver. I think listing HostVirtualNics in the interface driver is not the correct mapping between vSphere API and libvirt. Also listing HostVirtualNics as bridges is not correct because a HostVirtualNic is not a bridge. A HostVirtualSwitch can be seen as a kind of bridge, but a HostVirtualSwitch is more like a virtual network in libvirt terms. In terms of libvirt the interface driver is about physical NICs that can be used to connect a libvirt virtual network to the physical network. Therefore, the interface driver should just list the PhysicalNics, but not the HostVirtualNics. I think there is currently no place in the libvirt API to map the HostVirtualNics to. Also I don't think that it is important to make the HostVirtualNics available via libvirt API. I might be wrong here, but mapping them via libvirt interface driver is still wrong in my opinion. Regarding the network driver, I think a libvirt virtual network is best represented by a HostVirtualSwitch and the HostPortGroups are mapped to the portgroups of a libvirt virtual switch. I'm sorry that I let you wait for quite a while now until I came to this understanding that is contrary to your proposed interface driver. -- Matthias Bolte http://photron.blogspot.com

2012/8/5 Matthias Bolte <matthias.bolte@googlemail.com>:
2012/8/2 Ata E Husain Bohra <ata.husain@hotmail.com>:
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@hotmail.com>
Okay, I finally had time to take a detailed look at the interface driver and the related network driver and your proposed implementation for the interface driver.
I think listing HostVirtualNics in the interface driver is not the correct mapping between vSphere API and libvirt. Also listing HostVirtualNics as bridges is not correct because a HostVirtualNic is not a bridge. A HostVirtualSwitch can be seen as a kind of bridge, but a HostVirtualSwitch is more like a virtual network in libvirt terms.
In terms of libvirt the interface driver is about physical NICs that can be used to connect a libvirt virtual network to the physical network. Therefore, the interface driver should just list the PhysicalNics, but not the HostVirtualNics. I think there is currently no place in the libvirt API to map the HostVirtualNics to. Also I don't think that it is important to make the HostVirtualNics available via libvirt API. I might be wrong here, but mapping them via libvirt interface driver is still wrong in my opinion.
Regarding the network driver, I think a libvirt virtual network is best represented by a HostVirtualSwitch and the HostPortGroups are mapped to the portgroups of a libvirt virtual switch.
I'm sorry that I let you wait for quite a while now until I came to this understanding that is contrary to your proposed interface driver.
I missed to mention that I proposed an implementation for the interface and network drivers according to the described mapping: https://www.redhat.com/archives/libvir-list/2012-August/msg00307.html https://www.redhat.com/archives/libvir-list/2012-August/msg00308.html -- Matthias Bolte http://photron.blogspot.com

Thanks Matthias for the explanation, I was working on the project which required libvirt to control/set networking on a given ESX host. I may need
Date: Sun, 5 Aug 2012 22:45:26 +0200 Subject: Re: [libvirt] [PATCH v5] ESX: Add routines to interface driver From: matthias.bolte@googlemail.com To: ata.husain@hotmail.com CC: libvir-list@redhat.com
2012/8/5 Matthias Bolte <matthias.bolte@googlemail.com>:
2012/8/2 Ata E Husain Bohra <ata.husain@hotmail.com>:
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@hotmail.com>
Okay, I finally had time to take a detailed look at the interface driver and the related network driver and your proposed implementation for the interface driver.
I think listing HostVirtualNics in the interface driver is not the correct mapping between vSphere API and libvirt. Also listing HostVirtualNics as bridges is not correct because a HostVirtualNic is not a bridge. A HostVirtualSwitch can be seen as a kind of bridge, but a HostVirtualSwitch is more like a virtual network in libvirt terms.
In terms of libvirt the interface driver is about physical NICs that can be used to connect a libvirt virtual network to the physical network. Therefore, the interface driver should just list the PhysicalNics, but not the HostVirtualNics. I think there is currently no place in the libvirt API to map the HostVirtualNics to. Also I don't think that it is important to make the HostVirtualNics available via libvirt API. I might be wrong here, but mapping them via libvirt interface driver is still wrong in my opinion.
Regarding the network driver, I think a libvirt virtual network is best represented by a HostVirtualSwitch and the HostPortGroups are mapped to the portgroups of a libvirt virtual switch.
I'm sorry that I let you wait for quite a while now until I came to this understanding that is contrary to your proposed interface driver.
I missed to mention that I proposed an implementation for the interface and network drivers according to the described mapping:
https://www.redhat.com/archives/libvir-list/2012-August/msg00307.html https://www.redhat.com/archives/libvir-list/2012-August/msg00308.html
-- Matthias Bolte http://photron.blogspot.com

(Please ignore earlier messages, as for reason the messages got truncated) Thanks Matthias for the explanation, I was working on the project which required libvirt to control/set networking on a given ESX host. As ESXi is different from hosted hypervisors, we need to configure ESX interface (IP, routing, bridge etc), also it is an integral part of the host settings. But re-thinking the whole design in light of the explanation provided by you, libvirt interfaces are actually mapping physical interfaces to virtual network. Further, hostVirtualSwitch behaves like switch which defines ports where we can plug VM virtual ethernet cards. It seems likely that we still want to have ability of configuring ESXi virtual interfaces (hostVirtualNics) so not sure if listing physical Nics is completly right to get an 100% operational ESX host. Michal has already reviewed the code and I would do the same if this design is one that maps to libvirt terminology the most. Though my design is not accpeted, but it was an amazing learning experience. Thanks for everyones input that came along the way. Regards, Ata
Date: Sun, 5 Aug 2012 22:45:26 +0200 Subject: Re: [libvirt] [PATCH v5] ESX: Add routines to interface driver From: matthias.bolte@googlemail.com To: ata.husain@hotmail.com CC: libvir-list@redhat.com
2012/8/5 Matthias Bolte <matthias.bolte@googlemail.com>:
2012/8/2 Ata E Husain Bohra <ata.husain@hotmail.com>:
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@hotmail.com>
Okay, I finally had time to take a detailed look at the interface driver and the related network driver and your proposed implementation for the interface driver.
I think listing HostVirtualNics in the interface driver is not the correct mapping between vSphere API and libvirt. Also listing HostVirtualNics as bridges is not correct because a HostVirtualNic is not a bridge. A HostVirtualSwitch can be seen as a kind of bridge, but a HostVirtualSwitch is more like a virtual network in libvirt terms.
In terms of libvirt the interface driver is about physical NICs that can be used to connect a libvirt virtual network to the physical network. Therefore, the interface driver should just list the PhysicalNics, but not the HostVirtualNics. I think there is currently no place in the libvirt API to map the HostVirtualNics to. Also I don't think that it is important to make the HostVirtualNics available via libvirt API. I might be wrong here, but mapping them via libvirt interface driver is still wrong in my opinion.
Regarding the network driver, I think a libvirt virtual network is best represented by a HostVirtualSwitch and the HostPortGroups are mapped to the portgroups of a libvirt virtual switch.
I'm sorry that I let you wait for quite a while now until I came to this understanding that is contrary to your proposed interface driver.
I missed to mention that I proposed an implementation for the interface and network drivers according to the described mapping:
https://www.redhat.com/archives/libvir-list/2012-August/msg00307.html https://www.redhat.com/archives/libvir-list/2012-August/msg00308.html
-- Matthias Bolte http://photron.blogspot.com
-- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list

On 08/06/2012 03:18 PM, Ata Bohra wrote:
But re-thinking the whole design in light of the explanation provided by you, libvirt interfaces are actually mapping physical interfaces to virtual network. Further, hostVirtualSwitch behaves like switch which defines ports where we can plug VM virtual ethernet cards. It seems likely that we still want to have ability of configuring ESXi virtual interfaces (hostVirtualNics) so not sure if listing physical Nics is completly right to get an 100% operational ESX host.
After reading Matthias' explanation, I was left wondering exactly what is the purpose of a hostVirtualNic. Is it used to give the hypervisor a connection to the hostVirtualSwitch? If so, that's something that's implied in libvirt's networks when they have an IP address defined - the presence of an IP address for the network is really indicating that there's a connection up to the host's (aka hypervisor) IP stack. (this is a legacy of the design of Linux host bridges - I think of there being an "implied port" on the bridge that is connected to the host kernel if the bridge has an IP address.)
Though my design is not accpeted, but it was an amazing learning experience. Thanks for everyones input that came along the way.
Not to mention that your patches were the catalyst that started the discussion and investigation by Matthias. So likely without your initiative, it would have been quite some time longer before these features were supported for ESX in libvirt. (Also, you now know a bit about the internals of libvirt, so maybe we can expect more patches in the future :-)

2012/8/7 Laine Stump <laine@laine.org>:
On 08/06/2012 03:18 PM, Ata Bohra wrote:
But re-thinking the whole design in light of the explanation provided by you, libvirt interfaces are actually mapping physical interfaces to virtual network. Further, hostVirtualSwitch behaves like switch which defines ports where we can plug VM virtual ethernet cards. It seems likely that we still want to have ability of configuring ESXi virtual interfaces (hostVirtualNics) so not sure if listing physical Nics is completly right to get an 100% operational ESX host.
After reading Matthias' explanation, I was left wondering exactly what is the purpose of a hostVirtualNic. Is it used to give the hypervisor a connection to the hostVirtualSwitch?
That its exact purpose. The hypervisor uses a HostVirtualNic to connect through a HostVirtualSwitch and PhysicalNic to the network in order to access network-based storage via NFS or iSCSI. This network connection is also used for migration.
If so, that's something that's implied in libvirt's networks when they have an IP address defined - the presence of an IP address for the network is really indicating that there's a connection up to the host's (aka hypervisor) IP stack. (this is a legacy of the design of Linux host bridges - I think of there being an "implied port" on the bridge that is connected to the host kernel if the bridge has an IP address.)
This sounds like a promising idea that might allow to expose a HostVirtualNic as part of a libvirt network. -- Matthias Bolte http://photron.blogspot.com

2012/8/6 Ata Bohra <ata.husain@hotmail.com>:
(Please ignore earlier messages, as for reason the messages got truncated)
Thanks Matthias for the explanation, I was working on the project which required libvirt to control/set networking on a given ESX host. As ESXi is different from hosted hypervisors, we need to configure ESX interface (IP, routing, bridge etc), also it is an integral part of the host settings.
Okay, now I understand why you choose to make the interface driver list HostVirtualNics. This gives you the possibility to configure this part of an ESX server.
But re-thinking the whole design in light of the explanation provided by you, libvirt interfaces are actually mapping physical interfaces to virtual network. Further, hostVirtualSwitch behaves like switch which defines ports where we can plug VM virtual ethernet cards. It seems likely that we still want to have ability of configuring ESXi virtual interfaces (hostVirtualNics) so not sure if listing physical Nics is completly right to get an 100% operational ESX host.
This should be possible, but as of the network driver. Laine mentioned that the IP element of a libvirt network config could be used for that purpose. This idea looks promising, but needs to be investigated in detail first. I might be able to spent some time on this next weekend. Regards, Matthias
Michal has already reviewed the code and I would do the same if this design is one that maps to libvirt terminology the most. Though my design is not accpeted, but it was an amazing learning experience. Thanks for everyones input that came along the way.
Regards, Ata
Date: Sun, 5 Aug 2012 22:45:26 +0200 Subject: Re: [libvirt] [PATCH v5] ESX: Add routines to interface driver From: matthias.bolte@googlemail.com To: ata.husain@hotmail.com CC: libvir-list@redhat.com
2012/8/5 Matthias Bolte <matthias.bolte@googlemail.com>:
2012/8/2 Ata E Husain Bohra <ata.husain@hotmail.com>:
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@hotmail.com>
Okay, I finally had time to take a detailed look at the interface driver and the related network driver and your proposed implementation for the interface driver.
I think listing HostVirtualNics in the interface driver is not the correct mapping between vSphere API and libvirt. Also listing HostVirtualNics as bridges is not correct because a HostVirtualNic is not a bridge. A HostVirtualSwitch can be seen as a kind of bridge, but a HostVirtualSwitch is more like a virtual network in libvirt terms.
In terms of libvirt the interface driver is about physical NICs that can be used to connect a libvirt virtual network to the physical network. Therefore, the interface driver should just list the PhysicalNics, but not the HostVirtualNics. I think there is currently no place in the libvirt API to map the HostVirtualNics to. Also I don't think that it is important to make the HostVirtualNics available via libvirt API. I might be wrong here, but mapping them via libvirt interface driver is still wrong in my opinion.
Regarding the network driver, I think a libvirt virtual network is best represented by a HostVirtualSwitch and the HostPortGroups are mapped to the portgroups of a libvirt virtual switch.
I'm sorry that I let you wait for quite a while now until I came to this understanding that is contrary to your proposed interface driver.
I missed to mention that I proposed an implementation for the interface and network drivers according to the described mapping:
https://www.redhat.com/archives/libvir-list/2012-August/msg00307.html https://www.redhat.com/archives/libvir-list/2012-August/msg00308.html
-- Matthias Bolte http://photron.blogspot.com
-- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
-- Matthias Bolte http://photron.blogspot.com
participants (4)
-
Ata Bohra
-
Ata E Husain Bohra
-
Laine Stump
-
Matthias Bolte