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
    virStorageAuthDefPtr authdef = NULL;
462
    char *name = NULL;
463
    char *port = NULL;
464
    char *ver = NULL;
465
    int n;
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
    VIR_FREE(nodeset);
617
    virStorageAuthDefFree(authdef);
618 619
    return ret;
}
620

621

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

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
    virStoragePoolSourceFree(def);
652 653 654 655 656
    xmlFreeDoc(doc);
    xmlXPathFreeContext(xpath_ctxt);

    return ret;
}
657

658

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

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

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

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

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

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

        perms->uid = val;
711 712
    }

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

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

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

736

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

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

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

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

763
    if ((options = virStoragePoolOptionsForPoolType(ret->type)) == NULL)
764
        goto error;
765

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

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

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

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

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

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

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

835 836 837
    /* If DEVICE is the only source type, then its required */
    if (options->flags == VIR_STORAGE_POOL_SOURCE_DEVICE) {
        if (!ret->source.ndevice) {
838 839
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("missing storage pool source device name"));
840
            goto error;
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
        if (ret->type == VIR_STORAGE_POOL_LOGICAL) {
848
            if (virAsprintf(&target_path, "/dev/%s", ret->source.name) < 0)
849
                goto error;
R
Roman Bogorodskiy 已提交
850
        } else if (ret->type == VIR_STORAGE_POOL_ZFS) {
851
            if (virAsprintf(&target_path, "/dev/zvol/%s", ret->source.name) < 0)
R
Roman Bogorodskiy 已提交
852
                goto error;
853 854 855 856 857 858 859
        } else {
            target_path = virXPathString("string(./target/path)", ctxt);
            if (!target_path) {
                virReportError(VIR_ERR_XML_ERROR, "%s",
                               _("missing storage pool target path"));
                goto error;
            }
860
        }
861
        ret->target.path = virFileSanitizePath(target_path);
862
        if (!ret->target.path)
863
            goto error;
864

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

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

877 878 879 880 881 882 883
    /* 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;

884
 cleanup:
885
    VIR_FREE(uuid);
886 887 888 889
    VIR_FREE(type);
    VIR_FREE(target_path);
    return ret;

890
 error:
891
    virStoragePoolDefFree(ret);
892 893
    ret = NULL;
    goto cleanup;
894 895
}

896

897
virStoragePoolDefPtr
898
virStoragePoolDefParseNode(xmlDocPtr xml,
899 900
                           xmlNodePtr root)
{
901 902 903
    xmlXPathContextPtr ctxt = NULL;
    virStoragePoolDefPtr def = NULL;

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

    ctxt = xmlXPathNewContext(xml);
    if (ctxt == NULL) {
914
        virReportOOMError();
915 916 917 918
        goto cleanup;
    }

    ctxt->node = root;
919
    def = virStoragePoolDefParseXML(ctxt);
920
 cleanup:
921 922 923 924
    xmlXPathFreeContext(ctxt);
    return def;
}

925

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

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

938 939 940
    return ret;
}

941

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

948

949
virStoragePoolDefPtr
950
virStoragePoolDefParseFile(const char *filename)
951
{
952
    return virStoragePoolDefParse(NULL, filename);
953 954
}

955

956
static int
957
virStoragePoolSourceFormat(virBufferPtr buf,
958
                           virStoragePoolOptionsPtr options,
959 960
                           virStoragePoolSourcePtr src)
{
961
    size_t i, j;
962

963 964 965
    virBufferAddLit(buf, "<source>\n");
    virBufferAdjustIndent(buf, 2);

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

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

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

1005
    if ((options->flags & VIR_STORAGE_POOL_SOURCE_ADAPTER) &&
1006 1007 1008
        (src->adapter.type == VIR_STORAGE_ADAPTER_TYPE_FC_HOST ||
         src->adapter.type == VIR_STORAGE_ADAPTER_TYPE_SCSI_HOST))
        virStorageAdapterFormat(buf, &src->adapter);
1009

1010
    if (options->flags & VIR_STORAGE_POOL_SOURCE_NAME)
1011
        virBufferEscapeString(buf, "<name>%s</name>\n", src->name);
1012

1013 1014
    if (options->flags & VIR_STORAGE_POOL_SOURCE_INITIATOR_IQN)
        virStorageSourceInitiatorFormatXML(&src->initiator, buf);
D
David Allan 已提交
1015

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

1027 1028
    if (src->auth)
        virStorageAuthDefFormat(buf, src->auth);
1029

1030 1031 1032
    if (src->protocolVer)
        virBufferAsprintf(buf, "<protocol ver='%u'/>\n", src->protocolVer);

1033 1034
    virBufferEscapeString(buf, "<vendor name='%s'/>\n", src->vendor);
    virBufferEscapeString(buf, "<product name='%s'/>\n", src->product);
1035

1036 1037
    virBufferAdjustIndent(buf, -2);
    virBufferAddLit(buf, "</source>\n");
1038 1039 1040
    return 0;
}

1041

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

1050
    options = virStoragePoolOptionsForPoolType(def->type);
1051
    if (options == NULL)
1052
        return -1;
1053

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

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

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

1077 1078
    if (virStoragePoolSourceFormat(buf, options, &def->source) < 0)
        return -1;
1079

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

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

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

1113 1114
        virBufferAdjustIndent(buf, -2);
        virBufferAddLit(buf, "</target>\n");
1115
    }
1116 1117 1118 1119 1120 1121

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

1122 1123 1124 1125 1126 1127
    virBufferAdjustIndent(buf, -2);
    virBufferAddLit(buf, "</pool>\n");

    return 0;
}

1128

1129 1130 1131 1132 1133 1134 1135
char *
virStoragePoolDefFormat(virStoragePoolDefPtr def)
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;

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

1137
    if (virBufferCheckError(&buf) < 0)
1138
        goto error;
1139

1140
    return virBufferContentAndReset(&buf);
1141

1142
 error:
1143
    virBufferFreeAndReset(&buf);
1144 1145 1146 1147 1148
    return NULL;
}


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

    return 0;
}

1166

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

1184 1185
    virCheckFlags(VIR_VOL_XML_PARSE_NO_CAPACITY |
                  VIR_VOL_XML_PARSE_OPT_CAPACITY, NULL);
1186

1187
    options = virStorageVolOptionsForPoolType(pool->type);
1188 1189 1190
    if (options == NULL)
        return NULL;

1191
    if (VIR_ALLOC(ret) < 0)
1192 1193
        return NULL;

1194 1195
    ret->target.type = VIR_STORAGE_TYPE_FILE;

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

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

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

1216 1217 1218 1219
    if ((backingStore = virXPathString("string(./backingStore/path)", ctxt))) {
        if (VIR_ALLOC(ret->target.backingStore) < 0)
            goto error;

1220 1221
        ret->target.backingStore->type = VIR_STORAGE_TYPE_FILE;

1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243
        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,
1244
                                    "./backingStore/permissions") < 0)
1245 1246 1247
            goto error;
    }

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

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

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

        if (ret->target.format < 0) {
1280
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1281
                           _("unknown volume format type %s"), format);
1282
            VIR_FREE(format);
1283
            goto error;
1284
        }
1285
        VIR_FREE(format);
1286 1287
    }

1288 1289 1290
    if (VIR_ALLOC(ret->target.perms) < 0)
        goto error;
    if (virStorageDefParsePerms(ctxt, ret->target.perms,
1291
                                "./target/permissions") < 0)
1292
        goto error;
1293

1294
    node = virXPathNode("./target/encryption", ctxt);
1295
    if (node != NULL) {
1296
        ret->target.encryption = virStorageEncryptionParseNode(node, ctxt);
1297
        if (ret->target.encryption == NULL)
1298
            goto error;
1299 1300
    }

1301
    ret->target.compat = virXPathString("string(./target/compat)", ctxt);
1302 1303
    if (virStorageFileCheckCompat(ret->target.compat) < 0)
        goto error;
1304

C
Chunyan Liu 已提交
1305 1306 1307
    if (virXPathNode("./target/nocow", ctxt))
        ret->target.nocow = true;

1308
    if (virXPathNode("./target/features", ctxt)) {
1309 1310 1311 1312 1313 1314 1315
        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)))
1316
            goto error;
1317 1318

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

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

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 1339
    return ret;

1340
 error:
1341
    virStorageVolDefFree(ret);
1342 1343
    ret = NULL;
    goto cleanup;
1344 1345
}

1346

1347
virStorageVolDefPtr
1348
virStorageVolDefParseNode(virStoragePoolDefPtr pool,
1349
                          xmlDocPtr xml,
1350 1351
                          xmlNodePtr root,
                          unsigned int flags)
1352
{
1353 1354 1355
    xmlXPathContextPtr ctxt = NULL;
    virStorageVolDefPtr def = NULL;

1356
    if (!virXMLNodeNameEqual(root, "volume")) {
1357
        virReportError(VIR_ERR_XML_ERROR,
1358 1359 1360
                       _("unexpected root element <%s>, "
                         "expecting <volume>"),
                       root->name);
1361 1362 1363 1364 1365
        goto cleanup;
    }

    ctxt = xmlXPathNewContext(xml);
    if (ctxt == NULL) {
1366
        virReportOOMError();
1367 1368 1369 1370
        goto cleanup;
    }

    ctxt->node = root;
1371
    def = virStorageVolDefParseXML(pool, ctxt, flags);
1372
 cleanup:
1373 1374 1375 1376
    xmlXPathFreeContext(ctxt);
    return def;
}

1377

1378
static virStorageVolDefPtr
1379
virStorageVolDefParse(virStoragePoolDefPtr pool,
1380
                      const char *xmlStr,
1381 1382
                      const char *filename,
                      unsigned int flags)
1383
{
1384
    virStorageVolDefPtr ret = NULL;
J
Jiri Denemark 已提交
1385
    xmlDocPtr xml;
1386

1387
    if ((xml = virXMLParse(filename, xmlStr, _("(storage_volume_definition)")))) {
1388
        ret = virStorageVolDefParseNode(pool, xml, xmlDocGetRootElement(xml), flags);
J
Jiri Denemark 已提交
1389
        xmlFreeDoc(xml);
1390 1391 1392 1393 1394
    }

    return ret;
}

1395

1396
virStorageVolDefPtr
1397
virStorageVolDefParseString(virStoragePoolDefPtr pool,
1398 1399
                            const char *xmlStr,
                            unsigned int flags)
1400
{
1401
    return virStorageVolDefParse(pool, xmlStr, NULL, flags);
1402 1403
}

1404

1405
virStorageVolDefPtr
1406
virStorageVolDefParseFile(virStoragePoolDefPtr pool,
1407 1408
                          const char *filename,
                          unsigned int flags)
1409
{
1410
    return virStorageVolDefParse(pool, NULL, filename, flags);
1411
}
1412

1413

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

1427

1428
static int
1429
virStorageVolTargetDefFormat(virStorageVolOptionsPtr options,
1430
                             virBufferPtr buf,
1431
                             virStorageSourcePtr def,
1432 1433
                             const char *type)
{
1434 1435
    virBufferAsprintf(buf, "<%s>\n", type);
    virBufferAdjustIndent(buf, 2);
1436

1437
    virBufferEscapeString(buf, "<path>%s</path>\n", def->path);
1438 1439 1440 1441

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

1450 1451 1452 1453 1454
    if (def->perms &&
        (def->perms->mode != (mode_t) -1 ||
         def->perms->uid != (uid_t) -1 ||
         def->perms->gid != (gid_t) -1 ||
         def->perms->label)) {
1455 1456
        virBufferAddLit(buf, "<permissions>\n");
        virBufferAdjustIndent(buf, 2);
1457

1458 1459 1460
        if (def->perms->mode != (mode_t) -1)
            virBufferAsprintf(buf, "<mode>0%o</mode>\n",
                              def->perms->mode);
1461 1462 1463 1464 1465 1466
        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);
1467

1468 1469
        virBufferEscapeString(buf, "<label>%s</label>\n",
                              def->perms->label);
1470

1471 1472 1473
        virBufferAdjustIndent(buf, -2);
        virBufferAddLit(buf, "</permissions>\n");
    }
1474

1475
    if (def->timestamps) {
1476 1477
        virBufferAddLit(buf, "<timestamps>\n");
        virBufferAdjustIndent(buf, 2);
1478 1479 1480 1481
        virStorageVolTimestampFormat(buf, "atime", &def->timestamps->atime);
        virStorageVolTimestampFormat(buf, "mtime", &def->timestamps->mtime);
        virStorageVolTimestampFormat(buf, "ctime", &def->timestamps->ctime);
        virStorageVolTimestampFormat(buf, "btime", &def->timestamps->btime);
1482 1483
        virBufferAdjustIndent(buf, -2);
        virBufferAddLit(buf, "</timestamps>\n");
1484 1485
    }

1486 1487
    if (def->encryption &&
        virStorageEncryptionFormat(buf, def->encryption) < 0)
1488
            return -1;
1489

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

1492
    if (def->features) {
1493
        size_t i;
1494 1495
        bool empty = virBitmapIsAllClear(def->features);

1496 1497 1498 1499 1500 1501
        if (empty) {
            virBufferAddLit(buf, "<features/>\n");
        } else {
            virBufferAddLit(buf, "<features>\n");
            virBufferAdjustIndent(buf, 2);
        }
1502 1503

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

1514 1515
    virBufferAdjustIndent(buf, -2);
    virBufferAsprintf(buf, "</%s>\n", type);
1516 1517
    return 0;
}
1518

1519

1520
char *
1521
virStorageVolDefFormat(virStoragePoolDefPtr pool,
1522 1523
                       virStorageVolDefPtr def)
{
1524
    virStorageVolOptionsPtr options;
1525
    virBuffer buf = VIR_BUFFER_INITIALIZER;
1526

1527
    options = virStorageVolOptionsForPoolType(pool->type);
1528 1529 1530
    if (options == NULL)
        return NULL;

1531 1532
    virBufferAsprintf(&buf, "<volume type='%s'>\n",
                      virStorageVolTypeToString(def->type));
1533 1534 1535 1536 1537 1538
    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);
1539 1540

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

1549
                virBufferEscapeString(&buf, "<device path='%s'>\n",
1550
                                      def->source.extents[i].path);
1551 1552
            }

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

1564 1565 1566 1567
    virBufferAdjustIndent(&buf, -2);
    virBufferAddLit(&buf, "</source>\n");

    virBufferAsprintf(&buf, "<capacity unit='bytes'>%llu</capacity>\n",
1568
                      def->target.capacity);
1569
    virBufferAsprintf(&buf, "<allocation unit='bytes'>%llu</allocation>\n",
1570
                      def->target.allocation);
1571 1572 1573 1574 1575 1576
    /* 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);
1577

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

1582
    if (virStorageSourceHasBacking(&def->target) &&
1583
        virStorageVolTargetDefFormat(options, &buf,
1584 1585
                                     def->target.backingStore,
                                     "backingStore") < 0)
1586
        goto cleanup;
1587

1588
    virBufferAdjustIndent(&buf, -2);
E
Eric Blake 已提交
1589
    virBufferAddLit(&buf, "</volume>\n");
1590

1591 1592
    if (virBufferCheckError(&buf) < 0)
        goto cleanup;
1593

1594
    return virBufferContentAndReset(&buf);
1595

1596
 cleanup:
1597
    virBufferFreeAndReset(&buf);
1598 1599 1600 1601
    return NULL;
}


1602 1603 1604 1605
static int
virStoragePoolSaveXML(const char *path,
                      virStoragePoolDefPtr def,
                      const char *xml)
1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616
{
    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;
}
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 1646 1647 1648 1649 1650


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;
}
1651 1652


1653
int
1654
virStoragePoolSaveConfig(const char *configFile,
1655 1656
                         virStoragePoolDefPtr def)
{
1657
    char *xml;
1658
    int ret = -1;
1659

1660 1661 1662 1663 1664 1665
    if (!(xml = virStoragePoolDefFormat(def))) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("failed to generate XML"));
        return -1;
    }

1666 1667
    if (virStoragePoolSaveXML(configFile, def, xml))
        goto cleanup;
1668

1669 1670 1671
    ret = 0;
 cleanup:
    VIR_FREE(xml);
1672 1673 1674
    return ret;
}

1675

1676
virStoragePoolSourcePtr
1677
virStoragePoolSourceListNewSource(virStoragePoolSourceListPtr list)
1678 1679 1680
{
    virStoragePoolSourcePtr source;

1681
    if (VIR_REALLOC_N(list->sources, list->nsources + 1) < 0)
1682 1683 1684 1685 1686 1687 1688 1689
        return NULL;

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

    return source;
}

1690

1691 1692
char *
virStoragePoolSourceListFormat(virStoragePoolSourceListPtr def)
1693
{
1694
    virStoragePoolOptionsPtr options;
1695
    virBuffer buf = VIR_BUFFER_INITIALIZER;
1696
    const char *type;
1697
    size_t i;
1698

1699
    options = virStoragePoolOptionsForPoolType(def->type);
1700 1701 1702
    if (options == NULL)
        return NULL;

1703
    type = virStoragePoolTypeToString(def->type);
1704
    if (!type) {
1705 1706
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("unexpected pool type"));
1707 1708 1709 1710
        goto cleanup;
    }

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

1713
    for (i = 0; i < def->nsources; i++)
1714
        virStoragePoolSourceFormat(&buf, options, &def->sources[i]);
1715

1716
    virBufferAdjustIndent(&buf, -2);
1717 1718
    virBufferAddLit(&buf, "</sources>\n");

1719 1720
    if (virBufferCheckError(&buf) < 0)
        goto cleanup;
1721 1722

    return virBufferContentAndReset(&buf);
1723

1724
 cleanup:
1725
    virBufferFreeAndReset(&buf);
1726
    return NULL;
1727
}