storage_conf.c 51.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
    {.poolType = VIR_STORAGE_POOL_ISCSI,
     .poolOptions = {
         .flags = (VIR_STORAGE_POOL_SOURCE_HOST |
                   VIR_STORAGE_POOL_SOURCE_DEVICE |
                   VIR_STORAGE_POOL_SOURCE_INITIATOR_IQN),
      },
211
      .volOptions = {
212 213 214
         .formatToString = virStoragePoolFormatDiskTypeToString,
      }
    },
215 216 217 218 219 220 221 222 223 224 225
    {.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,
      }
    },
226 227 228 229 230 231 232
    {.poolType = VIR_STORAGE_POOL_SCSI,
     .poolOptions = {
         .flags = (VIR_STORAGE_POOL_SOURCE_ADAPTER),
     },
     .volOptions = {
         .formatToString = virStoragePoolFormatDiskTypeToString,
     }
233
    },
234 235 236 237 238 239
    {.poolType = VIR_STORAGE_POOL_RBD,
     .poolOptions = {
         .flags = (VIR_STORAGE_POOL_SOURCE_HOST |
                   VIR_STORAGE_POOL_SOURCE_NETWORK |
                   VIR_STORAGE_POOL_SOURCE_NAME),
      },
240
      .volOptions = {
241
          .defaultFormat = VIR_STORAGE_FILE_RAW,
242 243
          .formatFromString = virStorageVolumeFormatFromString,
          .formatToString = virStorageFileFormatTypeToString,
244
      }
245
    },
246 247 248 249 250 251 252 253 254 255
    {.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,
     }
256
    },
257 258 259 260 261 262 263 264 265 266 267 268 269
    {.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,
     }
    },
270 271 272 273
    {.poolType = VIR_STORAGE_POOL_MPATH,
     .volOptions = {
         .formatToString = virStoragePoolFormatDiskTypeToString,
     }
274
    },
275 276 277 278 279 280 281 282 283 284 285 286
    {.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 已提交
287 288 289
    },
    {.poolType = VIR_STORAGE_POOL_ZFS,
     .poolOptions = {
290 291
         .flags = (VIR_STORAGE_POOL_SOURCE_NAME |
                   VIR_STORAGE_POOL_SOURCE_DEVICE),
R
Roman Bogorodskiy 已提交
292 293 294
         .defaultFormat = VIR_STORAGE_FILE_RAW,
     },
    },
295 296 297 298 299 300 301 302 303 304
    {.poolType = VIR_STORAGE_POOL_VSTORAGE,
     .poolOptions = {
        .flags = VIR_STORAGE_POOL_SOURCE_NAME,
     },
     .volOptions = {
        .defaultFormat = VIR_STORAGE_FILE_RAW,
        .formatFromString = virStorageVolumeFormatFromString,
        .formatToString = virStorageFileFormatTypeToString,
     },
    },
305 306 307 308
};


static virStoragePoolTypeInfoPtr
309 310
virStoragePoolTypeInfoLookup(int type)
{
311
    size_t i;
312
    for (i = 0; i < ARRAY_CARDINALITY(poolTypeInfo); i++)
313 314 315
        if (poolTypeInfo[i].poolType == type)
            return &poolTypeInfo[i];

316 317
    virReportError(VIR_ERR_INTERNAL_ERROR,
                   _("missing backend for pool type %d"), type);
318 319 320
    return NULL;
}

321

322
static virStoragePoolOptionsPtr
323 324
virStoragePoolOptionsForPoolType(int type)
{
325 326 327 328 329 330
    virStoragePoolTypeInfoPtr backend = virStoragePoolTypeInfoLookup(type);
    if (backend == NULL)
        return NULL;
    return &backend->poolOptions;
}

331

332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359
/* 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;
}


360
static virStorageVolOptionsPtr
361 362
virStorageVolOptionsForPoolType(int type)
{
363 364 365 366 367 368 369
    virStoragePoolTypeInfoPtr backend = virStoragePoolTypeInfoLookup(type);
    if (backend == NULL)
        return NULL;
    return &backend->volOptions;
}


370
void
371 372
virStorageVolDefFree(virStorageVolDefPtr def)
{
373
    size_t i;
374 375 376 377

    if (!def)
        return;

378 379
    VIR_FREE(def->name);
    VIR_FREE(def->key);
380

381
    for (i = 0; i < def->source.nextent; i++)
382 383
        VIR_FREE(def->source.extents[i].path);
    VIR_FREE(def->source.extents);
384

385
    virStorageSourceClear(&def->target);
386
    VIR_FREE(def);
387 388
}

389

390 391 392 393 394 395 396
void
virStoragePoolSourceDeviceClear(virStoragePoolSourceDevicePtr dev)
{
    VIR_FREE(dev->freeExtents);
    VIR_FREE(dev->path);
}

397

398
void
399 400
virStoragePoolSourceClear(virStoragePoolSourcePtr source)
{
401
    size_t i;
402

403
    if (!source)
404 405
        return;

406
    for (i = 0; i < source->nhost; i++)
407 408 409
        VIR_FREE(source->hosts[i].name);
    VIR_FREE(source->hosts);

410 411
    for (i = 0; i < source->ndevice; i++)
        virStoragePoolSourceDeviceClear(&source->devices[i]);
412 413 414
    VIR_FREE(source->devices);
    VIR_FREE(source->dir);
    VIR_FREE(source->name);
415
    virStorageAdapterClear(&source->adapter);
416
    virStorageSourceInitiatorClear(&source->initiator);
417
    virStorageAuthDefFree(source->auth);
418 419
    VIR_FREE(source->vendor);
    VIR_FREE(source->product);
420 421
}

422

423 424 425 426 427 428 429
void
virStoragePoolSourceFree(virStoragePoolSourcePtr source)
{
    virStoragePoolSourceClear(source);
    VIR_FREE(source);
}

430

431
void
432 433
virStoragePoolDefFree(virStoragePoolDefPtr def)
{
434 435 436 437 438
    if (!def)
        return;

    VIR_FREE(def->name);

439
    virStoragePoolSourceClear(&def->source);
440

441 442
    VIR_FREE(def->target.path);
    VIR_FREE(def->target.perms.label);
443 444
    if (def->namespaceData && def->ns.free)
        (def->ns.free)(def->namespaceData);
445
    VIR_FREE(def);
446 447 448
}


449
static int
450
virStoragePoolDefParseSource(xmlXPathContextPtr ctxt,
451 452
                             virStoragePoolSourcePtr source,
                             int pool_type,
453 454
                             xmlNodePtr node)
{
455
    int ret = -1;
456
    xmlNodePtr relnode, authnode, *nodeset = NULL;
457
    xmlNodePtr adapternode;
458 459
    int nsource;
    size_t i;
460
    virStoragePoolOptionsPtr options;
461
    char *name = NULL;
462
    char *port = NULL;
463
    char *ver = NULL;
464
    int n;
465
    VIR_AUTOPTR(virStorageAuthDef) authdef = NULL;
466 467 468 469

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

470
    if ((options = virStoragePoolOptionsForPoolType(pool_type)) == NULL)
471 472
        goto cleanup;

473
    source->name = virXPathString("string(./name)", ctxt);
474
    if (pool_type == VIR_STORAGE_POOL_RBD && source->name == NULL) {
475
        virReportError(VIR_ERR_XML_ERROR, "%s",
476
                       _("element 'name' is mandatory for RBD pool"));
477 478
        goto cleanup;
    }
479 480

    if (options->formatFromString) {
481
        char *format = virXPathString("string(./format/@type)", ctxt);
482 483 484 485 486 487
        if (format == NULL)
            source->format = options->defaultFormat;
        else
            source->format = options->formatFromString(format);

        if (source->format < 0) {
488
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
489
                           _("unknown pool format type %s"), format);
490 491 492 493 494 495
            VIR_FREE(format);
            goto cleanup;
        }
        VIR_FREE(format);
    }

496 497
    if ((n = virXPathNodeSet("./host", ctxt, &nodeset)) < 0)
        goto cleanup;
498

499 500
    if (n) {
        if (VIR_ALLOC_N(source->hosts, n) < 0)
501
            goto cleanup;
502
        source->nhost = n;
503

504
        for (i = 0; i < source->nhost; i++) {
505 506
            name = virXMLPropString(nodeset[i], "name");
            if (name == NULL) {
507 508
                virReportError(VIR_ERR_XML_ERROR, "%s",
                               _("missing storage pool host name"));
509 510 511 512 513 514 515
                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) {
516 517 518
                    virReportError(VIR_ERR_XML_ERROR,
                                   _("Invalid port number: %s"),
                                   port);
519 520
                    goto cleanup;
                }
521
                VIR_FREE(port);
522 523 524
            }
        }
    }
525

526
    VIR_FREE(nodeset);
527 528

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

530
    nsource = virXPathNodeSet("./device", ctxt, &nodeset);
531 532 533
    if (nsource < 0)
        goto cleanup;

534
    for (i = 0; i < nsource; i++) {
535
        char *partsep;
536 537 538 539 540 541
        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"));
542 543 544
            goto cleanup;
        }

545 546 547 548 549 550 551 552 553 554 555 556 557 558
        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);
        }

559 560 561
        if (VIR_APPEND_ELEMENT(source->devices, source->ndevice, dev) < 0) {
            virStoragePoolSourceDeviceClear(&dev);
            goto cleanup;
562
        }
563

564 565
    }

566
    source->dir = virXPathString("string(./dir/@path)", ctxt);
567 568 569 570
    /* In gluster, a missing dir defaults to "/" */
    if (!source->dir && pool_type == VIR_STORAGE_POOL_GLUSTER &&
        VIR_STRDUP(source->dir, "/") < 0)
        goto cleanup;
