]>
git.proxmox.com Git - pve-storage.git/blob - PVE/Storage/GlusterfsPlugin.pm
8697ea23e4b7e996c7e6dccabb794b669eb56a55
1 package PVE
::Storage
::GlusterfsPlugin
;
7 use PVE
::Tools
qw(run_command);
8 use PVE
::Storage
::Plugin
;
9 use PVE
::JSONSchema
qw(get_standard_option);
12 use base
qw(PVE::Storage::Plugin);
14 # Glusterfs helper functions
16 sub read_proc_mounts
{
18 local $/; # enable slurp mode
21 if (my $fd = IO
::File-
>new("/proc/mounts", "r")) {
29 sub glusterfs_is_mounted
{
30 my ($server, $volume, $mountpoint, $mountdata) = @_;
32 my $source = "$server:$volume";
34 $mountdata = read_proc_mounts
() if !$mountdata;
36 if ($mountdata =~ m
|^$source/?\s$mountpoint\sfuse.glusterfs
|m
) {
44 my ($server, $volume, $mountpoint) = @_;
46 my $source = "$server:$volume";
48 my $cmd = ['/bin/mount', '-t', 'glusterfs', $source, $mountpoint];
50 run_command
($cmd, errmsg
=> "mount error");
61 content
=> [ { images
=> 1, rootdir
=> 1, vztmpl
=> 1, iso
=> 1, backup
=> 1},
63 format
=> [ { raw
=> 1, qcow2
=> 1, vmdk
=> 1 } , 'raw' ],
70 description
=> "Glusterfs Volume.",
78 path
=> { fixed
=> 1 },
79 server
=> { optional
=> 1 },
80 volume
=> { fixed
=> 1 },
81 nodes
=> { optional
=> 1 },
82 disable
=> { optional
=> 1 },
83 maxfiles
=> { optional
=> 1 },
84 content
=> { optional
=> 1 },
85 format
=> { optional
=> 1 },
91 my ($class, $sectionId, $config, $create, $skipSchemaCheck) = @_;
93 $config->{path
} = "/mnt/pve/$sectionId" if $create && !$config->{path
};
95 return $class->SUPER::check_config
($sectionId, $config, $create, $skipSchemaCheck);
98 # Storage implementation
103 if ($name =~ m!^((base-)?[^/\s]+\.(raw|qcow2|vmdk))$!) {
107 die "unable to parse volume filename '$name'\n";
110 my $find_free_diskname = sub {
111 my ($imgdir, $vmid, $fmt) = @_;
114 PVE
::Tools
::dir_glob_foreach
($imgdir,
115 qr!(vm|base)-$vmid-disk-(\d+)\..*!,
117 my ($fn, $type, $disk) = @_;
118 $disk_ids->{$disk} = 1;
121 for (my $i = 1; $i < 100; $i++) {
122 if (!$disk_ids->{$i}) {
123 return "vm-$vmid-disk-$i.$fmt";
127 die "unable to allocate a new image name for VM $vmid in '$imgdir'\n";
131 my ($class, $scfg, $volname, $storeid) = @_;
133 my ($vtype, $name, $vmid) = $class->parse_volname($volname);
135 my $server = $scfg->{server
} ?
$scfg->{server
} : 'localhost';
136 my $glustervolume = $scfg->{volume
};
139 if($vtype eq 'images'){
140 $path = "gluster://$server/$glustervolume/images/$vmid/$name";
142 my $dir = $class->get_subdir($scfg, $vtype);
143 $path = "$dir/$name";
147 return wantarray ?
($path, $vmid, $vtype) : $path;
151 my ($class, $storeid, $scfg, $vmid, $fmt, $name, $size) = @_;
153 my $imagedir = $class->get_subdir($scfg, 'images');
154 $imagedir .= "/$vmid";
158 $name = &$find_free_diskname($imagedir, $vmid, $fmt) if !$name;
160 my (undef, $tmpfmt) = parse_name_dir
($name);
162 die "illegal name '$name' - wrong extension for format ('$tmpfmt != '$fmt')\n"
165 my $path = "$imagedir/$name";
167 die "disk image '$path' already exists\n" if -e
$path;
169 my $server = $scfg->{server
} ?
$scfg->{server
} : 'localhost';
170 my $glustervolume = $scfg->{volume
};
171 my $volumepath = "gluster://$server/$glustervolume/images/$vmid/$name";
173 my $cmd = ['/usr/bin/qemu-img', 'create'];
175 push @$cmd, '-o', 'preallocation=metadata' if $fmt eq 'qcow2';
177 push @$cmd, '-f', $fmt, $volumepath, "${size}K";
179 run_command
($cmd, errmsg
=> "unable to create image");
181 return "$vmid/$name";
185 my ($class, $storeid, $scfg, $cache) = @_;
187 $cache->{mountdata
} = read_proc_mounts
() if !$cache->{mountdata
};
189 my $path = $scfg->{path
};
190 my $server = $scfg->{server
} ?
$scfg->{server
} : 'localhost';
192 my $volume = $scfg->{volume
};
194 return undef if !glusterfs_is_mounted
($server, $volume, $path, $cache->{mountdata
});
196 return $class->SUPER::status
($storeid, $scfg, $cache);
199 sub activate_storage
{
200 my ($class, $storeid, $scfg, $cache) = @_;
202 $cache->{mountdata
} = read_proc_mounts
() if !$cache->{mountdata
};
204 my $path = $scfg->{path
};
205 my $server = $scfg->{server
} ?
$scfg->{server
} : 'localhost';
206 my $volume = $scfg->{volume
};
208 if (!glusterfs_is_mounted
($server, $volume, $path, $cache->{mountdata
})) {
212 die "unable to activate storage '$storeid' - " .
213 "directory '$path' does not exist\n" if ! -d
$path;
215 glusterfs_mount
($server, $volume, $path, $scfg->{options
});
218 $class->SUPER::activate_storage
($storeid, $scfg, $cache);
221 sub deactivate_storage
{
222 my ($class, $storeid, $scfg, $cache) = @_;
224 $cache->{mountdata
} = read_proc_mounts
() if !$cache->{mountdata
};
226 my $path = $scfg->{path
};
227 my $server = $scfg->{server
} ?
$scfg->{server
} : 'localhost';
228 my $volume = $scfg->{volume
};
230 if (glusterfs_is_mounted
($server, $volume, $path, $cache->{mountdata
})) {
231 my $cmd = ['/bin/umount', $path];
232 run_command
($cmd, errmsg
=> 'umount error');
236 sub activate_volume
{
237 my ($class, $storeid, $scfg, $volname, $exclusive, $cache) = @_;
239 # do nothing by default
242 sub deactivate_volume
{
243 my ($class, $storeid, $scfg, $volname, $cache) = @_;
245 # do nothing by default
248 sub check_connection
{
249 my ($class, $storeid, $scfg) = @_;
251 my $server = $scfg->{server
} ?
$scfg->{server
} : 'localhost';
252 my $volume = $scfg->{volume
};
256 if($server && $server ne 'localhost' && $server ne '127.0.0.1'){
257 my $p = Net
::Ping-
>new("tcp", 2);
258 $status = $p->ping($server);
265 if ($line =~ m/Status: Started$/) {
270 my $cmd = ['/usr/sbin/gluster', 'volume', 'info', $volume];
272 run_command
($cmd, errmsg
=> "glusterfs error", errfunc
=> sub {}, outfunc
=> $parser);