storage_conf.c 51.4 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 53
              "file", "block", "dir", "network",
              "netdir", "ploop")
54

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

VIR_ENUM_IMPL(virStoragePoolFormatFileSystem,
              VIR_STORAGE_POOL_FS_LAST,
              "auto", "ext2", "ext3",
              "ext4", "ufs", "iso9660", "udf",
J
Jim Fehlig 已提交
67
              "gfs", "gfs2", "vfat", "hfs+", "xfs", "ocfs2")
68 69 70

VIR_ENUM_IMPL(virStoragePoolFormatFileSystemNet,
              VIR_STORAGE_POOL_NETFS_LAST,
71
              "auto", "nfs", "glusterfs", "cifs")
72 73 74 75

VIR_ENUM_IMPL(virStoragePoolFormatDisk,
              VIR_STORAGE_POOL_DISK_LAST,
              "unknown", "dos", "dvh", "gpt",
76
              "mac", "bsd", "pc98", "sun", "lvm2")
77 78 79

VIR_ENUM_IMPL(virStoragePoolFormatLogical,
              VIR_STORAGE_POOL_LOGICAL_LAST,
80
              "unknown", "lvm2")
81 82 83 84 85 86 87


VIR_ENUM_IMPL(virStorageVolFormatDisk,
              VIR_STORAGE_VOL_DISK_LAST,
              "none", "linux", "fat16",
              "fat32", "linux-swap",
              "linux-lvm", "linux-raid",
88
              "extended")
89

90
VIR_ENUM_IMPL(virStoragePartedFs,
91
              VIR_STORAGE_PARTED_FS_TYPE_LAST,
92
              "ext2", "ext2", "fat16",
93 94 95
              "fat32", "linux-swap",
              "ext2", "ext2",
              "extended")
96 97 98 99 100 101 102 103 104 105

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 {
106
    int defaultFormat;
107 108 109 110 111 112
    virStorageVolFormatToString formatToString;
    virStorageVolFormatFromString formatFromString;
};

/* Flags to indicate mandatory components in the pool source */
enum {
O
Osier Yang 已提交
113 114 115 116 117 118 119
    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),
120 121 122 123 124
};

typedef struct _virStoragePoolOptions virStoragePoolOptions;
typedef virStoragePoolOptions *virStoragePoolOptionsPtr;
struct _virStoragePoolOptions {
E
Eric Blake 已提交
125
    unsigned int flags;
126
    int defaultFormat;
127 128 129

    virStoragePoolXMLNamespace ns;

130 131 132 133 134 135 136 137 138 139 140 141
    virStoragePoolFormatToString formatToString;
    virStoragePoolFormatFromString formatFromString;
};

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

142

E
Eric Blake 已提交
143 144 145 146 147 148 149 150 151
static int
virStorageVolumeFormatFromString(const char *format)
{
    int ret = virStorageFileFormatTypeFromString(format);
    if (ret == VIR_STORAGE_FILE_NONE)
        return -1;
    return ret;
}

152

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


static virStoragePoolTypeInfoPtr
301 302
virStoragePoolTypeInfoLookup(int type)
{
303
    size_t i;
304
    for (i = 0; i < ARRAY_CARDINALITY(poolTypeInfo); i++)
305 306 307
        if (poolTypeInfo[i].poolType == type)
            return &poolTypeInfo[i];

308 309
    virReportError(VIR_ERR_INTERNAL_ERROR,
                   _("missing backend for pool type %d"), type);
310 311 312
    return NULL;
}

313

314
static virStoragePoolOptionsPtr
315 316
virStoragePoolOptionsForPoolType(int type)
{
317 318 319 320 321 322
    virStoragePoolTypeInfoPtr backend = virStoragePoolTypeInfoLookup(type);
    if (backend == NULL)
        return NULL;
    return &backend->poolOptions;
}

323

324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351
/* 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;
}


352
static virStorageVolOptionsPtr
353 354
virStorageVolOptionsForPoolType(int type)
{
355 356 357 358 359 360 361
    virStoragePoolTypeInfoPtr backend = virStoragePoolTypeInfoLookup(type);
    if (backend == NULL)
        return NULL;
    return &backend->volOptions;
}


362
void
363 364
virStorageVolDefFree(virStorageVolDefPtr def)
{
365
    size_t i;
366 367 368 369

    if (!def)
        return;

370 371
    VIR_FREE(def->name);
    VIR_FREE(def->key);
372

373
    for (i = 0; i < def->source.nextent; i++)
374 375
        VIR_FREE(def->source.extents[i].path);
    VIR_FREE(def->source.extents);
376

377
    virStorageSourceClear(&def->target);
378
    VIR_FREE(def);
379 380
}

381

382 383 384 385 386 387 388
void
virStoragePoolSourceDeviceClear(virStoragePoolSourceDevicePtr dev)
{
    VIR_FREE(dev->freeExtents);
    VIR_FREE(dev->path);
}

389

390
void
391 392
virStoragePoolSourceClear(virStoragePoolSourcePtr source)
{
393
    size_t i;
394

395
    if (!source)
396 397
        return;

398
    for (i = 0; i < source->nhost; i++)
399 400 401
        VIR_FREE(source->hosts[i].name);
    VIR_FREE(source->hosts);

402 403
    for (i = 0; i < source->ndevice; i++)
        virStoragePoolSourceDeviceClear(&source->devices[i]);
404 405 406
    VIR_FREE(source->devices);
    VIR_FREE(source->dir);
    VIR_FREE(source->name);
407
    virStorageAdapterClear(&source->adapter);
408
    virStorageSourceInitiatorClear(&source->initiator);
409
    virStorageAuthDefFree(source->auth);
410 411
    VIR_FREE(source->vendor);
    VIR_FREE(source->product);
412 413
}

414

415 416 417 418 419 420 421
void
virStoragePoolSourceFree(virStoragePoolSourcePtr source)
{
    virStoragePoolSourceClear(source);
    VIR_FREE(source);
}

422

423
void
424 425
virStoragePoolDefFree(virStoragePoolDefPtr def)
{
426 427 428 429 430
    if (!def)
        return;

    VIR_FREE(def->name);

431
    virStoragePoolSourceClear(&def->source);
432

433 434
    VIR_FREE(def->target.path);
    VIR_FREE(def->target.perms.label);
435 436
    if (def->namespaceData && def->ns.free)
        (def->ns.free)(def->namespaceData);
437
    VIR_FREE(def);
438 439 440
}


441
static int
442
virStoragePoolDefParseSource(xmlXPathContextPtr ctxt,
443 444
                             virStoragePoolSourcePtr source,
                             int pool_type,
445 446
                             xmlNodePtr node)
{
447
    int ret = -1;
448
    xmlNodePtr relnode, authnode, *nodeset = NULL;
449
    xmlNodePtr adapternode;
450 451
    int nsource;
    size_t i;
452
    virStoragePoolOptionsPtr options;
453
    virStorageAuthDefPtr authdef = NULL;
454
    char *name = NULL;
455
    char *port = NULL;
456
    char *ver = NULL;
457
    int n;
458 459 460 461

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

462
    if ((options = virStoragePoolOptionsForPoolType(pool_type)) == NULL)
463 464
        goto cleanup;

465
    source->name = virXPathString("string(./name)", ctxt);
466
    if (pool_type == VIR_STORAGE_POOL_RBD && source->name == NULL) {
467
        virReportError(VIR_ERR_XML_ERROR, "%s",
468
                       _("element 'name' is mandatory for RBD pool"));
469 470
        goto cleanup;
    }
471 472

    if (options->formatFromString) {
473
        char *format = virXPathString("string(./format/@type)", ctxt);
474 475 476 477 478 479
        if (format == NULL)
            source->format = options->defaultFormat;
        else
            source->format = options->formatFromString(format);

        if (source->format < 0) {
480
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
481
                           _("unknown pool format type %s"), format);
482 483 484 485 486 487
            VIR_FREE(format);
            goto cleanup;
        }
        VIR_FREE(format);
    }

488 489
    if ((n = virXPathNodeSet("./host", ctxt, &nodeset)) < 0)
        goto cleanup;
490

491 492
    if (n) {
        if (VIR_ALLOC_N(source->hosts, n) < 0)
493
            goto cleanup;
494
        source->nhost = n;
495

496
        for (i = 0; i < source->nhost; i++) {
497 498
            name = virXMLPropString(nodeset[i], "name");
            if (name == NULL) {
499 500
                virReportError(VIR_ERR_XML_ERROR, "%s",
                               _("missing storage pool host name"));
501 502 503 504 505 506 507
                goto cleanup;
            }
            source->hosts[i].name = name;

            port = virXMLPropString(nodeset[i], "port");
            if (port) {
                if (virStrToLong_i(port, NULL, 10, &source->hosts[i].port) < 0) {
508 509 510
                    virReportError(VIR_ERR_XML_ERROR,
                                   _("Invalid port number: %s"),
                                   port);
511 512
                    goto cleanup;
                }
513
                VIR_FREE(port);
514 515 516
            }
        }
    }
517

518
    VIR_FREE(nodeset);
519 520

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

522
    nsource = virXPathNodeSet("./device", ctxt, &nodeset);
523 524 525
    if (nsource < 0)
        goto cleanup;

526
    for (i = 0; i < nsource; i++) {
527
        char *partsep;
528 529 530 531 532 533
        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"));
534 535 536
            goto cleanup;
        }

537 538 539 540 541 542 543 544 545 546 547 548 549 550
        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);
                VIR_FREE(partsep);
                goto cleanup;
            }
            VIR_FREE(partsep);
        }

551 552 553
        if (VIR_APPEND_ELEMENT(source->devices, source->ndevice, dev) < 0) {
            virStoragePoolSourceDeviceClear(&dev);
            goto cleanup;
554
        }
555

556 557
    }

558
    source->dir = virXPathString("string(./dir/@path)", ctxt);
559 560 561 562
    /* In gluster, a missing dir defaults to "/" */
    if (!source->dir && pool_type == VIR_STORAGE_POOL_GLUSTER &&
        VIR_STRDUP(source->dir, "/") < 0)
        goto cleanup;
563

564
    if ((adapternode = virXPathNode("./adapter", ctxt))) {
565
        if (virStorageAdapterParseXML(&source->adapter, adapternode, ctxt) < 0)
566 567
            goto cleanup;
    }
568

569
    if ((authnode = virXPathNode("./auth", ctxt))) {
570
        if (!(authdef = virStorageAuthDefParse(authnode, ctxt)))
571 572 573 574 575 576 577 578 579
            goto cleanup;

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

        source->auth = authdef;
580
        authdef = NULL;
581
    }
582

583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600
    /* 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;
        }
    }

601 602 603
    source->vendor = virXPathString("string(./vendor/@name)", ctxt);
    source->product = virXPathString("string(./product/@name)", ctxt);

604
    ret = 0;
605
 cleanup:
606 607
    ctxt->node = relnode;

608
    VIR_FREE(port);
609
    VIR_FREE(nodeset);
610
    virStorageAuthDefFree(authdef);
611 612
    return ret;
}
613

614

615
virStoragePoolSourcePtr
616
virStoragePoolDefParseSourceString(const char *srcSpec,
617 618 619 620 621 622 623
                                   int pool_type)
{
    xmlDocPtr doc = NULL;
    xmlNodePtr node = NULL;
    xmlXPathContextPtr xpath_ctxt = NULL;
    virStoragePoolSourcePtr def = NULL, ret = NULL;

624 625 626
    if (!(doc = virXMLParseStringCtxt(srcSpec,
                                      _("(storage_source_specification)"),
                                      &xpath_ctxt)))
627 628
        goto cleanup;

629
    if (VIR_ALLOC(def) < 0)
630 631
        goto cleanup;

632
    if (!(node = virXPathNode("/source", xpath_ctxt))) {
633 634
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("root element was not source"));
635 636 637
        goto cleanup;
    }

638
    if (virStoragePoolDefParseSource(xpath_ctxt, def, pool_type,
639 640 641
                                     node) < 0)
        goto cleanup;

642
    VIR_STEAL_PTR(ret, def);
643
 cleanup:
644
    virStoragePoolSourceFree(def);
645 646 647 648 649
    xmlFreeDoc(doc);
    xmlXPathFreeContext(xpath_ctxt);

    return ret;
}
650

651

652
static int
653
virStorageDefParsePerms(xmlXPathContextPtr ctxt,
654
                        virStoragePermsPtr perms,
655
                        const char *permxpath)
656
{
657
    char *mode;
658
    long long val;
659 660 661
    int ret = -1;
    xmlNodePtr relnode;
    xmlNodePtr node;
662

663
    node = virXPathNode(permxpath, ctxt);
664 665
    if (node == NULL) {
        /* Set default values if there is not <permissions> element */
666
        perms->mode = (mode_t) -1;
P
Philipp Hahn 已提交
667 668
        perms->uid = (uid_t) -1;
        perms->gid = (gid_t) -1;
669 670 671 672 673 674 675
        perms->label = NULL;
        return 0;
    }

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

676
    if ((mode = virXPathString("string(./mode)", ctxt))) {
677 678 679
        int tmp;

        if (virStrToLong_i(mode, NULL, 8, &tmp) < 0 || (tmp & ~0777)) {
680
            VIR_FREE(mode);
681 682
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("malformed octal mode"));
683
            goto error;
684
        }
685
        perms->mode = tmp;
686
        VIR_FREE(mode);
687 688
    } else {
        perms->mode = (mode_t) -1;
689 690
    }

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

        perms->uid = val;
704 705
    }

706
    if (virXPathNode("./group", ctxt) == NULL) {
P
Philipp Hahn 已提交
707
        perms->gid = (gid_t) -1;
708
    } else {
709
        /* We previously could output -1, so continue to parse it */
710
        if (virXPathLongLong("number(./group)", ctxt, &val) < 0 ||
711 712
            ((gid_t) val != val &&
             val != -1)) {
713 714
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("malformed group element"));
715
            goto error;
716
        }
717
        perms->gid = val;
718 719 720
    }

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

723
    ret = 0;
724
 error:
725 726
    ctxt->node = relnode;
    return ret;
727 728
}

729

J
John Ferlan 已提交
730
virStoragePoolDefPtr
731 732
virStoragePoolDefParseXML(xmlXPathContextPtr ctxt)
{
733
    virStoragePoolOptionsPtr options;
734
    virStoragePoolDefPtr ret;
735
    xmlNodePtr source_node;
736
    char *type = NULL;
737
    char *uuid = NULL;
738
    char *target_path = NULL;
739

740
    if (VIR_ALLOC(ret) < 0)
741 742
        return NULL;

743
    type = virXPathString("string(./@type)", ctxt);
744 745 746 747 748 749
    if (type == NULL) {
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("storage pool missing type attribute"));
        goto error;
    }

750
    if ((ret->type = virStoragePoolTypeFromString(type)) < 0) {
751
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
752
                       _("unknown storage pool type %s"), type);
753
        goto error;
754 755
    }

756
    if ((options = virStoragePoolOptionsForPoolType(ret->type)) == NULL)
757
        goto error;
758

759
    source_node = virXPathNode("./source", ctxt);
760
    if (source_node) {
761
        if (virStoragePoolDefParseSource(ctxt, &ret->source, ret->type,
762
                                         source_node) < 0)
763
            goto error;
764 765 766
    } else {
        if (options->formatFromString)
            ret->source.format = options->defaultFormat;
767 768
    }

769
    ret->name = virXPathString("string(./name)", ctxt);
770
    if (ret->name == NULL &&
771 772 773
        options->flags & VIR_STORAGE_POOL_SOURCE_NAME &&
        VIR_STRDUP(ret->name, ret->source.name) < 0)
        goto error;
774
    if (ret->name == NULL) {
775 776
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("missing pool source name element"));
777
        goto error;
778 779
    }

780 781 782 783 784 785
    if (strchr(ret->name, '/')) {
        virReportError(VIR_ERR_XML_ERROR,
                       _("name %s cannot contain '/'"), ret->name);
        goto error;
    }

786
    uuid = virXPathString("string(./uuid)", ctxt);
787 788
    if (uuid == NULL) {
        if (virUUIDGenerate(ret->uuid) < 0) {
789 790
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("unable to generate uuid"));
791
            goto error;
792 793 794
        }
    } else {
        if (virUUIDParse(uuid, ret->uuid) < 0) {
795 796
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("malformed uuid element"));
797
            goto error;
798 799 800
        }
    }

801
    if (options->flags & VIR_STORAGE_POOL_SOURCE_HOST) {
802
        if (!ret->source.nhost) {
803
            virReportError(VIR_ERR_XML_ERROR, "%s",
804
                           _("missing storage pool source host name"));
805
            goto error;
806 807 808
        }
    }

809
    if (options->flags & VIR_STORAGE_POOL_SOURCE_DIR) {
810
        if (!ret->source.dir) {
811 812
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("missing storage pool source path"));
813
            goto error;
814 815
        }
    }
816
    if (options->flags & VIR_STORAGE_POOL_SOURCE_NAME) {
817 818
        if (ret->source.name == NULL) {
            /* source name defaults to pool name */
819
            if (VIR_STRDUP(ret->source.name, ret->name) < 0)
820
                goto error;
821 822
        }
    }
823

824
    if ((options->flags & VIR_STORAGE_POOL_SOURCE_ADAPTER) &&
825
        (virStorageAdapterValidate(&ret->source.adapter)) < 0)
826
            goto error;
827

828 829 830
    /* If DEVICE is the only source type, then its required */
    if (options->flags == VIR_STORAGE_POOL_SOURCE_DEVICE) {
        if (!ret->source.ndevice) {
831 832
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("missing storage pool source device name"));
833
            goto error;
834 835 836
        }
    }

