Skip to content

Conversation

@winterhazel
Copy link
Member

Description

The secondary storage selectors allow operators to specify, for instance, that templates should go to secondary storage A and snapshots to secondary storage B. When registering a template, it will be downloaded only to secondary storage A.

During the startup of the SSVM's service, the MS executes a template synchronization process to verify what templates are in which secondary storage in order to download them to secondary storages in which they do not exist. However, this process does not consider the secondary storage selectors. Hence, templates will be downloaded to secondary storage B.

This PR makes the MS consider the secondary storage selectors during the template synchronization process.

Types of changes

  • Breaking change (fix or feature that would cause existing functionality to change)
  • New feature (non-breaking change which adds functionality)
  • Bug fix (non-breaking change which fixes an issue)
  • Enhancement (improves an existing feature and functionality)
  • Cleanup (Code refactoring and cleanup, that may add test cases)

Feature/Enhancement Scale or Bug Severity

Feature/Enhancement Scale

  • Major
  • Minor

How Has This Been Tested?

  1. I created a secondary storage selector directing templates to secondary storage A, and another directing snapshots to secondary storage B.

  2. I registered two new templates. Both were downloaded only to secondary storage A.

  3. I restarted the SSVM's service. I validated that the MS did not begin downloading the two templates to secondary storage B.

  4. I took some volume snapshots. I validated that they went to secondary storage B.

  5. I removed the selector that was directing templates to secondary storage A, and restarted the SSVM's service. I validated that they were downloaded to secondary storage B.

@winterhazel
Copy link
Member Author

@blueorangutan package

@codecov
Copy link

codecov bot commented Jun 4, 2025

Codecov Report

❌ Patch coverage is 90.32258% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 16.24%. Comparing base (432a306) to head (b0e586a).
⚠️ Report is 58 commits behind head on 4.20.

Files with missing lines Patch % Lines
.../cloudstack/storage/image/TemplateServiceImpl.java 90.90% 1 Missing and 1 partial ⚠️
.../com/cloud/template/HypervisorTemplateAdapter.java 50.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff            @@
##               4.20   #10956   +/-   ##
=========================================
  Coverage     16.23%   16.24%           
- Complexity    13378    13380    +2     
=========================================
  Files          5657     5657           
  Lines        498865   498878   +13     
  Branches      60545    60547    +2     
=========================================
+ Hits          81014    81024   +10     
+ Misses       408820   408819    -1     
- Partials       9031     9035    +4     
Flag Coverage Δ
uitests 4.00% <ø> (ø)
unittests 17.09% <90.32%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@sureshanaparti sureshanaparti added this to the 4.20.2 milestone Jun 5, 2025
@sureshanaparti
Copy link
Contributor

@blueorangutan package

@blueorangutan
Copy link

@sureshanaparti a [SL] Jenkins job has been kicked to build packages. It will be bundled with KVM, XenServer and VMware SystemVM templates. I'll keep you posted as I make progress.

@blueorangutan
Copy link

Packaging result [SF]: ✔️ el8 ✔️ el9 ✖️ debian ✔️ suse15. SL-JID 13610

@DaanHoogland
Copy link
Contributor

@blueorangutan package

@blueorangutan
Copy link

@DaanHoogland a [SL] Jenkins job has been kicked to build packages. It will be bundled with KVM, XenServer and VMware SystemVM templates. I'll keep you posted as I make progress.

@blueorangutan
Copy link

Packaging result [SF]: ✔️ el8 ✔️ el9 ✔️ debian ✔️ suse15. SL-JID 13666

Copy link
Contributor

@DaanHoogland DaanHoogland left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clgtm

@DaanHoogland
Copy link
Contributor

@blueorangutan test

@blueorangutan
Copy link

@DaanHoogland a [SL] Trillian-Jenkins test job (ol8 mgmt + kvm-ol8) has been kicked to run smoke tests

@blueorangutan
Copy link

[SF] Trillian test result (tid-13499)
Environment: kvm-ol8 (x2), Advanced Networking with Mgmt server ol8
Total time taken: 54526 seconds
Marvin logs: https://github.com/blueorangutan/acs-prs/releases/download/trillian/pr10956-t13499-kvm-ol8.zip
Smoke tests completed. 136 look OK, 0 have errors, 5 did not run
Only failed and skipped tests results shown below:

Test Result Time (s) Test File
all_test_vpc_vpn Skipped --- test_vpc_vpn.py
all_test_webhook_delivery Skipped --- test_webhook_delivery.py
all_test_webhook_lifecycle Skipped --- test_webhook_lifecycle.py
all_test_host_maintenance Skipped --- test_host_maintenance.py
all_test_hostha_kvm Skipped --- test_hostha_kvm.py

@weizhouapache
Copy link
Member

@blueorangutan package

@blueorangutan
Copy link

@weizhouapache a [SL] Jenkins job has been kicked to build packages. It will be bundled with KVM, XenServer and VMware SystemVM templates. I'll keep you posted as I make progress.

@blueorangutan
Copy link

Packaging result [SF]: ✔️ el8 ✔️ el9 ✔️ el10 ✔️ debian ✔️ suse15. SL-JID 14955

@weizhouapache weizhouapache modified the milestones: 4.20.2, 4.20.3 Sep 12, 2025
@DaanHoogland
Copy link
Contributor

@blueorangutan test

@blueorangutan
Copy link

@DaanHoogland a [SL] Trillian-Jenkins test job (ol8 mgmt + kvm-ol8) has been kicked to run smoke tests

@blueorangutan
Copy link

[SF] Trillian test result (tid-14332)
Environment: kvm-ol8 (x2), zone: Advanced Networking with Mgmt server ol8
Total time taken: 54052 seconds
Marvin logs: https://github.com/blueorangutan/acs-prs/releases/download/trillian/pr10956-t14332-kvm-ol8.zip
Smoke tests completed. 141 look OK, 0 have errors, 0 did not run
Only failed and skipped tests results shown below:

Test Result Time (s) Test File

@github-actions
Copy link

This pull request has merge conflicts. Dear author, please fix the conflicts and sync your branch with the base branch.

@winterhazel
Copy link
Member Author

@blueorangutan package

@blueorangutan
Copy link

@winterhazel a [SL] Jenkins job has been kicked to build packages. It will be bundled with KVM, XenServer and VMware SystemVM templates. I'll keep you posted as I make progress.

@blueorangutan
Copy link

Packaging result [SF]: ✖️ el8 ✖️ el9 ✖️ debian ✖️ suse15. SL-JID 16167

@winterhazel
Copy link
Member Author

@blueorangutan package

@blueorangutan
Copy link

@winterhazel a [SL] Jenkins job has been kicked to build packages. It will be bundled with KVM, XenServer and VMware SystemVM templates. I'll keep you posted as I make progress.

@blueorangutan
Copy link

Packaging result [SF]: ✔️ el8 ✔️ el9 ✔️ el10 ✔️ debian ✔️ suse15. SL-JID 16168

@DaanHoogland
Copy link
Contributor

@blueorangutan test

@blueorangutan
Copy link

@DaanHoogland a [SL] Trillian-Jenkins test job (ol8 mgmt + kvm-ol8) has been kicked to run smoke tests

@blueorangutan
Copy link

[SF] Trillian test result (tid-15072)
Environment: kvm-ol8 (x2), zone: Advanced Networking with Mgmt server ol8
Total time taken: 54044 seconds
Marvin logs: https://github.com/blueorangutan/acs-prs/releases/download/trillian/pr10956-t15072-kvm-ol8.zip
Smoke tests completed. 141 look OK, 0 have errors, 0 did not run
Only failed and skipped tests results shown below:

Test Result Time (s) Test File

@RosiKyu RosiKyu self-assigned this Jan 26, 2026
@RosiKyu
Copy link
Collaborator

RosiKyu commented Jan 26, 2026

@blueorangutan package

@blueorangutan
Copy link

@RosiKyu a [SL] Jenkins job has been kicked to build packages. It will be bundled with KVM, XenServer and VMware SystemVM templates. I'll keep you posted as I make progress.

@blueorangutan
Copy link

Packaging result [SF]: ✔️ el8 ✔️ el9 ✔️ el10 ✔️ debian ✔️ suse15. SL-JID 16538

Copy link
Contributor

@sureshanaparti sureshanaparti left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clgtm

@RosiKyu
Copy link
Collaborator

RosiKyu commented Jan 27, 2026

@blueorangutan test

@blueorangutan
Copy link

@RosiKyu a [SL] Trillian-Jenkins test job (ol8 mgmt + kvm-ol8) has been kicked to run smoke tests

@blueorangutan
Copy link

[SF] Trillian Build Failed (tid-15293)

Copy link
Collaborator

@RosiKyu RosiKyu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Tested template and ISO registration with and without secondary storage selectors on KVM with NFS storage (3 secondary storages).

Test Case Description Result
TC1 Template registration WITHOUT selector (syncs to all secondary storages) PASSED
TC2 Template registration WITH TEMPLATE type selector (only to specified storage) PASSED
TC3 ISO registration WITH ISO type selector (only to specified storage) PASSED

TC1: Template Registration WITHOUT Secondary Storage Selector

Objective
Verify that template registration without any secondary storage selector syncs the template to ALL secondary storages in the zone (default behavior).

Test Steps

  1. Deploy fresh CloudStack environment with multiple secondary storages
  2. Verify js.interpretation.enabled is false (default) - no selectors can be created
  3. Verify no secondary storage selectors exist
  4. List templates and check downloaddetails to confirm templates are present on all secondary storages

Expected Result:
Templates should be downloaded to ALL secondary storages in the zone.

Actual Result:
Templates are downloaded to all 3 secondary storages (sec1, sec2, sec3).

Test Evidence:

1. List secondary storages:

(localcloud) 🐱 > list imagestores 
{
  "count": 3,
  "imagestore": [
    {
      "id": "cf524b6c-0043-4d75-b1f7-19568f8f52a4",
      "name": "NFS://10.0.32.4/acs/secondary/ref-trl-10724-k-Mol9-rositsa-kyuchukova/ref-trl-10724-k-Mol9-rositsa-kyuchukova-sec1",
      "protocol": "nfs",
      "providername": "NFS",
      "zoneid": "2b853fbe-39ab-4282-88b5-eca6464db31b",
      "zonename": "ref-trl-10724-k-Mol9-rositsa-kyuchukova"
    },
    {
      "id": "b400311d-2ffa-401d-96c5-5bec35efc741",
      "name": "NFS://10.0.32.4/acs/secondary/ref-trl-10724-k-Mol9-rositsa-kyuchukova/ref-trl-10724-k-Mol9-rositsa-kyuchukova-sec2",
      "protocol": "nfs",
      "providername": "NFS",
      "zoneid": "2b853fbe-39ab-4282-88b5-eca6464db31b",
      "zonename": "ref-trl-10724-k-Mol9-rositsa-kyuchukova"
    },
    {
      "id": "4afb6866-1be7-4f34-8067-8864232d8694",
      "name": "NFS://10.0.32.4/acs/secondary/ref-trl-10724-k-Mol9-rositsa-kyuchukova/ref-trl-10724-k-Mol9-rositsa-kyuchukova-sec3",
      "protocol": "nfs",
      "providername": "NFS",
      "zoneid": "2b853fbe-39ab-4282-88b5-eca6464db31b",
      "zonename": "ref-trl-10724-k-Mol9-rositsa-kyuchukova"
    }
  ]
}

2. List templates showing download status on all secondary storages:

(localcloud) 🐱 > list templates templatefilter=all
{
  "count": 2,
  "template": [
    {
      "account": "system",
      "displaytext": "SystemVM Template (KVM)",
      "format": "QCOW2",
      "hypervisor": "KVM",
      "id": "35037aea-fac6-11f0-84c5-1e00b700018d",
      "isready": true,
      "name": "SystemVM Template (KVM)",
      "templatetype": "SYSTEM",
      "downloaddetails": [
        {
          "datastore": "NFS://10.0.32.4/acs/secondary/ref-trl-10724-k-Mol9-rositsa-kyuchukova/ref-trl-10724-k-Mol9-rositsa-kyuchukova-sec1",
          "datastoreId": "cf524b6c-0043-4d75-b1f7-19568f8f52a4",
          "datastoreRole": "Image",
          "downloadPercent": "100",
          "downloadState": "DOWNLOADED"
        },
        {
          "datastore": "NFS://10.0.32.4/acs/secondary/ref-trl-10724-k-Mol9-rositsa-kyuchukova/ref-trl-10724-k-Mol9-rositsa-kyuchukova-sec2",
          "datastoreId": "b400311d-2ffa-401d-96c5-5bec35efc741",
          "datastoreRole": "Image",
          "downloadPercent": "100",
          "downloadState": "DOWNLOADED"
        },
        {
          "datastore": "NFS://10.0.32.4/acs/secondary/ref-trl-10724-k-Mol9-rositsa-kyuchukova/ref-trl-10724-k-Mol9-rositsa-kyuchukova-sec3",
          "datastoreId": "4afb6866-1be7-4f34-8067-8864232d8694",
          "datastoreRole": "Image",
          "downloadPercent": "100",
          "downloadState": "DOWNLOADED"
        },
        {
          "datastore": "ref-trl-10724-k-Mol9-rositsa-kyuchukova-kvm-pri1",
          "datastoreId": "9bdddcd4-57f6-3f1f-b741-7fb743f0a84f",
          "datastoreRole": "Primary",
          "downloadPercent": "100",
          "downloadState": "DOWNLOADED"
        }
      ]
    },
    {
      "account": "system",
      "displaytext": "CentOS 5.5(64-bit) no GUI (KVM)",
      "format": "QCOW2",
      "hypervisor": "KVM",
      "id": "35047d32-fac6-11f0-84c5-1e00b700018d",
      "isfeatured": true,
      "ispublic": true,
      "isready": true,
      "name": "CentOS 5.5(64-bit) no GUI (KVM)",
      "templatetype": "BUILTIN",
      "downloaddetails": [
        {
          "datastore": "NFS://10.0.32.4/acs/secondary/ref-trl-10724-k-Mol9-rositsa-kyuchukova/ref-trl-10724-k-Mol9-rositsa-kyuchukova-sec1",
          "datastoreId": "cf524b6c-0043-4d75-b1f7-19568f8f52a4",
          "datastoreRole": "Image",
          "downloadPercent": "100",
          "downloadState": "DOWNLOADED"
        },
        {
          "datastore": "NFS://10.0.32.4/acs/secondary/ref-trl-10724-k-Mol9-rositsa-kyuchukova/ref-trl-10724-k-Mol9-rositsa-kyuchukova-sec2",
          "datastoreId": "b400311d-2ffa-401d-96c5-5bec35efc741",
          "datastoreRole": "Image",
          "downloadPercent": "100",
          "downloadState": "DOWNLOADED"
        },
        {
          "datastore": "NFS://10.0.32.4/acs/secondary/ref-trl-10724-k-Mol9-rositsa-kyuchukova/ref-trl-10724-k-Mol9-rositsa-kyuchukova-sec3",
          "datastoreId": "4afb6866-1be7-4f34-8067-8864232d8694",
          "datastoreRole": "Image",
          "downloadPercent": "100",
          "downloadState": "DOWNLOADED"
        }
      ]
    }
  ]
}

Key evidence:

  • Both templates show downloadState: "DOWNLOADED" on all 3 secondary storages (sec1, sec2, sec3)
  • This confirms default behavior: without selector, templates sync to ALL secondary storages

Result: PASSED

TC2: Template Registration WITH Secondary Storage Selector

Objective
Verify that template registration with a TEMPLATE type secondary storage selector downloads the template ONLY to the secondary storage specified by the selector, not to all secondary storages.

Test Steps

  1. Enable js.interpretation.enabled setting (encrypted value)
  2. Verify all 4 secondary storage selector APIs are available
  3. Create a TEMPLATE type selector directing templates to sec3
  4. Register a new private template
  5. Verify template downloads ONLY to sec3 (not sec1 or sec2)

Expected Result:
Template should be downloaded ONLY to sec3 as specified by the selector, not to sec1 or sec2.

