Repository: ansible/ansible

Issue:
XFS filesystem is incorrectly resized due to issue with finding its current size
<!---
Verify first that your issue/request is not already reported on GitHub.
Also test if the latest release, and master branch are affected too.
-->

##### ISSUE TYPE
<!--- Pick one below and delete the rest: -->
 - Bug Report

##### COMPONENT NAME
<!--- Name of the module/plugin/task/feature -->
filesystem (module)

##### ANSIBLE VERSION
<!--- Paste verbatim output from “ansible --version” between quotes below -->
```
ansible 2.2.2.0
  config file = /data/ansible.cfg
  configured module search path = Default w/o overrides
```

##### CONFIGURATION
<!---
Mention any settings you have changed/added/removed in ansible.cfg
(or using the ANSIBLE_* environment variables).
-->
N/A

##### 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.
-->
Running on and managing Ubuntu Xenial.

##### SUMMARY
<!--- Explain the problem briefly -->
The filesystem module is not idempotent when:
- `dev` ends with "data"
- fstype="xfs"
- resizefs=yes

The module will call `xfs_growfs` each time and report a change. 

This issue is caused by the [incorrect parsing of the output of `xfs_info`](https://github.com/ansible/ansible/blob/eb1214baad0cbe2c4b7304caebb9ae1c7dc0d8db/lib/ansible/modules/system/filesystem.py#L100-L108):
```python
# Get Block count and Block size
rc, size, err = module.run_command("%s %s" % (cmd, dev))
if rc == 0:
    for line in size.splitlines():
        #if 'data' in line:
        if 'data ' in line:
            block_size = int(line.split('=')[2].split()[0])
            block_count = int(line.split('=')[3].split(',')[0])
            break
```
The code assumes that the first output line with the string "data ", contains the information required to calculate the current size. However, the parser incorrectly identifies this line if `dev` ends with "data". There are then no checks that the values read correspond to the block size and count.



##### STEPS TO REPRODUCE
<!---
For bugs, show exactly how to reproduce the problem, using a minimal test-case.
For new features, show how the feature would be used.
-->

<!--- Paste example playbooks or commands between quotes below -->
```yaml
- become: yes
  filesystem: dev="/dev/consul-vg/consul-data" fstype=xfs resizefs=yes
```

On the machine, after it has been configured:
```bash
$ xfs_info /dev/mapper/consul--vg-consul--data  
meta-data=/dev/mapper/consul--vg-consul--data isize=512    agcount=4, agsize=655104 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1 spinodes=0
data     =                       bsize=4096   blocks=2620416, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=1
log      =internal               bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
```

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->
Idempotence.

##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->
Filesystem is resized each time due to incorrect identification of its current block size/count.



Discussion:
cc @abulimov
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->

Resolving patch:
diff --git a/lib/ansible/modules/system/filesystem.py b/lib/ansible/modules/system/filesystem.py
--- a/lib/ansible/modules/system/filesystem.py
+++ b/lib/ansible/modules/system/filesystem.py
@@ -101,10 +101,10 @@ def _get_fs_size(fssize_cmd, dev, module):
         rc, size, err = module.run_command("%s %s" % (cmd, dev))
         if rc == 0:
             for line in size.splitlines():
-                #if 'data' in line:
-                if 'data ' in line:
-                    block_size = int(line.split('=')[2].split()[0])
-                    block_count = int(line.split('=')[3].split(',')[0])
+                col = line.split('=')
+                if col[0].strip() == 'data':
+                    block_size = int(col[2].split()[0])
+                    block_count = int(col[3].split(',')[0])
                     break
         else:
             module.fail_json(msg="Failed to get block count and block size of %s with %s" % (dev, cmd), rc=rc, err=err )


Test patch: