
The Software Defined Data Center – It’s everywhere. You can’t go to any big trade show in the IT industry without hearing the phrase “Software Defined X” being tossed around at all of the booths. Over the last decade or so we have seen software take center stage in our data centers – being the glue that holds everything together. With this focus on software it’s extremely important that companies develop and support API’s within their products – one, it’s our way of taking application x and integrating it with application y. Secondly, its important for the success of the company – without an API organizations may look elsewhere for a solution that provides one – and without an API vendors cannot securely control the access into their solutions, leaving customers developing unsupported and faulty applications to get around it.
One big example that shows the benefit of api integration that I always like to use is that of the deployment of a VM. Sure, we use our Hypervisor of choice to take our templates and clone VMs from them, providing some sort of automation and orchestration around the configuration of that said VM – but the job doesn’t simply end here – we have monitoring solutions we may need to add our VM into, we have IP management tools in order to integrate into to retrieve IPs and DNS information, and most importantly, we have to ensure that our newly created VM is adequately protected in terms of backup and recovery. With so many hands inside of the data center creating VMs our backup administrators might not always know a certain solution has been created – and when a failure occurs, there’s a pretty good chance we won’t be able to recover without any backups – so it’s this situation we will look at today…
Automatically protecting our VMs
Our software of choice today will be Nakivo Backup and Replication – a company based out of Silicon Valley providing data protection solutions. Nakivo provides full API integration into their backup suite allowing administrators and developers to create automation around the creation, modification, and removal of jobs. The scope of our integration will be as follows – Let’s create a simply vRealize Orchestrator workflow that will allow us to simply right-click a VM from within the vSphere Web Client, and add this VM into an already existing backup job. From here I’ll let your imagination run wild – maybe you integrate this code into your VM deployment workflow to automatically protect it on creation – the point is that we have a starting point to look at the possibilities of consuming Nakivo’s API and creating some automation within your environment for backup and recovery.
A little about the Nakivo API
Before we get into the actual creation of the vRO workflow it’s best we understand a little bit about the Nakivo API itself. Nakivo provides an API based around JSON content – so all of our requests and responses will be formatted within JSON format. These requests will all go through using POST, and are always provided to the /c/router realm (ie https://ip_of_nakivo:4443/c/router) As far as authentication goes Nakivo utilizes cookie based authentication – what this means is that our first request will be sent to the login method, upon which we will receive a JSESSIONID which we will have to pass with every subsequent request in order to secure our connection. As we can see from the example request below they need to be formatted in such a way that we first specify and instance (IE AuthenticationManagement, BackupManagement, InventoryManagement, etc) and a method (IE login, saveJob, getJob, etc). From there we attach the data associated with the method and instance, as well as a transaction id (tid). The transaction id can utilize an auto increment integer if you like, or can simply be set to any integer – it’s main purpose is to group multiple method calls into a single POST – which we won’t be doing anyways so you will see I always use 1.
var requestJSON = “{‘action’: ‘AuthenticationManagement’,’method’:’login’,’data’: [admin,VMware1!,true],’type’: ‘rpc’,’tid’: 1}”;
Above we show an example of a login request in JavaScript, because this is the language of choice for vRealize Orchestrator which we will be using – but do remember that you could use PHP/JAVA/PowerShell – whatever language you want so long as you can form an HTTP request and send JSON along with it.
On with the workflow
Before diving right into the code it’s best to take a look at the different sections or components that we will need to run through in order to add a given VM to a Nakivo job through vRealize Orchestrator. With that said we can break the process down into the following sections…
- Add Nakivo as an HTTPRest object within vRO
- Create workflow w/ VM as an input object and the Nakivo HTTPREST as an argument
- Create some variables in regards to our VM (IE Name, Cluster, etc)
- Login to Nakivo to retrieve session
- Retrieve our target job
- Find VMs Cluster ID within Nakivo (ClusterID is required in order to find the actual VM within Nakivo).
- Gather VM information from within Nakivo
- Gather information about our repository from within Nakivo
- Build JSON request and add VM to job
With our workflow broken down into manageable chunks let’s go ahead and start coding
Add Nakivo as an HTTPRest object.
If you have ever worked with the HTTPRest plugin within vRO then this will seem like review – however for those that haven’t let’s take a look at the process of getting this setup. From within workflow view simply run the ‘Add a REST host’ workflow located under the HTTP-REST/Configuration folders. As far as parameters go simply give the host a name, use https://ip_of_nakivo:4443 as the URL, and be sure to select ‘Yes’ under the certification acceptance as shown below
The remaining steps are somewhat invalid as it pertains to adding Nakivo as a REST host within vRO – for authentication I selected basic and provided the credentials for Nakivo – however this really doesn’t matter as we are going to use cookie/header based authentication through our code anyways – however something needs to be selected and inputted within vRO. After clicking submit the NakivoAPI REST host should be added to our vRO inventory.
Workflow creation
As far as the workflow goes I’ve tried to keep it as simple as possible, requiring only 1 input attribute and 1 input parameter as follows
- Input Attribute (Name: NakivoAPI – Type: RESTHost – Value: set to the Nakivo object created earlier
- Input Parameter (Name: sourceVM – Type: VC:VirtualMachine )
Code time!
After this simply drag and drop a scriptable task into the Schema and we get started with the code! I’ve always found it easier to simply just display all the code and then go through the main sections by line afterwards. As far as the javascript we need you can find it below…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
var vmName = sourceVM.name var cluster = System.getModule("com.vmware.library.vc.cluster").getComputeResourceOfVm(sourceVM); var clusterName = cluster.name; // login and retreive sessionID var requestJSON = "{'action': 'AuthenticationManagement','method':'login','data': [admin,VMware1!,true],'type': 'rpc','tid': 1}"; var request = NakivoAPI.createRequest("POST", "/c/router", requestJSON); request.setHeader("Content-Type","application/json"); var response = request.execute(); var headers = response.getAllHeaders(); var cookie = headers.get("Set-Cookie"); // retrieve target job requestJSON = "{'action': 'JobManagement','method':'getJob','data': [1],'type': 'rpc','tid': 1}"; request = NakivoAPI.createRequest("POST","/c/router",requestJSON); request.setHeader("Content-Type","application/json"); request.setHeader("Cookie", cookie); response = request.execute(); var jsonResponse = JSON.parse(response.contentAsString); var job = jsonResponse.data; // find clusterID requestJSON = "{'action': 'InventoryManagement','method':'collect','data': [{'viewType':'VIRTUAL_ENVIRONMENT'}],'type': 'rpc','tid': 1}"; request = NakivoAPI.createRequest("POST","/c/router",requestJSON); request.setHeader("Content-Type","application/json"); request.setHeader("Cookie", cookie); response = request.execute(); jsonResponse = JSON.parse(response.contentAsString); // reduce to datacenters var vcenter = jsonResponse.data.children[0]; var datacenters = vcenter.children; var datacenter; var cluster; for ( var p in datacenters) { for (var c in datacenters[p].children) { if (datacenters[p].children[c].name == clusterName) { cluster = datacenters[p].children[c]; } } } var clusterid = cluster.identifier; // look in cluster for VM info... requestJSON = "{'action': 'InventoryManagement','method':'list','data': [{'nodeType':'VMWARE_CLUSTER','nodeId': '" + clusterid + "','includeTypes': ['VM'] }],'type': 'rpc','tid': 1}"; request = NakivoAPI.createRequest("POST","/c/router",requestJSON); request.setHeader("Content-Type","application/json"); request.setHeader("Cookie", cookie); response = request.execute(); jsonResponse = JSON.parse(response.contentAsString); var vms = JSON.parse(response.contentAsString); vms = vms.data.children; var vm; for (var p in vms) { if (vms[p].name == vmName) { vm = vms[p]; } } // get more info on VM requestJSON = "{'action': 'InventoryManagement','method':'getNodes','data': [true, ['"+ vm.vid + "']],'type': 'rpc','tid': 1}"; request = NakivoAPI.createRequest("POST","/c/router",requestJSON); request.setHeader("Content-Type","application/json"); request.setHeader("Cookie", cookie); response = request.execute(); var vminfo = JSON.parse(response.contentAsString); vminfo = vminfo.data.children[0]; var vmdisk = vminfo.extendedInfo.disks[0].vid; // get target storage requestJSON = "{'action': 'InventoryManagement','method':'list','data': [{'includeTypes': ['BACKUP_REPOSITORY'] }],'type': 'rpc','tid': 1}"; request = NakivoAPI.createRequest("POST","/c/router",requestJSON); request.setHeader("Content-Type","application/json"); request.setHeader("Cookie", cookie); response = request.execute(); jsonResponse = JSON.parse(response.contentAsString); var targetVid = jsonResponse.data.children[0].vid; //build data portion of JSON to add VM to job var jsonSTR = '{ "sourceVid": "' + vminfo.vid + '","targetStorageVid": "' + targetVid + '","mappings": [{"type": "NORMAL","sourceVid": "' + vmdisk + '"}], "appAwareEnabled": false}'; var json = JSON.parse(jsonSTR); //push new object to original job job.objects.push(json); System.log(JSON.stringify(job)); // let's try and push this back in now.... requestJSON = "{'action': 'JobManagement','method': 'saveJob', 'data': [" + JSON.stringify(job) + "],'type': 'rpc','tid': 1}"; request = NakivoAPI.createRequest("POST","/c/router",requestJSON); request.setHeader("Content-Type","application/json"); request.setHeader("Cookie", cookie); response = request.execute(); // done!!!! |
Lines 1 -3 – Here we simply setup a few variables we will need later on within the script; vmName, which is assigned the name attribute of our input parameter sourceVM as well as going out and running a built in action to get the name of the cluster that the VM belongs to. Both these variables will be needed when we attempt to get all of the information we need to add the VM to the backup job.
Lines 5-11 – This is our request to login to Nakivo. As you can see we simply create our request and send the login method, along with the associated login data to the AuthenticationManagement interface. This request basically authenticates us and sends back the JSSESSIONID that we need in order to make subsequent requests, which we store in a cookie variable on line 11.
Lines 13 – 20 – Again, we make a request to Nakivo to get our job that we want to add the backup to. I only have one job within my environment so I’ve simply utilized the getJob method and sent the data type of 1 (the jobID) since I know that is my one and only job id in the system. If need be you may need to write a similar request to get the job id if you don’t know it – Nakivo does provide methods within their API to search for a job ID by the job name. Also note, since this is a subsequent request after a login we are sending our cookie authentication data on line 17 – also, we are taking our response data and storing it in a variable named job on line 20 – we will need this later when we update the job.
Lines 22 – 45 – This is basically a request to the InventoryManagement interface that we can use to find out what the id (as it is within Nakivo) of the cluster housing the virtual machine. First, on line 23 we build a request to basically return our complete virtual infrastructure inventory – upon which we parse through from lines 35-44 looking for a match on our cluster names. I’ve had to loop through data centers as my test environment contains more than one virtual data center. Finally, on line 45 we simply assign the clusterid variable the nakivo identifier of the cluster.
Lines 47 – 73 – Here we use our cluster identifier and basically list out the VM inventory within it. After looping through when we find a match on our VM name, we simply assign it to a vm variable. We then, on line 66 send a request to the InventoryManagement interface again, this time looking at the Virtual Machine level and sending the identifier of our newly discovered VM. Once we have the response we assign the identifier of the VMs disk(s) on Line 73 to a variable. Again, I know this environment and I know the VM only contains one disk so I’ve hard coded my index – if it was unknown, or truly automated you would most likely have to loop through the disks here to get your desired output.
Lines 75 – 82 – This block of code is used to get the identifier of the target storage, or repository within Nakivo. Again we need this information for our final request that will add the VM to the job – and again, this is a known environment so I could simply hard code my array index on line 82 to return the proper repository (as there is only one).
Lines 84 – 90 – Here we are simply building out the JSON variable that we need in order to push all of the information we have previously gathered above. We basically form our string on line 85, convert it to JSON directly after, and push it into the original job variable we set on line 20.
Lines 92-99 – Ah, finally – This block basically takes all of our hard work and pushes the job back into the saveJob method of the Nakivo JobManagement interface. Once executed you should manually see your job info within Nakivo update reflecting the new VMs added to the job.
So there you have it! A completely automated way of selecting a VM within vRealize Orchestrator and adding it to a Nakivo backup job – all without having to open up the Nakivo UI at all!
But wait, there’s more!
Ahh – we eliminated the need of opening up the Nakivo UI but how about eliminating the Orchestrator client as well – and simply just executing this job from directly within the vSphere Web Client – sounds like a good idea to me! If you have properly, and I say that because it can sometimes be difficult – but if you have properly integrated vRO and vSphere then doing this is a pretty easy task.
Within the ‘Context Actions’ tab on our vRO configuration within the web client simply click ‘+’ to add a new action. As shown below we can simply browse our workflow library and select our newly created Nakivo workflow and associate that with the right-click context menu of a virtual machine.
What we have essentially done now is allowed our administrators to simply right-click on a VM, browse to ‘All vRealize Orchestrator Actions’ and click on our workflow name. From there the vRO workflow will take the associated VM (the one we right-clicked on) and assign it to our sourceVM parameter – meaning we’ve taken the complete process of logging into Nakivo, editing our backup job, adding a new VM, and saving it and converted it to a simple right click, followed up by a left click – without having to leave the vSphere Web Client!
So in all this is a pretty basic example of some of the things we can do with the Nakivo API – and it followed a pretty simple and stripped down workflow – but the point is Nakivo offers a wide variety of methods and integration points into their product. Pretty much anything you can do within the GUI can be performed by making calls to the API. This is what helps a product integrate into the Software Defined Data center – and what allows administrators to save time, provide consistency, all the while ensuring our data is protected. Nakivo also has a wide variety of documentation and also a Java SDK built around their API, complete with documents and explanations around all of the interfaces provided. If you are interested in learning more, about Nakivo’s API or Nakivo’s products in general head on over to their site here – you can get started for the low cost of free! Until next time, happy automating!