]> git.proxmox.com Git - pve-storage.git/blob - PVE/Storage/SheepdogPlugin.pm
sheepdog : add volume_snapshot_rollback
[pve-storage.git] / PVE / Storage / SheepdogPlugin.pm
1 package PVE::Storage::SheepdogPlugin;
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 use base qw(PVE::Storage::Plugin);
11
12 my $collie_cmd = sub {
13 my ($scfg, $class, $op, @options) = @_;
14
15 my $portal = $scfg->{portal};
16 my ($server, $port) = split(':', $portal);
17 my $cmd = ['/usr/sbin/collie', $class, $op, '-a', $server];
18 push @$cmd, '-p', $port if $port;
19
20 push @$cmd, @options if scalar(@options);
21
22 return $cmd;
23 };
24
25 sub sheepdog_ls {
26 my ($scfg, $storeid) = @_;
27
28 my $cmd = &$collie_cmd($scfg, 'vdi', 'list', '-r');
29
30 my $list = {};
31
32 run_command($cmd, outfunc => sub {
33 my $line = shift;
34 $line = trim($line);
35 if ($line =~ /= (vm-(\d+)-\S+)\s+(\d+)\s+(\d+)\s(\d+)\s(\d+)\s/) {
36 my $image = $1;
37 my $owner = $2;
38 my $size = $4;
39
40 $list->{$storeid}->{$image} = {
41 name => $image,
42 size => $size,
43 vmid => $owner
44 };
45 }
46 });
47
48 return $list;
49 }
50
51 # Configuration
52
53
54 sub type {
55 return 'sheepdog';
56 }
57
58 sub plugindata {
59 return {
60 content => [ {images => 1}, { images => 1 }],
61 };
62 }
63
64
65 sub options {
66 return {
67 nodes => { optional => 1 },
68 disable => { optional => 1 },
69 portal => { fixed => 1 },
70 content => { optional => 1 },
71 };
72 }
73
74 # Storage implementation
75
76 sub parse_volname {
77 my ($class, $volname) = @_;
78
79 if ($volname =~ m/^(vm-(\d+)-\S+)$/) {
80 return ('images', $1, $2);
81 }
82
83 die "unable to parse rbd volume name '$volname'\n";
84 }
85
86 sub path {
87 my ($class, $scfg, $volname, $storeid) = @_;
88
89 my ($vtype, $name, $vmid) = $class->parse_volname($volname);
90
91 my $portal = $scfg->{portal};
92 my ($server, $port) = split(':', $portal);
93 $port = 7000 if !$port;
94
95 my $path = "sheepdog:$server:$port:$name";
96
97 return ($path, $vmid, $vtype);
98 }
99
100 sub alloc_image {
101 my ($class, $storeid, $scfg, $vmid, $fmt, $name, $size) = @_;
102
103
104 die "illegal name '$name' - sould be 'vm-$vmid-*'\n"
105 if $name && $name !~ m/^vm-$vmid-/;
106
107 if (!$name) {
108 my $sheepdog = sheepdog_ls($scfg, $storeid);
109
110 for (my $i = 1; $i < 100; $i++) {
111 my $tn = "vm-$vmid-disk-$i";
112 if (!defined ($sheepdog->{$storeid}->{$tn})) {
113 $name = $tn;
114 last;
115 }
116 }
117 }
118
119 die "unable to allocate an image name for VM $vmid in storage '$storeid'\n"
120 if !$name;
121
122 my $cmd = &$collie_cmd($scfg, 'vdi', 'create', $name , "${size}KB");
123
124 run_command($cmd, errmsg => "sheepdog create $name' error");
125
126 return $name;
127 }
128
129 sub free_image {
130 my ($class, $storeid, $scfg, $volname) = @_;
131
132 my $cmd = &$collie_cmd($scfg, 'vdi', 'delete' , $volname);
133
134 run_command($cmd, errmsg => "sheepdog delete $volname' error");
135
136 return undef;
137 }
138
139 sub list_images {
140 my ($class, $storeid, $scfg, $vmid, $vollist, $cache) = @_;
141
142 $cache->{sheepdog} = sheepdog_ls($scfg, $storeid) if !$cache->{sheepdog};
143 my $res = [];
144
145 if (my $dat = $cache->{sheepdog}->{$storeid}) {
146 foreach my $image (keys %$dat) {
147
148 my $volname = $dat->{$image}->{name};
149
150 my $volid = "$storeid:$volname";
151
152 my $owner = $dat->{$volname}->{vmid};
153 if ($vollist) {
154 my $found = grep { $_ eq $volid } @$vollist;
155 next if !$found;
156 } else {
157 next if defined ($vmid) && ($owner ne $vmid);
158 }
159
160 my $info = $dat->{$volname};
161 $info->{volid} = $volid;
162 $info->{format} = 'raw';
163 push @$res, $info;
164 }
165 }
166
167 return $res;
168 }
169
170
171 sub status {
172 my ($class, $storeid, $scfg, $cache) = @_;
173
174 my $total = 0;
175 my $free = 0;
176 my $used = 0;
177 my $active = 1;
178
179 my $cmd = &$collie_cmd($scfg, 'node', 'info' , '-r');
180
181 my $parser = sub {
182 my $line = shift;
183 if ($line =~ m/^Total\s(\d+)\s(\d+)\s/) {
184 $total = $1;
185 $used = $2;
186 $free = $total - $used;
187 }
188 };
189
190 run_command($cmd, outfunc => $parser, errmsg => "sheepdog node info error");
191
192 return ($total,$free,$used,$active);
193
194 return undef;
195 }
196
197 sub activate_storage {
198 my ($class, $storeid, $scfg, $cache) = @_;
199 return 1;
200 }
201
202 sub deactivate_storage {
203 my ($class, $storeid, $scfg, $cache) = @_;
204 return 1;
205 }
206
207 sub activate_volume {
208 my ($class, $storeid, $scfg, $volname, $exclusive, $cache) = @_;
209 return 1;
210 }
211
212 sub deactivate_volume {
213 my ($class, $storeid, $scfg, $volname, $exclusive, $cache) = @_;
214 return 1;
215 }
216
217 sub volume_size_info {
218 my ($class, $scfg, $storeid, $volname, $timeout) = @_;
219
220 my $size = undef;
221
222 my $cmd = &$collie_cmd($scfg, 'vdi', 'list', '-r', $volname);
223
224 run_command($cmd, outfunc => sub {
225 my $line = shift;
226 $line = trim($line);
227 if ($line =~ /= (vm-(\d+)-\S+)\s+(\d+)\s+(\d+)\s(\d+)\s(\d+)\s/) {
228 $size = $4;
229
230 }
231 });
232
233 return $size;
234 }
235
236 sub volume_resize {
237 my ($class, $scfg, $storeid, $volname, $size, $running) = @_;
238
239 my $cmd = &$collie_cmd($scfg, 'vdi', 'resize' , $volname, $size);
240 run_command($cmd, errmsg => "sheepdog resize $volname' error");
241
242 return undef;
243 }
244
245 sub volume_snapshot {
246 my ($class, $scfg, $storeid, $volname, $snap, $running) = @_;
247
248 return 1 if $running;
249
250 my $cmd = &$collie_cmd($scfg, 'vdi', 'snapshot', '-s', $snap, $volname);
251 run_command($cmd, errmsg => "sheepdog snapshot $volname' error");
252
253 return undef;
254 }
255
256 sub volume_snapshot_rollback {
257 my ($class, $scfg, $storeid, $volname, $snap) = @_;
258
259 my $cmd = &$collie_cmd($scfg, 'vdi', 'rollback', '-s', $snap, $volname);
260 run_command($cmd, errmsg => "sheepdog snapshot $volname' error");
261
262 }
263
264 1;