1use log::{debug, error, info, trace};
2use std::{collections::HashMap, sync::Arc};
3
4use crate::libcni::{
5 self,
6 api::{RuntimeConf, CNI},
7};
8
9pub struct Network {
10 pub cni: Arc<Box<dyn CNI + Send + Sync>>,
11 pub config: libcni::api::NetworkConfigList,
12 pub ifname: String,
13}
14
15impl Network {
16 pub fn attach(&self, ns: &Namespace) -> Result<(), String> {
17 debug!(
18 "Attaching network {} with interface {}",
19 self.config.name, self.ifname
20 );
21
22 match self
23 .cni
24 .add_network_list(self.config.clone(), ns.config(self.ifname.clone()))
25 {
26 Ok(result) => {
27 info!(
28 "Successfully attached network {} to namespace",
29 self.config.name
30 );
31 trace!("Network attachment result: {:?}", result.get_json());
32 Ok(())
33 }
34 Err(e) => Err(e.to_string()),
35 }
36 }
37
38 pub fn remove(&self, ns: &Namespace) -> Result<(), String> {
39 debug!(
40 "Removing network {} with interface {}",
41 self.config.name, self.ifname
42 );
43
44 match self
45 .cni
46 .delete_network_list(self.config.clone(), ns.config(self.ifname.clone()))
47 {
48 Ok(_) => {
49 info!(
50 "Successfully removed network {} from namespace",
51 self.config.name
52 );
53 Ok(())
54 }
55 Err(e) => {
56 let err_msg = format!("Failed to remove network {}: {}", self.config.name, e);
57 error!("{}", err_msg);
58 Err(err_msg)
59 }
60 }
61 }
62
63 pub fn check(&self, ns: &Namespace) -> Result<(), String> {
64 debug!(
65 "Checking network {} with interface {}",
66 self.config.name, self.ifname
67 );
68
69 match self
70 .cni
71 .check_network_list(self.config.clone(), ns.config(self.ifname.clone()))
72 {
73 Ok(_) => {
74 debug!("Network {} is properly configured", self.config.name);
75 Ok(())
76 }
77 Err(e) => {
78 let err_msg = format!("Network check failed for {}: {}", self.config.name, e);
79 error!("{}", err_msg);
80 Err(err_msg)
81 }
82 }
83 }
84
85 pub fn get_stats(&self, ns: &Namespace) -> Result<String, String> {
86 debug!(
87 "Getting stats for network {} with interface {}",
88 self.config.name, self.ifname
89 );
90
91 match self
92 .cni
93 .get_network_list_cached_result(self.config.clone(), ns.config(self.ifname.clone()))
94 {
95 Ok(result) => {
96 let stats_json = result.get_json().dump();
97 trace!("Network stats: {}", stats_json);
98 Ok(stats_json)
99 }
100 Err(e) => {
101 let err_msg = format!(
102 "Failed to get stats for network {}: {}",
103 self.config.name, e
104 );
105 error!("{}", err_msg);
106 Err(err_msg)
107 }
108 }
109 }
110}
111
112#[derive(Clone, Default)]
113pub struct Namespace {
114 id: String,
115 path: String,
116 capability_args: HashMap<String, String>,
117 args: HashMap<String, String>,
118}
119
120impl Namespace {
121 pub fn new(id: String, path: String) -> Self {
122 debug!(
123 "Creating new namespace for container {} at path {}",
124 id, path
125 );
126 Self {
127 id,
128 path,
129 capability_args: HashMap::default(),
130 args: HashMap::default(),
131 }
132 }
133
134 pub fn with_args(mut self, args: HashMap<String, String>) -> Self {
135 debug!("Adding {} arguments to namespace", args.len());
136 self.args = args;
137 self
138 }
139
140 pub fn with_capabilities(mut self, capabilities: HashMap<String, String>) -> Self {
141 debug!("Adding {} capabilities to namespace", capabilities.len());
142 self.capability_args = capabilities;
143 self
144 }
145
146 pub fn add_arg(&mut self, key: &str, value: &str) {
147 debug!("Adding argument {}={} to namespace", key, value);
148 self.args.insert(key.to_string(), value.to_string());
149 }
150
151 pub fn add_capability(&mut self, key: &str, value: &str) {
152 debug!("Adding capability {}={} to namespace", key, value);
153 self.capability_args
154 .insert(key.to_string(), value.to_string());
155 }
156
157 pub fn config(&self, ifname: String) -> libcni::api::RuntimeConf {
158 trace!(
159 "Creating runtime config for namespace with interface {}",
160 ifname
161 );
162 let args = self
163 .args
164 .iter()
165 .map(|(key, val)| [key.clone(), val.clone()])
166 .collect();
167
168 RuntimeConf {
169 container_id: self.id.clone(),
170 net_ns: self.path.clone(),
171 if_name: ifname,
172 args,
173 capability_args: self.capability_args.clone(),
174 cache_dir: String::default(),
175 }
176 }
177
178 pub fn get_id(&self) -> &str {
179 &self.id
180 }
181
182 pub fn get_path(&self) -> &str {
183 &self.path
184 }
185}