837 838 839
    /* When we are working with a virtual disk we can skip the target
     * path and permissions */
    if (!(options->flags & VIR_STORAGE_POOL_SOURCE_NETWORK)) {
840
        if (ret->type == VIR_STORAGE_POOL_LOGICAL) {
841
            if (virAsprintf(&target_path, "/dev/%s", ret->source.name) < 0)
842
                goto error;
R
Roman Bogorodskiy 已提交
843
        } else if (ret->type == VIR_STORAGE_POOL_ZFS) {
844
            if (virAsprintf(&target_path, "/dev/zvol/%s", ret->source.name) < 0)
R
Roman Bogorodskiy 已提交
845
                goto error;
846 847 848 849 850 851 852
        } else {
            target_path = virXPathString("string(./target/path)", ctxt);
            if (!target_path) {
                virReportError(VIR_ERR_XML_ERROR, "%s",
                               _("missing storage pool target path"));
                goto error;
            }
853
        }
854
        ret->target.path = virFileSanitizePath(target_path);
855
        if (!ret->target.path)
856
            goto error;
857

858
        if (virStorageDefParsePerms(ctxt, &ret->target.perms,
859
                                    "./target/permissions") < 0)
860
            goto error;
861
    }
862

863 864 865 866 867 868 869
    if (ret->type == VIR_STORAGE_POOL_ISCSI_DIRECT &&
        !ret->source.initiator.iqn) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("missing initiator IQN"));
        goto error;
    }

870 871 872 873 874 875 876
    /* Make a copy of all the callback pointers here for easier use,
     * especially during the virStoragePoolSourceClear method */
    ret->ns = options->ns;
    if (ret->ns.parse &&
        (ret->ns.parse)(ctxt, &ret->namespaceData) < 0)
        goto error;

877
 cleanup:
878
    VIR_FREE(uuid);
879 880 881 882
    VIR_FREE(type);
    VIR_FREE(target_path);
    return ret;

883
 error:
884
    virStoragePoolDefFree(ret);
885 886
    ret = NULL;
    goto cleanup;
887 888
}

889

890
virStoragePoolDefPtr
891
virStoragePoolDefParseNode(xmlDocPtr xml,
892 893
                           xmlNodePtr root)
{
894 895 896
    xmlXPathContextPtr ctxt = NULL;
    virStoragePoolDefPtr def = NULL;

897
    if (!virXMLNodeNameEqual(root, "pool")) {
898
        virReportError(VIR_ERR_XML_ERROR,
899 900 901
                       _("unexpected root element <%s>, "
                         "expecting <pool>"),
                       root->name);
902 903 904 905 906
        goto cleanup;
    }

    ctxt = xmlXPathNewContext(xml);
    if (ctxt == NULL) {
907
        virReportOOMError();
908 909 910 911
        goto cleanup;
    }

    ctxt->node = root;
912
    def = virStoragePoolDefParseXML(ctxt);
913
 cleanup:
914 915 916 917
    xmlXPathFreeContext(ctxt);
    return def;
}

918

919
static virStoragePoolDefPtr
920
virStoragePoolDefParse(const char *xmlStr,
921 922
                       const char *filename)
{
923
    virStoragePoolDefPtr ret = NULL;
J
Jiri Denemark 已提交
924
    xmlDocPtr xml;
925

926
    if ((xml = virXMLParse(filename, xmlStr, _("(storage_pool_definition)")))) {
J
Jiri Denemark 已提交
927 928
        ret = virStoragePoolDefParseNode(xml, xmlDocGetRootElement(xml));
        xmlFreeDoc(xml);
929 930
    }

931 932 933
    return ret;
}

934

935
virStoragePoolDefPtr
936
virStoragePoolDefParseString(const char *xmlStr)
937
{
938
    return virStoragePoolDefParse(xmlStr, NULL);
939 940
}

941

942
virStoragePoolDefPtr
943
virStoragePoolDefParseFile(const char *filename)
944
{
945
    return virStoragePoolDefParse(NULL, filename);
946 947
}

948

949
static int
950
virStoragePoolSourceFormat(virBufferPtr buf,
951
                           virStoragePoolOptionsPtr options,
952 953
                           virStoragePoolSourcePtr src)
{
954
    size_t i, j;
955

956 957 958
    virBufferAddLit(buf, "<source>\n");
    virBufferAdjustIndent(buf, 2);

959 960
    if ((options->flags & VIR_STORAGE_POOL_SOURCE_HOST) && src->nhost) {
        for (i = 0; i < src->nhost; i++) {
961
            virBufferEscapeString(buf, "<host name='%s'",
962
                                  src->hosts[i].name);
963 964 965 966
            if (src->hosts[i].port)
                virBufferAsprintf(buf, " port='%d'", src->hosts[i].port);
            virBufferAddLit(buf, "/>\n");
        }
967
    }
968

969
    if ((options->flags & VIR_STORAGE_POOL_SOURCE_DEVICE) &&
970
        src->ndevice) {
971
        for (i = 0; i < src->ndevice; i++) {
972 973 974 975 976 977 978
            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));
            }
979
            if (src->devices[i].nfreeExtent) {
980
                virBufferAddLit(buf, ">\n");
981
                virBufferAdjustIndent(buf, 2);
982
                for (j = 0; j < src->devices[i].nfreeExtent; j++) {
983
                    virBufferAsprintf(buf, "<freeExtent start='%llu' end='%llu'/>\n",
984 985 986
                                      src->devices[i].freeExtents[j].start,
                                      src->devices[i].freeExtents[j].end);
                }
987 988
                virBufferAdjustIndent(buf, -2);
                virBufferAddLit(buf, "</device>\n");
989
            } else {
990
                virBufferAddLit(buf, "/>\n");
991
            }
992 993
        }
    }
994

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

998
    if ((options->flags & VIR_STORAGE_POOL_SOURCE_ADAPTER) &&
999 1000 1001
        (src->adapter.type == VIR_STORAGE_ADAPTER_TYPE_FC_HOST ||
         src->adapter.type == VIR_STORAGE_ADAPTER_TYPE_SCSI_HOST))
        virStorageAdapterFormat(buf, &src->adapter);
1002

1003
    if (options->flags & VIR_STORAGE_POOL_SOURCE_NAME)
