storage_conf.c 51.1 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;
457
    xmlNodePtr adapternode;
458 459
    int nsource;
    size_t i;
460
    virStoragePoolOptionsPtr options;
461
    int n;
462
    VIR_AUTOPTR(virStorageAuthDef) authdef = NULL;
463 464 465
    VIR_AUTOFREE(char *) port = NULL;
    VIR_AUTOFREE(char *) ver = NULL;
    VIR_AUTOFREE(xmlNodePtr *) nodeset = 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 482 483
        VIR_AUTOFREE(char *) format = NULL;

        format = virXPathString("string(./format/@type)", ctxt);
484 485 486 487 488 489
        if (format == NULL)
            source->format = options->defaultFormat;
        else
            source->format = options->formatFromString(format);

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

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
            source->hosts[i].name = virXMLPropString(nodeset[i], "name");
            if (!source->hosts[i].name) {
507 508
                virReportError(VIR_ERR_XML_ERROR, "%s",
                               _("missing storage pool host name"));
509 510 511 512 513 514
                goto cleanup;
            }

            port = virXMLPropString(nodeset[i], "port");
            if (port) {
                if (virStrToLong_i(port, NULL, 10, &source->hosts[i].port) < 0) {
515 516 517
                    virReportError(VIR_ERR_XML_ERROR,
                                   _("Invalid port number: %s"),
                                   port);
518 519 520 521 522
                    goto cleanup;
                }
            }
        }
    }
523

524
    VIR_FREE(nodeset);
525 526

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

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

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

543 544 545 546 547 548 549 550 551 552 553 554
        partsep = virXMLPropString(nodeset[i], "part_separator");
        if (partsep) {
            dev.part_separator = virTristateBoolTypeFromString(partsep);
            if (dev.part_separator <= 0) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("invalid part_separator setting '%s'"),
                               partsep);
                virStoragePoolSourceDeviceClear(&dev);
                goto cleanup;
            }
        }

555 556 557
        if (VIR_APPEND_ELEMENT(source->devices, source->ndevice, dev) < 0) {
            virStoragePoolSourceDeviceClear(&dev);
            goto cleanup;
558
        }
559

560 561
    }

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

568
    if ((adapternode = virXPathNode("./adapter", ctxt))) {
569
        if (virStorageAdapterParseXML(&source->adapter, adapternode, ctxt) < 0)
570 571
            goto cleanup;
    }
572

573
    if ((authnode = virXPathNode("./auth", ctxt))) {
574
        if (!(authdef = virStorageAuthDefParse(authnode, ctxt)))
575 576 577 578 579 580 581 582
            goto cleanup;

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

583
        VIR_STEAL_PTR(source->auth, authdef);
584
    }
585

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

604 605 606
    source->vendor = virXPathString("string(./vendor/@name)", ctxt);
    source->product = virXPathString("string(./product/@name)", ctxt);

607
    ret = 0;
608
 cleanup:
609 610 611 612
    ctxt->node = relnode;

    return ret;
}
613

614

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

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

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

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

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

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

    return ret;
}
650

651

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

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

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

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

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

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

        perms->uid = val;
702 703
    }

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

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

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

727

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

739
    if (VIR_ALLOC(def) < 0)
740 741
        return NULL;

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

749
    if ((def->type = virStoragePoolTypeFromString(type)) < 0) {
750
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
751
                       _("unknown storage pool type %s"), type);
752
        return NULL;
753 754
    }

755
    if ((options = virStoragePoolOptionsForPoolType(def->type)) == NULL)
756
        return NULL;
757

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

768 769
    def->name = virXPathString("string(./name)", ctxt);
    if (def->name == NULL &&
770
        options->flags & VIR_STORAGE_POOL_SOURCE_NAME &&
771
        VIR_STRDUP(def->name, def->source.name) < 0)
772 773
        return NULL;

774
    if (def->name == NULL) {
775 776
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("missing pool source name element"));
777
        return NULL;
778 779
    }

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

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

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

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

