]> git.proxmox.com Git - pve-network.git/blame - PVE/Network/SDN/Ipams/PVEPlugin.pm
ipams: add mac address
[pve-network.git] / PVE / Network / SDN / Ipams / PVEPlugin.pm
CommitLineData
70b03506
AD
1package PVE::Network::SDN::Ipams::PVEPlugin;
2
3use strict;
4use warnings;
5use PVE::INotify;
6use PVE::Cluster qw(cfs_read_file cfs_write_file cfs_register_file cfs_lock_file);
7use PVE::Tools;
8use JSON;
aba0731c
AD
9use NetAddr::IP qw(:lower);
10
e8736dac 11use Net::IP;
70b03506
AD
12use Digest::SHA;
13
14use base('PVE::Network::SDN::Ipams::Plugin');
15
16
17my $ipamdb_file = "priv/ipam.db";
18
19PVE::Cluster::cfs_register_file($ipamdb_file,
20 sub { PVE::Network::SDN::Ipams::PVEPlugin->parse_config(@_); },
21 sub { PVE::Network::SDN::Ipams::PVEPlugin->write_config(@_); });
22
23sub type {
24 return 'pve';
25}
26
27sub properties {
28}
29
30sub options {
31}
32
33# Plugin implementation
34
35sub add_subnet {
36 my ($class, $plugin_config, $subnetid, $subnet) = @_;
37
e8736dac
AD
38 my $cidr = $subnet->{cidr};
39 my $zone = $subnet->{zone};
70b03506
AD
40 my $gateway = $subnet->{gateway};
41
e8736dac 42
70b03506 43 cfs_lock_file($ipamdb_file, undef, sub {
e8736dac
AD
44 my $db = {};
45 $db = read_db();
46
47 $db->{zones}->{$zone} = {} if !$db->{zones}->{$zone};
48 my $zonedb = $db->{zones}->{$zone};
49
50 if(!$zonedb->{subnets}->{$cidr}) {
51 #create subnet
52 $zonedb->{subnets}->{$cidr}->{ips} = {};
53 write_db($db);
70b03506
AD
54 }
55 });
56 die "$@" if $@;
57}
58
59sub del_subnet {
60 my ($class, $plugin_config, $subnetid, $subnet) = @_;
61
e8736dac
AD
62 my $cidr = $subnet->{cidr};
63 my $zone = $subnet->{zone};
70b03506
AD
64
65 cfs_lock_file($ipamdb_file, undef, sub {
66
67 my $db = read_db();
e8736dac
AD
68
69 my $dbzone = $db->{zones}->{$zone};
70 die "zone '$zone' doesn't exist in IPAM DB\n" if !$dbzone;
71 my $dbsubnet = $dbzone->{subnets}->{$cidr};
72 die "subnet '$cidr' doesn't exist in IPAM DB\n" if !$dbsubnet;
73
74 die "cannot delete subnet '$cidr', not empty\n" if keys %{$dbsubnet->{ips}} > 0;
75
76 delete $dbzone->{subnets}->{$cidr};
77
70b03506
AD
78 write_db($db);
79 });
80 die "$@" if $@;
81
82}
83
84sub add_ip {
e9365ab0 85 my ($class, $plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $description, $is_gateway) = @_;
70b03506 86
e8736dac
AD
87 my $cidr = $subnet->{cidr};
88 my $zone = $subnet->{zone};
70b03506
AD
89
90 cfs_lock_file($ipamdb_file, undef, sub {
91
92 my $db = read_db();
70b03506 93
e8736dac
AD
94 my $dbzone = $db->{zones}->{$zone};
95 die "zone '$zone' doesn't exist in IPAM DB\n" if !$dbzone;
96 my $dbsubnet = $dbzone->{subnets}->{$cidr};
97 die "subnet '$cidr' doesn't exist in IPAM DB\n" if !$dbsubnet;
98
99 die "IP '$ip' already exist\n" if defined($dbsubnet->{ips}->{$ip});
100
b850741e 101 $dbsubnet->{ips}->{$ip} = {};
70b03506 102
70b03506
AD
103 write_db($db);
104 });
105 die "$@" if $@;
106}
107
108sub add_next_freeip {
e9365ab0 109 my ($class, $plugin_config, $subnetid, $subnet, $hostname, $mac, $description) = @_;
70b03506 110
e8736dac
AD
111 my $cidr = $subnet->{cidr};
112 my $network = $subnet->{network};
113 my $zone = $subnet->{zone};
114 my $mask = $subnet->{mask};
70b03506
AD
115 my $freeip = undef;
116
117 cfs_lock_file($ipamdb_file, undef, sub {
118
119 my $db = read_db();
e8736dac
AD
120 my $dbzone = $db->{zones}->{$zone};
121 die "zone '$zone' doesn't exist in IPAM DB\n" if !$dbzone;
122 my $dbsubnet = $dbzone->{subnets}->{$cidr};
123 die "subnet '$cidr' doesn't exist in IPAM DB" if !$dbsubnet;
124
125 if (Net::IP::ip_is_ipv4($network) && $mask == 32) {
126 die "cannot find free IP in subnet '$cidr'\n" if defined($dbsubnet->{ips}->{$network});
127 $freeip = $network;
128 } else {
129 my $iplist = new NetAddr::IP($cidr);
130 my $broadcast = $iplist->broadcast();
131
132 while(1) {
133 $iplist++;
134 last if $iplist eq $broadcast;
aba0731c 135 my $ip = $iplist->canon();
e8736dac
AD
136 next if defined($dbsubnet->{ips}->{$ip});
137 $freeip = $ip;
138 last;
139 }
70b03506
AD
140 }
141
142 die "can't find free ip in subnet '$cidr'\n" if !$freeip;
143
b850741e 144 $dbsubnet->{ips}->{$freeip} = {};
ceb972a9 145
70b03506
AD
146 write_db($db);
147 });
148 die "$@" if $@;
149
70b03506
AD
150 return "$freeip/$mask";
151}
152
153sub del_ip {
e8736dac 154 my ($class, $plugin_config, $subnetid, $subnet, $ip) = @_;
70b03506 155
e8736dac
AD
156 my $cidr = $subnet->{cidr};
157 my $zone = $subnet->{zone};
70b03506
AD
158
159 cfs_lock_file($ipamdb_file, undef, sub {
160
161 my $db = read_db();
e8736dac
AD
162 die "zone $zone don't exist in ipam db" if !$db->{zones}->{$zone};
163 my $dbzone = $db->{zones}->{$zone};
164 die "subnet $cidr don't exist in ipam db" if !$dbzone->{subnets}->{$cidr};
165 my $dbsubnet = $dbzone->{subnets}->{$cidr};
166
167 die "IP '$ip' does not exist in IPAM DB\n" if !defined($dbsubnet->{ips}->{$ip});
168 delete $dbsubnet->{ips}->{$ip};
70b03506 169
70b03506
AD
170 write_db($db);
171 });
172 die "$@" if $@;
173}
174
175#helpers
176
177sub read_db {
178 my $db = cfs_read_file($ipamdb_file);
179 return $db;
180}
181
182sub write_db {
183 my ($cfg) = @_;
184
185 my $json = to_json($cfg);
186 cfs_write_file($ipamdb_file, $json);
187}
188
189sub write_config {
190 my ($class, $filename, $cfg) = @_;
191
192 return $cfg;
193}
194
195sub parse_config {
196 my ($class, $filename, $raw) = @_;
197
198 $raw = '{}' if !defined($raw) ||$raw eq '';
199 my $cfg = from_json($raw);
200
201 return $cfg;
202}
203
2041;