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