]> git.proxmox.com Git - pve-container.git/blame - src/PVE/API2/LXC/Config.pm
add old config and unprivileged to check_ct_modify_config_perm
[pve-container.git] / src / PVE / API2 / LXC / Config.pm
CommitLineData
52389a07
DM
1package PVE::API2::LXC::Config;
2
3use strict;
4use warnings;
5
6use PVE::SafeSyslog;
7use PVE::Tools qw(extract_param run_command);
8use PVE::Exception qw(raise raise_param_exc);
9use PVE::INotify;
10use PVE::Cluster qw(cfs_read_file);
11use PVE::AccessControl;
12use PVE::Firewall;
13use PVE::Storage;
14use PVE::RESTHandler;
15use PVE::RPCEnvironment;
16use PVE::LXC;
7c92bb72 17use PVE::LXC::Config;
52389a07 18use PVE::LXC::Create;
52389a07 19use PVE::JSONSchema qw(get_standard_option);
1e17438e 20
52389a07
DM
21use base qw(PVE::RESTHandler);
22
52389a07
DM
23__PACKAGE__->register_method({
24 name => 'vm_config',
25 path => '',
26 method => 'GET',
27 proxyto => 'node',
28 description => "Get container configuration.",
29 permissions => {
30 check => ['perm', '/vms/{vmid}', [ 'VM.Audit' ]],
31 },
32 parameters => {
1e17438e 33 additionalProperties => 0,
52389a07
DM
34 properties => {
35 node => get_standard_option('pve-node'),
68e8f3c5 36 vmid => get_standard_option('pve-vmid', { completion => \&PVE::LXC::complete_ctid }),
52e8da5d
OB
37 current => {
38 description => "Get current values (instead of pending values).",
39 optional => 1,
40 default => 0,
41 type => 'boolean',
42 },
98f59049
TL
43 snapshot => get_standard_option('pve-snapshot-name', {
44 description => "Fetch config values from given snapshot.",
45 optional => 1,
46 completion => sub {
47 my ($cmd, $pname, $cur, $args) = @_;
48 PVE::LXC::Config->snapshot_list($args->[0]);
49 },
50 }),
52389a07
DM
51 },
52 },
53 returns => {
54 type => "object",
7c92bb72
DM
55 properties => PVE::LXC::Config->json_config_properties({
56 lxc => {
57 description => "Array of lxc low-level configurations ([[key1, value1], [key2, value2] ...]).",
58 type => 'array',
59 items => { type => 'array', items => { type => 'string' }},
60 optional => 1,
61 },
52389a07
DM
62 digest => {
63 type => 'string',
64 description => 'SHA1 digest of configuration file. This can be used to prevent concurrent modifications.',
65 }
7c92bb72 66 }),
52389a07
DM
67 },
68 code => sub {
69 my ($param) = @_;
70
52e8da5d
OB
71 raise_param_exc({ snapshot => "cannot use 'snapshot' parameter with 'current'",
72 current => "cannot use 'snapshot' parameter with 'current'"})
73 if ($param->{snapshot} && $param->{current});
52389a07 74
52e8da5d
OB
75 my $conf;
76 if ($param->{snapshot}) {
77 $conf = PVE::LXC::Config->load_snapshot_config($param->{vmid}, $param->{snapshot});
78 } else {
79 $conf = PVE::LXC::Config->load_current_config($param->{vmid}, $param->{current});
0a507a2d
RV
80 }
81
52389a07
DM
82 return $conf;
83 }});
84
85my $vm_config_perm_list = [
1e17438e
TL
86 'VM.Config.Disk',
87 'VM.Config.CPU',
88 'VM.Config.Memory',
89 'VM.Config.Network',
90 'VM.Config.Options',
91];
52389a07
DM
92
93__PACKAGE__->register_method({
94 name => 'update_vm',
95 path => '',
96 method => 'PUT',
97 protected => 1,
98 proxyto => 'node',
99 description => "Set container options.",
100 permissions => {
101 check => ['perm', '/vms/{vmid}', $vm_config_perm_list, any => 1],
9d294016 102 description => 'non-volume mount points in rootfs and mp[n] are restricted to root@pam',
52389a07
DM
103 },
104 parameters => {
1e17438e 105 additionalProperties => 0,
1b4cf758 106 properties => PVE::LXC::Config->json_config_properties(
52389a07
DM
107 {
108 node => get_standard_option('pve-node'),
68e8f3c5 109 vmid => get_standard_option('pve-vmid', { completion => \&PVE::LXC::complete_ctid }),
52389a07
DM
110 delete => {
111 type => 'string', format => 'pve-configid-list',
112 description => "A list of settings you want to delete.",
113 optional => 1,
114 },
6517e001
OB
115 revert => {
116 type => 'string', format => 'pve-configid-list',
117 description => "Revert a pending change.",
118 optional => 1,
119 },
52389a07
DM
120 digest => {
121 type => 'string',
122 description => 'Prevent changes if current configuration file has different SHA1 digest. This can be used to prevent concurrent modifications.',
123 maxLength => 40,
124 optional => 1,
125 }
126 }),
127 },
128 returns => { type => 'null'},
129 code => sub {
130 my ($param) = @_;
131
132 my $rpcenv = PVE::RPCEnvironment::get();
52389a07
DM
133 my $authuser = $rpcenv->get_user();
134
135 my $node = extract_param($param, 'node');
52389a07
DM
136 my $vmid = extract_param($param, 'vmid');
137
138 my $digest = extract_param($param, 'digest');
139
140 die "no options specified\n" if !scalar(keys %$param);
141
142 my $delete_str = extract_param($param, 'delete');
143 my @delete = PVE::Tools::split_list($delete_str);
6517e001
OB
144 my $revert_str = extract_param($param, 'revert');
145 my @revert = PVE::Tools::split_list($revert_str);
52389a07 146
de41bced 147 my $code = sub {
6517e001 148
de41bced
DC
149 my $conf = PVE::LXC::Config->load_config($vmid);
150 PVE::LXC::Config->check_lock($conf);
6517e001 151
de41bced 152 PVE::Tools::assert_if_modified($digest, $conf->{digest});
52389a07 153
de41bced
DC
154 my $unprivileged = $conf->{unprivileged};
155 PVE::LXC::check_ct_modify_config_perm($rpcenv, $authuser, $vmid, undef, $conf, {}, [@delete], $unprivileged);
156 PVE::LXC::check_ct_modify_config_perm($rpcenv, $authuser, $vmid, undef, $conf, {}, [@revert], $unprivileged);
6517e001 157
de41bced
DC
158 foreach my $opt (@revert) {
159 raise_param_exc({ revert => "unknown option '$opt'" })
160 if !PVE::LXC::Config->option_exists($opt);
52389a07 161
de41bced
DC
162 raise_param_exc({ revert => "you can't use '-$opt' and '-revert $opt' at the same time" })
163 if defined($param->{$opt});
164 }
52389a07 165
de41bced
DC
166 foreach my $opt (@delete) {
167 raise_param_exc({ delete => "unknown option '$opt'" })
168 if !PVE::LXC::Config->option_exists($opt);
2aee38e5 169
de41bced
DC
170 raise_param_exc({ delete => "you can't use '-$opt' and -delete $opt' at the same time" })
171 if defined($param->{$opt});
52389a07 172
de41bced
DC
173 raise_param_exc({ delete => "you can't use '-delete $opt' and '-revert $opt' at the same time" })
174 if grep(/^$opt$/, @revert);
175 }
52389a07 176
de41bced
DC
177 PVE::LXC::check_ct_modify_config_perm($rpcenv, $authuser, $vmid, undef, $conf, $param, [], $unprivileged);
178
179 my $storage_cfg = PVE::Storage::config();
180
181 my $repl_conf = PVE::ReplicationConfig->new();
182 my $is_replicated = $repl_conf->check_for_existing_jobs($vmid, 1);
183 if ($is_replicated) {
184 PVE::LXC::Config->foreach_volume($param, sub {
185 my ($opt, $mountpoint) = @_;
186 my $volid = $mountpoint->{volume};
187 return if !$volid || !($mountpoint->{replicate}//1);
188 if ($mountpoint->{type} eq 'volume') {
189 my ($storeid, $format);
190 if ($volid =~ $PVE::LXC::NEW_DISK_RE) {
191 $storeid = $1;
192 $format = $mountpoint->{format} || PVE::Storage::storage_default_format($storage_cfg, $storeid);
193 } else {
194 ($storeid, undef) = PVE::Storage::parse_volume_id($volid, 1);
195 $format = (PVE::Storage::parse_volname($storage_cfg, $volid))[6];
196 }
197 return if PVE::Storage::storage_can_replicate($storage_cfg, $storeid, $format);
198 my $scfg = PVE::Storage::storage_config($storage_cfg, $storeid);
199 return if $scfg->{shared};
200 }
201 die "cannot add non-replicatable volume to a replicated VM\n";
202 });
203 }
52389a07
DM
204
205 my $running = PVE::LXC::check_running($vmid);
206
6517e001 207 my $errors = PVE::LXC::Config->update_pct_config($vmid, $conf, $running, $param, \@delete, \@revert);
87c36547 208 PVE::LXC::Config->write_config($vmid, $conf);
6517e001 209 $conf = PVE::LXC::Config->load_config($vmid);
52389a07 210
f91f3669 211 PVE::LXC::update_lxc_config($vmid, $conf);
6517e001 212 raise_param_exc($errors) if scalar(keys %$errors);
52389a07
DM
213 };
214
67afe46e 215 PVE::LXC::Config->lock_config($vmid, $code);
52389a07
DM
216
217 return undef;
218 }});
219
2201;