]> git.proxmox.com Git - pve-network.git/blob - PVE/Network/SDN/SubnetPlugin.pm
vnets: add subnets
[pve-network.git] / PVE / Network / SDN / SubnetPlugin.pm
1 package PVE::Network::SDN::SubnetPlugin;
2
3 use strict;
4 use warnings;
5
6 use PVE::Cluster qw(cfs_read_file cfs_write_file cfs_lock_file);
7 use base qw(PVE::SectionConfig);
8 use PVE::JSONSchema qw(get_standard_option);
9 use PVE::Exception qw(raise raise_param_exc);
10 use Net::Subnet qw(subnet_matcher);
11
12 PVE::Cluster::cfs_register_file('sdn/subnets.cfg',
13 sub { __PACKAGE__->parse_config(@_); },
14 sub { __PACKAGE__->write_config(@_); });
15
16 PVE::JSONSchema::register_standard_option('pve-sdn-subnet-id', {
17 description => "The SDN subnet object identifier.",
18 type => 'string', format => 'pve-sdn-subnet-id',
19 type => 'string'
20 });
21
22 PVE::JSONSchema::register_format('pve-sdn-subnet-id', \&parse_sdn_subnet_id);
23 sub parse_sdn_subnet_id {
24 my ($id, $noerr) = @_;
25
26 my $cidr = $id =~ s/-/\//r;
27
28 if (!(PVE::JSONSchema::pve_verify_cidrv4($cidr, 1) ||
29 PVE::JSONSchema::pve_verify_cidrv6($cidr, 1)))
30 {
31 return undef if $noerr;
32 die "value does not look like a valid CIDR network\n";
33 }
34 return $id;
35 }
36
37 my $defaultData = {
38
39 propertyList => {
40 subnet => get_standard_option('pve-sdn-subnet-id',
41 { completion => \&PVE::Network::SDN::Subnets::complete_sdn_subnet }),
42 },
43 };
44
45 sub type {
46 return 'subnet';
47 }
48
49 sub private {
50 return $defaultData;
51 }
52
53 sub properties {
54 return {
55 gateway => {
56 type => 'string', format => 'ip',
57 description => "Subnet Gateway: Will be assign on vnet for layer3 zones",
58 },
59 snat => {
60 type => 'boolean',
61 description => "enable masquerade for this subnet if pve-firewall",
62 },
63 #cloudinit, dhcp options
64 routes => {
65 type => 'string',
66 description => "static routes [network=<network>:gateway=<ip>,network=<network>:gateway=<ip>,... ]",
67 },
68 #cloudinit, dhcp options
69 nameservers => {
70 type => 'string', format => 'address-list',
71 description => " dns nameserver",
72 },
73 #cloudinit, dhcp options
74 searchdomain => {
75 type => 'string',
76 },
77 dhcp => {
78 type => 'boolean',
79 description => "enable dhcp for this subnet",
80 },
81 dns_driver => {
82 type => 'string',
83 description => "Develop some dns registrations plugins (powerdns,...)",
84 },
85 ipam_driver => {
86 type => 'string',
87 description => "use a specific ipam",
88 },
89 };
90 }
91
92 sub options {
93 return {
94 gateway => { optional => 1 },
95 routes => { optional => 1 },
96 nameservers => { optional => 1 },
97 searchdomain => { optional => 1 },
98 snat => { optional => 1 },
99 dhcp => { optional => 1 },
100 dns_driver => { optional => 1 },
101 ipam_driver => { optional => 1 },
102 };
103 }
104
105 sub on_update_hook {
106 my ($class, $subnetid, $subnet_cfg) = @_;
107
108 my $subnet = $subnetid =~ s/-/\//r;
109 my $subnet_matcher = subnet_matcher($subnet);
110
111 my $gateway = $subnet_cfg->{ids}->{$subnetid}->{gateway};
112 raise_param_exc({ gateway => "$gateway is not in subnet $subnet"}) if $gateway && !$subnet_matcher->($gateway);
113 }
114
115 sub on_delete_hook {
116 my ($class, $subnetid, $subnet_cfg, $vnet_cfg) = @_;
117
118 #verify if vnets have subnet
119 foreach my $vnetid (keys %{$vnet_cfg->{ids}}) {
120 my $vnet = $vnet_cfg->{ids}->{$vnetid};
121 my @subnets = PVE::Tools::split_list($vnet->{subnets}) if $vnet->{subnets};
122 foreach my $subnet (@subnets) {
123 my $id = $subnet =~ s/\//-/r;
124 raise_param_exc({ subnet => "$subnet is attached to vnet $vnetid"}) if $id eq $subnetid;
125 }
126 }
127
128 return;
129 }
130
131 1;