824
    if ((options->flags & VIR_STORAGE_POOL_SOURCE_ADAPTER) &&
825
        (virStorageAdapterValidate(&def->source.adapter)) < 0)
826
            return NULL;
827

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

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

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

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

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

877
    VIR_STEAL_PTR(ret, def);
878
    return ret;
879 880
}

881

882
virStoragePoolDefPtr
883
virStoragePoolDefParseNode(xmlDocPtr xml,
884 885
                           xmlNodePtr root)
{
886 887 888
    xmlXPathContextPtr ctxt = NULL;
    virStoragePoolDefPtr def = NULL;

889
    if (!virXMLNodeNameEqual(root, "pool")) {
890
        virReportError(VIR_ERR_XML_ERROR,
891 892 893
                       _("unexpected root element <%s>, "
                         "expecting <pool>"),
                       root->name);
894 895 896 897 898
        goto cleanup;
    }

    ctxt = xmlXPathNewContext(xml);
    if (ctxt == NULL) {
899
        virReportOOMError();
900 901 902 903
        goto cleanup;
    }

    ctxt->node = root;
904
    def = virStoragePoolDefParseXML(ctxt);
905
 cleanup:
906 907 908 909
    xmlXPathFreeContext(ctxt);
    return def;
}

910

911
static virStoragePoolDefPtr
912
virStoragePoolDefParse(const char *xmlStr,
913 914
                       const char *filename)
{
915
    virStoragePoolDefPtr ret = NULL;
J
Jiri Denemark 已提交
916
    xmlDocPtr xml;
917

918
    if ((xml = virXMLParse(filename, xmlStr, _("(storage_pool_definition)")))) {
J
Jiri Denemark 已提交
919 920
        ret = virStoragePoolDefParseNode(xml, xmlDocGetRootElement(xml));
        xmlFreeDoc(xml);
921 922
    }

923 924 925
    return ret;
}

926

927
virStoragePoolDefPtr
928
virStoragePoolDefParseString(const char *xmlStr)
929
{
930
    return virStoragePoolDefParse(xmlStr, NULL);
931 932
}

933

934
virStoragePoolDefPtr
935
virStoragePoolDefParseFile(const char *filename)
936
{
937
    return virStoragePoolDefParse(NULL, filename);
938 939
}

940

941
static int
942
virStoragePoolSourceFormat(virBufferPtr buf,
943
                           virStoragePoolOptionsPtr options,
944 945
                           virStoragePoolSourcePtr src)
{
946
    size_t i, j;
947

948 949 950
    virBufferAddLit(buf, "<source>\n");
    virBufferAdjustIndent(buf, 2);

951 952
    if ((options->flags & VIR_STORAGE_POOL_SOURCE_HOST) && src->nhost) {
        for (i = 0; i < src->nhost; i++) {
953
            virBufferEscapeString(buf, "<host name='%s'",
954
                                  src->hosts[i].name);
955 956 957 958
            if (src->hosts[i].port)
                virBufferAsprintf(buf, " port='%d'", src->hosts[i].port);
            virBufferAddLit(buf, "/>\n");
        }
959
    }
960

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

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

990
    if ((options->flags & VIR_STORAGE_POOL_SOURCE_ADAPTER) &&
991 992 993
        (src->adapter.type == VIR_STORAGE_ADAPTER_TYPE_FC_HOST ||
         src->adapter.type == VIR_STORAGE_ADAPTER_TYPE_SCSI_HOST))
        virStorageAdapterFormat(buf, &src->adapter);
994

995
    if (options->flags & VIR_STORAGE_POOL_SOURCE_NAME)
996
        virBufferEscapeString(buf, "<name>%s</name>\n", src->name);
997

998 999
    if (options->flags & VIR_STORAGE_POOL_SOURCE_INITIATOR_IQN)
        virStorageSourceInitiatorFormatXML(&src->initiator, buf);
D
David Allan 已提交
1000

1001 1002 1003
    if (options->formatToString) {
        const char *format = (options->formatToString)(src->format);
        if (!format) {
1004 1005 1006
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("unknown pool format number %d"),
                           src->format);
1007 1008
            return -1;
        }
1009
        virBufferAsprintf(buf, "<format type='%s'/>\n", format);
1010 1011
    }

1012 1013
    if (src->auth)
        virStorageAuthDefFormat(buf, src->auth);
1014

1015 1016 1017
    if (src->protocolVer)
        virBufferAsprintf(buf, "<protocol ver='%u'/>\n", src->protocolVer);

1018 1019
    virBufferEscapeString(buf, "<vendor name='%s'/>\n", src->vendor);
    virBufferEscapeString(buf, "<product name='%s'/>\n", src->product);
1020

1021 1022
    virBufferAdjustIndent(buf, -2);
    virBufferAddLit(buf, "</source>\n");
1023 1024 1025
    return 0;
}

1026

1027 1028 1029
static int
virStoragePoolDefFormatBuf(virBufferPtr buf,
                           virStoragePoolDefPtr def)
1030
{
1031
    virStoragePoolOptionsPtr options;
1032
    char uuid[VIR_UUID_STRING_BUFLEN];
1033
    const char *type;
1034

1035
    options = virStoragePoolOptionsForPoolType(def->type);
1036
    if (options == NULL)
1037
        return -1;
1038

1039
    type = virStoragePoolTypeToString(def->type);
1040
    if (!type) {
1041 1042
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("unexpected pool type"));
1043
        return -1;
1044
    }
1045 1046 1047 1048
    virBufferAsprintf(buf, "<pool type='%s'", type);
    if (def->namespaceData && def->ns.href)
        virBufferAsprintf(buf, " %s", (def->ns.href)());
    virBufferAddLit(buf, ">\n");
1049 1050
    virBufferAdjustIndent(buf, 2);
    virBufferEscapeString(buf, "<name>%s</name>\n", def->name);
1051 1052

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

1055
    virBufferAsprintf(buf, "<capacity unit='bytes'>%llu</capacity>\n",
1056
                      def->capacity);
1057
    virBufferAsprintf(buf, "<allocation unit='bytes'>%llu</allocation>\n",
1058
                      def->allocation);
1059
    virBufferAsprintf(buf, "<available unit='bytes'>%llu</available>\n",
1060
                      def->available);
1061

1062 1063
    if (virStoragePoolSourceFormat(buf, options, &def->source) < 0)
        return -1;
1064

1065
    /* RBD, Sheepdog, Gluster and Iscsi-direct devices are not local block devs nor
1066
     * files, so they don't have a target */
1067
    if (def->type != VIR_STORAGE_POOL_RBD &&
1068
        def->type != VIR_STORAGE_POOL_SHEEPDOG &&
1069 1070
        def->type != VIR_STORAGE_POOL_GLUSTER &&
        def->type != VIR_STORAGE_POOL_ISCSI_DIRECT) {
1071 1072
        virBufferAddLit(buf, "<target>\n");
        virBufferAdjustIndent(buf, 2);
1073

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

1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096
        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");
        }
1097

1098 1099
        virBufferAdjustIndent(buf, -2);
        virBufferAddLit(buf, "</target>\n");
1100
    }
1101 1102 1103 1104 1105 1106

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

1107 1108 1109 1110 1111 1112
    virBufferAdjustIndent(buf, -2);
    virBufferAddLit(buf, "</pool>\n");

    return 0;
}

1113

1114 1115 1116 1117 1118 1119 1120
char *
virStoragePoolDefFormat(virStoragePoolDefPtr def)
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;

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

1122
    if (virBufferCheckError(&buf) < 0)
1123
        goto error;
1124

1125
    return virBufferContentAndReset(&buf);
1126

1127
 error:
1128
    virBufferFreeAndReset(&buf);
1129 1130 1131 1132 1133
    return NULL;
}


static int
1134
virStorageSize(const char *unit,
1135
               const char *val,
1136 1137
               unsigned long long *ret)
{
J
Ján Tomko 已提交
1138
    if (virStrToLong_ullp(val, NULL, 10, ret) < 0) {
1139 1140
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("malformed capacity element"));
1141 1142
        return -1;
    }
1143 1144 1145 1146
    /* 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;
1147 1148 1149 1150

    return 0;
}

1151

1152
static virStorageVolDefPtr
1153
virStorageVolDefParseXML(virStoragePoolDefPtr pool,
1154 1155
                         xmlXPathContextPtr ctxt,
                         unsigned int flags)
1156
{
1157
    virStorageVolDefPtr ret = NULL;
1158
    virStorageVolOptionsPtr options;
1159
    xmlNodePtr node;
1160 1161
    size_t i;
    int n;
1162
    VIR_AUTOPTR(virStorageVolDef) def = NULL;
1163 1164 1165 1166 1167 1168
    VIR_AUTOFREE(char *) type = NULL;
    VIR_AUTOFREE(char *) allocation = NULL;
    VIR_AUTOFREE(char *) capacity = NULL;
    VIR_AUTOFREE(char *) unit = NULL;
    VIR_AUTOFREE(char *) backingStore = NULL;
    VIR_AUTOFREE(xmlNodePtr *) nodes = NULL;
1169

1170 1171
    virCheckFlags(VIR_VOL_XML_PARSE_NO_CAPACITY |
                  VIR_VOL_XML_PARSE_OPT_CAPACITY, NULL);
1172

1173
    options = virStorageVolOptionsForPoolType(pool->type);
1174 1175 1176
    if (options == NULL)
        return NULL;

1177
    if (VIR_ALLOC(def) < 0)
1178 1179
        return NULL;

1180
    def->target.type = VIR_STORAGE_TYPE_FILE;
1181

1182 1183
    def->name = virXPathString("string(./name)", ctxt);
    if (def->name == NULL) {
1184 1185
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("missing volume name element"));
1186
        return NULL;
1187 1188
    }

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

1192 1193 1194
    /* Technically overridden by pool refresh, but useful for unit tests */
    type = virXPathString("string(./@type)", ctxt);
    if (type) {
1195
        if ((def->type = virStorageVolTypeFromString(type)) < 0) {
1196
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1197
                           _("unknown volume type '%s'"), type);
1198
            return NULL;
1199 1200 1201
        }
    }

1202
    if ((backingStore = virXPathString("string(./backingStore/path)", ctxt))) {
1203
        if (VIR_ALLOC(def->target.backingStore) < 0)
1204
            return NULL;
1205

1206
        def->target.backingStore->type = VIR_STORAGE_TYPE_FILE;
1207

1208
        def->target.backingStore->path = backingStore;
1209 1210 1211
        backingStore = NULL;

        if (options->formatFromString) {
1212 1213 1214
            VIR_AUTOFREE(char *) format = NULL;

            format = virXPathString("string(./backingStore/format/@type)", ctxt);
1215
            if (format == NULL)
1216
                def->target.backingStore->format = options->defaultFormat;
1217
            else
1218
                def->target.backingStore->format = (options->formatFromString)(format);
1219

1220
            if (def->target.backingStore->format < 0) {
1221 1222
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("unknown volume format type %s"), format);
1223
                return NULL;
1224 1225 1226
            }
        }

1227
        if (VIR_ALLOC(def->target.backingStore->perms) < 0)
1228
            return NULL;
1229
        if (virStorageDefParsePerms(ctxt, def->target.backingStore->perms,
1230
                                    "./backingStore/permissions") < 0)
1231
            return NULL;
1232 1233
    }

1234 1235
    capacity = virXPathString("string(./capacity)", ctxt);
    unit = virXPathString("string(./capacity/@unit)", ctxt);
1236
    if (capacity) {
1237
        if (virStorageSize(unit, capacity, &def->target.capacity) < 0)
1238
            return NULL;
1239
    } else if (!(flags & VIR_VOL_XML_PARSE_NO_CAPACITY) &&
1240
               !((flags & VIR_VOL_XML_PARSE_OPT_CAPACITY) &&
1241
                 virStorageSourceHasBacking(&def->target))) {
1242
        virReportError(VIR_ERR_XML_ERROR, "%s", _("missing capacity element"));
1243
        return NULL;
1244
    }
1245
    VIR_FREE(unit);
1246

1247
    allocation = virXPathString("string(./allocation)", ctxt);
1248
    if (allocation) {
1249
        unit = virXPathString("string(./allocation/@unit)", ctxt);
1250
        if (virStorageSize(unit, allocation, &def->target.allocation) < 0)
1251
            return NULL;
1252
        def->target.has_allocation = true;
1253
    } else {
1254
        def->target.allocation = def->target.capacity;
1255 1256
    }

1257
    def->target.path = virXPathString("string(./target/path)", ctxt);
1258
    if (options->formatFromString) {
1259 1260 1261
        VIR_AUTOFREE(char *) format = NULL;

        format = virXPathString("string(./target/format/@type)", ctxt);
1262
        if (format == NULL)
1263
            def->target.format = options->defaultFormat;
1264
        else
1265
            def->target.format = (options->formatFromString)(format);
1266

1267
        if (def->target.format < 0) {
1268
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1269
                           _("unknown volume format type %s"), format);
1270
            return NULL;
1271 1272 1273
        }
    }

1274
    if (VIR_ALLOC(def->target.perms) < 0)
1275
        return NULL;
1276
    if (virStorageDefParsePerms(ctxt, def->target.perms,
1277
                                "./target/permissions") < 0)
1278
        return NULL;
1279

1280
    node = virXPathNode("./target/encryption", ctxt);
1281
    if (node != NULL) {
1282 1283
        def->target.encryption = virStorageEncryptionParseNode(node, ctxt);
        if (def->target.encryption == NULL)
1284
            return NULL;
1285 1286
    }

1287 1288
    def->target.compat = virXPathString("string(./target/compat)", ctxt);
    if (virStorageFileCheckCompat(def->target.compat) < 0)
1289
        return NULL;
1290

C
Chunyan Liu 已提交
1291
    if (virXPathNode("./target/nocow", ctxt))
1292
        def->target.nocow = true;
C
Chunyan Liu 已提交
1293

1294
    if (virXPathNode("./target/features", ctxt)) {
1295
        if ((n = virXPathNodeSet("./target/features/*", ctxt, &nodes)) < 0)
1296
            return NULL;
1297

1298
        if (!def->target.compat && VIR_STRDUP(def->target.compat, "1.1") < 0)
1299
            return NULL;
1300

1301
        if (!(def->target.features = virBitmapNew(VIR_STORAGE_FILE_FEATURE_LAST)))
1302
            return NULL;
1303 1304

        for (i = 0; i < n; i++) {
1305
            int f = virStorageFileFeatureTypeFromString((const char*)nodes[i]->name);
1306 1307

            if (f < 0) {
1308
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unsupported feature %s"),
1309
                               (const char*)nodes[i]->name);
1310
                return NULL;
1311
            }
1312
            ignore_value(virBitmapSetBit(def->target.features, f));
1313 1314 1315 1316
        }
        VIR_FREE(nodes);
    }

1317
    VIR_STEAL_PTR(ret, def);
1318
    return ret;
1319 1320
}

1321

1322
virStorageVolDefPtr
1323
virStorageVolDefParseNode(virStoragePoolDefPtr pool,
1324
                          xmlDocPtr xml,
1325 1326
                          xmlNodePtr root,
                          unsigned int flags)
1327
{
1328 1329 1330
    xmlXPathContextPtr ctxt = NULL;
    virStorageVolDefPtr def = NULL;

1331
    if (!virXMLNodeNameEqual(root, "volume")) {
1332
        virReportError(VIR_ERR_XML_ERROR,
1333 1334 1335
                       _("unexpected root element <%s>, "
                         "expecting <volume>"),
                       root->name);
1336 1337 1338 1339 1340
        goto cleanup;
    }

    ctxt = xmlXPathNewContext(xml);
    if (ctxt == NULL) {
1341
        virReportOOMError();
1342 1343 1344 1345
        goto cleanup;
    }

    ctxt->node = root;
1346
    def = virStorageVolDefParseXML(pool, ctxt, flags);
1347
 cleanup:
1348 1349 1350 1351
    xmlXPathFreeContext(ctxt);
    return def;
}

1352

1353
static virStorageVolDefPtr
1354
virStorageVolDefParse(virStoragePoolDefPtr pool,
1355
                      const char *xmlStr,
1356 1357
                      const char *filename,
                      unsigned int flags)
1358
{
1359
    virStorageVolDefPtr ret = NULL;
J
Jiri Denemark 已提交
1360
    xmlDocPtr xml;
1361

1362
    if ((xml = virXMLParse(filename, xmlStr, _("(storage_volume_definition)")))) {
1363
        ret = virStorageVolDefParseNode(pool, xml, xmlDocGetRootElement(xml), flags);
J
Jiri Denemark 已提交
1364
        xmlFreeDoc(xml);
1365 1366 1367 1368 1369
    }

    return ret;
}

1370

1371
virStorageVolDefPtr
1372
virStorageVolDefParseString(virStoragePoolDefPtr pool,
1373 1374
                            const char *xmlStr,
                            unsigned int flags)
1375
{
1376
    return virStorageVolDefParse(pool, xmlStr, NULL, flags);
1377 1378
}

1379

1380
virStorageVolDefPtr
1381
virStorageVolDefParseFile(virStoragePoolDefPtr pool,
1382 1383
                          const char *filename,
                          unsigned int flags)
1384
{
1385
    return virStorageVolDefParse(pool, NULL, filename, flags);
1386
}
1387

1388

1389 1390 1391 1392 1393 1394
static void
virStorageVolTimestampFormat(virBufferPtr buf, const char *name,
                             struct timespec *ts)
{
    if (ts->tv_nsec < 0)
        return;
1395
    virBufferAsprintf(buf, "<%s>%llu", name,
1396 1397 1398 1399 1400 1401
                      (unsigned long long) ts->tv_sec);
    if (ts->tv_nsec)
       virBufferAsprintf(buf, ".%09ld", ts->tv_nsec);
    virBufferAsprintf(buf, "</%s>\n", name);
}

1402

1403
static int
1404
virStorageVolTargetDefFormat(virStorageVolOptionsPtr options,
1405
                             virBufferPtr buf,
1406
                             virStorageSourcePtr def,
1407 1408
                             const char *type)
{
1409 1410
    virBufferAsprintf(buf, "<%s>\n", type);
    virBufferAdjustIndent(buf, 2);
1411

1412
    virBufferEscapeString(buf, "<path>%s</path>\n", def->path);
1413 1414 1415 1416

    if (options->formatToString) {
        const char *format = (options->formatToString)(def->format);
        if (!format) {
1417 1418 1419
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("unknown volume format number %d"),
                           def->format);
1420 1421
            return -1;
        }
1422
        virBufferAsprintf(buf, "<format type='%s'/>\n", format);
1423 1424
    }

1425 1426 1427 1428 1429
    if (def->perms &&
        (def->perms->mode != (mode_t) -1 ||
         def->perms->uid != (uid_t) -1 ||
         def->perms->gid != (gid_t) -1 ||
         def->perms->label)) {
1430 1431
        virBufferAddLit(buf, "<permissions>\n");
        virBufferAdjustIndent(buf, 2);
1432

1433 1434 1435
        if (def->perms->mode != (mode_t) -1)
            virBufferAsprintf(buf, "<mode>0%o</mode>\n",
                              def->perms->mode);
1436 1437 1438 1439 1440 1441
        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);
1442

1443 1444
        virBufferEscapeString(buf, "<label>%s</label>\n",
                              def->perms->label);
1445

1446 1447 1448
        virBufferAdjustIndent(buf, -2);
        virBufferAddLit(buf, "</permissions>\n");
    }
1449

1450
    if (def->timestamps) {
1451 1452
        virBufferAddLit(buf, "<timestamps>\n");
        virBufferAdjustIndent(buf, 2);
1453 1454 1455 1456
        virStorageVolTimestampFormat(buf, "atime", &def->timestamps->atime);
        virStorageVolTimestampFormat(buf, "mtime", &def->timestamps->mtime);
        virStorageVolTimestampFormat(buf, "ctime", &def->timestamps->ctime);
        virStorageVolTimestampFormat(buf, "btime", &def->timestamps->btime);
1457 1458
        virBufferAdjustIndent(buf, -2);
        virBufferAddLit(buf, "</timestamps>\n");
1459 1460
    }

1461 1462
    if (def->encryption &&
        virStorageEncryptionFormat(buf, def->encryption) < 0)
1463
            return -1;
1464

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

1467
    if (def->features) {
1468
        size_t i;
1469 1470
        bool empty = virBitmapIsAllClear(def->features);

1471 1472 1473 1474 1475 1476
        if (empty) {
            virBufferAddLit(buf, "<features/>\n");
        } else {
            virBufferAddLit(buf, "<features>\n");
            virBufferAdjustIndent(buf, 2);
        }
1477 1478

        for (i = 0; i < VIR_STORAGE_FILE_FEATURE_LAST; i++) {
J
Ján Tomko 已提交
1479
            if (virBitmapIsBitSet(def->features, i))
1480
                virBufferAsprintf(buf, "<%s/>\n",
1481
                                  virStorageFileFeatureTypeToString(i));
1482
        }
1483 1484 1485 1486
        if (!empty) {
            virBufferAdjustIndent(buf, -2);
            virBufferAddLit(buf, "</features>\n");
        }
1487 1488
    }

1489 1490
    virBufferAdjustIndent(buf, -2);
    virBufferAsprintf(buf, "</%s>\n", type);
1491 1492
    return 0;
}
1493

1494

1495
char *
1496
virStorageVolDefFormat(virStoragePoolDefPtr pool,
1497 1498
                       virStorageVolDefPtr def)
{
1499
    virStorageVolOptionsPtr options;
1500
    virBuffer buf = VIR_BUFFER_INITIALIZER;
1501

1502
    options = virStorageVolOptionsForPoolType(pool->type);
1503 1504 1505
    if (options == NULL)
        return NULL;

1506 1507
    virBufferAsprintf(&buf, "<volume type='%s'>\n",
                      virStorageVolTypeToString(def->type));
1508 1509 1510 1511 1512 1513
    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);
1514 1515

    if (def->source.nextent) {
1516
        size_t i;
1517
        const char *thispath = NULL;
1518
        for (i = 0; i < def->source.nextent; i++) {
1519 1520 1521
            if (thispath == NULL ||
                STRNEQ(thispath, def->source.extents[i].path)) {
                if (thispath != NULL)
1522
                    virBufferAddLit(&buf, "</device>\n");
1523

1524
                virBufferEscapeString(&buf, "<device path='%s'>\n",
1525
                                      def->source.extents[i].path);
1526 1527
            }

1528 1529
            virBufferAdjustIndent(&buf, 2);
            virBufferAsprintf(&buf, "<extent start='%llu' end='%llu'/>\n",
1530 1531
                              def->source.extents[i].start,
                              def->source.extents[i].end);
1532
            virBufferAdjustIndent(&buf, -2);
1533 1534 1535
            thispath = def->source.extents[i].path;
        }
        if (thispath != NULL)
1536
            virBufferAddLit(&buf, "</device>\n");
1537 1538
    }

1539 1540 1541 1542
    virBufferAdjustIndent(&buf, -2);
    virBufferAddLit(&buf, "</source>\n");

    virBufferAsprintf(&buf, "<capacity unit='bytes'>%llu</capacity>\n",
1543
                      def->target.capacity);
1544
    virBufferAsprintf(&buf, "<allocation unit='bytes'>%llu</allocation>\n",
1545
                      def->target.allocation);
1546 1547 1548 1549 1550 1551
    /* 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);
1552

1553
    if (virStorageVolTargetDefFormat(options, &buf,
1554 1555
                                     &def->target, "target") < 0)
        goto cleanup;
1556

1557
    if (virStorageSourceHasBacking(&def->target) &&
1558
        virStorageVolTargetDefFormat(options, &buf,
1559 1560
                                     def->target.backingStore,
                                     "backingStore") < 0)
1561
        goto cleanup;
1562

1563
    virBufferAdjustIndent(&buf, -2);
E
Eric Blake 已提交
1564
    virBufferAddLit(&buf, "</volume>\n");
1565

1566 1567
    if (virBufferCheckError(&buf) < 0)
        goto cleanup;
1568

1569
    return virBufferContentAndReset(&buf);
1570

1571
 cleanup:
1572
    virBufferFreeAndReset(&buf);
1573 1574 1575 1576
    return NULL;
}


1577 1578 1579 1580
static int
virStoragePoolSaveXML(const char *path,
                      virStoragePoolDefPtr def,
                      const char *xml)
1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591
{
    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;
}
1592 1593 1594 1595 1596 1597 1598


int
virStoragePoolSaveState(const char *stateFile,
                        virStoragePoolDefPtr def)
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;
1599
    VIR_AUTOFREE(char *) xml = NULL;
1600 1601 1602 1603 1604

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

    if (virStoragePoolDefFormatBuf(&buf, def) < 0)
1605
        return -1;
1606 1607 1608 1609 1610

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

    if (virBufferCheckError(&buf) < 0)
1611
        return -1;
1612 1613

    if (!(xml = virBufferContentAndReset(&buf)))
1614
        return -1;
1615 1616

    if (virStoragePoolSaveXML(stateFile, def, xml))
1617
        return -1;
1618

1619
    return 0;
1620
}
1621 1622


1623
int
1624
virStoragePoolSaveConfig(const char *configFile,
1625 1626
                         virStoragePoolDefPtr def)
{
1627
    VIR_AUTOFREE(char *) xml = NULL;
1628

1629 1630 1631 1632 1633 1634
    if (!(xml = virStoragePoolDefFormat(def))) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("failed to generate XML"));
        return -1;
    }

1635
    return virStoragePoolSaveXML(configFile, def, xml);
1636 1637
}

1638

1639
virStoragePoolSourcePtr
1640
virStoragePoolSourceListNewSource(virStoragePoolSourceListPtr list)
1641 1642 1643
{
    virStoragePoolSourcePtr source;

1644
    if (VIR_REALLOC_N(list->sources, list->nsources + 1) < 0)
1645 1646 1647 1648 1649 1650 1651 1652
        return NULL;

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

    return source;
}

1653

1654 1655
char *
virStoragePoolSourceListFormat(virStoragePoolSourceListPtr def)
1656
{
1657
    virStoragePoolOptionsPtr options;
1658
    virBuffer buf = VIR_BUFFER_INITIALIZER;
1659
    const char *type;
1660
    size_t i;
1661

1662
    options = virStoragePoolOptionsForPoolType(def->type);
1663 1664 1665
    if (options == NULL)
        return NULL;

1666
    type = virStoragePoolTypeToString(def->type);
1667
    if (!type) {
1668 1669
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("unexpected pool type"));
1670 1671 1672 1673
        goto cleanup;
    }

    virBufferAddLit(&buf, "<sources>\n");
1674
    virBufferAdjustIndent(&buf, 2);
1675

1676
    for (i = 0; i < def->nsources; i++)
1677
        virStoragePoolSourceFormat(&buf, options, &def->sources[i]);
1678

1679
    virBufferAdjustIndent(&buf, -2);
1680 1681
    virBufferAddLit(&buf, "</sources>\n");

1682 1683
    if (virBufferCheckError(&buf) < 0)
        goto cleanup;
1684 1685

    return virBufferContentAndReset(&buf);
1686

1687
 cleanup:
1688
    virBufferFreeAndReset(&buf);
1689
    return NULL;
1690
}