[libvirt] [PATCH v5 3/9] pvs: add functions to list domains and get info
Eric Blake
eblake at redhat.com
Tue May 1 23:11:07 UTC 2012
On 04/20/2012 10:01 AM, Dmitry Guryanov wrote:
> PVS driver is 'stateless', like vmware or openvz drivers.
> It collects information about domains during startup using
> command-line utility prlctl. VMs in PVS identified by UUIDs
s/identified/are identified/
> or unique names, which can be used as respective fields in
> virDomainDef structure. Currently only basic info, like
> description, virtual cpus number and memory amount implemented.
s/amount implemented/amount, is implemented/
> Quering devices information will be added in the next patches.
s/Quering/Querying/
>
> PVS does't support non-persistent domains - you can't run
s/does't/doesn't/
> a domain having only disk image, it must always be registered
> in system.
>
> Functions for quering domain info have been just copied from
s/quering/querying/
> test driver with some changes - they extract needed data from
> previouly created list of virDomainObj objects.
s/previouly/previously/
> +++ b/po/POTFILES.in
> @@ -165,6 +165,7 @@ src/xenapi/xenapi_driver.c
> src/xenapi/xenapi_utils.c
> src/xenxs/xen_sxpr.c
> src/xenxs/xen_xm.c
> +src/pvs/pvs_driver.c
> tools/console.c
> tools/libvirt-guests.init.sh
> tools/virsh.c
I think this hunk belongs in 1/9.
> @@ -77,6 +78,14 @@ pvsDefaultConsoleType(const char *ostype ATTRIBUTE_UNUSED)
> return VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL;
> }
>
> +void
> +pvsFreeDomObj(void *p)
> +{
> + pvsDomObjPtr pdom = (pvsDomObjPtr) p;
> +
> + VIR_FREE(pdom);
Simpler to just write VIR_FREE(p) and avoid the intermediate variable.
Also, this function can safely be marked static.
> +/*
> + * Must be called with privconn->lock held
> + */
> +static virDomainObjPtr
> +pvsLoadDomain(pvsConnPtr privconn, virJSONValuePtr jobj)
> +{
Long, but looks okay.
> +/*
> + * Must be called with privconn->lock held
> + */
> +static int
> +pvsLoadDomains(pvsConnPtr privconn, const char *domain_name)
> +{
> + int count, i;
> + virJSONValuePtr jobj;
> + virJSONValuePtr jobj2;
> + virDomainObjPtr dom = NULL;
> + int ret = -1;
> +
> + jobj = pvsParseOutput(PRLCTL, "list", "-j", "-a",
> + "-i", "-H", domain_name, NULL);
I guess you can call this command with a domain name, to limit to one
output, or with no argument, to list all domains, given...
> @@ -150,6 +371,9 @@ pvsOpenDefault(virConnectPtr conn)
> if (virDomainObjListInit(&privconn->domains) < 0)
> goto error;
>
> + if (pvsLoadDomains(privconn, NULL))
> + goto error;
this usage.
> +static int
> +pvsDomainIsPersistent(virDomainPtr dom ATTRIBUTE_UNUSED)
> +{
> + return 1;
> +}
I'm wondering if we should at least validate that dom still exists in
our hash table. But I can live with this implementation.
> +
> +static int
> +pvsDomainGetState(virDomainPtr domain,
> + int *state, int *reason, unsigned int flags)
> +{
> + pvsConnPtr privconn = domain->conn->privateData;
> + virDomainObjPtr privdom;
> + int ret = -1;
> + virCheckFlags(0, -1);
> +
> + pvsDriverLock(privconn);
> + privdom = virDomainFindByName(&privconn->domains, domain->name);
> + pvsDriverUnlock(privconn);
> +
> + if (privdom == NULL) {
> + pvsError(VIR_ERR_INVALID_ARG, __FUNCTION__);
Use of __FUNCTION__ as the error message is not a good habit, since
pvsError _already_ adds the function name automatically. You should
instead provide a real message, such as _("Domain '%s' not found"),
domain->name.
> +static char *
> +pvsDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
> +{
> + pvsConnPtr privconn = domain->conn->privateData;
> + virDomainDefPtr def;
> + virDomainObjPtr privdom;
> + char *ret = NULL;
> +
> + /* Flags checked by virDomainDefFormat */
> +
> + pvsDriverLock(privconn);
> + privdom = virDomainFindByName(&privconn->domains, domain->name);
> + pvsDriverUnlock(privconn);
> +
> + if (privdom == NULL) {
> + pvsError(VIR_ERR_INVALID_ARG, __FUNCTION__);
Likewise (and probably throughout the series, so I'll quit pointing it out).
> # define pvsError(code, ...) \
> virReportErrorHelper(VIR_FROM_TEST, code, __FILE__, \
> __FUNCTION__, __LINE__, __VA_ARGS__)
> # define PRLCTL "prlctl"
> +# define pvsParseError() \
> + virReportErrorHelper(VIR_FROM_TEST, VIR_ERR_OPERATION_FAILED, __FILE__, \
> + __FUNCTION__, __LINE__, "Can't parse prlctl output")
Mark this string for translation: _("Can't parse prlctl output")
> +
> +struct pvsDomObj {
> + int id;
> + char *uuid;
> + char *os;
> +};
>
> +typedef struct pvsDomObj *pvsDomObjPtr;
>
> struct _pvsConn {
> virMutex lock;
> @@ -48,4 +60,6 @@ typedef struct _pvsConn *pvsConnPtr;
>
> int pvsRegister(void);
>
> +virJSONValuePtr pvsParseOutput(const char *binary, ...);
Mark this with ATTRIBUTE_NONNULL(1) ATTRIBUTE_SENTINEL.
> +
> +static int
> +pvsDoCmdRun(char **outbuf, const char *binary, va_list list)
> +{
> + virCommandPtr cmd = virCommandNew(binary);
> + const char *arg;
> + int exitstatus;
> + char *scmd = NULL;
> + char *sstatus = NULL;
> + int ret = -1;
> +
> + while ((arg = va_arg(list, const char *)) != NULL)
> + virCommandAddArg(cmd, arg);
> +
> + if (outbuf)
> + virCommandSetOutputBuffer(cmd, outbuf);
> +
> + scmd = virCommandToString(cmd);
> + if (!scmd)
> + goto cleanup;
> +
> + if (virCommandRun(cmd, &exitstatus)) {
If you pass NULL as the second argument here,
> + pvsError(VIR_ERR_INTERNAL_ERROR,
> + _("Failed to execute command '%s'"), scmd);
> + goto cleanup;
> + }
> +
> + if (exitstatus) {
> + sstatus = virCommandTranslateStatus(exitstatus);
> + pvsError(VIR_ERR_INTERNAL_ERROR,
> + _("Command '%s' finished with errors: %s"), scmd, sstatus);
then virCommand will take care of ensuring a 0 exit status, and with
more uniform error reporting. No need to reinvent the work that someone
else will do for you :) The only reason to ever pass an &exitstatus
parameter is if you validly expect non-zero exit status.
> +/*
> + * Run command and parse its JSON output, return
> + * pointer to virJSONValue or NULL in case of error.
> + */
> +virJSONValuePtr
> +pvsParseOutput(const char *binary, ...)
> +{
> + char *outbuf;
> + virJSONValuePtr jobj = NULL;
> + va_list list;
> + int ret;
> +
> + va_start(list, binary);
> + ret = pvsDoCmdRun(&outbuf, binary, list);
> + va_end(list);
> + if (ret)
> + return NULL;
> +
> + jobj = virJSONValueFromString(outbuf);
> + if (!jobj)
> + pvsError(VIR_ERR_INTERNAL_ERROR, "%s: %s",
> + _("invalid output from prlctl"), outbuf);
> +
> + return jobj;
You leak outbuf if you reach the virJSONValueFromString() call.
--
Eric Blake eblake at redhat.com +1-919-301-3266
Libvirt virtualization library http://libvirt.org
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 620 bytes
Desc: OpenPGP digital signature
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20120501/8f765b02/attachment-0001.sig>
More information about the libvir-list
mailing list