libvirt-admin.c 27.4 KB
Newer Older
M
Martin Kletzander 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
/*
 * libvirt-admin.c
 *
 * Copyright (C) 2014-2015 Red Hat, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library.  If not, see
 * <http://www.gnu.org/licenses/>.
 *
 * Author: Martin Kletzander <mkletzan@redhat.com>
 */

#include <config.h>

#include "internal.h"
#include "datatypes.h"
27 28
#include "configmake.h"

M
Martin Kletzander 已提交
29
#include "viralloc.h"
30
#include "virconf.h"
M
Martin Kletzander 已提交
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
#include "virlog.h"
#include "virnetclient.h"
#include "virobject.h"
#include "virstring.h"
#include "viruri.h"
#include "virutil.h"
#include "viruuid.h"

#define VIR_FROM_THIS VIR_FROM_ADMIN

#define LIBVIRTD_ADMIN_SOCK_NAME "/libvirt-admin-sock"
#define LIBVIRTD_ADMIN_UNIX_SOCKET LOCALSTATEDIR "/run/libvirt" LIBVIRTD_ADMIN_SOCK_NAME

VIR_LOG_INIT("libvirt-admin");

46
#include "admin_remote.c"
M
Martin Kletzander 已提交
47 48 49 50 51 52 53 54 55

static bool virAdmGlobalError;
static virOnceControl virAdmGlobalOnce = VIR_ONCE_CONTROL_INITIALIZER;

static void
virAdmGlobalInit(void)
{
    /* It would be nice if we could trace the use of this call, to
     * help diagnose in log files if a user calls something other than
56
     * virAdmConnectOpen first.  But we can't rely on VIR_DEBUG working
M
Martin Kletzander 已提交
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
     * until after initialization is complete, and since this is
     * one-shot, we never get here again.  */
    if (virThreadInitialize() < 0 ||
        virErrorInitialize() < 0)
        goto error;

    virLogSetFromEnv();

    if (!bindtextdomain(PACKAGE, LOCALEDIR))
        goto error;

    if (!(remoteAdminPrivClass = virClassNew(virClassForObjectLockable(),
                                             "remoteAdminPriv",
                                             sizeof(remoteAdminPriv),
                                             remoteAdminPrivDispose)))
        goto error;

    return;
 error:
    virAdmGlobalError = true;
}

/**
 * virAdmInitialize:
 *
 * Initialize the library.
 *
 * Returns 0 in case of success, -1 in case of error
 */
static int
virAdmInitialize(void)
{
    if (virOnce(&virAdmGlobalOnce, virAdmGlobalInit) < 0)
        return -1;

    if (virAdmGlobalError)
        return -1;

    return 0;
}

static char *
99
getSocketPath(virURIPtr uri)
M
Martin Kletzander 已提交
100 101 102 103 104
{
    char *rundir = virGetUserRuntimeDirectory();
    char *sock_path = NULL;
    size_t i = 0;

105 106
    if (!uri)
        goto cleanup;
M
Martin Kletzander 已提交
107 108


109 110
    for (i = 0; i < uri->paramsCount; i++) {
        virURIParamPtr param = &uri->params[i];
M
Martin Kletzander 已提交
111

112 113 114
        if (STREQ(param->name, "socket")) {
            VIR_FREE(sock_path);
            if (VIR_STRDUP(sock_path, param->value) < 0)
M
Martin Kletzander 已提交
115
                goto error;
116 117 118 119
        } else {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("Unknown URI parameter '%s'"), param->name);
            goto error;
M
Martin Kletzander 已提交
120 121 122 123
        }
    }

    if (!sock_path) {
124
        if (STRNEQ_NULLABLE(uri->scheme, "libvirtd")) {
125 126
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("Unsupported URI scheme '%s'"),
127
                           NULLSTR(uri->scheme));
128 129 130
            goto error;
        }
        if (STREQ_NULLABLE(uri->path, "/system")) {
M
Martin Kletzander 已提交
131 132 133
            if (VIR_STRDUP(sock_path, LIBVIRTD_ADMIN_UNIX_SOCKET) < 0)
                goto error;
        } else if (STREQ_NULLABLE(uri->path, "/session")) {
134 135
            if (!rundir || virAsprintf(&sock_path, "%s%s", rundir,
                                       LIBVIRTD_ADMIN_SOCK_NAME) < 0)
M
Martin Kletzander 已提交
136 137 138
                goto error;
        } else {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
139 140
                           _("Invalid URI path '%s', try '/system'"),
                           uri->path ? uri->path : "");
M
Martin Kletzander 已提交
141 142 143 144 145 146 147 148 149 150 151 152 153
            goto error;
        }
    }

 cleanup:
    VIR_FREE(rundir);
    return sock_path;

 error:
    VIR_FREE(sock_path);
    goto cleanup;
}

154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
static const char *
virAdmGetDefaultURI(virConfPtr conf)
{
    virConfValuePtr value = NULL;
    const char *uristr = NULL;

    uristr = virGetEnvAllowSUID("LIBVIRT_ADMIN_DEFAULT_URI");
    if (uristr && *uristr) {
        VIR_DEBUG("Using LIBVIRT_ADMIN_DEFAULT_URI '%s'", uristr);
    } else if ((value = virConfGetValue(conf, "admin_uri_default"))) {
        if (value->type != VIR_CONF_STRING) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("Expected a string for 'admin_uri_default' config "
                             "parameter"));
            return NULL;
        }

        VIR_DEBUG("Using config file uri '%s'", value->str);
        uristr = value->str;
    } else {
        /* Since we can't probe connecting via any hypervisor driver as libvirt
         * does, if no explicit URI was given and neither the environment
         * variable, nor the configuration parameter had previously been set,
         * we set the default admin server URI to 'libvirtd://system'.
         */
        uristr = "libvirtd:///system";
    }

    return uristr;
}

M
Martin Kletzander 已提交
185
/**
186
 * virAdmConnectOpen:
M
Martin Kletzander 已提交
187
 * @name: uri of the daemon to connect to, NULL for default
188
 * @flags: extra flags; not used yet, so callers should always pass 0
M
Martin Kletzander 已提交
189 190 191
 *
 * Opens connection to admin interface of the daemon.
 *
192
 * Returns @virAdmConnectPtr object or NULL on error
M
Martin Kletzander 已提交
193
 */
194 195
virAdmConnectPtr
virAdmConnectOpen(const char *name, unsigned int flags)
M
Martin Kletzander 已提交
196 197
{
    char *sock_path = NULL;
E
Erik Skultety 已提交
198
    char *alias = NULL;
199
    virAdmConnectPtr conn = NULL;
200
    virConfPtr conf = NULL;
M
Martin Kletzander 已提交
201 202 203 204 205 206

    if (virAdmInitialize() < 0)
        goto error;

    VIR_DEBUG("flags=%x", flags);
    virResetLastError();
207
    virCheckFlagsGoto(VIR_CONNECT_NO_ALIASES, error);
M
Martin Kletzander 已提交
208

209
    if (!(conn = virAdmConnectNew()))
M
Martin Kletzander 已提交
210 211
        goto error;

212 213 214 215 216 217
    if (virConfLoadConfig(&conf, "libvirt-admin.conf") < 0)
        goto error;

    if (!name && !(name = virAdmGetDefaultURI(conf)))
        goto error;

E
Erik Skultety 已提交
218 219 220 221
    if ((!(flags & VIR_CONNECT_NO_ALIASES) &&
         virURIResolveAlias(conf, name, &alias) < 0))
        goto error;

222
    if (!(conn->uri = virURIParse(alias ? alias : name)))
223 224
        goto error;

225
    if (!(sock_path = getSocketPath(conn->uri)))
M
Martin Kletzander 已提交
226 227
        goto error;

228
    if (!(conn->privateData = remoteAdminPrivNew(sock_path)))
M
Martin Kletzander 已提交
229 230
        goto error;

231
    conn->privateDataFreeFunc = remoteAdminPrivFree;
M
Martin Kletzander 已提交
232

233
    if (remoteAdminConnectOpen(conn, flags) < 0)
M
Martin Kletzander 已提交
234 235 236 237
        goto error;

 cleanup:
    VIR_FREE(sock_path);
E
Erik Skultety 已提交
238
    VIR_FREE(alias);
239
    virConfFree(conf);
240
    return conn;
M
Martin Kletzander 已提交
241 242 243

 error:
    virDispatchError(NULL);
244 245
    virObjectUnref(conn);
    conn = NULL;
M
Martin Kletzander 已提交
246 247 248 249
    goto cleanup;
}

/**
250 251
 * virAdmConnectClose:
 * @conn: pointer to admin connection to close
M
Martin Kletzander 已提交
252 253 254 255 256 257
 *
 * This function closes the admin connection to the Hypervisor. This should not
 * be called if further interaction with the Hypervisor are needed especially if
 * there is running domain which need further monitoring by the application.
 *
 * Connections are reference counted; the count is explicitly increased by the
258
 * initial virAdmConnectOpen, as well as virAdmConnectRef; it is also temporarily
M
Martin Kletzander 已提交
259
 * increased by other API that depend on the connection remaining alive.  The
260 261
 * open and every virAdmConnectRef call should have a matching
 * virAdmConnectClose, and all other references will be released after the
M
Martin Kletzander 已提交
262 263 264 265 266 267 268
 * corresponding operation completes.
 *
 * Returns a positive number if at least 1 reference remains on success. The
 * returned value should not be assumed to be the total reference count. A
 * return of 0 implies no references remain and the connection is closed and
 * memory has been freed. A return of -1 implies a failure.
 *
269
 * It is possible for the last virAdmConnectClose to return a positive value if
M
Martin Kletzander 已提交
270 271
 * some other object still has a temporary reference to the connection, but the
 * application should not try to further use a connection after the
272
 * virAdmConnectClose that matches the initial open.
M
Martin Kletzander 已提交
273 274
 */
int
275
virAdmConnectClose(virAdmConnectPtr conn)
M
Martin Kletzander 已提交
276
{
277
    VIR_DEBUG("conn=%p", conn);
M
Martin Kletzander 已提交
278 279

    virResetLastError();
280
    if (!conn)
M
Martin Kletzander 已提交
281 282
        return 0;

283
    virCheckAdmConnectReturn(conn, -1);
M
Martin Kletzander 已提交
284

285
    if (!virObjectUnref(conn))
M
Martin Kletzander 已提交
286 287 288 289 290 291
        return 0;
    return 1;
}


/**
292 293
 * virAdmConnectRef:
 * @conn: the connection to hold a reference on
M
Martin Kletzander 已提交
294 295
 *
 * Increment the reference count on the connection. For each additional call to
296
 * this method, there shall be a corresponding call to virAdmConnectClose to
M
Martin Kletzander 已提交
297 298 299 300 301 302 303 304 305 306 307
 * release the reference count, once the caller no longer needs the reference to
 * this object.
 *
 * This method is typically useful for applications where multiple threads are
 * using a connection, and it is required that the connection remain open until
 * all threads have finished using it. I.e., each new thread using a connection
 * would increment the reference count.
 *
 * Returns 0 in case of success, -1 in case of failure
 */
int
308
virAdmConnectRef(virAdmConnectPtr conn)
M
Martin Kletzander 已提交
309
{
310 311
    VIR_DEBUG("conn=%p refs=%d", conn,
              conn ? conn->object.parent.u.s.refs : 0);
M
Martin Kletzander 已提交
312 313

    virResetLastError();
314
    virCheckAdmConnectReturn(conn, -1);
M
Martin Kletzander 已提交
315

316
    virObjectRef(conn);
M
Martin Kletzander 已提交
317 318 319

    return 0;
}
E
Erik Skultety 已提交
320 321 322 323 324 325 326 327 328 329

/**
 * virAdmGetVersion:
 * @libVer: where to store the library version
 *
 * Provides version information. @libVer is the version of the library and will
 * allways be set unless an error occurs in which case an error code and a
 * generic message will be returned. @libVer format is as follows:
 * major * 1,000,000 + minor * 1,000 + release.
 *
330 331
 * NOTE: To get the remote side library version use virAdmConnectGetLibVersion
 * instead.
E
Erik Skultety 已提交
332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353
 *
 * Returns 0 on success, -1 in case of an error.
 */
int
virAdmGetVersion(unsigned long long *libVer)
{
    if (virAdmInitialize() < 0)
        goto error;

    VIR_DEBUG("libVer=%p", libVer);

    virResetLastError();
    if (!libVer)
        goto error;
    *libVer = LIBVIR_VERSION_NUMBER;

    return 0;

 error:
    virDispatchError(NULL);
    return -1;
}
354 355

/**
356 357
 * virAdmConnectIsAlive:
 * @conn: connection to admin server
358 359 360 361 362 363 364 365 366
 *
 * Decide whether the connection to the admin server is alive or not.
 * Connection is considered alive if the channel it is running over is not
 * closed.
 *
 * Returns 1, if the connection is alive, 0 if there isn't an existing
 * connection at all or the channel has already been closed, or -1 on error.
 */
int
367
virAdmConnectIsAlive(virAdmConnectPtr conn)
368 369 370 371
{
    bool ret;
    remoteAdminPrivPtr priv = NULL;

372
    VIR_DEBUG("conn=%p", conn);
373

374 375
    virResetLastError();

376
    if (!conn)
377 378
        return 0;

379
    virCheckAdmConnectReturn(conn, -1);
380

381
    priv = conn->privateData;
382 383 384 385 386 387
    virObjectLock(priv);
    ret = virNetClientIsOpen(priv->client);
    virObjectUnlock(priv);

    return ret;
}
388 389

/**
390 391
 * virAdmConnectGetURI:
 * @conn: pointer to an admin connection
392 393
 *
 * String returned by this method is normally the same as the string passed
394
 * to the virAdmConnectOpen. Even if NULL was passed to virAdmConnectOpen,
395 396 397 398 399 400
 * this method returns a non-null URI string.
 *
 * Returns an URI string related to the connection or NULL in case of an error.
 * Caller is responsible for freeing the string.
 */
char *
401
virAdmConnectGetURI(virAdmConnectPtr conn)
402 403
{
    char *uri = NULL;
404
    VIR_DEBUG("conn=%p", conn);
405 406 407

    virResetLastError();

408
    virCheckAdmConnectReturn(conn, NULL);
409

410
    if (!(uri = virURIFormat(conn->uri)))
411 412 413 414
        virDispatchError(NULL);

    return uri;
}
415 416

/**
417 418
 * virAdmConnectRegisterCloseCallback:
 * @conn: connection to admin server
419 420 421 422 423 424 425 426 427 428 429 430 431 432 433
 * @cb: callback to be invoked upon connection close
 * @opaque: user data to pass to @cb
 * @freecb: callback to free @opaque
 *
 * Registers a callback to be invoked when the connection
 * is closed. This callback is invoked when there is any
 * condition that causes the socket connection to the
 * hypervisor to be closed.
 *
 * The @freecb must not invoke any other libvirt public
 * APIs, since it is not called from a re-entrant safe
 * context.
 *
 * Returns 0 on success, -1 on error
 */
434 435 436 437
int virAdmConnectRegisterCloseCallback(virAdmConnectPtr conn,
                                       virAdmConnectCloseFunc cb,
                                       void *opaque,
                                       virFreeCallback freecb)
438
{
439
    VIR_DEBUG("conn=%p", conn);
440 441 442

    virResetLastError();

443
    virCheckAdmConnectReturn(conn, -1);
444

445
    virObjectRef(conn);
446

447 448
    virObjectLock(conn);
    virObjectLock(conn->closeCallback);
449 450 451

    virCheckNonNullArgGoto(cb, error);

452
    if (conn->closeCallback->callback) {
453 454 455 456 457
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("A close callback is already registered"));
        goto error;
    }

