]> git.puffer.fish Git - matthieu/pve-network.git/commitdiff
ipam: netbox integration: add fingerprint option to api requests
authorHannes Duerr <h.duerr@proxmox.com>
Mon, 10 Feb 2025 14:19:29 +0000 (15:19 +0100)
committerThomas Lamprecht <t.lamprecht@proxmox.com>
Thu, 6 Mar 2025 09:00:21 +0000 (10:00 +0100)
Signed-off-by: Hannes Duerr <h.duerr@proxmox.com>
Tested-by: Stefan Hanreich <s.hanreich@proxmox.com>
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
src/PVE/Network/SDN/Ipams/NetboxPlugin.pm

index d9232696e4cb638c788f94f3b01c8c13c6fb2d93..18089b7ef5b781164813431f8ef6dee0dff576ea 100644 (file)
@@ -18,10 +18,10 @@ sub properties {
 }
 
 sub options {
-
     return {
         url => { optional => 0},
         token => { optional => 0 },
+        fingerprint => { optional => 1 },
     };
 }
 
@@ -34,9 +34,10 @@ sub add_subnet {
     my $gateway = $subnet->{gateway};
     my $url = $plugin_config->{url};
     my $token = $plugin_config->{token};
+    my $fingerprint = $plugin_config->{fingerprint};
     my $headers = ['Content-Type' => 'application/json; charset=UTF-8', 'Authorization' => "token $token"];
 
-    my $internalid = get_prefix_id($url, $cidr, $headers);
+    my $internalid = get_prefix_id($url, $cidr, $headers, $fingerprint);
 
     #create subnet
     if (!$internalid) {
@@ -44,7 +45,8 @@ sub add_subnet {
        my $params = { prefix => $cidr };
 
        eval {
-               my $result = PVE::Network::SDN::api_request("POST", "$url/ipam/prefixes/", $headers, $params);
+           my $result = PVE::Network::SDN::api_request(
+               "POST", "$url/ipam/prefixes/", $headers, $params, $fingerprint );
        };
        if ($@) {
            die "error add subnet to ipam: $@" if !$noerr;
@@ -60,15 +62,17 @@ sub del_subnet {
     my $url = $plugin_config->{url};
     my $token = $plugin_config->{token};
     my $gateway = $subnet->{gateway};
+    my $fingerprint = $plugin_config->{fingerprint};
     my $headers = ['Content-Type' => 'application/json; charset=UTF-8', 'Authorization' => "token $token"];
 
-    my $internalid = get_prefix_id($url, $cidr, $headers);
+    my $internalid = get_prefix_id($url, $cidr, $headers, $fingerprint);
     return if !$internalid;
 
     return; #fixme: check that prefix is empty exluding gateway, before delete
 
     eval {
-       PVE::Network::SDN::api_request("DELETE", "$url/ipam/prefixes/$internalid/", $headers);
+       PVE::Network::SDN::api_request(
+           "DELETE", "$url/ipam/prefixes/$internalid/", $headers, undef, $fingerprint);
     };
     if ($@) {
        die "error deleting subnet from ipam: $@" if !$noerr;
@@ -82,7 +86,7 @@ sub add_ip {
     my $mask = $subnet->{mask};
     my $url = $plugin_config->{url};
     my $token = $plugin_config->{token};
-    my $section = $plugin_config->{section};
+    my $fingerprint = $plugin_config->{fingerprint};
     my $headers = ['Content-Type' => 'application/json; charset=UTF-8', 'Authorization' => "token $token"];
 
     my $description = undef;
@@ -95,14 +99,17 @@ sub add_ip {
     my $params = { address => "$ip/$mask", dns_name => $hostname, description => $description };
 
     eval {
-       PVE::Network::SDN::api_request("POST", "$url/ipam/ip-addresses/", $headers, $params);
+       PVE::Network::SDN::api_request(
+           "POST", "$url/ipam/ip-addresses/", $headers, $params, $fingerprint);
     };
 
     if ($@) {
-        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;
+       if ($is_gateway) {
+           if (!is_ip_gateway($url, $ip, $headers, $fingerprint) && !$noerr) {
+               die "error add subnet ip to ipam: ip $ip already exist: $@";
+           }
+       } elsif (!$noerr) {
+           die "error add subnet ip to ipam: ip already exist: $@";
        }
     }
 }
@@ -114,6 +121,7 @@ sub update_ip {
     my $url = $plugin_config->{url};
     my $token = $plugin_config->{token};
     my $section = $plugin_config->{section};
+    my $fingerprint = $plugin_config->{fingerprint};
     my $headers = ['Content-Type' => 'application/json; charset=UTF-8', 'Authorization' => "token $token"];
 
     my $description = undef;
@@ -125,11 +133,12 @@ sub update_ip {
 
     my $params = { address => "$ip/$mask", dns_name => $hostname, description => $description };
 
-    my $ip_id = get_ip_id($url, $ip, $headers);
+    my $ip_id = get_ip_id($url, $ip, $headers, $fingerprint);
     die "can't find ip $ip in ipam" if !$ip_id;
 
     eval {
-       PVE::Network::SDN::api_request("PATCH", "$url/ipam/ip-addresses/$ip_id/", $headers, $params);
+       PVE::Network::SDN::api_request(
+           "PATCH", "$url/ipam/ip-addresses/$ip_id/", $headers, $params, $fingerprint);
     };
     if ($@) {
        die "error update ip $ip : $@" if !$noerr;
@@ -143,16 +152,18 @@ sub add_next_freeip {
 
     my $url = $plugin_config->{url};
     my $token = $plugin_config->{token};
+    my $fingerprint = $plugin_config->{fingerprint};
     my $headers = ['Content-Type' => 'application/json; charset=UTF-8', 'Authorization' => "token $token"];
 
-    my $internalid = get_prefix_id($url, $cidr, $headers);
+    my $internalid = get_prefix_id($url, $cidr, $headers, $fingerprint);
 
     my $description = "mac:$mac" if $mac;
 
     my $params = { dns_name => $hostname, description => $description };
 
     eval {
-       my $result = PVE::Network::SDN::api_request("POST", "$url/ipam/prefixes/$internalid/available-ips/", $headers, $params);
+       my $result = PVE::Network::SDN::api_request(
+           "POST", "$url/ipam/prefixes/$internalid/available-ips/", $headers, $params, $fingerprint);
        my ($ip, undef) = split(/\//, $result->{address});
        return $ip;
     };
@@ -168,14 +179,16 @@ sub add_range_next_freeip {
     my $url = $plugin_config->{url};
     my $token = $plugin_config->{token};
     my $headers = ['Content-Type' => 'application/json; charset=UTF-8', 'Authorization' => "token $token"];
+    my $fingerprint = $plugin_config->{fingerprint};
 
-    my $internalid = get_iprange_id($url, $range, $headers);
+    my $internalid = get_iprange_id($url, $range, $headers, $fingerprint);
     my $description = "mac:$data->{mac}" if $data->{mac};
 
     my $params = { dns_name => $data->{hostname}, description => $description };
 
     eval {
-       my $result = PVE::Network::SDN::api_request("POST", "$url/ipam/ip-ranges/$internalid/available-ips/", $headers, $params);
+       my $result = PVE::Network::SDN::api_request(
+           "POST", "$url/ipam/ip-ranges/$internalid/available-ips/", $headers, $params, $fingerprint);
        my ($ip, undef) = split(/\//, $result->{address});
        print "found ip free $ip in range $range->{'start-address'}-$range->{'end-address'}\n" if $ip;
        return $ip;
@@ -194,12 +207,13 @@ sub del_ip {
     my $url = $plugin_config->{url};
     my $token = $plugin_config->{token};
     my $headers = ['Content-Type' => 'application/json; charset=UTF-8', 'Authorization' => "token $token"];
+    my $fingerprint = $plugin_config->{fingerprint};
 
-    my $ip_id = get_ip_id($url, $ip, $headers);
+    my $ip_id = get_ip_id($url, $ip, $headers, $fingerprint);
     die "can't find ip $ip in ipam" if !$ip_id;
 
     eval {
-       PVE::Network::SDN::api_request("DELETE", "$url/ipam/ip-addresses/$ip_id/", $headers);
+       PVE::Network::SDN::api_request("DELETE", "$url/ipam/ip-addresses/$ip_id/", $headers, undef, $fingerprint);
     };
     if ($@) {
        die "error delete ip $ip : $@" if !$noerr;
@@ -212,11 +226,14 @@ sub get_ips_from_mac {
     my $url = $plugin_config->{url};
     my $token = $plugin_config->{token};
     my $headers = ['Content-Type' => 'application/json; charset=UTF-8', 'Authorization' => "token $token"];
+    my $fingerprint = $plugin_config->{fingerprint};
 
     my $ip4 = undef;
     my $ip6 = undef;
 
-    my $data = PVE::Network::SDN::api_request("GET", "$url/ipam/ip-addresses/?description__ic=$mac", $headers);
+    my $data = PVE::Network::SDN::api_request(
+       "GET", "$url/ipam/ip-addresses/?description__ic=$mac", $headers, undef, $fingerprint);
+
     for my $ip (@{$data->{results}}) {
        if ($ip->{family}->{value} == 4 && !$ip4) {
            ($ip4, undef) = split(/\//, $ip->{address});
@@ -237,10 +254,10 @@ sub verify_api {
     my $url = $plugin_config->{url};
     my $token = $plugin_config->{token};
     my $headers = ['Content-Type' => 'application/json; charset=UTF-8', 'Authorization' => "token $token"];
-
+    my $fingerprint = $plugin_config->{fingerprint};
 
     eval {
-       PVE::Network::SDN::api_request("GET", "$url/ipam/aggregates/", $headers);
+       PVE::Network::SDN::api_request("GET", "$url/ipam/aggregates/", $headers, undef, $fingerprint);
     };
     if ($@) {
        die "Can't connect to netbox api: $@";
@@ -256,34 +273,40 @@ sub on_update_hook {
 #helpers
 
 sub get_prefix_id {
-    my ($url, $cidr, $headers) = @_;
-
-    my $result = PVE::Network::SDN::api_request("GET", "$url/ipam/prefixes/?q=$cidr", $headers);
+    my ($url, $cidr, $headers, $fingerprint) = @_;
+    my $result = PVE::Network::SDN::api_request(
+       "GET", "$url/ipam/prefixes/?q=$cidr", $headers, undef, $fingerprint);
     my $data = @{$result->{results}}[0];
     my $internalid = $data->{id};
     return $internalid;
 }
 
 sub get_iprange_id {
-    my ($url, $range, $headers) = @_;
-
-    my $result = PVE::Network::SDN::api_request("GET", "$url/ipam/ip-ranges/?start_address=$range->{'start-address'}&end_address=$range->{'end-address'}", $headers);
+    my ($url, $range, $headers, $fingerprint) = @_;
+    my $result = PVE::Network::SDN::api_request(
+       "GET",
+       "$url/ipam/ip-ranges/?start_address=$range->{'start-address'}&end_address=$range->{'end-address'}",
+       $headers,
+       undef,
+       $fingerprint
+    );
     my $data = @{$result->{results}}[0];
     my $internalid = $data->{id};
     return $internalid;
 }
 
 sub get_ip_id {
-    my ($url, $ip, $headers) = @_;
-    my $result = PVE::Network::SDN::api_request("GET", "$url/ipam/ip-addresses/?q=$ip", $headers);
+    my ($url, $ip, $headers, $fingerprint) = @_;
+    my $result = PVE::Network::SDN::api_request(
+       "GET", "$url/ipam/ip-addresses/?q=$ip", $headers, undef, $fingerprint);
     my $data = @{$result->{results}}[0];
     my $ip_id = $data->{id};
     return $ip_id;
 }
 
 sub is_ip_gateway {
-    my ($url, $ip, $headers) = @_;
-    my $result = PVE::Network::SDN::api_request("GET", "$url/ipam/ip-addresses/?q=$ip", $headers);
+    my ($url, $ip, $headers, $fingerprint) = @_;
+    my $result = PVE::Network::SDN::api_request("GET", "$url/ipam/ip-addresses/?q=$ip", $headers, undef, $fingerprint);
     my $data = @{$result->{data}}[0];
     my $description = $data->{description};
     my $is_gateway = 1 if $description eq 'gateway';