storage_conf.c 54.7 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
    virXMLNamespace ns;
144

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
      .volOptions = {
          .defaultFormat = VIR_STORAGE_FILE_RAW,
          .formatFromString = virStorageVolumeFormatFromString,
          .formatToString = virStorageFileFormatTypeToString,
      }
249
    },
250 251 252 253 254 255
    {.poolType = VIR_STORAGE_POOL_SHEEPDOG,
     .poolOptions = {
         .flags = (VIR_STORAGE_POOL_SOURCE_HOST |
                   VIR_STORAGE_POOL_SOURCE_NETWORK |
                   VIR_STORAGE_POOL_SOURCE_NAME),
     },
256
    },
257 258 259 260 261 262 263 264 265
    {.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,
266
         .lastFormat = VIR_STORAGE_FILE_LAST,
267 268 269 270
         .formatToString = virStorageFileFormatTypeToString,
         .formatFromString = virStorageVolumeFormatFromString,
     }
    },
271
    {.poolType = VIR_STORAGE_POOL_MPATH,
272
    },
273 274 275 276
    {.poolType = VIR_STORAGE_POOL_DISK,
     .poolOptions = {
         .flags = (VIR_STORAGE_POOL_SOURCE_DEVICE),
         .defaultFormat = VIR_STORAGE_POOL_DISK_UNKNOWN,
277
         .lastFormat = VIR_STORAGE_POOL_DISK_LAST,
278 279 280 281 282
         .formatFromString = virStoragePoolFormatDiskTypeFromString,
         .formatToString = virStoragePoolFormatDiskTypeToString,
     },
     .volOptions = {
         .defaultFormat = VIR_STORAGE_VOL_DISK_NONE,
283
         .lastFormat = VIR_STORAGE_VOL_DISK_LAST,
284 285 286
         .formatFromString = virStorageVolFormatDiskTypeFromString,
         .formatToString = virStorageVolFormatDiskTypeToString,
     },
R
Roman Bogorodskiy 已提交
287 288 289
    },
    {.poolType = VIR_STORAGE_POOL_ZFS,
     .poolOptions = {
290 291
         .flags = (VIR_STORAGE_POOL_SOURCE_NAME |
                   VIR_STORAGE_POOL_SOURCE_DEVICE),
R
Roman Bogorodskiy 已提交
292 293
     },
    },
294 295 296 297 298 299
    {.poolType = VIR_STORAGE_POOL_VSTORAGE,
     .poolOptions = {
        .flags = VIR_STORAGE_POOL_SOURCE_NAME,
     },
     .volOptions = {
        .defaultFormat = VIR_STORAGE_FILE_RAW,
300
        .lastFormat = VIR_STORAGE_FILE_LAST,
301 302 303 304
        .formatFromString = virStorageVolumeFormatFromString,
        .formatToString = virStorageFileFormatTypeToString,
     },
    },
305 306 307 308
};


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

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

321

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

331

332 333 334 335 336 337 338 339 340 341 342 343
/* 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,
344
                                             virXMLNamespacePtr ns)
345 346 347 348 349 350 351 352 353 354 355 356 357 358 359
{
    int ret = -1;
    virStoragePoolTypeInfoPtr backend = virStoragePoolTypeInfoLookup(type);

    if (!backend)
        goto cleanup;

    backend->poolOptions.ns = *ns;
    ret = 0;

 cleanup:
    return ret;
}


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


370 371 372 373 374 375 376 377 378
int
virStoragePoolOptionsFormatPool(virBufferPtr buf,
                                int type)
{
    virStoragePoolOptionsPtr poolOptions;

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

379
    if (!poolOptions->formatToString)
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 439 440 441 442 443
        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;
}


444
void
445 446
virStorageVolDefFree(virStorageVolDefPtr def)
{
447
    size_t i;
448 449 450 451

    if (!def)
        return;

452 453
    VIR_FREE(def->name);
    VIR_FREE(def->key);
454

455
    for (i = 0; i < def->source.nextent; i++)
456 457
        VIR_FREE(def->source.extents[i].path);
    VIR_FREE(def->source.extents);
458

459
    virStorageSourceClear(&def->target);
460
    VIR_FREE(def);
461 462
}

463

464 465 466 467 468 469 470
void
virStoragePoolSourceDeviceClear(virStoragePoolSourceDevicePtr dev)
{
    VIR_FREE(dev->freeExtents);
    VIR_FREE(dev->path);
}

471

472
void
473 474
virStoragePoolSourceClear(virStoragePoolSourcePtr source)
{
475
    size_t i;
476

477
    if (!source)
478 479
        return;

480
    for (i = 0; i < source->nhost; i++)
481 482 483
        VIR_FREE(source->hosts[i].name);
    VIR_FREE(source->hosts);

484 485
    for (i = 0; i < source->ndevice; i++)
        virStoragePoolSourceDeviceClear(&source->devices[i]);
486 487 488
    VIR_FREE(source->devices);
    VIR_FREE(source->dir);
    VIR_FREE(source->name);
489
    virStorageAdapterClear(&source->adapter);
490
    virStorageSourceInitiatorClear(&source->initiator);
491
    virStorageAuthDefFree(source->auth);
492 493
    VIR_FREE(source->vendor);
    VIR_FREE(source->product);
494 495
}

496

497 498 499 500 501 502 503
void
virStoragePoolSourceFree(virStoragePoolSourcePtr source)
{
    virStoragePoolSourceClear(source);
    VIR_FREE(source);
}

504

505
void
506 507
virStoragePoolDefFree(virStoragePoolDefPtr def)
{
508 509 510 511 512
    if (!def)
        return;

    VIR_FREE(def->name);

513
    virStoragePoolSourceClear(&def->source);
514

515 516
    VIR_FREE(def->target.path);
    VIR_FREE(def->target.perms.label);
517
    VIR_FREE(def->refresh);
518 519
    if (def->namespaceData && def->ns.free)
        (def->ns.free)(def->namespaceData);
520
    VIR_FREE(def);
521 522 523
}


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

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

546
    if ((options = virStoragePoolOptionsForPoolType(pool_type)) == NULL)
547 548
        goto cleanup;

549
    source->name = virXPathString("string(./name)", ctxt);
550
    if (pool_type == VIR_STORAGE_POOL_RBD && source->name == NULL) {
551
        virReportError(VIR_ERR_XML_ERROR, "%s",
552
                       _("element 'name' is mandatory for RBD pool"));
553 554
        goto cleanup;
    }
555 556

    if (options->formatFromString) {
557 558 559
        VIR_AUTOFREE(char *) format = NULL;

        format = virXPathString("string(./format/@type)", ctxt);
560 561 562 563 564 565
        if (format == NULL)
            source->format = options->defaultFormat;
        else
            source->format = options->formatFromString(format);

        if (source->format < 0) {
566
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
567
                           _("unknown pool format type %s"), format);
568 569 570 571
            goto cleanup;
        }
    }

572 573
    if ((n = virXPathNodeSet("./host", ctxt, &nodeset)) < 0)
        goto cleanup;
574

575 576
    if (n) {
        if (VIR_ALLOC_N(source->hosts, n) < 0)
577
            goto cleanup;
578
        source->nhost = n;
579

580
        for (i = 0; i < source->nhost; i++) {
581 582
            source->hosts[i].name = virXMLPropString(nodeset[i], "name");
            if (!source->hosts[i].name) {
583 584
                virReportError(VIR_ERR_XML_ERROR, "%s",
                               _("missing storage pool host name"));
585 586 587 588 589 590
                goto cleanup;
            }

            port = virXMLPropString(nodeset[i], "port");
            if (port) {
                if (virStrToLong_i(port, NULL, 10, &source->hosts[i].port) < 0) {
591 592 593
                    virReportError(VIR_ERR_XML_ERROR,
                                   _("Invalid port number: %s"),
                                   port);
594 595 596
                    goto cleanup;
                }
            }
597
            VIR_FREE(port);
598 599
        }
    }
600

601
    VIR_FREE(nodeset);
602 603

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

605
    nsource = virXPathNodeSet("./device", ctxt, &nodeset);
606 607 608
    if (nsource < 0)
        goto cleanup;

609
    for (i = 0; i < nsource; i++) {
610
        VIR_AUTOFREE(char *) partsep = NULL;
611 612 613 614 615 616
        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"));
617 618 619
            goto cleanup;
        }

620 621 622 623 624 625 626 627 628 629 630 631
        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;
            }
        }

632 633 634
        if (VIR_APPEND_ELEMENT(source->devices, source->ndevice, dev) < 0) {
            virStoragePoolSourceDeviceClear(&dev);
            goto cleanup;
635
        }
636

637 638
    }

639 640 641
    sourcedir = virXPathString("string(./dir/@path)", ctxt);
    if (sourcedir)
        source->dir = virFileSanitizePath(sourcedir);
642 643 644 645
    /* In gluster, a missing dir defaults to "/" */
    if (!source->dir && pool_type == VIR_STORAGE_POOL_GLUSTER &&
        VIR_STRDUP(source->dir, "/") < 0)
        goto cleanup;
646

647
    if ((adapternode = virXPathNode("./adapter", ctxt))) {
648
        if (virStorageAdapterParseXML(&source->adapter, adapternode, ctxt) < 0)
649 650
            goto cleanup;
    }
651

652
    if ((authnode = virXPathNode("./auth", ctxt))) {
653
        if (!(authdef = virStorageAuthDefParse(authnode, ctxt)))
654 655 656 657 658 659 660 661
            goto cleanup;

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

662
        VIR_STEAL_PTR(source->auth, authdef);
663
    }
664

665 666 667 668 669 670 671 672 673 674 675 676
    /* 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,
J
John Ferlan 已提交
677
                           _("storage pool protocol ver '%s' is malformed"),
678 679 680 681 682
                           ver);
            goto cleanup;
        }
    }

683 684 685
    source->vendor = virXPathString("string(./vendor/@name)", ctxt);
    source->product = virXPathString("string(./product/@name)", ctxt);

686
    ret = 0;
687
 cleanup:
688 689 690 691
    ctxt->node = relnode;

    return ret;
}
692

693

694
virStoragePoolSourcePtr
695
virStoragePoolDefParseSourceString(const char *srcSpec,
696 697 698 699 700
                                   int pool_type)
{
    xmlDocPtr doc = NULL;
    xmlNodePtr node = NULL;
    xmlXPathContextPtr xpath_ctxt = NULL;
701 702
    virStoragePoolSourcePtr ret = NULL;
    VIR_AUTOPTR(virStoragePoolSource) def = NULL;
703

704 705 706
    if (!(doc = virXMLParseStringCtxt(srcSpec,
                                      _("(storage_source_specification)"),
                                      &xpath_ctxt)))
707 708
        goto cleanup;

709
    if (VIR_ALLOC(def) < 0)
710 711
        goto cleanup;

712
    if (!(node = virXPathNode("/source", xpath_ctxt))) {
713 714
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("root element was not source"));
715 716 717
        goto cleanup;
    }

718
    if (virStoragePoolDefParseSource(xpath_ctxt, def, pool_type,
719 720 721
                                     node) < 0)
        goto cleanup;

722
    VIR_STEAL_PTR(ret, def);
723
 cleanup:
724 725 726 727 728
    xmlFreeDoc(doc);
    xmlXPathFreeContext(xpath_ctxt);

    return ret;
}
729

730

731
static int
732
virStorageDefParsePerms(xmlXPathContextPtr ctxt,
733
                        virStoragePermsPtr perms,
734
                        const char *permxpath)
735
{
736
    long long val;
737 738 739
    int ret = -1;
    xmlNodePtr relnode;
    xmlNodePtr node;
740
    VIR_AUTOFREE(char *) mode = NULL;
741

742
    node = virXPathNode(permxpath, ctxt);
743 744
    if (node == NULL) {
        /* Set default values if there is not <permissions> element */
745
        perms->mode = (mode_t) -1;
P
Philipp Hahn 已提交
746 747
        perms->uid = (uid_t) -1;
        perms->gid = (gid_t) -1;
748 749 750 751 752 753 754
        perms->label = NULL;
        return 0;
    }

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

755
    if ((mode = virXPathString("string(./mode)", ctxt))) {
756 757 758
        int tmp;

        if (virStrToLong_i(mode, NULL, 8, &tmp) < 0 || (tmp & ~0777)) {
759 760
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("malformed octal mode"));
761
            goto error;
762
        }
763
        perms->mode = tmp;
764 765
    } else {
        perms->mode = (mode_t) -1;
766 767
    }

768
    if (virXPathNode("./owner", ctxt) == NULL) {
P
Philipp Hahn 已提交
769
        perms->uid = (uid_t) -1;
770
    } else {
771
        /* We previously could output -1, so continue to parse it */
772
        if (virXPathLongLong("number(./owner)", ctxt, &val) < 0 ||
773 774
            ((uid_t)val != val &&
             val != -1)) {
775 776
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("malformed owner element"));
777
            goto error;
778
        }
779 780

        perms->uid = val;
781 782
    }

783
    if (virXPathNode("./group", ctxt) == NULL) {
P
Philipp Hahn 已提交
784
        perms->gid = (gid_t) -1;
785
    } else {
786
        /* We previously could output -1, so continue to parse it */
787
        if (virXPathLongLong("number(./group)", ctxt, &val) < 0 ||
788 789
            ((gid_t) val != val &&
             val != -1)) {
790 791
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("malformed group element"));
792
            goto error;
793
        }
794
        perms->gid = val;
795 796 797
    }

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

800
    ret = 0;
801
 error:
802 803
    ctxt->node = relnode;
    return ret;
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 844 845 846 847 848 849 850 851
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 已提交
852
virStoragePoolDefPtr
853 854
virStoragePoolDefParseXML(xmlXPathContextPtr ctxt)
{
855
    virStoragePoolOptionsPtr options;
856
    virStoragePoolDefPtr ret = NULL;
857
    xmlNodePtr source_node;
858
    VIR_AUTOPTR(virStoragePoolDef) def = NULL;
859 860 861
    VIR_AUTOFREE(char *) type = NULL;
    VIR_AUTOFREE(char *) uuid = NULL;
    VIR_AUTOFREE(char *) target_path = NULL;
862

863
    if (VIR_ALLOC(def) < 0)
864 865
        return NULL;

866
    type = virXPathString("string(./@type)", ctxt);
867 868 869
    if (type == NULL) {
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("storage pool missing type attribute"));
870
        return NULL;
871 872
    }

873
    if ((def->type = virStoragePoolTypeFromString(type)) < 0) {
874
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
875
                       _("unknown storage pool type %s"), type);
876
        return NULL;
877 878
    }

879
    if ((options = virStoragePoolOptionsForPoolType(def->type)) == NULL)
880
        return NULL;
881

882
    source_node = virXPathNode("./source", ctxt);
883
    if (source_node) {
884
        if (virStoragePoolDefParseSource(ctxt, &def->source, def->type,
885
                                         source_node) < 0)
886
            return NULL;
887 888
    } else {
        if (options->formatFromString)
889
            def->source.format = options->defaultFormat;
890 891
    }

892 893
    def->name = virXPathString("string(./name)", ctxt);
    if (def->name == NULL &&
894
        options->flags & VIR_STORAGE_POOL_SOURCE_NAME &&
895
        VIR_STRDUP(def->name, def->source.name) < 0)
896 897
        return NULL;

898
    if (def->name == NULL) {
899 900
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("missing pool source name element"));
901
        return NULL;
902 903
    }

904
    if (strchr(def->name, '/')) {
905
        virReportError(VIR_ERR_XML_ERROR,
906
                       _("name %s cannot contain '/'"), def->name);
907
        return NULL;
908 909
    }

910
    uuid = virXPathString("string(./uuid)", ctxt);
911
    if (uuid == NULL) {
912
        if (virUUIDGenerate(def->uuid) < 0) {
913 914
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("unable to generate uuid"));
915
            return NULL;
916 917
        }
    } else {
918
        if (virUUIDParse(uuid, def->uuid) < 0) {
919 920
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("malformed uuid element"));
921
            return NULL;
922 923 924
        }
    }

925
    if (options->flags & VIR_STORAGE_POOL_SOURCE_HOST) {
926
        if (!def->source.nhost) {
927
            virReportError(VIR_ERR_XML_ERROR, "%s",
928
                           _("missing storage pool source host name"));
929
            return NULL;
930 931 932
        }
    }

933
    if (options->flags & VIR_STORAGE_POOL_SOURCE_DIR) {
934
        if (!def->source.dir) {
935 936
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("missing storage pool source path"));
937
            return NULL;
938 939
        }
    }
940
    if (options->flags & VIR_STORAGE_POOL_SOURCE_NAME) {
941
        if (def->source.name == NULL) {
942
            /* source name defaults to pool name */
943
            if (VIR_STRDUP(def->source.name, def->name) < 0)
944
                return NULL;
945 946
        }
    }
947

948
    if ((options->flags & VIR_STORAGE_POOL_SOURCE_ADAPTER) &&
949
        (virStorageAdapterValidate(&def->source.adapter)) < 0)
950
            return NULL;
951

952 953
    /* If DEVICE is the only source type, then its required */
    if (options->flags == VIR_STORAGE_POOL_SOURCE_DEVICE) {
954
        if (!def->source.ndevice) {
955 956
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("missing storage pool source device name"));
957
            return NULL;
958 959 960
        }
    }

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

982
        if (virStorageDefParsePerms(ctxt, &def->target.perms,
983
                                    "./target/permissions") < 0)
984
            return NULL;
985
    }
986

987 988
    if (def->type == VIR_STORAGE_POOL_ISCSI_DIRECT &&
        !def->source.initiator.iqn) {
989 990
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("missing initiator IQN"));
991
        return NULL;
992 993
    }

994 995 996
    if (virStoragePoolDefRefreshParse(ctxt, def) < 0)
        return NULL;

997 998
    /* Make a copy of all the callback pointers here for easier use,
     * especially during the virStoragePoolSourceClear method */
999
    def->ns = options->ns;
1000 1001 1002 1003
    if (def->ns.parse) {
        if ((def->ns.parse)(ctxt, &def->namespaceData) < 0)
            return NULL;
    }
1004

1005
    VIR_STEAL_PTR(ret, def);
1006
    return ret;
1007 1008
}

1009

1010
virStoragePoolDefPtr
1011
virStoragePoolDefParseNode(xmlDocPtr xml,
1012 1013
                           xmlNodePtr root)
{
1014 1015 1016
    xmlXPathContextPtr ctxt = NULL;
    virStoragePoolDefPtr def = NULL;

1017
    if (!virXMLNodeNameEqual(root, "pool")) {
1018
        virReportError(VIR_ERR_XML_ERROR,
1019 1020 1021
                       _("unexpected root element <%s>, "
                         "expecting <pool>"),
                       root->name);
1022 1023 1024 1025 1026
        goto cleanup;
    }

    ctxt = xmlXPathNewContext(xml);
    if (ctxt == NULL) {
1027
        virReportOOMError();
1028 1029 1030 1031
        goto cleanup;
    }

    ctxt->node = root;
1032
    def = virStoragePoolDefParseXML(ctxt);
1033
 cleanup:
1034 1035 1036 1037
    xmlXPathFreeContext(ctxt);
    return def;
}

1038

1039
static virStoragePoolDefPtr
1040
virStoragePoolDefParse(const char *xmlStr,
1041 1042
                       const char *filename)
{
1043
    virStoragePoolDefPtr ret = NULL;
J
Jiri Denemark 已提交
1044
    xmlDocPtr xml;
1045

1046
    if ((xml = virXMLParse(filename, xmlStr, _("(storage_pool_definition)")))) {
J
Jiri Denemark 已提交
1047 1048
        ret = virStoragePoolDefParseNode(xml, xmlDocGetRootElement(xml));
        xmlFreeDoc(xml);
1049 1050
    }

1051 1052 1053
    return ret;
}

1054

1055
virStoragePoolDefPtr
1056
virStoragePoolDefParseString(const char *xmlStr)
1057
{
1058
    return virStoragePoolDefParse(xmlStr, NULL);
1059 1060
}

1061

1062
virStoragePoolDefPtr
1063
virStoragePoolDefParseFile(const char *filename)
1064
{
1065
    return virStoragePoolDefParse(NULL, filename);
1066 1067
}

1068

1069
static int
1070
virStoragePoolSourceFormat(virBufferPtr buf,
1071
                           virStoragePoolOptionsPtr options,
1072 1073
                           virStoragePoolSourcePtr src)
{
1074
    size_t i, j;
1075

1076 1077 1078
    virBufferAddLit(buf, "<source>\n");
    virBufferAdjustIndent(buf, 2);

1079 1080
    if ((options->flags & VIR_STORAGE_POOL_SOURCE_HOST) && src->nhost) {
        for (i = 0; i < src->nhost; i++) {
1081
            virBufferEscapeString(buf, "<host name='%s'",
1082
                                  src->hosts[i].name);
1083 1084 1085 1086
            if (src->hosts[i].port)
                virBufferAsprintf(buf, " port='%d'", src->hosts[i].port);
            virBufferAddLit(buf, "/>\n");
        }
1087
    }
1088

1089
    if ((options->flags & VIR_STORAGE_POOL_SOURCE_DEVICE) &&
1090
        src->ndevice) {
1091
        for (i = 0; i < src->ndevice; i++) {
1092 1093 1094 1095 1096 1097 1098
            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));
            }
1099
            if (src->devices[i].nfreeExtent) {
1100
                virBufferAddLit(buf, ">\n");
1101
                virBufferAdjustIndent(buf, 2);
1102
                for (j = 0; j < src->devices[i].nfreeExtent; j++) {
1103
                    virBufferAsprintf(buf, "<freeExtent start='%llu' end='%llu'/>\n",
1104 1105 1106
                                      src->devices[i].freeExtents[j].start,
                                      src->devices[i].freeExtents[j].end);
                }
1107 1108
                virBufferAdjustIndent(buf, -2);
                virBufferAddLit(buf, "</device>\n");
1109
            } else {
1110
                virBufferAddLit(buf, "/>\n");
1111
            }
1112 1113
        }
    }
1114

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

1118
    if ((options->flags & VIR_STORAGE_POOL_SOURCE_ADAPTER) &&
1119 1120 1121
        (src->adapter.type == VIR_STORAGE_ADAPTER_TYPE_FC_HOST ||
         src->adapter.type == VIR_STORAGE_ADAPTER_TYPE_SCSI_HOST))
        virStorageAdapterFormat(buf, &src->adapter);
1122

1123
    if (options->flags & VIR_STORAGE_POOL_SOURCE_NAME)
1124
        virBufferEscapeString(buf, "<name>%s</name>\n", src->name);
1125

1126 1127
    if (options->flags & VIR_STORAGE_POOL_SOURCE_INITIATOR_IQN)
        virStorageSourceInitiatorFormatXML(&src->initiator, buf);
D
David Allan 已提交
1128