458 459 460 461
    conn->closeCallback->conn = conn;
    conn->closeCallback->callback = cb;
    conn->closeCallback->opaque = opaque;
    conn->closeCallback->freeCallback = freecb;
462

463 464
    virObjectUnlock(conn->closeCallback);
    virObjectUnlock(conn);
465 466 467 468

    return 0;

 error:
469 470
    virObjectUnlock(conn->closeCallback);
    virObjectUnlock(conn);
471
    virDispatchError(NULL);
472
    virObjectUnref(conn);
473 474 475 476 477
    return -1;

}

/**
478 479
 * virAdmConnectUnregisterCloseCallback:
 * @conn: pointer to connection object
480 481 482
 * @cb: pointer to the current registered callback
 *
 * Unregisters the callback previously set with the
483
 * virAdmConnectRegisterCloseCallback method. The callback
484 485 486 487 488 489
 * will no longer receive notifications when the connection
 * closes. If a virFreeCallback was provided at time of
 * registration, it will be invoked.
 *
 * Returns 0 on success, -1 on error
 */
490 491
int virAdmConnectUnregisterCloseCallback(virAdmConnectPtr conn,
                                         virAdmConnectCloseFunc cb)
492
{
493
    VIR_DEBUG("conn=%p", conn);
494 495 496

    virResetLastError();

497
    virCheckAdmConnectReturn(conn, -1);
498

499 500
    virObjectLock(conn);
    virObjectLock(conn->closeCallback);
501 502 503

    virCheckNonNullArgGoto(cb, error);

504
    if (conn->closeCallback->callback != cb) {
505 506 507 508 509
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("A different callback was requested"));
        goto error;
    }

510 511 512 513
    conn->closeCallback->callback = NULL;
    if (conn->closeCallback->freeCallback)
        conn->closeCallback->freeCallback(conn->closeCallback->opaque);
    conn->closeCallback->freeCallback = NULL;
514

515 516 517
    virObjectUnlock(conn->closeCallback);
    virObjectUnlock(conn);
    virObjectUnref(conn);
518 519 520 521

    return 0;

 error:
522 523
    virObjectUnlock(conn->closeCallback);
    virObjectUnlock(conn);
524 525 526
    virDispatchError(NULL);
    return -1;
}
527 528

/**
529 530
 * virAdmConnectGetLibVersion:
 * @conn: pointer to an active admin connection
531 532 533 534 535 536 537 538
 * @libVer: stores the current remote libvirt version number
 *
 * Retrieves the remote side libvirt version used by the daemon. Format
 * returned in @libVer is of a following pattern:
 * major * 1,000,000 + minor * 1,000 + release.
 *
 * Returns 0 on success, -1 on failure and @libVer follows this format:
 */
539 540
int virAdmConnectGetLibVersion(virAdmConnectPtr conn,
                               unsigned long long *libVer)
541
{
542
    VIR_DEBUG("conn=%p, libVir=%p", conn, libVer);
543 544 545

    virResetLastError();

546
    virCheckAdmConnectReturn(conn, -1);
547 548
    virCheckNonNullArgReturn(libVer, -1);

549
    if (remoteAdminConnectGetLibVersion(conn, libVer) < 0)
550 551 552
        goto error;

    return 0;
553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589
 error:
    virDispatchError(NULL);
    return -1;
}

/**
 * virAdmServerGetName:
 * @srv: a server object
 *
 *  Get the public name for specified server
 *
 * Returns a pointer to the name or NULL. The string doesn't need to be
 * deallocated since its lifetime will be the same as the server object.
 */
const char *
virAdmServerGetName(virAdmServerPtr srv)
{
    VIR_DEBUG("server=%p", srv);

    virResetLastError();
    virCheckAdmServerReturn(srv, NULL);

    return srv->name;
}

/**
 * virAdmServerFree:
 * @srv: server object
 *
 * Release the server object. The running instance is kept alive.
 * The data structure is freed and should not be used thereafter.
 *
 * Returns 0 on success, -1 on failure.
 */
int virAdmServerFree(virAdmServerPtr srv)
{
    VIR_DEBUG("server=%p", srv);
590

591
    virResetLastError();
592 593 594 595

    if (!srv)
        return 0;

596 597 598 599 600 601
    virCheckAdmServerReturn(srv, -1);

    virObjectUnref(srv);
    return 0;
}

602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691
/**
 * virAdmClientGetID:
 * @client: a client object
 *
 * Get client's unique numeric ID.
 *
 * Returns numeric value used for client's ID or -1 in case of an error.
 */
unsigned long long
virAdmClientGetID(virAdmClientPtr client)
{
    VIR_DEBUG("client=%p", client);

    virResetLastError();
    virCheckAdmClientReturn(client, -1);
    return client->id;
}

/**
 * virAdmClientGetTimestamp:
 * @client: a client object
 *
 * Get client's connection time.
 * A situation may happen, that some clients had connected prior to the update
 * to admin API, thus, libvirt assigns these clients epoch time to express that
 * it doesn't know when the client connected.
 *
 * Returns client's connection timestamp (seconds from epoch in UTC) or 0
 * (epoch time) if libvirt doesn't have any information about client's
 * connection time, or -1 in case of an error.
 */
long long
virAdmClientGetTimestamp(virAdmClientPtr client)
{
    VIR_DEBUG("client=%p", client);

    virResetLastError();
    virCheckAdmClientReturn(client, -1);
    return client->timestamp;
}

/**
 * virAdmClientGetTransport:
 * @client: a client object
 *
 * Get client's connection transport type. This information can be helpful to
 * differentiate between clients connected locally or remotely. An exception to
 * this would be SSH which is one of libvirt's supported transports.
 * Although SSH creates a channel between two (preferably) remote endpoints,
 * the client process libvirt spawns automatically on the remote side will
 * still connect to a UNIX socket, thus becoming indistinguishable from any
 * other locally connected clients.
 *
 * Returns integer representation of the connection transport used by @client
 * (this will be one of virClientTransport) or -1 in case of an error.
 */
int
virAdmClientGetTransport(virAdmClientPtr client)
{
    VIR_DEBUG("client=%p", client);

    virResetLastError();
    virCheckAdmClientReturn(client, -1);
    return client->transport;
}

/**
 * virAdmClientFree:
 * @client: a client object
 *
 * Release the client object. The running instance is kept alive. The data
 * structure is freed and should not be used thereafter.
 *
 * Returns 0 in success, -1 on failure.
 */
int virAdmClientFree(virAdmClientPtr client)
{
    VIR_DEBUG("client=%p", client);

    virResetLastError();

    if (!client)
        return 0;

    virCheckAdmClientReturn(client, -1);

    virObjectUnref(client);
    return 0;
}

692 693 694 695 696
/**
 * virAdmConnectListServers:
 * @conn: daemon connection reference
 * @servers: Pointer to a list to store an array containing objects or NULL
 *           if the list is not required (number of servers only)
697
 * @flags: extra flags; not used yet, so callers should always pass 0
698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717
 *
 * Collect list of all servers provided by daemon the client is connected to.
 *
 * Returns the number of servers available on daemon side or -1 in case of a
 * failure, setting @servers to NULL. There is a guaranteed extra element set
 * to NULL in the @servers list returned to make the iteration easier, excluding
 * this extra element from the final count.
 * Caller is responsible to call virAdmServerFree() on each list element,
 * followed by freeing @servers.
 */
int
virAdmConnectListServers(virAdmConnectPtr conn,
                         virAdmServerPtr **servers,
                         unsigned int flags)
{
    int ret = -1;

    VIR_DEBUG("conn=%p, servers=%p, flags=%x", conn, servers, flags);

    virResetLastError();
718
    virCheckFlagsGoto(0, error);
719 720 721 722 723 724 725 726 727

    if (servers)
        *servers = NULL;

    virCheckAdmConnectReturn(conn, -1);
    if ((ret = remoteAdminConnectListServers(conn, servers, flags)) < 0)
        goto error;

    return ret;
728 729 730 731
 error:
    virDispatchError(NULL);
    return -1;
}
732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766

