1use crate::error::{oci_error, OciSpecError};
2
3use derive_builder::Builder;
4use getset::{CopyGetters, Getters, MutGetters, Setters};
5use serde::{Deserialize, Serialize};
6use std::{collections::HashMap, fmt::Display, path::PathBuf, vec};
7use strum_macros::{Display as StrumDisplay, EnumString};
8
9#[derive(
10 Builder, Clone, Debug, Deserialize, Eq, Getters, MutGetters, Setters, PartialEq, Serialize,
11)]
12#[serde(rename_all = "camelCase")]
13#[builder(
14 default,
15 pattern = "owned",
16 setter(into, strip_option),
17 build_fn(error = "OciSpecError")
18)]
19#[getset(get_mut = "pub", get = "pub", set = "pub")]
20pub struct Linux {
23 #[serde(default, skip_serializing_if = "Option::is_none")]
24 net_devices: Option<HashMap<String, LinuxNetDevice>>,
26
27 #[serde(default, skip_serializing_if = "Option::is_none")]
28 uid_mappings: Option<Vec<LinuxIdMapping>>,
30
31 #[serde(default, skip_serializing_if = "Option::is_none")]
32 gid_mappings: Option<Vec<LinuxIdMapping>>,
34
35 #[serde(default, skip_serializing_if = "Option::is_none")]
36 sysctl: Option<HashMap<String, String>>,
39
40 #[serde(default, skip_serializing_if = "Option::is_none")]
41 resources: Option<LinuxResources>,
44
45 #[serde(default, skip_serializing_if = "Option::is_none")]
46 cgroups_path: Option<PathBuf>,
51
52 #[serde(default, skip_serializing_if = "Option::is_none")]
53 namespaces: Option<Vec<LinuxNamespace>>,
56
57 #[serde(default, skip_serializing_if = "Option::is_none")]
58 devices: Option<Vec<LinuxDevice>>,
61
62 #[serde(default, skip_serializing_if = "Option::is_none")]
63 seccomp: Option<LinuxSeccomp>,
65
66 #[serde(default, skip_serializing_if = "Option::is_none")]
67 rootfs_propagation: Option<String>,
70
71 #[serde(default, skip_serializing_if = "Option::is_none")]
72 masked_paths: Option<Vec<String>>,
74
75 #[serde(default, skip_serializing_if = "Option::is_none")]
76 readonly_paths: Option<Vec<String>>,
78
79 #[serde(default, skip_serializing_if = "Option::is_none")]
80 mount_label: Option<String>,
83
84 #[serde(default, skip_serializing_if = "Option::is_none")]
85 intel_rdt: Option<LinuxIntelRdt>,
89
90 #[serde(default, skip_serializing_if = "Option::is_none")]
91 memory_policy: Option<LinuxMemoryPolicy>,
93
94 #[serde(default, skip_serializing_if = "Option::is_none")]
95 personality: Option<LinuxPersonality>,
98
99 #[serde(default, skip_serializing_if = "Option::is_none")]
100 time_offsets: Option<HashMap<String, LinuxTimeOffset>>,
102}
103
104impl Default for Linux {
106 fn default() -> Self {
107 Linux {
108 net_devices: None,
110 uid_mappings: Default::default(),
112 gid_mappings: Default::default(),
114 sysctl: Default::default(),
116 resources: Some(LinuxResources {
117 devices: vec![].into(),
118 memory: Default::default(),
119 cpu: Default::default(),
120 pids: Default::default(),
121 block_io: Default::default(),
122 hugepage_limits: Default::default(),
123 network: Default::default(),
124 rdma: Default::default(),
125 unified: Default::default(),
126 }),
127 cgroups_path: Default::default(),
129 namespaces: get_default_namespaces().into(),
130 devices: Default::default(),
132 rootfs_propagation: Default::default(),
134 masked_paths: get_default_maskedpaths().into(),
135 readonly_paths: get_default_readonly_paths().into(),
136 mount_label: Default::default(),
138 seccomp: None,
139 intel_rdt: None,
140 memory_policy: None,
141 personality: None,
142 time_offsets: None,
143 }
144 }
145}
146
147impl Linux {
148 pub fn rootless(uid: u32, gid: u32) -> Self {
150 let mut namespaces = get_default_namespaces();
151 namespaces.retain(|ns| ns.typ != LinuxNamespaceType::Network);
152 namespaces.push(LinuxNamespace {
153 typ: LinuxNamespaceType::User,
154 ..Default::default()
155 });
156 Self {
157 resources: None,
158 uid_mappings: Some(vec![LinuxIdMapping {
159 container_id: 0,
160 host_id: uid,
161 size: 1,
162 }]),
163 gid_mappings: Some(vec![LinuxIdMapping {
164 container_id: 0,
165 host_id: gid,
166 size: 1,
167 }]),
168 namespaces: Some(namespaces),
169 ..Default::default()
170 }
171 }
172}
173
174#[derive(
175 Builder, Clone, Copy, CopyGetters, Debug, Default, Deserialize, Eq, PartialEq, Serialize,
176)]
177#[serde(rename_all = "camelCase")]
178#[builder(
179 default,
180 pattern = "owned",
181 setter(into, strip_option),
182 build_fn(error = "OciSpecError")
183)]
184#[getset(get_copy = "pub", set = "pub")]
185pub struct LinuxIdMapping {
187 #[serde(default, rename = "hostID")]
188 host_id: u32,
191
192 #[serde(default, rename = "containerID")]
193 container_id: u32,
195
196 #[serde(default)]
197 size: u32,
199}
200
201#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize, EnumString)]
202#[strum(serialize_all = "lowercase")]
203#[serde(rename_all = "lowercase")]
204pub enum LinuxDeviceType {
206 A,
208
209 B,
211
212 C,
214
215 U,
217
218 P,
220}
221
222#[allow(clippy::derivable_impls)] impl Default for LinuxDeviceType {
224 fn default() -> LinuxDeviceType {
225 LinuxDeviceType::A
226 }
227}
228
229impl LinuxDeviceType {
230 pub fn as_str(&self) -> &str {
232 match self {
233 Self::A => "a",
234 Self::B => "b",
235 Self::C => "c",
236 Self::U => "u",
237 Self::P => "p",
238 }
239 }
240}
241
242#[derive(
243 Builder,
244 Clone,
245 Debug,
246 Default,
247 Deserialize,
248 Eq,
249 Getters,
250 MutGetters,
251 Setters,
252 PartialEq,
253 Serialize,
254)]
255#[builder(
256 default,
257 pattern = "owned",
258 setter(into, strip_option),
259 build_fn(error = "OciSpecError")
260)]
261pub struct LinuxNetDevice {
263 #[serde(default)]
264 #[getset(get_mut = "pub", get = "pub", set = "pub")]
265 name: Option<String>,
267}
268
269#[derive(
270 Builder,
271 Clone,
272 CopyGetters,
273 Debug,
274 Default,
275 Deserialize,
276 Eq,
277 Getters,
278 MutGetters,
279 Setters,
280 PartialEq,
281 Serialize,
282)]
283#[builder(
284 default,
285 pattern = "owned",
286 setter(into, strip_option),
287 build_fn(error = "OciSpecError")
288)]
289pub struct LinuxDeviceCgroup {
292 #[serde(default)]
293 #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
294 allow: bool,
296
297 #[serde(default, rename = "type", skip_serializing_if = "Option::is_none")]
298 #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
299 typ: Option<LinuxDeviceType>,
301
302 #[serde(default, skip_serializing_if = "Option::is_none")]
303 #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
304 major: Option<i64>,
306
307 #[serde(default, skip_serializing_if = "Option::is_none")]
308 #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
309 minor: Option<i64>,
311
312 #[serde(default)]
314 #[getset(get_mut = "pub", get = "pub", set = "pub")]
315 access: Option<String>,
316}
317
318impl Display for LinuxDeviceCgroup {
322 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
323 let major = self
324 .major
325 .map(|mj| mj.to_string())
326 .unwrap_or_else(|| "*".to_string());
327 let minor = self
328 .minor
329 .map(|mi| mi.to_string())
330 .unwrap_or_else(|| "*".to_string());
331 let access = self.access.as_deref().unwrap_or("");
332 write!(
333 f,
334 "{} {}:{} {}",
335 &self.typ.unwrap_or_default().as_str(),
336 &major,
337 &minor,
338 &access
339 )
340 }
341}
342
343#[derive(
344 Builder,
345 Clone,
346 Copy,
347 CopyGetters,
348 Debug,
349 Default,
350 Deserialize,
351 Eq,
352 PartialEq,
353 Serialize,
354 Setters,
355)]
356#[serde(rename_all = "camelCase")]
357#[builder(
358 default,
359 pattern = "owned",
360 setter(into, strip_option),
361 build_fn(error = "OciSpecError")
362)]
363#[getset(get_copy = "pub", set = "pub")]
364pub struct LinuxMemory {
366 #[serde(skip_serializing_if = "Option::is_none")]
367 #[getset(get_copy = "pub", set = "pub")]
368 limit: Option<i64>,
370
371 #[serde(skip_serializing_if = "Option::is_none")]
372 #[getset(get_copy = "pub", set = "pub")]
373 reservation: Option<i64>,
375
376 #[serde(skip_serializing_if = "Option::is_none")]
377 #[getset(get_copy = "pub", set = "pub")]
378 swap: Option<i64>,
380
381 #[serde(skip_serializing_if = "Option::is_none")]
382 #[getset(get_copy = "pub", set = "pub")]
383 kernel: Option<i64>,
385
386 #[serde(skip_serializing_if = "Option::is_none", rename = "kernelTCP")]
387 #[getset(get_copy = "pub", set = "pub")]
388 kernel_tcp: Option<i64>,
390
391 #[serde(skip_serializing_if = "Option::is_none")]
392 #[getset(get_copy = "pub", set = "pub")]
393 swappiness: Option<u64>,
395
396 #[serde(skip_serializing_if = "Option::is_none", rename = "disableOOMKiller")]
397 #[getset(get_copy = "pub", set = "pub")]
398 disable_oom_killer: Option<bool>,
401
402 #[serde(skip_serializing_if = "Option::is_none")]
403 #[getset(get_copy = "pub", set = "pub")]
404 use_hierarchy: Option<bool>,
406
407 #[serde(skip_serializing_if = "Option::is_none")]
408 #[getset(get_copy = "pub", set = "pub")]
409 check_before_update: Option<bool>,
411}
412
413#[derive(
414 Builder,
415 Clone,
416 CopyGetters,
417 Debug,
418 Default,
419 Deserialize,
420 Eq,
421 Getters,
422 Setters,
423 PartialEq,
424 Serialize,
425)]
426#[serde(rename_all = "camelCase")]
427#[builder(
428 default,
429 pattern = "owned",
430 setter(into, strip_option),
431 build_fn(error = "OciSpecError")
432)]
433pub struct LinuxCpu {
435 #[serde(skip_serializing_if = "Option::is_none")]
436 #[getset(get_copy = "pub", set = "pub")]
437 shares: Option<u64>,
440
441 #[serde(skip_serializing_if = "Option::is_none")]
442 #[getset(get_copy = "pub", set = "pub")]
443 quota: Option<i64>,
445
446 #[serde(skip_serializing_if = "Option::is_none")]
447 #[getset(get_copy = "pub", set = "pub")]
448 idle: Option<i64>,
450
451 #[serde(skip_serializing_if = "Option::is_none")]
452 #[getset(get_copy = "pub", set = "pub")]
453 burst: Option<u64>,
456
457 #[serde(skip_serializing_if = "Option::is_none")]
458 #[getset(get_copy = "pub", set = "pub")]
459 period: Option<u64>,
461
462 #[serde(skip_serializing_if = "Option::is_none")]
463 #[getset(get_copy = "pub", set = "pub")]
464 realtime_runtime: Option<i64>,
466
467 #[serde(skip_serializing_if = "Option::is_none")]
468 #[getset(get_copy = "pub", set = "pub")]
469 realtime_period: Option<u64>,
471
472 #[serde(default, skip_serializing_if = "Option::is_none")]
473 #[getset(get = "pub", set = "pub")]
474 cpus: Option<String>,
476
477 #[serde(default, skip_serializing_if = "Option::is_none")]
478 #[getset(get = "pub", set = "pub")]
479 mems: Option<String>,
482}
483
484#[derive(
485 Builder,
486 Clone,
487 Copy,
488 Debug,
489 Default,
490 Deserialize,
491 Eq,
492 CopyGetters,
493 Setters,
494 PartialEq,
495 Serialize,
496)]
497#[builder(
498 default,
499 pattern = "owned",
500 setter(into, strip_option),
501 build_fn(error = "OciSpecError")
502)]
503#[getset(get_copy = "pub", set = "pub")]
504pub struct LinuxPids {
506 #[serde(default)]
507 limit: i64,
509}
510
511#[derive(
512 Builder, Clone, Copy, CopyGetters, Debug, Default, Deserialize, Eq, PartialEq, Serialize,
513)]
514#[serde(rename_all = "camelCase")]
515#[builder(
516 default,
517 pattern = "owned",
518 setter(into, strip_option),
519 build_fn(error = "OciSpecError")
520)]
521#[getset(get_copy = "pub", set = "pub")]
522pub struct LinuxWeightDevice {
525 #[serde(default)]
526 major: i64,
528
529 #[serde(default)]
530 minor: i64,
532
533 #[serde(skip_serializing_if = "Option::is_none")]
534 weight: Option<u16>,
536
537 #[serde(skip_serializing_if = "Option::is_none")]
538 leaf_weight: Option<u16>,
541}
542
543#[derive(
544 Builder, Clone, Copy, CopyGetters, Debug, Default, Deserialize, Eq, PartialEq, Serialize,
545)]
546#[builder(
547 default,
548 pattern = "owned",
549 setter(into, strip_option),
550 build_fn(error = "OciSpecError")
551)]
552#[getset(get_copy = "pub", set = "pub")]
553pub struct LinuxThrottleDevice {
555 #[serde(default)]
556 major: i64,
558
559 #[serde(default)]
560 minor: i64,
562
563 #[serde(default)]
564 rate: u64,
566}
567
568#[derive(
569 Builder,
570 Clone,
571 CopyGetters,
572 Debug,
573 Default,
574 Deserialize,
575 Eq,
576 Getters,
577 Setters,
578 PartialEq,
579 Serialize,
580)]
581#[serde(rename_all = "camelCase")]
582#[builder(
583 default,
584 pattern = "owned",
585 setter(into, strip_option),
586 build_fn(error = "OciSpecError")
587)]
588pub struct LinuxBlockIo {
590 #[serde(skip_serializing_if = "Option::is_none")]
591 #[getset(get_copy = "pub", set = "pub")]
592 weight: Option<u16>,
594
595 #[serde(skip_serializing_if = "Option::is_none")]
596 #[getset(get_copy = "pub", set = "pub")]
597 leaf_weight: Option<u16>,
600
601 #[serde(skip_serializing_if = "Option::is_none")]
602 #[getset(get = "pub", set = "pub")]
603 weight_device: Option<Vec<LinuxWeightDevice>>,
605
606 #[serde(skip_serializing_if = "Option::is_none")]
607 #[getset(get = "pub", set = "pub")]
608 throttle_read_bps_device: Option<Vec<LinuxThrottleDevice>>,
610
611 #[serde(skip_serializing_if = "Option::is_none")]
612 #[getset(get = "pub", set = "pub")]
613 throttle_write_bps_device: Option<Vec<LinuxThrottleDevice>>,
615
616 #[serde(
617 skip_serializing_if = "Option::is_none",
618 rename = "throttleReadIOPSDevice"
619 )]
620 #[getset(get = "pub", set = "pub")]
621 throttle_read_iops_device: Option<Vec<LinuxThrottleDevice>>,
623
624 #[serde(
625 skip_serializing_if = "Option::is_none",
626 rename = "throttleWriteIOPSDevice"
627 )]
628 #[getset(get = "pub", set = "pub")]
629 throttle_write_iops_device: Option<Vec<LinuxThrottleDevice>>,
631}
632
633#[derive(
634 Builder,
635 Clone,
636 CopyGetters,
637 Debug,
638 Default,
639 Deserialize,
640 Eq,
641 Getters,
642 Setters,
643 PartialEq,
644 Serialize,
645)]
646#[serde(rename_all = "camelCase")]
647#[builder(
648 default,
649 pattern = "owned",
650 setter(into, strip_option),
651 build_fn(error = "OciSpecError")
652)]
653pub struct LinuxHugepageLimit {
656 #[serde(default)]
657 #[getset(get = "pub", set = "pub")]
658 page_size: String,
661
662 #[serde(default)]
663 #[getset(get_copy = "pub", set = "pub")]
664 limit: i64,
666}
667
668#[derive(
669 Builder,
670 Clone,
671 CopyGetters,
672 Debug,
673 Default,
674 Deserialize,
675 Eq,
676 Getters,
677 Setters,
678 PartialEq,
679 Serialize,
680)]
681#[builder(
682 default,
683 pattern = "owned",
684 setter(into, strip_option),
685 build_fn(error = "OciSpecError")
686)]
687pub struct LinuxInterfacePriority {
689 #[serde(default)]
690 #[getset(get = "pub", set = "pub")]
691 name: String,
693
694 #[serde(default)]
695 #[getset(get_copy = "pub", set = "pub")]
696 priority: u32,
698}
699
700impl Display for LinuxInterfacePriority {
704 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
705 writeln!(f, "{} {}", self.name, self.priority)
708 }
709}
710
711#[derive(
712 Builder,
713 Clone,
714 CopyGetters,
715 Debug,
716 Default,
717 Deserialize,
718 Eq,
719 Getters,
720 Setters,
721 PartialEq,
722 Serialize,
723)]
724#[builder(
725 default,
726 pattern = "owned",
727 setter(into, strip_option),
728 build_fn(error = "OciSpecError")
729)]
730pub struct LinuxNetwork {
732 #[serde(skip_serializing_if = "Option::is_none", rename = "classID")]
733 #[getset(get_copy = "pub", set = "pub")]
734 class_id: Option<u32>,
736
737 #[serde(default, skip_serializing_if = "Option::is_none")]
738 #[getset(get = "pub", set = "pub")]
739 priorities: Option<Vec<LinuxInterfacePriority>>,
741}
742
743#[derive(
744 Builder,
745 Clone,
746 CopyGetters,
747 Debug,
748 Default,
749 Deserialize,
750 Eq,
751 Getters,
752 MutGetters,
753 Setters,
754 PartialEq,
755 Serialize,
756)]
757#[serde(rename_all = "camelCase")]
758#[builder(
759 default,
760 pattern = "owned",
761 setter(into, strip_option),
762 build_fn(error = "OciSpecError")
763)]
764pub struct LinuxResources {
766 #[serde(default, skip_serializing_if = "Option::is_none")]
767 #[getset(get_mut = "pub", get = "pub", set = "pub")]
768 devices: Option<Vec<LinuxDeviceCgroup>>,
770
771 #[serde(default, skip_serializing_if = "Option::is_none")]
772 #[getset(get_mut = "pub", get = "pub", set = "pub")]
773 memory: Option<LinuxMemory>,
775
776 #[serde(default, skip_serializing_if = "Option::is_none")]
777 #[getset(get_mut = "pub", get = "pub", set = "pub")]
778 cpu: Option<LinuxCpu>,
780
781 #[serde(default, skip_serializing_if = "Option::is_none")]
782 #[getset(get_mut = "pub", get = "pub", set = "pub")]
783 pids: Option<LinuxPids>,
785
786 #[serde(default, skip_serializing_if = "Option::is_none", rename = "blockIO")]
787 #[getset(get_mut = "pub", get = "pub", set = "pub")]
788 block_io: Option<LinuxBlockIo>,
790
791 #[serde(default, skip_serializing_if = "Option::is_none")]
792 #[getset(get_mut = "pub", get = "pub", set = "pub")]
793 hugepage_limits: Option<Vec<LinuxHugepageLimit>>,
795
796 #[serde(default, skip_serializing_if = "Option::is_none")]
797 #[getset(get_mut = "pub", get = "pub", set = "pub")]
798 network: Option<LinuxNetwork>,
800
801 #[serde(default, skip_serializing_if = "Option::is_none")]
802 #[getset(get_mut = "pub", get = "pub", set = "pub")]
803 rdma: Option<HashMap<String, LinuxRdma>>,
807
808 #[serde(default, skip_serializing_if = "Option::is_none")]
809 #[getset(get_mut = "pub", get = "pub", set = "pub")]
810 unified: Option<HashMap<String, String>>,
812}
813
814#[derive(
815 Builder,
816 Clone,
817 Copy,
818 CopyGetters,
819 Debug,
820 Default,
821 Deserialize,
822 Eq,
823 MutGetters,
824 PartialEq,
825 Serialize,
826)]
827#[serde(rename_all = "camelCase")]
828#[builder(
829 default,
830 pattern = "owned",
831 setter(into, strip_option),
832 build_fn(error = "OciSpecError")
833)]
834#[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
835pub struct LinuxRdma {
837 #[serde(skip_serializing_if = "Option::is_none")]
838 hca_handles: Option<u32>,
841
842 #[serde(skip_serializing_if = "Option::is_none")]
843 hca_objects: Option<u32>,
846}
847
848#[derive(
849 Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize, Hash, StrumDisplay,
850)]
851#[strum(serialize_all = "lowercase")]
852#[serde(rename_all = "snake_case")]
853pub enum LinuxNamespaceType {
855 #[strum(to_string = "mnt")]
856 Mount = 0x00020000,
858
859 Cgroup = 0x02000000,
861
862 Uts = 0x04000000,
864
865 Ipc = 0x08000000,
867
868 User = 0x10000000,
870
871 #[default]
873 Pid = 0x20000000,
874
875 #[strum(to_string = "net")]
876 Network = 0x40000000,
878
879 Time = 0x00000080,
881}
882
883impl TryFrom<&str> for LinuxNamespaceType {
884 type Error = OciSpecError;
885
886 fn try_from(namespace: &str) -> Result<Self, Self::Error> {
887 match namespace {
888 "mnt" | "mount" => Ok(LinuxNamespaceType::Mount),
889 "cgroup" => Ok(LinuxNamespaceType::Cgroup),
890 "uts" => Ok(LinuxNamespaceType::Uts),
891 "ipc" => Ok(LinuxNamespaceType::Ipc),
892 "user" => Ok(LinuxNamespaceType::User),
893 "pid" => Ok(LinuxNamespaceType::Pid),
894 "net" | "network" => Ok(LinuxNamespaceType::Network),
895 "time" => Ok(LinuxNamespaceType::Time),
896 _ => Err(oci_error(format!(
897 "unknown namespace {namespace}, could not convert"
898 ))),
899 }
900 }
901}
902
903#[derive(
904 Builder,
905 Clone,
906 CopyGetters,
907 Debug,
908 Default,
909 Deserialize,
910 Eq,
911 Getters,
912 Setters,
913 PartialEq,
914 Serialize,
915)]
916#[builder(
917 default,
918 pattern = "owned",
919 setter(into, strip_option),
920 build_fn(error = "OciSpecError")
921)]
922pub struct LinuxNamespace {
924 #[serde(rename = "type")]
925 #[getset(get_copy = "pub", set = "pub")]
926 typ: LinuxNamespaceType,
928
929 #[serde(default, skip_serializing_if = "Option::is_none")]
930 #[getset(get = "pub", set = "pub")]
931 path: Option<PathBuf>,
934}
935
936pub fn get_default_namespaces() -> Vec<LinuxNamespace> {
938 vec![
939 LinuxNamespace {
940 typ: LinuxNamespaceType::Pid,
941 path: Default::default(),
942 },
943 LinuxNamespace {
944 typ: LinuxNamespaceType::Network,
945 path: Default::default(),
946 },
947 LinuxNamespace {
948 typ: LinuxNamespaceType::Ipc,
949 path: Default::default(),
950 },
951 LinuxNamespace {
952 typ: LinuxNamespaceType::Uts,
953 path: Default::default(),
954 },
955 LinuxNamespace {
956 typ: LinuxNamespaceType::Mount,
957 path: Default::default(),
958 },
959 LinuxNamespace {
960 typ: LinuxNamespaceType::Cgroup,
961 path: Default::default(),
962 },
963 ]
964}
965
966#[derive(
967 Builder,
968 Clone,
969 CopyGetters,
970 Debug,
971 Default,
972 Deserialize,
973 Eq,
974 Getters,
975 MutGetters,
976 Setters,
977 PartialEq,
978 Serialize,
979)]
980#[serde(rename_all = "camelCase")]
981#[builder(
982 default,
983 pattern = "owned",
984 setter(into, strip_option),
985 build_fn(error = "OciSpecError")
986)]
987pub struct LinuxDevice {
990 #[serde(default)]
991 #[getset(get_mut = "pub", get = "pub", set = "pub")]
992 path: PathBuf,
994
995 #[serde(rename = "type")]
996 #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
997 typ: LinuxDeviceType,
999
1000 #[serde(default)]
1001 #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
1002 major: i64,
1004
1005 #[serde(default)]
1006 #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
1007 minor: i64,
1009
1010 #[serde(default, skip_serializing_if = "Option::is_none")]
1011 #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
1012 file_mode: Option<u32>,
1014
1015 #[serde(default, skip_serializing_if = "Option::is_none")]
1016 #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
1017 uid: Option<u32>,
1019
1020 #[serde(default, skip_serializing_if = "Option::is_none")]
1021 #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
1022 gid: Option<u32>,
1024}
1025
1026impl From<&LinuxDevice> for LinuxDeviceCgroup {
1027 fn from(linux_device: &LinuxDevice) -> LinuxDeviceCgroup {
1028 LinuxDeviceCgroup {
1029 allow: true,
1030 typ: linux_device.typ.into(),
1031 major: Some(linux_device.major),
1032 minor: Some(linux_device.minor),
1033 access: "rwm".to_string().into(),
1034 }
1035 }
1036}
1037
1038#[derive(
1039 Builder,
1040 Clone,
1041 CopyGetters,
1042 Debug,
1043 Default,
1044 Deserialize,
1045 Eq,
1046 Getters,
1047 Setters,
1048 PartialEq,
1049 Serialize,
1050)]
1051#[serde(rename_all = "camelCase")]
1052#[builder(
1053 default,
1054 pattern = "owned",
1055 setter(into, strip_option),
1056 build_fn(error = "OciSpecError")
1057)]
1058pub struct LinuxSeccomp {
1060 #[getset(get_copy = "pub", set = "pub")]
1061 default_action: LinuxSeccompAction,
1063
1064 #[serde(default, skip_serializing_if = "Option::is_none")]
1065 #[getset(get_copy = "pub", set = "pub")]
1066 default_errno_ret: Option<u32>,
1068
1069 #[serde(default, skip_serializing_if = "Option::is_none")]
1070 #[getset(get = "pub", set = "pub")]
1071 architectures: Option<Vec<Arch>>,
1073
1074 #[serde(default, skip_serializing_if = "Option::is_none")]
1075 #[getset(get = "pub", set = "pub")]
1076 flags: Option<Vec<LinuxSeccompFilterFlag>>,
1078
1079 #[serde(default, skip_serializing_if = "Option::is_none")]
1080 #[getset(get = "pub", set = "pub")]
1081 listener_path: Option<PathBuf>,
1083
1084 #[serde(default, skip_serializing_if = "Option::is_none")]
1085 #[getset(get = "pub", set = "pub")]
1086 listener_metadata: Option<String>,
1088
1089 #[serde(default, skip_serializing_if = "Option::is_none")]
1090 #[getset(get = "pub", set = "pub")]
1091 syscalls: Option<Vec<LinuxSyscall>>,
1093}
1094
1095#[derive(
1096 Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize, StrumDisplay, EnumString,
1097)]
1098#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1099#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
1100pub enum LinuxSeccompAction {
1102 ScmpActKill,
1104
1105 ScmpActKillThread,
1107
1108 ScmpActKillProcess,
1110
1111 ScmpActTrap,
1113
1114 ScmpActErrno,
1116
1117 ScmpActNotify,
1119
1120 ScmpActTrace,
1122
1123 ScmpActLog,
1125
1126 #[default]
1128 ScmpActAllow,
1129}
1130
1131impl From<LinuxSeccompAction> for u32 {
1132 fn from(action: LinuxSeccompAction) -> Self {
1133 match action {
1134 LinuxSeccompAction::ScmpActKill => 0x00000000,
1135 LinuxSeccompAction::ScmpActKillThread => 0x00000000,
1136 LinuxSeccompAction::ScmpActKillProcess => 0x80000000,
1137 LinuxSeccompAction::ScmpActTrap => 0x00030000,
1138 LinuxSeccompAction::ScmpActErrno => 0x00050001,
1139 LinuxSeccompAction::ScmpActNotify => 0x7fc00000,
1140 LinuxSeccompAction::ScmpActTrace => 0x7ff00001,
1141 LinuxSeccompAction::ScmpActLog => 0x7ffc0000,
1142 LinuxSeccompAction::ScmpActAllow => 0x7fff0000,
1143 }
1144 }
1145}
1146
1147#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize, StrumDisplay, EnumString)]
1148#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1149#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
1150#[repr(u32)]
1151pub enum Arch {
1153 ScmpArchNative = 0x00000000,
1155
1156 ScmpArchX86 = 0x40000003,
1158
1159 ScmpArchX86_64 = 0xc000003e,
1161
1162 ScmpArchX32 = 0x4000003e,
1167
1168 ScmpArchArm = 0x40000028,
1170
1171 ScmpArchAarch64 = 0xc00000b7,
1173
1174 ScmpArchMips = 0x00000008,
1176
1177 ScmpArchMips64 = 0x80000008,
1179
1180 ScmpArchMips64n32 = 0xa0000008,
1182
1183 ScmpArchMipsel = 0x40000008,
1185
1186 ScmpArchMipsel64 = 0xc0000008,
1188
1189 ScmpArchMipsel64n32 = 0xe0000008,
1191
1192 ScmpArchPpc = 0x00000014,
1194
1195 ScmpArchPpc64 = 0x80000015,
1197
1198 ScmpArchPpc64le = 0xc0000015,
1200
1201 ScmpArchS390 = 0x00000016,
1203
1204 ScmpArchS390x = 0x80000016,
1206
1207 ScmpArchRiscv64 = 0xc00000f3,
1209}
1210
1211#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize, StrumDisplay, EnumString)]
1212#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1213#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
1214pub enum LinuxSeccompFilterFlag {
1216 SeccompFilterFlagLog,
1220
1221 SeccompFilterFlagTsync,
1231
1232 SeccompFilterFlagSpecAllow,
1234}
1235
1236#[derive(
1237 Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize, StrumDisplay, EnumString,
1238)]
1239#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1240#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
1241#[repr(u32)]
1242pub enum LinuxSeccompOperator {
1244 ScmpCmpNe = 1,
1246
1247 ScmpCmpLt = 2,
1249
1250 ScmpCmpLe = 3,
1252
1253 #[default]
1255 ScmpCmpEq = 4,
1256
1257 ScmpCmpGe = 5,
1259
1260 ScmpCmpGt = 6,
1262
1263 ScmpCmpMaskedEq = 7,
1265}
1266
1267#[derive(
1268 Builder,
1269 Clone,
1270 CopyGetters,
1271 Debug,
1272 Default,
1273 Deserialize,
1274 Eq,
1275 Getters,
1276 Setters,
1277 PartialEq,
1278 Serialize,
1279)]
1280#[serde(rename_all = "camelCase")]
1281#[builder(
1282 default,
1283 pattern = "owned",
1284 setter(into, strip_option),
1285 build_fn(error = "OciSpecError")
1286)]
1287pub struct LinuxSyscall {
1289 #[getset(get = "pub", set = "pub")]
1290 names: Vec<String>,
1292
1293 #[getset(get_copy = "pub", set = "pub")]
1294 action: LinuxSeccompAction,
1296
1297 #[serde(default, skip_serializing_if = "Option::is_none")]
1298 #[getset(get_copy = "pub", set = "pub")]
1299 errno_ret: Option<u32>,
1301
1302 #[serde(default, skip_serializing_if = "Option::is_none")]
1303 #[getset(get = "pub", set = "pub")]
1304 args: Option<Vec<LinuxSeccompArg>>,
1306}
1307
1308#[derive(
1309 Builder, Clone, Copy, CopyGetters, Debug, Default, Deserialize, Eq, PartialEq, Serialize,
1310)]
1311#[serde(rename_all = "camelCase")]
1312#[builder(
1313 default,
1314 pattern = "owned",
1315 setter(into, strip_option),
1316 build_fn(error = "OciSpecError")
1317)]
1318#[getset(get_copy = "pub", set = "pub")]
1319pub struct LinuxSeccompArg {
1321 index: usize,
1323
1324 value: u64,
1326
1327 #[serde(default, skip_serializing_if = "Option::is_none")]
1328 value_two: Option<u64>,
1330
1331 op: LinuxSeccompOperator,
1333}
1334
1335pub fn get_default_maskedpaths() -> Vec<String> {
1337 vec![
1338 "/proc/acpi".to_string(),
1341 "/proc/asound".to_string(),
1342 "/proc/kcore".to_string(),
1343 "/proc/keys".to_string(),
1344 "/proc/latency_stats".to_string(),
1345 "/proc/timer_list".to_string(),
1346 "/proc/timer_stats".to_string(),
1347 "/proc/sched_debug".to_string(),
1348 "/sys/firmware".to_string(),
1349 "/proc/scsi".to_string(),
1350 ]
1351}
1352
1353pub fn get_default_readonly_paths() -> Vec<String> {
1356 vec![
1357 "/proc/bus".to_string(),
1358 "/proc/fs".to_string(),
1359 "/proc/irq".to_string(),
1360 "/proc/sys".to_string(),
1361 "/proc/sysrq-trigger".to_string(),
1362 ]
1363}
1364
1365#[derive(
1366 Builder,
1367 Clone,
1368 Debug,
1369 Default,
1370 Deserialize,
1371 Eq,
1372 Getters,
1373 MutGetters,
1374 Setters,
1375 PartialEq,
1376 Serialize,
1377)]
1378#[serde(rename_all = "camelCase")]
1379#[builder(
1380 default,
1381 pattern = "owned",
1382 setter(into, strip_option),
1383 build_fn(error = "OciSpecError")
1384)]
1385#[getset(get_mut = "pub", get = "pub", set = "pub")]
1386pub struct LinuxIntelRdt {
1390 #[serde(default, skip_serializing_if = "Option::is_none", rename = "closID")]
1391 clos_id: Option<String>,
1393
1394 #[serde(default, skip_serializing_if = "Option::is_none")]
1395 l3_cache_schema: Option<String>,
1398
1399 #[serde(default, skip_serializing_if = "Option::is_none")]
1400 mem_bw_schema: Option<String>,
1406
1407 #[serde(default, skip_serializing_if = "Option::is_none")]
1408 enable_cmt: Option<bool>,
1411
1412 #[serde(default, skip_serializing_if = "Option::is_none")]
1413 enable_mbm: Option<bool>,
1416}
1417
1418#[derive(
1419 Builder,
1420 Clone,
1421 CopyGetters,
1422 Debug,
1423 Default,
1424 Deserialize,
1425 Eq,
1426 Getters,
1427 Setters,
1428 PartialEq,
1429 Serialize,
1430)]
1431#[builder(
1432 default,
1433 pattern = "owned",
1434 setter(into, strip_option),
1435 build_fn(error = "OciSpecError")
1436)]
1437pub struct LinuxPersonality {
1439 #[getset(get_copy = "pub", set = "pub")]
1440 domain: LinuxPersonalityDomain,
1442
1443 #[serde(default, skip_serializing_if = "Option::is_none")]
1444 #[getset(get = "pub", set = "pub")]
1445 flags: Option<Vec<String>>,
1447}
1448
1449#[derive(
1450 Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize, StrumDisplay, EnumString,
1451)]
1452pub enum LinuxPersonalityDomain {
1454 #[serde(rename = "LINUX")]
1455 #[strum(serialize = "LINUX")]
1456 #[default]
1458 PerLinux,
1459
1460 #[serde(rename = "LINUX32")]
1461 #[strum(serialize = "LINUX32")]
1462 PerLinux32,
1464}
1465
1466#[derive(
1467 Builder,
1468 Clone,
1469 CopyGetters,
1470 Debug,
1471 Deserialize,
1472 Eq,
1473 Getters,
1474 MutGetters,
1475 Setters,
1476 PartialEq,
1477 Serialize,
1478)]
1479#[serde(rename_all = "camelCase")]
1480#[builder(
1481 pattern = "owned",
1482 setter(into, strip_option),
1483 build_fn(error = "OciSpecError")
1484)]
1485pub struct LinuxMemoryPolicy {
1487 #[getset(get_copy = "pub", set = "pub")]
1488 mode: MemoryPolicyModeType,
1490
1491 #[serde(default, skip_serializing_if = "Option::is_none")]
1492 #[getset(get = "pub", set = "pub")]
1493 nodes: Option<String>,
1496
1497 #[serde(default, skip_serializing_if = "Option::is_none")]
1498 #[getset(get = "pub", get_mut = "pub", set = "pub")]
1499 flags: Option<Vec<MemoryPolicyFlagType>>,
1501}
1502
1503impl Default for LinuxMemoryPolicy {
1504 fn default() -> Self {
1505 Self {
1506 mode: MemoryPolicyModeType::MpolDefault,
1507 nodes: None,
1508 flags: None,
1509 }
1510 }
1511}
1512
1513#[derive(
1514 Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize, StrumDisplay, EnumString,
1515)]
1516pub enum MemoryPolicyModeType {
1518 #[serde(rename = "MPOL_DEFAULT")]
1519 #[strum(serialize = "MPOL_DEFAULT")]
1520 #[default]
1522 MpolDefault,
1523
1524 #[serde(rename = "MPOL_BIND")]
1525 #[strum(serialize = "MPOL_BIND")]
1526 MpolBind,
1528
1529 #[serde(rename = "MPOL_INTERLEAVE")]
1530 #[strum(serialize = "MPOL_INTERLEAVE")]
1531 MpolInterleave,
1533
1534 #[serde(rename = "MPOL_WEIGHTED_INTERLEAVE")]
1535 #[strum(serialize = "MPOL_WEIGHTED_INTERLEAVE")]
1536 MpolWeightedInterleave,
1538
1539 #[serde(rename = "MPOL_PREFERRED")]
1540 #[strum(serialize = "MPOL_PREFERRED")]
1541 MpolPreferred,
1543
1544 #[serde(rename = "MPOL_PREFERRED_MANY")]
1545 #[strum(serialize = "MPOL_PREFERRED_MANY")]
1546 MpolPreferredMany,
1548
1549 #[serde(rename = "MPOL_LOCAL")]
1550 #[strum(serialize = "MPOL_LOCAL")]
1551 MpolLocal,
1553}
1554
1555#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize, StrumDisplay, EnumString)]
1556pub enum MemoryPolicyFlagType {
1558 #[serde(rename = "MPOL_F_NUMA_BALANCING")]
1559 #[strum(serialize = "MPOL_F_NUMA_BALANCING")]
1560 MpolFNumaBalancing,
1562
1563 #[serde(rename = "MPOL_F_RELATIVE_NODES")]
1564 #[strum(serialize = "MPOL_F_RELATIVE_NODES")]
1565 MpolFRelativeNodes,
1567
1568 #[serde(rename = "MPOL_F_STATIC_NODES")]
1569 #[strum(serialize = "MPOL_F_STATIC_NODES")]
1570 MpolFStaticNodes,
1572}
1573
1574#[derive(
1575 Builder,
1576 Clone,
1577 CopyGetters,
1578 Debug,
1579 Default,
1580 Deserialize,
1581 Eq,
1582 Getters,
1583 Setters,
1584 PartialEq,
1585 Serialize,
1586)]
1587#[builder(
1588 default,
1589 pattern = "owned",
1590 setter(into, strip_option),
1591 build_fn(error = "OciSpecError")
1592)]
1593pub struct LinuxTimeOffset {
1595 #[serde(default, skip_serializing_if = "Option::is_none")]
1597 #[getset(get_copy = "pub", set = "pub")]
1598 secs: Option<i64>,
1599 #[serde(default, skip_serializing_if = "Option::is_none")]
1601 #[getset(get_copy = "pub", set = "pub")]
1602 nanosecs: Option<u32>,
1603}
1604
1605#[cfg(feature = "proptests")]
1606use quickcheck::{Arbitrary, Gen};
1607
1608#[cfg(feature = "proptests")]
1609fn some_none_generator_util<T: Arbitrary>(g: &mut Gen) -> Option<T> {
1610 let choice = g.choose(&[true, false]).unwrap();
1611 match choice {
1612 false => None,
1613 true => Some(T::arbitrary(g)),
1614 }
1615}
1616
1617#[cfg(feature = "proptests")]
1618impl Arbitrary for LinuxDeviceCgroup {
1619 fn arbitrary(g: &mut Gen) -> LinuxDeviceCgroup {
1620 let typ_choices = ["a", "b", "c", "u", "p"];
1621
1622 let typ_chosen = g.choose(&typ_choices).unwrap();
1623
1624 let typ = match typ_chosen.to_string().as_str() {
1625 "a" => LinuxDeviceType::A,
1626 "b" => LinuxDeviceType::B,
1627 "c" => LinuxDeviceType::C,
1628 "u" => LinuxDeviceType::U,
1629 "p" => LinuxDeviceType::P,
1630 _ => LinuxDeviceType::A,
1631 };
1632
1633 let access_choices = ["rwm", "m"];
1634 LinuxDeviceCgroup {
1635 allow: bool::arbitrary(g),
1636 typ: typ.into(),
1637 major: some_none_generator_util::<i64>(g),
1638 minor: some_none_generator_util::<i64>(g),
1639 access: g.choose(&access_choices).unwrap().to_string().into(),
1640 }
1641 }
1642}
1643
1644#[cfg(feature = "proptests")]
1645impl Arbitrary for LinuxMemory {
1646 fn arbitrary(g: &mut Gen) -> LinuxMemory {
1647 LinuxMemory {
1648 kernel: some_none_generator_util::<i64>(g),
1649 kernel_tcp: some_none_generator_util::<i64>(g),
1650 limit: some_none_generator_util::<i64>(g),
1651 reservation: some_none_generator_util::<i64>(g),
1652 swap: some_none_generator_util::<i64>(g),
1653 swappiness: some_none_generator_util::<u64>(g),
1654 disable_oom_killer: some_none_generator_util::<bool>(g),
1655 use_hierarchy: some_none_generator_util::<bool>(g),
1656 check_before_update: some_none_generator_util::<bool>(g),
1657 }
1658 }
1659}
1660
1661#[cfg(feature = "proptests")]
1662impl Arbitrary for LinuxHugepageLimit {
1663 fn arbitrary(g: &mut Gen) -> LinuxHugepageLimit {
1664 let unit_choice = ["KB", "MB", "GB"];
1665 let unit = g.choose(&unit_choice).unwrap();
1666 let page_size = u64::arbitrary(g).to_string() + unit;
1667
1668 LinuxHugepageLimit {
1669 page_size,
1670 limit: i64::arbitrary(g),
1671 }
1672 }
1673}
1674
1675#[cfg(test)]
1676mod tests {
1677 use super::*;
1678
1679 #[test]
1681 fn device_type_enum_to_str() {
1682 let type_a = LinuxDeviceType::A;
1683 assert_eq!(type_a.as_str(), "a");
1684
1685 let type_b = LinuxDeviceType::B;
1686 assert_eq!(type_b.as_str(), "b");
1687
1688 let type_c = LinuxDeviceType::C;
1689 assert_eq!(type_c.as_str(), "c");
1690 }
1691
1692 #[test]
1693 fn device_type_string_to_enum() {
1694 let devtype_str = "a";
1695 let devtype_enum: LinuxDeviceType = devtype_str.parse().unwrap();
1696 assert_eq!(devtype_enum, LinuxDeviceType::A);
1697
1698 let devtype_str = "b";
1699 let devtype_enum: LinuxDeviceType = devtype_str.parse().unwrap();
1700 assert_eq!(devtype_enum, LinuxDeviceType::B);
1701
1702 let devtype_str = "c";
1703 let devtype_enum: LinuxDeviceType = devtype_str.parse().unwrap();
1704 assert_eq!(devtype_enum, LinuxDeviceType::C);
1705
1706 let invalid_devtype_str = "x";
1707 let unknown_devtype = invalid_devtype_str.parse::<LinuxDeviceType>();
1708 assert!(unknown_devtype.is_err());
1709 }
1710
1711 #[test]
1713 fn ns_type_enum_to_string() {
1714 let type_a = LinuxNamespaceType::Network;
1715 assert_eq!(type_a.to_string(), "net");
1716
1717 let type_b = LinuxNamespaceType::Mount;
1718 assert_eq!(type_b.to_string(), "mnt");
1719
1720 let type_c = LinuxNamespaceType::Ipc;
1721 assert_eq!(type_c.to_string(), "ipc");
1722 }
1723
1724 #[test]
1725 fn ns_type_string_to_enum() {
1726 let nstype_str = "net";
1727 let nstype_enum = LinuxNamespaceType::try_from(nstype_str).unwrap();
1728 assert_eq!(nstype_enum, LinuxNamespaceType::Network);
1729
1730 let nstype_str = "network";
1731 let nstype_enum = LinuxNamespaceType::try_from(nstype_str).unwrap();
1732 assert_eq!(nstype_enum, LinuxNamespaceType::Network);
1733
1734 let nstype_str = "ipc";
1735 let nstype_enum = LinuxNamespaceType::try_from(nstype_str).unwrap();
1736 assert_eq!(nstype_enum, LinuxNamespaceType::Ipc);
1737
1738 let nstype_str = "cgroup";
1739 let nstype_enum = LinuxNamespaceType::try_from(nstype_str).unwrap();
1740 assert_eq!(nstype_enum, LinuxNamespaceType::Cgroup);
1741
1742 let nstype_str = "mount";
1743 let nstype_enum = LinuxNamespaceType::try_from(nstype_str).unwrap();
1744 assert_eq!(nstype_enum, LinuxNamespaceType::Mount);
1745
1746 let invalid_nstype_str = "xxx";
1747 let unknown_nstype = LinuxNamespaceType::try_from(invalid_nstype_str);
1748 assert!(unknown_nstype.is_err());
1749 }
1750
1751 #[test]
1753 fn seccomp_action_enum_to_string() {
1754 let type_a = LinuxSeccompAction::ScmpActKill;
1755 assert_eq!(type_a.to_string(), "SCMP_ACT_KILL");
1756
1757 let type_b = LinuxSeccompAction::ScmpActAllow;
1758 assert_eq!(type_b.to_string(), "SCMP_ACT_ALLOW");
1759
1760 let type_c = LinuxSeccompAction::ScmpActNotify;
1761 assert_eq!(type_c.to_string(), "SCMP_ACT_NOTIFY");
1762 }
1763
1764 #[test]
1765 fn seccomp_action_string_to_enum() {
1766 let action_str = "SCMP_ACT_KILL";
1767 let action_enum: LinuxSeccompAction = action_str.parse().unwrap();
1768 assert_eq!(action_enum, LinuxSeccompAction::ScmpActKill);
1769
1770 let action_str = "SCMP_ACT_ALLOW";
1771 let action_enum: LinuxSeccompAction = action_str.parse().unwrap();
1772 assert_eq!(action_enum, LinuxSeccompAction::ScmpActAllow);
1773
1774 let action_str = "SCMP_ACT_NOTIFY";
1775 let action_enum: LinuxSeccompAction = action_str.parse().unwrap();
1776 assert_eq!(action_enum, LinuxSeccompAction::ScmpActNotify);
1777
1778 let invalid_action_str = "x";
1779 let unknown_action = invalid_action_str.parse::<LinuxSeccompAction>();
1780 assert!(unknown_action.is_err());
1781 }
1782
1783 #[test]
1785 fn seccomp_arch_enum_to_string() {
1786 let type_a = Arch::ScmpArchX86_64;
1787 assert_eq!(type_a.to_string(), "SCMP_ARCH_X86_64");
1788
1789 let type_b = Arch::ScmpArchAarch64;
1790 assert_eq!(type_b.to_string(), "SCMP_ARCH_AARCH64");
1791
1792 let type_c = Arch::ScmpArchPpc64le;
1793 assert_eq!(type_c.to_string(), "SCMP_ARCH_PPC64LE");
1794 }
1795
1796 #[test]
1797 fn seccomp_arch_string_to_enum() {
1798 let arch_type_str = "SCMP_ARCH_X86_64";
1799 let arch_type_enum: Arch = arch_type_str.parse().unwrap();
1800 assert_eq!(arch_type_enum, Arch::ScmpArchX86_64);
1801
1802 let arch_type_str = "SCMP_ARCH_AARCH64";
1803 let arch_type_enum: Arch = arch_type_str.parse().unwrap();
1804 assert_eq!(arch_type_enum, Arch::ScmpArchAarch64);
1805
1806 let arch_type_str = "SCMP_ARCH_PPC64LE";
1807 let arch_type_enum: Arch = arch_type_str.parse().unwrap();
1808 assert_eq!(arch_type_enum, Arch::ScmpArchPpc64le);
1809
1810 let invalid_arch_str = "x";
1811 let unknown_arch = invalid_arch_str.parse::<Arch>();
1812 assert!(unknown_arch.is_err());
1813 }
1814
1815 #[test]
1817 fn seccomp_filter_flag_enum_to_string() {
1818 let type_a = LinuxSeccompFilterFlag::SeccompFilterFlagLog;
1819 assert_eq!(type_a.to_string(), "SECCOMP_FILTER_FLAG_LOG");
1820
1821 let type_b = LinuxSeccompFilterFlag::SeccompFilterFlagTsync;
1822 assert_eq!(type_b.to_string(), "SECCOMP_FILTER_FLAG_TSYNC");
1823
1824 let type_c = LinuxSeccompFilterFlag::SeccompFilterFlagSpecAllow;
1825 assert_eq!(type_c.to_string(), "SECCOMP_FILTER_FLAG_SPEC_ALLOW");
1826 }
1827
1828 #[test]
1829 fn seccomp_filter_flag_string_to_enum() {
1830 let filter_flag_type_str = "SECCOMP_FILTER_FLAG_LOG";
1831 let filter_flag_type_enum: LinuxSeccompFilterFlag = filter_flag_type_str.parse().unwrap();
1832 assert_eq!(
1833 filter_flag_type_enum,
1834 LinuxSeccompFilterFlag::SeccompFilterFlagLog
1835 );
1836
1837 let filter_flag_type_str = "SECCOMP_FILTER_FLAG_TSYNC";
1838 let filter_flag_type_enum: LinuxSeccompFilterFlag = filter_flag_type_str.parse().unwrap();
1839 assert_eq!(
1840 filter_flag_type_enum,
1841 LinuxSeccompFilterFlag::SeccompFilterFlagTsync
1842 );
1843
1844 let filter_flag_type_str = "SECCOMP_FILTER_FLAG_SPEC_ALLOW";
1845 let filter_flag_type_enum: LinuxSeccompFilterFlag = filter_flag_type_str.parse().unwrap();
1846 assert_eq!(
1847 filter_flag_type_enum,
1848 LinuxSeccompFilterFlag::SeccompFilterFlagSpecAllow
1849 );
1850
1851 let invalid_filter_flag_str = "x";
1852 let unknown_arch = invalid_filter_flag_str.parse::<LinuxSeccompFilterFlag>();
1853 assert!(unknown_arch.is_err());
1854 }
1855
1856 #[test]
1858 fn seccomp_operator_enum_to_string() {
1859 let type_a = LinuxSeccompOperator::ScmpCmpNe;
1860 assert_eq!(type_a.to_string(), "SCMP_CMP_NE");
1861
1862 let type_b = LinuxSeccompOperator::ScmpCmpMaskedEq;
1863 assert_eq!(type_b.to_string(), "SCMP_CMP_MASKED_EQ");
1864
1865 let type_c = LinuxSeccompOperator::ScmpCmpGt;
1866 assert_eq!(type_c.to_string(), "SCMP_CMP_GT");
1867 }
1868
1869 #[test]
1870 fn seccomp_operator_string_to_enum() {
1871 let seccomp_operator_str = "SCMP_CMP_GT";
1872 let seccomp_operator_enum: LinuxSeccompOperator = seccomp_operator_str.parse().unwrap();
1873 assert_eq!(seccomp_operator_enum, LinuxSeccompOperator::ScmpCmpGt);
1874
1875 let seccomp_operator_str = "SCMP_CMP_NE";
1876 let seccomp_operator_enum: LinuxSeccompOperator = seccomp_operator_str.parse().unwrap();
1877 assert_eq!(seccomp_operator_enum, LinuxSeccompOperator::ScmpCmpNe);
1878
1879 let seccomp_operator_str = "SCMP_CMP_MASKED_EQ";
1880 let seccomp_operator_enum: LinuxSeccompOperator = seccomp_operator_str.parse().unwrap();
1881 assert_eq!(seccomp_operator_enum, LinuxSeccompOperator::ScmpCmpMaskedEq);
1882
1883 let invalid_seccomp_operator_str = "x";
1884 let unknown_operator = invalid_seccomp_operator_str.parse::<LinuxSeccompOperator>();
1885 assert!(unknown_operator.is_err());
1886 }
1887
1888 #[test]
1890 fn memory_policy_mode_enum_to_string() {
1891 let mode_a = MemoryPolicyModeType::MpolDefault;
1892 assert_eq!(mode_a.to_string(), "MPOL_DEFAULT");
1893
1894 let mode_b = MemoryPolicyModeType::MpolBind;
1895 assert_eq!(mode_b.to_string(), "MPOL_BIND");
1896
1897 let mode_c = MemoryPolicyModeType::MpolInterleave;
1898 assert_eq!(mode_c.to_string(), "MPOL_INTERLEAVE");
1899
1900 let mode_d = MemoryPolicyModeType::MpolWeightedInterleave;
1901 assert_eq!(mode_d.to_string(), "MPOL_WEIGHTED_INTERLEAVE");
1902
1903 let mode_e = MemoryPolicyModeType::MpolPreferred;
1904 assert_eq!(mode_e.to_string(), "MPOL_PREFERRED");
1905
1906 let mode_f = MemoryPolicyModeType::MpolPreferredMany;
1907 assert_eq!(mode_f.to_string(), "MPOL_PREFERRED_MANY");
1908
1909 let mode_g = MemoryPolicyModeType::MpolLocal;
1910 assert_eq!(mode_g.to_string(), "MPOL_LOCAL");
1911 }
1912
1913 #[test]
1914 fn memory_policy_mode_string_to_enum() {
1915 let mode_str = "MPOL_INTERLEAVE";
1916 let mode_enum: MemoryPolicyModeType = mode_str.parse().unwrap();
1917 assert_eq!(mode_enum, MemoryPolicyModeType::MpolInterleave);
1918
1919 let mode_str = "MPOL_BIND";
1920 let mode_enum: MemoryPolicyModeType = mode_str.parse().unwrap();
1921 assert_eq!(mode_enum, MemoryPolicyModeType::MpolBind);
1922
1923 let mode_str = "MPOL_DEFAULT";
1924 let mode_enum: MemoryPolicyModeType = mode_str.parse().unwrap();
1925 assert_eq!(mode_enum, MemoryPolicyModeType::MpolDefault);
1926
1927 let mode_str = "MPOL_WEIGHTED_INTERLEAVE";
1928 let mode_enum: MemoryPolicyModeType = mode_str.parse().unwrap();
1929 assert_eq!(mode_enum, MemoryPolicyModeType::MpolWeightedInterleave);
1930
1931 let mode_str = "MPOL_PREFERRED";
1932 let mode_enum: MemoryPolicyModeType = mode_str.parse().unwrap();
1933 assert_eq!(mode_enum, MemoryPolicyModeType::MpolPreferred);
1934
1935 let mode_str = "MPOL_PREFERRED_MANY";
1936 let mode_enum: MemoryPolicyModeType = mode_str.parse().unwrap();
1937 assert_eq!(mode_enum, MemoryPolicyModeType::MpolPreferredMany);
1938
1939 let mode_str = "MPOL_LOCAL";
1940 let mode_enum: MemoryPolicyModeType = mode_str.parse().unwrap();
1941 assert_eq!(mode_enum, MemoryPolicyModeType::MpolLocal);
1942
1943 let invalid_mode_str = "INVALID_MODE";
1944 let unknown_mode = invalid_mode_str.parse::<MemoryPolicyModeType>();
1945 assert!(unknown_mode.is_err());
1946 }
1947
1948 #[test]
1950 fn memory_policy_flag_enum_to_string() {
1951 let flag_a = MemoryPolicyFlagType::MpolFNumaBalancing;
1952 assert_eq!(flag_a.to_string(), "MPOL_F_NUMA_BALANCING");
1953
1954 let flag_b = MemoryPolicyFlagType::MpolFRelativeNodes;
1955 assert_eq!(flag_b.to_string(), "MPOL_F_RELATIVE_NODES");
1956
1957 let flag_c = MemoryPolicyFlagType::MpolFStaticNodes;
1958 assert_eq!(flag_c.to_string(), "MPOL_F_STATIC_NODES");
1959 }
1960
1961 #[test]
1962 fn memory_policy_flag_string_to_enum() {
1963 let flag_str = "MPOL_F_NUMA_BALANCING";
1964 let flag_enum: MemoryPolicyFlagType = flag_str.parse().unwrap();
1965 assert_eq!(flag_enum, MemoryPolicyFlagType::MpolFNumaBalancing);
1966
1967 let flag_str = "MPOL_F_RELATIVE_NODES";
1968 let flag_enum: MemoryPolicyFlagType = flag_str.parse().unwrap();
1969 assert_eq!(flag_enum, MemoryPolicyFlagType::MpolFRelativeNodes);
1970
1971 let flag_str = "MPOL_F_STATIC_NODES";
1972 let flag_enum: MemoryPolicyFlagType = flag_str.parse().unwrap();
1973 assert_eq!(flag_enum, MemoryPolicyFlagType::MpolFStaticNodes);
1974
1975 let invalid_flag_str = "INVALID_FLAG";
1976 let unknown_flag = invalid_flag_str.parse::<MemoryPolicyFlagType>();
1977 assert!(unknown_flag.is_err());
1978 }
1979
1980 #[test]
1981 fn test_linux_memory_policy_serialization() {
1982 let memory_policy = LinuxMemoryPolicy {
1983 mode: MemoryPolicyModeType::MpolInterleave,
1984 nodes: Some("0-3,7".to_string()),
1985 flags: Some(vec![
1986 MemoryPolicyFlagType::MpolFStaticNodes,
1987 MemoryPolicyFlagType::MpolFRelativeNodes,
1988 ]),
1989 };
1990
1991 let json = serde_json::to_string(&memory_policy).unwrap();
1992 let deserialized: LinuxMemoryPolicy = serde_json::from_str(&json).unwrap();
1993
1994 assert_eq!(deserialized.mode, MemoryPolicyModeType::MpolInterleave);
1995 assert_eq!(deserialized.nodes, Some("0-3,7".to_string()));
1996 assert_eq!(
1997 deserialized.flags,
1998 Some(vec![
1999 MemoryPolicyFlagType::MpolFStaticNodes,
2000 MemoryPolicyFlagType::MpolFRelativeNodes,
2001 ])
2002 );
2003 }
2004
2005 #[test]
2006 fn test_linux_memory_policy_default() {
2007 let memory_policy = LinuxMemoryPolicy::default();
2008 assert_eq!(memory_policy.mode, MemoryPolicyModeType::MpolDefault);
2009 assert_eq!(memory_policy.nodes, None);
2010 assert_eq!(memory_policy.flags, None);
2011 }
2012}