@@ -511,6 +511,189 @@ pub fn test_libvirt_vm_lifecycle() {
511511 println ! ( "VM lifecycle test completed" ) ;
512512}
513513
514+ /// Test container storage binding functionality end-to-end
515+ pub fn test_libvirt_bind_storage_ro ( ) {
516+ let bck = get_bck_command ( ) . unwrap ( ) ;
517+ let test_image = get_test_image ( ) ;
518+
519+ // Generate unique domain name for this test
520+ let domain_name = format ! (
521+ "test-bind-storage-{}" ,
522+ std:: time:: SystemTime :: now( )
523+ . duration_since( std:: time:: UNIX_EPOCH )
524+ . unwrap( )
525+ . as_secs( )
526+ ) ;
527+
528+ println ! ( "Testing --bind-storage-ro with domain: {}" , domain_name) ;
529+
530+ // Cleanup any existing domain with this name
531+ let _ = Command :: new ( "virsh" )
532+ . args ( & [ "destroy" , & domain_name] )
533+ . output ( ) ;
534+ let _ = Command :: new ( "virsh" )
535+ . args ( & [ "undefine" , & domain_name] )
536+ . output ( ) ;
537+
538+ // Create domain with --bind-storage-ro flag
539+ println ! ( "Creating libvirt domain with --bind-storage-ro..." ) ;
540+ let create_output = Command :: new ( "timeout" )
541+ . args ( [
542+ "300s" , // 5 minute timeout for domain creation
543+ & bck,
544+ "libvirt" ,
545+ "run" ,
546+ "--name" ,
547+ & domain_name,
548+ "--bind-storage-ro" ,
549+ "--filesystem" ,
550+ "ext4" ,
551+ & test_image,
552+ ] )
553+ . output ( )
554+ . expect ( "Failed to run libvirt run with --bind-storage-ro" ) ;
555+
556+ let create_stdout = String :: from_utf8_lossy ( & create_output. stdout ) ;
557+ let create_stderr = String :: from_utf8_lossy ( & create_output. stderr ) ;
558+
559+ println ! ( "Create stdout: {}" , create_stdout) ;
560+ println ! ( "Create stderr: {}" , create_stderr) ;
561+
562+ if !create_output. status . success ( ) {
563+ cleanup_domain ( & domain_name) ;
564+ panic ! (
565+ "Failed to create domain with --bind-storage-ro: {}" ,
566+ create_stderr
567+ ) ;
568+ }
569+
570+ println ! ( "Successfully created domain: {}" , domain_name) ;
571+
572+ // Check that the domain was created with virtiofs filesystem
573+ println ! ( "Checking domain XML for virtiofs filesystem..." ) ;
574+ let dumpxml_output = Command :: new ( "virsh" )
575+ . args ( & [ "dumpxml" , & domain_name] )
576+ . output ( )
577+ . expect ( "Failed to dump domain XML" ) ;
578+
579+ if !dumpxml_output. status . success ( ) {
580+ cleanup_domain ( & domain_name) ;
581+ let stderr = String :: from_utf8_lossy ( & dumpxml_output. stderr ) ;
582+ panic ! ( "Failed to dump domain XML: {}" , stderr) ;
583+ }
584+
585+ let domain_xml = String :: from_utf8_lossy ( & dumpxml_output. stdout ) ;
586+ println ! (
587+ "Domain XML snippet: {}" ,
588+ & domain_xml[ ..std:: cmp:: min( 500 , domain_xml. len( ) ) ]
589+ ) ;
590+
591+ // Verify that the domain XML contains virtiofs configuration
592+ assert ! (
593+ domain_xml. contains( "type='virtiofs'" ) || domain_xml. contains( "driver type='virtiofs'" ) ,
594+ "Domain XML should contain virtiofs filesystem configuration"
595+ ) ;
596+
597+ // Verify that the filesystem has the correct tag
598+ assert ! (
599+ domain_xml. contains( "hoststorage" ) || domain_xml. contains( "dir='hoststorage'" ) ,
600+ "Domain XML should reference the hoststorage tag for container storage"
601+ ) ;
602+
603+ // Verify readonly configuration is present
604+ assert ! (
605+ domain_xml. contains( "<readonly/>" ) ,
606+ "Domain XML should have readonly configuration for container storage"
607+ ) ;
608+
609+ // Check metadata for bind-storage-ro configuration
610+ if domain_xml. contains ( "bootc:bind-storage-ro" ) {
611+ assert ! (
612+ domain_xml. contains( "<bootc:bind-storage-ro>true</bootc:bind-storage-ro>" ) ,
613+ "Domain metadata should indicate bind-storage-ro is enabled"
614+ ) ;
615+ }
616+
617+ println ! ( "✓ Domain XML contains expected virtiofs configuration" ) ;
618+ println ! ( "✓ Container storage mount is configured as read-only" ) ;
619+ println ! ( "✓ hoststorage tag is present in filesystem configuration" ) ;
620+
621+ // Wait for VM to boot and SSH to become available
622+ println ! ( "Waiting for VM to boot and SSH to become available..." ) ;
623+ std:: thread:: sleep ( std:: time:: Duration :: from_secs ( 45 ) ) ;
624+
625+ // Create mount point and mount virtiofs filesystem
626+ println ! ( "Creating mount point and mounting virtiofs filesystem..." ) ;
627+ let mount_setup = Command :: new ( "timeout" )
628+ . args ( [
629+ "30s" ,
630+ & bck,
631+ "libvirt" ,
632+ "ssh" ,
633+ & domain_name,
634+ "--" ,
635+ "sudo" ,
636+ "mkdir" ,
637+ "-p" ,
638+ "/run/virtiofs-mnt-hoststorage" ,
639+ ] )
640+ . output ( )
641+ . expect ( "Failed to create mount point" ) ;
642+
643+ if !mount_setup. status . success ( ) {
644+ let stderr = String :: from_utf8_lossy ( & mount_setup. stderr ) ;
645+ println ! ( "Warning: Failed to create mount point: {}" , stderr) ;
646+ }
647+
648+ let mount_cmd = Command :: new ( "timeout" )
649+ . args ( [
650+ "30s" ,
651+ & bck,
652+ "libvirt" ,
653+ "ssh" ,
654+ & domain_name,
655+ "--" ,
656+ "sudo" ,
657+ "mount" ,
658+ "-t" ,
659+ "virtiofs" ,
660+ "hoststorage" ,
661+ "/run/virtiofs-mnt-hoststorage" ,
662+ ] )
663+ . output ( )
664+ . expect ( "Failed to mount virtiofs" ) ;
665+
666+ if !mount_cmd. status . success ( ) {
667+ cleanup_domain ( & domain_name) ;
668+ let stderr = String :: from_utf8_lossy ( & mount_cmd. stderr ) ;
669+ panic ! ( "Failed to mount virtiofs filesystem: {}" , stderr) ;
670+ }
671+
672+ // Test SSH connection and verify container storage mount inside VM
673+ println ! ( "Testing SSH connection and checking container storage mount..." ) ;
674+ let st = Command :: new ( "timeout" )
675+ . args ( [
676+ "60s" ,
677+ & bck,
678+ "libvirt" ,
679+ "ssh" ,
680+ & domain_name,
681+ "--" ,
682+ "ls" ,
683+ "-la" ,
684+ "/run/virtiofs-mnt-hoststorage/overlay" ,
685+ ] )
686+ . status ( )
687+ . expect ( "Failed to run SSH command to check container storage" ) ;
688+
689+ assert ! ( st. success( ) ) ;
690+
691+ // Cleanup domain before completing test
692+ cleanup_domain ( & domain_name) ;
693+
694+ println ! ( "✓ --bind-storage-ro end-to-end test passed" ) ;
695+ }
696+
514697/// Test error handling for invalid configurations
515698pub fn test_libvirt_error_handling ( ) {
516699 let bck = get_bck_command ( ) . unwrap ( ) ;
0 commit comments