storage_conf.c 54.4 KB
Newer Older
1 2 3
/*
 * storage_conf.c: config handling for storage driver
 *
4
 * Copyright (C) 2006-2016 Red Hat, Inc.
5 6 7 8 9 10 11 12 13 14 15 16 17
 * Copyright (C) 2006-2008 Daniel P. Berrange
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with this library.  If not, see
O
Osier Yang 已提交
19
 * <http://www.gnu.org/licenses/>.
20 21 22 23 24 25 26 27 28
 */

#include <config.h>

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

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

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

46 47
#define VIR_FROM_THIS VIR_FROM_STORAGE

48 49
VIR_LOG_INIT("conf.storage_conf");

50 51
VIR_ENUM_IMPL(virStorageVol,
              VIR_STORAGE_VOL_LAST,
O
Olga Krishtal 已提交
52
              "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 98 99 100 101
VIR_ENUM_IMPL(virStorageVolDefRefreshAllocation,
              VIR_STORAGE_VOL_DEF_REFRESH_ALLOCATION_LAST,
              "default", "capacity",
);

102
VIR_ENUM_IMPL(virStoragePartedFs,
103
              VIR_STORAGE_PARTED_FS_TYPE_LAST,
104
              "ext2", "ext2", "fat16",
105 106
              "fat32", "linux-swap",
              "ext2", "ext2",
107 108
              "extended",
);
109 110 111 112 113 114 115 116 117 118

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 {
119
    int defaultFormat;
120
    int lastFormat;
121 122 123 124 125 126
    virStorageVolFormatToString formatToString;
    virStorageVolFormatFromString formatFromString;
};

/* Flags to indicate mandatory components in the pool source */
enum {
O
Osier Yang 已提交
127 128 129 130 131 132 133
    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),
134 135 136 137 138
};

typedef struct _virStoragePoolOptions virStoragePoolOptions;
typedef virStoragePoolOptions *virStoragePoolOptionsPtr;
struct _virStoragePoolOptions {
E
Eric Blake 已提交
139
    unsigned int flags;
140
    int defaultFormat;
141
    int lastFormat;
142 143 144

    virStoragePoolXMLNamespace ns;

145 146 147 148 149 150 151 152 153 154 155 156
    virStoragePoolFormatToString formatToString;
    virStoragePoolFormatFromString formatFromString;
};

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

157

E
Eric Blake 已提交
158 159 160 161 162 163 164 165 166
static int
virStorageVolumeFormatFromString(const char *format)
{
    int ret = virStorageFileFormatTypeFromString(format);
    if (ret == VIR_STORAGE_FILE_NONE)
        return -1;
    return ret;
}

167

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


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

311 312
    virReportError(VIR_ERR_INTERNAL_ERROR,
                   _("missing backend for pool type %d"), type);
313 314 315
    return NULL;
}

316

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

326

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


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


365 366 367 368 369 370 371 372 373
int
virStoragePoolOptionsFormatPool(virBufferPtr buf,
                                int type)
{
    virStoragePoolOptionsPtr poolOptions;

    if (!(poolOptions = virStoragePoolOptionsForPoolType(type)))
        return -1;

374
    if (!poolOptions->formatToString)
375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438
        return 0;

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

    if (poolOptions->formatToString) {
        size_t i;

        virBufferAsprintf(buf, "<defaultFormat type='%s'/>\n",
                          (poolOptions->formatToString)(poolOptions->defaultFormat));

        virBufferAddLit(buf, "<enum name='sourceFormatType'>\n");
        virBufferAdjustIndent(buf, 2);

        for (i = 0; i < poolOptions->lastFormat; i++)
            virBufferAsprintf(buf, "<value>%s</value>\n",
                              (poolOptions->formatToString)(i));

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

    virBufferAdjustIndent(buf, -2);
    virBufferAddLit(buf, "</poolOptions>\n");
    return 0;
}


int
virStoragePoolOptionsFormatVolume(virBufferPtr buf,
                                  int type)
{
    size_t i;
    virStorageVolOptionsPtr volOptions;

    if (!(volOptions = virStorageVolOptionsForPoolType(type)))
        return -1;

    if (!volOptions->formatToString)
        return 0;

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

    virBufferAsprintf(buf, "<defaultFormat type='%s'/>\n",
                      (volOptions->formatToString)(volOptions->defaultFormat));

    virBufferAddLit(buf, "<enum name='targetFormatType'>\n");
    virBufferAdjustIndent(buf, 2);

    for (i = 0; i < volOptions->lastFormat; i++)
        virBufferAsprintf(buf, "<value>%s</value>\n",
                          (volOptions->formatToString)(i));

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

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

    return 0;
}


439
void
440 441
virStorageVolDefFree(virStorageVolDefPtr def)
{
442
    size_t i;
443 444 445 446

    if (!def)
        return;

447 448
    VIR_FREE(def->name);
    VIR_FREE(def->key);
449

450
    for (i = 0; i < def->source.nextent; i++)
451 452
        VIR_FREE(def->source.extents[i].path);
    VIR_FREE(def->source.extents);
453

454
    virStorageSourceClear(&def->target);
455
    VIR_FREE(def);
456 457
}

458

459 460 461 462 463 464 465
void
virStoragePoolSourceDeviceClear(virStoragePoolSourceDevicePtr dev)
{
    VIR_FREE(dev->freeExtents);
    VIR_FREE(dev->path);
}

466

467
void
468 469
virStoragePoolSourceClear(virStoragePoolSourcePtr source)
{
470
    size_t i;
471

472
    if (!source)
473 474
        return;

475
    for (i = 0; i < source->nhost; i++)
476 477 478
        VIR_FREE(source->hosts[i].name);
    VIR_FREE(source->hosts);

479 480
    for (i = 0; i < source->ndevice; i++)
        virStoragePoolSourceDeviceClear(&source->devices[i]);
481 482 483
    VIR_FREE(source->devices);
    VIR_FREE(source->dir);
    VIR_FREE(source->name);
484
    virStorageAdapterClear(&source->adapter);
485
    virStorageSourceInitiatorClear(&source->initiator);
486
    virStorageAuthDefFree(source->auth);
487 488
    VIR_FREE(source->vendor);
    VIR_FREE(source->product);
489 490
}

491

492 493 494 495 496 497 498
void
virStoragePoolSourceFree(virStoragePoolSourcePtr source)
{
    virStoragePoolSourceClear(source);
    VIR_FREE(source);
}

499

500
void
501 502
virStoragePoolDefFree(virStoragePoolDefPtr def)
{
503 504 505 506 507
    if (!def)
        return;

    VIR_FREE(def->name);

508
    virStoragePoolSourceClear(&def->source);
509

510 511
    VIR_FREE(def->target.path);
    VIR_FREE(def->target.perms.label);
512
    VIR_FREE(def->refresh);
513 514
    if (def->namespaceData && def->ns.free)
        (def->ns.free)(def->namespaceData);
515
    VIR_FREE(def);
516 517 518
}


519
static int
520
virStoragePoolDefParseSource(xmlXPathContextPtr ctxt,
521 522
                             virStoragePoolSourcePtr source,
                             int pool_type,
523 524
                             xmlNodePtr node)
{
525
    int ret = -1;
526
    xmlNodePtr relnode, authnode;
527
    xmlNodePtr adapternode;
528 529
    int nsource;
    size_t i;
530
    virStoragePoolOptionsPtr options;
531
    int n;
532
    VIR_AUTOPTR(virStorageAuthDef) authdef = NULL;
533 534 535
    VIR_AUTOFREE(char *) port = NULL;
    VIR_AUTOFREE(char *) ver = NULL;
    VIR_AUTOFREE(xmlNodePtr *) nodeset = NULL;
536 537 538 539

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

540
    if ((options = virStoragePoolOptionsForPoolType(pool_type)) == NULL)
541 542
        goto cleanup;

543
    source->name = virXPathString("string(./name)", ctxt);
544
    if (pool_type == VIR_STORAGE_POOL_RBD && source->name == NULL) {
545
        virReportError(VIR_ERR_XML_ERROR, "%s",
546
                       _("element 'name' is mandatory for RBD pool"));
547 548
        goto cleanup;
    }
549 550

    if (options->formatFromString) {
551 552 553
        VIR_AUTOFREE(char *) format = NULL;

        format = virXPathString("string(./format/@type)", ctxt);
554 555 556 557 558 559
        if (format == NULL)
            source->format = options->defaultFormat;
        else
            source->format = options->formatFromString(format);

        if (source->format < 0) {
560
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
561
                           _("unknown pool format type %s"), format);
562 563 564 565
            goto cleanup;
        }
    }

566 567
    if ((n = virXPathNodeSet("./host", ctxt, &nodeset)) < 0)
        goto cleanup;
568

569 570
    if (n) {
        if (VIR_ALLOC_N(source->hosts, n) < 0)
571
            goto cleanup;
572
        source->nhost = n;
573

574
        for (i = 0; i < source->nhost; i++) {
575 576
            source->hosts[i].name = virXMLPropString(nodeset[i], "name");
            if (!source->hosts[i].name) {
577 578
                virReportError(VIR_ERR_XML_ERROR, "%s",
                               _("missing storage pool host name"));
579 580 581 582 583 584
                goto cleanup;
            }

            port = virXMLPropString(nodeset[i], "port");
            if (port) {
                if (virStrToLong_i(port, NULL, 10, &source->hosts[i].port) < 0) {
585 586 587
                    virReportError(VIR_ERR_XML_ERROR,
                                   _("Invalid port number: %s"),
                                   port);
588 589 590
                    goto cleanup;
                }
            }
591
            VIR_FREE(port);
592 593
        }
    }
594

595
    VIR_FREE(nodeset);
596 597

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

599
    nsource = virXPathNodeSet("./device", ctxt, &nodeset);
600 601 602
    if (nsource < 0)
        goto cleanup;

603
    for (i = 0; i < nsource; i++) {
604
        VIR_AUTOFREE(char *) partsep = NULL;
605 606 607 608 609 610
        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"));
611 612 613
            goto cleanup;
        }

614 615 616 617 618 619 620 621 622 623 624 625
        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;
            }
        }

626 627 628
        if (VIR_APPEND_ELEMENT(source->devices, source->ndevice, dev) < 0) {
            virStoragePoolSourceDeviceClear(&dev);
            goto cleanup;
629
        }
630

631 632
    }

633
    source->dir = virXPathString("string(./dir/@path)", ctxt);
634 635 636 637
    /* In gluster, a missing dir defaults to "/" */
    if (!source->dir && pool_type == VIR_STORAGE_POOL_GLUSTER &&
        VIR_STRDUP(source->dir, "/") < 0)
        goto cleanup;
638

639
    if ((adapternode = virXPathNode("./adapter", ctxt))) {
640
        if (virStorageAdapterParseXML(&source->adapter, adapternode, ctxt) < 0)
641 642
            goto cleanup;
    }
643

644
    if ((authnode = virXPathNode("./auth", ctxt))) {
645
        if (!(authdef = virStorageAuthDefParse(authnode, ctxt)))
646 647 648 649 650 651 652 653
            goto cleanup;

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

654
        VIR_STEAL_PTR(source->auth, authdef);
655
    }
656

657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674
    /* 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;
        }
    }

675 676 677
    source->vendor = virXPathString("string(./vendor/@name)", ctxt);
    source->product = virXPathString("string(./product/@name)", ctxt);

678
    ret = 0;
679
 cleanup:
680 681 682 683
    ctxt->node = relnode;

    return ret;
}
684

685

686
virStoragePoolSourcePtr
687
virStoragePoolDefParseSourceString(const char *srcSpec,
688 689 690 691 692
                                   int pool_type)
{
    xmlDocPtr doc = NULL;
    xmlNodePtr node = NULL;
    xmlXPathContextPtr xpath_ctxt = NULL;
693 694
    virStoragePoolSourcePtr ret = NULL;
    VIR_AUTOPTR(virStoragePoolSource) def = NULL;
695

696 697 698
    if (!(doc = virXMLParseStringCtxt(srcSpec,
                                      _("(storage_source_specification)"),
                                      &xpath_ctxt)))
699 700
        goto cleanup;

701
    if (VIR_ALLOC(def) < 0)
702 703
        goto cleanup;

704
    if (!(node = virXPathNode("/source", xpath_ctxt))) {
705 706
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("root element was not source"));
707 708 709
        goto cleanup;
    }

710
    if (virStoragePoolDefParseSource(xpath_ctxt, def, pool_type,
711 712 713
                                     node) < 0)
        goto cleanup;

714
    VIR_STEAL_PTR(ret, def);
715
 cleanup:
716 717 718 719 720
    xmlFreeDoc(doc);
    xmlXPathFreeContext(xpath_ctxt);

    return ret;
}
721

722

723
static int
724
virStorageDefParsePerms(xmlXPathContextPtr ctxt,
725
                        virStoragePermsPtr perms,
726
                        const char *permxpath)
727
{
728
    long long val;
729 730 731
    int ret = -1;
    xmlNodePtr relnode;
    xmlNodePtr node;
732
    VIR_AUTOFREE(char *) mode = NULL;
733

734
    node = virXPathNode(permxpath, ctxt);
735 736
    if (node == NULL) {
        /* Set default values if there is not <permissions> element */
737
        perms->mode = (mode_t) -1;
P
Philipp Hahn 已提交
738 739
        perms->uid = (uid_t) -1;
        perms->gid = (gid_t) -1;
740 741 742 743 744 745 746
        perms->label = NULL;
        return 0;
    }

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

747
    if ((mode = virXPathString("string(./mode)", ctxt))) {
748 749 750
        int tmp;

        if (virStrToLong_i(mode, NULL, 8, &tmp) < 0 || (tmp & ~0777)) {
751 752
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("malformed octal mode"));
753
            goto error;
754
        }
755
        perms->mode = tmp;
756 757
    } else {
        perms->mode = (mode_t) -1;
758 759
    }

760
    if (virXPathNode("./owner", ctxt) == NULL) {
P
Philipp Hahn 已提交
761
        perms->uid = (uid_t) -1;
762
    } else {
763
        /* We previously could output -1, so continue to parse it */
764
        if (virXPathLongLong("number(./owner)", ctxt, &val) < 0 ||
765 766
            ((uid_t)val != val &&
             val != -1)) {
767 768
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("malformed owner element"));
769
            goto error;
770
        }
771 772

        perms->uid = val;
773 774
    }

775
    if (virXPathNode("./group", ctxt) == NULL) {
P
Philipp Hahn 已提交
776
        perms->gid = (gid_t) -1;
777
    } else {
778
        /* We previously could output -1, so continue to parse it */
779
        if (virXPathLongLong("number(./group)", ctxt, &val) < 0 ||
780 781
            ((gid_t) val != val &&
             val != -1)) {
782 783
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("malformed group element"));
784
            goto error;
785
        }
786
        perms->gid = val;
787 788 789
    }

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

792
    ret = 0;
793
 error:
794 795
    ctxt->node = relnode;
    return ret;
796 797
}

798

799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843
static int
virStoragePoolDefRefreshParse(xmlXPathContextPtr ctxt,
                              virStoragePoolDefPtr def)
{
    VIR_AUTOFREE(virStoragePoolDefRefreshPtr) refresh = NULL;
    VIR_AUTOFREE(char *) allocation = NULL;
    int tmp;

    allocation = virXPathString("string(./refresh/volume/@allocation)", ctxt);

    if (!allocation)
        return 0;

    if ((tmp = virStorageVolDefRefreshAllocationTypeFromString(allocation)) < 0) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("unknown storage pool volume refresh allocation type %s"),
                       allocation);
        return -1;
    }

    if (VIR_ALLOC(refresh) < 0)
        return -1;

    refresh->volume.allocation = tmp;
    VIR_STEAL_PTR(def->refresh, refresh);
    return 0;
}


static void
virStoragePoolDefRefreshFormat(virBufferPtr buf,
                               virStoragePoolDefRefreshPtr refresh)
{
    if (!refresh)
        return;

    virBufferAddLit(buf, "<refresh>\n");
    virBufferAdjustIndent(buf, 2);
    virBufferAsprintf(buf, "<volume allocation='%s'/>\n",
                      virStorageVolDefRefreshAllocationTypeToString(refresh->volume.allocation));
    virBufferAdjustIndent(buf, -2);
    virBufferAddLit(buf, "</refresh>\n");
}


J
John Ferlan 已提交
844
virStoragePoolDefPtr
845 846
virStoragePoolDefParseXML(xmlXPathContextPtr ctxt)
{
847
    virStoragePoolOptionsPtr options;
848
    virStoragePoolDefPtr ret = NULL;
849
    xmlNodePtr source_node;
850
    VIR_AUTOPTR(virStoragePoolDef) def = NULL;
851 852 853
    VIR_AUTOFREE(char *) type = NULL;
    VIR_AUTOFREE(char *) uuid = NULL;
    VIR_AUTOFREE(char *) target_path = NULL;
854

855
    if (VIR_ALLOC(def) < 0)
856 857
        return NULL;

858
    type = virXPathString("string(./@type)", ctxt);
859 860 861
    if (type == NULL) {
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("storage pool missing type attribute"));
862
        return NULL;
863 864
    }

865
    if ((def->type = virStoragePoolTypeFromString(type)) < 0) {
866
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
867
                       _("unknown storage pool type %s"), type);
868
        return NULL;
869 870
    }

871
    if ((options = virStoragePoolOptionsForPoolType(def->type)) == NULL)
872
        return NULL;
873

874
    source_node = virXPathNode("./source", ctxt);
875
    if (source_node) {
876
        if (virStoragePoolDefParseSource(ctxt, &def->source, def->type,
877
                                         source_node) < 0)
878
            return NULL;
879 880
    } else {
        if (options->formatFromString)
881
            def->source.format = options->defaultFormat;
882 883
    }

884 885
    def->name = virXPathString("string(./name)", ctxt);
    if (def->name == NULL &&
886
        options->flags & VIR_STORAGE_POOL_SOURCE_NAME &&
887
        VIR_STRDUP(def->name, def->source.name) < 0)
888 889
        return NULL;

890
    if (def->name == NULL) {
891 892
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("missing pool source name element"));
893
        return NULL;
894 895
    }

896
    if (strchr(def->name, '/')) {
897
        virReportError(VIR_ERR_XML_ERROR,
898
                       _("name %s cannot contain '/'"), def->name);
899
        return NULL;
900 901
    }

902
    uuid = virXPathString("string(./uuid)", ctxt);
903
    if (uuid == NULL) {
904
        if (virUUIDGenerate(def->uuid) < 0) {
905 906
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("unable to generate uuid"));
907
            return NULL;
908 909
        }
    } else {
910
        if (virUUIDParse(uuid, def->uuid) < 0) {
911 912
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("malformed uuid element"));
913
            return NULL;
914 915 916
        }
    }

