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