Repository: ansible/ansible-modules-core

Issue:
mount module can't update flags on a mounted FS on OpenBSD
<!--- Verify first that your issue/request is not already reported in GitHub -->

##### ISSUE TYPE
<!--- Pick one below and delete the rest: -->
 - Bug Report


##### COMPONENT NAME
<!--- Name of the plugin/module/task -->
mount module

##### ANSIBLE VERSION
<!--- Paste verbatim output from “ansible --version” between quotes below -->
```
ansible 2.2.0.0
```

##### CONFIGURATION
<!---
Mention any settings you have changed/added/removed in ansible.cfg
(or using the ANSIBLE_* environment variables).
-->

##### OS / ENVIRONMENT
<!---
Mention the OS you are running Ansible from, and the OS you are
managing, or say “N/A” for anything that is not platform-specific.
-->
OpenBSD

##### SUMMARY
<!--- Explain the problem briefly -->
https://github.com/ansible/ansible-modules-core/blob/devel/system/mount.py#L319 uses `-o remount`, which doesn't exist on OpenBSD. if you try to update the flags for an existing mountpoint, it will update fstab correctly, but then will try to remount/update the flags on the living FS, and mount module will fail.
##### STEPS TO REPRODUCE
<!---
For bugs, show exactly how to reproduce the problem.
For new features, show how the feature would be used.
-->

<!--- Paste example playbooks or commands between quotes below -->
```
#grep local /etc/fstab                                                                                       
/dev/wd0g /usr/local ffs rw,wxallowed 0 0

#ansible master -m mount -a 'name=/usr/local opts=rw,wxallowed,nosuid state=mounted fstype=ffs src=/dev/wd0g'
master | FAILED! => {
    "changed": false, 
    "failed": true, 
    "msg": "Error mounting /usr/local: mount_ffs: -o remount: option not supported\n"
}
#grep local /etc/fstab                                                                                       
/dev/wd0g /usr/local ffs rw,wxallowed,nosuid 0 0
#mount |grep /usr/local
/dev/wd0g on /usr/local type ffs (local, wxallowed)
```

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->
the living FS should have seen its opts updated.
##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->
mount module failed...  a possible fix would be to use `mount -u` which is more or less the equivalent of `mount -o remount`
<!--- Paste verbatim command output between quotes below -->
```
#mount -u -o nosuid /usr/local
#mount |grep /usr/local       
/dev/wd0g on /usr/local type ffs (local, nosuid, wxallowed)

```



Discussion:
<!-- @landryb: Thanks for filing this bug report! -->

@ansible ping, this issue is waiting for your response.
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)

<!--- boilerplate: issue_bug_new --->

The relevant commit is a backport of a different patch
https://github.com/ansible/ansible-modules-core/commit/d843204575952a57e7e866bf21f93d6eb957ce04

> The relevant commit is a backport of a different patch
> d843204

Interesting, but that still uses `-o remount`...
This should be fixed by the inclusion of these two PRs: https://github.com/ansible/ansible-modules-core/pull/2445  https://github.com/ansible/ansible-modules-core/pull/5673

if you can confirm that latest devel or latest stable-2.2 work, that would be great.  If you can't I'll close this in a few days.  It works with my tests on FreeBSD (which also uses -u for remount).

needs_info
Tried with 2.2.1.0-0.1.rc1 (not sure it has those two PRs), there's no error message, but the living FS isn't updated.