917
    if (options->flags & VIR_STORAGE_POOL_SOURCE_HOST) {
918
        if (!def->source.nhost) {
919
            virReportError(VIR_ERR_XML_ERROR, "%s",
920
                           _("missing storage pool source host name"));
921
            return NULL;
922 923 924
        }
    }

925
    if (options->flags & VIR_STORAGE_POOL_SOURCE_DIR) {
926
        if (!def->source.dir) {
927 928
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("missing storage pool source path"));
929
            return NULL;
930 931
        }
    }
932
    if (options->flags & VIR_STORAGE_POOL_SOURCE_NAME) {
933
        if (def->source.name == NULL) {
934
            /* source name defaults to pool name */
935
            if (VIR_STRDUP(def->source.name, def->name) < 0)
936
                return NULL;
937 938
        }
    }
939

940
    if ((options->flags & VIR_STORAGE_POOL_SOURCE_ADAPTER) &&
941
        (virStorageAdapterValidate(&def->source.adapter)) < 0)
942
            return NULL;
943

944 945
    /* If DEVICE is the only source type, then its required */
    if (options->flags == VIR_STORAGE_POOL_SOURCE_DEVICE) {
946
        if (!def->source.ndevice) {
947 948
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("missing storage pool source device name"));
949
            return NULL;
950 951 952
        }
    }

953 954 955
    /* When we are working with a virtual disk we can skip the target
     * path and permissions */
    if (!(options->flags & VIR_STORAGE_POOL_SOURCE_NETWORK)) {
956 957
        if (def->type == VIR_STORAGE_POOL_LOGICAL) {
            if (virAsprintf(&target_path, "/dev/%s", def->source.name) < 0)
958
                return NULL;
959 960
        } else if (def->type == VIR_STORAGE_POOL_ZFS) {
            if (virAsprintf(&target_path, "/dev/zvol/%s", def->source.name) < 0)
961
                return NULL;
962 963 964 965 966
        } else {
            target_path = virXPathString("string(./target/path)", ctxt);
            if (!target_path) {
                virReportError(VIR_ERR_XML_ERROR, "%s",
                               _("missing storage pool target path"));
967
                return NULL;
968
            }
969
        }
970 971
        def->target.path = virFileSanitizePath(target_path);
        if (!def->target.path)
972
            return NULL;
973

974
        if (virStorageDefParsePerms(ctxt, &def->target.perms,
975
                                    "./target/permissions") < 0)
976
            return NULL;
977
    }
978

979 980
    if (def->type == VIR_STORAGE_POOL_ISCSI_DIRECT &&
        !def->source.initiator.iqn) {
981 982
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("missing initiator IQN"));
983
        return NULL;
984 985
    }

986 987 988
    if (virStoragePoolDefRefreshParse(ctxt, def) < 0)
        return NULL;

989 990
    /* Make a copy of all the callback pointers here for easier use,
     * especially during the virStoragePoolSourceClear method */
991 992 993
    def->ns = options->ns;
    if (def->ns.parse &&
        (def->ns.parse)(ctxt, &def->namespaceData) < 0)
994
        return NULL;
995

996
    VIR_STEAL_PTR(ret, def);
997
    return ret;
998 999
}

1000

1001
virStoragePoolDefPtr
1002
virStoragePoolDefParseNode(xmlDocPtr xml,
1003 1004
                           xmlNodePtr root)
{
1005 1006 1007
    xmlXPathContextPtr ctxt = NULL;
    virStoragePoolDefPtr def = NULL;

1008
    if (!virXMLNodeNameEqual(root, "pool")) {
1009
        virReportError(VIR_ERR_XML_ERROR,
1010 1011 1012
                       _("unexpected root element <%s>, "
                         "expecting <pool>"),
                       root->name);
1013 1014 1015 1016 1017
        goto cleanup;
    }

    ctxt = xmlXPathNewContext(xml);
    if (ctxt == NULL) {
1018
        virReportOOMError();
1019 1020 1021 1022
        goto cleanup;
    }

    ctxt->node = root;
1023
    def = virStoragePoolDefParseXML(ctxt);
1024
 cleanup:
1025 1026 1027 1028
    xmlXPathFreeContext(ctxt);
    return def;
}

1029

1030
static virStoragePoolDefPtr
1031
virStoragePoolDefParse(const char *xmlStr,
1032 1033
                       const char *filename)
{
1034
    virStoragePoolDefPtr ret = NULL;
J
Jiri Denemark 已提交
1035
    xmlDocPtr xml;
1036

1037
    if ((xml = virXMLParse(filename, xmlStr, _("(storage_pool_definition)")))) {
J
Jiri Denemark 已提交
1038 1039
        ret = virStoragePoolDefParseNode(xml, xmlDocGetRootElement(xml));
        xmlFreeDoc(xml);
1040 1041
    }

1042 1043 1044
    return ret;
}

1045

1046
virStoragePoolDefPtr
1047
virStoragePoolDefParseString(const char *xmlStr)
1048
{
1049
    return virStoragePoolDefParse(xmlStr, NULL);
1050 1051
}

1052

1053
virStoragePoolDefPtr
1054
virStoragePoolDefParseFile(const char *filename)
1055
{
1056
    return virStoragePoolDefParse(NULL, filename);
1057 1058
}

1059

1060
static int
1061
virStoragePoolSourceFormat(virBufferPtr buf,
1062
                           virStoragePoolOptionsPtr options,
1063 1064
                           virStoragePoolSourcePtr src)
{
1065
    size_t i, j;
1066

1067 1068 1069
    virBufferAddLit(buf, "<source>\n");
    virBufferAdjustIndent(buf, 2);

1070 1071
    if ((options->flags & VIR_STORAGE_POOL_SOURCE_HOST) && src->nhost) {
        for (i = 0; i < src->nhost; i++) {
1072
            virBufferEscapeString(buf, "<host name='%s'",
1073
                                  src->hosts[i].name);
1074 1075 1076 1077
            if (src->hosts[i].port)
                virBufferAsprintf(buf, " port='%d'", src->hosts[i].port);
            virBufferAddLit(buf, "/>\n");
        }
1078
    }
1079

1080
    if ((options->flags & VIR_STORAGE_POOL_SOURCE_DEVICE) &&
1081
        src->ndevice) {
1082
        for (i = 0; i < src->ndevice; i++) {
1083 1084 1085 1086 1087 1088 1089
            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));
            }
1090
            if (src->devices[i].nfreeExtent) {
1091
                virBufferAddLit(buf, ">\n");
1092
                virBufferAdjustIndent(buf, 2);
1093
                for (j = 0; j < src->devices[i].nfreeExtent; j++) {
1094
                    virBufferAsprintf(buf, "<freeExtent start='%llu' end='%llu'/>\n",
1095 1096 1097
                                      src->devices[i].freeExtents[j].start,
                                      src->devices[i].freeExtents[j].end);
                }
1098 1099
                virBufferAdjustIndent(buf, -2);
                virBufferAddLit(buf, "</device>\n");
1100
            } else {
1101
                virBufferAddLit(buf, "/>\n");
1102
            }
1103 1104
        }
    }
1105

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

1109
    if ((options->flags & VIR_STORAGE_POOL_SOURCE_ADAPTER) &&
1110 1111 1112
        (src->adapter.type == VIR_STORAGE_ADAPTER_TYPE_FC_HOST ||
         src->adapter.type == VIR_STORAGE_ADAPTER_TYPE_SCSI_HOST))
        virStorageAdapterFormat(buf, &src->adapter);
1113

1114
    if (options->flags & VIR_STORAGE_POOL_SOURCE_NAME)
1115
        virBufferEscapeString(buf, "<name>%s</name>\n", src->name);
1116

1117 1118
    if (options->flags & VIR_STORAGE_POOL_SOURCE_INITIATOR_IQN)
        virStorageSourceInitiatorFormatXML(&src->initiator, buf);
D
David Allan 已提交
1119

1120 1121 1122
    if (options->formatToString) {
        const char *format = (options->formatToString)(src->format);
        if (!format) {
1123 1124 1125
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("unknown pool format number %d"),
                           src->format);
1126 1127
            return -1;
        }
1128
        virBufferAsprintf(buf, "<format type='%s'/>\n", format);
1129 1130
    }

1131 1132
    if (src->auth)
        virStorageAuthDefFormat(buf, src->auth);
1133

1134 1135 1136
    if (src->protocolVer)
        virBufferAsprintf(buf, "<protocol ver='%u'/>\n", src->protocolVer);

1137 1138
    virBufferEscapeString(buf, "<vendor name='%s'/>\n", src->vendor);
    virBufferEscapeString(buf, "<product name='%s'/>\n", src->product);
1139

1140 1141
    virBufferAdjustIndent(buf, -2);
    virBufferAddLit(buf, "</source>\n");
1142 1143 1144
    return 0;
}

1145

1146 1147 1148
static int
virStoragePoolDefFormatBuf(virBufferPtr buf,
                           virStoragePoolDefPtr def)
1149
{
1150
    virStoragePoolOptionsPtr options;
1151
    char uuid[VIR_UUID_STRING_BUFLEN];
1152
    const char *type;
1153

1154
    options = virStoragePoolOptionsForPoolType(def->type);
1155
    if (options == NULL)
1156
        return -1;
1157

1158
    type = virStoragePoolTypeToString(def->type);
1159
    if (!type) {
1160 1161
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("unexpected pool type"));
1162
        return -1;
1163
    }
1164 1165 1166 1167
    virBufferAsprintf(buf, "<pool type='%s'", type);
    if (def->namespaceData && def->ns.href)
        virBufferAsprintf(buf, " %s", (def->ns.href)());
    virBufferAddLit(buf, ">\n");
1168 1169
    virBufferAdjustIndent(buf, 2);
    virBufferEscapeString(buf, "<name>%s</name>\n", def->name);
1170 1171

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

1174
    virBufferAsprintf(buf, "<capacity unit='bytes'>%llu</capacity>\n",
1175
                      def->capacity);
1176
    virBufferAsprintf(buf, "<allocation unit='bytes'>%llu</allocation>\n",
1177
                      def->allocation);
1178
    virBufferAsprintf(buf, "<available unit='bytes'>%llu</available>\n",
1179
                      def->available);
1180

1181 1182
    if (virStoragePoolSourceFormat(buf, options, &def->source) < 0)
        return -1;
1183

1184
    /* RBD, Sheepdog, Gluster and Iscsi-direct devices are not local block devs nor
1185
     * files, so they don't have a target */
1186
    if (def->type != VIR_STORAGE_POOL_RBD &&
1187
        def->type != VIR_STORAGE_POOL_SHEEPDOG &&
1188 1189
        def->type != VIR_STORAGE_POOL_GLUSTER &&
        def->type != VIR_STORAGE_POOL_ISCSI_DIRECT) {
1190 1191
        virBufferAddLit(buf, "<target>\n");
        virBufferAdjustIndent(buf, 2);
1192

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

1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215
        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");
        }
1216

1217 1218
        virBufferAdjustIndent(buf, -2);
        virBufferAddLit(buf, "</target>\n");
1219
    }
1220

1221 1222
    virStoragePoolDefRefreshFormat(buf, def->refresh);

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

1228 1229 1230 1231 1232 1233
    virBufferAdjustIndent(buf, -2);
    virBufferAddLit(buf, "</pool>\n");

    return 0;
}

1234

1235 1236 1237 1238 1239 1240 1241
char *
virStoragePoolDefFormat(virStoragePoolDefPtr def)
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;

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

1243
    if (virBufferCheckError(&buf) < 0)
1244
        goto error;
1245

1246
    return virBufferContentAndReset(&buf);
1247

1248
 error:
1249
    virBufferFreeAndReset(&buf);
1250 1251 1252 1253 1254
    return NULL;
}


static int
1255
virStorageSize(const char *unit,
1256
               const char *val,
1257 1258
               unsigned long long *ret)
{
J
Ján Tomko 已提交
1259
    if (virStrToLong_ullp(val, NULL, 10, ret) < 0) {
1260 1261
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("malformed capacity element"));
1262 1263
        return -1;
    }
