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
;
15 use PVE
::RPCEnvironment
;
19 use PVE
::JSONSchema
qw(get_standard_option);
21 use base
qw(PVE::RESTHandler);
23 __PACKAGE__-
>register_method({
28 description
=> "Get container configuration.",
30 check
=> ['perm', '/vms/{vmid}', [ 'VM.Audit' ]],
33 additionalProperties
=> 0,
35 node
=> get_standard_option
('pve-node'),
36 vmid
=> get_standard_option
('pve-vmid', { completion
=> \
&PVE
::LXC
::complete_ctid
}),
38 description
=> "Get current values (instead of pending values).",
43 snapshot
=> get_standard_option
('pve-snapshot-name', {
44 description
=> "Fetch config values from given snapshot.",
47 my ($cmd, $pname, $cur, $args) = @_;
48 PVE
::LXC
::Config-
>snapshot_list($args->[0]);
55 properties
=> PVE
::LXC
::Config-
>json_config_properties({
57 description
=> "Array of lxc low-level configurations ([[key1, value1], [key2, value2] ...]).",
59 items
=> { type
=> 'array', items
=> { type
=> 'string' }},
64 description
=> 'SHA1 digest of configuration file. This can be used to prevent concurrent modifications.',
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
});
76 if ($param->{snapshot
}) {
77 $conf = PVE
::LXC
::Config-
>load_snapshot_config($param->{vmid
}, $param->{snapshot
});
79 $conf = PVE
::LXC
::Config-
>load_current_config($param->{vmid
}, $param->{current
});
85 my $vm_config_perm_list = [
93 __PACKAGE__-
>register_method({
99 description
=> "Set container options.",
101 check
=> ['perm', '/vms/{vmid}', $vm_config_perm_list, any
=> 1],
102 description
=> 'non-volume mount points in rootfs and mp[n] are restricted to root@pam',
105 additionalProperties
=> 0,
106 properties
=> PVE
::LXC
::Config-
>json_config_properties(
108 node
=> get_standard_option
('pve-node'),
109 vmid
=> get_standard_option
('pve-vmid', { completion
=> \
&PVE
::LXC
::complete_ctid
}),
111 type
=> 'string', format
=> 'pve-configid-list',
112 description
=> "A list of settings you want to delete.",
116 type
=> 'string', format
=> 'pve-configid-list',
117 description
=> "Revert a pending change.",
122 description
=> 'Prevent changes if current configuration file has different SHA1 digest. This can be used to prevent concurrent modifications.',
128 returns
=> { type
=> 'null'},
132 my $rpcenv = PVE
::RPCEnvironment
::get
();
133 my $authuser = $rpcenv->get_user();
135 my $node = extract_param
($param, 'node');
136 my $vmid = extract_param
($param, 'vmid');
138 my $digest = extract_param
($param, 'digest');
140 die "no options specified\n" if !scalar(keys %$param);
142 my $delete_str = extract_param
($param, 'delete');
143 my @delete = PVE
::Tools
::split_list
($delete_str);
144 my $revert_str = extract_param
($param, 'revert');
145 my @revert = PVE
::Tools
::split_list
($revert_str);
147 PVE
::LXC
::check_ct_modify_config_perm
($rpcenv, $authuser, $vmid, undef, {}, [@delete]);
148 PVE
::LXC
::check_ct_modify_config_perm
($rpcenv, $authuser, $vmid, undef, {}, [@revert]);
150 foreach my $opt (@revert) {
151 raise_param_exc
({ revert
=> "unknown option '$opt'" })
152 if !PVE
::LXC
::Config-
>option_exists($opt);
154 raise_param_exc
({ revert
=> "you can't use '-$opt' and '-revert $opt' at the same time" })
155 if defined($param->{$opt});
158 foreach my $opt (@delete) {
159 raise_param_exc
({ delete => "unknown option '$opt'" })
160 if !PVE
::LXC
::Config-
>option_exists($opt);
162 raise_param_exc
({ delete => "you can't use '-$opt' and -delete $opt' at the same time" })
163 if defined($param->{$opt});
165 raise_param_exc
({ delete => "you can't use '-delete $opt' and '-revert $opt' at the same time" })
166 if grep(/^$opt$/, @revert);
169 PVE
::LXC
::check_ct_modify_config_perm
($rpcenv, $authuser, $vmid, undef, $param, []);
171 my $storage_cfg = PVE
::Storage
::config
();
173 my $repl_conf = PVE
::ReplicationConfig-
>new();
174 my $is_replicated = $repl_conf->check_for_existing_jobs($vmid, 1);
175 if ($is_replicated) {
176 PVE
::LXC
::Config-
>foreach_volume($param, sub {
177 my ($opt, $mountpoint) = @_;
178 my $volid = $mountpoint->{volume
};
179 return if !$volid || !($mountpoint->{replicate
}//1);
180 if ($mountpoint->{type
} eq 'volume') {
181 my ($storeid, $format);
182 if ($volid =~ $PVE::LXC
::NEW_DISK_RE
) {
184 $format = $mountpoint->{format
} || PVE
::Storage
::storage_default_format
($storage_cfg, $storeid);
186 ($storeid, undef) = PVE
::Storage
::parse_volume_id
($volid, 1);
187 $format = (PVE
::Storage
::parse_volname
($storage_cfg, $volid))[6];
189 return if PVE
::Storage
::storage_can_replicate
($storage_cfg, $storeid, $format);
190 my $scfg = PVE
::Storage
::storage_config
($storage_cfg, $storeid);
191 return if $scfg->{shared
};
193 die "cannot add non-replicatable volume to a replicated VM\n";
199 my $conf = PVE
::LXC
::Config-
>load_config($vmid);
200 PVE
::LXC
::Config-
>check_lock($conf);
202 PVE
::Tools
::assert_if_modified
($digest, $conf->{digest
});
204 my $running = PVE
::LXC
::check_running
($vmid);
206 my $errors = PVE
::LXC
::Config-
>update_pct_config($vmid, $conf, $running, $param, \
@delete, \
@revert);
207 $conf = PVE
::LXC
::Config-
>load_config($vmid);
209 PVE
::LXC
::update_lxc_config
($vmid, $conf);
210 raise_param_exc
($errors) if scalar(keys %$errors);
213 PVE
::LXC
::Config-
>lock_config($vmid, $code);