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

#include <config.h>

#include <sys/wait.h>
#include <sys/stat.h>
#include <stdio.h>
#include <regex.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>

34
#include "virerror.h"
35 36
#include "storage_backend_logical.h"
#include "storage_conf.h"
37
#include "vircommand.h"
38
#include "viralloc.h"
39
#include "virlog.h"
E
Eric Blake 已提交
40
#include "virfile.h"
41
#include "virstring.h"
42

43 44
#define VIR_FROM_THIS VIR_FROM_STORAGE

45 46
VIR_LOG_INIT("storage.storage_backend_logical");

47 48 49 50
#define PV_BLANK_SECTOR_SIZE 512


static int
51
virStorageBackendLogicalSetActive(virStoragePoolObjPtr pool,
52 53
                                  int on)
{
54 55 56 57 58 59 60 61 62 63
    int ret;
    virCommandPtr cmd =
        virCommandNewArgList(VGCHANGE,
                             on ? "-aly" : "-aln",
                             pool->def->source.name,
                             NULL);

    ret = virCommandRun(cmd, NULL);
    virCommandFree(cmd);
    return ret;
64 65 66
}


67 68
#define VIR_STORAGE_VOL_LOGICAL_SEGTYPE_STRIPED "striped"

69 70 71 72 73
struct virStorageBackendLogicalPoolVolData {
    virStoragePoolObjPtr pool;
    virStorageVolDefPtr vol;
};

74
static int
75 76
virStorageBackendLogicalMakeVol(char **const groups,
                                void *opaque)
77
{
78 79
    struct virStorageBackendLogicalPoolVolData *data = opaque;
    virStoragePoolObjPtr pool = data->pool;
80
    virStorageVolDefPtr vol = NULL;
81
    bool is_new_vol = false;
82
    unsigned long long offset, size, length;
83 84 85 86 87
    const char *regex_unit = "(\\S+)\\((\\S+)\\)";
    char *regex = NULL;
    regex_t *reg = NULL;
    regmatch_t *vars = NULL;
    char *p = NULL;
88 89
    size_t i;
    int err, nextents, nvars, ret = -1;
O
Osier Yang 已提交
90 91 92 93 94
    const char *attrs = groups[9];

    /* Skip inactive volume */
    if (attrs[4] != 'a')
        return 0;
95

D
Dusty Mabe 已提交
96 97 98 99 100 101 102 103
    /*
     * Skip thin pools(t). These show up in normal lvs output
     * but do not have a corresponding /dev/$vg/$lv device that
     * is created by udev. This breaks assumptions in later code.
     */
    if (attrs[0] == 't')
        return 0;

104
    /* See if we're only looking for a specific volume */
105 106
    if (data->vol != NULL) {
        vol = data->vol;
107 108 109 110 111 112 113 114 115 116
        if (STRNEQ(vol->name, groups[0]))
            return 0;
    }

    /* Or filling in more data on an existing volume */
    if (vol == NULL)
        vol = virStorageVolDefFindByName(pool, groups[0]);

    /* Or a completely new volume */
    if (vol == NULL) {
117
        if (VIR_ALLOC(vol) < 0)
118 119
            return -1;

120
        is_new_vol = true;
121 122
        vol->type = VIR_STORAGE_VOL_BLOCK;

123
        if (VIR_STRDUP(vol->name, groups[0]) < 0)
124
            goto cleanup;
125 126 127 128

    }

    if (vol->target.path == NULL) {
129
        if (virAsprintf(&vol->target.path, "%s/%s",
130
                        pool->def->target.path, vol->name) < 0)
131
            goto cleanup;
132 133
    }

134 135 136 137 138 139 140 141 142
    /* Mark the (s) sparse/snapshot lv, e.g. the lv created using
     * the --virtualsize/-V option. We've already ignored the (t)hin
     * pool definition. In the manner libvirt defines these, the
     * thin pool is hidden to the lvs output, except as the name
     * in brackets [] described for the groups[1] (backingStore).
     */
    if (attrs[0] == 's')
        vol->target.sparse = true;

143 144 145 146 147 148 149
    /* Skips the backingStore of lv created with "--virtualsize",
     * its original device "/dev/$vgname/$lvname_vorigin" is
     * just for lvm internal use, one should never use it.
     *
     * (lvs outputs "[$lvname_vorigin] for field "origin" if the
     *  lv is created with "--virtualsize").
     */
150
    if (groups[1] && STRNEQ(groups[1], "") && (groups[1][0] != '[')) {
151 152 153 154
        if (VIR_ALLOC(vol->target.backingStore) < 0)
            goto cleanup;

        if (virAsprintf(&vol->target.backingStore->path, "%s/%s",
155
                        pool->def->target.path, groups[1]) < 0)
156
            goto cleanup;
157

158
        vol->target.backingStore->format = VIR_STORAGE_POOL_LOGICAL_LVM2;
159 160
    }

161
    if (!vol->key && VIR_STRDUP(vol->key, groups[2]) < 0)
162
        goto cleanup;
163

164
    if (virStorageBackendUpdateVolInfo(vol, false,
165
                                       VIR_STORAGE_VOL_OPEN_DEFAULT, 0) < 0)
166 167 168 169 170
        goto cleanup;

    nextents = 1;
    if (STREQ(groups[4], VIR_STORAGE_VOL_LOGICAL_SEGTYPE_STRIPED)) {
        if (virStrToLong_i(groups[5], NULL, 10, &nextents) < 0) {
171 172
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("malformed volume extent stripes value"));
173 174 175
            goto cleanup;
        }
    }
176 177

    /* Finally fill in extents information */
178
    if (VIR_REALLOC_N(vol->source.extents,
179
                      vol->source.nextent + nextents) < 0)
180
        goto cleanup;
181

182
    if (virStrToLong_ull(groups[6], NULL, 10, &length) < 0) {
183 184
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("malformed volume extent length value"));
185 186 187
        goto cleanup;
    }
    if (virStrToLong_ull(groups[7], NULL, 10, &size) < 0) {
188 189
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("malformed volume extent size value"));
190 191
        goto cleanup;
    }
192
    if (virStrToLong_ull(groups[8], NULL, 10, &vol->target.allocation) < 0) {
193 194
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("malformed volume allocation value"));
195 196
        goto cleanup;
    }
197

E
Eric Blake 已提交
198
    /* Now parse the "devices" field separately */
199 200
    if (VIR_STRDUP(regex, regex_unit) < 0)
        goto cleanup;
201 202

    for (i = 1; i < nextents; i++) {
203
        if (VIR_REALLOC_N(regex, strlen(regex) + strlen(regex_unit) + 2) < 0)
204
            goto cleanup;
E
Eric Blake 已提交
205
        /* "," is the separator of "devices" field */
206 207 208 209
        strcat(regex, ",");
        strncat(regex, regex_unit, strlen(regex_unit));
    }

210
    if (VIR_ALLOC(reg) < 0)
211
        goto cleanup;
212

213 214 215 216
    /* Each extent has a "path:offset" pair, and vars[0] will
     * be the whole matched string.
     */
    nvars = (nextents * 2) + 1;
217
    if (VIR_ALLOC_N(vars, nvars) < 0)
218 219 220 221 222 223
        goto cleanup;

    err = regcomp(reg, regex, REG_EXTENDED);
    if (err != 0) {
        char error[100];
        regerror(err, reg, error, sizeof(error));
224 225 226
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to compile regex %s"),
                       error);
227
        goto cleanup;
228
    }
229

230 231 232
    err = regexec(reg, groups[3], nvars, vars, 0);
    regfree(reg);
    if (err != 0) {
233 234
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("malformed volume extent devices value"));
235
        goto cleanup;
236 237
    }

238
    p = groups[3];
239

240 241
    /* vars[0] is skipped */
    for (i = 0; i < nextents; i++) {
242 243
        size_t j;
        int len;
244
        char *offset_str = NULL;
245 246 247 248 249

        j = (i * 2) + 1;
        len = vars[j].rm_eo - vars[j].rm_so;
        p[vars[j].rm_eo] = '\0';

250 251
        if (VIR_STRNDUP(vol->source.extents[vol->source.nextent].path,
                        p + vars[j].rm_so, len) < 0)
252 253 254
            goto cleanup;

        len = vars[j + 1].rm_eo - vars[j + 1].rm_so;
255
        if (VIR_STRNDUP(offset_str, p + vars[j + 1].rm_so, len) < 0)
256 257 258
            goto cleanup;

        if (virStrToLong_ull(offset_str, NULL, 10, &offset) < 0) {
259 260
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("malformed volume extent offset value"));
E
Eric Blake 已提交
261
            VIR_FREE(offset_str);
262 263 264 265 266 267 268 269 270 271
            goto cleanup;
        }

        VIR_FREE(offset_str);

        vol->source.extents[vol->source.nextent].start = offset * size;
        vol->source.extents[vol->source.nextent].end = (offset * size) + length;
        vol->source.nextent++;
    }

272 273 274
    if (is_new_vol &&
        VIR_APPEND_ELEMENT(pool->volumes.objs, pool->volumes.count, vol) < 0)
        goto cleanup;
275

276 277
    ret = 0;

278
 cleanup:
279
    VIR_FREE(regex);
280
    VIR_FREE(reg);
281 282 283 284
    VIR_FREE(vars);
    if (is_new_vol && (ret == -1))
        virStorageVolDefFree(vol);
    return ret;
285 286 287
}

static int
288
virStorageBackendLogicalFindLVs(virStoragePoolObjPtr pool,
289 290 291
                                virStorageVolDefPtr vol)
{
    /*
292 293
     * # lvs --separator # --noheadings --units b --unbuffered --nosuffix --options \
     * "lv_name,origin,uuid,devices,segtype,stripes,seg_size,vg_extent_size,size,lv_attr" VGNAME
O
Osier Yang 已提交
294
     *
295 296 297 298 299 300
     * RootLV##06UgP5-2rhb-w3Bo-3mdR-WeoL-pytO-SAa2ky#/dev/hda2(0)#linear#1#5234491392#33554432#5234491392#-wi-ao
     * SwapLV##oHviCK-8Ik0-paqS-V20c-nkhY-Bm1e-zgzU0M#/dev/hda2(156)#linear#1#1040187392#33554432#1040187392#-wi-ao
     * Test2##3pg3he-mQsA-5Sui-h0i6-HNmc-Cz7W-QSndcR#/dev/hda2(219)#linear#1#1073741824#33554432#1073741824#owi-a-
     * Test3##UB5hFw-kmlm-LSoX-EI1t-ioVd-h7GL-M0W8Ht#/dev/hda2(251)#linear#1#2181038080#33554432#2181038080#-wi-a-
     * Test3#Test2#UB5hFw-kmlm-LSoX-EI1t-ioVd-h7GL-M0W8Ht#/dev/hda2(187)#linear#1#1040187392#33554432#1040187392#swi-a-
     * test_stripes##fSLSZH-zAS2-yAIb-n4mV-Al9u-HA3V-oo9K1B#/dev/sdc1(10240),/dev/sdd1(0)#striped#2#42949672960#4194304#-wi-a-
301
     *
O
Osier Yang 已提交
302 303
     * Pull out name, origin, & uuid, device, device extent start #,
     * segment size, extent size, size, attrs
304 305
     *
     * NB can be multiple rows per volume if they have many extents
306
     *
307 308
     * NB lvs from some distros (e.g. SLES10 SP2) outputs trailing ","
     * on each line
309 310 311
     *
     * NB Encrypted logical volumes can print ':' in their name, so it is
     *    not a suitable separator (rhbz 470693).
312
     *
313 314
     * NB "devices" field has multiple device paths and "," if the volume is
     *    striped, so "," is not a suitable separator either (rhbz 727474).
315 316
     */
    const char *regexes[] = {
O
Osier Yang 已提交
317
       "^\\s*(\\S+)#(\\S*)#(\\S+)#(\\S+)#(\\S+)#([0-9]+)#(\\S+)#([0-9]+)#([0-9]+)#(\\S+)#?\\s*$"
318 319
    };
    int vars[] = {
O
Osier Yang 已提交
320
        10
321
    };
322 323
    int ret = -1;
    virCommandPtr cmd;
324 325 326 327
    struct virStorageBackendLogicalPoolVolData cbdata = {
        .pool = pool,
        .vol = vol,
    };
328 329 330 331 332 333 334

    cmd = virCommandNewArgList(LVS,
                               "--separator", "#",
                               "--noheadings",
                               "--units", "b",
                               "--unbuffered",
                               "--nosuffix",
O
Osier Yang 已提交
335 336
                               "--options",
                               "lv_name,origin,uuid,devices,segtype,stripes,seg_size,vg_extent_size,size,lv_attr",
337 338
                               pool->def->source.name,
                               NULL);
339 340 341 342 343 344 345
    if (virCommandRunRegex(cmd,
                           1,
                           regexes,
                           vars,
                           virStorageBackendLogicalMakeVol,
                           &cbdata,
                           "lvs") < 0)
346
        goto cleanup;
347

348
    ret = 0;
349
 cleanup:
350 351
    virCommandFree(cmd);
    return ret;
352 353 354
}

static int
355 356
virStorageBackendLogicalRefreshPoolFunc(char **const groups,
                                        void *data)
357
{
358
    virStoragePoolObjPtr pool = data;
359 360 361 362 363 364 365 366 367 368
    if (virStrToLong_ull(groups[0], NULL, 10, &pool->def->capacity) < 0)
        return -1;
    if (virStrToLong_ull(groups[1], NULL, 10, &pool->def->available) < 0)
        return -1;
    pool->def->allocation = pool->def->capacity - pool->def->available;

    return 0;
}


369
static int
370
virStorageBackendLogicalFindPoolSourcesFunc(char **const groups,
371 372
                                            void *data)
{
373 374 375
    virStoragePoolSourceListPtr sourceList = data;
    char *pvname = NULL;
    char *vgname = NULL;
376
    size_t i;
377 378 379
    virStoragePoolSourceDevicePtr dev;
    virStoragePoolSource *thisSource;

380 381 382
    if (VIR_STRDUP(pvname, groups[0]) < 0 ||
        VIR_STRDUP(vgname, groups[1]) < 0)
        goto error;
383 384

    thisSource = NULL;
385
    for (i = 0; i < sourceList->nsources; i++) {
386 387 388 389 390
        if (STREQ(sourceList->sources[i].name, vgname)) {
            thisSource = &sourceList->sources[i];
            break;
        }
    }
391

392
    if (thisSource == NULL) {
393
        if (!(thisSource = virStoragePoolSourceListNewSource(sourceList)))
394
            goto error;
395 396

        thisSource->name = vgname;
397
    }
398 399
    else
        VIR_FREE(vgname);
400

401
    if (VIR_REALLOC_N(thisSource->devices, thisSource->ndevice + 1) != 0)
402
        goto error;
403

404 405
    dev = &thisSource->devices[thisSource->ndevice];
    thisSource->ndevice++;
406
    thisSource->format = VIR_STORAGE_POOL_LOGICAL_LVM2;
407 408 409

    memset(dev, 0, sizeof(*dev));
    dev->path = pvname;
410 411

    return 0;
412

413
 error:
414 415 416 417
    VIR_FREE(pvname);
    VIR_FREE(vgname);

    return -1;
418 419
}

420 421 422 423 424 425 426 427 428 429
/*
 * @sourceList: Pointer to a storage pool source list
 *
 * Use the pvs command to fill the list of pv_name and vg_name associated
 * into the passed sourceList.
 *
 * Returns 0 if successful, -1 and sets error on failure
 */
static int
virStorageBackendLogicalGetPoolSources(virStoragePoolSourceListPtr sourceList)
430 431
{
    /*
432 433 434
     * # pvs --noheadings -o pv_name,vg_name
     *   /dev/sdb
     *   /dev/sdc VolGroup00
435 436
     */
    const char *regexes[] = {
437
        "^\\s*(\\S+)\\s+(\\S+)\\s*$"
438 439
    };
    int vars[] = {
440
        2
441
    };
442
    virCommandPtr cmd;
443
    int ret = -1;
E
Eric Blake 已提交
444

445 446 447 448 449
    /*
     * NOTE: ignoring errors here; this is just to "touch" any logical volumes
     * that might be hanging around, so if this fails for some reason, the
     * worst that happens is that scanning doesn't pick everything up
     */
450 451
    cmd = virCommandNew(VGSCAN);
    if (virCommandRun(cmd, NULL) < 0)
452
        VIR_WARN("Failure when running vgscan to refresh physical volumes");
453
    virCommandFree(cmd);
454

455 456 457 458
    cmd = virCommandNewArgList(PVS,
                               "--noheadings",
                               "-o", "pv_name,vg_name",
                               NULL);
459 460
    if (virCommandRunRegex(cmd, 1, regexes, vars,
                           virStorageBackendLogicalFindPoolSourcesFunc,
461 462 463 464 465
                           sourceList, "pvs") < 0)
        goto cleanup;
    ret = 0;

 cleanup:
466
    virCommandFree(cmd);
467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486
    return ret;
}


static char *
virStorageBackendLogicalFindPoolSources(virConnectPtr conn ATTRIBUTE_UNUSED,
                                        const char *srcSpec ATTRIBUTE_UNUSED,
                                        unsigned int flags)
{
    virStoragePoolSourceList sourceList;
    size_t i;
    char *retval = NULL;

    virCheckFlags(0, NULL);

    memset(&sourceList, 0, sizeof(sourceList));
    sourceList.type = VIR_STORAGE_POOL_LOGICAL;

    if (virStorageBackendLogicalGetPoolSources(&sourceList) < 0)
        goto cleanup;
487

488
    retval = virStoragePoolSourceListFormat(&sourceList);
489
    if (retval == NULL) {
490 491
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("failed to get source from sourceList"));
492 493 494 495
        goto cleanup;
    }

 cleanup:
496
    for (i = 0; i < sourceList.nsources; i++)
497
        virStoragePoolSourceClear(&sourceList.sources[i]);
498
    VIR_FREE(sourceList.sources);
499 500 501 502 503

    return retval;
}


504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546
/*
 * virStorageBackendLogicalMatchPoolSource
 * @pool: Pointer to the source pool object
 *
 * Search the output generated by a 'pvs --noheadings -o pv_name,vg_name'
 * to match the 'vg_name' with the pool def->source.name and for the list
 * of pool def->source.devices[].
 *
 * Returns true if the volume group name matches the pool's source.name
 * and at least one of the pool's def->source.devices[] matches the
 * list of physical device names listed for the pool. Return false if
 * we cannot find a matching volume group name and if we cannot match
 * the any device list members.
 */
static bool
virStorageBackendLogicalMatchPoolSource(virStoragePoolObjPtr pool)
{
    virStoragePoolSourceList sourceList;
    virStoragePoolSource *thisSource;
    size_t i, j;
    int matchcount = 0;
    bool ret = false;

    memset(&sourceList, 0, sizeof(sourceList));
    sourceList.type = VIR_STORAGE_POOL_LOGICAL;

    if (virStorageBackendLogicalGetPoolSources(&sourceList) < 0)
        goto cleanup;

    /* Search the pvs output for this pool's source.name */
    for (i = 0; i < sourceList.nsources; i++) {
        thisSource = &sourceList.sources[i];
        if (STREQ(thisSource->name, pool->def->source.name))
            break;
    }

    if (i == sourceList.nsources) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("cannot find logical volume group name '%s'"),
                       pool->def->source.name);
        goto cleanup;
    }

547 548 549 550 551 552 553 554 555
    /* If the pool has defined source device(s), then let's make sure
     * they match as well; otherwise, matching can only occur on the
     * pool's name.
     */
    if (!pool->def->source.ndevice) {
        ret = true;
        goto cleanup;
    }

556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595
    /* Let's make sure the pool's device(s) match what the pvs output has
     * for volume group devices.
     */
    for (i = 0; i < pool->def->source.ndevice; i++) {
        for (j = 0; j < thisSource->ndevice; j++) {
            if (STREQ(pool->def->source.devices[i].path,
                      thisSource->devices[j].path))
                matchcount++;
        }
    }

    /* If we didn't find any matches, then this pool has listed (a) source
     * device path(s) that don't/doesn't match what was created for the pool
     */
    if (matchcount == 0) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("cannot find any matching source devices for logical "
                         "volume group '%s'"), pool->def->source.name);
        goto cleanup;
    }

    /* Either there's more devices in the pool source device list or there's
     * more devices in the pvs output. Could easily happen if someone decides
     * to 'add' to or 'remove' from the volume group outside of libvirt's
     * knowledge. Rather than fail on that, provide a warning and move on.
     */
    if (matchcount != pool->def->source.ndevice)
        VIR_WARN("pool device list count doesn't match pvs device list count");

    ret = true;

 cleanup:
    for (i = 0; i < sourceList.nsources; i++)
        virStoragePoolSourceClear(&sourceList.sources[i]);
    VIR_FREE(sourceList.sources);

    return ret;
}


596
static int
597
virStorageBackendLogicalCheckPool(virStoragePoolObjPtr pool,
598 599
                                  bool *isActive)
{
600 601 602 603 604
    /* If we can find the target.path as well as ensure that the
     * pool's def source
     */
    *isActive = virFileExists(pool->def->target.path) &&
                virStorageBackendLogicalMatchPoolSource(pool);
605 606 607
    return 0;
}

608
static int
609
virStorageBackendLogicalStartPool(virConnectPtr conn ATTRIBUTE_UNUSED,
610 611
                                  virStoragePoolObjPtr pool)
{
612 613 614 615 616
    /* Let's make sure that the pool's name matches the pvs output and
     * that the pool's source devices match the pvs output.
     */
    if (!virStorageBackendLogicalMatchPoolSource(pool) ||
        virStorageBackendLogicalSetActive(pool, 1) < 0)
617 618 619 620 621 622 623
        return -1;

    return 0;
}


static int
624
virStorageBackendLogicalBuildPool(virConnectPtr conn ATTRIBUTE_UNUSED,
625
                                  virStoragePoolObjPtr pool,
E
Eric Blake 已提交
626
                                  unsigned int flags)
627
{
628 629
    virCommandPtr vgcmd;
    int fd;
630
    char zeros[PV_BLANK_SECTOR_SIZE];
631 632
    int ret = -1;
    size_t i;
633

E
Eric Blake 已提交
634 635
    virCheckFlags(0, -1);

636 637
    memset(zeros, 0, sizeof(zeros));

638
    vgcmd = virCommandNewArgList(VGCREATE, pool->def->source.name, NULL);
639

640
    for (i = 0; i < pool->def->source.ndevice; i++) {
641
        virCommandPtr pvcmd;
642 643 644 645 646 647
        /*
         * LVM requires that the first sector is blanked if using
         * a whole disk as a PV. So we just blank them out regardless
         * rather than trying to figure out if we're a disk or partition
         */
        if ((fd = open(pool->def->source.devices[i].path, O_WRONLY)) < 0) {
648
            virReportSystemError(errno,
649 650
                                 _("cannot open device '%s'"),
                                 pool->def->source.devices[i].path);
651 652
            goto cleanup;
        }
653
        if (safewrite(fd, zeros, sizeof(zeros)) < 0) {
654
            virReportSystemError(errno,
655 656
                                 _("cannot clear device header of '%s'"),
                                 pool->def->source.devices[i].path);
657 658 659 660 661 662 663
            VIR_FORCE_CLOSE(fd);
            goto cleanup;
        }
        if (fsync(fd) < 0) {
            virReportSystemError(errno,
                                 _("cannot flush header of device'%s'"),
                                 pool->def->source.devices[i].path);
664
            VIR_FORCE_CLOSE(fd);
665 666
            goto cleanup;
        }
667
        if (VIR_CLOSE(fd) < 0) {
668
            virReportSystemError(errno,
669 670
                                 _("cannot close device '%s'"),
                                 pool->def->source.devices[i].path);
671 672 673 674 675 676 677
            goto cleanup;
        }

        /*
         * Initialize the physical volume because vgcreate is not
         * clever enough todo this for us :-(
         */
678 679 680 681 682
        pvcmd = virCommandNewArgList(PVCREATE,
                                     pool->def->source.devices[i].path,
                                     NULL);
        if (virCommandRun(pvcmd, NULL) < 0) {
            virCommandFree(pvcmd);
683
            goto cleanup;
684 685
        }
        virCommandFree(pvcmd);
686

687 688
        virCommandAddArg(vgcmd, pool->def->source.devices[i].path);
    }
689 690

    /* Now create the volume group itself */
691
    if (virCommandRun(vgcmd, NULL) < 0)
692 693
        goto cleanup;

694
    ret = 0;
695

696
 cleanup:
697 698
    virCommandFree(vgcmd);
    return ret;
699 700 701 702
}


static int
703
virStorageBackendLogicalRefreshPool(virConnectPtr conn ATTRIBUTE_UNUSED,
704 705 706 707 708 709 710
                                    virStoragePoolObjPtr pool)
{
    /*
     *  # vgs --separator : --noheadings --units b --unbuffered --nosuffix --options "vg_size,vg_free" VGNAME
     *    10603200512:4328521728
     *
     * Pull out size & free
711 712
     *
     * NB vgs from some distros (e.g. SLES10 SP2) outputs trailing ":" on each line
713 714
     */
    const char *regexes[] = {
715
        "^\\s*(\\S+):([0-9]+):?\\s*$"
716 717 718 719
    };
    int vars[] = {
        2
    };
720 721
    virCommandPtr cmd = NULL;
    int ret = -1;
722

723
    virFileWaitForDevices();
724

725
    /* Get list of all logical volumes */
726 727 728 729 730 731 732 733 734 735 736 737
    if (virStorageBackendLogicalFindLVs(pool, NULL) < 0)
        goto cleanup;

    cmd = virCommandNewArgList(VGS,
                               "--separator", ":",
                               "--noheadings",
                               "--units", "b",
                               "--unbuffered",
                               "--nosuffix",
                               "--options", "vg_size,vg_free",
                               pool->def->source.name,
                               NULL);
738 739

    /* Now get basic volgrp metadata */
740 741 742 743 744 745 746
    if (virCommandRunRegex(cmd,
                           1,
                           regexes,
                           vars,
                           virStorageBackendLogicalRefreshPoolFunc,
                           pool,
                           "vgs") < 0)
747
        goto cleanup;
748

749 750
    ret = 0;

751
 cleanup:
752 753 754 755
    virCommandFree(cmd);
    if (ret < 0)
        virStoragePoolObjClearVols(pool);
    return ret;
756 757
}

758 759 760 761
/*
 * This is actually relatively safe; if you happen to try to "stop" the
 * pool that your / is on, for instance, you will get failure like:
 * "Can't deactivate volume group "VolGroup00" with 3 open logical volume(s)"
762 763
 */
static int
764
virStorageBackendLogicalStopPool(virConnectPtr conn ATTRIBUTE_UNUSED,
765 766
                                 virStoragePoolObjPtr pool)
{
767
    if (virStorageBackendLogicalSetActive(pool, 0) < 0)
768 769 770 771 772 773
        return -1;

    return 0;
}

static int
774
virStorageBackendLogicalDeletePool(virConnectPtr conn ATTRIBUTE_UNUSED,
775
                                   virStoragePoolObjPtr pool,
E
Eric Blake 已提交
776
                                   unsigned int flags)
777
{
778 779 780
    virCommandPtr cmd = NULL;
    size_t i;
    int ret = -1;
781

E
Eric Blake 已提交
782 783
    virCheckFlags(0, -1);

784
    /* first remove the volume group */
785 786 787 788 789 790
    cmd = virCommandNewArgList(VGREMOVE,
                               "-f", pool->def->source.name,
                               NULL);
    if (virCommandRun(cmd, NULL) < 0)
        goto cleanup;
    virCommandFree(cmd);
791
    cmd = NULL;
792

793
    /* now remove the pv devices and clear them out */
794
    ret = 0;
795
    for (i = 0; i < pool->def->source.ndevice; i++) {
796 797 798 799 800
        cmd = virCommandNewArgList(PVREMOVE,
                                   pool->def->source.devices[i].path,
                                   NULL);
        if (virCommandRun(cmd, NULL) < 0) {
            ret = -1;
801 802
            break;
        }
803 804
        virCommandFree(cmd);
        cmd = NULL;
805
    }
806

807
 cleanup:
808 809
    virCommandFree(cmd);
    return ret;
810 811 812 813
}


static int
814 815
virStorageBackendLogicalDeleteVol(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
816
                                  virStorageVolDefPtr vol,
817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840
                                  unsigned int flags)
{
    int ret = -1;

    virCommandPtr lvchange_cmd = NULL;
    virCommandPtr lvremove_cmd = NULL;

    virCheckFlags(0, -1);

    virFileWaitForDevices();

    lvchange_cmd = virCommandNewArgList(LVCHANGE, "-aln", vol->target.path, NULL);
    lvremove_cmd = virCommandNewArgList(LVREMOVE, "-f", vol->target.path, NULL);

    if (virCommandRun(lvremove_cmd, NULL) < 0) {
        if (virCommandRun(lvchange_cmd, NULL) < 0) {
            goto cleanup;
        } else {
            if (virCommandRun(lvremove_cmd, NULL) < 0)
                goto cleanup;
        }
    }

    ret = 0;
841
 cleanup:
842 843 844 845
    virCommandFree(lvchange_cmd);
    virCommandFree(lvremove_cmd);
    return ret;
}
846 847 848


static int
849 850 851
virStorageBackendLogicalCreateVol(virConnectPtr conn,
                                  virStoragePoolObjPtr pool,
                                  virStorageVolDefPtr vol)
852
{
853
    int fd = -1;
854
    virCommandPtr cmd = NULL;
855
    virErrorPtr err;
856
    struct stat sb;
857
    bool created = false;
858

859 860 861 862 863 864 865 866 867
    if (vol->target.encryption != NULL) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       "%s", _("storage pool does not support encrypted "
                               "volumes"));
        return -1;
    }

    vol->type = VIR_STORAGE_VOL_BLOCK;

868 869
    /* A target path passed to CreateVol has no meaning */
    VIR_FREE(vol->target.path);
870 871 872 873 874

    if (virAsprintf(&vol->target.path, "%s/%s",
                    pool->def->target.path,
                    vol->name) == -1)
        return -1;
875

876 877 878 879
    cmd = virCommandNewArgList(LVCREATE,
                               "--name", vol->name,
                               NULL);
    virCommandAddArg(cmd, "-L");
880
    if (vol->target.capacity != vol->target.allocation) {
881
        virCommandAddArgFormat(cmd, "%lluK",
882 883
                               VIR_DIV_UP(vol->target.allocation
                                          ? vol->target.allocation : 1, 1024));
884
        virCommandAddArgList(cmd, "--type", "snapshot", NULL);
885
        virCommandAddArg(cmd, "--virtualsize");
886
        vol->target.sparse = true;
887
    }
888 889
    virCommandAddArgFormat(cmd, "%lluK", VIR_DIV_UP(vol->target.capacity,
                                                    1024));
890 891
    if (vol->target.backingStore)
        virCommandAddArgList(cmd, "-s", vol->target.backingStore->path, NULL);
892 893 894 895
    else
        virCommandAddArg(cmd, pool->def->source.name);

    if (virCommandRun(cmd, NULL) < 0)
896
        goto error;
897

898
    created = true;
899 900 901
    virCommandFree(cmd);
    cmd = NULL;

902 903
    if ((fd = virStorageBackendVolOpen(vol->target.path, &sb,
                                       VIR_STORAGE_VOL_OPEN_DEFAULT)) < 0)
