Repository: ansible/ansible

Issue:
open_iscsi fails to login when discovery returns multiple portals
From @do11 on 2016-05-01T18:13:39Z
##### ISSUE TYPE

Maybe bug, maybe lack of feature.
##### COMPONENT NAME

open_iscsi
##### ANSIBLE VERSION

```
ansible 2.0.1.0
```
##### OS / ENVIRONMENT

Centos 7
##### SUMMARY

Sometimes, iscsi target is configured to return multiple portals with only one IP is really available. Others are firewalled or non-routed to this box.

But, even when I specify `portal=` option `open_iscsi` module does not pass it to `iscsiadm` when doing login, thus `iscsiadm`  tries to login to _all_ portals, failing to do that.
##### STEPS TO REPRODUCE

Target should have multiple portals but only one (10.10.38.1) is accessible:

```
storage# iscsiadm -m discovery -t st -p 10.10.38.1 -P 1
Target: iqn.1991-05.com.microsoft:nas2-stor-target
        Portal: 10.10.38.1:3260,1
                Iface Name: default
        Portal: 10.10.37.1:3260,1
                Iface Name: default
        Portal: 192.168.0.45:3260,1
                Iface Name: default
        Portal: [2002:c11c:2121::c111:112d]:3260,1
                Iface Name: default
```

On ansible box:

```
$ ansible storage -m open_iscsi -a 'auto_node_startup=true discover=true login=yes portal=10.10.38.1'
```
##### EXPECTED RESULTS

I expect `iscsiadm` to login only to specified portal, there is `-p` option `iscsiadm -m node --login` for that.

**Also**, `auto_node_startup=true` option should **not** mark other (ie. all) portals as `node.startup = automatic`, but only specified by `portal=` value.

If `open_iscsi` module is implemented to be always sensitive to `portal` option, It would be possible to add single iscsi target with correct portal to be logged in, and also properly marked automatic, and work w/o fatal error.
##### ACTUAL RESULTS

`iscsiadm` tries to log in via _all_ portals because `--portal` or `-p` option is not passed by `open_iscsi` module.

```
stor | FAILED! => {
    "changed": false,
    "cmd": "/usr/sbin/iscsiadm --mode node --targetname iqn.1991-05.com.microsoft:nas2-stor-target --login",
    "failed": true,
    "msg": "iscsiadm: Could not login to [iface: default, target: iqn.1991-05.com.microsoft:nas2-stor-target, portal: 10.10.37.1,3260].\niscsiadm: initiator reported error (8 - connection timed out)\niscsiadm: Could not login to [iface: default, target: iqn.1991-05.com.microsoft:nas2-stor-target, portal: 192.168.0.45,3260].\niscsiadm: initiator reported error (8 - connection timed out)\niscsiadm: Could not login to [iface: default, target: iqn.1991-05.com.microsoft:nas2-stor-target, portal: 2002:c11c:2121::c111:112d,3260].\niscsiadm: initiator reported error (8 - connection timed out)\niscsiadm: Could not log into all portals\n",
    "rc": 8
}
```

Copied from original issue: ansible/ansible-modules-extras#2137



Discussion:
From @do11 on 2016-05-01T18:13:39Z

Actually, currently I could do like this:

```
    - name: Discover iscsi
      open_iscsi: auto_node_startup=true discover=true login=yes portal=10.10.38.1
      ignore_errors: true

    - name: Delete invalid portals
      command: iscsiadm -m node -o delete
      failed_when: false
      changed_when: false
```

After valid target/portal is logged in `iscsiadm -m node -o delete` only able to delete invalid portals, because, opened session blocks deletion of valid portal, thus, it works. But, this is obviously a bit nasty.

From @srvg on 2016-05-01T18:13:39Z

Only finding out about this issue right now after an ansibot mail. Putting it on my todo list ASAP...

From @srvg on 2016-05-01T18:13:39Z

needs_contributor


Resolving patch:
diff --git a/lib/ansible/modules/system/open_iscsi.py b/lib/ansible/modules/system/open_iscsi.py
--- a/lib/ansible/modules/system/open_iscsi.py
+++ b/lib/ansible/modules/system/open_iscsi.py
@@ -171,7 +171,7 @@ def target_loggedon(module, target):
         module.fail_json(cmd=cmd, rc=rc, msg=err)
 
 
-def target_login(module, target):
+def target_login(module, target, portal=None, port=None):
     node_auth = module.params['node_auth']
     node_user = module.params['node_user']
     node_pass = module.params['node_pass']
@@ -187,6 +187,9 @@ def target_login(module, target):
                 module.fail_json(cmd=cmd, rc=rc, msg=err)
 
     cmd = '%s --mode node --targetname %s --login' % (iscsiadm_cmd, target)
+    if portal is not None and port is not None:
+        cmd += ' --portal %s:%s' % (portal, port)
+
     (rc, out, err) = module.run_command(cmd)
 
     if rc > 0:
@@ -333,7 +336,7 @@ def main():
                 result['devicenodes'] = target_device_node(module, target)
         elif not check:
             if login:
-                target_login(module, target)
+                target_login(module, target, portal, port)
                 # give udev some time
                 time.sleep(1)
                 result['devicenodes'] = target_device_node(module, target)


Test patch: