Lists available PhysicalNic devices. A PhysicalNic is always active and can neither be defined nor undefined. A PhysicalNic is used to bridge a HostVirtualSwitch to the physical network. --- This implementation differs from Ata's. It just lists PhysicalNics instead of listing HostVirtualNics as bridges. src/esx/esx_interface_driver.c | 239 +++++++++++++++++++++++++++++++++++++++- src/esx/esx_vi.c | 144 ++++++++++++++++++++++++- src/esx/esx_vi.h | 13 ++- src/esx/esx_vi_generator.input | 34 ++++++- src/esx/esx_vi_generator.py | 5 +- 5 files changed, 430 insertions(+), 5 deletions(-) diff --git a/src/esx/esx_interface_driver.c b/src/esx/esx_interface_driver.c index 501409a..a78a744 100644 --- a/src/esx/esx_interface_driver.c +++ b/src/esx/esx_interface_driver.c @@ -4,7 +4,7 @@ * host interfaces * * Copyright (C) 2010-2011 Red Hat, Inc. - * Copyright (C) 2010 Matthias Bolte <matthias.bolte@xxxxxxxxxxxxxx> + * Copyright (C) 2010-2012 Matthias Bolte <matthias.bolte@xxxxxxxxxxxxxx> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -29,6 +29,8 @@ #include "memory.h" #include "logging.h" #include "uuid.h" +#include "interface_conf.h" +#include "virsocketaddr.h" #include "esx_private.h" #include "esx_interface_driver.h" #include "esx_vi.h" @@ -67,10 +69,245 @@ esxInterfaceClose(virConnectPtr conn) +static int +esxNumberOfInterfaces(virConnectPtr conn) +{ + esxPrivate *priv = conn->interfacePrivateData; + esxVI_PhysicalNic *physicalNicList = NULL; + esxVI_PhysicalNic *physicalNic = NULL; + int count = 0; + + if (esxVI_EnsureSession(priv->primary) < 0 || + esxVI_LookupPhysicalNicList(priv->primary, &physicalNicList) < 0) { + return -1; + } + + for (physicalNic = physicalNicList; physicalNic != NULL; + physicalNic = physicalNic->_next) { + ++count; + } + + esxVI_PhysicalNic_Free(&physicalNicList); + + return count; +} + + + +static int +esxListInterfaces(virConnectPtr conn, char **const names, int maxnames) +{ + bool success = false; + esxPrivate *priv = conn->interfacePrivateData; + esxVI_PhysicalNic *physicalNicList = NULL; + esxVI_PhysicalNic *physicalNic = NULL; + int count = 0; + int i; + + if (maxnames == 0) { + return 0; + } + + if (esxVI_EnsureSession(priv->primary) < 0 || + esxVI_LookupPhysicalNicList(priv->primary, &physicalNicList) < 0) { + return -1; + } + + for (physicalNic = physicalNicList; physicalNic != NULL; + physicalNic = physicalNic->_next) { + names[count] = strdup(physicalNic->device); + + if (names[count] == NULL) { + virReportOOMError(); + goto cleanup; + } + + ++count; + } + + success = true; + + cleanup: + if (! success) { + for (i = 0; i < count; ++i) { + VIR_FREE(names[i]); + } + + count = -1; + } + + esxVI_PhysicalNic_Free(&physicalNicList); + + return count; +} + + + +static int +esxNumberOfDefinedInterfaces(virConnectPtr conn ATTRIBUTE_UNUSED) +{ + /* ESX interfaces are always active */ + return 0; +} + + + +static int +esxListDefinedInterfaces(virConnectPtr conn ATTRIBUTE_UNUSED, + char **const names ATTRIBUTE_UNUSED, + int maxnames ATTRIBUTE_UNUSED) +{ + /* ESX interfaces are always active */ + return 0; +} + + + +static virInterfacePtr +esxInterfaceLookupByName(virConnectPtr conn, const char *name) +{ + virInterfacePtr iface = NULL; + esxPrivate *priv = conn->interfacePrivateData; + esxVI_PhysicalNic *physicalNic = NULL; + + if (esxVI_EnsureSession(priv->primary) < 0 || + esxVI_LookupPhysicalNicByMACAddress(priv->primary, name, &physicalNic, + esxVI_Occurrence_RequiredItem) < 0) { + return NULL; + } + + iface = virGetInterface(conn, physicalNic->device, physicalNic->mac); + + esxVI_PhysicalNic_Free(&physicalNic); + + return iface; +} + + + +static virInterfacePtr +esxInterfaceLookupByMACString(virConnectPtr conn, const char *mac) +{ + virInterfacePtr iface = NULL; + esxPrivate *priv = conn->interfacePrivateData; + esxVI_PhysicalNic *physicalNic = NULL; + + if (esxVI_EnsureSession(priv->primary) < 0 || + esxVI_LookupPhysicalNicByMACAddress(priv->primary, mac, &physicalNic, + esxVI_Occurrence_RequiredItem) < 0) { + return NULL; + } + + iface = virGetInterface(conn, physicalNic->device, physicalNic->mac); + + esxVI_PhysicalNic_Free(&physicalNic); + + return iface; +} + + + +static char * +esxInterfaceGetXMLDesc(virInterfacePtr iface, unsigned int flags) +{ + char *xml = NULL; + esxPrivate *priv = iface->conn->interfacePrivateData; + esxVI_PhysicalNic *physicalNic = NULL; + virInterfaceDef def; + bool hasAddress = false; + virInterfaceProtocolDefPtr protocols; + virInterfaceProtocolDef protocol; + virSocketAddr socketAddress; + virInterfaceIpDefPtr ips; + virInterfaceIpDef ip; + + virCheckFlags(VIR_INTERFACE_XML_INACTIVE, NULL); + + memset(&def, 0, sizeof(def)); + memset(&protocol, 0, sizeof(protocol)); + memset(&socketAddress, 0, sizeof(socketAddress)); + memset(&ip, 0, sizeof(ip)); + + if (esxVI_EnsureSession(priv->primary) < 0 || + esxVI_LookupPhysicalNicByMACAddress(priv->primary, iface->mac, + &physicalNic, + esxVI_Occurrence_RequiredItem) < 0) { + return NULL; + } + + def.type = VIR_INTERFACE_TYPE_ETHERNET; + def.name = physicalNic->device; + def.mac = physicalNic->mac; + def.startmode = VIR_INTERFACE_START_ONBOOT; + + /* FIXME: Add support for IPv6, requires to use vSphere API 4.0 */ + if (physicalNic->spec->ip != NULL) { + protocol.family = (char *)"ipv4"; + + if (physicalNic->spec->ip->dhcp == esxVI_Boolean_True) { + protocol.dhcp = 1; + } + + if (physicalNic->spec->ip->ipAddress != NULL && + physicalNic->spec->ip->subnetMask != NULL && + strlen(physicalNic->spec->ip->ipAddress) > 0 && + strlen(physicalNic->spec->ip->subnetMask) > 0) { + hasAddress = true; + } + + if (protocol.dhcp || hasAddress) { + protocols = &protocol; + def.nprotos = 1; + def.protos = &protocols; + } + + if (hasAddress && + !(protocol.dhcp && (flags & VIR_INTERFACE_XML_INACTIVE))) { + ips = &ip; + protocol.nips = 1; + protocol.ips = &ips; + + if (virSocketAddrParseIPv4(&socketAddress, + physicalNic->spec->ip->subnetMask) < 0) { + goto cleanup; + } + + ip.address = physicalNic->spec->ip->ipAddress; + ip.prefix = virSocketAddrGetNumNetmaskBits(&socketAddress); + } + } + + xml = virInterfaceDefFormat(&def); + + cleanup: + esxVI_PhysicalNic_Free(&physicalNic); + + return xml; +} + + + +static int +esxInterfaceIsActive(virInterfacePtr iface ATTRIBUTE_UNUSED) +{ + /* ESX interfaces are always active */ + return 1; +} + + + static virInterfaceDriver esxInterfaceDriver = { .name = "ESX", .open = esxInterfaceOpen, /* 0.7.6 */ .close = esxInterfaceClose, /* 0.7.6 */ + .numOfInterfaces = esxNumberOfInterfaces, /* 0.10.0 */ + .listInterfaces = esxListInterfaces, /* 0.10.0 */ + .numOfDefinedInterfaces = esxNumberOfDefinedInterfaces, /* 0.10.0 */ + .listDefinedInterfaces = esxListDefinedInterfaces, /* 0.10.0 */ + .interfaceLookupByName = esxInterfaceLookupByName, /* 0.10.0 */ + .interfaceLookupByMACString = esxInterfaceLookupByMACString, /* 0.10.0 */ + .interfaceGetXMLDesc = esxInterfaceGetXMLDesc, /* 0.10.0 */ + .interfaceIsActive = esxInterfaceIsActive, /* 0.10.0 */ }; diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c index 2c789e1..c4217c9 100644 --- a/src/esx/esx_vi.c +++ b/src/esx/esx_vi.c @@ -3,7 +3,7 @@ * esx_vi.c: client for the VMware VI API 2.5 to manage ESX hosts * * Copyright (C) 2010-2011 Red Hat, Inc. - * Copyright (C) 2009-2011 Matthias Bolte <matthias.bolte@xxxxxxxxxxxxxx> + * Copyright (C) 2009-2012 Matthias Bolte <matthias.bolte@xxxxxxxxxxxxxx> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -3949,6 +3949,148 @@ esxVI_LookupAutoStartPowerInfoList(esxVI_Context *ctx, int +esxVI_LookupPhysicalNicList(esxVI_Context *ctx, + esxVI_PhysicalNic **physicalNicList) +{ + int result = -1; + esxVI_String *propertyNameList = NULL; + esxVI_ObjectContent *hostSystem = NULL; + esxVI_DynamicProperty *dynamicProperty = NULL; + + if (physicalNicList == NULL || *physicalNicList != NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument")); + return -1; + } + + if (esxVI_String_AppendValueToList(&propertyNameList, + "config.network.pnic") < 0 || + esxVI_LookupHostSystemProperties(ctx, propertyNameList, + &hostSystem) < 0) { + goto cleanup; + } + + for (dynamicProperty = hostSystem->propSet; dynamicProperty != NULL; + dynamicProperty = dynamicProperty->_next) { + if (STREQ(dynamicProperty->name, "config.network.pnic")) { + if (esxVI_PhysicalNic_CastListFromAnyType(dynamicProperty->val, + physicalNicList) < 0) { + goto cleanup; + } + } else { + VIR_WARN("Unexpected '%s' property", dynamicProperty->name); + } + } + + result = 0; + + cleanup: + esxVI_String_Free(&propertyNameList); + esxVI_ObjectContent_Free(&hostSystem); + + return result; +} + + + +int +esxVI_LookupPhysicalNicByName(esxVI_Context *ctx, const char *name, + esxVI_PhysicalNic **physicalNic, + esxVI_Occurrence occurrence) +{ + int result = -1; + esxVI_PhysicalNic *physicalNicList = NULL; + esxVI_PhysicalNic *candidate = NULL; + + if (physicalNic == NULL || *physicalNic != NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument")); + return -1; + } + + if (esxVI_LookupPhysicalNicList(ctx, &physicalNicList) < 0) { + goto cleanup; + } + + /* Search for a matching physical NIC */ + for (candidate = physicalNicList; candidate != NULL; + candidate = candidate->_next) { + if (STRCASEEQ(candidate->device, name)) { + if (esxVI_PhysicalNic_DeepCopy(physicalNic, candidate) < 0) { + goto cleanup; + } + + /* Found physical NIC with matching name */ + result = 0; + + goto cleanup; + } + } + + if (*physicalNic == NULL && occurrence != esxVI_Occurrence_OptionalItem) { + virReportError(VIR_ERR_NO_INTERFACE, + _("Could not find physical NIC with name '%s'"), name); + goto cleanup; + } + + result = 0; + + cleanup: + esxVI_PhysicalNic_Free(&physicalNicList); + + return result; +} + + + +int +esxVI_LookupPhysicalNicByMACAddress(esxVI_Context *ctx, const char *mac, + esxVI_PhysicalNic **physicalNic, + esxVI_Occurrence occurrence) +{ + int result = -1; + esxVI_PhysicalNic *physicalNicList = NULL; + esxVI_PhysicalNic *candidate = NULL; + + if (physicalNic == NULL || *physicalNic != NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument")); + return -1; + } + + if (esxVI_LookupPhysicalNicList(ctx, &physicalNicList) < 0) { + goto cleanup; + } + + /* Search for a matching physical NIC */ + for (candidate = physicalNicList; candidate != NULL; + candidate = candidate->_next) { + if (STRCASEEQ(candidate->mac, mac)) { + if (esxVI_PhysicalNic_DeepCopy(physicalNic, candidate) < 0) { + goto cleanup; + } + + /* Found physical NIC with matching MAC address */ + result = 0; + + goto cleanup; + } + } + + if (*physicalNic == NULL && occurrence != esxVI_Occurrence_OptionalItem) { + virReportError(VIR_ERR_NO_INTERFACE, + _("Could not find physical NIC with MAC address '%s'"), mac); + goto cleanup; + } + + result = 0; + + cleanup: + esxVI_PhysicalNic_Free(&physicalNicList); + + return result; +} + + + +int esxVI_HandleVirtualMachineQuestion (esxVI_Context *ctx, esxVI_ManagedObjectReference *virtualMachine, esxVI_VirtualMachineQuestionInfo *questionInfo, bool autoAnswer, diff --git a/src/esx/esx_vi.h b/src/esx/esx_vi.h index 4b84be8..597013c 100644 --- a/src/esx/esx_vi.h +++ b/src/esx/esx_vi.h @@ -3,7 +3,7 @@ * esx_vi.h: client for the VMware VI API 2.5 to manage ESX hosts * * Copyright (C) 2011 Red Hat, Inc. - * Copyright (C) 2009-2010 Matthias Bolte <matthias.bolte@xxxxxxxxxxxxxx> + * Copyright (C) 2009-2012 Matthias Bolte <matthias.bolte@xxxxxxxxxxxxxx> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -481,6 +481,17 @@ int esxVI_LookupAutoStartDefaults(esxVI_Context *ctx, int esxVI_LookupAutoStartPowerInfoList(esxVI_Context *ctx, esxVI_AutoStartPowerInfo **powerInfoList); +int esxVI_LookupPhysicalNicList(esxVI_Context *ctx, + esxVI_PhysicalNic **physicalNicList); + +int esxVI_LookupPhysicalNicByName(esxVI_Context *ctx, const char *name, + esxVI_PhysicalNic **physicalNic, + esxVI_Occurrence occurrence); + +int esxVI_LookupPhysicalNicByMACAddress(esxVI_Context *ctx, const char *mac, + esxVI_PhysicalNic **physicalNic, + esxVI_Occurrence occurrence); + int esxVI_HandleVirtualMachineQuestion (esxVI_Context *ctx, esxVI_ManagedObjectReference *virtualMachine, esxVI_VirtualMachineQuestionInfo *questionInfo, bool autoAnswer, diff --git a/src/esx/esx_vi_generator.input b/src/esx/esx_vi_generator.input index 1a67a8c..5572b36 100644 --- a/src/esx/esx_vi_generator.input +++ b/src/esx/esx_vi_generator.input @@ -317,6 +317,13 @@ object HostFileSystemVolume end +object HostIpConfig + Boolean dhcp r + String ipAddress o + String subnetMask o +end + + object HostMountInfo String path o String accessMode r @@ -455,6 +462,31 @@ object PerfSampleInfo end +object PhysicalNic + String key o + String device r + String pci r + String driver o + PhysicalNicLinkInfo linkSpeed o + PhysicalNicLinkInfo validLinkSpecification ol + PhysicalNicSpec spec r + Boolean wakeOnLanSupported r + String mac r +end + + +object PhysicalNicLinkInfo + Int speedMb r + Boolean duplex r +end + + +object PhysicalNicSpec + HostIpConfig ip o + PhysicalNicLinkInfo linkSpeed o +end + + object PropertyChange String name r PropertyChangeOp op r @@ -569,7 +601,7 @@ object TemplateConfigFileQuery extends VmConfigFileQuery end -object TraversalSpec extends SelectionSpec +object TraversalSpec extends SelectionSpec String type r String path r Boolean skip o diff --git a/src/esx/esx_vi_generator.py b/src/esx/esx_vi_generator.py index af2d57e..596bd16 100755 --- a/src/esx/esx_vi_generator.py +++ b/src/esx/esx_vi_generator.py @@ -3,7 +3,7 @@ # # esx_vi_generator.py: generates most of the SOAP type mapping code # -# Copyright (C) 2010-2011 Matthias Bolte <matthias.bolte@xxxxxxxxxxxxxx> +# Copyright (C) 2010-2012 Matthias Bolte <matthias.bolte@xxxxxxxxxxxxxx> # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -1522,6 +1522,9 @@ additional_object_features = { "AutoStartDefaults" : Object.FEATURE__AN Object.FEATURE__ANY_TYPE, "ManagedObjectReference" : Object.FEATURE__ANY_TYPE, "ObjectContent" : Object.FEATURE__DEEP_COPY, + "PhysicalNic" : Object.FEATURE__DEEP_COPY | + Object.FEATURE__LIST | + Object.FEATURE__ANY_TYPE, "ResourcePoolResourceUsage" : Object.FEATURE__ANY_TYPE, "ServiceContent" : Object.FEATURE__DESERIALIZE, "SharesInfo" : Object.FEATURE__ANY_TYPE, -- 1.7.4.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list