static int
virStorageBackendLogicalFindLVs(virStoragePoolObjPtr pool,
                                virStorageVolDefPtr vol)
{
    /*
     * # lvs --separator , --noheadings --units b --unbuffered --nosuffix --options \
     * "lv_name,origin,uuid,devices,seg_size,vg_extent_size,size,lv_attr" VGNAME
     *
     * RootLV,,06UgP5-2rhb-w3Bo-3mdR-WeoL-pytO-SAa2ky,/dev/hda2(0),5234491392,33554432,5234491392,-wi-ao
     * SwapLV,,oHviCK-8Ik0-paqS-V20c-nkhY-Bm1e-zgzU0M,/dev/hda2(156),1040187392,33554432,1040187392,-wi-ao
     * Test2,,3pg3he-mQsA-5Sui-h0i6-HNmc-Cz7W-QSndcR,/dev/hda2(219),1073741824,33554432,1073741824,owi-a-
     * Test3,,UB5hFw-kmlm-LSoX-EI1t-ioVd-h7GL-M0W8Ht,/dev/hda2(251),2181038080,33554432,2181038080,-wi-a-
     * Test3,Test2,UB5hFw-kmlm-LSoX-EI1t-ioVd-h7GL-M0W8Ht,/dev/hda2(187),1040187392,33554432,1040187392,swi-a-
     *
     * Pull out name, origin, & uuid, device, device extent start #,
     * segment size, extent size, size, attrs
     *
     * NB can be multiple rows per volume if they have many extents
     *
     * NB lvs from some distros (e.g. SLES10 SP2) outputs trailing "," on each line
     *
     * NB Encrypted logical volumes can print ':' in their name, so it is
     *    not a suitable separator (rhbz 470693).
     * NB "devices" field has multiple device paths and "," if the volume is
     *    striped, so "," is not a suitable separator either (rhbz 727474).
     */
    const char *regexes[] = {
       "^\\s*(\\S+)#(\\S*)#(\\S+)#(\\S+)#(\\S+)#([0-9]+)#(\\S+)#([0-9]+)#([0-9]+)#(\\S+)#?\\s*$"
    };
    int vars[] = {
        10
    };
    int ret = -1;
    virCommandPtr cmd;

    cmd = virCommandNewArgList(LVS,
                               "--separator", "#",
                               "--noheadings",
                               "--units", "b",
                               "--unbuffered",
                               "--nosuffix",
                               "--options",
                               "lv_name,origin,uuid,devices,segtype,stripes,seg_size,vg_extent_size,size,lv_attr",
                               pool->def->source.name,
                               NULL);
    if (virStorageBackendRunProgRegex(pool,
                                      cmd,
                                      1,
                                      regexes,
                                      vars,
                                      virStorageBackendLogicalMakeVol,
                                      vol, "lvs") < 0)
        goto cleanup;

    ret = 0;
cleanup:
    virCommandFree(cmd);
    return ret;
}
static int
virStorageBackendLogicalFindLVs(virStoragePoolObjPtr pool,
                                virStorageVolDefPtr vol)
{
    /*
     *  # lvs --separator , --noheadings --units b --unbuffered --nosuffix --options "lv_name,origin,uuid,devices,seg_size,vg_extent_size" VGNAME
     *  RootLV,,06UgP5-2rhb-w3Bo-3mdR-WeoL-pytO-SAa2ky,/dev/hda2(0),5234491392,33554432
     *  SwapLV,,oHviCK-8Ik0-paqS-V20c-nkhY-Bm1e-zgzU0M,/dev/hda2(156),1040187392,33554432
     *  Test2,,3pg3he-mQsA-5Sui-h0i6-HNmc-Cz7W-QSndcR,/dev/hda2(219),1073741824,33554432
     *  Test3,,UB5hFw-kmlm-LSoX-EI1t-ioVd-h7GL-M0W8Ht,/dev/hda2(251),2181038080,33554432
     *  Test3,Test2,UB5hFw-kmlm-LSoX-EI1t-ioVd-h7GL-M0W8Ht,/dev/hda2(187),1040187392,33554432
     *
     * Pull out name, origin, & uuid, device, device extent start #, segment size, extent size.
     *
     * NB can be multiple rows per volume if they have many extents
     *
     * NB lvs from some distros (e.g. SLES10 SP2) outputs trailing "," on each line
     *
     * NB Encrypted logical volumes can print ':' in their name, so it is
     *    not a suitable separator (rhbz 470693).
     */
    const char *regexes[] = {
        "^\\s*(\\S+),(\\S*),(\\S+),(\\S+)\\((\\S+)\\),(\\S+),([0-9]+),?\\s*$"
    };
    int vars[] = {
        7
    };
    const char *prog[] = {
        LVS, "--separator", ",", "--noheadings", "--units", "b",
        "--unbuffered", "--nosuffix", "--options",
        "lv_name,origin,uuid,devices,seg_size,vg_extent_size",
        pool->def->source.name, NULL
    };

    int exitstatus;

    if (virStorageBackendRunProgRegex(pool,
                                      prog,
                                      1,
                                      regexes,
                                      vars,
                                      virStorageBackendLogicalMakeVol,
                                      vol,
                                      &exitstatus) < 0) {
        virStorageReportError(VIR_ERR_INTERNAL_ERROR,
                              "%s", _("lvs command failed"));
                              return -1;
    }

    if (exitstatus != 0) {
        virStorageReportError(VIR_ERR_INTERNAL_ERROR,
                              _("lvs command failed with exitstatus %d"),
                              exitstatus);
        return -1;
    }

    return 0;
}
static char *
virStorageBackendISCSISession(virStoragePoolObjPtr pool,
                              int probe)
{
    /*
     * # iscsiadm --mode session
     * tcp: [1] 192.168.122.170:3260,1 demo-tgt-b
     * tcp: [2] 192.168.122.170:3260,1 demo-tgt-a
     *
     * Pull out 2nd and 4th fields
     */
    const char *regexes[] = {
        "^tcp:\\s+\\[(\\S+)\\]\\s+\\S+\\s+(\\S+)\\s*$"
    };
    int vars[] = {
        2,
    };
    const char *const prog[] = {
        ISCSIADM, "--mode", "session", NULL
    };
    char *session = NULL;

    /* Note that we ignore the exitstatus.  Older versions of iscsiadm tools
     * returned an exit status of > 0, even if they succeeded.  We will just
     * rely on whether session got filled in properly.
     */
    if (virStorageBackendRunProgRegex(pool,
                                      prog,
                                      1,
                                      regexes,
                                      vars,
                                      virStorageBackendISCSIExtractSession,
                                      &session,
                                      NULL) < 0)
        return NULL;

    if (session == NULL &&
        !probe) {
        virStorageReportError(VIR_ERR_INTERNAL_ERROR,
                              "%s", _("cannot find session"));
        return NULL;
    }

    return session;
}
static char *
virStorageBackendISCSISession(virStoragePoolObjPtr pool,
                              bool probe)
{
    /*
     * # iscsiadm --mode session
     * tcp: [1] 192.168.122.170:3260,1 demo-tgt-b
     * tcp: [2] 192.168.122.170:3260,1 demo-tgt-a
     *
     * Pull out 2nd and 4th fields
     */
    const char *regexes[] = {
        "^tcp:\\s+\\[(\\S+)\\]\\s+\\S+\\s+(\\S+).*$"
    };
    int vars[] = {
        2,
    };
    char *session = NULL;

    virCommandPtr cmd = virCommandNewArgList(ISCSIADM, "--mode", "session", NULL);

    if (virStorageBackendRunProgRegex(pool,
                                      cmd,
                                      1,
                                      regexes,
                                      vars,
                                      virStorageBackendISCSIExtractSession,
                                      &session, NULL) < 0)
        goto cleanup;

    if (session == NULL &&
        !probe) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("cannot find session"));
        goto cleanup;
    }

cleanup:
    virCommandFree(cmd);
    return session;
}
static char *
virStorageBackendFileSystemNetFindPoolSources(virConnectPtr conn ATTRIBUTE_UNUSED,
                                              const char *srcSpec,
                                              unsigned int flags)
{
    /*
     *  # showmount --no-headers -e HOSTNAME
     *  /tmp   *
     *  /A dir demo1.foo.bar,demo2.foo.bar
     *
     * Extract directory name (including possible interior spaces ...).
     */

    const char *regexes[] = {
        "^(/.*\\S) +\\S+$"
    };
    int vars[] = {
        1
    };
    virNetfsDiscoverState state = {
        .host = NULL,
        .list = {
            .type = VIR_STORAGE_POOL_NETFS,
            .nsources = 0,
            .sources = NULL
        }
    };
    const char *prog[] = { SHOWMOUNT, "--no-headers", "--exports", NULL, NULL };
    virStoragePoolSourcePtr source = NULL;
    char *retval = NULL;
    unsigned int i;

    virCheckFlags(0, NULL);

    source = virStoragePoolDefParseSourceString(srcSpec,
                                                VIR_STORAGE_POOL_NETFS);
    if (!source)
        goto cleanup;

    state.host = source->host.name;
    prog[3] = source->host.name;

    if (virStorageBackendRunProgRegex(NULL, prog, 1, regexes, vars,
                            virStorageBackendFileSystemNetFindPoolSourcesFunc,
                            &state, NULL) < 0)
        goto cleanup;

    retval = virStoragePoolSourceListFormat(&state.list);
    if (retval == NULL) {
        virReportOOMError();
        goto cleanup;
    }

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

    virStoragePoolSourceFree(source);

    return retval;
}
static int
virStorageBackendISCSIScanTargets(const char *portal,
                                  const char *initiatoriqn,
                                  size_t *ntargetsret,
                                  char ***targetsret)
{
    /**
     *
     * The output of sendtargets is very simple, just two columns,
     * portal then target name
     *
     * 192.168.122.185:3260,1 iqn.2004-04.com:fedora14:iscsi.demo0.bf6d84
     * 192.168.122.185:3260,1 iqn.2004-04.com:fedora14:iscsi.demo1.bf6d84
     * 192.168.122.185:3260,1 iqn.2004-04.com:fedora14:iscsi.demo2.bf6d84
     * 192.168.122.185:3260,1 iqn.2004-04.com:fedora14:iscsi.demo3.bf6d84
     */
    const char *regexes[] = {
        "^\\s*(\\S+)\\s+(\\S+)\\s*$"
    };
    int vars[] = { 2 };
    const char *const cmdsendtarget[] = {
        ISCSIADM, "--mode", "discovery", "--type", "sendtargets",
        "--portal", portal, NULL
    };
    struct virStorageBackendISCSITargetList list;
    int i;

    memset(&list, 0, sizeof(list));

    if (virStorageBackendRunProgRegex(NULL, /* No pool for callback */
                                      cmdsendtarget,
                                      1,
                                      regexes,
                                      vars,
                                      virStorageBackendISCSIGetTargets,
                                      &list, NULL) < 0) {
        return -1;
    }

    for (i = 0 ; i < list.ntargets ; i++) {
        /* We have to ignore failure, because we can't undo
         * the results of 'sendtargets', unless we go scrubbing
         * around in the dirt in /var/lib/iscsi.
         */
        if (virStorageBackendISCSITargetAutologin(portal,
                                                  initiatoriqn,
                                                  list.targets[i], false) < 0)
            VIR_WARN("Unable to disable auto-login on iSCSI target %s: %s",
                     portal, list.targets[i]);
    }

    if (ntargetsret && targetsret) {
        *ntargetsret = list.ntargets;
        *targetsret = list.targets;
    } else {
        for (i = 0 ; i < list.ntargets ; i++) {
            VIR_FREE(list.targets[i]);
        }
        VIR_FREE(list.targets);
    }

    return 0;
}
Beispiel #7
0
static char *
virStorageBackendFileSystemNetFindPoolSources(virConnectPtr conn ATTRIBUTE_UNUSED,
                                              const char *srcSpec,
                                              unsigned int flags)
{
    /*
     *  # showmount --no-headers -e HOSTNAME
     *  /tmp   *
     *  /A dir demo1.foo.bar,demo2.foo.bar
     *
     * Extract directory name (including possible interior spaces ...).
     */

    const char *regexes[] = {
        "^(/.*\\S) +\\S+$"
    };
    int vars[] = {
        1
    };
    virNetfsDiscoverState state = {
        .host = NULL,
        .list = {
            .type = VIR_STORAGE_POOL_NETFS,
            .nsources = 0,
            .sources = NULL
        }
    };
    virStoragePoolSourcePtr source = NULL;
    char *retval = NULL;
    unsigned int i;
    virCommandPtr cmd = NULL;

    virCheckFlags(0, NULL);

    if (!srcSpec) {
        virReportError(VIR_ERR_INVALID_ARG,
                       "%s", _("hostname must be specified for netfs sources"));
        return NULL;
    }

    if (!(source = virStoragePoolDefParseSourceString(srcSpec,
                                                      VIR_STORAGE_POOL_NETFS)))
        return NULL;

    if (source->nhost != 1) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("Expected exactly 1 host for the storage pool"));
        goto cleanup;
    }

    state.host = source->hosts[0].name;

    cmd = virCommandNewArgList(SHOWMOUNT,
                               "--no-headers",
                               "--exports",
                               source->hosts[0].name,
                               NULL);

    if (virStorageBackendRunProgRegex(NULL, cmd, 1, regexes, vars,
                            virStorageBackendFileSystemNetFindPoolSourcesFunc,
                            &state, NULL) < 0)
        goto cleanup;

    retval = virStoragePoolSourceListFormat(&state.list);
    if (retval == NULL) {
        virReportOOMError();
        goto cleanup;
    }

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

    virStoragePoolSourceFree(source);
    virCommandFree(cmd);
    return retval;
}