571

572
    if ((adapternode = virXPathNode("./adapter", ctxt))) {
573
        if (virStorageAdapterParseXML(&source->adapter, adapternode, ctxt) < 0)
574 575
            goto cleanup;
    }
576

577
    if ((authnode = virXPathNode("./auth", ctxt))) {
578
        if (!(authdef = virStorageAuthDefParse(authnode, ctxt)))
579 580 581 582 583 584 585 586
            goto cleanup;

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

587
        VIR_STEAL_PTR(source->auth, authdef);
588
    }
589

590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607
    /* 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;
        }
    }

608 609 610
    source->vendor = virXPathString("string(./vendor/@name)", ctxt);
    source->product = virXPathString("string(./product/@name)", ctxt);

611
    ret = 0;
612
 cleanup:
613 614
    ctxt->node = relnode;

615
    VIR_FREE(port);
616 617 618
    VIR_FREE(nodeset);
    return ret;
}
619

620

621
virStoragePoolSourcePtr
622
virStoragePoolDefParseSourceString(const char *srcSpec,
623 624 625 626 627
                                   int pool_type)
{
    xmlDocPtr doc = NULL;
    xmlNodePtr node = NULL;
    xmlXPathContextPtr xpath_ctxt = NULL;
628 629
    virStoragePoolSourcePtr ret = NULL;
    VIR_AUTOPTR(virStoragePoolSource) def = NULL;
630

631 632 633
    if (!(doc = virXMLParseStringCtxt(srcSpec,
                                      _("(storage_source_specification)"),
                                      &xpath_ctxt)))
634 635
        goto cleanup;

636
    if (VIR_ALLOC(def) < 0)
637 638
        goto cleanup;

639
    if (!(node = virXPathNode("/source", xpath_ctxt))) {
640 641
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("root element was not source"));
642 643 644
        goto cleanup;
    }

645
    if (virStoragePoolDefParseSource(xpath_ctxt, def, pool_type,
646 647 648
                                     node) < 0)
        goto cleanup;

649
    VIR_STEAL_PTR(ret, def);
650
 cleanup:
651 652 653 654 655
    xmlFreeDoc(doc);
    xmlXPathFreeContext(xpath_ctxt);

    return ret;
}
656

657

658
static int
659
virStorageDefParsePerms(xmlXPathContextPtr ctxt,
660
                        virStoragePermsPtr perms,
661
                        const char *permxpath)
662
{
663
    char *mode;
664
    long long val;
665 666 667
    int ret = -1;
    xmlNodePtr relnode;
    xmlNodePtr node;
668

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

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

682
    if ((mode = virXPathString("string(./mode)", ctxt))) {
683 684 685
        int tmp;

        if (virStrToLong_i(mode, NULL, 8, &tmp) < 0 || (tmp & ~0777)) {
686
            VIR_FREE(mode);
687 688
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("malformed octal mode"));
689
            goto error;
690
        }
691
        perms->mode = tmp;
692
        VIR_FREE(mode);
693 694
    } else {
        perms->mode = (mode_t) -1;
695 696
    }

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

        perms->uid = val;
710 711
    }

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

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

729
    ret = 0;
730
 error:
731 732
    ctxt->node = relnode;
    return ret;
733 734
}

735

J
John Ferlan 已提交
736
virStoragePoolDefPtr
737 738
virStoragePoolDefParseXML(xmlXPathContextPtr ctxt)
{
739
    virStoragePoolOptionsPtr options;
740 741
    virStoragePoolDefPtr def;
    virStoragePoolDefPtr ret = NULL;
742
    xmlNodePtr source_node;
743
    char *type = NULL;
744
    char *uuid = NULL;
745
    char *target_path = NULL;
746

747
    if (VIR_ALLOC(def) < 0)
748 749
        return NULL;

750
    type = virXPathString("string(./@type)", ctxt);
751 752 753
    if (type == NULL) {
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("storage pool missing type attribute"));
754
        goto cleanup;
755 756
    }

757
    if ((def->type = virStoragePoolTypeFromString(type)) < 0) {
758
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
759
                       _("unknown storage pool type %s"), type);
760
        goto cleanup;
761 762
    }

763 764
    if ((options = virStoragePoolOptionsForPoolType(def->type)) == NULL)
        goto cleanup;
765

766
    source_node = virXPathNode("./source", ctxt);
767
    if (source_node) {
768
        if (virStoragePoolDefParseSource(ctxt, &def->source, def->type,
769
                                         source_node) < 0)
770
            goto cleanup;
771 772
    } else {
        if (options->formatFromString)
773
            def->source.format = options->defaultFormat;
774 775
    }

776 777
    def->name = virXPathString("string(./name)", ctxt);
    if (def->name == NULL &&
778
        options->flags & VIR_STORAGE_POOL_SOURCE_NAME &&
779 780 781
        VIR_STRDUP(def->name, def->source.name) < 0)
        goto cleanup;
    if (def->name == NULL) {
782 783
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("missing pool source name element"));
784
        goto cleanup;
785 786
    }

787
    if (strchr(def->name, '/')) {
788
        virReportError(VIR_ERR_XML_ERROR,
789 790
                       _("name %s cannot contain '/'"), def->name);
        goto cleanup;
791 792
    }

793
    uuid = virXPathString("string(./uuid)", ctxt);
794
    if (uuid == NULL) {
795
        if (virUUIDGenerate(def->uuid) < 0) {
796 797
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("unable to generate uuid"));
798
            goto cleanup;
799 800
        }
    } else {
801
        if (virUUIDParse(uuid, def->uuid) < 0) {
802 803
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("malformed uuid element"));
804
            goto cleanup;
805 806 807
        }
    }

808
    if (options->flags & VIR_STORAGE_POOL_SOURCE_HOST) {
809
        if (!def->source.nhost) {
810
            virReportError(VIR_ERR_XML_ERROR, "%s",
811
                           _("missing storage pool source host name"));
812
            goto cleanup;
813 814 815
        }
    }

816
    if (options->flags & VIR_STORAGE_POOL_SOURCE_DIR) {
817
        if (!def->source.dir) {
818 819
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("missing storage pool source path"));
820
            goto cleanup;
821 822
        }
    }
823
    if (options->flags & VIR_STORAGE_POOL_SOURCE_NAME) {
824
        if (def->source.name == NULL) {
825
            /* source name defaults to pool name */
826 827
            if (VIR_STRDUP(def->source.name, def->name) < 0)
                goto cleanup;
828 829
        }
    }
830

831
    if ((options->flags & VIR_STORAGE_POOL_SOURCE_ADAPTER) &&
832 833
        (virStorageAdapterValidate(&def->source.adapter)) < 0)
            goto cleanup;
834

835 836
    /* If DEVICE is the only source type, then its required */
    if (options->flags == VIR_STORAGE_POOL_SOURCE_DEVICE) {
837
        if (!def->source.ndevice) {
838 839
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("missing storage pool source device name"));
840
            goto cleanup;
841 842 843
        }
    }

844 845 846
    /* When we are working with a virtual disk we can skip the target
     * path and permissions */
    if (!(options->flags & VIR_STORAGE_POOL_SOURCE_NETWORK)) {
847 848 849 850 851 852
        if (def->type == VIR_STORAGE_POOL_LOGICAL) {
            if (virAsprintf(&target_path, "/dev/%s", def->source.name) < 0)
                goto cleanup;
        } else if (def->type == VIR_STORAGE_POOL_ZFS) {
            if (virAsprintf(&target_path, "/dev/zvol/%s", def->source.name) < 0)
                goto cleanup;
853 854 855 856 857
        } else {
            target_path = virXPathString("string(./target/path)", ctxt);
            if (!target_path) {
                virReportError(VIR_ERR_XML_ERROR, "%s",
                               _("missing storage pool target path"));
858
                goto cleanup;
859
            }
860
        }
861 862 863
        def->target.path = virFileSanitizePath(target_path);
        if (!def->target.path)
            goto cleanup;
864

865
        if (virStorageDefParsePerms(ctxt, &def->target.perms,
866
                                    "./target/permissions") < 0)
867
            goto cleanup;
868
    }
869

870 871
    if (def->type == VIR_STORAGE_POOL_ISCSI_DIRECT &&
        !def->source.initiator.iqn) {
872 873
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("missing initiator IQN"));
874
        goto cleanup;
875 876
    }

877 878
    /* Make a copy of all the callback pointers here for easier use,
     * especially during the virStoragePoolSourceClear method */
879 880 881 882
    def->ns = options->ns;
    if (def->ns.parse &&
        (def->ns.parse)(ctxt, &def->namespaceData) < 0)
        goto cleanup;
883

884
    VIR_STEAL_PTR(ret, def);
885
 cleanup:
886
    virStoragePoolDefFree(def);
887
    VIR_FREE(uuid);
888 889 890
    VIR_FREE(type);
    VIR_FREE(target_path);
    return ret;
891 892
}

893

894
virStoragePoolDefPtr
895
virStoragePoolDefParseNode(xmlDocPtr xml,
896 897
                           xmlNodePtr root)
{
898 899 900
    xmlXPathContextPtr ctxt = NULL;
    virStoragePoolDefPtr def = NULL;

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

    ctxt = xmlXPathNewContext(xml);
    if (ctxt == NULL) {
911
        virReportOOMError();
912 913 914 915
        goto cleanup;
    }

    ctxt->node = root;
916
    def = virStoragePoolDefParseXML(ctxt);
917
 cleanup:
918 919 920 921
    xmlXPathFreeContext(ctxt);
    return def;
}

922

923
static virStoragePoolDefPtr
924
virStoragePoolDefParse(const char *xmlStr,
925 926
                       const char *filename)
{
927
    virStoragePoolDefPtr ret = NULL;
J
Jiri Denemark 已提交
928
    xmlDocPtr xml;
929

930
    if ((xml = virXMLParse(filename, xmlStr, _("(storage_pool_definition)")))) {
J
Jiri Denemark 已提交
931 932
        ret = virStoragePoolDefParseNode(xml, xmlDocGetRootElement(xml));
        xmlFreeDoc(xml);
933 934
    }

935 936 937
    return ret;
}

938

939
virStoragePoolDefPtr
940
virStoragePoolDefParseString(const char *xmlStr)
941
{
942
    return virStoragePoolDefParse(xmlStr, NULL);
943 944
}

945

946
virStoragePoolDefPtr
947
virStoragePoolDefParseFile(const char *filename)
948
{
949
    return virStoragePoolDefParse(NULL, filename);
950 951
}

952

953
static int
954
virStoragePoolSourceFormat(virBufferPtr buf,
955
                           virStoragePoolOptionsPtr options,
956 957
                           virStoragePoolSourcePtr src)
{
958
    size_t i, j;
959

960 961 962
    virBufferAddLit(buf, "<source>\n");
    virBufferAdjustIndent(buf, 2);

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

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

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

1002
    if ((options->flags & VIR_STORAGE_POOL_SOURCE_ADAPTER) &&
1003 1004 1005
        (src->adapter.type == VIR_STORAGE_ADAPTER_TYPE_FC_HOST ||
         src->adapter.type == VIR_STORAGE_ADAPTER_TYPE_SCSI_HOST))
        virStorageAdapterFormat(buf, &src->adapter);
1006

1007
    if (options->flags & VIR_STORAGE_POOL_SOURCE_NAME)
1008
        virBufferEscapeString(buf, "<name>%s</name>\n", src->name);
1009

1010 1011
    if (options->flags & VIR_STORAGE_POOL_SOURCE_INITIATOR_IQN)
        virStorageSourceInitiatorFormatXML(&src->initiator, buf);
D
David Allan 已提交
1012

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

1024 1025
    if (src->auth)
        virStorageAuthDefFormat(buf, src->auth);
1026

1027 1028 1029
    if (src->protocolVer)
        virBufferAsprintf(buf, "<protocol ver='%u'/>\n", src->protocolVer);

1030 1031
    virBufferEscapeString(buf, "<vendor name='%s'/>\n", src->vendor);
    virBufferEscapeString(buf, "<product name='%s'/>\n", src->product);
1032

1033 1034
    virBufferAdjustIndent(buf, -2);
    virBufferAddLit(buf, "</source>\n");
1035 1036 1037
    return 0;
}

1038

1039 1040 1041
static int
virStoragePoolDefFormatBuf(virBufferPtr buf,
                           virStoragePoolDefPtr def)
1042
{
1043
    virStoragePoolOptionsPtr options;
1044
    char uuid[VIR_UUID_STRING_BUFLEN];
1045
    const char *type;
1046

1047
    options = virStoragePoolOptionsForPoolType(def->type);
1048
    if (options == NULL)
1049
        return -1;
1050

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

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

1067
    virBufferAsprintf(buf, "<capacity unit='bytes'>%llu</capacity>\n",
1068
                      def->capacity);
1069
    virBufferAsprintf(buf, "<allocation unit='bytes'>%llu</allocation>\n",
1070
                      def->allocation);
1071
    virBufferAsprintf(buf, "<available unit='bytes'>%llu</available>\n",
1072
                      def->available);
1073

1074 1075
    if (virStoragePoolSourceFormat(buf, options, &def->source) < 0)
        return -1;
1076

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

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

1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108
        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");
        }
1109

1110 1111
        virBufferAdjustIndent(buf, -2);
        virBufferAddLit(buf, "</target>\n");
1112
    }
1113 1114 1115 1116 1117 1118

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

1119 1120 1121 1122 1123 1124
    virBufferAdjustIndent(buf, -2);
    virBufferAddLit(buf, "</pool>\n");

    return 0;
}

1125

1126 1127 1128 1129 1130 1131 1132
char *
virStoragePoolDefFormat(virStoragePoolDefPtr def)
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;

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

1134
    if (virBufferCheckError(&buf) < 0)
1135
        goto error;
1136

1137
    return virBufferContentAndReset(&buf);
1138

1139
 error:
1140
    virBufferFreeAndReset(&buf);
1141 1142 1143 1144 1145
    return NULL;
}


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

    return 0;
}

1163

1164
static virStorageVolDefPtr
1165
virStorageVolDefParseXML(virStoragePoolDefPtr pool,
1166 1167
                         xmlXPathContextPtr ctxt,
                         unsigned int flags)
1168
{
1169
    virStorageVolDefPtr ret = NULL;
1170
    virStorageVolOptionsPtr options;
1171
    char *type = NULL;
1172 1173 1174
    char *allocation = NULL;
    char *capacity = NULL;
    char *unit = NULL;
1175
    char *backingStore = NULL;
1176
    xmlNodePtr node;
1177
    xmlNodePtr *nodes = NULL;
1178 1179
    size_t i;
    int n;
1180
    VIR_AUTOPTR(virStorageVolDef) def = NULL;
1181

1182 1183
    virCheckFlags(VIR_VOL_XML_PARSE_NO_CAPACITY |
                  VIR_VOL_XML_PARSE_OPT_CAPACITY, NULL);
1184

1185
    options = virStorageVolOptionsForPoolType(pool->type);
1186 1187 1188
    if (options == NULL)
        return NULL;

1189
    if (VIR_ALLOC(def) < 0)
1190 1191
        return NULL;

1192
    def->target.type = VIR_STORAGE_TYPE_FILE;
1193

1194 1195
    def->name = virXPathString("string(./name)", ctxt);
    if (def->name == NULL) {
1196 1197
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("missing volume name element"));
1198
        goto cleanup;
1199 1200
    }

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

1204 1205 1206
    /* Technically overridden by pool refresh, but useful for unit tests */
    type = virXPathString("string(./@type)", ctxt);
    if (type) {
1207
        if ((def->type = virStorageVolTypeFromString(type)) < 0) {
1208
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1209
                           _("unknown volume type '%s'"), type);
1210
            goto cleanup;
1211 1212 1213
        }
    }

1214
    if ((backingStore = virXPathString("string(./backingStore/path)", ctxt))) {
1215 1216
        if (VIR_ALLOC(def->target.backingStore) < 0)
            goto cleanup;
1217

1218
        def->target.backingStore->type = VIR_STORAGE_TYPE_FILE;
1219

1220
        def->target.backingStore->path = backingStore;
1221 1222 1223 1224 1225
        backingStore = NULL;

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

1230
            if (def->target.backingStore->format < 0) {
1231 1232 1233
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("unknown volume format type %s"), format);
                VIR_FREE(format);
1234
                goto cleanup;
1235 1236 1237 1238
            }
            VIR_FREE(format);
        }

1239 1240 1241
        if (VIR_ALLOC(def->target.backingStore->perms) < 0)
            goto cleanup;
        if (virStorageDefParsePerms(ctxt, def->target.backingStore->perms,
1242
                                    "./backingStore/permissions") < 0)
1243
            goto cleanup;
1244 1245
    }

1246 1247
    capacity = virXPathString("string(./capacity)", ctxt);
    unit = virXPathString("string(./capacity/@unit)", ctxt);
1248
    if (capacity) {
1249 1250
        if (virStorageSize(unit, capacity, &def->target.capacity) < 0)
            goto cleanup;
1251
    } else if (!(flags & VIR_VOL_XML_PARSE_NO_CAPACITY) &&
1252
               !((flags & VIR_VOL_XML_PARSE_OPT_CAPACITY) &&
1253
                 virStorageSourceHasBacking(&def->target))) {
1254
        virReportError(VIR_ERR_XML_ERROR, "%s", _("missing capacity element"));
1255
        goto cleanup;
1256
    }
1257
    VIR_FREE(unit);
1258

1259
    allocation = virXPathString("string(./allocation)", ctxt);
1260
    if (allocation) {
1261
        unit = virXPathString("string(./allocation/@unit)", ctxt);
1262 1263 1264
        if (virStorageSize(unit, allocation, &def->target.allocation) < 0)
            goto cleanup;
        def->target.has_allocation = true;
1265
    } else {
1266
        def->target.allocation = def->target.capacity;
1267 1268
    }

1269
    def->target.path = virXPathString("string(./target/path)", ctxt);
1270
    if (options->formatFromString) {
1271
        char *format = virXPathString("string(./target/format/@type)", ctxt);
1272
        if (format == NULL)
1273
            def->target.format = options->defaultFormat;
1274
        else
1275
            def->target.format = (options->formatFromString)(format);
1276

1277
        if (def->target.format < 0) {
1278
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1279
                           _("unknown volume format type %s"), format);
1280
            VIR_FREE(format);
1281
            goto cleanup;
1282
        }
1283
        VIR_FREE(format);
1284 1285
    }

1286 1287 1288
    if (VIR_ALLOC(def->target.perms) < 0)
        goto cleanup;
    if (virStorageDefParsePerms(ctxt, def->target.perms,
1289
                                "./target/permissions") < 0)
1290
        goto cleanup;
1291

1292
    node = virXPathNode("./target/encryption", ctxt);
1293
    if (node != NULL) {
1294 1295 1296
        def->target.encryption = virStorageEncryptionParseNode(node, ctxt);
        if (def->target.encryption == NULL)
            goto cleanup;
1297 1298
    }

1299 1300 1301
    def->target.compat = virXPathString("string(./target/compat)", ctxt);
    if (virStorageFileCheckCompat(def->target.compat) < 0)
        goto cleanup;
1302

C
Chunyan Liu 已提交
1303
    if (virXPathNode("./target/nocow", ctxt))
1304
        def->target.nocow = true;
C
Chunyan Liu 已提交
1305

1306
    if (virXPathNode("./target/features", ctxt)) {
1307
        if ((n = virXPathNodeSet("./target/features/*", ctxt, &nodes)) < 0)
1308
            goto cleanup;
1309

1310 1311
        if (!def->target.compat && VIR_STRDUP(def->target.compat, "1.1") < 0)
            goto cleanup;
1312

1313 1314
        if (!(def->target.features = virBitmapNew(VIR_STORAGE_FILE_FEATURE_LAST)))
            goto cleanup;
1315 1316

        for (i = 0; i < n; i++) {
1317
            int f = virStorageFileFeatureTypeFromString((const char*)nodes[i]->name);
1318 1319

            if (f < 0) {
1320
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unsupported feature %s"),
1321
                               (const char*)nodes[i]->name);
1322
                goto cleanup;
1323
            }
1324
            ignore_value(virBitmapSetBit(def->target.features, f));
1325 1326 1327 1328
        }
        VIR_FREE(nodes);
    }

1329 1330
    VIR_STEAL_PTR(ret, def);

1331
 cleanup:
1332
    VIR_FREE(nodes);
1333 1334 1335
    VIR_FREE(allocation);
    VIR_FREE(capacity);
    VIR_FREE(unit);
1336
    VIR_FREE(type);
1337
    VIR_FREE(backingStore);
1338
    return ret;
1339 1340
}

1341

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

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

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

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

1372

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

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

    return ret;
}

1390

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

1399

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

1408

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

1422

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1514

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

1522
    options = virStorageVolOptionsForPoolType(pool->type);
1523 1524 1525
    if (options == NULL)
        return NULL;

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

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

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

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

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

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

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

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

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

1586 1587
    if (virBufferCheckError(&buf) < 0)
        goto cleanup;
1588

1589
    return virBufferContentAndReset(&buf);
1590

1591
 cleanup:
1592
    virBufferFreeAndReset(&buf);
1593 1594 1595 1596
    return NULL;
}


1597 1598 1599 1600
static int
virStoragePoolSaveXML(const char *path,
                      virStoragePoolDefPtr def,
                      const char *xml)
1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611
{
    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;
}
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 1644 1645


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;
}
1646 1647


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

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

1661 1662
    if (virStoragePoolSaveXML(configFile, def, xml))
        goto cleanup;
1663

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

1670

1671
virStoragePoolSourcePtr
1672
virStoragePoolSourceListNewSource(virStoragePoolSourceListPtr list)
1673 1674 1675
{
    virStoragePoolSourcePtr source;

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

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

    return source;
}

1685

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

1694
    options = virStoragePoolOptionsForPoolType(def->type);
1695 1696 1697
    if (options == NULL)
        return NULL;

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

    virBufferAddLit(&buf, "<sources>\n");
1706
    virBufferAdjustIndent(&buf, 2);
1707

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

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

1714 1715
    if (virBufferCheckError(&buf) < 0)
        goto cleanup;
1716 1717

    return virBufferContentAndReset(&buf);
1718

1719
 cleanup:
1720
    virBufferFreeAndReset(&buf);
1721
    return NULL;
1722
}