community.vmware
community.vmware copied to clipboard
ESXi without vCenter - Duplicate existing template VM
SUMMARY
It seems currently there is no way of duplicating an existing VM that is available on an ESXi server running without vCenter.
The story goes like this: User uploads a Windows template OVA that gets successfully registered on the ESXi. Now this template VM is used to get copied as instances of real VM's. Since the clone opration is only available to ESXi hosts that are connected to a vCenter, this operation does not work using community.vmware.vmware_guest.
ISSUE TYPE
- Feature Idea
COMPONENT NAME
community.vmware.vmware_guest_copy
ADDITIONAL INFORMATION
Required functionality implemented:
- User defines the source VM name (required to have the VM powered off during all operations).
- Source VM folder get copied to new folder using defined destination VM name on defined destination datastore on the same ESXi.
- Rename the .vmx file in destination folder using specified destination VM name.
- Register the renamed .vmx file to ESXi inventory.
- name: Copy VM from local VM
community.vmware.vmware_guest_copy:
hostname: '{{ esxi_host }}'
username: '{{ esxi_user }}'
password: '{{ esxi_pw }}'
name: New-VM1
sourcevmname: Win2016-TemplateVM
folder: vm
datastore: VM-DS01
state: present
validate_certs: no
delegate_to: localhost
Files identified in the description: None
If these files are inaccurate, please update the component name section of the description or use the !component bot command.
Thanks, @linuxcrash for the feature idea.
As you say, unfortunately, there isn't API to clone on ESXi only environment without vCenter.
As an alternative, you can clone with vmkfstools command and so on via SSH.
For example, the following playbook can clone a new vm from a template on ESXi only environment.
My Environment Information
pip list | grep -e ansible -e pyvmomi -e '-' -e Pack
Package Version
------------ ---------
ansible-base 2.10.8
pyvmomi 7.0.2
community.vmware is the latest version.
ESXi is 7.0.
ansible.cfg
$ ansible-config dump --only-changed
HOST_KEY_CHECKING(/PATH/ansible.cfg) = True
inventory.yml
---
all:
hosts:
esxi-test03:
ansible_host: 192.xxx.xxx.xxx
vars:
ansible_user: root
ansible_password: secret
clone_vm_without_vcenter_sample.yml
---
- name: Sample Playbook for cloning a vm on ESXi only environment without vCenter
hosts: all
gather_facts: false
vars:
clone_vms: # is new vm list for you want
- name: clone_vm01
disk_type: thin
datastore_name: VM3 # is datastore name to be deployed of VM
template: test_vm2 # is template vm name from you want to use
tasks:
- name: Enable SSH Service of ESXi host
community.vmware.vmware_host_service_manager:
hostname: "{{ ansible_host }}"
username: "{{ ansible_user }}"
password: "{{ ansible_password }}"
validate_certs: false
esxi_hostname: "{{ inventory_hostname }}"
service_name: TSM-SSH
state: present
delegate_to: localhost
- name: Gather datastores information
community.vmware.vmware_datastore_info:
hostname: "{{ ansible_host }}"
username: "{{ ansible_user }}"
password: "{{ ansible_password }}"
validate_certs: false
datacenter: ha-datacenter
delegate_to: localhost
register: datastore_result
- name: Set datastore_path variable
set_fact:
datastore_path: "{{ item.url }}"
loop: "{{ datastore_result.datastores }}"
when:
- item.name == datastore_name
- when:
- datastore_path is defined
block:
- name: Create a directory to store virtual machines
file:
path: "{{ datastore_path }}/{{ item.name }}"
mode: 0755
state: directory
loop: "{{ clone_vms }}"
- name: Copy vmdk file(Multiple file support)
shell: >-
for vmdk in $(find {{ datastore_path }}/{{ template }} -name "*.vmdk" | grep -v flat | awk -F / '{print $(NF)}') ; do
rename_vmdk=`echo $vmdk | sed -e "s/{{ template }}\(.*\)/{{ item.name }}\1/g"`
vmkfstools -i {{ datastore_path }}/{{ template }}/$vmdk -d {{ item.disk_type }} {{ datastore_path }}/{{ item.name }}/$rename_vmdk
done
loop: "{{ clone_vms }}"
- name: Copy vmx file
copy:
src: "{{ datastore_path }}/{{ template }}/{{ template }}.vmx"
dest: "{{ datastore_path }}/{{ item.name }}/{{ item.name }}.vmx"
mode: 0644
remote_src: true
loop: "{{ clone_vms }}"
- name: Replace vmx file parameter
replace:
path: "{{ datastore_path }}/{{ item.name }}/{{ item.name }}.vmx"
regexp: "{{ template }}(\\.vmdk|\\.nvram|\"$)"
replace: "{{ item.name }}\\1"
loop: "{{ clone_vms }}"
- name: Register VM to inventory
community.vmware.vmware_guest_register_operation:
hostname: "{{ ansible_host }}"
username: "{{ ansible_user }}"
password: "{{ ansible_password }}"
validate_certs: false
folder: '/vm'
esxi_hostname: "{{ inventory_hostname }}"
name: "{{ item.name }}"
path: "[{{ datastore_name }}] {{ item.name }}/{{ item.name }}.vmx"
state: present
delegate_to: localhost
loop: "{{ clone_vms }}"
execute playbook
$ ansible-playbook -i inventory.yml clone_vm_without_vcenter_sample.yml
How about this like?
@sky-joker you legend. Just the code I was looking for.