-
Notifications
You must be signed in to change notification settings - Fork 37
feat: error out on qcow2 block devices #300
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
Reviewer's Guide by SourceryThis pull request adds validation to detect qcow2 block devices used with VirtioBlk and returns an error if found, as vfkit does not support this format. It also includes tests for the new validation logic. No diagrams generated as the changes look simple and do not need a visual representation. File-Level Changes
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here.
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
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.
Hey @vyasgun - I've reviewed your changes - here's some feedback:
Overall Comments:
- Consider defining the qcow2 magic number
"QFI\xfb"
as a constant for better readability and maintainability. - The type assertion for
VirtioBlk
can be combined with theswitch
statement (e.g.,case dev := device.(*VirtioBlk):
) for improved conciseness.
Here's what I looked at during the review
- 🟢 General issues: all looks good
- 🟢 Security: all looks good
- 🟢 Testing: all looks good
- 🟡 Complexity: 1 issue found
- 🟢 Documentation: all looks good
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
pkg/config/config.go
Outdated
@@ -250,6 +250,32 @@ func (vm *VirtualMachine) AddIgnitionFileFromCmdLine(cmdlineOpts string) error { | |||
return nil | |||
} | |||
|
|||
func (vm *VirtualMachine) ValidBlkDevices() error { |
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.
issue (complexity): Consider using a type switch with an assignment and moving the file validation logic into its own helper function to improve code structure.
Try using a type switch with an assignment and move the file‐validation logic into its own helper. For example:
func (vm *VirtualMachine) ValidBlkDevices() error {
for _, device := range vm.Devices {
switch dev := device.(type) {
case *VirtioBlk:
if dev.ImagePath == "" {
continue
}
if err := validateBlkDevice(dev.ImagePath); err != nil {
return err
}
}
}
return nil
}
func validateBlkDevice(imgPath string) error {
file, err := os.Open(imgPath)
if err != nil {
return fmt.Errorf("failed to open file %s: %v", imgPath, err)
}
defer file.Close()
header := make([]byte, 4)
if _, err := file.Read(header); err != nil {
return fmt.Errorf("failed to read the header of file %s: %v", imgPath, err)
}
if string(header) == "QFI\xfb" {
return fmt.Errorf("vfkit does not support qcow2 block devices")
}
return nil
}
This reduces redundant assertions and flattens the nested ifs, while keeping functionality intact.
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.
This is a good advice. Even better is to add a Validate() interface to devices so we can keep device related code in the same place.
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.
That's a great point, @nirs! Adding a Validate()
method to a device interface would definitely be a cleaner and more scalable solution in the long run. It keeps the validation logic tightly coupled with the device implementation itself.
My suggestion aimed for a more localized improvement within the existing structure, but your interface-based approach is certainly preferable for future maintainability and extensibility. If you have the bandwidth to implement that, it would be an excellent enhancement!
pkg/config/config.go
Outdated
@@ -250,6 +250,32 @@ func (vm *VirtualMachine) AddIgnitionFileFromCmdLine(cmdlineOpts string) error { | |||
return nil | |||
} | |||
|
|||
func (vm *VirtualMachine) ValidBlkDevices() error { |
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.
This is a good advice. Even better is to add a Validate() interface to devices so we can keep device related code in the same place.
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.
Can you split this PR in at least 2 commits, one adding the Validate
method to the VirtioDevice
interface (+ValidateDevices), and a second commit adding the qcow2 check? I’d even move ValidateDevices
to its own commit so that each commit does a single thing.
pkg/config/config.go
Outdated
@@ -250,6 +250,15 @@ func (vm *VirtualMachine) AddIgnitionFileFromCmdLine(cmdlineOpts string) error { | |||
return nil | |||
} | |||
|
|||
func (vm *VirtualMachine) ValidateDevices() error { | |||
for _, device := range vm.Devices { | |||
if err := device.Validate(); err != nil { |
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.
There are a number of calls to Validate
in virtio.go, are they made redundant by this new method? or do we need both?
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.
I think either the Validate() calls at the end of FromOptions
in some places can be removed or we can add dev.Validate to the end of all FromOptions
. I have removed the redundant occurrences in this iteration.
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.
One concern I have with this is that this weakens the FromOptions
and AddDevicesFromCommandLine
APIs, which are kind of public: I expect other go programs to be using github.com/crc-org/pkg/config
, even if I’m not sure these specific methods will be widely used.
Before this change, they were returning an error when the config does not validate, after this change, all users of the API need to remember to do the validation themselves or they could get invalid device configuration.
I would keep the validation at the end of each FromOptions
, or add the validation to either AddDevicesFromCmdLine
or deviceFromCmdLine
if we want to avoid the duplication.
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.
Ah yes, that makes sense. I will add validate back to FromOptions
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.
Looks much nicer like this!
@@ -371,7 +378,7 @@ func (dev *VirtioGPU) FromOptions(options []option) error { | |||
dev.Height = defaultVirtioGPUResolutionHeight | |||
} | |||
|
|||
return dev.validate() | |||
return dev.Validate() |
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.
This looks like the right way to validate - after creating from options. Maybe we don't need a public Validate() but add the missing validation in VirtioBlk?
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.
I wrote a public method because it is more conventional and can be used to validate devices from other packages if needed. I can make it private if it's more suitable for this usecase.
a914f7f
to
38b68ea
Compare
pkg/config/config.go
Outdated
@@ -250,6 +250,15 @@ func (vm *VirtualMachine) AddIgnitionFileFromCmdLine(cmdlineOpts string) error { | |||
return nil | |||
} | |||
|
|||
func (vm *VirtualMachine) ValidateDevices() error { | |||
for _, device := range vm.Devices { | |||
if err := device.Validate(); err != nil { |
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.
One concern I have with this is that this weakens the FromOptions
and AddDevicesFromCommandLine
APIs, which are kind of public: I expect other go programs to be using github.com/crc-org/pkg/config
, even if I’m not sure these specific methods will be widely used.
Before this change, they were returning an error when the config does not validate, after this change, all users of the API need to remember to do the validation themselves or they could get invalid device configuration.
I would keep the validation at the end of each FromOptions
, or add the validation to either AddDevicesFromCmdLine
or deviceFromCmdLine
if we want to avoid the duplication.
1f49554
to
49c7338
Compare
This method allows each VirtioDevice implementation to perform its own validation logic before being attached to the VM. It helps catch misconfigurations early and ensures that invalid devices don't cause runtime errors during VM startup.
Adds a Validate() implementation to the VirtioBlk device that inspects the disk image header. If the image is in qcow2 format, validation fails with an appropriate error.
This function runs validation on all devices added via CmdLine, ensuring they are properly configured before VM startup. It eliminates redundant individual calls to dev.Validate(), centralizing validation logic. Also includes a test case to verify ValidateDevices behavior.
Adds qemu-utils (for qemu-img) to the CI environment to support new tests that validate block devices and reject unsupported qemu image formats.
/retest |
Adding |
Summary by Sourcery
Add validation to reject qcow2 formatted block device images.
Bug Fixes:
Tests: