You can add custom settings (transformations) to virtual machine (VM) XML configurations. More about the XML configuration can be found in Libvirt documentation.
Transformations can be applied to an existing VM or to a configuration from which VMs are created.
Working logic
Transformations are created in the XSLT language. More details can be found in XSLT documentation. The created transformation is uploaded to the platform and applied to the VM or configuration through API requests.
To apply a transformation to a VM, the platform creates a task Restoring the VM xml file. After the transformation is applied, the platform reboots the VM. Only one transformation can be applied to each VM or configuration at a time. When the transformation is disabled, the XML configuration is restored to its original state.
To change or delete a transformation from the platform, you must first detach it from the VM or configuration.
Transformation examples
Example 1 — Basic copy template
The template copies node and VM parameters without changes and is applied at the beginning of all other transformations.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>Example 2 — Changing the network interface model
The template allows you to replace the model of the emulated network adapter with e1000 in all interface elements, regardless of what is selected in the VM settings.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- Basic copy template -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<!-- For each interface: copy everything except <model> and insert yours -->
<xsl:template match="interface">
<xsl:copy>
<xsl:apply-templates select="@*|node()[not(self::model)]"/>
<model type="e1000"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>Example 3 — Passing additional QEMU arguments
The template sets the physical block size for the IDE hard drive to 4096 bytes.
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:qemu="http://libvirt.org/schemas/domain/qemu/1.0">
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<!-- Adding qemu:commandline to the end of domain and declaring the required namespace -->
<xsl:template match="domain">
<xsl:copy>
<xsl:attribute name="xmlns:qemu">http://libvirt.org/schemas/domain/qemu/1.0</xsl:attribute>
<xsl:apply-templates select="@*|node()"/>
<qemu:commandline>
<qemu:arg value="-global"/>
<qemu:arg value="ide-hd.physical_block_size=4096"/>
</qemu:commandline>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>Managing transformations
Upload a transformation to the platform
Execute the request:
curl -X 'POST' \
'https://vm6.example.com/vm/v3/host_transformation' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"content": "<transformation_content>",
"name": "<transformation_name>"
}'Explanations:
vm6.example.com— IP address or domain name of the server with the platform;-
<transformation_content>— transformation content in XSLT format;Special characters in the transformation (quotes, backslashes, line breaks, etc.) must be escaped according to the JSON format.Example <transformation_name>— transformation name.
If the addition is successful, the response will contain the transformation id.
Get the list of uploaded transformations
Execute the request:
curl -X 'GET' \
'https://vm6.example.com/vm/v3/host_transformation' \
-H 'accept: application/json'Explanations:
vm6.example.com— IP address or domain name of the server with the platform.
The request returns only the ids and names of transformations uploaded to the platform, without binding them to VMs and configurations.
Modify a transformation
Execute the request:
curl -X 'POST' \
'https://vm6.example.com/vm/v3/host_transformation/<id>' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"content": "<transformation_content>",
"name": "<transformation_name>"
}'Explanations:
vm6.example.com— IP address or domain name of the server with the platform;<id>— transformation id;-
<transformation_content>— transformation content in XSLT format;
Special characters in the transformation (quotes, backslashes, line breaks, etc.) must be escaped according to the JSON format.Example <transformation_name>— transformation name.
Delete a transformation
Execute the request:
curl -X 'DELETE' \
'https://vm6.example.com/vm/v3/host_transformation/<id>' \
-H 'accept: application/json'Explanations:
vm6.example.com— IP address or domain name of the server with the platform;<id>— transformation id.
If the deletion is successful, the response will contain the transformation id.
Applying a transformation to a VM
Attach a transformation to a VM
Execute the request:
curl -X 'POST' \
'https://vm6.example.com/vm/v3/host/<host_id>/transformation/<id>/apply' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{}'Explanations:
vm6.example.com— IP address or domain name of the server with the platform;<host_id>— VM id;<id>— transformation id.
If the attachment is successful, the response will contain the VM id and the created task.
Detach a transformation from a VM
Execute the request:
curl -X 'DELETE' \
'https://vm6.example.com/vm/v3/host/<host_id>/transformation/' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{}'Explanations:
vm6.example.com— IP address or domain name of the server with the platform;<host_id>— VM id.
Applying a transformation to a configuration
Attach a transformation to a configuration
Execute the request:
curl -X 'POST' \
'https://vm6.example.com/vm/v3/preset/<preset_id>' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{"transformation_id": <id>}'Explanations:
vm6.example.com— IP address or domain name of the server with the platform;<preset_id>— configuration id;<id>— transformation id.
Detach a transformation from a configuration
Execute the request:
curl -X 'POST' \
'https://vm6.example.com/vm/v3/preset/<preset_id>' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{"transformation_id": null}'Explanations:
vm6.example.com— IP address or domain name of the server with the platform;<preset_id>— configuration id.
En
Es