mirror of
https://github.com/libvirt/libvirt.git
synced 2025-02-25 18:55:26 -06:00
virsh-completer: Provide completer for '--top' and '--base' for blockjobs
Complete with the indexed targets (e.g. vda[3]) based on existing indexes. Signed-off-by: Peter Krempa <pkrempa@redhat.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
parent
071bab399a
commit
c580c8db70
@ -32,6 +32,7 @@
|
|||||||
#include "virperf.h"
|
#include "virperf.h"
|
||||||
#include "virbitmap.h"
|
#include "virbitmap.h"
|
||||||
#include "virkeycode.h"
|
#include "virkeycode.h"
|
||||||
|
#include "virglibutil.h"
|
||||||
#include "virkeynametable_linux.h"
|
#include "virkeynametable_linux.h"
|
||||||
#include "virkeynametable_osx.h"
|
#include "virkeynametable_osx.h"
|
||||||
#include "virkeynametable_win32.h"
|
#include "virkeynametable_win32.h"
|
||||||
@ -256,6 +257,105 @@ virshDomainUndefineStorageDisksCompleter(vshControl *ctl,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static GSList *
|
||||||
|
virshDomainBlockjobBaseTopCompleteDisk(const char *target,
|
||||||
|
xmlXPathContext *ctxt)
|
||||||
|
{
|
||||||
|
g_autofree xmlNodePtr *indexlist = NULL;
|
||||||
|
int nindexlist = 0;
|
||||||
|
size_t i;
|
||||||
|
GSList *ret = NULL;
|
||||||
|
|
||||||
|
if ((nindexlist = virXPathNodeSet("./source|./backingStore",
|
||||||
|
ctxt, &indexlist)) < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ret = g_slist_prepend(ret, g_strdup(target));
|
||||||
|
|
||||||
|
for (i = 0; i < nindexlist; i++) {
|
||||||
|
g_autofree char *idx = virXMLPropString(indexlist[i], "index");
|
||||||
|
|
||||||
|
if (!idx)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ret = g_slist_prepend(ret, g_strdup_printf("%s[%s]", target, idx));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char **
|
||||||
|
virshDomainBlockjobBaseTopCompleter(vshControl *ctl,
|
||||||
|
const vshCmd *cmd,
|
||||||
|
unsigned int flags)
|
||||||
|
{
|
||||||
|
virshControl *priv = ctl->privData;
|
||||||
|
g_autoptr(xmlDoc) xmldoc = NULL;
|
||||||
|
g_autoptr(xmlXPathContext) ctxt = NULL;
|
||||||
|
g_autofree xmlNodePtr *disks = NULL;
|
||||||
|
int ndisks;
|
||||||
|
size_t i;
|
||||||
|
const char *path = NULL;
|
||||||
|
g_autoptr(virGSListString) list = NULL;
|
||||||
|
GSList *n;
|
||||||
|
GStrv ret = NULL;
|
||||||
|
size_t nelems;
|
||||||
|
|
||||||
|
virCheckFlags(0, NULL);
|
||||||
|
|
||||||
|
if (!priv->conn || virConnectIsAlive(priv->conn) <= 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (virshDomainGetXML(ctl, cmd, 0, &xmldoc, &ctxt) < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ignore_value(vshCommandOptStringQuiet(ctl, cmd, "path", &path));
|
||||||
|
|
||||||
|
if ((ndisks = virXPathNodeSet("./devices/disk", ctxt, &disks)) <= 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < ndisks; i++) {
|
||||||
|
g_autofree char *disktarget = NULL;
|
||||||
|
|
||||||
|
ctxt->node = disks[i];
|
||||||
|
disktarget = virXPathString("string(./target/@dev)", ctxt);
|
||||||
|
|
||||||
|
if (STREQ_NULLABLE(path, disktarget))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == ndisks)
|
||||||
|
path = NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < ndisks; i++) {
|
||||||
|
g_autofree char *disktarget = NULL;
|
||||||
|
GSList *tmplist;
|
||||||
|
|
||||||
|
ctxt->node = disks[i];
|
||||||
|
|
||||||
|
if (!(disktarget = virXPathString("string(./target/@dev)", ctxt)))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (path && STRNEQ(path, disktarget))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* note that ctxt->node moved */
|
||||||
|
if ((tmplist = virshDomainBlockjobBaseTopCompleteDisk(disktarget, ctxt)))
|
||||||
|
list = g_slist_concat(tmplist, list);
|
||||||
|
}
|
||||||
|
|
||||||
|
list = g_slist_reverse(list);
|
||||||
|
nelems = g_slist_length(list);
|
||||||
|
ret = g_new0(char *, nelems + 1);
|
||||||
|
i = 0;
|
||||||
|
|
||||||
|
for (n = list; n; n = n->next)
|
||||||
|
ret[i++] = g_strdup(n->data);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
char **
|
char **
|
||||||
virshDomainEventNameCompleter(vshControl *ctl G_GNUC_UNUSED,
|
virshDomainEventNameCompleter(vshControl *ctl G_GNUC_UNUSED,
|
||||||
const vshCmd *cmd G_GNUC_UNUSED,
|
const vshCmd *cmd G_GNUC_UNUSED,
|
||||||
|
@ -176,3 +176,8 @@ char **
|
|||||||
virshDomainUndefineStorageDisksCompleter(vshControl *ctl,
|
virshDomainUndefineStorageDisksCompleter(vshControl *ctl,
|
||||||
const vshCmd *cmd,
|
const vshCmd *cmd,
|
||||||
unsigned int completeflags);
|
unsigned int completeflags);
|
||||||
|
|
||||||
|
char **
|
||||||
|
virshDomainBlockjobBaseTopCompleter(vshControl *ctl,
|
||||||
|
const vshCmd *cmd,
|
||||||
|
unsigned int flags);
|
||||||
|
@ -1991,6 +1991,7 @@ static const vshCmdOptDef opts_blockcommit[] = {
|
|||||||
},
|
},
|
||||||
{.name = "base",
|
{.name = "base",
|
||||||
.type = VSH_OT_STRING,
|
.type = VSH_OT_STRING,
|
||||||
|
.completer = virshDomainBlockjobBaseTopCompleter,
|
||||||
.help = N_("path of base file to commit into (default bottom of chain)")
|
.help = N_("path of base file to commit into (default bottom of chain)")
|
||||||
},
|
},
|
||||||
{.name = "shallow",
|
{.name = "shallow",
|
||||||
@ -1999,6 +2000,7 @@ static const vshCmdOptDef opts_blockcommit[] = {
|
|||||||
},
|
},
|
||||||
{.name = "top",
|
{.name = "top",
|
||||||
.type = VSH_OT_STRING,
|
.type = VSH_OT_STRING,
|
||||||
|
.completer = virshDomainBlockjobBaseTopCompleter,
|
||||||
.help = N_("path of top file to commit from (default top of chain)")
|
.help = N_("path of top file to commit from (default top of chain)")
|
||||||
},
|
},
|
||||||
{.name = "active",
|
{.name = "active",
|
||||||
@ -2772,6 +2774,7 @@ static const vshCmdOptDef opts_blockpull[] = {
|
|||||||
},
|
},
|
||||||
{.name = "base",
|
{.name = "base",
|
||||||
.type = VSH_OT_STRING,
|
.type = VSH_OT_STRING,
|
||||||
|
.completer = virshDomainBlockjobBaseTopCompleter,
|
||||||
.help = N_("path of backing file in chain for a partial pull")
|
.help = N_("path of backing file in chain for a partial pull")
|
||||||
},
|
},
|
||||||
{.name = "wait",
|
{.name = "wait",
|
||||||
|
Loading…
Reference in New Issue
Block a user