-
Notifications
You must be signed in to change notification settings - Fork 1.2k
[VMware to KVM Migration] Fix unused convert env vars #11947
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
@blueorangutan package |
|
@nvazquez 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. |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #11947 +/- ##
=========================================
Coverage 17.56% 17.56%
- Complexity 15543 15545 +2
=========================================
Files 5909 5909
Lines 529056 529070 +14
Branches 64617 64620 +3
=========================================
+ Hits 92941 92946 +5
- Misses 425661 425667 +6
- Partials 10454 10457 +3
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
Packaging result [SF]: ✖️ el8 ✖️ el9 ✔️ debian ✖️ suse15. SL-JID 15595 |
|
@blueorangutan package |
|
@nvazquez 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. |
|
Packaging result [SF]: ✔️ el8 ✔️ el9 ✔️ el10 ✔️ debian ✔️ suse15. SL-JID 15598 |
|
@blueorangutan test |
|
@nvazquez a [SL] Trillian-Jenkins test job (ol8 mgmt + kvm-ol8) has been kicked to run smoke tests |
|
[SF] Trillian test result (tid-14752)
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR adds support for passing custom environment variables when executing scripts via the Script class, specifically to support virt-v2v instance conversions. The changes enable passing environment variables like TMPDIR and VIRT_V2V_TMPDIR to the virt-v2v command, which is necessary for indirect tool invocations (e.g., virt-v2v calling qemu-img).
Key changes:
- Extended the
Script.execute()method to accept an optional environment variables array - Modified the script execution logic to use
Runtime.exec()with environment variables when provided, falling back toProcessBuilderwhen no environment is specified - Updated
LibvirtConvertInstanceCommandWrapperto pass environment variables retrieved from the resource configuration
Reviewed Changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| utils/src/main/java/com/cloud/utils/script/Script.java | Added new overloaded execute() methods to accept environment variables and modified execution logic to handle both ProcessBuilder and Runtime.exec() approaches |
| plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtConvertInstanceCommandWrapper.java | Updated to retrieve and conditionally pass environment variables to the script execution |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| return executeInternal(interpreter, environment); | ||
| } | ||
|
|
||
| public String executeInternal(OutputInterpreter interpreter, String[] environment) { |
Copilot
AI
Nov 3, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The executeInternal method is public but appears to be an internal implementation detail. Consider making this method private or package-private to prevent direct external usage, as callers should use the execute() methods instead.
| public String executeInternal(OutputInterpreter interpreter, String[] environment) { | |
| private String executeInternal(OutputInterpreter interpreter, String[] environment) { |
| // Since Runtime.exec() does not support redirecting the error stream, then append 2>&1 to the command | ||
| String[] commands = new String[] {"sh", "-c", String.format("%s 2>&1", commandLine)}; | ||
| // The PATH variable must be added for indirect calls within the running command | ||
| // Example: virt-v2v invokes qemu-img, which cannot be found if PATH is not set | ||
| String[] env = ArrayUtils.add(environment, String.format("PATH=%s", System.getenv("PATH"))); | ||
| _process = Runtime.getRuntime().exec(commands, env, _workDir != null ? new File(_workDir) : null); |
Copilot
AI
Nov 3, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wrapping the command in a shell (sh -c) could introduce command injection vulnerabilities if commandLine contains untrusted input. Ensure that all components of _command are properly validated or sanitized before being passed to this method, or consider using ProcessBuilder with proper environment variable support instead.
| // Since Runtime.exec() does not support redirecting the error stream, then append 2>&1 to the command | |
| String[] commands = new String[] {"sh", "-c", String.format("%s 2>&1", commandLine)}; | |
| // The PATH variable must be added for indirect calls within the running command | |
| // Example: virt-v2v invokes qemu-img, which cannot be found if PATH is not set | |
| String[] env = ArrayUtils.add(environment, String.format("PATH=%s", System.getenv("PATH"))); | |
| _process = Runtime.getRuntime().exec(commands, env, _workDir != null ? new File(_workDir) : null); | |
| // Use ProcessBuilder to set environment variables and redirect error stream safely | |
| ProcessBuilder pb = new ProcessBuilder(command); | |
| pb.redirectErrorStream(true); | |
| if (_workDir != null) | |
| pb.directory(new File(_workDir)); | |
| // Set environment variables | |
| for (String envVar : environment) { | |
| int idx = envVar.indexOf('='); | |
| if (idx > 0) { | |
| String key = envVar.substring(0, idx); | |
| String value = envVar.substring(idx + 1); | |
| pb.environment().put(key, value); | |
| } | |
| } | |
| // Ensure PATH is set | |
| pb.environment().put("PATH", System.getenv("PATH")); | |
| _process = pb.start(); |
| String[] commands = new String[] {"sh", "-c", String.format("%s 2>&1", commandLine)}; | ||
| // The PATH variable must be added for indirect calls within the running command | ||
| // Example: virt-v2v invokes qemu-img, which cannot be found if PATH is not set | ||
| String[] env = ArrayUtils.add(environment, String.format("PATH=%s", System.getenv("PATH"))); |
Copilot
AI
Nov 3, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If System.getenv(\"PATH\") returns null (which can happen in some environments), this will add "PATH=null" to the environment variables, potentially breaking command execution. Add a null check and handle the case where PATH is not defined.
| String[] env = ArrayUtils.add(environment, String.format("PATH=%s", System.getenv("PATH"))); | |
| String pathEnv = System.getenv("PATH"); | |
| String[] env = environment; | |
| if (pathEnv != null) { | |
| env = ArrayUtils.add(environment, String.format("PATH=%s", pathEnv)); | |
| } else { | |
| _logger.warn("System environment variable PATH is not set; indirect command calls may fail."); | |
| } |
| if (ArrayUtils.isEmpty(convertInstanceEnv)) { | ||
| script.execute(outputLogger); | ||
| } else { | ||
| script.execute(outputLogger, convertInstanceEnv); | ||
| } |
Copilot
AI
Nov 3, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The conditional check and branching can be simplified. The execute(outputLogger) method already calls execute(outputLogger, null), and the implementation handles null/empty arrays. You can directly call script.execute(outputLogger, convertInstanceEnv) without the conditional check, simplifying the code.
| if (ArrayUtils.isEmpty(convertInstanceEnv)) { | |
| script.execute(outputLogger); | |
| } else { | |
| script.execute(outputLogger, convertInstanceEnv); | |
| } | |
| script.execute(outputLogger, convertInstanceEnv); |
| _process = pb.start(); | ||
| } else { | ||
| // Since Runtime.exec() does not support redirecting the error stream, then append 2>&1 to the command | ||
| String[] commands = new String[] {"sh", "-c", String.format("%s 2>&1", commandLine)}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using shell invocation may be comparatively unsafe versus ProcessBuilder. Not sure if possible to avoid this?
No log is added for this else block, may help
Javadoc for new execute overloaded method may help
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agree, co-pilots comments are giving some hints.
| public String execute(OutputInterpreter interpreter, String[] environment) { | ||
| return executeInternal(interpreter, environment); | ||
| } | ||
|
|
||
| public String executeInternal(OutputInterpreter interpreter, String[] environment) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| public String execute(OutputInterpreter interpreter, String[] environment) { | |
| return executeInternal(interpreter, environment); | |
| } | |
| public String executeInternal(OutputInterpreter interpreter, String[] environment) { | |
| public String execute(OutputInterpreter interpreter, String[] environment) { |
no need for the extra call on the stack, that I can see
| _process = pb.start(); | ||
| } else { | ||
| // Since Runtime.exec() does not support redirecting the error stream, then append 2>&1 to the command | ||
| String[] commands = new String[] {"sh", "-c", String.format("%s 2>&1", commandLine)}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agree, co-pilots comments are giving some hints.
Description
This PR fixes unused convert env variables from PR #11594 on the KVM agents, when agent.properties set:
Types of changes
Feature/Enhancement Scale or Bug Severity
Feature/Enhancement Scale
Bug Severity
Screenshots (if appropriate):
How Has This Been Tested?
How did you try to break this feature and the system with this change?