Home > Blogs > vCloud Architecture Toolkit (vCAT) Blog


Publishing vCloud Director User Interface Extensions

vCloud Director has been designed with extensibility in mind.  For many years now, developers have been able to extend the standard vCloud Director API, enabling Service Providers to provide a single point of integration to their customers.  The vCloud Director 9.1 release enhances this extensibility by allowing you to also extend the user interface with custom extensions, which enables you to add your own screens and workflows directly inside the vCloud Director HTML5 client.  For example, you could create a simple informational page displaying all of your service offerings, so that your customers can easily learn more about them.  Or with a little more effort, you could fully integrate your in-house ticketing system, allowing customers to create, view, edit and delete tickets without ever leaving the vCloud Director user interface.

To learn more about how to create your own user interface extensions, read the following two white papers: Extending VMware vCloud Director® User Interface Using Portal Extensibility and Extending VMware vCloud Director® User Interface Using Portal Extensibility – Ticketing Example.

This rest of this post assumes that you have already developed the desired code and are now ready to publish your extension into a vCloud Director environment.  Let’s walk through the process.

Build the plugin bundle

Inside the project directory, execute the “yarn install” command, to install all the dependencies specified in the package.json file.  This automatically downloads and installs the specified version of each package.

> cd about_page
> yarn install

yarn install v1.6.0
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
[4/4] 📃  Building fresh packages...
✨  Done in 86.62s.

Execute the “yarn run build” command to build your source code into a plugin bundle.  This packages all of the code into a single file named “plugin.zip”, located in the ./dist directory, which will later be uploaded to vCloud Director.

> yarn run build
yarn run v1.6.0
Writing bundle.js, manifest.json, i18n.json, assets/ to plugin.zip...
zipped!
✨  Done in 1.04s.

> ls -l ./dist
total 40
drwxr-xr-x  2 admin  vmware    68 May 14 14:05 assets
-rw-r--r--  1 admin  vmware  5554 May 14 14:05 bundle.js
-rw-r--r--  1 admin  vmware    94 May 14 14:05 i18n.json
-rw-r--r--  1 admin  vmware   463 May 14 14:05 manifest.json
-rw-r--r--  1 admin  vmware  2981 May 14 14:05 plugin.zip

Manually deploying the plugin bundle

Deploying your source code into your vCloud Director instance requires a series of API calls to register the extension and to upload the plugin bundle.  For this example, we will use curl, but you can use any REST API client that supports file uploads.

Generate session token

To get started, you need to generate a vCloud Director session token using the vCloud API.  To simplify future API calls, we store the vCloud Director server (VCDHOST) and the session token (VCDSESSION) in environment variables.

> VCDHOST=vcd.corp.local
> curl -i -s -k -X POST -H 'Accept: application/*+xml;version=29.0;multisite=global' -u 'administrator@System' https://$VCDHOST/api/sessions | grep -F 'x-vcloud-authorization'
x-vcloud-authorization: bfec07ffb51d4e2297787ed84f203465

> VCDSESSION=bfec07ffb51d4e2297787ed84f203465

Register the extension

Register the extension in vCloud Director, by creating a JSON structure describing the extension and then post it to https://$VCDHOST/cloudapi/extensions/ui.  Each field is described in section A.1: Registering Extension of the Extending VMware vCloud Director® User Interface Using Portal Extensibility white paper.  This call returns the provided JSON along with the newly assigned plugin ID.

> curl -k -X POST -H 'Accept: application/json' -H 'Content-Type: application/json' -H "x-vcloud-authorization: $VCDSESSION" --data '{"pluginName":"AboutPage", "vendor":"VMware", "description":"An example About Page extension", "version":"1.0.0", "license":"Proprietary", "link":"http://www.vmware.com", "tenant_scoped":true, "provider_scoped":false, "enabled":true}' https://$VCDHOST/cloudapi/extensions/ui

{"id":"urn:vcloud:uiPlugin:1f5ac058-e7f0-4fdc-9e32-88d7cc32e088", "pluginName":"AboutPage", "vendor":"VMware", "description":"An example About Page extension", "version":"1.0.0", "license":"Proprietary", "link":"http://www.vmware.com", "tenant_scoped":true, "provider_scoped":false, "enabled":true, "plugin_status":"unavailable", "resourcePath":""}%

Define plugin bundle

Define the plugin bundle by creating a JSON structure containing both the filename (plugin.zip) and its file size, then post it to https://$VCDHOST/cloudapi/extensions/ui/<plugin-id>/plugin.  This call returns the Link header needed to upload the plugin bundle.  Note: The <plugin-id> can be found in the previous result or by making a get request to https://$VCDHOST/cloudapi/extensions/ui.

> curl -i -k -X POST -H 'Accept: application/json' -H 'Content-Type: application/json' -H "x-vcloud-authorization: $VCDSESSION" --data '{"fileName":"plugin.zip", "size":3018}' https://$VCDHOST/cloudapi/extensions/ui/urn:vcloud:uiPlugin:1f5ac058-e7f0-4fdc-9e32-88d7cc32e088/plugin

HTTP/1.1 204 No Content
Date: Mon, 14 May 2018 19:21:50 GMT
X-VMWARE-VCLOUD-REQUEST-ID: c1d3ca85-0e17-4a8d-8ba6-6bd0bf9b0d71
X-VMWARE-VCLOUD-CEIP-ID: a0b75ae0-5ed4-48c2-aa9d-38e219d93ab8
Location: https://vcd.corp.local/cloudapi/extensions/ui/urn:vcloud:uiPlugin:1f5ac058-e7f0-4fdc-9e32-88d7cc32e088/plugin
Allow: DELETE,POST,OPTIONS
Link: <https://vcd.corp.local/transfer/ac0f0946-b79f-4775-89b8-efbade65dc36/plugin.zip>;rel="upload:default";type="application/octet-stream"

Upload plugin bundle

Upload the plugin bundle to vCloud Director using the URL in the Link header returned in the previous request.  Make sure to use a PUT method and to set the Content-Type header to “application/zip”.

> curl -i -k -X PUT -H 'Content-Type: application/zip' -H "x-vcloud-authorization: $VCDSESSION" --data-binary @dist/plugin.zip https://vcd.corp.local/transfer/b658b912-b727-4a25-9a17-3d655cd85dc9/plugin.zip

HTTP/1.1 100 Continue

HTTP/1.1 200 OK
Date: Mon, 14 May 2018 19:30:51 GMT
X-VMWARE-VCLOUD-REQUEST-ID: 110a2a77-f616-4427-ab0d-d6a91ec41baf
X-VMWARE-VCLOUD-CEIP-ID: a0b75ae0-5ed4-48c2-aa9d-38e219d93ab8
Content-Length: 0

Publish extension

Publish the new extension to all organizations by using a post request to https://$VCDHOST/cloudapi/extensions/ui/<plugin-id>/tenants/publishAll.  Note: You can also publish to individual organizations by using the https://$VCDHOST/cloudapi/extensions/ui/<plugin-id>/tenants/publish endpoint.

> curl -k -X POST -H 'Accept: application/json' -H 'Content-Type: application/json' -H "x-vcloud-authorization: $VCDSESSION" https://$VCDHOST/cloudapi/extensions/ui/urn:vcloud:uiPlugin:1f5ac058-e7f0-4fdc-9e32-88d7cc32e088/tenants/publishAll

[{"name":"System","id":"urn:vcloud:org:a93c9db9-7471-3192-8d09-a8f7eeda85f9"},{"name":"E-Corp","id":"urn:vcloud:org:b3a69d63-1fd0-41c1-8a13-1ab34597d75b"},{"name":"acme","id":"urn:vcloud:org:da7026bb-0ef0-429a-9d2f-d164613813c8"}]%

View extension

Login in to your vCloud Director instance and verify that you can now see and interact with your extension.

About Page

Remove plugin bundle and extension

To remove your plugin bundle and extension, execute the following code:

> curl -k -X DELETE -H 'Accept: application/json' -H 'Content-Type: application/json' -H "x-vcloud-authorization: $VCDSESSION" https://$VCDHOST/cloudapi/extensions/ui/urn:vcloud:uiPlugin:1f5ac058-e7f0-4fdc-9e32-88d7cc32e088/plugin
> curl -k -X DELETE -H 'Accept: application/json' -H 'Content-Type: application/json' -H "x-vcloud-authorization: $VCDSESSION" https://$VCDHOST/cloudapi/extensions/ui/urn:vcloud:uiPlugin:1f5ac058-e7f0-4fdc-9e32-88d7cc32e088

Automatically deploying the module bundle

All the manual steps completed above can be replaced by using the ui_ext_api.py script included in the plugin seed section of the vcd-ext-sdk project.  This script fully automates the entire deployment process for new extensions.  It also includes methods which can remove the current extension and list out all the existing extensions.

Configure script

To use the automated script, you need to create a configuration file describing your environment.  Copy the ui_ext_api.ini.template file to ui_ext_api.ini and then set the proper values for your environment.

> cp ui_ext_api.ini.template ui_ext_api.ini
> vi ui_ext_api.ini

#Copy this file to ui_ext_api.ini and update the values

[DEFAULT]
vcduri=https://vcd.corp.local
organization=System
username=administrator
password=MyVMware1!

Deploy extension

With the configuration complete, you are ready to automatically deploy your extension into your environment. For ease of use, the ui_ext_api.py script has also been wrapped into a yarn package script.  To use the script under yarn, execute “yarn run deploy”.

Each time you execute the “yarn run deploy” command, it takes the following steps:

  1. Check to see if the current extension has been previously registered
    1. If it has not been previously registered, register the current extension using the values found in the manifest.json file.
    2. If it has been previously registered, delete the existing plugin.
  2. Define the new plugin bundle
  3. Upload the new plugin bundle
  4. Publish the extension to all organizations

This means that you can execute the “yarn run deploy” command repeatably during your development process.  The first time you execute the command, it registers the extension, defines the plugin, uploads the plugin and finally publishes the extension to all organizations. Each time after that, it replaces the existing plugin bundle with the current plugin bundle, leaving the extension meta-data in place.

First Execution:

> yarn run build; yarn run deploy

yarn run v1.6.0

$ rollup -c && ncp src/public dist && cd dist && bestzip plugin.zip bundle.js manifest.json i18n.json assets/ && cd ..
Writing bundle.js, manifest.json, i18n.json, assets/ to plugin.zip...
zipped!
✨  Done in 1.15s.
yarn run v1.6.0

$ python ui_ext_api.py deploy
2018-05-14 18:24:23,060 DEBUG Added a stderr logging handler to logger: urllib3
2018-05-14 18:24:23,065 DEBUG Starting new HTTPS connection (1): vcd.corp.local
2018-05-14 18:24:23,534 DEBUG https://vcd.corp.local:443 "POST /api/sessions HTTP/1.1" 200 2595
2018-05-14 18:24:23,538 DEBUG Starting new HTTPS connection (1): vcd.corp.local
2018-05-14 18:24:23,803 DEBUG https://vcd.corp.local:443 "GET /cloudapi/extensions/ui/ HTTP/1.1" 200 None
2018-05-14 18:24:23,806 DEBUG Starting new HTTPS connection (1): vcd.corp.local
2018-05-14 18:24:24,074 DEBUG https://vcd.corp.local:443 "POST /cloudapi/extensions/ui/ HTTP/1.1" 201 None
2018-05-14 18:24:24,077 DEBUG Starting new HTTPS connection (1): vcd.corp.local
2018-05-14 18:24:24,366 DEBUG https://vcd.corp.local:443 "POST /cloudapi/extensions/ui/urn:vcloud:uiPlugin:c0340993-78dd-4bd4-979e-de7ca03fb2ea/plugin HTTP/1.1" 204 0
2018-05-14 18:24:24,369 DEBUG Starting new HTTPS connection (1): vcd.corp.local
2018-05-14 18:24:24,673 DEBUG https://vcd.corp.local:443 "PUT /transfer/a3b96778-a8be-4931-8972-d9d378941fbc/plugin.zip HTTP/1.1" 200 0
2018-05-14 18:24:24,676 DEBUG Starting new HTTPS connection (1): vcd.corp.local
2018-05-14 18:24:24,964 DEBUG https://vcd.corp.local:443 "POST /cloudapi/extensions/ui/urn:vcloud:uiPlugin:c0340993-78dd-4bd4-979e-de7ca03fb2ea/tenants/publishAll HTTP/1.1" 200 None
✨  Done in 2.42s.

Subsequent Executions:

> yarn run build; yarn run deploy

yarn run v1.6.0

$ rollup -c && ncp src/public dist && cd dist && bestzip plugin.zip bundle.js manifest.json i18n.json assets/ && cd ..
Writing bundle.js, manifest.json, i18n.json, assets/ to plugin.zip...
zipped!
✨  Done in 1.10s.
yarn run v1.6.0

$ python ui_ext_api.py deploy
2018-05-14 18:26:34,025 DEBUG Added a stderr logging handler to logger: urllib3
2018-05-14 18:26:34,028 DEBUG Starting new HTTPS connection (1): vcd.corp.local
2018-05-14 18:26:34,475 DEBUG https://vcd.corp.local:443 "POST /api/sessions HTTP/1.1" 200 2595
2018-05-14 18:26:34,479 DEBUG Starting new HTTPS connection (1): vcd.corp.local
2018-05-14 18:26:34,750 DEBUG https://vcd.corp.local:443 "GET /cloudapi/extensions/ui/ HTTP/1.1" 200 None
2018-05-14 18:26:34,753 DEBUG Starting new HTTPS connection (1): vcd.corp.local
2018-05-14 18:26:35,017 DEBUG https://vcd.corp.local:443 "DELETE /cloudapi/extensions/ui/urn:vcloud:uiPlugin:c0340993-78dd-4bd4-979e-de7ca03fb2ea/plugin HTTP/1.1" 204 0
2018-05-14 18:26:35,019 DEBUG Starting new HTTPS connection (1): vcd.corp.local
2018-05-14 18:26:35,319 DEBUG https://vcd.corp.local:443 "POST /cloudapi/extensions/ui/urn:vcloud:uiPlugin:c0340993-78dd-4bd4-979e-de7ca03fb2ea/plugin HTTP/1.1" 204 0
2018-05-14 18:26:35,322 DEBUG Starting new HTTPS connection (1): vcd.corp.local
2018-05-14 18:26:35,615 DEBUG https://vcd.corp.local:443 "PUT /transfer/6610aa57-2c0b-46c8-9eaa-1a58bf8b739e/plugin.zip HTTP/1.1" 200 0
2018-05-14 18:26:35,618 DEBUG Starting new HTTPS connection (1): vcd.corp.local
2018-05-14 18:26:35,898 DEBUG https://vcd.corp.local:443 "POST /cloudapi/extensions/ui/urn:vcloud:uiPlugin:c0340993-78dd-4bd4-979e-de7ca03fb2ea/tenants/publishAll HTTP/1.1" 200 None
✨  Done in 2.37s.

View extension

Login in to your vCloud Director instance and verify that you can now see and interact with your extension.

About Page

Delete extension

To completely remove the current extension from vCloud Director, execute the “yarn run remove” command.  This removes the existing plugin bundle and the extension meta-data from vCloud Director.

> yarn run remove

yarn run v1.6.0

$ python ui_ext_api.py remove
2018-05-14 18:50:21,616 DEBUG Added a stderr logging handler to logger: urllib3
2018-05-14 18:50:21,620 DEBUG Starting new HTTPS connection (1): vcd.corp.local
2018-05-14 18:50:22,136 DEBUG https://vcd.corp.local:443 "POST /api/sessions HTTP/1.1" 200 2595
2018-05-14 18:50:22,143 DEBUG Starting new HTTPS connection (1): vcd.corp.local
2018-05-14 18:50:22,434 DEBUG https://vcd.corp.local:443 "GET /cloudapi/extensions/ui/ HTTP/1.1" 200 None
2018-05-14 18:50:22,437 DEBUG Starting new HTTPS connection (1): vcd.corp.local
2018-05-14 18:50:22,724 DEBUG https://vcd.corp.local:443 "DELETE /cloudapi/extensions/ui/urn:vcloud:uiPlugin:c0340993-78dd-4bd4-979e-de7ca03fb2ea/plugin HTTP/1.1" 204 0
2018-05-14 18:50:22,727 DEBUG Starting new HTTPS connection (1): vcd.corp.local
2018-05-14 18:50:23,003 DEBUG https://vcd.corp.local:443 "DELETE /cloudapi/extensions/ui/urn:vcloud:uiPlugin:c0340993-78dd-4bd4-979e-de7ca03fb2ea HTTP/1.1" 204 0
✨  Done in 1.95s.

List all extensions

To see a list of all existing registered extensions, execute the “yarn run listUiExtensions” command.

> yarn run listUiExtensions

yarn run v1.6.0

$ python ui_ext_api.py listUiExtensions
2018-05-14 18:27:44,885 DEBUG Added a stderr logging handler to logger: urllib3
2018-05-14 18:27:44,889 DEBUG Starting new HTTPS connection (1): vcd.corp.local
2018-05-14 18:27:45,395 DEBUG https://vcd.corp.local:443 "POST /api/sessions HTTP/1.1" 200 2595
2018-05-14 18:27:45,400 DEBUG Starting new HTTPS connection (1): vcd.corp.local
2018-05-14 18:27:45,683 DEBUG https://vcd.corp.local:443 "GET /cloudapi/extensions/ui/ HTTP/1.1" 200 None
[{u'description': u'An example About Page extension',
  u'enabled': True,
  u'id': u'urn:vcloud:uiPlugin:c0340993-78dd-4bd4-979e-de7ca03fb2ea',
  u'license': u'SPDX-License-Identifier: BSD-2-Clause; Copyright (C) VMware 2018.  All rights reserved.',
  u'link': u'http://www.vmware.com/support',
  u'pluginName': u'About Page extension',
  u'plugin_status': u'ready',
  u'provider_scoped': False,
  u'resourcePath': u'https://vcd.corp.local/tenant/System/uiPlugins/c0340993-78dd-4bd4-979e-de7ca03fb2ea/e045d3cd-dc2a-4175-9c7d-1dc61a60447d',
  u'tenant_scoped': True,
  u'vendor': u'VMware',
  u'version': u'0.0.1'}]
✨  Done in 1.31s.

Conclusion

In this post, we demonstrated how to register, upload and publish new extensions into a vCloud Director instance using both the manual method and the automated method included in the seed project.  You are now ready to deploy and publish your first user interface extension.  For more information, make sure to read the two UI Extensibility white papers previously listed.