]> git.proxmox.com Git - pve-network.git/blobdiff - PVE/Network/SDN/Zones/Plugin.pm
add tap|veth create|plug
[pve-network.git] / PVE / Network / SDN / Zones / Plugin.pm
index 4d0732e31a7589547fd7af485f34d2eff7a8887b..e4adcbd73927473c7048dd0e2204c267012e733f 100644 (file)
@@ -3,9 +3,10 @@ package PVE::Network::SDN::Zones::Plugin;
 use strict;
 use warnings;
 
-use PVE::Tools;
+use PVE::Tools qw(run_command);
 use PVE::JSONSchema;
 use PVE::Cluster;
+use PVE::Network;
 
 use Data::Dumper;
 use PVE::JSONSchema qw(get_standard_option);
@@ -179,4 +180,140 @@ sub parse_tag_number_or_range {
     return (scalar(@elements) > 1);
 }
 
+sub status {
+    my ($class, $plugin_config, $zone, $id, $vnet, $err_config, $status, $vnet_status, $zone_status) = @_;
+
+    $vnet_status->{$id}->{zone} = $zone;
+    $zone_status->{$zone}->{status} = 'available' if !defined($zone_status->{$zone}->{status});
+
+    if($err_config) {
+       $vnet_status->{$id}->{status} = 'pending';
+       $vnet_status->{$id}->{statusmsg} = $err_config;
+       $zone_status->{$zone}->{status} = 'pending';
+    } elsif ($status->{$id}->{status} && $status->{$id}->{status} eq 'pass') {
+       $vnet_status->{$id}->{status} = 'available';
+       my $bridgeport = $status->{$id}->{config}->{'bridge-ports'};
+
+       if ($bridgeport && $status->{$bridgeport}->{status} && $status->{$bridgeport}->{status} ne 'pass') {
+           $vnet_status->{$id}->{status} = 'error';
+           $vnet_status->{$id}->{statusmsg} = 'configuration not fully applied';
+           $zone_status->{$zone}->{status} = 'error';
+       }
+
+    } else {
+       $vnet_status->{$id}->{status} = 'error';
+       $vnet_status->{$id}->{statusmsg} = 'missing';
+       $zone_status->{$zone}->{status} = 'error';
+    }
+}
+
+
+sub get_bridge_vlan {
+    my ($class, $plugin_config, $vnetid, $tag) = @_;
+
+    my $bridge = $vnetid;
+    $tag = undef;
+
+    die "bridge $bridge is missing" if !-d "/sys/class/net/$bridge/";
+
+    return ($bridge, $tag);
+}
+
+sub tap_create {
+    my ($class, $plugin_config, $vnet, $iface, $vnetid) = @_;
+
+    my ($bridge, undef) = $class->get_bridge_vlan($plugin_config, $vnetid);
+    die "unable to get bridge setting\n" if !$bridge;
+
+    PVE::Network::tap_create($iface, $bridge);
+}
+
+sub veth_create {
+    my ($class, $plugin_config, $vnet, $veth, $vethpeer, $vnetid, $hwaddr) = @_;
+
+    my ($bridge, undef) = $class->get_bridge_vlan($plugin_config, $vnetid);
+    die "unable to get bridge setting\n" if !$bridge;
+
+    PVE::Network::veth_create($veth, $vethpeer, $bridge, $hwaddr);
+}
+
+sub tap_plug {
+    my ($class, $plugin_config, $vnet, $iface, $vnetid, $firewall, $rate) = @_;
+
+    my $tag = $vnet->{tag};
+
+    ($vnetid, $tag) = $class->get_bridge_vlan($plugin_config, $vnetid, $tag);
+    my $trunks = undef;
+
+    PVE::Network::tap_plug($iface, $vnetid, $tag, $firewall, $trunks, $rate);
+}
+
+#helper
+
+sub get_uplink_iface {
+    my ($interfaces_config, $uplink) = @_;
+
+    my $iface = undef;
+    foreach my $id (keys %{$interfaces_config->{ifaces}}) {
+        my $interface = $interfaces_config->{ifaces}->{$id};
+        if (my $iface_uplink = $interface->{'uplink-id'}) {
+           next if $iface_uplink ne $uplink;
+            if($interface->{type} ne 'eth' && $interface->{type} ne 'bond') {
+                warn "uplink $uplink is not a physical or bond interface";
+                next;
+            }
+           $iface = $id;
+        }
+    }
+
+    #create a dummy uplink interface if no uplink found
+    if(!$iface) {
+        warn "can't find uplink $uplink in physical interface";
+        $iface = "uplink${uplink}";
+    }
+
+    return $iface;
+}
+
+sub get_local_route_ip {
+    my ($targetip) = @_;
+
+    my $ip = undef;
+    my $interface = undef;
+
+    run_command(['/sbin/ip', 'route', 'get', $targetip], outfunc => sub {
+        if ($_[0] =~ m/src ($PVE::Tools::IPRE)/) {
+            $ip = $1;
+        }
+        if ($_[0] =~ m/dev (\S+)/) {
+            $interface = $1;
+        }
+
+    });
+    return ($ip, $interface);
+}
+
+
+sub find_local_ip_interface_peers {
+    my ($peers) = @_;
+
+    my $network_config = PVE::INotify::read_file('interfaces');
+    my $ifaces = $network_config->{ifaces};
+    #is a local ip member of peers list ?
+    foreach my $address (@{$peers}) {
+       while (my $interface = each %$ifaces) {
+           my $ip = $ifaces->{$interface}->{address};
+           if ($ip && $ip eq $address) {
+               return ($ip, $interface);
+           }
+       }
+    }
+
+    #if peer is remote, find source with ip route
+    foreach my $address (@{$peers}) {
+       my ($ip, $interface) = get_local_route_ip($address);
+       return ($ip, $interface);
+    }
+}
+
 1;