]> git.proxmox.com Git - pve-storage.git/blob - PVE/Storage/RBDPlugin.pm
rbd : rbd_ls: doesn't throw error if pool doesn't contain image
[pve-storage.git] / PVE / Storage / RBDPlugin.pm
1 package PVE::Storage::RBDPlugin;
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
13 sub rbd_ls{
14 my ($scfg, $storeid) = @_;
15
16 my $rbdpool = $scfg->{pool};
17 my $monhost = $scfg->{monhost};
18 $monhost =~ s/;/,/g;
19
20 my $cmd = ['/usr/bin/rbd', '-p', $rbdpool, '-m', $monhost, '-n', "client.".$scfg->{username} ,'--keyfile', '/etc/pve/priv/ceph/'.$storeid.'.'.$scfg->{username}.'.key', '--auth_supported',$scfg->{authsupported}, 'ls' ];
21 my $list = {};
22
23 my $errfunc = sub {
24 my $line = shift;
25 die $line if $line;
26 };
27
28 eval {
29 run_command($cmd, errmsg => "rbd error", errfunc => $errfunc,outfunc => sub {
30 my $line = shift;
31
32 $line = trim($line);
33 my ($image) = $line;
34
35 $list->{$rbdpool}->{$image} = {
36 name => $image,
37 size => "",
38 };
39
40 });
41 };
42
43 my $err = $@;
44 die $err if $err && $err !~ m/doesn't contain rbd images/ ;
45
46 return $list;
47
48 }
49
50 sub addslashes {
51 my $text = shift;
52 $text =~ s/;/\\;/g;
53 $text =~ s/:/\\:/g;
54 return $text;
55 }
56
57 # Configuration
58
59 PVE::JSONSchema::register_format('pve-storage-monhost', \&parse_monhost);
60 sub parse_monhost {
61 my ($name, $noerr) = @_;
62
63 if ($name !~ m/^[a-z][a-z0-9\-\_\.]*[a-z0-9]$/i) {
64 return undef if $noerr;
65 die "lvm name '$name' contains illegal characters\n";
66 }
67
68 return $name;
69 }
70
71
72 sub type {
73 return 'rbd';
74 }
75
76 sub plugindata {
77 return {
78 content => [ {images => 1}, { images => 1 }],
79 };
80 }
81
82 sub properties {
83 return {
84 monhost => {
85 description => "Monitors daemon ips.",
86 type => 'string',
87 },
88 pool => {
89 description => "Pool.",
90 type => 'string',
91 },
92 username => {
93 description => "RBD Id.",
94 type => 'string',
95 },
96 authsupported => {
97 description => "Authsupported.",
98 type => 'string',
99 },
100 };
101 }
102
103 sub options {
104 return {
105 monhost => { fixed => 1 },
106 pool => { fixed => 1 },
107 username => { fixed => 1 },
108 authsupported => { fixed => 1 },
109 content => { optional => 1 },
110 };
111 }
112
113 # Storage implementation
114
115 sub parse_volname {
116 my ($class, $volname) = @_;
117
118 if ($volname =~ m/^(vm-(\d+)-\S+)$/) {
119 return ('images', $1, $2);
120 }
121
122 die "unable to parse rbd volume name '$volname'\n";
123 }
124
125 sub path {
126 my ($class, $scfg, $volname, $storeid) = @_;
127
128 my ($vtype, $name, $vmid) = $class->parse_volname($volname);
129
130 my $monhost = addslashes($scfg->{monhost});
131 my $pool = $scfg->{pool};
132 my $username = $scfg->{username};
133 my $authsupported = addslashes($scfg->{authsupported});
134
135 my $path = "rbd:$pool/$name:id=$username:auth_supported=$authsupported:keyfile=/etc/pve/priv/ceph/$storeid.$username.key:mon_host=$monhost";
136
137 return ($path, $vmid, $vtype);
138 }
139
140 sub alloc_image {
141 my ($class, $storeid, $scfg, $vmid, $fmt, $name, $size) = @_;
142
143
144 die "illegal name '$name' - sould be 'vm-$vmid-*'\n"
145 if $name && $name !~ m/^vm-$vmid-/;
146 my $rbdpool = $scfg->{pool};
147 my $monhost = $scfg->{monhost};
148 $monhost =~ s/;/,/g;
149
150 if (!$name) {
151 my $rdb = rbd_ls($scfg, $storeid);
152
153 for (my $i = 1; $i < 100; $i++) {
154 my $tn = "vm-$vmid-disk-$i";
155 if (!defined ($rdb->{$rbdpool}->{$tn})) {
156 $name = $tn;
157 last;
158 }
159 }
160 }
161
162 die "unable to allocate an image name for VM $vmid in storage '$storeid'\n"
163 if !$name;
164
165 my $cmd = ['/usr/bin/rbd', '-p', $rbdpool, '-m', $monhost, '-n', "client.".$scfg->{username}, '--keyfile','/etc/pve/priv/ceph/'.$storeid.'.'.$scfg->{username}.'.key','--auth_supported', $scfg->{authsupported}, 'create', '--size', ($size/1024), $name ];
166 run_command($cmd, errmsg => "rbd create $name' error");
167
168 return $name;
169 }
170
171 sub free_image {
172 my ($class, $storeid, $scfg, $volname) = @_;
173
174 my $rbdpool = $scfg->{pool};
175 my $monhost = $scfg->{monhost};
176 $monhost =~ s/;/,/g;
177
178 my $cmd = ['/usr/bin/rbd', '-p', $rbdpool, '-m', $monhost, '-n', "client.".$scfg->{username}, '--keyfile','/etc/pve/priv/ceph/'.$storeid.'.'.$scfg->{username}.'.key','--auth_supported',$scfg->{authsupported}, 'rm', $volname ];
179 run_command($cmd, errmsg => "rbd rm $volname' error");
180
181 return undef;
182 }
183
184 sub list_images {
185 my ($class, $storeid, $scfg, $vmid, $vollist, $cache) = @_;
186
187 $cache->{rbd} = rbd_ls($scfg, $storeid) if !$cache->{rbd};
188 my $rbdpool = $scfg->{pool};
189 my $res = [];
190
191 if (my $dat = $cache->{rbd}->{$rbdpool}) {
192 foreach my $image (keys %$dat) {
193
194 my $volname = $dat->{$image}->{name};
195
196 my $volid = "$storeid:$volname";
197
198
199 my $owner = $dat->{$volname}->{vmid};
200 if ($vollist) {
201 my $found = grep { $_ eq $volid } @$vollist;
202 next if !$found;
203 } else {
204 next if defined ($vmid) && ($owner ne $vmid);
205 }
206
207 my $info = $dat->{$volname};
208 $info->{volid} = $volid;
209
210 push @$res, $info;
211 }
212 }
213
214 return $res;
215 }
216
217
218 sub status {
219 my ($class, $storeid, $scfg, $cache) = @_;
220
221 my $total = 0;
222 my $free = 0;
223 my $used = 0;
224 my $active = 1;
225 return ($total,$free,$used,$active);
226
227 return undef;
228 }
229
230 sub activate_storage {
231 my ($class, $storeid, $scfg, $cache) = @_;
232 return 1;
233 }
234
235 sub deactivate_storage {
236 my ($class, $storeid, $scfg, $cache) = @_;
237 return 1;
238 }
239
240 sub activate_volume {
241 my ($class, $storeid, $scfg, $volname, $exclusive, $cache) = @_;
242 return 1;
243 }
244
245 sub deactivate_volume {
246 my ($class, $storeid, $scfg, $volname, $exclusive, $cache) = @_;
247 return 1;
248 }
249
250 1;