Hi All: [PATCH 0/1]: Contains sample xml file showing features supported so far. [PATCH 1/1]: Contains the patch for adding Networking API to change/create/etc. hostonly/internal network in VirtualBox Regards, Pritesh
diff --git a/src/network_conf.c b/src/network_conf.c index b4da3fb..b4e0b39 100644 --- a/src/network_conf.c +++ b/src/network_conf.c @@ -50,7 +50,11 @@ VIR_ENUM_DECL(virNetworkForward) VIR_ENUM_IMPL(virNetworkForward, VIR_NETWORK_FORWARD_LAST, - "none", "nat", "route" ) + "none", + "nat", + "route", + "hostonly", + "internal") #define virNetworkReportError(conn, code, fmt...) \ virReportErrorHelper(conn, VIR_FROM_NETWORK, code, __FILE__, \ diff --git a/src/network_conf.h b/src/network_conf.h index 365d469..32db7c2 100644 --- a/src/network_conf.h +++ b/src/network_conf.h @@ -36,6 +36,8 @@ enum virNetworkForwardType { VIR_NETWORK_FORWARD_NONE = 0, VIR_NETWORK_FORWARD_NAT, VIR_NETWORK_FORWARD_ROUTE, + VIR_NETWORK_FORWARD_HOSTONLY, + VIR_NETWORK_FORWARD_INTERNAL, VIR_NETWORK_FORWARD_LAST, }; diff --git a/src/vbox/vbox_driver.c b/src/vbox/vbox_driver.c index 1d2d3ed..eef67a7 100644 --- a/src/vbox/vbox_driver.c +++ b/src/vbox/vbox_driver.c @@ -41,15 +41,19 @@ extern virDriver vbox22Driver; extern virDriver vbox25Driver; +extern virNetworkDriver vbox22NetworkDriver; +extern virNetworkDriver vbox25NetworkDriver; int vboxRegister(void) { virDriverPtr driver; + virNetworkDriverPtr networkDriver; uint32_t uVersion; /* vboxRegister() shouldn't fail as that will render libvirt unless. * So, we use the v2.2 driver as a fallback/dummy. */ driver = &vbox22Driver; + networkDriver = &vbox22NetworkDriver; /* Init the glue and get the API version. */ if (VBoxCGlueInit() == 0) { @@ -67,9 +71,11 @@ int vboxRegister(void) { if (uVersion >= 2001052 && uVersion < 2002051) { DEBUG0("VirtualBox API version: 2.2"); driver = &vbox22Driver; + networkDriver = &vbox22NetworkDriver; } else if (uVersion >= 2002051 && uVersion < 2005051) { DEBUG0("VirtualBox API version: 2.5"); driver = &vbox25Driver; + networkDriver = &vbox25NetworkDriver; } else { DEBUG0("Unsupport VirtualBox API version"); } @@ -80,6 +86,8 @@ int vboxRegister(void) { if (virRegisterDriver(driver) < 0) return -1; + if (virRegisterNetworkDriver(networkDriver) < 0) + return -1; return 0; } diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 9cc883f..9854e5b 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -3635,6 +3635,963 @@ cleanup: return ret; } +/** + * The Network Functions here on + */ +static virDrvOpenStatus vboxNetworkOpen(virConnectPtr conn, + virConnectAuthPtr auth ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED) { + vboxGlobalData *data = conn->privateData; + + if (STRNEQ(conn->driver->name, "VBOX")) + goto cleanup; + + if ((data->pFuncs == NULL) || + (data->vboxObj == NULL) || + (data->vboxSession == NULL)) + goto cleanup; + + DEBUG0("network intialized"); + /* conn->networkPrivateData = some network specific data */ + return VIR_DRV_OPEN_SUCCESS; + +cleanup: + return VIR_DRV_OPEN_DECLINED; +} + +static int vboxNetworkClose(virConnectPtr conn) { + DEBUG0("network unintialized"); + conn->networkPrivateData = NULL; + return 0; +} + +static int vboxNumOfNetworks(virConnectPtr conn) { + vboxGlobalData *data = conn->privateData; + int numActive = 0; + + /* TODO: "internal" networks are just strings and + * thus can't do much with them + */ + if (data->vboxObj) { + IHost *host = NULL; + + data->vboxObj->vtbl->GetHost(data->vboxObj, &host); + if (host) { + int i = 0; + PRUint32 networkInterfacesSize = 0; + IHostNetworkInterface **networkInterfaces = NULL; + + host->vtbl->GetNetworkInterfaces(host, &networkInterfacesSize, &networkInterfaces); + + for (i = 0; i < networkInterfacesSize; i++) { + if (networkInterfaces[i]) { + PRUint32 interfaceType = 0; + + networkInterfaces[i]->vtbl->GetInterfaceType(networkInterfaces[i], &interfaceType); + if (interfaceType == HostNetworkInterfaceType_HostOnly) + numActive++; + + networkInterfaces[i]->vtbl->nsisupports.Release((nsISupports *) networkInterfaces[i]); + } + } + + host->vtbl->nsisupports.Release((nsISupports *) host); + } + } + + DEBUG("numActive: %d", numActive); + return numActive; +} + +static int vboxListNetworks(virConnectPtr conn, char **const names, int nnames) { + vboxGlobalData *data = conn->privateData; + int numActive = 0; + + /* TODO: "internal" networks are just strings and + * thus can't do much with them + */ + if (data->vboxObj) { + IHost *host = NULL; + + data->vboxObj->vtbl->GetHost(data->vboxObj, &host); + if (host) { + int i = 0; + PRUint32 networkInterfacesSize = 0; + IHostNetworkInterface **networkInterfaces = NULL; + + host->vtbl->GetNetworkInterfaces(host, &networkInterfacesSize, &networkInterfaces); + + for (i = 0; (numActive < nnames) && (i < networkInterfacesSize); i++) { + if (networkInterfaces[i]) { + PRUint32 interfaceType = 0; + + networkInterfaces[i]->vtbl->GetInterfaceType(networkInterfaces[i], &interfaceType); + + if (interfaceType == HostNetworkInterfaceType_HostOnly) { + char *nameUtf8 = NULL; + PRUnichar *nameUtf16 = NULL; + + networkInterfaces[i]->vtbl->GetName(networkInterfaces[i], &nameUtf16); + data->pFuncs->pfnUtf16ToUtf8(nameUtf16, &nameUtf8); + + DEBUG("nnames[%d]: %s", numActive, nameUtf8); + names[numActive++] = strdup(nameUtf8); + + data->pFuncs->pfnUtf8Free(nameUtf8); + data->pFuncs->pfnUtf16Free(nameUtf16); + } + } + } + + for (i = 0; i < networkInterfacesSize; i++) { + if (networkInterfaces[i]) { + networkInterfaces[i]->vtbl->nsisupports.Release((nsISupports *) networkInterfaces[i]); + } + } + + host->vtbl->nsisupports.Release((nsISupports *) host); + } + } + + return numActive; +} + +static virNetworkPtr vboxNetworkLookupByUUID(virConnectPtr conn, const unsigned char *uuid) { + vboxGlobalData *data = conn->privateData; + virNetworkPtr ret = NULL; + nsID *iid = NULL; + + if (VIR_ALLOC(iid) < 0) { + virReportOOMError(conn); + goto cleanup; + } + + /* TODO: "internal" networks are just strings and + * thus can't do much with them + */ + if (data->vboxObj) { + IHost *host = NULL; + + data->vboxObj->vtbl->GetHost(data->vboxObj, &host); + if (host) { + IHostNetworkInterface *networkInterface = NULL; + + nsIDFromChar(iid, uuid); + host->vtbl->FindHostNetworkInterfaceById(host, iid, &networkInterface); + if (networkInterface) { + PRUint32 interfaceType = 0; + + networkInterface->vtbl->GetInterfaceType(networkInterface, &interfaceType); + + if (interfaceType == HostNetworkInterfaceType_HostOnly) { + char *nameUtf8 = NULL; + PRUnichar *nameUtf16 = NULL; + + networkInterface->vtbl->GetName(networkInterface, &nameUtf16); + data->pFuncs->pfnUtf16ToUtf8(nameUtf16, &nameUtf8); + + ret = virGetNetwork(conn, nameUtf8, uuid); + + DEBUG("Network Name: %s", nameUtf8); + DEBUG("Network UUID: " + "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", + (unsigned)iid->m0, (unsigned)iid->m1, + (unsigned)iid->m2, (unsigned)iid->m3[0], + (unsigned)iid->m3[1], (unsigned)iid->m3[2], + (unsigned)iid->m3[3], (unsigned)iid->m3[4], + (unsigned)iid->m3[5], (unsigned)iid->m3[6], + (unsigned)iid->m3[7]); + + data->pFuncs->pfnUtf8Free(nameUtf8); + data->pFuncs->pfnUtf16Free(nameUtf16); + } + + networkInterface->vtbl->nsisupports.Release((nsISupports *) networkInterface); + } + + host->vtbl->nsisupports.Release((nsISupports *) host); + } + } + +cleanup: + VIR_FREE(iid); + return ret; +} + +static virNetworkPtr vboxNetworkLookupByName(virConnectPtr conn, const char *name) { + vboxGlobalData *data = conn->privateData; + virNetworkPtr ret = NULL; + + /* TODO: "internal" networks are just strings and + * thus can't do much with them + */ + if (data->vboxObj) { + IHost *host = NULL; + + data->vboxObj->vtbl->GetHost(data->vboxObj, &host); + if (host) { + PRUnichar *nameUtf16 = NULL; + IHostNetworkInterface *networkInterface = NULL; + + data->pFuncs->pfnUtf8ToUtf16(name, &nameUtf16); + + host->vtbl->FindHostNetworkInterfaceByName(host, nameUtf16, &networkInterface); + + if (networkInterface) { + PRUint32 interfaceType = 0; + + networkInterface->vtbl->GetInterfaceType(networkInterface, &interfaceType); + + if (interfaceType == HostNetworkInterfaceType_HostOnly) { + unsigned char uuid[VIR_UUID_BUFLEN]; + nsID *iid = NULL; + + networkInterface->vtbl->GetId(networkInterface, &iid); + + nsIDtoChar(uuid, iid); + + ret = virGetNetwork(conn, name, uuid); + + DEBUG("Network Name: %s", name); + DEBUG("Network UUID: " + "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", + (unsigned)iid->m0, (unsigned)iid->m1, + (unsigned)iid->m2, (unsigned)iid->m3[0], + (unsigned)iid->m3[1], (unsigned)iid->m3[2], + (unsigned)iid->m3[3], (unsigned)iid->m3[4], + (unsigned)iid->m3[5], (unsigned)iid->m3[6], + (unsigned)iid->m3[7]); + + data->pFuncs->pfnComUnallocMem(iid); + } + + networkInterface->vtbl->nsisupports.Release((nsISupports *) networkInterface); + } + + data->pFuncs->pfnUtf16Free(nameUtf16); + host->vtbl->nsisupports.Release((nsISupports *) host); + } + } + + return ret; +} + +static virNetworkPtr vboxNetworkCreateXML(virConnectPtr conn, const char *xml) { + vboxGlobalData *data = conn->privateData; + virNetworkDefPtr def = NULL; + virNetworkPtr ret = NULL; + nsID *iid = NULL; + char *networkNameUtf8 = NULL; + int i = 0; + + /* TODO: "internal" networks are just strings and + * thus can't do much with them + */ + if ((def = virNetworkDefParseString(conn, xml)) == NULL) + goto cleanup; + + if (VIR_ALLOC(iid) < 0) { + virReportOOMError(conn); + goto cleanup; + } + + if (VIR_ALLOC_N(networkNameUtf8, sizeof("HostInterfaceNetworking-") + + sizeof(def->name) + 1) < 0) { + virReportOOMError(conn); + goto cleanup; + } + + strcpy (networkNameUtf8, "HostInterfaceNetworking-"); + strcat (networkNameUtf8, def->name); + + nsIDFromChar(iid, def->uuid); + + DEBUG("Network Name: %s", def->name); + DEBUG("Network UUID: " + "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", + (unsigned)iid->m0, (unsigned)iid->m1, + (unsigned)iid->m2, (unsigned)iid->m3[0], + (unsigned)iid->m3[1], (unsigned)iid->m3[2], + (unsigned)iid->m3[3], (unsigned)iid->m3[4], + (unsigned)iid->m3[5], (unsigned)iid->m3[6], + (unsigned)iid->m3[7]); + DEBUG("bridge : %s", def->bridge); + DEBUG("domain : %s", def->domain); + DEBUG("forwardType : %d", def->forwardType); + DEBUG("forwardDev : %s", def->forwardDev); + DEBUG("ipAddress : %s", def->ipAddress); + DEBUG("netmask : %s", def->netmask); + DEBUG("network : %s", def->network); + for (i = 0; i < def->nranges; i++) { + DEBUG("DHCP(%d) start: %s", i, def->ranges[i].start); + DEBUG("DHCP(%d) end : %s", i, def->ranges[i].end); + } + for (i = 0; i < def->nhosts; i++) { + DEBUG("DHCP Host(%d) mac : %s", i, def->hosts[i].mac); + DEBUG("DHCP Host(%d) name: %s", i, def->hosts[i].name); + DEBUG("DHCP Host(%d) ip : %s", i, def->hosts[i].ip); + } + + if ((data->vboxObj) && (def->forwardType == VIR_NETWORK_FORWARD_HOSTONLY)) { + /* VirtualBox version 2.2.* has only one "hostonly" + * network called "vboxnet0" for linux + */ + if (STREQ(def->name, "vboxnet0")) { + IHost *host = NULL; + + data->vboxObj->vtbl->GetHost(data->vboxObj, &host); + if (host) { + PRUnichar *networkInterfaceNameUtf16 = NULL; + IHostNetworkInterface *networkInterface = NULL; + + data->pFuncs->pfnUtf8ToUtf16(def->name, &networkInterfaceNameUtf16); + + host->vtbl->FindHostNetworkInterfaceByName(host, networkInterfaceNameUtf16, &networkInterface); + + if (networkInterface) { + PRUint32 interfaceType = 0; + + networkInterface->vtbl->GetInterfaceType(networkInterface, &interfaceType); + + if (interfaceType == HostNetworkInterfaceType_HostOnly) { + unsigned char uuid[VIR_UUID_BUFLEN]; + nsID *vboxnet0IID = NULL; + PRUnichar *networkNameUtf16 = NULL; + + data->pFuncs->pfnUtf8ToUtf16(networkNameUtf8 , &networkNameUtf16); + + networkInterface->vtbl->GetId(networkInterface, &vboxnet0IID); + + nsIDtoChar(uuid, vboxnet0IID); + + /* Currently support only one dhcp server per network + * with contigious address space from start to end + */ + if ((def->nranges == 1) && + (def->ranges[0].start) && + (def->ranges[0].end)) { + IDHCPServer *dhcpServer = NULL; + + data->vboxObj->vtbl->FindDHCPServerByNetworkName(data->vboxObj, + networkNameUtf16, + &dhcpServer); + if (!dhcpServer) { + /* create a dhcp server */ + data->vboxObj->vtbl->CreateDHCPServer(data->vboxObj, + networkNameUtf16, + &dhcpServer); + DEBUG0("couldn't find dhcp server so creating one"); + } + if (dhcpServer) { + PRUnichar *ipAddressUtf16 = NULL; + PRUnichar *networkMaskUtf16 = NULL; + PRUnichar *fromIPAddressUtf16 = NULL; + PRUnichar *toIPAddressUtf16 = NULL; + PRUnichar *trunkTypeUtf16 = NULL; + + + data->pFuncs->pfnUtf8ToUtf16(def->ipAddress, &ipAddressUtf16); + data->pFuncs->pfnUtf8ToUtf16(def->netmask, &networkMaskUtf16); + data->pFuncs->pfnUtf8ToUtf16(def->ranges[0].start, &fromIPAddressUtf16); + data->pFuncs->pfnUtf8ToUtf16(def->ranges[0].end, &toIPAddressUtf16); + data->pFuncs->pfnUtf8ToUtf16("netflt", &trunkTypeUtf16); + + dhcpServer->vtbl->SetEnabled(dhcpServer, PR_TRUE); + + dhcpServer->vtbl->SetConfiguration(dhcpServer, + ipAddressUtf16, + networkMaskUtf16, + fromIPAddressUtf16, + toIPAddressUtf16); + + dhcpServer->vtbl->Start(dhcpServer, + networkNameUtf16, + networkInterfaceNameUtf16, + trunkTypeUtf16); + + data->pFuncs->pfnUtf16Free(ipAddressUtf16); + data->pFuncs->pfnUtf16Free(networkMaskUtf16); + data->pFuncs->pfnUtf16Free(fromIPAddressUtf16); + data->pFuncs->pfnUtf16Free(toIPAddressUtf16); + data->pFuncs->pfnUtf16Free(trunkTypeUtf16); + dhcpServer->vtbl->nsisupports.Release((nsISupports *) dhcpServer); + } + } + + ret = virGetNetwork(conn, def->name, uuid); + + DEBUG("Real Network UUID: " + "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", + (unsigned)vboxnet0IID->m0, (unsigned)vboxnet0IID->m1, + (unsigned)vboxnet0IID->m2, (unsigned)vboxnet0IID->m3[0], + (unsigned)vboxnet0IID->m3[1], (unsigned)vboxnet0IID->m3[2], + (unsigned)vboxnet0IID->m3[3], (unsigned)vboxnet0IID->m3[4], + (unsigned)vboxnet0IID->m3[5], (unsigned)vboxnet0IID->m3[6], + (unsigned)vboxnet0IID->m3[7]); + + data->pFuncs->pfnComUnallocMem(vboxnet0IID); + data->pFuncs->pfnUtf16Free(networkNameUtf16); + } + + networkInterface->vtbl->nsisupports.Release((nsISupports *) networkInterface); + } + + data->pFuncs->pfnUtf16Free(networkInterfaceNameUtf16); + host->vtbl->nsisupports.Release((nsISupports *) host); + } + } + } + +cleanup: + VIR_FREE(iid); + VIR_FREE(networkNameUtf8); + virNetworkDefFree(def); + return ret; +} + +static virNetworkPtr vboxNetworkDefineXML(virConnectPtr conn, const char *xml) { + vboxGlobalData *data = conn->privateData; + virNetworkDefPtr def = NULL; + virNetworkPtr ret = NULL; + nsID *iid = NULL; + char *networkNameUtf8 = NULL; + int i = 0; + + /* vboxNetworkDefineXML() is not exactly "network definition" + * as the network is up and running, only the DHCP server is off, + * so you can always assign static IP and get the network running. + */ + /* TODO: "internal" networks are just strings and + * thus can't do much with them + */ + if ((def = virNetworkDefParseString(conn, xml)) == NULL) + goto cleanup; + + if (VIR_ALLOC(iid) < 0) { + virReportOOMError(conn); + goto cleanup; + } + + if (VIR_ALLOC_N(networkNameUtf8, sizeof("HostInterfaceNetworking-") + + sizeof(def->name) + 1) < 0) { + virReportOOMError(conn); + goto cleanup; + } + + strcpy (networkNameUtf8, "HostInterfaceNetworking-"); + strcat (networkNameUtf8, def->name); + + nsIDFromChar(iid, def->uuid); + + DEBUG("Network Name: %s", def->name); + DEBUG("Network UUID: " + "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", + (unsigned)iid->m0, (unsigned)iid->m1, + (unsigned)iid->m2, (unsigned)iid->m3[0], + (unsigned)iid->m3[1], (unsigned)iid->m3[2], + (unsigned)iid->m3[3], (unsigned)iid->m3[4], + (unsigned)iid->m3[5], (unsigned)iid->m3[6], + (unsigned)iid->m3[7]); + DEBUG("bridge : %s", def->bridge); + DEBUG("domain : %s", def->domain); + DEBUG("forwardType : %d", def->forwardType); + DEBUG("forwardDev : %s", def->forwardDev); + DEBUG("ipAddress : %s", def->ipAddress); + DEBUG("netmask : %s", def->netmask); + DEBUG("network : %s", def->network); + for (i = 0; i < def->nranges; i++) { + DEBUG("DHCP(%d) start: %s", i, def->ranges[i].start); + DEBUG("DHCP(%d) end : %s", i, def->ranges[i].end); + } + for (i = 0; i < def->nhosts; i++) { + DEBUG("DHCP Host(%d) mac : %s", i, def->hosts[i].mac); + DEBUG("DHCP Host(%d) name: %s", i, def->hosts[i].name); + DEBUG("DHCP Host(%d) ip : %s", i, def->hosts[i].ip); + } + + if ((data->vboxObj) && (def->forwardType == VIR_NETWORK_FORWARD_HOSTONLY)) { + /* VirtualBox version 2.2.* has only one "hostonly" + * network called "vboxnet0" for linux + */ + if (STREQ(def->name, "vboxnet0")) { + IHost *host = NULL; + + data->vboxObj->vtbl->GetHost(data->vboxObj, &host); + if (host) { + PRUnichar *networkInterfaceNameUtf16 = NULL; + IHostNetworkInterface *networkInterface = NULL; + + data->pFuncs->pfnUtf8ToUtf16(def->name, &networkInterfaceNameUtf16); + + host->vtbl->FindHostNetworkInterfaceByName(host, networkInterfaceNameUtf16, &networkInterface); + + if (networkInterface) { + PRUint32 interfaceType = 0; + + networkInterface->vtbl->GetInterfaceType(networkInterface, &interfaceType); + + if (interfaceType == HostNetworkInterfaceType_HostOnly) { + unsigned char uuid[VIR_UUID_BUFLEN]; + nsID *vboxnet0IID = NULL; + PRUnichar *networkNameUtf16 = NULL; + + data->pFuncs->pfnUtf8ToUtf16(networkNameUtf8 , &networkNameUtf16); + + networkInterface->vtbl->GetId(networkInterface, &vboxnet0IID); + + nsIDtoChar(uuid, vboxnet0IID); + + /* Currently support only one dhcp server per network + * with contigious address space from start to end + */ + if ((def->nranges == 1) && + (def->ranges[0].start) && + (def->ranges[0].end)) { + IDHCPServer *dhcpServer = NULL; + + data->vboxObj->vtbl->FindDHCPServerByNetworkName(data->vboxObj, + networkNameUtf16, + &dhcpServer); + if (!dhcpServer) { + /* create a dhcp server */ + data->vboxObj->vtbl->CreateDHCPServer(data->vboxObj, + networkNameUtf16, + &dhcpServer); + DEBUG0("couldn't find dhcp server so creating one"); + } + if (dhcpServer) { + PRUnichar *ipAddressUtf16 = NULL; + PRUnichar *networkMaskUtf16 = NULL; + PRUnichar *fromIPAddressUtf16 = NULL; + PRUnichar *toIPAddressUtf16 = NULL; + + + data->pFuncs->pfnUtf8ToUtf16(def->ipAddress, &ipAddressUtf16); + data->pFuncs->pfnUtf8ToUtf16(def->netmask, &networkMaskUtf16); + data->pFuncs->pfnUtf8ToUtf16(def->ranges[0].start, &fromIPAddressUtf16); + data->pFuncs->pfnUtf8ToUtf16(def->ranges[0].end, &toIPAddressUtf16); + + dhcpServer->vtbl->SetEnabled(dhcpServer, PR_FALSE); + + dhcpServer->vtbl->SetConfiguration(dhcpServer, + ipAddressUtf16, + networkMaskUtf16, + fromIPAddressUtf16, + toIPAddressUtf16); + + data->pFuncs->pfnUtf16Free(ipAddressUtf16); + data->pFuncs->pfnUtf16Free(networkMaskUtf16); + data->pFuncs->pfnUtf16Free(fromIPAddressUtf16); + data->pFuncs->pfnUtf16Free(toIPAddressUtf16); + dhcpServer->vtbl->nsisupports.Release((nsISupports *) dhcpServer); + } + } + + ret = virGetNetwork(conn, def->name, uuid); + + DEBUG("Real Network UUID: " + "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", + (unsigned)vboxnet0IID->m0, (unsigned)vboxnet0IID->m1, + (unsigned)vboxnet0IID->m2, (unsigned)vboxnet0IID->m3[0], + (unsigned)vboxnet0IID->m3[1], (unsigned)vboxnet0IID->m3[2], + (unsigned)vboxnet0IID->m3[3], (unsigned)vboxnet0IID->m3[4], + (unsigned)vboxnet0IID->m3[5], (unsigned)vboxnet0IID->m3[6], + (unsigned)vboxnet0IID->m3[7]); + + data->pFuncs->pfnComUnallocMem(vboxnet0IID); + data->pFuncs->pfnUtf16Free(networkNameUtf16); + } + + networkInterface->vtbl->nsisupports.Release((nsISupports *) networkInterface); + } + + data->pFuncs->pfnUtf16Free(networkInterfaceNameUtf16); + host->vtbl->nsisupports.Release((nsISupports *) host); + } + } + } + +cleanup: + VIR_FREE(iid); + VIR_FREE(networkNameUtf8); + virNetworkDefFree(def); + return ret; +} + +static int vboxNetworkUndefine(virNetworkPtr network) { + vboxGlobalData *data = network->conn->privateData; + char *networkNameUtf8 = NULL; + int ret = -1; + + /* Current limitation of the function for VirtualBox 2.2.* is + * that you can't delete the default hostonly adaptor namely: + * vboxnet0 and thus all this functions does is remove the + * dhcp server configuration, but the network can still be used + * by giving the machine static IP and also it will still + * show up in the net-list in virsh + */ + if (VIR_ALLOC_N(networkNameUtf8, sizeof("HostInterfaceNetworking-") + + sizeof(network->name) + 1) < 0) { + virReportOOMError(network->conn); + goto cleanup; + } + + strcpy (networkNameUtf8, "HostInterfaceNetworking-"); + strcat (networkNameUtf8, network->name); + + if (data->vboxObj) { + IHost *host = NULL; + + data->vboxObj->vtbl->GetHost(data->vboxObj, &host); + if (host) { + PRUnichar *networkInterfaceNameUtf16 = NULL; + IHostNetworkInterface *networkInterface = NULL; + + data->pFuncs->pfnUtf8ToUtf16(network->name, &networkInterfaceNameUtf16); + + host->vtbl->FindHostNetworkInterfaceByName(host, networkInterfaceNameUtf16, &networkInterface); + + if (networkInterface) { + PRUint32 interfaceType = 0; + + networkInterface->vtbl->GetInterfaceType(networkInterface, &interfaceType); + + if (interfaceType == HostNetworkInterfaceType_HostOnly) { + PRUnichar *networkNameUtf16 = NULL; + IDHCPServer *dhcpServer = NULL; + + data->pFuncs->pfnUtf8ToUtf16(networkNameUtf8 , &networkNameUtf16); + + data->vboxObj->vtbl->FindDHCPServerByNetworkName(data->vboxObj, + networkNameUtf16, + &dhcpServer); + if (dhcpServer) { + data->vboxObj->vtbl->RemoveDHCPServer(data->vboxObj, dhcpServer); + dhcpServer->vtbl->nsisupports.Release((nsISupports *) dhcpServer); + } + + data->pFuncs->pfnUtf16Free(networkNameUtf16); + } + + networkInterface->vtbl->nsisupports.Release((nsISupports *) networkInterface); + } + + data->pFuncs->pfnUtf16Free(networkInterfaceNameUtf16); + host->vtbl->nsisupports.Release((nsISupports *) host); + } + } + + ret = 0; + +cleanup: + VIR_FREE(networkNameUtf8); + return ret; +} + +static int vboxNetworkCreate(virNetworkPtr network) { + vboxGlobalData *data = network->conn->privateData; + char *networkNameUtf8 = NULL; + int ret = -1; + + /* Current limitation of the function for VirtualBox 2.2.* is + * that the default hostonly network "vboxnet0" is always active + * and thus all this functions does is start the dhcp server, + * but the network can still be used without starting the dhcp + * server by giving the machine static IP + */ + if (VIR_ALLOC_N(networkNameUtf8, sizeof("HostInterfaceNetworking-") + + sizeof(network->name) + 1) < 0) { + virReportOOMError(network->conn); + goto cleanup; + } + + strcpy (networkNameUtf8, "HostInterfaceNetworking-"); + strcat (networkNameUtf8, network->name); + + if (data->vboxObj) { + IHost *host = NULL; + + data->vboxObj->vtbl->GetHost(data->vboxObj, &host); + if (host) { + PRUnichar *networkInterfaceNameUtf16 = NULL; + IHostNetworkInterface *networkInterface = NULL; + + data->pFuncs->pfnUtf8ToUtf16(network->name, &networkInterfaceNameUtf16); + + host->vtbl->FindHostNetworkInterfaceByName(host, networkInterfaceNameUtf16, &networkInterface); + + if (networkInterface) { + PRUint32 interfaceType = 0; + + networkInterface->vtbl->GetInterfaceType(networkInterface, &interfaceType); + + if (interfaceType == HostNetworkInterfaceType_HostOnly) { + PRUnichar *networkNameUtf16 = NULL; + IDHCPServer *dhcpServer = NULL; + + + data->pFuncs->pfnUtf8ToUtf16(networkNameUtf8 , &networkNameUtf16); + + data->vboxObj->vtbl->FindDHCPServerByNetworkName(data->vboxObj, + networkNameUtf16, + &dhcpServer); + if (dhcpServer) { + PRUnichar *trunkTypeUtf16 = NULL; + + dhcpServer->vtbl->SetEnabled(dhcpServer, PR_TRUE); + + data->pFuncs->pfnUtf8ToUtf16("netflt", &trunkTypeUtf16); + + dhcpServer->vtbl->Start(dhcpServer, + networkNameUtf16, + networkInterfaceNameUtf16, + trunkTypeUtf16); + + data->pFuncs->pfnUtf16Free(trunkTypeUtf16); + dhcpServer->vtbl->nsisupports.Release((nsISupports *) dhcpServer); + } + + data->pFuncs->pfnUtf16Free(networkNameUtf16); + } + + networkInterface->vtbl->nsisupports.Release((nsISupports *) networkInterface); + } + + data->pFuncs->pfnUtf16Free(networkInterfaceNameUtf16); + host->vtbl->nsisupports.Release((nsISupports *) host); + } + } + + ret = 0; + +cleanup: + VIR_FREE(networkNameUtf8); + return ret; +} + +static int vboxNetworkDestroy(virNetworkPtr network) { + vboxGlobalData *data = network->conn->privateData; + char *networkNameUtf8 = NULL; + int ret = -1; + + /* Current limitation of the function for VirtualBox 2.2.* is + * that the default hostonly network "vboxnet0" is always active + * and thus all this functions does is stop the dhcp server, + * but the network can still be used without the dhcp server + * by giving the machine static IP + */ + if (VIR_ALLOC_N(networkNameUtf8, sizeof("HostInterfaceNetworking-") + + sizeof(network->name) + 1) < 0) { + virReportOOMError(network->conn); + goto cleanup; + } + + strcpy (networkNameUtf8, "HostInterfaceNetworking-"); + strcat (networkNameUtf8, network->name); + + if (data->vboxObj) { + IHost *host = NULL; + + data->vboxObj->vtbl->GetHost(data->vboxObj, &host); + if (host) { + PRUnichar *networkInterfaceNameUtf16 = NULL; + IHostNetworkInterface *networkInterface = NULL; + + data->pFuncs->pfnUtf8ToUtf16(network->name, &networkInterfaceNameUtf16); + + host->vtbl->FindHostNetworkInterfaceByName(host, networkInterfaceNameUtf16, &networkInterface); + + if (networkInterface) { + PRUint32 interfaceType = 0; + + networkInterface->vtbl->GetInterfaceType(networkInterface, &interfaceType); + + if (interfaceType == HostNetworkInterfaceType_HostOnly) { + PRUnichar *networkNameUtf16 = NULL; + IDHCPServer *dhcpServer = NULL; + + + data->pFuncs->pfnUtf8ToUtf16(networkNameUtf8 , &networkNameUtf16); + + data->vboxObj->vtbl->FindDHCPServerByNetworkName(data->vboxObj, + networkNameUtf16, + &dhcpServer); + if (dhcpServer) { + + dhcpServer->vtbl->SetEnabled(dhcpServer, PR_FALSE); + + dhcpServer->vtbl->Stop(dhcpServer); + + dhcpServer->vtbl->nsisupports.Release((nsISupports *) dhcpServer); + } + + data->pFuncs->pfnUtf16Free(networkNameUtf16); + } + + networkInterface->vtbl->nsisupports.Release((nsISupports *) networkInterface); + } + + data->pFuncs->pfnUtf16Free(networkInterfaceNameUtf16); + host->vtbl->nsisupports.Release((nsISupports *) host); + } + } + + ret = 0; + +cleanup: + VIR_FREE(networkNameUtf8); + return ret; +} + +static char *vboxNetworkDumpXML(virNetworkPtr network, int flags ATTRIBUTE_UNUSED) { + vboxGlobalData *data = network->conn->privateData; + virNetworkDefPtr def = NULL; + char *ret = NULL; + char *networkNameUtf8 = NULL; + + if (VIR_ALLOC(def) < 0) { + virReportOOMError(network->conn); + goto cleanup; + } + + if (VIR_ALLOC_N(networkNameUtf8, sizeof("HostInterfaceNetworking-") + + sizeof(network->name) + 1) < 0) { + virReportOOMError(network->conn); + goto cleanup; + } + + strcpy (networkNameUtf8, "HostInterfaceNetworking-"); + strcat (networkNameUtf8, network->name); + + if (data->vboxObj) { + IHost *host = NULL; + + data->vboxObj->vtbl->GetHost(data->vboxObj, &host); + if (host) { + PRUnichar *networkInterfaceNameUtf16 = NULL; + IHostNetworkInterface *networkInterface = NULL; + + data->pFuncs->pfnUtf8ToUtf16(network->name, &networkInterfaceNameUtf16); + + host->vtbl->FindHostNetworkInterfaceByName(host, networkInterfaceNameUtf16, &networkInterface); + + if (networkInterface) { + PRUint32 interfaceType = 0; + + networkInterface->vtbl->GetInterfaceType(networkInterface, &interfaceType); + + if (interfaceType == HostNetworkInterfaceType_HostOnly) { + nsID *vboxnet0IID = NULL; + PRUnichar *networkNameUtf16 = NULL; + IDHCPServer *dhcpServer = NULL; + + data->pFuncs->pfnUtf8ToUtf16(networkNameUtf8 , &networkNameUtf16); + + networkInterface->vtbl->GetId(networkInterface, &vboxnet0IID); + + nsIDtoChar(def->uuid, vboxnet0IID); + + def->name = strdup(network->name); + def->forwardType = VIR_NETWORK_FORWARD_HOSTONLY; + + data->vboxObj->vtbl->FindDHCPServerByNetworkName(data->vboxObj, + networkNameUtf16, + &dhcpServer); + if (dhcpServer) { + def->nranges = 1; + if (VIR_ALLOC_N(def->ranges, def->nranges) >=0 ) { + PRUnichar *ipAddressUtf16 = NULL; + PRUnichar *networkMaskUtf16 = NULL; + PRUnichar *fromIPAddressUtf16 = NULL; + PRUnichar *toIPAddressUtf16 = NULL; + + dhcpServer->vtbl->GetIPAddress(dhcpServer, &ipAddressUtf16); + dhcpServer->vtbl->GetNetworkMask(dhcpServer, &networkMaskUtf16); + dhcpServer->vtbl->GetLowerIP(dhcpServer, &fromIPAddressUtf16); + dhcpServer->vtbl->GetUpperIP(dhcpServer, &toIPAddressUtf16); + /* Currently virtualbox supports only one dhcp server per network + * with contigious address space from start to end + */ + data->pFuncs->pfnUtf16ToUtf8(ipAddressUtf16, &def->ipAddress); + data->pFuncs->pfnUtf16ToUtf8(networkMaskUtf16, &def->netmask); + data->pFuncs->pfnUtf16ToUtf8(fromIPAddressUtf16, &def->ranges[0].start); + data->pFuncs->pfnUtf16ToUtf8(toIPAddressUtf16, &def->ranges[0].end); + + data->pFuncs->pfnUtf16Free(ipAddressUtf16); + data->pFuncs->pfnUtf16Free(networkMaskUtf16); + data->pFuncs->pfnUtf16Free(fromIPAddressUtf16); + data->pFuncs->pfnUtf16Free(toIPAddressUtf16); + } else { + def->nranges = 0; + } + + def->nhosts = 1; + if (VIR_ALLOC_N(def->hosts, def->nhosts) >=0 ) { + PRUnichar *macAddressUtf16 = NULL; + PRUnichar *ipAddressUtf16 = NULL; + + networkInterface->vtbl->GetHardwareAddress(networkInterface, &macAddressUtf16); + networkInterface->vtbl->GetIPAddress(networkInterface, &ipAddressUtf16); + + data->pFuncs->pfnUtf16ToUtf8(macAddressUtf16, &def->hosts[0].mac); + def->hosts[0].name = strdup(network->name); + data->pFuncs->pfnUtf16ToUtf8(ipAddressUtf16, &def->hosts[0].ip); + + data->pFuncs->pfnUtf16Free(macAddressUtf16); + data->pFuncs->pfnUtf16Free(ipAddressUtf16); + } else { + def->nranges = 0; + } + + dhcpServer->vtbl->nsisupports.Release((nsISupports *) dhcpServer); + } else { + PRUnichar *networkMaskUtf16 = NULL; + PRUnichar *ipAddressUtf16 = NULL; + + networkInterface->vtbl->GetNetworkMask(networkInterface, &networkMaskUtf16); + networkInterface->vtbl->GetIPAddress(networkInterface, &ipAddressUtf16); + + data->pFuncs->pfnUtf16ToUtf8(networkMaskUtf16, &def->netmask); + data->pFuncs->pfnUtf16ToUtf8(ipAddressUtf16, &def->ipAddress); + + data->pFuncs->pfnUtf16Free(networkMaskUtf16); + data->pFuncs->pfnUtf16Free(ipAddressUtf16); + } + + + DEBUG("Network UUID: " + "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", + (unsigned)vboxnet0IID->m0, (unsigned)vboxnet0IID->m1, + (unsigned)vboxnet0IID->m2, (unsigned)vboxnet0IID->m3[0], + (unsigned)vboxnet0IID->m3[1], (unsigned)vboxnet0IID->m3[2], + (unsigned)vboxnet0IID->m3[3], (unsigned)vboxnet0IID->m3[4], + (unsigned)vboxnet0IID->m3[5], (unsigned)vboxnet0IID->m3[6], + (unsigned)vboxnet0IID->m3[7]); + + data->pFuncs->pfnComUnallocMem(vboxnet0IID); + data->pFuncs->pfnUtf16Free(networkNameUtf16); + } + + networkInterface->vtbl->nsisupports.Release((nsISupports *) networkInterface); + } + + data->pFuncs->pfnUtf16Free(networkInterfaceNameUtf16); + host->vtbl->nsisupports.Release((nsISupports *) host); + } + } + + ret = virNetworkDefFormat(network->conn, def); + +cleanup: + VIR_FREE(networkNameUtf8); + return ret; +} + + +/** + * Function Tables + */ + virDriver NAME(Driver) = { VIR_DRV_VBOX, "VBOX", @@ -3697,3 +4654,24 @@ virDriver NAME(Driver) = { .domainMigratePrepare2 = NULL, .domainMigrateFinish2 = NULL, }; + +virNetworkDriver NAME(NetworkDriver) = { + "VBOX", + .open = vboxNetworkOpen, + .close = vboxNetworkClose, + .numOfNetworks = vboxNumOfNetworks, + .listNetworks = vboxListNetworks, + .numOfDefinedNetworks = NULL, + .listDefinedNetworks = NULL, + .networkLookupByUUID = vboxNetworkLookupByUUID, + .networkLookupByName = vboxNetworkLookupByName, + .networkCreateXML = vboxNetworkCreateXML, + .networkDefineXML = vboxNetworkDefineXML, + .networkUndefine = vboxNetworkUndefine, + .networkCreate = vboxNetworkCreate, + .networkDestroy = vboxNetworkDestroy, + .networkDumpXML = vboxNetworkDumpXML, + .networkGetBridgeName = NULL, + .networkGetAutostart = NULL, + .networkSetAutostart = NULL +};
-- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list