1129 1130 1131
    if (options->formatToString) {
        const char *format = (options->formatToString)(src->format);
        if (!format) {
1132 1133 1134
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("unknown pool format number %d"),
                           src->format);
1135 1136
            return -1;
        }
1137
        virBufferAsprintf(buf, "<format type='%s'/>\n", format);
1138 1139
    }

1140 1141
    if (src->auth)
        virStorageAuthDefFormat(buf, src->auth);
1142

1143 1144 1145
    if (src->protocolVer)
        virBufferAsprintf(buf, "<protocol ver='%u'/>\n", src->protocolVer);

1146 1147
    virBufferEscapeString(buf, "<vendor name='%s'/>\n", src->vendor);
    virBufferEscapeString(buf, "<product name='%s'/>\n", src->product);
1148

1149 1150
    virBufferAdjustIndent(buf, -2);
    virBufferAddLit(buf, "</source>\n");
1151 1152 1153
    return 0;
}

1154

1155 1156 1157
static int
virStoragePoolDefFormatBuf(virBufferPtr buf,
                           virStoragePoolDefPtr def)
1158
{
1159
    virStoragePoolOptionsPtr options;
1160
    char uuid[VIR_UUID_STRING_BUFLEN];
1161
    const char *type;
1162

1163
    options = virStoragePoolOptionsForPoolType(def->type);
1164
    if (options == NULL)
1165
        return -1;
1166

1167
    type = virStoragePoolTypeToString(def->type);
1168
    if (!type) {
1169 1170
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("unexpected pool type"));
1171
        return -1;
1172
    }
1173 1174 1175 1176
    virBufferAsprintf(buf, "<pool type='%s'", type);
    if (def->namespaceData && def->ns.href)
        virBufferAsprintf(buf, " %s", (def->ns.href)());
    virBufferAddLit(buf, ">\n");
1177 1178
    virBufferAdjustIndent(buf, 2);
    virBufferEscapeString(buf, "<name>%s</name>\n", def->name);
1179 1180

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

1183
    virBufferAsprintf(buf, "<capacity unit='bytes'>%llu</capacity>\n",
1184
                      def->capacity);
1185
    virBufferAsprintf(buf, "<allocation unit='bytes'>%llu</allocation>\n",
1186
                      def->allocation);
1187
    virBufferAsprintf(buf, "<available unit='bytes'>%llu</available>\n",
1188
                      def->available);
1189

1190 1191
    if (virStoragePoolSourceFormat(buf, options, &def->source) < 0)
        return -1;
1192

1193
    /* RBD, Sheepdog, Gluster and Iscsi-direct devices are not local block devs nor
1194
     * files, so they don't have a target */
1195
    if (def->type != VIR_STORAGE_POOL_RBD &&
1196
        def->type != VIR_STORAGE_POOL_SHEEPDOG &&
1197 1198
        def->type != VIR_STORAGE_POOL_GLUSTER &&
        def->type != VIR_STORAGE_POOL_ISCSI_DIRECT) {
1199 1200
        virBufferAddLit(buf, "<target>\n");
        virBufferAdjustIndent(buf, 2);
1201

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

1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224
        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");
        }
1225

1226 1227
        virBufferAdjustIndent(buf, -2);
        virBufferAddLit(buf, "</target>\n");
1228
    }
1229

1230 1231
    virStoragePoolDefRefreshFormat(buf, def->refresh);

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

1237 1238 1239 1240 1241 1242
    virBufferAdjustIndent(buf, -2);
    virBufferAddLit(buf, "</pool>\n");

    return 0;
}

1243

1244 1245 1246 1247 1248 1249 1250
char *
virStoragePoolDefFormat(virStoragePoolDefPtr def)
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;

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

1252
    if (virBufferCheckError(&buf) < 0)
1253
        goto error;
1254

1255
    return virBufferContentAndReset(&buf);
1256

1257
 error:
1258
    virBufferFreeAndReset(&buf);
1259 1260 1261 1262 1263
    return NULL;
}


static int
1264
virStorageSize(const char *unit,
1265
               const char *val,
1266 1267
               unsigned long long *ret)
{
J
Ján Tomko 已提交
1268
    if (virStrToLong_ullp(val, NULL, 10, ret) < 0) {
1269 1270
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("malformed capacity element"));
1271 1272
        return -1;
    }
1273 1274 1275 1276
    /* 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;
1277 1278 1279 1280

    return 0;
}

1281

1282
static virStorageVolDefPtr
1283
virStorageVolDefParseXML(virStoragePoolDefPtr pool,
1284 1285
                         xmlXPathContextPtr ctxt,
                         unsigned int flags)
1286
{
1287
    virStorageVolDefPtr ret = NULL;
1288
    virStorageVolOptionsPtr options;
1289
    xmlNodePtr node;
1290 1291
    size_t i;
    int n;
1292
    VIR_AUTOPTR(virStorageVolDef) def = NULL;
1293 1294 1295 1296 1297 1298
    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;
1299

1300 1301
    virCheckFlags(VIR_VOL_XML_PARSE_NO_CAPACITY |
                  VIR_VOL_XML_PARSE_OPT_CAPACITY, NULL);
1302

1303
    options = virStorageVolOptionsForPoolType(pool->type);
1304 1305 1306
    if (options == NULL)
        return NULL;

1307
    if (VIR_ALLOC(def) < 0)
1308 1309
        return NULL;

1310
    def->target.type = VIR_STORAGE_TYPE_FILE;
1311

1312 1313
    def->name = virXPathString("string(./name)", ctxt);
    if (def->name == NULL) {
1314 1315
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("missing volume name element"));
1316
        return NULL;
1317 1318
    }

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

1322 1323 1324
    /* Technically overridden by pool refresh, but useful for unit tests */
    type = virXPathString("string(./@type)", ctxt);
    if (type) {
1325
        if ((def->type = virStorageVolTypeFromString(type)) < 0) {
1326
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1327
                           _("unknown volume type '%s'"), type);
1328
            return NULL;
1329 1330 1331
        }
    }

1332
    if ((backingStore = virXPathString("string(./backingStore/path)", ctxt))) {
1333
        if (!(def->target.backingStore = virStorageSourceNew()))
1334
            return NULL;
1335

1336
        def->target.backingStore->type = VIR_STORAGE_TYPE_FILE;
1337

1338
        def->target.backingStore->path = backingStore;
1339 1340 1341
        backingStore = NULL;

        if (options->formatFromString) {
1342 1343 1344
            VIR_AUTOFREE(char *) format = NULL;

            format = virXPathString("string(./backingStore/format/@type)", ctxt);
1345
            if (format == NULL)
1346
                def->target.backingStore->format = options->defaultFormat;
1347
            else
1348
                def->target.backingStore->format = (options->formatFromString)(format);
1349

1350
            if (def->target.backingStore->format < 0) {
1351 1352
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("unknown volume format type %s"), format);
1353
                return NULL;
1354 1355 1356
            }
        }

1357
        if (VIR_ALLOC(def->target.backingStore->perms) < 0)
1358
            return NULL;
1359
        if (virStorageDefParsePerms(ctxt, def->target.backingStore->perms,
1360
                                    "./backingStore/permissions") < 0)
1361
            return NULL;
1362 1363
    }

1364 1365
    capacity = virXPathString("string(./capacity)", ctxt);
    unit = virXPathString("string(./capacity/@unit)", ctxt);
1366
    if (capacity) {
1367
        if (virStorageSize(unit, capacity, &def->target.capacity) < 0)
1368
            return NULL;
1369
    } else if (!(flags & VIR_VOL_XML_PARSE_NO_CAPACITY) &&
1370
               !((flags & VIR_VOL_XML_PARSE_OPT_CAPACITY) &&
1371
                 virStorageSourceHasBacking(&def->target))) {
1372
        virReportError(VIR_ERR_XML_ERROR, "%s", _("missing capacity element"));
1373
        return NULL;
1374
    }
1375
    VIR_FREE(unit);
1376

1377
    allocation = virXPathString("string(./allocation)", ctxt);
1378
    if (allocation) {
1379
        unit = virXPathString("string(./allocation/@unit)", ctxt);
1380
        if (virStorageSize(unit, allocation, &def->target.allocation) < 0)
1381
            return NULL;
1382
        def->target.has_allocation = true;
1383
    } else {
1384
        def->target.allocation = def->target.capacity;
1385 1386
    }

1387
    def->target.path = virXPathString("string(./target/path)", ctxt);
1388
    if (options->formatFromString) {
1389 1390 1391
        VIR_AUTOFREE(char *) format = NULL;

        format = virXPathString("string(./target/format/@type)", ctxt);
1392
        if (format == NULL)
1393
            def->target.format = options->defaultFormat;
1394
        else
1395
            def->target.format = (options->formatFromString)(format);
1396

1397
        if (def->target.format < 0) {
1398
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1399
                           _("unknown volume format type %s"), format);
1400
            return NULL;
1401 1402 1403
        }
    }

1404
    if (VIR_ALLOC(def->target.perms) < 0)
1405
        return NULL;
1406
    if (virStorageDefParsePerms(ctxt, def->target.perms,
1407
                                "./target/permissions") < 0)
1408
        return NULL;
1409

1410
    node = virXPathNode("./target/encryption", ctxt);
1411
    if (node != NULL) {
1412 1413
        def->target.encryption = virStorageEncryptionParseNode(node, ctxt);
        if (def->target.encryption == NULL)
1414
            return NULL;
1415 1416
    }

1417 1418
    def->target.compat = virXPathString("string(./target/compat)", ctxt);
    if (virStorageFileCheckCompat(def->target.compat) < 0)
1419
        return NULL;
1420

C
Chunyan Liu 已提交
1421
    if (virXPathNode("./target/nocow", ctxt))
1422
        def->target.nocow = true;
C
Chunyan Liu 已提交
1423

1424
    if (virXPathNode("./target/features", ctxt)) {
1425
        if ((n = virXPathNodeSet("./target/features/*", ctxt, &nodes)) < 0)
1426
            return NULL;
1427

1428
        if (!def->target.compat && VIR_STRDUP(def->target.compat, "1.1") < 0)
1429
            return NULL;
1430

1431
        if (!(def->target.features = virBitmapNew(VIR_STORAGE_FILE_FEATURE_LAST)))
1432
            return NULL;
1433 1434

        for (i = 0; i < n; i++) {
1435
            int f = virStorageFileFeatureTypeFromString((const char*)nodes[i]->name);
1436 1437

            if (f < 0) {
1438
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unsupported feature %s"),
1439
                               (const char*)nodes[i]->name);
1440
                return NULL;
1441
            }
1442
            ignore_value(virBitmapSetBit(def->target.features, f));
1443 1444 1445 1446
        }
        VIR_FREE(nodes);
    }

1447
    VIR_STEAL_PTR(ret, def);
1448
    return ret;
1449 1450
}

1451

1452
virStorageVolDefPtr
1453
virStorageVolDefParseNode(virStoragePoolDefPtr pool,
1454
                          xmlDocPtr xml,
1455 1456
                          xmlNodePtr root,
                          unsigned int flags)
1457
{
1458 1459 1460
    xmlXPathContextPtr ctxt = NULL;
    virStorageVolDefPtr def = NULL;

1461
    if (!virXMLNodeNameEqual(root, "volume")) {
1462
        virReportError(VIR_ERR_XML_ERROR,
1463 1464 1465
                       _("unexpected root element <%s>, "
                         "expecting <volume>"),
                       root->name);
1466 1467 1468 1469 1470
        goto cleanup;
    }

    ctxt = xmlXPathNewContext(xml);
    if (ctxt == NULL) {
1471
        virReportOOMError();
1472 1473 1474 1475
        goto cleanup;
    }

    ctxt->node = root;
1476
    def = virStorageVolDefParseXML(pool, ctxt, flags);
1477
 cleanup:
1478 1479 1480 1481
    xmlXPathFreeContext(ctxt);
    return def;
}

1482

1483
static virStorageVolDefPtr
1484
virStorageVolDefParse(virStoragePoolDefPtr pool,
1485
                      const char *xmlStr,
1486 1487
                      const char *filename,
                      unsigned int flags)
1488
{
1489
    virStorageVolDefPtr ret = NULL;
J
Jiri Denemark 已提交
1490
    xmlDocPtr xml;
1491

1492
    if ((xml = virXMLParse(filename, xmlStr, _("(storage_volume_definition)")))) {
1493
        ret = virStorageVolDefParseNode(pool, xml, xmlDocGetRootElement(xml), flags);
J
Jiri Denemark 已提交
1494
        xmlFreeDoc(xml);
1495 1496 1497 1498 1499
    }

    return ret;
}

1500

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

1509

1510
virStorageVolDefPtr
1511
virStorageVolDefParseFile(virStoragePoolDefPtr pool,
1512 1513
                          const char *filename,
                          unsigned int flags)
1514
{
1515
    return virStorageVolDefParse(pool, NULL, filename, flags);
1516
}
1517

1518

1519 1520 1521 1522 1523 1524
static void
virStorageVolTimestampFormat(virBufferPtr buf, const char *name,
                             struct timespec *ts)
{
    if (ts->tv_nsec < 0)
        return;
1525
    virBufferAsprintf(buf, "<%s>%llu", name,
1526 1527 1528 1529 1530 1531
                      (unsigned long long) ts->tv_sec);
    if (ts->tv_nsec)
       virBufferAsprintf(buf, ".%09ld", ts->tv_nsec);
    virBufferAsprintf(buf, "</%s>\n", name);
}

1532

1533
static int
1534
virStorageVolTargetDefFormat(virStorageVolOptionsPtr options,
1535
                             virBufferPtr buf,
1536
                             virStorageSourcePtr def,
1537 1538
                             const char *type)
{
1539 1540
    virBufferAsprintf(buf, "<%s>\n", type);
    virBufferAdjustIndent(buf, 2);
1541

1542
    virBufferEscapeString(buf, "<path>%s</path>\n", def->path);
1543 1544 1545 1546

    if (options->formatToString) {
        const char *format = (options->formatToString)(def->format);
        if (!format) {
1547 1548 1549
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("unknown volume format number %d"),
                           def->format);
1550 1551
            return -1;
        }
1552
        virBufferAsprintf(buf, "<format type='%s'/>\n", format);
1553 1554
    }

1555 1556 1557 1558 1559
    if (def->perms &&
        (def->perms->mode != (mode_t) -1 ||
         def->perms->uid != (uid_t) -1 ||
         def->perms->gid != (gid_t) -1 ||
         def->perms->label)) {
1560 1561
        virBufferAddLit(buf, "<permissions>\n");
        virBufferAdjustIndent(buf, 2);
1562

1563 1564 1565
        if (def->perms->mode != (mode_t) -1)
            virBufferAsprintf(buf, "<mode>0%o</mode>\n",
                              def->perms->mode);
1566 1567 1568 1569 1570 1571
        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);
1572

1573 1574
        virBufferEscapeString(buf, "<label>%s</label>\n",
                              def->perms->label);
1575

1576 1577 1578
        virBufferAdjustIndent(buf, -2);
        virBufferAddLit(buf, "</permissions>\n");
    }
1579

1580
    if (def->timestamps) {
1581 1582
        virBufferAddLit(buf, "<timestamps>\n");
        virBufferAdjustIndent(buf, 2);
1583 1584 1585 1586
        virStorageVolTimestampFormat(buf, "atime", &def->timestamps->atime);
        virStorageVolTimestampFormat(buf, "mtime", &def->timestamps->mtime);
        virStorageVolTimestampFormat(buf, "ctime", &def->timestamps->ctime);
        virStorageVolTimestampFormat(buf, "btime", &def->timestamps->btime);
1587 1588
        virBufferAdjustIndent(buf, -2);
        virBufferAddLit(buf, "</timestamps>\n");
1589 1590
    }

1591 1592
    if (def->encryption &&
        virStorageEncryptionFormat(buf, def->encryption) < 0)
1593
            return -1;
1594

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

1597
    if (def->features) {
1598
        size_t i;
1599 1600
        bool empty = virBitmapIsAllClear(def->features);

1601 1602 1603 1604 1605 1606
        if (empty) {
            virBufferAddLit(buf, "<features/>\n");
        } else {
            virBufferAddLit(buf, "<features>\n");
            virBufferAdjustIndent(buf, 2);
        }
1607 1608

        for (i = 0; i < VIR_STORAGE_FILE_FEATURE_LAST; i++) {
J
Ján Tomko 已提交
1609
            if (virBitmapIsBitSet(def->features, i))
1610
                virBufferAsprintf(buf, "<%s/>\n",
1611
                                  virStorageFileFeatureTypeToString(i));
1612
        }
1613 1614 1615 1616
        if (!empty) {
            virBufferAdjustIndent(buf, -2);
            virBufferAddLit(buf, "</features>\n");
        }
1617 1618
    }

1619 1620
    virBufferAdjustIndent(buf, -2);
    virBufferAsprintf(buf, "</%s>\n", type);
1621 1622
    return 0;
}
1623

1624

1625
char *
1626
virStorageVolDefFormat(virStoragePoolDefPtr pool,
1627 1628
                       virStorageVolDefPtr def)
{
1629
    virStorageVolOptionsPtr options;
1630
    virBuffer buf = VIR_BUFFER_INITIALIZER;
1631

1632
    options = virStorageVolOptionsForPoolType(pool->type);
1633 1634 1635
    if (options == NULL)
        return NULL;

1636 1637
    virBufferAsprintf(&buf, "<volume type='%s'>\n",
                      virStorageVolTypeToString(def->type));
1638 1639 1640 1641 1642 1643
    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);
1644 1645

    if (def->source.nextent) {
1646
        size_t i;
1647
        const char *thispath = NULL;
1648
        for (i = 0; i < def->source.nextent; i++) {
1649 1650 1651
            if (thispath == NULL ||
                STRNEQ(thispath, def->source.extents[i].path)) {
                if (thispath != NULL)
1652
                    virBufferAddLit(&buf, "</device>\n");
1653

1654
                virBufferEscapeString(&buf, "<device path='%s'>\n",
1655
                                      def->source.extents[i].path);
1656 1657
            }

1658 1659
            virBufferAdjustIndent(&buf, 2);
            virBufferAsprintf(&buf, "<extent start='%llu' end='%llu'/>\n",
1660 1661
                              def->source.extents[i].start,
                              def->source.extents[i].end);
1662
            virBufferAdjustIndent(&buf, -2);
1663 1664 1665
            thispath = def->source.extents[i].path;
        }
        if (thispath != NULL)
1666
            virBufferAddLit(&buf, "</device>\n");
1667 1668
    }

1669 1670 1671 1672
    virBufferAdjustIndent(&buf, -2);
    virBufferAddLit(&buf, "</source>\n");

    virBufferAsprintf(&buf, "<capacity unit='bytes'>%llu</capacity>\n",
1673
                      def->target.capacity);
1674
    virBufferAsprintf(&buf, "<allocation unit='bytes'>%llu</allocation>\n",
1675
                      def->target.allocation);
1676 1677 1678 1679 1680 1681
    /* 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);
1682

1683
    if (virStorageVolTargetDefFormat(options, &buf,
1684 1685
                                     &def->target, "target") < 0)
        goto cleanup;
1686

1687
    if (virStorageSourceHasBacking(&def->target) &&
1688
        virStorageVolTargetDefFormat(options, &buf,
1689 1690
                                     def->target.backingStore,
                                     "backingStore") < 0)
1691
        goto cleanup;
1692

1693
    virBufferAdjustIndent(&buf, -2);
E
Eric Blake 已提交
1694
    virBufferAddLit(&buf, "</volume>\n");
1695

1696 1697
    if (virBufferCheckError(&buf) < 0)
        goto cleanup;
1698

1699
    return virBufferContentAndReset(&buf);
1700

1701
 cleanup:
1702
    virBufferFreeAndReset(&buf);
1703 1704 1705 1706
    return NULL;
}


1707 1708 1709 1710
static int
virStoragePoolSaveXML(const char *path,
                      virStoragePoolDefPtr def,
                      const char *xml)
1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721
{
    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;
}
1722 1723 1724 1725 1726 1727 1728


int
virStoragePoolSaveState(const char *stateFile,
                        virStoragePoolDefPtr def)
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;
1729
    VIR_AUTOFREE(char *) xml = NULL;
1730 1731 1732 1733 1734

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

    if (virStoragePoolDefFormatBuf(&buf, def) < 0)
1735
        return -1;
1736 1737 1738 1739 1740

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

    if (virBufferCheckError(&buf) < 0)
1741
        return -1;
1742 1743

    if (!(xml = virBufferContentAndReset(&buf)))
1744
        return -1;
1745 1746

    if (virStoragePoolSaveXML(stateFile, def, xml))
1747
        return -1;
1748

1749
    return 0;
1750
}
1751 1752


1753
int
1754
virStoragePoolSaveConfig(const char *configFile,
1755 1756
                         virStoragePoolDefPtr def)
{
1757
    VIR_AUTOFREE(char *) xml = NULL;
1758

1759 1760 1761 1762 1763 1764
    if (!(xml = virStoragePoolDefFormat(def))) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("failed to generate XML"));
        return -1;
    }

1765
    return virStoragePoolSaveXML(configFile, def, xml);
1766 1767
}

1768

1769
virStoragePoolSourcePtr
1770
virStoragePoolSourceListNewSource(virStoragePoolSourceListPtr list)
1771 1772 1773
{
    virStoragePoolSourcePtr source;

1774
    if (VIR_REALLOC_N(list->sources, list->nsources + 1) < 0)
1775 1776 1777 1778 1779 1780 1781 1782
        return NULL;

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

    return source;
}

1783

1784 1785
char *
virStoragePoolSourceListFormat(virStoragePoolSourceListPtr def)
1786
{
1787
    virStoragePoolOptionsPtr options;
1788
    virBuffer buf = VIR_BUFFER_INITIALIZER;
1789
    const char *type;
1790
    size_t i;
1791

1792
    options = virStoragePoolOptionsForPoolType(def->type);
1793 1794 1795
    if (options == NULL)
        return NULL;

1796
    type = virStoragePoolTypeToString(def->type);
1797
    if (!type) {
1798 1799
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("unexpected pool type"));
1800 1801 1802 1803
        goto cleanup;
    }

    virBufferAddLit(&buf, "<sources>\n");
1804
    virBufferAdjustIndent(&buf, 2);
1805

1806
    for (i = 0; i < def->nsources; i++)
1807
        virStoragePoolSourceFormat(&buf, options, &def->sources[i]);
1808

1809
    virBufferAdjustIndent(&buf, -2);
1810 1811
    virBufferAddLit(&buf, "</sources>\n");

1812 1813
    if (virBufferCheckError(&buf) < 0)
        goto cleanup;
1814 1815

    return virBufferContentAndReset(&buf);
1816

1817
 cleanup:
1818
    virBufferFreeAndReset(&buf);
1819
    return NULL;
1820
}