Skip to content

kubernetes: clean up temporary provisioning scripts on the management server#13592

Open
nikolauseppinger wants to merge 1 commit into
apache:mainfrom
nikolauseppinger:kubernetes/cleanup-temp-provisioning-scripts
Open

kubernetes: clean up temporary provisioning scripts on the management server#13592
nikolauseppinger wants to merge 1 commit into
apache:mainfrom
nikolauseppinger:kubernetes/cleanup-temp-provisioning-scripts

Conversation

@nikolauseppinger

@nikolauseppinger nikolauseppinger commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Description

The CKS action workers copy provisioning scripts to the cluster nodes via
retrieveScriptFiles() + copyScripts() / copyScriptFile(). Each script is
written to a local temp file with File.createTempFile(filename, ".sh") in
retrieveScriptFile(), but that local copy on the management server is never
deleted
after it has been SCP'd to the node.

As a result, every cluster deploy, provider/CSI deploy, autoscale enable, PV
cleanup and Kubernetes upgrade leaks one *.sh file per script into the
management server's temp directory, growing without bound over the cluster
lifetime:

-rw-r--r--. 1 cloud cloud 3230 ... autoscale-kube-cluster10402639792822688389.sh
-rw-r--r--. 1 cloud cloud 7197 ... delete-pv-reclaimpolicy-delete10664788910304997694.sh
-rw-r--r--. 1 cloud cloud 2303 ... deploy-cloudstack-secret10522058804386657778.sh
-rw-r--r--. 1 cloud cloud 1811 ... deploy-csi-driver1118819744193036791.sh
-rw-r--r--. 1 cloud cloud 1472 ... deploy-provider10072339396849174814.sh
-rw-r--r--. 1 cloud cloud 4971 ... upgrade-kubernetes.sh10982436999748062804.sh
... (dozens more, one set per CKS action)

This PR adds cleanupScriptFiles() / deleteScriptFileQuietly() to the base
KubernetesClusterActionWorker and invokes it in a finally block around
every copy site:

  • KubernetesClusterActionWorker.deployProvider()
  • KubernetesClusterActionWorker.deployCsiDriver()
  • KubernetesClusterResourceModifierActionWorker.autoscaleCluster()
  • KubernetesClusterResourceModifierActionWorker.deletePVsWithReclaimPolicyDelete()
  • KubernetesClusterUpgradeWorker (overrides cleanupScriptFiles() to also remove
    its upgrade-kubernetes.sh temp file, cleaned up after the per-node upgrade loop
    completes since the same file is reused across nodes)

There is no functional change to the provisioning itself: the scripts are still
written, copied and executed exactly as before; only the leftover local copies
on the management server are removed once they have been transferred.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)

Bug Severity

  • Minor

Observed on a CloudStack 4.22.1 management server running CKS clusters; the code
path is unchanged on main.

… server

The CKS action workers copy provisioning scripts (deploy-cloudstack-secret,
deploy-provider, deploy-csi-driver, delete-pv-reclaimpolicy-delete,
autoscale-kube-cluster and upgrade-kubernetes.sh) to the cluster nodes via
retrieveScriptFiles() + copyScripts()/copyScriptFile(). Each script is written
to a local temp file via File.createTempFile(), but that local copy is never
deleted after it has been SCP'd to the node.

As a result every cluster deploy, provider/CSI deploy, autoscale enable, PV
cleanup and Kubernetes upgrade leaks one *.sh file per script into the
management server's temp directory, growing without bound over the cluster
lifetime. On a long-running management server this accumulates to hundreds of
stale scripts in /tmp.

This adds cleanupScriptFiles()/deleteScriptFileQuietly() to the base action
worker and invokes it in a finally block around every copy site
(deployProvider, deployCsiDriver, autoscaleCluster, deletePVsWithReclaimPolicyDelete
and the upgrade worker), so the local temp copies are removed once they have
been transferred to the node. The upgrade worker additionally removes its
upgrade-kubernetes.sh temp file after the node loop completes.

No functional change to the provisioning itself: the scripts are still written,
copied and executed exactly as before; only the leftover local copies are
deleted.

Covered by new unit tests for cleanupScriptFiles()/deleteScriptFileQuietly()
(temp files deleted, null/missing files handled without throwing).
@codecov

codecov Bot commented Jul 14, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 23.07692% with 30 lines in your changes missing coverage. Please review.
✅ Project coverage is 19.47%. Comparing base (a503a52) to head (9f72e75).
⚠️ Report is 20 commits behind head on main.

Files with missing lines Patch % Lines
...KubernetesClusterResourceModifierActionWorker.java 0.00% 15 Missing ⚠️
...r/actionworkers/KubernetesClusterActionWorker.java 52.94% 7 Missing and 1 partial ⚠️
.../actionworkers/KubernetesClusterUpgradeWorker.java 0.00% 7 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff            @@
##               main   #13592   +/-   ##
=========================================
  Coverage     19.47%   19.47%           
- Complexity    19351    19355    +4     
=========================================
  Files          6296     6296           
  Lines        568368   568394   +26     
  Branches      69622    69622           
=========================================
+ Hits         110673   110717   +44     
+ Misses       445618   445597   -21     
- Partials      12077    12080    +3     
Flag Coverage Δ
uitests 3.44% <ø> (ø)
unittests 20.74% <23.07%> (+<0.01%) ⬆️

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

☔ View full report in Codecov by Harness.
📢 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.

@shwstppr

Copy link
Copy Markdown
Contributor

@blueorangutan package

@blueorangutan

Copy link
Copy Markdown

@shwstppr a [SL] Jenkins job has been kicked to build packages. It will be bundled with no SystemVM templates. I'll keep you posted as I make progress.

@blueorangutan

Copy link
Copy Markdown

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

@DaanHoogland

Copy link
Copy Markdown
Contributor

@blueorangutan test

@blueorangutan

Copy link
Copy Markdown

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

}

@Override
protected void cleanupScriptFiles() {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Doesn't this delete upgradeScriptFile too early? deployProvider() runs per node in the loop and calls cleanupScriptFiles() in its own finally, and since this is an UpgradeWorker, that hits this override and deletes upgradeScriptFile before runInstallScriptOnVM() (next line) SCPs it. Could this break the upgrade the first time a node needs the provider re-deployed?

deleteScriptFileQuietly(autoscaleScriptFile);
}

protected void deleteScriptFileQuietly(File file) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Should the field be set to null after deleting? Right now it still points to a file that no longer exists. If it's used again before retrieveScriptFiles() runs, it could silently try to work with a deleted file.

logMessage(Level.INFO, "Provider files missing. Adding them now", null);
retrieveScriptFiles();
copyScripts(publicIpAddress, sshPort);
try {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This same try { copyScripts(...) } finally { cleanupScriptFiles(); } block shows up 3 times (here, deployCsiDriver(), and autoscaleCluster()). Could this be a small shared helper, like copyScriptsWithCleanup(nodeAddress, sshPort), to avoid repeating it?

* once they have been copied to the cluster node(s). Without this, every deploy/autoscale/PV-cleanup
* action leaks a *.sh file in the management server's tmp directory.
*/
protected void cleanupScriptFiles() {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Nit: could this loop over a list of the 5 fields instead of calling deleteScriptFileQuietly 5 times by hand? Would be one line instead of five, and less to update if a new script field gets added later.


@Test
public void testCleanupScriptFilesDeletesAllTempFiles() throws Exception {
actionWorker.deploySecretsScriptFile = File.createTempFile("deploy-cloudstack-secret", ".sh");

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Nit: these strings duplicate actionWorker.deploySecretsScriptFilename and friends. Could reuse those constants instead?

@blueorangutan

Copy link
Copy Markdown

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

Test Result Time (s) Test File
test_04_dhcp_dns_userdata Error 10.89 test_network_extension_namespace.py
test_05_isolated_network_full_lifecycle Failure 276.49 test_network_extension_namespace.py
test_06_vpc_multi_tier_and_restart Failure 310.85 test_network_extension_namespace.py
test_07_vpc_network_acl Failure 307.50 test_network_extension_namespace.py
test_08_custom_action_policy_based_routing Error 14.10 test_network_extension_namespace.py
test_09_vpc_source_nat_ip_update Error 19.84 test_network_extension_namespace.py
test_10_vpc_custom_action_policy_based_routing Error 12.96 test_network_extension_namespace.py
test_11_ipv6_dualstack_isolated_network Error 9.84 test_network_extension_namespace.py
test_03_network_operations_on_created_vm_of_otheruser Error 3.06 test_network_permissions.py
test_03_network_operations_on_created_vm_of_otheruser Error 3.06 test_network_permissions.py
test_04_deploy_vm_for_other_user_and_test_vm_operations Failure 2.08 test_network_permissions.py
ContextSuite context=TestNetworkPermissions>:teardown Error 1.10 test_network_permissions.py
test_reboot_router Error 9.59 test_network.py
test_releaseIP Error 8.99 test_network.py
test_releaseIP_using_IP Error 9.61 test_network.py
ContextSuite context=TestRouterRules>:setup Error 18.94 test_network.py
test_01_deployVMInSharedNetwork Failure 5.81 test_network.py
test_02_verifyRouterIpAfterNetworkRestart Failure 5.62 test_network.py
test_03_destroySharedNetwork Failure 2.23 test_network.py
ContextSuite context=TestSharedNetwork>:teardown Error 3.99 test_network.py
ContextSuite context=TestSharedNetworkWithConfigDrive>:setup Error 1524.00 test_network.py
ContextSuite context=TestNonStrictAffinityGroups>:setup Error 0.00 test_nonstrict_affinity_group.py
test_01_add_primary_storage_disabled_host Error 37.43 test_primary_storage.py
test_01_primary_storage_nfs Error 0.24 test_primary_storage.py
ContextSuite context=TestStorageTags>:setup Error 0.41 test_primary_storage.py
test_01_primary_storage_scope_change Error 0.15 test_primary_storage_scope.py
test_03_vpc_privategw_restart_vpc_cleanup Error 278.93 test_privategw_acl.py
test_04_rvpc_privategw_static_routes Failure 12.53 test_privategw_acl.py
ContextSuite context=TestRAMCPUResourceAccounting>:setup Error 0.00 test_resource_accounting.py
test_router_dhcphosts Failure 22.49 test_router_dhcphosts.py
ContextSuite context=TestRouterDnsService>:setup Error 0.00 test_router_dnsservice.py
test_01_vpc_site2site_vpn_multiple_options Failure 307.38 test_vpc_vpn.py

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.

5 participants