]> git.proxmox.com Git - pve-network.git/blame - PVE/Network/SDN.pm
sdn: fix : pending parser
[pve-network.git] / PVE / Network / SDN.pm
CommitLineData
86d22462 1package PVE::Network::SDN;
92b6f291
AD
2
3use strict;
4use warnings;
434125ce 5
92b6f291 6use Data::Dumper;
c665cefc 7use JSON;
434125ce 8
e382bf71
AD
9use PVE::JSONSchema;
10
7129a3ca 11use PVE::Network::SDN::Vnets;
f5eabba0 12use PVE::Network::SDN::Zones;
5d3e0248
AD
13use PVE::Network::SDN::Controllers;
14use PVE::Network::SDN::Subnets;
f5eabba0 15
434125ce 16use PVE::Tools qw(extract_param dir_glob_regex run_command);
92b6f291 17use PVE::Cluster qw(cfs_read_file cfs_write_file cfs_lock_file);
92b6f291 18
f9bc9640 19
5d3e0248 20my $running_cfg = "sdn/.running-config";
f9bc9640 21
5d3e0248 22my $parse_running_cfg = sub {
f9bc9640
AD
23 my ($filename, $raw) = @_;
24
5d3e0248 25 my $cfg = {};
28664c9b 26
5d3e0248 27 return $cfg if !defined($raw) || $raw eq '';
f9bc9640 28
5d3e0248
AD
29 eval {
30 $cfg = from_json($raw);
31 };
32 return {} if $@;
33
34 return $cfg;
f9bc9640
AD
35};
36
5d3e0248
AD
37my $write_running_cfg = sub {
38 my ($filename, $cfg) = @_;
f9bc9640 39
5d3e0248 40 my $json = to_json($cfg);
f9bc9640 41
5d3e0248 42 return $json;
f9bc9640
AD
43};
44
5d3e0248 45PVE::Cluster::cfs_register_file($running_cfg, $parse_running_cfg, $write_running_cfg);
f9bc9640
AD
46
47
f5eabba0 48# improve me : move status code inside plugins ?
92b6f291 49
e424c7ac 50sub ifquery_check {
c665cefc
AD
51
52 my $cmd = ['ifquery', '-a', '-c', '-o','json'];
c665cefc 53
0c5021ad
TL
54 my $result = '';
55 my $reader = sub { $result .= shift };
c665cefc
AD
56
57 eval {
6e9fff39 58 run_command($cmd, outfunc => $reader);
c665cefc
AD
59 };
60
6e9fff39 61 my $resultjson = decode_json($result);
c665cefc
AD
62 my $interfaces = {};
63
64 foreach my $interface (@$resultjson) {
6e9fff39
AD
65 my $name = $interface->{name};
66 $interfaces->{$name} = {
67 status => $interface->{status},
68 config => $interface->{config},
69 config_status => $interface->{config_status},
70 };
c665cefc
AD
71 }
72
73 return $interfaces;
74}
75
e424c7ac
AD
76sub status {
77
56cdcac9
AD
78 my ($zone_status, $vnet_status) = PVE::Network::SDN::Zones::status();
79 return($zone_status, $vnet_status);
e424c7ac
AD
80}
81
5d3e0248
AD
82sub config {
83 return cfs_read_file($running_cfg);
84}
85
6f5f42e4
AD
86sub pending_config {
87 my ($running_cfg, $cfg, $type) = @_;
88
89 my $pending = {};
90
91 my $running_objects = $running_cfg->{$type}->{ids};
92 my $config_objects = $cfg->{ids};
93
94 foreach my $id (sort keys %{$running_objects}) {
95 my $running_object = $running_objects->{$id};
96 my $config_object = $config_objects->{$id};
97 foreach my $key (sort keys %{$running_object}) {
98 $pending->{$id}->{$key} = $running_object->{$key};
99 if(!keys %{$config_object}) {
100 $pending->{$id}->{state} = "deleted";
e382bf71
AD
101 } elsif (!defined($config_object->{$key})) {
102 $pending->{$id}->{"pending"}->{$key} = 'deleted';
103 $pending->{$id}->{state} = "changed";
104 } elsif (PVE::Network::SDN::encode_value(undef, $key, $running_object->{$key})
105 ne PVE::Network::SDN::encode_value(undef, $key, $config_object->{$key})) {
6f5f42e4
AD
106 $pending->{$id}->{state} = "changed";
107 }
108 }
109 }
110
111 foreach my $id (sort keys %{$config_objects}) {
112 my $running_object = $running_objects->{$id};
113 my $config_object = $config_objects->{$id};
114
115 foreach my $key (sort keys %{$config_object}) {
e382bf71
AD
116 my $config_value = PVE::Network::SDN::encode_value(undef, $key, $config_object->{$key}) if $config_object->{$key};
117 my $running_value = PVE::Network::SDN::encode_value(undef, $key, $running_object->{$key}) if $running_object->{$key};
6f5f42e4
AD
118 if($key eq 'type' || $key eq 'vnet') {
119 $pending->{$id}->{$key} = $config_value;
120 } else {
121 $pending->{$id}->{"pending"}->{$key} = $config_value if !defined($running_value) || ($config_value ne $running_value);
122 }
123 if(!keys %{$running_object}) {
124 $pending->{$id}->{state} = "new";
125 } elsif (!defined($running_value) && defined($config_value)) {
126 $pending->{$id}->{state} = "changed";
127 }
128 }
129 }
130
131 return {ids => $pending};
132
133}
134
5d3e0248 135sub commit_config {
f9bc9640 136
5d3e0248
AD
137 my $cfg = cfs_read_file($running_cfg);
138 my $version = $cfg->{version};
f9bc9640 139
22b24447 140 if ($version) {
f9bc9640
AD
141 $version++;
142 } else {
143 $version = 1;
144 }
145
5d3e0248
AD
146 my $vnets_cfg = PVE::Network::SDN::Vnets::config();
147 my $zones_cfg = PVE::Network::SDN::Zones::config();
148 my $controllers_cfg = PVE::Network::SDN::Controllers::config();
149 my $subnets_cfg = PVE::Network::SDN::Subnets::config();
150
151 my $vnets = { ids => $vnets_cfg->{ids} };
152 my $zones = { ids => $zones_cfg->{ids} };
153 my $controllers = { ids => $controllers_cfg->{ids} };
154 my $subnets = { ids => $subnets_cfg->{ids} };
155
156 $cfg = { version => $version, vnets => $vnets, zones => $zones, controllers => $controllers, subnets => $subnets };
157
158 cfs_write_file($running_cfg, $cfg);
f9bc9640
AD
159}
160
161sub lock_sdn_config {
162 my ($code, $errmsg) = @_;
163
5d3e0248 164 cfs_lock_file($running_cfg, undef, $code);
f9bc9640
AD
165
166 if (my $err = $@) {
167 $errmsg ? die "$errmsg: $err" : die $err;
168 }
169}
170
7129a3ca
AD
171sub get_local_vnets {
172
173 my $rpcenv = PVE::RPCEnvironment::get();
174
175 my $authuser = $rpcenv->get_user();
176
177 my $nodename = PVE::INotify::nodename();
178
5d3e0248
AD
179 my $cfg = PVE::Network::SDN::config();
180 my $vnets_cfg = $cfg->{vnets};
181 my $zones_cfg = $cfg->{zones};
7129a3ca
AD
182
183 my @vnetids = PVE::Network::SDN::Vnets::sdn_vnets_ids($vnets_cfg);
184
185 my $vnets = {};
186
187 foreach my $vnetid (@vnetids) {
188
189 my $vnet = PVE::Network::SDN::Vnets::sdn_vnets_config($vnets_cfg, $vnetid);
190 my $zoneid = $vnet->{zone};
191 my $privs = [ 'SDN.Audit', 'SDN.Allocate' ];
192
193 next if !$zoneid;
194 next if !$rpcenv->check_any($authuser, "/sdn/zones/$zoneid", $privs, 1);
195
196 my $zone_config = PVE::Network::SDN::Zones::sdn_zones_config($zones_cfg, $zoneid);
197
198 next if defined($zone_config->{nodes}) && !$zone_config->{nodes}->{$nodename};
199 $vnets->{$vnetid} = { type => 'vnet', active => '1' };
200 }
201
202 return $vnets;
203}
204
22b24447
TL
205sub generate_zone_config {
206 my $raw_config = PVE::Network::SDN::Zones::generate_etc_network_config();
207 PVE::Network::SDN::Zones::write_etc_network_config($raw_config);
208}
209
210sub generate_controller_config {
211 my ($reload) = @_;
212
213 my $raw_config = PVE::Network::SDN::Controllers::generate_controller_config();
214 PVE::Network::SDN::Controllers::write_controller_config($raw_config);
215
216 PVE::Network::SDN::Controllers::reload_controller() if $reload;
217}
218
e382bf71
AD
219
220sub decode_value {
221 my ($type, $key, $value) = @_;
222
223 if ($key eq 'nodes') {
224 my $res = {};
225
226 foreach my $node (PVE::Tools::split_list($value)) {
227 if (PVE::JSONSchema::pve_verify_node_name($node)) {
228 $res->{$node} = 1;
229 }
230 }
231
232 return $res;
233 }
234
235 return $value;
236}
237
238sub encode_value {
239 my ($type, $key, $value) = @_;
240
241 if ($key eq 'nodes' || $key eq 'exitnodes') {
242 if(ref($value) eq 'HASH') {
243 return join(',', sort keys(%$value));
244 } else {
245 return $value;
246 }
247 }
248
249 return $value;
250}
251
e424c7ac 2521;
80348b2d 253