1264 1265 1266 1267
    /* 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;
1268 1269 1270 1271

    return 0;
}

1272

1273
static virStorageVolDefPtr
1274
virStorageVolDefParseXML(virStoragePoolDefPtr pool,
1275 1276
                         xmlXPathContextPtr ctxt,
                         unsigned int flags)
1277
{
1278
    virStorageVolDefPtr ret = NULL;
1279
    virStorageVolOptionsPtr options;
1280
    xmlNodePtr node;
1281 1282
    size_t i;
    int n;
1283
    VIR_AUTOPTR(virStorageVolDef) def = NULL;
1284 1285 1286 1287 1288 1289
    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;
1290

1291 1292
    virCheckFlags(VIR_VOL_XML_PARSE_NO_CAPACITY |
                  VIR_VOL_XML_PARSE_OPT_CAPACITY, NULL);
1293

1294
    options = virStorageVolOptionsForPoolType(pool->type);
1295 1296 1297
    if (options == NULL)
        return NULL;

1298
    if (VIR_ALLOC(def) < 0)
1299 1300
        return NULL;

1301
    def->target.type = VIR_STORAGE_TYPE_FILE;
1302

1303 1304
    def->name = virXPathString("string(./name)", ctxt);
    if (def->name == NULL) {
1305 1306
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("missing volume name element"));
1307
        return NULL;
1308 1309
    }

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

1313 1314 1315
    /* Technically overridden by pool refresh, but useful for unit tests */
    type = virXPathString("string(./@type)", ctxt);
    if (type) {
1316
        if ((def->type = virStorageVolTypeFromString(type)) < 0) {
1317
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1318
                           _("unknown volume type '%s'"), type);
1319
            return NULL;
1320 1321 1322
        }
    }

1323
    if ((backingStore = virXPathString("string(./backingStore/path)", ctxt))) {
1324
        if (!(def->target.backingStore = virStorageSourceNew()))
1325
            return NULL;
1326

1327
        def->target.backingStore->type = VIR_STORAGE_TYPE_FILE;
1328

1329
        def->target.backingStore->path = backingStore;
1330 1331 1332
        backingStore = NULL;

        if (options->formatFromString) {
1333 1334 1335
            VIR_AUTOFREE(char *) format = NULL;

            format = virXPathString("string(./backingStore/format/@type)", ctxt);
1336
            if (format == NULL)
1337
                def->target.backingStore->format = options->defaultFormat;
1338
            else
1339
                def->target.backingStore->format = (options->formatFromString)(format);
1340

1341
            if (def->target.backingStore->format < 0) {
1342 1343
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("unknown volume format type %s"), format);
1344
                return NULL;
1345 1346 1347
            }
        }

1348
        if (VIR_ALLOC(def->target.backingStore->perms) < 0)
1349
            return NULL;
1350
        if (virStorageDefParsePerms(ctxt, def->target.backingStore->perms,
1351
                                    "./backingStore/permissions") < 0)
1352
            return NULL;
1353 1354
    }

1355 1356
    capacity = virXPathString("string(./capacity)", ctxt);
    unit = virXPathString("string(./capacity/@unit)", ctxt);
1357
    if (capacity) {
1358
        if (virStorageSize(unit, capacity, &def->target.capacity) < 0)
1359
            return NULL;
1360
    } else if (!(flags & VIR_VOL_XML_PARSE_NO_CAPACITY) &&
1361
               !((flags & VIR_VOL_XML_PARSE_OPT_CAPACITY) &&
1362
                 virStorageSourceHasBacking(&def->target))) {
1363
        virReportError(VIR_ERR_XML_ERROR, "%s", _("missing capacity element"));
1364
        return NULL;
1365
    }
1366
    VIR_FREE(unit);
1367

1368
    allocation = virXPathString("string(./allocation)", ctxt);
1369
    if (allocation) {
1370
        unit = virXPathString("string(./allocation/@unit)", ctxt);
1371
        if (virStorageSize(unit, allocation, &def->target.allocation) < 0)
1372
            return NULL;
1373
        def->target.has_allocation = true;
1374
    } else {
1375
        def->target.allocation = def->target.capacity;
1376 1377
    }

1378
    def->target.path = virXPathString("string(./target/path)", ctxt);
1379
    if (options->formatFromString) {
1380 1381 1382
        VIR_AUTOFREE(char *) format = NULL;

        format = virXPathString("string(./target/format/@type)", ctxt);
1383
        if (format == NULL)
1384
            def->target.format = options->defaultFormat;
1385
        else
1386
            def->target.format = (options->formatFromString)(format);
1387

1388
        if (def->target.format < 0) {
1389
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1390
                           _("unknown volume format type %s"), format);
1391
            return NULL;
1392 1393 1394
        }
    }

1395
    if (VIR_ALLOC(def->target.perms) < 0)
1396
        return NULL;
1397
    if (virStorageDefParsePerms(ctxt, def->target.perms,
1398
                                "./target/permissions") < 0)
1399
        return NULL;
1400

1401
    node = virXPathNode("./target/encryption", ctxt);
1402
    if (node != NULL) {
1403 1404
        def->target.encryption = virStorageEncryptionParseNode(node, ctxt);
        if (def->target.encryption == NULL)
1405
            return NULL;
1406 1407
    }

1408 1409
    def->target.compat = virXPathString("string(./target/compat)", ctxt);
    if (virStorageFileCheckCompat(def->target.compat) < 0)
1410
        return NULL;
1411

C
Chunyan Liu 已提交
1412
    if (virXPathNode("./target/nocow", ctxt))
1413
        def->target.nocow = true;
C
Chunyan Liu 已提交
1414

1415
    if (virXPathNode("./target/features", ctxt)) {
1416
        if ((n = virXPathNodeSet("./target/features/*", ctxt, &nodes)) < 0)
1417
            return NULL;
1418

1419
        if (!def->target.compat && VIR_STRDUP(def->target.compat, "1.1") < 0)
1420
            return NULL;
1421

1422
        if (!(def->target.features = virBitmapNew(VIR_STORAGE_FILE_FEATURE_LAST)))
1423
            return NULL;
1424 1425

        for (i = 0; i < n; i++) {
1426
            int f = virStorageFileFeatureTypeFromString((const char*)nodes[i]->name);
1427 1428

            if (f < 0) {
1429
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unsupported feature %s"),
1430
                               (const char*)nodes[i]->name);
1431
                return NULL;
1432
            }
1433
            ignore_value(virBitmapSetBit(def->target.features, f));
1434 1435 1436 1437
        }
        VIR_FREE(nodes);
    }

