How to deploy and reconfigure a new Virtual Machine from Template
Deploying a virtual machine interacting directly with the ITS Private Cloud API could somehow be overwhelming due to its multiple resources to check such as networks, folders, disks, etc. In order to streamline the interaction with the API we created a Python Client named pyvss with many self-descriptive methods and available in the Python Package Index.
For this example we will be using the official PyVSS Docker image to create two virtual machines deployed from a given virtual machine template with a preconfigured Operating System (Ubuntu 16.04 64bit). The full specification is listed below:
- name: pyvss1 pyvss2
- source_template: Moref or UUId of the template
- built process: template
- billing department: VSS
- description: virtual machine deployed from vss
- usage: Testing
- networks: any available network in your account
- folder: any folder available in your account
Also, both new virtual machines will be reconfigured via a new feature called Guest Operating System Customization Specification, allowing us to change Hostname, and NIC IP address configuration automatically by processing these changes through VMware Tools. The customization specification consists of the following key value items:
- Hostname: pyvss1 and pyvss2
- DHCP: No
- Domain: eis.utoronto.ca
- IP: 128.100.102.226 and 128.100.102.227
- Subnet Mask: 255.255.255.0
- Gateway: 128.100.102.224
- DNS Servers: 128.100.102.1 128.100.102.3
If DHCP is used, you should set DHCP, Domain and Hostname
Pre-requirements
Access to the ITS Private Cloud RESTful API
Pulling the image from docker:
docker pull uofteis/pyvss:py35
API access token and save it in an environment variable
curl -X POST -a username https://vss-api.eis.utoronto.ca/auth/request-token export VSS_API_TOKEN="super_long_string"
Run the PyVSS Docker image in interactive mode passing previously set environment variable
docker run --rm -it -e VSS_API_TOKEN=$VSS_API_TOKEN uofteis/pyvss:py35 ptpython
Step-by-step guide
Import VssManager and Create a VssManager instance:
from pyvss.manager import VssManager vss = VssManager()
Refer to the official docs or use the help built in function to display what parameters are required by the deploy_vms_from_template function:
help(vss.deploy_vms_from_template)
Get source template Moref or Uuid, target folder, networks to mount for the installation
templates = vss.get_templates(filter="name,like,%ubuntu-16.04_x64%") source_template = templates[0]['moref'] networks = vss.get_networks(filter='name,like,%1102%') # filtering by name networks = [{'network': net.get('moref')} for net in networks] folders = vss.get_folders(filter='name,like,%APIDemo%') # filtering by name folder = folders[0].get('moref') description = 'virtual machine deployed from vss'
Create custom specifications for each network interface and for the whole virtual machines:
New custom specification has been introduced in version v0.9.3 which supports customizing multiple Network Interfaces on resulting virtual machines.
# custom specification for each interface in a list pyvss1_cspec_interfaces = [vss.get_custom_spec_interface(dhcp=False, ip='128.100.102.226', mask='255.255.255.0', gateway=['128.100.102.224'])] # custom specification for the VM pyvss1_cspec = vss.get_custom_spec(hostname='pyvss1', domain='eis.utoronto.ca', dns=['128.100.102.1', '128.100.20.3'], interfaces=pyvss1_cspec_interfaces) # custom specification for each interface in a list pyvss2_cspec_interfaces = [vss.get_custom_spec_interface(dhcp=False, ip='128.100.102.227', mask='255.255.255.0', gateway=['128.100.102.224'])] pyvss2_cspec = vss.get_custom_spec(hostname='pyvss2', domain='eis.utoronto.ca', dns=['128.100.102.1', '128.100.20.3'], interfaces=pyvss2_cspec_interfaces)
Submit New VM requests
pyvss1 = vss.deploy_vms_from_template(source_template=source_template, description=description, count=1, name='pyvss1', custom_spec=pyvss1_cspec, networks=networks, folder=folder, power_on=True) pyvss2 = vss.deploy_vms_from_template(source_template=source_template, description=description, count=1, name='pyvss2', custom_spec=pyvss2_cspec, networks=networks, folder=folder, power_on=True)
Wait until VM is deployed:
pyvss1_id = vss.wait_for_request(pyvss1.get('_links').get('requests')[0], 'vm_moref', 'Processed') pyvss2_id = vss.wait_for_request(pyvss2.get('_links').get('requests')[0], 'vm_moref', 'Processed')
Validate new VM state:
for vm_id in [pyvss1_id, pyvss2_id]: print(vss.get_vm_state(vm_id).get('power_state'))
Obtain guest operating system IP addresses or ping target ip addresses:
for vm_id in [pyvss1_id, pyvss2_id]: print(vss.get_vm_guest_ip(vm_id)[0].get('ip_address'))
ping 128.100.102.226 PING 128.100.102.226 (128.100.102.226): 56 data bytes 64 bytes from 128.100.102.226: icmp_seq=0 ttl=64 time=0.519 ms 64 bytes from 128.100.102.226: icmp_seq=1 ttl=64 time=0.364 ms ping 128.100.102.227 PING 128.100.102.227 (128.100.102.227): 56 data bytes 64 bytes from 128.100.102.227: icmp_seq=0 ttl=64 time=0.617 ms 64 bytes from 128.100.102.227: icmp_seq=1 ttl=64 time=0.455 ms
Launch a one time virtual machine vSphere client link and access the VMs console.
for vm_id in [pyvss1_id, pyvss2_id]: print(vss.get_vm_vsphere_link(vm_id))
Related articles