storage_conf.c 49.7 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 = virXMLParseStringCtxt(srcSpec, "srcSpec.xml", &xpath_ctxt))) {
509 510 511 512
        goto cleanup;
    }

    if (VIR_ALLOC(def) < 0) {
513
        virReportOOMError();
514 515 516
        goto cleanup;
    }

517
    node = virXPathNode("/source", xpath_ctxt);
518
    if (!node) {
519
        virStorageReportError(VIR_ERR_XML_ERROR,
520 521 522 523
                              "%s", _("root element was not source"));
        goto cleanup;
    }

524
    if (virStoragePoolDefParseSource(xpath_ctxt, def, pool_type,
525 526 527 528 529 530
                                     node) < 0)
        goto cleanup;

    ret = def;
    def = NULL;
cleanup:
531 532
    virStoragePoolSourceFree(def);
    VIR_FREE(def);
533 534 535 536 537
    xmlFreeDoc(doc);
    xmlXPathFreeContext(xpath_ctxt);

    return ret;
}
538
static int
539
virStorageDefParsePerms(xmlXPathContextPtr ctxt,
540 541 542
                        virStoragePermsPtr perms,
                        const char *permxpath,
                        int defaultmode) {
543 544
    char *mode;
    long v;
545 546 547
    int ret = -1;
    xmlNodePtr relnode;
    xmlNodePtr node;
548

549
    node = virXPathNode(permxpath, ctxt);
550 551 552
    if (node == NULL) {
        /* Set default values if there is not <permissions> element */
        perms->mode = defaultmode;
553 554
        perms->uid = -1;
        perms->gid = -1;
555 556 557 558 559 560 561
        perms->label = NULL;
        return 0;
    }

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

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

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

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

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

602 603 604 605
    ret = 0;
error:
    ctxt->node = relnode;
    return ret;
606 607 608
}

static virStoragePoolDefPtr
609
virStoragePoolDefParseXML(xmlXPathContextPtr ctxt) {
610
    virStoragePoolOptionsPtr options;
611
    virStoragePoolDefPtr ret;
612
    xmlNodePtr source_node;
613
    char *type = NULL;
614
    char *uuid = NULL;
615
    char *tmppath;
616

617
    if (VIR_ALLOC(ret) < 0) {
618
        virReportOOMError();
619
        return NULL;
620
    }
621

622
    type = virXPathString("string(./@type)", ctxt);
623
    if ((ret->type = virStoragePoolTypeFromString((const char *)type)) < 0) {
624
        virStorageReportError(VIR_ERR_INTERNAL_ERROR,
625
                              _("unknown storage pool type %s"), (const char*)type);
626
        goto cleanup;
627 628
    }

629 630 631
    xmlFree(type);
    type = NULL;

632
    if ((options = virStoragePoolOptionsForPoolType(ret->type)) == NULL) {
633 634 635
        goto cleanup;
    }

636
    source_node = virXPathNode("./source", ctxt);
637
    if (source_node) {
638
        if (virStoragePoolDefParseSource(ctxt, &ret->source, ret->type,
639 640 641 642
                                         source_node) < 0)
            goto cleanup;
    }

643
    ret->name = virXPathString("string(./name)", ctxt);
644
    if (ret->name == NULL &&
645
        options->flags & VIR_STORAGE_POOL_SOURCE_NAME)
646
        ret->name = ret->source.name;
647
    if (ret->name == NULL) {
648
        virStorageReportError(VIR_ERR_XML_ERROR,
649
                              "%s", _("missing pool source name element"));
650 651 652
        goto cleanup;
    }

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

669
    if (options->flags & VIR_STORAGE_POOL_SOURCE_HOST) {
670
        if (!ret->source.host.name) {
671
            virStorageReportError(VIR_ERR_XML_ERROR,
672 673
                                  "%s",
                                  _("missing storage pool source host name"));
674 675 676 677
            goto cleanup;
        }
    }

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

696
    if (options->flags & VIR_STORAGE_POOL_SOURCE_ADAPTER) {
697
        if (!ret->source.adapter) {
698
            virStorageReportError(VIR_ERR_XML_ERROR,
699
                                  "%s", _("missing storage pool source adapter name"));
700 701 702
            goto cleanup;
        }
    }
703

704 705 706 707 708 709 710 711 712
    /* 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;
        }
    }

713
    if ((tmppath = virXPathString("string(./target/path)", ctxt)) == NULL) {
714
        virStorageReportError(VIR_ERR_XML_ERROR,
715
                              "%s", _("missing storage pool target path"));
716 717
        goto cleanup;
    }
718 719 720 721 722
    ret->target.path = virFileSanitizePath(tmppath);
    VIR_FREE(tmppath);
    if (!ret->target.path)
        goto cleanup;

723

724
    if (virStorageDefParsePerms(ctxt, &ret->target.perms,
725
                                "./target/permissions", 0700) < 0)
726 727 728 729 730
        goto cleanup;

    return ret;

 cleanup:
731
    VIR_FREE(uuid);
732
    xmlFree(type);
733 734 735 736 737
    virStoragePoolDefFree(ret);
    return NULL;
}

virStoragePoolDefPtr
738
virStoragePoolDefParseNode(xmlDocPtr xml,
739 740 741 742 743
                           xmlNodePtr root) {
    xmlXPathContextPtr ctxt = NULL;
    virStoragePoolDefPtr def = NULL;

    if (STRNEQ((const char *)root->name, "pool")) {
744 745
        virStorageReportError(VIR_ERR_XML_ERROR,
                              "%s", _("unknown root element for storage pool"));
746 747 748 749 750
        goto cleanup;
    }

    ctxt = xmlXPathNewContext(xml);
    if (ctxt == NULL) {
751
        virReportOOMError();
752 753 754 755
        goto cleanup;
    }

    ctxt->node = root;
756
    def = virStoragePoolDefParseXML(ctxt);
757 758 759 760 761 762
cleanup:
    xmlXPathFreeContext(ctxt);
    return def;
}

static virStoragePoolDefPtr
763
virStoragePoolDefParse(const char *xmlStr,
764 765
                       const char *filename) {
    virStoragePoolDefPtr ret = NULL;
J
Jiri Denemark 已提交
766
    xmlDocPtr xml;
767

J
Jiri Denemark 已提交
768 769 770
    if ((xml = virXMLParse(filename, xmlStr, "storage.xml"))) {
        ret = virStoragePoolDefParseNode(xml, xmlDocGetRootElement(xml));
        xmlFreeDoc(xml);
771 772
    }

773 774 775
    return ret;
}

776
virStoragePoolDefPtr
777
virStoragePoolDefParseString(const char *xmlStr)
778
{
779
    return virStoragePoolDefParse(xmlStr, NULL);
780 781 782
}

virStoragePoolDefPtr
783
virStoragePoolDefParseFile(const char *filename)
784
{
785
    return virStoragePoolDefParse(NULL, filename);
786 787
}

788
static int
789
virStoragePoolSourceFormat(virBufferPtr buf,
790
                           virStoragePoolOptionsPtr options,
791 792 793 794 795
                           virStoragePoolSourcePtr src)
{
    int i, j;

    virBufferAddLit(buf,"  <source>\n");
796
    if ((options->flags & VIR_STORAGE_POOL_SOURCE_HOST) &&
797
        src->host.name) {
798
        virBufferAsprintf(buf, "    <host name='%s'", src->host.name);
799
        if (src->host.port)
800
            virBufferAsprintf(buf, " port='%d'", src->host.port);
801 802
        virBufferAddLit(buf, "/>\n");
    }
803

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

D
David Allan 已提交
832 833 834 835 836 837 838
    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");
    }

839 840 841
    if (options->formatToString) {
        const char *format = (options->formatToString)(src->format);
        if (!format) {
842
            virStorageReportError(VIR_ERR_INTERNAL_ERROR,
843 844 845 846
                                  _("unknown pool format number %d"),
                                  src->format);
            return -1;
        }
847
        virBufferAsprintf(buf,"    <format type='%s'/>\n", format);
848 849 850 851
    }


    if (src->authType == VIR_STORAGE_POOL_AUTH_CHAP)
852
        virBufferAsprintf(buf,"    <auth type='chap' login='%s' passwd='%s'/>\n",
853 854
                          src->auth.chap.login,
                          src->auth.chap.passwd);
855 856 857 858 859 860 861 862 863

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

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

864 865 866 867 868
    virBufferAddLit(buf,"  </source>\n");

    return 0;
}

869 870

char *
871
virStoragePoolDefFormat(virStoragePoolDefPtr def) {
872
    virStoragePoolOptionsPtr options;
873
    virBuffer buf = VIR_BUFFER_INITIALIZER;
874 875 876
    const char *type;
    char uuid[VIR_UUID_STRING_BUFLEN];

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

881
    type = virStoragePoolTypeToString(def->type);
882
    if (!type) {
883
        virStorageReportError(VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
884
                              "%s", _("unexpected pool type"));
885 886
        goto cleanup;
    }
887 888
    virBufferAsprintf(&buf, "<pool type='%s'>\n", type);
    virBufferAsprintf(&buf,"  <name>%s</name>\n", def->name);
889 890

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

893
    virBufferAsprintf(&buf,"  <capacity>%llu</capacity>\n",
894
                      def->capacity);
895
    virBufferAsprintf(&buf,"  <allocation>%llu</allocation>\n",
896
                      def->allocation);
897
    virBufferAsprintf(&buf,"  <available>%llu</available>\n",
898
                      def->available);
899

900
    if (virStoragePoolSourceFormat(&buf, options, &def->source) < 0)
901
        goto cleanup;
902

903
    virBufferAddLit(&buf,"  <target>\n");
904

905
    if (def->target.path)
906
        virBufferAsprintf(&buf,"    <path>%s</path>\n", def->target.path);
907

908
    virBufferAddLit(&buf,"    <permissions>\n");
909
    virBufferAsprintf(&buf,"      <mode>0%o</mode>\n",
910
                      def->target.perms.mode);
911
    virBufferAsprintf(&buf,"      <owner>%d</owner>\n",
912
                      def->target.perms.uid);
913
    virBufferAsprintf(&buf,"      <group>%d</group>\n",
914
                      def->target.perms.gid);
915

916
    if (def->target.perms.label)
917
        virBufferAsprintf(&buf,"      <label>%s</label>\n",
918
                          def->target.perms.label);
919

920 921 922
    virBufferAddLit(&buf,"    </permissions>\n");
    virBufferAddLit(&buf,"  </target>\n");
    virBufferAddLit(&buf,"</pool>\n");
923

924
    if (virBufferError(&buf))
925 926
        goto no_memory;

927
    return virBufferContentAndReset(&buf);
928 929

 no_memory:
930
    virReportOOMError();
931
 cleanup:
932
    virBufferFreeAndReset(&buf);
933 934 935 936 937
    return NULL;
}


static int
938
virStorageSize(const char *unit,
939 940 941 942 943 944 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
               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;

973 974
        case 'e':
        case 'E':
975 976 977 978 979
            mult = 1024ull * 1024ull * 1024ull * 1024ull * 1024ull *
                1024ull;
            break;

        default:
980
            virStorageReportError(VIR_ERR_XML_ERROR,
981 982 983 984 985 986
                                  _("unknown size units '%s'"), unit);
            return -1;
        }
    }

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

    *ret *= mult;

    return 0;
}

static virStorageVolDefPtr
1003
virStorageVolDefParseXML(virStoragePoolDefPtr pool,
1004
                         xmlXPathContextPtr ctxt) {
1005
    virStorageVolDefPtr ret;
1006
    virStorageVolOptionsPtr options;
1007 1008 1009
    char *allocation = NULL;
    char *capacity = NULL;
    char *unit = NULL;
1010
    xmlNodePtr node;
1011

1012
    options = virStorageVolOptionsForPoolType(pool->type);
1013 1014 1015
    if (options == NULL)
        return NULL;

1016
    if (VIR_ALLOC(ret) < 0) {
1017
        virReportOOMError();
1018
        return NULL;
1019
    }
1020

1021
    ret->name = virXPathString("string(./name)", ctxt);
1022
    if (ret->name == NULL) {
1023
        virStorageReportError(VIR_ERR_XML_ERROR,
1024
                              "%s", _("missing volume name element"));
1025 1026 1027
        goto cleanup;
    }

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

1031 1032
    capacity = virXPathString("string(./capacity)", ctxt);
    unit = virXPathString("string(./capacity/@unit)", ctxt);
1033
    if (capacity == NULL) {
1034
        virStorageReportError(VIR_ERR_XML_ERROR,
J
Jim Meyering 已提交
1035
                              "%s", _("missing capacity element"));
1036 1037
        goto cleanup;
    }
1038
    if (virStorageSize(unit, capacity, &ret->capacity) < 0)
1039
        goto cleanup;
1040 1041
    VIR_FREE(capacity);
    VIR_FREE(unit);
1042

1043
    allocation = virXPathString("string(./allocation)", ctxt);
1044
    if (allocation) {
1045
        unit = virXPathString("string(./allocation/@unit)", ctxt);
1046
        if (virStorageSize(unit, allocation, &ret->allocation) < 0)
1047
            goto cleanup;
1048 1049
        VIR_FREE(allocation);
        VIR_FREE(unit);
1050 1051 1052 1053
    } else {
        ret->allocation = ret->capacity;
    }

1054
    ret->target.path = virXPathString("string(./target/path)", ctxt);
1055
    if (options->formatFromString) {
1056
        char *format = virXPathString("string(./target/format/@type)", ctxt);
1057 1058 1059 1060 1061 1062
        if (format == NULL)
            ret->target.format = options->defaultFormat;
        else
            ret->target.format = (options->formatFromString)(format);

        if (ret->target.format < 0) {
1063
            virStorageReportError(VIR_ERR_XML_ERROR,
1064
                                  _("unknown volume format type %s"), format);
1065
            VIR_FREE(format);
1066 1067
            goto cleanup;
        }
1068
        VIR_FREE(format);
1069 1070
    }

1071
    if (virStorageDefParsePerms(ctxt, &ret->target.perms,
1072
                                "./target/permissions", 0600) < 0)
1073 1074
        goto cleanup;

1075
    node = virXPathNode("./target/encryption", ctxt);
1076
    if (node != NULL) {
1077
        ret->target.encryption = virStorageEncryptionParseNode(ctxt->doc,
1078 1079 1080 1081 1082
                                                               node);
        if (ret->target.encryption == NULL)
            goto cleanup;
    }

1083 1084


1085
    ret->backingStore.path = virXPathString("string(./backingStore/path)", ctxt);
1086
    if (options->formatFromString) {
1087
        char *format = virXPathString("string(./backingStore/format/@type)", ctxt);
1088 1089 1090 1091 1092 1093
        if (format == NULL)
            ret->backingStore.format = options->defaultFormat;
        else
            ret->backingStore.format = (options->formatFromString)(format);

        if (ret->backingStore.format < 0) {
1094
            virStorageReportError(VIR_ERR_XML_ERROR,
1095 1096 1097 1098 1099 1100 1101
                                  _("unknown volume format type %s"), format);
            VIR_FREE(format);
            goto cleanup;
        }
        VIR_FREE(format);
    }

1102
    if (virStorageDefParsePerms(ctxt, &ret->backingStore.perms,
1103
                                "./backingStore/permissions", 0600) < 0)
1104 1105
        goto cleanup;

1106 1107 1108
    return ret;

 cleanup:
1109 1110 1111
    VIR_FREE(allocation);
    VIR_FREE(capacity);
    VIR_FREE(unit);
1112 1113 1114 1115 1116
    virStorageVolDefFree(ret);
    return NULL;
}

virStorageVolDefPtr
1117
virStorageVolDefParseNode(virStoragePoolDefPtr pool,
1118 1119 1120 1121 1122 1123
                          xmlDocPtr xml,
                          xmlNodePtr root) {
    xmlXPathContextPtr ctxt = NULL;
    virStorageVolDefPtr def = NULL;

    if (STRNEQ((const char *)root->name, "volume")) {
1124
        virStorageReportError(VIR_ERR_XML_ERROR,
1125 1126 1127 1128 1129 1130
                          "%s", _("unknown root element for storage vol"));
        goto cleanup;
    }

    ctxt = xmlXPathNewContext(xml);
    if (ctxt == NULL) {
1131
        virReportOOMError();
1132 1133 1134 1135
        goto cleanup;
    }

    ctxt->node = root;
1136
    def = virStorageVolDefParseXML(pool, ctxt);
1137 1138 1139 1140 1141 1142
cleanup:
    xmlXPathFreeContext(ctxt);
    return def;
}

static virStorageVolDefPtr
1143
virStorageVolDefParse(virStoragePoolDefPtr pool,
1144 1145 1146
                      const char *xmlStr,
                      const char *filename) {
    virStorageVolDefPtr ret = NULL;
J
Jiri Denemark 已提交
1147
    xmlDocPtr xml;
1148

J
Jiri Denemark 已提交
1149 1150 1151
    if ((xml = virXMLParse(filename, xmlStr, "storage.xml"))) {
        ret = virStorageVolDefParseNode(pool, xml, xmlDocGetRootElement(xml));
        xmlFreeDoc(xml);
1152 1153 1154 1155 1156
    }

    return ret;
}

1157
virStorageVolDefPtr
1158
virStorageVolDefParseString(virStoragePoolDefPtr pool,
1159 1160
                            const char *xmlStr)
{
1161
    return virStorageVolDefParse(pool, xmlStr, NULL);
1162 1163 1164
}

virStorageVolDefPtr
1165
virStorageVolDefParseFile(virStoragePoolDefPtr pool,
1166 1167
                          const char *filename)
{
1168
    return virStorageVolDefParse(pool, NULL, filename);
1169
}
1170

1171
static int
1172
virStorageVolTargetDefFormat(virStorageVolOptionsPtr options,
1173 1174 1175
                             virBufferPtr buf,
                             virStorageVolTargetPtr def,
                             const char *type) {
1176
    virBufferAsprintf(buf, "  <%s>\n", type);
1177 1178

    if (def->path)
1179
        virBufferAsprintf(buf,"    <path>%s</path>\n", def->path);
1180 1181 1182 1183

    if (options->formatToString) {
        const char *format = (options->formatToString)(def->format);
        if (!format) {
1184
            virStorageReportError(VIR_ERR_INTERNAL_ERROR,
1185 1186 1187 1188
                                  _("unknown volume format number %d"),
                                  def->format);
            return -1;
        }
1189
        virBufferAsprintf(buf,"    <format type='%s'/>\n", format);
1190 1191 1192
    }

    virBufferAddLit(buf,"    <permissions>\n");
1193
    virBufferAsprintf(buf,"      <mode>0%o</mode>\n",
1194
                      def->perms.mode);
1195
    virBufferAsprintf(buf,"      <owner>%d</owner>\n",
1196
                      def->perms.uid);
1197
    virBufferAsprintf(buf,"      <group>%d</group>\n",
1198 1199 1200 1201
                      def->perms.gid);


    if (def->perms.label)
1202
        virBufferAsprintf(buf,"      <label>%s</label>\n",
1203 1204 1205 1206
                          def->perms.label);

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

1207
    if (def->encryption != NULL &&
1208
        virStorageEncryptionFormat(buf, def->encryption, 4) < 0)
1209 1210
        return -1;

1211
    virBufferAsprintf(buf, "  </%s>\n", type);
1212 1213 1214

    return 0;
}
1215 1216

char *
1217
virStorageVolDefFormat(virStoragePoolDefPtr pool,
1218
                       virStorageVolDefPtr def) {
1219
    virStorageVolOptionsPtr options;
1220
    virBuffer buf = VIR_BUFFER_INITIALIZER;
1221

1222
    options = virStorageVolOptionsForPoolType(pool->type);
1223 1224 1225
    if (options == NULL)
        return NULL;

1226
    virBufferAddLit(&buf, "<volume>\n");
1227 1228
    virBufferAsprintf(&buf,"  <name>%s</name>\n", def->name);
    virBufferAsprintf(&buf,"  <key>%s</key>\n", def->key);
1229
    virBufferAddLit(&buf, "  <source>\n");
1230 1231 1232 1233 1234 1235 1236 1237

    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)
1238 1239
                    virBufferAddLit(&buf, "    </device>\n");

1240
                virBufferAsprintf(&buf, "    <device path='%s'>\n",
1241
                                  def->source.extents[i].path);
1242 1243
            }

1244
            virBufferAsprintf(&buf,
1245 1246 1247
                              "      <extent start='%llu' end='%llu'/>\n",
                              def->source.extents[i].start,
                              def->source.extents[i].end);
1248 1249 1250
            thispath = def->source.extents[i].path;
        }
        if (thispath != NULL)
1251
            virBufferAddLit(&buf, "    </device>\n");
1252
    }
1253
    virBufferAddLit(&buf, "  </source>\n");
1254

1255
    virBufferAsprintf(&buf,"  <capacity>%llu</capacity>\n",
1256
                      def->capacity);
1257
    virBufferAsprintf(&buf,"  <allocation>%llu</allocation>\n",
1258
                      def->allocation);
1259

1260
    if (virStorageVolTargetDefFormat(options, &buf,
1261 1262
                                     &def->target, "target") < 0)
        goto cleanup;
1263

1264
    if (def->backingStore.path &&
1265
        virStorageVolTargetDefFormat(options, &buf,
1266 1267
                                     &def->backingStore, "backingStore") < 0)
        goto cleanup;
1268 1269

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

1271
    if (virBufferError(&buf))
1272 1273
        goto no_memory;

1274
    return virBufferContentAndReset(&buf);
1275 1276

 no_memory:
1277
    virReportOOMError();
1278
 cleanup:
1279
    virBufferFreeAndReset(&buf);
1280 1281 1282 1283 1284
    return NULL;
}


virStoragePoolObjPtr
1285
virStoragePoolObjFindByUUID(virStoragePoolObjListPtr pools,
1286
                            const unsigned char *uuid) {
1287
    unsigned int i;
1288

1289 1290
    for (i = 0 ; i < pools->count ; i++) {
        virStoragePoolObjLock(pools->objs[i]);
1291 1292
        if (!memcmp(pools->objs[i]->def->uuid, uuid, VIR_UUID_BUFLEN))
            return pools->objs[i];
1293 1294
        virStoragePoolObjUnlock(pools->objs[i]);
    }
1295 1296 1297 1298 1299

    return NULL;
}

virStoragePoolObjPtr
1300
virStoragePoolObjFindByName(virStoragePoolObjListPtr pools,
1301
                            const char *name) {
1302
    unsigned int i;
1303

1304 1305
    for (i = 0 ; i < pools->count ; i++) {
        virStoragePoolObjLock(pools->objs[i]);
1306 1307
        if (STREQ(pools->objs[i]->def->name, name))
            return pools->objs[i];
1308 1309
        virStoragePoolObjUnlock(pools->objs[i]);
    }
1310 1311 1312 1313 1314 1315 1316

    return NULL;
}

void
virStoragePoolObjClearVols(virStoragePoolObjPtr pool)
{
1317 1318 1319 1320 1321 1322
    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;
1323 1324 1325 1326 1327
}

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

1330 1331 1332
    for (i = 0 ; i < pool->volumes.count ; i++)
        if (STREQ(pool->volumes.objs[i]->key, key))
            return pool->volumes.objs[i];
1333 1334 1335 1336 1337 1338 1339

    return NULL;
}

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

1342 1343 1344
    for (i = 0 ; i < pool->volumes.count ; i++)
        if (STREQ(pool->volumes.objs[i]->target.path, path))
            return pool->volumes.objs[i];
1345 1346 1347 1348 1349 1350 1351

    return NULL;
}

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

1354 1355 1356
    for (i = 0 ; i < pool->volumes.count ; i++)
        if (STREQ(pool->volumes.objs[i]->name, name))
            return pool->volumes.objs[i];
1357 1358 1359 1360 1361

    return NULL;
}

virStoragePoolObjPtr
1362
virStoragePoolObjAssignDef(virStoragePoolObjListPtr pools,
1363 1364 1365
                           virStoragePoolDefPtr def) {
    virStoragePoolObjPtr pool;

1366
    if ((pool = virStoragePoolObjFindByName(pools, def->name))) {
1367 1368 1369 1370
        if (!virStoragePoolObjIsActive(pool)) {
            virStoragePoolDefFree(pool->def);
            pool->def = def;
        } else {
1371
            virStoragePoolDefFree(pool->newDef);
1372 1373 1374 1375 1376
            pool->newDef = def;
        }
        return pool;
    }

1377
    if (VIR_ALLOC(pool) < 0) {
1378
        virReportOOMError();
1379 1380 1381
        return NULL;
    }

1382
    if (virMutexInit(&pool->lock) < 0) {
1383
        virStorageReportError(VIR_ERR_INTERNAL_ERROR,
1384 1385 1386 1387
                              "%s", _("cannot initialize mutex"));
        VIR_FREE(pool);
        return NULL;
    }
1388
    virStoragePoolObjLock(pool);
1389 1390 1391
    pool->active = 0;
    pool->def = def;

1392 1393
    if (VIR_REALLOC_N(pools->objs, pools->count+1) < 0) {
        pool->def = NULL;
1394
        virStoragePoolObjUnlock(pool);
1395
        virStoragePoolObjFree(pool);
1396
        virReportOOMError();
1397 1398 1399
        return NULL;
    }
    pools->objs[pools->count++] = pool;
1400 1401 1402 1403 1404

    return pool;
}

static virStoragePoolObjPtr
1405
virStoragePoolObjLoad(virStoragePoolObjListPtr pools,
1406 1407 1408 1409 1410 1411
                      const char *file,
                      const char *path,
                      const char *autostartLink) {
    virStoragePoolDefPtr def;
    virStoragePoolObjPtr pool;

1412
    if (!(def = virStoragePoolDefParseFile(path))) {
1413 1414 1415 1416
        return NULL;
    }

    if (!virFileMatchesNameSuffix(file, def->name, ".xml")) {
1417
        virStorageReportError(VIR_ERR_XML_ERROR,
1418
                              _("Storage pool config filename '%s' does not match pool name '%s'"),
1419
                              path, def->name);
1420 1421 1422 1423
        virStoragePoolDefFree(def);
        return NULL;
    }

1424
    if (!(pool = virStoragePoolObjAssignDef(pools, def))) {
1425 1426 1427 1428
        virStoragePoolDefFree(def);
        return NULL;
    }

1429
    VIR_FREE(pool->configFile);  /* for driver reload */
1430 1431
    pool->configFile = strdup(path);
    if (pool->configFile == NULL) {
1432
        virReportOOMError();
1433 1434 1435
        virStoragePoolDefFree(def);
        return NULL;
    }
1436
    VIR_FREE(pool->autostartLink); /* for driver reload */
1437 1438
    pool->autostartLink = strdup(autostartLink);
    if (pool->autostartLink == NULL) {
1439
        virReportOOMError();
1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451
        virStoragePoolDefFree(def);
        return NULL;
    }

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

    return pool;
}


