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