]> git.proxmox.com Git - pve-container.git/blame - src/PVE/LXC/Config.pm
Refactor mountpoint and general conf methods
[pve-container.git] / src / PVE / LXC / Config.pm
CommitLineData
67afe46e
FG
1package PVE::LXC::Config;
2
3use strict;
4use warnings;
5
6use PVE::AbstractConfig;
7use PVE::Cluster qw(cfs_register_file);
8use PVE::INotify;
9use PVE::JSONSchema qw(get_standard_option);
10use PVE::Tools;
11
12use base qw(PVE::AbstractConfig);
13
14my $nodename = PVE::INotify::nodename();
15my $lock_handles = {};
16my $lockdir = "/run/lock/lxc";
17mkdir $lockdir;
18mkdir "/etc/pve/nodes/$nodename/lxc";
19my $MAX_MOUNT_POINTS = 10;
20my $MAX_UNUSED_DISKS = $MAX_MOUNT_POINTS;
21
22# BEGIN implemented abstract methods from PVE::AbstractConfig
23
24sub guest_type {
25 return "CT";
26}
27
4518000b
FG
28sub __config_max_unused_disks {
29 my ($class) = @_;
30
31 return $MAX_UNUSED_DISKS;
32}
33
67afe46e
FG
34sub config_file_lock {
35 my ($class, $vmid) = @_;
36
37 return "$lockdir/pve-config-${vmid}.lock";
38}
39
40sub cfs_config_path {
41 my ($class, $vmid, $node) = @_;
42
43 $node = $nodename if !$node;
44 return "nodes/$node/lxc/$vmid.conf";
45}
46
4518000b
FG
47sub has_feature {
48 my ($class, $feature, $conf, $storecfg, $snapname, $running, $backup_only) = @_;
49 my $err;
50
d250604f 51 $class->foreach_mountpoint($conf, sub {
4518000b
FG
52 my ($ms, $mountpoint) = @_;
53
54 return if $err; # skip further test
55 return if $backup_only && $ms ne 'rootfs' && !$mountpoint->{backup};
56
57 $err = 1
58 if !PVE::Storage::volume_has_feature($storecfg, $feature,
59 $mountpoint->{volume},
60 $snapname, $running);
61 });
62
63 return $err ? 0 : 1;
64}
65
66sub __snapshot_save_vmstate {
67 my ($class, $vmid, $conf, $snapname, $storecfg) = @_;
68 die "implement me - snapshot_save_vmstate\n";
69}
70
71sub __snapshot_check_running {
72 my ($class, $vmid) = @_;
73 return PVE::LXC::check_running($vmid);
74}
75
76sub __snapshot_check_freeze_needed {
77 my ($class, $vmid, $config, $save_vmstate) = @_;
78
79 my $ret = $class->__snapshot_check_running($vmid);
80 return ($ret, $ret);
81}
82
83sub __snapshot_freeze {
84 my ($class, $vmid, $unfreeze) = @_;
85
86 if ($unfreeze) {
87 eval { PVE::Tools::run_command(['/usr/bin/lxc-unfreeze', '-n', $vmid]); };
88 warn $@ if $@;
89 } else {
90 PVE::Tools::run_command(['/usr/bin/lxc-freeze', '-n', $vmid]);
91 PVE::LXC::sync_container_namespace($vmid);
92 }
93}
94
95sub __snapshot_create_vol_snapshot {
96 my ($class, $vmid, $ms, $mountpoint, $snapname) = @_;
97
98 my $storecfg = PVE::Storage::config();
99
100 return if $snapname eq 'vzdump' && $ms ne 'rootfs' && !$mountpoint->{backup};
101 PVE::Storage::volume_snapshot($storecfg, $mountpoint->{volume}, $snapname);
102}
103
104sub __snapshot_delete_remove_drive {
105 my ($class, $snap, $remove_drive) = @_;
106
107 if ($remove_drive eq 'vmstate') {
108 die "implement me - saving vmstate\n";
109 } else {
110 my $value = $snap->{$remove_drive};
111 my $mountpoint = $remove_drive eq 'rootfs' ? PVE::LXC::parse_ct_rootfs($value, 1) : PVE::LXC::parse_ct_mountpoint($value, 1);
112 delete $snap->{$remove_drive};
113 $class->add_unused_volume($snap, $mountpoint->{volume});
114 }
115}
116
117sub __snapshot_delete_vmstate_file {
118 my ($class, $snap, $force) = @_;
119
120 die "implement me - saving vmstate\n";
121}
122
123sub __snapshot_delete_vol_snapshot {
124 my ($class, $vmid, $ms, $mountpoint, $snapname) = @_;
125
126 my $storecfg = PVE::Storage::config();
127 PVE::Storage::volume_snapshot_delete($storecfg, $mountpoint->{volume}, $snapname);
128}
129
130sub __snapshot_rollback_vol_possible {
131 my ($class, $mountpoint, $snapname) = @_;
132
133 my $storecfg = PVE::Storage::config();
134 PVE::Storage::volume_rollback_is_possible($storecfg, $mountpoint->{volume}, $snapname);
135}
136
137sub __snapshot_rollback_vol_rollback {
138 my ($class, $mountpoint, $snapname) = @_;
139
140 my $storecfg = PVE::Storage::config();
141 PVE::Storage::volume_snapshot_rollback($storecfg, $mountpoint->{volume}, $snapname);
142}
143
144sub __snapshot_rollback_vm_stop {
145 my ($class, $vmid) = @_;
146
147 PVE::Tools::run_command(['/usr/bin/lxc-stop', '-n', $vmid, '--kill'])
148 if $class->__snapshot_check_running($vmid);
149}
150
151sub __snapshot_rollback_vm_start {
152 my ($class, $vmid, $vmstate, $forcemachine);
153
154 die "implement me - save vmstate\n";
155}
156
157sub __snapshot_foreach_volume {
158 my ($class, $conf, $func) = @_;
159
d250604f 160 $class->foreach_mountpoint($conf, $func);
4518000b
FG
161}
162
67afe46e
FG
163# END implemented abstract methods from PVE::AbstractConfig
164
d250604f
FG
165sub classify_mountpoint {
166 my ($class, $vol) = @_;
167 if ($vol =~ m!^/!) {
168 return 'device' if $vol =~ m!^/dev/!;
169 return 'bind';
170 }
171 return 'volume';
172}
173
174sub is_volume_in_use {
175 my ($class, $config, $volid, $include_snapshots) = @_;
176 my $used = 0;
177
178 $class->foreach_mountpoint($config, sub {
179 my ($ms, $mountpoint) = @_;
180 return if $used;
181 $used = $mountpoint->{type} eq 'volume' && $mountpoint->{volume} eq $volid;
182 });
183
184 my $snapshots = $config->{snapshots};
185 if ($include_snapshots && $snapshots) {
186 foreach my $snap (keys %$snapshots) {
187 $used ||= $class->is_volume_in_use($snapshots->{$snap}, $volid);
188 }
189 }
190
191 return $used;
192}
193
194sub has_dev_console {
195 my ($class, $conf) = @_;
196
197 return !(defined($conf->{console}) && !$conf->{console});
198}
199
200sub mountpoint_names {
201 my ($class, $reverse) = @_;
202
203 my @names = ('rootfs');
204
205 for (my $i = 0; $i < $MAX_MOUNT_POINTS; $i++) {
206 push @names, "mp$i";
207 }
208
209 return $reverse ? reverse @names : @names;
210}
211
212sub foreach_mountpoint_full {
213 my ($class, $conf, $reverse, $func) = @_;
214
215 foreach my $key ($class->mountpoint_names($reverse)) {
216 my $value = $conf->{$key};
217 next if !defined($value);
218 my $mountpoint = $key eq 'rootfs' ? PVE::LXC::parse_ct_rootfs($value, 1) : PVE::LXC::parse_ct_mountpoint($value, 1);
219 next if !defined($mountpoint);
220
221 &$func($key, $mountpoint);
222 }
223}
224
225sub foreach_mountpoint {
226 my ($class, $conf, $func) = @_;
227
228 $class->foreach_mountpoint_full($conf, 0, $func);
229}
230
231sub foreach_mountpoint_reverse {
232 my ($class, $conf, $func) = @_;
233
234 $class->foreach_mountpoint_full($conf, 1, $func);
235}
236
237sub get_vm_volumes {
238 my ($class, $conf, $excludes) = @_;
239
240 my $vollist = [];
241
242 $class->foreach_mountpoint($conf, sub {
243 my ($ms, $mountpoint) = @_;
244
245 return if $excludes && $ms eq $excludes;
246
247 my $volid = $mountpoint->{volume};
248 return if !$volid || $mountpoint->{type} ne 'volume';
249
250 my ($sid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
251 return if !$sid;
252
253 push @$vollist, $volid;
254 });
255
256 return $vollist;
257}
258
67afe46e 259return 1;