Actual Result:
Template downloaded only to sec3. The downloaddetails array contains only one entry for sec3 with downloadState: "DOWNLOADED".

Test Evidence:

1. Enable js.interpretation.enabled (encrypted value):

[root@ref-trl-10724-k-Mol9-rositsa-kyuchukova-mgmt1 ~]# java -classpath /usr/share/cloudstack-common/lib/cloudstack-utils.jar com.cloud.utils.crypt.EncryptionCLI -p password -i true
DxMq2qildaSTHKX1jrMhQa6ABjN951WreQZTlA6ajlQ=

[root@ref-trl-10724-k-Mol9-rositsa-kyuchukova-mgmt1 ~]# mysql -u root -p'P@ssword123' cloud -e "UPDATE configuration SET value='DxMq2qildaSTHKX1jrMhQa6ABjN951WreQZTlA6ajlQ=' WHERE name='js.interpretation.enabled';"

[root@ref-trl-10724-k-Mol9-rositsa-kyuchukova-mgmt1 ~]# systemctl restart cloudstack-management
[root@ref-trl-10724-k-Mol9-rositsa-kyuchukova-mgmt1 ~]# sleep 180
[root@ref-trl-10724-k-Mol9-rositsa-kyuchukova-mgmt1 ~]# curl -s "http://localhost:8080/client/api?command=listZones" | head -5
<?xml version="1.0" encoding="UTF-8"?><listzonesresponse cloud-stack-version="4.20.3.0-SNAPSHOT"><errorcode>401</errorcode><errortext>unable to verify user credentials and/or request signature</errortext></listzonesresponse>

2. Verify all 4 selector APIs available:

(localcloud) 🐱 > sync
Discovered 832 APIs
(localcloud) 🐱 > list apis | grep -i "name.*selector"
      "name": "createSecondaryStorageSelector",
      "name": "updateSecondaryStorageSelector",
      "name": "listSecondaryStorageSelectors",
      "name": "removeSecondaryStorageSelector",

3. List secondary storages:

(localcloud) 🐱 > list imagestores filter=id,name
{
  "count": 3,
  "imagestore": [
    {
      "id": "cf524b6c-0043-4d75-b1f7-19568f8f52a4",
      "name": "NFS://10.0.32.4/acs/secondary/ref-trl-10724-k-Mol9-rositsa-kyuchukova/ref-trl-10724-k-Mol9-rositsa-kyuchukova-sec1"
    },
    {
      "id": "b400311d-2ffa-401d-96c5-5bec35efc741",
      "name": "NFS://10.0.32.4/acs/secondary/ref-trl-10724-k-Mol9-rositsa-kyuchukova/ref-trl-10724-k-Mol9-rositsa-kyuchukova-sec2"
    },
    {
      "id": "4afb6866-1be7-4f34-8067-8864232d8694",
      "name": "NFS://10.0.32.4/acs/secondary/ref-trl-10724-k-Mol9-rositsa-kyuchukova/ref-trl-10724-k-Mol9-rositsa-kyuchukova-sec3"
    }
  ]
}

4. Create TEMPLATE type selector directing to sec3:

(localcloud) 🐱 > create secondarystorageselector name="direct-templates-to-sec3" description="directs templates to sec3" zoneid=2b853fbe-39ab-4282-88b5-eca6464db31b heuristicrule="'4afb6866-1be7-4f34-8067-8864232d8694'" type=TEMPLATE
{
  "heuristics": {
    "created": "2026-01-27T08:53:48+0000",
    "description": "directs templates to sec3",
    "heuristicrule": "'4afb6866-1be7-4f34-8067-8864232d8694'",
    "id": "e51b42c0-f500-4bd4-ac57-9b81de66aa50",
    "name": "direct-templates-to-sec3",
    "type": "TEMPLATE",
    "zoneid": "2b853fbe-39ab-4282-88b5-eca6464db31b"
  }
}

5. Verify selector created:

(localcloud) 🐱 > list secondarystorageselectors zoneid=2b853fbe-39ab-4282-88b5-eca6464db31b type=TEMPLATE
{
  "count": 1,
  "heuristics": [
    {
      "created": "2026-01-27T08:53:48+0000",
      "description": "directs templates to sec3",
      "heuristicrule": "'4afb6866-1be7-4f34-8067-8864232d8694'",
      "id": "e51b42c0-f500-4bd4-ac57-9b81de66aa50",
      "name": "direct-templates-to-sec3",
      "type": "TEMPLATE",
      "zoneid": "2b853fbe-39ab-4282-88b5-eca6464db31b"
    }
  ]
}

6. Register private template:

(localcloud) 🐱 > register template name="tc2-private-template" displaytext="TC2 private template for selector test" format=QCOW2 hypervisor=KVM zoneid=2b853fbe-39ab-4282-88b5-eca6464db31b ostypeid=535efec2-fac6-11f0-84c5-1e00b700018d url=http://dl.openvm.eu/cloudstack/macchinina/x86_64/macchinina-kvm.qcow2.bz2 ispublic=false isfeatured=false
{
  "count": 1,
  "template": [
    {
      "account": "admin",
      "arch": "x86_64",
      "bits": 0,
      "created": "2026-01-27T08:54:23+0000",
      "crossZones": false,
      "deployasis": false,
      "details": {},
      "directdownload": false,
      "displaytext": "TC2 private template for selector test",
      "domain": "ROOT",
      "domainid": "34f2d1f8-fac6-11f0-84c5-1e00b700018d",
      "domainpath": "/",
      "downloaddetails": [
        {
          "datastore": "NFS://10.0.32.4/acs/secondary/ref-trl-10724-k-Mol9-rositsa-kyuchukova/ref-trl-10724-k-Mol9-rositsa-kyuchukova-sec3",
          "datastoreId": "4afb6866-1be7-4f34-8067-8864232d8694",
          "datastoreRole": "Image",
          "downloadPercent": "0",
          "downloadState": "NOT_DOWNLOADED"
        }
      ],
      "format": "QCOW2",
      "hasannotations": false,
      "hypervisor": "KVM",
      "id": "7cf94644-fd6e-4854-aaf4-4d4ac7227758",
      "isdynamicallyscalable": false,
      "isextractable": false,
      "isfeatured": false,
      "ispublic": false,
      "isready": false,
      "name": "tc2-private-template",
      "ostypeid": "535efec2-fac6-11f0-84c5-1e00b700018d",
      "ostypename": "CentOS 5 (32-bit)",
      "passwordenabled": false,
      "requireshvm": true,
      "sshkeyenabled": false,
      "status": "",
      "tags": [],
      "templatetype": "USER",
      "url": "http://dl.openvm.eu/cloudstack/macchinina/x86_64/macchinina-kvm.qcow2.bz2",
      "zoneid": "2b853fbe-39ab-4282-88b5-eca6464db31b",
      "zonename": "ref-trl-10724-k-Mol9-rositsa-kyuchukova"
    }
  ]
}

7. Verify template downloaded ONLY to sec3:

(localcloud) 🐱 > list templates name="tc2-private-template" templatefilter=all 
{
  "count": 1,
  "template": [
    {
      "account": "admin",
      "arch": "x86_64",
      "bits": 0,
      "checksum": "027ca55ae2ddcd4752ef32e5b851b8899436e8479b5a48a61b0996afabadcbfae8eac04a467f4d65bd85c1c87557119f7ee27facfdf6c19ae88e0ac9b9ffe612",
      "created": "2026-01-27T08:54:23+0000",
      "crossZones": false,
      "deployasis": false,
      "details": {},
      "directdownload": false,
      "displaytext": "TC2 private template for selector test",
      "domain": "ROOT",
      "domainid": "34f2d1f8-fac6-11f0-84c5-1e00b700018d",
      "domainpath": "/",
      "downloaddetails": [
        {
          "datastore": "NFS://10.0.32.4/acs/secondary/ref-trl-10724-k-Mol9-rositsa-kyuchukova/ref-trl-10724-k-Mol9-rositsa-kyuchukova-sec3",
          "datastoreId": "4afb6866-1be7-4f34-8067-8864232d8694",
          "datastoreRole": "Image",
          "downloadPercent": "100",
          "downloadState": "DOWNLOADED"
        }
      ],
      "format": "QCOW2",
      "hasannotations": false,
      "hypervisor": "KVM",
      "id": "7cf94644-fd6e-4854-aaf4-4d4ac7227758",
      "isdynamicallyscalable": false,
      "isextractable": false,
      "isfeatured": false,
      "ispublic": false,
      "isready": true,
      "name": "tc2-private-template",
      "ostypeid": "535efec2-fac6-11f0-84c5-1e00b700018d",
      "ostypename": "CentOS 5 (32-bit)",
      "passwordenabled": false,
      "physicalsize": 43646976,
      "requireshvm": true,
      "size": 52428800,
      "sshkeyenabled": false,
      "status": "Download Complete",
      "tags": [],
      "templatetype": "USER",
      "url": "http://dl.openvm.eu/cloudstack/macchinina/x86_64/macchinina-kvm.qcow2.bz2",
      "zoneid": "2b853fbe-39ab-4282-88b5-eca6464db31b",
      "zonename": "ref-trl-10724-k-Mol9-rositsa-kyuchukova"
    }
  ]
}

Key evidence:

  • downloaddetails array contains ONLY one entry for sec3
  • downloadState: "DOWNLOADED" and downloadPercent: "100" confirms successful download
  • sec1 and sec2 are NOT present in downloaddetails - selector worked correctly

Result: PASSED

TC3: ISO Registration WITH Secondary Storage Selector

Objective
Verify that ISO registration with an ISO type secondary storage selector downloads the ISO ONLY to the secondary storage specified by the selector, not to all secondary storages.

Test Steps

  1. Ensure js.interpretation.enabled is enabled (from TC2)
  2. Create an ISO type selector directing ISOs to sec2
  3. Register a new private ISO
  4. Verify ISO downloads ONLY to sec2 (not sec1 or sec3)

Expected Result:
ISO should be downloaded ONLY to sec2 as specified by the selector, not to sec1 or sec3.

Actual Result:
ISO downloaded only to sec2. The downloaddetails array contains only one entry for sec2 with downloadState: "DOWNLOADED".

Test Evidence:

1. Create ISO type selector directing to sec2:

(localcloud) 🐱 > create secondarystorageselector name="direct-isos-to-sec2" description="directs ISOs to sec2" zoneid=2b853fbe-39ab-4282-88b5-eca6464db31b heuristicrule="'b400311d-2ffa-401d-96c5-5bec35efc741'" type=ISO
{
  "heuristics": {
    "created": "2026-01-27T08:56:24+0000",
    "description": "directs ISOs to sec2",
    "heuristicrule": "'b400311d-2ffa-401d-96c5-5bec35efc741'",
    "id": "a367dedc-b33e-457b-abc8-57adba905148",
    "name": "direct-isos-to-sec2",
    "type": "ISO",
    "zoneid": "2b853fbe-39ab-4282-88b5-eca6464db31b"
  }
}

2. Verify selector created:

(localcloud) 🐱 > list secondarystorageselectors zoneid=2b853fbe-39ab-4282-88b5-eca6464db31b type=ISO
{
  "count": 1,
  "heuristics": [
    {
      "created": "2026-01-27T08:56:24+0000",
      "description": "directs ISOs to sec2",
      "heuristicrule": "'b400311d-2ffa-401d-96c5-5bec35efc741'",
      "id": "a367dedc-b33e-457b-abc8-57adba905148",
      "name": "direct-isos-to-sec2",
      "type": "ISO",
      "zoneid": "2b853fbe-39ab-4282-88b5-eca6464db31b"
    }
  ]
}

3. Register private ISO:

(localcloud) 🐱 > register iso name="tc3-private-iso" displaytext="TC3 private ISO for selector test" zoneid=2b853fbe-39ab-4282-88b5-eca6464db31b ostypeid=535efec2-fac6-11f0-84c5-1e00b700018d url=http://10.0.3.122/vladitemplates/iso/debian-live-11.0.0-amd64-standard.iso ispublic=false isfeatured=false
{
  "count": 1,
  "iso": [
    {
      "account": "admin",
      "arch": "x86_64",
      "bits": 64,
      "bootable": true,
      "created": "2026-01-27T08:57:21+0000",
      "crossZones": false,
      "directdownload": false,
      "displaytext": "TC3 private ISO for selector test",
      "domain": "ROOT",
      "domainid": "34f2d1f8-fac6-11f0-84c5-1e00b700018d",
      "domainpath": "/",
      "downloaddetails": [
        {
          "datastore": "NFS://10.0.32.4/acs/secondary/ref-trl-10724-k-Mol9-rositsa-kyuchukova/ref-trl-10724-k-Mol9-rositsa-kyuchukova-sec2",
          "downloadPercent": "0",
          "downloadState": "NOT_DOWNLOADED"
        }
      ],
      "format": "ISO",
      "hasannotations": false,
      "id": "fb60169a-2de6-46ac-b871-01b69ca225be",
      "isdynamicallyscalable": false,
      "isextractable": false,
      "isfeatured": false,
      "ispublic": false,
      "isready": false,
      "name": "tc3-private-iso",
      "ostypeid": "535efec2-fac6-11f0-84c5-1e00b700018d",
      "ostypename": "CentOS 5 (32-bit)",
      "passwordenabled": false,
      "status": "",
      "tags": [],
      "url": "http://10.0.3.122/vladitemplates/iso/debian-live-11.0.0-amd64-standard.iso",
      "zoneid": "2b853fbe-39ab-4282-88b5-eca6464db31b",
      "zonename": "ref-trl-10724-k-Mol9-rositsa-kyuchukova"
    }
  ]
}

4. Verify ISO downloaded ONLY to sec2:

(localcloud) 🐱 > list isos name="tc3-private-iso" isofilter=all
{
  "count": 1,
  "iso": [
    {
      "account": "admin",
      "arch": "x86_64",
      "bits": 64,
      "bootable": true,
      "checksum": "93348c6bc0979d8a9ffd056f6e7b53e95fd78ea651af4e5e495d3a5da267c411b7a0be4d2b4b9345800013eda3526452be8a513df2881b5ee474ff89221bae6b",
      "created": "2026-01-27T08:57:21+0000",
      "crossZones": false,
      "directdownload": false,
      "displaytext": "TC3 private ISO for selector test",
      "domain": "ROOT",
      "domainid": "34f2d1f8-fac6-11f0-84c5-1e00b700018d",
      "domainpath": "/",
      "downloaddetails": [
        {
          "datastore": "NFS://10.0.32.4/acs/secondary/ref-trl-10724-k-Mol9-rositsa-kyuchukova/ref-trl-10724-k-Mol9-rositsa-kyuchukova-sec2",
          "datastoreId": "b400311d-2ffa-401d-96c5-5bec35efc741",
          "datastoreRole": "Image",
          "downloadPercent": "100",
          "downloadState": "DOWNLOADED"
        }
      ],
      "format": "ISO",
      "hasannotations": false,
      "id": "fb60169a-2de6-46ac-b871-01b69ca225be",
      "isdynamicallyscalable": false,
      "isextractable": false,
      "isfeatured": false,
      "ispublic": false,
      "isready": true,
      "name": "tc3-private-iso",
      "ostypeid": "535efec2-fac6-11f0-84c5-1e00b700018d",
      "ostypename": "CentOS 5 (32-bit)",
      "passwordenabled": false,
      "physicalsize": 946864128,
      "size": 946864128,
      "status": "Successfully Installed",
      "tags": [],
      "url": "http://10.0.3.122/vladitemplates/iso/debian-live-11.0.0-amd64-standard.iso",
      "zoneid": "2b853fbe-39ab-4282-88b5-eca6464db31b",
      "zonename": "ref-trl-10724-k-Mol9-rositsa-kyuchukova"
    }
  ]
}

Key evidence:

  • downloaddetails array contains ONLY one entry for sec2
  • downloadState: "DOWNLOADED" and downloadPercent: "100" confirms successful download
  • sec1 and sec3 are NOT present in downloaddetails - ISO selector worked correctly

Result: PASSED

@borisstoyanov borisstoyanov merged commit 0458c53 into apache:4.20 Jan 27, 2026
25 of 26 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants