/* * esx_interface_driver.c: interface driver functions for managing VMware ESX * host interfaces * * Copyright (C) 2010-2011 Red Hat, Inc. * Copyright (C) 2010-2012 Matthias Bolte * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see * . * */ #include #include "internal.h" #include "util.h" #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" #include "esx_vi_methods.h" #include "esx_util.h" #define VIR_FROM_THIS VIR_FROM_ESX static virDrvOpenStatus esxInterfaceOpen(virConnectPtr conn, virConnectAuthPtr auth ATTRIBUTE_UNUSED, unsigned int flags) { virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR); if (conn->driver->no != VIR_DRV_ESX) { return VIR_DRV_OPEN_DECLINED; } conn->interfacePrivateData = conn->privateData; return VIR_DRV_OPEN_SUCCESS; } static int esxInterfaceClose(virConnectPtr conn) { conn->interfacePrivateData = NULL; return 0; } 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 */ }; int esxInterfaceRegister(void) { return virRegisterInterfaceDriver(&esxInterfaceDriver); }