1 package PVE
::API2
::LXC
::Config
;
7 use PVE
::Tools
qw(extract_param run_command);
8 use PVE
::Exception
qw(raise raise_param_exc);
10 use PVE
::Cluster
qw(cfs_read_file);
11 use PVE
::AccessControl
;
13 use PVE
::GuestHelpers
;
16 use PVE
::RPCEnvironment
;
20 use PVE
::JSONSchema
qw(get_standard_option);
22 use base
qw(PVE::RESTHandler);
24 __PACKAGE__-
>register_method({
29 description
=> "Get container configuration.",
31 check
=> ['perm', '/vms/{vmid}', [ 'VM.Audit' ]],
34 additionalProperties
=> 0,
36 node
=> get_standard_option
('pve-node'),
37 vmid
=> get_standard_option
('pve-vmid', { completion
=> \
&PVE
::LXC
::complete_ctid
}),
39 description
=> "Get current values (instead of pending values).",
44 snapshot
=> get_standard_option
('pve-snapshot-name', {
45 description
=> "Fetch config values from given snapshot.",
48 my ($cmd, $pname, $cur, $args) = @_;
49 PVE
::LXC
::Config-
>snapshot_list($args->[0]);
56 properties
=> PVE
::LXC
::Config-
>json_config_properties({
58 description
=> "Array of lxc low-level configurations ([[key1, value1], [key2, value2] ...]).",
60 items
=> { type
=> 'array', items
=> { type
=> 'string' }},
65 description
=> 'SHA1 digest of configuration file. This can be used to prevent concurrent modifications.',
72 raise_param_exc
({ snapshot
=> "cannot use 'snapshot' parameter with 'current'",
73 current
=> "cannot use 'snapshot' parameter with 'current'"})
74 if ($param->{snapshot
} && $param->{current
});
77 if ($param->{snapshot
}) {
78 $conf = PVE
::LXC
::Config-
>load_snapshot_config($param->{vmid
}, $param->{snapshot
});
80 $conf = PVE
::LXC
::Config-
>load_current_config($param->{vmid
}, $param->{current
});
86 my $vm_config_perm_list = [
94 __PACKAGE__-
>register_method({
100 description
=> "Set container options.",
102 check
=> ['perm', '/vms/{vmid}', $vm_config_perm_list, any
=> 1],
103 description
=> 'non-volume mount points in rootfs and mp[n] are restricted to root@pam',
106 additionalProperties
=> 0,
107 properties
=> PVE
::LXC
::Config-
>json_config_properties(
109 node
=> get_standard_option
('pve-node'),
110 vmid
=> get_standard_option
('pve-vmid', { completion
=> \
&PVE
::LXC
::complete_ctid
}),
112 type
=> 'string', format
=> 'pve-configid-list',
113 description
=> "A list of settings you want to delete.",
117 type
=> 'string', format
=> 'pve-configid-list',
118 description
=> "Revert a pending change.",
123 description
=> 'Prevent changes if current configuration file has different SHA1 digest. This can be used to prevent concurrent modifications.',
129 returns
=> { type
=> 'null'},
133 my $rpcenv = PVE
::RPCEnvironment
::get
();
134 my $authuser = $rpcenv->get_user();
136 my $node = extract_param
($param, 'node');
137 my $vmid = extract_param
($param, 'vmid');
139 my $digest = extract_param
($param, 'digest');
141 die "no options specified\n" if !scalar(keys %$param);
143 my $delete_str = extract_param
($param, 'delete');
144 my @delete = PVE
::Tools
::split_list
($delete_str);
145 my $revert_str = extract_param
($param, 'revert');
146 my @revert = PVE
::Tools
::split_list
($revert_str);
148 $param->{cpuunits
} = PVE
::CGroup
::clamp_cpu_shares
($param->{cpuunits
})
149 if defined($param->{cpuunits
}); # clamp value depending on cgroup version
153 my $conf = PVE
::LXC
::Config-
>load_config($vmid);
154 PVE
::LXC
::Config-
>check_lock($conf);
156 PVE
::Tools
::assert_if_modified
($digest, $conf->{digest
});
158 my $unprivileged = $conf->{unprivileged
};
159 PVE
::LXC
::check_ct_modify_config_perm
($rpcenv, $authuser, $vmid, undef, $conf, {}, [@delete], $unprivileged);
160 PVE
::LXC
::check_ct_modify_config_perm
($rpcenv, $authuser, $vmid, undef, $conf, {}, [@revert], $unprivileged);
162 foreach my $opt (@revert) {
163 raise_param_exc
({ revert
=> "unknown option '$opt'" })
164 if !PVE
::LXC
::Config-
>option_exists($opt);
166 raise_param_exc
({ revert
=> "you can't use '-$opt' and '-revert $opt' at the same time" })
167 if defined($param->{$opt});
170 foreach my $opt (@delete) {
171 raise_param_exc
({ delete => "unknown option '$opt'" })
172 if !PVE
::LXC
::Config-
>option_exists($opt);
174 raise_param_exc
({ delete => "you can't use '-$opt' and -delete $opt' at the same time" })
175 if defined($param->{$opt});
177 raise_param_exc
({ delete => "you can't use '-delete $opt' and '-revert $opt' at the same time" })
178 if grep(/^$opt$/, @revert);
181 PVE
::LXC
::check_ct_modify_config_perm
($rpcenv, $authuser, $vmid, undef, $conf, $param, [], $unprivileged);
183 my $storage_cfg = PVE
::Storage
::config
();
185 my $repl_conf = PVE
::ReplicationConfig-
>new();
186 my $is_replicated = $repl_conf->check_for_existing_jobs($vmid, 1);
187 if ($is_replicated) {
188 PVE
::LXC
::Config-
>foreach_volume($param, sub {
189 my ($opt, $mountpoint) = @_;
190 my $volid = $mountpoint->{volume
};
191 return if !$volid || !($mountpoint->{replicate
}//1);
192 if ($mountpoint->{type
} eq 'volume') {
193 my ($storeid, $format);
194 if ($volid =~ $PVE::LXC
::NEW_DISK_RE
) {
196 $format = $mountpoint->{format
} || PVE
::Storage
::storage_default_format
($storage_cfg, $storeid);
198 ($storeid, undef) = PVE
::Storage
::parse_volume_id
($volid, 1);
199 $format = (PVE
::Storage
::parse_volname
($storage_cfg, $volid))[6];
201 return if PVE
::Storage
::storage_can_replicate
($storage_cfg, $storeid, $format);
202 my $scfg = PVE
::Storage
::storage_config
($storage_cfg, $storeid);
203 return if $scfg->{shared
};
205 die "cannot add non-replicatable volume to a replicated VM\n";
209 my $running = PVE
::LXC
::check_running
($vmid);
211 my $errors = PVE
::LXC
::Config-
>update_pct_config($vmid, $conf, $running, $param, \
@delete, \
@revert);
212 PVE
::LXC
::Config-
>write_config($vmid, $conf);
213 $conf = PVE
::LXC
::Config-
>load_config($vmid);
215 PVE
::LXC
::update_lxc_config
($vmid, $conf);
216 raise_param_exc
($errors) if scalar(keys %$errors);
219 PVE
::LXC
::Config-
>lock_config($vmid, $code);