diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c index 50f7eed127..9d0da6827d 100644 --- a/src/libxl/libxl_domain.c +++ b/src/libxl/libxl_domain.c @@ -762,6 +762,18 @@ libxlDomainCleanup(libxlDriverPrivatePtr driver, } } + if ((vm->def->nnets)) { + size_t i; + + for (i = 0; i < vm->def->nnets; i++) { + virDomainNetDefPtr net = vm->def->nets[i]; + + if (net->ifname && + STRPREFIX(net->ifname, LIBXL_GENERATED_PREFIX_XEN)) + VIR_FREE(net->ifname); + } + } + if (virAsprintf(&file, "%s/%s.xml", cfg->stateDir, vm->def->name) > 0) { if (unlink(file) < 0 && errno != ENOENT && errno != ENOTDIR) VIR_DEBUG("Failed to remove domain XML for %s", vm->def->name); @@ -929,6 +941,32 @@ libxlConsoleCallback(libxl_ctx *ctx, libxl_event *ev, void *for_callback) libxl_event_free(ctx, ev); } +/* + * Create interface names for the network devices in parameter def. + * Names are created with the pattern 'vif.'. + * devid is extracted from the network devices in the d_config + * parameter. User-provided interface names are skipped. + */ +static void +libxlDomainCreateIfaceNames(virDomainDefPtr def, libxl_domain_config *d_config) +{ + size_t i; + + for (i = 0; i < def->nnets && i < d_config->num_nics; i++) { + virDomainNetDefPtr net = def->nets[i]; + libxl_device_nic *x_nic = &d_config->nics[i]; + const char *suffix = + x_nic->nictype != LIBXL_NIC_TYPE_VIF ? "-emu" : ""; + + if (net->ifname) + continue; + + ignore_value(virAsprintf(&net->ifname, + LIBXL_GENERATED_PREFIX_XEN "%d.%d%s", + def->id, x_nic->devid, suffix)); + } +} + /* * Start a domain through libxenlight. @@ -1073,6 +1111,7 @@ libxlDomainStart(libxlDriverPrivatePtr driver, virDomainObjPtr vm, if (libxl_evenable_domain_death(cfg->ctx, vm->def->id, 0, &priv->deathW)) goto cleanup_dom; + libxlDomainCreateIfaceNames(vm->def, &d_config); if ((dom_xml = virDomainDefFormat(vm->def, cfg->caps, 0)) == NULL) goto cleanup_dom; diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 404016e6d3..29d65cd4c3 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -58,6 +58,7 @@ #include "virhostdev.h" #include "network/bridge_driver.h" #include "locking/domain_lock.h" +#include "virstats.h" #define VIR_FROM_THIS VIR_FROM_LIBXL @@ -4661,6 +4662,56 @@ libxlDomainIsUpdated(virDomainPtr dom) return ret; } +static int +libxlDomainInterfaceStats(virDomainPtr dom, + const char *path, + virDomainInterfaceStatsPtr stats) +{ + libxlDriverPrivatePtr driver = dom->conn->privateData; + virDomainObjPtr vm; + size_t i; + int ret = -1; + + if (!(vm = libxlDomObjFromDomain(dom))) + goto cleanup; + + if (virDomainInterfaceStatsEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + + if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_QUERY) < 0) + goto cleanup; + + if (!virDomainObjIsActive(vm)) { + virReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("domain is not running")); + goto endjob; + } + + /* Check the path is one of the domain's network interfaces. */ + for (i = 0; i < vm->def->nnets; i++) { + if (vm->def->nets[i]->ifname && + STREQ(vm->def->nets[i]->ifname, path)) { + ret = 0; + break; + } + } + + if (ret == 0) + ret = virNetInterfaceStats(path, stats); + else + virReportError(VIR_ERR_INVALID_ARG, + _("'%s' is not a known interface"), path); + + endjob: + if (!libxlDomainObjEndJob(driver, vm)) + vm = NULL; + + cleanup: + if (vm) + virObjectUnlock(vm); + return ret; +} + static int libxlDomainGetTotalCPUStats(libxlDriverPrivatePtr driver, virDomainObjPtr vm, @@ -5539,6 +5590,7 @@ static virHypervisorDriver libxlHypervisorDriver = { .domainGetJobStats = libxlDomainGetJobStats, /* 1.3.1 */ .domainMemoryStats = libxlDomainMemoryStats, /* 1.3.0 */ .domainGetCPUStats = libxlDomainGetCPUStats, /* 1.3.0 */ + .domainInterfaceStats = libxlDomainInterfaceStats, /* 1.3.2 */ .connectDomainEventRegister = libxlConnectDomainEventRegister, /* 0.9.0 */ .connectDomainEventDeregister = libxlConnectDomainEventDeregister, /* 0.9.0 */ .domainManagedSave = libxlDomainManagedSave, /* 0.9.2 */