@@ -1310,6 +1310,15 @@ impl Vmm {
13101310
13111311 Ok ( ( ) )
13121312 }
1313+
1314+ #[ cfg( test) ]
1315+ fn get_kernel_cmdline ( & self ) -> & str {
1316+ if let Some ( ref k) = self . kernel_config {
1317+ k. cmdline . as_str ( )
1318+ } else {
1319+ ""
1320+ }
1321+ }
13131322}
13141323
13151324/// Starts a new vmm thread that can service API requests.
@@ -1370,7 +1379,7 @@ mod tests {
13701379 fn test_put_block_device ( ) {
13711380 let mut vmm = create_vmm_object ( ) ;
13721381 let f = NamedTempFile :: new ( ) . unwrap ( ) ;
1373- // test that creating a new block device returns the correct output
1382+ // Test that creating a new block device returns the correct output (i.e. "Created").
13741383 let root_block_device = BlockDeviceConfig {
13751384 drive_id : String :: from ( "root" ) ,
13761385 path_on_host : f. path ( ) . to_path_buf ( ) ,
@@ -1389,7 +1398,7 @@ mod tests {
13891398 . contains( & root_block_device)
13901399 ) ;
13911400
1392- // test that updating an existing block device returns the correct output
1401+ // Test that creating a new block device returns the correct output (i.e. "Updated").
13931402 let root_block_device = BlockDeviceConfig {
13941403 drive_id : String :: from ( "root" ) ,
13951404 path_on_host : f. path ( ) . to_path_buf ( ) ,
@@ -1703,4 +1712,122 @@ mod tests {
17031712 assert_eq ! ( m1. dev( ) , m2. dev( ) ) ;
17041713 assert_eq ! ( m1. ino( ) , m2. ino( ) ) ;
17051714 }
1715+
1716+ #[ test]
1717+ pub fn test_attach_block_devices ( ) {
1718+ let mut vmm = create_vmm_object ( ) ;
1719+ let block_file = NamedTempFile :: new ( ) . unwrap ( ) ;
1720+ let kernel_file_temp =
1721+ NamedTempFile :: new ( ) . expect ( "Failed to create temporary kernel file." ) ;
1722+ let kernel_path = String :: from ( kernel_file_temp. path ( ) . to_path_buf ( ) . to_str ( ) . unwrap ( ) ) ;
1723+ let kernel_file = File :: open ( kernel_path) . unwrap ( ) ;
1724+
1725+ // Use Case 1: Root Block Device is not specified through PARTUUID.
1726+ let root_block_device = BlockDeviceConfig {
1727+ drive_id : String :: from ( "root" ) ,
1728+ path_on_host : block_file. path ( ) . to_path_buf ( ) ,
1729+ is_root_device : true ,
1730+ partuuid : None ,
1731+ is_read_only : false ,
1732+ rate_limiter : None ,
1733+ } ;
1734+ // Test that creating a new block device returns the correct output.
1735+ match vmm. put_block_device ( root_block_device. clone ( ) ) {
1736+ Ok ( outcome) => assert ! ( outcome == PutDriveOutcome :: Created ) ,
1737+ Err ( _) => assert ! ( false ) ,
1738+ } ;
1739+ assert ! ( vmm. init_guest_memory( ) . is_ok( ) ) ;
1740+ assert ! ( vmm. guest_memory. is_some( ) ) ;
1741+ let mut cmdline = kernel_cmdline:: Cmdline :: new ( x86_64:: layout:: CMDLINE_MAX_SIZE ) ;
1742+ assert ! ( cmdline. insert_str( DEFAULT_KERNEL_CMDLINE ) . is_ok( ) ) ;
1743+ let kernel_cfg = KernelConfig {
1744+ cmdline,
1745+ kernel_file,
1746+ cmdline_addr : GuestAddress ( x86_64:: layout:: CMDLINE_START ) ,
1747+ } ;
1748+ vmm. configure_kernel ( kernel_cfg) ;
1749+ let guest_mem = vmm. guest_memory . clone ( ) . unwrap ( ) ;
1750+ let mut device_manager =
1751+ MMIODeviceManager :: new ( guest_mem. clone ( ) , x86_64:: get_32bit_gap_start ( ) as u64 ) ;
1752+ assert ! ( vmm. attach_block_devices( & mut device_manager) . is_ok( ) ) ;
1753+ assert ! ( vmm. get_kernel_cmdline( ) . contains( "root=/dev/vda" ) ) ;
1754+
1755+ // Use Case 2: Root Block Device is specified through PARTUUID.
1756+ let mut vmm = create_vmm_object ( ) ;
1757+ let root_block_device = BlockDeviceConfig {
1758+ drive_id : String :: from ( "root" ) ,
1759+ path_on_host : block_file. path ( ) . to_path_buf ( ) ,
1760+ is_root_device : true ,
1761+ partuuid : Some ( "0eaa91a0-01" . to_string ( ) ) ,
1762+ is_read_only : false ,
1763+ rate_limiter : None ,
1764+ } ;
1765+ let kernel_file_temp =
1766+ NamedTempFile :: new ( ) . expect ( "Failed to create temporary kernel file." ) ;
1767+ let kernel_path = String :: from ( kernel_file_temp. path ( ) . to_path_buf ( ) . to_str ( ) . unwrap ( ) ) ;
1768+ let kernel_file = File :: open ( kernel_path) . unwrap ( ) ;
1769+
1770+ // Test that creating a new block device returns the correct output.
1771+ match vmm. put_block_device ( root_block_device. clone ( ) ) {
1772+ Ok ( outcome) => assert ! ( outcome == PutDriveOutcome :: Created ) ,
1773+ Err ( _) => assert ! ( false ) ,
1774+ } ;
1775+ assert ! ( vmm. init_guest_memory( ) . is_ok( ) ) ;
1776+ assert ! ( vmm. guest_memory. is_some( ) ) ;
1777+ let mut cmdline = kernel_cmdline:: Cmdline :: new ( x86_64:: layout:: CMDLINE_MAX_SIZE ) ;
1778+ assert ! ( cmdline. insert_str( DEFAULT_KERNEL_CMDLINE ) . is_ok( ) ) ;
1779+ let kernel_cfg = KernelConfig {
1780+ cmdline,
1781+ kernel_file,
1782+ cmdline_addr : GuestAddress ( x86_64:: layout:: CMDLINE_START ) ,
1783+ } ;
1784+ vmm. configure_kernel ( kernel_cfg) ;
1785+ let guest_mem = vmm. guest_memory . clone ( ) . unwrap ( ) ;
1786+ let mut device_manager =
1787+ MMIODeviceManager :: new ( guest_mem. clone ( ) , x86_64:: get_32bit_gap_start ( ) as u64 ) ;
1788+ assert ! ( vmm. attach_block_devices( & mut device_manager) . is_ok( ) ) ;
1789+ assert ! (
1790+ vmm. get_kernel_cmdline( )
1791+ . contains( "root=PARTUUID=0eaa91a0-01" )
1792+ ) ;
1793+
1794+ // Use Case 3: Root Block Device is not added at all.
1795+ let mut vmm = create_vmm_object ( ) ;
1796+ let non_root_block_device = BlockDeviceConfig {
1797+ drive_id : String :: from ( "not_root" ) ,
1798+ path_on_host : block_file. path ( ) . to_path_buf ( ) ,
1799+ is_root_device : false ,
1800+ partuuid : Some ( "0eaa91a0-01" . to_string ( ) ) ,
1801+ is_read_only : false ,
1802+ rate_limiter : None ,
1803+ } ;
1804+ let kernel_file_temp =
1805+ NamedTempFile :: new ( ) . expect ( "Failed to create temporary kernel file." ) ;
1806+ let kernel_path = String :: from ( kernel_file_temp. path ( ) . to_path_buf ( ) . to_str ( ) . unwrap ( ) ) ;
1807+ let kernel_file = File :: open ( kernel_path) . unwrap ( ) ;
1808+
1809+ // Test that creating a new block device returns the correct output.
1810+ match vmm. put_block_device ( non_root_block_device. clone ( ) ) {
1811+ Ok ( outcome) => assert ! ( outcome == PutDriveOutcome :: Created ) ,
1812+ Err ( _) => assert ! ( false ) ,
1813+ } ;
1814+ assert ! ( vmm. init_guest_memory( ) . is_ok( ) ) ;
1815+ assert ! ( vmm. guest_memory. is_some( ) ) ;
1816+ let mut cmdline = kernel_cmdline:: Cmdline :: new ( x86_64:: layout:: CMDLINE_MAX_SIZE ) ;
1817+ assert ! ( cmdline. insert_str( DEFAULT_KERNEL_CMDLINE ) . is_ok( ) ) ;
1818+ let kernel_cfg = KernelConfig {
1819+ cmdline,
1820+ kernel_file,
1821+ cmdline_addr : GuestAddress ( x86_64:: layout:: CMDLINE_START ) ,
1822+ } ;
1823+ vmm. configure_kernel ( kernel_cfg) ;
1824+ let guest_mem = vmm. guest_memory . clone ( ) . unwrap ( ) ;
1825+ let mut device_manager =
1826+ MMIODeviceManager :: new ( guest_mem. clone ( ) , x86_64:: get_32bit_gap_start ( ) as u64 ) ;
1827+ assert ! ( vmm. attach_block_devices( & mut device_manager) . is_ok( ) ) ;
1828+ // Test that kernel commandline does not contain either /dev/vda or PARTUUID.
1829+ assert ! ( !vmm. get_kernel_cmdline( ) . contains( "root=PARTUUID=" ) ) ;
1830+ assert ! ( !vmm. get_kernel_cmdline( ) . contains( "root=/dev/vda" ) ) ;
1831+
1832+ }
17061833}
0 commit comments