]> git.proxmox.com Git - pve-network.git/blob - PVE/Network/Network/VnetPlugin.pm
b255691c102aded0ea98dc763d1c1732b9b1dcf9
[pve-network.git] / PVE / Network / Network / VnetPlugin.pm
1 package PVE::Network::Network::VnetPlugin;
2
3 use strict;
4 use warnings;
5 use PVE::Network::Network::Plugin;
6
7 use base('PVE::Network::Network::Plugin');
8
9 use PVE::Cluster;
10
11 # dynamically include PVE::QemuServer and PVE::LXC
12 # to avoid dependency problems
13 my $have_qemu_server;
14 eval {
15 require PVE::QemuServer;
16 require PVE::QemuConfig;
17 $have_qemu_server = 1;
18 };
19
20 my $have_lxc;
21 eval {
22 require PVE::LXC;
23 require PVE::LXC::Config;
24
25 $have_lxc = 1;
26 };
27
28 sub type {
29 return 'vnet';
30 }
31
32
33
34 sub properties {
35 return {
36 transportzone => {
37 type => 'string',
38 description => "transportzone id",
39 },
40 tag => {
41 type => 'integer',
42 description => "vlan or vxlan id",
43 },
44 alias => {
45 type => 'string',
46 description => "alias name of the vnet",
47 optional => 1,
48 },
49 mtu => {
50 type => 'integer',
51 description => "mtu",
52 optional => 1,
53 },
54 ipv4 => {
55 description => "Anycast router ipv4 address.",
56 type => 'string', format => 'ipv4',
57 optional => 1,
58 },
59 ipv6 => {
60 description => "Anycast router ipv6 address.",
61 type => 'string', format => 'ipv6',
62 optional => 1,
63 },
64 mac => {
65 type => 'boolean',
66 description => "Anycast router mac address",
67 optional => 1,
68 }
69 };
70 }
71
72 sub options {
73 return {
74 transportzone => { optional => 0},
75 tag => { optional => 0},
76 alias => { optional => 1 },
77 ipv4 => { optional => 1 },
78 ipv6 => { optional => 1 },
79 mtu => { optional => 1 },
80 };
81 }
82
83 sub on_delete_hook {
84 my ($class, $networkid, $network_cfg) = @_;
85
86 # verify than no vm or ct have interfaces in this bridge
87 my $vmdata = read_cluster_vm_config();
88
89 foreach my $vmid (sort keys %{$vmdata->{qemu}}) {
90 my $conf = $vmdata->{qemu}->{$vmid};
91 foreach my $netid (sort keys %$conf) {
92 next if $netid !~ m/^net(\d+)$/;
93 my $net = PVE::QemuServer::parse_net($conf->{$netid});
94 die "vnet $networkid is used by vm $vmid" if $net->{bridge} eq $networkid;
95 }
96 }
97
98 foreach my $vmid (sort keys %{$vmdata->{lxc}}) {
99 my $conf = $vmdata->{lxc}->{$vmid};
100 foreach my $netid (sort keys %$conf) {
101 next if $netid !~ m/^net(\d+)$/;
102 my $net = PVE::LXC::Config->parse_lxc_network($conf->{$netid});
103 die "vnet $networkid is used by ct $vmid" if $net->{bridge} eq $networkid;
104 }
105 }
106
107 }
108
109 sub on_update_hook {
110 my ($class, $networkid, $network_cfg) = @_;
111 # verify that tag is not already defined in another vnet
112 if (defined($network_cfg->{ids}->{$networkid}->{tag})) {
113 my $tag = $network_cfg->{ids}->{$networkid}->{tag};
114 foreach my $id (keys %{$network_cfg->{ids}}) {
115 next if $id eq $networkid;
116 my $network = $network_cfg->{ids}->{$id};
117 if ($network->{type} eq 'vnet' && defined($network->{tag})) {
118 die "tag $tag already exist in vnet $id" if $tag eq $network->{tag};
119 }
120 }
121 }
122 }
123
124 sub read_cluster_vm_config {
125
126 my $qemu = {};
127 my $lxc = {};
128
129 my $vmdata = { qemu => $qemu, lxc => $lxc };
130
131 my $vmlist = PVE::Cluster::get_vmlist();
132 return $vmdata if !$vmlist || !$vmlist->{ids};
133 my $ids = $vmlist->{ids};
134
135 foreach my $vmid (keys %$ids) {
136 next if !$vmid;
137 my $d = $ids->{$vmid};
138 next if !$d->{type};
139 if ($d->{type} eq 'qemu' && $have_qemu_server) {
140 my $cfspath = PVE::QemuConfig->cfs_config_path($vmid);
141 if (my $conf = PVE::Cluster::cfs_read_file($cfspath)) {
142 $qemu->{$vmid} = $conf;
143 }
144 } elsif ($d->{type} eq 'lxc' && $have_lxc) {
145 my $cfspath = PVE::LXC::Config->cfs_config_path($vmid);
146 if (my $conf = PVE::Cluster::cfs_read_file($cfspath)) {
147 $lxc->{$vmid} = $conf;
148 }
149 }
150 }
151
152 return $vmdata;
153 };
154
155 1;