@@ -13,12 +13,6 @@ use regex::Regex;
13
13
14
14
use crate :: { readln_special, writeln_special, JailerError } ;
15
15
16
- const PROC_MOUNTS : & str = if cfg ! ( test) {
17
- "/tmp/firecracker/test/jailer/proc/mounts"
18
- } else {
19
- "/proc/mounts"
20
- } ;
21
-
22
16
// Holds information on a cgroup mount point discovered on the system
23
17
#[ derive( Debug ) ]
24
18
struct CgroupMountPoint {
@@ -38,15 +32,15 @@ impl CgroupHierarchies {
38
32
// It will discover cgroup mount points and hierarchies configured
39
33
// on the system and cache the info required to create cgroups later
40
34
// within this hierarchies
41
- fn new ( ver : u8 ) -> Result < Self , JailerError > {
35
+ fn new ( ver : u8 , proc_mounts_path : & str ) -> Result < Self , JailerError > {
42
36
let mut h = CgroupHierarchies {
43
37
hierarchies : HashMap :: new ( ) ,
44
38
mount_points : Vec :: new ( ) ,
45
39
} ;
46
40
47
41
// search PROC_MOUNTS for cgroup mount points
48
- let f = File :: open ( PROC_MOUNTS )
49
- . map_err ( |err| JailerError :: FileOpen ( PathBuf :: from ( PROC_MOUNTS ) , err) ) ?;
42
+ let f = File :: open ( proc_mounts_path )
43
+ . map_err ( |err| JailerError :: FileOpen ( PathBuf :: from ( proc_mounts_path ) , err) ) ?;
50
44
51
45
// Regex courtesy of Filippo.
52
46
// This will match on each line from /proc/mounts for both v1 and v2 mount points.
@@ -66,7 +60,7 @@ impl CgroupHierarchies {
66
60
) . map_err ( JailerError :: RegEx ) ?;
67
61
68
62
for l in BufReader :: new ( f) . lines ( ) {
69
- let l = l. map_err ( |err| JailerError :: ReadLine ( PathBuf :: from ( PROC_MOUNTS ) , err) ) ?;
63
+ let l = l. map_err ( |err| JailerError :: ReadLine ( PathBuf :: from ( proc_mounts_path ) , err) ) ?;
70
64
if let Some ( capture) = re. captures ( & l) {
71
65
if ver == 2 && capture[ "ver" ] . len ( ) == 1 {
72
66
// Found the cgroupv2 unified mountpoint; with cgroupsv2 there is only one
@@ -146,9 +140,9 @@ pub struct CgroupConfigurationBuilder {
146
140
impl CgroupConfigurationBuilder {
147
141
// Creates the builder object
148
142
// It will initialize the CgroupHierarchy cache.
149
- pub fn new ( ver : u8 ) -> Result < Self , JailerError > {
143
+ pub fn new ( ver : u8 , proc_mounts_path : & str ) -> Result < Self , JailerError > {
150
144
Ok ( CgroupConfigurationBuilder {
151
- hierarchies : CgroupHierarchies :: new ( ver) ?,
145
+ hierarchies : CgroupHierarchies :: new ( ver, proc_mounts_path ) ?,
152
146
cgroup_conf : match ver {
153
147
1 => Ok ( CgroupConfiguration :: V1 ( HashMap :: new ( ) ) ) ,
154
148
2 => Ok ( CgroupConfiguration :: V2 ( HashMap :: new ( ) ) ) ,
@@ -510,20 +504,19 @@ pub mod test_util {
510
504
use std:: io:: Write ;
511
505
use std:: path:: { Path , PathBuf } ;
512
506
513
- use super :: PROC_MOUNTS ;
507
+ use utils :: rand ;
514
508
515
509
#[ derive( Debug ) ]
516
510
pub struct MockCgroupFs {
517
511
mounts_file : File ,
512
+ pub proc_mounts_path : String ,
513
+ pub sys_cgroups_path : String ,
518
514
}
519
515
520
516
// Helper object that simulates the layout of the cgroup file system
521
517
// This can be used for testing regardless of the availability of a particular
522
518
// version of cgroups on the system
523
519
impl MockCgroupFs {
524
- const MOCK_PROCDIR : & ' static str = "/tmp/firecracker/test/jailer/proc" ;
525
- pub const MOCK_SYS_CGROUPS_DIR : & ' static str = "/tmp/firecracker/test/jailer/sys_cgroup" ;
526
-
527
520
pub fn create_file_with_contents < P : AsRef < Path > + Debug > (
528
521
filename : P ,
529
522
contents : & str ,
@@ -540,16 +533,28 @@ pub mod test_util {
540
533
}
541
534
542
535
pub fn new ( ) -> std:: result:: Result < MockCgroupFs , std:: io:: Error > {
536
+ let mock_jailer_dir = format ! (
537
+ "/tmp/firecracker/test/{}/jailer" ,
538
+ rand:: rand_alphanumerics( 4 ) . into_string( ) . unwrap( )
539
+ ) ;
540
+ let mock_proc_mounts = format ! ( "{}/{}" , mock_jailer_dir, "proc/mounts" , ) ;
541
+ let mock_sys_cgroups = format ! ( "{}/{}" , mock_jailer_dir, "sys_cgroup" , ) ;
542
+
543
+ let mock_proc_dir = Path :: new ( & mock_proc_mounts) . parent ( ) . unwrap ( ) ;
544
+
543
545
// create a mock /proc/mounts file in a temporary directory
544
- fs:: create_dir_all ( Self :: MOCK_PROCDIR ) ?;
546
+ fs:: create_dir_all ( mock_proc_dir ) ?;
545
547
let file = OpenOptions :: new ( )
546
548
. read ( true )
547
549
. write ( true )
548
550
. create ( true )
549
551
. truncate ( true )
550
- . open ( PROC_MOUNTS ) ?;
551
-
552
- Ok ( MockCgroupFs { mounts_file : file } )
552
+ . open ( mock_proc_mounts. clone ( ) ) ?;
553
+ Ok ( MockCgroupFs {
554
+ mounts_file : file,
555
+ proc_mounts_path : mock_proc_mounts,
556
+ sys_cgroups_path : mock_sys_cgroups,
557
+ } )
553
558
}
554
559
555
560
// Populate the mocked proc/mounts file with cgroupv2 entries
@@ -558,9 +563,9 @@ pub mod test_util {
558
563
writeln ! (
559
564
self . mounts_file,
560
565
"cgroupv2 {}/unified cgroup2 rw,nosuid,nodev,noexec,relatime,nsdelegate 0 0" ,
561
- Self :: MOCK_SYS_CGROUPS_DIR
566
+ self . sys_cgroups_path ,
562
567
) ?;
563
- let cg_unified_path = PathBuf :: from ( format ! ( "{}/unified" , Self :: MOCK_SYS_CGROUPS_DIR ) ) ;
568
+ let cg_unified_path = PathBuf :: from ( format ! ( "{}/unified" , self . sys_cgroups_path ) ) ;
564
569
fs:: create_dir_all ( & cg_unified_path) ?;
565
570
Self :: create_file_with_contents (
566
571
cg_unified_path. join ( "cgroup.controllers" ) ,
@@ -584,9 +589,7 @@ pub mod test_util {
584
589
writeln ! (
585
590
self . mounts_file,
586
591
"cgroup {}/{} cgroup rw,nosuid,nodev,noexec,relatime,{} 0 0" ,
587
- Self :: MOCK_SYS_CGROUPS_DIR ,
588
- c,
589
- c,
592
+ self . sys_cgroups_path, c, c,
590
593
) ?;
591
594
}
592
595
Ok ( ( ) )
@@ -596,8 +599,14 @@ pub mod test_util {
596
599
// Cleanup created files when object goes out of scope
597
600
impl Drop for MockCgroupFs {
598
601
fn drop ( & mut self ) {
599
- let _ = fs:: remove_file ( PROC_MOUNTS ) ;
600
- let _ = fs:: remove_dir_all ( "/tmp/firecracker/test" ) ;
602
+ let tmp_dir = Path :: new ( self . proc_mounts_path . as_str ( ) )
603
+ . parent ( )
604
+ . unwrap ( )
605
+ . parent ( )
606
+ . unwrap ( )
607
+ . parent ( )
608
+ . unwrap ( ) ;
609
+ let _ = fs:: remove_dir_all ( tmp_dir) ;
601
610
}
602
611
}
603
612
}
@@ -629,51 +638,54 @@ mod tests {
629
638
630
639
#[ test]
631
640
fn test_cgroup_conf_builder_invalid_version ( ) {
632
- let builder = CgroupConfigurationBuilder :: new ( 0 ) ;
641
+ let mock_cgroups = MockCgroupFs :: new ( ) . unwrap ( ) ;
642
+ let builder = CgroupConfigurationBuilder :: new ( 0 , mock_cgroups. proc_mounts_path . as_str ( ) ) ;
633
643
builder. unwrap_err ( ) ;
634
644
}
635
645
636
646
#[ test]
637
647
fn test_cgroup_conf_builder_no_mounts ( ) {
638
- let builder = CgroupConfigurationBuilder :: new ( 1 ) ;
648
+ let mock_cgroups = MockCgroupFs :: new ( ) . unwrap ( ) ;
649
+ let builder = CgroupConfigurationBuilder :: new ( 1 , mock_cgroups. proc_mounts_path . as_str ( ) ) ;
639
650
builder. unwrap_err ( ) ;
640
651
}
641
652
642
653
#[ test]
643
654
fn test_cgroup_conf_builder_v1 ( ) {
644
655
let mut mock_cgroups = MockCgroupFs :: new ( ) . unwrap ( ) ;
645
656
mock_cgroups. add_v1_mounts ( ) . unwrap ( ) ;
646
- let builder = CgroupConfigurationBuilder :: new ( 1 ) ;
657
+ let builder = CgroupConfigurationBuilder :: new ( 1 , mock_cgroups . proc_mounts_path . as_str ( ) ) ;
647
658
builder. unwrap ( ) ;
648
659
}
649
660
650
661
#[ test]
651
662
fn test_cgroup_conf_builder_v2 ( ) {
652
663
let mut mock_cgroups = MockCgroupFs :: new ( ) . unwrap ( ) ;
653
664
mock_cgroups. add_v2_mounts ( ) . unwrap ( ) ;
654
- let builder = CgroupConfigurationBuilder :: new ( 2 ) ;
665
+ let builder = CgroupConfigurationBuilder :: new ( 2 , mock_cgroups . proc_mounts_path . as_str ( ) ) ;
655
666
builder. unwrap ( ) ;
656
667
}
657
668
658
669
#[ test]
659
670
fn test_cgroup_conf_builder_v2_with_v1_mounts ( ) {
660
671
let mut mock_cgroups = MockCgroupFs :: new ( ) . unwrap ( ) ;
661
672
mock_cgroups. add_v1_mounts ( ) . unwrap ( ) ;
662
- let builder = CgroupConfigurationBuilder :: new ( 2 ) ;
673
+ let builder = CgroupConfigurationBuilder :: new ( 2 , mock_cgroups . proc_mounts_path . as_str ( ) ) ;
663
674
builder. unwrap_err ( ) ;
664
675
}
665
676
666
677
#[ test]
667
678
fn test_cgroup_conf_builder_v2_no_mounts ( ) {
668
- let builder = CgroupConfigurationBuilder :: new ( 2 ) ;
679
+ let mock_cgroups = MockCgroupFs :: new ( ) . unwrap ( ) ;
680
+ let builder = CgroupConfigurationBuilder :: new ( 2 , mock_cgroups. proc_mounts_path . as_str ( ) ) ;
669
681
builder. unwrap_err ( ) ;
670
682
}
671
683
672
684
#[ test]
673
685
fn test_cgroup_conf_builder_v1_with_v2_mounts ( ) {
674
686
let mut mock_cgroups = MockCgroupFs :: new ( ) . unwrap ( ) ;
675
687
mock_cgroups. add_v2_mounts ( ) . unwrap ( ) ;
676
- let builder = CgroupConfigurationBuilder :: new ( 1 ) ;
688
+ let builder = CgroupConfigurationBuilder :: new ( 1 , mock_cgroups . proc_mounts_path . as_str ( ) ) ;
677
689
builder. unwrap_err ( ) ;
678
690
}
679
691
@@ -684,7 +696,9 @@ mod tests {
684
696
mock_cgroups. add_v2_mounts ( ) . unwrap ( ) ;
685
697
686
698
for v in & [ 1 , 2 ] {
687
- let mut builder = CgroupConfigurationBuilder :: new ( * v) . unwrap ( ) ;
699
+ let mut builder =
700
+ CgroupConfigurationBuilder :: new ( * v, mock_cgroups. proc_mounts_path . as_str ( ) )
701
+ . unwrap ( ) ;
688
702
689
703
builder
690
704
. add_cgroup_property (
@@ -705,7 +719,9 @@ mod tests {
705
719
mock_cgroups. add_v2_mounts ( ) . unwrap ( ) ;
706
720
707
721
for v in & [ 1 , 2 ] {
708
- let mut builder = CgroupConfigurationBuilder :: new ( * v) . unwrap ( ) ;
722
+ let mut builder =
723
+ CgroupConfigurationBuilder :: new ( * v, mock_cgroups. proc_mounts_path . as_str ( ) )
724
+ . unwrap ( ) ;
709
725
builder
710
726
. add_cgroup_property (
711
727
"invalid.cg" . to_string ( ) ,
@@ -722,7 +738,8 @@ mod tests {
722
738
let mut mock_cgroups = MockCgroupFs :: new ( ) . unwrap ( ) ;
723
739
mock_cgroups. add_v1_mounts ( ) . unwrap ( ) ;
724
740
725
- let mut builder = CgroupConfigurationBuilder :: new ( 1 ) . unwrap ( ) ;
741
+ let mut builder =
742
+ CgroupConfigurationBuilder :: new ( 1 , mock_cgroups. proc_mounts_path . as_str ( ) ) . unwrap ( ) ;
726
743
builder
727
744
. add_cgroup_property (
728
745
"cpuset.mems" . to_string ( ) ,
@@ -733,7 +750,7 @@ mod tests {
733
750
. unwrap ( ) ;
734
751
let cg_conf = builder. build ( ) ;
735
752
736
- let cg_root = PathBuf :: from ( format ! ( "{}/cpuset" , MockCgroupFs :: MOCK_SYS_CGROUPS_DIR ) ) ;
753
+ let cg_root = PathBuf :: from ( format ! ( "{}/cpuset" , mock_cgroups . sys_cgroups_path ) ) ;
737
754
738
755
// with real cgroups these files are created automatically
739
756
// since the mock will not do it automatically, we create it here
@@ -756,10 +773,11 @@ mod tests {
756
773
fn test_cgroup_conf_v2_write_value ( ) {
757
774
let mut mock_cgroups = MockCgroupFs :: new ( ) . unwrap ( ) ;
758
775
mock_cgroups. add_v2_mounts ( ) . unwrap ( ) ;
759
- let builder = CgroupConfigurationBuilder :: new ( 2 ) ;
776
+ let builder = CgroupConfigurationBuilder :: new ( 2 , mock_cgroups . proc_mounts_path . as_str ( ) ) ;
760
777
builder. unwrap ( ) ;
761
778
762
- let mut builder = CgroupConfigurationBuilder :: new ( 2 ) . unwrap ( ) ;
779
+ let mut builder =
780
+ CgroupConfigurationBuilder :: new ( 2 , mock_cgroups. proc_mounts_path . as_str ( ) ) . unwrap ( ) ;
763
781
builder
764
782
. add_cgroup_property (
765
783
"cpuset.mems" . to_string ( ) ,
@@ -769,7 +787,7 @@ mod tests {
769
787
)
770
788
. unwrap ( ) ;
771
789
772
- let cg_root = PathBuf :: from ( format ! ( "{}/unified" , MockCgroupFs :: MOCK_SYS_CGROUPS_DIR ) ) ;
790
+ let cg_root = PathBuf :: from ( format ! ( "{}/unified" , mock_cgroups . sys_cgroups_path ) ) ;
773
791
774
792
assert_eq ! ( builder. get_v2_hierarchy_path( ) . unwrap( ) , & cg_root) ;
775
793
0 commit comments