]> git.proxmox.com Git - pve-network.git/blob - PVE/Network/SDN/Controllers.pm
controllers: evpn : use frr restart if reload fail
[pve-network.git] / PVE / Network / SDN / Controllers.pm
1 package PVE::Network::SDN::Controllers;
2
3 use strict;
4 use warnings;
5
6 use Data::Dumper;
7 use JSON;
8
9 use PVE::Tools qw(extract_param dir_glob_regex run_command);
10 use PVE::Cluster qw(cfs_read_file cfs_write_file cfs_lock_file);
11
12 use PVE::Network::SDN::Vnets;
13 use PVE::Network::SDN::Zones;
14
15 use PVE::Network::SDN::Controllers::EvpnPlugin;
16 use PVE::Network::SDN::Controllers::BgpPlugin;
17 use PVE::Network::SDN::Controllers::FaucetPlugin;
18 use PVE::Network::SDN::Controllers::Plugin;
19 PVE::Network::SDN::Controllers::EvpnPlugin->register();
20 PVE::Network::SDN::Controllers::BgpPlugin->register();
21 PVE::Network::SDN::Controllers::FaucetPlugin->register();
22 PVE::Network::SDN::Controllers::Plugin->init();
23
24
25 sub sdn_controllers_config {
26 my ($cfg, $id, $noerr) = @_;
27
28 die "no sdn controller ID specified\n" if !$id;
29
30 my $scfg = $cfg->{ids}->{$id};
31 die "sdn '$id' does not exist\n" if (!$noerr && !$scfg);
32
33 return $scfg;
34 }
35
36 sub config {
37 my $config = cfs_read_file("sdn/controllers.cfg");
38 $config = cfs_read_file("sdn/controllers.cfg") if !keys %{$config->{ids}};
39 return $config;
40 }
41
42 sub write_config {
43 my ($cfg) = @_;
44
45 cfs_write_file("sdn/controllers.cfg", $cfg);
46 }
47
48 sub lock_sdn_controllers_config {
49 my ($code, $errmsg) = @_;
50
51 cfs_lock_file("sdn/controllers.cfg", undef, $code);
52 if (my $err = $@) {
53 $errmsg ? die "$errmsg: $err" : die $err;
54 }
55 }
56
57 sub sdn_controllers_ids {
58 my ($cfg) = @_;
59
60 return sort keys %{$cfg->{ids}};
61 }
62
63 sub complete_sdn_controller {
64 my ($cmdname, $pname, $cvalue) = @_;
65
66 my $cfg = PVE::Network::SDN::running_config();
67
68 return $cmdname eq 'add' ? [] : [ PVE::Network::SDN::sdn_controllers_ids($cfg) ];
69 }
70
71 sub generate_controller_config {
72
73 my $cfg = PVE::Network::SDN::running_config();
74 my $vnet_cfg = $cfg->{vnets};
75 my $zone_cfg = $cfg->{zones};
76 my $controller_cfg = $cfg->{controllers};
77
78 return if !$vnet_cfg && !$zone_cfg && !$controller_cfg;
79
80 #read main config for physical interfaces
81 my $current_config_file = "/etc/network/interfaces";
82 my $fh = IO::File->new($current_config_file);
83 my $interfaces_config = PVE::INotify::read_etc_network_interfaces(1,$fh);
84 $fh->close();
85
86 # check uplinks
87 my $uplinks = {};
88 foreach my $id (keys %{$interfaces_config->{ifaces}}) {
89 my $interface = $interfaces_config->{ifaces}->{$id};
90 if (my $uplink = $interface->{'uplink-id'}) {
91 die "uplink-id $uplink is already defined on $uplinks->{$uplink}" if $uplinks->{$uplink};
92 $interface->{name} = $id;
93 $uplinks->{$interface->{'uplink-id'}} = $interface;
94 }
95 }
96
97 # generate configuration
98 my $config = {};
99
100 foreach my $id (sort keys %{$controller_cfg->{ids}}) {
101 my $plugin_config = $controller_cfg->{ids}->{$id};
102 my $plugin = PVE::Network::SDN::Controllers::Plugin->lookup($plugin_config->{type});
103 $plugin->generate_controller_config($plugin_config, $controller_cfg, $id, $uplinks, $config);
104 }
105
106 foreach my $id (sort keys %{$zone_cfg->{ids}}) {
107 my $plugin_config = $zone_cfg->{ids}->{$id};
108 my $controllerid = $plugin_config->{controller};
109 next if !$controllerid;
110 my $controller = $controller_cfg->{ids}->{$controllerid};
111 if ($controller) {
112 my $controller_plugin = PVE::Network::SDN::Controllers::Plugin->lookup($controller->{type});
113 $controller_plugin->generate_controller_zone_config($plugin_config, $controller, $controller_cfg, $id, $uplinks, $config);
114 }
115 }
116
117 foreach my $id (sort keys %{$vnet_cfg->{ids}}) {
118 my $plugin_config = $vnet_cfg->{ids}->{$id};
119 my $zoneid = $plugin_config->{zone};
120 next if !$zoneid;
121 my $zone = $zone_cfg->{ids}->{$zoneid};
122 next if !$zone;
123 my $controllerid = $zone->{controller};
124 next if !$controllerid;
125 my $controller = $controller_cfg->{ids}->{$controllerid};
126 if ($controller) {
127 my $controller_plugin = PVE::Network::SDN::Controllers::Plugin->lookup($controller->{type});
128 $controller_plugin->generate_controller_vnet_config($plugin_config, $controller, $zone, $zoneid, $id, $config);
129 }
130 }
131
132 return $config;
133 }
134
135
136 sub reload_controller {
137
138 my $cfg = PVE::Network::SDN::running_config();
139 my $controller_cfg = $cfg->{controllers};
140
141 return if !$controller_cfg;
142
143 foreach my $id (keys %{$controller_cfg->{ids}}) {
144 my $plugin_config = $controller_cfg->{ids}->{$id};
145 my $plugin = PVE::Network::SDN::Controllers::Plugin->lookup($plugin_config->{type});
146 $plugin->reload_controller();
147 }
148 }
149
150 sub generate_controller_rawconfig {
151 my ($config) = @_;
152
153 my $cfg = PVE::Network::SDN::running_config();
154 my $controller_cfg = $cfg->{controllers};
155 return if !$controller_cfg;
156
157 my $rawconfig = "";
158 foreach my $id (keys %{$controller_cfg->{ids}}) {
159 my $plugin_config = $controller_cfg->{ids}->{$id};
160 my $plugin = PVE::Network::SDN::Controllers::Plugin->lookup($plugin_config->{type});
161 $rawconfig .= $plugin->generate_controller_rawconfig($plugin_config, $config);
162 }
163 return $rawconfig;
164 }
165
166 sub write_controller_config {
167 my ($config) = @_;
168
169 my $cfg = PVE::Network::SDN::running_config();
170 my $controller_cfg = $cfg->{controllers};
171 return if !$controller_cfg;
172
173 foreach my $id (keys %{$controller_cfg->{ids}}) {
174 my $plugin_config = $controller_cfg->{ids}->{$id};
175 my $plugin = PVE::Network::SDN::Controllers::Plugin->lookup($plugin_config->{type});
176 $plugin->write_controller_config($plugin_config, $config);
177 }
178 }
179
180 1;
181