storage_conf.c 49.8 KB
Newer Older
1 2 3
/*
 * storage_conf.c: config handling for storage driver
 *
E
Eric Blake 已提交
4
 * Copyright (C) 2006-2011 Red Hat, Inc.
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
 * 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
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
 *
 * Author: Daniel P. Berrange <berrange@redhat.com>
 */

#include <config.h>

#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>

36
#include "virterror_internal.h"
37
#include "datatypes.h"
38
#include "storage_conf.h"
39
#include "storage_file.h"
40

41 42 43 44
#include "xml.h"
#include "uuid.h"
#include "buf.h"
#include "util.h"
45
#include "memory.h"
E
Eric Blake 已提交
46
#include "virfile.h"
47

48 49
#define VIR_FROM_THIS VIR_FROM_STORAGE

50

51 52 53 54
VIR_ENUM_IMPL(virStoragePool,
              VIR_STORAGE_POOL_LAST,
              "dir", "fs", "netfs",
              "logical", "disk", "iscsi",
D
Dave Allan 已提交
55
              "scsi", "mpath")
56 57 58 59 60

VIR_ENUM_IMPL(virStoragePoolFormatFileSystem,
              VIR_STORAGE_POOL_FS_LAST,
              "auto", "ext2", "ext3",
              "ext4", "ufs", "iso9660", "udf",
J
Jim Fehlig 已提交
61
              "gfs", "gfs2", "vfat", "hfs+", "xfs", "ocfs2")
62 63 64

VIR_ENUM_IMPL(virStoragePoolFormatFileSystemNet,
              VIR_STORAGE_POOL_NETFS_LAST,
65
              "auto", "nfs", "glusterfs", "cifs")
66 67 68 69

VIR_ENUM_IMPL(virStoragePoolFormatDisk,
              VIR_STORAGE_POOL_DISK_LAST,
              "unknown", "dos", "dvh", "gpt",
70
              "mac", "bsd", "pc98", "sun", "lvm2")
71 72 73

VIR_ENUM_IMPL(virStoragePoolFormatLogical,
              VIR_STORAGE_POOL_LOGICAL_LAST,
74
              "unknown", "lvm2")
75 76 77 78 79 80 81


VIR_ENUM_IMPL(virStorageVolFormatDisk,
              VIR_STORAGE_VOL_DISK_LAST,
              "none", "linux", "fat16",
              "fat32", "linux-swap",
              "linux-lvm", "linux-raid",
82
              "extended")
83

84 85
VIR_ENUM_IMPL(virStoragePartedFsType,
              VIR_STORAGE_PARTED_FS_TYPE_LAST,
86
              "ext2", "ext2", "fat16",
87 88 89
              "fat32", "linux-swap",
              "ext2", "ext2",
              "extended")
90 91 92 93 94 95 96 97 98 99

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 {
100
    int defaultFormat;
101 102 103 104 105 106
    virStorageVolFormatToString formatToString;
    virStorageVolFormatFromString formatFromString;
};

/* Flags to indicate mandatory components in the pool source */
enum {
D
David Allan 已提交
107 108 109 110 111 112
    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),
113 114 115 116 117 118 119
};



typedef struct _virStoragePoolOptions virStoragePoolOptions;
typedef virStoragePoolOptions *virStoragePoolOptionsPtr;
struct _virStoragePoolOptions {
E
Eric Blake 已提交
120
    unsigned int flags;
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
    int defaultFormat;
    virStoragePoolFormatToString formatToString;
    virStoragePoolFormatFromString formatFromString;
};

typedef struct _virStoragePoolTypeInfo virStoragePoolTypeInfo;
typedef virStoragePoolTypeInfo *virStoragePoolTypeInfoPtr;

struct _virStoragePoolTypeInfo {
    int poolType;
    virStoragePoolOptions poolOptions;
    virStorageVolOptions volOptions;
};

static virStoragePoolTypeInfo poolTypeInfo[] = {
    { .poolType = VIR_STORAGE_POOL_LOGICAL,
      .poolOptions = {
            .flags = (VIR_STORAGE_POOL_SOURCE_NAME |
                      VIR_STORAGE_POOL_SOURCE_DEVICE),
            .defaultFormat = VIR_STORAGE_POOL_LOGICAL_LVM2,
            .formatFromString = virStoragePoolFormatLogicalTypeFromString,
            .formatToString = virStoragePoolFormatLogicalTypeToString,
        },
    },
    { .poolType = VIR_STORAGE_POOL_DIR,
      .volOptions = {
147 148 149
            .defaultFormat = VIR_STORAGE_FILE_RAW,
            .formatFromString = virStorageFileFormatTypeFromString,
            .formatToString = virStorageFileFormatTypeToString,
150 151 152 153 154
        },
    },
    { .poolType = VIR_STORAGE_POOL_FS,
      .poolOptions = {
            .flags = (VIR_STORAGE_POOL_SOURCE_DEVICE),
155
            .defaultFormat = VIR_STORAGE_POOL_FS_AUTO,
156 157 158 159
            .formatFromString = virStoragePoolFormatFileSystemTypeFromString,
            .formatToString = virStoragePoolFormatFileSystemTypeToString,
        },
      .volOptions = {
160 161 162
            .defaultFormat = VIR_STORAGE_FILE_RAW,
            .formatFromString = virStorageFileFormatTypeFromString,
            .formatToString = virStorageFileFormatTypeToString,
163 164 165 166 167 168
        },
    },
    { .poolType = VIR_STORAGE_POOL_NETFS,
      .poolOptions = {
            .flags = (VIR_STORAGE_POOL_SOURCE_HOST |
                      VIR_STORAGE_POOL_SOURCE_DIR),
169
            .defaultFormat = VIR_STORAGE_POOL_NETFS_AUTO,
170 171 172 173
            .formatFromString = virStoragePoolFormatFileSystemNetTypeFromString,
            .formatToString = virStoragePoolFormatFileSystemNetTypeToString,
        },
      .volOptions = {
174 175 176
            .defaultFormat = VIR_STORAGE_FILE_RAW,
            .formatFromString = virStorageFileFormatTypeFromString,
            .formatToString = virStorageFileFormatTypeToString,
177 178 179 180 181
        },
    },
    { .poolType = VIR_STORAGE_POOL_ISCSI,
      .poolOptions = {
            .flags = (VIR_STORAGE_POOL_SOURCE_HOST |
D
David Allan 已提交
182 183
                      VIR_STORAGE_POOL_SOURCE_DEVICE |
                      VIR_STORAGE_POOL_SOURCE_INITIATOR_IQN),
184 185 186 187 188
        },
      .volOptions = {
            .formatToString = virStoragePoolFormatDiskTypeToString,
        }
    },
189 190 191 192 193 194 195 196
    { .poolType = VIR_STORAGE_POOL_SCSI,
      .poolOptions = {
            .flags = (VIR_STORAGE_POOL_SOURCE_ADAPTER),
        },
      .volOptions = {
            .formatToString = virStoragePoolFormatDiskTypeToString,
        }
    },
D
Dave Allan 已提交
197 198 199 200 201
    { .poolType = VIR_STORAGE_POOL_MPATH,
      .volOptions = {
            .formatToString = virStoragePoolFormatDiskTypeToString,
        }
    },
202 203 204 205 206 207 208 209
    { .poolType = VIR_STORAGE_POOL_DISK,
      .poolOptions = {
            .flags = (VIR_STORAGE_POOL_SOURCE_DEVICE),
            .defaultFormat = VIR_STORAGE_POOL_DISK_UNKNOWN,
            .formatFromString = virStoragePoolFormatDiskTypeFromString,
            .formatToString = virStoragePoolFormatDiskTypeToString,
        },
      .volOptions = {
210
            .defaultFormat = VIR_STORAGE_VOL_DISK_NONE,
211 212 213 214 215 216 217 218 219 220 221 222 223 224
            .formatFromString = virStorageVolFormatDiskTypeFromString,
            .formatToString = virStorageVolFormatDiskTypeToString,
        },
    }
};


static virStoragePoolTypeInfoPtr
virStoragePoolTypeInfoLookup(int type) {
    unsigned int i;
    for (i = 0; i < ARRAY_CARDINALITY(poolTypeInfo) ; i++)
        if (poolTypeInfo[i].poolType == type)
            return &poolTypeInfo[i];

225
    virStorageReportError(VIR_ERR_INTERNAL_ERROR,
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
                          _("missing backend for pool type %d"), type);
    return NULL;
}

static virStoragePoolOptionsPtr
virStoragePoolOptionsForPoolType(int type) {
    virStoragePoolTypeInfoPtr backend = virStoragePoolTypeInfoLookup(type);
    if (backend == NULL)
        return NULL;
    return &backend->poolOptions;
}

static virStorageVolOptionsPtr
virStorageVolOptionsForPoolType(int type) {
    virStoragePoolTypeInfoPtr backend = virStoragePoolTypeInfoLookup(type);
    if (backend == NULL)
        return NULL;
    return &backend->volOptions;
}


247 248 249
void
virStorageVolDefFree(virStorageVolDefPtr def) {
    int i;
250 251 252 253

    if (!def)
        return;

254 255
    VIR_FREE(def->name);
    VIR_FREE(def->key);
256 257

    for (i = 0 ; i < def->source.nextent ; i++) {
258
        VIR_FREE(def->source.extents[i].path);
259
    }
260
    VIR_FREE(def->source.extents);
261

262 263
    VIR_FREE(def->target.path);
    VIR_FREE(def->target.perms.label);
264
    virStorageEncryptionFree(def->target.encryption);
265 266
    VIR_FREE(def->backingStore.path);
    VIR_FREE(def->backingStore.perms.label);
267
    virStorageEncryptionFree(def->backingStore.encryption);
268
    VIR_FREE(def);
269 270 271
}

void
272
virStoragePoolSourceFree(virStoragePoolSourcePtr source) {
273 274
    int i;

275
    if (!source)
276 277
        return;

278 279 280 281
    VIR_FREE(source->host.name);
    for (i = 0 ; i < source->ndevice ; i++) {
        VIR_FREE(source->devices[i].freeExtents);
        VIR_FREE(source->devices[i].path);
282
    }
283 284 285
    VIR_FREE(source->devices);
    VIR_FREE(source->dir);
    VIR_FREE(source->name);
286
    VIR_FREE(source->adapter);
D
David Allan 已提交
287
    VIR_FREE(source->initiator.iqn);
288 289
    VIR_FREE(source->vendor);
    VIR_FREE(source->product);
290

291 292 293
    if (source->authType == VIR_STORAGE_POOL_AUTH_CHAP) {
        VIR_FREE(source->auth.chap.login);
        VIR_FREE(source->auth.chap.passwd);
294
    }
295 296 297 298 299 300 301 302 303 304
}

void
virStoragePoolDefFree(virStoragePoolDefPtr def) {
    if (!def)
        return;

    VIR_FREE(def->name);

    virStoragePoolSourceFree(&def->source);
305

306 307 308
    VIR_FREE(def->target.path);
    VIR_FREE(def->target.perms.label);
    VIR_FREE(def);
309 310 311 312 313
}


void
virStoragePoolObjFree(virStoragePoolObjPtr obj) {
314 315 316
    if (!obj)
        return;

317 318
    virStoragePoolObjClearVols(obj);

319 320
    virStoragePoolDefFree(obj->def);
    virStoragePoolDefFree(obj->newDef);
321

322 323
    VIR_FREE(obj->configFile);
    VIR_FREE(obj->autostartLink);
324 325 326

    virMutexDestroy(&obj->lock);

327
    VIR_FREE(obj);
328 329
}

330 331 332 333 334 335 336 337 338
void virStoragePoolObjListFree(virStoragePoolObjListPtr pools)
{
    unsigned int i;
    for (i = 0 ; i < pools->count ; i++)
        virStoragePoolObjFree(pools->objs[i]);
    VIR_FREE(pools->objs);
    pools->count = 0;
}

339
void
340
virStoragePoolObjRemove(virStoragePoolObjListPtr pools,
341 342
                        virStoragePoolObjPtr pool)
{
343
    unsigned int i;
344

345 346
    virStoragePoolObjUnlock(pool);

347
    for (i = 0 ; i < pools->count ; i++) {
348
        virStoragePoolObjLock(pools->objs[i]);
349
        if (pools->objs[i] == pool) {
350
            virStoragePoolObjUnlock(pools->objs[i]);
351
            virStoragePoolObjFree(pools->objs[i]);
352

353 354 355
            if (i < (pools->count - 1))
                memmove(pools->objs + i, pools->objs + i + 1,
                        sizeof(*(pools->objs)) * (pools->count - (i + 1)));
356

357 358 359 360
            if (VIR_REALLOC_N(pools->objs, pools->count - 1) < 0) {
                ; /* Failure to reduce memory allocation isn't fatal */
            }
            pools->count--;
361

362 363
            break;
        }
364
        virStoragePoolObjUnlock(pools->objs[i]);
365
    }
366 367 368 369
}


static int
370
virStoragePoolDefParseAuthChap(xmlXPathContextPtr ctxt,
371
                               virStoragePoolAuthChapPtr auth) {
372
    auth->login = virXPathString("string(./auth/@login)", ctxt);
373
    if (auth->login == NULL) {
374
        virStorageReportError(VIR_ERR_XML_ERROR,
J
Jim Meyering 已提交
375
                              "%s", _("missing auth host attribute"));
376 377 378
        return -1;
    }

379
    auth->passwd = virXPathString("string(./auth/@passwd)", ctxt);
380
    if (auth->passwd == NULL) {
381
        virStorageReportError(VIR_ERR_XML_ERROR,
J
Jim Meyering 已提交
382
                              "%s", _("missing auth passwd attribute"));
383 384 385 386 387 388
        return -1;
    }

    return 0;
}

389
static int
390
virStoragePoolDefParseSource(xmlXPathContextPtr ctxt,
391 392 393 394 395 396 397 398
                             virStoragePoolSourcePtr source,
                             int pool_type,
                             xmlNodePtr node) {
    int ret = -1;
    xmlNodePtr relnode, *nodeset = NULL;
    char *authType = NULL;
    int nsource, i;
    virStoragePoolOptionsPtr options;
399
    char *port = NULL;
400 401 402 403 404 405 406 407

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

    if ((options = virStoragePoolOptionsForPoolType(pool_type)) == NULL) {
        goto cleanup;
    }

408
    source->name = virXPathString("string(./name)", ctxt);
409 410

    if (options->formatFromString) {
411
        char *format = virXPathString("string(./format/@type)", ctxt);
412 413 414 415 416 417
        if (format == NULL)
            source->format = options->defaultFormat;
        else
            source->format = options->formatFromString(format);

        if (source->format < 0) {
418
            virStorageReportError(VIR_ERR_XML_ERROR,
419 420 421 422 423 424 425
                                  _("unknown pool format type %s"), format);
            VIR_FREE(format);
            goto cleanup;
        }
        VIR_FREE(format);
    }

426
    source->host.name = virXPathString("string(./host/@name)", ctxt);
427 428 429 430 431 432 433 434 435 436 437
    port = virXPathString("string(./host/@port)", ctxt);
    if (port) {
        if (virStrToLong_i(port, NULL, 10, &source->host.port) < 0) {
            virStorageReportError(VIR_ERR_XML_ERROR,
                                  _("Invalid port number: %s"),
                                  port);
            goto cleanup;
        }
    }


438
    source->initiator.iqn = virXPathString("string(./initiator/iqn/@name)", ctxt);
439

440
    nsource = virXPathNodeSet("./device", ctxt, &nodeset);
441 442 443
    if (nsource < 0)
        goto cleanup;

444 445 446
    if (nsource > 0) {
        if (VIR_ALLOC_N(source->devices, nsource) < 0) {
            VIR_FREE(nodeset);
447
            virReportOOMError();
448 449 450 451
            goto cleanup;
        }

        for (i = 0 ; i < nsource ; i++) {
452
            char *path = virXMLPropString(nodeset[i], "path");
453 454
            if (path == NULL) {
                VIR_FREE(nodeset);
455
                virStorageReportError(VIR_ERR_XML_ERROR,
456 457 458
                        "%s", _("missing storage pool source device path"));
                goto cleanup;
            }
459
            source->devices[i].path = path;
460 461 462 463
        }
        source->ndevice = nsource;
    }

464 465
    source->dir = virXPathString("string(./dir/@path)", ctxt);
    source->adapter = virXPathString("string(./adapter/@name)", ctxt);
466

467
    authType = virXPathString("string(./auth/@type)", ctxt);
468 469 470 471 472 473
    if (authType == NULL) {
        source->authType = VIR_STORAGE_POOL_AUTH_NONE;
    } else {
        if (STREQ(authType, "chap")) {
            source->authType = VIR_STORAGE_POOL_AUTH_CHAP;
        } else {
474
            virStorageReportError(VIR_ERR_XML_ERROR,
475 476 477 478 479 480 481
                                  _("unknown auth type '%s'"),
                                  (const char *)authType);
            goto cleanup;
        }
    }

    if (source->authType == VIR_STORAGE_POOL_AUTH_CHAP) {
482
        if (virStoragePoolDefParseAuthChap(ctxt, &source->auth.chap) < 0)
483 484 485
            goto cleanup;
    }

486 487 488
    source->vendor = virXPathString("string(./vendor/@name)", ctxt);
    source->product = virXPathString("string(./product/@name)", ctxt);

489 490 491 492
    ret = 0;
cleanup:
    ctxt->node = relnode;

493
    VIR_FREE(port);
494 495 496 497
    VIR_FREE(authType);
    VIR_FREE(nodeset);
    return ret;
}
498

499
virStoragePoolSourcePtr
500
virStoragePoolDefParseSourceString(const char *srcSpec,
501 502 503 504 505 506 507
                                   int pool_type)
{
    xmlDocPtr doc = NULL;
    xmlNodePtr node = NULL;
    xmlXPathContextPtr xpath_ctxt = NULL;
    virStoragePoolSourcePtr def = NULL, ret = NULL;

508
    if (!(doc = virXMLParseString(srcSpec, "srcSpec.xml"))) {
509 510 511 512 513
        goto cleanup;
    }

    xpath_ctxt = xmlXPathNewContext(doc);
    if (xpath_ctxt == NULL) {
514
        virReportOOMError();
515 516 517 518
        goto cleanup;
    }

    if (VIR_ALLOC(def) < 0) {
519
        virReportOOMError();
520 521 522
        goto cleanup;
    }

523
    node = virXPathNode("/source", xpath_ctxt);
524
    if (!node) {
525
        virStorageReportError(VIR_ERR_XML_ERROR,
526 527 528 529
                              "%s", _("root element was not source"));
        goto cleanup;
    }

530
    if (virStoragePoolDefParseSource(xpath_ctxt, def, pool_type,
531 532 533 534 535 536
                                     node) < 0)
        goto cleanup;

    ret = def;
    def = NULL;
cleanup:
537 538
    virStoragePoolSourceFree(def);
    VIR_FREE(def);
539 540 541 542 543
    xmlFreeDoc(doc);
    xmlXPathFreeContext(xpath_ctxt);

    return ret;
}
544
static int
545
virStorageDefParsePerms(xmlXPathContextPtr ctxt,
546 547 548
                        virStoragePermsPtr perms,
                        const char *permxpath,
                        int defaultmode) {
549 550
    char *mode;
    long v;
551 552 553
    int ret = -1;
    xmlNodePtr relnode;
    xmlNodePtr node;
554

555
    node = virXPathNode(permxpath, ctxt);
556 557 558
    if (node == NULL) {
        /* Set default values if there is not <permissions> element */
        perms->mode = defaultmode;
559 560
        perms->uid = -1;
        perms->gid = -1;
561 562 563 564 565 566 567
        perms->label = NULL;
        return 0;
    }

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

568
    mode = virXPathString("string(./mode)", ctxt);
569
    if (!mode) {
570
        perms->mode = defaultmode;
571
    } else {
572
        char *end = NULL;
573 574
        perms->mode = strtol(mode, &end, 8);
        if (*end || perms->mode < 0 || perms->mode > 0777) {
575
            VIR_FREE(mode);
576
            virStorageReportError(VIR_ERR_XML_ERROR,
J
Jim Meyering 已提交
577
                                  "%s", _("malformed octal mode"));
578
            goto error;
579
        }
580
        VIR_FREE(mode);
581 582
    }

583
    if (virXPathNode("./owner", ctxt) == NULL) {
584
        perms->uid = -1;
585
    } else {
586
        if (virXPathLong("number(./owner)", ctxt, &v) < 0) {
587
            virStorageReportError(VIR_ERR_XML_ERROR,
J
Jim Meyering 已提交
588
                                  "%s", _("malformed owner element"));
589
            goto error;
590 591 592 593
        }
        perms->uid = (int)v;
    }

594
    if (virXPathNode("./group", ctxt) == NULL) {
595
        perms->gid = -1;
596
    } else {
597
        if (virXPathLong("number(./group)", ctxt, &v) < 0) {
598
            virStorageReportError(VIR_ERR_XML_ERROR,
J
Jim Meyering 已提交
599
                                  "%s", _("malformed group element"));
600
            goto error;
601 602 603 604 605
        }
        perms->gid = (int)v;
    }

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

608 609 610 611
    ret = 0;
error:
    ctxt->node = relnode;
    return ret;
612 613 614
}

