]> git.proxmox.com Git - pve-network.git/blame - PVE/Network/SDN/Zones.pm
whitespace cleanup
[pve-network.git] / PVE / Network / SDN / Zones.pm
CommitLineData
f5eabba0
AD
1package PVE::Network::SDN::Zones;
2
3use strict;
4use warnings;
5
6use Data::Dumper;
7use JSON;
8
9use PVE::Tools qw(extract_param dir_glob_regex run_command);
10use PVE::Cluster qw(cfs_read_file cfs_write_file cfs_lock_file);
11
12use PVE::Network::SDN::Vnets;
13use PVE::Network::SDN::Zones::VlanPlugin;
14use PVE::Network::SDN::Zones::QinQPlugin;
15use PVE::Network::SDN::Zones::VxlanPlugin;
16use PVE::Network::SDN::Zones::EvpnPlugin;
17use PVE::Network::SDN::Zones::FaucetPlugin;
18use PVE::Network::SDN::Zones::Plugin;
19
20PVE::Network::SDN::Zones::VlanPlugin->register();
21PVE::Network::SDN::Zones::QinQPlugin->register();
22PVE::Network::SDN::Zones::VxlanPlugin->register();
23PVE::Network::SDN::Zones::EvpnPlugin->register();
24PVE::Network::SDN::Zones::FaucetPlugin->register();
25PVE::Network::SDN::Zones::Plugin->init();
26
27
28sub sdn_zones_config {
29 my ($cfg, $id, $noerr) = @_;
30
31 die "no sdn zone ID specified\n" if !$id;
32
33 my $scfg = $cfg->{ids}->{$id};
b2d83056 34 die "sdn '$id' does not exist\n" if (!$noerr && !$scfg);
f5eabba0
AD
35
36 return $scfg;
37}
38
39sub config {
40 my $config = cfs_read_file("sdn/zones.cfg.new");
41 $config = cfs_read_file("sdn/zones.cfg") if !keys %{$config->{ids}};
42 return $config;
43}
44
45sub write_config {
46 my ($cfg) = @_;
47
48 cfs_write_file("sdn/zones.cfg.new", $cfg);
49}
50
51sub lock_sdn_zones_config {
52 my ($code, $errmsg) = @_;
53
54 cfs_lock_file("sdn/zones.cfg.new", undef, $code);
55 if (my $err = $@) {
56 $errmsg ? die "$errmsg: $err" : die $err;
57 }
58}
59
60sub sdn_zones_ids {
61 my ($cfg) = @_;
62
63 return keys %{$cfg->{ids}};
64}
65
66sub complete_sdn_zone {
67 my ($cmdname, $pname, $cvalue) = @_;
68
69 my $cfg = PVE::Network::SDN::config();
70
71 return $cmdname eq 'add' ? [] : [ PVE::Network::SDN::sdn_zones_ids($cfg) ];
72}
73
74
75sub generate_etc_network_config {
76
77 my $vnet_cfg = PVE::Cluster::cfs_read_file('sdn/vnets.cfg');
56cdcac9 78 my $zone_cfg = PVE::Cluster::cfs_read_file('sdn/zones.cfg');
4405f2de 79 my $controller_cfg = PVE::Cluster::cfs_read_file('sdn/controllers.cfg');
56cdcac9 80 return if !$vnet_cfg && !$zone_cfg;
f5eabba0 81
ba7ac021 82 my $interfaces_config = PVE::INotify::read_file('interfaces');
f5eabba0
AD
83
84 #generate configuration
85 my $config = {};
c2b9c173
AD
86 my $nodename = PVE::INotify::nodename();
87
f5eabba0
AD
88 foreach my $id (keys %{$vnet_cfg->{ids}}) {
89 my $vnet = $vnet_cfg->{ids}->{$id};
3fd3e917 90 my $zone = $vnet->{zone};
f5eabba0
AD
91
92 if(!$zone) {
93 warn "can't generate vnet $vnet : zone $zone don't exist";
94 next;
95 }
96
56cdcac9 97 my $plugin_config = $zone_cfg->{ids}->{$zone};
f5eabba0
AD
98
99 if (!defined($plugin_config)) {
100 warn "can't generate vnet $vnet : zone $zone don't exist";
101 next;
102 }
103
c2b9c173
AD
104 next if defined($plugin_config->{nodes}) && !$plugin_config->{nodes}->{$nodename};
105
4405f2de
AD
106 my $controller = undef;
107 if($plugin_config->{controller}) {
108 my $controllerid = $plugin_config->{controller};
109 $controller = $controller_cfg->{ids}->{$controllerid};
110 }
111
f5eabba0 112 my $plugin = PVE::Network::SDN::Zones::Plugin->lookup($plugin_config->{type});
ba7ac021 113 $plugin->generate_sdn_config($plugin_config, $zone, $id, $vnet, $controller, $interfaces_config, $config);
f5eabba0
AD
114 }
115
116 my $raw_network_config = "";
117 foreach my $iface (keys %$config) {
118 $raw_network_config .= "\n";
119 $raw_network_config .= "auto $iface\n";
120 $raw_network_config .= "iface $iface\n";
121 foreach my $option (@{$config->{$iface}}) {
122 $raw_network_config .= "\t$option\n";
123 }
124 }
125
126 return $raw_network_config;
127}
128
129sub write_etc_network_config {
130 my ($rawconfig) = @_;
131
132 return if !$rawconfig;
133 my $sdn_interfaces_file = "/etc/network/interfaces.d/sdn";
134
135 my $writefh = IO::File->new($sdn_interfaces_file,">");
136 print $writefh $rawconfig;
137 $writefh->close();
138}
139
140sub ifquery_check {
141
142 my $cmd = ['ifquery', '-a', '-c', '-o','json'];
143
144 my $result = '';
145 my $reader = sub { $result .= shift };
146
147 eval {
148 run_command($cmd, outfunc => $reader);
149 };
150
151 my $resultjson = decode_json($result);
152 my $interfaces = {};
153
154 foreach my $interface (@$resultjson) {
155 my $name = $interface->{name};
156 $interfaces->{$name} = {
157 status => $interface->{status},
158 config => $interface->{config},
159 config_status => $interface->{config_status},
160 };
161 }
162
163 return $interfaces;
164}
165
166# improve me : move status code inside plugins ?
167sub status {
168
169 my $cluster_vnet_file = "/etc/pve/sdn/vnets.cfg";
56cdcac9 170 my $cluster_zone_file = "/etc/pve/sdn/zones.cfg";
f5eabba0
AD
171 my $local_sdn_file = "/etc/network/interfaces.d/sdn";
172 my $err_config = undef;
173
56cdcac9 174 return if !-e $cluster_vnet_file && !-e $cluster_zone_file;
f5eabba0
AD
175
176 if (!-e $local_sdn_file) {
3709a203
AD
177
178 $err_config = "local sdn network configuration is not yet generated, please reload";
179 warn $err_config;
f5eabba0
AD
180 } else {
181 # fixme : use some kind of versioning info?
182 my $cluster_vnet_timestamp = (stat($cluster_vnet_file))[9];
56cdcac9 183 my $cluster_zone_timestamp = (stat($cluster_zone_file))[9];
f5eabba0
AD
184 my $local_sdn_timestamp = (stat($local_sdn_file))[9];
185
56cdcac9 186 if ($local_sdn_timestamp < $cluster_vnet_timestamp || $local_sdn_timestamp < $cluster_zone_timestamp) {
3709a203
AD
187 $err_config = "local sdn network configuration is too old, please reload";
188 warn $err_config;
f5eabba0
AD
189 }
190 }
191
192 my $status = ifquery_check();
193
194 my $vnet_cfg = PVE::Cluster::cfs_read_file('sdn/vnets.cfg');
c2b9c173
AD
195 my $zone_cfg = PVE::Cluster::cfs_read_file('sdn/zones.cfg');
196 my $nodename = PVE::INotify::nodename();
f5eabba0 197
627b1694 198
f5eabba0 199 my $vnet_status = {};
56cdcac9 200 my $zone_status = {};
f5eabba0
AD
201
202 foreach my $id (keys %{$vnet_cfg->{ids}}) {
627b1694
AD
203 my $vnet = $vnet_cfg->{ids}->{$id};
204 my $zone = $vnet->{zone};
205
206 next if !$zone;
207 my $plugin_config = $zone_cfg->{ids}->{$zone};
208 next if defined($plugin_config->{nodes}) && !$plugin_config->{nodes}->{$nodename};
209
210 my $plugin = PVE::Network::SDN::Zones::Plugin->lookup($plugin_config->{type});
211 $plugin->status($plugin_config, $zone, $id, $vnet, $err_config, $status, $vnet_status, $zone_status);
f5eabba0 212 }
627b1694 213
56cdcac9 214 return($zone_status, $vnet_status);
f5eabba0
AD
215}
216
2ba9613b
AD
217sub get_bridge_vlan {
218 my ($vnetid) = @_;
219
220 my $vnet_cfg = PVE::Cluster::cfs_read_file('sdn/vnets.cfg');
221 my $zone_cfg = PVE::Cluster::cfs_read_file('sdn/zones.cfg');
222 my $nodename = PVE::INotify::nodename();
223
224 my $vnet = $vnet_cfg->{ids}->{$vnetid};
225 return if !$vnet;
226
227 my $zoneid = $vnet->{zone};
228 my $tag = $vnet->{tag};
229
230 die "vnet $vnetid is not allowed on this node" if defined($zone_cfg->{ids}->{$zoneid}->{nodes}) && !$zone_cfg->{ids}->{$zoneid}->{nodes}->{$nodename};
231
232 my $plugin_config = $zone_cfg->{ids}->{$zoneid};
233 my $plugin = PVE::Network::SDN::Zones::Plugin->lookup($plugin_config->{type});
234 return $plugin->get_bridge_vlan($plugin_config, $zoneid, $vnetid, $tag);
235}
236
f5eabba0
AD
2371;
238