[libvirt] [PATCH] esx: Implement interface driver

Matthias Bolte matthias.bolte at googlemail.com
Sun Aug 5 20:10:29 UTC 2012


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 at googlemail.com>
+ * Copyright (C) 2010-2012 Matthias Bolte <matthias.bolte at googlemail.com>
  *
  * 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 at googlemail.com>
+ * Copyright (C) 2009-2012 Matthias Bolte <matthias.bolte at googlemail.com>
  *
  * 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 at googlemail.com>
+ * Copyright (C) 2009-2012 Matthias Bolte <matthias.bolte at googlemail.com>
  *
  * 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 at googlemail.com>
+# Copyright (C) 2010-2012 Matthias Bolte <matthias.bolte at googlemail.com>
 #
 # 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




More information about the libvir-list mailing list