storage_conf.c 50.5 KB
Newer Older
1 2 3
/*
 * storage_conf.c: config handling for storage driver
 *
4
 * Copyright (C) 2006-2016 Red Hat, Inc.
5 6 7 8 9 10 11 12 13 14 15 16 17
 * Copyright (C) 2006-2008 Daniel P. Berrange
 *
 * 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
18
 * License along with this library.  If not, see
O
Osier Yang 已提交
19
 * <http://www.gnu.org/licenses/>.
20 21 22 23 24 25 26 27 28
 */

#include <config.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>

29
#include "virerror.h"
30
#include "datatypes.h"
31
#include "node_device_conf.h"
32
#include "storage_adapter_conf.h"
33
#include "storage_conf.h"
34
#include "virstoragefile.h"
35

36
#include "virxml.h"
37
#include "viruuid.h"
38
#include "virbuffer.h"
39
#include "viralloc.h"
E
Eric Blake 已提交
40
#include "virfile.h"
41
#include "virscsihost.h"
42
#include "virstring.h"
43
#include "virlog.h"
44
#include "virvhba.h"
45

46 47
#define VIR_FROM_THIS VIR_FROM_STORAGE

48 49
VIR_LOG_INIT("conf.storage_conf");

50 51
VIR_ENUM_IMPL(virStorageVol,
              VIR_STORAGE_VOL_LAST,
O
Olga Krishtal 已提交
52
              "file", "block", "dir", "network",
53 54
              "netdir", "ploop",
);
55

56 57 58 59
VIR_ENUM_IMPL(virStoragePool,
              VIR_STORAGE_POOL_LAST,
              "dir", "fs", "netfs",
              "logical", "disk", "iscsi",
60 61
              "iscsi-direct", "scsi", "mpath",
              "rbd", "sheepdog", "gluster",
62 63
              "zfs", "vstorage",
);
64 65 66 67 68

VIR_ENUM_IMPL(virStoragePoolFormatFileSystem,
              VIR_STORAGE_POOL_FS_LAST,
              "auto", "ext2", "ext3",
              "ext4", "ufs", "iso9660", "udf",
69 70
              "gfs", "gfs2", "vfat", "hfs+", "xfs", "ocfs2",
);
71 72 73

VIR_ENUM_IMPL(virStoragePoolFormatFileSystemNet,
              VIR_STORAGE_POOL_NETFS_LAST,
74 75
              "auto", "nfs", "glusterfs", "cifs",
);
76 77 78 79

VIR_ENUM_IMPL(virStoragePoolFormatDisk,
              VIR_STORAGE_POOL_DISK_LAST,
              "unknown", "dos", "dvh", "gpt",
80 81
              "mac", "bsd", "pc98", "sun", "lvm2",
);
82 83 84

VIR_ENUM_IMPL(virStoragePoolFormatLogical,
              VIR_STORAGE_POOL_LOGICAL_LAST,
85 86
              "unknown", "lvm2",
);
87 88 89 90 91 92 93


VIR_ENUM_IMPL(virStorageVolFormatDisk,
              VIR_STORAGE_VOL_DISK_LAST,
              "none", "linux", "fat16",
              "fat32", "linux-swap",
              "linux-lvm", "linux-raid",
94 95
              "extended",
);
96

97
VIR_ENUM_IMPL(virStoragePartedFs,
98
              VIR_STORAGE_PARTED_FS_TYPE_LAST,
99
              "ext2", "ext2", "fat16",
100 101
              "fat32", "linux-swap",
              "ext2", "ext2",
102 103
              "extended",
);
104 105 106 107 108 109 110 111 112 113

typedef const char *(*virStorageVolFormatToString)(int format);
typedef int (*virStorageVolFormatFromString)(const char *format);

typedef const char *(*virStoragePoolFormatToString)(int format);
typedef int (*virStoragePoolFormatFromString)(const char *format);

typedef struct _virStorageVolOptions virStorageVolOptions;
typedef virStorageVolOptions *virStorageVolOptionsPtr;
struct _virStorageVolOptions {
114
    int defaultFormat;
115 116 117 118 119 120
    virStorageVolFormatToString formatToString;
    virStorageVolFormatFromString formatFromString;
};

/* Flags to indicate mandatory components in the pool source */
enum {
O
Osier Yang 已提交
121 122 123 124 125 126 127
    VIR_STORAGE_POOL_SOURCE_HOST            = (1 << 0),
    VIR_STORAGE_POOL_SOURCE_DEVICE          = (1 << 1),
    VIR_STORAGE_POOL_SOURCE_DIR             = (1 << 2),
    VIR_STORAGE_POOL_SOURCE_ADAPTER         = (1 << 3),
    VIR_STORAGE_POOL_SOURCE_NAME            = (1 << 4),
    VIR_STORAGE_POOL_SOURCE_INITIATOR_IQN   = (1 << 5),
    VIR_STORAGE_POOL_SOURCE_NETWORK         = (1 << 6),
128 129 130 131 132
};

typedef struct _virStoragePoolOptions virStoragePoolOptions;
typedef virStoragePoolOptions *virStoragePoolOptionsPtr;
struct _virStoragePoolOptions {
E
Eric Blake 已提交
133
    unsigned int flags;
134
    int defaultFormat;
135 136 137

    virStoragePoolXMLNamespace ns;

138 139 140 141 142 143 144 145 146 147 148 149
    virStoragePoolFormatToString formatToString;
    virStoragePoolFormatFromString formatFromString;
};

typedef struct _virStoragePoolTypeInfo virStoragePoolTypeInfo;
typedef virStoragePoolTypeInfo *virStoragePoolTypeInfoPtr;
struct _virStoragePoolTypeInfo {
    int poolType;
    virStoragePoolOptions poolOptions;
    virStorageVolOptions volOptions;
};

150

E
Eric Blake 已提交
151 152 153 154 155 156 157 158 159
static int
virStorageVolumeFormatFromString(const char *format)
{
    int ret = virStorageFileFormatTypeFromString(format);
    if (ret == VIR_STORAGE_FILE_NONE)
        return -1;
    return ret;
}

160

161
static virStoragePoolTypeInfo poolTypeInfo[] = {
162 163 164 165 166 167 168 169
    {.poolType = VIR_STORAGE_POOL_LOGICAL,
     .poolOptions = {
         .flags = (VIR_STORAGE_POOL_SOURCE_NAME |
                   VIR_STORAGE_POOL_SOURCE_DEVICE),
         .defaultFormat = VIR_STORAGE_POOL_LOGICAL_LVM2,
         .formatFromString = virStoragePoolFormatLogicalTypeFromString,
         .formatToString = virStoragePoolFormatLogicalTypeToString,
     },
170
    },
171 172 173 174 175 176
    {.poolType = VIR_STORAGE_POOL_DIR,
     .volOptions = {
         .defaultFormat = VIR_STORAGE_FILE_RAW,
         .formatFromString = virStorageVolumeFormatFromString,
         .formatToString = virStorageFileFormatTypeToString,
     },
177
    },
178 179 180 181 182 183 184
    {.poolType = VIR_STORAGE_POOL_FS,
     .poolOptions = {
         .flags = (VIR_STORAGE_POOL_SOURCE_DEVICE),
         .defaultFormat = VIR_STORAGE_POOL_FS_AUTO,
         .formatFromString = virStoragePoolFormatFileSystemTypeFromString,
         .formatToString = virStoragePoolFormatFileSystemTypeToString,
      },
185
      .volOptions = {
186 187 188 189
         .defaultFormat = VIR_STORAGE_FILE_RAW,
         .formatFromString = virStorageVolumeFormatFromString,
         .formatToString = virStorageFileFormatTypeToString,
      },
190
    },
191 192 193 194 195 196 197 198
    {.poolType = VIR_STORAGE_POOL_NETFS,
     .poolOptions = {
         .flags = (VIR_STORAGE_POOL_SOURCE_HOST |
                   VIR_STORAGE_POOL_SOURCE_DIR),
         .defaultFormat = VIR_STORAGE_POOL_NETFS_AUTO,
         .formatFromString = virStoragePoolFormatFileSystemNetTypeFromString,
         .formatToString = virStoragePoolFormatFileSystemNetTypeToString,
      },
199
      .volOptions = {
200 201 202 203
         .defaultFormat = VIR_STORAGE_FILE_RAW,
         .formatFromString = virStorageVolumeFormatFromString,
         .formatToString = virStorageFileFormatTypeToString,
      },
204
    },
205 206 207 208 209 210 211
    {.poolType = VIR_STORAGE_POOL_ISCSI,
     .poolOptions = {
         .flags = (VIR_STORAGE_POOL_SOURCE_HOST |
                   VIR_STORAGE_POOL_SOURCE_DEVICE |
                   VIR_STORAGE_POOL_SOURCE_INITIATOR_IQN),
      },
    },
212 213 214 215 216 217 218 219
    {.poolType = VIR_STORAGE_POOL_ISCSI_DIRECT,
     .poolOptions = {
         .flags = (VIR_STORAGE_POOL_SOURCE_HOST |
                   VIR_STORAGE_POOL_SOURCE_DEVICE |
                   VIR_STORAGE_POOL_SOURCE_NETWORK |
                   VIR_STORAGE_POOL_SOURCE_INITIATOR_IQN),
      },
    },
220 221 222 223
    {.poolType = VIR_STORAGE_POOL_SCSI,
     .poolOptions = {
         .flags = (VIR_STORAGE_POOL_SOURCE_ADAPTER),
     },
224
    },
225 226 227 228 229 230
    {.poolType = VIR_STORAGE_POOL_RBD,
     .poolOptions = {
         .flags = (VIR_STORAGE_POOL_SOURCE_HOST |
                   VIR_STORAGE_POOL_SOURCE_NETWORK |
                   VIR_STORAGE_POOL_SOURCE_NAME),
      },
231
    },
232 233 234 235 236 237
    {.poolType = VIR_STORAGE_POOL_SHEEPDOG,
     .poolOptions = {
         .flags = (VIR_STORAGE_POOL_SOURCE_HOST |
                   VIR_STORAGE_POOL_SOURCE_NETWORK |
                   VIR_STORAGE_POOL_SOURCE_NAME),
     },
238
    },
239 240 241 242 243 244 245 246 247 248 249 250 251
    {.poolType = VIR_STORAGE_POOL_GLUSTER,
     .poolOptions = {
         .flags = (VIR_STORAGE_POOL_SOURCE_HOST |
                   VIR_STORAGE_POOL_SOURCE_NETWORK |
                   VIR_STORAGE_POOL_SOURCE_NAME |
                   VIR_STORAGE_POOL_SOURCE_DIR),
     },
     .volOptions = {
         .defaultFormat = VIR_STORAGE_FILE_RAW,
         .formatToString = virStorageFileFormatTypeToString,
         .formatFromString = virStorageVolumeFormatFromString,
     }
    },
252 253 254 255
    {.poolType = VIR_STORAGE_POOL_MPATH,
     .volOptions = {
         .formatToString = virStoragePoolFormatDiskTypeToString,
     }
256
    },
257 258 259 260 261 262 263 264 265 266 267 268
    {.poolType = VIR_STORAGE_POOL_DISK,
     .poolOptions = {
         .flags = (VIR_STORAGE_POOL_SOURCE_DEVICE),
         .defaultFormat = VIR_STORAGE_POOL_DISK_UNKNOWN,
         .formatFromString = virStoragePoolFormatDiskTypeFromString,
         .formatToString = virStoragePoolFormatDiskTypeToString,
     },
     .volOptions = {
         .defaultFormat = VIR_STORAGE_VOL_DISK_NONE,
         .formatFromString = virStorageVolFormatDiskTypeFromString,
         .formatToString = virStorageVolFormatDiskTypeToString,
     },
R
Roman Bogorodskiy 已提交
269 270 271
    },
    {.poolType = VIR_STORAGE_POOL_ZFS,
     .poolOptions = {
272 273
         .flags = (VIR_STORAGE_POOL_SOURCE_NAME |
                   VIR_STORAGE_POOL_SOURCE_DEVICE),
R
Roman Bogorodskiy 已提交
274 275 276
         .defaultFormat = VIR_STORAGE_FILE_RAW,
     },
    },
277 278 279 280 281 282 283 284 285 286
    {.poolType = VIR_STORAGE_POOL_VSTORAGE,
     .poolOptions = {
        .flags = VIR_STORAGE_POOL_SOURCE_NAME,
     },
     .volOptions = {
        .defaultFormat = VIR_STORAGE_FILE_RAW,
        .formatFromString = virStorageVolumeFormatFromString,
        .formatToString = virStorageFileFormatTypeToString,
     },
    },
287 288 289 290
};


static virStoragePoolTypeInfoPtr
291 292
virStoragePoolTypeInfoLookup(int type)
{
293
    size_t i;
294
    for (i = 0; i < ARRAY_CARDINALITY(poolTypeInfo); i++)
295 296 297
        if (poolTypeInfo[i].poolType == type)
            return &poolTypeInfo[i];

298 299
    virReportError(VIR_ERR_INTERNAL_ERROR,
                   _("missing backend for pool type %d"), type);
300 301 302
    return NULL;
}

303

304
static virStoragePoolOptionsPtr
305 306
virStoragePoolOptionsForPoolType(int type)
{
307 308 309 310 311 312
    virStoragePoolTypeInfoPtr backend = virStoragePoolTypeInfoLookup(type);
    if (backend == NULL)
        return NULL;
    return &backend->poolOptions;
}

313

314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341
/* virStoragePoolOptionsPoolTypeSetXMLNamespace:
 * @type: virStoragePoolType
 * @ns: xmlopt namespace pointer
 *
 * Store the @ns in the pool options for the particular backend.
 * This allows the parse/format code to then directly call the Namespace
 * method space (parse, format, href, free) as needed during processing.
 *
 * Returns: 0 on success, -1 on failure.
 */
int
virStoragePoolOptionsPoolTypeSetXMLNamespace(int type,
                                             virStoragePoolXMLNamespacePtr ns)
{
    int ret = -1;
    virStoragePoolTypeInfoPtr backend = virStoragePoolTypeInfoLookup(type);

    if (!backend)
        goto cleanup;

    backend->poolOptions.ns = *ns;
    ret = 0;

 cleanup:
    return ret;
}


342
static virStorageVolOptionsPtr
343 344
virStorageVolOptionsForPoolType(int type)
{
345 346 347 348 349 350 351
    virStoragePoolTypeInfoPtr backend = virStoragePoolTypeInfoLookup(type);
    if (backend == NULL)
        return NULL;
    return &backend->volOptions;
}


352
void
353 354
virStorageVolDefFree(virStorageVolDefPtr def)
{
355
    size_t i;
356 357 358 359

    if (!def)
        return;

360 361
    VIR_FREE(def->name);
    VIR_FREE(def->key);
362

363
    for (i = 0; i < def->source.nextent; i++)
364 365
        VIR_FREE(def->source.extents[i].path);
    VIR_FREE(def->source.extents);
366

367
    virStorageSourceClear(&def->target);
368
    VIR_FREE(def);
369 370
}

371

372 373 374 375 376 377 378
void
virStoragePoolSourceDeviceClear(virStoragePoolSourceDevicePtr dev)
{
    VIR_FREE(dev->freeExtents);
    VIR_FREE(dev->path);
}

379

380
void
381 382
virStoragePoolSourceClear(virStoragePoolSourcePtr source)
{
383
    size_t i;
384

385
    if (!source)
386 387
        return;

388
    for (i = 0; i < source->nhost; i++)
389 390 391
        VIR_FREE(source->hosts[i].name);
    VIR_FREE(source->hosts);

392 393
    for (i = 0; i < source->ndevice; i++)
        virStoragePoolSourceDeviceClear(&source->devices[i]);
394 395 396
    VIR_FREE(source->devices);
    VIR_FREE(source->dir);
    VIR_FREE(source->name);
397
    virStorageAdapterClear(&source->adapter);
398
    virStorageSourceInitiatorClear(&source->initiator);
399
    virStorageAuthDefFree(source->auth);
400 401
    VIR_FREE(source->vendor);
    VIR_FREE(source->product);
402 403
}

