libvirt-admin.c 15.1 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 125 126 127 128 129 130
        if (STRNEQ(uri->scheme, "libvirtd")) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("Unsupported URI scheme '%s'"),
                           uri->scheme);
            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 188 189 190 191
 * @name: uri of the daemon to connect to, NULL for default
 * @flags: unused, must be 0
 *
 * 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();
E
Erik Skultety 已提交
207
    virCheckFlags(VIR_CONNECT_NO_ALIASES, NULL);
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
    if (!conn)
375 376
        return 0;

377
    virCheckAdmConnectReturn(conn, -1);
378 379
    virResetLastError();

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

    return ret;
}
387 388

/**
389 390
 * virAdmConnectGetURI:
 * @conn: pointer to an admin connection
391 392
 *
 * String returned by this method is normally the same as the string passed
393
 * to the virAdmConnectOpen. Even if NULL was passed to virAdmConnectOpen,
394 395 396 397 398 399
 * 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 *
400
virAdmConnectGetURI(virAdmConnectPtr conn)
401 402
{
    char *uri = NULL;
403
    VIR_DEBUG("conn=%p", conn);
404 405 406

    virResetLastError();

407
    virCheckAdmConnectReturn(conn, NULL);
408

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

    return uri;
}
414 415

/**
416 417
 * virAdmConnectRegisterCloseCallback:
 * @conn: connection to admin server
418 419 420 421 422 423 424 425 426 427 428 429 430 431 432
 * @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
 */
433 434 435 436
int virAdmConnectRegisterCloseCallback(virAdmConnectPtr conn,
                                       virAdmConnectCloseFunc cb,
                                       void *opaque,
                                       virFreeCallback freecb)
437
{
438
    VIR_DEBUG("conn=%p", conn);
439 440 441

    virResetLastError();

442
    virCheckAdmConnectReturn(conn, -1);
443

444
    virObjectRef(conn);
445

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

    virCheckNonNullArgGoto(cb, error);

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

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

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

    return 0;

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

}

/**
477 478
 * virAdmConnectUnregisterCloseCallback:
 * @conn: pointer to connection object
479 480 481
 * @cb: pointer to the current registered callback
 *
 * Unregisters the callback previously set with the
482
 * virAdmConnectRegisterCloseCallback method. The callback
483 484 485 486 487 488
 * 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
 */
489 490
int virAdmConnectUnregisterCloseCallback(virAdmConnectPtr conn,
                                         virAdmConnectCloseFunc cb)
491
{
492
    VIR_DEBUG("conn=%p", conn);
493 494 495

    virResetLastError();

496
    virCheckAdmConnectReturn(conn, -1);
497

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

    virCheckNonNullArgGoto(cb, error);

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

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

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

    return 0;

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

/**
528 529
 * virAdmConnectGetLibVersion:
 * @conn: pointer to an active admin connection
530 531 532 533 534 535 536 537
 * @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:
 */
538 539
int virAdmConnectGetLibVersion(virAdmConnectPtr conn,
                               unsigned long long *libVer)
540
{
541
    VIR_DEBUG("conn=%p, libVir=%p", conn, libVer);
542 543 544

    virResetLastError();

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

548
    if (remoteAdminConnectGetLibVersion(conn, libVer) < 0)
549 550 551 552 553 554 555 556
        goto error;

    return 0;

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