A lot of work has gone into the CloudStack UI recently, and it is now a modern, role-based UI that not only gives a fresh look to CloudStack but also makes development and customisation much easier. In this blog, I provide guidance on how to customise the UI, and have classified customisation into two categories – basic and advanced.

Basic Customisations

Users can customise the UI by means of this configuration file: /etc/cloudstack/management/config.json to modify theme, logos, etc. as required. These changes can be made while the CloudStack management server is running, and the changes can be seen immediately with a browser refresh.

The configuration file provides the following properties for basic customisation:

Property Description
apiBase Changes the suffix for the API endpoint
docBase Changes the base URL for the documentation
appTitle Changes the title of the portal
footer Changes the footer text
logo Changes the logo top-left side image
banner Changes the login banner image
error.404 Changes the image of error Page not found
error.403 Changes the image of error Forbidden
error.500 Changes the image of error Internal Server Error.

 

To change the logo, login banner, error page icon, documentation base URL, etc. the following details can be edited in config.json:

"apiBase": "/client/api",
"docBase": "http://docs.cloudstack.apache.org/en/latest",
"appTitle": "CloudStack",
"footer": "Licensed under the <a href='http://www.apache.org/licenses/' target='_blank'>Apache License</a>, Version 2.0.",
"logo": "assets/logo.svg",
"banner": "assets/banner.svg",
"error": {
    "404": "assets/404.png",
    "403": "assets/403.png",
    "500": "assets/500.png"
}

Theme Customisation

The customisation of themes is also possible, such as modifying banner width or general color. This can be done by editing the “theme” section of the config.json file. This section provides the following properties for customisation:

Property Description
@logo-background- Changes the logo background color
@project-nav-text-color Changes the navigation menu background color of the project
@project-nav-text-color Changes the navigation menu background color of the project view.
@navigation-background-color Changes the navigation menu background color
@primary-color Changes the major background color of the page (background button, icon hover, etc).
@link-color Changes the link color
@link-hover-color Changes the link hover color
@loading-color Changes the message loading color and page loading bar at the top page
@success-color Changes success state color
@processing-color Changes processing state color. Exp: progress status
@warning-color Changes warning state color
@error-color Changes error state color
@heading-color Changes table header color
@text-color Change in major text color
@text-color-secondary Change of secondary text color (breadcrumb icon)
@disabled-color Disable state color (disabled button, switch, etc)
@border-color-base Change in major border color
@logo-width Change the width of the logo top-left side
@logo-height Change the height of the logo top-left side
@banner-width Changes the width of the login banner
@banner-height Changes the height of the login banner
@error-width Changes the width of the error image
@error-height Changes the height of the error image

 

Some example theme colors:

  • Blue: #1890FF
  • Red: #F5222D
  • Yellow: #FAAD14
  • Cyan: #13C2C2
  • Green: #52C41A
  • Purple: #722ED1

This example shows the configuration changes necessary in /etc/cloudstack/management/config.json to customise logo and colors:

{
  "apiBase": "/client/api",
  "docBase": "http://docs.cloudstack.apache.org/en/latest",
  "appTitle": "Shapeblue Cloud",
  ...
  "logo": "assets/customlogo.svg",
  ...
  "theme": {
    ...
    "@primary-": "#dd55ff",
    ...
    "@warning-color": "#ff2a7f",
    ...
    "@text-color": "#37c8ab
",

...

Basic Customizations on CloudStack UI

Links to Contextual Help

The UI provides support for showing links to contextual help in pages and forms. By default, the links are to the official CloudStack documentation. For each section item (menu items in the left pane of the UI such as Instances, Volumes, Templates, etc.) or UI form there is a suffix defined in the code in the Javascript file for the section as docHelp property. This suffix is added to the docBase property defined in the config file / and the resulting URL is set as the link for a contextual help button.

The docHelpMappings property can be used to provide a list of override mappings for different suffix values, and to change a particular help URL, a mapping can be added in the configuration using the suffix part of the URL. By default, `docHelpMappings` lists all existing documentation URL suffixes, mapped to themselves, in the configuration file that are used in the code. This list of documentation URL suffixes can also be found in the CloudStack documentation.

In the example below, we change the docBase and docHelpMappings values to show a custom link for contextual help. By default, docBase is set to http://docs.cloudstack.apache.org/en/latest and contextual help on Instances page links to http://docs.cloudstack.apache.org/en/latest/adminguide/virtual_machines.html.

To make Instances page link to http://mycustomwebsite.com/custom_vm_page.html, docBase can be set to http://mycustomwebsite.com and a docHelpMapping can be added for adminguide/virtual_machines.html as custom_vm_page.html.

Changes in /etc/cloudstack/management/config.json:

{
  ...
  "docBase": http://mycustomwebsite.com,
  ...
  "docHelpMappings": {
    "adminguide/virtual_machines.html": "custom_vm_page.html",
    ...
  },
  ...
}

 

Plugin support

The CloudStack UI also supports custom plugins. Changes in /etc/cloudstack/management/config.json can show a list of custom plugins that would allow showing custom in an iframe. Custom HTML pages can be used for showing some static content to the users while an HTTP service running on an internally deployed web server or an external website can be used to show any dynamic content.

The example below adds two custom plugins in the UI with their own navigation sections. The first plugin shows a custom HTML file. The second plugin shows CloudStack website within the UI.

...
  "plugins": [
    {
      "name": "ExamplePlugin",
      "icon": "appstore",
      "path": "example.html"
    },
    {
      "name": "ExamplePlugin1",
      "icon": "fire",
      "path": "https://cloudstack.apache.org/"
    }
  ]
}

Custom Plugin 1 Custom Plugin

An icon for the plugin can be chosen from Ant Design icons listed at Icon – Ant Design Vue.

For displaying custom HTML in the plugin, an HTML file can be stored in the CloudStack management server’s web application directory on the server, i.e., /usr/share/cloudstack-management/webapp and path can be set to the name of the file. For displaying an HTTP service or a web page, URL can be set as the path of the plugin.

 

Advanced Customisation

Advanced UI customisation is possible by changing source code files that define rules for different elements in the UI, and requires building CloudStack from the source code (available at github.com/apache/cloudstack). This will require some experience in JavaScript, VueJS and nodejs. Also, the UI is built using Ant Design components, so knowledge of ant-design-vue & its principles would help greatly. More information about Ant Design Vue can be found here.

The source code can be obtained either from the CloudStack website in tarball form or from the Apache Cloudstack Github repository. For example, using git, the repository can be cloned locally:

git clone https://github.com/apache/cloudstack.git
# To checkout specific release TAG
cd cloudstack
git fetch --tags
git checkout TAG
# CloudStack 4.15.0.0 has tag named 4.15.0.0 on Github, to checkout the same
git checkout 4.15.0.0

After obtaining the CloudStack source code, the UI code can be found in the UI sub-directory. For different customisations, changes can be made in the code and then npm can be used to create a static web application. Finally, one would copy the built UI to the webapp directory on the management server host. Building the UI will require installing dependencies for nodejs, npm and VueJS. The necessary steps for building UI from source code are dependent on the host operating system and can be found in the CloudStack UI development documentation. The instructions below have been tested on Ubuntu 20.04.

Install dependencies:

sudo apt-get install npm nodejs
# Install system-wide dev tools
sudo npm install -g @vue/cli npm-check-updates

 

Fetch npm package dependencies and build:

cd ui
npm install
npm run build

 

Copy built UI to webapp directory on the management server host:

cd dist
scp -rp ./ {user-on-management-server}@{management-server}:/usr/share/cloudstack-management/webapp/
# Access UI at {management-server}:8080/client in browser

 

Alternatively, packages can be rebuilt for the desired platform. UI will be packaged in cloudstack-ui package. Refer to the CloudStack packaging documentation for more details. For testing changes during development npm can be started without build:

cd ui
npm install
npm run serve
# Or run: npm start

Examples of advanced customisations can be seen below.

Icon changes

Custom icons can be added in the directory cloudstack/ui/src/assets/icons

Once a new icon file (preferably an SVG file) is placed in the directory it can be imported in the Javascript (.js) file for the corresponding section item (menu items in the left pane in the UI).

A list of available Ant Design icons can be found at https://www.antdv.com/components/icon/

The example below shows changing icon for Compute menu and Instances sub-menu:

New files added named customcompute.svg and custominstances.svg added in the cloudstack/ui/src/assets/icons/ directory:

⇒ ls cloudstack/ui/src/assets/icons/ -l
total 36
-rw-rw-r-- 1 shwstppr shwstppr 3008 Feb 16 15:55 cloudian.svg
-rw-r--r-- 1 shwstppr shwstppr 483 Oct 26 1985 customcompute.svg
-rw-r--r-- 1 shwstppr shwstppr 652 Oct 26 1985 custominstances.svg
-rw-rw-r-- 1 shwstppr shwstppr 10775 Feb 16 15:55 debian.svg
-rw-rw-r-- 1 shwstppr shwstppr 10001 Feb 16 15:55 kubernetes.svg

cloudstack/ui/src/config/section/compute.js updated to import and set a new icon for the menu items,

...
import kubernetes from '@/assets/icons/kubernetes.svg?inline'
import store from '@/store'
+import customcompute from '@/assets/icons/customcompute.svg?inline'
+import custominstances from '@/assets/icons/custominstances.svg?inline'

export default {
   name: 'compute',
   title: 'label.compute',
-  icon: 'cloud',
+  icon: 'customcompute',
   children: [
     {
       name: 'vm',
       title: 'label.instances',
-      icon: 'desktop',
+      icon: 'custominstances',
       docHelp: 'adminguide/virtual_machines.html',
       permission: ['listVirtualMachinesMetrics'],

...

After rebuilding and installing the new packages, the UI will show the new icon(s):

Localization

Language translation files for text in the UI are placed in cloudstack/ui/public/locales/. A copy of the file cloudstack/ui/public/locales/en.json can be made in the same directory to include all translation keys, following the naming convention for locales (for example, el will be for Greek, but el_CY and el_GR can be other variants as well).

Once string keys are translated, changes can be made in the file cloudstack/ui/src/components/header/TranslationMenu.vue for the new language to be displayed as an option in the Languages dropdown in the UI. This example shows a dummy locale being added in the UI.

 

New file added in cloudstack/ui/public/locales/ with name zz.json:

⇒ ls cloudstack/ui/public/locales/ -lr
total 3112
-rw-rw-r-- 1 shwstppr shwstppr 196471 Feb 25 11:42 zz.json
-rw-rw-r-- 1 shwstppr shwstppr 186117 Feb 16 15:55 zh_CN.json
-rw-rw-r-- 1 shwstppr shwstppr 354705 Feb 16 15:55 ru_RU.json
...

Changes necessary in cloudstack/ui/src/components/header/TranslationMenu.vue to add the new language with above translation file:

...
       :selectedKeys="[language]"
       @click="onClick">
       <a-menu-item key="en" value="enUS">English</a-menu-item>
+      <a-menu-item key="zz" value="hi">New Language</a-menu-item>
       <a-menu-item key="hi" value="hi">हिन्दी</a-menu-item>
       <a-menu-item key="ja_JP" value="jpJP">日本語</a-menu-item>
       <a-menu-item key="ko_KR" value="koKR">한국어</a-menu-item>
...

Upon re-building and installing new packages, the UI will show the newly added language in the Languages dropdown:

Other Modifications

There could be several use-cases that require tweaking the UI to enable/disable functionality or to hide or show different elements in the UI. For such modifications, a thorough understanding of Javascript and Vue.js will be required. The development section on the CloudStack repository can be referred to for making such advanced changes.

The following example shows hiding Register Template from URL action from Templates view in the UI for User role:

The templates sub-menu is defined in the Images section cloudstack/ui/src/config/section/image.js, and a list of actions can be defined for each child of the section item. The Register Template from URL action can be found in the actions property with label value label.action.register.template. To hide the action for User role accounts, we can use show property for the action. It can be set as follows:

...
       actions: [
 {
   api: 'registerTemplate',
   icon: 'plus',
   label: 'label.action.register.template',
   docHelp: 'adminguide/templates.html#uploading-templates-from-a-remote-http-server',
           listView: true,
           popup: true,
+          show: (record, store) => {
+            return (['Admin', 'DomainAdmin'].includes(store.userInfo.roletype))
+          },
           component: () => import('@/views/image/RegisterOrUploadTemplate.vue')
         },
...

After making these changes, the Register Template from URL action is shown only for Admin and Domain Admin accounts.

Custom Templates View CloudStack

It should be considered that removing elements from the UI does NOT restrict a users ability to access the functionality through the CloudStack API and should, therefore, only be used in a usability context, not a security context. CloudStacks Roles based security model should be used if a user is to be prohibited from accessing functionality.

 

Conclusion

The UI is no longer part of the core CloudStack Management server code (giving a much more modular and flexible approach) and is highly customisable, with even advanced changes possible with some knowledge of JS and Vue.js. The UI was designed keeping simplicity and user experience in mind.

The UI is designed to work across all browsers, tablets and phones. From a developer perspective, the codebase should be about a quarter that of the old UI and, most importantly, the Vue.JS framework is far easier for developers to work with.