static virStoragePoolDefPtr
615
virStoragePoolDefParseXML(xmlXPathContextPtr ctxt) {
616
    virStoragePoolOptionsPtr options;
617
    virStoragePoolDefPtr ret;
618
    xmlNodePtr source_node;
619
    char *type = NULL;
620
    char *uuid = NULL;
621
    char *tmppath;
622

623
    if (VIR_ALLOC(ret) < 0) {
624
        virReportOOMError();
625
        return NULL;
626
    }
627

628
    type = virXPathString("string(./@type)", ctxt);
629
    if ((ret->type = virStoragePoolTypeFromString((const char *)type)) < 0) {
630
        virStorageReportError(VIR_ERR_INTERNAL_ERROR,
631
                              _("unknown storage pool type %s"), (const char*)type);
632
        goto cleanup;
633 634
    }

635 636 637
    xmlFree(type);
    type = NULL;

638
    if ((options = virStoragePoolOptionsForPoolType(ret->type)) == NULL) {
639 640 641
        goto cleanup;
    }

642
    source_node = virXPathNode("./source", ctxt);
643
    if (source_node) {
644
        if (virStoragePoolDefParseSource(ctxt, &ret->source, ret->type,
645 646 647 648
                                         source_node) < 0)
            goto cleanup;
    }

649
    ret->name = virXPathString("string(./name)", ctxt);
650
    if (ret->name == NULL &&
651
        options->flags & VIR_STORAGE_POOL_SOURCE_NAME)
652
        ret->name = ret->source.name;
653
    if (ret->name == NULL) {
654
        virStorageReportError(VIR_ERR_XML_ERROR,
655
                              "%s", _("missing pool source name element"));
656 657 658
        goto cleanup;
    }

659
    uuid = virXPathString("string(./uuid)", ctxt);
660 661
    if (uuid == NULL) {
        if (virUUIDGenerate(ret->uuid) < 0) {
662
            virStorageReportError(VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
663
                                  "%s", _("unable to generate uuid"));
664 665 666 667
            goto cleanup;
        }
    } else {
        if (virUUIDParse(uuid, ret->uuid) < 0) {
668
            virStorageReportError(VIR_ERR_XML_ERROR,
J
Jim Meyering 已提交
669
                                  "%s", _("malformed uuid element"));
670 671
            goto cleanup;
        }
672
        VIR_FREE(uuid);
673 674
    }

675
    if (options->flags & VIR_STORAGE_POOL_SOURCE_HOST) {
676
        if (!ret->source.host.name) {
677
            virStorageReportError(VIR_ERR_XML_ERROR,
678 679
                                  "%s",
                                  _("missing storage pool source host name"));
680 681 682 683
            goto cleanup;
        }
    }

684
    if (options->flags & VIR_STORAGE_POOL_SOURCE_DIR) {
685
        if (!ret->source.dir) {
686
            virStorageReportError(VIR_ERR_XML_ERROR,
687
                                  "%s", _("missing storage pool source path"));
688 689 690
            goto cleanup;
        }
    }
691
    if (options->flags & VIR_STORAGE_POOL_SOURCE_NAME) {
692 693 694
        if (ret->source.name == NULL) {
            /* source name defaults to pool name */
            ret->source.name = strdup(ret->name);
695
            if (ret->source.name == NULL) {
696
                virReportOOMError();
697 698
                goto cleanup;
            }
699 700
        }
    }
701

702
    if (options->flags & VIR_STORAGE_POOL_SOURCE_ADAPTER) {
703
        if (!ret->source.adapter) {
704
            virStorageReportError(VIR_ERR_XML_ERROR,
705
                                  "%s", _("missing storage pool source adapter name"));
706 707 708
            goto cleanup;
        }
    }
709

710 711 712 713 714 715 716 717 718
    /* If DEVICE is the only source type, then its required */
    if (options->flags == VIR_STORAGE_POOL_SOURCE_DEVICE) {
        if (!ret->source.ndevice) {
            virStorageReportError(VIR_ERR_XML_ERROR,
                                  "%s", _("missing storage pool source device name"));
            goto cleanup;
        }
    }

719
    if ((tmppath = virXPathString("string(./target/path)", ctxt)) == NULL) {
720
        virStorageReportError(VIR_ERR_XML_ERROR,
721
                              "%s", _("missing storage pool target path"));
722 723
        goto cleanup;
    }
724 725 726 727 728
    ret->target.path = virFileSanitizePath(tmppath);
    VIR_FREE(tmppath);
    if (!ret->target.path)
        goto cleanup;

729

730
    if (virStorageDefParsePerms(ctxt, &ret->target.perms,
731
                                "./target/permissions", 0700) < 0)
732 733 734 735 736
        goto cleanup;

    return ret;

 cleanup:
737
    VIR_FREE(uuid);
738
    xmlFree(type);
739 740 741 742 743
    virStoragePoolDefFree(ret);
    return NULL;
}

virStoragePoolDefPtr
744
virStoragePoolDefParseNode(xmlDocPtr xml,
745 746 747 748 749
                           xmlNodePtr root) {
    xmlXPathContextPtr ctxt = NULL;
    virStoragePoolDefPtr def = NULL;

    if (STRNEQ((const char *)root->name, "pool")) {
750 751
        virStorageReportError(VIR_ERR_XML_ERROR,
                              "%s", _("unknown root element for storage pool"));
752 753 754 755 756
        goto cleanup;
    }

    ctxt = xmlXPathNewContext(xml);
    if (ctxt == NULL) {
757
        virReportOOMError();
758 759 760 761
        goto cleanup;
    }

    ctxt->node = root;
762
    def = virStoragePoolDefParseXML(ctxt);
763 764 765 766 767 768
cleanup:
    xmlXPathFreeContext(ctxt);
    return def;
}

static virStoragePoolDefPtr
769
virStoragePoolDefParse(const char *xmlStr,
770 771
                       const char *filename) {
    virStoragePoolDefPtr ret = NULL;
J
Jiri Denemark 已提交
772
    xmlDocPtr xml;
773

J
Jiri Denemark 已提交
774 775 776
    if ((xml = virXMLParse(filename, xmlStr, "storage.xml"))) {
        ret = virStoragePoolDefParseNode(xml, xmlDocGetRootElement(xml));
        xmlFreeDoc(xml);
777 778
    }

779 780 781
    return ret;
}

782
virStoragePoolDefPtr
783
virStoragePoolDefParseString(const char *xmlStr)
784
{
785
    return virStoragePoolDefParse(xmlStr, NULL);
786 787 788
}

virStoragePoolDefPtr
789
virStoragePoolDefParseFile(const char *filename)
790
{
791
    return virStoragePoolDefParse(NULL, filename);
792 793
}

794
static int
795
virStoragePoolSourceFormat(virBufferPtr buf,
796
                           virStoragePoolOptionsPtr options,
797 798 799 800 801
                           virStoragePoolSourcePtr src)
{
    int i, j;

    virBufferAddLit(buf,"  <source>\n");
802
    if ((options->flags & VIR_STORAGE_POOL_SOURCE_HOST) &&
803
        src->host.name) {
804
        virBufferAsprintf(buf, "    <host name='%s'", src->host.name);
805
        if (src->host.port)
806
            virBufferAsprintf(buf, " port='%d'", src->host.port);
807 808
        virBufferAddLit(buf, "/>\n");
    }
809

810
    if ((options->flags & VIR_STORAGE_POOL_SOURCE_DEVICE) &&
811 812 813
        src->ndevice) {
        for (i = 0 ; i < src->ndevice ; i++) {
            if (src->devices[i].nfreeExtent) {
814
                virBufferAsprintf(buf,"    <device path='%s'>\n",
815 816
                                  src->devices[i].path);
                for (j = 0 ; j < src->devices[i].nfreeExtent ; j++) {
817
                    virBufferAsprintf(buf, "    <freeExtent start='%llu' end='%llu'/>\n",
818 819 820 821 822 823
                                      src->devices[i].freeExtents[j].start,
                                      src->devices[i].freeExtents[j].end);
                }
                virBufferAddLit(buf,"    </device>\n");
            }
            else
824
                virBufferAsprintf(buf, "    <device path='%s'/>\n",
825 826 827
                                  src->devices[i].path);
        }
    }
828
    if ((options->flags & VIR_STORAGE_POOL_SOURCE_DIR) &&
829
        src->dir)
830
        virBufferAsprintf(buf,"    <dir path='%s'/>\n", src->dir);
831
    if ((options->flags & VIR_STORAGE_POOL_SOURCE_ADAPTER) &&
832
        src->adapter)
833
        virBufferAsprintf(buf,"    <adapter name='%s'/>\n", src->adapter);
834
    if ((options->flags & VIR_STORAGE_POOL_SOURCE_NAME) &&
835
        src->name)
836
        virBufferAsprintf(buf,"    <name>%s</name>\n", src->name);
837

D
David Allan 已提交
838 839 840 841 842 843 844
    if ((options->flags & VIR_STORAGE_POOL_SOURCE_INITIATOR_IQN) &&
        src->initiator.iqn) {
        virBufferAddLit(buf,"    <initiator>\n");
        virBufferEscapeString(buf,"      <iqn name='%s'/>\n", src->initiator.iqn);
        virBufferAddLit(buf,"    </initiator>\n");
    }

845 846 847
    if (options->formatToString) {
        const char *format = (options->formatToString)(src->format);
        if (!format) {
848
            virStorageReportError(VIR_ERR_INTERNAL_ERROR,
849 850 851 852
                                  _("unknown pool format number %d"),
                                  src->format);
            return -1;
        }
853
        virBufferAsprintf(buf,"    <format type='%s'/>\n", format);
854 855 856 857
    }


    if (src->authType == VIR_STORAGE_POOL_AUTH_CHAP)
858
        virBufferAsprintf(buf,"    <auth type='chap' login='%s' passwd='%s'/>\n",
859 860
                          src->auth.chap.login,
                          src->auth.chap.passwd);
861 862 863 864 865 866 867 868 869

    if (src->vendor != NULL) {
        virBufferEscapeString(buf,"    <vendor name='%s'/>\n", src->vendor);
    }

    if (src->product != NULL) {
        virBufferEscapeString(buf,"    <product name='%s'/>\n", src->product);
    }

870 871 872 873 874
    virBufferAddLit(buf,"  </source>\n");

    return 0;
}

875 876

char *
877
virStoragePoolDefFormat(virStoragePoolDefPtr def) {
878
    virStoragePoolOptionsPtr options;
879
    virBuffer buf = VIR_BUFFER_INITIALIZER;
880 881 882
    const char *type;
    char uuid[VIR_UUID_STRING_BUFLEN];

883
    options = virStoragePoolOptionsForPoolType(def->type);
884 885 886
    if (options == NULL)
        return NULL;

887
    type = virStoragePoolTypeToString(def->type);
888
    if (!type) {
889
        virStorageReportError(VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
890
                              "%s", _("unexpected pool type"));
891 892
        goto cleanup;
    }
893 894
    virBufferAsprintf(&buf, "<pool type='%s'>\n", type);
    virBufferAsprintf(&buf,"  <name>%s</name>\n", def->name);
895 896

    virUUIDFormat(def->uuid, uuid);
897
    virBufferAsprintf(&buf,"  <uuid>%s</uuid>\n", uuid);
898

899
    virBufferAsprintf(&buf,"  <capacity>%llu</capacity>\n",
900
                      def->capacity);
901
    virBufferAsprintf(&buf,"  <allocation>%llu</allocation>\n",
902
                      def->allocation);
903
    virBufferAsprintf(&buf,"  <available>%llu</available>\n",
904
                      def->available);
905

906
    if (virStoragePoolSourceFormat(&buf, options, &def->source) < 0)
907
        goto cleanup;
908

909
    virBufferAddLit(&buf,"  <target>\n");
910

911
    if (def->target.path)
912
        virBufferAsprintf(&buf,"    <path>%s</path>\n", def->target.path);
913

914
    virBufferAddLit(&buf,"    <permissions>\n");
915
    virBufferAsprintf(&buf,"      <mode>0%o</mode>\n",
916
                      def->target.perms.mode);
917
    virBufferAsprintf(&buf,"      <owner>%d</owner>\n",
918
                      def->target.perms.uid);
919
    virBufferAsprintf(&buf,"      <group>%d</group>\n",
920
                      def->target.perms.gid);
921

922
    if (def->target.perms.label)
923
        virBufferAsprintf(&buf,"      <label>%s</label>\n",
924
                          def->target.perms.label);
925

926 927 928
    virBufferAddLit(&buf,"    </permissions>\n");
    virBufferAddLit(&buf,"  </target>\n");
    virBufferAddLit(&buf,"</pool>\n");
929

930
    if (virBufferError(&buf))
931 932
        goto no_memory;

933
    return virBufferContentAndReset(&buf);
934 935

 no_memory:
936
    virReportOOMError();
937
 cleanup:
938
    virBufferFreeAndReset(&buf);
939 940 941 942 943
    return NULL;
}


static int
944
virStorageSize(const char *unit,
945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978
               const char *val,
               unsigned long long *ret) {
    unsigned long long mult;
    char *end;

    if (!unit) {
        mult = 1;
    } else {
        switch (unit[0]) {
        case 'k':
        case 'K':
            mult = 1024ull;
            break;

        case 'm':
        case 'M':
            mult = 1024ull * 1024ull;
            break;

        case 'g':
        case 'G':
            mult = 1024ull * 1024ull * 1024ull;
            break;

        case 't':
        case 'T':
            mult = 1024ull * 1024ull * 1024ull * 1024ull;
            break;

        case 'p':
        case 'P':
            mult = 1024ull * 1024ull * 1024ull * 1024ull * 1024ull;
            break;

979 980
        case 'e':
        case 'E':
981 982 983 984 985
            mult = 1024ull * 1024ull * 1024ull * 1024ull * 1024ull *
                1024ull;
            break;

        default:
986
            virStorageReportError(VIR_ERR_XML_ERROR,
987 988 989 990 991 992
                                  _("unknown size units '%s'"), unit);
            return -1;
        }
    }

    if (virStrToLong_ull (val, &end, 10, ret) < 0) {
993
        virStorageReportError(VIR_ERR_XML_ERROR,
J
Jim Meyering 已提交
994
                              "%s", _("malformed capacity element"));
995 996 997
        return -1;
    }
    if (*ret > (ULLONG_MAX / mult)) {
998
        virStorageReportError(VIR_ERR_XML_ERROR,
J
Jim Meyering 已提交
999
                              "%s", _("capacity element value too large"));
1000 1001 1002 1003 1004 1005 1006 1007 1008
            return -1;
    }

    *ret *= mult;

    return 0;
}

static virStorageVolDefPtr
1009
virStorageVolDefParseXML(virStoragePoolDefPtr pool,
1010
                         xmlXPathContextPtr ctxt) {
1011
    virStorageVolDefPtr ret;
1012
    virStorageVolOptionsPtr options;
1013 1014 1015
    char *allocation = NULL;
    char *capacity = NULL;
    char *unit = NULL;
1016
    xmlNodePtr node;
1017

1018
    options = virStorageVolOptionsForPoolType(pool->type);
1019 1020 1021
    if (options == NULL)
        return NULL;

1022
    if (VIR_ALLOC(ret) < 0) {
1023
        virReportOOMError();
1024
        return NULL;
1025
    }
1026

1027
    ret->name = virXPathString("string(./name)", ctxt);
1028
    if (ret->name == NULL) {
1029
        virStorageReportError(VIR_ERR_XML_ERROR,
1030
                              "%s", _("missing volume name element"));
1031 1032 1033
        goto cleanup;
    }

R
Richard W.M. Jones 已提交
1034
    /* Auto-generated so deliberately ignore */
1035
    /*ret->key = virXPathString("string(./key)", ctxt);*/
1036

1037 1038
    capacity = virXPathString("string(./capacity)", ctxt);
    unit = virXPathString("string(./capacity/@unit)", ctxt);
1039
    if (capacity == NULL) {
1040
        virStorageReportError(VIR_ERR_XML_ERROR,
J
Jim Meyering 已提交
1041
                              "%s", _("missing capacity element"));
1042 1043
        goto cleanup;
    }
1044
    if (virStorageSize(unit, capacity, &ret->capacity) < 0)
1045
        goto cleanup;
1046 1047
    VIR_FREE(capacity);
    VIR_FREE(unit);
1048

1049
    allocation = virXPathString("string(./allocation)", ctxt);
1050
    if (allocation) {
1051
        unit = virXPathString("string(./allocation/@unit)", ctxt);
1052
        if (virStorageSize(unit, allocation, &ret->allocation) < 0)
1053
            goto cleanup;
1054 1055
        VIR_FREE(allocation);
        VIR_FREE(unit);
1056 1057 1058 1059
    } else {
        ret->allocation = ret->capacity;
    }

1060
    ret->target.path = virXPathString("string(./target/path)", ctxt);
1061
    if (options->formatFromString) {
1062
        char *format = virXPathString("string(./target/format/@type)", ctxt);
1063 1064 1065 1066 1067 1068
        if (format == NULL)
            ret->target.format = options->defaultFormat;
        else
            ret->target.format = (options->formatFromString)(format);

        if (ret->target.format < 0) {
1069
            virStorageReportError(VIR_ERR_XML_ERROR,
1070
                                  _("unknown volume format type %s"), format);
1071
            VIR_FREE(format);
1072 1073
            goto cleanup;
        }
1074
        VIR_FREE(format);
1075 1076
    }

1077
    if (virStorageDefParsePerms(ctxt, &ret->target.perms,
1078
                                "./target/permissions", 0600) < 0)
1079 1080
        goto cleanup;

1081
    node = virXPathNode("./target/encryption", ctxt);
1082
    if (node != NULL) {
1083
        ret->target.encryption = virStorageEncryptionParseNode(ctxt->doc,
1084 1085 1086 1087 1088
                                                               node);
        if (ret->target.encryption == NULL)
            goto cleanup;
    }

1089 1090


1091
    ret->backingStore.path = virXPathString("string(./backingStore/path)", ctxt);
1092
    if (options->formatFromString) {
1093
        char *format = virXPathString("string(./backingStore/format/@type)", ctxt);
1094 1095 1096 1097 1098 1099
        if (format == NULL)
            ret->backingStore.format = options->defaultFormat;
        else
            ret->backingStore.format = (options->formatFromString)(format);

        if (ret->backingStore.format < 0) {
1100
            virStorageReportError(VIR_ERR_XML_ERROR,
1101 1102 1103 1104 1105 1106 1107
                                  _("unknown volume format type %s"), format);
            VIR_FREE(format);
            goto cleanup;
        }
        VIR_FREE(format);
    }

1108
    if (virStorageDefParsePerms(ctxt, &ret->backingStore.perms,
1109
                                "./backingStore/permissions", 0600) < 0)
1110 1111
        goto cleanup;

1112 1113 1114
    return ret;

 cleanup:
1115 1116 1117
    VIR_FREE(allocation);
    VIR_FREE(capacity);
    VIR_FREE(unit);
1118 1119 1120 1121 1122
    virStorageVolDefFree(ret);
    return NULL;
}

virStorageVolDefPtr
1123
virStorageVolDefParseNode(virStoragePoolDefPtr pool,
1124 1125 1126 1127 1128 1129
                          xmlDocPtr xml,
                          xmlNodePtr root) {
    xmlXPathContextPtr ctxt = NULL;
    virStorageVolDefPtr def = NULL;

    if (STRNEQ((const char *)root->name, "volume")) {
1130
        virStorageReportError(VIR_ERR_XML_ERROR,
1131 1132 1133 1134 1135 1136
                          "%s", _("unknown root element for storage vol"));
        goto cleanup;
    }

    ctxt = xmlXPathNewContext(xml);
    if (ctxt == NULL) {
1137
        virReportOOMError();
1138 1139 1140 1141
        goto cleanup;
    }

    ctxt->node = root;
1142
    def = virStorageVolDefParseXML(pool, ctxt);
1143 1144 1145 1146 1147 1148
cleanup:
    xmlXPathFreeContext(ctxt);
    return def;
}

static virStorageVolDefPtr
1149
virStorageVolDefParse(virStoragePoolDefPtr pool,
1150 1151 1152
                      const char *xmlStr,
                      const char *filename) {
    virStorageVolDefPtr ret = NULL;
J
Jiri Denemark 已提交
1153
    xmlDocPtr xml;
1154

J
Jiri Denemark 已提交
1155 1156 1157
    if ((xml = virXMLParse(filename, xmlStr, "storage.xml"))) {
        ret = virStorageVolDefParseNode(pool, xml, xmlDocGetRootElement(xml));
        xmlFreeDoc(xml);
1158 1159 1160 1161 1162
    }

    return ret;
}

1163
virStorageVolDefPtr
1164
virStorageVolDefParseString(virStoragePoolDefPtr pool,
1165 1166
                            const char *xmlStr)
{
1167
    return virStorageVolDefParse(pool, xmlStr, NULL);
1168 1169 1170
}

virStorageVolDefPtr
1171
virStorageVolDefParseFile(virStoragePoolDefPtr pool,
1172 1173
                          const char *filename)
{
1174
    return virStorageVolDefParse(pool, NULL, filename);
1175
}
1176

1177
static int
1178
virStorageVolTargetDefFormat(virStorageVolOptionsPtr options,
1179 1180 1181
                             virBufferPtr buf,
                             virStorageVolTargetPtr def,
                             const char *type) {
1182
    virBufferAsprintf(buf, "  <%s>\n", type);
1183 1184

    if (def->path)
1185
        virBufferAsprintf(buf,"    <path>%s</path>\n", def->path);
1186 1187 1188 1189

    if (options->formatToString) {
        const char *format = (options->formatToString)(def->format);
        if (!format) {
1190
            virStorageReportError(VIR_ERR_INTERNAL_ERROR,
1191 1192 1193 1194
                                  _("unknown volume format number %d"),
                                  def->format);
            return -1;
        }
1195
        virBufferAsprintf(buf,"    <format type='%s'/>\n", format);
1196 1197 1198
    }

    virBufferAddLit(buf,"    <permissions>\n");
1199
    virBufferAsprintf(buf,"      <mode>0%o</mode>\n",
1200
                      def->perms.mode);
1201
    virBufferAsprintf(buf,"      <owner>%d</owner>\n",
1202
                      def->perms.uid);
1203
    virBufferAsprintf(buf,"      <group>%d</group>\n",
1204 1205 1206 1207
                      def->perms.gid);


    if (def->perms.label)
1208
        virBufferAsprintf(buf,"      <label>%s</label>\n",
1209 1210 1211 1212
                          def->perms.label);

    virBufferAddLit(buf,"    </permissions>\n");

1213
    if (def->encryption != NULL &&
1214
        virStorageEncryptionFormat(buf, def->encryption, 4) < 0)
1215 1216
        return -1;

1217
    virBufferAsprintf(buf, "  </%s>\n", type);
1218 1219 1220

    return 0;
}
1221 1222

char *
1223
virStorageVolDefFormat(virStoragePoolDefPtr pool,
1224
                       virStorageVolDefPtr def) {
1225
    virStorageVolOptionsPtr options;
1226
    virBuffer buf = VIR_BUFFER_INITIALIZER;
1227

1228
    options = virStorageVolOptionsForPoolType(pool->type);
1229 1230 1231
    if (options == NULL)
        return NULL;

1232
    virBufferAddLit(&buf, "<volume>\n");
1233 1234
    virBufferAsprintf(&buf,"  <name>%s</name>\n", def->name);
    virBufferAsprintf(&buf,"  <key>%s</key>\n", def->key);
1235
    virBufferAddLit(&buf, "  <source>\n");
1236 1237 1238 1239 1240 1241 1242 1243

    if (def->source.nextent) {
        int i;
        const char *thispath = NULL;
        for (i = 0 ; i < def->source.nextent ; i++) {
            if (thispath == NULL ||
                STRNEQ(thispath, def->source.extents[i].path)) {
                if (thispath != NULL)
1244 1245
                    virBufferAddLit(&buf, "    </device>\n");

1246
                virBufferAsprintf(&buf, "    <device path='%s'>\n",
1247
                                  def->source.extents[i].path);
1248 1249
            }

1250
            virBufferAsprintf(&buf,
1251 1252 1253
                              "      <extent start='%llu' end='%llu'/>\n",
                              def->source.extents[i].start,
                              def->source.extents[i].end);
1254 1255 1256
            thispath = def->source.extents[i].path;
        }
        if (thispath != NULL)
1257
            virBufferAddLit(&buf, "    </device>\n");
1258
    }
1259
    virBufferAddLit(&buf, "  </source>\n");
1260

1261
    virBufferAsprintf(&buf,"  <capacity>%llu</capacity>\n",
1262
                      def->capacity);
1263
    virBufferAsprintf(&buf,"  <allocation>%llu</allocation>\n",
1264
                      def->allocation);
1265

1266
    if (virStorageVolTargetDefFormat(options, &buf,
1267 1268
                                     &def->target, "target") < 0)
        goto cleanup;
1269

1270
    if (def->backingStore.path &&
1271
        virStorageVolTargetDefFormat(options, &buf,
1272 1273
                                     &def->backingStore, "backingStore") < 0)
        goto cleanup;
1274 1275

    virBufferAddLit(&buf,"</volume>\n");
1276

1277
    if (virBufferError(&buf))
1278 1279
        goto no_memory;

1280
    return virBufferContentAndReset(&buf);
1281 1282

 no_memory:
1283
    virReportOOMError();
1284
 cleanup:
1285
    virBufferFreeAndReset(&buf);
1286 1287 1288 1289 1290
    return NULL;
}


