[libvirt] [PATCH] - added mapping to Network object - added implementation of select networking functions - virsh net-list and net-info commands now work for esx

From: jbarkely <jbarkley@willo.(none)> --- src/esx/esx_network_driver.c | 181 +++++++++++++++++++++++++++++++++++++++- src/esx/esx_vi.c | 104 ++++++++++++++++++++++- src/esx/esx_vi.h | 9 ++ src/esx/esx_vi_generator.input | 78 +++++++++++++++++ 4 files changed, 366 insertions(+), 6 deletions(-) diff --git a/src/esx/esx_network_driver.c b/src/esx/esx_network_driver.c index a64bb8e..c4cc7b4 100644 --- a/src/esx/esx_network_driver.c +++ b/src/esx/esx_network_driver.c @@ -34,6 +34,7 @@ #include "esx_vi.h" #include "esx_vi_methods.h" #include "esx_util.h" +#include "md5.h" #define VIR_FROM_THIS VIR_FROM_ESX @@ -63,18 +64,190 @@ esxNetworkClose(virConnectPtr conn) return 0; } +static virNetworkPtr +esxNetworkLookupByName(virConnectPtr conn, const char *name) { + //esxPrivate *priv = conn->networkPrivateData; + esxPrivate *priv = conn->networkPrivateData; + esxVI_String *propertyNameList = NULL; + esxVI_ObjectContent *network = NULL; + virNetworkPtr virNetwork = NULL; + unsigned char uuid[VIR_UUID_BUFLEN]; + unsigned char md5[MD5_DIGEST_SIZE]; /* MD5_DIGEST_SIZE = VIR_UUID_BUFLEN = 16 */ + + if (esxVI_EnsureSession(priv->primary) < 0) { + return NULL; + } + + if (esxVI_LookupNetworkByName(priv->primary, name, propertyNameList, + &network, + esxVI_Occurrence_OptionalItem) < 0) { + goto cleanup; + } + + if (NULL==network) { + // raise error + ESX_ERROR(VIR_ERR_NO_NETWORK, _("No network with name '%s'"), name); + goto cleanup; + + } + + char *name_candidate = NULL; + esxVI_GetStringValue(network, "name", &name_candidate, esxVI_Occurrence_OptionalItem); + + md5_buffer(name, strlen(name), md5); + virNetwork = virGetNetwork(conn, name, md5); + + cleanup: + esxVI_String_Free(&propertyNameList); + //esxVI_ObjectContent_Free(&network); +// printf("virNetwork=%s\n", virNetwork->name); + return virNetwork; +} + +static int +esxListNetworks(virConnectPtr conn, char **const names, int nnames) +{ + //setup + bool success = false; + esxPrivate *priv = conn->networkPrivateData; + esxVI_String *propertyNameList = NULL; + esxVI_DynamicProperty *dynamicProperty = NULL; + esxVI_ObjectContent *networkList = NULL; + esxVI_ObjectContent *network = NULL; + int count = 0; + int i; + + //check args + if (names == NULL || nnames < 0) { + ESX_ERROR(VIR_ERR_INVALID_ARG, "%s", _("Invalid argument")); + return -1; + } + + if (nnames == 0) { + return 0; + } + + //check connection + if (esxVI_EnsureSession(priv->primary) < 0) { + return -1; + } + + //get network(s) + if (esxVI_String_AppendValueToList(&propertyNameList, + "summary.name") < 0 || + esxVI_LookupNetworkList(priv->primary, propertyNameList, + &networkList) < 0) { + goto cleanup; + } + + for (network = networkList; network != NULL; + network = network->_next) { + for (dynamicProperty = network->propSet; dynamicProperty != NULL; + dynamicProperty = dynamicProperty->_next) { + if (STREQ(dynamicProperty->name, "summary.name")) { + if (esxVI_AnyType_ExpectType(dynamicProperty->val, + esxVI_Type_String) < 0) { + goto cleanup; + } + + names[count] = strdup(dynamicProperty->val->string); + + if (names[count] == NULL) { + virReportOOMError(); + goto cleanup; + } + + ++count; + break; + } else { + VIR_WARN("Unexpected '%s' property", dynamicProperty->name); + } + } + } + + success = true; + + //cleanup + cleanup: + if (! success) { + for (i = 0; i < count; ++i) { + VIR_FREE(names[i]); + } + + count = -1; + } + + esxVI_String_Free(&propertyNameList); + esxVI_ObjectContent_Free(&networkList); + + return count; +} + +static int +esxNumOfNetworks(virConnectPtr conn) +{ + //setup + esxPrivate *priv = conn->networkPrivateData; + esxVI_String *propertyNameList = NULL; + esxVI_DynamicProperty *dynamicProperty = NULL; + esxVI_ObjectContent *networkList = NULL; + esxVI_ObjectContent *network = NULL; + int count = 0; + int i; + + //check connection + if (esxVI_EnsureSession(priv->primary) < 0) { + return -1; + } + + //get network(s) + if (esxVI_String_AppendValueToList(&propertyNameList, + "summary.name") < 0 || + esxVI_LookupNetworkList(priv->primary, propertyNameList, + &networkList) < 0) { + esxVI_String_Free(&propertyNameList); + esxVI_ObjectContent_Free(&networkList); + + return -1; + } + + for (network = networkList; network != NULL; + network = network->_next) { + for (dynamicProperty = network->propSet; dynamicProperty != NULL; + dynamicProperty = dynamicProperty->_next) { + if (STREQ(dynamicProperty->name, "summary.name")) { + ++count; + break; + } else { + VIR_WARN("Unexpected '%s' property", dynamicProperty->name); + } + } + } + + + esxVI_String_Free(&propertyNameList); + esxVI_ObjectContent_Free(&networkList); + + return count; +} + +static int esxNumOfDefinedNetworks(virConnectPtr conn) +{ + printf("JB-BUG C\n"); + return 8; +} static virNetworkDriver esxNetworkDriver = { "ESX", /* name */ esxNetworkOpen, /* open */ esxNetworkClose, /* close */ - NULL, /* numOfNetworks */ - NULL, /* listNetworks */ - NULL, /* numOfDefinedNetworks */ + esxNumOfNetworks, /* numOfNetworks */ + esxListNetworks, /* listNetworks */ + esxNumOfDefinedNetworks, /* numOfDefinedNetworks */ NULL, /* listDefinedNetworks */ NULL, /* networkLookupByUUID */ - NULL, /* networkLookupByName */ + esxNetworkLookupByName, /* networkLookupByName */ NULL, /* networkCreateXML */ NULL, /* networkDefineXML */ NULL, /* networkUndefine */ diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c index 7446ec5..509cf07 100644 --- a/src/esx/esx_vi.c +++ b/src/esx/esx_vi.c @@ -109,6 +109,7 @@ ESX_VI__TEMPLATE__FREE(Context, esxVI_SelectionSpec_Free(&item->selectSet_hostSystemToParent); esxVI_SelectionSpec_Free(&item->selectSet_hostSystemToVm); esxVI_SelectionSpec_Free(&item->selectSet_hostSystemToDatastore); + esxVI_SelectionSpec_Free(&item->selectSet_hostSystemToNetwork); esxVI_SelectionSpec_Free(&item->selectSet_computeResourceToHost); esxVI_SelectionSpec_Free(&item->selectSet_computeResourceToParentToParent); }); @@ -1483,6 +1484,13 @@ esxVI_BuildSelectSetCollection(esxVI_Context *ctx) return -1; } + /* HostSystem -> network (Network) */ + if (esxVI_BuildSelectSet(&ctx->selectSet_hostSystemToNetwork, + "hostSystemToNetwork", + "HostSystem", "network", NULL) < 0) { + return -1; + } + /* Folder -> parent (Folder, Datacenter) */ if (esxVI_BuildSelectSet(&ctx->selectSet_computeResourceToParentToParent, "managedEntityToParent", @@ -1543,9 +1551,13 @@ esxVI_EnsureSession(esxVI_Context *ctx) * Query the session manager for the current session of this connection * and re-login if there is no current session for this connection. */ + if (esxVI_String_AppendValueToList(&propertyNameList, - "currentSession") < 0 || - esxVI_LookupObjectContentByType(ctx, ctx->service->sessionManager, + "currentSession") < 0) { + goto cleanup; + } + + if (esxVI_LookupObjectContentByType(ctx, ctx->service->sessionManager, "SessionManager", propertyNameList, &sessionManager, esxVI_Occurrence_RequiredItem) < 0) { @@ -1649,6 +1661,8 @@ esxVI_LookupObjectContentByType(esxVI_Context *ctx, objectSpec->selectSet = ctx->selectSet_hostSystemToVm; } else if (STREQ(type, "Datastore")) { objectSpec->selectSet = ctx->selectSet_hostSystemToDatastore; + } else if (STREQ(type, "Network")) { + objectSpec->selectSet = ctx->selectSet_hostSystemToNetwork; } else { ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, _("Invalid lookup of '%s' from '%s'"), @@ -2474,6 +2488,92 @@ esxVI_LookupDatastoreList(esxVI_Context *ctx, esxVI_String *propertyNameList, esxVI_Occurrence_OptionalList); } +int +esxVI_LookupNetworkList(esxVI_Context *ctx, + esxVI_String *propertyNameList, + esxVI_ObjectContent **networkList) +{ + return esxVI_LookupObjectContentByType(ctx, ctx->hostSystem->_reference, + "Network", propertyNameList, + networkList, + esxVI_Occurrence_OptionalList); +} + +int +esxVI_LookupNetworkByName(esxVI_Context *ctx, const char *name, + esxVI_String *propertyNameList, + esxVI_ObjectContent **network, + esxVI_Occurrence occurrence) +{ + int result = -1; + esxVI_String *completePropertyNameList = NULL; + esxVI_ObjectContent *networkList = NULL; + esxVI_ObjectContent *candidate = NULL; + char *name_candidate = NULL; + + if (network == NULL || *network != NULL) { + ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument")); + return -1; + } + + + if (esxVI_String_DeepCopyList(&completePropertyNameList, + propertyNameList) < 0 || + esxVI_String_AppendValueToList(&completePropertyNameList, "name") < 0 || + esxVI_LookupNetworkList(ctx, completePropertyNameList, + &networkList) < 0) { + goto cleanup; + } + + for (candidate = networkList; candidate != NULL; + candidate = candidate->_next) { + VIR_FREE(name_candidate); + + /* + if (esxVI_GetVirtualMachineIdentity(candidate, NULL, &name_candidate, + NULL) < 0) { + goto cleanup; + } + */ + if (esxVI_GetStringValue(candidate, "name", &name_candidate, + esxVI_Occurrence_OptionalItem) < 0) { + goto cleanup; + } + + if (STRNEQ(name, name_candidate)) { + continue; + } + + if (esxVI_ObjectContent_DeepCopy(network, candidate) < 0) { + goto cleanup; + } + + break; + } + + /* + if (*network == NULL) { + if (occurrence == esxVI_Occurrence_OptionalItem) { + result = 0; + + goto cleanup; + } else { + ESX_VI_ERROR(VIR_ERR_NO_NETWORK, + _("Could not find network with name '%s'"), name); + goto cleanup; + } + } + */ + + result = 0; + + cleanup: + esxVI_String_Free(&completePropertyNameList); + esxVI_ObjectContent_Free(&networkList); + //VIR_FREE(name_candidate); + + return result; +} int diff --git a/src/esx/esx_vi.h b/src/esx/esx_vi.h index e150dbf..cbd6068 100644 --- a/src/esx/esx_vi.h +++ b/src/esx/esx_vi.h @@ -165,6 +165,7 @@ struct _esxVI_Context { esxVI_SelectionSpec *selectSet_hostSystemToParent; esxVI_SelectionSpec *selectSet_hostSystemToVm; esxVI_SelectionSpec *selectSet_hostSystemToDatastore; + esxVI_SelectionSpec *selectSet_hostSystemToNetwork; esxVI_SelectionSpec *selectSet_computeResourceToHost; esxVI_SelectionSpec *selectSet_computeResourceToParentToParent; bool hasQueryVirtualDiskUuid; @@ -367,11 +368,19 @@ int esxVI_LookupVirtualMachineByUuidAndPrepareForTask int esxVI_LookupDatastoreList(esxVI_Context *ctx, esxVI_String *propertyNameList, esxVI_ObjectContent **datastoreList); +int esxVI_LookupNetworkList(esxVI_Context *ctx, esxVI_String *propertyNameList, + esxVI_ObjectContent **networkList); + int esxVI_LookupDatastoreByName(esxVI_Context *ctx, const char *name, esxVI_String *propertyNameList, esxVI_ObjectContent **datastore, esxVI_Occurrence occurrence); +int esxVI_LookupNetworkByName(esxVI_Context *ctx, const char *name, + esxVI_String *propertyNameList, + esxVI_ObjectContent **network, + esxVI_Occurrence occurrence); + int esxVI_LookupDatastoreByAbsolutePath(esxVI_Context *ctx, const char *absolutePath, esxVI_String *propertyNameList, diff --git a/src/esx/esx_vi_generator.input b/src/esx/esx_vi_generator.input index 44d1d9b..86c4b12 100644 --- a/src/esx/esx_vi_generator.input +++ b/src/esx/esx_vi_generator.input @@ -334,6 +334,84 @@ object HostNasVolume extends HostFileSystemVolume String userName o end +object HostNetCapabilities +end + +object HostIpRouteConfig +end + +object HostDnsConfig +end + +object HostIpRouteConfig +end + +object HostNetworkConfig +end + +object HostNetworkInfo +end + +object HostNetworkSystem + HostNetCapabilities capabilities rl + HostIpRouteConfig consoleIpRuteConfig r + HostDnsConfig dnsConfig r + HostIpRouteConfig ipRouteConfig r + HostNetworkConfig networkConfig r + HostNetworkInfo networkInfo r +end + + +object HostIpRouteConfig +end + +object HostVirtualNic +end + +object HostDhcpService +end + +object HostDnsConfig +end + +object HostNatService +end + +object PhysicalNic +end + +object HostPortGroup +end + +object HostProxySwitch +end + +object HostIpRouteTableInfo +end + +object HostVirtualNic +end + +object HostVirtualSwitch +end + +object HostNetworkInfo + Boolean atBootIpV6Enabled r + HostIpRouteConfig consoleIpRouteConfig r + HostVirtualNic consoleVnic rl + HostDhcpService dhcp rl + HostDnsConfig dnsConfig r + HostIpRouteConfig ipRouteConfig r + Boolean ipV6Enabled r + HostNatService nat rl + PhysicalNic pnic rl + HostPortGroup portgroup rl + HostProxySwitch proxySwitch rl + HostIpRouteTableInfo routeTableInfo r + HostVirtualNic vnic rl + HostVirtualSwitch vswitch rl +end + object HostScsiDiskPartition String diskName r -- 1.7.4.1

Long summary line. You could reformat it like this: esx: Support virsh net-list and net-info Add mapping of Network object and implementation of select networking functions. This makes virsh net-list and net-info commands work for ESX. 2011/4/12 jbarkley <james.barkley@gmail.com>:
From: jbarkely <jbarkley@willo.(none)>
You should tell git your name and email address to get it properly recorded in a patch. See git config for this: git config --global user.name "your name" git config --global user.email "your email"
--- src/esx/esx_network_driver.c | 181 +++++++++++++++++++++++++++++++++++++++- src/esx/esx_vi.c | 104 ++++++++++++++++++++++- src/esx/esx_vi.h | 9 ++ src/esx/esx_vi_generator.input | 78 +++++++++++++++++ 4 files changed, 366 insertions(+), 6 deletions(-)
As I'm a bit short of time right now just some general comments. - C style comments (/* */) are preferred over C++ style ones (//). - Remove code that you have commented out. - I'm not sure if using the MD5 sum of the name of a network it's UUID is the stablest possible source. I'd like to find a better option for this, but I'm not sure that it exists. - Instead of adding many empty objects for the members of HostNetworkSystem and HostNetworkInfo that aren't used yet you could mark them as ignored (i) instead in the .input file. Overall the patch looks okay. I'll give it a detailed review and test it over the weekend. In the meantime I'd like to delay the inclusion of this patch into the codebase until we are confident that this approach is the correct one. Matthias

On Wed, Apr 13, 2011 at 2:51 AM, Matthias Bolte < matthias.bolte@googlemail.com> wrote:
Long summary line. You could reformat it like this:
esx: Support virsh net-list and net-info
Add mapping of Network object and implementation of select networking functions.
This makes virsh net-list and net-info commands work for ESX.
Right, can do. I didn't realize it was just taking the commit message and stuffing it into the subject line.
2011/4/12 jbarkley <james.barkley@gmail.com>:
From: jbarkely <jbarkley@willo.(none)>
You should tell git your name and email address to get it properly recorded in a patch. See git config for this:
git config --global user.name "your name" git config --global user.email "your email"
whoops - thought I had done that.
--- src/esx/esx_network_driver.c | 181 +++++++++++++++++++++++++++++++++++++++- src/esx/esx_vi.c | 104 ++++++++++++++++++++++- src/esx/esx_vi.h | 9 ++ src/esx/esx_vi_generator.input | 78 +++++++++++++++++ 4 files changed, 366 insertions(+), 6 deletions(-)
As I'm a bit short of time right now just some general comments.
- C style comments (/* */) are preferred over C++ style ones (//).
Noted
- Remove code that you have commented out.
Got it
- I'm not sure if using the MD5 sum of the name of a network it's UUID
is the stablest possible source. I'd like to find a better option for
this, but I'm not sure that it exists.
Agreed - this was a hack placeholder to get *something* in place for the UUID. But a hash of the network name won't be UU, but just U since different hosts can have networks with the same name (and in fact do by default with ESX - the "VM Network"). Not sure if there is a better alternative, but I'll keep looking.
- Instead of adding many empty objects for the members of HostNetworkSystem and HostNetworkInfo that aren't used yet you could mark them as ignored (i) instead in the .input file.
Cool - didn't realize I could do this.
Overall the patch looks okay. I'll give it a detailed review and test it over the weekend.
In the meantime I'd like to delay the inclusion of this patch into the codebase until we are confident that this approach is the correct one.
Sure - whenever you're comfortable. I needed the functionality for some software we're building so we're using the added functionality now. I just thought it'd be nice to give you a chance to add it back in. Let me know how your in-depth review turns out - in the meantime I may clean up the other things you mentioned (comments, ignore marks, etc.). I doubt I'll get to the functionality for adding a network for another week or even two, but I'll let you know how that goes.
Matthias
Thanks for taking the time -jb

On 04/12/2011 08:13 AM, jbarkley wrote:
From: jbarkely<jbarkley@willo.(none)>
James and Mathias: Have you taken a look yet at my proposal to expand the usage of the network XML? https://www.redhat.com/archives/libvir-list/2011-April/msg00591.html I'm wondering if you hit any limitations while trying to make ESX's view of networks match libvirt's view, and if I could do anything in the code I'll be writing to make the two fit together better (note, for example, that in the new model, you can specify a normal host bridge device, to be used for connecting a guest "directly" to the physical network, and likely we'll add other types, such as the 'openvswitch' type I suggested in (so far the only) followup). My own last experience with the VMWare network model was when using VMWare Workstation over 2 years ago, but I recall that for them bridge vs. NAT vs. routed was a 3 way switch at one level, rather than having bridging setup off in the Balkans, as is currently the case with libvirt+KVM/Xen ;-) Also, danpb mentioned yesterday that this expansion of libvirt's network model may bring it closer to VMWare's. I will be adding in this code "very soon" (within the next month) so it may be reasonable for you to put yours on top of mine, rather than putting in something now, then re-working it later (which could cause pain if we had to forever support some "interim" config model that we later decided to change). Please have a look at my mail and rip it apart. Let me know if there's anything in there that won't work for you, and if there may be something else you'd like added.
participants (4)
-
James Barkley
-
jbarkley
-
Laine Stump
-
Matthias Bolte