1use crate::error::{oci_error, OciSpecError};
2use crate::is_none_or_empty;
3
4use derive_builder::Builder;
5use getset::{CopyGetters, Getters, MutGetters, Setters};
6use serde::{Deserialize, Serialize};
7use std::{collections::HashMap, fmt::Display, path::PathBuf, vec};
8use strum_macros::{Display as StrumDisplay, EnumString};
9
10#[derive(
11 Builder, Clone, Debug, Deserialize, Eq, Getters, MutGetters, Setters, PartialEq, Serialize,
12)]
13#[serde(rename_all = "camelCase")]
14#[builder(
15 default,
16 pattern = "owned",
17 setter(into, strip_option),
18 build_fn(error = "OciSpecError")
19)]
20#[getset(get_mut = "pub", get = "pub", set = "pub")]
21pub struct Linux {
24 #[serde(default, skip_serializing_if = "Option::is_none")]
25 net_devices: Option<HashMap<String, LinuxNetDevice>>,
27
28 #[serde(default, skip_serializing_if = "Option::is_none")]
29 uid_mappings: Option<Vec<LinuxIdMapping>>,
31
32 #[serde(default, skip_serializing_if = "Option::is_none")]
33 gid_mappings: Option<Vec<LinuxIdMapping>>,
35
36 #[serde(default, skip_serializing_if = "Option::is_none")]
37 sysctl: Option<HashMap<String, String>>,
40
41 #[serde(default, skip_serializing_if = "Option::is_none")]
42 resources: Option<LinuxResources>,
45
46 #[serde(default, skip_serializing_if = "Option::is_none")]
47 cgroups_path: Option<PathBuf>,
52
53 #[serde(default, skip_serializing_if = "Option::is_none")]
54 namespaces: Option<Vec<LinuxNamespace>>,
57
58 #[serde(default, skip_serializing_if = "Option::is_none")]
59 devices: Option<Vec<LinuxDevice>>,
62
63 #[serde(default, skip_serializing_if = "Option::is_none")]
64 seccomp: Option<LinuxSeccomp>,
66
67 #[serde(default, skip_serializing_if = "Option::is_none")]
68 rootfs_propagation: Option<String>,
71
72 #[serde(default, skip_serializing_if = "Option::is_none")]
73 masked_paths: Option<Vec<String>>,
75
76 #[serde(default, skip_serializing_if = "Option::is_none")]
77 readonly_paths: Option<Vec<String>>,
79
80 #[serde(default, skip_serializing_if = "Option::is_none")]
81 mount_label: Option<String>,
84
85 #[serde(default, skip_serializing_if = "Option::is_none")]
86 intel_rdt: Option<LinuxIntelRdt>,
90
91 #[serde(default, skip_serializing_if = "Option::is_none")]
92 memory_policy: Option<LinuxMemoryPolicy>,
94
95 #[serde(default, skip_serializing_if = "Option::is_none")]
96 personality: Option<LinuxPersonality>,
99
100 #[serde(default, skip_serializing_if = "Option::is_none")]
101 time_offsets: Option<HashMap<String, LinuxTimeOffset>>,
103}
104
105impl Default for Linux {
107 fn default() -> Self {
108 Linux {
109 net_devices: None,
111 uid_mappings: Default::default(),
113 gid_mappings: Default::default(),
115 sysctl: Default::default(),
117 resources: Some(LinuxResources {
118 devices: vec![].into(),
119 memory: Default::default(),
120 cpu: Default::default(),
121 pids: Default::default(),
122 block_io: Default::default(),
123 hugepage_limits: Default::default(),
124 network: Default::default(),
125 rdma: Default::default(),
126 unified: Default::default(),
127 }),
128 cgroups_path: Default::default(),
130 namespaces: get_default_namespaces().into(),
131 devices: Default::default(),
133 rootfs_propagation: Default::default(),
135 masked_paths: get_default_maskedpaths().into(),
136 readonly_paths: get_default_readonly_paths().into(),
137 mount_label: Default::default(),
139 seccomp: None,
140 intel_rdt: None,
141 memory_policy: None,
142 personality: None,
143 time_offsets: None,
144 }
145 }
146}
147
148impl Linux {
149 pub fn rootless(uid: u32, gid: u32) -> Self {
151 let mut namespaces = get_default_namespaces();
152 namespaces.retain(|ns| ns.typ != LinuxNamespaceType::Network);
153 namespaces.push(LinuxNamespace {
154 typ: LinuxNamespaceType::User,
155 ..Default::default()
156 });
157 Self {
158 resources: None,
159 uid_mappings: Some(vec![LinuxIdMapping {
160 container_id: 0,
161 host_id: uid,
162 size: 1,
163 }]),
164 gid_mappings: Some(vec![LinuxIdMapping {
165 container_id: 0,
166 host_id: gid,
167 size: 1,
168 }]),
169 namespaces: Some(namespaces),
170 ..Default::default()
171 }
172 }
173}
174
175#[derive(
176 Builder, Clone, Copy, CopyGetters, Debug, Default, Deserialize, Eq, PartialEq, Serialize,
177)]
178#[serde(rename_all = "camelCase")]
179#[builder(
180 default,
181 pattern = "owned",
182 setter(into, strip_option),
183 build_fn(error = "OciSpecError")
184)]
185#[getset(get_copy = "pub", set = "pub")]
186pub struct LinuxIdMapping {
188 #[serde(default, rename = "hostID")]
189 host_id: u32,
192
193 #[serde(default, rename = "containerID")]
194 container_id: u32,
196
197 #[serde(default)]
198 size: u32,
200}
201
202#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize, EnumString)]
203#[strum(serialize_all = "lowercase")]
204#[serde(rename_all = "lowercase")]
205pub enum LinuxDeviceType {
207 A,
209
210 B,
212
213 C,
215
216 U,
218
219 P,
221}
222
223#[allow(clippy::derivable_impls)] impl Default for LinuxDeviceType {
225 fn default() -> LinuxDeviceType {
226 LinuxDeviceType::A
227 }
228}
229
230impl LinuxDeviceType {
231 pub fn as_str(&self) -> &str {
233 match self {
234 Self::A => "a",
235 Self::B => "b",
236 Self::C => "c",
237 Self::U => "u",
238 Self::P => "p",
239 }
240 }
241}
242
243#[derive(
244 Builder,
245 Clone,
246 Debug,
247 Default,
248 Deserialize,
249 Eq,
250 Getters,
251 MutGetters,
252 Setters,
253 PartialEq,
254 Serialize,
255)]
256#[builder(
257 default,
258 pattern = "owned",
259 setter(into, strip_option),
260 build_fn(error = "OciSpecError")
261)]
262pub struct LinuxNetDevice {
264 #[serde(default)]
265 #[getset(get_mut = "pub", get = "pub", set = "pub")]
266 name: Option<String>,
268}
269
270#[derive(
271 Builder,
272 Clone,
273 CopyGetters,
274 Debug,
275 Default,
276 Deserialize,
277 Eq,
278 Getters,
279 MutGetters,
280 Setters,
281 PartialEq,
282 Serialize,
283)]
284#[builder(
285 default,
286 pattern = "owned",
287 setter(into, strip_option),
288 build_fn(error = "OciSpecError")
289)]
290pub struct LinuxDeviceCgroup {
293 #[serde(default)]
294 #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
295 allow: bool,
297
298 #[serde(default, rename = "type", skip_serializing_if = "Option::is_none")]
299 #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
300 typ: Option<LinuxDeviceType>,
302
303 #[serde(default, skip_serializing_if = "Option::is_none")]
304 #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
305 major: Option<i64>,
307
308 #[serde(default, skip_serializing_if = "Option::is_none")]
309 #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
310 minor: Option<i64>,
312
313 #[serde(default)]
315 #[getset(get_mut = "pub", get = "pub", set = "pub")]
316 access: Option<String>,
317}
318
319impl Display for LinuxDeviceCgroup {
323 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
324 let major = self
325 .major
326 .map(|mj| mj.to_string())
327 .unwrap_or_else(|| "*".to_string());
328 let minor = self
329 .minor
330 .map(|mi| mi.to_string())
331 .unwrap_or_else(|| "*".to_string());
332 let access = self.access.as_deref().unwrap_or("");
333 write!(
334 f,
335 "{} {}:{} {}",
336 self.typ.unwrap_or_default().as_str(),
337 major,
338 minor,
339 access
340 )
341 }
342}
343
344#[derive(
345 Builder,
346 Clone,
347 Copy,
348 CopyGetters,
349 Debug,
350 Default,
351 Deserialize,
352 Eq,
353 PartialEq,
354 Serialize,
355 Setters,
356)]
357#[serde(rename_all = "camelCase")]
358#[builder(
359 default,
360 pattern = "owned",
361 setter(into, strip_option),
362 build_fn(error = "OciSpecError")
363)]
364#[getset(get_copy = "pub", set = "pub")]
365pub struct LinuxMemory {
367 #[serde(skip_serializing_if = "Option::is_none")]
368 #[getset(get_copy = "pub", set = "pub")]
369 limit: Option<i64>,
371
372 #[serde(skip_serializing_if = "Option::is_none")]
373 #[getset(get_copy = "pub", set = "pub")]
374 reservation: Option<i64>,
376
377 #[serde(skip_serializing_if = "Option::is_none")]
378 #[getset(get_copy = "pub", set = "pub")]
379 swap: Option<i64>,
381
382 #[deprecated(
383 note = "kernel-memory limits are not supported in cgroups v2, and were obsoleted in kernel v5.4"
384 )]
385 #[serde(skip_serializing_if = "Option::is_none")]
386 #[getset(get_copy = "pub", set = "pub")]
387 kernel: Option<i64>,
394
395 #[serde(skip_serializing_if = "Option::is_none", rename = "kernelTCP")]
396 #[getset(get_copy = "pub", set = "pub")]
397 kernel_tcp: Option<i64>,
399
400 #[serde(skip_serializing_if = "Option::is_none")]
401 #[getset(get_copy = "pub", set = "pub")]
402 swappiness: Option<u64>,
404
405 #[serde(skip_serializing_if = "Option::is_none", rename = "disableOOMKiller")]
406 #[getset(get_copy = "pub", set = "pub")]
407 disable_oom_killer: Option<bool>,
410
411 #[serde(skip_serializing_if = "Option::is_none")]
412 #[getset(get_copy = "pub", set = "pub")]
413 use_hierarchy: Option<bool>,
415
416 #[serde(skip_serializing_if = "Option::is_none")]
417 #[getset(get_copy = "pub", set = "pub")]
418 check_before_update: Option<bool>,
420}
421
422#[derive(
423 Builder,
424 Clone,
425 CopyGetters,
426 Debug,
427 Default,
428 Deserialize,
429 Eq,
430 Getters,
431 Setters,
432 PartialEq,
433 Serialize,
434)]
435#[serde(rename_all = "camelCase")]
436#[builder(
437 default,
438 pattern = "owned",
439 setter(into, strip_option),
440 build_fn(error = "OciSpecError")
441)]
442pub struct LinuxCpu {
444 #[serde(skip_serializing_if = "Option::is_none")]
445 #[getset(get_copy = "pub", set = "pub")]
446 shares: Option<u64>,
449
450 #[serde(skip_serializing_if = "Option::is_none")]
451 #[getset(get_copy = "pub", set = "pub")]
452 quota: Option<i64>,
454
455 #[serde(skip_serializing_if = "Option::is_none")]
456 #[getset(get_copy = "pub", set = "pub")]
457 idle: Option<i64>,
459
460 #[serde(skip_serializing_if = "Option::is_none")]
461 #[getset(get_copy = "pub", set = "pub")]
462 burst: Option<u64>,
465
466 #[serde(skip_serializing_if = "Option::is_none")]
467 #[getset(get_copy = "pub", set = "pub")]
468 period: Option<u64>,
470
471 #[serde(skip_serializing_if = "Option::is_none")]
472 #[getset(get_copy = "pub", set = "pub")]
473 realtime_runtime: Option<i64>,
475
476 #[serde(skip_serializing_if = "Option::is_none")]
477 #[getset(get_copy = "pub", set = "pub")]
478 realtime_period: Option<u64>,
480
481 #[serde(default, skip_serializing_if = "Option::is_none")]
482 #[getset(get = "pub", set = "pub")]
483 cpus: Option<String>,
485
486 #[serde(default, skip_serializing_if = "Option::is_none")]
487 #[getset(get = "pub", set = "pub")]
488 mems: Option<String>,
491}
492
493#[derive(
494 Builder,
495 Clone,
496 Copy,
497 Debug,
498 Default,
499 Deserialize,
500 Eq,
501 CopyGetters,
502 Setters,
503 PartialEq,
504 Serialize,
505)]
506#[builder(
507 default,
508 pattern = "owned",
509 setter(into, strip_option),
510 build_fn(error = "OciSpecError")
511)]
512#[getset(get_copy = "pub", set = "pub")]
513pub struct LinuxPids {
515 #[serde(default)]
516 limit: i64,
518}
519
520#[derive(
521 Builder, Clone, Copy, CopyGetters, Debug, Default, Deserialize, Eq, PartialEq, Serialize,
522)]
523#[serde(rename_all = "camelCase")]
524#[builder(
525 default,
526 pattern = "owned",
527 setter(into, strip_option),
528 build_fn(error = "OciSpecError")
529)]
530#[getset(get_copy = "pub", set = "pub")]
531pub struct LinuxWeightDevice {
534 #[serde(default)]
535 major: i64,
537
538 #[serde(default)]
539 minor: i64,
541
542 #[serde(skip_serializing_if = "Option::is_none")]
543 weight: Option<u16>,
545
546 #[serde(skip_serializing_if = "Option::is_none")]
547 leaf_weight: Option<u16>,
550}
551
552#[derive(
553 Builder, Clone, Copy, CopyGetters, Debug, Default, Deserialize, Eq, PartialEq, Serialize,
554)]
555#[builder(
556 default,
557 pattern = "owned",
558 setter(into, strip_option),
559 build_fn(error = "OciSpecError")
560)]
561#[getset(get_copy = "pub", set = "pub")]
562pub struct LinuxThrottleDevice {
564 #[serde(default)]
565 major: i64,
567
568 #[serde(default)]
569 minor: i64,
571
572 #[serde(default)]
573 rate: u64,
575}
576
577#[derive(
578 Builder,
579 Clone,
580 CopyGetters,
581 Debug,
582 Default,
583 Deserialize,
584 Eq,
585 Getters,
586 Setters,
587 PartialEq,
588 Serialize,
589)]
590#[serde(rename_all = "camelCase")]
591#[builder(
592 default,
593 pattern = "owned",
594 setter(into, strip_option),
595 build_fn(error = "OciSpecError")
596)]
597pub struct LinuxBlockIo {
599 #[serde(skip_serializing_if = "Option::is_none")]
600 #[getset(get_copy = "pub", set = "pub")]
601 weight: Option<u16>,
603
604 #[serde(skip_serializing_if = "Option::is_none")]
605 #[getset(get_copy = "pub", set = "pub")]
606 leaf_weight: Option<u16>,
609
610 #[serde(skip_serializing_if = "Option::is_none")]
611 #[getset(get = "pub", set = "pub")]
612 weight_device: Option<Vec<LinuxWeightDevice>>,
614
615 #[serde(skip_serializing_if = "Option::is_none")]
616 #[getset(get = "pub", set = "pub")]
617 throttle_read_bps_device: Option<Vec<LinuxThrottleDevice>>,
619
620 #[serde(skip_serializing_if = "Option::is_none")]
621 #[getset(get = "pub", set = "pub")]
622 throttle_write_bps_device: Option<Vec<LinuxThrottleDevice>>,
624
625 #[serde(
626 skip_serializing_if = "Option::is_none",
627 rename = "throttleReadIOPSDevice"
628 )]
629 #[getset(get = "pub", set = "pub")]
630 throttle_read_iops_device: Option<Vec<LinuxThrottleDevice>>,
632
633 #[serde(
634 skip_serializing_if = "Option::is_none",
635 rename = "throttleWriteIOPSDevice"
636 )]
637 #[getset(get = "pub", set = "pub")]
638 throttle_write_iops_device: Option<Vec<LinuxThrottleDevice>>,
640}
641
642#[derive(
643 Builder,
644 Clone,
645 CopyGetters,
646 Debug,
647 Default,
648 Deserialize,
649 Eq,
650 Getters,
651 Setters,
652 PartialEq,
653 Serialize,
654)]
655#[serde(rename_all = "camelCase")]
656#[builder(
657 default,
658 pattern = "owned",
659 setter(into, strip_option),
660 build_fn(error = "OciSpecError")
661)]
662pub struct LinuxHugepageLimit {
665 #[serde(default)]
666 #[getset(get = "pub", set = "pub")]
667 page_size: String,
670
671 #[serde(default)]
672 #[getset(get_copy = "pub", set = "pub")]
673 limit: i64,
675}
676
677#[derive(
678 Builder,
679 Clone,
680 CopyGetters,
681 Debug,
682 Default,
683 Deserialize,
684 Eq,
685 Getters,
686 Setters,
687 PartialEq,
688 Serialize,
689)]
690#[builder(
691 default,
692 pattern = "owned",
693 setter(into, strip_option),
694 build_fn(error = "OciSpecError")
695)]
696pub struct LinuxInterfacePriority {
698 #[serde(default)]
699 #[getset(get = "pub", set = "pub")]
700 name: String,
702
703 #[serde(default)]
704 #[getset(get_copy = "pub", set = "pub")]
705 priority: u32,
707}
708
709impl Display for LinuxInterfacePriority {
713 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
714 writeln!(f, "{} {}", self.name, self.priority)
717 }
718}
719
720#[derive(
721 Builder,
722 Clone,
723 CopyGetters,
724 Debug,
725 Default,
726 Deserialize,
727 Eq,
728 Getters,
729 Setters,
730 PartialEq,
731 Serialize,
732)]
733#[builder(
734 default,
735 pattern = "owned",
736 setter(into, strip_option),
737 build_fn(error = "OciSpecError")
738)]
739pub struct LinuxNetwork {
741 #[serde(skip_serializing_if = "Option::is_none", rename = "classID")]
742 #[getset(get_copy = "pub", set = "pub")]
743 class_id: Option<u32>,
745
746 #[serde(default, skip_serializing_if = "Option::is_none")]
747 #[getset(get = "pub", set = "pub")]
748 priorities: Option<Vec<LinuxInterfacePriority>>,
750}
751
752#[derive(
753 Builder,
754 Clone,
755 CopyGetters,
756 Debug,
757 Default,
758 Deserialize,
759 Eq,
760 Getters,
761 MutGetters,
762 Setters,
763 PartialEq,
764 Serialize,
765)]
766#[serde(rename_all = "camelCase")]
767#[builder(
768 default,
769 pattern = "owned",
770 setter(into, strip_option),
771 build_fn(error = "OciSpecError")
772)]
773pub struct LinuxResources {
775 #[serde(default, skip_serializing_if = "Option::is_none")]
776 #[getset(get_mut = "pub", get = "pub", set = "pub")]
777 devices: Option<Vec<LinuxDeviceCgroup>>,
779
780 #[serde(default, skip_serializing_if = "Option::is_none")]
781 #[getset(get_mut = "pub", get = "pub", set = "pub")]
782 memory: Option<LinuxMemory>,
784
785 #[serde(default, skip_serializing_if = "Option::is_none")]
786 #[getset(get_mut = "pub", get = "pub", set = "pub")]
787 cpu: Option<LinuxCpu>,
789
790 #[serde(default, skip_serializing_if = "Option::is_none")]
791 #[getset(get_mut = "pub", get = "pub", set = "pub")]
792 pids: Option<LinuxPids>,
794
795 #[serde(default, skip_serializing_if = "Option::is_none", rename = "blockIO")]
796 #[getset(get_mut = "pub", get = "pub", set = "pub")]
797 block_io: Option<LinuxBlockIo>,
799
800 #[serde(default, skip_serializing_if = "Option::is_none")]
801 #[getset(get_mut = "pub", get = "pub", set = "pub")]
802 hugepage_limits: Option<Vec<LinuxHugepageLimit>>,
804
805 #[serde(default, skip_serializing_if = "Option::is_none")]
806 #[getset(get_mut = "pub", get = "pub", set = "pub")]
807 network: Option<LinuxNetwork>,
809
810 #[serde(default, skip_serializing_if = "Option::is_none")]
811 #[getset(get_mut = "pub", get = "pub", set = "pub")]
812 rdma: Option<HashMap<String, LinuxRdma>>,
816
817 #[serde(default, skip_serializing_if = "Option::is_none")]
818 #[getset(get_mut = "pub", get = "pub", set = "pub")]
819 unified: Option<HashMap<String, String>>,
821}
822
823#[derive(
824 Builder,
825 Clone,
826 Copy,
827 CopyGetters,
828 Debug,
829 Default,
830 Deserialize,
831 Eq,
832 MutGetters,
833 PartialEq,
834 Serialize,
835)]
836#[serde(rename_all = "camelCase")]
837#[builder(
838 default,
839 pattern = "owned",
840 setter(into, strip_option),
841 build_fn(error = "OciSpecError")
842)]
843#[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
844pub struct LinuxRdma {
846 #[serde(skip_serializing_if = "Option::is_none")]
847 hca_handles: Option<u32>,
850
851 #[serde(skip_serializing_if = "Option::is_none")]
852 hca_objects: Option<u32>,
855}
856
857#[derive(
858 Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize, Hash, StrumDisplay,
859)]
860#[strum(serialize_all = "lowercase")]
861#[serde(rename_all = "snake_case")]
862pub enum LinuxNamespaceType {
864 #[strum(to_string = "mnt")]
865 Mount = 0x00020000,
867
868 Cgroup = 0x02000000,
870
871 Uts = 0x04000000,
873
874 Ipc = 0x08000000,
876
877 User = 0x10000000,
879
880 #[default]
882 Pid = 0x20000000,
883
884 #[strum(to_string = "net")]
885 Network = 0x40000000,
887
888 Time = 0x00000080,
890}
891
892impl TryFrom<&str> for LinuxNamespaceType {
893 type Error = OciSpecError;
894
895 fn try_from(namespace: &str) -> Result<Self, Self::Error> {
896 match namespace {
897 "mnt" | "mount" => Ok(LinuxNamespaceType::Mount),
898 "cgroup" => Ok(LinuxNamespaceType::Cgroup),
899 "uts" => Ok(LinuxNamespaceType::Uts),
900 "ipc" => Ok(LinuxNamespaceType::Ipc),
901 "user" => Ok(LinuxNamespaceType::User),
902 "pid" => Ok(LinuxNamespaceType::Pid),
903 "net" | "network" => Ok(LinuxNamespaceType::Network),
904 "time" => Ok(LinuxNamespaceType::Time),
905 _ => Err(oci_error(format!(
906 "unknown namespace {namespace}, could not convert"
907 ))),
908 }
909 }
910}
911
912#[derive(
913 Builder,
914 Clone,
915 CopyGetters,
916 Debug,
917 Default,
918 Deserialize,
919 Eq,
920 Getters,
921 Setters,
922 PartialEq,
923 Serialize,
924)]
925#[builder(
926 default,
927 pattern = "owned",
928 setter(into, strip_option),
929 build_fn(error = "OciSpecError")
930)]
931pub struct LinuxNamespace {
933 #[serde(rename = "type")]
934 #[getset(get_copy = "pub", set = "pub")]
935 typ: LinuxNamespaceType,
937
938 #[serde(default, skip_serializing_if = "Option::is_none")]
939 #[getset(get = "pub", set = "pub")]
940 path: Option<PathBuf>,
943}
944
945pub fn get_default_namespaces() -> Vec<LinuxNamespace> {
947 vec![
948 LinuxNamespace {
949 typ: LinuxNamespaceType::Pid,
950 path: Default::default(),
951 },
952 LinuxNamespace {
953 typ: LinuxNamespaceType::Network,
954 path: Default::default(),
955 },
956 LinuxNamespace {
957 typ: LinuxNamespaceType::Ipc,
958 path: Default::default(),
959 },
960 LinuxNamespace {
961 typ: LinuxNamespaceType::Uts,
962 path: Default::default(),
963 },
964 LinuxNamespace {
965 typ: LinuxNamespaceType::Mount,
966 path: Default::default(),
967 },
968 LinuxNamespace {
969 typ: LinuxNamespaceType::Cgroup,
970 path: Default::default(),
971 },
972 ]
973}
974
975#[derive(
976 Builder,
977 Clone,
978 CopyGetters,
979 Debug,
980 Default,
981 Deserialize,
982 Eq,
983 Getters,
984 MutGetters,
985 Setters,
986 PartialEq,
987 Serialize,
988)]
989#[serde(rename_all = "camelCase")]
990#[builder(
991 default,
992 pattern = "owned",
993 setter(into, strip_option),
994 build_fn(error = "OciSpecError")
995)]
996pub struct LinuxDevice {
999 #[serde(default)]
1000 #[getset(get_mut = "pub", get = "pub", set = "pub")]
1001 path: PathBuf,
1003
1004 #[serde(rename = "type")]
1005 #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
1006 typ: LinuxDeviceType,
1008
1009 #[serde(default)]
1010 #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
1011 major: i64,
1013
1014 #[serde(default)]
1015 #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
1016 minor: i64,
1018
1019 #[serde(default, skip_serializing_if = "Option::is_none")]
1020 #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
1021 file_mode: Option<u32>,
1023
1024 #[serde(default, skip_serializing_if = "Option::is_none")]
1025 #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
1026 uid: Option<u32>,
1028
1029 #[serde(default, skip_serializing_if = "Option::is_none")]
1030 #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
1031 gid: Option<u32>,
1033}
1034
1035impl From<&LinuxDevice> for LinuxDeviceCgroup {
1036 fn from(linux_device: &LinuxDevice) -> LinuxDeviceCgroup {
1037 LinuxDeviceCgroup {
1038 allow: true,
1039 typ: linux_device.typ.into(),
1040 major: Some(linux_device.major),
1041 minor: Some(linux_device.minor),
1042 access: "rwm".to_string().into(),
1043 }
1044 }
1045}
1046
1047#[derive(
1048 Builder,
1049 Clone,
1050 CopyGetters,
1051 Debug,
1052 Default,
1053 Deserialize,
1054 Eq,
1055 Getters,
1056 Setters,
1057 PartialEq,
1058 Serialize,
1059)]
1060#[serde(rename_all = "camelCase")]
1061#[builder(
1062 default,
1063 pattern = "owned",
1064 setter(into, strip_option),
1065 build_fn(error = "OciSpecError")
1066)]
1067pub struct LinuxSeccomp {
1069 #[getset(get_copy = "pub", set = "pub")]
1070 default_action: LinuxSeccompAction,
1072
1073 #[serde(default, skip_serializing_if = "Option::is_none")]
1074 #[getset(get_copy = "pub", set = "pub")]
1075 default_errno_ret: Option<u32>,
1077
1078 #[serde(default, skip_serializing_if = "Option::is_none")]
1079 #[getset(get = "pub", set = "pub")]
1080 architectures: Option<Vec<Arch>>,
1082
1083 #[serde(default, skip_serializing_if = "Option::is_none")]
1084 #[getset(get = "pub", set = "pub")]
1085 flags: Option<Vec<LinuxSeccompFilterFlag>>,
1087
1088 #[serde(default, skip_serializing_if = "Option::is_none")]
1089 #[getset(get = "pub", set = "pub")]
1090 listener_path: Option<PathBuf>,
1092
1093 #[serde(default, skip_serializing_if = "Option::is_none")]
1094 #[getset(get = "pub", set = "pub")]
1095 listener_metadata: Option<String>,
1097
1098 #[serde(default, skip_serializing_if = "Option::is_none")]
1099 #[getset(get = "pub", set = "pub")]
1100 syscalls: Option<Vec<LinuxSyscall>>,
1102}
1103
1104#[derive(
1105 Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize, StrumDisplay, EnumString,
1106)]
1107#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1108#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
1109pub enum LinuxSeccompAction {
1111 ScmpActKill,
1113
1114 ScmpActKillThread,
1116
1117 ScmpActKillProcess,
1119
1120 ScmpActTrap,
1122
1123 ScmpActErrno,
1125
1126 ScmpActNotify,
1128
1129 ScmpActTrace,
1131
1132 ScmpActLog,
1134
1135 #[default]
1137 ScmpActAllow,
1138}
1139
1140impl From<LinuxSeccompAction> for u32 {
1142 fn from(action: LinuxSeccompAction) -> Self {
1143 action.as_u32(None)
1144 }
1145}
1146
1147impl LinuxSeccompAction {
1148 pub fn as_u32(&self, errno_ret: Option<u32>) -> u32 {
1154 match self {
1155 LinuxSeccompAction::ScmpActKill => 0x00000000,
1156 LinuxSeccompAction::ScmpActKillThread => 0x00000000,
1157 LinuxSeccompAction::ScmpActKillProcess => 0x80000000,
1158 LinuxSeccompAction::ScmpActTrap => 0x00030000,
1159 LinuxSeccompAction::ScmpActErrno => {
1160 if let Some(errno_ret) = errno_ret {
1161 0x00050000 | errno_ret
1162 } else {
1163 0x00050001
1164 }
1165 }
1166 LinuxSeccompAction::ScmpActNotify => 0x7fc00000,
1167 LinuxSeccompAction::ScmpActTrace => {
1168 if let Some(errno_ret) = errno_ret {
1169 0x7ff00000 | errno_ret
1170 } else {
1171 0x7ff00001
1172 }
1173 }
1174 LinuxSeccompAction::ScmpActLog => 0x7ffc0000,
1175 LinuxSeccompAction::ScmpActAllow => 0x7fff0000,
1176 }
1177 }
1178}
1179
1180#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize, StrumDisplay, EnumString)]
1181#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1182#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
1183#[repr(u32)]
1184pub enum Arch {
1186 ScmpArchNative = 0x00000000,
1188
1189 ScmpArchX86 = 0x40000003,
1191
1192 ScmpArchX86_64 = 0xc000003e,
1194
1195 ScmpArchX32 = 0x4000003e,
1200
1201 ScmpArchArm = 0x40000028,
1203
1204 ScmpArchAarch64 = 0xc00000b7,
1206
1207 ScmpArchMips = 0x00000008,
1209
1210 ScmpArchMips64 = 0x80000008,
1212
1213 ScmpArchMips64n32 = 0xa0000008,
1215
1216 ScmpArchMipsel = 0x40000008,
1218
1219 ScmpArchMipsel64 = 0xc0000008,
1221
1222 ScmpArchMipsel64n32 = 0xe0000008,
1224
1225 ScmpArchPpc = 0x00000014,
1227
1228 ScmpArchPpc64 = 0x80000015,
1230
1231 ScmpArchPpc64le = 0xc0000015,
1233
1234 ScmpArchS390 = 0x00000016,
1236
1237 ScmpArchS390x = 0x80000016,
1239
1240 ScmpArchParisc = 0x0000000f,
1242
1243 ScmpArchParisc64 = 0x8000000f,
1245
1246 ScmpArchRiscv64 = 0xc00000f3,
1248
1249 ScmpArchLoongarch64 = 0xc0000102,
1251
1252 ScmpArchM68k = 0x00000004,
1254
1255 ScmpArchSh = 0x4000002a,
1257
1258 ScmpArchSheb = 0x0000002a,
1260}
1261
1262#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize, StrumDisplay, EnumString)]
1263#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1264#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
1265pub enum LinuxSeccompFilterFlag {
1267 SeccompFilterFlagLog,
1271
1272 SeccompFilterFlagTsync,
1282
1283 SeccompFilterFlagSpecAllow,
1285
1286 SeccompFilterFlagWaitKillableRecv,
1288}
1289
1290#[derive(
1291 Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize, StrumDisplay, EnumString,
1292)]
1293#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1294#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
1295#[repr(u32)]
1296pub enum LinuxSeccompOperator {
1298 ScmpCmpNe = 1,
1300
1301 ScmpCmpLt = 2,
1303
1304 ScmpCmpLe = 3,
1306
1307 #[default]
1309 ScmpCmpEq = 4,
1310
1311 ScmpCmpGe = 5,
1313
1314 ScmpCmpGt = 6,
1316
1317 ScmpCmpMaskedEq = 7,
1319}
1320
1321#[derive(
1322 Builder,
1323 Clone,
1324 CopyGetters,
1325 Debug,
1326 Default,
1327 Deserialize,
1328 Eq,
1329 Getters,
1330 Setters,
1331 PartialEq,
1332 Serialize,
1333)]
1334#[serde(rename_all = "camelCase")]
1335#[builder(
1336 default,
1337 pattern = "owned",
1338 setter(into, strip_option),
1339 build_fn(error = "OciSpecError")
1340)]
1341pub struct LinuxSyscall {
1343 #[getset(get = "pub", set = "pub")]
1344 names: Vec<String>,
1346
1347 #[getset(get_copy = "pub", set = "pub")]
1348 action: LinuxSeccompAction,
1350
1351 #[serde(default, skip_serializing_if = "Option::is_none")]
1352 #[getset(get_copy = "pub", set = "pub")]
1353 errno_ret: Option<u32>,
1355
1356 #[serde(default, skip_serializing_if = "Option::is_none")]
1357 #[getset(get = "pub", set = "pub")]
1358 args: Option<Vec<LinuxSeccompArg>>,
1360}
1361
1362#[derive(
1363 Builder, Clone, Copy, CopyGetters, Debug, Default, Deserialize, Eq, PartialEq, Serialize,
1364)]
1365#[serde(rename_all = "camelCase")]
1366#[builder(
1367 default,
1368 pattern = "owned",
1369 setter(into, strip_option),
1370 build_fn(error = "OciSpecError")
1371)]
1372#[getset(get_copy = "pub", set = "pub")]
1373pub struct LinuxSeccompArg {
1375 index: usize,
1377
1378 value: u64,
1380
1381 #[serde(default, skip_serializing_if = "Option::is_none")]
1382 value_two: Option<u64>,
1384
1385 op: LinuxSeccompOperator,
1387}
1388
1389pub fn get_default_maskedpaths() -> Vec<String> {
1391 vec![
1392 "/proc/acpi".to_string(),
1395 "/proc/asound".to_string(),
1396 "/proc/kcore".to_string(),
1397 "/proc/keys".to_string(),
1398 "/proc/latency_stats".to_string(),
1399 "/proc/timer_list".to_string(),
1400 "/proc/timer_stats".to_string(),
1401 "/proc/sched_debug".to_string(),
1402 "/sys/firmware".to_string(),
1403 "/proc/scsi".to_string(),
1404 ]
1405}
1406
1407pub fn get_default_readonly_paths() -> Vec<String> {
1410 vec![
1411 "/proc/bus".to_string(),
1412 "/proc/fs".to_string(),
1413 "/proc/irq".to_string(),
1414 "/proc/sys".to_string(),
1415 "/proc/sysrq-trigger".to_string(),
1416 ]
1417}
1418
1419#[derive(
1420 Builder,
1421 Clone,
1422 Debug,
1423 Default,
1424 Deserialize,
1425 Eq,
1426 Getters,
1427 MutGetters,
1428 Setters,
1429 PartialEq,
1430 Serialize,
1431)]
1432#[serde(rename_all = "camelCase")]
1433#[builder(
1434 default,
1435 pattern = "owned",
1436 setter(into, strip_option),
1437 build_fn(error = "OciSpecError")
1438)]
1439#[getset(get_mut = "pub", get = "pub", set = "pub")]
1440pub struct LinuxIntelRdt {
1444 #[serde(default, skip_serializing_if = "Option::is_none", rename = "closID")]
1445 clos_id: Option<String>,
1447
1448 #[serde(default, skip_serializing_if = "is_none_or_empty")]
1449 schemata: Option<Vec<String>>,
1454
1455 #[serde(default, skip_serializing_if = "Option::is_none")]
1456 l3_cache_schema: Option<String>,
1460
1461 #[serde(default, skip_serializing_if = "Option::is_none")]
1462 mem_bw_schema: Option<String>,
1469
1470 #[deprecated(
1471 since = "0.10.0",
1472 note = "enable_cmt is deprecated in runtime-spec v1.3.0. Use enable_monitoring instead."
1473 )]
1474 #[serde(default, skip_serializing_if = "Option::is_none")]
1475 enable_cmt: Option<bool>,
1482
1483 #[deprecated(
1484 since = "0.10.0",
1485 note = "enable_mbm is deprecated in runtime-spec v1.3.0. Use enable_monitoring instead."
1486 )]
1487 #[serde(default, skip_serializing_if = "Option::is_none")]
1488 enable_mbm: Option<bool>,
1495
1496 #[serde(default, skip_serializing_if = "Option::is_none")]
1497 enable_monitoring: Option<bool>,
1500}
1501
1502#[derive(
1503 Builder,
1504 Clone,
1505 CopyGetters,
1506 Debug,
1507 Default,
1508 Deserialize,
1509 Eq,
1510 Getters,
1511 Setters,
1512 PartialEq,
1513 Serialize,
1514)]
1515#[builder(
1516 default,
1517 pattern = "owned",
1518 setter(into, strip_option),
1519 build_fn(error = "OciSpecError")
1520)]
1521pub struct LinuxPersonality {
1523 #[getset(get_copy = "pub", set = "pub")]
1524 domain: LinuxPersonalityDomain,
1526
1527 #[serde(default, skip_serializing_if = "Option::is_none")]
1528 #[getset(get = "pub", set = "pub")]
1529 flags: Option<Vec<String>>,
1531}
1532
1533#[derive(
1534 Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize, StrumDisplay, EnumString,
1535)]
1536pub enum LinuxPersonalityDomain {
1538 #[serde(rename = "LINUX")]
1539 #[strum(serialize = "LINUX")]
1540 #[default]
1542 PerLinux,
1543
1544 #[serde(rename = "LINUX32")]
1545 #[strum(serialize = "LINUX32")]
1546 PerLinux32,
1548}
1549
1550#[derive(
1551 Builder,
1552 Clone,
1553 CopyGetters,
1554 Debug,
1555 Deserialize,
1556 Eq,
1557 Getters,
1558 MutGetters,
1559 Setters,
1560 PartialEq,
1561 Serialize,
1562)]
1563#[serde(rename_all = "camelCase")]
1564#[builder(
1565 pattern = "owned",
1566 setter(into, strip_option),
1567 build_fn(error = "OciSpecError")
1568)]
1569pub struct LinuxMemoryPolicy {
1571 #[getset(get_copy = "pub", set = "pub")]
1572 mode: MemoryPolicyModeType,
1574
1575 #[serde(default, skip_serializing_if = "Option::is_none")]
1576 #[getset(get = "pub", set = "pub")]
1577 nodes: Option<String>,
1580
1581 #[serde(default, skip_serializing_if = "Option::is_none")]
1582 #[getset(get = "pub", get_mut = "pub", set = "pub")]
1583 flags: Option<Vec<MemoryPolicyFlagType>>,
1585}
1586
1587impl Default for LinuxMemoryPolicy {
1588 fn default() -> Self {
1589 Self {
1590 mode: MemoryPolicyModeType::MpolDefault,
1591 nodes: None,
1592 flags: None,
1593 }
1594 }
1595}
1596
1597#[derive(
1598 Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize, StrumDisplay, EnumString,
1599)]
1600pub enum MemoryPolicyModeType {
1602 #[serde(rename = "MPOL_DEFAULT")]
1603 #[strum(serialize = "MPOL_DEFAULT")]
1604 #[default]
1606 MpolDefault,
1607
1608 #[serde(rename = "MPOL_BIND")]
1609 #[strum(serialize = "MPOL_BIND")]
1610 MpolBind,
1612
1613 #[serde(rename = "MPOL_INTERLEAVE")]
1614 #[strum(serialize = "MPOL_INTERLEAVE")]
1615 MpolInterleave,
1617
1618 #[serde(rename = "MPOL_WEIGHTED_INTERLEAVE")]
1619 #[strum(serialize = "MPOL_WEIGHTED_INTERLEAVE")]
1620 MpolWeightedInterleave,
1622
1623 #[serde(rename = "MPOL_PREFERRED")]
1624 #[strum(serialize = "MPOL_PREFERRED")]
1625 MpolPreferred,
1627
1628 #[serde(rename = "MPOL_PREFERRED_MANY")]
1629 #[strum(serialize = "MPOL_PREFERRED_MANY")]
1630 MpolPreferredMany,
1632
1633 #[serde(rename = "MPOL_LOCAL")]
1634 #[strum(serialize = "MPOL_LOCAL")]
1635 MpolLocal,
1637}
1638
1639#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize, StrumDisplay, EnumString)]
1640pub enum MemoryPolicyFlagType {
1642 #[serde(rename = "MPOL_F_NUMA_BALANCING")]
1643 #[strum(serialize = "MPOL_F_NUMA_BALANCING")]
1644 MpolFNumaBalancing,
1646
1647 #[serde(rename = "MPOL_F_RELATIVE_NODES")]
1648 #[strum(serialize = "MPOL_F_RELATIVE_NODES")]
1649 MpolFRelativeNodes,
1651
1652 #[serde(rename = "MPOL_F_STATIC_NODES")]
1653 #[strum(serialize = "MPOL_F_STATIC_NODES")]
1654 MpolFStaticNodes,
1656}
1657
1658#[derive(
1659 Builder,
1660 Clone,
1661 CopyGetters,
1662 Debug,
1663 Default,
1664 Deserialize,
1665 Eq,
1666 Getters,
1667 Setters,
1668 PartialEq,
1669 Serialize,
1670)]
1671#[builder(
1672 default,
1673 pattern = "owned",
1674 setter(into, strip_option),
1675 build_fn(error = "OciSpecError")
1676)]
1677pub struct LinuxTimeOffset {
1679 #[serde(default, skip_serializing_if = "Option::is_none")]
1681 #[getset(get_copy = "pub", set = "pub")]
1682 secs: Option<i64>,
1683 #[serde(default, skip_serializing_if = "Option::is_none")]
1685 #[getset(get_copy = "pub", set = "pub")]
1686 nanosecs: Option<u32>,
1687}
1688
1689#[cfg(feature = "proptests")]
1690use quickcheck::{Arbitrary, Gen};
1691
1692#[cfg(feature = "proptests")]
1693fn some_none_generator_util<T: Arbitrary>(g: &mut Gen) -> Option<T> {
1694 let choice = g.choose(&[true, false]).unwrap();
1695 match choice {
1696 false => None,
1697 true => Some(T::arbitrary(g)),
1698 }
1699}
1700
1701#[cfg(feature = "proptests")]
1702impl Arbitrary for LinuxDeviceCgroup {
1703 fn arbitrary(g: &mut Gen) -> LinuxDeviceCgroup {
1704 let typ_choices = ["a", "b", "c", "u", "p"];
1705
1706 let typ_chosen = g.choose(&typ_choices).unwrap();
1707
1708 let typ = match typ_chosen.to_string().as_str() {
1709 "a" => LinuxDeviceType::A,
1710 "b" => LinuxDeviceType::B,
1711 "c" => LinuxDeviceType::C,
1712 "u" => LinuxDeviceType::U,
1713 "p" => LinuxDeviceType::P,
1714 _ => LinuxDeviceType::A,
1715 };
1716
1717 let access_choices = ["rwm", "m"];
1718 LinuxDeviceCgroup {
1719 allow: bool::arbitrary(g),
1720 typ: typ.into(),
1721 major: some_none_generator_util::<i64>(g),
1722 minor: some_none_generator_util::<i64>(g),
1723 access: g.choose(&access_choices).unwrap().to_string().into(),
1724 }
1725 }
1726}
1727
1728#[cfg(feature = "proptests")]
1729impl Arbitrary for LinuxMemory {
1730 #[allow(deprecated)]
1731 fn arbitrary(g: &mut Gen) -> LinuxMemory {
1732 LinuxMemory {
1733 kernel: some_none_generator_util::<i64>(g),
1734 kernel_tcp: some_none_generator_util::<i64>(g),
1735 limit: some_none_generator_util::<i64>(g),
1736 reservation: some_none_generator_util::<i64>(g),
1737 swap: some_none_generator_util::<i64>(g),
1738 swappiness: some_none_generator_util::<u64>(g),
1739 disable_oom_killer: some_none_generator_util::<bool>(g),
1740 use_hierarchy: some_none_generator_util::<bool>(g),
1741 check_before_update: some_none_generator_util::<bool>(g),
1742 }
1743 }
1744}
1745
1746#[cfg(feature = "proptests")]
1747impl Arbitrary for LinuxHugepageLimit {
1748 fn arbitrary(g: &mut Gen) -> LinuxHugepageLimit {
1749 let unit_choice = ["KB", "MB", "GB"];
1750 let unit = g.choose(&unit_choice).unwrap();
1751 let page_size = u64::arbitrary(g).to_string() + unit;
1752
1753 LinuxHugepageLimit {
1754 page_size,
1755 limit: i64::arbitrary(g),
1756 }
1757 }
1758}
1759
1760#[cfg(test)]
1761mod tests {
1762 use super::*;
1763
1764 #[test]
1766 fn device_type_enum_to_str() {
1767 let type_a = LinuxDeviceType::A;
1768 assert_eq!(type_a.as_str(), "a");
1769
1770 let type_b = LinuxDeviceType::B;
1771 assert_eq!(type_b.as_str(), "b");
1772
1773 let type_c = LinuxDeviceType::C;
1774 assert_eq!(type_c.as_str(), "c");
1775 }
1776
1777 #[test]
1778 fn device_type_string_to_enum() {
1779 let devtype_str = "a";
1780 let devtype_enum: LinuxDeviceType = devtype_str.parse().unwrap();
1781 assert_eq!(devtype_enum, LinuxDeviceType::A);
1782
1783 let devtype_str = "b";
1784 let devtype_enum: LinuxDeviceType = devtype_str.parse().unwrap();
1785 assert_eq!(devtype_enum, LinuxDeviceType::B);
1786
1787 let devtype_str = "c";
1788 let devtype_enum: LinuxDeviceType = devtype_str.parse().unwrap();
1789 assert_eq!(devtype_enum, LinuxDeviceType::C);
1790
1791 let invalid_devtype_str = "x";
1792 let unknown_devtype = invalid_devtype_str.parse::<LinuxDeviceType>();
1793 assert!(unknown_devtype.is_err());
1794 }
1795
1796 #[test]
1798 fn ns_type_enum_to_string() {
1799 let type_a = LinuxNamespaceType::Network;
1800 assert_eq!(type_a.to_string(), "net");
1801
1802 let type_b = LinuxNamespaceType::Mount;
1803 assert_eq!(type_b.to_string(), "mnt");
1804
1805 let type_c = LinuxNamespaceType::Ipc;
1806 assert_eq!(type_c.to_string(), "ipc");
1807 }
1808
1809 #[test]
1810 fn ns_type_string_to_enum() {
1811 let nstype_str = "net";
1812 let nstype_enum = LinuxNamespaceType::try_from(nstype_str).unwrap();
1813 assert_eq!(nstype_enum, LinuxNamespaceType::Network);
1814
1815 let nstype_str = "network";
1816 let nstype_enum = LinuxNamespaceType::try_from(nstype_str).unwrap();
1817 assert_eq!(nstype_enum, LinuxNamespaceType::Network);
1818
1819 let nstype_str = "ipc";
1820 let nstype_enum = LinuxNamespaceType::try_from(nstype_str).unwrap();
1821 assert_eq!(nstype_enum, LinuxNamespaceType::Ipc);
1822
1823 let nstype_str = "cgroup";
1824 let nstype_enum = LinuxNamespaceType::try_from(nstype_str).unwrap();
1825 assert_eq!(nstype_enum, LinuxNamespaceType::Cgroup);
1826
1827 let nstype_str = "mount";
1828 let nstype_enum = LinuxNamespaceType::try_from(nstype_str).unwrap();
1829 assert_eq!(nstype_enum, LinuxNamespaceType::Mount);
1830
1831 let invalid_nstype_str = "xxx";
1832 let unknown_nstype = LinuxNamespaceType::try_from(invalid_nstype_str);
1833 assert!(unknown_nstype.is_err());
1834 }
1835
1836 #[test]
1838 fn seccomp_action_enum_to_string() {
1839 let type_a = LinuxSeccompAction::ScmpActKill;
1840 assert_eq!(type_a.to_string(), "SCMP_ACT_KILL");
1841
1842 let type_b = LinuxSeccompAction::ScmpActAllow;
1843 assert_eq!(type_b.to_string(), "SCMP_ACT_ALLOW");
1844
1845 let type_c = LinuxSeccompAction::ScmpActNotify;
1846 assert_eq!(type_c.to_string(), "SCMP_ACT_NOTIFY");
1847 }
1848
1849 #[test]
1850 fn seccomp_action_string_to_enum() {
1851 let action_str = "SCMP_ACT_KILL";
1852 let action_enum: LinuxSeccompAction = action_str.parse().unwrap();
1853 assert_eq!(action_enum, LinuxSeccompAction::ScmpActKill);
1854
1855 let action_str = "SCMP_ACT_ALLOW";
1856 let action_enum: LinuxSeccompAction = action_str.parse().unwrap();
1857 assert_eq!(action_enum, LinuxSeccompAction::ScmpActAllow);
1858
1859 let action_str = "SCMP_ACT_NOTIFY";
1860 let action_enum: LinuxSeccompAction = action_str.parse().unwrap();
1861 assert_eq!(action_enum, LinuxSeccompAction::ScmpActNotify);
1862
1863 let invalid_action_str = "x";
1864 let unknown_action = invalid_action_str.parse::<LinuxSeccompAction>();
1865 assert!(unknown_action.is_err());
1866 }
1867
1868 #[test]
1870 fn seccomp_arch_enum_to_string() {
1871 let type_a = Arch::ScmpArchX86_64;
1872 assert_eq!(type_a.to_string(), "SCMP_ARCH_X86_64");
1873
1874 let type_b = Arch::ScmpArchAarch64;
1875 assert_eq!(type_b.to_string(), "SCMP_ARCH_AARCH64");
1876
1877 let type_c = Arch::ScmpArchPpc64le;
1878 assert_eq!(type_c.to_string(), "SCMP_ARCH_PPC64LE");
1879
1880 let type_d = Arch::ScmpArchParisc;
1881 assert_eq!(type_d.to_string(), "SCMP_ARCH_PARISC");
1882
1883 let type_e = Arch::ScmpArchParisc64;
1884 assert_eq!(type_e.to_string(), "SCMP_ARCH_PARISC64");
1885
1886 let type_f = Arch::ScmpArchLoongarch64;
1887 assert_eq!(type_f.to_string(), "SCMP_ARCH_LOONGARCH64");
1888
1889 let type_g = Arch::ScmpArchM68k;
1890 assert_eq!(type_g.to_string(), "SCMP_ARCH_M68K");
1891
1892 let type_h = Arch::ScmpArchSh;
1893 assert_eq!(type_h.to_string(), "SCMP_ARCH_SH");
1894
1895 let type_i = Arch::ScmpArchSheb;
1896 assert_eq!(type_i.to_string(), "SCMP_ARCH_SHEB");
1897 }
1898
1899 #[test]
1900 fn seccomp_arch_string_to_enum() {
1901 let arch_type_str = "SCMP_ARCH_X86_64";
1902 let arch_type_enum: Arch = arch_type_str.parse().unwrap();
1903 assert_eq!(arch_type_enum, Arch::ScmpArchX86_64);
1904
1905 let arch_type_str = "SCMP_ARCH_AARCH64";
1906 let arch_type_enum: Arch = arch_type_str.parse().unwrap();
1907 assert_eq!(arch_type_enum, Arch::ScmpArchAarch64);
1908
1909 let arch_type_str = "SCMP_ARCH_PPC64LE";
1910 let arch_type_enum: Arch = arch_type_str.parse().unwrap();
1911 assert_eq!(arch_type_enum, Arch::ScmpArchPpc64le);
1912
1913 let arch_type_str = "SCMP_ARCH_PARISC";
1914 let arch_type_enum: Arch = arch_type_str.parse().unwrap();
1915 assert_eq!(arch_type_enum, Arch::ScmpArchParisc);
1916
1917 let arch_type_str = "SCMP_ARCH_PARISC64";
1918 let arch_type_enum: Arch = arch_type_str.parse().unwrap();
1919 assert_eq!(arch_type_enum, Arch::ScmpArchParisc64);
1920
1921 let arch_type_str = "SCMP_ARCH_LOONGARCH64";
1922 let arch_type_enum: Arch = arch_type_str.parse().unwrap();
1923 assert_eq!(arch_type_enum, Arch::ScmpArchLoongarch64);
1924
1925 let arch_type_str = "SCMP_ARCH_M68K";
1926 let arch_type_enum: Arch = arch_type_str.parse().unwrap();
1927 assert_eq!(arch_type_enum, Arch::ScmpArchM68k);
1928
1929 let arch_type_str = "SCMP_ARCH_SH";
1930 let arch_type_enum: Arch = arch_type_str.parse().unwrap();
1931 assert_eq!(arch_type_enum, Arch::ScmpArchSh);
1932
1933 let arch_type_str = "SCMP_ARCH_SHEB";
1934 let arch_type_enum: Arch = arch_type_str.parse().unwrap();
1935 assert_eq!(arch_type_enum, Arch::ScmpArchSheb);
1936
1937 let invalid_arch_str = "x";
1938 let unknown_arch = invalid_arch_str.parse::<Arch>();
1939 assert!(unknown_arch.is_err());
1940 }
1941
1942 #[test]
1944 fn seccomp_filter_flag_enum_to_string() {
1945 let type_a = LinuxSeccompFilterFlag::SeccompFilterFlagLog;
1946 assert_eq!(type_a.to_string(), "SECCOMP_FILTER_FLAG_LOG");
1947
1948 let type_b = LinuxSeccompFilterFlag::SeccompFilterFlagTsync;
1949 assert_eq!(type_b.to_string(), "SECCOMP_FILTER_FLAG_TSYNC");
1950
1951 let type_c = LinuxSeccompFilterFlag::SeccompFilterFlagSpecAllow;
1952 assert_eq!(type_c.to_string(), "SECCOMP_FILTER_FLAG_SPEC_ALLOW");
1953
1954 let type_d = LinuxSeccompFilterFlag::SeccompFilterFlagWaitKillableRecv;
1955 assert_eq!(type_d.to_string(), "SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV");
1956 }
1957
1958 #[test]
1959 fn seccomp_filter_flag_string_to_enum() {
1960 let filter_flag_type_str = "SECCOMP_FILTER_FLAG_LOG";
1961 let filter_flag_type_enum: LinuxSeccompFilterFlag = filter_flag_type_str.parse().unwrap();
1962 assert_eq!(
1963 filter_flag_type_enum,
1964 LinuxSeccompFilterFlag::SeccompFilterFlagLog
1965 );
1966
1967 let filter_flag_type_str = "SECCOMP_FILTER_FLAG_TSYNC";
1968 let filter_flag_type_enum: LinuxSeccompFilterFlag = filter_flag_type_str.parse().unwrap();
1969 assert_eq!(
1970 filter_flag_type_enum,
1971 LinuxSeccompFilterFlag::SeccompFilterFlagTsync
1972 );
1973
1974 let filter_flag_type_str = "SECCOMP_FILTER_FLAG_SPEC_ALLOW";
1975 let filter_flag_type_enum: LinuxSeccompFilterFlag = filter_flag_type_str.parse().unwrap();
1976 assert_eq!(
1977 filter_flag_type_enum,
1978 LinuxSeccompFilterFlag::SeccompFilterFlagSpecAllow
1979 );
1980
1981 let filter_flag_type_str = "SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV";
1982 let filter_flag_type_enum: LinuxSeccompFilterFlag = filter_flag_type_str.parse().unwrap();
1983 assert_eq!(
1984 filter_flag_type_enum,
1985 LinuxSeccompFilterFlag::SeccompFilterFlagWaitKillableRecv
1986 );
1987
1988 let invalid_filter_flag_str = "x";
1989 let unknown_arch = invalid_filter_flag_str.parse::<LinuxSeccompFilterFlag>();
1990 assert!(unknown_arch.is_err());
1991 }
1992
1993 #[test]
1995 fn seccomp_operator_enum_to_string() {
1996 let type_a = LinuxSeccompOperator::ScmpCmpNe;
1997 assert_eq!(type_a.to_string(), "SCMP_CMP_NE");
1998
1999 let type_b = LinuxSeccompOperator::ScmpCmpMaskedEq;
2000 assert_eq!(type_b.to_string(), "SCMP_CMP_MASKED_EQ");
2001
2002 let type_c = LinuxSeccompOperator::ScmpCmpGt;
2003 assert_eq!(type_c.to_string(), "SCMP_CMP_GT");
2004 }
2005
2006 #[test]
2008 fn seccomp_action_as_u32() {
2009 let action = LinuxSeccompAction::ScmpActErrno;
2010 assert_eq!(action.as_u32(Option::None), 0x00050001);
2011
2012 let action = LinuxSeccompAction::ScmpActErrno;
2013 assert_eq!(action.as_u32(Option::Some(10)), 0x00050000 | 10);
2014
2015 let action = LinuxSeccompAction::ScmpActTrace;
2016 assert_eq!(action.as_u32(Option::None), 0x7ff00001);
2017
2018 let action = LinuxSeccompAction::ScmpActTrace;
2019 assert_eq!(action.as_u32(Option::Some(10)), 0x7ff00000 | 10);
2020 }
2021
2022 #[test]
2023 fn seccomp_operator_string_to_enum() {
2024 let seccomp_operator_str = "SCMP_CMP_GT";
2025 let seccomp_operator_enum: LinuxSeccompOperator = seccomp_operator_str.parse().unwrap();
2026 assert_eq!(seccomp_operator_enum, LinuxSeccompOperator::ScmpCmpGt);
2027
2028 let seccomp_operator_str = "SCMP_CMP_NE";
2029 let seccomp_operator_enum: LinuxSeccompOperator = seccomp_operator_str.parse().unwrap();
2030 assert_eq!(seccomp_operator_enum, LinuxSeccompOperator::ScmpCmpNe);
2031
2032 let seccomp_operator_str = "SCMP_CMP_MASKED_EQ";
2033 let seccomp_operator_enum: LinuxSeccompOperator = seccomp_operator_str.parse().unwrap();
2034 assert_eq!(seccomp_operator_enum, LinuxSeccompOperator::ScmpCmpMaskedEq);
2035
2036 let invalid_seccomp_operator_str = "x";
2037 let unknown_operator = invalid_seccomp_operator_str.parse::<LinuxSeccompOperator>();
2038 assert!(unknown_operator.is_err());
2039 }
2040
2041 #[test]
2043 fn memory_policy_mode_enum_to_string() {
2044 let mode_a = MemoryPolicyModeType::MpolDefault;
2045 assert_eq!(mode_a.to_string(), "MPOL_DEFAULT");
2046
2047 let mode_b = MemoryPolicyModeType::MpolBind;
2048 assert_eq!(mode_b.to_string(), "MPOL_BIND");
2049
2050 let mode_c = MemoryPolicyModeType::MpolInterleave;
2051 assert_eq!(mode_c.to_string(), "MPOL_INTERLEAVE");
2052
2053 let mode_d = MemoryPolicyModeType::MpolWeightedInterleave;
2054 assert_eq!(mode_d.to_string(), "MPOL_WEIGHTED_INTERLEAVE");
2055
2056 let mode_e = MemoryPolicyModeType::MpolPreferred;
2057 assert_eq!(mode_e.to_string(), "MPOL_PREFERRED");
2058
2059 let mode_f = MemoryPolicyModeType::MpolPreferredMany;
2060 assert_eq!(mode_f.to_string(), "MPOL_PREFERRED_MANY");
2061
2062 let mode_g = MemoryPolicyModeType::MpolLocal;
2063 assert_eq!(mode_g.to_string(), "MPOL_LOCAL");
2064 }
2065
2066 #[test]
2067 fn memory_policy_mode_string_to_enum() {
2068 let mode_str = "MPOL_INTERLEAVE";
2069 let mode_enum: MemoryPolicyModeType = mode_str.parse().unwrap();
2070 assert_eq!(mode_enum, MemoryPolicyModeType::MpolInterleave);
2071
2072 let mode_str = "MPOL_BIND";
2073 let mode_enum: MemoryPolicyModeType = mode_str.parse().unwrap();
2074 assert_eq!(mode_enum, MemoryPolicyModeType::MpolBind);
2075
2076 let mode_str = "MPOL_DEFAULT";
2077 let mode_enum: MemoryPolicyModeType = mode_str.parse().unwrap();
2078 assert_eq!(mode_enum, MemoryPolicyModeType::MpolDefault);
2079
2080 let mode_str = "MPOL_WEIGHTED_INTERLEAVE";
2081 let mode_enum: MemoryPolicyModeType = mode_str.parse().unwrap();
2082 assert_eq!(mode_enum, MemoryPolicyModeType::MpolWeightedInterleave);
2083
2084 let mode_str = "MPOL_PREFERRED";
2085 let mode_enum: MemoryPolicyModeType = mode_str.parse().unwrap();
2086 assert_eq!(mode_enum, MemoryPolicyModeType::MpolPreferred);
2087
2088 let mode_str = "MPOL_PREFERRED_MANY";
2089 let mode_enum: MemoryPolicyModeType = mode_str.parse().unwrap();
2090 assert_eq!(mode_enum, MemoryPolicyModeType::MpolPreferredMany);
2091
2092 let mode_str = "MPOL_LOCAL";
2093 let mode_enum: MemoryPolicyModeType = mode_str.parse().unwrap();
2094 assert_eq!(mode_enum, MemoryPolicyModeType::MpolLocal);
2095
2096 let invalid_mode_str = "INVALID_MODE";
2097 let unknown_mode = invalid_mode_str.parse::<MemoryPolicyModeType>();
2098 assert!(unknown_mode.is_err());
2099 }
2100
2101 #[test]
2103 fn memory_policy_flag_enum_to_string() {
2104 let flag_a = MemoryPolicyFlagType::MpolFNumaBalancing;
2105 assert_eq!(flag_a.to_string(), "MPOL_F_NUMA_BALANCING");
2106
2107 let flag_b = MemoryPolicyFlagType::MpolFRelativeNodes;
2108 assert_eq!(flag_b.to_string(), "MPOL_F_RELATIVE_NODES");
2109
2110 let flag_c = MemoryPolicyFlagType::MpolFStaticNodes;
2111 assert_eq!(flag_c.to_string(), "MPOL_F_STATIC_NODES");
2112 }
2113
2114 #[test]
2115 fn memory_policy_flag_string_to_enum() {
2116 let flag_str = "MPOL_F_NUMA_BALANCING";
2117 let flag_enum: MemoryPolicyFlagType = flag_str.parse().unwrap();
2118 assert_eq!(flag_enum, MemoryPolicyFlagType::MpolFNumaBalancing);
2119
2120 let flag_str = "MPOL_F_RELATIVE_NODES";
2121 let flag_enum: MemoryPolicyFlagType = flag_str.parse().unwrap();
2122 assert_eq!(flag_enum, MemoryPolicyFlagType::MpolFRelativeNodes);
2123
2124 let flag_str = "MPOL_F_STATIC_NODES";
2125 let flag_enum: MemoryPolicyFlagType = flag_str.parse().unwrap();
2126 assert_eq!(flag_enum, MemoryPolicyFlagType::MpolFStaticNodes);
2127
2128 let invalid_flag_str = "INVALID_FLAG";
2129 let unknown_flag = invalid_flag_str.parse::<MemoryPolicyFlagType>();
2130 assert!(unknown_flag.is_err());
2131 }
2132
2133 #[test]
2134 fn test_linux_memory_policy_serialization() {
2135 let memory_policy = LinuxMemoryPolicy {
2136 mode: MemoryPolicyModeType::MpolInterleave,
2137 nodes: Some("0-3,7".to_string()),
2138 flags: Some(vec![
2139 MemoryPolicyFlagType::MpolFStaticNodes,
2140 MemoryPolicyFlagType::MpolFRelativeNodes,
2141 ]),
2142 };
2143
2144 let json = serde_json::to_string(&memory_policy).unwrap();
2145 let deserialized: LinuxMemoryPolicy = serde_json::from_str(&json).unwrap();
2146
2147 assert_eq!(deserialized.mode, MemoryPolicyModeType::MpolInterleave);
2148 assert_eq!(deserialized.nodes, Some("0-3,7".to_string()));
2149 assert_eq!(
2150 deserialized.flags,
2151 Some(vec![
2152 MemoryPolicyFlagType::MpolFStaticNodes,
2153 MemoryPolicyFlagType::MpolFRelativeNodes,
2154 ])
2155 );
2156 }
2157
2158 #[test]
2159 fn test_linux_memory_policy_default() {
2160 let memory_policy = LinuxMemoryPolicy::default();
2161 assert_eq!(memory_policy.mode, MemoryPolicyModeType::MpolDefault);
2162 assert_eq!(memory_policy.nodes, None);
2163 assert_eq!(memory_policy.flags, None);
2164 }
2165}