From faa575afb54b7534d57c06b1ab6e56881eee0a3b Mon Sep 17 00:00:00 2001
From: Rene Moser <mail@renemoser.net>
Date: Tue, 22 Sep 2015 16:28:14 +0200
Subject: [PATCH] cloudstack: implement common argument spec handling

---
 cloud/cloudstack/cs_account.py            | 41 +++++------
 cloud/cloudstack/cs_affinitygroup.py      | 31 ++++-----
 cloud/cloudstack/cs_domain.py             | 27 +++-----
 cloud/cloudstack/cs_firewall.py           | 51 +++++++-------
 cloud/cloudstack/cs_instance.py           | 83 +++++++++++------------
 cloud/cloudstack/cs_instancegroup.py      | 27 +++-----
 cloud/cloudstack/cs_ip_address.py         | 33 ++++-----
 cloud/cloudstack/cs_iso.py                | 45 ++++++------
 cloud/cloudstack/cs_network.py            | 70 ++++++++++---------
 cloud/cloudstack/cs_portforward.py        | 47 ++++++-------
 cloud/cloudstack/cs_project.py            | 29 ++++----
 cloud/cloudstack/cs_securitygroup.py      | 25 +++----
 cloud/cloudstack/cs_securitygroup_rule.py | 46 ++++++-------
 cloud/cloudstack/cs_sshkeypair.py         | 29 ++++----
 cloud/cloudstack/cs_staticnat.py          | 35 ++++------
 cloud/cloudstack/cs_template.py           | 81 +++++++++++-----------
 cloud/cloudstack/cs_user.py               | 37 +++++-----
 cloud/cloudstack/cs_vmsnapshot.py         | 43 ++++++------
 18 files changed, 356 insertions(+), 424 deletions(-)

diff --git a/cloud/cloudstack/cs_account.py b/cloud/cloudstack/cs_account.py
index 2ffecf06fcf..839f6e53281 100644
--- a/cloud/cloudstack/cs_account.py
+++ b/cloud/cloudstack/cs_account.py
@@ -343,30 +343,25 @@ class AnsibleCloudStackAccount(AnsibleCloudStack):
 
 
 def main():
+    argument_spec = cs_argument_spec()
+    argument_spec.update(dict(
+        name = dict(required=True),
+        state = dict(choices=['present', 'absent', 'enabled', 'disabled', 'locked', 'unlocked'], default='present'),
+        account_type = dict(choices=['user', 'root_admin', 'domain_admin'], default='user'),
+        network_domain = dict(default=None),
+        domain = dict(default='ROOT'),
+        email = dict(default=None),
+        first_name = dict(default=None),
+        last_name = dict(default=None),
+        username = dict(default=None),
+        password = dict(default=None),
+        timezone = dict(default=None),
+        poll_async = dict(choices=BOOLEANS, default=True),
+    ))
+
     module = AnsibleModule(
-        argument_spec = dict(
-            name = dict(required=True),
-            state = dict(choices=['present', 'absent', 'enabled', 'disabled', 'locked', 'unlocked'], default='present'),
-            account_type = dict(choices=['user', 'root_admin', 'domain_admin'], default='user'),
-            network_domain = dict(default=None),
-            domain = dict(default='ROOT'),
-            email = dict(default=None),
-            first_name = dict(default=None),
-            last_name = dict(default=None),
-            username = dict(default=None),
-            password = dict(default=None),
-            timezone = dict(default=None),
-            poll_async = dict(choices=BOOLEANS, default=True),
-            api_key = dict(default=None),
-            api_secret = dict(default=None, no_log=True),
-            api_url = dict(default=None),
-            api_http_method = dict(choices=['get', 'post'], default='get'),
-            api_timeout = dict(type='int', default=10),
-            api_region = dict(default='cloudstack'),
-        ),
-        required_together = (
-            ['api_key', 'api_secret', 'api_url'],
-        ),
+        argument_spec=argument_spec,
+        required_together=cs_required_together(),
         supports_check_mode=True
     )
 
diff --git a/cloud/cloudstack/cs_affinitygroup.py b/cloud/cloudstack/cs_affinitygroup.py
index 8a2f40fae62..5a7cb5f9714 100644
--- a/cloud/cloudstack/cs_affinitygroup.py
+++ b/cloud/cloudstack/cs_affinitygroup.py
@@ -201,25 +201,20 @@ class AnsibleCloudStackAffinityGroup(AnsibleCloudStack):
 
 
 def main():
+    argument_spec = cs_argument_spec()
+    argument_spec.update(dict(
+        name = dict(required=True),
+        affinty_type = dict(default=None),
+        description = dict(default=None),
+        state = dict(choices=['present', 'absent'], default='present'),
+        domain = dict(default=None),
+        account = dict(default=None),
+        poll_async = dict(choices=BOOLEANS, default=True),
+    ))
+
     module = AnsibleModule(
-        argument_spec = dict(
-            name = dict(required=True),
-            affinty_type = dict(default=None),
-            description = dict(default=None),
-            state = dict(choices=['present', 'absent'], default='present'),
-            domain = dict(default=None),
-            account = dict(default=None),
-            poll_async = dict(choices=BOOLEANS, default=True),
-            api_key = dict(default=None),
-            api_secret = dict(default=None, no_log=True),
-            api_url = dict(default=None),
-            api_http_method = dict(choices=['get', 'post'], default='get'),
-            api_timeout = dict(type='int', default=10),
-            api_region = dict(default='cloudstack'),
-        ),
-        required_together = (
-            ['api_key', 'api_secret', 'api_url'],
-        ),
+        argument_spec=argument_spec,
+        required_together=cs_required_together(),
         supports_check_mode=True
     )
 
