]> git.proxmox.com Git - pve-network.git/commitdiff
subnets/ipam : fix is_gateway
authorAlexandre Derumier <aderumier@odiso.com>
Fri, 4 Jun 2021 11:25:00 +0000 (13:25 +0200)
committerThomas Lamprecht <t.lamprecht@proxmox.com>
Fri, 18 Jun 2021 16:29:15 +0000 (18:29 +0200)
- add lost is_gateway in subnets subnet when creating subnet
- allow reuse ip as gateway in subnet create if it's already flagged gateway in the ipamdb
- add tests

PVE/Network/SDN/Ipams/NetboxPlugin.pm
PVE/Network/SDN/Ipams/PVEPlugin.pm
PVE/Network/SDN/Ipams/PhpIpamPlugin.pm
PVE/Network/SDN/SubnetPlugin.pm
PVE/Network/SDN/Subnets.pm
test/ipams/netbox/expected.add_ip_notgateway [new file with mode: 0644]
test/ipams/phpipam/expected.add_ip_notgateway [new file with mode: 0644]
test/run_test_ipams.pl
test/run_test_subnets.pl

index 5a03f39412d3bff2fe6f5c379a2dfcedc5ecb4ae..f0e7168850a22b2e4775559aade911ef1473adfb 100644 (file)
@@ -93,7 +93,11 @@ sub add_ip {
     };
 
     if ($@) {
-       die "error add subnet ip to ipam: ip already exist: $@" if !$noerr;
+        if($is_gateway) {
+           die "error add subnet ip to ipam: ip $ip already exist: $@" if !is_ip_gateway($url, $ip, $headers) && !$noerr;
+        } else {
+           die "error add subnet ip to ipam: ip already exist: $@" if !$noerr;
+       }
     }
 }
 
@@ -208,6 +212,14 @@ sub get_ip_id {
     return $ip_id;
 }
 
+sub is_ip_gateway {
+    my ($url, $ip, $headers) = @_;
+    my $result = PVE::Network::SDN::api_request("GET", "$url/addresses/search/$ip", $headers);
+    my $data = @{$result->{data}}[0];
+    my $description = $data->{description};
+    my $is_gateway = 1 if $description eq 'gateway';
+    return $is_gateway;
+}
 
 1;
 
index 8fe5bbbbf27ec4fb58b552dd084940724ab379f0..3e8ffc5ab86108f6ae6c5b78d80e5ee5ac152167 100644 (file)
@@ -95,9 +95,9 @@ sub add_ip {
        my $dbsubnet = $dbzone->{subnets}->{$cidr};
        die "subnet '$cidr' doesn't exist in IPAM DB\n" if !$dbsubnet;
 
-       die "IP '$ip' already exist\n" if defined($dbsubnet->{ips}->{$ip});
-
+       die "IP '$ip' already exist\n" if (!$is_gateway && defined($dbsubnet->{ips}->{$ip})) || ($is_gateway && defined($dbsubnet->{ips}->{$ip}) && !defined($dbsubnet->{ips}->{$ip}->{gateway}));
        $dbsubnet->{ips}->{$ip} = {};
+       $dbsubnet->{ips}->{$ip} = {gateway => 1} if $is_gateway;
 
        write_db($db);
     });
index ed66ea9f5928863a66464a4c28972f6188aa08ec..ad5286b6bcafbcf0948099cf0900bd62983ef41e 100644 (file)
@@ -106,10 +106,10 @@ sub add_ip {
 
     my $params = { ip => $ip,
                   subnetId => $internalid,
-                  is_gateway => $is_gateway,
                   hostname => $hostname,
                   description => $description,
                  };
+    $params->{is_gateway} = 1 if $is_gateway;
     $params->{mac} = $mac if $mac;
 
     eval {
@@ -117,7 +117,11 @@ sub add_ip {
     };
 
     if ($@) {
-       die "error add subnet ip to ipam: ip $ip already exist: $@" if !$noerr;
+       if($is_gateway) {
+           die "error add subnet ip to ipam: ip $ip already exist: $@" if !is_ip_gateway($url, $ip, $headers) && !$noerr;
+       } else {
+           die "error add subnet ip to ipam: ip $ip already exist: $@" if !$noerr;
+       }
     }
 }
 
@@ -134,10 +138,10 @@ sub update_ip {
     die "can't find ip addresse in ipam" if !$ip_id;
 
     my $params = { 
-                  is_gateway => $is_gateway,
                   hostname => $hostname,
                   description => $description,
                  };
+    $params->{is_gateway} = 1 if $is_gateway;
     $params->{mac} = $mac if $mac;
 
     eval {
@@ -242,6 +246,14 @@ sub get_ip_id {
     return $ip_id;
 }
 
+sub is_ip_gateway {
+    my ($url, $ip, $headers) = @_;
+    my $result = PVE::Network::SDN::api_request("GET", "$url/addresses/search/$ip", $headers);
+    my $data = @{$result->{data}}[0];
+    my $is_gateway = $data->{is_gateway};
+    return $is_gateway;
+}
+
 1;
 
 
index b4c89543aa91caef4520be81dd1f26441848bcbf..15b370fb91ce80e9cab368aad42c75dbf314eea7 100644 (file)
@@ -143,7 +143,7 @@ sub on_update_hook {
        }
         if(!$old_gateway || $gateway && $gateway ne $old_gateway) {
            my $hostname = "$vnetid-gw";
-           my $description = "$vnetid gw";
+           my $description = "gateway";
            PVE::Network::SDN::Subnets::add_ip($zone, $subnetid, $subnet, $gateway, $hostname, $mac, $description, 1);
        }
 
index 46d9830729711029714db552579f5446d3e9745a..0231822ce0a2493cff5894ca140501b90ec9ec8b 100644 (file)
@@ -232,7 +232,7 @@ sub next_free_ip {
 }
 
 sub add_ip {
-    my ($zone, $subnetid, $subnet, $ip, $hostname, $mac, $description) = @_;
+    my ($zone, $subnetid, $subnet, $ip, $hostname, $mac, $description, $is_gateway) = @_;
 
     return if !$subnet || !$ip; 
 
@@ -259,7 +259,7 @@ sub add_ip {
        my $plugin = PVE::Network::SDN::Ipams::Plugin->lookup($plugin_config->{type});
 
        eval {
-           $plugin->add_ip($plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $description);
+           $plugin->add_ip($plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $description, $is_gateway);
        };
        die $@ if $@;
     }
diff --git a/test/ipams/netbox/expected.add_ip_notgateway b/test/ipams/netbox/expected.add_ip_notgateway
new file mode 100644 (file)
index 0000000..ae876f2
--- /dev/null
@@ -0,0 +1,9 @@
+bless( {
+                  '_content' => '{"address":"10.0.0.1/24","description":"mydescription mac:da:65:8f:18:9b:6f","dns_name":"myhostname"}',
+                  '_headers' => bless( {
+                                         'authorization' => 'token 0123456789abcdef0123456789abcdef01234567',
+                                         'content-type' => 'application/json; charset=UTF-8'
+                                       }, 'HTTP::Headers' ),
+                  '_method' => 'POST',
+                  '_uri' => bless( do{\(my $o = 'http://localhost:8000/api/ipam/ip-addresses/')}, 'URI::http' )
+                }, 'HTTP::Request' );
diff --git a/test/ipams/phpipam/expected.add_ip_notgateway b/test/ipams/phpipam/expected.add_ip_notgateway
new file mode 100644 (file)
index 0000000..7a91359
--- /dev/null
@@ -0,0 +1,12 @@
+bless( {
+                  '_content' => '{"description":"mydescription","hostname":"myhostname","ip":"10.0.0.1","mac":"da:65:8f:18:9b:6f","subnetId":1}',
+                  '_headers' => bless( {
+                                         '::std_case' => {
+                                                           'token' => 'Token'
+                                                         },
+                                         'content-type' => 'application/json; charset=UTF-8',
+                                         'token' => 'JPHkPSLB4O_XL-GQz4qtEFmNpx-99Htw'
+                                       }, 'HTTP::Headers' ),
+                  '_method' => 'POST',
+                  '_uri' => bless( do{\(my $o = 'https://localhost/api/apiadmin/addresses/')}, 'URI::https' )
+                }, 'HTTP::Request' );
index 6743effaa4a86d340995c2f0841a6ce0e1b8a39f..27bd441172e9b38a0f44c67bd828d198e72a24b2 100755 (executable)
@@ -99,6 +99,9 @@ foreach my $path (@plugins) {
        },
        get_ip_id => sub {
            return 1;
+       },
+       is_ip_gateway => sub {
+           return 1;
        }
     );
 
@@ -146,9 +149,22 @@ foreach my $path (@plugins) {
     $test = "update_ip";
     $expected = Dumper read_sdn_config("$path/expected.$test");
     $name = "$ipamid $test";
-
     $plugin->update_ip($plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $description, $is_gateway, 1);
 
+    if ($@) {
+       is ($@, $expected, $name);
+    } else {
+       fail($name);
+    }
+
+    ## add_ip_notgateway
+    $is_gateway = undef;
+    $test = "add_ip_notgateway";
+    $expected = Dumper read_sdn_config("$path/expected.$test");
+    $name = "$ipamid $test";
+
+    $plugin->add_ip($plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $description, $is_gateway, 1);
+
     if ($@) {
        is ($@, $expected, $name);
     } else {
index 9fca202ff35a301f1c222021a09aaeaaa538b5d4..f6564e186442609e8ff4707659451568309737dd 100755 (executable)
@@ -135,10 +135,10 @@ foreach my $path (@plugins) {
     $test = "add_ip $ip";
     $name = "$testid $test";
     $result = undef;
-    $expected = '{"zones":{"myzone":{"subnets":{"'.$subnet_cidr.'":{"ips":{"'.$ip.'":{}}}}}}}';
+    $expected = '{"zones":{"myzone":{"subnets":{"'.$subnet_cidr.'":{"ips":{"'.$ip.'":{"gateway":1}}}}}}}';
 
     eval {
-       PVE::Network::SDN::Subnets::add_ip($zone, $subnetid, $subnet, $ip, $hostname, $mac, $description);
+       PVE::Network::SDN::Subnets::add_ip($zone, $subnetid, $subnet, $ip, $hostname, $mac, $description, $is_gateway);
     };
 
     if ($@) {
@@ -170,7 +170,7 @@ foreach my $path (@plugins) {
     $test = "add_second_ip $ip2";
     $name = "$testid $test";
     $result = undef;
-    $expected = '{"zones":{"myzone":{"subnets":{"'.$subnet_cidr.'":{"ips":{"'.$ip.'":{},"'.$ip2.'":{}}}}}}}';
+    $expected = '{"zones":{"myzone":{"subnets":{"'.$subnet_cidr.'":{"ips":{"'.$ip.'":{"gateway":1},"'.$ip2.'":{}}}}}}}';
 
     eval {
        PVE::Network::SDN::Subnets::add_ip($zone, $subnetid, $subnet, $ip2, $hostname, $mac, $description);
@@ -189,7 +189,7 @@ foreach my $path (@plugins) {
     $test = "find_next_freeip ($ipnextfree)";
     $name = "$testid $test";
     $result = undef;
-    $expected = '{"zones":{"myzone":{"subnets":{"'.$subnet_cidr.'":{"ips":{"'.$ip.'":{},"'.$ipnextfree.'":{},"'.$ip2.'":{}}}}}}}';
+    $expected = '{"zones":{"myzone":{"subnets":{"'.$subnet_cidr.'":{"ips":{"'.$ip.'":{"gateway":1},"'.$ipnextfree.'":{},"'.$ip2.'":{}}}}}}}';
 
     eval {
        $ip3 = PVE::Network::SDN::Subnets::next_free_ip($zone, $subnetid, $subnet, $hostname, $mac, $description);