1004
        virBufferEscapeString(buf, "<name>%s</name>\n", src->name);
1005

1006 1007
    if (options->flags & VIR_STORAGE_POOL_SOURCE_INITIATOR_IQN)
        virStorageSourceInitiatorFormatXML(&src->initiator, buf);
D
David Allan 已提交
1008

1009 1010 1011
    if (options->formatToString) {
        const char *format = (options->formatToString)(src->format);
        if (!format) {
1012 1013 1014
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("unknown pool format number %d"),
                           src->format);
1015 1016
            return -1;
        }
1017
        virBufferAsprintf(buf, "<format type='%s'/>\n", format);
1018 1019
    }

1020 1021
    if (src->auth)
        virStorageAuthDefFormat(buf, src->auth);
1022

1023 1024 1025
    if (src->protocolVer)
        virBufferAsprintf(buf, "<protocol ver='%u'/>\n", src->protocolVer);

1026 1027
    virBufferEscapeString(buf, "<vendor name='%s'/>\n", src->vendor);
    virBufferEscapeString(buf, "<product name='%s'/>\n", src->product);
1028

1029 1030
    virBufferAdjustIndent(buf, -2);
    virBufferAddLit(buf, "</source>\n");
1031 1032 1033
    return 0;
}

1034

1035 1036 1037
static int
virStoragePoolDefFormatBuf(virBufferPtr buf,
                           virStoragePoolDefPtr def)
1038
{
1039
    virStoragePoolOptionsPtr options;
1040
    char uuid[VIR_UUID_STRING_BUFLEN];
1041
    const char *type;
1042

1043
    options = virStoragePoolOptionsForPoolType(def->type);
1044
    if (options == NULL)
1045
        return -1;
1046

1047
    type = virStoragePoolTypeToString(def->type);
1048
    if (!type) {
1049 1050
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("unexpected pool type"));
1051
        return -1;
1052
    }
1053 1054 1055 1056
    virBufferAsprintf(buf, "<pool type='%s'", type);
    if (def->namespaceData && def->ns.href)
        virBufferAsprintf(buf, " %s", (def->ns.href)());
    virBufferAddLit(buf, ">\n");
1057 1058
    virBufferAdjustIndent(buf, 2);
    virBufferEscapeString(buf, "<name>%s</name>\n", def->name);
1059 1060

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

1063
    virBufferAsprintf(buf, "<capacity unit='bytes'>%llu</capacity>\n",
1064
                      def->capacity);
1065
    virBufferAsprintf(buf, "<allocation unit='bytes'>%llu</allocation>\n",
1066
                      def->allocation);
1067
    virBufferAsprintf(buf, "<available unit='bytes'>%llu</available>\n",
1068
                      def->available);
1069

1070 1071
    if (virStoragePoolSourceFormat(buf, options, &def->source) < 0)
        return -1;
1072

1073
    /* RBD, Sheepdog, Gluster and Iscsi-direct devices are not local block devs nor
1074
     * files, so they don't have a target */
1075
    if (def->type != VIR_STORAGE_POOL_RBD &&
1076
        def->type != VIR_STORAGE_POOL_SHEEPDOG &&
1077 1078
        def->type != VIR_STORAGE_POOL_GLUSTER &&
        def->type != VIR_STORAGE_POOL_ISCSI_DIRECT) {
1079 1080
        virBufferAddLit(buf, "<target>\n");
        virBufferAdjustIndent(buf, 2);
1081

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

1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104
        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");
        }
1105

1106 1107
        virBufferAdjustIndent(buf, -2);
        virBufferAddLit(buf, "</target>\n");
1108
    }
1109 1110 1111 1112 1113 1114

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

1115 1116 1117 1118 1119 1120
    virBufferAdjustIndent(buf, -2);
    virBufferAddLit(buf, "</pool>\n");

    return 0;
}

1121

1122 1123 1124 1125 1126 1127 1128
char *
virStoragePoolDefFormat(virStoragePoolDefPtr def)
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;

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

1130
    if (virBufferCheckError(&buf) < 0)
1131
        goto error;
1132

1133
    return virBufferContentAndReset(&buf);
1134

1135
 error:
1136
    virBufferFreeAndReset(&buf);
1137 1138 1139 1140 1141
    return NULL;
}


static int
1142
virStorageSize(const char *unit,
1143
               const char *val,
1144 1145
               unsigned long long *ret)
{
J
Ján Tomko 已提交
1146
    if (virStrToLong_ullp(val, NULL, 10, ret) < 0) {
1147 1148
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("malformed capacity element"));
1149 1150
        return -1;
    }
1151 1152 1153 1154
    /* 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;
1155 1156 1157 1158

    return 0;
}

1159

1160
static virStorageVolDefPtr
1161
virStorageVolDefParseXML(virStoragePoolDefPtr pool,
1162 1163
                         xmlXPathContextPtr ctxt,
                         unsigned int flags)
1164
{
1165
    virStorageVolDefPtr ret;
1166
    virStorageVolOptionsPtr options;
1167
    char *type = NULL;
1168 1169 1170
    char *allocation = NULL;
    char *capacity = NULL;
    char *unit = NULL;
1171
    char *backingStore = NULL;
1172
    xmlNodePtr node;
1173
    xmlNodePtr *nodes = NULL;
1174 1175
    size_t i;
    int n;
1176

1177 1178
    virCheckFlags(VIR_VOL_XML_PARSE_NO_CAPACITY |
                  VIR_VOL_XML_PARSE_OPT_CAPACITY, NULL);
1179

1180
    options = virStorageVolOptionsForPoolType(pool->type);
1181 1182 1183
    if (options == NULL)
        return NULL;

1184
    if (VIR_ALLOC(ret) < 0)
1185 1186
        return NULL;

1187 1188
    ret->target.type = VIR_STORAGE_TYPE_FILE;

1189
    ret->name = virXPathString("string(./name)", ctxt);
1190
    if (ret->name == NULL) {
1191 1192
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("missing volume name element"));
1193
        goto error;
1194 1195
    }

1196 1197
    /* Normally generated by pool refresh, but useful for unit tests */
    ret->key = virXPathString("string(./key)", ctxt);
1198

1199 1200 1201 1202
    /* Technically overridden by pool refresh, but useful for unit tests */
    type = virXPathString("string(./@type)", ctxt);
    if (type) {
        if ((ret->type = virStorageVolTypeFromString(type)) < 0) {
1203
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1204 1205 1206 1207 1208
                           _("unknown volume type '%s'"), type);
            goto error;
        }
    }

1209 1210 1211 1212
    if ((backingStore = virXPathString("string(./backingStore/path)", ctxt))) {
        if (VIR_ALLOC(ret->target.backingStore) < 0)
            goto error;

1213 1214
        ret->target.backingStore->type = VIR_STORAGE_TYPE_FILE;

1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236
        ret->target.backingStore->path = backingStore;
        backingStore = NULL;

        if (options->formatFromString) {
            char *format = virXPathString("string(./backingStore/format/@type)", ctxt);
            if (format == NULL)
                ret->target.backingStore->format = options->defaultFormat;
            else
                ret->target.backingStore->format = (options->formatFromString)(format);

            if (ret->target.backingStore->format < 0) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("unknown volume format type %s"), format);
                VIR_FREE(format);
                goto error;
            }
            VIR_FREE(format);
        }

        if (VIR_ALLOC(ret->target.backingStore->perms) < 0)
            goto error;
        if (virStorageDefParsePerms(ctxt, ret->target.backingStore->perms,
1237
                                    "./backingStore/permissions") < 0)
1238 1239 1240
            goto error;
    }

1241 1242
    capacity = virXPathString("string(./capacity)", ctxt);
    unit = virXPathString("string(./capacity/@unit)", ctxt);
1243 1244 1245
    if (capacity) {
        if (virStorageSize(unit, capacity, &ret->target.capacity) < 0)
            goto error;
1246
    } else if (!(flags & VIR_VOL_XML_PARSE_NO_CAPACITY) &&
1247 1248
               !((flags & VIR_VOL_XML_PARSE_OPT_CAPACITY) &&
                 virStorageSourceHasBacking(&ret->target))) {
1249
        virReportError(VIR_ERR_XML_ERROR, "%s", _("missing capacity element"));
1250
        goto error;
1251
    }
1252
    VIR_FREE(unit);
1253

1254
    allocation = virXPathString("string(./allocation)", ctxt);
1255
    if (allocation) {
1256
        unit = virXPathString("string(./allocation/@unit)", ctxt);
1257
        if (virStorageSize(unit, allocation, &ret->target.allocation) < 0)
1258
            goto error;
1259
        ret->target.has_allocation = true;
1260
    } else {
1261
        ret->target.allocation = ret->target.capacity;
1262 1263
    }

1264
    ret->target.path = virXPathString("string(./target/path)", ctxt);
1265
    if (options->formatFromString) {
1266
        char *format = virXPathString("string(./target/format/@type)", ctxt);
1267 1268 1269 1270 1271 1272
        if (format == NULL)
            ret->target.format = options->defaultFormat;
        else
            ret->target.format = (options->formatFromString)(format);

        if (ret->target.format < 0) {
1273
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1274
                           _("unknown volume format type %s"), format);
1275
            VIR_FREE(format);
1276
            goto error;
1277
        }
1278
        VIR_FREE(format);
1279 1280
    }

1281 1282 1283
    if (VIR_ALLOC(ret->target.perms) < 0)
        goto error;
    if (virStorageDefParsePerms(ctxt, ret->target.perms,
1284
                                "./target/permissions") < 0)
1285
        goto error;
1286

1287
    node = virXPathNode("./target/encryption", ctxt);
1288
    if (node != NULL) {
1289
        ret->target.encryption = virStorageEncryptionParseNode(node, ctxt);
1290
        if (ret->target.encryption == NULL)
1291
            goto error;
1292 1293
    }

1294
    ret->target.compat = virXPathString("string(./target/compat)", ctxt);
1295 1296
    if (virStorageFileCheckCompat(ret->target.compat) < 0)
        goto error;
1297

C
Chunyan Liu 已提交
1298 1299 1300
    if (virXPathNode("./target/nocow", ctxt))
        ret->target.nocow = true;

1301
    if (virXPathNode("./target/features", ctxt)) {
1302 1303 1304 1305 1306 1307 1308
        if ((n = virXPathNodeSet("./target/features/*", ctxt, &nodes)) < 0)
            goto error;

        if (!ret->target.compat && VIR_STRDUP(ret->target.compat, "1.1") < 0)
            goto error;

        if (!(ret->target.features = virBitmapNew(VIR_STORAGE_FILE_FEATURE_LAST)))
1309
            goto error;
1310 1311

        for (i = 0; i < n; i++) {
1312
            int f = virStorageFileFeatureTypeFromString((const char*)nodes[i]->name);
1313 1314

            if (f < 0) {
1315
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unsupported feature %s"),
1316 1317 1318 1319 1320 1321 1322 1323
                               (const char*)nodes[i]->name);
                goto error;
            }
            ignore_value(virBitmapSetBit(ret->target.features, f));
        }
        VIR_FREE(nodes);
    }

1324
 cleanup:
1325
    VIR_FREE(nodes);
1326 1327 1328
    VIR_FREE(allocation);
    VIR_FREE(capacity);
    VIR_FREE(unit);
1329
    VIR_FREE(type);
1330
    VIR_FREE(backingStore);
1331 1332
    return ret;

1333
 error:
1334
    virStorageVolDefFree(ret);
1335 1336
    ret = NULL;
    goto cleanup;
1337 1338
}

1339

1340
virStorageVolDefPtr
1341
virStorageVolDefParseNode(virStoragePoolDefPtr pool,
1342
                          xmlDocPtr xml,
1343 1344
                          xmlNodePtr root,
                          unsigned int flags)
1345
{
1346 1347 1348
    xmlXPathContextPtr ctxt = NULL;
    virStorageVolDefPtr def = NULL;

1349
    if (!virXMLNodeNameEqual(root, "volume")) {
1350
        virReportError(VIR_ERR_XML_ERROR,
1351 1352 1353
                       _("unexpected root element <%s>, "
                         "expecting <volume>"),
                       root->name);
1354 1355 1356 1357 1358
        goto cleanup;
    }

    ctxt = xmlXPathNewContext(xml);
    if (ctxt == NULL) {
1359
        virReportOOMError();
1360 1361 1362 1363
        goto cleanup;
    }

    ctxt->node = root;
1364
    def = virStorageVolDefParseXML(pool, ctxt, flags);
1365
 cleanup:
1366 1367 1368 1369
    xmlXPathFreeContext(ctxt);
    return def;
}

1370

1371
static virStorageVolDefPtr
1372
virStorageVolDefParse(virStoragePoolDefPtr pool,
1373
                      const char *xmlStr,
1374 1375
                      const char *filename,
                      unsigned int flags)
1376
{
1377
    virStorageVolDefPtr ret = NULL;
J
Jiri Denemark 已提交
1378
    xmlDocPtr xml;
1379

1380
    if ((xml = virXMLParse(filename, xmlStr, _("(storage_volume_definition)")))) {
1381
        ret = virStorageVolDefParseNode(pool, xml, xmlDocGetRootElement(xml), flags);
J
Jiri Denemark 已提交
1382
        xmlFreeDoc(xml);
1383 1384 1385 1386 1387
    }

    return ret;
}

1388

1389
virStorageVolDefPtr
1390
virStorageVolDefParseString(virStoragePoolDefPtr pool,
1391 1392
                            const char *xmlStr,
                            unsigned int flags)
1393
{
1394
    return virStorageVolDefParse(pool, xmlStr, NULL, flags);
1395 1396
}

1397

1398
virStorageVolDefPtr
1399
virStorageVolDefParseFile(virStoragePoolDefPtr pool,
1400 1401
                          const char *filename,
                          unsigned int flags)
1402
{
1403
    return virStorageVolDefParse(pool, NULL, filename, flags);
1404
}
1405

1406

1407 1408 1409 1410 1411 1412
static void
virStorageVolTimestampFormat(virBufferPtr buf, const char *name,
                             struct timespec *ts)
{
    if (ts->tv_nsec < 0)
        return;
1413
    virBufferAsprintf(buf, "<%s>%llu", name,
1414 1415 1416 1417 1418 1419
                      (unsigned long long) ts->tv_sec);
    if (ts->tv_nsec)
       virBufferAsprintf(buf, ".%09ld", ts->tv_nsec);
    virBufferAsprintf(buf, "</%s>\n", name);
}

1420

1421
static int
1422
virStorageVolTargetDefFormat(virStorageVolOptionsPtr options,
1423
                             virBufferPtr buf,
1424
                             virStorageSourcePtr def,
1425 1426
                             const char *type)
{
1427 1428
    virBufferAsprintf(buf, "<%s>\n", type);
    virBufferAdjustIndent(buf, 2);
1429

1430
    virBufferEscapeString(buf, "<path>%s</path>\n", def->path);
1431 1432 1433 1434

    if (options->formatToString) {
        const char *format = (options->formatToString)(def->format);
        if (!format) {
1435 1436 1437
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("unknown volume format number %d"),
                           def->format);
1438 1439
            return -1;
        }
1440
        virBufferAsprintf(buf, "<format type='%s'/>\n", format);
1441 1442
    }

1443 1444 1445 1446 1447
    if (def->perms &&
        (def->perms->mode != (mode_t) -1 ||
         def->perms->uid != (uid_t) -1 ||
         def->perms->gid != (gid_t) -1 ||
         def->perms->label)) {
1448 1449
        virBufferAddLit(buf, "<permissions>\n");
        virBufferAdjustIndent(buf, 2);
1450

1451 1452 1453
        if (def->perms->mode != (mode_t) -1)
            virBufferAsprintf(buf, "<mode>0%o</mode>\n",
                              def->perms->mode);
1454 1455 1456 1457 1458 1459
        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);
1460

1461 1462
        virBufferEscapeString(buf, "<label>%s</label>\n",
                              def->perms->label);
1463

1464 1465 1466
        virBufferAdjustIndent(buf, -2);
        virBufferAddLit(buf, "</permissions>\n");
    }
1467

1468
    if (def->timestamps) {
1469 1470
        virBufferAddLit(buf, "<timestamps>\n");
        virBufferAdjustIndent(buf, 2);
1471 1472 1473 1474
        virStorageVolTimestampFormat(buf, "atime", &def->timestamps->atime);
        virStorageVolTimestampFormat(buf, "mtime", &def->timestamps->mtime);
        virStorageVolTimestampFormat(buf, "ctime", &def->timestamps->ctime);
        virStorageVolTimestampFormat(buf, "btime", &def->timestamps->btime);
1475 1476
        virBufferAdjustIndent(buf, -2);
        virBufferAddLit(buf, "</timestamps>\n");
1477 1478
    }

1479 1480
    if (def->encryption &&
        virStorageEncryptionFormat(buf, def->encryption) < 0)
1481
            return -1;
1482

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

1485
    if (def->features) {
1486
        size_t i;
1487 1488
        bool empty = virBitmapIsAllClear(def->features);

1489 1490 1491 1492 1493 1494
        if (empty) {
            virBufferAddLit(buf, "<features/>\n");
        } else {
            virBufferAddLit(buf, "<features>\n");
            virBufferAdjustIndent(buf, 2);
        }
1495 1496

        for (i = 0; i < VIR_STORAGE_FILE_FEATURE_LAST; i++) {
J
Ján Tomko 已提交
1497
            if (virBitmapIsBitSet(def->features, i))
1498
                virBufferAsprintf(buf, "<%s/>\n",
1499
                                  virStorageFileFeatureTypeToString(i));
1500
        }
1501 1502 1503 1504
        if (!empty) {
            virBufferAdjustIndent(buf, -2);
            virBufferAddLit(buf, "</features>\n");
        }
1505 1506
    }

1507 1508
    virBufferAdjustIndent(buf, -2);
    virBufferAsprintf(buf, "</%s>\n", type);
1509 1510
    return 0;
}
1511

1512

1513
char *
1514
virStorageVolDefFormat(virStoragePoolDefPtr pool,
1515 1516
                       virStorageVolDefPtr def)
{
1517
    virStorageVolOptionsPtr options;
1518
    virBuffer buf = VIR_BUFFER_INITIALIZER;
1519

1520
    options = virStorageVolOptionsForPoolType(pool->type);
1521 1522 1523
    if (options == NULL)
        return NULL;

1524 1525
    virBufferAsprintf(&buf, "<volume type='%s'>\n",
                      virStorageVolTypeToString(def->type));
1526 1527 1528 1529 1530 1531
    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);
1532 1533

    if (def->source.nextent) {
1534
        size_t i;
1535
        const char *thispath = NULL;
1536
        for (i = 0; i < def->source.nextent; i++) {
1537 1538 1539
            if (thispath == NULL ||
                STRNEQ(thispath, def->source.extents[i].path)) {
                if (thispath != NULL)
1540
                    virBufferAddLit(&buf, "</device>\n");
1541

1542
                virBufferEscapeString(&buf, "<device path='%s'>\n",
1543
                                      def->source.extents[i].path);
1544 1545
            }

1546 1547
            virBufferAdjustIndent(&buf, 2);
            virBufferAsprintf(&buf, "<extent start='%llu' end='%llu'/>\n",
1548 1549
                              def->source.extents[i].start,
                              def->source.extents[i].end);
1550
            virBufferAdjustIndent(&buf, -2);
1551 1552 1553
            thispath = def->source.extents[i].path;
        }
        if (thispath != NULL)
1554
            virBufferAddLit(&buf, "</device>\n");
1555 1556
    }

1557 1558 1559 1560
    virBufferAdjustIndent(&buf, -2);
    virBufferAddLit(&buf, "</source>\n");

    virBufferAsprintf(&buf, "<capacity unit='bytes'>%llu</capacity>\n",
1561
                      def->target.capacity);
1562
    virBufferAsprintf(&buf, "<allocation unit='bytes'>%llu</allocation>\n",
1563
                      def->target.allocation);
1564 1565 1566 1567 1568 1569
    /* 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);
1570

1571
    if (virStorageVolTargetDefFormat(options, &buf,
1572 1573
                                     &def->target, "target") < 0)
        goto cleanup;
1574

1575
    if (virStorageSourceHasBacking(&def->target) &&
1576
        virStorageVolTargetDefFormat(options, &buf,
1577 1578
                                     def->target.backingStore,
                                     "backingStore") < 0)
1579
        goto cleanup;
1580

1581
    virBufferAdjustIndent(&buf, -2);
E
Eric Blake 已提交
1582
    virBufferAddLit(&buf, "</volume>\n");
1583

1584 1585
    if (virBufferCheckError(&buf) < 0)
        goto cleanup;
1586

1587
    return virBufferContentAndReset(&buf);
1588

1589
 cleanup:
1590
    virBufferFreeAndReset(&buf);
1591 1592 1593 1594
    return NULL;
}


1595 1596 1597 1598
static int
virStoragePoolSaveXML(const char *path,
                      virStoragePoolDefPtr def,
                      const char *xml)
1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609
{
    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;
}
1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643


int
virStoragePoolSaveState(const char *stateFile,
                        virStoragePoolDefPtr def)
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    int ret = -1;
    char *xml;

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

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

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

    if (virBufferCheckError(&buf) < 0)
        goto error;

    if (!(xml = virBufferContentAndReset(&buf)))
        goto error;

    if (virStoragePoolSaveXML(stateFile, def, xml))
        goto error;

    ret = 0;

 error:
    VIR_FREE(xml);
    return ret;
}
1644 1645


1646
int
1647
virStoragePoolSaveConfig(const char *configFile,
1648 1649
                         virStoragePoolDefPtr def)
{
1650
    char *xml;
1651
    int ret = -1;
1652

1653 1654 1655 1656 1657 1658
    if (!(xml = virStoragePoolDefFormat(def))) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("failed to generate XML"));
        return -1;
    }

1659 1660
    if (virStoragePoolSaveXML(configFile, def, xml))
        goto cleanup;
1661

1662 1663 1664
    ret = 0;
 cleanup:
    VIR_FREE(xml);
1665 1666 1667
    return ret;
}

1668

1669
virStoragePoolSourcePtr
1670
virStoragePoolSourceListNewSource(virStoragePoolSourceListPtr list)
1671 1672 1673
{
    virStoragePoolSourcePtr source;

1674
    if (VIR_REALLOC_N(list->sources, list->nsources + 1) < 0)
1675 1676 1677 1678 1679 1680 1681 1682
        return NULL;

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

    return source;
}

1683

1684 1685
char *
virStoragePoolSourceListFormat(virStoragePoolSourceListPtr def)
1686
{
1687
    virStoragePoolOptionsPtr options;
1688
    virBuffer buf = VIR_BUFFER_INITIALIZER;
1689
    const char *type;
1690
    size_t i;
1691

1692
    options = virStoragePoolOptionsForPoolType(def->type);
1693 1694 1695
    if (options == NULL)
        return NULL;

1696
    type = virStoragePoolTypeToString(def->type);
1697
    if (!type) {
1698 1699
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("unexpected pool type"));
1700 1701 1702 1703
        goto cleanup;
    }

    virBufferAddLit(&buf, "<sources>\n");
1704
    virBufferAdjustIndent(&buf, 2);
1705

1706
    for (i = 0; i < def->nsources; i++)
1707
        virStoragePoolSourceFormat(&buf, options, &def->sources[i]);
1708

1709
    virBufferAdjustIndent(&buf, -2);
1710 1711
    virBufferAddLit(&buf, "</sources>\n");

1712 1713
    if (virBufferCheckError(&buf) < 0)
        goto cleanup;
1714 1715

    return virBufferContentAndReset(&buf);
1716

1717
 cleanup:
1718
    virBufferFreeAndReset(&buf);
1719
    return NULL;
1720
}