]> git.proxmox.com Git - pve-network.git/blob - PVE/Network/SDN/Ipams/NetboxPlugin.pm
01f82f2201f576547285e6984dabc33d69ad4831
[pve-network.git] / PVE / Network / SDN / Ipams / NetboxPlugin.pm
1 package PVE::Network::SDN::Ipams::NetboxPlugin;
2
3 use strict;
4 use warnings;
5 use PVE::INotify;
6 use PVE::Cluster;
7 use PVE::Tools;
8
9 use base('PVE::Network::SDN::Ipams::Plugin');
10
11 sub type {
12 return 'netbox';
13 }
14
15 sub properties {
16 return {
17 };
18 }
19
20 sub options {
21
22 return {
23 url => { optional => 0},
24 token => { optional => 0 },
25 };
26 }
27
28 # Plugin implementation
29
30 sub add_subnet {
31 my ($class, $plugin_config, $subnetid, $subnet) = @_;
32
33 my $cidr = $subnetid =~ s/-/\//r;
34 my $gateway = $subnet->{gateway};
35 my $url = $plugin_config->{url};
36 my $token = $plugin_config->{token};
37 my $headers = ['Content-Type' => 'application/json; charset=UTF-8', 'Authorization' => "token $token"];
38
39 my $internalid = get_prefix_id($url, $cidr, $headers);
40
41 #create subnet
42 if (!$internalid) {
43 my ($network, $mask) = split(/-/, $subnetid);
44
45 my $params = { prefix => $cidr };
46
47 eval {
48 my $result = PVE::Network::SDN::Ipams::Plugin::api_request("POST", "$url/ipam/prefixes/", $headers, $params);
49 $subnet->{ipamid} = $result->{id} if defined($result->{id});
50 };
51 if ($@) {
52 die "error add subnet to ipam: $@";
53 }
54 }
55
56 }
57
58 sub del_subnet {
59 my ($class, $plugin_config, $subnetid, $subnet) = @_;
60
61 my $cidr = $subnetid =~ s/-/\//r;
62 my $url = $plugin_config->{url};
63 my $token = $plugin_config->{token};
64 my $gateway = $subnet->{gateway};
65 my $headers = ['Content-Type' => 'application/json; charset=UTF-8', 'Authorization' => "token $token"];
66
67 my $internalid = get_prefix_id($url, $cidr, $headers);
68 return if !$internalid;
69 #fixme: check that prefix is empty exluding gateway, before delete
70
71 PVE::Network::SDN::Ipams::NetboxPlugin::del_ip($class, $plugin_config, $subnetid, $gateway) if $gateway;
72
73 eval {
74 PVE::Network::SDN::Ipams::Plugin::api_request("DELETE", "$url/ipam/prefixes/$internalid/", $headers);
75 };
76 if ($@) {
77 die "error deleting subnet from ipam: $@";
78 }
79
80 }
81
82 sub add_ip {
83 my ($class, $plugin_config, $subnetid, $ip, $is_gateway) = @_;
84
85 my ($network, $mask) = split(/-/, $subnetid);
86 my $url = $plugin_config->{url};
87 my $token = $plugin_config->{token};
88 my $section = $plugin_config->{section};
89 my $headers = ['Content-Type' => 'application/json; charset=UTF-8', 'Authorization' => "token $token"];
90
91 my $params = { address => "$ip/$mask" };
92
93 eval {
94 PVE::Network::SDN::Ipams::Plugin::api_request("POST", "$url/ipam/ip-addresses/", $headers, $params);
95 };
96
97 if ($@) {
98 die "error add subnet ip to ipam: ip already exist: $@";
99 }
100 }
101
102 sub add_next_freeip {
103 my ($class, $plugin_config, $subnetid, $subnet) = @_;
104
105 my $cidr = $subnetid =~ s/-/\//r;
106 my $url = $plugin_config->{url};
107 my $token = $plugin_config->{token};
108 my $headers = ['Content-Type' => 'application/json; charset=UTF-8', 'Authorization' => "token $token"];
109
110 my $internalid = get_prefix_id($url, $cidr, $headers);
111
112 my $params = {};
113
114 my $ip = undef;
115 eval {
116 my $result = PVE::Network::SDN::Ipams::Plugin::api_request("POST", "$url/ipam/prefixes/$internalid/available-ips/", $headers, $params);
117 $ip = $result->{address};
118 };
119
120 if ($@) {
121 die "can't find free ip in subnet $cidr: $@";
122 }
123
124 return $ip;
125 }
126
127 sub del_ip {
128 my ($class, $plugin_config, $subnetid, $ip) = @_;
129
130 return if !$ip;
131
132 my $url = $plugin_config->{url};
133 my $token = $plugin_config->{token};
134 my $headers = ['Content-Type' => 'application/json; charset=UTF-8', 'Authorization' => "token $token"];
135
136 my $ip_id = get_ip_id($url, $ip, $headers);
137 die "can't find ip $ip in ipam" if !$ip_id;
138
139 eval {
140 PVE::Network::SDN::Ipams::Plugin::api_request("DELETE", "$url/ipam/ip-addresses/$ip_id/", $headers);
141 };
142 if ($@) {
143 die "error delete ip $ip : $@";
144 }
145 }
146
147 sub verify_api {
148 my ($class, $plugin_config) = @_;
149
150 my $url = $plugin_config->{url};
151 my $token = $plugin_config->{token};
152 my $headers = ['Content-Type' => 'application/json; charset=UTF-8', 'Authorization' => "token $token"];
153
154
155 eval {
156 PVE::Network::SDN::Ipams::Plugin::api_request("GET", "$url/ipam/aggregates/", $headers);
157 };
158 if ($@) {
159 die "Can't connect to netbox api: $@";
160 }
161 }
162
163 sub on_update_hook {
164 my ($class, $plugin_config) = @_;
165
166 PVE::Network::SDN::Ipams::NetboxPlugin::verify_api($class, $plugin_config);
167 }
168
169 #helpers
170
171 sub get_prefix_id {
172 my ($url, $cidr, $headers) = @_;
173
174 my $result = PVE::Network::SDN::Ipams::Plugin::api_request("GET", "$url/ipam/prefixes/?q=$cidr", $headers);
175 my $data = @{$result->{results}}[0];
176 my $internalid = $data->{id};
177 return $internalid;
178 }
179
180 sub get_ip_id {
181 my ($url, $ip, $headers) = @_;
182 my $result = PVE::Network::SDN::Ipams::Plugin::api_request("GET", "$url/ipam/ip-addresses/?q=$ip", $headers);
183 my $data = @{$result->{results}}[0];
184 my $ip_id = $data->{id};
185 return $ip_id;
186 }
187
188
189 1;
190
191