]> git.proxmox.com Git - pve-storage.git/commitdiff
Add rados block plugin storage
authorAlexandre Derumier <aderumier@odiso.com>
Thu, 31 May 2012 08:31:01 +0000 (10:31 +0200)
committerDietmar Maurer <dietmar@proxmox.com>
Fri, 1 Jun 2012 05:18:11 +0000 (07:18 +0200)
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 <aderumier@odiso.com>
PVE/Storage.pm
PVE/Storage/Makefile
PVE/Storage/RBDPlugin.pm [new file with mode: 0644]

index 99f09da56c24d004ccd80b9b6738a2a735fd2885..ffe24565782b4d17a9c720c9f6041c0b9e76c047 100755 (executable)
@@ -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';
index 1d2322f92e4369c56a5c587d10a235bc6230cd74..0f9950af9e81659f94cfbba92bbb90a8f9f2762e 100644 (file)
@@ -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 (file)
index 0000000..7edbbeb
--- /dev/null
@@ -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;