-
Notifications
You must be signed in to change notification settings - Fork 85
/
host-device-plugin.rs
109 lines (87 loc) · 3.2 KB
/
host-device-plugin.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
//! This is just an example plugin, do not use it in production!
use std::{collections::HashMap, os::fd::AsFd};
use netavark::{
network::{
core_utils::{open_netlink_sockets, CoreUtils},
netlink, types,
},
new_error,
plugin::{Info, Plugin, PluginExec, API_VERSION},
};
use netlink_packet_route::{address::AddressAttribute, link::LinkAttribute};
fn main() {
let info = Info::new("0.1.0-dev".to_owned(), API_VERSION.to_owned(), None);
PluginExec::new(Exec {}, info).exec();
}
struct Exec {}
impl Plugin for Exec {
fn create(
&self,
network: types::Network,
) -> Result<types::Network, Box<dyn std::error::Error>> {
if network.network_interface.as_deref().unwrap_or_default() == "" {
return Err(new_error!("no network interface is specified"));
}
Ok(network)
}
fn setup(
&self,
netns: String,
opts: types::NetworkPluginExec,
) -> Result<types::StatusBlock, Box<dyn std::error::Error>> {
let (mut host, netns) = open_netlink_sockets(&netns)?;
let name = opts.network.network_interface.unwrap_or_default();
let link = host.netlink.get_link(netlink::LinkID::Name(name.clone()))?;
let mut mac_address = String::from("");
for nla in link.attributes {
if let LinkAttribute::Address(ref addr) = nla {
mac_address = CoreUtils::encode_address_to_hex(addr);
}
}
let addresses = host.netlink.dump_addresses()?;
let mut subnets = Vec::new();
for address in addresses {
if address.header.index == link.header.index {
for nla in address.attributes {
if let AddressAttribute::Address(ip) = &nla {
let net = ipnet::IpNet::new(*ip, address.header.prefix_len)?;
subnets.push(types::NetAddress {
gateway: None,
ipnet: net,
})
}
}
}
}
host.netlink
.set_link_ns(link.header.index, netns.file.as_fd())?;
// interfaces map, but we only ever expect one, for response
let mut interfaces: HashMap<String, types::NetInterface> = HashMap::new();
let interface = types::NetInterface {
mac_address,
subnets: Option::from(subnets),
};
interfaces.insert(name, interface);
// StatusBlock response
let response = types::StatusBlock {
dns_server_ips: None,
dns_search_domains: None,
interfaces: Some(interfaces),
};
Ok(response)
}
fn teardown(
&self,
netns: String,
opts: types::NetworkPluginExec,
) -> Result<(), Box<dyn std::error::Error>> {
// on teardown revert what was done in setup
let (host, mut netns) = open_netlink_sockets(&netns)?;
let name = opts.network.network_interface.unwrap_or_default();
let link = netns.netlink.get_link(netlink::LinkID::Name(name))?;
netns
.netlink
.set_link_ns(link.header.index, host.file.as_fd())?;
Ok(())
}
}