]> git.proxmox.com Git - pve-network.git/blob - PVE/Network/SDN/Subnets.pm
move dns options from subnets to zone
[pve-network.git] / PVE / Network / SDN / Subnets.pm
1 package PVE::Network::SDN::Subnets;
2
3 use strict;
4 use warnings;
5
6 use Net::Subnet qw(subnet_matcher);
7 use PVE::Cluster qw(cfs_read_file cfs_write_file cfs_lock_file);
8 use Net::IP;
9
10 use PVE::Network::SDN::Ipams;
11 use PVE::Network::SDN::Dns;
12 use PVE::Network::SDN::SubnetPlugin;
13 PVE::Network::SDN::SubnetPlugin->register();
14 PVE::Network::SDN::SubnetPlugin->init();
15
16 sub sdn_subnets_config {
17 my ($cfg, $id, $noerr) = @_;
18
19 die "no sdn subnet ID specified\n" if !$id;
20
21 my $scfg = $cfg->{ids}->{$id};
22 die "sdn subnet '$id' does not exist\n" if (!$noerr && !$scfg);
23
24 return $scfg;
25 }
26
27 sub config {
28 my $config = cfs_read_file("sdn/subnets.cfg");
29 }
30
31 sub write_config {
32 my ($cfg) = @_;
33
34 cfs_write_file("sdn/subnets.cfg", $cfg);
35 }
36
37 sub sdn_subnets_ids {
38 my ($cfg) = @_;
39
40 return keys %{$cfg->{ids}};
41 }
42
43 sub complete_sdn_subnet {
44 my ($cmdname, $pname, $cvalue) = @_;
45
46 my $cfg = PVE::Network::SDN::Subnets::config();
47
48 return $cmdname eq 'add' ? [] : [ PVE::Network::SDN::Subnets::sdn_subnets_ids($cfg) ];
49 }
50
51 sub get_subnet {
52 my ($subnetid, $running) = @_;
53
54 my $cfg = {};
55 if($running) {
56 my $cfg = PVE::Network::SDN::config();
57 $cfg = $cfg->{subnets};
58 } else {
59 $cfg = PVE::Network::SDN::Subnets::config();
60 }
61
62 my $subnet = PVE::Network::SDN::Subnets::sdn_subnets_config($cfg, $subnetid, 1);
63 return $subnet;
64 }
65
66 sub find_ip_subnet {
67 my ($ip, $subnets) = @_;
68
69 my $subnet = undef;
70 my $subnetid = undef;
71
72 foreach my $id (sort keys %{$subnets}) {
73 my $cidr = $id =~ s/-/\//r;
74 my $subnet_matcher = subnet_matcher($cidr);
75 next if !$subnet_matcher->($ip);
76 $subnet = $subnets->{$id};
77 $subnetid = $id;
78 last;
79 }
80 die "can't find any subnet for ip $ip" if !$subnet;
81
82 return ($subnetid, $subnet);
83 }
84
85 my $verify_dns_zone = sub {
86 my ($zone, $dns) = @_;
87
88 return if !$zone || !$dns;
89
90 my $dns_cfg = PVE::Network::SDN::Dns::config();
91 my $plugin_config = $dns_cfg->{ids}->{$dns};
92 my $plugin = PVE::Network::SDN::Dns::Plugin->lookup($plugin_config->{type});
93 $plugin->verify_zone($plugin_config, $zone);
94 };
95
96 my $get_reversedns_zone = sub {
97 my ($subnetid, $dns, $ip) = @_;
98
99 return if !$subnetid || !$dns || !$ip;
100
101 my $dns_cfg = PVE::Network::SDN::Dns::config();
102 my $plugin_config = $dns_cfg->{ids}->{$dns};
103 my $plugin = PVE::Network::SDN::Dns::Plugin->lookup($plugin_config->{type});
104 $plugin->get_reversedns_zone($plugin_config, $subnetid, $ip);
105 };
106
107 my $add_dns_record = sub {
108 my ($zone, $dns, $hostname, $dnszoneprefix, $ip) = @_;
109 return if !$zone || !$dns || !$hostname || !$ip;
110
111 $hostname .= ".$dnszoneprefix" if $dnszoneprefix;
112
113 my $dns_cfg = PVE::Network::SDN::Dns::config();
114 my $plugin_config = $dns_cfg->{ids}->{$dns};
115 my $plugin = PVE::Network::SDN::Dns::Plugin->lookup($plugin_config->{type});
116 $plugin->add_a_record($plugin_config, $zone, $hostname, $ip);
117
118 };
119
120 my $add_dns_ptr_record = sub {
121 my ($reversezone, $zone, $dns, $hostname, $dnszoneprefix, $ip) = @_;
122
123 return if !$zone || !$reversezone || !$dns || !$hostname || !$ip;
124
125 $hostname .= ".$dnszoneprefix" if $dnszoneprefix;
126 $hostname .= ".$zone";
127 my $dns_cfg = PVE::Network::SDN::Dns::config();
128 my $plugin_config = $dns_cfg->{ids}->{$dns};
129 my $plugin = PVE::Network::SDN::Dns::Plugin->lookup($plugin_config->{type});
130 $plugin->add_ptr_record($plugin_config, $reversezone, $hostname, $ip);
131 };
132
133 my $del_dns_record = sub {
134 my ($zone, $dns, $hostname, $dnszoneprefix, $ip) = @_;
135
136 return if !$zone || !$dns || !$hostname || !$ip;
137
138 $hostname .= ".$dnszoneprefix" if $dnszoneprefix;
139
140 my $dns_cfg = PVE::Network::SDN::Dns::config();
141 my $plugin_config = $dns_cfg->{ids}->{$dns};
142 my $plugin = PVE::Network::SDN::Dns::Plugin->lookup($plugin_config->{type});
143 $plugin->del_a_record($plugin_config, $zone, $hostname, $ip);
144 };
145
146 my $del_dns_ptr_record = sub {
147 my ($reversezone, $dns, $ip) = @_;
148
149 return if !$reversezone || !$dns || !$ip;
150
151 my $dns_cfg = PVE::Network::SDN::Dns::config();
152 my $plugin_config = $dns_cfg->{ids}->{$dns};
153 my $plugin = PVE::Network::SDN::Dns::Plugin->lookup($plugin_config->{type});
154 $plugin->del_ptr_record($plugin_config, $reversezone, $ip);
155 };
156
157 sub next_free_ip {
158 my ($zone, $subnetid, $subnet, $hostname) = @_;
159
160 my $cidr = undef;
161 my $ip = undef;
162
163 my $ipamid = $subnet->{ipam};
164 my $dns = $zone->{dns};
165 my $dnszone = $zone->{dnszone};
166 my $reversedns = $zone->{reversedns};
167 my $dnszoneprefix = $subnet->{dnszoneprefix};
168
169 #verify dns zones before ipam
170 &$verify_dns_zone($dnszone, $dns);
171
172 if($ipamid) {
173 my $ipam_cfg = PVE::Network::SDN::Ipams::config();
174 my $plugin_config = $ipam_cfg->{ids}->{$ipamid};
175 my $plugin = PVE::Network::SDN::Ipams::Plugin->lookup($plugin_config->{type});
176 eval {
177 $cidr = $plugin->add_next_freeip($plugin_config, $subnetid, $subnet);
178 ($ip, undef) = split(/\//, $cidr);
179 };
180 die $@ if $@;
181 }
182
183 eval {
184 my $reversednszone = &$get_reversedns_zone($subnetid, $reversedns, $ip);
185
186 #add dns
187 &$add_dns_record($dnszone, $dns, $hostname, $dnszoneprefix, $ip);
188 #add reverse dns
189 &$add_dns_ptr_record($reversednszone, $dnszone, $reversedns, $hostname, $dnszoneprefix, $ip);
190 };
191 if ($@) {
192 #rollback
193 my $err = $@;
194 eval {
195 PVE::Network::SDN::Subnets::del_ip($subnetid, $subnet, $ip, $hostname)
196 };
197 die $err;
198 }
199 return $cidr;
200 }
201
202 sub add_ip {
203 my ($zone, $subnetid, $subnet, $ip, $hostname) = @_;
204
205 return if !$subnet;
206
207 my $ipamid = $subnet->{ipam};
208 my $dns = $zone->{dns};
209 my $dnszone = $zone->{dnszone};
210 my $reversedns = $zone->{reversedns};
211 my $reversednszone = &$get_reversedns_zone($subnetid, $reversedns, $ip);
212 my $dnszoneprefix = $subnet->{dnszoneprefix};
213
214 #verify dns zones before ipam
215 &$verify_dns_zone($dnszone, $dns);
216 &$verify_dns_zone($reversednszone, $reversedns);
217
218 if ($ipamid) {
219 my $ipam_cfg = PVE::Network::SDN::Ipams::config();
220 my $plugin_config = $ipam_cfg->{ids}->{$ipamid};
221 my $plugin = PVE::Network::SDN::Ipams::Plugin->lookup($plugin_config->{type});
222 eval {
223 $plugin->add_ip($plugin_config, $subnetid, $ip);
224 };
225 die $@ if $@;
226 }
227
228 eval {
229 #add dns
230 &$add_dns_record($dnszone, $dns, $hostname, $dnszoneprefix, $ip);
231 #add reverse dns
232 &$add_dns_ptr_record($reversednszone, $dnszone, $reversedns, $hostname, $dnszoneprefix, $ip);
233 };
234 if ($@) {
235 #rollback
236 my $err = $@;
237 eval {
238 PVE::Network::SDN::Subnets::del_ip($subnetid, $subnet, $ip, $hostname)
239 };
240 die $err;
241 }
242 }
243
244 sub del_ip {
245 my ($zone, $subnetid, $subnet, $ip, $hostname) = @_;
246
247 return if !$subnet;
248
249 my $ipamid = $subnet->{ipam};
250 my $dns = $zone->{dns};
251 my $dnszone = $zone->{dnszone};
252 my $reversedns = $zone->{reversedns};
253 my $reversednszone = &$get_reversedns_zone($subnetid, $reversedns, $ip);
254 my $dnszoneprefix = $subnet->{dnszoneprefix};
255
256 &$verify_dns_zone($dnszone, $dns);
257 &$verify_dns_zone($reversednszone, $reversedns);
258
259 if ($ipamid) {
260 my $ipam_cfg = PVE::Network::SDN::Ipams::config();
261 my $plugin_config = $ipam_cfg->{ids}->{$ipamid};
262 my $plugin = PVE::Network::SDN::Ipams::Plugin->lookup($plugin_config->{type});
263 $plugin->del_ip($plugin_config, $subnetid, $ip);
264 }
265
266 eval {
267 &$del_dns_record($dnszone, $dns, $hostname, $dnszoneprefix, $ip);
268 &$del_dns_ptr_record($reversednszone, $reversedns, $ip);
269 };
270 if ($@) {
271 warn $@;
272 }
273 }
274
275 1;