before:
```
$mount|grep sd0d ; grep sd0d /etc/fstab  
/dev/sd0d on /home type ffs (local, nodev, nosuid)
/dev/sd0d /home ffs rw,nodev,nosuid 1 2
```
ansible invocation with local connection:
```
$doas ansible -vvvv -c local localhost -m mount -a 'name=/home opts=rw,nodev,nosuid,wxallowed state=mounted fstype=ffs src=/dev/sd0d dump=1 passno=2'

Using /etc/ansible/ansible.cfg as config file
 [WARNING]: provided hosts list is empty, only localhost is available

Loading callback plugin minimal of type stdout, v2.0 from /usr/local/lib/python2.7/site-packages/ansible/plugins/callback/__init__.pyc
Using module file /usr/local/lib/python2.7/site-packages/ansible/modules/core/system/mount.py
<127.0.0.1> ESTABLISH LOCAL CONNECTION FOR USER: landry
<127.0.0.1> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo $HOME/.ansible/tmp/ansible-tmp-1479806309.65-74141033850670 `" && echo ansible-tmp-1479806309.65-74141033850670="` echo $HOME/.ansible/tmp/ansible-tmp-1479806309.65-74141033850670 `" ) && sleep 0'
<127.0.0.1> PUT /tmp/tmp2QsDsI TO /home/landry/.ansible/tmp/ansible-tmp-1479806309.65-74141033850670/mount.py
<127.0.0.1> EXEC /bin/sh -c 'chmod u+x /home/landry/.ansible/tmp/ansible-tmp-1479806309.65-74141033850670/ /home/landry/.ansible/tmp/ansible-tmp-1479806309.65-74141033850670/mount.py && sleep 0'
<127.0.0.1> EXEC /bin/sh -c '/usr/local/bin/python2.7 /home/landry/.ansible/tmp/ansible-tmp-1479806309.65-74141033850670/mount.py; rm -rf "/home/landry/.ansible/tmp/ansible-tmp-1479806309.65-74141033850670/" > /dev/null 2>&1 && sleep 0'
localhost | SUCCESS => {
    "changed": true, 
    "dump": "1", 
    "fstab": "/etc/fstab", 
    "fstype": "ffs", 
    "invocation": {
        "module_args": {
            "boot": "yes", 
            "dump": "1", 
            "fstab": "/etc/fstab", 
            "fstype": "ffs", 
            "name": "/home", 
            "opts": "rw,nodev,nosuid,wxallowed", 
            "passno": "2", 
            "src": "/dev/sd0d", 
            "state": "mounted"
        }, 
        "module_name": "mount"
    }, 
    "name": "/home", 
    "opts": "rw,nodev,nosuid,wxallowed", 
    "passno": "2", 
    "src": "/dev/sd0d"
}

```
after:
```
$mount|grep sd0d ; grep sd0d /etc/fstab                                              
/dev/sd0d on /home type ffs (local, nodev, nosuid)
/dev/sd0d /home ffs rw,nodev,nosuid,wxallowed 1 2
```
According to https://github.com/ansible/ansible-modules-core/commits/stable-2.2 2.2.1.0-0.1.rc1 should have those two PRs, so.. i'm puzzled.
Same thing using ` -b --become-method=doas` instead of `doas ansible`
@landryb  What happens if you run "doas mount -u -F/etc/fstab /dev/sd0d" (which is what ansible is going to attempt first to remount on openbsd)?
Well.. on freebsd10 ```mount -u``` seems inconsistently broken...
* fstab has:
> /dev/ada0p3    /tmp    ufs    rw,nosuid     2 2
* mounted by boot
* Confirmed that nosuid was in the live mount options by running mount and checking output
* Removed ```,nosuid``` from the fstab line
* Ran mount -u -F /etc/fstab /dev/ada0p3
* Comfirmed that nosuid had been removed from the live mount.
* Re-added ```,nosuid``` to the fstab line
* Ran mount -u -F /etc/fstab /dev/ada0p3
* ```,nosuid``` **was not** added to the live mount options.

So between FreeBSD's behaviour and your report on OpenBSD I'm guessing that remounting with options specified in /etc/fstab is buggy and can't be relied on.  I'll change the code to always explicitly umount and then mount filesystems when changing the options on the *BSDs... That is not ideal as a filesystem in-use can't be unmounted (and at least some platforms allow remounting with different options in this case) but it's probably the best we can do in the short term.

Longer term, somebody could rewrite the mount module (or write a new mount module) which had a cleaner separation between fstab modification and adhoc mounting.  The adhoc mounting case (specifying the new mount options via "-o" on the command line)  appears to work on freebsd10.  I don't know if it works or not on other platforms.

Resolving patch:
diff --git a/system/mount.py b/system/mount.py
--- a/system/mount.py
+++ b/system/mount.py
@@ -366,16 +366,26 @@ def remount(module, mount_bin, args):
 
     cmd += _set_fstab_args(args)
     cmd += [ args['name'], ]
+    out = err = ''
     try:
-        rc, out, err = module.run_command(cmd)
+        if get_platform().lower().endswith('bsd'):
+            # Note: Forcing BSDs to do umount/mount due to BSD remount not
+            # working as expected (suspect bug in the BSD mount command)
+            # Interested contributor could rework this to use mount options on
+            # the CLI instead of relying on fstab
+            # https://github.com/ansible/ansible-modules-core/issues/5591
+            rc = 1
+        else:
+            rc, out, err = module.run_command(cmd)
     except:
         rc = 1
+
     if rc != 0:
-        msg = out+err
+        msg = out + err
         if ismount(args['name']):
             rc, msg = umount(module, args['name'])
         if rc == 0:
-            rc,msg = mount(module, args)
+            rc, msg = mount(module, args)
     return rc, msg
 
 # Note if we wanted to put this into module_utils we'd have to get permission


Test patch: