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

  1. Import VssManager and Create a VssManager instance:

    from pyvss.manager import VssManager
    vss = VssManager()
  2.  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)
  3. 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'
  4. 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)
  5. 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)
  6. 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')
  7. Validate new VM state:

    for vm_id in [pyvss1_id, pyvss2_id]:
        print(vss.get_vm_state(vm_id).get('power_state'))
        
  8. 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
  9. 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))