From: Alexandre Derumier Date: Mon, 12 Aug 2013 07:59:00 +0000 (+0200) Subject: add Glusterfs Plugin X-Git-Url: https://git.proxmox.com/?p=pve-storage.git;a=commitdiff_plain;h=f4648aef06ab86f3a5269403786df75571cba541 add Glusterfs Plugin storage.cfg ------------ glusterfs: glusterstore path /mnt/pve/gluster server server.fqdn (optional, default is localhost) volume glustervolume content images maxfiles 1 Signed-off-by: Alexandre Derumier --- diff --git a/PVE/Storage.pm b/PVE/Storage.pm index c6d9d12..2bda7c6 100755 --- a/PVE/Storage.pm +++ b/PVE/Storage.pm @@ -25,6 +25,7 @@ use PVE::Storage::RBDPlugin; use PVE::Storage::SheepdogPlugin; use PVE::Storage::ISCSIDirectPlugin; use PVE::Storage::NexentaPlugin; +use PVE::Storage::GlusterfsPlugin; # load and initialize all plugins PVE::Storage::DirPlugin->register(); @@ -35,6 +36,7 @@ PVE::Storage::RBDPlugin->register(); PVE::Storage::SheepdogPlugin->register(); PVE::Storage::ISCSIDirectPlugin->register(); PVE::Storage::NexentaPlugin->register(); +PVE::Storage::GlusterfsPlugin->register(); PVE::Storage::Plugin->init(); my $UDEVADM = '/sbin/udevadm'; diff --git a/PVE/Storage/GlusterfsPlugin.pm b/PVE/Storage/GlusterfsPlugin.pm new file mode 100644 index 0000000..93d1509 --- /dev/null +++ b/PVE/Storage/GlusterfsPlugin.pm @@ -0,0 +1,214 @@ +package PVE::Storage::GlusterfsPlugin; + +use strict; +use warnings; +use IO::File; +use File::Path; +use PVE::Tools qw(run_command); +use PVE::Storage::Plugin; +use PVE::JSONSchema qw(get_standard_option); +use Net::Ping; + +use base qw(PVE::Storage::Plugin); + +# Glusterfs helper functions + +sub read_proc_mounts { + + local $/; # enable slurp mode + + my $data = ""; + if (my $fd = IO::File->new("/proc/mounts", "r")) { + $data = <$fd>; + close ($fd); + } + + return $data; +} + +sub glusterfs_is_mounted { + my ($server, $volume, $mountpoint, $mountdata) = @_; + + my $source = "$server:$volume"; + + $mountdata = read_proc_mounts() if !$mountdata; + + if ($mountdata =~ m|^$source/?\s$mountpoint\sfuse.glusterfs|m) { + return $mountpoint; + } + + return undef; +} + +sub glusterfs_mount { + my ($server, $volume, $mountpoint) = @_; + + my $source = "$server:$volume"; + + my $cmd = ['/bin/mount', '-t', 'glusterfs', $source, $mountpoint]; + + run_command($cmd, errmsg => "mount error"); +} + +# Configuration + +sub type { + return 'glusterfs'; +} + +sub plugindata { + return { + content => [ { images => 1, rootdir => 1, vztmpl => 1, iso => 1, backup => 1}, + { images => 1 }], + format => [ { raw => 1, qcow2 => 1, vmdk => 1 } , 'raw' ], + }; +} + +sub properties { + return { + volume => { + description => "Glusterfs Volume.", + type => 'string', + }, + }; +} + +sub options { + return { + path => { fixed => 1 }, + server => { optional => 1 }, + volume => { fixed => 1 }, + nodes => { optional => 1 }, + disable => { optional => 1 }, + maxfiles => { optional => 1 }, + content => { optional => 1 }, + format => { optional => 1 }, + }; +} + + +sub check_config { + my ($class, $sectionId, $config, $create, $skipSchemaCheck) = @_; + + $config->{path} = "/mnt/pve/$sectionId" if $create && !$config->{path}; + + return $class->SUPER::check_config($sectionId, $config, $create, $skipSchemaCheck); +} + +# Storage implementation + +sub path { + my ($class, $scfg, $volname, $storeid) = @_; + + my ($vtype, $name, $vmid) = $class->parse_volname($volname); + + my $server = $scfg->{server} ? $scfg->{server} : 'localhost'; + my $glustervolume = $scfg->{volume}; + + my $path = undef; + if($vtype eq 'images'){ + $path = "gluster://$server/$glustervolume/images/$vmid/$name"; + }else{ + my $dir = $class->get_subdir($scfg, $vtype); + $path = "$dir/$name"; + } + + + return wantarray ? ($path, $vmid, $vtype) : $path; +} + +sub status { + my ($class, $storeid, $scfg, $cache) = @_; + + $cache->{mountdata} = read_proc_mounts() if !$cache->{mountdata}; + + my $path = $scfg->{path}; + my $server = $scfg->{server} ? $scfg->{server} : 'localhost'; + + my $volume = $scfg->{volume}; + + return undef if !glusterfs_is_mounted($server, $volume, $path, $cache->{mountdata}); + + return $class->SUPER::status($storeid, $scfg, $cache); +} + +sub activate_storage { + my ($class, $storeid, $scfg, $cache) = @_; + + $cache->{mountdata} = read_proc_mounts() if !$cache->{mountdata}; + + my $path = $scfg->{path}; + my $server = $scfg->{server} ? $scfg->{server} : 'localhost'; + my $volume = $scfg->{volume}; + + if (!glusterfs_is_mounted($server, $volume, $path, $cache->{mountdata})) { + + mkpath $path; + + die "unable to activate storage '$storeid' - " . + "directory '$path' does not exist\n" if ! -d $path; + + glusterfs_mount($server, $volume, $path, $scfg->{options}); + } + + $class->SUPER::activate_storage($storeid, $scfg, $cache); +} + +sub deactivate_storage { + my ($class, $storeid, $scfg, $cache) = @_; + + $cache->{mountdata} = read_proc_mounts() if !$cache->{mountdata}; + + my $path = $scfg->{path}; + my $server = $scfg->{server} ? $scfg->{server} : 'localhost'; + my $volume = $scfg->{volume}; + + if (glusterfs_is_mounted($server, $volume, $path, $cache->{mountdata})) { + my $cmd = ['/bin/umount', $path]; + run_command($cmd, errmsg => 'umount error'); + } +} + +sub activate_volume { + my ($class, $storeid, $scfg, $volname, $exclusive, $cache) = @_; + + # do nothing by default +} + +sub deactivate_volume { + my ($class, $storeid, $scfg, $volname, $cache) = @_; + + # do nothing by default +} + +sub check_connection { + my ($class, $storeid, $scfg) = @_; + + my $server = $scfg->{server} ? $scfg->{server} : 'localhost'; + my $volume = $scfg->{volume}; + + my $status = 0; + + if($server && $server ne 'localhost' && $server ne '127.0.0.1'){ + my $p = Net::Ping->new("tcp", 2); + $status = $p->ping($server); + + }else{ + + my $parser = sub { + my $line = shift; + + if ($line =~ m/Status: Started$/) { + $status = 1; + } + }; + + my $cmd = ['/usr/sbin/gluster', 'volume', 'info', $volume]; + + run_command($cmd, errmsg => "glusterfs error", errfunc => sub {}, outfunc => $parser); + } + + return $status; +} + +1; diff --git a/PVE/Storage/Makefile b/PVE/Storage/Makefile index ed65a18..0014c51 100644 --- a/PVE/Storage/Makefile +++ b/PVE/Storage/Makefile @@ -1,4 +1,4 @@ -SOURCES=Plugin.pm DirPlugin.pm LVMPlugin.pm NFSPlugin.pm ISCSIPlugin.pm RBDPlugin.pm SheepdogPlugin.pm ISCSIDirectPlugin.pm NexentaPlugin.pm +SOURCES=Plugin.pm DirPlugin.pm LVMPlugin.pm NFSPlugin.pm ISCSIPlugin.pm RBDPlugin.pm SheepdogPlugin.pm ISCSIDirectPlugin.pm NexentaPlugin.pm GlusterfsPlugin.pm .PHONY: install install: diff --git a/PVE/Storage/Plugin.pm b/PVE/Storage/Plugin.pm index 88e34a9..df1c77b 100644 --- a/PVE/Storage/Plugin.pm +++ b/PVE/Storage/Plugin.pm @@ -312,7 +312,7 @@ sub parse_config { $d->{content} = $def->{content}->[1] if !$d->{content}; } - if ($type eq 'iscsi' || $type eq 'nfs' || $type eq 'rbd' || $type eq 'sheepdog' || $type eq 'iscsidirect' || $type eq 'nexenta' ) { + if ($type eq 'iscsi' || $type eq 'nfs' || $type eq 'rbd' || $type eq 'sheepdog' || $type eq 'iscsidirect' || $type eq 'nexenta' || $type eq 'glusterfs') { $d->{shared} = 1; } } diff --git a/control.in b/control.in index ee0b847..220fe74 100644 --- a/control.in +++ b/control.in @@ -3,7 +3,7 @@ Version: @@VERSION@@-@@PKGRELEASE@@ Section: perl Priority: optional Architecture: @@ARCH@@ -Depends: perl (>= 5.6.0-16), nfs-common, udev, libpve-common-perl, lvm2, clvm, libfile-chdir-perl +Depends: perl (>= 5.6.0-16), nfs-common, udev, libpve-common-perl, lvm2, clvm, libfile-chdir-perl, glusterfs-client (>= 3.4.0-2) Maintainer: Proxmox Support Team Description: Proxmox VE storage management library This package contains the storage management library used by Proxmox VE.