Skip to content

Commit 358a655

Browse files
committed
notes on writing extensions
Signed-off-by: Abhishek Kumar <[email protected]>
1 parent acf154f commit 358a655

File tree

2 files changed

+158
-0
lines changed

2 files changed

+158
-0
lines changed

source/adminguide/extensions.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ CloudStack provides sample built-in orchestrator extensions for demonstration an
8484

8585
.. include:: extensions/troubleshooting.rst
8686

87+
.. include:: extensions/developer.rst
88+
8789
.. Images
8890
8991
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
Writing Extensions for CloudStack
2+
=================================
3+
4+
The CloudStack Extensions Framework allows developers and operators to write extensions using any programming language or script. From CloudStack’s perspective, an extension is simply an executable capable of handling specific actions and processing input payloads. CloudStack invokes the executable by passing the action name and the path to a JSON-formatted payload file as command-line arguments. The extension processes the payload, performs the required operations on an external system, and returns the result as a JSON response written to `stdout`.
5+
6+
7+
Create a New Extension
8+
^^^^^^^^^^^^^^^^^^^^^^
9+
10+
You must first register a new extension using the API or UI:
11+
12+
.. code-block:: bash
13+
14+
cloudmonkey createExtension name=myext path=myext-executable
15+
16+
Arguments:
17+
18+
- ``name``: Unique name
19+
- ``path``: Relative path to the executable. Root path will be `/usr/share/cloudstack-management/extensions/<extension_name>`
20+
21+
The path must be:
22+
23+
- Executable (``chmod +x``)
24+
- Owned by the ``cloud:cloud`` user
25+
- Present on all management servers (identical path and binary)
26+
27+
If no explicit path is provided during extension creation, CloudStack will scaffold a basic shell script at a default location with minimal required action handlers. This provides a starting point for customization and ensures the extension is immediately recognized and callable by the system.
28+
29+
CloudStack checks extension readiness periodically and shows its state in the UI/API.
30+
31+
Extension Structure
32+
^^^^^^^^^^^^^^^^^^^
33+
34+
Your extension must support the following invocation structure:
35+
36+
.. code-block:: bash
37+
38+
/path/to/executable <action> <payload_file> <timeout_seconds>
39+
40+
Arguments:
41+
42+
- ``<action>``: Action name (e.g., ``deploy``, ``start``, ``status``)
43+
- ``<payload_file>``: Path to the input JSON file
44+
- ``<timeout_seconds>``: Max duration CloudStack will wait for completion
45+
46+
Sample Invocation:
47+
48+
.. code-block:: bash
49+
50+
/usr/share/cloudstack-management/extensions/myext/myext.py /var/lib/cloudstack/management/extensions/myext/162345.json 60
51+
52+
Input Format (Payload)
53+
^^^^^^^^^^^^^^^^^^^^^^
54+
55+
CloudStack provides input via a JSON file, which your executable must read and parse.
56+
57+
Example:
58+
59+
.. code-block:: json
60+
61+
{
62+
"resourceType": "VM",
63+
"resourceUuid": "2b3c3e54-1ef3-4b8b-941d-61a1adcc7fa2",
64+
"action": "deploy",
65+
"accessDetails": {
66+
"username": "admin",
67+
"apiKey": "ABCD1234"
68+
}
69+
}
70+
71+
The schema varies depending on the resource and action. Use this to perform context-specific logic.
72+
73+
Output Format
74+
^^^^^^^^^^^^^
75+
76+
Your extension should write a response JSON to ``stdout``. Example:
77+
78+
.. code-block:: json
79+
80+
{
81+
"status": "success",
82+
"message": "Deployment completed"
83+
}
84+
85+
For custom actions, CloudStack may use the response to show it in the UI.
86+
87+
Action Lifecycle
88+
^^^^^^^^^^^^^^^^
89+
90+
1. A CloudStack action (e.g., deploy VM) triggers a corresponding extension action.
91+
2. CloudStack invokes the extension’s executable with appropriate parameters.
92+
3. The extension processes the input and responds within the timeout.
93+
4. CloudStack continues orchestration based on the result.
94+
95+
Custom Actions
96+
^^^^^^^^^^^^^^
97+
98+
You can define new custom actions for users or admin-triggered workflows.
99+
100+
- Register via UI or ``addCustomAction`` API
101+
- Define input parameters (name, type, required)
102+
- Implement the handler for the custom action in your executable.
103+
104+
CloudStack UI will render forms dynamically based on these definitions.
105+
106+
Best Practices
107+
^^^^^^^^^^^^^^
108+
109+
- Make executable/script idempotent and stateless
110+
- Validate all inputs before acting
111+
- Avoid hard dependencies on CloudStack internals
112+
- Implement logging for troubleshooting
113+
- Use exit code and ``stdout`` for signaling success/failure
114+
115+
Extension Examples
116+
^^^^^^^^^^^^^^^^^^
117+
118+
**Bash Example**
119+
120+
.. code-block:: bash
121+
122+
#!/bin/bash
123+
ACTION=$1
124+
FILE=$2
125+
TIMEOUT=$3
126+
127+
if [ "$ACTION" == "deploy" ]; then
128+
echo '{ "success": true, "result": { "message": "OK" } }'
129+
else
130+
echo '{ "success": false, "result": { "message": "Unsupported action" } }'
131+
fi
132+
133+
**Python Example**
134+
135+
.. code-block:: python
136+
137+
import sys, json
138+
139+
action = sys.argv[1]
140+
payload_file = sys.argv[2]
141+
142+
with open(payload_file) as f:
143+
data = json.load(f)
144+
145+
if action == "deploy":
146+
print(json.dumps({"success": True, "result": {"message": "Deployed"}}))
147+
else:
148+
print(json.dumps({"success": False, "result": {"message": "Unknown action"}}))
149+
150+
For a clearer understanding of how to implement an extension, developers can refer to the base shell script scaffolded by CloudStack for orchestrator-type extensions. This script is located at:
151+
152+
/usr/share/cloudstack-common/scripts/vm/hypervisor/external/provisioner/provisioner.sh
153+
154+
It serves as a template with minimal required action handlers, making it a useful starting point for building new extensions.
155+
156+
Additionally, CloudStack includes built-in extensions for Proxmox and Hyper-V that demonstrate how to implement extensions in different languages - Bash and Python.

0 commit comments

Comments
 (0)