]>
Commit | Line | Data |
---|---|---|
610798bc DM |
1 | package PVE::Storage::LvmThinPlugin; |
2 | ||
3 | use strict; | |
4 | use warnings; | |
5 | use IO::File; | |
6 | use PVE::Tools qw(run_command trim); | |
7 | use PVE::Storage::Plugin; | |
8 | use PVE::JSONSchema qw(get_standard_option); | |
9 | ||
10 | # see: man lvmthin | |
11 | ||
12 | use base qw(PVE::Storage::LVMPlugin); | |
13 | ||
14 | sub type { | |
15 | return 'lvmthin'; | |
16 | } | |
17 | ||
18 | sub plugindata { | |
19 | return { | |
20 | content => [ {images => 1, rootdir => 1}, { images => 1, rootdir => 1}], | |
21 | }; | |
22 | } | |
23 | ||
24 | sub properties { | |
25 | return { | |
26 | thinpool => { | |
27 | description => "LVM thin pool LV name.", | |
28 | type => 'string', format => 'pve-storage-vgname', | |
29 | }, | |
30 | }; | |
31 | } | |
32 | ||
33 | sub options { | |
34 | return { | |
35 | thinpool => { fixed => 1 }, | |
36 | vgname => { fixed => 1 }, | |
37 | nodes => { optional => 1 }, | |
38 | disable => { optional => 1 }, | |
39 | content => { optional => 1 }, | |
40 | }; | |
41 | } | |
42 | ||
43 | sub alloc_image { | |
44 | my ($class, $storeid, $scfg, $vmid, $fmt, $name, $size) = @_; | |
45 | ||
46 | die "unsupported format '$fmt'" if $fmt ne 'raw'; | |
47 | ||
48 | die "illegal name '$name' - sould be 'vm-$vmid-*'\n" | |
49 | if $name && $name !~ m/^vm-$vmid-/; | |
50 | ||
51 | die "implement me"; | |
52 | } | |
53 | ||
54 | sub free_image { | |
55 | my ($class, $storeid, $scfg, $volname, $isBase) = @_; | |
56 | ||
57 | my $vg = $scfg->{vgname}; | |
58 | my $cmd = ['/sbin/lvremove', '-f', "$vg/$volname"]; | |
59 | run_command($cmd, errmsg => "lvremove '$vg/$volname' error"); | |
60 | ||
61 | return undef; | |
62 | } | |
63 | ||
64 | sub list_images { | |
65 | my ($class, $storeid, $scfg, $vmid, $vollist, $cache) = @_; | |
66 | ||
67 | die "implement me"; | |
68 | } | |
69 | ||
70 | sub status { | |
71 | my ($class, $storeid, $scfg, $cache) = @_; | |
72 | ||
73 | my $lvname = "$scfg->{vgname}/$scfg->{thinpool}"; | |
74 | ||
75 | my $cmd = ['/sbin/lvs', '--separator', ':', '--noheadings', '--units', 'b', | |
76 | '--unbuffered', '--nosuffix', '--options', | |
77 | 'vg_name,lv_name,lv_size,data_percent,metadata_percent,snap_percent', $lvname]; | |
78 | ||
79 | my $total = 0; | |
80 | my $used = 0; | |
81 | ||
82 | run_command($cmd, outfunc => sub { | |
83 | my $line = shift; | |
84 | ||
85 | $line = trim($line); | |
86 | ||
87 | my ($vg, $lv, $size, $data_percent, $meta_percent, $snap_percent) = split(':', $line); | |
88 | ||
89 | return if !$vg || $vg ne $scfg->{vgname}; | |
90 | return if !$lv || $lv ne $scfg->{thinpool}; | |
91 | ||
92 | $data_percent ||= 0; | |
93 | $meta_percent ||= 0; | |
94 | $snap_percent ||= 0; | |
95 | ||
96 | $total = $size; | |
97 | $used = int((($data_percent + $meta_percent + $snap_percent) * $size)/100) | |
98 | }); | |
99 | ||
100 | return ($total, $total - $used, $used, 1) if $total; | |
101 | ||
102 | return undef; | |
103 | } | |
104 | ||
105 | sub activate_volume { | |
106 | my ($class, $storeid, $scfg, $volname, $snapname, $cache) = @_; | |
107 | } | |
108 | ||
109 | sub deactivate_volume { | |
110 | my ($class, $storeid, $scfg, $volname, $snapname, $cache) = @_; | |
111 | } | |
112 | ||
113 | sub volume_resize { | |
114 | my ($class, $scfg, $storeid, $volname, $size, $running) = @_; | |
115 | die "implement me"; | |
116 | } | |
117 | ||
118 | sub volume_has_feature { | |
119 | my ($class, $scfg, $feature, $storeid, $volname, $snapname, $running) = @_; | |
120 | ||
121 | my $features = { | |
122 | copy => { base => 1, current => 1}, | |
123 | }; | |
124 | ||
125 | my ($vtype, $name, $vmid, $basename, $basevmid, $isBase) = | |
126 | $class->parse_volname($volname); | |
127 | ||
128 | my $key = undef; | |
129 | if($snapname){ | |
130 | $key = 'snap'; | |
131 | }else{ | |
132 | $key = $isBase ? 'base' : 'current'; | |
133 | } | |
134 | return 1 if $features->{$feature}->{$key}; | |
135 | ||
136 | return undef; | |
137 | } | |
138 | ||
139 | 1; |