@@ -759,58 +759,24 @@ fn test_libvirt_bind_storage_ro() -> Result<()> {
759759 panic ! ( "Failed to establish SSH connection: {}" , e) ;
760760 }
761761
762- // Create mount point and mount virtiofs filesystem
763- println ! ( "Creating mount point and mounting virtiofs filesystem..." ) ;
764- let mount_setup = run_bcvk ( & [
765- "libvirt" ,
766- "ssh" ,
767- & domain_name,
768- "--" ,
769- "sudo" ,
770- "mkdir" ,
771- "-p" ,
772- "/run/virtiofs-mnt-hoststorage" ,
773- ] )
774- . expect ( "Failed to create mount point" ) ;
775-
776- if !mount_setup. success ( ) {
777- println ! (
778- "Warning: Failed to create mount point: {}" ,
779- mount_setup. stderr
780- ) ;
781- }
782-
783- let mount_cmd = run_bcvk ( & [
784- "libvirt" ,
785- "ssh" ,
786- & domain_name,
787- "--" ,
788- "sudo" ,
789- "mount" ,
790- "-t" ,
791- "virtiofs" ,
792- "hoststorage" ,
793- "/run/virtiofs-mnt-hoststorage" ,
794- ] )
795- . expect ( "Failed to mount virtiofs" ) ;
796-
797- if !mount_cmd. success ( ) {
798- cleanup_domain ( & domain_name) ;
799- panic ! ( "Failed to mount virtiofs filesystem: {}" , mount_cmd. stderr) ;
800- }
762+ // Wait for VM to boot and automatic mount to complete
763+ println ! ( "Waiting for VM to boot and automatic mount to complete..." ) ;
764+ std:: thread:: sleep ( std:: time:: Duration :: from_secs ( 10 ) ) ;
801765
802- // Test SSH connection and verify container storage mount inside VM
803- println ! ( "Testing SSH connection and checking container storage mount..." ) ;
766+ // Test SSH connection and verify container storage is automatically mounted
767+ println ! (
768+ "Verifying container storage is automatically mounted at /run/host-container-storage..."
769+ ) ;
804770 run_bcvk_nocapture ( & [
805771 "libvirt" ,
806772 "ssh" ,
807773 & domain_name,
808774 "--" ,
809775 "ls" ,
810776 "-la" ,
811- "/run/virtiofs-mnt-hoststorage /overlay" ,
777+ "/run/host-container-storage /overlay" ,
812778 ] )
813- . expect ( "Failed to run SSH command to check container storage" ) ;
779+ . expect ( "Failed to verify automatic mount of container storage" ) ;
814780
815781 // Verify that the mount is read-only
816782 println ! ( "Verifying that the mount is read-only..." ) ;
@@ -820,7 +786,7 @@ fn test_libvirt_bind_storage_ro() -> Result<()> {
820786 & domain_name,
821787 "--" ,
822788 "touch" ,
823- "/run/virtiofs-mnt-hoststorage /test-write" ,
789+ "/run/host-container-storage /test-write" ,
824790 ] )
825791 . expect ( "Failed to run SSH command to test read-only mount" ) ;
826792
@@ -1176,3 +1142,250 @@ fn test_libvirt_transient_vm() -> Result<()> {
11761142 println ! ( "✓ Transient VM test passed" ) ;
11771143 Ok ( ( ) )
11781144}
1145+
1146+ #[ distributed_slice( INTEGRATION_TESTS ) ]
1147+ static TEST_LIBVIRT_BIND_MOUNTS : IntegrationTest =
1148+ IntegrationTest :: new ( "test_libvirt_bind_mounts" , test_libvirt_bind_mounts) ;
1149+
1150+ /// Test automatic bind mount functionality with systemd mount units
1151+ fn test_libvirt_bind_mounts ( ) -> Result < ( ) > {
1152+ use camino:: Utf8Path ;
1153+ use std:: fs;
1154+ use tempfile:: TempDir ;
1155+
1156+ let test_image = get_test_image ( ) ;
1157+
1158+ // Generate unique domain name for this test
1159+ let domain_name = format ! (
1160+ "test-bind-mounts-{}" ,
1161+ std:: time:: SystemTime :: now( )
1162+ . duration_since( std:: time:: UNIX_EPOCH )
1163+ . unwrap( )
1164+ . as_secs( )
1165+ ) ;
1166+
1167+ println ! ( "Testing bind mounts with domain: {}" , domain_name) ;
1168+
1169+ // Create temporary directories for testing bind mounts
1170+ let rw_dir = TempDir :: new ( ) . expect ( "Failed to create read-write temp directory" ) ;
1171+ let rw_dir_path = Utf8Path :: from_path ( rw_dir. path ( ) ) . expect ( "rw dir path is not utf8" ) ;
1172+ let rw_test_file = rw_dir_path. join ( "rw-test.txt" ) ;
1173+ fs:: write ( & rw_test_file, "read-write content" ) . expect ( "Failed to write rw test file" ) ;
1174+
1175+ let ro_dir = TempDir :: new ( ) . expect ( "Failed to create read-only temp directory" ) ;
1176+ let ro_dir_path = Utf8Path :: from_path ( ro_dir. path ( ) ) . expect ( "ro dir path is not utf8" ) ;
1177+ let ro_test_file = ro_dir_path. join ( "ro-test.txt" ) ;
1178+ fs:: write ( & ro_test_file, "read-only content" ) . expect ( "Failed to write ro test file" ) ;
1179+
1180+ println ! ( "RW directory: {}" , rw_dir_path) ;
1181+ println ! ( "RO directory: {}" , ro_dir_path) ;
1182+
1183+ // Cleanup any existing domain with this name
1184+ cleanup_domain ( & domain_name) ;
1185+
1186+ // Create domain with bind mounts
1187+ println ! ( "Creating libvirt domain with bind mounts..." ) ;
1188+ let create_output = run_bcvk ( & [
1189+ "libvirt" ,
1190+ "run" ,
1191+ "--name" ,
1192+ & domain_name,
1193+ "--label" ,
1194+ LIBVIRT_INTEGRATION_TEST_LABEL ,
1195+ "--filesystem" ,
1196+ "ext4" ,
1197+ "--bind" ,
1198+ & format ! ( "{}:/var/mnt/test-rw" , rw_dir_path) ,
1199+ "--bind-ro" ,
1200+ & format ! ( "{}:/var/mnt/test-ro" , ro_dir_path) ,
1201+ & test_image,
1202+ ] )
1203+ . expect ( "Failed to run libvirt run with bind mounts" ) ;
1204+
1205+ println ! ( "Create stdout: {}" , create_output. stdout) ;
1206+ println ! ( "Create stderr: {}" , create_output. stderr) ;
1207+
1208+ if !create_output. success ( ) {
1209+ cleanup_domain ( & domain_name) ;
1210+ panic ! (
1211+ "Failed to create domain with bind mounts: {}" ,
1212+ create_output. stderr
1213+ ) ;
1214+ }
1215+
1216+ println ! ( "Successfully created domain: {}" , domain_name) ;
1217+
1218+ // Check domain XML for virtiofs filesystems and SMBIOS credentials
1219+ println ! ( "Checking domain XML for virtiofs and SMBIOS credentials..." ) ;
1220+ let dumpxml_output = Command :: new ( "virsh" )
1221+ . args ( & [ "dumpxml" , & domain_name] )
1222+ . output ( )
1223+ . expect ( "Failed to dump domain XML" ) ;
1224+
1225+ if !dumpxml_output. status . success ( ) {
1226+ cleanup_domain ( & domain_name) ;
1227+ let stderr = String :: from_utf8_lossy ( & dumpxml_output. stderr ) ;
1228+ panic ! ( "Failed to dump domain XML: {}" , stderr) ;
1229+ }
1230+
1231+ let domain_xml = String :: from_utf8_lossy ( & dumpxml_output. stdout ) ;
1232+
1233+ // Verify virtiofs filesystems are present
1234+ assert ! (
1235+ domain_xml. contains( "type='virtiofs'" ) || domain_xml. contains( "driver type='virtiofs'" ) ,
1236+ "Domain XML should contain virtiofs filesystem configuration"
1237+ ) ;
1238+
1239+ // Verify SMBIOS credentials are injected
1240+ assert ! (
1241+ domain_xml. contains( "systemd.extra-unit" ) ,
1242+ "Domain XML should contain systemd.extra-unit SMBIOS credentials for mount units"
1243+ ) ;
1244+
1245+ println ! ( "✓ Domain XML contains virtiofs and SMBIOS credentials" ) ;
1246+
1247+ // Wait for VM to boot and mounts to be ready
1248+ println ! ( "Waiting for VM to boot and mounts to be ready..." ) ;
1249+ std:: thread:: sleep ( std:: time:: Duration :: from_secs ( 15 ) ) ;
1250+
1251+ // Debug: Check systemd credentials
1252+ println ! ( "Debugging: Checking systemd credentials..." ) ;
1253+ let _creds_check = run_bcvk ( & [
1254+ "libvirt" ,
1255+ "ssh" ,
1256+ & domain_name,
1257+ "--" ,
1258+ "ls" ,
1259+ "-la" ,
1260+ "/run/credentials" ,
1261+ ] )
1262+ . expect ( "Failed to check credentials" ) ;
1263+
1264+ // Debug: Check mount units
1265+ println ! ( "Debugging: Checking mount units..." ) ;
1266+ let _units_check = run_bcvk ( & [
1267+ "libvirt" ,
1268+ "ssh" ,
1269+ & domain_name,
1270+ "--" ,
1271+ "systemctl" ,
1272+ "list-units" ,
1273+ "*.mount" ,
1274+ ] )
1275+ . expect ( "Failed to check mount units" ) ;
1276+
1277+ // Debug: Check mount status
1278+ println ! ( "Debugging: Checking if mounts exist..." ) ;
1279+ let _mount_check = run_bcvk ( & [
1280+ "libvirt" ,
1281+ "ssh" ,
1282+ & domain_name,
1283+ "--" ,
1284+ "mount" ,
1285+ "|" ,
1286+ "grep" ,
1287+ "virtiofs" ,
1288+ ] )
1289+ . expect ( "Failed to check mounts" ) ;
1290+
1291+ // Test read-write bind mount - verify file exists and is readable
1292+ println ! ( "Testing read-write bind mount..." ) ;
1293+ let rw_read_test = run_bcvk ( & [
1294+ "libvirt" ,
1295+ "ssh" ,
1296+ & domain_name,
1297+ "--" ,
1298+ "cat" ,
1299+ "/var/mnt/test-rw/rw-test.txt" ,
1300+ ] )
1301+ . expect ( "Failed to read from rw bind mount" ) ;
1302+
1303+ assert ! (
1304+ rw_read_test. success( ) ,
1305+ "Should be able to read from rw bind mount. stderr: {}" ,
1306+ rw_read_test. stderr
1307+ ) ;
1308+ assert ! (
1309+ rw_read_test. stdout. contains( "read-write content" ) ,
1310+ "Should read correct content from rw bind mount"
1311+ ) ;
1312+ println ! ( "✓ RW bind mount is readable" ) ;
1313+
1314+ // Test write access on read-write mount
1315+ println ! ( "Testing write access on read-write bind mount..." ) ;
1316+ let rw_write_test = run_bcvk ( & [
1317+ "libvirt" ,
1318+ "ssh" ,
1319+ & domain_name,
1320+ "--" ,
1321+ "sh" ,
1322+ "-c" ,
1323+ "echo 'new content' > /var/mnt/test-rw/write-test.txt" ,
1324+ ] )
1325+ . expect ( "Failed to write to rw bind mount" ) ;
1326+
1327+ assert ! (
1328+ rw_write_test. success( ) ,
1329+ "Should be able to write to rw bind mount. stderr: {}" ,
1330+ rw_write_test. stderr
1331+ ) ;
1332+ println ! ( "✓ RW bind mount is writable" ) ;
1333+
1334+ // Verify written file exists on host
1335+ let written_file = rw_dir_path. join ( "write-test.txt" ) ;
1336+ assert ! (
1337+ written_file. exists( ) ,
1338+ "Written file should exist on host filesystem"
1339+ ) ;
1340+ println ! ( "✓ Written file exists on host" ) ;
1341+
1342+ // Test read-only bind mount - verify file exists and is readable
1343+ println ! ( "Testing read-only bind mount..." ) ;
1344+ let ro_read_test = run_bcvk ( & [
1345+ "libvirt" ,
1346+ "ssh" ,
1347+ & domain_name,
1348+ "--" ,
1349+ "cat" ,
1350+ "/var/mnt/test-ro/ro-test.txt" ,
1351+ ] )
1352+ . expect ( "Failed to read from ro bind mount" ) ;
1353+
1354+ assert ! (
1355+ ro_read_test. success( ) ,
1356+ "Should be able to read from ro bind mount. stderr: {}" ,
1357+ ro_read_test. stderr
1358+ ) ;
1359+ assert ! (
1360+ ro_read_test. stdout. contains( "read-only content" ) ,
1361+ "Should read correct content from ro bind mount"
1362+ ) ;
1363+ println ! ( "✓ RO bind mount is readable" ) ;
1364+
1365+ // Test that read-only mount rejects writes
1366+ println ! ( "Testing that read-only bind mount rejects writes..." ) ;
1367+ let ro_write_test = run_bcvk ( & [
1368+ "libvirt" ,
1369+ "ssh" ,
1370+ & domain_name,
1371+ "--" ,
1372+ "sh" ,
1373+ "-c" ,
1374+ "echo 'should fail' > /var/mnt/test-ro/write-test.txt 2>&1" ,
1375+ ] )
1376+ . expect ( "Failed to test write to ro bind mount" ) ;
1377+
1378+ assert ! (
1379+ !ro_write_test. success( ) ,
1380+ "Write to read-only bind mount should fail. stdout: {}, stderr: {}" ,
1381+ ro_write_test. stdout,
1382+ ro_write_test. stderr
1383+ ) ;
1384+ println ! ( "✓ RO bind mount correctly rejects writes" ) ;
1385+
1386+ // Cleanup domain
1387+ cleanup_domain ( & domain_name) ;
1388+
1389+ println ! ( "✓ Bind mounts test passed" ) ;
1390+ Ok ( ( ) )
1391+ }
0 commit comments