1 /*
2  * esx_interface_driver.c: interface driver functions for managing VMware ESX
3  *                         host interfaces
4  *
5  * Copyright (C) 2010-2011 Red Hat, Inc.
6  * Copyright (C) 2010-2012 Matthias Bolte <matthias.bolte@googlemail.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library.  If not, see
20  * <http://www.gnu.org/licenses/>.
21  *
22  */
23 
24 #include <config.h>
25 
26 #include "internal.h"
27 #include "viralloc.h"
28 #include "viruuid.h"
29 #include "interface_conf.h"
30 #include "virsocketaddr.h"
31 #include "esx_private.h"
32 #include "esx_interface_driver.h"
33 #include "esx_vi.h"
34 #include "esx_vi_methods.h"
35 #include "esx_util.h"
36 #include "virstring.h"
37 
38 #define VIR_FROM_THIS VIR_FROM_ESX
39 
40 
41 static int
esxConnectNumOfInterfaces(virConnectPtr conn)42 esxConnectNumOfInterfaces(virConnectPtr conn)
43 {
44     esxPrivate *priv = conn->privateData;
45     esxVI_PhysicalNic *physicalNicList = NULL;
46     esxVI_PhysicalNic *physicalNic = NULL;
47     int count = 0;
48 
49     if (esxVI_EnsureSession(priv->primary) < 0 ||
50         esxVI_LookupPhysicalNicList(priv->primary, &physicalNicList) < 0) {
51         return -1;
52     }
53 
54     for (physicalNic = physicalNicList; physicalNic;
55          physicalNic = physicalNic->_next) {
56         ++count;
57     }
58 
59     esxVI_PhysicalNic_Free(&physicalNicList);
60 
61     return count;
62 }
63 
64 
65 
66 static int
esxConnectListInterfaces(virConnectPtr conn,char ** const names,int maxnames)67 esxConnectListInterfaces(virConnectPtr conn, char **const names, int maxnames)
68 {
69     esxPrivate *priv = conn->privateData;
70     esxVI_PhysicalNic *physicalNicList = NULL;
71     esxVI_PhysicalNic *physicalNic = NULL;
72     int count = 0;
73 
74     if (maxnames == 0)
75         return 0;
76 
77     if (esxVI_EnsureSession(priv->primary) < 0 ||
78         esxVI_LookupPhysicalNicList(priv->primary, &physicalNicList) < 0) {
79         return -1;
80     }
81 
82     for (physicalNic = physicalNicList; physicalNic;
83          physicalNic = physicalNic->_next) {
84         names[count] = g_strdup(physicalNic->device);
85 
86         ++count;
87     }
88 
89     esxVI_PhysicalNic_Free(&physicalNicList);
90 
91     return count;
92 }
93 
94 
95 
96 static int
esxConnectNumOfDefinedInterfaces(virConnectPtr conn G_GNUC_UNUSED)97 esxConnectNumOfDefinedInterfaces(virConnectPtr conn G_GNUC_UNUSED)
98 {
99     /* ESX interfaces are always active */
100     return 0;
101 }
102 
103 
104 
105 static int
esxConnectListDefinedInterfaces(virConnectPtr conn G_GNUC_UNUSED,char ** const names G_GNUC_UNUSED,int maxnames G_GNUC_UNUSED)106 esxConnectListDefinedInterfaces(virConnectPtr conn G_GNUC_UNUSED,
107                                 char **const names G_GNUC_UNUSED,
108                                 int maxnames G_GNUC_UNUSED)
109 {
110     /* ESX interfaces are always active */
111     return 0;
112 }
113 
114 
115 
116 static virInterfacePtr
esxInterfaceLookupByName(virConnectPtr conn,const char * name)117 esxInterfaceLookupByName(virConnectPtr conn, const char *name)
118 {
119     virInterfacePtr iface = NULL;
120     esxPrivate *priv = conn->privateData;
121     esxVI_PhysicalNic *physicalNic = NULL;
122 
123     if (esxVI_EnsureSession(priv->primary) < 0 ||
124         esxVI_LookupPhysicalNicByMACAddress(priv->primary, name, &physicalNic,
125                                             esxVI_Occurrence_RequiredItem) < 0) {
126         return NULL;
127     }
128 
129     iface = virGetInterface(conn, physicalNic->device, physicalNic->mac);
130 
131     esxVI_PhysicalNic_Free(&physicalNic);
132 
133     return iface;
134 }
135 
136 
137 
138 static virInterfacePtr
esxInterfaceLookupByMACString(virConnectPtr conn,const char * mac)139 esxInterfaceLookupByMACString(virConnectPtr conn, const char *mac)
140 {
141     virInterfacePtr iface = NULL;
142     esxPrivate *priv = conn->privateData;
143     esxVI_PhysicalNic *physicalNic = NULL;
144 
145     if (esxVI_EnsureSession(priv->primary) < 0 ||
146         esxVI_LookupPhysicalNicByMACAddress(priv->primary, mac, &physicalNic,
147                                             esxVI_Occurrence_RequiredItem) < 0) {
148         return NULL;
149     }
150 
151     iface = virGetInterface(conn, physicalNic->device, physicalNic->mac);
152 
153     esxVI_PhysicalNic_Free(&physicalNic);
154 
155     return iface;
156 }
157 
158 
159 
160 static char *
esxInterfaceGetXMLDesc(virInterfacePtr iface,unsigned int flags)161 esxInterfaceGetXMLDesc(virInterfacePtr iface, unsigned int flags)
162 {
163     char *xml = NULL;
164     esxPrivate *priv = iface->conn->privateData;
165     esxVI_PhysicalNic *physicalNic = NULL;
166     virInterfaceDef def;
167     bool hasAddress = false;
168     virInterfaceProtocolDef *protocols;
169     virInterfaceProtocolDef protocol;
170     virSocketAddr socketAddress;
171     virInterfaceIPDef *ips;
172     virInterfaceIPDef ip;
173 
174     virCheckFlags(VIR_INTERFACE_XML_INACTIVE, NULL);
175 
176     memset(&def, 0, sizeof(def));
177     memset(&protocol, 0, sizeof(protocol));
178     memset(&socketAddress, 0, sizeof(socketAddress));
179     memset(&ip, 0, sizeof(ip));
180 
181     if (esxVI_EnsureSession(priv->primary) < 0 ||
182         esxVI_LookupPhysicalNicByMACAddress(priv->primary, iface->mac,
183                                             &physicalNic,
184                                             esxVI_Occurrence_RequiredItem) < 0) {
185         return NULL;
186     }
187 
188     def.type = VIR_INTERFACE_TYPE_ETHERNET;
189     def.name = physicalNic->device;
190     def.mac = physicalNic->mac;
191     def.startmode = VIR_INTERFACE_START_ONBOOT;
192 
193     /* FIXME: Add support for IPv6, requires to use vSphere API 4.0 */
194     if (physicalNic->spec->ip) {
195         protocol.family = (char *)"ipv4";
196 
197         if (physicalNic->spec->ip->dhcp == esxVI_Boolean_True)
198             protocol.dhcp = 1;
199 
200         if (physicalNic->spec->ip->ipAddress &&
201             physicalNic->spec->ip->subnetMask &&
202             strlen(physicalNic->spec->ip->ipAddress) > 0 &&
203             strlen(physicalNic->spec->ip->subnetMask) > 0) {
204             hasAddress = true;
205         }
206 
207         if (protocol.dhcp || hasAddress) {
208             protocols = &protocol;
209             def.nprotos = 1;
210             def.protos = &protocols;
211         }
212 
213         if (hasAddress &&
214             !(protocol.dhcp && (flags & VIR_INTERFACE_XML_INACTIVE))) {
215             ips = &ip;
216             protocol.nips = 1;
217             protocol.ips = &ips;
218 
219             if (virSocketAddrParseIPv4(&socketAddress,
220                                        physicalNic->spec->ip->subnetMask) < 0) {
221                 goto cleanup;
222             }
223 
224             ip.address = physicalNic->spec->ip->ipAddress;
225             ip.prefix = virSocketAddrGetNumNetmaskBits(&socketAddress);
226         }
227     }
228 
229     xml = virInterfaceDefFormat(&def);
230 
231  cleanup:
232     esxVI_PhysicalNic_Free(&physicalNic);
233 
234     return xml;
235 }
236 
237 
238 
239 static int
esxInterfaceIsActive(virInterfacePtr iface G_GNUC_UNUSED)240 esxInterfaceIsActive(virInterfacePtr iface G_GNUC_UNUSED)
241 {
242     /* ESX interfaces are always active */
243     return 1;
244 }
245 
246 
247 
248 virInterfaceDriver esxInterfaceDriver = {
249     .connectNumOfInterfaces = esxConnectNumOfInterfaces, /* 0.10.0 */
250     .connectListInterfaces = esxConnectListInterfaces, /* 0.10.0 */
251     .connectNumOfDefinedInterfaces = esxConnectNumOfDefinedInterfaces, /* 0.10.0 */
252     .connectListDefinedInterfaces = esxConnectListDefinedInterfaces, /* 0.10.0 */
253     .interfaceLookupByName = esxInterfaceLookupByName, /* 0.10.0 */
254     .interfaceLookupByMACString = esxInterfaceLookupByMACString, /* 0.10.0 */
255     .interfaceGetXMLDesc = esxInterfaceGetXMLDesc, /* 0.10.0 */
256     .interfaceIsActive = esxInterfaceIsActive, /* 0.10.0 */
257 };
258