]>
Commit | Line | Data |
---|---|---|
70b03506 AD |
1 | package PVE::Network::SDN::Ipams::PVEPlugin; |
2 | ||
3 | use strict; | |
4 | use warnings; | |
5 | use PVE::INotify; | |
6 | use PVE::Cluster qw(cfs_read_file cfs_write_file cfs_register_file cfs_lock_file); | |
7 | use PVE::Tools; | |
8 | use JSON; | |
9 | use NetAddr::IP; | |
10 | use Digest::SHA; | |
11 | ||
12 | use base('PVE::Network::SDN::Ipams::Plugin'); | |
13 | ||
14 | ||
15 | my $ipamdb_file = "priv/ipam.db"; | |
16 | ||
17 | PVE::Cluster::cfs_register_file($ipamdb_file, | |
18 | sub { PVE::Network::SDN::Ipams::PVEPlugin->parse_config(@_); }, | |
19 | sub { PVE::Network::SDN::Ipams::PVEPlugin->write_config(@_); }); | |
20 | ||
21 | sub type { | |
22 | return 'pve'; | |
23 | } | |
24 | ||
25 | sub properties { | |
26 | } | |
27 | ||
28 | sub options { | |
29 | } | |
30 | ||
31 | # Plugin implementation | |
32 | ||
33 | sub add_subnet { | |
34 | my ($class, $plugin_config, $subnetid, $subnet) = @_; | |
35 | ||
36 | my $cidr = $subnetid =~ s/-/\//r; | |
37 | my $gateway = $subnet->{gateway}; | |
38 | ||
39 | cfs_lock_file($ipamdb_file, undef, sub { | |
40 | my $config = read_db(); | |
41 | #create subnet | |
42 | if (!defined($config->{subnets}->{$cidr})) { | |
43 | $config->{subnets}->{$cidr}->{ips} = {}; | |
44 | write_db($config); | |
45 | } | |
46 | }); | |
47 | die "$@" if $@; | |
48 | } | |
49 | ||
50 | sub del_subnet { | |
51 | my ($class, $plugin_config, $subnetid, $subnet) = @_; | |
52 | ||
53 | my $cidr = $subnetid =~ s/-/\//r; | |
54 | ||
55 | cfs_lock_file($ipamdb_file, undef, sub { | |
56 | ||
57 | my $db = read_db(); | |
58 | my $ips = $db->{subnets}->{$cidr}->{ips}; | |
59 | die "can't delete subnet, not empty" if keys %{$ips} > 0; | |
60 | delete $db->{subnets}->{$cidr}; | |
61 | write_db($db); | |
62 | }); | |
63 | die "$@" if $@; | |
64 | ||
65 | } | |
66 | ||
67 | sub add_ip { | |
68 | my ($class, $plugin_config, $subnetid, $ip, $is_gateway) = @_; | |
69 | ||
70 | my $cidr = $subnetid =~ s/-/\//r; | |
71 | ||
72 | cfs_lock_file($ipamdb_file, undef, sub { | |
73 | ||
74 | my $db = read_db(); | |
75 | my $s = $db->{subnets}->{$cidr}; | |
76 | ||
77 | die "ip already exist" if defined($s->{ips}->{$ip}); | |
78 | ||
79 | #verify that ip is valid for this subnet | |
80 | $s->{ips}->{$ip} = 1; | |
81 | write_db($db); | |
82 | }); | |
83 | die "$@" if $@; | |
84 | } | |
85 | ||
86 | sub add_next_freeip { | |
87 | my ($class, $plugin_config, $subnetid, $subnet) = @_; | |
88 | ||
89 | my $cidr = $subnetid =~ s/-/\//r; | |
90 | my $freeip = undef; | |
91 | ||
92 | cfs_lock_file($ipamdb_file, undef, sub { | |
93 | ||
94 | my $db = read_db(); | |
95 | my $s = $db->{subnets}->{$cidr}; | |
96 | my $iplist = new NetAddr::IP($cidr); | |
97 | my $broadcast = $iplist->broadcast(); | |
98 | ||
99 | while (1) { | |
100 | $iplist++; | |
101 | last if $iplist eq $broadcast; | |
102 | my $ip = $iplist->addr(); | |
103 | next if defined($s->{ips}->{$ip}); | |
104 | $freeip = $ip; | |
105 | last; | |
106 | } | |
107 | ||
108 | die "can't find free ip in subnet '$cidr'\n" if !$freeip; | |
109 | ||
110 | $s->{ips}->{$freeip} = 1; | |
111 | write_db($db); | |
112 | }); | |
113 | die "$@" if $@; | |
114 | ||
115 | my ($network, $mask) = split(/-/, $subnetid); | |
116 | return "$freeip/$mask"; | |
117 | } | |
118 | ||
119 | sub del_ip { | |
120 | my ($class, $plugin_config, $subnetid, $ip) = @_; | |
121 | ||
122 | my $cidr = $subnetid =~ s/-/\//r; | |
123 | ||
124 | cfs_lock_file($ipamdb_file, undef, sub { | |
125 | ||
126 | my $db = read_db(); | |
127 | my $s = $db->{subnets}->{$cidr}; | |
128 | return if !$ip; | |
129 | ||
130 | die "IP '$ip' does not exist in IPAM DB\n" if !defined($s->{ips}->{$ip}); | |
131 | delete $s->{ips}->{$ip}; | |
132 | write_db($db); | |
133 | }); | |
134 | die "$@" if $@; | |
135 | } | |
136 | ||
137 | #helpers | |
138 | ||
139 | sub read_db { | |
140 | my $db = cfs_read_file($ipamdb_file); | |
141 | return $db; | |
142 | } | |
143 | ||
144 | sub write_db { | |
145 | my ($cfg) = @_; | |
146 | ||
147 | my $json = to_json($cfg); | |
148 | cfs_write_file($ipamdb_file, $json); | |
149 | } | |
150 | ||
151 | sub write_config { | |
152 | my ($class, $filename, $cfg) = @_; | |
153 | ||
154 | return $cfg; | |
155 | } | |
156 | ||
157 | sub parse_config { | |
158 | my ($class, $filename, $raw) = @_; | |
159 | ||
160 | $raw = '{}' if !defined($raw) ||$raw eq ''; | |
161 | my $cfg = from_json($raw); | |
162 | ||
163 | return $cfg; | |
164 | } | |
165 | ||
166 | 1; |