VMware vCloud Director(vCD) Test Automation
VMware vCloud Director is one of the most popular tools when it comes to full lifecycle management for business infrastructures. The things that make it so popular among vCloud suite users are agility, efficiency, choice, and control to enhance the service experience, simplify application release automation and, in turn, achieve the fastest time-to-value. Testing software is crucial in order to check whether it will deliver what it promises. When it comes to using hosted VMware vCloud Director, it is necessary to create a set of tests that will validate the proper execution of the vCloud instance. In this blog, I will try to explain the best approach to automate these tests for vCloud Director, but first, let’s see what vCloud Director is-
What is vCloud Director?
VMware vCloud Director enables cloud service providers to convert physical data centers into highly elastic Virtual Data Centers(VDCs). It is used for secure and efficient data delivery along with multi-tenant resource pooling, data center extension, cloud migration, operational visibility, automation, and multi-site management. Some of the benefits that it offers to cloud providers include operational efficiency, differentiation, hybridity, and security, among others.
Now to explain the test automation process for the vCD, I will take an example where I had to automate different scenarios for one of our clients at Opcito. The client wanted to create resources like vApp template, vApp, network, firewall & NAT rules, VPN, etc; then perform verification on this setup; and at the end, delete all the created resources. Now, there are multiple ways to achieve this. But to do this in an efficient way, one must consider the following criteria:
- Low resource utilization
- Ease of automation and maintenance
- Ease of consumption in the CI server
- Ease of running on any region where vCloud Director is installed
- Modularity to run a single test case / single test suite / multiple test cases / all test cases depending on the requirement.
Keeping in mind the aforementioned criteria, we used setup and teardown scripts to create and destroy commonly required resources. The setup and teardown scripts run before and after the execution of test suites, respectively. We created a set of test suites, each containing separate functionalities. Thus, resources required by test suites are created and deleted within test cases, and after the execution of the teardown script, no object remains in the vCloud director, irrespective of whether a test case executes successfully or not.
It will be a good idea to group operations that are to be used from setup, teardown, and test suites, and hence we created common functions for such operations. The operations include creating vApp, creating a network, creating firewall rules, etc. The common functions are handy when new test cases are to be written.
There are different tools that can be used to achieve test automation, such as pyvcloud, vCloud Director APIs, terraform, and vRO. In the scenario that I will be explaining here, I have used pyvcloud and vCloud Director APIs. I will also be elaborating on the advantages and disadvantages along with a sample code.
The reason behind preferring pytest is the flexibility that it adds to test execution and the inherent set of features and functions like creating vApp, creating a network, specifying firewall rules, etc. These functions come in handy while writing new test cases. The common configurable objects, such as network name, template name, IP addresses to be used, public IPs on the edge gateway, etc., are also included in the config file. While going through these files, you can also have a quick glance at objects and values used in test scripts.
Now, let’s have a look at how your setup and teardown scripts will look like -
The setup script includes a setup class with a single test case with separate functions to create expected resources. One can then call these functions from the only test case in this class. For consistency purposes, we have included a test case in the setup script so that we get the report of this test case. This is how the code will look like:
class SetUp(TestCase): def configure_dhcp_environment(self): ''' Configure DHCP routed network, firewall, and NAT rules ''' # Code to create DHCP routed network, firewall, and NAT rules. def test_setup(self): self.configure_dhcp_environment() # Call other functions as required.
As we see in the code, we have combined all code required to set up an HDCP routed network environment in the configure_dhcp_environment() function, and we call it from the setup script test cases.
The Teardown script is a simple script which deletes all resources created from the setup script. The important thing while writing a teardown script is, it should delete all resources irrespective of the success of test cases. This will help to make sure there is no stale resource present in the environment once the test suites are executed. The sample code is as follows:
class TearDown(TestCase): def delete_dhcp_environment(self): ''' Delete DHCP routed network, firewall and NAT rules ''' # Code to delete DHCP routed network, firewall and NAT rules. def test_teardown(self): self.delete_dhcp_environment() # Call other functions as required to cleanup resources.
Test Suites and Test Cases
Each test suite will contain multiple test cases. Each test case will also create resources required for that test case and will have the teardown function. The sample test suite is as follows:
class TestSample(TestCase): @pytest.fixture(scope='function', autouse=True) def cleanup_resources(self): # we have not added any code here, as we are creating resources in the test case. yield # delete resources created from the test case. def test_sample(self): # create resources required for this test case # test case Verification
Here, we have cleanup_resources() as a pytest fixture, which will be called before and after the test case. The part before the yield statement will be executed before each test case. I have not included the code for the test case setup in this case. The part after yield will be executed after the test case, which implies that we will be using it only for teardown.
As mentioned earlier, we can write common functions for common tasks like creating vApp, creating network, etc. The sample code to create vApp from the vApp template is as follows:
def create_vapp_from_template(name, catalog_name, template, description, network_name=None, ip_allocation_mode='dhcp', hostname="admin", password=None, expected_status='success', deploy=True, power_on=True): ''' Create vApp using template :param name: name for the new vApp :param catalog: name of the catalog :param template: template for the vapp from catalog :param description: Description for the network :param network_name: network name for the vApp :param ip_allocation_mode: IP allocation mode (`pool`, `dhcp` and `manual`) :param hostname: hostname for the new VM (for guest OS customization) :param password: password for the new VM (for Guest OS customization) :return: task for vApp creation ''' vdc_obj = get_pyvcloud_vdc() # get vdc object logger.info("Creating %s vapp from template", name) result = vdc_obj.instantiate_vapp(name, catalog, template, description, network_name, ip_allocation_mode=ip_allocation_mode, password=password,hostname=hostname, deploy=deploy, power_on=power_on) common_lib.task_monitor('Waiting for %s vApp to be created' % name, result['Tasks']['Task'], expected_status, timeout=600) logger.info("Created %s vapp from template", name) return result
I have provided parameters to the function so that it can be dynamically used from anywhere during test automation as and when required. In the above code snippet, we get the VDC object and then instantiate vApp with the values that we want. The task_monitor() function then needs to be called. The task monitor function is a wrapper for the task monitor pyvcloud function to make it work with tasks to wait till its completion or failure or timeout.
The next important thing that one needs to focus on is pyvcloud and vCloud Director APIs.
Pyvcloud is Python SDK for vCloud Director. It can be used for setup/teardown and for the verification part of the test cases. It has functions for vApp, VMs, firewall rules, NAT rules, etc. Verification could be to check if the vApp with the specified name is present or not.
- It can be easily used in Python scripts by importing.
- Resource utilization would be minimal as we will create and use an object for a single test case and destroy it immediately after verification.
- Best suited even if the number of test cases in a test suite increases.
- pyvcloud will add overhead to write setup and teardown for each test case.
- Creating a large number of resources(VMs/vApps) would be tedious.
- As of today, pyvcloud does not support all the functionality that is possible on the vCloud Director.
The code snippet from the above-mentioned common function to call pyvcloud function to instantiate vApp will look like this:
vdc_obj = get_pyvcloud_vdc() # get vdc object result = vdc_obj.instantiate_vapp(name, catalog, template, description, network_name, ip_allocation_mode=ip_allocation_mode, password=password,hostname=hostname, deploy=deploy, power_on=power_on) common_lib.task_monitor('Waiting for %s vApp to be created' % name, result['Tasks']['Task'],
Here, instantiate_vapp() is pyvcloud function of a VDC object. After calling instantiate_vapp(), we will wait for vApp to be created using common_lib.task_monitor(),
vCloud Director APIs
vCloud Director APIs can be used to perform all the operations supported by vCloud Director. We can map operations on the vCloud Director portal to vCloud Director APIs and use the respective APIs to achieve the same operation in the test suite/test case.
- Each operation supported on the vCloud Director portal can be achieved through APIs, as vCloud Director portal uses vCloud Director APIs internally.
- We need to write functions around these APIs, including their dependencies. This could be tedious.
- We need to know APIs in detail in order to use them in the script. The tricky part is headers and request parameters.
- Some APIs support json and xml formats, while others support only xml. We need to be careful about this depending on which APIs we are using.
Below is a sample code to get the network information
network_data = rest.get('api/admin/network/%s' % network_id)
As you can see, this statement gives details of the network with the given network_id. We have also developed the rest module to handle REST API calls.
One should consider the following points while using vCloud Director APIs:
We need to be careful about the content type of the API that we are using. vCloud Director APIs support json as well as xml.
Some of the operations on the vCloud Director are asynchronous; in that case, the vCloud Director API return the Task object in response. For example, vApp creation operation takes some time, but pyvcloud function and API both have a Task object in response to instantiate vApp. We should wait for this operation to finish before moving ahead with the further test cases.
You should make your API version configurable in the config file and use the same version for all APIs in the request header. This will give you the flexibility to switch between API versions in the future from a central location(config file). But keep in mind that if the response of any API changes in the newer versions, then you will need to change the respective code to handle it.
Retaining existing firewall and NAT rules while creating new ones
When we create new firewall and NAT rules through API PUT calls, we should make sure that we add a new rule in the existing rules and then execute the PUT call so that we retain the existing rules and add a new one. The same is applicable while deleting firewall/NAT rules.
We can use html-report python module to generate a test execution report. This works fine with pytest.
As mentioned earlier, there are multiple ways to achieve what I have explained in this blog. But if you want to do with efficient resource utilization, extendable test automation framework, and presentable reporting, I think this should be your best bet.