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