int
1452
virStoragePoolLoadAllConfigs(virStoragePoolObjListPtr pools,
1453 1454
                             const char *configDir,
                             const char *autostartDir) {
1455 1456 1457
    DIR *dir;
    struct dirent *entry;

1458
    if (!(dir = opendir(configDir))) {
1459 1460
        if (errno == ENOENT)
            return 0;
1461
        virReportSystemError(errno, _("Failed to open dir '%s'"),
1462
                             configDir);
1463 1464 1465 1466
        return -1;
    }

    while ((entry = readdir(dir))) {
1467 1468
        char *path;
        char *autostartLink;
1469
        virStoragePoolObjPtr pool;
1470 1471 1472 1473 1474 1475 1476

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

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

1477
        if (!(path = virFileBuildPath(configDir, entry->d_name, NULL)))
1478 1479
            continue;

1480 1481 1482
        if (!(autostartLink = virFileBuildPath(autostartDir, entry->d_name,
                                               NULL))) {
            VIR_FREE(path);
1483 1484 1485
            continue;
        }

1486
        pool = virStoragePoolObjLoad(pools, entry->d_name, path,
1487
                                     autostartLink);
1488 1489
        if (pool)
            virStoragePoolObjUnlock(pool);
1490 1491 1492

        VIR_FREE(path);
        VIR_FREE(autostartLink);
1493 1494 1495 1496 1497 1498 1499 1500
    }

    closedir(dir);

    return 0;
}

int
1501
virStoragePoolObjSaveDef(virStorageDriverStatePtr driver,
1502 1503 1504 1505 1506 1507 1508
                         virStoragePoolObjPtr pool,
                         virStoragePoolDefPtr def) {
    char *xml;
    int fd = -1, ret = -1;
    ssize_t towrite;

    if (!pool->configFile) {
1509 1510
        if (virFileMakePath(driver->configDir) < 0) {
            virReportSystemError(errno,
C
Cole Robinson 已提交
1511 1512
                                 _("cannot create config directory %s"),
                                 driver->configDir);
1513 1514 1515
            return -1;
        }

1516 1517
        if (!(pool->configFile = virFileBuildPath(driver->configDir,
                                                  def->name, ".xml"))) {
1518 1519 1520
            return -1;
        }

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

1528 1529
    if (!(xml = virStoragePoolDefFormat(def))) {
        virStorageReportError(VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
1530
                              "%s", _("failed to generate XML"));
1531 1532 1533 1534 1535 1536
        return -1;
    }

    if ((fd = open(pool->configFile,
                   O_WRONLY | O_CREAT | O_TRUNC,
                   S_IRUSR | S_IWUSR )) < 0) {
1537
        virReportSystemError(errno,
1538 1539
                             _("cannot create config file %s"),
                             pool->configFile);
1540 1541 1542
        goto cleanup;
    }

1543 1544
    virEmitXMLWarning(fd, def->name, "pool-edit");

1545 1546
    towrite = strlen(xml);
    if (safewrite(fd, xml, towrite) != towrite) {
1547
        virReportSystemError(errno,
1548 1549
                             _("cannot write config file %s"),
                             pool->configFile);
1550 1551 1552
        goto cleanup;
    }

1553
    if (VIR_CLOSE(fd) < 0) {
1554
        virReportSystemError(errno,
1555 1556
                             _("cannot save config file %s"),
                             pool->configFile);
1557 1558 1559 1560 1561 1562
        goto cleanup;
    }

    ret = 0;

 cleanup:
1563
    VIR_FORCE_CLOSE(fd);
1564
    VIR_FREE(xml);
1565 1566 1567 1568 1569

    return ret;
}

int
1570
virStoragePoolObjDeleteDef(virStoragePoolObjPtr pool) {
1571
    if (!pool->configFile) {
1572
        virStorageReportError(VIR_ERR_INTERNAL_ERROR,
1573 1574 1575 1576 1577
                              _("no config file for %s"), pool->def->name);
        return -1;
    }

    if (unlink(pool->configFile) < 0) {
1578
        virStorageReportError(VIR_ERR_INTERNAL_ERROR,
1579 1580 1581 1582 1583 1584 1585
                              _("cannot remove config for %s"),
                              pool->def->name);
        return -1;
    }

    return 0;
}
1586

1587
virStoragePoolSourcePtr
1588
virStoragePoolSourceListNewSource(virStoragePoolSourceListPtr list)
1589 1590 1591 1592
{
    virStoragePoolSourcePtr source;

    if (VIR_REALLOC_N(list->sources, list->nsources+1) < 0) {
1593
        virReportOOMError();
1594 1595 1596 1597 1598 1599 1600 1601 1602
        return NULL;
    }

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

    return source;
}

1603
char *virStoragePoolSourceListFormat(virStoragePoolSourceListPtr def)
1604
{
1605
    virStoragePoolOptionsPtr options;
1606
    virBuffer buf = VIR_BUFFER_INITIALIZER;
1607 1608
    const char *type;
    int i;
1609

1610
    options = virStoragePoolOptionsForPoolType(def->type);
1611 1612 1613
    if (options == NULL)
        return NULL;

1614
    type = virStoragePoolTypeToString(def->type);
1615
    if (!type) {
1616
        virStorageReportError(VIR_ERR_INTERNAL_ERROR,
1617 1618 1619 1620 1621
                              "%s", _("unexpected pool type"));
        goto cleanup;
    }

    virBufferAddLit(&buf, "<sources>\n");
1622 1623

    for (i = 0; i < def->nsources; i++) {
1624
        virStoragePoolSourceFormat(&buf, options, &def->sources[i]);
1625 1626
    }

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

    if (virBufferError(&buf))
        goto no_memory;
1631 1632

    return virBufferContentAndReset(&buf);
1633 1634

 no_memory:
1635
    virReportOOMError();
1636
 cleanup:
1637
    virBufferFreeAndReset(&buf);
1638
    return NULL;
1639
}
D
Daniel P. Berrange 已提交
1640 1641


1642 1643 1644 1645 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
/*
 * 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;
}


1705 1706
void virStoragePoolObjLock(virStoragePoolObjPtr obj)
{
1707
    virMutexLock(&obj->lock);
1708 1709 1710 1711
}

void virStoragePoolObjUnlock(virStoragePoolObjPtr obj)
{
1712
    virMutexUnlock(&obj->lock);
1713
}