Tag-Based Automation: Manage VM CPU Priority via assigned tag.
-
WHAT: Automatically assigns CPU weights and I/O priorities based on assigned VM tag (i.e. replicating what vcenter did via resource pools etc.).
HOW: Run via cron for regular enforcement.
WHY: Automatically assign performance metrics on all pool VMs (as well as preventing configuration drift if settings are accidentally changed).
TAGS: The Performance Tiering Concept: 4-tier system with a naming convention that sorts logically in XO:
TAG CPU WEIGHT I/O PRIORITY USE CASE 0-core 2048 7 (Highest) Domain Controllers, DNS, DHCP, Core DBs 1-high 1024 7 Critical App Servers 2-normal 256 4 Standard Workloads 3-low 128 1 Dev/Test, Noisy NeighborsWhy the "0-" prefix? It forces core VMs to the top of the VM list in XO for easy visibility and management.
Important: CPU weights only matter during contention. When the host is under-utilized, all VMs get the performance they need regardless of weight. These are an insurance policy.
Change-Log
# ============================================ # CHANGE-LOG: set-performance.sh # ============================================ v2.0 - 2026-05-14 - Added external configuration file (set-performance.conf) for easier management without editing the script directly - Added Master Host Check: script safely exits on non-master hosts, allowing deployment across all pool hosts via cron - Added detailed main log (/var/log/set-performance.log) - Added summary counters per tier (0-core, 1-high, 2-normal, 3-low) - Added one-line timestamped summary output to separate /var/log/set-performance-summary.log for easy auditing - Added optional NFS copy of summary log for centralized reporting via Xen Orchestra v1.0 - Initial Release - Tag-based CPU weight and I/O priority enforcement - Four performance tiers: 0-core, 1-high, 2-normal, 3-low - Network QoS cap (100Mbps) for 3-low tagged VMs - Designed for hourly cron executionThe Files:
Conf: set-performance.conf
# ============================================ # set-performance.conf # Configuration file for set-performance.sh # Edit this file to customize your environment # ============================================ # --- LOG FILES --- MAIN_LOG="/var/log/set-performance.log" SUMMARY_LOG="/var/log/set-performance-summary.log" # --- TAG NAMES --- CORE_TAG="0-core" HIGH_TAG="1-high" NORMAL_TAG="2-normal" LOW_TAG="3-low" # --- PERFORMANCE SETTINGS --- CORE_WEIGHT="2048" CORE_IO_PRI="7" HIGH_WEIGHT="1024" HIGH_IO_PRI="7" NORMAL_WEIGHT="256" NORMAL_IO_PRI="4" LOW_WEIGHT="128" LOW_IO_PRI="1"Script: set-performance.sh (v2 - updated 20260514)
#!/bin/bash # ============================================ # XCP-ng set-performance.sh (v2) # Purpose: Enforce VM Performance Tiers via Tags # Tags: 0-core, 1-high, 2-normal, 3-low # Runs: Hourly via cron # ============================================ # --- LOAD CONFIGURATION --- CONF_FILE="$(dirname "$0")/set-performance.conf" if [ -f "$CONF_FILE" ]; then source "$CONF_FILE" else echo "Error: Configuration file $CONF_FILE not found." exit 1 fi # --- MASTER HOST CHECK --- # Only run on the current Pool Master IS_MASTER=$(xe host-is-master) if [ "$IS_MASTER" != "true" ]; then exit 0 fi # --- INITIALIZE COUNTERS --- count_0=0 count_1=0 count_2=0 count_3=0 # --- REDIRECT OUTPUT TO MAIN LOG --- exec >> "$MAIN_LOG" 2>&1 echo "--- Starting Performance Sync: $(date) ---" # --- CORE CRITICAL VMs --- echo "=== Applying $CORE_TAG CPU & I/O Priority ===" for uuid in $(xe vm-list tags:contains="$CORE_TAG" --minimal | tr ',' '\n'); do [ -z "$uuid" ] && continue xe vm-param-set uuid=$uuid VCPUs-params:weight=$CORE_WEIGHT other-config:sched-pri=$CORE_IO_PRI echo " ✓ CORE CRITICAL applied: $uuid" ((count_0++)) done # --- HIGH PRIORITY VMs --- echo "=== Applying $HIGH_TAG CPU & I/O Priority ===" for uuid in $(xe vm-list tags:contains="$HIGH_TAG" --minimal | tr ',' '\n'); do [ -z "$uuid" ] && continue xe vm-param-set uuid=$uuid VCPUs-params:weight=$HIGH_WEIGHT other-config:sched-pri=$HIGH_IO_PRI echo " ✓ HIGH priority applied: $uuid" ((count_1++)) done # --- NORMAL PRIORITY VMs --- echo "=== Applying $NORMAL_TAG CPU & I/O Priority ===" for uuid in $(xe vm-list tags:contains="$NORMAL_TAG" --minimal | tr ',' '\n'); do [ -z "$uuid" ] && continue xe vm-param-set uuid=$uuid VCPUs-params:weight=$NORMAL_WEIGHT other-config:sched-pri=$NORMAL_IO_PRI echo " ✓ NORMAL priority applied: $uuid" ((count_2++)) done # --- LOW PRIORITY VMs --- echo "=== Applying $LOW_TAG CPU & I/O Priority ===" for uuid in $(xe vm-list tags:contains="$LOW_TAG" --minimal | tr ',' '\n'); do [ -z "$uuid" ] && continue xe vm-param-set uuid=$uuid VCPUs-params:weight=$LOW_WEIGHT other-config:sched-pri=$LOW_IO_PRI echo " ✓ LOW priority applied: $uuid" ((count_3++)) done echo "--- Sync Complete: $(date) ---" # --- ONE-LINE SUMMARY → set-performance-summary.log --- SUMMARY_LINE="$(date '+%Y-%m-%d %H:%M:%S'):$(hostname) $CORE_TAG:$count_0 $HIGH_TAG:$count_1 $NORMAL_TAG:$count_2 $LOW_TAG:$count_3" echo "$SUMMARY_LINE" >> "$SUMMARY_LOG"How to Deploy:
1 Upload script
bash # Copy both files to the same directory cp set-performance.conf /usr/local/bin/ cp set-performance.sh /usr/local/bin/ chmod +x /usr/local/bin/set-performance.sh2 Add to crontab
# Add to crontab (runs hourly) 0 * * * * root /usr/local/bin/set-performance.sh >> /var/log/set-performance.log 2>&13 Test
# Test it manually /usr/local/bin/set-performace.sh -
Nice. I believe that I read elsewhere that our dev team was working on something similar.
FYI, you have a typo (performace.sh vs performance.sh)

-
WHAT: Automatically assigns CPU weights and I/O priorities based on assigned VM tag (i.e. replicating what vcenter did via resource pools etc.).
It would be even better if you could split the configuration section off, so that it’s in its own conf file. Would make it easier to manage, also if this ends up being used, by Vates in the Vates VMS software. There can then be a vendor recommended configuration with the option of customer’s own workflow based, configuration.
-
Ping @julienxovates
-
@Danp Thanks for the correction - i.e. "Good-eye, Good-eye

-
@john.c Great idea, and done! ("Keep 'em coming")
-
@john.c Great idea, and done! ("Keep 'em coming")
Thanks for the change. By the way I meant when doing Vendor config and customer workflow config. To implement that requires nested config file. In other words the set-performance.conf, then a file for instance in a set-performance.conf.d/custom.conf (or similar). The custom.conf in the conf.d directory overrides the same property as well as section within set-performance.conf.
-
@john.c Great ideas (especially if Vates decides to bake something similar into XO someday) but may be getting too far into the weeds for now...
-
@john.c Great ideas (especially if Vates decides to bake something similar into XO someday) but may be getting too far into the weeds for now...
That’s okay. Just putting it out there - no rush! Any way to maintain Linux good practice relocate the conf file to /usr/local/etc/ (or /etc) then keep script in /usr/local/bin.
-
@johnnezero Also there’s shortcut directories including one called cron.hourly, you can place a symlink (or hard link) to the script there. Cron will then execute the script without you needing to alter the crontab file.
Just drop .sh for using the shortcut directory as it will not run there otherwise.
-
@john.c Yet another awesome idea - adding it to the "ToDo List", thanks!
Hello! It looks like you're interested in this conversation, but you don't have an account yet.
Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.
With your input, this post could be even better 💗
Register Login