1438
    VIR_STEAL_PTR(ret, def);
1439
    return ret;
1440 1441
}

1442

1443
virStorageVolDefPtr
1444
virStorageVolDefParseNode(virStoragePoolDefPtr pool,
1445
                          xmlDocPtr xml,
1446 1447
                          xmlNodePtr root,
                          unsigned int flags)
1448
{
1449 1450 1451
    xmlXPathContextPtr ctxt = NULL;
    virStorageVolDefPtr def = NULL;

1452
    if (!virXMLNodeNameEqual(root, "volume")) {
1453
        virReportError(VIR_ERR_XML_ERROR,
1454 1455 1456
                       _("unexpected root element <%s>, "
                         "expecting <volume>"),
                       root->name);
1457 1458 1459 1460 1461
        goto cleanup;
    }

    ctxt = xmlXPathNewContext(xml);
    if (ctxt == NULL) {
1462
        virReportOOMError();
1463 1464 1465 1466
        goto cleanup;
    }

    ctxt->node = root;
1467
    def = virStorageVolDefParseXML(pool, ctxt, flags);
1468
 cleanup:
1469 1470 1471 1472
    xmlXPathFreeContext(ctxt);
    return def;
}

1473

1474
static virStorageVolDefPtr
1475
virStorageVolDefParse(virStoragePoolDefPtr pool,
1476
                      const char *xmlStr,
1477 1478
                      const char *filename,
                      unsigned int flags)
1479
{
1480
    virStorageVolDefPtr ret = NULL;
J
Jiri Denemark 已提交
1481
    xmlDocPtr xml;
1482

1483
    if ((xml = virXMLParse(filename, xmlStr, _("(storage_volume_definition)")))) {
1484
        ret = virStorageVolDefParseNode(pool, xml, xmlDocGetRootElement(xml), flags);
J
Jiri Denemark 已提交
1485
        xmlFreeDoc(xml);
1486 1487 1488 1489 1490
    }

    return ret;
}

1491

1492
virStorageVolDefPtr
1493
virStorageVolDefParseString(virStoragePoolDefPtr pool,
1494 1495
                            const char *xmlStr,
                            unsigned int flags)
1496
{
1497
    return virStorageVolDefParse(pool, xmlStr, NULL, flags);
1498 1499
}

1500

1501
virStorageVolDefPtr
1502
virStorageVolDefParseFile(virStoragePoolDefPtr pool,
1503 1504
                          const char *filename,
                          unsigned int flags)
1505
{
1506
    return virStorageVolDefParse(pool, NULL, filename, flags);
1507
}
1508

1509

1510 1511 1512 1513 1514 1515
static void
virStorageVolTimestampFormat(virBufferPtr buf, const char *name,
                             struct timespec *ts)
{
    if (ts->tv_nsec < 0)
        return;
1516
    virBufferAsprintf(buf, "<%s>%llu", name,
1517 1518 1519 1520 1521 1522
                      (unsigned long long) ts->tv_sec);
    if (ts->tv_nsec)
       virBufferAsprintf(buf, ".%09ld", ts->tv_nsec);
    virBufferAsprintf(buf, "</%s>\n", name);
}

1523

1524
static int
1525
virStorageVolTargetDefFormat(virStorageVolOptionsPtr options,
1526
                             virBufferPtr buf,
1527
                             virStorageSourcePtr def,
1528 1529
                             const char *type)
{
1530 1531
    virBufferAsprintf(buf, "<%s>\n", type);
    virBufferAdjustIndent(buf, 2);
1532

1533
    virBufferEscapeString(buf, "<path>%s</path>\n", def->path);
1534 1535 1536 1537

    if (options->formatToString) {
        const char *format = (options->formatToString)(def->format);
        if (!format) {
1538 1539 1540
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("unknown volume format number %d"),
                           def->format);
1541 1542
            return -1;
        }
1543
        virBufferAsprintf(buf, "<format type='%s'/>\n", format);
1544 1545
    }

1546 1547 1548 1549 1550
    if (def->perms &&
        (def->perms->mode != (mode_t) -1 ||
         def->perms->uid != (uid_t) -1 ||
         def->perms->gid != (gid_t) -1 ||
         def->perms->label)) {
1551 1552
        virBufferAddLit(buf, "<permissions>\n");
        virBufferAdjustIndent(buf, 2);
1553

1554 1555 1556
        if (def->perms->mode != (mode_t) -1)
            virBufferAsprintf(buf, "<mode>0%o</mode>\n",
                              def->perms->mode);
1557 1558 1559 1560 1561 1562
        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);
1563

1564 1565
        virBufferEscapeString(buf, "<label>%s</label>\n",
                              def->perms->label);
1566

1567 1568 1569
        virBufferAdjustIndent(buf, -2);
        virBufferAddLit(buf, "</permissions>\n");
    }
1570

1571
    if (def->timestamps) {
1572 1573
        virBufferAddLit(buf, "<timestamps>\n");
        virBufferAdjustIndent(buf, 2);
1574 1575 1576 1577
        virStorageVolTimestampFormat(buf, "atime", &def->timestamps->atime);
        virStorageVolTimestampFormat(buf, "mtime", &def->timestamps->mtime);
        virStorageVolTimestampFormat(buf, "ctime", &def->timestamps->ctime);
        virStorageVolTimestampFormat(buf, "btime", &def->timestamps->btime);
1578 1579
        virBufferAdjustIndent(buf, -2);
        virBufferAddLit(buf, "</timestamps>\n");
1580 1581
    }

1582 1583
    if (def->encryption &&
        virStorageEncryptionFormat(buf, def->encryption) < 0)
1584
            return -1;
1585

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

1588
    if (def->features) {
1589
        size_t i;
1590 1591
        bool empty = virBitmapIsAllClear(def->features);

1592 1593 1594 1595 1596 1597
        if (empty) {
            virBufferAddLit(buf, "<features/>\n");
        } else {
            virBufferAddLit(buf, "<features>\n");
            virBufferAdjustIndent(buf, 2);
        }
1598 1599

        for (i = 0; i < VIR_STORAGE_FILE_FEATURE_LAST; i++) {
J
Ján Tomko 已提交
1600
            if (virBitmapIsBitSet(def->features, i))
1601
                virBufferAsprintf(buf, "<%s/>\n",
1602
                                  virStorageFileFeatureTypeToString(i));
1603
        }
1604 1605 1606 1607
        if (!empty) {
            virBufferAdjustIndent(buf, -2);
            virBufferAddLit(buf, "</features>\n");
        }
1608 1609
    }

1610 1611
    virBufferAdjustIndent(buf, -2);
    virBufferAsprintf(buf, "</%s>\n", type);
1612 1613
    return 0;
}
1614

1615

1616
char *
1617
virStorageVolDefFormat(virStoragePoolDefPtr pool,
1618 1619
                       virStorageVolDefPtr def)
{
1620
    virStorageVolOptionsPtr options;
1621
    virBuffer buf = VIR_BUFFER_INITIALIZER;
1622

1623
    options = virStorageVolOptionsForPoolType(pool->type);
1624 1625 1626
    if (options == NULL)
        return NULL;

1627 1628
    virBufferAsprintf(&buf, "<volume type='%s'>\n",
                      virStorageVolTypeToString(def->type));
1629 1630 1631 1632 1633 1634
    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);
1635 1636

    if (def->source.nextent) {
1637
        size_t i;
1638
        const char *thispath = NULL;
1639
        for (i = 0; i < def->source.nextent; i++) {
1640 1641 1642
            if (thispath == NULL ||
                STRNEQ(thispath, def->source.extents[i].path)) {
                if (thispath != NULL)
1643
                    virBufferAddLit(&buf, "</device>\n");
1644

1645
                virBufferEscapeString(&buf, "<device path='%s'>\n",
1646
                                      def->source.extents[i].path);
1647 1648
            }

1649 1650
            virBufferAdjustIndent(&buf, 2);
            virBufferAsprintf(&buf, "<extent start='%llu' end='%llu'/>\n",
1651 1652
                              def->source.extents[i].start,
                              def->source.extents[i].end);
1653
            virBufferAdjustIndent(&buf, -2);
1654 1655 1656
            thispath = def->source.extents[i].path;
        }
        if (thispath != NULL)
1657
            virBufferAddLit(&buf, "</device>\n");
1658 1659
    }

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

    virBufferAsprintf(&buf, "<capacity unit='bytes'>%llu</capacity>\n",
1664
                      def->target.capacity);
1665
    virBufferAsprintf(&buf, "<allocation unit='bytes'>%llu</allocation>\n",
1666
                      def->target.allocation);
1667 1668 1669 1670 1671 1672
    /* 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);
1673

1674
    if (virStorageVolTargetDefFormat(options, &buf,
1675 1676
                                     &def->target, "target") < 0)
        goto cleanup;
1677

1678
    if (virStorageSourceHasBacking(&def->target) &&
1679
        virStorageVolTargetDefFormat(options, &buf,
1680 1681
                                     def->target.backingStore,
                                     "backingStore") < 0)
1682
        goto cleanup;
1683

1684
    virBufferAdjustIndent(&buf, -2);
E
Eric Blake 已提交
1685
    virBufferAddLit(&buf, "</volume>\n");
1686

1687 1688
    if (virBufferCheckError(&buf) < 0)
        goto cleanup;
1689

1690
    return virBufferContentAndReset(&buf);
1691

1692
 cleanup:
1693
    virBufferFreeAndReset(&buf);
1694 1695 1696 1697
    return NULL;
}


1698 1699 1700 1701
static int
virStoragePoolSaveXML(const char *path,
                      virStoragePoolDefPtr def,
                      const char *xml)
1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712
{
    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;
}
1713 1714 1715 1716 1717 1718 1719


int
virStoragePoolSaveState(const char *stateFile,
                        virStoragePoolDefPtr def)
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;
1720
    VIR_AUTOFREE(char *) xml = NULL;
1721 1722 1723 1724 1725

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

    if (virStoragePoolDefFormatBuf(&buf, def) < 0)
1726
        return -1;
1727 1728 1729 1730 1731

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

    if (virBufferCheckError(&buf) < 0)
1732
        return -1;
1733 1734

    if (!(xml = virBufferContentAndReset(&buf)))
1735
        return -1;
1736 1737

    if (virStoragePoolSaveXML(stateFile, def, xml))
1738
        return -1;
1739

1740
    return 0;
1741
}
1742 1743


1744
int
1745
virStoragePoolSaveConfig(const char *configFile,
1746 1747
                         virStoragePoolDefPtr def)
{
1748
    VIR_AUTOFREE(char *) xml = NULL;
1749

1750 1751 1752 1753 1754 1755
    if (!(xml = virStoragePoolDefFormat(def))) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("failed to generate XML"));
        return -1;
    }

1756
    return virStoragePoolSaveXML(configFile, def, xml);
1757 1758
}

1759

1760
virStoragePoolSourcePtr
1761
virStoragePoolSourceListNewSource(virStoragePoolSourceListPtr list)
1762 1763 1764
{
    virStoragePoolSourcePtr source;

1765
    if (VIR_REALLOC_N(list->sources, list->nsources + 1) < 0)
1766 1767 1768 1769 1770 1771 1772 1773
        return NULL;

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

    return source;
}

1774

1775 1776
char *
virStoragePoolSourceListFormat(virStoragePoolSourceListPtr def)
1777
{
1778
    virStoragePoolOptionsPtr options;
1779
    virBuffer buf = VIR_BUFFER_INITIALIZER;
1780
    const char *type;
1781
    size_t i;
1782

1783
    options = virStoragePoolOptionsForPoolType(def->type);
1784 1785 1786
    if (options == NULL)
        return NULL;

1787
    type = virStoragePoolTypeToString(def->type);
1788
    if (!type) {
1789 1790
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("unexpected pool type"));
1791 1792 1793 1794
        goto cleanup;
    }

    virBufferAddLit(&buf, "<sources>\n");
1795
    virBufferAdjustIndent(&buf, 2);
1796

1797
    for (i = 0; i < def->nsources; i++)
1798
        virStoragePoolSourceFormat(&buf, options, &def->sources[i]);
1799

1800
    virBufferAdjustIndent(&buf, -2);
1801 1802
    virBufferAddLit(&buf, "</sources>\n");

1803 1804
    if (virBufferCheckError(&buf) < 0)
        goto cleanup;
1805 1806

    return virBufferContentAndReset(&buf);
1807

1808
 cleanup:
1809
    virBufferFreeAndReset(&buf);
1810
    return NULL;
1811
}