/**
 * virAdmConnectLookupServer:
 * @conn: daemon connection reference
 * @name: name of the server too lookup
 * @flags: extra flags; not used yet, so callers should always pass 0
 *
 * Try to lookup a server on the given daemon based on @name.
 *
 * virAdmServerFree() should be used to free the resources after the
 * server object is no longer needed.
 *
 * Returns the requested server or NULL in case of failure.  If the
 * server cannot be found, then VIR_ERR_NO_SERVER error is raised.
 */
virAdmServerPtr
virAdmConnectLookupServer(virAdmConnectPtr conn,
                          const char *name,
                          unsigned int flags)
{
    virAdmServerPtr ret = NULL;

    VIR_DEBUG("conn=%p, name=%s, flags=%x", conn, NULLSTR(name), flags);
    virResetLastError();

    virCheckAdmConnectGoto(conn, cleanup);
    virCheckNonNullArgGoto(name, cleanup);
    virCheckFlagsGoto(0, cleanup);

    ret = remoteAdminConnectLookupServer(conn, name, flags);
 cleanup:
    if (!ret)
        virDispatchError(NULL);
    return ret;
}
767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813

/**
 * virAdmServerGetThreadPoolParameters:
 * @srv: a valid server object reference
 * @params: pointer to a list of typed parameters which will be allocated
 *          to store all returned parameters
 * @nparams: pointer which will hold the number of params returned in @params
 * @flags: extra flags; not used yet, so callers should always pass 0
 *
 * Retrieves threadpool parameters from @srv. Upon successful completion,
 * @params will be allocated automatically to hold all returned data, setting
 * @nparams accordingly.
 * When extracting parameters from @params, following search keys are
 * supported:
 *      VIR_THREADPOOL_WORKERS_MIN
 *      VIR_THREADPOOL_WORKERS_MAX
 *      VIR_THREADPOOL_WORKERS_PRIORITY
 *      VIR_THREADPOOL_WORKERS_FREE
 *      VIR_THREADPOOL_WORKERS_CURRENT
 *
 * Returns 0 on success, -1 in case of an error.
 */
int
virAdmServerGetThreadPoolParameters(virAdmServerPtr srv,
                                    virTypedParameterPtr *params,
                                    int *nparams,
                                    unsigned int flags)
{
    int ret = -1;

    VIR_DEBUG("srv=%p, params=%p, nparams=%p, flags=%x",
              srv, params, nparams, flags);

    virResetLastError();

    virCheckAdmServerReturn(srv, -1);
    virCheckNonNullArgGoto(params, error);

    if ((ret = remoteAdminServerGetThreadPoolParameters(srv, params, nparams,
                                                        flags)) < 0)
        goto error;

    return ret;
 error:
    virDispatchError(NULL);
    return -1;
}
814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840

/**
 * virAdmServerSetThreadPoolParameters:
 * @srv: a valid server object reference
 * @params: pointer to threadpool typed parameter objects
 * @nparams: number of parameters in @params
 * @flags: extra flags; not used yet, so callers should always pass 0
 *
 * Change server threadpool parameters according to @params. Note that some
 * tunables are read-only, thus any attempt to set them will result in a
 * failure.
 *
 * Returns 0 on success, -1 in case of an error.
 */
int
virAdmServerSetThreadPoolParameters(virAdmServerPtr srv,
                                    virTypedParameterPtr params,
                                    int nparams,
                                    unsigned int flags)
{
    VIR_DEBUG("srv=%p, params=%p, nparams=%x, flags=%x",
              srv, params, nparams, flags);

    virResetLastError();

    virCheckAdmServerReturn(srv, -1);
    virCheckNonNullArgGoto(params, error);
841
    virCheckNonNegativeArgGoto(nparams, error);
842 843 844 845 846 847 848 849 850 851

    if (remoteAdminServerSetThreadPoolParameters(srv, params,
                                                 nparams, flags) < 0)
        goto error;

    return 0;
 error:
    virDispatchError(NULL);
    return -1;
}
E
Erik Skultety 已提交
852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892

