diff --git a/lib/ansible/modules/cloud/azure/azure_rm_image.py b/lib/ansible/modules/cloud/azure/azure_rm_image.py index 5f9a24b0e11..40bbba01cb8 100644 --- a/lib/ansible/modules/cloud/azure/azure_rm_image.py +++ b/lib/ansible/modules/cloud/azure/azure_rm_image.py @@ -31,12 +31,17 @@ options: required: true source: description: - - OS disk source from the same region, including a virtual machine id or name, - OS disk blob uri, managed OS disk id or name, or OS snapshot id or name. + - OS disk source from the same region. + - It can be a virtual machine, OS disk blob URI, managed OS disk, or OS snapshot. + - Each type of source except for blob URI can be given as resource id, name or a dict contains C(resource_group), C(name) and C(types). + - If source type is blob URI, the source should be the full URI of the blob in string type. + - If you specify the C(type) in a dict, acceptable value constains C(disks), C(virtual_machines) and C(snapshots). + type: raw required: true data_disk_sources: description: - - List of data disk sources, including unmanaged blob uri, managed disk id or name, or snapshot id or name. + - List of data disk sources, including unmanaged blob URI, managed disk id or name, or snapshot id or name. + type: list location: description: - Location of the image. Derived from I(resource_group) if not specified. @@ -79,6 +84,19 @@ EXAMPLES = ''' - datadisk002 os_type: Linux +- name: Create an image from os disk via dict + azure_rm_image: + resource_group: Testing + name: foobar + source: + type: disks + resource_group: Testing + name: disk001 + data_disk_sources: + - datadisk001 + - datadisk002 + os_type: Linux + - name: Delete an image azure_rm_image: state: absent @@ -114,7 +132,7 @@ class AzureRMImage(AzureRMModuleBase): name=dict(type='str', required=True), state=dict(type='str', default='present', choices=['present', 'absent']), location=dict(type='str'), - source=dict(type='str'), + source=dict(type='raw'), data_disk_sources=dict(type='list', default=[]), os_type=dict(type='str', choices=['Windows', 'Linux']) ) @@ -208,17 +226,32 @@ class AzureRMImage(AzureRMModuleBase): blob_uri = None disk = None snapshot = None - if source.lower().endswith('.vhd'): + # blob URI can only be given by str + if isinstance(source, str) and source.lower().endswith('.vhd'): blob_uri = source return (blob_uri, disk, snapshot) - tokenize = parse_resource_id(source) + tokenize = dict() + if isinstance(source, dict): + tokenize = source + elif isinstance(source, str): + tokenize = parse_resource_id(source) + else: + self.fail("source parameter sould be in type string or dictionary") if tokenize.get('type') == 'disks': - disk = source + disk = format_resource_id(tokenize['name'], + tokenize.get('subscription_id') or self.subscription_id, + 'Microsoft.Compute', + 'disks', + tokenize.get('resource_group') or self.resource_group) return (blob_uri, disk, snapshot) if tokenize.get('type') == 'snapshots': - snapshot = source + snapshot = format_resource_id(tokenize['name'], + tokenize.get('subscription_id') or self.subscription_id, + 'Microsoft.Compute', + 'snapshots', + tokenize.get('resource_group') or self.resource_group) return (blob_uri, disk, snapshot) # not a disk or snapshots @@ -226,12 +259,14 @@ class AzureRMImage(AzureRMModuleBase): return (blob_uri, disk, snapshot) # source can be name of snapshot or disk - snapshot_instance = self.get_snapshot(source) + snapshot_instance = self.get_snapshot(tokenize.get('resource_group') or self.resource_group, + tokenize['name']) if snapshot_instance: snapshot = snapshot_instance.id return (blob_uri, disk, snapshot) - disk_instance = self.get_disk(source) + disk_instance = self.get_disk(tokenize.get('resource_group') or self.resource_group, + tokenize['name']) if disk_instance: disk = disk_instance.id return (blob_uri, disk, snapshot) @@ -260,19 +295,30 @@ class AzureRMImage(AzureRMModuleBase): return list(filter(None, [self.create_data_disk(lun, source) for lun, source in enumerate(self.data_disk_sources)])) def get_source_vm(self): - vm_resource_id = format_resource_id(self.source, - self.subscription_id, - 'Microsoft.Compute', - 'virtualMachines', - self.resource_group) - resource = parse_resource_id(vm_resource_id) + # self.resource can be a vm (id/name/dict), or not a vm. return the vm iff it is an existing vm. + resource = dict() + if isinstance(self.source, dict): + if self.source.get('type') != 'virtual_machines': + return None + resource = dict(type='virtualMachines', + name=self.source['name'], + resource_group=self.source.get('resource_group') or self.resource_group) + elif isinstance(self.source, str): + vm_resource_id = format_resource_id(self.source, + self.subscription_id, + 'Microsoft.Compute', + 'virtualMachines', + self.resource_group) + resource = parse_resource_id(vm_resource_id) + else: + self.fail("Unsupported type of source parameter, please give string or dictionary") return self.get_vm(resource['resource_group'], resource['name']) if resource['type'] == 'virtualMachines' else None - def get_snapshot(self, snapshot_name): - return self._get_resource(self.compute_client.snapshots.get, self.resource_group, snapshot_name) + def get_snapshot(self, resource_group, snapshot_name): + return self._get_resource(self.compute_client.snapshots.get, resource_group, snapshot_name) - def get_disk(self, disk_name): - return self._get_resource(self.compute_client.disks.get, self.resource_group, disk_name) + def get_disk(self, resource_group, disk_name): + return self._get_resource(self.compute_client.disks.get, resource_group, disk_name) def get_vm(self, resource_group, vm_name): return self._get_resource(self.compute_client.virtual_machines.get, resource_group, vm_name, 'instanceview') diff --git a/test/integration/targets/azure_rm_image/tasks/main.yml b/test/integration/targets/azure_rm_image/tasks/main.yml index 163fb0894e2..7a7bc7095f7 100644 --- a/test/integration/targets/azure_rm_image/tasks/main.yml +++ b/test/integration/targets/azure_rm_image/tasks/main.yml @@ -1,19 +1,10 @@ - name: Create storage account name set_fact: vm_name: "vm{{ resource_group | hash('md5') | truncate(7, True, '') }}{{ 1000 | random }}x" - storage_name: "st{{ resource_group | hash('md5') | truncate(7, True, '') }}{{ 1000 | random }}" - storage_container_name: "sc{{ resource_group | hash('md5') | truncate(7, True, '') }}{{ 1000 | random }}" public_ip_name: "pip{{ resource_group | hash('md5') | truncate(7, True, '') }}{{ 1000 | random }}" security_group_name: "sg{{ resource_group | hash('md5') | truncate(7, True, '') }}{{ 1000 | random }}" - blob_name: "blob{{ resource_group | hash('md5') | truncate(7, True, '') }}{{ 1000 | random }}" empty_disk_name: "emptydisk{{ resource_group | hash('md5') | truncate(7, True, '') }}{{ 1000 | random }}" -- name: Create storage account - azure_rm_storageaccount: - resource_group: "{{ resource_group }}" - name: "{{ storage_name }}" - account_type: Standard_LRS - - name: Create virtual network azure_rm_virtualnetwork: resource_group: "{{ resource_group }}" @@ -52,9 +43,7 @@ resource_group: "{{ resource_group }}" name: "{{ vm_name }}" vm_size: Standard_A0 - storage_account: "{{ storage_name }}" - storage_container: "{{ storage_container_name }}" - storage_blob: "{{ blob_name }}.vhd" + managed_disk_type: Standard_LRS admin_username: adminuser admin_password: Password123! os_type: Linux @@ -64,20 +53,7 @@ publisher: Canonical sku: 16.04-LTS version: latest - -- name: Deallocate the virtual machine - azure_rm_virtualmachine: - resource_group: "{{ resource_group }}" - name: "{{ vm_name }}" - allocated: no - vm_size: Standard_A0 - register: output - -- name: Start the virtual machine - azure_rm_virtualmachine: - resource_group: "{{ resource_group }}" - name: "{{ vm_name }}" - vm_size: Standard_A0 + register: vm - name: Create new empty managed disk azure_rm_managed_disk: @@ -90,7 +66,7 @@ - name: Create an image from VM (check mode) azure_rm_image: resource_group: "{{ resource_group }}" - source: "https://{{ storage_name }}.blob.core.windows.net/{{ storage_container_name }}/{{ blob_name }}.vhd" + source: "{{ vm.ansible_facts.azure_vm.properties.storageProfile.osDisk.managedDisk.id }}" name: testimage001 os_type: Linux data_disk_sources: @@ -104,7 +80,9 @@ - name: Create an image from VM azure_rm_image: resource_group: "{{ resource_group }}" - source: "https://{{ storage_name }}.blob.core.windows.net/{{ storage_container_name }}/{{ blob_name }}.vhd" + source: + name: "{{ vm_name }}" + type: disks name: testimage001 os_type: Linux register: output @@ -117,7 +95,7 @@ - name: Create an image from VM (idempotent) azure_rm_image: resource_group: "{{ resource_group }}" - source: "https://{{ storage_name }}.blob.core.windows.net/{{ storage_container_name }}/{{ blob_name }}.vhd" + source: "{{ vm.ansible_facts.azure_vm.properties.storageProfile.osDisk.managedDisk.id }}" name: testimage001 os_type: Linux register: output