]>
git.proxmox.com Git - pve-container.git/blob - src/PVE/API2/LXC.pm
1 package PVE
::API2
::LXC
;
7 use PVE
::Tools
qw(extract_param run_command);
8 use PVE
::Exception
qw(raise raise_param_exc);
10 use PVE
::AccessControl
;
13 use PVE
::RPCEnvironment
;
15 use PVE
::JSONSchema
qw(get_standard_option);
16 use base
qw(PVE::RESTHandler);
18 use Data
::Dumper
; # fixme: remove
20 my $get_container_storage = sub {
21 my ($stcfg, $vmid, $lxc_conf) = @_;
23 my $path = $lxc_conf->{'lxc.rootfs'};
24 my ($vtype, $volid) = PVE
::Storage
::path_to_volume_id
($stcfg, $path);
25 my ($sid, $volname) = PVE
::Storage
::parse_volume_id
($volid, 1) if $volid;
26 return wantarray ?
($sid, $volname, $path) : $sid;
29 my $check_ct_modify_config_perm = sub {
30 my ($rpcenv, $authuser, $vmid, $pool, $key_list) = @_;
32 return 1 if $authuser ne 'root@pam';
34 foreach my $opt (@$key_list) {
36 if ($opt eq 'cpus' || $opt eq 'cpuunits' || $opt eq 'cpulimit') {
37 $rpcenv->check_vm_perm($authuser, $vmid, $pool, ['VM.Config.CPU']);
38 } elsif ($opt eq 'disk') {
39 $rpcenv->check_vm_perm($authuser, $vmid, $pool, ['VM.Config.Disk']);
40 } elsif ($opt eq 'memory' || $opt eq 'swap') {
41 $rpcenv->check_vm_perm($authuser, $vmid, $pool, ['VM.Config.Memory']);
42 } elsif ($opt =~ m/^net\d+$/ || $opt eq 'nameserver' ||
43 $opt eq 'searchdomain' || $opt eq 'hostname') {
44 $rpcenv->check_vm_perm($authuser, $vmid, $pool, ['VM.Config.Network']);
46 $rpcenv->check_vm_perm($authuser, $vmid, $pool, ['VM.Config.Options']);
54 __PACKAGE__-
>register_method({
58 description
=> "LXC container index (per node).",
60 description
=> "Only list CTs where you have VM.Audit permissons on /vms/<vmid>.",
64 protected
=> 1, # /proc files are only readable by root
66 additionalProperties
=> 0,
68 node
=> get_standard_option
('pve-node'),
77 links
=> [ { rel
=> 'child', href
=> "{vmid}" } ],
82 my $rpcenv = PVE
::RPCEnvironment
::get
();
83 my $authuser = $rpcenv->get_user();
85 my $vmstatus = PVE
::LXC
::vmstatus
();
88 foreach my $vmid (keys %$vmstatus) {
89 next if !$rpcenv->check($authuser, "/vms/$vmid", [ 'VM.Audit' ], 1);
91 my $data = $vmstatus->{$vmid};
92 $data->{vmid
} = $vmid;
100 my $vm_config_perm_list = [
108 __PACKAGE__-
>register_method({
110 path
=> '{vmid}/config',
114 description
=> "Set container options.",
116 check
=> ['perm', '/vms/{vmid}', $vm_config_perm_list, any
=> 1],
119 additionalProperties
=> 0,
120 properties
=> PVE
::LXC
::json_config_properties
(
122 node
=> get_standard_option
('pve-node'),
123 vmid
=> get_standard_option
('pve-vmid'),
126 description
=> 'Prevent changes if current configuration file has different SHA1 digest. This can be used to prevent concurrent modifications.',
132 returns
=> { type
=> 'null'},
136 my $rpcenv = PVE
::RPCEnvironment
::get
();
138 my $authuser = $rpcenv->get_user();
140 my $node = extract_param
($param, 'node');
142 my $vmid = extract_param
($param, 'vmid');
144 my $digest = extract_param
($param, 'digest');
146 die "no options specified\n" if !scalar(keys %$param);
148 &$check_ct_modify_config_perm($rpcenv, $authuser, $vmid, undef, [keys %$param]);
152 my $conf = PVE
::LXC
::load_config
($vmid);
154 PVE
::Tools
::assert_if_modified
($digest, $conf->{digest
});
159 PVE
::LXC
::lock_container
($vmid, undef, $code);
164 __PACKAGE__-
>register_method ({
165 subclass
=> "PVE::API2::Firewall::CT",
166 path
=> '{vmid}/firewall',
169 __PACKAGE__-
>register_method({
174 description
=> "Directory index",
179 additionalProperties
=> 0,
181 node
=> get_standard_option
('pve-node'),
182 vmid
=> get_standard_option
('pve-vmid'),
190 subdir
=> { type
=> 'string' },
193 links
=> [ { rel
=> 'child', href
=> "{subdir}" } ],
199 my $conf = PVE
::OpenVZ
::load_config
($param->{vmid
});
202 { subdir
=> 'config' },
203 # { subdir => 'status' },
204 # { subdir => 'vncproxy' },
205 # { subdir => 'spiceproxy' },
206 # { subdir => 'migrate' },
207 # { subdir => 'initlog' },
209 { subdir
=> 'rrddata' },
210 { subdir
=> 'firewall' },
216 __PACKAGE__-
>register_method({
218 path
=> '{vmid}/rrd',
220 protected
=> 1, # fixme: can we avoid that?
222 check
=> ['perm', '/vms/{vmid}', [ 'VM.Audit' ]],
224 description
=> "Read VM RRD statistics (returns PNG)",
226 additionalProperties
=> 0,
228 node
=> get_standard_option
('pve-node'),
229 vmid
=> get_standard_option
('pve-vmid'),
231 description
=> "Specify the time frame you are interested in.",
233 enum
=> [ 'hour', 'day', 'week', 'month', 'year' ],
236 description
=> "The list of datasources you want to display.",
237 type
=> 'string', format
=> 'pve-configid-list',
240 description
=> "The RRD consolidation function",
242 enum
=> [ 'AVERAGE', 'MAX' ],
250 filename
=> { type
=> 'string' },
256 return PVE
::Cluster
::create_rrd_graph
(
257 "pve2-vm/$param->{vmid}", $param->{timeframe
},
258 $param->{ds
}, $param->{cf
});
262 __PACKAGE__-
>register_method({
264 path
=> '{vmid}/rrddata',
266 protected
=> 1, # fixme: can we avoid that?
268 check
=> ['perm', '/vms/{vmid}', [ 'VM.Audit' ]],
270 description
=> "Read VM RRD statistics",
272 additionalProperties
=> 0,
274 node
=> get_standard_option
('pve-node'),
275 vmid
=> get_standard_option
('pve-vmid'),
277 description
=> "Specify the time frame you are interested in.",
279 enum
=> [ 'hour', 'day', 'week', 'month', 'year' ],
282 description
=> "The RRD consolidation function",
284 enum
=> [ 'AVERAGE', 'MAX' ],
299 return PVE
::Cluster
::create_rrd_data
(
300 "pve2-vm/$param->{vmid}", $param->{timeframe
}, $param->{cf
});
304 __PACKAGE__-
>register_method({
306 path
=> '{vmid}/config',
309 description
=> "Get container configuration.",
311 check
=> ['perm', '/vms/{vmid}', [ 'VM.Audit' ]],
314 additionalProperties
=> 0,
316 node
=> get_standard_option
('pve-node'),
317 vmid
=> get_standard_option
('pve-vmid'),
325 description
=> 'SHA1 digest of configuration file. This can be used to prevent concurrent modifications.',
332 my $lxc_conf = PVE
::LXC
::load_config
($param->{vmid
});
334 # NOTE: we only return selected/converted values
336 my $conf = { digest
=> $lxc_conf->{digest
} };
338 my $stcfg = PVE
::Cluster
::cfs_read_file
("storage.cfg");
340 my ($sid, undef, $path) = &$get_container_storage($stcfg, $param->{vmid
}, $lxc_conf);
341 $conf->{storage
} = $sid || $path;
343 my $properties = PVE
::LXC
::json_config_properties
();
345 foreach my $k (keys %$properties) {
347 if ($k eq 'description') {
348 if (my $raw = $lxc_conf->{'pve.comment'}) {
349 $conf->{$k} = PVE
::Tools
::decode_text
($raw);
351 } elsif ($k eq 'hostname') {
352 $conf->{$k} = $lxc_conf->{'lxc.utsname'} if $lxc_conf->{'lxc.utsname'};
353 } elsif ($k =~ m/^net\d$/) {
354 my $net = $lxc_conf->{$k};
356 $conf->{$k} = PVE
::LXC
::print_netif
($net);
363 __PACKAGE__-
>register_method({
364 name
=> 'destroy_vm',
369 description
=> "Destroy the container (also delete all uses files).",
371 check
=> [ 'perm', '/vms/{vmid}', ['VM.Allocate']],
374 additionalProperties
=> 0,
376 node
=> get_standard_option
('pve-node'),
377 vmid
=> get_standard_option
('pve-vmid'),
386 my $rpcenv = PVE
::RPCEnvironment
::get
();
388 my $authuser = $rpcenv->get_user();
390 my $vmid = $param->{vmid
};
392 # test if container exists
393 my $conf = PVE
::LXC
::load_config
($param->{vmid
});
396 my $cmd = ['lxc-destroy', '-n', $vmid ];
400 PVE
::AccessControl
::remove_vm_from_pool
($vmid);
403 return $rpcenv->fork_worker('vzdestroy', $vmid, $authuser, $realcmd);