mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-21 10:52:22 +00:00
list: Use virConnectListAllInterfaces in virsh
tools/virsh-interface.c: * vshInterfaceSorter to sort interfaces by name * vshInterfaceListFree to free the interface objects list. * vshInterfaceListCollect to collect the interface objects, trying to use new API first, fall back to older APIs if it's not supported.
This commit is contained in:
parent
a3cf061c82
commit
3c2e6472d8
@ -131,6 +131,176 @@ cleanup:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
vshInterfaceSorter(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
virInterfacePtr *ia = (virInterfacePtr *) a;
|
||||||
|
virInterfacePtr *ib = (virInterfacePtr *) b;
|
||||||
|
|
||||||
|
if (*ia && !*ib)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (!*ia)
|
||||||
|
return *ib != NULL;
|
||||||
|
|
||||||
|
return vshStrcasecmp(virInterfaceGetName(*ia),
|
||||||
|
virInterfaceGetName(*ib));
|
||||||
|
}
|
||||||
|
|
||||||
|
struct vshInterfaceList {
|
||||||
|
virInterfacePtr *ifaces;
|
||||||
|
size_t nifaces;
|
||||||
|
};
|
||||||
|
typedef struct vshInterfaceList *vshInterfaceListPtr;
|
||||||
|
|
||||||
|
static void
|
||||||
|
vshInterfaceListFree(vshInterfaceListPtr list)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (list && list->nifaces) {
|
||||||
|
for (i = 0; i < list->nifaces; i++) {
|
||||||
|
if (list->ifaces[i])
|
||||||
|
virInterfaceFree(list->ifaces[i]);
|
||||||
|
}
|
||||||
|
VIR_FREE(list->ifaces);
|
||||||
|
}
|
||||||
|
VIR_FREE(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
static vshInterfaceListPtr
|
||||||
|
vshInterfaceListCollect(vshControl *ctl,
|
||||||
|
unsigned int flags)
|
||||||
|
{
|
||||||
|
vshInterfaceListPtr list = vshMalloc(ctl, sizeof(*list));
|
||||||
|
int i;
|
||||||
|
int ret;
|
||||||
|
char **activeNames = NULL;
|
||||||
|
char **inactiveNames = NULL;
|
||||||
|
virInterfacePtr iface;
|
||||||
|
bool success = false;
|
||||||
|
size_t deleted = 0;
|
||||||
|
int nActiveIfaces = 0;
|
||||||
|
int nInactiveIfaces = 0;
|
||||||
|
int nAllIfaces = 0;
|
||||||
|
|
||||||
|
/* try the list with flags support (0.10.2 and later) */
|
||||||
|
if ((ret = virConnectListAllInterfaces(ctl->conn,
|
||||||
|
&list->ifaces,
|
||||||
|
flags)) >= 0) {
|
||||||
|
list->nifaces = ret;
|
||||||
|
goto finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if the command is actually supported */
|
||||||
|
if (last_error && last_error->code == VIR_ERR_NO_SUPPORT)
|
||||||
|
goto fallback;
|
||||||
|
|
||||||
|
/* there was an error during the first or second call */
|
||||||
|
vshError(ctl, "%s", _("Failed to list interfaces"));
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
|
||||||
|
fallback:
|
||||||
|
/* fall back to old method (0.10.1 and older) */
|
||||||
|
vshResetLibvirtError();
|
||||||
|
|
||||||
|
if (flags & VIR_CONNECT_LIST_INTERFACES_ACTIVE) {
|
||||||
|
nActiveIfaces = virConnectNumOfInterfaces(ctl->conn);
|
||||||
|
if (nActiveIfaces < 0) {
|
||||||
|
vshError(ctl, "%s", _("Failed to list active interfaces"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
if (nActiveIfaces) {
|
||||||
|
activeNames = vshMalloc(ctl, sizeof(char *) * nActiveIfaces);
|
||||||
|
|
||||||
|
if ((nActiveIfaces = virConnectListInterfaces(ctl->conn, activeNames,
|
||||||
|
nActiveIfaces)) < 0) {
|
||||||
|
vshError(ctl, "%s", _("Failed to list active interfaces"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & VIR_CONNECT_LIST_INTERFACES_INACTIVE) {
|
||||||
|
nInactiveIfaces = virConnectNumOfDefinedInterfaces(ctl->conn);
|
||||||
|
if (nInactiveIfaces < 0) {
|
||||||
|
vshError(ctl, "%s", _("Failed to list inactive interfaces"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
if (nInactiveIfaces) {
|
||||||
|
inactiveNames = vshMalloc(ctl, sizeof(char *) * nInactiveIfaces);
|
||||||
|
|
||||||
|
if ((nInactiveIfaces =
|
||||||
|
virConnectListDefinedInterfaces(ctl->conn, inactiveNames,
|
||||||
|
nInactiveIfaces)) < 0) {
|
||||||
|
vshError(ctl, "%s", _("Failed to list inactive interfaces"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nAllIfaces = nActiveIfaces + nInactiveIfaces;
|
||||||
|
if (nAllIfaces == 0) {
|
||||||
|
VIR_FREE(activeNames);
|
||||||
|
VIR_FREE(inactiveNames);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
list->ifaces = vshMalloc(ctl, sizeof(virInterfacePtr) * (nAllIfaces));
|
||||||
|
list->nifaces = 0;
|
||||||
|
|
||||||
|
/* get active interfaces */
|
||||||
|
for (i = 0; i < nActiveIfaces; i++) {
|
||||||
|
if (!(iface = virInterfaceLookupByName(ctl->conn, activeNames[i]))) {
|
||||||
|
vshResetLibvirtError();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
list->ifaces[list->nifaces++] = iface;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get inactive interfaces */
|
||||||
|
for (i = 0; i < nInactiveIfaces; i++) {
|
||||||
|
if (!(iface = virInterfaceLookupByName(ctl->conn, inactiveNames[i]))) {
|
||||||
|
vshResetLibvirtError();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
list->ifaces[list->nifaces++] = iface;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* truncate interfaces that weren't found */
|
||||||
|
deleted = nAllIfaces - list->nifaces;
|
||||||
|
|
||||||
|
finished:
|
||||||
|
/* sort the list */
|
||||||
|
if (list->ifaces && list->nifaces)
|
||||||
|
qsort(list->ifaces, list->nifaces,
|
||||||
|
sizeof(*list->ifaces), vshInterfaceSorter);
|
||||||
|
|
||||||
|
/* truncate the list if filter simulation deleted entries */
|
||||||
|
if (deleted)
|
||||||
|
VIR_SHRINK_N(list->ifaces, list->nifaces, deleted);
|
||||||
|
|
||||||
|
success = true;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
for (i = 0; i < nActiveIfaces; i++)
|
||||||
|
VIR_FREE(activeNames[i]);
|
||||||
|
|
||||||
|
for (i = 0; i < nInactiveIfaces; i++)
|
||||||
|
VIR_FREE(inactiveNames[i]);
|
||||||
|
|
||||||
|
VIR_FREE(activeNames);
|
||||||
|
VIR_FREE(inactiveNames);
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
vshInterfaceListFree(list);
|
||||||
|
list = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* "iface-list" command
|
* "iface-list" command
|
||||||
*/
|
*/
|
||||||
@ -145,99 +315,40 @@ static const vshCmdOptDef opts_interface_list[] = {
|
|||||||
{"all", VSH_OT_BOOL, 0, N_("list inactive & active interfaces")},
|
{"all", VSH_OT_BOOL, 0, N_("list inactive & active interfaces")},
|
||||||
{NULL, 0, 0, NULL}
|
{NULL, 0, 0, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
cmdInterfaceList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
|
cmdInterfaceList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
|
||||||
{
|
{
|
||||||
bool inactive = vshCommandOptBool(cmd, "inactive");
|
bool inactive = vshCommandOptBool(cmd, "inactive");
|
||||||
bool all = vshCommandOptBool(cmd, "all");
|
bool all = vshCommandOptBool(cmd, "all");
|
||||||
bool active = !inactive || all;
|
unsigned int flags = VIR_CONNECT_LIST_INTERFACES_ACTIVE;
|
||||||
int maxactive = 0, maxinactive = 0, i;
|
vshInterfaceListPtr list = NULL;
|
||||||
char **activeNames = NULL, **inactiveNames = NULL;
|
int i;
|
||||||
inactive |= all;
|
|
||||||
|
|
||||||
if (active) {
|
if (inactive)
|
||||||
maxactive = virConnectNumOfInterfaces(ctl->conn);
|
flags = VIR_CONNECT_LIST_INTERFACES_INACTIVE;
|
||||||
if (maxactive < 0) {
|
if (all)
|
||||||
vshError(ctl, "%s", _("Failed to list active interfaces"));
|
flags = VIR_CONNECT_LIST_INTERFACES_INACTIVE |
|
||||||
return false;
|
VIR_CONNECT_LIST_INTERFACES_ACTIVE;
|
||||||
}
|
|
||||||
if (maxactive) {
|
|
||||||
activeNames = vshMalloc(ctl, sizeof(char *) * maxactive);
|
|
||||||
|
|
||||||
if ((maxactive = virConnectListInterfaces(ctl->conn, activeNames,
|
if (!(list = vshInterfaceListCollect(ctl, flags)))
|
||||||
maxactive)) < 0) {
|
return false;
|
||||||
vshError(ctl, "%s", _("Failed to list active interfaces"));
|
|
||||||
VIR_FREE(activeNames);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
qsort(&activeNames[0], maxactive, sizeof(char *), vshNameSorter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (inactive) {
|
|
||||||
maxinactive = virConnectNumOfDefinedInterfaces(ctl->conn);
|
|
||||||
if (maxinactive < 0) {
|
|
||||||
vshError(ctl, "%s", _("Failed to list inactive interfaces"));
|
|
||||||
VIR_FREE(activeNames);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (maxinactive) {
|
|
||||||
inactiveNames = vshMalloc(ctl, sizeof(char *) * maxinactive);
|
|
||||||
|
|
||||||
if ((maxinactive =
|
|
||||||
virConnectListDefinedInterfaces(ctl->conn, inactiveNames,
|
|
||||||
maxinactive)) < 0) {
|
|
||||||
vshError(ctl, "%s", _("Failed to list inactive interfaces"));
|
|
||||||
VIR_FREE(activeNames);
|
|
||||||
VIR_FREE(inactiveNames);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
qsort(&inactiveNames[0], maxinactive, sizeof(char*), vshNameSorter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
vshPrintExtra(ctl, "%-20s %-10s %s\n", _("Name"), _("State"),
|
vshPrintExtra(ctl, "%-20s %-10s %s\n", _("Name"), _("State"),
|
||||||
_("MAC Address"));
|
_("MAC Address"));
|
||||||
vshPrintExtra(ctl, "--------------------------------------------\n");
|
vshPrintExtra(ctl, "--------------------------------------------\n");
|
||||||
|
|
||||||
for (i = 0; i < maxactive; i++) {
|
for (i = 0; i < list->nifaces; i++) {
|
||||||
virInterfacePtr iface =
|
virInterfacePtr iface = list->ifaces[i];
|
||||||
virInterfaceLookupByName(ctl->conn, activeNames[i]);
|
|
||||||
|
|
||||||
/* this kind of work with interfaces is not atomic */
|
|
||||||
if (!iface) {
|
|
||||||
VIR_FREE(activeNames[i]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
vshPrint(ctl, "%-20s %-10s %s\n",
|
vshPrint(ctl, "%-20s %-10s %s\n",
|
||||||
virInterfaceGetName(iface),
|
virInterfaceGetName(iface),
|
||||||
_("active"),
|
virInterfaceIsActive(iface) ? _("active") : _("inactive"),
|
||||||
virInterfaceGetMACString(iface));
|
virInterfaceGetMACString(iface));
|
||||||
virInterfaceFree(iface);
|
|
||||||
VIR_FREE(activeNames[i]);
|
|
||||||
}
|
}
|
||||||
for (i = 0; i < maxinactive; i++) {
|
|
||||||
virInterfacePtr iface =
|
|
||||||
virInterfaceLookupByName(ctl->conn, inactiveNames[i]);
|
|
||||||
|
|
||||||
/* this kind of work with interfaces is not atomic */
|
vshInterfaceListFree(list);
|
||||||
if (!iface) {
|
|
||||||
VIR_FREE(inactiveNames[i]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
vshPrint(ctl, "%-20s %-10s %s\n",
|
|
||||||
virInterfaceGetName(iface),
|
|
||||||
_("inactive"),
|
|
||||||
virInterfaceGetMACString(iface));
|
|
||||||
virInterfaceFree(iface);
|
|
||||||
VIR_FREE(inactiveNames[i]);
|
|
||||||
}
|
|
||||||
VIR_FREE(activeNames);
|
|
||||||
VIR_FREE(inactiveNames);
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user