904
        goto error;
905 906

    /* We can only chown/grp if root */
907
    if (geteuid() == 0) {
908
        if (fchown(fd, vol->target.perms->uid, vol->target.perms->gid) < 0) {
909
            virReportSystemError(errno,
910 911
                                 _("cannot set file owner '%s'"),
                                 vol->target.path);
912
            goto error;
913 914
        }
    }
915 916 917
    if (fchmod(fd, (vol->target.perms->mode == (mode_t) -1 ?
                    VIR_STORAGE_DEFAULT_VOL_PERM_MODE :
                    vol->target.perms->mode)) < 0) {
918
        virReportSystemError(errno,
919 920
                             _("cannot set file mode '%s'"),
                             vol->target.path);
921
        goto error;
922 923
    }

924
    if (VIR_CLOSE(fd) < 0) {
925
        virReportSystemError(errno,
926 927
                             _("cannot close file '%s'"),
                             vol->target.path);
928
        goto error;
929 930 931
    }

    /* Fill in data about this new vol */
932
    if (virStorageBackendLogicalFindLVs(pool, vol) < 0) {
933
        virReportSystemError(errno,
934 935
                             _("cannot find newly created volume '%s'"),
                             vol->target.path);
936
        goto error;
937 938 939 940
    }

    return 0;

941
 error:
942
    err = virSaveLastError();
943
    VIR_FORCE_CLOSE(fd);
944 945
    if (created)
        virStorageBackendLogicalDeleteVol(conn, pool, vol, 0);
946
    virCommandFree(cmd);
947
    virSetError(err);
948
    virFreeError(err);
949 950 951
    return -1;
}

952 953
static int
virStorageBackendLogicalBuildVolFrom(virConnectPtr conn,
954
                                     virStoragePoolObjPtr pool,
955 956 957 958 959 960
                                     virStorageVolDefPtr vol,
                                     virStorageVolDefPtr inputvol,
                                     unsigned int flags)
{
    virStorageBackendBuildVolFrom build_func;

961
    build_func = virStorageBackendGetBuildVolFromFunction(vol, inputvol);
962 963 964
    if (!build_func)
        return -1;

965
    return build_func(conn, pool, vol, inputvol, flags);
966 967
}

968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990
static int
virStorageBackendLogicalVolWipe(virConnectPtr conn,
                                virStoragePoolObjPtr pool,
                                virStorageVolDefPtr vol,
                                unsigned int algorithm,
                                unsigned int flags)
{
    if (!vol->target.sparse)
        return virStorageBackendVolWipeLocal(conn, pool, vol, algorithm, flags);

    /* The wiping algorithms will write something to the logical volume.
     * Writing to a sparse logical volume causes it to be filled resulting
     * in the volume becoming INACTIVE because there is some amount of
     * metadata contained within the sparse lv. Choosing to only write
     * a wipe pattern to the already written portion lv based on what
     * 'lvs' shows in the "Data%" column/field for the sparse lv was
     * considered. However, there is no guarantee that sparse lv could
     * grow or shrink outside of libvirt's knowledge and thus still render
     * the volume INACTIVE. Until there is some sort of wipe function
     * implemented by lvm for one of these sparse lv, we'll just return
     * unsupported.
     */
    virReportError(VIR_ERR_NO_SUPPORT,
J
John Ferlan 已提交
991 992
                   _("logical volume '%s' is sparse, volume wipe "
                     "not supported"),
993 994 995
                   vol->target.path);
    return -1;
}
996 997 998 999

virStorageBackend virStorageBackendLogical = {
    .type = VIR_STORAGE_POOL_LOGICAL,

1000
    .findPoolSources = virStorageBackendLogicalFindPoolSources,
1001
    .checkPool = virStorageBackendLogicalCheckPool,
1002 1003 1004 1005 1006
    .startPool = virStorageBackendLogicalStartPool,
    .buildPool = virStorageBackendLogicalBuildPool,
    .refreshPool = virStorageBackendLogicalRefreshPool,
    .stopPool = virStorageBackendLogicalStopPool,
    .deletePool = virStorageBackendLogicalDeletePool,
1007
    .buildVol = NULL,
1008
    .buildVolFrom = virStorageBackendLogicalBuildVolFrom,
1009 1010
    .createVol = virStorageBackendLogicalCreateVol,
    .deleteVol = virStorageBackendLogicalDeleteVol,
1011 1012
    .uploadVol = virStorageBackendVolUploadLocal,
    .downloadVol = virStorageBackendVolDownloadLocal,
1013
    .wipeVol = virStorageBackendLogicalVolWipe,
1014
};