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 513
    if (def->namespaceData && def->ns.free)
        (def->ns.free)(def->namespaceData);
514
    VIR_FREE(def);
515 516 517
}


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

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

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

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

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

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

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

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

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

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

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

593
    VIR_FREE(nodeset);
594 595

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

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

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

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

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

629 630
    }

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

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

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

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

652
        VIR_STEAL_PTR(source->auth, authdef);
653
    }
654

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

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

676
    ret = 0;
677
 cleanup:
678 679 680 681
    ctxt->node = relnode;

    return ret;
}
682

683

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

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

699
    if (VIR_ALLOC(def) < 0)
700 701
        goto cleanup;

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

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

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

    return ret;
}
719

720

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

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

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

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

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

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

        perms->uid = val;
771 772
    }

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

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

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

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
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 已提交
842
virStoragePoolDefPtr
843 844
virStoragePoolDefParseXML(xmlXPathContextPtr ctxt)
{
845
    virStoragePoolOptionsPtr options;
846
    virStoragePoolDefPtr ret = NULL;
847
    xmlNodePtr source_node;
848
    VIR_AUTOPTR(virStoragePoolDef) def = NULL;
849 850 851
    VIR_AUTOFREE(char *) type = NULL;
    VIR_AUTOFREE(char *) uuid = NULL;
    VIR_AUTOFREE(char *) target_path = NULL;
852

853
    if (VIR_ALLOC(def) < 0)
854 855
        return NULL;

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

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

869
    if ((options = virStoragePoolOptionsForPoolType(def->type)) == NULL)
870
        return NULL;
871

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

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

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

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

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

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

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

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

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

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

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

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

984 985 986
    if (virStoragePoolDefRefreshParse(ctxt, def) < 0)
        return NULL;

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

994
    VIR_STEAL_PTR(ret, def);
995
    return ret;
996 997
}

998

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

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

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

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

1027

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

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

1040 1041 1042
    return ret;
}

1043

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

1050

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

1057

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

1065 1066 1067
    virBufferAddLit(buf, "<source>\n");
    virBufferAdjustIndent(buf, 2);

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

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

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

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

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

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

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

1129 1130
    if (src->auth)
        virStorageAuthDefFormat(buf, src->auth);
1131

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

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

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

1143

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

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

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

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

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

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

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

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

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

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

1219 1220
    virStoragePoolDefRefreshFormat(buf, def->refresh);

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

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

    return 0;
}

1232

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

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

1241
    if (virBufferCheckError(&buf) < 0)
1242
        goto error;
1243

1244
    return virBufferContentAndReset(&buf);
1245

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


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

    return 0;
}

1270

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

1289 1290
    virCheckFlags(VIR_VOL_XML_PARSE_NO_CAPACITY |
                  VIR_VOL_XML_PARSE_OPT_CAPACITY, NULL);
1291

1292
    options = virStorageVolOptionsForPoolType(pool->type);
1293 1294 1295
    if (options == NULL)
        return NULL;

1296
    if (VIR_ALLOC(def) < 0)
1297 1298
        return NULL;

1299
    def->target.type = VIR_STORAGE_TYPE_FILE;
1300

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

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

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

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

1325
        def->target.backingStore->type = VIR_STORAGE_TYPE_FILE;
1326

1327
        def->target.backingStore->path = backingStore;
1328 1329 1330
        backingStore = NULL;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1436
    VIR_STEAL_PTR(ret, def);
1437
    return ret;
1438 1439
}

1440

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

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

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

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

1471

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

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

    return ret;
}

1489

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

1498

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

1507

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

1521

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1613

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

1621
    options = virStorageVolOptionsForPoolType(pool->type);
1622 1623 1624
    if (options == NULL)
        return NULL;

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

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

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

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

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

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

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

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

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

1685 1686
    if (virBufferCheckError(&buf) < 0)
        goto cleanup;
1687

1688
    return virBufferContentAndReset(&buf);
1689

1690
 cleanup:
1691
    virBufferFreeAndReset(&buf);
1692 1693 1694 1695
    return NULL;
}


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


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

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

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

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

    if (virBufferCheckError(&buf) < 0)
1730
        return -1;
1731 1732

    if (!(xml = virBufferContentAndReset(&buf)))
1733
        return -1;
1734 1735

    if (virStoragePoolSaveXML(stateFile, def, xml))
1736
        return -1;
1737

1738
    return 0;
1739
}
1740 1741


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

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

1754
    return virStoragePoolSaveXML(configFile, def, xml);
1755 1756
}

1757

1758
virStoragePoolSourcePtr
1759
virStoragePoolSourceListNewSource(virStoragePoolSourceListPtr list)
1760 1761 1762
{
    virStoragePoolSourcePtr source;

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

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

    return source;
}

1772

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

1781
    options = virStoragePoolOptionsForPoolType(def->type);
1782 1783 1784
    if (options == NULL)
        return NULL;

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

    virBufferAddLit(&buf, "<sources>\n");
1793
    virBufferAdjustIndent(&buf, 2);
1794

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

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

1801 1802
    if (virBufferCheckError(&buf) < 0)
        goto cleanup;
1803 1804

    return virBufferContentAndReset(&buf);
1805

1806
 cleanup:
1807
    virBufferFreeAndReset(&buf);
1808
    return NULL;
1809
}