/**
 * virAdmServerListClients:
 * @srv: a valid server object reference
 * @clients: pointer to a list to store an array containing objects or NULL
 *           if the list is not required (number of clients only)
 * @flags: extra flags; not used yet, so callers should always pass 0
 *
 * Collect list of all clients connected to daemon on server @srv.
 *
 * Returns the number of clients connected to daemon on server @srv -1 in case
 * of a failure, setting @clients to NULL. There is a guaranteed extra element
 * set to NULL in the @clients list returned to make the iteration easier,
 * excluding this extra element from the final count.
 * Caller is responsible to call virAdmClientFree() on each list element,
 * followed by freeing @clients.
 */
int
virAdmServerListClients(virAdmServerPtr srv,
                        virAdmClientPtr **clients,
                        unsigned int flags)
{
    int ret = -1;

    VIR_DEBUG("srv=%p, clients=%p, flags=%x", srv, clients, flags);

    virResetLastError();
    virCheckFlagsGoto(0, error);

    if (clients)
        *clients = NULL;

    virCheckAdmServerReturn(srv, -1);
    if ((ret = remoteAdminServerListClients(srv, clients, flags)) < 0)
        goto error;

    return ret;
 error:
    virDispatchError(NULL);
    return -1;
}
893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928

/**
 * virAdmServerLookupClient:
 * @srv: a valid server object reference
 * @id: ID of the client to lookup on server @srv
 * @flags: extra flags; not used yet, so callers should always pass 0
 *
 * Try to lookup a client on the given server based on @id.
 *
 * virAdmClientFree() should be used to free the resources after the
 * client object is no longer needed.
 *
 * Returns the requested client or NULL in case of failure.  If the
 * client could not be found, then VIR_ERR_NO_CLIENT error is raised.
 */
virAdmClientPtr
virAdmServerLookupClient(virAdmServerPtr srv,
                         unsigned long long id,
                         unsigned int flags)
{
    virAdmClientPtr ret = NULL;

    VIR_DEBUG("srv=%p, id=%llu, flags=%x", srv, id, flags);
    virResetLastError();

    virCheckAdmServerGoto(srv, error);
    virCheckFlagsGoto(0, error);

    if (!(ret = remoteAdminServerLookupClient(srv, id, flags)))
        goto error;

    return ret;
 error:
    virDispatchError(NULL);
    return NULL;
}
929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978

/**
 * virAdmClientGetInfo:
 * @client: a client object reference
 * @params: pointer to a list of typed parameters which will be allocated
 *          to store all returned parameters
 * @nparams: pointer which will hold the number of params returned in @params
 * @flags: extra flags; not used yet, so callers should always pass 0
 *
 * Extract identity information about a client. Attributes returned in @params
 * are mostly transport-dependent, i.e. some attributes including client
 * process's pid, gid, uid, or remote side's socket address are only available
 * for a specific connection type - local vs remote.
 * Other identity attributes like authentication method used
 * (if authentication is enabled on the remote host), SELinux context, or
 * an indicator whether client is connected via a read-only connection are
 * independent of the connection transport.
 *
 * Note that the read-only connection indicator returns false for TCP/TLS
 * clients because libvirt treats such connections as read-write by default,
 * even though a TCP client is able to restrict access to certain APIs for
 * itself.
 *
 * Returns 0 if the information has been successfully retrieved or -1 in case
 * of an error.
 */
int
virAdmClientGetInfo(virAdmClientPtr client,
                    virTypedParameterPtr *params,
                    int *nparams,
                    unsigned int flags)
{
    int ret = -1;

    VIR_DEBUG("client=%p, params=%p, nparams=%p, flags=%x",
              client, params, nparams, flags);

    virResetLastError();
    virCheckAdmClientReturn(client, -1);
    virCheckNonNullArgGoto(params, error);
    virCheckFlagsGoto(0, error);

    if ((ret = remoteAdminClientGetInfo(client, params, nparams, flags)) < 0)
        goto error;

    return ret;
 error:
    virDispatchError(NULL);
    return -1;
}