vRealize Automation 8.x has a neat feature where you use a workload onboarding plan to identify machines that have been data-collected from a cloud account type in a target region or data center but that are not yet managed by a vRealize Automation Cloud Assembly project. This can be found in infrastructure > onboarding tab. My customer had over 2000 VMs in vCenter which they wanted to onboard few at a time, based on their tags. They wanted to follow their change process and do bunch at a time. The requirement was to create a workflow that will take tags as an input and then onboard VMs with those tags into the specified project. Each VM was to have its own deployment. The deployment naming convention was <Deployment-><VM name>. 

Solution:

To achieve that, I did the below steps.

    • Get the projectId and endpointId.
    • Create a Plan and add the VMs to the plan.
    • Rename the deployments.
    • Execute the plan.

To get the projectId and endpointId, I used the apis /iaas/api/projects and /iaas/api/cloud-accounts-vsphere respectively.

var url{"type":"block","srcClientIds":["0b1e6aee-b64c-4520-83bf-947d557d417c"],"srcRootClientId":""} = "/iaas/api/projects";
var contentType = "application/json"
var requestResponse = System.getModule("org.harjinder.dev").executeRestOp("GET",url,null,contentType);

var allProjects = JSON.parse(requestResponse).content;
for each (var project in allProjects) {
    if (project.name == projectName) {
        System.log(project.name +" found with id " + project.id)
        projectId = project.id;
    } else {throw "Please check the project name"}
}
System.log("Project id found: " + projectId);

var endpointName = "vcenter"
var url = "/iaas/api/cloud-accounts-vsphere";
var contentType = "application/json"
var requestResponse = System.getModule("org.harjinder.dev").executeRestOp("GET",url,null,contentType);

var allEndpoints = JSON.parse(requestResponse).content
for each (var endpoint in allEndpoints){
    if (endpoint.name == endpointName){
        endpointId = endpoint.id
    }
}

System.log("endpoint id: " + endpointId);

Next, I call the /relocation/onboarding/plan api that will create the onboarding plan on the endpoint and the project that we got above.

var url = "/relocation/onboarding/plan";
var requestContent = 
    '{"description": "api test", "endpointIds": ["'+ endpointId+'"], "name":' + planName +', "projectId":' + projectId +', "deploymentTagName": "'+deploymentTagKey+'" }';

var contentType = "application/json"
var requestResponse = System.getModule("org.harjinder.dev").executeRestOp("POST",url,requestContent,contentType);
var planCreated = JSON.parse(requestResponse).name
System.log("plan created with the name " + planCreated);

To add VMs to the plan we just created, we need the planLink. To do that, I used the api /relocation/onboarding/plan. This will take the name of the plan that we used during the creation of the plan and then get the link for it.

var url = "/relocation/onboarding/plan";
var contentType = "application/json"
var requestResponse = System.getModule("org.harjinder.dev").executeRestOp("GET",url+ "?expand=true",null,contentType);

var planDocuments = JSON.parse(requestResponse).documents;
for each (var item in planDocuments){
    if (item.name == planName)
    System.log("found plan with name " + JSON.stringify(item.name) + " and link " + item.documentSelfLink);
    planLink = item.documentSelfLink;
}
System.log("plan link: " + planLink);

Next step is to add the VMs to the plan. To do that I had to query all the unmanaged VMs in the endpoint and then extract them based on the tag and add them to the plan. A new deployment for each VM gets created.

//GET unmanaged resources by their tag
var url = "/relocation/api/wo/query-unmanaged-machine?expand=true";
var requestContent = '{ \n' +
    '"planLink": "' + planLink + '", \n' +
    '"expandFields": ["id", "documentSelfLink", "name", "powerState", "address", "creationTimeMicros", "expandedTags"], \n' +
    '"filters": [{field: "ANY", values: ['+tags+']}], \n' +
    '"optionExcludePlanMachines": true \n' +
'}'
var contentType = "application/json"
var requestResponse = System.getModule("org.harjinder.dev").executeRestOp("POST",url,requestContent,contentType);
var machineArray = JSON.parse(requestResponse).page.documents;

//Create request body for the POST request
var requestContent = new Object;
requestContent.planLink = planLink;
var deployments = new Array;

for each (var machine in machineArray) {
    System.log(machine["name"] + " : " + machine["documentSelfLink"])
    var vm = new Object;    
    var resourceObj = new Object;
    var resources = new Array;
    vm.link = machine["documentSelfLink"];
    vm.name = machine["name"];
    resources.push(vm);
    resourceObj.resources = resources;
    deployments.push(resourceObj);

}

requestContent.deployments = deployments;
System.log(JSON.stringify(requestContent));
requestContent = JSON.stringify(requestContent);

//send POST request to add the machines to plan
var url = "/relocation/onboarding/task/create-deployment-bulk";
var contentType = "application/json"
var requestResponse = System.getModule("org.harjinder.dev").executeRestOp("POST",url,requestContent,contentType);

System.log("machine add to plan response: " + requestResponse);

Once all the VMs get added to the plan, it generates a random deployment name for each VM. To rename the deployments, I had to get all the deployments for the plan I created above. Then, I extracted the deployment links for all deployments and the name of each vm in the respective deployments and made a PATCH api call to /relocation/onboarding/deployment/{id} to rename the deployments.

/////get all deployments in the plan/////
var url = "/relocation/onboarding/deployment?expand&$filter=planLink%20eq%20%27"+planLink+"%27"
var contentType = "application/json"
var requestResponse = System.getModule("org.harjinder.dev").executeRestOp("GET",url,null,contentType);

///////get deployments plan links/////
var deploymentPlanLinks = JSON.parse(requestResponse).documentLinks;
System.log("deployment plan links: " + deploymentPlanLinks);

//////get the resource in each deployment plan and its corresponding link /////

for each (var link in deploymentPlanLinks){
    var url = "/relocation/onboarding/resource?expand&$filter=deploymentLink%20eq%20%27" + link + "%27";
    var contentType = "application/json"
    var requestResponse = System.getModule("org.harjinder.dev").executeRestOp("GET",url,null,contentType);
    var requestResponse = JSON.parse(requestResponse).documents;
    for each (var item in requestResponse) {
        if (link == item.deploymentLink) {
            ///// rename the deployment/////
            var url = item.deploymentLink;
            System.log("attempting to rename the deployment with link : " + url);

            var requestContent = '{"name":"Deployment-' + item.resourceName +'"}';
            System.log("requestContent ### " + requestContent);
            var contentType = "application/json"
            var requestResponse = System.getModule("org.harjinder.dev").executeRestOp("PATCH",url,requestContent,contentType);
            System.log("PATCH call response " + requestResponse)
        }
    }
}


Finally, I executed the plan to add all deployments to vRA.

var url = "/relocation/api/wo/execute-plan";
var requestContent = 
    '{"planLink":"'+ planLink+'" }';

var contentType = "application/json"
System.debug("executing plan with link: " + planLink);
var requestResponse = System.getModule("org.harjinder.dev").executeRestOp("POST",url,requestContent,contentType);

12 Comments

Alex Garner · July 14, 2021 at 1:39 am

I love that you scripted the renaming of the deployments instead of leaving the random name. Nice work.

Dustin · November 2, 2022 at 3:35 pm

Long shot here, relatively new to api’s. Is there a good way to take a list of VM’s i’d want to import rather than the unmanaged machines query? Or maybe even filter off another value other than tags.

What are the possible filters? Where can I find that documentation? Sorry that may be a dumb question.

    Harjinder · November 4, 2022 at 1:56 am

    you could use the name of the vm instead of using tags. try the api URL: /relocation/onboarding/task/create-deployment-bulk
    Request Method: POST
    payload: {“deployments”:[{“resources”:[{“link”:”/resources/compute/d176ef46-8c51-32f8-84e1-b77b4bb2189f”,”name”:”{{ vm name }}”,”tagLinks”:[]}]}],”planLink”:”/relocation/onboarding/plan/d98197c2-3b65-45fc-b895-618a9a2bdf6f”}

    you will have to query the unmanaged machines to get the compute link and query plans to get the plan link

      Dustin · November 4, 2022 at 6:43 pm

      Sorry I replied to the wrong comment below.

      I was able to actually create the deployment using this example below.

      {
      “planLink”: “/relocation/onboarding/plan/11111111-2222-3333-4444-555555555555”,
      “name”: “deployment-test
      “description”: “test-api”,
      “owner”: “test”
      “resources”: [
      {
      “link”: “/resources/compute/11111111-2222-3333-4444-555555555555”,
      “name”: test
      “tagLinks”: [],
      }
      ],
      “createBlueprint”: false
      }

      It looks good, however I’m getting an error “Cannot read properties of undefined (reading ‘autoGenerate). It almost sounds like i’m missing a parameter, but I’m not sure which one

Micha · November 3, 2022 at 9:12 am

Can you put the Action System.getModule(“org.harjinder.dev”) on your website?

    Harjinder · November 4, 2022 at 2:33 am

    var accessToken = System.getModule(“org.harjinder.dev”).getVraApiToken();
    var restHost = System.getModule(“org.harjinder.dev”).getConfigurationElement(“web-root”, “vraRestHost”, “endpointConfig”);

    try {
    var request = restHost.createRequest(httpMethod, url, content);
    request.setHeader(“Authorization”, “Bearer ” + accessToken);
    request.setHeader(“Content-Type”, contentType);
    request.setHeader(“Cache-Control”, “no-cache”);
    var requestResponse = request.execute();
    System.debug(“Status code: ” + requestResponse.statusCode);
    if (requestResponse.statusCode > 201 ) {
    System.log (“REST operation failed: ” + requestResponse.statusCode);
    throw “ERROR ” + requestResponse.statusCode;
    }
    } catch (e) {
    throw (“Error: REST operation failed: ” + e);
    }
    return (requestResponse.contentAsString);

      Dustin · November 4, 2022 at 6:42 pm

      I was able to actually create the deployment using this example below.

      {
      “planLink”: “/relocation/onboarding/plan/11111111-2222-3333-4444-555555555555”,
      “name”: “deployment-test
      “description”: “test-api”,
      “owner”: “test”
      “resources”: [
      {
      “link”: “/resources/compute/11111111-2222-3333-4444-555555555555”,
      “name”: test
      “tagLinks”: [],
      }
      ],
      “createBlueprint”: false
      }

      It looks good, however I’m getting an error “Cannot read properties of undefined (reading ‘autoGenerate)

Dustin · November 8, 2022 at 4:31 pm

Any ideas on getting an error when clicking on the deployments tab inside the onboarding plan?

I keep getting this:
Cannot read properties of undefined (reading ‘autoGenerate’)

And when I run the plan, it’s not changing the owner.

    Bjarte · November 11, 2022 at 10:12 am

    We are also having the same issue that the owner is not changed. We have checked that the new owner is member of the project we are onboarding to. The owner is set as the user running the workflow not the one specified in the onboarding plan.

      Harjinder · November 14, 2022 at 6:22 am

      the owner should change to the user that is running the api.

      Dustin · November 18, 2022 at 2:46 pm

      So I think this is a known issue that I just found out. The users you’re trying to set the owner to, need to be added to the project individually. They cannot be a part of a group that you added to the project. Really dumb, I know. But once I added the users individually to the project and ran the onboarding plan. The owners changed successfully.

Antonio · April 1, 2024 at 10:07 am

Hi,
Thank you very much for sharing this post.

I am testing the procedure to onboard a VM using API calls as follows:

POST request to /relocation/onboarding/task/create-deployment with
parameters = {
“planLink” : varOnboardingPlan,
“deploymentLink” : varOnboardingDeployment,
“name” : deploymentName,
“description” : “VM ” + vmName + ” cloned to ” + varNewVMName,
“resources” : [
{
“link” : varNewVMResourceLink,
“name” : varNewVMName
}
],
//”createBlueprint” : false,
//”tag”: “”,
//”owner” : deploymentOwner,
//”ownerType” : “USER”,
};

Then POST request to /relocation/api/wo/execute-plan with:
parameters = {
“planLink” : varOnboardingPlan
}

This last API call works with no errors, however onboarding never completes. I saw the following error in logs:

c.v.r.wo.execution.PlanExecutionTask – [8980/relocation/api/wo/execute-plan/8373097b-2c77-4313-b5a5-7243c41a41c4] Failed: RuntimeException: Validation failed.

Have you seen that “RuntimeException: Validation failed”?

Do you know how validation process works while onboarding VM through API?

Best regards

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *