static int virISCSIConnection(const char *portal, const char *initiatoriqn, const char *target, const char **extraargv) { int ret = -1; const char *const baseargv[] = { ISCSIADM, "--mode", "node", "--portal", portal, "--targetname", target, NULL }; virCommandPtr cmd; char *ifacename = NULL; cmd = virCommandNewArgs(baseargv); virCommandAddArgSet(cmd, extraargv); if (initiatoriqn) { switch (virStorageBackendIQNFound(initiatoriqn, &ifacename)) { case IQN_FOUND: VIR_DEBUG("ifacename: '%s'", ifacename); break; case IQN_MISSING: if (virStorageBackendCreateIfaceIQN(initiatoriqn, &ifacename) != 0) goto cleanup; /* * iscsiadm doesn't let you send commands to the Interface IQN, * unless you've first issued a 'sendtargets' command to the * portal. Without the sendtargets all that is received is a * "iscsiadm: No records found" */ if (virISCSIScanTargets(portal, NULL, NULL) < 0) goto cleanup; break; case IQN_ERROR: default: goto cleanup; } virCommandAddArgList(cmd, "--interface", ifacename, NULL); } if (virCommandRun(cmd, NULL) < 0) goto cleanup; ret = 0; cleanup: virCommandFree(cmd); VIR_FREE(ifacename); return ret; }
static int virStorageBackendISCSIStartPool(virConnectPtr conn, virStoragePoolObjPtr pool) { char *portal = NULL; char *session = NULL; int ret = -1; if (pool->def->source.nhost != 1) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Expected exactly 1 host for the storage pool")); return -1; } if (pool->def->source.hosts[0].name == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("missing source host")); return -1; } if (pool->def->source.ndevice != 1 || pool->def->source.devices[0].path == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("missing source device")); return -1; } if ((session = virStorageBackendISCSISession(pool, true)) == NULL) { if ((portal = virStorageBackendISCSIPortal(&pool->def->source)) == NULL) goto cleanup; /* * iscsiadm doesn't let you login to a target, unless you've * first issued a 'sendtargets' command to the portal :-( */ if (virISCSIScanTargets(portal, pool->def->source.initiator.iqn, NULL, NULL) < 0) goto cleanup; if (virStorageBackendISCSISetAuth(portal, conn, &pool->def->source) < 0) goto cleanup; if (virISCSIConnectionLogin(portal, pool->def->source.initiator.iqn, pool->def->source.devices[0].path) < 0) goto cleanup; } ret = 0; cleanup: VIR_FREE(portal); VIR_FREE(session); return ret; }
static char * virStorageBackendISCSIFindPoolSources(virConnectPtr conn ATTRIBUTE_UNUSED, const char *srcSpec, unsigned int flags) { virStoragePoolSourcePtr source = NULL; size_t ntargets = 0; char **targets = NULL; char *ret = NULL; size_t i; virStoragePoolSourceList list = { .type = VIR_STORAGE_POOL_ISCSI, .nsources = 0, .sources = NULL }; char *portal = NULL; virCheckFlags(0, NULL); if (!srcSpec) { virReportError(VIR_ERR_INVALID_ARG, "%s", _("hostname must be specified for iscsi sources")); return NULL; } if (!(source = virStoragePoolDefParseSourceString(srcSpec, list.type))) return NULL; if (source->nhost != 1) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Expected exactly 1 host for the storage pool")); goto cleanup; } if (!(portal = virStorageBackendISCSIPortal(source))) goto cleanup; if (virISCSIScanTargets(portal, source->initiator.iqn, &ntargets, &targets) < 0) goto cleanup; if (VIR_ALLOC_N(list.sources, ntargets) < 0) goto cleanup; for (i = 0; i < ntargets; i++) { if (VIR_ALLOC_N(list.sources[i].devices, 1) < 0 || VIR_ALLOC_N(list.sources[i].hosts, 1) < 0) goto cleanup; list.sources[i].nhost = 1; list.sources[i].hosts[0] = source->hosts[0]; list.sources[i].initiator = source->initiator; list.sources[i].ndevice = 1; list.sources[i].devices[0].path = targets[i]; list.nsources++; } if (!(ret = virStoragePoolSourceListFormat(&list))) goto cleanup; cleanup: if (list.sources) { for (i = 0; i < ntargets; i++) { VIR_FREE(list.sources[i].hosts); VIR_FREE(list.sources[i].devices); } VIR_FREE(list.sources); } for (i = 0; i < ntargets; i++) VIR_FREE(targets[i]); VIR_FREE(targets); VIR_FREE(portal); virStoragePoolSourceFree(source); return ret; } static int virStorageBackendISCSICheckPool(virStoragePoolObjPtr pool, bool *isActive) { char *session = NULL; int ret = -1; *isActive = false; if (pool->def->source.nhost != 1) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Expected exactly 1 host for the storage pool")); return -1; } if (pool->def->source.hosts[0].name == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("missing source host")); return -1; } if (pool->def->source.ndevice != 1 || pool->def->source.devices[0].path == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("missing source device")); return -1; } if ((session = virStorageBackendISCSISession(pool, true)) != NULL) { *isActive = true; VIR_FREE(session); } ret = 0; return ret; }