From 0509010d6eda953e4695ca2aea39eedf8dd00bc3 Mon Sep 17 00:00:00 2001 From: Alexandre Derumier Date: Thu, 31 May 2012 10:31:01 +0200 Subject: [PATCH] Add rados block plugin storage This add rados plugin storage. We need rbd command from ceph repository (ceph-common package) to create/delete volumes,I didn't have add depends for the moment. /etc/pve/storage.cfg sample config rbd: rbdtest rbd_monhost 10.3.94.27:6789;10.3.94.28:6789;10.3.94.29:6789 rbd_pool pool2 rbd_id admin rbd_key AQAmOcZPwNY7GRAAuvJjVAKIm1r3JKqLCa4LGQ== rbd_authsupported cephx;none content images Signed-off-by: Alexandre Derumier --- PVE/Storage.pm | 3 + PVE/Storage/Makefile | 2 +- PVE/Storage/RBDPlugin.pm | 247 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 251 insertions(+), 1 deletion(-) create mode 100644 PVE/Storage/RBDPlugin.pm diff --git a/PVE/Storage.pm b/PVE/Storage.pm index 99f09da..ffe2456 100755 --- a/PVE/Storage.pm +++ b/PVE/Storage.pm @@ -21,12 +21,15 @@ use PVE::Storage::DirPlugin; use PVE::Storage::LVMPlugin; use PVE::Storage::NFSPlugin; use PVE::Storage::ISCSIPlugin; +use PVE::Storage::RBDPlugin; # load and initialize all plugins PVE::Storage::DirPlugin->register(); PVE::Storage::LVMPlugin->register(); PVE::Storage::NFSPlugin->register(); PVE::Storage::ISCSIPlugin->register(); +PVE::Storage::RBDPlugin->register(); + PVE::Storage::Plugin->init(); my $UDEVADM = '/sbin/udevadm'; diff --git a/PVE/Storage/Makefile b/PVE/Storage/Makefile index 1d2322f..0f9950a 100644 --- a/PVE/Storage/Makefile +++ b/PVE/Storage/Makefile @@ -1,4 +1,4 @@ -SOURCES=Plugin.pm DirPlugin.pm LVMPlugin.pm NFSPlugin.pm ISCSIPlugin.pm +SOURCES=Plugin.pm DirPlugin.pm LVMPlugin.pm NFSPlugin.pm ISCSIPlugin.pm RBDPlugin.pm .PHONY: install install: diff --git a/PVE/Storage/RBDPlugin.pm b/PVE/Storage/RBDPlugin.pm new file mode 100644 index 0000000..7edbbeb --- /dev/null +++ b/PVE/Storage/RBDPlugin.pm @@ -0,0 +1,247 @@ +package PVE::Storage::RBDPlugin; + +use strict; +use warnings; +use IO::File; +use PVE::Tools qw(run_command trim); +use PVE::Storage::Plugin; +use PVE::JSONSchema qw(get_standard_option); + +use base qw(PVE::Storage::Plugin); + + +sub rbd_ls{ + my ($scfg) = @_; + + my $rbdpool = $scfg->{rbd_pool}; + my $monhost = $scfg->{rbd_monhost}; + $monhost =~ s/;/,/g; + + my $cmd = ['/usr/bin/rbd', '-p', $rbdpool, '-m', $monhost, '-n', "client.".$scfg->{rbd_id} ,'--key',$scfg->{rbd_key} ,'ls' ]; + my $list = {}; + run_command($cmd, errfunc => sub {},outfunc => sub { + my $line = shift; + + $line = trim($line); + my ($image) = $line; + + $list->{$rbdpool}->{$image} = { + name => $image, + size => "", + }; + + }); + + + return $list; + +} + +sub addslashes { + my $text = shift; + $text =~ s/;/\\;/g; + $text =~ s/:/\\:/g; + return $text; +} + +# Configuration + +PVE::JSONSchema::register_format('pve-storage-rbd-mon', \&parse_rbd_mon); +sub parse_rbd_mon { + my ($name, $noerr) = @_; + + if ($name !~ m/^[a-z][a-z0-9\-\_\.]*[a-z0-9]$/i) { + return undef if $noerr; + die "lvm name '$name' contains illegal characters\n"; + } + + return $name; +} + + +sub type { + return 'rbd'; +} + +sub plugindata { + return { + content => [ {images => 1}, { images => 1 }], + }; +} + +sub properties { + return { + rbd_monhost => { + description => "Monitors daemon ips.", + type => 'string', + }, + rbd_pool => { + description => "RBD Pool.", + type => 'string', + }, + rbd_id => { + description => "RBD Id.", + type => 'string', + }, + rbd_key => { + description => "Key.", + type => 'string', + }, + rbd_authsupported => { + description => "Authsupported.", + type => 'string', + }, + }; +} + +sub options { + return { + rbd_monhost => { fixed => 1 }, + rbd_pool => { fixed => 1 }, + rbd_id => { fixed => 1 }, + rbd_key => { fixed => 1 }, + rbd_authsupported => { fixed => 1 }, + content => { optional => 1 }, + }; +} + +# Storage implementation + +sub parse_volname { + my ($class, $volname) = @_; + + if ($volname =~ m/^(vm-(\d+)-\S+)$/) { + return ('images', $1, $2); + } + + die "unable to parse rbd volume name '$volname'\n"; +} + +sub path { + my ($class, $scfg, $volname) = @_; + + my ($vtype, $name, $vmid) = $class->parse_volname($volname); + + my $monhost = addslashes($scfg->{rbd_monhost}); + my $pool = $scfg->{rbd_pool}; + my $id = $scfg->{rbd_id}; + my $key = $scfg->{rbd_key}; + my $authsupported = addslashes($scfg->{rbd_authsupported}); + + my $path = "rbd:$pool/$name:id=$id:key=$key:auth_supported=$authsupported:mon_host=$monhost"; + + return ($path, $vmid, $vtype); +} + +sub alloc_image { + my ($class, $storeid, $scfg, $vmid, $fmt, $name, $size) = @_; + + + die "illegal name '$name' - sould be 'vm-$vmid-*'\n" + if $name && $name !~ m/^vm-$vmid-/; + my $rbdpool = $scfg->{rbd_pool}; + my $monhost = $scfg->{rbd_monhost}; + $monhost =~ s/;/,/g; + + if (!$name) { + my $rdb = rbd_ls($scfg); + + for (my $i = 1; $i < 100; $i++) { + my $tn = "vm-$vmid-disk-$i"; + if (!defined ($rdb->{$rbdpool}->{$tn})) { + $name = $tn; + last; + } + } + } + + die "unable to allocate an image name for VM $vmid in storage '$storeid'\n" + if !$name; + + my $cmd = ['/usr/bin/rbd', '-p', $rbdpool, '-m', $monhost, '-n', "client.".$scfg->{rbd_id}, '--key', $scfg->{rbd_key}, 'create', '--size', ($size/1024), $name ]; + run_command($cmd, errmsg => "rbd create $name' error"); + + return $name; +} + +sub free_image { + my ($class, $storeid, $scfg, $volname) = @_; + + my $rbdpool = $scfg->{rbd_pool}; + my $monhost = $scfg->{rbd_monhost}; + $monhost =~ s/;/,/g; + + my $cmd = ['/usr/bin/rbd', '-p', $rbdpool, '-m', $monhost, '-n', "client.".$scfg->{rbd_id}, '--key',$scfg->{rbd_key}, 'rm', $volname ]; + run_command($cmd, errmsg => "rbd rm $volname' error"); + + return undef; +} + +sub list_images { + my ($class, $storeid, $scfg, $vmid, $vollist, $cache) = @_; + + $cache->{rbd} = rbd_ls($scfg) if !$cache->{rbd}; + my $rbdpool = $scfg->{rbd_pool}; + my $res = []; + + if (my $dat = $cache->{rbd}->{$rbdpool}) { + foreach my $image (keys %$dat) { + + my $volname = $dat->{$image}->{name}; + + my $volid = "$storeid:$volname"; + + + my $owner = $dat->{$volname}->{vmid}; + if ($vollist) { + my $found = grep { $_ eq $volid } @$vollist; + next if !$found; + } else { + next if defined ($vmid) && ($owner ne $vmid); + } + + my $info = $dat->{$volname}; + $info->{volid} = $volid; + + push @$res, $info; + } + } + + return $res; +} + + +sub status { + my ($class, $storeid, $scfg, $cache) = @_; + + + my $total = 0; + my $free = 0; + my $used = 0; + my $active = 1; + return ($total,$free,$used,$active); + + return undef; +} + +sub activate_storage { + my ($class, $storeid, $scfg, $cache) = @_; + return 1; +} + +sub deactivate_storage { + my ($class, $storeid, $scfg, $cache) = @_; + return 1; +} + +sub activate_volume { + my ($class, $storeid, $scfg, $volname, $exclusive, $cache) = @_; + return 1; +} + +sub deactivate_volume { + my ($class, $storeid, $scfg, $volname, $exclusive, $cache) = @_; + return 1; +} + +1; -- 2.39.2