diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_vm.py b/lib/ansible/modules/cloud/ovirt/ovirt_vm.py index 247051b50da..ddba4641a70 100644 --- a/lib/ansible/modules/cloud/ovirt/ovirt_vm.py +++ b/lib/ansible/modules/cloud/ovirt/ovirt_vm.py @@ -784,6 +784,18 @@ options: - NOTE - If there are multiple next run configuration changes on the VM, the first change may get reverted if this option is not passed. version_added: "2.8" type: bool + snapshot_name: + description: + - "Snapshot to clone VM from." + - "Snapshot with description specified should exist." + - "You have to specify C(snapshot_vm) parameter with virtual machine name of this snapshot." + version_added: "2.9" + snapshot_vm: + description: + - "Source VM to clone VM from." + - "VM should have snapshot specified by C(snapshot)." + - "If C(snapshot_name) specified C(snapshot_vm) is required." + version_added: "2.9" notes: - If VM is in I(UNASSIGNED) or I(UNKNOWN) state before any operation, the module will fail. @@ -1141,6 +1153,13 @@ EXAMPLES = ''' host: myhost filename: myvm.ova directory: /tmp/ + +- name: Clone VM from snapshot + ovirt_vm: + snapshot_vm: myvm + snapshot_name: myvm_snap + name: myvm_clone + state: present ''' @@ -1254,8 +1273,38 @@ class VmsModule(BaseModule): return disks + def __get_snapshot(self): + + if self.param('snapshot_vm') is None: + return None + + if self.param('snapshot_name') is None: + return None + + vms_service = self._connection.system_service().vms_service() + vm_id = get_id_by_name(vms_service, self.param('snapshot_vm')) + vm_service = vms_service.vm_service(vm_id) + + snaps_service = vm_service.snapshots_service() + snaps = snaps_service.list() + snap = next( + (s for s in snaps if s.description == self.param('snapshot_name')), + None + ) + return snap + + def __get_cluster(self): + if self.param('cluster') is not None: + return self.param('cluster') + elif self.param('snapshot_name') is not None and self.param('snapshot_vm') is not None: + vms_service = self._connection.system_service().vms_service() + vm = search_by_name(vms_service, self.param('snapshot_vm')) + return self._connection.system_service().clusters_service().cluster_service(vm.cluster.id).get().name + def build_entity(self): template = self.__get_template_with_version() + cluster = self.__get_cluster() + snapshot = self.__get_snapshot() disk_attachments = self.__get_storage_domain_and_all_template_disks(template) @@ -1263,8 +1312,8 @@ class VmsModule(BaseModule): id=self.param('id'), name=self.param('name'), cluster=otypes.Cluster( - name=self.param('cluster') - ) if self.param('cluster') else None, + name=cluster + ) if cluster else None, disk_attachments=disk_attachments, template=otypes.Template( id=template.id, @@ -1400,6 +1449,7 @@ class VmsModule(BaseModule): ) for cp in self.param('custom_properties') if cp ] if self.param('custom_properties') is not None else None, initialization=self.get_initialization() if self.param('cloud_init_persist') else None, + snapshots=[otypes.Snapshot(id=snapshot.id)] if snapshot is not None else None, ) def _get_export_domain_service(self): @@ -2264,6 +2314,8 @@ def main(): force_migrate=dict(type='bool'), migrate=dict(type='bool', default=None), next_run=dict(type='bool'), + snapshot_name=dict(type='str'), + snapshot_vm=dict(type='str'), ) module = AnsibleModule( argument_spec=argument_spec, @@ -2271,7 +2323,8 @@ def main(): required_one_of=[['id', 'name']], required_if=[ ('state', 'registered', ['storage_domain']), - ] + ], + required_together=[['snapshot_name', 'snapshot_vm']] ) check_sdk(module)