404

405 406 407 408 409 410 411
void
virStoragePoolSourceFree(virStoragePoolSourcePtr source)
{
    virStoragePoolSourceClear(source);
    VIR_FREE(source);
}

412

413
void
414 415
virStoragePoolDefFree(virStoragePoolDefPtr def)
{
416 417 418 419 420
    if (!def)
        return;

    VIR_FREE(def->name);

421
    virStoragePoolSourceClear(&def->source);
422

423 424
    VIR_FREE(def->target.path);
    VIR_FREE(def->target.perms.label);
425 426
    if (def->namespaceData && def->ns.free)
        (def->ns.free)(def->namespaceData);
427
    VIR_FREE(def);
428 429 430
}


431
static int
432
virStoragePoolDefParseSource(xmlXPathContextPtr ctxt,
433 434
                             virStoragePoolSourcePtr source,
                             int pool_type,
435 436
                             xmlNodePtr node)
{
437
    int ret = -1;
438
    xmlNodePtr relnode, authnode;
439
    xmlNodePtr adapternode;
440 441
    int nsource;
    size_t i;
442
    virStoragePoolOptionsPtr options;
443
    int n;
444
    VIR_AUTOPTR(virStorageAuthDef) authdef = NULL;
445 446 447
    VIR_AUTOFREE(char *) port = NULL;
    VIR_AUTOFREE(char *) ver = NULL;
    VIR_AUTOFREE(xmlNodePtr *) nodeset = NULL;
448 449 450 451

    relnode = ctxt->node;
    ctxt->node = node;

452
    if ((options = virStoragePoolOptionsForPoolType(pool_type)) == NULL)
453 454
        goto cleanup;

455
    source->name = virXPathString("string(./name)", ctxt);
456
    if (pool_type == VIR_STORAGE_POOL_RBD && source->name == NULL) {
457
        virReportError(VIR_ERR_XML_ERROR, "%s",
458
                       _("element 'name' is mandatory for RBD pool"));
459 460
        goto cleanup;
    }
461 462

    if (options->formatFromString) {
463 464 465
        VIR_AUTOFREE(char *) format = NULL;

        format = virXPathString("string(./format/@type)", ctxt);
466 467 468 469 470 471
        if (format == NULL)
            source->format = options->defaultFormat;
        else
            source->format = options->formatFromString(format);

        if (source->format < 0) {
472
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
473
                           _("unknown pool format type %s"), format);
474 475 476 477
            goto cleanup;
        }
    }

478 479
    if ((n = virXPathNodeSet("./host", ctxt, &nodeset)) < 0)
        goto cleanup;
480

481 482
    if (n) {
        if (VIR_ALLOC_N(source->hosts, n) < 0)
483
            goto cleanup;
484
        source->nhost = n;
485

486
        for (i = 0; i < source->nhost; i++) {
487 488
            source->hosts[i].name = virXMLPropString(nodeset[i], "name");
            if (!source->hosts[i].name) {
489 490
                virReportError(VIR_ERR_XML_ERROR, "%s",
                               _("missing storage pool host name"));
491 492 493 494 495 496
                goto cleanup;
            }

            port = virXMLPropString(nodeset[i], "port");
            if (port) {
                if (virStrToLong_i(port, NULL, 10, &source->hosts[i].port) < 0) {
497 498 499
                    virReportError(VIR_ERR_XML_ERROR,
                                   _("Invalid port number: %s"),
                                   port);
500 501 502 503 504
                    goto cleanup;
                }
            }
        }
    }
505

506
    VIR_FREE(nodeset);
507 508

    virStorageSourceInitiatorParseXML(ctxt, &source->initiator);
509

510
    nsource = virXPathNodeSet("./device", ctxt, &nodeset);
511 512 513
    if (nsource < 0)
        goto cleanup;

514
    for (i = 0; i < nsource; i++) {
515
        VIR_AUTOFREE(char *) partsep = NULL;
516 517 518 519 520 521
        virStoragePoolSourceDevice dev = { .path = NULL };
        dev.path = virXMLPropString(nodeset[i], "path");

        if (dev.path == NULL) {
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("missing storage pool source device path"));
522 523 524
            goto cleanup;
        }

525 526 527 528 529 530 531 532 533 534 535 536
        partsep = virXMLPropString(nodeset[i], "part_separator");
        if (partsep) {
            dev.part_separator = virTristateBoolTypeFromString(partsep);
            if (dev.part_separator <= 0) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("invalid part_separator setting '%s'"),
                               partsep);
                virStoragePoolSourceDeviceClear(&dev);
                goto cleanup;
            }
        }

537 538 539
        if (VIR_APPEND_ELEMENT(source->devices, source->ndevice, dev) < 0) {
            virStoragePoolSourceDeviceClear(&dev);
            goto cleanup;
540
        }
541

542 543
    }

544
    source->dir = virXPathString("string(./dir/@path)", ctxt);
545 546 547 548
    /* In gluster, a missing dir defaults to "/" */
    if (!source->dir && pool_type == VIR_STORAGE_POOL_GLUSTER &&
        VIR_STRDUP(source->dir, "/") < 0)
        goto cleanup;
549

550
    if ((adapternode = virXPathNode("./adapter", ctxt))) {
551
        if (virStorageAdapterParseXML(&source->adapter, adapternode, ctxt) < 0)
552 553
            goto cleanup;
    }
554

555
    if ((authnode = virXPathNode("./auth", ctxt))) {
556
        if (!(authdef = virStorageAuthDefParse(authnode, ctxt)))
557 558 559 560 561 562 563 564
            goto cleanup;

        if (authdef->authType == VIR_STORAGE_AUTH_TYPE_NONE) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("storage pool missing auth type"));
            goto cleanup;
        }

565
        VIR_STEAL_PTR(source->auth, authdef);
566
    }
567

568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585
    /* Option protocol version string (NFSvN) */
    if ((ver = virXPathString("string(./protocol/@ver)", ctxt))) {
        if ((source->format != VIR_STORAGE_POOL_NETFS_NFS) &&
            (source->format != VIR_STORAGE_POOL_NETFS_AUTO)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("storage pool protocol ver unsupported for "
                             "pool type '%s'"),
                           virStoragePoolFormatFileSystemNetTypeToString(source->format));
            goto cleanup;
        }
        if (virStrToLong_uip(ver, NULL, 0, &source->protocolVer) < 0) {
            virReportError(VIR_ERR_XML_ERROR,
                           _("storage pool protocol ver '%s' is malformaed"),
                           ver);
            goto cleanup;
        }
    }

586 587 588
    source->vendor = virXPathString("string(./vendor/@name)", ctxt);
    source->product = virXPathString("string(./product/@name)", ctxt);

589
    ret = 0;
590
 cleanup:
591 592 593 594
    ctxt->node = relnode;

    return ret;
}
595

596

597
virStoragePoolSourcePtr
598
virStoragePoolDefParseSourceString(const char *srcSpec,
599 600 601 602 603
                                   int pool_type)
{
    xmlDocPtr doc = NULL;
    xmlNodePtr node = NULL;
    xmlXPathContextPtr xpath_ctxt = NULL;
604 605
    virStoragePoolSourcePtr ret = NULL;
    VIR_AUTOPTR(virStoragePoolSource) def = NULL;
606

607 608 609
    if (!(doc = virXMLParseStringCtxt(srcSpec,
                                      _("(storage_source_specification)"),
                                      &xpath_ctxt)))
610 611
        goto cleanup;

612
    if (VIR_ALLOC(def) < 0)
613 614
        goto cleanup;

615
    if (!(node = virXPathNode("/source", xpath_ctxt))) {
616 617
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("root element was not source"));
618 619 620
        goto cleanup;
    }

621
    if (virStoragePoolDefParseSource(xpath_ctxt, def, pool_type,
622 623 624
                                     node) < 0)
        goto cleanup;

625
    VIR_STEAL_PTR(ret, def);
626
 cleanup:
627 628 629 630 631
    xmlFreeDoc(doc);
    xmlXPathFreeContext(xpath_ctxt);

    return ret;
}
632

633

634
static int
635
virStorageDefParsePerms(xmlXPathContextPtr ctxt,
636
                        virStoragePermsPtr perms,
637
                        const char *permxpath)
638
{
639
    long long val;
640 641 642
    int ret = -1;
    xmlNodePtr relnode;
    xmlNodePtr node;
643
    VIR_AUTOFREE(char *) mode = NULL;
644

645
    node = virXPathNode(permxpath, ctxt);
646 647
    if (node == NULL) {
        /* Set default values if there is not <permissions> element */
648
        perms->mode = (mode_t) -1;
P
Philipp Hahn 已提交
649 650
        perms->uid = (uid_t) -1;
        perms->gid = (gid_t) -1;
651 652 653 654 655 656 657
        perms->label = NULL;
        return 0;
    }

    relnode = ctxt->node;
    ctxt->node = node;

658
    if ((mode = virXPathString("string(./mode)", ctxt))) {
659 660 661
        int tmp;

        if (virStrToLong_i(mode, NULL, 8, &tmp) < 0 || (tmp & ~0777)) {
662 663
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("malformed octal mode"));
664
            goto error;
665
        }
666
        perms->mode = tmp;
667 668
    } else {
        perms->mode = (mode_t) -1;
669 670
    }

671
    if (virXPathNode("./owner", ctxt) == NULL) {
P
Philipp Hahn 已提交
672
        perms->uid = (uid_t) -1;
673
    } else {
674
        /* We previously could output -1, so continue to parse it */
675
        if (virXPathLongLong("number(./owner)", ctxt, &val) < 0 ||
676 677
            ((uid_t)val != val &&
             val != -1)) {
678 679
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("malformed owner element"));
680
            goto error;
681
        }
682 683

        perms->uid = val;
684 685
    }

686
    if (virXPathNode("./group", ctxt) == NULL) {
P
Philipp Hahn 已提交
687
        perms->gid = (gid_t) -1;
688
    } else {
689
        /* We previously could output -1, so continue to parse it */
690
        if (virXPathLongLong("number(./group)", ctxt, &val) < 0 ||
691 692
            ((gid_t) val != val &&
             val != -1)) {
693 694
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("malformed group element"));
695
            goto error;
696
        }
697
        perms->gid = val;
698 699 700
    }

    /* NB, we're ignoring missing labels here - they'll simply inherit */
701
    perms->label = virXPathString("string(./label)", ctxt);
702

703
    ret = 0;
704
 error:
705 706
    ctxt->node = relnode;
    return ret;
707 708
}

709

J
John Ferlan 已提交
710
virStoragePoolDefPtr
711 712
virStoragePoolDefParseXML(xmlXPathContextPtr ctxt)
{
713
    virStoragePoolOptionsPtr options;
714
    virStoragePoolDefPtr ret = NULL;
715
    xmlNodePtr source_node;
716
    VIR_AUTOPTR(virStoragePoolDef) def = NULL;
717 718 719
    VIR_AUTOFREE(char *) type = NULL;
    VIR_AUTOFREE(char *) uuid = NULL;
    VIR_AUTOFREE(char *) target_path = NULL;
720

721
    if (VIR_ALLOC(def) < 0)
722 723
        return NULL;

724
    type = virXPathString("string(./@type)", ctxt);
725 726 727
    if (type == NULL) {
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("storage pool missing type attribute"));
728
        return NULL;
729 730
    }

731
    if ((def->type = virStoragePoolTypeFromString(type)) < 0) {
732
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
733
                       _("unknown storage pool type %s"), type);
734
        return NULL;
735 736
    }

737
    if ((options = virStoragePoolOptionsForPoolType(def->type)) == NULL)
738
        return NULL;
739

740
    source_node = virXPathNode("./source", ctxt);
741
    if (source_node) {
742
        if (virStoragePoolDefParseSource(ctxt, &def->source, def->type,
743
                                         source_node) < 0)
744
            return NULL;
745 746
    } else {
        if (options->formatFromString)
747
            def->source.format = options->defaultFormat;
748 749
    }

750 751
    def->name = virXPathString("string(./name)", ctxt);
    if (def->name == NULL &&
752
        options->flags & VIR_STORAGE_POOL_SOURCE_NAME &&
753
        VIR_STRDUP(def->name, def->source.name) < 0)
754 755
        return NULL;

756
    if (def->name == NULL) {
757 758
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("missing pool source name element"));
759
        return NULL;
760 761
    }

762
    if (strchr(def->name, '/')) {
763
        virReportError(VIR_ERR_XML_ERROR,
764
                       _("name %s cannot contain '/'"), def->name);
765
        return NULL;
766 767
    }

768
    uuid = virXPathString("string(./uuid)", ctxt);
769
    if (uuid == NULL) {
770
        if (virUUIDGenerate(def->uuid) < 0) {
771 772
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("unable to generate uuid"));
773
            return NULL;
774 775
        }
    } else {
776
        if (virUUIDParse(uuid, def->uuid) < 0) {
777 778
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("malformed uuid element"));
779
            return NULL;
780 781 782
        }
    }

783
    if (options->flags & VIR_STORAGE_POOL_SOURCE_HOST) {
784
        if (!def->source.nhost) {
785
            virReportError(VIR_ERR_XML_ERROR, "%s",
786
                           _("missing storage pool source host name"));
787
            return NULL;
788 789 790
        }
    }

791
    if (options->flags & VIR_STORAGE_POOL_SOURCE_DIR) {
792
        if (!def->source.dir) {
793 794
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("missing storage pool source path"));
795
            return NULL;
796 797
        }
    }
798
    if (options->flags & VIR_STORAGE_POOL_SOURCE_NAME) {
799
        if (def->source.name == NULL) {
800
            /* source name defaults to pool name */
801
            if (VIR_STRDUP(def->source.name, def->name) < 0)
802
                return NULL;
803 804
        }
    }
805

806
    if ((options->flags & VIR_STORAGE_POOL_SOURCE_ADAPTER) &&
807
        (virStorageAdapterValidate(&def->source.adapter)) < 0)
808
            return NULL;
809

810 811
    /* If DEVICE is the only source type, then its required */
    if (options->flags == VIR_STORAGE_POOL_SOURCE_DEVICE) {
812
        if (!def->source.ndevice) {
813 814
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("missing storage pool source device name"));
815
            return NULL;
816 817 818
        }
    }

819 820 821
    /* When we are working with a virtual disk we can skip the target
     * path and permissions */
    if (!(options->flags & VIR_STORAGE_POOL_SOURCE_NETWORK)) {
822 823
        if (def->type == VIR_STORAGE_POOL_LOGICAL) {
            if (virAsprintf(&target_path, "/dev/%s", def->source.name) < 0)
824
                return NULL;
825 826
        } else if (def->type == VIR_STORAGE_POOL_ZFS) {
            if (virAsprintf(&target_path, "/dev/zvol/%s", def->source.name) < 0)
827
                return NULL;
828 829 830 831 832
        } else {
            target_path = virXPathString("string(./target/path)", ctxt);
            if (!target_path) {
                virReportError(VIR_ERR_XML_ERROR, "%s",
                               _("missing storage pool target path"));
833
                return NULL;
834
            }
835
        }
836 837
        def->target.path = virFileSanitizePath(target_path);
        if (!def->target.path)
838
            return NULL;
839

840
        if (virStorageDefParsePerms(ctxt, &def->target.perms,
841
                                    "./target/permissions") < 0)
842
            return NULL;
843
    }
844

845 846
    if (def->type == VIR_STORAGE_POOL_ISCSI_DIRECT &&
        !def->source.initiator.iqn) {
847 848
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("missing initiator IQN"));
849
        return NULL;
850 851
    }

852 853
    /* Make a copy of all the callback pointers here for easier use,
     * especially during the virStoragePoolSourceClear method */
854 855 856
    def->ns = options->ns;
    if (def->ns.parse &&
        (def->ns.parse)(ctxt, &def->namespaceData) < 0)
857
        return NULL;
858

859
    VIR_STEAL_PTR(ret, def);
860
    return ret;
861 862
}

863

864
virStoragePoolDefPtr
865
virStoragePoolDefParseNode(xmlDocPtr xml,
866 867
                           xmlNodePtr root)
{
868 869 870
    xmlXPathContextPtr ctxt = NULL;
    virStoragePoolDefPtr def = NULL;

871
    if (!virXMLNodeNameEqual(root, "pool")) {
872
        virReportError(VIR_ERR_XML_ERROR,
873 874 875
                       _("unexpected root element <%s>, "
                         "expecting <pool>"),
                       root->name);
876 877 878 879 880
        goto cleanup;
    }

    ctxt = xmlXPathNewContext(xml);
    if (ctxt == NULL) {
881
        virReportOOMError();
882 883 884 885
        goto cleanup;
    }

    ctxt->node = root;
886
    def = virStoragePoolDefParseXML(ctxt);
887
 cleanup:
888 889 890 891
    xmlXPathFreeContext(ctxt);
    return def;
}

892

893
static virStoragePoolDefPtr
894
virStoragePoolDefParse(const char *xmlStr,
895 896
                       const char *filename)
{
897
    virStoragePoolDefPtr ret = NULL;
J
Jiri Denemark 已提交
898
    xmlDocPtr xml;
899

900
    if ((xml = virXMLParse(filename, xmlStr, _("(storage_pool_definition)")))) {
J
Jiri Denemark 已提交
901 902
        ret = virStoragePoolDefParseNode(xml, xmlDocGetRootElement(xml));
        xmlFreeDoc(xml);
903 904
    }

905 906 907
    return ret;
}

908

909
virStoragePoolDefPtr
910
virStoragePoolDefParseString(const char *xmlStr)
911
{
912
    return virStoragePoolDefParse(xmlStr, NULL);
913 914
}

915

916
virStoragePoolDefPtr
917
virStoragePoolDefParseFile(const char *filename)
918
{
919
    return virStoragePoolDefParse(NULL, filename);
920 921
}

922

923
static int
924
virStoragePoolSourceFormat(virBufferPtr buf,
925
                           virStoragePoolOptionsPtr options,
926 927
                           virStoragePoolSourcePtr src)
{
928
    size_t i, j;
929

930 931 932
    virBufferAddLit(buf, "<source>\n");
    virBufferAdjustIndent(buf, 2);

933 934
    if ((options->flags & VIR_STORAGE_POOL_SOURCE_HOST) && src->nhost) {
        for (i = 0; i < src->nhost; i++) {
935
            virBufferEscapeString(buf, "<host name='%s'",
936
                                  src->hosts[i].name);
937 938 939 940
            if (src->hosts[i].port)
                virBufferAsprintf(buf, " port='%d'", src->hosts[i].port);
            virBufferAddLit(buf, "/>\n");
        }
941
    }
942

943
    if ((options->flags & VIR_STORAGE_POOL_SOURCE_DEVICE) &&
944
        src->ndevice) {
945
        for (i = 0; i < src->ndevice; i++) {
946 947 948 949 950 951 952
            virBufferEscapeString(buf, "<device path='%s'",
                                  src->devices[i].path);
            if (src->devices[i].part_separator !=
                VIR_TRISTATE_SWITCH_ABSENT) {
                virBufferAsprintf(buf, " part_separator='%s'",
                                  virTristateBoolTypeToString(src->devices[i].part_separator));
            }
953
            if (src->devices[i].nfreeExtent) {
954
                virBufferAddLit(buf, ">\n");
955
                virBufferAdjustIndent(buf, 2);
956
                for (j = 0; j < src->devices[i].nfreeExtent; j++) {
957
                    virBufferAsprintf(buf, "<freeExtent start='%llu' end='%llu'/>\n",
958 959 960
                                      src->devices[i].freeExtents[j].start,
                                      src->devices[i].freeExtents[j].end);
                }
961 962
                virBufferAdjustIndent(buf, -2);
                virBufferAddLit(buf, "</device>\n");
963
            } else {
964
                virBufferAddLit(buf, "/>\n");
965
            }
966 967
        }
    }
968

969
    if (options->flags & VIR_STORAGE_POOL_SOURCE_DIR)
970
        virBufferEscapeString(buf, "<dir path='%s'/>\n", src->dir);
971

972
    if ((options->flags & VIR_STORAGE_POOL_SOURCE_ADAPTER) &&
973 974 975
        (src->adapter.type == VIR_STORAGE_ADAPTER_TYPE_FC_HOST ||
         src->adapter.type == VIR_STORAGE_ADAPTER_TYPE_SCSI_HOST))
        virStorageAdapterFormat(buf, &src->adapter);
976

977
    if (options->flags & VIR_STORAGE_POOL_SOURCE_NAME)
978
        virBufferEscapeString(buf, "<name>%s</name>\n", src->name);
979

980 981
    if (options->flags & VIR_STORAGE_POOL_SOURCE_INITIATOR_IQN)
        virStorageSourceInitiatorFormatXML(&src->initiator, buf);
D
David Allan 已提交
982

983 984 985
    if (options->formatToString) {
        const char *format = (options->formatToString)(src->format);
        if (!format) {
986 987 988
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("unknown pool format number %d"),
                           src->format);
989 990
            return -1;
        }
991
        virBufferAsprintf(buf, "<format type='%s'/>\n", format);
992 993
    }

994 995
    if (src->auth)
        virStorageAuthDefFormat(buf, src->auth);
996

997 998 999
    if (src->protocolVer)
        virBufferAsprintf(buf, "<protocol ver='%u'/>\n", src->protocolVer);

1000 1001
    virBufferEscapeString(buf, "<vendor name='%s'/>\n", src->vendor);
    virBufferEscapeString(buf, "<product name='%s'/>\n", src->product);
1002

1003 1004
    virBufferAdjustIndent(buf, -2);
    virBufferAddLit(buf, "</source>\n");
1005 1006 1007
    return 0;
}

1008

1009 1010 1011
static int
virStoragePoolDefFormatBuf(virBufferPtr buf,
                           virStoragePoolDefPtr def)
1012
{
1013
    virStoragePoolOptionsPtr options;
1014
    char uuid[VIR_UUID_STRING_BUFLEN];
1015
    const char *type;
1016

1017
    options = virStoragePoolOptionsForPoolType(def->type);
1018
    if (options == NULL)
1019
        return -1;
1020

1021
    type = virStoragePoolTypeToString(def->type);
1022
    if (!type) {
1023 1024
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("unexpected pool type"));
1025
        return -1;
1026
    }
1027 1028 1029 1030
    virBufferAsprintf(buf, "<pool type='%s'", type);
    if (def->namespaceData && def->ns.href)
        virBufferAsprintf(buf, " %s", (def->ns.href)());
    virBufferAddLit(buf, ">\n");
1031 1032
    virBufferAdjustIndent(buf, 2);
    virBufferEscapeString(buf, "<name>%s</name>\n", def->name);
1033 1034

    virUUIDFormat(def->uuid, uuid);
1035
    virBufferAsprintf(buf, "<uuid>%s</uuid>\n", uuid);
1036

1037
    virBufferAsprintf(buf, "<capacity unit='bytes'>%llu</capacity>\n",
1038
                      def->capacity);
1039
    virBufferAsprintf(buf, "<allocation unit='bytes'>%llu</allocation>\n",
1040
                      def->allocation);
1041
    virBufferAsprintf(buf, "<available unit='bytes'>%llu</available>\n",
1042
                      def->available);
1043

1044 1045
    if (virStoragePoolSourceFormat(buf, options, &def->source) < 0)
        return -1;
1046

1047
    /* RBD, Sheepdog, Gluster and Iscsi-direct devices are not local block devs nor
1048
     * files, so they don't have a target */
1049
    if (def->type != VIR_STORAGE_POOL_RBD &&
1050
        def->type != VIR_STORAGE_POOL_SHEEPDOG &&
1051 1052
        def->type != VIR_STORAGE_POOL_GLUSTER &&
        def->type != VIR_STORAGE_POOL_ISCSI_DIRECT) {
1053 1054
        virBufferAddLit(buf, "<target>\n");
        virBufferAdjustIndent(buf, 2);
1055

1056
        virBufferEscapeString(buf, "<path>%s</path>\n", def->target.path);
1057

1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078
        if (def->target.perms.mode != (mode_t) -1 ||
            def->target.perms.uid != (uid_t) -1 ||
            def->target.perms.gid != (gid_t) -1 ||
            def->target.perms.label) {
            virBufferAddLit(buf, "<permissions>\n");
            virBufferAdjustIndent(buf, 2);
            if (def->target.perms.mode != (mode_t) -1)
                virBufferAsprintf(buf, "<mode>0%o</mode>\n",
                                  def->target.perms.mode);
            if (def->target.perms.uid != (uid_t) -1)
                virBufferAsprintf(buf, "<owner>%d</owner>\n",
                                  (int) def->target.perms.uid);
            if (def->target.perms.gid != (gid_t) -1)
                virBufferAsprintf(buf, "<group>%d</group>\n",
                                  (int) def->target.perms.gid);
            virBufferEscapeString(buf, "<label>%s</label>\n",
                                  def->target.perms.label);

            virBufferAdjustIndent(buf, -2);
            virBufferAddLit(buf, "</permissions>\n");
        }
1079

1080 1081
        virBufferAdjustIndent(buf, -2);
        virBufferAddLit(buf, "</target>\n");
1082
    }
1083 1084 1085 1086 1087 1088

    if (def->namespaceData && def->ns.format) {
        if ((def->ns.format)(buf, def->namespaceData) < 0)
            return -1;
    }

1089 1090 1091 1092 1093 1094
    virBufferAdjustIndent(buf, -2);
    virBufferAddLit(buf, "</pool>\n");

    return 0;
}

1095

1096 1097 1098 1099 1100 1101 1102
char *
virStoragePoolDefFormat(virStoragePoolDefPtr def)
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    if (virStoragePoolDefFormatBuf(&buf, def) < 0)
        goto error;
1103

1104
    if (virBufferCheckError(&buf) < 0)
1105
        goto error;
1106

1107
    return virBufferContentAndReset(&buf);
1108

1109
 error:
1110
    virBufferFreeAndReset(&buf);
1111 1112 1113 1114 1115
    return NULL;
}


static int
1116
virStorageSize(const char *unit,
1117
               const char *val,
1118 1119
               unsigned long long *ret)
{
J
Ján Tomko 已提交
1120
    if (virStrToLong_ullp(val, NULL, 10, ret) < 0) {
1121 1122
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("malformed capacity element"));
1123 1124
        return -1;
    }
1125 1126 1127 1128
    /* off_t is signed, so you cannot create a file larger than 2**63
     * bytes in the first place.  */
    if (virScaleInteger(ret, unit, 1, LLONG_MAX) < 0)
        return -1;
1129 1130 1131 1132

    return 0;
}

1133

1134
static virStorageVolDefPtr
1135
virStorageVolDefParseXML(virStoragePoolDefPtr pool,
1136 1137
                         xmlXPathContextPtr ctxt,
                         unsigned int flags)
1138
{
1139
    virStorageVolDefPtr ret = NULL;
1140
    virStorageVolOptionsPtr options;
1141
    xmlNodePtr node;
1142 1143
    size_t i;
    int n;
1144
    VIR_AUTOPTR(virStorageVolDef) def = NULL;
1145 1146 1147 1148 1149 1150
    VIR_AUTOFREE(char *) type = NULL;
    VIR_AUTOFREE(char *) allocation = NULL;
    VIR_AUTOFREE(char *) capacity = NULL;
    VIR_AUTOFREE(char *) unit = NULL;
    VIR_AUTOFREE(char *) backingStore = NULL;
    VIR_AUTOFREE(xmlNodePtr *) nodes = NULL;
1151

1152 1153
    virCheckFlags(VIR_VOL_XML_PARSE_NO_CAPACITY |
                  VIR_VOL_XML_PARSE_OPT_CAPACITY, NULL);
1154

1155
    options = virStorageVolOptionsForPoolType(pool->type);
1156 1157 1158
    if (options == NULL)
        return NULL;

1159
    if (VIR_ALLOC(def) < 0)
1160 1161
        return NULL;

1162
    def->target.type = VIR_STORAGE_TYPE_FILE;
1163

1164 1165
    def->name = virXPathString("string(./name)", ctxt);
    if (def->name == NULL) {
1166 1167
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("missing volume name element"));
1168
        return NULL;
1169 1170
    }

1171
    /* Normally generated by pool refresh, but useful for unit tests */
1172
    def->key = virXPathString("string(./key)", ctxt);
1173

1174 1175 1176
    /* Technically overridden by pool refresh, but useful for unit tests */
    type = virXPathString("string(./@type)", ctxt);
    if (type) {
1177
        if ((def->type = virStorageVolTypeFromString(type)) < 0) {
1178
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1179
                           _("unknown volume type '%s'"), type);
1180
            return NULL;
1181 1182 1183
        }
    }

1184
    if ((backingStore = virXPathString("string(./backingStore/path)", ctxt))) {
1185
        if (!(def->target.backingStore = virStorageSourceNew()))
1186
            return NULL;
1187

1188
        def->target.backingStore->type = VIR_STORAGE_TYPE_FILE;
1189

1190
        def->target.backingStore->path = backingStore;
1191 1192 1193
        backingStore = NULL;

        if (options->formatFromString) {
1194 1195 1196
            VIR_AUTOFREE(char *) format = NULL;

            format = virXPathString("string(./backingStore/format/@type)", ctxt);
1197
            if (format == NULL)
1198
                def->target.backingStore->format = options->defaultFormat;
1199
            else
1200
                def->target.backingStore->format = (options->formatFromString)(format);
1201

1202
            if (def->target.backingStore->format < 0) {
1203 1204
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("unknown volume format type %s"), format);
1205
                return NULL;
1206 1207 1208
            }
        }

1209
        if (VIR_ALLOC(def->target.backingStore->perms) < 0)
1210
            return NULL;
1211
        if (virStorageDefParsePerms(ctxt, def->target.backingStore->perms,
1212
                                    "./backingStore/permissions") < 0)
1213
            return NULL;
1214 1215
    }

1216 1217
    capacity = virXPathString("string(./capacity)", ctxt);
    unit = virXPathString("string(./capacity/@unit)", ctxt);
1218
    if (capacity) {
1219
        if (virStorageSize(unit, capacity, &def->target.capacity) < 0)
1220
            return NULL;
1221
    } else if (!(flags & VIR_VOL_XML_PARSE_NO_CAPACITY) &&
1222
               !((flags & VIR_VOL_XML_PARSE_OPT_CAPACITY) &&
1223
                 virStorageSourceHasBacking(&def->target))) {
1224
        virReportError(VIR_ERR_XML_ERROR, "%s", _("missing capacity element"));
1225
        return NULL;
1226
    }
1227
    VIR_FREE(unit);
1228

1229
    allocation = virXPathString("string(./allocation)", ctxt);
1230
    if (allocation) {
1231
        unit = virXPathString("string(./allocation/@unit)", ctxt);
1232
        if (virStorageSize(unit, allocation, &def->target.allocation) < 0)
1233
            return NULL;
1234
        def->target.has_allocation = true;
1235
    } else {
1236
        def->target.allocation = def->target.capacity;
1237 1238
    }

1239
    def->target.path = virXPathString("string(./target/path)", ctxt);
1240
    if (options->formatFromString) {
1241 1242 1243
        VIR_AUTOFREE(char *) format = NULL;

        format = virXPathString("string(./target/format/@type)", ctxt);
1244
        if (format == NULL)
1245
            def->target.format = options->defaultFormat;
1246
        else
1247
            def->target.format = (options->formatFromString)(format);
1248

1249
        if (def->target.format < 0) {
1250
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1251
                           _("unknown volume format type %s"), format);
1252
            return NULL;
1253 1254 1255
        }
    }

1256
    if (VIR_ALLOC(def->target.perms) < 0)
1257
        return NULL;
1258
    if (virStorageDefParsePerms(ctxt, def->target.perms,
1259
                                "./target/permissions") < 0)
1260
        return NULL;
1261

1262
    node = virXPathNode("./target/encryption", ctxt);
1263
    if (node != NULL) {
1264 1265
        def->target.encryption = virStorageEncryptionParseNode(node, ctxt);
        if (def->target.encryption == NULL)
1266
            return NULL;
1267 1268
    }

1269 1270
    def->target.compat = virXPathString("string(./target/compat)", ctxt);
    if (virStorageFileCheckCompat(def->target.compat) < 0)
1271
        return NULL;
1272

C
Chunyan Liu 已提交
1273
    if (virXPathNode("./target/nocow", ctxt))
1274
        def->target.nocow = true;
C
Chunyan Liu 已提交
1275

1276
    if (virXPathNode("./target/features", ctxt)) {
1277
        if ((n = virXPathNodeSet("./target/features/*", ctxt, &nodes)) < 0)
1278
            return NULL;
1279

1280
        if (!def->target.compat && VIR_STRDUP(def->target.compat, "1.1") < 0)
1281
            return NULL;
1282

1283
        if (!(def->target.features = virBitmapNew(VIR_STORAGE_FILE_FEATURE_LAST)))
1284
            return NULL;
1285 1286

        for (i = 0; i < n; i++) {
1287
            int f = virStorageFileFeatureTypeFromString((const char*)nodes[i]->name);
1288 1289

            if (f < 0) {
1290
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unsupported feature %s"),
1291
                               (const char*)nodes[i]->name);
1292
                return NULL;
1293
            }
1294
            ignore_value(virBitmapSetBit(def->target.features, f));
1295 1296 1297 1298
        }
        VIR_FREE(nodes);
    }

1299
    VIR_STEAL_PTR(ret, def);
1300
    return ret;
1301 1302
}

1303

1304
virStorageVolDefPtr
1305
virStorageVolDefParseNode(virStoragePoolDefPtr pool,
1306
                          xmlDocPtr xml,
1307 1308
                          xmlNodePtr root,
                          unsigned int flags)
1309
{
1310 1311 1312
    xmlXPathContextPtr ctxt = NULL;
    virStorageVolDefPtr def = NULL;

1313
    if (!virXMLNodeNameEqual(root, "volume")) {
1314
        virReportError(VIR_ERR_XML_ERROR,
1315 1316 1317
                       _("unexpected root element <%s>, "
                         "expecting <volume>"),
                       root->name);
1318 1319 1320 1321 1322
        goto cleanup;
    }

    ctxt = xmlXPathNewContext(xml);
    if (ctxt == NULL) {
1323
        virReportOOMError();
1324 1325 1326 1327
        goto cleanup;
    }

    ctxt->node = root;
1328
    def = virStorageVolDefParseXML(pool, ctxt, flags);
1329
 cleanup:
1330 1331 1332 1333
    xmlXPathFreeContext(ctxt);
    return def;
}

1334

1335
static virStorageVolDefPtr
1336
virStorageVolDefParse(virStoragePoolDefPtr pool,
1337
                      const char *xmlStr,
1338 1339
                      const char *filename,
                      unsigned int flags)
1340
{
1341
    virStorageVolDefPtr ret = NULL;
J
Jiri Denemark 已提交
1342
    xmlDocPtr xml;
1343

1344
    if ((xml = virXMLParse(filename, xmlStr, _("(storage_volume_definition)")))) {
1345
        ret = virStorageVolDefParseNode(pool, xml, xmlDocGetRootElement(xml), flags);
J
Jiri Denemark 已提交
1346
        xmlFreeDoc(xml);
1347 1348 1349 1350 1351
    }

    return ret;
}

1352

1353
virStorageVolDefPtr
1354
virStorageVolDefParseString(virStoragePoolDefPtr pool,
1355 1356
                            const char *xmlStr,
                            unsigned int flags)
1357
{
1358
    return virStorageVolDefParse(pool, xmlStr, NULL, flags);
1359 1360
}

1361

1362
virStorageVolDefPtr
1363
virStorageVolDefParseFile(virStoragePoolDefPtr pool,
1364 1365
                          const char *filename,
                          unsigned int flags)
1366
{
1367
    return virStorageVolDefParse(pool, NULL, filename, flags);
1368
}
1369

1370

1371 1372 1373 1374 1375 1376
static void
virStorageVolTimestampFormat(virBufferPtr buf, const char *name,
                             struct timespec *ts)
{
    if (ts->tv_nsec < 0)
        return;
1377
    virBufferAsprintf(buf, "<%s>%llu", name,
1378 1379 1380 1381 1382 1383
                      (unsigned long long) ts->tv_sec);
    if (ts->tv_nsec)
       virBufferAsprintf(buf, ".%09ld", ts->tv_nsec);
    virBufferAsprintf(buf, "</%s>\n", name);
}

1384

1385
static int
1386
virStorageVolTargetDefFormat(virStorageVolOptionsPtr options,
1387
                             virBufferPtr buf,
1388
                             virStorageSourcePtr def,
1389 1390
                             const char *type)
{
1391 1392
    virBufferAsprintf(buf, "<%s>\n", type);
    virBufferAdjustIndent(buf, 2);
1393

1394
    virBufferEscapeString(buf, "<path>%s</path>\n", def->path);
1395 1396 1397 1398

    if (options->formatToString) {
        const char *format = (options->formatToString)(def->format);
        if (!format) {
1399 1400 1401
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("unknown volume format number %d"),
                           def->format);
1402 1403
            return -1;
        }
1404
        virBufferAsprintf(buf, "<format type='%s'/>\n", format);
1405 1406
    }

1407 1408 1409 1410 1411
    if (def->perms &&
        (def->perms->mode != (mode_t) -1 ||
         def->perms->uid != (uid_t) -1 ||
         def->perms->gid != (gid_t) -1 ||
         def->perms->label)) {
1412 1413
        virBufferAddLit(buf, "<permissions>\n");
        virBufferAdjustIndent(buf, 2);
1414

1415 1416 1417
        if (def->perms->mode != (mode_t) -1)
            virBufferAsprintf(buf, "<mode>0%o</mode>\n",
                              def->perms->mode);
1418 1419 1420 1421 1422 1423
        if (def->perms->uid != (uid_t) -1)
            virBufferAsprintf(buf, "<owner>%d</owner>\n",
                              (int) def->perms->uid);
        if (def->perms->gid != (gid_t) -1)
            virBufferAsprintf(buf, "<group>%d</group>\n",
                              (int) def->perms->gid);
1424

1425 1426
        virBufferEscapeString(buf, "<label>%s</label>\n",
                              def->perms->label);
1427

1428 1429 1430
        virBufferAdjustIndent(buf, -2);
        virBufferAddLit(buf, "</permissions>\n");
    }
1431

1432
    if (def->timestamps) {
1433 1434
        virBufferAddLit(buf, "<timestamps>\n");
        virBufferAdjustIndent(buf, 2);
1435 1436 1437 1438
        virStorageVolTimestampFormat(buf, "atime", &def->timestamps->atime);
        virStorageVolTimestampFormat(buf, "mtime", &def->timestamps->mtime);
        virStorageVolTimestampFormat(buf, "ctime", &def->timestamps->ctime);
        virStorageVolTimestampFormat(buf, "btime", &def->timestamps->btime);
1439 1440
        virBufferAdjustIndent(buf, -2);
        virBufferAddLit(buf, "</timestamps>\n");
1441 1442
    }

1443 1444
    if (def->encryption &&
        virStorageEncryptionFormat(buf, def->encryption) < 0)
1445
            return -1;
1446

1447
    virBufferEscapeString(buf, "<compat>%s</compat>\n", def->compat);
1448

1449
    if (def->features) {
1450
        size_t i;
1451 1452
        bool empty = virBitmapIsAllClear(def->features);

1453 1454 1455 1456 1457 1458
        if (empty) {
            virBufferAddLit(buf, "<features/>\n");
        } else {
            virBufferAddLit(buf, "<features>\n");
            virBufferAdjustIndent(buf, 2);
        }
1459 1460

        for (i = 0; i < VIR_STORAGE_FILE_FEATURE_LAST; i++) {
J
Ján Tomko 已提交
1461
            if (virBitmapIsBitSet(def->features, i))
1462
                virBufferAsprintf(buf, "<%s/>\n",
1463
                                  virStorageFileFeatureTypeToString(i));
1464
        }
1465 1466 1467 1468
        if (!empty) {
            virBufferAdjustIndent(buf, -2);
            virBufferAddLit(buf, "</features>\n");
        }
1469 1470
    }

1471 1472
    virBufferAdjustIndent(buf, -2);
    virBufferAsprintf(buf, "</%s>\n", type);
1473 1474
    return 0;
}
1475

1476

1477
char *
1478
virStorageVolDefFormat(virStoragePoolDefPtr pool,
1479 1480
                       virStorageVolDefPtr def)
{
1481
    virStorageVolOptionsPtr options;
1482
    virBuffer buf = VIR_BUFFER_INITIALIZER;
1483

1484
    options = virStorageVolOptionsForPoolType(pool->type);
1485 1486 1487
    if (options == NULL)
        return NULL;

1488 1489
    virBufferAsprintf(&buf, "<volume type='%s'>\n",
                      virStorageVolTypeToString(def->type));
1490 1491 1492 1493 1494 1495
    virBufferAdjustIndent(&buf, 2);

    virBufferEscapeString(&buf, "<name>%s</name>\n", def->name);
    virBufferEscapeString(&buf, "<key>%s</key>\n", def->key);
    virBufferAddLit(&buf, "<source>\n");
    virBufferAdjustIndent(&buf, 2);
1496 1497

    if (def->source.nextent) {
1498
        size_t i;
1499
        const char *thispath = NULL;
1500
        for (i = 0; i < def->source.nextent; i++) {
1501 1502 1503
            if (thispath == NULL ||
                STRNEQ(thispath, def->source.extents[i].path)) {
                if (thispath != NULL)
1504
                    virBufferAddLit(&buf, "</device>\n");
1505

1506
                virBufferEscapeString(&buf, "<device path='%s'>\n",
1507
                                      def->source.extents[i].path);
1508 1509
            }

1510 1511
            virBufferAdjustIndent(&buf, 2);
            virBufferAsprintf(&buf, "<extent start='%llu' end='%llu'/>\n",
1512 1513
                              def->source.extents[i].start,
                              def->source.extents[i].end);
1514
            virBufferAdjustIndent(&buf, -2);
1515 1516 1517
            thispath = def->source.extents[i].path;
        }
        if (thispath != NULL)
1518
            virBufferAddLit(&buf, "</device>\n");
1519 1520
    }

1521 1522 1523 1524
    virBufferAdjustIndent(&buf, -2);
    virBufferAddLit(&buf, "</source>\n");

    virBufferAsprintf(&buf, "<capacity unit='bytes'>%llu</capacity>\n",
1525
                      def->target.capacity);
1526
    virBufferAsprintf(&buf, "<allocation unit='bytes'>%llu</allocation>\n",
1527
                      def->target.allocation);
1528 1529 1530 1531 1532 1533
    /* NB: Display only - since virStorageVolInfo is limited to just
     * 'capacity' and 'allocation' on output. Since we don't read this
     * in, be sure it was filled in before printing */
    if (def->target.physical)
        virBufferAsprintf(&buf, "<physical unit='bytes'>%llu</physical>\n",
                          def->target.physical);
1534

1535
    if (virStorageVolTargetDefFormat(options, &buf,
1536 1537
                                     &def->target, "target") < 0)
        goto cleanup;
1538

1539
    if (virStorageSourceHasBacking(&def->target) &&
1540
        virStorageVolTargetDefFormat(options, &buf,
1541 1542
                                     def->target.backingStore,
                                     "backingStore") < 0)
1543
        goto cleanup;
1544

1545
    virBufferAdjustIndent(&buf, -2);
E
Eric Blake 已提交
1546
    virBufferAddLit(&buf, "</volume>\n");
1547

1548 1549
    if (virBufferCheckError(&buf) < 0)
        goto cleanup;
1550

1551
    return virBufferContentAndReset(&buf);
1552

1553
 cleanup:
1554
    virBufferFreeAndReset(&buf);
1555 1556 1557 1558
    return NULL;
}


1559 1560 1561 1562
static int
virStoragePoolSaveXML(const char *path,
                      virStoragePoolDefPtr def,
                      const char *xml)
1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573
{
    char uuidstr[VIR_UUID_STRING_BUFLEN];
    int ret = -1;

    virUUIDFormat(def->uuid, uuidstr);
    ret = virXMLSaveFile(path,
                         virXMLPickShellSafeComment(def->name, uuidstr),
                         "pool-edit", xml);

    return ret;
}
1574 1575 1576 1577 1578 1579 1580


int
virStoragePoolSaveState(const char *stateFile,
                        virStoragePoolDefPtr def)
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;
1581
    VIR_AUTOFREE(char *) xml = NULL;
1582 1583 1584 1585 1586

    virBufferAddLit(&buf, "<poolstate>\n");
    virBufferAdjustIndent(&buf, 2);

    if (virStoragePoolDefFormatBuf(&buf, def) < 0)
1587
        return -1;
1588 1589 1590 1591 1592

    virBufferAdjustIndent(&buf, -2);
    virBufferAddLit(&buf, "</poolstate>\n");

    if (virBufferCheckError(&buf) < 0)
1593
        return -1;
1594 1595

    if (!(xml = virBufferContentAndReset(&buf)))
1596
        return -1;
1597 1598

    if (virStoragePoolSaveXML(stateFile, def, xml))
1599
        return -1;
1600

1601
    return 0;
1602
}
1603 1604


1605
int
1606
virStoragePoolSaveConfig(const char *configFile,
1607 1608
                         virStoragePoolDefPtr def)
{
1609
    VIR_AUTOFREE(char *) xml = NULL;
1610

1611 1612 1613 1614 1615 1616
    if (!(xml = virStoragePoolDefFormat(def))) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("failed to generate XML"));
        return -1;
    }

1617
    return virStoragePoolSaveXML(configFile, def, xml);
1618 1619
}

1620

1621
virStoragePoolSourcePtr
1622
virStoragePoolSourceListNewSource(virStoragePoolSourceListPtr list)
1623 1624 1625
{
    virStoragePoolSourcePtr source;

1626
    if (VIR_REALLOC_N(list->sources, list->nsources + 1) < 0)
1627 1628 1629 1630 1631 1632 1633 1634
        return NULL;

    source = &list->sources[list->nsources++];
    memset(source, 0, sizeof(*source));

    return source;
}

1635

1636 1637
char *
virStoragePoolSourceListFormat(virStoragePoolSourceListPtr def)
1638
{
1639
    virStoragePoolOptionsPtr options;
1640
    virBuffer buf = VIR_BUFFER_INITIALIZER;
1641
    const char *type;
1642
    size_t i;
1643

1644
    options = virStoragePoolOptionsForPoolType(def->type);
1645 1646 1647
    if (options == NULL)
        return NULL;

1648
    type = virStoragePoolTypeToString(def->type);
1649
    if (!type) {
1650 1651
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("unexpected pool type"));
1652 1653 1654 1655
        goto cleanup;
    }

    virBufferAddLit(&buf, "<sources>\n");
1656
    virBufferAdjustIndent(&buf, 2);
1657

1658
    for (i = 0; i < def->nsources; i++)
1659
        virStoragePoolSourceFormat(&buf, options, &def->sources[i]);
1660

1661
    virBufferAdjustIndent(&buf, -2);
1662 1663
    virBufferAddLit(&buf, "</sources>\n");

1664 1665
    if (virBufferCheckError(&buf) < 0)
        goto cleanup;
1666 1667

    return virBufferContentAndReset(&buf);
1668

1669
 cleanup:
1670
    virBufferFreeAndReset(&buf);
1671
    return NULL;
1672
}