};
}
+sub netbox_api_request {
+ my ($config, $method, $path, $params) = @_;
+
+ return PVE::Network::SDN::api_request(
+ $method,
+ "$config->{url}${path}",
+ [
+ 'Content-Type' => 'application/json; charset=UTF-8',
+ 'Authorization' => "token $config->{token}"
+ ],
+ $params,
+ $config->{fingerprint},
+ );
+}
+
# Plugin implementation
sub add_subnet {
my $cidr = $subnet->{cidr};
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, $fingerprint);
- #create subnet
- if (!$internalid) {
-
- my $params = { prefix => $cidr };
+ if (get_prefix_id($plugin_config, $cidr, $noerr)) {
+ return if $noerr;
+ die "prefix $cidr already exists in netbox";
+ }
- eval {
- my $result = PVE::Network::SDN::api_request(
- "POST", "$url/ipam/prefixes/", $headers, $params, $fingerprint );
- };
- if ($@) {
- die "error add subnet to ipam: $@" if !$noerr;
- }
+ eval {
+ netbox_api_request($plugin_config, "POST", "/ipam/prefixes/", {
+ prefix => $cidr
+ });
+ };
+ if ($@) {
+ return if $noerr;
+ die "error adding subnet to ipam: $@";
}
-
}
sub del_subnet {
my ($class, $plugin_config, $subnetid, $subnet, $noerr) = @_;
my $cidr = $subnet->{cidr};
- 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, $fingerprint);
- return if !$internalid;
+ my $internalid = get_prefix_id($plugin_config, $cidr, $noerr);
return; #fixme: check that prefix is empty exluding gateway, before delete
eval {
- PVE::Network::SDN::api_request(
- "DELETE", "$url/ipam/prefixes/$internalid/", $headers, undef, $fingerprint);
+ netbox_api_request($plugin_config, "DELETE", "/ipam/prefixes/$internalid/");
};
- if ($@) {
- die "error deleting subnet from ipam: $@" if !$noerr;
- }
-
+ die "error deleting subnet from ipam: $@" if $@ && !$noerr;
}
sub add_ip {
my ($class, $plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $vmid, $is_gateway, $noerr) = @_;
my $mask = $subnet->{mask};
- 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 $description = undef;
if ($is_gateway) {
$description = "mac:$mac";
}
- my $params = { address => "$ip/$mask", dns_name => $hostname, description => $description };
-
eval {
- PVE::Network::SDN::api_request(
- "POST", "$url/ipam/ip-addresses/", $headers, $params, $fingerprint);
+ netbox_api_request($plugin_config, "POST", "/ipam/ip-addresses/", {
+ address => "$ip/$mask",
+ dns_name => $hostname,
+ description => $description,
+ });
};
if ($@) {
if ($is_gateway) {
- if (!is_ip_gateway($url, $ip, $headers, $fingerprint) && !$noerr) {
- die "error add subnet ip to ipam: ip $ip already exist: $@";
- }
+ die "error add subnet ip to ipam: ip $ip already exist: $@"
+ if !is_ip_gateway($plugin_config, $ip, $noerr);
} elsif (!$noerr) {
die "error add subnet ip to ipam: ip already exist: $@";
}
my ($class, $plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $vmid, $is_gateway, $noerr) = @_;
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;
if ($is_gateway) {
$description = "mac:$mac";
}
- my $params = { address => "$ip/$mask", dns_name => $hostname, description => $description };
+ my $ip_id = get_ip_id($plugin_config, $ip, $noerr);
- my $ip_id = get_ip_id($url, $ip, $headers, $fingerprint);
- die "can't find ip $ip in ipam" if !$ip_id;
+ # definedness check, because ID could be 0
+ if (!defined($ip_id)) {
+ return if $noerr;
+ die "could not find id for ip address $ip";
+ }
eval {
- PVE::Network::SDN::api_request(
- "PATCH", "$url/ipam/ip-addresses/$ip_id/", $headers, $params, $fingerprint);
+ netbox_api_request($plugin_config, "PATCH", "/ipam/ip-addresses/$ip_id/", {
+ address => "$ip/$mask",
+ dns_name => $hostname,
+ description => $description,
+ });
};
if ($@) {
die "error update ip $ip : $@" if !$noerr;
my $cidr = $subnet->{cidr};
- 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($plugin_config, $cidr, $noerr);
- my $internalid = get_prefix_id($url, $cidr, $headers, $fingerprint);
+ # definedness check, because ID could be 0
+ if (!defined($internalid)) {
+ return if $noerr;
+ die "could not find id for prefix $cidr";
+ }
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, $fingerprint);
+ my $result = netbox_api_request($plugin_config, "POST", "/ipam/prefixes/$internalid/available-ips/", {
+ dns_name => $hostname,
+ description => $description,
+ });
+
my ($ip, undef) = split(/\//, $result->{address});
return $ip;
};
sub add_range_next_freeip {
my ($class, $plugin_config, $subnet, $range, $data, $noerr) = @_;
- 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($plugin_config, $range, $noerr);
- my $internalid = get_iprange_id($url, $range, $headers, $fingerprint);
- my $description = "mac:$data->{mac}" if $data->{mac};
+ # definedness check, because ID could be 0
+ if (!defined($internalid)) {
+ return if $noerr;
+ die "could not find id for ip range $range->{'start-address'}:$range->{'end-address'}";
+ }
- my $params = { dns_name => $data->{hostname}, description => $description };
+ my $description = "mac:$data->{mac}" if $data->{mac};
eval {
- my $result = PVE::Network::SDN::api_request(
- "POST", "$url/ipam/ip-ranges/$internalid/available-ips/", $headers, $params, $fingerprint);
+ my $result = netbox_api_request($plugin_config, "POST", "/ipam/ip-ranges/$internalid/available-ips/", {
+ dns_name => $data->{hostname},
+ description => $description,
+ });
+
my ($ip, undef) = split(/\//, $result->{address});
print "found ip free $ip in range $range->{'start-address'}-$range->{'end-address'}\n" if $ip;
return $ip;
return if !$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, $fingerprint);
- die "can't find ip $ip in ipam" if !$ip_id;
+ my $ip_id = get_ip_id($plugin_config, $ip, $noerr);
+ if (!defined($ip_id)) {
+ warn "could not find id for ip $ip";
+ return;
+ }
eval {
- PVE::Network::SDN::api_request("DELETE", "$url/ipam/ip-addresses/$ip_id/", $headers, undef, $fingerprint);
+ netbox_api_request($plugin_config, "DELETE", "/ipam/ip-addresses/$ip_id/");
};
if ($@) {
die "error delete ip $ip : $@" if !$noerr;
}
sub get_ips_from_mac {
- my ($class, $plugin_config, $mac, $zoneid) = @_;
-
- 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 ($class, $plugin_config, $mac, $zoneid, $noerr) = @_;
my $ip4 = undef;
my $ip6 = undef;
- my $data = PVE::Network::SDN::api_request(
- "GET", "$url/ipam/ip-addresses/?description__ic=$mac", $headers, undef, $fingerprint);
+ my $data = eval {
+ netbox_api_request($plugin_config, "GET", "/ipam/ip-addresses/?description__ic=$mac");
+ };
for my $ip (@{$data->{results}}) {
if ($ip->{family}->{value} == 4 && !$ip4) {
return ($ip4, $ip6);
}
-
sub verify_api {
my ($class, $plugin_config) = @_;
- 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, undef, $fingerprint);
- };
+ eval { netbox_api_request($plugin_config, "GET", "/ipam/aggregates/"); };
if ($@) {
die "Can't connect to netbox api: $@";
}
sub on_update_hook {
my ($class, $plugin_config) = @_;
-
- PVE::Network::SDN::Ipams::NetboxPlugin::verify_api($class, $plugin_config);
+ verify_api($class, $plugin_config);
}
-#helpers
-
+# helpers
sub get_prefix_id {
- my ($url, $cidr, $headers, $fingerprint) = @_;
- my $result = PVE::Network::SDN::api_request(
- "GET", "$url/ipam/prefixes/?q=$cidr", $headers, undef, $fingerprint);
+ my ($config, $cidr, $noerr) = @_;
+
+ # we need to supply any IP inside the prefix, without supplying the mask, so
+ # just take the one from the cidr
+ my ($ip, undef) = split(/\//, $cidr);
+
+ my $result = eval { netbox_api_request($config, "GET", "/ipam/prefixes/?q=$ip") };
+ if ($@) {
+ return if $noerr;
+ die "could not obtain ID for prefix $cidr: $@";
+ }
+
my $data = @{$result->{results}}[0];
my $internalid = $data->{id};
return $internalid;
}
sub get_iprange_id {
- 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 ($config, $range, $noerr) = @_;
+
+ my $result = eval {
+ netbox_api_request(
+ $config,
+ "GET",
+ "/ipam/ip-ranges/?start_address=$range->{'start-address'}&end_address=$range->{'end-address'}",
+ );
+ };
+ if ($@) {
+ return if $noerr;
+ die "could not obtain ID for IP range $range->{'start-address'}:$range->{'end-address'}: $@";
+ }
+
my $data = @{$result->{results}}[0];
my $internalid = $data->{id};
return $internalid;
}
sub get_ip_id {
- my ($url, $ip, $headers, $fingerprint) = @_;
- my $result = PVE::Network::SDN::api_request(
- "GET", "$url/ipam/ip-addresses/?q=$ip", $headers, undef, $fingerprint);
+ my ($config, $ip, $noerr) = @_;
+
+ my $result = eval { netbox_api_request($config, "GET", "/ipam/ip-addresses/?q=$ip") };
+ if ($@) {
+ return if $noerr;
+ die "could not obtain ID for IP $ip: $@";
+ }
+
my $data = @{$result->{results}}[0];
my $ip_id = $data->{id};
return $ip_id;
}
sub is_ip_gateway {
- my ($url, $ip, $headers, $fingerprint) = @_;
- my $result = PVE::Network::SDN::api_request("GET", "$url/ipam/ip-addresses/?q=$ip", $headers, undef, $fingerprint);
+ my ($config, $ip, $noerr) = @_;
+
+ my $result = eval { netbox_api_request($config, "GET", "/ipam/ip-addresses/?q=$ip") };
+ if ($@) {
+ return if $noerr;
+ die "could not obtain ipam entry for address $ip: $@";
+ }
+
my $data = @{$result->{data}}[0];
my $description = $data->{description};
my $is_gateway = 1 if $description eq 'gateway';