emu_cli/network/
mod.rs

1// all of this code and everything underneath it is dead currently. I am building it slowly as I
2// solve several problems towards making it reality.
3
4mod address;
5mod netlink;
6mod subnet;
7
8use self::address::Address;
9use crate::vm::VM;
10
11use anyhow::Result;
12use async_trait::async_trait;
13use serde::{Deserialize, Serialize};
14use std::{collections::HashMap, path::PathBuf};
15
16pub trait Network<'a>: Send + Clone + Default + Serialize + Deserialize<'a> {
17    fn name(&self) -> String;
18    fn set_name(&self, name: String) -> Self;
19
20    // optional
21    fn index(&self) -> Option<u32>;
22    fn set_index(&self, index: u32) -> Self;
23}
24
25pub trait NetworkInterface: Send + Default {
26    fn name(&self) -> String;
27    fn addresses(&self) -> Vec<Address>;
28
29    // optional stuff
30    fn peer_name(&self) -> Option<String>;
31    fn index(&self) -> Option<u32>;
32    fn id(&self) -> Option<u32>;
33}
34
35#[async_trait]
36pub trait NetworkManager<'a, I, N>
37where
38    Self: Clone,
39    I: NetworkInterface,
40    N: Network<'a>,
41{
42    async fn create_network(&self, name: &str) -> Result<N>;
43    async fn delete_network(&self, network: N) -> Result<()>;
44    async fn exists_network(&self, network: N) -> Result<bool>;
45    async fn create_interface(&self, network: N, id: u32) -> Result<I>;
46    async fn delete_interface(&self, interface: I) -> Result<()>;
47    async fn exists_interface(&self, interface: I) -> Result<bool>;
48    async fn bind(&self, network: N, interface: I) -> Result<()>;
49    async fn unbind(&self, interface: I) -> Result<()>;
50    async fn add_address(&self, interface: I, address: &Address) -> Result<()>;
51}
52
53pub trait VMInterface<N>
54where
55    Self: Default,
56    N: Network<'static>,
57{
58    fn add_to_network(&self, network: N) -> Result<()>;
59    fn remove_from_network(&self, network: N) -> Result<()>;
60    fn configure_addresses(&self, addresses: Vec<Address>) -> Result<()>;
61}
62
63#[derive(Debug, Clone, Default)]
64pub struct VMNetwork<V, I, N>
65where
66    N: Network<'static>,
67    V: VMInterface<N>,
68    I: NetworkInterface,
69{
70    network: N,
71    vms: HashMap<String, VM>,
72    vm: std::marker::PhantomData<V>,
73    interface: std::marker::PhantomData<I>,
74}
75
76impl<V, T, N> VMNetwork<V, T, N>
77where
78    N: Network<'static>,
79    V: VMInterface<N>,
80    T: NetworkInterface,
81{
82    pub fn add_vm(&mut self, vm: &VM) -> Result<()> {
83        self.vms.insert(vm.name(), vm.clone());
84        Ok(())
85    }
86
87    pub fn remove_vm(&mut self, vm: &VM) -> Result<()> {
88        self.vms.remove(&vm.name());
89        Ok(())
90    }
91
92    pub fn list(&self) -> Result<Vec<VM>> {
93        Ok(self.vms.values().map(Clone::clone).collect::<Vec<VM>>())
94    }
95
96    pub fn network(&self) -> N {
97        self.network.clone()
98    }
99}
100
101pub type NetworkMap = HashMap<String, Vec<String>>;
102pub type NetworkIndexMap = HashMap<String, u32>;
103
104#[derive(Debug, Clone, Default, Serialize, Deserialize)]
105pub struct NetworkConfig {
106    networks: NetworkMap,
107    indexes: NetworkIndexMap,
108}
109
110pub type VMNetworkMap<V, T, N> = HashMap<String, VMNetwork<V, T, N>>;
111
112pub struct NetworkList<V, M, T, N>
113where
114    N: Network<'static>,
115    V: VMInterface<N>,
116    M: NetworkManager<'static, T, N>,
117    T: NetworkInterface,
118{
119    networks: VMNetworkMap<V, T, N>,
120    manager: M,
121}
122
123impl<V, M, T, N> NetworkList<V, M, T, N>
124where
125    N: Network<'static>,
126    V: VMInterface<N>,
127    M: NetworkManager<'static, T, N>,
128    T: NetworkInterface,
129{
130    pub fn create(&self, _: String) -> Result<()> {
131        Ok(())
132    }
133
134    pub fn teardown(&self, _: String) -> Result<()> {
135        Ok(())
136    }
137
138    pub fn save(&self, filename: PathBuf) -> Result<()> {
139        let mut config = NetworkConfig::default();
140
141        for (name, network) in &self.networks {
142            config.networks.insert(
143                name.to_string(),
144                network
145                    .list()?
146                    .iter()
147                    .map(|n| n.name())
148                    .collect::<Vec<String>>(),
149            );
150
151            config.indexes.insert(
152                network.network().name(),
153                network.network().index().unwrap_or_default(),
154            );
155        }
156
157        Ok(std::fs::write(filename, toml::to_string(&config)?)?)
158    }
159
160    pub fn load(manager: M, filename: PathBuf) -> Result<Self> {
161        let map: NetworkConfig = toml::from_str(&std::fs::read_to_string(filename)?)?;
162        let mut networks = VMNetworkMap::default();
163
164        for (key, vms) in map.networks {
165            let mut tmp: HashMap<String, VM> = HashMap::default();
166            for vm in vms {
167                tmp.insert(vm.clone(), vm.clone().into());
168            }
169
170            networks.insert(
171                key.to_string(),
172                VMNetwork {
173                    network: N::default()
174                        .set_name(key.to_string())
175                        .set_index(map.indexes.get(&key).map_or_else(|| 0, |x| *x)),
176                    vms: tmp,
177                    ..Default::default()
178                },
179            );
180        }
181
182        Ok(Self { networks, manager })
183    }
184
185    pub fn manager(&self) -> M {
186        self.manager.clone()
187    }
188}
189
190impl<V, M, T, N> std::ops::Deref for NetworkList<V, M, T, N>
191where
192    N: Network<'static>,
193    V: VMInterface<N>,
194    M: NetworkManager<'static, T, N>,
195    T: NetworkInterface,
196{
197    type Target = HashMap<String, VMNetwork<V, T, N>>;
198
199    fn deref(&self) -> &Self::Target {
200        &self.networks
201    }
202}
203
204impl<V, M, T, N> std::ops::DerefMut for NetworkList<V, M, T, N>
205where
206    N: Network<'static>,
207    V: VMInterface<N>,
208    M: NetworkManager<'static, T, N>,
209    T: NetworkInterface,
210{
211    fn deref_mut(&mut self) -> &mut Self::Target {
212        &mut self.networks
213    }
214}