virStoragePoolObjPtr
1291
virStoragePoolObjFindByUUID(virStoragePoolObjListPtr pools,
1292
                            const unsigned char *uuid) {
1293
    unsigned int i;
1294

1295 1296
    for (i = 0 ; i < pools->count ; i++) {
        virStoragePoolObjLock(pools->objs[i]);
1297 1298
        if (!memcmp(pools->objs[i]->def->uuid, uuid, VIR_UUID_BUFLEN))
            return pools->objs[i];
1299 1300
        virStoragePoolObjUnlock(pools->objs[i]);
    }
1301 1302 1303 1304 1305

    return NULL;
}

virStoragePoolObjPtr
1306
virStoragePoolObjFindByName(virStoragePoolObjListPtr pools,
1307
                            const char *name) {
1308
    unsigned int i;
1309

1310 1311
    for (i = 0 ; i < pools->count ; i++) {
        virStoragePoolObjLock(pools->objs[i]);
1312 1313
        if (STREQ(pools->objs[i]->def->name, name))
            return pools->objs[i];
1314 1315
        virStoragePoolObjUnlock(pools->objs[i]);
    }
1316 1317 1318 1319 1320 1321 1322

    return NULL;
}

void
virStoragePoolObjClearVols(virStoragePoolObjPtr pool)
{
1323 1324 1325 1326 1327 1328
    unsigned int i;
    for (i = 0 ; i < pool->volumes.count ; i++)
        virStorageVolDefFree(pool->volumes.objs[i]);

    VIR_FREE(pool->volumes.objs);
    pool->volumes.count = 0;
1329 1330 1331 1332 1333
}

virStorageVolDefPtr
virStorageVolDefFindByKey(virStoragePoolObjPtr pool,
                          const char *key) {
1334
    unsigned int i;
1335

1336 1337 1338
    for (i = 0 ; i < pool->volumes.count ; i++)
        if (STREQ(pool->volumes.objs[i]->key, key))
            return pool->volumes.objs[i];
1339 1340 1341 1342 1343 1344 1345

    return NULL;
}

virStorageVolDefPtr
virStorageVolDefFindByPath(virStoragePoolObjPtr pool,
                           const char *path) {
1346
    unsigned int i;
1347

1348 1349 1350
    for (i = 0 ; i < pool->volumes.count ; i++)
        if (STREQ(pool->volumes.objs[i]->target.path, path))
            return pool->volumes.objs[i];
1351 1352 1353 1354 1355 1356 1357

    return NULL;
}

virStorageVolDefPtr
virStorageVolDefFindByName(virStoragePoolObjPtr pool,
                           const char *name) {
1358
    unsigned int i;
1359

1360 1361 1362
    for (i = 0 ; i < pool->volumes.count ; i++)
        if (STREQ(pool->volumes.objs[i]->name, name))
            return pool->volumes.objs[i];
1363 1364 1365 1366 1367

    return NULL;
}

virStoragePoolObjPtr
1368
virStoragePoolObjAssignDef(virStoragePoolObjListPtr pools,
1369 1370 1371
                           virStoragePoolDefPtr def) {
    virStoragePoolObjPtr pool;

1372
    if ((pool = virStoragePoolObjFindByName(pools, def->name))) {
1373 1374 1375 1376
        if (!virStoragePoolObjIsActive(pool)) {
            virStoragePoolDefFree(pool->def);
            pool->def = def;
        } else {
1377
            virStoragePoolDefFree(pool->newDef);
1378 1379 1380 1381 1382
            pool->newDef = def;
        }
        return pool;
    }

1383
    if (VIR_ALLOC(pool) < 0) {
1384
        virReportOOMError();
1385 1386 1387
        return NULL;
    }

1388
    if (virMutexInit(&pool->lock) < 0) {
1389
        virStorageReportError(VIR_ERR_INTERNAL_ERROR,
1390 1391 1392 1393
                              "%s", _("cannot initialize mutex"));
        VIR_FREE(pool);
        return NULL;
    }
1394
    virStoragePoolObjLock(pool);
1395 1396 1397
    pool->active = 0;
    pool->def = def;

1398 1399
    if (VIR_REALLOC_N(pools->objs, pools->count+1) < 0) {
        pool->def = NULL;
1400
        virStoragePoolObjUnlock(pool);
1401
        virStoragePoolObjFree(pool);
1402
        virReportOOMError();
1403 1404 1405
        return NULL;
    }
    pools->objs[pools->count++] = pool;
1406 1407 1408 1409 1410

    return pool;
}

static virStoragePoolObjPtr
1411
virStoragePoolObjLoad(virStoragePoolObjListPtr pools,
1412 1413 1414 1415 1416 1417
                      const char *file,
                      const char *path,
                      const char *autostartLink) {
    virStoragePoolDefPtr def;
    virStoragePoolObjPtr pool;

1418
    if (!(def = virStoragePoolDefParseFile(path))) {
1419 1420 1421 1422
        return NULL;
    }

    if (!virFileMatchesNameSuffix(file, def->name, ".xml")) {
1423
        virStorageReportError(VIR_ERR_XML_ERROR,
1424
                              _("Storage pool config filename '%s' does not match pool name '%s'"),
1425
                              path, def->name);
1426 1427 1428 1429
        virStoragePoolDefFree(def);
        return NULL;
    }

1430
    if (!(pool = virStoragePoolObjAssignDef(pools, def))) {
1431 1432 1433 1434
        virStoragePoolDefFree(def);
        return NULL;
    }

1435
    VIR_FREE(pool->configFile);  /* for driver reload */
1436 1437
    pool->configFile = strdup(path);
    if (pool->configFile == NULL) {
1438
        virReportOOMError();
1439 1440 1441
        virStoragePoolDefFree(def);
        return NULL;
    }
1442
    VIR_FREE(pool->autostartLink); /* for driver reload */
1443 1444
    pool->autostartLink = strdup(autostartLink);
    if (pool->autostartLink == NULL) {
1445
        virReportOOMError();
1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457
        virStoragePoolDefFree(def);
        return NULL;
    }

    pool->autostart = virFileLinkPointsTo(pool->autostartLink,
                                          pool->configFile);

    return pool;
}


int
1458
virStoragePoolLoadAllConfigs(virStoragePoolObjListPtr pools,
1459 1460
                             const char *configDir,
                             const char *autostartDir) {
1461 1462 1463
    DIR *dir;
    struct dirent *entry;

1464
    if (!(dir = opendir(configDir))) {
1465 1466
        if (errno == ENOENT)
            return 0;
1467
        virReportSystemError(errno, _("Failed to open dir '%s'"),
1468
                             configDir);
1469 1470 1471 1472
        return -1;
    }

    while ((entry = readdir(dir))) {
1473 1474
        char *path;
        char *autostartLink;
1475
        virStoragePoolObjPtr pool;
1476 1477 1478 1479 1480 1481 1482

        if (entry->d_name[0] == '.')
            continue;

        if (!virFileHasSuffix(entry->d_name, ".xml"))
            continue;

1483
        if (!(path = virFileBuildPath(configDir, entry->d_name, NULL)))
1484 1485
            continue;

1486 1487 1488
        if (!(autostartLink = virFileBuildPath(autostartDir, entry->d_name,
                                               NULL))) {
            VIR_FREE(path);
1489 1490 1491
            continue;
        }

1492
        pool = virStoragePoolObjLoad(pools, entry->d_name, path,
1493
                                     autostartLink);
1494 1495
        if (pool)
            virStoragePoolObjUnlock(pool);
1496 1497 1498

        VIR_FREE(path);
        VIR_FREE(autostartLink);
1499 1500 1501 1502 1503 1504 1505 1506
    }

    closedir(dir);

    return 0;
}

int
1507
virStoragePoolObjSaveDef(virStorageDriverStatePtr driver,
1508 1509 1510 1511 1512 1513 1514
                         virStoragePoolObjPtr pool,
                         virStoragePoolDefPtr def) {
    char *xml;
    int fd = -1, ret = -1;
    ssize_t towrite;

    if (!pool->configFile) {
1515 1516
        if (virFileMakePath(driver->configDir) < 0) {
            virReportSystemError(errno,
C
Cole Robinson 已提交
1517 1518
                                 _("cannot create config directory %s"),
                                 driver->configDir);
1519 1520 1521
            return -1;
        }

1522 1523
        if (!(pool->configFile = virFileBuildPath(driver->configDir,
                                                  def->name, ".xml"))) {
1524 1525 1526
            return -1;
        }

1527 1528
        if (!(pool->autostartLink = virFileBuildPath(driver->autostartDir,
                                                     def->name, ".xml"))) {
1529
            VIR_FREE(pool->configFile);
1530 1531 1532 1533
            return -1;
        }
    }

1534 1535
    if (!(xml = virStoragePoolDefFormat(def))) {
        virStorageReportError(VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
1536
                              "%s", _("failed to generate XML"));
1537 1538 1539 1540 1541 1542
        return -1;
    }

    if ((fd = open(pool->configFile,
                   O_WRONLY | O_CREAT | O_TRUNC,
                   S_IRUSR | S_IWUSR )) < 0) {
1543
        virReportSystemError(errno,
1544 1545
                             _("cannot create config file %s"),
                             pool->configFile);
1546 1547 1548
        goto cleanup;
    }

1549 1550
    virEmitXMLWarning(fd, def->name, "pool-edit");

1551 1552
    towrite = strlen(xml);
    if (safewrite(fd, xml, towrite) != towrite) {
1553
        virReportSystemError(errno,
1554 1555
                             _("cannot write config file %s"),
                             pool->configFile);
1556 1557 1558
        goto cleanup;
    }

1559
    if (VIR_CLOSE(fd) < 0) {
1560
        virReportSystemError(errno,
1561 1562
                             _("cannot save config file %s"),
                             pool->configFile);
1563 1564 1565 1566 1567 1568
        goto cleanup;
    }

    ret = 0;

 cleanup:
1569
    VIR_FORCE_CLOSE(fd);
1570
    VIR_FREE(xml);
1571 1572 1573 1574 1575

    return ret;
}

int
1576
virStoragePoolObjDeleteDef(virStoragePoolObjPtr pool) {
1577
    if (!pool->configFile) {
1578
        virStorageReportError(VIR_ERR_INTERNAL_ERROR,
1579 1580 1581 1582 1583
                              _("no config file for %s"), pool->def->name);
        return -1;
    }

    if (unlink(pool->configFile) < 0) {
1584
        virStorageReportError(VIR_ERR_INTERNAL_ERROR,
1585 1586 1587 1588 1589 1590 1591
                              _("cannot remove config for %s"),
                              pool->def->name);
        return -1;
    }

    return 0;
}
1592

1593
virStoragePoolSourcePtr
1594
virStoragePoolSourceListNewSource(virStoragePoolSourceListPtr list)
1595 1596 1597 1598
{
    virStoragePoolSourcePtr source;

    if (VIR_REALLOC_N(list->sources, list->nsources+1) < 0) {
1599
        virReportOOMError();
1600 1601 1602 1603 1604 1605 1606 1607 1608
        return NULL;
    }

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

    return source;
}

1609
char *virStoragePoolSourceListFormat(virStoragePoolSourceListPtr def)
1610
{
1611
    virStoragePoolOptionsPtr options;
1612
    virBuffer buf = VIR_BUFFER_INITIALIZER;
1613 1614
    const char *type;
    int i;
1615

1616
    options = virStoragePoolOptionsForPoolType(def->type);
1617 1618 1619
    if (options == NULL)
        return NULL;

1620
    type = virStoragePoolTypeToString(def->type);
1621
    if (!type) {
1622
        virStorageReportError(VIR_ERR_INTERNAL_ERROR,
1623 1624 1625 1626 1627
                              "%s", _("unexpected pool type"));
        goto cleanup;
    }

    virBufferAddLit(&buf, "<sources>\n");
1628 1629

    for (i = 0; i < def->nsources; i++) {
1630
        virStoragePoolSourceFormat(&buf, options, &def->sources[i]);
1631 1632
    }

1633 1634 1635 1636
    virBufferAddLit(&buf, "</sources>\n");

    if (virBufferError(&buf))
        goto no_memory;
1637 1638

    return virBufferContentAndReset(&buf);
1639 1640

 no_memory:
1641
    virReportOOMError();
1642
 cleanup:
1643
    virBufferFreeAndReset(&buf);
1644
    return NULL;
1645
}
D
Daniel P. Berrange 已提交
1646 1647


1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710
/*
 * virStoragePoolObjIsDuplicate:
 * @doms : virStoragePoolObjListPtr to search
 * @def  : virStoragePoolDefPtr definition of pool to lookup
 * @check_active: If true, ensure that pool is not active
 *
 * Returns: -1 on error
 *          0 if pool is new
 *          1 if pool is a duplicate
 */
int virStoragePoolObjIsDuplicate(virStoragePoolObjListPtr pools,
                                 virStoragePoolDefPtr def,
                                 unsigned int check_active)
{
    int ret = -1;
    int dupPool = 0;
    virStoragePoolObjPtr pool = NULL;

    /* See if a Pool with matching UUID already exists */
    pool = virStoragePoolObjFindByUUID(pools, def->uuid);
    if (pool) {
        /* UUID matches, but if names don't match, refuse it */
        if (STRNEQ(pool->def->name, def->name)) {
            char uuidstr[VIR_UUID_STRING_BUFLEN];
            virUUIDFormat(pool->def->uuid, uuidstr);
            virStorageReportError(VIR_ERR_OPERATION_FAILED,
                                  _("pool '%s' is already defined with uuid %s"),
                                  pool->def->name, uuidstr);
            goto cleanup;
        }

        if (check_active) {
            /* UUID & name match, but if Pool is already active, refuse it */
            if (virStoragePoolObjIsActive(pool)) {
                virStorageReportError(VIR_ERR_OPERATION_INVALID,
                                      _("pool is already active as '%s'"),
                                      pool->def->name);
                goto cleanup;
            }
        }

        dupPool = 1;
    } else {
        /* UUID does not match, but if a name matches, refuse it */
        pool = virStoragePoolObjFindByName(pools, def->name);
        if (pool) {
            char uuidstr[VIR_UUID_STRING_BUFLEN];
            virUUIDFormat(pool->def->uuid, uuidstr);
            virStorageReportError(VIR_ERR_OPERATION_FAILED,
                                  _("pool '%s' already exists with uuid %s"),
                                  def->name, uuidstr);
            goto cleanup;
        }
    }

    ret = dupPool;
cleanup:
    if (pool)
        virStoragePoolObjUnlock(pool);
    return ret;
}


1711 1712
void virStoragePoolObjLock(virStoragePoolObjPtr obj)
{
1713
    virMutexLock(&obj->lock);
1714 1715 1716 1717
}

void virStoragePoolObjUnlock(virStoragePoolObjPtr obj)
{
1718
    virMutexUnlock(&obj->lock);
1719
}