diff --git a/lib/ansible/module_utils/azure_rm_common.py b/lib/ansible/module_utils/azure_rm_common.py index df25c2d9abf..bce6515072f 100644 --- a/lib/ansible/module_utils/azure_rm_common.py +++ b/lib/ansible/module_utils/azure_rm_common.py @@ -546,7 +546,7 @@ class AzureRMModuleBase(object): self.fail("Error creating blob service client for storage account {0} - {1}".format(storage_account_name, str(exc))) - def create_default_pip(self, resource_group, location, public_ip_name, allocation_method='Dynamic'): + def create_default_pip(self, resource_group, location, public_ip_name, allocation_method='Dynamic', sku=None): ''' Create a default public IP address to associate with a network interface. If a PIP address matching exists, return it. Otherwise, create one. @@ -555,6 +555,7 @@ class AzureRMModuleBase(object): :param location: a valid azure location :param public_ip_name: base name to assign the public IP address :param allocation_method: one of 'Static' or 'Dynamic' + :param sku: sku :return: PIP object ''' pip = None @@ -574,6 +575,7 @@ class AzureRMModuleBase(object): params = self.network_models.PublicIPAddress( location=location, public_ip_allocation_method=allocation_method, + sku=sku ) self.log('Creating default public IP {0}'.format(public_ip_name)) try: diff --git a/lib/ansible/modules/cloud/azure/azure_rm_virtualmachine.py b/lib/ansible/modules/cloud/azure/azure_rm_virtualmachine.py index 2ade4cfb227..60950592838 100644 --- a/lib/ansible/modules/cloud/azure/azure_rm_virtualmachine.py +++ b/lib/ansible/modules/cloud/azure/azure_rm_virtualmachine.py @@ -305,6 +305,11 @@ options: type: bool default: false version_added: "2.7" + zones: + description: + - A list of Availability Zones for your virtual machine + type: list + version_added: "2.8" extends_documentation_fragment: - azure @@ -498,6 +503,16 @@ EXAMPLES = ''' remove_on_absent: - network_interfaces - virtual_storage + +- name: Create a VM with an Availability Zone + azure_rm_virtualmachine: + resource_group: Testing + name: testvm001 + vm_size: Standard_DS1_v2 + admin_username: adminUser + admin_password: password01 + image: customimage001 + zones: [1] ''' RETURN = ''' @@ -737,7 +752,8 @@ class AzureRMVirtualMachine(AzureRMModuleBase): generalized=dict(type='bool', default=False), data_disks=dict(type='list'), plan=dict(type='dict'), - accept_terms=dict(type='bool', default=False) + accept_terms=dict(type='bool', default=False), + zones=dict(type='list') ) self.resource_group = None @@ -778,6 +794,7 @@ class AzureRMVirtualMachine(AzureRMModuleBase): self.data_disks = None self.plan = None self.accept_terms = None + self.zones = None self.results = dict( changed=False, @@ -797,6 +814,9 @@ class AzureRMVirtualMachine(AzureRMModuleBase): # make sure options are lower case self.remove_on_absent = set([resource.lower() for resource in self.remove_on_absent]) + # convert elements to ints + self.zones = [int(i) for i in self.zones] if self.zones else None + changed = False powerstate_change = None results = dict() @@ -968,6 +988,12 @@ class AzureRMVirtualMachine(AzureRMModuleBase): changed = True powerstate_change = 'generalized' + vm_dict['zones'] = [int(i) for i in vm_dict['zones']] if 'zones' in vm_dict and vm_dict['zones'] else None + if self.zones != vm_dict['zones']: + self.log("CHANGED: virtual machine {0} zones".format(self.name)) + differences.append('Zones') + changed = True + self.differences = differences elif self.state == 'absent': @@ -1014,6 +1040,9 @@ class AzureRMVirtualMachine(AzureRMModuleBase): parsed_availability_set.get('name')) availability_set_resource = self.compute_models.SubResource(id=availability_set.id) + if self.zones: + self.fail("Parameter error: you can't use Availability Set and Availability Zones at the same time") + # Get defaults if not self.network_interface_names: default_nic = self.create_default_nic() @@ -1081,7 +1110,8 @@ class AzureRMVirtualMachine(AzureRMModuleBase): network_interfaces=nics ), availability_set=availability_set_resource, - plan=plan + plan=plan, + zones=self.zones, ) if self.admin_password: @@ -1220,6 +1250,10 @@ class AzureRMVirtualMachine(AzureRMModuleBase): else: image_reference = None + # You can't change a vm zone + if vm_dict['zones'] != self.zones: + self.fail("You can't change the Availability Zone of a virtual machine (have: {0}, want: {1})".format(vm_dict['zones'], self.zones)) + if 'osProfile' in vm_dict['properties']: os_profile = self.compute_models.OSProfile( admin_username=vm_dict['properties'].get('osProfile', {}).get('adminUsername'), @@ -1810,8 +1844,9 @@ class AzureRMVirtualMachine(AzureRMModuleBase): pip = None if self.public_ip_allocation_method != 'Disabled': self.results['actions'].append('Created default public IP {0}'.format(self.name + '01')) - pip_info = self.create_default_pip(self.resource_group, self.location, self.name + '01', self.public_ip_allocation_method) - pip = self.network_models.PublicIPAddress(id=pip_info.id, location=pip_info.location, resource_guid=pip_info.resource_guid) + sku = self.network_models.PublicIPAddressSku(name="Standard") if self.zones else None + pip_info = self.create_default_pip(self.resource_group, self.location, self.name + '01', self.public_ip_allocation_method, sku=sku) + pip = self.network_models.PublicIPAddress(id=pip_info.id, location=pip_info.location, resource_guid=pip_info.resource_guid, sku=sku) self.results['actions'].append('Created default security group {0}'.format(self.name + '01')) group = self.create_default_securitygroup(self.resource_group, self.location, self.name + '01', self.os_type, diff --git a/lib/ansible/modules/cloud/azure/azure_rm_virtualmachine_scaleset.py b/lib/ansible/modules/cloud/azure/azure_rm_virtualmachine_scaleset.py index d0205ca826e..14e0c841209 100644 --- a/lib/ansible/modules/cloud/azure/azure_rm_virtualmachine_scaleset.py +++ b/lib/ansible/modules/cloud/azure/azure_rm_virtualmachine_scaleset.py @@ -203,6 +203,11 @@ options: type: bool default: True version_added: "2.8" + zones: + description: + - A list of Availability Zones for your virtual machine scale set + type: list + version_added: "2.8" extends_documentation_fragment: - azure @@ -410,7 +415,8 @@ class AzureRMVirtualMachineScaleSet(AzureRMModuleBase): remove_on_absent=dict(type='list', default=['all']), enable_accelerated_networking=dict(type='bool'), security_group=dict(type='raw', aliases=['security_group_name']), - overprovision=dict(type='bool', default=True) + overprovision=dict(type='bool', default=True), + zones=dict(type='list') ) self.resource_group = None @@ -440,6 +446,7 @@ class AzureRMVirtualMachineScaleSet(AzureRMModuleBase): self.enable_accelerated_networking = None self.security_group = None self.overprovision = None + self.zones = None self.results = dict( changed=False, @@ -462,6 +469,9 @@ class AzureRMVirtualMachineScaleSet(AzureRMModuleBase): # make sure options are lower case self.remove_on_absent = set([resource.lower() for resource in self.remove_on_absent]) + # convert elements to ints + self.zones = [int(i) for i in self.zones] if self.zones else None + # default virtual_network_resource_group to resource_group if not self.virtual_network_resource_group: self.virtual_network_resource_group = self.resource_group @@ -582,6 +592,13 @@ class AzureRMVirtualMachineScaleSet(AzureRMModuleBase): differences.append('overprovision') changed = True + vmss_dict['zones'] = [int(i) for i in vmss_dict['zones']] if 'zones' in vmss_dict and vmss_dict['zones'] else None + if self.zones != vmss_dict['zones']: + self.log("CHANGED: virtual machine scale sets {0} zones".format(self.name)) + differences.append('Zones') + changed = True + vmss_dict['zones'] = self.zones + self.differences = differences elif self.state == 'absent': @@ -694,7 +711,8 @@ class AzureRMVirtualMachineScaleSet(AzureRMModuleBase): ) ] ) - ) + ), + zones=self.zones ) if self.admin_password: