stag7824 opened a new pull request, #14096:
URL: https://github.com/apache/cloudstack/pull/14096

   ### Description
   
   Fixes #14013
   
   A backup repository whose mount options carry stray whitespace, for example 
`vers=4.1 `,
   backs up fine but fails to restore:
   
       mount.nfs: an incorrect mount option was specified for
       /usr/share/cloudstack-agent/tmp/csbackup...
   
   `LibvirtRestoreBackupCommandWrapper.mountBackupDirectory` builds the mount 
command as an argv
   list and runs it without a shell:
   
       if (StringUtils.isNotBlank(mountOptions)) {
           mountCmd.add("-o");
           mountCmd.add(mountOptions);
       }
       Script.executeCommand(mountCmd.toArray(new String[0]));
   
   `Script.executeCommand(String...)` hands each element to `ProcessBuilder` 
verbatim, so mount
   receives the literal option list `vers=4.1 `. libmount splits that list on 
commas only, so the
   blank stays glued to the last option and the kernel rejects it as part of 
the option value.
   
   Backup, delete and stats do not hit this today because they pass the options 
to `nasbackup.sh`,
   which expands them unquoted:
   
       mount -t ${NAS_TYPE} ${NAS_ADDRESS} ${mount_point} $([[ ! -z 
"${MOUNT_OPTS}" ]] && echo -o ${MOUNT_OPTS})
   
   Shell word splitting drops the blank there, which is why restore is the only 
operation that
   fails: it is the only one of the four that builds the mount command in Java.
   
   Fixed by normalising the option list before it is used. Each comma-separated 
option is trimmed
   and empty ones are dropped. Only the whitespace around the delimiters is 
removed; the option
   text itself is passed through unchanged, since deciding whether an option is 
well formed
   belongs to the API layer rather than the agent.
   
   The normalisation happens **before** the cifs branch appends `,nobrl`. 
Trimming afterwards
   would leave `vers=3.0 ,nobrl`, moving the blank into the middle of the list 
where libmount
   cannot ignore it either.
   
   #### Relationship to #14009
   
   #14009 stops this class of value from being stored: it rejects whitespace 
per option in
   `AddBackupRepositoryCmd` / `UpdateBackupRepositoryCmd`, and it quotes 
`"${MOUNT_OPTS}"` in
   `nasbackup.sh`. That is the right place for validation and I have 
deliberately not duplicated
   any of it here — the two changes touch no common files.
   
   They are complementary rather than alternatives, because #14009 validates on 
the way in and
   cannot clean rows that are already in the database. On an existing 
deployment such as the one
   in #14013, the stored `vers=4.1 ` survives, and once `MOUNT_OPTS` is quoted 
it will break the
   script-based operations too, not just restore. Normalising at the point of 
use fixes those
   repositories without a schema migration.
   
   ### Types of changes
   
   - [x] Bug fix (non-breaking change which fixes an issue)
   
   ### Feature/Enhancement Scale or Bug Severity
   
   #### Bug Severity
   
   - [x] Minor
   
   ### How Has This Been Tested?
   
   Added seven unit tests to `LibvirtRestoreBackupCommandWrapperTest` that 
invoke
   `mountBackupDirectory` and assert on the exact `-o` argument handed to 
`mount`:
   
   | mount options | repo type | `-o` argument | fails without the fix |
   | --- | --- | --- | --- |
   | `vers=4.1 ` | nfs | `vers=4.1` | yes |
   | ` vers=4.1 , soft ` | nfs | `vers=4.1,soft` | yes |
   | `vers=4.1,,soft` | nfs | `vers=4.1,soft` | yes |
   | `vers=3.0 ` | cifs | `vers=3.0,nobrl` | yes |
   | `username=some user` | cifs | `username=some user,nobrl` | no |
   | `   ` | nfs | no `-o` at all | no |
   | `   ` | cifs | `nobrl` | no |
   
   The last three already hold today. They are there to pin behaviour the fix 
must not change:
   that trimming is scoped to the delimiters rather than stripping whitespace 
throughout, and
   that an all-whitespace value still collapses to no options at all (or to 
bare `nobrl` for
   cifs) instead of becoming an empty option.
   
       mvn test -pl plugins/hypervisors/kvm 
-Dtest=LibvirtRestoreBackupCommandWrapperTest
       Tests run: 24, Failures: 0, Errors: 0, Skipped: 0
   
   Removing just the `normalizeMountOptions` call and rerunning gives 4 
failures, each showing
   the blank that mount rejects:
   
       expected:<vers=4.1[]>        but was:<vers=4.1[ ]>
       expected:<[vers=4.1,soft]>   but was:<[ vers=4.1 , soft ]>
       expected:<vers=4.1,[]soft>   but was:<vers=4.1,[,]soft>
       expected:<vers=3.0[],nobrl>  but was:<vers=3.0[ ],nobrl>
   
   The last of those is the ordering point: the blank lands in the middle of 
the list once
   `nobrl` is appended after it.
   
   I do not have a KVM zone with a NAS repository available, so this is 
unit-level only; the
   mount argument that the kernel rejects is asserted directly rather than end 
to end.
   
   The same construction is present on 4.20. I targeted 4.22 because that is 
the version the
   issue is reported against, but happy to retarget if it should land on 4.20 
first.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to