mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 13:45:38 +00:00
cmdDomblkinfo: add --all to show all block devices info
This patch introduces --all to show all block devices info of guests like: virsh # domblkinfo w08 --all Target Capacity Allocation Physical --------------------------------------------------- hda 42949672960 9878110208 9878110208 vda 10737418240 10736439296 10737418240 Target Capacity Allocation Physical --------------------------------------------------- hda 40.000 GiB 9.200 GiB 9.200 GiB vda 10.000 GiB 9.999 GiB 10.000 GiB For inactive domains using networked storage, a "-" will be printed instead of the value since it's not possible to determine the value without the storage connection. Signed-off-by: Chen Hanxiao <chenhanxiao@gmail.com> Reviewed-by: John Ferlan <jferlan@redhat.com>
This commit is contained in:
parent
4afcaa8843
commit
62c3919328
@ -388,8 +388,7 @@ static const vshCmdInfo info_domblkinfo[] = {
|
|||||||
static const vshCmdOptDef opts_domblkinfo[] = {
|
static const vshCmdOptDef opts_domblkinfo[] = {
|
||||||
VIRSH_COMMON_OPT_DOMAIN_FULL(0),
|
VIRSH_COMMON_OPT_DOMAIN_FULL(0),
|
||||||
{.name = "device",
|
{.name = "device",
|
||||||
.type = VSH_OT_DATA,
|
.type = VSH_OT_STRING,
|
||||||
.flags = VSH_OFLAG_REQ,
|
|
||||||
.completer = virshDomainDiskTargetCompleter,
|
.completer = virshDomainDiskTargetCompleter,
|
||||||
.help = N_("block device")
|
.help = N_("block device")
|
||||||
},
|
},
|
||||||
@ -397,30 +396,66 @@ static const vshCmdOptDef opts_domblkinfo[] = {
|
|||||||
.type = VSH_OT_BOOL,
|
.type = VSH_OT_BOOL,
|
||||||
.help = N_("Human readable output")
|
.help = N_("Human readable output")
|
||||||
},
|
},
|
||||||
|
{.name = "all",
|
||||||
|
.type = VSH_OT_BOOL,
|
||||||
|
.help = N_("display all block devices info")
|
||||||
|
},
|
||||||
{.name = NULL}
|
{.name = NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cmdDomblkinfoPrint(vshControl *ctl,
|
cmdDomblkinfoPrint(vshControl *ctl,
|
||||||
const virDomainBlockInfo *info,
|
const virDomainBlockInfo *info,
|
||||||
bool human)
|
const char *device,
|
||||||
|
bool human, bool title)
|
||||||
{
|
{
|
||||||
if (!human) {
|
char *cap = NULL;
|
||||||
vshPrint(ctl, "%-15s %llu\n", _("Capacity:"), info->capacity);
|
char *alloc = NULL;
|
||||||
vshPrint(ctl, "%-15s %llu\n", _("Allocation:"), info->allocation);
|
char *phy = NULL;
|
||||||
vshPrint(ctl, "%-15s %llu\n", _("Physical:"), info->physical);
|
|
||||||
} else {
|
|
||||||
double val;
|
|
||||||
const char *unit;
|
|
||||||
|
|
||||||
val = vshPrettyCapacity(info->capacity, &unit);
|
if (title) {
|
||||||
vshPrint(ctl, "%-15s %-.3lf %s\n", _("Capacity:"), val, unit);
|
vshPrintExtra(ctl, "%-10s %-15s %-15s %-15s\n", _("Target"),
|
||||||
val = vshPrettyCapacity(info->allocation, &unit);
|
_("Capacity"), _("Allocation"), _("Physical"));
|
||||||
vshPrint(ctl, "%-15s %-.3lf %s\n", _("Allocation:"), val, unit);
|
vshPrintExtra(ctl, "-----------------------------"
|
||||||
val = vshPrettyCapacity(info->physical, &unit);
|
"------------------------\n");
|
||||||
vshPrint(ctl, "%-15s %-.3lf %s\n", _("Physical:"), val, unit);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (info->capacity == 0 && info->allocation == 0 && info->physical == 0) {
|
||||||
|
cap = vshStrdup(ctl, "-");
|
||||||
|
alloc = vshStrdup(ctl, "-");
|
||||||
|
phy = vshStrdup(ctl, "-");
|
||||||
|
} else if (!human) {
|
||||||
|
if (virAsprintf(&cap, "%llu", info->capacity) < 0 ||
|
||||||
|
virAsprintf(&alloc, "%llu", info->allocation) < 0 ||
|
||||||
|
virAsprintf(&phy, "%llu", info->physical) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
} else {
|
||||||
|
double val_cap, val_alloc, val_phy;
|
||||||
|
const char *unit_cap, *unit_alloc, *unit_phy;
|
||||||
|
|
||||||
|
val_cap = vshPrettyCapacity(info->capacity, &unit_cap);
|
||||||
|
val_alloc = vshPrettyCapacity(info->allocation, &unit_alloc);
|
||||||
|
val_phy = vshPrettyCapacity(info->physical, &unit_phy);
|
||||||
|
|
||||||
|
if (virAsprintf(&cap, "%.3lf %s", val_cap, unit_cap) < 0 ||
|
||||||
|
virAsprintf(&alloc, "%.3lf %s", val_alloc, unit_alloc) < 0 ||
|
||||||
|
virAsprintf(&phy, "%.3lf %s", val_phy, unit_phy) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (device) {
|
||||||
|
vshPrint(ctl, "%-10s %-15s %-15s %-15s\n", device, cap, alloc, phy);
|
||||||
|
} else {
|
||||||
|
vshPrint(ctl, "%-15s %s\n", _("Capacity:"), cap);
|
||||||
|
vshPrint(ctl, "%-15s %s\n", _("Allocation:"), alloc);
|
||||||
|
vshPrint(ctl, "%-15s %s\n", _("Physical:"), phy);
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
VIR_FREE(cap);
|
||||||
|
VIR_FREE(alloc);
|
||||||
|
VIR_FREE(phy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -431,25 +466,83 @@ cmdDomblkinfo(vshControl *ctl, const vshCmd *cmd)
|
|||||||
virDomainPtr dom;
|
virDomainPtr dom;
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
bool human = false;
|
bool human = false;
|
||||||
|
bool all = false;
|
||||||
const char *device = NULL;
|
const char *device = NULL;
|
||||||
|
xmlDocPtr xmldoc = NULL;
|
||||||
|
xmlXPathContextPtr ctxt = NULL;
|
||||||
|
int ndisks;
|
||||||
|
size_t i;
|
||||||
|
xmlNodePtr *disks = NULL;
|
||||||
|
char *target = NULL;
|
||||||
|
char *protocol = NULL;
|
||||||
|
|
||||||
if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
|
if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (vshCommandOptStringReq(ctl, cmd, "device", &device) < 0)
|
all = vshCommandOptBool(cmd, "all");
|
||||||
goto cleanup;
|
if (!all && vshCommandOptStringQuiet(ctl, cmd, "device", &device) <= 0) {
|
||||||
|
vshError(ctl, "command 'domblkinfo' requires <device> option");
|
||||||
if (virDomainGetBlockInfo(dom, device, &info, 0) < 0)
|
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
human = vshCommandOptBool(cmd, "human");
|
human = vshCommandOptBool(cmd, "human");
|
||||||
|
|
||||||
cmdDomblkinfoPrint(ctl, &info, human);
|
if (all) {
|
||||||
|
bool active = virDomainIsActive(dom) == 1;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (virshDomainGetXML(ctl, cmd, 0, &xmldoc, &ctxt) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
ndisks = virXPathNodeSet("./devices/disk", ctxt, &disks);
|
||||||
|
if (ndisks < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
/* print the title */
|
||||||
|
cmdDomblkinfoPrint(ctl, NULL, NULL, false, true);
|
||||||
|
|
||||||
|
for (i = 0; i < ndisks; i++) {
|
||||||
|
ctxt->node = disks[i];
|
||||||
|
protocol = virXPathString("string(./source/@protocol)", ctxt);
|
||||||
|
target = virXPathString("string(./target/@dev)", ctxt);
|
||||||
|
|
||||||
|
rc = virDomainGetBlockInfo(dom, target, &info, 0);
|
||||||
|
|
||||||
|
if (rc < 0) {
|
||||||
|
/* If protocol is present that's an indication of a networked
|
||||||
|
* storage device which cannot provide statistics, so generate
|
||||||
|
* 0 based data and get the next disk. */
|
||||||
|
if (protocol && !active &&
|
||||||
|
virGetLastErrorCode() == VIR_ERR_INTERNAL_ERROR &&
|
||||||
|
virGetLastErrorDomain() == VIR_FROM_STORAGE) {
|
||||||
|
memset(&info, 0, sizeof(info));
|
||||||
|
vshResetLibvirtError();
|
||||||
|
} else {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cmdDomblkinfoPrint(ctl, &info, target, human, false);
|
||||||
|
|
||||||
|
VIR_FREE(target);
|
||||||
|
VIR_FREE(protocol);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (virDomainGetBlockInfo(dom, device, &info, 0) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
cmdDomblkinfoPrint(ctl, &info, NULL, human, false);
|
||||||
|
}
|
||||||
|
|
||||||
ret = true;
|
ret = true;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
virshDomainFree(dom);
|
virshDomainFree(dom);
|
||||||
|
VIR_FREE(target);
|
||||||
|
VIR_FREE(protocol);
|
||||||
|
VIR_FREE(disks);
|
||||||
|
xmlXPathFreeContext(ctxt);
|
||||||
|
xmlFreeDoc(xmldoc);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -949,13 +949,16 @@ B<domstate> command says that a domain was paused due to I/O error.
|
|||||||
The B<domblkerror> command lists all block devices in error state and
|
The B<domblkerror> command lists all block devices in error state and
|
||||||
the error seen on each of them.
|
the error seen on each of them.
|
||||||
|
|
||||||
=item B<domblkinfo> I<domain> I<block-device> [I<--human>]
|
=item B<domblkinfo> I<domain> [I<block-device> I<--all>] [I<--human>]
|
||||||
|
|
||||||
Get block device size info for a domain. A I<block-device> corresponds
|
Get block device size info for a domain. A I<block-device> corresponds
|
||||||
to a unique target name (<target dev='name'/>) or source file (<source
|
to a unique target name (<target dev='name'/>) or source file (<source
|
||||||
file='name'/>) for one of the disk devices attached to I<domain> (see
|
file='name'/>) for one of the disk devices attached to I<domain> (see
|
||||||
also B<domblklist> for listing these names). If I<--human> is set, the
|
also B<domblklist> for listing these names). If I<--human> is set, the
|
||||||
output will have a human readable output.
|
output will have a human readable output.
|
||||||
|
If I<--all> is set, the output will be a table showing all block devices
|
||||||
|
size info associated with I<domain>.
|
||||||
|
The I<--all> option takes precedence of the others.
|
||||||
|
|
||||||
=item B<domblklist> I<domain> [I<--inactive>] [I<--details>]
|
=item B<domblklist> I<domain> [I<--inactive>] [I<--details>]
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user