VMware Cloud Community
nmshadey
Enthusiast
Enthusiast
Jump to solution

Change the Deployment owner in vRA 7.x using vRO

I am struggling to find a way to change the owner of a deployment (and all it's child items) using vRO.

changeowner.PNG

To put this into context, I am using XaaS blueprints where the associated workflow makes a call to System.getModule("com.vmware.library.vcaccafe.request").requestCatalogItemWithProvisioningRequest to send a custom request to vRA. I am using a 'service helper' account that requests 'hidden' blueprints that only this account is entitled for.

I have tried setting the following Custom props on the request:

Cafe.Shim.VirtualMachine.AssignToUser

VirtualMachine.Admin.Owner

These fields apply as expected but the deployment and component resources are still owned by this service account and not the user that requested the XaaS blueprint.

I have used the RequestedFor field but this requires that the requestor also have an entitlement to the 'hidden' blueprints, which I do not want as users would see duplication in the service catalog.

Does anyone know if there is an API within vRO that I can use to achieve this or does it not exist for vRA 7?

Thanks,

Gavin

Reply
0 Kudos
1 Solution

Accepted Solutions
SeanKohler
Expert
Expert
Jump to solution

There should be three ways... your VRO service account for VRA needs to be entitled to run the Change Owner resource action.  If you cannot see the action HERE... you cannot request the action.

changeOwner.jpg

1. Requires you to leverage the REST API to send a valid makeRequest POST to the catalog-service service.  There are some builtin capabilities to send REST calls out of VRO to the service and there are many examples in blogs.  In my case, I created my own workflows for making REST calls to authenticate, get, and post to any service.  (I think there is even a blog post out there that explains how to do this now.) You can go to https://YOURAPPLIANCE/component-registry/services/docs to review the REST API documentation.  You would want to pick catalog-service.

The REST body is pretty simple, and you have to just specify (replace) the ID, Resource ID, tenant (if applicable), subtenant ID / Label (which are a pair in the subtenant reference) and the new owner information to include their UPN and probably the Label Name (though I would try to skip that last one to see if it works) The general concept behind this method is to modify a the REST components and then POST a valid JSON string to the REST endpoint.  (this can be added as a REST host, or through some of the builtin coding in the CAFE plugin)

{

  "@type": "ResourceActionRequest",

  "resourceRef": {

  "id": "e3b7d6fc-5feb-4db5-9b9e-e3688648f316"

  },

  "resourceActionRef": {

  "id": "14612878-a85d-4963-a64f-b55ec274dc2a"

  },

  "organization": {

  "tenantRef": "vsphere.local",

  "tenantLabel": "vsphere.local",

  "subtenantRef": "cf666f51-203d-4ce8-a920-499ea32f7e8a",

  "subtenantLabel": "##SOME-SUBTENANT##"

  },

  "state": "SUBMITTED",

  "requestNumber": 0,

  "requestData": {

  "entries": [{

  "key": "provider-NewOwner",

  "value": {

  "type": "entityRef",

  "classId": "principal",

  "id": "##UPN-ACCOUNT##",

  "label": "Sean Kohler"

  }

  }]

  }

}

2. Requires you to run the Request a Resource Action workflow on the deployment Resource with a Change Owner Resource Action and specify provider-NewOwner with the ID (UPN for user).  This is easy, but I recommend still understanding the REST interface and methods to work with it.

changeOwner2.jpg

3. Use Cloud Client from a Script Host, and have VRO run a normal SSH (or PS) command to run Cloud Client with the request.  The (purported) benefits to Cloud Client is that the product will allow you to stay with consistent noun/verb command line execution for various requests, and they will change CloudClient to match the API.  We do use Cloud Client for a lot of things where we want a service account (authenticated and entitled) to request various catalog items and resource actions.  As I think you will go with number 2, I won't put screenshots of a standard request in cloud client...but effectively, you are just calling the request with provider-NewOwner=UPN as the input value switch.

Best of luck to you!

View solution in original post

Reply
0 Kudos
5 Replies
SeanKohler
Expert
Expert
Jump to solution

There should be three ways... your VRO service account for VRA needs to be entitled to run the Change Owner resource action.  If you cannot see the action HERE... you cannot request the action.

changeOwner.jpg

1. Requires you to leverage the REST API to send a valid makeRequest POST to the catalog-service service.  There are some builtin capabilities to send REST calls out of VRO to the service and there are many examples in blogs.  In my case, I created my own workflows for making REST calls to authenticate, get, and post to any service.  (I think there is even a blog post out there that explains how to do this now.) You can go to https://YOURAPPLIANCE/component-registry/services/docs to review the REST API documentation.  You would want to pick catalog-service.

The REST body is pretty simple, and you have to just specify (replace) the ID, Resource ID, tenant (if applicable), subtenant ID / Label (which are a pair in the subtenant reference) and the new owner information to include their UPN and probably the Label Name (though I would try to skip that last one to see if it works) The general concept behind this method is to modify a the REST components and then POST a valid JSON string to the REST endpoint.  (this can be added as a REST host, or through some of the builtin coding in the CAFE plugin)

{

  "@type": "ResourceActionRequest",

  "resourceRef": {

  "id": "e3b7d6fc-5feb-4db5-9b9e-e3688648f316"

  },

  "resourceActionRef": {

  "id": "14612878-a85d-4963-a64f-b55ec274dc2a"

  },

  "organization": {

  "tenantRef": "vsphere.local",

  "tenantLabel": "vsphere.local",

  "subtenantRef": "cf666f51-203d-4ce8-a920-499ea32f7e8a",

  "subtenantLabel": "##SOME-SUBTENANT##"

  },

  "state": "SUBMITTED",

  "requestNumber": 0,

  "requestData": {

  "entries": [{

  "key": "provider-NewOwner",

  "value": {

  "type": "entityRef",

  "classId": "principal",

  "id": "##UPN-ACCOUNT##",

  "label": "Sean Kohler"

  }

  }]

  }

}

2. Requires you to run the Request a Resource Action workflow on the deployment Resource with a Change Owner Resource Action and specify provider-NewOwner with the ID (UPN for user).  This is easy, but I recommend still understanding the REST interface and methods to work with it.

changeOwner2.jpg

3. Use Cloud Client from a Script Host, and have VRO run a normal SSH (or PS) command to run Cloud Client with the request.  The (purported) benefits to Cloud Client is that the product will allow you to stay with consistent noun/verb command line execution for various requests, and they will change CloudClient to match the API.  We do use Cloud Client for a lot of things where we want a service account (authenticated and entitled) to request various catalog items and resource actions.  As I think you will go with number 2, I won't put screenshots of a standard request in cloud client...but effectively, you are just calling the request with provider-NewOwner=UPN as the input value switch.

Best of luck to you!

Reply
0 Kudos
nmshadey
Enthusiast
Enthusiast
Jump to solution

Hi Sean

That is exactly what I was looking for. Stupidly, I had looked under the 'Items' tree and due to the naming conventions we use it was displaying 100s of Virtual Machine resources and I never through to look further and see the Deployment resources. I assumed that the Deployment resources simply weren't available there. Anyhow, as you suspected, I am going with option 2 for the moment as option 1 is still outside my knowledge area 🙂

Some of the code is based from https://www.helloitscraig.co.uk/2016/03/get-resources-provisioned-vra-request.html and another site which I forget where (please let me know if you recognise any of the code Smiley Happy)

I am executing the following workflow at the end of the provisioning lifecycle

/*

Name: ChangeDeploymentOwner

Input: vCACCAFEHost - vCACCAFE:VCACHost

Input: _requestId - String

Input: newOwnerUPN - String

Output: void

Description: Get deployment catalog item resources provisioned from a request, return the available operations and request the 'Change Owner' operation.

*/

//Create an instance of vCACCAFECatalogClient

System.log("Creating Catalog Client");

var _client = vCACCAFEHost.createCatalogClient();

System.log(_client);

//Create an instance of vCACCAFECatalogConsumerRequestService

System.log("Creating an instance of vCACCAFECatalogConsumerRequestService");

var _requestService = _client.getCatalogConsumerRequestService();

System.log(_requestService);

//getResourcesProvisionedByRequest returns type vCACCAFEPagedResources .getContent() will return an array of vCACCAFECatalogResource

System.log("Get a list of vCACCAFECatalogResource");

var _resources = _requestService.getResourcesProvisionedByRequest(_requestId, null).getContent();

System.log(_resources);

//Loop through results

System.log("Output each resource name");

for (var i = 0; i < _resources.length; i++){

    if (_resources[i].resourceTypeRef.label == "Deployment") {

     System.log("Id: " + _resources[i].id);

     System.log("Name: " + _resources[i].name);

     System.log("Provider binding is: " + _resources[i].providerBinding.getBindingId());

     var resourceActions = _resources[i].operations;

        var count = 0;

       System.log("resourceActions.length " + resourceActions.length);

       while(resourceActions.length > count){

           if(resourceActions[count].Id == _operationId){

               System.log("Reconfigure action available on this catalog resource: " + resourceActions[count].name);

               var vmOperation = vCACCAFEEntitiesFinder.getCatalogResourceAction(_resources[i],resourceActions[count].Id);

           };

        count++;

       };

    System.log("Resource Operation: " + vmOperation);

    System.log("Resource Operation binding ID: " + vmOperation.getBindingId());

    // Build input list for the form

    var FormInputs = new Properties();

    FormInputs.put("provider-NewOwner", newOwnerUPN);

       System.log("Getting resource action " + vmOperation.getName() + " request form... ");

    var form = vCACCAFERequestsHelper.getRequestFormForResourceAction(vmOperation);

    System.log("Expected inputs: ");

    var fields = vCACCAFERequestsHelper.getFormKeys(form);

    for (var i = 0; i < fields.length; i++) {

    System.log(" - " + fields[i]);

    };

    System.log("Filling in resource action request..");

    form = vCACCAFERequestsHelper.setFormValues(form, FormInputs);

    System.log("Sending resource action request...");

    var request = vCACCAFERequestsHelper.requestResourceAction(vmOperation, form);

    System.log("Resource action request " + request.getId() + " sent!");

  };

};

I am getting the inputs from the EBS payload during the MachineActivated lifecycle:

_requestId = RequestId

newOwnerUPN = Cafe.Shim.VirtualMachine.AssignToUser

I set the Cafe.Shim.VirtualMachine.AssignToUser property that is taken from the 'RequestedFor' field when the XaaS form is submitted. (I do not use setRequestedFor on the provisioning request, merely using this value for my own purposes),

There was one other caveat with this in that the 'Change Owner' operation would not change the Business Group. As a temporary workaround I set the subtenantId in the initial catalog request to the target users Business Group. I basically send the Business Group name to the workflow and use vCACEntityManager.readModelEntitiesByCustomFilter to locate the Business Group ID. I then use provisioningRequest.setBusinessGroupId("Business-Group-ID") before submitting the request.

I know some more elegance can be used for the above but it's a great start.

Many thanks for your help with this.

Gavin

Reply
0 Kudos
SeanKohler
Expert
Expert
Jump to solution

Hi Gavin,

I agree that it is a great start. Also, your code formatting and notation is impeccable.  I am very impressed!

Glad I could be of some assistance. Smiley Happy

Sean

Reply
0 Kudos
kumar6384
Enthusiast
Enthusiast
Jump to solution

Hi,

check whether below vRO Package helps.

Reply
0 Kudos
pizzle85
Expert
Expert
Jump to solution

FWIW method 2 no longer works. You now have to use the "Request a resource action with a request template" workflow and submit the request with an principal entity reference like this.

var newOwnerLiteral = new vCACCAFEEntityReference("principal" , newOwner);

json["provider-NewOwner"] = {"type":"entityRef", "classId":"principal", "id":newOwner, "label":""};

where newOwner is the UPN of the user as a string.

Reply
0 Kudos