]> git.proxmox.com Git - pve-manager.git/blame - lib/PVE/API2/Network.pm
imported from svn 'pve-manager/pve2'
[pve-manager.git] / lib / 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
109 my $config = PVE::INotify::read_file('interfaces');
110
111 delete $config->{lo}; # do not list the loopback device
112
113 if ($param->{type}) {
114 foreach my $k (keys %$config) {
115 delete $config->{$k} if $param->{type} ne $config->{$k}->{type};
116 }
117 }
118
119 return PVE::RESTHandler::hash_to_array($config, 'iface');
120 }});
121
122
123my $check_duplicate_gateway = sub {
124 my ($config, $newiface) = @_;
125
126 foreach my $iface (keys %$config) {
127 raise_param_exc({ gateway => "Default gateway already exists on interface '$iface'." })
128 if ($newiface ne $iface) && $config->{$iface}->{gateway};
129 }
130};
131
132
133__PACKAGE__->register_method({
134 name => 'create_network',
135 path => '',
136 method => 'POST',
137 permissions => {
138 path => '/nodes/{node}',
139 privs => [ 'Sys.Modify' ],
140 },
141 description => "Create network device configuration",
142 protected => 1,
143 proxyto => 'node',
144 parameters => {
145 additionalProperties => 0,
146 properties => json_config_properties({
147 node => get_standard_option('pve-node'),
148 iface => get_standard_option('pve-iface')}),
149 },
150 returns => { type => 'null' },
151 code => sub {
152 my ($param) = @_;
153
154 my $node = extract_param($param, 'node');
155 my $iface = extract_param($param, 'iface');
156
157 my $code = sub {
158 my $config = PVE::INotify::read_file('interfaces');
159
160 raise_param_exc({ iface => "interface already exists" })
161 if $config->{$iface};
162
163 &$check_duplicate_gateway($config, $iface)
164 if $param->{gateway};
165
166 $param->{method} = $param->{address} ? 'static' : 'manual';
167
168 $config->{$iface} = $param;
169
170 PVE::INotify::write_file('interfaces', $config);
171 };
172
173 PVE::Tools::lock_file($iflockfn, 10, $code);
174 die $@ if $@;
175
176 return undef;
177 }});
178
179__PACKAGE__->register_method({
180 name => 'update_network',
181 path => '{iface}',
182 method => 'PUT',
183 permissions => {
184 path => '/nodes/{node}',
185 privs => [ 'Sys.Modify' ],
186 },
187 description => "Update network device configuration",
188 protected => 1,
189 proxyto => 'node',
190 parameters => {
191 additionalProperties => 0,
192 properties => json_config_properties({
193 node => get_standard_option('pve-node'),
194 iface => get_standard_option('pve-iface'),
195 delete => {
196 type => 'string', format => 'pve-configid-list',
197 description => "A list of settings you want to delete.",
198 optional => 1,
199 }}),
200 },
201 returns => { type => 'null' },
202 code => sub {
203 my ($param) = @_;
204
205 my $node = extract_param($param, 'node');
206 my $iface = extract_param($param, 'iface');
207 my $delete = extract_param($param, 'delete');
208
209 my $code = sub {
210 my $config = PVE::INotify::read_file('interfaces');
211
212 raise_param_exc({ iface => "interface does not exist" })
213 if !$config->{$iface};
214
215 foreach my $k (PVE::Tools::split_list($delete)) {
216 delete $config->{$iface}->{$k};
217 }
218
219 &$check_duplicate_gateway($config, $iface)
220 if $param->{gateway};
221
222 $param->{method} = $param->{address} ? 'static' : 'manual';
223
224 foreach my $k (keys %$param) {
225 $config->{$iface}->{$k} = $param->{$k};
226 }
227
228 PVE::INotify::write_file('interfaces', $config);
229 };
230
231 PVE::Tools::lock_file($iflockfn, 10, $code);
232 die $@ if $@;
233
234 return undef;
235 }});
236
237__PACKAGE__->register_method({
238 name => 'network_config',
239 path => '{iface}',
240 method => 'GET',
241 permissions => {
242 path => '/nodes/{node}',
243 privs => [ 'Sys.Audit' ],
244 },
245 description => "Read network device configuration",
246 proxyto => 'node',
247 parameters => {
248 additionalProperties => 0,
249 properties => {
250 node => get_standard_option('pve-node'),
251 iface => get_standard_option('pve-iface'),
252 },
253 },
254 returns => {
255 type => "object",
256 properties => {
257 type => {
258 type => 'string',
259 },
260 method => {
261 type => 'string',
262 },
263 },
264 },
265 code => sub {
266 my ($param) = @_;
267
268 my $config = PVE::INotify::read_file('interfaces');
269
270 raise_param_exc({ iface => "interface does not exist" })
271 if !$config->{$param->{iface}};
272
273 return $config->{$param->{iface}};
274 }});
275
276__PACKAGE__->register_method({
277 name => 'delete_network',
278 path => '{iface}',
279 method => 'DELETE',
280 permissions => {
281 path => '/nodes/{node}',
282 privs => [ 'Sys.Modify' ],
283 },
284 description => "Delete network device configuration",
285 protected => 1,
286 proxyto => 'node',
287 parameters => {
288 additionalProperties => 0,
289 properties => {
290 node => get_standard_option('pve-node'),
291 iface => get_standard_option('pve-iface'),
292 },
293 },
294 returns => { type => 'null' },
295 code => sub {
296 my ($param) = @_;
297
298 my $code = sub {
299 my $config = PVE::INotify::read_file('interfaces');
300
301 raise_param_exc({ iface => "interface does not exist" })
302 if !$config->{$param->{iface}};
303
304 delete $config->{$param->{iface}};
305
306 PVE::INotify::write_file('interfaces', $config);
307 };
308
309 PVE::Tools::lock_file($iflockfn, 10, $code);
310 die $@ if $@;
311
312 return undef;
313 }});
314
315
316