Repository: ansible/ansible

Issue:
lvol fails with ValueError
##### ISSUE TYPE
 - Bug Report


##### COMPONENT NAME

lvol

##### ANSIBLE VERSION
<!--- Paste verbatim output from "ansible --version" between quotes below -->
```
ansible 2.3.2.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = Default w/o overrides
  python version = 2.7.5 (default, Jun 17 2014, 18:11:42) [GCC 4.8.2 20140120 (Red Hat 4.8.2-16)]
```

##### CONFIGURATION
<!---
If using Ansible 2.4 or above, paste the results of "ansible-config dump --only-changed"

Otherwise, mention any settings you have changed/added/removed in ansible.cfg
(or using the ANSIBLE_* environment variables).

-->

##### OS / ENVIRONMENT

Linux 3.10.0-229.el7.x86_64 #1 SMP Fri Mar 6 11:36:42 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

##### SUMMARY
<!--- Explain the problem briefly -->

The lvol module is not idempotent with the size of a partition when it's not exactly an integer


##### 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
- name: Create infravg volume
  lvg:
     vg: "infravg"
     pvs: "/dev/sdb"

- name: Create logical volumes
  lvol:
    vg: "infravg"
    lv: "myvolume"
    size: "9.8"

- name: Create filesystem
  filesystem:
    fstype: ext4
    dev: /dev/infravg/myvolume

- name: Mount logical volume
  mount:
    name: "/appli"
    src: /dev/infravg/myvolume
    fstype: ext4
    state: mounted

```

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->

Works everytime I use it.

##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->

Works on the first time, fail on the second with the following error

<!--- Paste verbatim command output between quotes below -->
```
    "module_stdout": "Traceback (most recent call last):\r\n  File \"/tmp/ansible_l98tgx/ansible_module_lvol.py\", line 497, in <module>\r\n    main()\r\n  File \"/tmp/ansible_l98tgx/ansible_module_lvol.py\", line 452, in main\r\n    elif shrink and int(size) < this_lv['size']:\r\nValueError: invalid literal for int() with base 10: '9.8'\r\n",
```



Discussion:
And considering I'm a complete noob for contributions here is the patch file I've made to correct the file ansible/modules/system/lvol.py :

```
450c450
<             if int(size) > this_lv['size']:
---
>             if float(size) > this_lv['size']:
452,453c452,453
<             elif shrink and int(size) < this_lv['size']:
<                 if int(size) == 0:
---
>             elif shrink and size < this_lv['size']:
>                 if size == 0:

```
cc @abulimov @jhoekx
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
@cyrbi Would you like to raise a PR for this change?

Resolving patch:
diff --git a/lib/ansible/modules/system/lvol.py b/lib/ansible/modules/system/lvol.py
--- a/lib/ansible/modules/system/lvol.py
+++ b/lib/ansible/modules/system/lvol.py
@@ -208,10 +208,11 @@
 '''
 
 import re
+import locale
 
 from ansible.module_utils.basic import AnsibleModule
 
-decimal_point = re.compile(r"(\d+)")
+locale.setlocale(locale.LC_ALL, '')
 
 
 def mkversion(major, minor, patch):
@@ -224,7 +225,7 @@ def parse_lvs(data):
         parts = line.strip().split(';')
         lvs.append({
             'name': parts[0].replace('[', '').replace(']', ''),
-            'size': int(decimal_point.match(parts[1]).group(1)),
+            'size': locale.atof(parts[1]),
             'active': (parts[2][4] == 'a'),
             'thinpool': (parts[2][0] == 't'),
             'thinvol': (parts[2][0] == 'V'),
@@ -238,9 +239,9 @@ def parse_vgs(data):
         parts = line.strip().split(';')
         vgs.append({
             'name': parts[0],
-            'size': int(decimal_point.match(parts[1]).group(1)),
-            'free': int(decimal_point.match(parts[2]).group(1)),
-            'ext_size': int(decimal_point.match(parts[3]).group(1))
+            'size': locale.atof(parts[1]),
+            'free': locale.atof(parts[2]),
+            'ext_size': locale.atof(parts[3])
         })
     return vgs
 
@@ -339,7 +340,7 @@ def main():
                 size = size[0:-1]
 
             try:
-                float(size)
+                locale.atof(size)
                 if not size[0].isdigit():
                     raise ValueError()
             except ValueError:
@@ -354,7 +355,7 @@ def main():
     # Get information on volume group requested
     vgs_cmd = module.get_bin_path("vgs", required=True)
     rc, current_vgs, err = module.run_command(
-        "%s --noheadings -o vg_name,size,free,vg_extent_size --units %s --separator ';' %s" % (vgs_cmd, unit, vg))
+        "%s --noheadings --nosuffix -o vg_name,size,free,vg_extent_size --units %s --separator ';' %s" % (vgs_cmd, unit, vg))
 
     if rc != 0:
         if state == 'absent':
@@ -507,10 +508,10 @@ def main():
         else:
             # resize LV based on absolute values
             tool = None
-            if int(size) > this_lv['size']:
+            if locale.atof(size) > this_lv['size']:
                 tool = module.get_bin_path("lvextend", required=True)
-            elif shrink and int(size) < this_lv['size']:
-                if int(size) == 0:
+            elif shrink and locale.atof(size) < this_lv['size']:
+                if locale.atof(size) == 0:
                     module.fail_json(msg="Sorry, no shrinking of %s to 0 permitted." % (this_lv['name']))
                 if not force:
                     module.fail_json(msg="Sorry, no shrinking of %s without force=yes." % (this_lv['name']))


Test patch: