Virtual Machine Orchestrator
The following are common scenarios that you may encounter when using Virtual Machine Orchestrator (VMO).
Scenario - Hot-Plugged Blank Disk Never Becomes Ready
On PaletteAI VM Launchpad and VMO pack versions earlier than 4.10.25, when you hot-plug a disk to a running virtual
machine and select Create New Blank Disk, the VMO UI creates the DataVolume with the ReadWriteMany access mode and
the Block volume mode. If the StorageClass cannot provision Block volumes, for example because its StorageProfile
allows only the Filesystem volume mode, the DataVolume never becomes ready. The virtual machine cannot use the disk,
even though VMO displays a message that the volume is attached.
To work around this issue, create the DataVolume first, and then attach it as an existing DataVolume.
Debug Steps
-
Create a DataVolume in the namespace of the virtual machine with a Blank source. Set the Volume Mode to
Filesystem, and select an Access Mode that the StorageClass supports, such asReadWriteMany. -
On the Configuration tab of the virtual machine, select Hot-plug Disk.
-
Select Existing DataVolume, and then select your DataVolume.
-
Select Attach Disk.
Scenario - VMO Loading Errors in Self-Hosted Palette
On self-hosted Palette and Palette VerteX installations, the cluster's Virtual Machines tab or the VMO Graphical UI (GUI) may fail to load. This issue applies to all installation methods but does not apply to self-hosted environments that use an IP address instead of a domain name.
The root cause is a Content-Security-Policy header with frame-ancestors set to https://*.spectrocloud.com, which
blocks the VMO GUI from loading when your Palette instance uses a different domain name.
Debug Steps
-
Log in to your self-hosted Palette or Palette VerteX system console.
-
From the left main menu, select Enterprise Cluster.
-
On the Overview tab, download the Kubernetes Config File.
-
From your terminal, set the
KUBECONFIGvariable to the file path of the kubeconfig.export KUBECONFIG=<path-to-kubeconfig> -
Verify the current
Content-Security-Policyvalue for the following TraefikMiddlewareresources.kubectl get middleware ui-csp-frame-ancestors --namespace ui-system --output yaml
kubectl get middleware cp-csp-frame-ancestors --namespace cp-system --output yaml
kubectl get middleware foreq-security-headers --namespace hubble-system --output yamlExample outputapiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
annotations:
meta.helm.sh/release-name: hubble
meta.helm.sh/release-namespace: default
creationTimestamp: "2026-04-07T15:03:54Z"
generation: 1
labels:
app.kubernetes.io/managed-by: Helm
name: ui-csp-frame-ancestors
namespace: ui-system
resourceVersion: "36023"
uid: 2f87aada-b8cf-454f-8c32-38be34b060bf
spec:
headers:
customResponseHeaders:
Content-Security-Policy: frame-ancestors 'self' https://*.spectrocloud.com -
Update each applicable
Middlewareresource by replacinghttps://*.spectrocloud.comwith your root domain. Replace<root-domain>in the following commands with your Palette root domain.tipUse the following command to identify your root domain.
kubectl get configmap root-domain-info --namespace hubble-system --output jsonpath='{.data.apiEndpoint}'kubectl patch middleware ui-csp-frame-ancestors --namespace ui-system --type merge \
--patch '{"spec":{"headers":{"customResponseHeaders":{"Content-Security-Policy":"frame-ancestors '\''self'\'' https://*.<root-domain> https://<root-domain>"}}}}'kubectl patch middleware cp-csp-frame-ancestors --namespace cp-system --type merge \
--patch '{"spec":{"headers":{"customResponseHeaders":{"Content-Security-Policy":"frame-ancestors '\''self'\'' https://*.<root-domain> https://<root-domain>"}}}}'kubectl patch middleware foreq-security-headers --namespace hubble-system --type merge \
--patch '{"spec":{"headers":{"customResponseHeaders":{"Content-Security-Policy":"frame-ancestors '\''self'\'' https://*.<root-domain> https://<root-domain>;"}}}}' -
Verify the updated values. Each
Middlewareresource should display aContent-Security-Policyheader withframe-ancestors 'self' https://*.<root-domain> https://<root-domain>.kubectl get middleware ui-csp-frame-ancestors --namespace ui-system --output yaml
kubectl get middleware cp-csp-frame-ancestors --namespace cp-system --output yaml
kubectl get middleware foreq-security-headers --namespace hubble-system --output yamlExample outputapiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
annotations:
meta.helm.sh/release-name: hubble
meta.helm.sh/release-namespace: default
creationTimestamp: "2026-04-07T15:03:54Z"
generation: 2
labels:
app.kubernetes.io/managed-by: Helm
name: ui-csp-frame-ancestors
namespace: ui-system
resourceVersion: "83150"
uid: 2f87aada-b8cf-454f-8c32-38be34b060bf
spec:
headers:
customResponseHeaders:
Content-Security-Policy: frame-ancestors 'self' https://*.docs-test.spectrocloud.com
https://docs-test.spectrocloud.com
Scenario - Virtual Machine (VM) Migration Plans in Unknown State
When using the VM Migration Assistant to migrate VMs to your VMO cluster, migration plans can enter an Unknown state if more VMs are selected for migration than the Maximum concurrent VM migrations setting allows. This value determines the maximum number of VMs that can be migrated simultaneously across all active migration plans.
To avoid this scenario, we recommend setting an appropriate value for Maximum concurrent VM migrations based on your workload and expected migration patterns. A higher value helps prevent migration plans from entering an Unknown state due to excessive concurrency.
If migration plans do enter an Unknown state, use the following steps to resolve the issue.
Debug Steps
-
From the left main menu, select Overview.
-
Select the Settings tab.
-
Click the Edit option next to Settings.
-
In the pop-up window, increase the value for Maximum concurrent VM migrations based on the maximum number of VMs you expect to migrate concurrently across all active migration plans.
For example, if you expect to migrate a maximum of 25 VMs across all active migration plans, set this value to 25 or more.
-
Click Save after making the change.
You will now need to recreate any migration plans that are in an Unknown state, and start them again. Refer to Create Migration Plans for guidance.
Scenario - Virtual Machines (VM) Stuck in a Migration Loop
Clusters with the VMO pack may experience VMs getting stuck in a continuous migration loop, as indicated by a
Migrating or Migration VM status. Use the following steps to troubleshoot and resolve the issue.
Debug Steps
-
Log in to Palette and click Clusters from the left Main Menu.
-
Select your cluster and click on the Profile tab.
-
Select the VMO pack layer and click Values under the Pack Details section.
-
Comment out the following lines under the
kubevirtResourcesection and click Save.workloads: {}
# workloadsUpdateStrategy:
# workloadUpdateMethods:
# - LiveMigrate -
The KubeVirt custom resource may fail to update after changing the VMO pack values in the Palette UI. To ensure the changes take effect, follow the Access Cluster with CLI guide to connect to your host cluster using the kubectl CLI.
-
In your terminal, issue the following command to edit the KubeVirt custom resource.
kubectl edit kubevirt --namespace kubevirt -
Comment out the following lines under the
specblock and save the file.# workloadUpdateStrategy:
# workloadUpdateMethods:
# - LiveMigrate -
Within a few minutes, the VMs will stop being stuck in the continuous migration loop.
warningStep 4 affects the CPU Hotplug functionality. If your cluster has CPU Hotplug enabled, you will need to manually restart your VM each time you add a virtual CPU for the changes to take effect.