Originally Cloudstack console proxy supports US keyboard. As time goes on, we add support for Japanese language keyboard. Other types of language keyboard support are added per customer requests. We realize the keyboard support matrix for all the languages can grow quite large and complex, it is necessary to automate this process. 

In a cloud system, typical customer deployments involve various browsers, hypervisors, host OSes, and keyboards. Keyboard is not an isolated component. The hypervisors, OSes, browsers all affect the key translation along the way as they each has its own translation. 

The combination of these system variables can be quite large. The current infrastructure requires the developers to understand the architecture of the console proxy and write a new keyboard translation table for every new combination. 

The new feature is to help automate the language keyboard support so that users and developers can add new support for a non-US keyboard in Cloudstack system without much difficulty. The goal is to make it simpler and easier to add new non-US keyboard support.


This is a functional specification for feature ‘Support for non-US keyboards in Console Proxy’.


CLOUDSTACK-8665 - Getting issue details... STATUS




Document History




Anshul Gangwar, Fang Wang

First revision

23 July 2015 


Feature specifications

The journey of a key

When a key is pressed on the user keyboard, before it reaches its destination and displays a key output on the user VM, it passes through the browser the client uses, the client OS, the console proxy, the server side hypervisor, host OS, and displays a key on the VM. Even when console proxy does the key translation correctly according to the standard and keyboard layout, any component in this path can change the key translation, hence it can make the key output at the end user VM incorrect. 

Each component, for example, the OS, usually has its own key translation mechanism. With all the components’ own key translation involved, it adds complication to the console proxy key translation. In the end, the correct key translation for the console proxy is to make the correct key gets displayed at the end user VM.

For each different language keyboard, the main engine to be changed is the keyboard key translation rules and tables. There are ten parameters affecting which keyboard translation table to deploy. Five parameters are on server side, which include server OS, hypervisor, and keyboard. Server can obtain this information from the ManagementServer (MS) in Cloudstack. 

Parameters on server side: 

  1. s_os: OS type for VM, such as Windows, Linux (Rhel, Centos, …)
  2. s_osVersion: os version;
  3. s_hypervisor: hypervisor type, such as Vmware, Xen, LVM, Hyper
  4. s_hypVersion: version;
  5. s_keyb: VM keyboard, such as English keyboard(EN), Japanese, …

There are five parameters on client side:

  1. c_os: client OS type, such as Windows, Linux ...
  2. c_osVersion: OS version;
  3. c_browser: IE(IE can have different versions too, IE8, IE9, etc); Firefox, Chrome, Safari
  4. c_browserVersion: browser version;
  5. c_keyb: client keyboard, English keyboard(EN), Japanese(jp), ….
    Based on the different combination of the parameters on the server side and the client side, each combination corresponds to one keyboard mapping table.

Console proxy language keyboard translation

At present, if anyone needs to add a new keyboard support for a language, he needs to spend time understanding the console proxy code and the various key translation logic and rules. Then he can modify a javasript file to add the new language key translation table. However, since this javascript file contains complex logic and rules used for other languages, any change to this file needs to be thought out carefully, otherwise it can cause regression and made some existing keys fail. 

To make this process easier, we refactor the console proxy code for keyboard support. Our goal is to save users and developers time to understand the code path, and limit the scope of change as much as possible. Hence it can reduce the possibility of regression and testing time. After the refactor, the majority of keyboard translation rules and logic stay in a file which the users will not need to understand fully and make modifications. Users only need to modify a small table, which has direct input and output mapping, This small file to be modified handles some special keys for the special language keyboard. 

For special keyboard such as Japanese keyboard, it is required that the hypervisor, host OS and browser also need to deploy Japanese version. 
Even though the console proxy does the translation we expect, the final result at the end may not display the correct key, because of the other components and their own key translations along the way. Hence, all we need to find at the console proxy level is to get the input key translated to a value that eventually display the proper key at the user VM terminal.

What is input and output key codes
Ajaxviewer.js is a javascript file handles all the keys translations. We refer to this translation ‘T’. 

There are two codes users need to be aware of and work with:
Input_keycode: this is the keycode when user presses a key, before any translation. It is related to the key’s physical location on the keyboard;

Output_keycode: this is the keycode sent out by console proxy, to display the correct key on the VM, after all the translations;

T(input_keycode) = output_keycode; 

For example, a general ASCII letter a, we may have T(97) = 97; – when the key for ‘a’ is pressed, the input code is 97; when output keycode is 97, letter ‘a’ is displayed on user VM;

 Key type events 
There are two types of key events: key down/key up, and key press. 

There are two main translation schemes: X11 key system and non-X11 key systems. For X11 key system, the translation follows the X11 keys. It handles the key down/key up events, and skip the key press event. For example, a translation for CapsLock key may be like this (we use X11_ prefix to denote the X11 key):


For non-X11 key system, it does not use the standard X11 key code. It mainly handles the key press event. We build a translation table to handle the majority of the keys for non-X11. 

For the majority of the keys, the logic and rules are set up in ajaxviewer.js. Users do not normally need to modify this file, unless there is a need to change or add any rule there. Users for a special keyboard support need to add entries into the table in ajaxkeys.js. This is a table to handle the special keys which are not covered by the rules and tables in ajaxviewer.js. The rules in ajaxviewer.js handles the default key translation and covers the common keys on the keyboard. It has rules for the special keys. It treats the special keys in a conditional mapping table. For each special keyboard, users just add the entries in the conditional event mapping table in ajaxkeys.js. 

Algorithm for the X11 type of keys:
Step 1: if entry exists in the jsX11KeysymMap table in ajaxviewer.js, translate that key to a corresponding X11_key in that table using key down/key up event;
Step 2: if the condition matches, translate the keys in the conditional map table with jsX11KeysymMap;

For non-X11 type of keys: it handles only the keyPress events; 
Step 1: for every keyPress event, do the key translation;
Step 2: shall only handles key down/up event if all the conditions are true for a special key in the conditional mapping table. 

The conditional mapping table is in a separate file ajaxkeys.js, it has the format for each conditional entry:


Conditional mapping entry   { 
    type: <event type>, code: <mapped key code>, modifiers: <modifiers>,
    shift : <shift state match condition>,        -- match on shift state
    guestos : <guest os match condition>,     -- match on guestos type
    browser: <browser type match condition>,  -- match on browser
    browserVersion: <brower version match condition>  -- match on browser version


For example a match for a particular browser can be like this:


{keycode: 59, entry: X11_KEY_COLON, browser: "Firefox"}, when the browser is Firefox, the rule will apply. Otherwise the rule will not apply. 


Browser, type and guestos all have string type.


Find the input_keycode and output_keycode for a particular key

The new translation table in ajaxkeys.js handles the conditional mappings for some special keys. It implements the “T” function: T(input_keycode) = output_keycode. 

When a key is pressed, we need to know its input_keycode, so that we can find out if it already has an entry in the table. If it has an entry in the table, but the output is not correct, we need to modify or add a conditional entry to match the current browser and os conditions. If there is no existing entry for this key, we need to add a new entry in the table. So by all means, we need to know its input_keycode. 

To find out the Input_keycode, we can turn on the keyboard logger window which will show the keycode for every key pressed. “CTRL-ATL-SHIFT+SPACE” turns on the logger. To have a fresh window to show the code for a new key, clear the window first, and then press a key. 
For example, an output of a logger window:
(insert the figure)

However, for the value of output_keycode, it is tricky. It is more of a trial and error process. We can search the keyboard standard key document, and try various values. In the future release, we expect that a script will be added to automatically display the output of a range of output_keycodes on the user VM. From this range of output, we can inspect and find the matching output code for the key. This process can be repeated till the correct output_keycode is found.



With the refactored infrastructure, when we add a new keyboard support, we modify the ajaxkeys.js file. We need to find out the input_keycode and output_keycode for special keys for a new language keyboard and add them in the conditional mapping table with the proper conditions specified. Ajaxviewer.js will parse this file and add them into its main key translation table to support the new keyboard.

Passing ajaxviewer.js and ajaxkeys.js to CPVM without regenerating systemvm.iso

If user want to update his/her modified ajaxviewer.js and ajaxkeys.js to CPVM then he/she shouldn't be modifying system.iso to pass them to CPVM.

Use case

  • Allow users to add support for any locale keyboard

Design description

Partial implementation of design is already present in CloudStack. Keymap table is already partially decoupled into ajaxkeys.js and ajaxviewer.js. We now have to refine them to made it more user friendly.

To pass  ajaxkviewer.js and ajaxkeys.js to CPVM user can copy them to folder systemvm/js (/usr/share/cloudstack-common/systemvm/js). After copying them user has to stop start CPVM manually to get the updated keyboard mappings deployed in CPVM. These files will be copied to  folder on CPVM.

During stop start of CPVM, if  scripts are present at folder systemvm/js (/usr/share/cloudstack-common/systemvm/js) then we pass them to CPVM.

After this user will be able to use the updated locale key mappings.

Instead of selecting user vm locale in console, we will automatically set the locale of user vm locale on top to show him with what locale his console is running.

API Changes


DB Changes


UI Flow

After these changes user will not be able to select his keyboard language in console UI. Instead he has to select the keyboard language during VM deployment. If he want to change keyboard layout later then he has to update the VM details with correct keyboard. For example through API if user wants to set the locale to french(fr) then he has to use api something like





  • No labels