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[] = {
|
||||
VIRSH_COMMON_OPT_DOMAIN_FULL(0),
|
||||
{.name = "device",
|
||||
.type = VSH_OT_DATA,
|
||||
.flags = VSH_OFLAG_REQ,
|
||||
.type = VSH_OT_STRING,
|
||||
.completer = virshDomainDiskTargetCompleter,
|
||||
.help = N_("block device")
|
||||
},
|
||||
@ -397,30 +396,66 @@ static const vshCmdOptDef opts_domblkinfo[] = {
|
||||
.type = VSH_OT_BOOL,
|
||||
.help = N_("Human readable output")
|
||||
},
|
||||
{.name = "all",
|
||||
.type = VSH_OT_BOOL,
|
||||
.help = N_("display all block devices info")
|
||||
},
|
||||
{.name = NULL}
|
||||
};
|
||||
|
||||
static void
|
||||
cmdDomblkinfoPrint(vshControl *ctl,
|
||||
const virDomainBlockInfo *info,
|
||||
bool human)
|
||||
const char *device,
|
||||
bool human, bool title)
|
||||
{
|
||||
if (!human) {
|
||||
vshPrint(ctl, "%-15s %llu\n", _("Capacity:"), info->capacity);
|
||||
vshPrint(ctl, "%-15s %llu\n", _("Allocation:"), info->allocation);
|
||||
vshPrint(ctl, "%-15s %llu\n", _("Physical:"), info->physical);
|
||||
} else {
|
||||
double val;
|
||||
const char *unit;
|
||||
char *cap = NULL;
|
||||
char *alloc = NULL;
|
||||
char *phy = NULL;
|
||||
|
||||
val = vshPrettyCapacity(info->capacity, &unit);
|
||||
vshPrint(ctl, "%-15s %-.3lf %s\n", _("Capacity:"), val, unit);
|
||||
val = vshPrettyCapacity(info->allocation, &unit);
|
||||
vshPrint(ctl, "%-15s %-.3lf %s\n", _("Allocation:"), val, unit);
|
||||
val = vshPrettyCapacity(info->physical, &unit);
|
||||
vshPrint(ctl, "%-15s %-.3lf %s\n", _("Physical:"), val, unit);
|
||||
if (title) {
|
||||
vshPrintExtra(ctl, "%-10s %-15s %-15s %-15s\n", _("Target"),
|
||||
_("Capacity"), _("Allocation"), _("Physical"));
|
||||
vshPrintExtra(ctl, "-----------------------------"
|
||||
"------------------------\n");
|
||||
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;
|
||||
bool ret = false;
|
||||
bool human = false;
|
||||
bool all = false;
|
||||
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)))
|
||||
return false;
|
||||
|
||||
if (vshCommandOptStringReq(ctl, cmd, "device", &device) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (virDomainGetBlockInfo(dom, device, &info, 0) < 0)
|
||||
all = vshCommandOptBool(cmd, "all");
|
||||
if (!all && vshCommandOptStringQuiet(ctl, cmd, "device", &device) <= 0) {
|
||||
vshError(ctl, "command 'domblkinfo' requires <device> option");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
cleanup:
|
||||
virshDomainFree(dom);
|
||||
VIR_FREE(target);
|
||||
VIR_FREE(protocol);
|
||||
VIR_FREE(disks);
|
||||
xmlXPathFreeContext(ctxt);
|
||||
xmlFreeDoc(xmldoc);
|
||||
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 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
|
||||
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
|
||||
also B<domblklist> for listing these names). If I<--human> is set, the
|
||||
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>]
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user