diff --git a/src/libvirtSnmp.c b/src/libvirtSnmp.c index a9fa185..cd706a8 100644 --- a/src/libvirtSnmp.c +++ b/src/libvirtSnmp.c @@ -119,9 +119,15 @@ out: int libvirtSnmpLoadGuests(netsnmp_container *container) { - int ret = 0, i, numIds, numActiveDomains; + int ret = 0, i, numIds, + numActiveDomains = 0, + numInactiveDomains = 0, + numInactiveNames = 0, + numTotalDomains = 0; int *idList = NULL; + char **inactiveNameList = NULL; virDomainPtr domain = NULL; + virDomainPtr *domainList = NULL; virDomainInfo info; libvirtGuestTable_rowreq_ctx *row_ctx = NULL; const char *name = NULL; @@ -134,6 +140,14 @@ libvirtSnmpLoadGuests(netsnmp_container *container) goto out; } + numInactiveDomains = virConnectNumOfDefinedDomains(conn); + if (-1 == numInactiveDomains) { + ret = -1; + printf("Failed to get number of inactive domains\n"); + showError(conn); + goto out; + } + idList = malloc(sizeof(*idList) * numActiveDomains); if (NULL == idList) { @@ -153,9 +167,47 @@ libvirtSnmpLoadGuests(netsnmp_container *container) goto out; } - for (i = 0 ; i < numIds ; i++) { - unsigned char uuid[16]; + inactiveNameList = malloc(sizeof(*inactiveNameList) * numInactiveDomains); + + if (NULL == inactiveNameList) { + ret = -1; + printf("Could not allocate memory for list of inactive domains\n"); + goto out; + } + /* Set each entry to NULL so we can correctly free used + entries. */ + memset(inactiveNameList, 0, sizeof(*inactiveNameList) * numInactiveDomains); + + numInactiveNames = virConnectListDefinedDomains(conn, + inactiveNameList, + numInactiveDomains); + + if (-1 == numInactiveNames) { + ret = -1; + printf("Could not get list of inactive domains from hypervisor\n"); + showError(conn); + goto out; + } + + /* Populate a list of all domains, active and inactive. We do this + * because active domains are resolved by ID while inactive + * domains are resolved by name. */ + numTotalDomains = numActiveDomains + numInactiveNames; + domainList = malloc(sizeof(*domainList) * numTotalDomains); + + if (NULL == domainList) { + ret = -1; + printf("Could not allocate list of domain info structures\n"); + goto out; + } + + /* Before building the list, set each entry to NULL so we can + correctly free used entries. */ + memset(domainList, 0, sizeof(*domainList) * numTotalDomains); + + /* Resolve active domains by ID. */ + for (i = 0 ; i < numIds ; i++) { domain = virDomainLookupByID(conn, *(idList + i)); if (NULL == domain) { printf("Failed to lookup domain\n"); @@ -164,18 +216,39 @@ libvirtSnmpLoadGuests(netsnmp_container *container) goto out; } + domainList[i] = domain; + } + + /* Resolve inactive domains by name. */ + for (i = 0 ; i < numInactiveNames ; i++) { + domain = virDomainLookupByName(conn, *(inactiveNameList + i)); + if (NULL == domain) { + printf("Failed to lookup inactive domain\n"); + showError(conn); + ret = -1; + goto out; + } + + domainList[i + numActiveDomains] = domain; + } + + /* Build the list of guest table rows from the combined domain + * list */ + for (i = 0 ; i < numTotalDomains ; i++) { + unsigned char uuid[16]; + + domain = domainList[i]; + if (-1 == virDomainGetInfo(domain, &info)) { printf("Failed to get domain info\n"); showError(conn); - virDomainFree(domain); - ret = -1; + ret = -1; goto out; } /* create new row in the container */ row_ctx = libvirtGuestTable_allocate_rowreq_ctx(NULL); if (!row_ctx) { - virDomainFree(domain); snmp_log(LOG_ERR, "Error creating row"); ret = -1; goto out; @@ -183,7 +256,6 @@ libvirtSnmpLoadGuests(netsnmp_container *container) /* set the index of the row */ ret = virDomainGetUUID(domain, uuid); if (ret) { - virDomainFree(domain); snmp_log(LOG_ERR, "Cannot get UUID"); libvirtGuestTable_release_rowreq_ctx(row_ctx); ret = -1; @@ -191,7 +263,6 @@ libvirtSnmpLoadGuests(netsnmp_container *container) } if (MFD_SUCCESS != libvirtGuestTable_indexes_set(row_ctx, (char*) uuid, sizeof(uuid))) { - virDomainFree(domain); snmp_log(LOG_ERR, "Error setting row index"); libvirtGuestTable_release_rowreq_ctx(row_ctx); ret = -1; @@ -199,11 +270,11 @@ libvirtSnmpLoadGuests(netsnmp_container *container) } /* set the data */ - name = virDomainGetName(domain); + name = virDomainGetName(domainList[i]); if (name) row_ctx->data.libvirtGuestName = strdup(name); else - row_ctx->data.libvirtGuestName = strdup(""); + row_ctx->data.libvirtGuestName = strdup("empty"); if (!row_ctx->data.libvirtGuestName) { snmp_log(LOG_ERR, "Not enough memory for domain name '%s'", name); libvirtGuestTable_release_rowreq_ctx(row_ctx); @@ -220,7 +291,6 @@ libvirtSnmpLoadGuests(netsnmp_container *container) row_ctx->data.libvirtGuestCpuTime.low = info.cpuTime & 0xFFFFFFFF; row_ctx->data.libvirtGuestRowStatus = ROWSTATUS_ACTIVE; - virDomainFree(domain); ret = CONTAINER_INSERT(container, row_ctx); if (ret) { @@ -229,10 +299,19 @@ libvirtSnmpLoadGuests(netsnmp_container *container) ret = -1; goto out; } - } out: + for (i = 0 ; i < numTotalDomains ; i++ ) { + if (NULL != domainList[i]) + virDomainFree(domainList[i]); + } + + for (i = 0; i < numInactiveNames; i++) + free(inactiveNameList[i]); + + free(domainList); + free(inactiveNameList); free(idList); return ret; }