diff --git a/cloud/cloudstack/cs_domain.py b/cloud/cloudstack/cs_domain.py
index 94299d5d6a3..0d8b7deaab4 100644
--- a/cloud/cloudstack/cs_domain.py
+++ b/cloud/cloudstack/cs_domain.py
@@ -239,23 +239,18 @@ class AnsibleCloudStackDomain(AnsibleCloudStack):
 
 
 def main():
+    argument_spec = cs_argument_spec()
+    argument_spec.update(dict(
+        path = dict(required=True),
+        state = dict(choices=['present', 'absent'], default='present'),
+        network_domain = dict(default=None),
+        clean_up = dict(choices=BOOLEANS, default=False),
+        poll_async = dict(choices=BOOLEANS, default=True),
+    ))
+
     module = AnsibleModule(
-        argument_spec = dict(
-            path = dict(required=True),
-            state = dict(choices=['present', 'absent'], default='present'),
-            network_domain = dict(default=None),
-            clean_up = dict(choices=BOOLEANS, default=False),
-            poll_async = dict(choices=BOOLEANS, default=True),
-            api_key = dict(default=None),
-            api_secret = dict(default=None, no_log=True),
-            api_url = dict(default=None),
-            api_http_method = dict(choices=['get', 'post'], default='get'),
-            api_timeout = dict(type='int', default=10),
-            api_region = dict(default='cloudstack'),
-        ),
-        required_together = (
-            ['api_key', 'api_secret', 'api_url'],
-        ),
+        argument_spec=argument_spec,
+        required_together=cs_required_together(),
         supports_check_mode=True
     )
 
diff --git a/cloud/cloudstack/cs_firewall.py b/cloud/cloudstack/cs_firewall.py
index 59a2a57e9f2..4f4c1e7895a 100644
--- a/cloud/cloudstack/cs_firewall.py
+++ b/cloud/cloudstack/cs_firewall.py
@@ -392,36 +392,35 @@ class AnsibleCloudStackFirewall(AnsibleCloudStack):
 
 
 def main():
+    argument_spec = cs_argument_spec()
+    argument_spec.update(dict(
+        ip_address = dict(default=None),
+        network = dict(default=None),
+        cidr = dict(default='0.0.0.0/0'),
+        protocol = dict(choices=['tcp', 'udp', 'icmp', 'all'], default='tcp'),
+        type = dict(choices=['ingress', 'egress'], default='ingress'),
+        icmp_type = dict(type='int', default=None),
+        icmp_code = dict(type='int', default=None),
+        start_port = dict(type='int', aliases=['port'], default=None),
+        end_port = dict(type='int', default=None),
+        state = dict(choices=['present', 'absent'], default='present'),
+        domain = dict(default=None),
+        account = dict(default=None),
+        project = dict(default=None),
+        poll_async = dict(choices=BOOLEANS, default=True),
+    ))
+
+    required_together = cs_required_together()
+    required_together.extend([
+        ['icmp_type', 'icmp_code'],
+    ])
+
     module = AnsibleModule(
-        argument_spec = dict(
-            ip_address = dict(default=None),
-            network = dict(default=None),
-            cidr = dict(default='0.0.0.0/0'),
-            protocol = dict(choices=['tcp', 'udp', 'icmp', 'all'], default='tcp'),
-            type = dict(choices=['ingress', 'egress'], default='ingress'),
-            icmp_type = dict(type='int', default=None),
-            icmp_code = dict(type='int', default=None),
-            start_port = dict(type='int', aliases=['port'], default=None),
-            end_port = dict(type='int', default=None),
-            state = dict(choices=['present', 'absent'], default='present'),
-            domain = dict(default=None),
-            account = dict(default=None),
-            project = dict(default=None),
-            poll_async = dict(choices=BOOLEANS, default=True),
-            api_key = dict(default=None),
-            api_secret = dict(default=None, no_log=True),
-            api_url = dict(default=None),
-            api_http_method = dict(choices=['get', 'post'], default='get'),
-            api_timeout = dict(type='int', default=10),
-            api_region = dict(default='cloudstack'),
-        ),
+        argument_spec=argument_spec,
+        required_together=required_together,
         required_one_of = (
             ['ip_address', 'network'],
         ),
-        required_together = (
-            ['icmp_type', 'icmp_code'],
-            ['api_key', 'api_secret', 'api_url'],
-        ),
         mutually_exclusive = (
             ['icmp_type', 'start_port'],
             ['icmp_type', 'end_port'],
diff --git a/cloud/cloudstack/cs_instance.py b/cloud/cloudstack/cs_instance.py
index f15241f5354..3af06382d6e 100644
--- a/cloud/cloudstack/cs_instance.py
+++ b/cloud/cloudstack/cs_instance.py
@@ -819,52 +819,51 @@ class AnsibleCloudStackInstance(AnsibleCloudStack):
         return self.result
 
 def main():
+    argument_spec = cs_argument_spec()
+    argument_spec.update(dict(
+        name = dict(required=True),
+        display_name = dict(default=None),
+        group = dict(default=None),
+        state = dict(choices=['present', 'deployed', 'started', 'stopped', 'restarted', 'absent', 'destroyed', 'expunged'], default='present'),
+        service_offering = dict(default=None),
+        cpu = dict(default=None, type='int'),
+        cpu_speed = dict(default=None, type='int'),
+        memory = dict(default=None, type='int'),
+        template = dict(default=None),
+        iso = dict(default=None),
+        networks = dict(type='list', aliases=[ 'network' ], default=None),
+        ip_to_networks = dict(type='list', aliases=['ip_to_network'], default=None),
+        ip_address = dict(defaul=None),
+        ip6_address = dict(defaul=None),
+        disk_offering = dict(default=None),
+        disk_size = dict(type='int', default=None),
+        root_disk_size = dict(type='int', default=None),
+        keyboard = dict(choices=['de', 'de-ch', 'es', 'fi', 'fr', 'fr-be', 'fr-ch', 'is', 'it', 'jp', 'nl-be', 'no', 'pt', 'uk', 'us'], default=None),
+        hypervisor = dict(choices=['KVM', 'VMware', 'BareMetal', 'XenServer', 'LXC', 'HyperV', 'UCS', 'OVM', 'Simulator'], default=None),
+        security_groups = dict(type='list', aliases=[ 'security_group' ], default=[]),
+        affinity_groups = dict(type='list', aliases=[ 'affinity_group' ], default=[]),
+        domain = dict(default=None),
+        account = dict(default=None),
+        project = dict(default=None),
+        user_data = dict(default=None),
+        zone = dict(default=None),
+        ssh_key = dict(default=None),
+        force = dict(choices=BOOLEANS, default=False),
+        tags = dict(type='list', aliases=[ 'tag' ], default=None),
+        poll_async = dict(choices=BOOLEANS, default=True),
+    ))
+
+    required_together = cs_required_together()
+    required_together.extend([
+        ['cpu', 'cpu_speed', 'memory'],
+    ])
+
     module = AnsibleModule(
-        argument_spec = dict(
-            name = dict(required=True),
-            display_name = dict(default=None),
-            group = dict(default=None),
-            state = dict(choices=['present', 'deployed', 'started', 'stopped', 'restarted', 'absent', 'destroyed', 'expunged'], default='present'),
-            service_offering = dict(default=None),
-            cpu = dict(default=None, type='int'),
-            cpu_speed = dict(default=None, type='int'),
-            memory = dict(default=None, type='int'),
-            template = dict(default=None),
-            iso = dict(default=None),
-            networks = dict(type='list', aliases=[ 'network' ], default=None),
-            ip_to_networks = dict(type='list', aliases=['ip_to_network'], default=None),
-            ip_address = dict(defaul=None),
-            ip6_address = dict(defaul=None),
-            disk_offering = dict(default=None),
-            disk_size = dict(type='int', default=None),
-            root_disk_size = dict(type='int', default=None),
-            keyboard = dict(choices=['de', 'de-ch', 'es', 'fi', 'fr', 'fr-be', 'fr-ch', 'is', 'it', 'jp', 'nl-be', 'no', 'pt', 'uk', 'us'], default=None),
-            hypervisor = dict(choices=['KVM', 'VMware', 'BareMetal', 'XenServer', 'LXC', 'HyperV', 'UCS', 'OVM', 'Simulator'], default=None),
-            security_groups = dict(type='list', aliases=[ 'security_group' ], default=[]),
-            affinity_groups = dict(type='list', aliases=[ 'affinity_group' ], default=[]),
-            domain = dict(default=None),
-            account = dict(default=None),
-            project = dict(default=None),
-            user_data = dict(default=None),
-            zone = dict(default=None),
-            ssh_key = dict(default=None),
-            force = dict(choices=BOOLEANS, default=False),
-            tags = dict(type='list', aliases=[ 'tag' ], default=None),
-            poll_async = dict(choices=BOOLEANS, default=True),
-            api_key = dict(default=None),
-            api_secret = dict(default=None, no_log=True),
-            api_url = dict(default=None),
-            api_http_method = dict(choices=['get', 'post'], default='get'),
-            api_timeout = dict(type='int', default=10),
-            api_region = dict(default='cloudstack'),
-        ),
+        argument_spec=argument_spec,
+        required_together=required_together,
         mutually_exclusive = (
             ['template', 'iso'],
         ),
-        required_together = (
-            ['api_key', 'api_secret', 'api_url'],
-            ['cpu', 'cpu_speed', 'memory'],
-        ),
         supports_check_mode=True
     )
 
diff --git a/cloud/cloudstack/cs_instancegroup.py b/cloud/cloudstack/cs_instancegroup.py
index f3ac8e4caa8..4ffda0ede1a 100644
--- a/cloud/cloudstack/cs_instancegroup.py
+++ b/cloud/cloudstack/cs_instancegroup.py
@@ -170,23 +170,18 @@ class AnsibleCloudStackInstanceGroup(AnsibleCloudStack):
 
 
 def main():
+    argument_spec = cs_argument_spec()
+    argument_spec.update(dict(
+        name = dict(required=True),
+        state = dict(default='present', choices=['present', 'absent']),
+        domain = dict(default=None),
+        account = dict(default=None),
+        project = dict(default=None),
+    ))
+
     module = AnsibleModule(
-        argument_spec = dict(
-            name = dict(required=True),
-            state = dict(default='present', choices=['present', 'absent']),
-            domain = dict(default=None),
-            account = dict(default=None),
-            project = dict(default=None),
-            api_key = dict(default=None),
-            api_secret = dict(default=None, no_log=True),
-            api_url = dict(default=None),
-            api_http_method = dict(choices=['get', 'post'], default='get'),
-            api_timeout = dict(type='int', default=10),
-            api_region = dict(default='cloudstack'),
-        ),
-        required_together = (
-            ['api_key', 'api_secret', 'api_url'],
-        ),
+        argument_spec=argument_spec,
+        required_together=cs_required_together(),
         supports_check_mode=True
     )
 
diff --git a/cloud/cloudstack/cs_ip_address.py b/cloud/cloudstack/cs_ip_address.py
index 3e55b9f4be1..1be597fd8cb 100644
--- a/cloud/cloudstack/cs_ip_address.py
+++ b/cloud/cloudstack/cs_ip_address.py
@@ -224,26 +224,21 @@ class AnsibleCloudStackIPAddress(AnsibleCloudStack):
 
 
 def main():
+    argument_spec = cs_argument_spec()
+    argument_spec.update(dict(
+        ip_address = dict(required=False),
+        state = dict(choices=['present', 'absent'], default='present'),
+        zone = dict(default=None),
+        domain = dict(default=None),
+        account = dict(default=None),
+        network = dict(default=None),
+        project = dict(default=None),
+        poll_async = dict(choices=BOOLEANS, default=True),
+    ))
+
     module = AnsibleModule(
-        argument_spec = dict(
-            ip_address = dict(required=False),
-            state = dict(choices=['present', 'absent'], default='present'),
-            zone = dict(default=None),
-            domain = dict(default=None),
-            account = dict(default=None),
-            network = dict(default=None),
-            project = dict(default=None),
-            poll_async = dict(choices=BOOLEANS, default=True),
-            api_key = dict(default=None),
-            api_secret = dict(default=None, no_log=True),
-            api_url = dict(default=None),
-            api_http_method = dict(choices=['get', 'post'], default='get'),
-            api_timeout = dict(type='int', default=10),
-            api_region = dict(default='cloudstack'),
-        ),
-        required_together = (
-            ['api_key', 'api_secret', 'api_url'],
-        ),
+        argument_spec=argument_spec,
+        required_together=cs_required_together(),
         supports_check_mode=True
     )
 
diff --git a/cloud/cloudstack/cs_iso.py b/cloud/cloudstack/cs_iso.py
index 4ce1804c762..98a06f6cd96 100644
--- a/cloud/cloudstack/cs_iso.py
+++ b/cloud/cloudstack/cs_iso.py
@@ -295,32 +295,27 @@ class AnsibleCloudStackIso(AnsibleCloudStack):
 
 
 def main():
+    argument_spec = cs_argument_spec()
+    argument_spec.update(dict(
+        name = dict(required=True),
+        url = dict(default=None),
+        os_type = dict(default=None),
+        zone = dict(default=None),
+        iso_filter = dict(default='self', choices=[ 'featured', 'self', 'selfexecutable','sharedexecutable','executable', 'community' ]),
+        domain = dict(default=None),
+        account = dict(default=None),
+        project = dict(default=None),
+        checksum = dict(default=None),
+        is_ready = dict(choices=BOOLEANS, default=False),
+        bootable = dict(choices=BOOLEANS, default=True),
+        is_featured = dict(choices=BOOLEANS, default=False),
+        is_dynamically_scalable = dict(choices=BOOLEANS, default=False),
+        state = dict(choices=['present', 'absent'], default='present'),
+    ))
+
     module = AnsibleModule(
-        argument_spec = dict(
-            name = dict(required=True),
-            url = dict(default=None),
-            os_type = dict(default=None),
-            zone = dict(default=None),
-            iso_filter = dict(default='self', choices=[ 'featured', 'self', 'selfexecutable','sharedexecutable','executable', 'community' ]),
-            domain = dict(default=None),
-            account = dict(default=None),
-            project = dict(default=None),
-            checksum = dict(default=None),
-            is_ready = dict(choices=BOOLEANS, default=False),
-            bootable = dict(choices=BOOLEANS, default=True),
-            is_featured = dict(choices=BOOLEANS, default=False),
-            is_dynamically_scalable = dict(choices=BOOLEANS, default=False),
-            state = dict(choices=['present', 'absent'], default='present'),
-            api_key = dict(default=None),
-            api_secret = dict(default=None, no_log=True),
-            api_url = dict(default=None),
-            api_http_method = dict(choices=['get', 'post'], default='get'),
-            api_timeout = dict(type='int', default=10),
-            api_region = dict(default='cloudstack'),
-        ),
-        required_together = (
-            ['api_key', 'api_secret', 'api_url'],
-        ),
+        argument_spec=argument_spec,
+        required_together=cs_required_together(),
         supports_check_mode=True
     )
 
diff --git a/cloud/cloudstack/cs_network.py b/cloud/cloudstack/cs_network.py
index 1cb97bf86ea..6dea3dd3ca6 100644
--- a/cloud/cloudstack/cs_network.py
+++ b/cloud/cloudstack/cs_network.py
@@ -522,43 +522,41 @@ class AnsibleCloudStackNetwork(AnsibleCloudStack):
 
 
 def main():
+    argument_spec = cs_argument_spec()
+    argument_spec.update(dict(
+        name = dict(required=True),
+        display_text = dict(default=None),
+        network_offering = dict(default=None),
+        zone = dict(default=None),
+        start_ip = dict(default=None),
+        end_ip = dict(default=None),
+        gateway = dict(default=None),
+        netmask = dict(default=None),
+        start_ipv6 = dict(default=None),
+        end_ipv6 = dict(default=None),
+        cidr_ipv6 = dict(default=None),
+        gateway_ipv6 = dict(default=None),
+        vlan = dict(default=None),
+        vpc = dict(default=None),
+        isolated_pvlan = dict(default=None),
+        clean_up = dict(type='bool', choices=BOOLEANS, default=False),
+        network_domain = dict(default=None),
+        state = dict(choices=['present', 'absent', 'restarted' ], default='present'),
+        acl_type = dict(choices=['account', 'domain'], default='account'),
+        project = dict(default=None),
+        domain = dict(default=None),
+        account = dict(default=None),
+        poll_async = dict(type='bool', choices=BOOLEANS, default=True),
+    ))
+    required_together = cs_required_together()
+    required_together.extend([
+        ['start_ip', 'netmask', 'gateway'],
+        ['start_ipv6', 'cidr_ipv6', 'gateway_ipv6'],
+    ])
+
     module = AnsibleModule(
-        argument_spec = dict(
-            name = dict(required=True),
-            display_text = dict(default=None),
-            network_offering = dict(default=None),
-            zone = dict(default=None),
-            start_ip = dict(default=None),
-            end_ip = dict(default=None),
-            gateway = dict(default=None),
-            netmask = dict(default=None),
-            start_ipv6 = dict(default=None),
-            end_ipv6 = dict(default=None),
-            cidr_ipv6 = dict(default=None),
-            gateway_ipv6 = dict(default=None),
-            vlan = dict(default=None),
-            vpc = dict(default=None),
-            isolated_pvlan = dict(default=None),
-            clean_up = dict(type='bool', choices=BOOLEANS, default=False),
-            network_domain = dict(default=None),
-            state = dict(choices=['present', 'absent', 'restarted' ], default='present'),
-            acl_type = dict(choices=['account', 'domain'], default='account'),
-            project = dict(default=None),
-            domain = dict(default=None),
-            account = dict(default=None),
-            poll_async = dict(type='bool', choices=BOOLEANS, default=True),
-            api_key = dict(default=None),
-            api_secret = dict(default=None, no_log=True),
-            api_url = dict(default=None),
-            api_http_method = dict(choices=['get', 'post'], default='get'),
-            api_timeout = dict(type='int', default=10),
-            api_region = dict(default='cloudstack'),
-        ),
-        required_together = (
-            ['api_key', 'api_secret', 'api_url'],
-            ['start_ip', 'netmask', 'gateway'],
-            ['start_ipv6', 'cidr_ipv6', 'gateway_ipv6'],
-        ),
+        argument_spec=argument_spec,
+        required_together=required_together,
         supports_check_mode=True
     )
 
diff --git a/cloud/cloudstack/cs_portforward.py b/cloud/cloudstack/cs_portforward.py
index df867915a07..555f30e54b3 100644
--- a/cloud/cloudstack/cs_portforward.py
+++ b/cloud/cloudstack/cs_portforward.py
@@ -368,33 +368,28 @@ class AnsibleCloudStackPortforwarding(AnsibleCloudStack):
 
 
 def main():
+    argument_spec = cs_argument_spec()
+    argument_spec.update(dict(
+        ip_address = dict(required=True),
+        protocol= dict(choices=['tcp', 'udp'], default='tcp'),
+        public_port = dict(type='int', required=True),
+        public_end_port = dict(type='int', default=None),
+        private_port = dict(type='int', required=True),
+        private_end_port = dict(type='int', default=None),
+        state = dict(choices=['present', 'absent'], default='present'),
+        open_firewall = dict(choices=BOOLEANS, default=False),
+        vm_guest_ip = dict(default=None),
+        vm = dict(default=None),
+        zone = dict(default=None),
+        domain = dict(default=None),
+        account = dict(default=None),
+        project = dict(default=None),
+        poll_async = dict(choices=BOOLEANS, default=True),
+    ))
+
     module = AnsibleModule(
-        argument_spec = dict(
-            ip_address = dict(required=True),
-            protocol= dict(choices=['tcp', 'udp'], default='tcp'),
-            public_port = dict(type='int', required=True),
-            public_end_port = dict(type='int', default=None),
-            private_port = dict(type='int', required=True),
-            private_end_port = dict(type='int', default=None),
-            state = dict(choices=['present', 'absent'], default='present'),
-            open_firewall = dict(choices=BOOLEANS, default=False),
-            vm_guest_ip = dict(default=None),
-            vm = dict(default=None),
-            zone = dict(default=None),
-            domain = dict(default=None),
-            account = dict(default=None),
-            project = dict(default=None),
-            poll_async = dict(choices=BOOLEANS, default=True),
-            api_key = dict(default=None),
-            api_secret = dict(default=None, no_log=True),
-            api_url = dict(default=None),
-            api_http_method = dict(choices=['get', 'post'], default='get'),
-            api_timeout = dict(type='int', default=10),
-            api_region = dict(default='cloudstack'),
-        ),
-        required_together = (
-            ['api_key', 'api_secret', 'api_url'],
-        ),
+        argument_spec=argument_spec,
+        required_together=cs_required_together(),
         supports_check_mode=True
     )
 
diff --git a/cloud/cloudstack/cs_project.py b/cloud/cloudstack/cs_project.py
index a7468e63118..504fefc6f0c 100644
--- a/cloud/cloudstack/cs_project.py
+++ b/cloud/cloudstack/cs_project.py
@@ -259,24 +259,19 @@ class AnsibleCloudStackProject(AnsibleCloudStack):
 
 
 def main():
+    argument_spec = cs_argument_spec()
+    argument_spec.update(dict(
+        name = dict(required=True),
+        display_text = dict(default=None),
+        state = dict(choices=['present', 'absent', 'active', 'suspended' ], default='present'),
+        domain = dict(default=None),
+        account = dict(default=None),
+        poll_async = dict(type='bool', choices=BOOLEANS, default=True),
+    ))
+
     module = AnsibleModule(
-        argument_spec = dict(
-            name = dict(required=True),
-            display_text = dict(default=None),
-            state = dict(choices=['present', 'absent', 'active', 'suspended' ], default='present'),
-            domain = dict(default=None),
-            account = dict(default=None),
-            poll_async = dict(type='bool', choices=BOOLEANS, default=True),
-            api_key = dict(default=None),
-            api_secret = dict(default=None, no_log=True),
-            api_url = dict(default=None),
-            api_http_method = dict(choices=['get', 'post'], default='get'),
-            api_timeout = dict(type='int', default=10),
-            api_region = dict(default='cloudstack'),
-        ),
-        required_together = (
-            ['api_key', 'api_secret', 'api_url'],
-        ),
+        argument_spec=argument_spec,
+        required_together=cs_required_together(),
         supports_check_mode=True
     )
 
diff --git a/cloud/cloudstack/cs_securitygroup.py b/cloud/cloudstack/cs_securitygroup.py
index 3bae64b4dd9..255d306c789 100644
--- a/cloud/cloudstack/cs_securitygroup.py
+++ b/cloud/cloudstack/cs_securitygroup.py
@@ -152,22 +152,17 @@ class AnsibleCloudStackSecurityGroup(AnsibleCloudStack):
 
 
 def main():
+    argument_spec = cs_argument_spec()
+    argument_spec.update(dict(
+        name = dict(required=True),
+        description = dict(default=None),
+        state = dict(choices=['present', 'absent'], default='present'),
+        project = dict(default=None),
+    ))
+
     module = AnsibleModule(
-        argument_spec = dict(
-            name = dict(required=True),
-            description = dict(default=None),
-            state = dict(choices=['present', 'absent'], default='present'),
-            project = dict(default=None),
-            api_key = dict(default=None),
-            api_secret = dict(default=None, no_log=True),
-            api_url = dict(default=None),
-            api_http_method = dict(choices=['get', 'post'], default='get'),
-            api_timeout = dict(type='int', default=10),
-            api_region = dict(default='cloudstack'),
-        ),
-        required_together = (
-            ['api_key', 'api_secret', 'api_url'],
-        ),
+        argument_spec=argument_spec,
+        required_together=cs_required_together(),
         supports_check_mode=True
     )
 
diff --git a/cloud/cloudstack/cs_securitygroup_rule.py b/cloud/cloudstack/cs_securitygroup_rule.py
index 2c75a83d4b3..69e04ee7f92 100644
--- a/cloud/cloudstack/cs_securitygroup_rule.py
+++ b/cloud/cloudstack/cs_securitygroup_rule.py
@@ -371,31 +371,29 @@ class AnsibleCloudStackSecurityGroupRule(AnsibleCloudStack):
 
 
 def main():
+    argument_spec = cs_argument_spec()
+    argument_spec.update(dict(
+        security_group = dict(required=True),
+        type = dict(choices=['ingress', 'egress'], default='ingress'),
+        cidr = dict(default='0.0.0.0/0'),
+        user_security_group = dict(default=None),
+        protocol = dict(choices=['tcp', 'udp', 'icmp', 'ah', 'esp', 'gre'], default='tcp'),
+        icmp_type = dict(type='int', default=None),
+        icmp_code = dict(type='int', default=None),
+        start_port = dict(type='int', default=None, aliases=['port']),
+        end_port = dict(type='int', default=None),
+        state = dict(choices=['present', 'absent'], default='present'),
+        project = dict(default=None),
+        poll_async = dict(choices=BOOLEANS, default=True),
+    ))
+    required_together = cs_required_together()
+    required_together.extend([
+        ['icmp_type', 'icmp_code'],
+    ])
+
     module = AnsibleModule(
-        argument_spec = dict(
-            security_group = dict(required=True),
-            type = dict(choices=['ingress', 'egress'], default='ingress'),
-            cidr = dict(default='0.0.0.0/0'),
-            user_security_group = dict(default=None),
-            protocol = dict(choices=['tcp', 'udp', 'icmp', 'ah', 'esp', 'gre'], default='tcp'),
-            icmp_type = dict(type='int', default=None),
-            icmp_code = dict(type='int', default=None),
-            start_port = dict(type='int', default=None, aliases=['port']),
-            end_port = dict(type='int', default=None),
-            state = dict(choices=['present', 'absent'], default='present'),
-            project = dict(default=None),
-            poll_async = dict(choices=BOOLEANS, default=True),
-            api_key = dict(default=None),
-            api_secret = dict(default=None, no_log=True),
-            api_url = dict(default=None),
-            api_http_method = dict(choices=['get', 'post'], default='get'),
-            api_timeout = dict(type='int', default=10),
-            api_region = dict(default='cloudstack'),
-        ),
-        required_together = (
-            ['icmp_type', 'icmp_code'],
-            ['api_key', 'api_secret', 'api_url'],
-        ),
+        argument_spec=argument_spec,
+        required_together=required_together,
         mutually_exclusive = (
             ['icmp_type', 'start_port'],
             ['icmp_type', 'end_port'],
diff --git a/cloud/cloudstack/cs_sshkeypair.py b/cloud/cloudstack/cs_sshkeypair.py
index a6576404c3c..7e665cd62f6 100644
--- a/cloud/cloudstack/cs_sshkeypair.py
+++ b/cloud/cloudstack/cs_sshkeypair.py
@@ -205,24 +205,19 @@ class AnsibleCloudStackSshKey(AnsibleCloudStack):
 
 
 def main():
+    argument_spec = cs_argument_spec()
+    argument_spec.update(dict(
+        name = dict(required=True),
+        public_key = dict(default=None),
+        domain = dict(default=None),
+        account = dict(default=None),
+        project = dict(default=None),
+        state = dict(choices=['present', 'absent'], default='present'),
+    ))
+
     module = AnsibleModule(
-        argument_spec = dict(
-            name = dict(required=True),
-            public_key = dict(default=None),
-            domain = dict(default=None),
-            account = dict(default=None),
-            project = dict(default=None),
-            state = dict(choices=['present', 'absent'], default='present'),
-            api_key = dict(default=None),
-            api_secret = dict(default=None, no_log=True),
-            api_url = dict(default=None),
-            api_http_method = dict(choices=['get', 'post'], default='get'),
-            api_timeout = dict(type='int', default=10),
-            api_region = dict(default='cloudstack'),
-        ),
-        required_together = (
-            ['api_key', 'api_secret', 'api_url'],
-        ),
+        argument_spec=argument_spec,
+        required_together=cs_required_together(),
         supports_check_mode=True
     )
 
diff --git a/cloud/cloudstack/cs_staticnat.py b/cloud/cloudstack/cs_staticnat.py
index c42b743d51c..c8fba54885e 100644
--- a/cloud/cloudstack/cs_staticnat.py
+++ b/cloud/cloudstack/cs_staticnat.py
@@ -259,27 +259,22 @@ class AnsibleCloudStackStaticNat(AnsibleCloudStack):
 
 
 def main():
+    argument_spec = cs_argument_spec()
+    argument_spec.update(dict(
+        ip_address = dict(required=True),
+        vm = dict(default=None),
+        vm_guest_ip = dict(default=None),
+        state = dict(choices=['present', 'absent'], default='present'),
+        zone = dict(default=None),
+        domain = dict(default=None),
+        account = dict(default=None),
+        project = dict(default=None),
+        poll_async = dict(choices=BOOLEANS, default=True),
+    ))
+
     module = AnsibleModule(
-        argument_spec = dict(
-            ip_address = dict(required=True),
-            vm = dict(default=None),
-            vm_guest_ip = dict(default=None),
-            state = dict(choices=['present', 'absent'], default='present'),
-            zone = dict(default=None),
-            domain = dict(default=None),
-            account = dict(default=None),
-            project = dict(default=None),
-            poll_async = dict(choices=BOOLEANS, default=True),
-            api_key = dict(default=None),
-            api_secret = dict(default=None, no_log=True),
-            api_url = dict(default=None),
-            api_http_method = dict(choices=['get', 'post'], default='get'),
-            api_timeout = dict(type='int', default=10),
-            api_region = dict(default='cloudstack'),
-        ),
-        required_together = (
-            ['api_key', 'api_secret', 'api_url'],
-        ),
+        argument_spec=argument_spec,
+        required_together=cs_required_together(),
         supports_check_mode=True
     )
 
diff --git a/cloud/cloudstack/cs_template.py b/cloud/cloudstack/cs_template.py
index fbaa5665eb2..94803aeb9eb 100644
--- a/cloud/cloudstack/cs_template.py
+++ b/cloud/cloudstack/cs_template.py
@@ -529,51 +529,50 @@ class AnsibleCloudStackTemplate(AnsibleCloudStack):
 
 
 def main():
+    argument_spec = cs_argument_spec()
+    argument_spec.update(dict(
+        name = dict(required=True),
+        display_text = dict(default=None),
+        url = dict(default=None),
+        vm = dict(default=None),
+        snapshot = dict(default=None),
+        os_type = dict(default=None),
+        is_ready = dict(type='bool', choices=BOOLEANS, default=False),
+        is_public = dict(type='bool', choices=BOOLEANS, default=True),
+        is_featured = dict(type='bool', choices=BOOLEANS, default=False),
+        is_dynamically_scalable = dict(type='bool', choices=BOOLEANS, default=False),
+        is_extractable = dict(type='bool', choices=BOOLEANS, default=False),
+        is_routing = dict(type='bool', choices=BOOLEANS, default=False),
+        checksum = dict(default=None),
+        template_filter = dict(default='self', choices=['featured', 'self', 'selfexecutable', 'sharedexecutable', 'executable', 'community']),
+        hypervisor = dict(choices=['KVM', 'VMware', 'BareMetal', 'XenServer', 'LXC', 'HyperV', 'UCS', 'OVM', 'Simulator'], default=None),
+        requires_hvm = dict(type='bool', choices=BOOLEANS, default=False),
+        password_enabled = dict(type='bool', choices=BOOLEANS, default=False),
+        template_tag = dict(default=None),
+        sshkey_enabled = dict(type='bool', choices=BOOLEANS, default=False),
+        format = dict(choices=['QCOW2', 'RAW', 'VHD', 'OVA'], default=None),
+        details = dict(default=None),
+        bits = dict(type='int', choices=[ 32, 64 ], default=64),
+        state = dict(choices=['present', 'absent'], default='present'),
+        cross_zones = dict(type='bool', choices=BOOLEANS, default=False),
+        zone = dict(default=None),
+        domain = dict(default=None),
+        account = dict(default=None),
+        project = dict(default=None),
+        poll_async = dict(type='bool', choices=BOOLEANS, default=True),
+    ))
+
+    required_together = cs_required_together()
+    required_together.extend([
+        ['format', 'url', 'hypervisor'],
+    ])
+
     module = AnsibleModule(
-        argument_spec = dict(
-            name = dict(required=True),
-            display_text = dict(default=None),
-            url = dict(default=None),
-            vm = dict(default=None),
-            snapshot = dict(default=None),
-            os_type = dict(default=None),
-            is_ready = dict(type='bool', choices=BOOLEANS, default=False),
-            is_public = dict(type='bool', choices=BOOLEANS, default=True),
-            is_featured = dict(type='bool', choices=BOOLEANS, default=False),
-            is_dynamically_scalable = dict(type='bool', choices=BOOLEANS, default=False),
-            is_extractable = dict(type='bool', choices=BOOLEANS, default=False),
-            is_routing = dict(type='bool', choices=BOOLEANS, default=False),
-            checksum = dict(default=None),
-            template_filter = dict(default='self', choices=['featured', 'self', 'selfexecutable', 'sharedexecutable', 'executable', 'community']),
-            hypervisor = dict(choices=['KVM', 'VMware', 'BareMetal', 'XenServer', 'LXC', 'HyperV', 'UCS', 'OVM', 'Simulator'], default=None),
-            requires_hvm = dict(type='bool', choices=BOOLEANS, default=False),
-            password_enabled = dict(type='bool', choices=BOOLEANS, default=False),
-            template_tag = dict(default=None),
-            sshkey_enabled = dict(type='bool', choices=BOOLEANS, default=False),
-            format = dict(choices=['QCOW2', 'RAW', 'VHD', 'OVA'], default=None),
-            details = dict(default=None),
-            bits = dict(type='int', choices=[ 32, 64 ], default=64),
-            state = dict(choices=['present', 'absent'], default='present'),
-            cross_zones = dict(type='bool', choices=BOOLEANS, default=False),
-            zone = dict(default=None),
-            domain = dict(default=None),
-            account = dict(default=None),
-            project = dict(default=None),
-            poll_async = dict(type='bool', choices=BOOLEANS, default=True),
-            api_key = dict(default=None),
-            api_secret = dict(default=None),
-            api_url = dict(default=None),
-            api_http_method = dict(choices=['get', 'post'], default='get'),
-            api_timeout = dict(type='int', default=10),
-            api_region = dict(default='cloudstack'),
-        ),
+        argument_spec=argument_spec,
+        required_together=required_together,
         mutually_exclusive = (
             ['url', 'vm'],
         ),
-        required_together = (
-            ['api_key', 'api_secret', 'api_url'],
-            ['format', 'url', 'hypervisor'],
-        ),
         supports_check_mode=True
     )
 
diff --git a/cloud/cloudstack/cs_user.py b/cloud/cloudstack/cs_user.py
index 43e83c06784..e6fe1c1f513 100644
--- a/cloud/cloudstack/cs_user.py
+++ b/cloud/cloudstack/cs_user.py
@@ -404,28 +404,23 @@ class AnsibleCloudStackUser(AnsibleCloudStack):
 
 
 def main():
+    argument_spec = cs_argument_spec()
+    argument_spec.update(dict(
+        username = dict(required=True),
+        account = dict(default=None),
+        state = dict(choices=['present', 'absent', 'enabled', 'disabled', 'locked', 'unlocked'], default='present'),
+        domain = dict(default='ROOT'),
+        email = dict(default=None),
+        first_name = dict(default=None),
+        last_name = dict(default=None),
+        password = dict(default=None),
+        timezone = dict(default=None),
+        poll_async = dict(choices=BOOLEANS, default=True),
+    ))
+
     module = AnsibleModule(
-        argument_spec = dict(
-            username = dict(required=True),
-            account = dict(default=None),
-            state = dict(choices=['present', 'absent', 'enabled', 'disabled', 'locked', 'unlocked'], default='present'),
-            domain = dict(default='ROOT'),
-            email = dict(default=None),
-            first_name = dict(default=None),
-            last_name = dict(default=None),
-            password = dict(default=None),
-            timezone = dict(default=None),
-            poll_async = dict(choices=BOOLEANS, default=True),
-            api_key = dict(default=None),
-            api_secret = dict(default=None, no_log=True),
-            api_url = dict(default=None),
-            api_http_method = dict(choices=['get', 'post'], default='get'),
-            api_timeout = dict(type='int', default=10),
-            api_region = dict(default='cloudstack'),
-        ),
-        required_together = (
-            ['api_key', 'api_secret', 'api_url'],
-        ),
+        argument_spec=argument_spec,
+        required_together=cs_required_together(),
         supports_check_mode=True
     )
 
diff --git a/cloud/cloudstack/cs_vmsnapshot.py b/cloud/cloudstack/cs_vmsnapshot.py
index 9b87c1c3567..43e561bb93a 100644
--- a/cloud/cloudstack/cs_vmsnapshot.py
+++ b/cloud/cloudstack/cs_vmsnapshot.py
@@ -257,29 +257,28 @@ class AnsibleCloudStackVmSnapshot(AnsibleCloudStack):
 
 
 def main():
+    argument_spec = cs_argument_spec()
+    argument_spec.update(dict(
+        name = dict(required=True, aliases=['display_name']),
+        vm = dict(required=True),
+        description = dict(default=None),
+        zone = dict(default=None),
+        snapshot_memory = dict(choices=BOOLEANS, default=False),
+        state = dict(choices=['present', 'absent', 'revert'], default='present'),
+        domain = dict(default=None),
+        account = dict(default=None),
+        project = dict(default=None),
+        poll_async = dict(type='bool', choices=BOOLEANS, default=True),
+    ))
+
+    required_together = cs_required_together()
+    required_together.extend([
+        ['icmp_type', 'icmp_code'],
+    ])
+
     module = AnsibleModule(
-        argument_spec = dict(
-            name = dict(required=True, aliases=['display_name']),
-            vm = dict(required=True),
-            description = dict(default=None),
-            zone = dict(default=None),
-            snapshot_memory = dict(choices=BOOLEANS, default=False),
-            state = dict(choices=['present', 'absent', 'revert'], default='present'),
-            domain = dict(default=None),
-            account = dict(default=None),
-            project = dict(default=None),
-            poll_async = dict(choices=BOOLEANS, default=True),
-            api_key = dict(default=None),
-            api_secret = dict(default=None, no_log=True),
-            api_url = dict(default=None),
-            api_http_method = dict(choices=['get', 'post'], default='get'),
-            api_timeout = dict(type='int', default=10),
-            api_region = dict(default='cloudstack'),
-        ),
-        required_together = (
-            ['icmp_type', 'icmp_code'],
-            ['api_key', 'api_secret', 'api_url'],
-        ),
+        argument_spec=argument_spec,
+        required_together=required_together,
         supports_check_mode=True
     )