The Linux iSCSI initiator toolchain has the dubious feature that if you ever run the 'sendtargets' command to merely query what targets are available from a server, the results will be recorded in /var/lib/iscsi. Any time the '/etc/init.d/iscsi' script runs in the future, it will then automatically login to all those targets. /etc/init.d/iscsi is automatically run whenever a NIC comes online. So from the moment you ask a server what targets are available, your client will forever more automatically try to login to all targets without ever asking if you actually want it todo this. To stop this stupid behaviour, we need to run iscsiadm --portal $PORTAL --target $TARGET --op update --name node.startup --value manual For every target on the server. * src/storage/storage_backend_iscsi.c: Disable automatic login for targets found as a result of a 'sendtargets' command --- src/storage/storage_backend_iscsi.c | 120 +++++++++++++++++++++++++++++++++-- 1 files changed, 113 insertions(+), 7 deletions(-) diff --git a/src/storage/storage_backend_iscsi.c b/src/storage/storage_backend_iscsi.c index 51f71af..2a36527 100644 --- a/src/storage/storage_backend_iscsi.c +++ b/src/storage/storage_backend_iscsi.c @@ -450,19 +450,123 @@ virStorageBackendISCSIRescanLUNs(virStoragePoolObjPtr pool ATTRIBUTE_UNUSED, return 0; } +struct virStorageBackendISCSITargetList { + size_t ntargets; + char **targets; +}; + +static int +virStorageBackendISCSIGetTargets(virStoragePoolObjPtr pool ATTRIBUTE_UNUSED, + char **const groups, + void *data) +{ + struct virStorageBackendISCSITargetList *list = data; + char *target; + + if (!(target = strdup(groups[1]))) { + virReportOOMError(); + return -1; + } + + if (VIR_REALLOC_N(list->targets, list->ntargets + 1) < 0) { + VIR_FREE(target); + virReportOOMError(); + return -1; + } + + list->targets[list->ntargets] = target; + list->ntargets++; + + return 0; +} + +static int +virStorageBackendISCSITargetAutologin(const char *portal, + const char *initiatoriqn, + const char *target, + bool enable) +{ + const char *extraargv[] = { "--op", "update", + "--name", "node.startup", + "--value", enable ? "automatic" : "manual", + NULL }; + + return virStorageBackendISCSIConnection(portal, initiatoriqn, target, extraargv); +} + static int -virStorageBackendISCSIScanTargets(const char *portal) +virStorageBackendISCSIScanTargets(const char *portal, + const char *initiatoriqn, + size_t *ntargetsret, + char ***targetsret) { - const char *const sendtargets[] = { - ISCSIADM, "--mode", "discovery", "--type", "sendtargets", "--portal", portal, NULL + /** + * + * 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 }; - if (virRun(sendtargets, NULL) < 0) { + struct virStorageBackendISCSITargetList list; + int i; + int exitstatus; + + memset(&list, 0, sizeof(list)); + + if (virStorageBackendRunProgRegex(NULL, /* No pool for callback */ + cmdsendtarget, + 1, + regexes, + vars, + virStorageBackendISCSIGetTargets, + &list, + &exitstatus) < 0) { virStorageReportError(VIR_ERR_INTERNAL_ERROR, - _("Failed to run %s to get target list"), - sendtargets[0]); + "%s", _("lvs command failed")); + return -1; + } + + if (exitstatus != 0) { + virStorageReportError(VIR_ERR_INTERNAL_ERROR, + _("iscsiadm sendtargets command failed with exitstatus %d"), + exitstatus); 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; } @@ -496,7 +600,9 @@ virStorageBackendISCSIStartPool(virConnectPtr conn ATTRIBUTE_UNUSED, * iscsiadm doesn't let you login to a target, unless you've * first issued a 'sendtargets' command to the portal :-( */ - if (virStorageBackendISCSIScanTargets(portal) < 0) + if (virStorageBackendISCSIScanTargets(portal, + pool->def->source.initiator.iqn, + NULL, NULL) < 0) goto cleanup; if (virStorageBackendISCSIConnection(portal, -- 1.7.2.3 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list