@@ -247,27 +247,8 @@ pub fn clone_from_base(
247
247
) ;
248
248
249
249
// Get the virtual size of the base disk to use for the new volume
250
- let qemu_img_output = std:: process:: Command :: new ( "qemu-img" )
251
- . args ( & [ "info" , "--output=json" , base_disk_path. as_str ( ) ] )
252
- . output ( )
253
- . with_context ( || format ! ( "Failed to get base disk info: {:?}" , base_disk_path) ) ?;
254
-
255
- if !qemu_img_output. status . success ( ) {
256
- let stderr = String :: from_utf8 ( qemu_img_output. stderr )
257
- . with_context ( || "Invalid UTF-8 in qemu-img stderr" ) ?;
258
- return Err ( color_eyre:: eyre:: eyre!(
259
- "Failed to query base disk size: {}" ,
260
- stderr
261
- ) ) ;
262
- }
263
-
264
- // Parse JSON directly from bytes
265
- let info: serde_json:: Value = serde_json:: from_slice ( & qemu_img_output. stdout )
266
- . with_context ( || "Failed to parse qemu-img info JSON" ) ?;
267
-
268
- let virtual_size = info[ "virtual-size" ]
269
- . as_u64 ( )
270
- . ok_or_else ( || color_eyre:: eyre:: eyre!( "Missing virtual-size in qemu-img output" ) ) ?;
250
+ let info = crate :: qemu_img:: info ( base_disk_path) ?;
251
+ let virtual_size = info. virtual_size ;
271
252
272
253
// Create volume with backing file using vol-create-as
273
254
// This creates a qcow2 image with the base disk as backing file (proper CoW)
@@ -448,33 +429,27 @@ fn count_base_disk_references(base_disk: &Utf8Path, vm_disks: &[&Utf8PathBuf]) -
448
429
449
430
for vm_disk in vm_disks {
450
431
// Use qemu-img info with --force-share to allow reading even if disk is locked by a running VM
451
- let output = std:: process:: Command :: new ( "qemu-img" )
452
- . args ( & [ "info" , "--force-share" , "--output=json" , vm_disk. as_str ( ) ] )
453
- . output ( )
454
- . with_context ( || format ! ( "Failed to run qemu-img info on {:?}" , vm_disk) ) ?;
455
-
456
- if !output. status . success ( ) {
457
- // If we can't read the disk, skip it for counting purposes
458
- // (We're conservative in check_base_disk_referenced but here we just want a count)
459
- debug ! (
460
- "Warning: Could not read disk info for {:?}, skipping for reference count" ,
461
- vm_disk
462
- ) ;
463
- continue ;
464
- }
465
-
466
- // Parse JSON directly from bytes
467
- let info: serde_json:: Value = serde_json:: from_slice ( & output. stdout )
468
- . with_context ( || format ! ( "Failed to parse qemu-img JSON output for {:?}" , vm_disk) ) ?;
432
+ let info = match crate :: qemu_img:: info ( vm_disk) {
433
+ Ok ( info) => info,
434
+ Err ( _) => {
435
+ // If we can't read the disk, skip it for counting purposes
436
+ // (We're conservative in check_base_disk_referenced but here we just want a count)
437
+ debug ! (
438
+ "Warning: Could not read disk info for {:?}, skipping for reference count" ,
439
+ vm_disk
440
+ ) ;
441
+ continue ;
442
+ }
443
+ } ;
469
444
470
445
// Check both "backing-filename" and "full-backing-filename" fields
471
- if let Some ( backing_file) = info[ "backing-filename" ] . as_str ( ) {
446
+ if let Some ( backing_file) = & info. backing_filename {
472
447
if backing_file. contains ( base_disk_name) {
473
448
count += 1 ;
474
449
continue ;
475
450
}
476
451
}
477
- if let Some ( backing_file) = info[ "full-backing-filename" ] . as_str ( ) {
452
+ if let Some ( backing_file) = & info. full_backing_filename {
478
453
if backing_file. contains ( base_disk_name) {
479
454
count += 1 ;
480
455
}
@@ -490,29 +465,21 @@ fn check_base_disk_referenced(base_disk: &Utf8Path, vm_disks: &[&Utf8PathBuf]) -
490
465
491
466
for vm_disk in vm_disks {
492
467
// Use qemu-img info with --force-share to allow reading even if disk is locked by a running VM
493
- let output = std:: process:: Command :: new ( "qemu-img" )
494
- . args ( & [ "info" , "--force-share" , "--output=json" , vm_disk. as_str ( ) ] )
495
- . output ( )
496
- . with_context ( || format ! ( "Failed to run qemu-img info on {:?}" , vm_disk) ) ?;
497
-
498
- if !output. status . success ( ) {
499
- // If we can't read the disk info, be conservative and assume it DOES reference this base
500
- // This prevents accidentally pruning base disks that are in use
501
- let stderr = String :: from_utf8 ( output. stderr )
502
- . with_context ( || format ! ( "Invalid UTF-8 in qemu-img stderr for {:?}" , vm_disk) ) ?;
503
- debug ! (
504
- "Warning: Could not read disk info for {:?}, conservatively assuming it references base disk: {}" ,
505
- vm_disk, stderr
506
- ) ;
507
- return Ok ( true ) ;
508
- }
509
-
510
- // Parse JSON directly from bytes
511
- let info: serde_json:: Value = serde_json:: from_slice ( & output. stdout )
512
- . with_context ( || format ! ( "Failed to parse qemu-img JSON output for {:?}" , vm_disk) ) ?;
468
+ let info = match crate :: qemu_img:: info ( vm_disk) {
469
+ Ok ( info) => info,
470
+ Err ( e) => {
471
+ // If we can't read the disk info, be conservative and assume it DOES reference this base
472
+ // This prevents accidentally pruning base disks that are in use
473
+ debug ! (
474
+ "Warning: Could not read disk info for {:?}, conservatively assuming it references base disk: {}" ,
475
+ vm_disk, e
476
+ ) ;
477
+ return Ok ( true ) ;
478
+ }
479
+ } ;
513
480
514
481
// Check both "backing-filename" and "full-backing-filename" fields
515
- if let Some ( backing_file) = info[ "backing-filename" ] . as_str ( ) {
482
+ if let Some ( backing_file) = & info. backing_filename {
516
483
if backing_file. contains ( base_disk_name) {
517
484
debug ! (
518
485
"Found backing file reference: {:?} -> {:?}" ,
@@ -521,7 +488,7 @@ fn check_base_disk_referenced(base_disk: &Utf8Path, vm_disks: &[&Utf8PathBuf]) -
521
488
return Ok ( true ) ;
522
489
}
523
490
}
524
- if let Some ( backing_file) = info[ "full-backing-filename" ] . as_str ( ) {
491
+ if let Some ( backing_file) = & info. full_backing_filename {
525
492
if backing_file. contains ( base_disk_name) {
526
493
debug ! (
527
494
"Found full backing file reference: {:?} -> {:?}" ,
0 commit comments