use PVE::Network::SDN::Plugin;
use PVE::Network::SDN::VnetPlugin;
use PVE::Network::SDN::VlanPlugin;
-use PVE::Network::SDN::VxlanMulticastPlugin;
+use PVE::Network::SDN::VxlanPlugin;
+use PVE::Network::SDN::FaucetPlugin;
+use PVE::Network::SDN::FaucetControllerPlugin;
+use PVE::Network::SDN::EvpnPlugin;
+use PVE::Network::SDN::EvpnControllerPlugin;
PVE::Network::SDN::VnetPlugin->register();
PVE::Network::SDN::VlanPlugin->register();
-PVE::Network::SDN::VxlanMulticastPlugin->register();
+PVE::Network::SDN::VxlanPlugin->register();
+PVE::Network::SDN::FaucetControllerPlugin->register();
+PVE::Network::SDN::FaucetPlugin->register();
+PVE::Network::SDN::EvpnPlugin->register();
+PVE::Network::SDN::EvpnControllerPlugin->register();
PVE::Network::SDN::Plugin->init();
return $cmdname eq 'add' ? [] : [ PVE::Network::SDN::sdn_ids($cfg) ];
}
-sub status {
+sub ifquery_check {
my $cmd = ['ifquery', '-a', '-c', '-o','json'];
}
#generate configuration
- my $rawconfig = "";
+ my $config = {};
foreach my $id (keys %{$vnet_cfg->{ids}}) {
my $vnet = $vnet_cfg->{ids}->{$id};
my $zone = $vnet->{transportzone};
}
my $plugin = PVE::Network::SDN::Plugin->lookup($plugin_config->{type});
- $rawconfig .= $plugin->generate_sdn_config($plugin_config, $zone, $id, $vnet, $uplinks);
+ $plugin->generate_sdn_config($plugin_config, $zone, $id, $vnet, $uplinks, $config);
+ }
+
+ my $raw_network_config = "";
+ foreach my $iface (keys %$config) {
+ $raw_network_config .= "\n";
+ $raw_network_config .= "auto $iface\n";
+ $raw_network_config .= "iface $iface\n";
+ foreach my $option (@{$config->{$iface}}) {
+ $raw_network_config .= "\t$option\n";
+ }
+ }
+
+ return $raw_network_config;
+}
+
+sub generate_controller_config {
+
+ my $sdn_cfg = PVE::Cluster::cfs_read_file('sdn.cfg');
+ return if !$sdn_cfg;
+
+ #read main config for physical interfaces
+ my $current_config_file = "/etc/network/interfaces";
+ my $fh = IO::File->new($current_config_file);
+ my $interfaces_config = PVE::INotify::read_etc_network_interfaces(1,$fh);
+ $fh->close();
+
+ #check uplinks
+ my $uplinks = {};
+ foreach my $id (keys %{$interfaces_config->{ifaces}}) {
+ my $interface = $interfaces_config->{ifaces}->{$id};
+ if (my $uplink = $interface->{'uplink-id'}) {
+ die "uplink-id $uplink is already defined on $uplinks->{$uplink}" if $uplinks->{$uplink};
+ $interface->{name} = $id;
+ $uplinks->{$interface->{'uplink-id'}} = $interface;
+ }
+ }
+
+ #generate configuration
+ my $config = {};
+
+ foreach my $id (keys %{$sdn_cfg->{ids}}) {
+ my $plugin_config = $sdn_cfg->{ids}->{$id};
+ my $plugin = PVE::Network::SDN::Plugin->lookup($plugin_config->{type});
+ my $pd = $plugin->plugindata();
+ my $role = $pd->{role};
+ if ($role eq 'controller') {
+ $plugin->generate_controller_config($plugin_config, $plugin_config, $id, $uplinks, $config);
+ } elsif ($role eq 'transport') {
+ my $controllerid = $plugin_config->{controller};
+ if ($controllerid) {
+ my $controller = $sdn_cfg->{ids}->{$controllerid};
+ if ($controller) {
+ my $controller_plugin = PVE::Network::SDN::Plugin->lookup($controller->{type});
+ $controller_plugin->generate_controller_transport_config($plugin_config, $controller, $id, $uplinks, $config);
+ }
+ }
+ } elsif ($role eq 'vnet') {
+ my $transportid = $plugin_config->{transportzone};
+ if ($transportid) {
+ my $transport = $sdn_cfg->{ids}->{$transportid};
+ if ($transport) {
+ my $controllerid = $transport->{controller};
+ if ($controllerid) {
+ my $controller = $sdn_cfg->{ids}->{$controllerid};
+ if ($controller) {
+ my $controller_plugin = PVE::Network::SDN::Plugin->lookup($controller->{type});
+ $controller_plugin->generate_controller_vnet_config($plugin_config, $controller, $transportid, $id, $config);
+ }
+ }
+ }
+ }
+ }
}
- return $rawconfig;
+ return $config;
+}
+
+
+sub reload_controller {
+
+ my $sdn_cfg = PVE::Cluster::cfs_read_file('sdn.cfg');
+ return if !$sdn_cfg;
+
+ foreach my $id (keys %{$sdn_cfg->{ids}}) {
+ my $plugin_config = $sdn_cfg->{ids}->{$id};
+ my $plugin = PVE::Network::SDN::Plugin->lookup($plugin_config->{type});
+ my $pd = $plugin->plugindata();
+ my $role = $pd->{role};
+ if ($role eq 'controller') {
+ $plugin->reload_controller();
+ }
+ }
}
sub write_etc_network_config {
$writefh->close();
}
-1;
+sub write_controller_config {
+ my ($config) = @_;
+ my $sdn_cfg = PVE::Cluster::cfs_read_file('sdn.cfg');
+ return if !$sdn_cfg;
+ foreach my $id (keys %{$sdn_cfg->{ids}}) {
+ my $plugin_config = $sdn_cfg->{ids}->{$id};
+ my $plugin = PVE::Network::SDN::Plugin->lookup($plugin_config->{type});
+ my $pd = $plugin->plugindata();
+ my $role = $pd->{role};
+ if ($role eq 'controller') {
+ $plugin->write_controller_config($plugin_config, $config);
+ }
+ }
+}
+
+sub status {
+
+ my $cluster_sdn_file = "/etc/pve/sdn.cfg";
+ my $local_sdn_file = "/etc/network/interfaces.d/sdn";
+ my $err_config = undef;
+
+ return if !-e $cluster_sdn_file;
+
+ if (!-e $local_sdn_file) {
+ warn "local sdn network configuration is not yet generated, please reload";
+ $err_config = 'pending';
+ } else {
+ # fixme : use some kind of versioning info?
+ my $cluster_sdn_timestamp = (stat($cluster_sdn_file))[9];
+ my $local_sdn_timestamp = (stat($local_sdn_file))[9];
+
+ if ($local_sdn_timestamp < $cluster_sdn_timestamp) {
+ warn "local sdn network configuration is too old, please reload";
+ $err_config = 'unknown';
+ }
+ }
+
+ my $status = ifquery_check();
+
+ my $network_cfg = PVE::Cluster::cfs_read_file('sdn.cfg');
+ my $vnet_cfg = undef;
+ my $transport_cfg = undef;
+
+ my $vnet_status = {};
+ my $transport_status = {};
+
+ foreach my $id (keys %{$network_cfg->{ids}}) {
+ if ($network_cfg->{ids}->{$id}->{type} eq 'vnet') {
+ my $transportzone = $network_cfg->{ids}->{$id}->{transportzone};
+ $vnet_status->{$id}->{transportzone} = $transportzone;
+ $transport_status->{$transportzone}->{status} = 'available' if !defined($transport_status->{$transportzone}->{status});
+
+ if($err_config) {
+ $vnet_status->{$id}->{status} = $err_config;
+ $transport_status->{$transportzone}->{status} = $err_config;
+ } elsif ($status->{$id}->{status} && $status->{$id}->{status} eq 'pass') {
+ $vnet_status->{$id}->{status} = 'available';
+ my $bridgeport = $status->{$id}->{config}->{'bridge-ports'};
+
+ if ($status->{$bridgeport}->{status} && $status->{$bridgeport}->{status} ne 'pass') {
+ $vnet_status->{$id}->{status} = 'error';
+ $transport_status->{$transportzone}->{status} = 'error';
+ }
+ } else {
+ $vnet_status->{$id}->{status} = 'error';
+ $transport_status->{$transportzone}->{status} = 'error';
+ }
+ }
+ }
+ return($transport_status, $vnet_status);
+}
+
+1;