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; }
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; }