diff --git a/cloud/cloudstack/cs_instance.py b/cloud/cloudstack/cs_instance.py index 73deb028be2..9674b589da4 100644 --- a/cloud/cloudstack/cs_instance.py +++ b/cloud/cloudstack/cs_instance.py @@ -143,7 +143,7 @@ options: description: - List of security groups the instance to be applied to. required: false - default: [] + default: null aliases: [ 'security_group' ] domain: description: @@ -521,6 +521,27 @@ class AnsibleCloudStackInstance(AnsibleCloudStack): return res + def security_groups_has_changed(self): + security_groups = self.module.params.get('security_groups') + if security_groups is None: + return False + + security_groups = [s.lower() for s in security_groups] + instance_security_groups = self.instance.get('securitygroup',[]) + + instance_security_group_names = [] + for instance_security_group in instance_security_groups: + if instance_security_group['name'].lower() not in security_groups: + return True + else: + instance_security_group_names.append(instance_security_group['name'].lower()) + + for security_group in security_groups: + if security_group not in instance_security_group_names: + return True + return False + + def get_network_ids(self, network_names=None): if network_names is None: network_names = self.module.params.get('networks') @@ -622,10 +643,13 @@ class AnsibleCloudStackInstance(AnsibleCloudStack): args['size'] = self.module.params.get('disk_size') args['startvm'] = start_vm args['rootdisksize'] = self.module.params.get('root_disk_size') - args['securitygroupnames'] = ','.join(self.module.params.get('security_groups')) args['affinitygroupnames'] = ','.join(self.module.params.get('affinity_groups')) args['details'] = self.get_details() + security_groups = self.module.params.get('security_groups') + if security_groups is not None: + args['securitygroupnames'] = ','.join(security_groups) + template_iso = self.get_template_or_iso() if 'hypervisor' not in template_iso: args['hypervisor'] = self.get_hypervisor() @@ -649,6 +673,7 @@ class AnsibleCloudStackInstance(AnsibleCloudStack): args_service_offering['id'] = instance['id'] if self.module.params.get('service_offering'): args_service_offering['serviceofferingid'] = self.get_service_offering_id() + service_offering_changed = self._has_changed(args_service_offering, instance) # Instance data args_instance_update = {} @@ -659,6 +684,7 @@ class AnsibleCloudStackInstance(AnsibleCloudStack): args_instance_update['group'] = self.module.params.get('group') if self.module.params.get('display_name'): args_instance_update['displayname'] = self.module.params.get('display_name') + instance_changed = self._has_changed(args_instance_update, instance) # SSH key data args_ssh_key = {} @@ -666,12 +692,18 @@ class AnsibleCloudStackInstance(AnsibleCloudStack): args_ssh_key['projectid'] = self.get_project(key='id') if self.module.params.get('ssh_key'): args_ssh_key['keypair'] = self.module.params.get('ssh_key') + ssh_key_changed = self._has_changed(args_ssh_key, instance) + security_groups_changed = self.security_groups_has_changed() - if self._has_changed(args_service_offering, instance) or \ - self._has_changed(args_instance_update, instance) or \ - self._has_changed(args_ssh_key, instance): + changed = [ + service_offering_changed, + instance_changed, + security_groups_changed, + ssh_key_changed, + ] + if True in changed: force = self.module.params.get('force') instance_state = instance['state'].lower() if instance_state == 'stopped' or force: @@ -684,7 +716,7 @@ class AnsibleCloudStackInstance(AnsibleCloudStack): self.instance = instance # Change service offering - if self._has_changed(args_service_offering, instance): + if service_offering_changed: res = self.cs.changeServiceForVirtualMachine(**args_service_offering) if 'errortext' in res: self.module.fail_json(msg="Failed: '%s'" % res['errortext']) @@ -692,7 +724,9 @@ class AnsibleCloudStackInstance(AnsibleCloudStack): self.instance = instance # Update VM - if self._has_changed(args_instance_update, instance): + if instance_changed or security_groups_changed: + if security_groups_changed: + args_instance_update['securitygroupnames'] = ','.join(self.module.params.get('security_groups')) res = self.cs.updateVirtualMachine(**args_instance_update) if 'errortext' in res: self.module.fail_json(msg="Failed: '%s'" % res['errortext']) @@ -700,7 +734,7 @@ class AnsibleCloudStackInstance(AnsibleCloudStack): self.instance = instance # Reset SSH key - if self._has_changed(args_ssh_key, instance): + if ssh_key_changed: instance = self.cs.resetSSHKeyForVirtualMachine(**args_ssh_key) if 'errortext' in instance: self.module.fail_json(msg="Failed: '%s'" % instance['errortext']) @@ -887,8 +921,8 @@ def main(): 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=[]), + hypervisor = dict(choices=CS_HYPERVISORS, default=None), + security_groups = dict(type='list', aliases=[ 'security_group' ], default=None), affinity_groups = dict(type='list', aliases=[ 'affinity_group' ], default=[]), domain = dict(default=None), account = dict(default=None), diff --git a/cloud/cloudstack/cs_template.py b/cloud/cloudstack/cs_template.py index 753a22abc82..8690a6e1756 100644 --- a/cloud/cloudstack/cs_template.py +++ b/cloud/cloudstack/cs_template.py @@ -592,7 +592,7 @@ def main(): is_routing = dict(type='bool', 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), + hypervisor = dict(choices=CS_HYPERVISORS, default=None), requires_hvm = dict(type='bool', default=False), password_enabled = dict(type='bool', default=False), template_tag = dict(default=None),