11-17-2015 02:25 PM - edited 03-01-2019 06:39 AM
Task Name | Multi VM Provisioning with Post Provisioning and Rollback |
Description | |
Prerequisites |
|
Category | Workflow |
Components | vSphere 5.x |
User Inputs | e-mail address |
Output | e-mail with counter |
Instructions for Regular Workflow Use:
The Workflow:
'
The workflow input with marked changes for different environment:
Catalog and VDC need to change from drop down in admin Input Value!
If desired the starting VM number needs to change as well.
The mapped input in the VM deploy task:
Workflow execution:
The catalog with the post Provisioning workflow selected:
The workflow will e-mail 2 inout variables:
The post provisioning workflow:
This workflow is also in the attached zip file.
The workflow will kick off 2 child workflows (Since deploy 2 VMs was selected):
The e-mail from the post provisioning workflow:
System Policy:
The Code:
importPackage(com.cloupia.model.cIM);
importPackage(java.util);
importPackage(java.lang);
importPackage(java.io);
importPackage(com.cloupia.lib.util);
importPackage(com.cloupia.model.cIM);
importPackage(com.cloupia.service.cIM.inframgr);
importPackage(org.apache.commons.httpclient);
importPackage(org.apache.commons.httpclient.cookie);
importPackage(org.apache.commons.httpclient.methods);
importPackage(org.apache.commons.httpclient.auth);
importPackage(com.cloupia.model.cEvent.notify);
importPackage(com.cloupia.lib.util.mail);
importPackage(com.cloupia.fw.objstore);
importPackage(com.cloupia.lib.cIaaS.vmware);
importPackage(com.cloupia.feature.customactions.configs);
importPackage(com.cloupia.lib.util.managedreports);
var delaySecondsBetweenInvocation = 30;
function sleep()
{
var milliseconds = delaySecondsBetweenInvocation * 1000;
Thread.sleep(milliseconds);
}
var catID = input.CatalogName;
var vdcID = input.VDCName;
var vmowner = input.VMOwner;
var vmname = input.VMName;
var vmcomment = input.VMComment;
var vmcpu = input.VMCPU;
var vmmemory = input.VMMemory;
var vmdisksize = input.VMDiskSize;
var wfi1 = input.WorkflowInput1;
var wfi2 = input.WorkflowInput2;
var counter = input.Counter;
var startcounter = input.StartCounter;
//
// Convert the VDC and Catalog ID to a name
//
var vdc2 = VDCUtil.getVDC(vdcID);
var vdcName = vdc2.getVdcName();
var cat2 = VDCUtil.getVDCCatalogItem(catID);
var catName = cat2.getCatalogItemName();
logger.addInfo("---------------------------------");
logger.addInfo("params vdcID = "+vdcID);
logger.addInfo("params vdcName = "+vdcName);
logger.addInfo("params catID = "+catID);
logger.addInfo("params cat = "+catName);
logger.addInfo("---------------------------------");
//
// Set up the provision VM information
//
var params = new APIProvisionParams();
logger.addInfo("params cat = "+catName);
params.setCatalogName(catName);
logger.addInfo("VDC = "+vdcName);
params.setVdcName(vdcName);
logger.addInfo("params vmowner = "+vmowner);
params.setUserID(vmowner);
logger.addInfo("params vmname = "+vmname);
params.setVmName(vmname);
logger.addInfo("params vmcomment = "+vmcomment);
params.setComments(vmcomment);
logger.addInfo("params vmcpu = "+vmcpu);
params.setCores(vmcpu);
logger.addInfo("params vmmemory = "+vmmemory);
params.setMemoryMB(vmmemory);
logger.addInfo("params disksize1 = "+vmdisksize);
params.setDiskGB(vmdisksize);
//
//If Post Provision workflow has user inputs then the following code is required to pass user inputs to API.
//If the post provision workflow has only task inputs then skip the below code.
//It is not required to setPostProvWFUserInputs.
//remember the catalog has the post provisioning workflow
//here only the inout parameters for the postprovisioning workflow are set
//
logger.addInfo("params wfi1 = "+wfi1);
var nv1 = new APINameValue("A1",wfi1);
logger.addInfo("params wfi2 = "+wfi2);
var nv2 = new APINameValue("A2",wfi2);
logger.addInfo("---------------------------------");
var list = new APINameValueList();
list.addNameValue(nv1);
list.addNameValue(nv2);
//Add this inputs list to provision params.
params.setPostProvWFUserInputs(list);
//
// Call New Service Request provision VM
//
var qty = 1;
try {
qty = Integer.valueOf(counter);
} catch( e) {
logger.addWarning("Invalid counter specified:"+counter+ " provisioning one VM");
}
try {
sc = Integer.valueOf(startcounter);
} catch( e) {
logger.addWarning("Invalid start counter specified:"+startcounter+ " provisioning one VM");
}
logger.addInfo("Start Counter ="+ startcounter);
var childSrIdArray = [];
// start loop
for (var ctr = 0; ctr < qty; ctr = ctr + 1)
{
logger.addInfo("Provision VM ="+ (ctr+1) + " of "+qty);
var number = sc + ctr + 1;
logger.addInfo("VM Number ="+ number);
logger.addInfo("params vmname = "+vmname+number);
params.setVmName(vmname+number);
logger.addInfo("params vmcomment = "+vmcomment+number);
params.setComments(vmcomment+number);
logger.addInfo("-------------------Provsion VM---------------------------------");
var srId = ctxt.getAPI().userAPIProvisionRequest(params);
logger.addInfo("childSrId= "+srId);
childSrIdArray[ctr] = srId;
logger.addInfo("Sleeping for a bit (30 sec...");
sleep();
}
// end loop
logger.addInfo("-------------------Waiting for Child Workflow(s) to Finish---------------------------------");
for (var i=0; i<childSrIdArray.length; i++)
{
var childSrId = childSrIdArray[i];
var status = ctxt.waitForCompletion(childSrId, 1800000);
if (status == 0)
{
logger.addInfo("Provisioned SR ID ="+ childSrId+ " successfully.");
} else {
logger.addError("SR ID ="+ childSrId+ " failed");
}
}
rollbackMultiVM(childSrIdArray);
function rollbackMultiVM(childSrIdArray){
for(var i=0; i<childSrIdArray.length; i++){
var srId = childSrIdArray[i];
var vmList = GroupManagerImpl.getVMsAssociatedWithServiceRequest(srId);
ctxt.getChangeTracker().undoableResourceModified(VMwareAssetTypeConstants.VMWARE_RELEASE_IP, srId+"",srId+"",
"IP to be released for SR:" + srId,
RemoveIPAddressReservationConfig.HANDLER_NAME,
new RemoveIPAddressReservationConfig(srId));
if(vmList != null && vmList.size()>0){
for(var j=0; j<vmList.size(); j++){
var gvm = vmList.get(j);
ctxt.getChangeTracker().undoableResourceModified(VMwareAssetTypeConstants.VMWARE_VM, String.valueOf(gvm.getVmId()),
gvm.getInstanceId(), "VM " + gvm.getInstanceId() + " provisioned on the host " + gvm.getParentHost(),
DeleteVMConfig.HANDLER_NAME,
new DeleteVMConfig(gvm.getVmId()));
}
}
}
}
Run with 3 VM's and rollback:
Workflow Inputs:
- VMname
- VMComment
- VDC
- Catalog
- Memory
- CPU
- Disk
- HowManyVMs
- VMStartCounter
- WorkFlowInput1
- WorkFlowInput2
- VMOwner
Nov 24, 2015 17:52:43 UTC Request submitted
Nov 24, 2015 17:52:48 UTC Executing workflow item number 1
Nov 24, 2015 17:52:48 UTC Completed workflow item number 0, with status Completed
Nov 24, 2015 17:52:55 UTC Executing workflow item number 2
Nov 24, 2015 17:52:55 UTC Trigger context executeWorkFlowStep called
Nov 24, 2015 17:52:55 UTC Executing custom action MultiVMDeploymentWithPostprovisioning (custom_MultiVMDeploymentwithPostProvisioning)
Nov 24, 2015 17:52:55 UTC Executing custom action MultiVMDeploymentWithPostprovisioning (custom_MultiVMDeploymentwithPostProvisioning)
Nov 24, 2015 17:52:55 UTC Executing custom script for MultiVMDeploymentwithPostProvisioning
Nov 24, 2015 17:52:58 UTC ---------------------------------
Nov 24, 2015 17:52:58 UTC params vdcID = 127
Nov 24, 2015 17:52:58 UTC params vdcName = VDC-Prod
Nov 24, 2015 17:52:58 UTC params catID = 154
Nov 24, 2015 17:52:58 UTC params cat = LinuxWebApp
Nov 24, 2015 17:52:58 UTC ---------------------------------
Nov 24, 2015 17:52:58 UTC params cat = LinuxWebApp
Nov 24, 2015 17:52:58 UTC VDC = VDC-Prod
Nov 24, 2015 17:52:58 UTC params vmowner = orf
Nov 24, 2015 17:52:58 UTC params vmname = Rock
Nov 24, 2015 17:52:58 UTC params vmcomment = Rock
Nov 24, 2015 17:52:58 UTC params vmcpu = 2
Nov 24, 2015 17:52:58 UTC params vmmemory = 2048
Nov 24, 2015 17:52:58 UTC params disksize1 = 10
Nov 24, 2015 17:52:58 UTC params wfi1 = happy
Nov 24, 2015 17:52:58 UTC params wfi2 = tuesday
Nov 24, 2015 17:52:58 UTC ---------------------------------
Nov 24, 2015 17:52:58 UTC Start Counter =99
Nov 24, 2015 17:52:58 UTC Provision VM =1 of 3
Nov 24, 2015 17:52:58 UTC VM Number =100
Nov 24, 2015 17:52:58 UTC params vmname = Rock100
Nov 24, 2015 17:52:58 UTC params vmcomment = Rock100
Nov 24, 2015 17:52:58 UTC -------------------Provsion VM---------------------------------
Nov 24, 2015 17:53:04 UTC childSrId= 5903
Nov 24, 2015 17:53:04 UTC Sleeping for a bit (30 sec...
Nov 24, 2015 17:53:34 UTC Provision VM =2 of 3
Nov 24, 2015 17:53:34 UTC VM Number =101
Nov 24, 2015 17:53:34 UTC params vmname = Rock101
Nov 24, 2015 17:53:34 UTC params vmcomment = Rock101
Nov 24, 2015 17:53:34 UTC -------------------Provsion VM---------------------------------
Nov 24, 2015 17:53:41 UTC childSrId= 5904
Nov 24, 2015 17:53:41 UTC Sleeping for a bit (30 sec...
Nov 24, 2015 17:54:11 UTC Provision VM =3 of 3
Nov 24, 2015 17:54:11 UTC VM Number =102
Nov 24, 2015 17:54:11 UTC params vmname = Rock102
Nov 24, 2015 17:54:11 UTC params vmcomment = Rock102
Nov 24, 2015 17:54:11 UTC -------------------Provsion VM---------------------------------
Nov 24, 2015 17:54:17 UTC childSrId= 5905
Nov 24, 2015 17:54:17 UTC Sleeping for a bit (30 sec...
Nov 24, 2015 17:54:47 UTC -------------------Done Waiting for Child Workflow to Finish---------------------------------
Nov 24, 2015 18:08:40 UTC Workflow with SR-ID 5903 is complete
Nov 24, 2015 18:08:40 UTC Provisioned SR ID =5903 successfully.
Nov 24, 2015 18:08:50 UTC Workflow with SR-ID 5904 is complete
Nov 24, 2015 18:08:50 UTC Provisioned SR ID =5904 successfully.
Nov 24, 2015 18:09:00 UTC Workflow with SR-ID 5905 is complete
Nov 24, 2015 18:09:00 UTC Provisioned SR ID =5905 successfully.
Nov 24, 2015 18:09:00 UTC Task #1 (MultiVMDeploymentWithPostprovisioning (custom_MultiVMDeploymentwithPostProvisioning)) completed successfully in 965 seconds
Nov 24, 2015 18:09:00 UTC Input/Output values for Task #1 (MultiVMDeploymentWithPostprovisioning (custom_MultiVMDeploymentwithPostProvisioning)):
Nov 24, 2015 18:09:00 UTC [Mapped Input: CatalogName = 154]
Nov 24, 2015 18:09:00 UTC [Mapped Input: VDCName = 127]
Nov 24, 2015 18:09:00 UTC [Template Input:VMOwner = ${INITIATING_USER}]
Nov 24, 2015 18:09:00 UTC [Resolved Template Input: VMOwner = orf]
Nov 24, 2015 18:09:00 UTC [Mapped Input: VMOwner = orf]
Nov 24, 2015 18:09:00 UTC [Mapped Input: VMName = Rock]
Nov 24, 2015 18:09:00 UTC [Mapped Input: VMComment = Rock]
Nov 24, 2015 18:09:00 UTC [Mapped Input: VMCPU = 2]
Nov 24, 2015 18:09:00 UTC [Mapped Input: VMMemory = 2048]
Nov 24, 2015 18:09:00 UTC [Mapped Input: VMDiskSize = 10]
Nov 24, 2015 18:09:00 UTC [Mapped Input: WorkflowInput1 = happy]
Nov 24, 2015 18:09:00 UTC [Mapped Input: WorkflowInput2 = tuesday]
Nov 24, 2015 18:09:00 UTC [Mapped Input: Counter = 3]
Nov 24, 2015 18:09:00 UTC [Mapped Input: StartCounter = 99]
Nov 24, 2015 18:09:00 UTC Completed workflow item number 1, with status Completed
Nov 24, 2015 18:09:06 UTC Executing workflow item number 3
Nov 24, 2015 18:09:06 UTC Completed workflow item number 2, with status Completed
The rollback options:
The rollback:
Here are the other options that the current workflow does not account for as input to the API call:
In ASCII form:
/app/api/rest?formatType=json&opName=userAPIProvisionRequest&opData={param0:{"catalogName":"sample","vdcName":"sample","userID":"sample","durationHours":1000,"beginTime":0,"quantity":1000,"memoryMB":0,"diskGB":1000,"cores":1000,"estimatedCost":1000.0,"comments":"sample","additionalInfo":"sample","chargeFrequency":1000,"nicAliasName":"sample","nicPortGroupName":"sample","resourceAllocated":true,"allocatedHost":"sample","allocatedDataStore":"sample","allocatedResourcePool":"sample","altAllocatedHost":"sample","altAllocatedDataStore":"sample","altAllocatedResourcePool":"sample","customStartupMemory":1000.0,"customMaxMemory":1000.0,"customMemoryBuffer":1000.0,"customMemoryConfig":true,"customStoragePolicy":"sample","allocatedCluster":"sample","customCpuSockets":1000,"customCpuCoresPerSocket":1000,"altAllocatedCluster":"sample","allocatedAddnlDatastores":"sample","altAllocatedAddnlDatastores":"sample","altAllocatedAddnlVNICs":"sample","altAllocatedAddnlVNICsIpv6":"sample","selectedDiskDataStore":"sample","actionId":"sample","vmName":"sample","vdcCategory":"sample","windowsLicensePool":"sample","templateUserId":"sample","templatePassword":"sample","credentialOption":"sample","provisionAllDisk":true,"enableGuestCustomization":true,"enablePostProvisioningCustomActions":true,"workflow":"sample","vmId":1000,"vMAppChargeFrequency":1000,"activeVMAppCost":1000.0,"inactiveVMAppCost":1000.0,"useLinkedClone":true,"snapshotId":1000,"snapshotKey":"sample","newSnapshotName":"sample","isHighlyAvailable":true,"overrideCatalogCategoryId":1000,"nicIPAddressOverride":"sample","postProvWFUserInputs":{"list":[{"name":"sample","value":"sample"},{"name":"sample","value":"sample"}]}}}
Notes on the rollback Function.
Thank you goes to Gabor Szabo and Tejeswar Sahu
Questions:
I would like to ask some clarification question:
1.) [endif]Is there a mandatory rule for the format of the „undoHandler” variable or can I choose it freely?
2.) [endif]What is the role of the first four parameter of the “ChangeTracker().undoableResourceModified()” method (assetType, assetId, assetLabel, description)? Where are these used and are there any rule for the values I need to be aware of?
3.) [endif]Do I need to clean-up the resources I have used for the rollback (like the undoContext or undoConfig)? Or it is done automatically?
answer for my Q1:
the format of the „undoHandler” string MUST be „custom_<Name-Of-A-Custom-Task>”, otherwise UCSD Javascript interpreter throws an exception.
Example: if a custom task is called “MyTask”, the undoHandler must be “custom_MyTask”. Either “custom1_MyTask” or “custom_xxMyTask” throws exception. Interestingly the undoHandler don’t need to refer to the same task, only it must include a valid custom task name (example: if I have another custom task called “MyOtherTask”, the undoHandler of “MyTask” can be “custom_MyOtherTask”). In such case the “MyTask” rollback workflow will call the “MyOtherTask” task with the prepared undoConfig oblect.
3 answers from the BU:
Generally we use the below line of code for registering the rollback task in the script part of custom task.
ctxt.getChangeTracker().undoableResourceModified(String assetType, String assetId, String assetLabel, String description, String undoTaskHandlerName, Object undoTaskConfigPOJO)
Here the last two parameters (undoTaskHandlerName, undoTaskConfigPOJO) are most important.
1.) [endif] Is there a mandatory rule for the format of the “undoHandler” variable or can I choose it freely?(In this case “undoTaskHandlerName”)?
Ans:We can’t choose it freely.It should and must be the task name which we want to register for the rollback purpose. We can get this task name as shown below.
First we need to drag and drop the task into the workflow designer and from there we can find the task name.
2.) [endif] What is the role of the first four parameter of the “ChangeTracker().undoableResourceModified()” method (assetType, assetId, assetLabel, description)? Where are these used and are there any rule for the values I need to be aware of?
Ans: assetId and description is used as shown below when we right click on the SR and try to roll back it.
As per my understanding ,assetType and assetLabel is not holding much significant role in our case and can be passed any string types.
[if !supportLists]3.) [endif]Do I need to clean-up the resources I have used for the rollback (like the undoContext or undoConfig)? Or it is done automatically?
Ans: Here undoContext or undoconfig are just like any other script variable in the script section.So these things will be taken care by the UCSD platform.
Update for UCSD 6.5 with Cores and Sockets:
From REST API browser
"customCpuSockets":1000,"customCpuCoresPerSocket":1000,
Good afternoon
This workflow is good, but don't have the Interface/portgroup selection.
Do you have another version with this feature?
I would add a few tasks to the top of this workflow to change the network policy for the VDC you are going to deploy the VM into. I do that in #123
in UCSD 6.6 this call needs to be adjusted to handle the pre-provisioning
app/api/rest?formatType=json&opName=userAPIProvisionRequest&opData={param0:{"catalogName":"sample","vdcName":"sample","userID":"sample","durationHours":1000,"beginTime":0,"quantity":1000,"memoryMB":0,"diskGB":1000,"cores":1000,"estimatedCost":1000.0,"comments":"sample","additionalInfo":"sample","chargeFrequency":1000,"nicAliasName":"sample","nicPortGroupName":"sample","resourceAllocated":true,"allocatedHost":"sample","allocatedDataStore":"sample","allocatedResourcePool":"sample","altAllocatedHost":"sample","altAllocatedDataStore":"sample","altAllocatedResourcePool":"sample","customStartupMemory":1000.0,"customMaxMemory":1000.0,"customMemoryBuffer":1000.0,"customMemoryWeight":1000,"customMemoryConfig":true,"customStoragePolicy":"sample","allocatedCluster":"sample","customCpuSockets":1000,"customCpuCoresPerSocket":1000,"altAllocatedCluster":"sample","allocatedAddnlDatastores":"sample","altAllocatedAddnlDatastores":"sample","altAllocatedAddnlVNICs":"sample","altAllocatedAddnlVNICsIpv6":"sample","selectedDiskDataStore":"sample","actionId":"sample","vmName":"sample","vdcCategory":"sample","windowsLicensePool":"sample","templateUserId":"sample","templatePassword":"sample","credentialOption":"sample","provisionAllDisk":true,"enableGuestCustomization":true,"enablePostProvisioningCustomActions":true,"workflow":"sample","vmId":1000,"vMAppChargeFrequency":1000,"activeVMAppCost":1000.0,"inactiveVMAppCost":1000.0,"useLinkedClone":true,"snapshotId":1000,"snapshotKey":"sample","newSnapshotName":"sample","isHighlyAvailable":true,"overrideCatalogCategoryId":1000,"nicIPAddressOverride":"sample","resourceUserName":"sample","postProvWFUserInputs":{"list":[{"name":"sample","value":"sample"},{"name":"sample","value":"sample"}]},"preProvWfUserInputs":{"list":[{"name":"sample","value":"sample"},{"name":"sample","value":"sample"}]},"enablePreProvisioningCustomActions":true,"preProvisionWorkFlowName":"sample"}}
Find answers to your questions by entering keywords or phrases in the Search bar above. New here? Use these resources to familiarize yourself with the community: