0 0

Ask Rick: Setting QoS at Scale

Rick Ehrhart is Tintri’s Developer Evangelist, Engineering. In his column, Rick solves IT problems with one simple solution: Tintri storage. Got a question? Let us know.

How do I set QoS at scale for all VMs in a server group?

With the introduction of Service Groups in TGC 2.0, and QoS in VMstore, our customers have brought to us several powerful new use cases. One such use case is the application of QoS at scale for all VMs in a Service Group, say, in a VDI environment, or that belong to a specific service provider tenant. Below is the Python script that I wrote that looks for a specific service group and sets the QoS for each VM in it.

This Python script has some bits of useful code for checking Tintri products and TGC and VMstore API versions. Let's look at them first.

# Get the preferred version and product
r = tintri.api_get(server_name, '/info')
json_info = r.json()
preferred_version = json_info['preferredVersion']
product_name = json_info['productName']

# Check for correct product
if product_name != "Tintri Global Center":
    print_error("Tintri server needs to be Tintri Global Center, not a " + product_name)

# Check for the correct version
versions = preferred_version.split(".")
major_version = versions[0]
minor_version = int(versions[1])
if major_version != "v310":
    print_error("Incorrect major version: " + major_version + ".  Should be v310.")
if minor_version < 21:
    print_error("Incorrect minor Version: " + minor_version + ".  Should be 21 or greater")

The /info API returns the preferred API version and the product. Here we check for Tintri Global Center (TGC). Next we verify that the API version is v310.21, because service groups are available in API version v310.21 and later. Note that the major_version is used as a string and minor_version is used as a number.

Next, we get the TGC service groups:

url = "/v310/servicegroup"
r = tintri.api_get(server_name, url, session_id)

Nothing special here. I didn't request the service groups in pages, because I assumed that was a small number of them. Since the script doesn't take a server group name as an input parameter, there is a loop that searches for the first service group that has more than 2 members, and uses it. Once found, the function get_sg_member() is called with the service group UUID.

The get_sg_member() function returns a list of VmInfo objects, which contain the VM name, UUID, and VMstore the VM's storage is residing on. Look at how we get the members of a service group:

# Create filter to obtain live VMs and VMs that belong in specified
# the service group.
sg_filter = {'live': 'TRUE',
             'serviceGroupIds' : sg_uuid}

url = "/v310/vm"

r = tintri.api_get_query(server_name, url, sg_filter, session_id)

The API /v310/servicegroup/{id}/members is currently not available for TGC, so we have to invoke '/v310/vm' filtering for VMs in the service group specified by the service group UUID.

Again, pagination wasn't used. Please see get _vms _page.py for a pagination example. Below is the loop that creates the VmInfo objects.

# For each live VM, create a VM info object
items = member_paginated_result["items"]
for vm in items:
    if not vm["isLive"]:
    member_vm = vm["vmware"]["name"]
    member_vmstore = vm["vmstoreName"]
    member_vm_uuid = vm["uuid"]["uuid"]
    print_debug("   " + member_vm + " (" + member_vmstore + ")")

    vm_info = VmInfo(member_vm, member_vm_uuid, member_vmstore)

For setting the QoS, we only want Live VMs; therefore, a quick check is done for every VM in the service group. A Live VM is a VM that you can take a snapshot of. The VM name is used for readability, but the VMstore name and VM UUID is absolutely required to set the QoS.

Currently QoS is set on the VMstore, so for each VM, the code logs into the VMstore, sets the QoS, and logs out. This could be optimized to set the QoS for all the VMs on a specific VMstore in a single API operation. Remember that a TGC service group could contain VMs from different VMstores, so the simple approach is taken. Let's look at the set_qos() function.

The set_qos() takes a VMstore server name, user name, password, a list of VM UUIDs, and the minimum and maximum IOP values for QoS. The PUT API uses the Multiple Selection Request DTO.

# Create new QoS object with the fields to be changed
modify_qos_info = {'minNormalizedIops': int(new_min_value),
                   'maxNormalizedIops': int(new_max_value),
                   'typeId': 'com.tintri.api.rest.v310.dto.domain.beans.vm.VirtualMachineQoSConfig'

# Create the MultipleSelectionRequest object
MS_Request = {'typeId': 'com.tintri.api.rest.v310.dto.MultipleSelectionRequest',
              'ids': vm_uuids,
              'newValue': modify_qos_info,
              'propertyNames': ["minNormalizedIops", "maxNormalizedIops"]

The Multiple Selection Request, MS_Request, contains a list of ids to modify, a DTO with new values, and the property names to modify. In the code above, the DTO, modify_qos_info, contains the new values for minNormalizedIops and maxNormalizedIops. Note that these fields match the values for propertyNames in MS_Request. The PUT API is called with MS_Request.

# Update the min and max QoS IOPs
modify_qos_url = "/v310/vm/qosConfig"
r = tintri.api_put(server_name, modify_qos_url, MS_Request, session_id)

This code is located at set _qos _service _group.py on the Tintri GitHub site.

Enjoy servicing IOPs,

   - Rick -

Rick Ehrhart / May 07, 2015

Rick Ehrhart is Tintri’s Developer Evangelist with a strong software development background focusing on APIs. Rick has assisted many companies with API integrations including VMware, NetApp, HP, ...more