]> git.proxmox.com Git - pve-manager.git/blame - PVE/API2/Network.pm
improve network API - add more gettext markers
[pve-manager.git] / PVE / API2 / Network.pm
CommitLineData
aff192e6
DM
1package PVE::API2::Network;
2
3use strict;
4use warnings;
5
6use PVE::Tools qw(extract_param);
7use PVE::SafeSyslog;
8use PVE::INotify;
9use PVE::Exception qw(raise_param_exc);
10use PVE::RESTHandler;
11use PVE::RPCEnvironment;
12use PVE::JSONSchema qw(get_standard_option);
13use PVE::AccessControl;
14use IO::File;
15
16use base qw(PVE::RESTHandler);
17
18my $iflockfn = "/etc/network/.pve-interfaces.lock";
19
20my $bond_mode_enum = [
21 'balance-rr',
22 'active-backup',
23 'balance-xor',
24 'broadcast',
25 '802.3ad',
26 'balance-tlb',
27 'balance-alb'
28 ];
29
30my $confdesc = {
31 autostart => {
32 description => "Automatically start interface on boot.",
33 type => 'boolean',
34 optional => 1,
35 },
36 bridge_ports => {
37 description => "Specify the iterfaces you want to add to your bridge.",
38 optional => 1,
39 type => 'string', format => 'pve-iface-list',
40 },
41 slaves => {
42 description => "Specify the interfaces used by the bonding device.",
43 optional => 1,
44 type => 'string', format => 'pve-iface-list',
45 },
46 bond_mode => {
47 description => "Bonding mode.",
48 optional => 1,
49 type => 'string', enum => $bond_mode_enum,
50 },
51 gateway => {
52 description => 'Default gateway address.',
53 type => 'string', format => 'ipv4',
54 optional => 1,
55 },
56 netmask => {
57 description => 'Network mask.',
58 type => 'string', format => 'ipv4mask',
59 optional => 1,
60 },
61 address => {
62 description => 'IP address.',
63 type => 'string', format => 'ipv4',
64 optional => 1,
65 requires => 'netmask',
66 }
67};
68
69sub json_config_properties {
70 my $prop = shift;
71
72 foreach my $opt (keys %$confdesc) {
73 $prop->{$opt} = $confdesc->{$opt};
74 }
75
76 return $prop;
77}
78
79__PACKAGE__->register_method({
80 name => 'index',
81 path => '',
82 method => 'GET',
83 permissions => { user => 'all' },
84 description => "List available networks",
85 proxyto => 'node',
86 parameters => {
87 additionalProperties => 0,
88 properties => {
89 node => get_standard_option('pve-node'),
90 type => {
91 description => "Only list specific interface types.",
92 type => 'string',
93 enum => ['bond', 'bridge', 'alias', 'eth'],
94 optional => 1,
95 },
96 },
97 },
98 returns => {
99 type => "array",
100 items => {
101 type => "object",
102 properties => {},
103 },
104 links => [ { rel => 'child', href => "{iface}" } ],
105 },
106 code => sub {
107 my ($param) = @_;
108
e4d5bf72
DM
109 my $rpcenv = PVE::RPCEnvironment::get();
110
111 my $tmp = PVE::INotify::read_file('interfaces', 1);
112 my $config = $tmp->{data};
113 my $changes = $tmp->{changes};
114
115 $rpcenv->set_result_attrib('changes', $changes) if $changes;
aff192e6
DM
116
117 delete $config->{lo}; # do not list the loopback device
118
119 if ($param->{type}) {
120 foreach my $k (keys %$config) {
121 delete $config->{$k} if $param->{type} ne $config->{$k}->{type};
122 }
123 }
124
125 return PVE::RESTHandler::hash_to_array($config, 'iface');
126 }});
127
e4d5bf72
DM
128__PACKAGE__->register_method({
129 name => 'revert_network_changes',
130 path => '',
131 method => 'DELETE',
132 permissions => {
133 check => ['perm', '/nodes/{node}', [ 'Sys.Modify' ]],
134 },
135 protected => 1,
136 description => "Revert network configuration changes.",
137 proxyto => 'node',
138 parameters => {
139 additionalProperties => 0,
140 properties => {
141 node => get_standard_option('pve-node'),
142 },
143 },
144 returns => { type => "null" },
145 code => sub {
146 my ($param) = @_;
147
148 unlink "/etc/network/interfaces.new";
149
150 return undef;
151 }});
aff192e6
DM
152
153my $check_duplicate_gateway = sub {
154 my ($config, $newiface) = @_;
155
156 foreach my $iface (keys %$config) {
157 raise_param_exc({ gateway => "Default gateway already exists on interface '$iface'." })
158 if ($newiface ne $iface) && $config->{$iface}->{gateway};
159 }
160};
161
162
163__PACKAGE__->register_method({
164 name => 'create_network',
165 path => '',
166 method => 'POST',
167 permissions => {
7d020b42 168 check => ['perm', '/nodes/{node}', [ 'Sys.Modify' ]],
aff192e6
DM
169 },
170 description => "Create network device configuration",
171 protected => 1,
172 proxyto => 'node',
173 parameters => {
174 additionalProperties => 0,
175 properties => json_config_properties({
176 node => get_standard_option('pve-node'),
177 iface => get_standard_option('pve-iface')}),
178 },
179 returns => { type => 'null' },
180 code => sub {
181 my ($param) = @_;
182
183 my $node = extract_param($param, 'node');
184 my $iface = extract_param($param, 'iface');
185
186 my $code = sub {
187 my $config = PVE::INotify::read_file('interfaces');
188
189 raise_param_exc({ iface => "interface already exists" })
190 if $config->{$iface};
191
192 &$check_duplicate_gateway($config, $iface)
193 if $param->{gateway};
194
195 $param->{method} = $param->{address} ? 'static' : 'manual';
196
197 $config->{$iface} = $param;
198
199 PVE::INotify::write_file('interfaces', $config);
200 };
201
202 PVE::Tools::lock_file($iflockfn, 10, $code);
203 die $@ if $@;
204
205 return undef;
206 }});
207
208__PACKAGE__->register_method({
209 name => 'update_network',
210 path => '{iface}',
211 method => 'PUT',
212 permissions => {
7d020b42 213 check => ['perm', '/nodes/{node}', [ 'Sys.Modify' ]],
aff192e6
DM
214 },
215 description => "Update network device configuration",
216 protected => 1,
217 proxyto => 'node',
218 parameters => {
219 additionalProperties => 0,
220 properties => json_config_properties({
221 node => get_standard_option('pve-node'),
222 iface => get_standard_option('pve-iface'),
223 delete => {
224 type => 'string', format => 'pve-configid-list',
225 description => "A list of settings you want to delete.",
226 optional => 1,
227 }}),
228 },
229 returns => { type => 'null' },
230 code => sub {
231 my ($param) = @_;
232
233 my $node = extract_param($param, 'node');
234 my $iface = extract_param($param, 'iface');
235 my $delete = extract_param($param, 'delete');
236
237 my $code = sub {
238 my $config = PVE::INotify::read_file('interfaces');
239
240 raise_param_exc({ iface => "interface does not exist" })
241 if !$config->{$iface};
242
243 foreach my $k (PVE::Tools::split_list($delete)) {
244 delete $config->{$iface}->{$k};
245 }
246
247 &$check_duplicate_gateway($config, $iface)
248 if $param->{gateway};
249
250 $param->{method} = $param->{address} ? 'static' : 'manual';
251
252 foreach my $k (keys %$param) {
253 $config->{$iface}->{$k} = $param->{$k};
254 }
255
256 PVE::INotify::write_file('interfaces', $config);
257 };
258
259 PVE::Tools::lock_file($iflockfn, 10, $code);
260 die $@ if $@;
261
262 return undef;
263 }});
264
265__PACKAGE__->register_method({
266 name => 'network_config',
267 path => '{iface}',
268 method => 'GET',
269 permissions => {
7d020b42 270 check => ['perm', '/nodes/{node}', [ 'Sys.Audit' ]],
aff192e6
DM
271 },
272 description => "Read network device configuration",
273 proxyto => 'node',
274 parameters => {
275 additionalProperties => 0,
276 properties => {
277 node => get_standard_option('pve-node'),
278 iface => get_standard_option('pve-iface'),
279 },
280 },
281 returns => {
282 type => "object",
283 properties => {
284 type => {
285 type => 'string',
286 },
287 method => {
288 type => 'string',
289 },
290 },
291 },
292 code => sub {
293 my ($param) = @_;
294
295 my $config = PVE::INotify::read_file('interfaces');
296
297 raise_param_exc({ iface => "interface does not exist" })
298 if !$config->{$param->{iface}};
299
300 return $config->{$param->{iface}};
301 }});
302
303__PACKAGE__->register_method({
304 name => 'delete_network',
305 path => '{iface}',
306 method => 'DELETE',
307 permissions => {
7d020b42 308 check => ['perm', '/nodes/{node}', [ 'Sys.Modify' ]],
aff192e6
DM
309 },
310 description => "Delete network device configuration",
311 protected => 1,
312 proxyto => 'node',
313 parameters => {
314 additionalProperties => 0,
315 properties => {
316 node => get_standard_option('pve-node'),
317 iface => get_standard_option('pve-iface'),
318 },
319 },
320 returns => { type => 'null' },
321 code => sub {
322 my ($param) = @_;
323
324 my $code = sub {
325 my $config = PVE::INotify::read_file('interfaces');
326
327 raise_param_exc({ iface => "interface does not exist" })
328 if !$config->{$param->{iface}};
329
330 delete $config->{$param->{iface}};
331
332 PVE::INotify::write_file('interfaces', $config);
333 };
334
335 PVE::Tools::lock_file($iflockfn, 10, $code);
336 die $@ if $@;
337
338 return undef;
339 }});