]>
git.proxmox.com Git - pve-storage.git/blob - PVE/Storage/ZFSPlugin.pm
e7acfb881d7614f0c8e20597ad11276b8a0230d9
1 package PVE
::Storage
::ZFSPlugin
;
7 use PVE
::Tools
qw(run_command);
8 use PVE
::Storage
::ZFSPoolPlugin
;
10 use base
qw(PVE::Storage::ZFSPoolPlugin);
11 use PVE
::Storage
::LunCmd
::Comstar
;
12 use PVE
::Storage
::LunCmd
::Istgt
;
13 use PVE
::Storage
::LunCmd
::Iet
;
15 my @ssh_opts = ('-o', 'BatchMode=yes');
16 my @ssh_cmd = ('/usr/bin/ssh', @ssh_opts);
17 my $id_rsa_path = '/etc/pve/priv/zfs';
29 my $zfs_unknown_scsi_provider = sub {
32 die "$provider: unknown iscsi provider. Available [comstar, istgt, iet]";
35 my $zfs_get_base = sub {
38 if ($scfg->{iscsiprovider
} eq 'comstar') {
39 return PVE
::Storage
::LunCmd
::Comstar
::get_base
;
40 } elsif ($scfg->{iscsiprovider
} eq 'istgt') {
41 return PVE
::Storage
::LunCmd
::Istgt
::get_base
;
42 } elsif ($scfg->{iscsiprovider
} eq 'iet') {
43 return PVE
::Storage
::LunCmd
::Iet
::get_base
;
45 $zfs_unknown_scsi_provider->($scfg->{iscsiprovider
});
50 my ($class, $scfg, $timeout, $method, @params) = @_;
52 $timeout = 5 if !$timeout;
56 if ($lun_cmds->{$method}) {
57 if ($scfg->{iscsiprovider
} eq 'comstar') {
58 $msg = PVE
::Storage
::LunCmd
::Comstar
::run_lun_command
($scfg, $timeout, $method, @params);
59 } elsif ($scfg->{iscsiprovider
} eq 'istgt') {
60 $msg = PVE
::Storage
::LunCmd
::Istgt
::run_lun_command
($scfg, $timeout, $method, @params);
61 } elsif ($scfg->{iscsiprovider
} eq 'iet') {
62 $msg = PVE
::Storage
::LunCmd
::Iet
::run_lun_command
($scfg, $timeout, $method, @params);
64 $zfs_unknown_scsi_provider->($scfg->{iscsiprovider
});
68 my $target = 'root@' . $scfg->{portal
};
70 my $cmd = [@ssh_cmd, '-i', "$id_rsa_path/$scfg->{portal}_id_rsa", $target];
72 if ($method eq 'zpool_list') {
73 push @$cmd, 'zpool', 'list';
75 push @$cmd, 'zfs', $method;
85 run_command
($cmd, outfunc
=> $output, timeout
=> $timeout);
92 my ($class, $scfg, $zvol) = @_;
94 my $base = $zfs_get_base->($scfg);
96 my $object = ($zvol =~ /^.+\/.+/) ? "$base/$zvol
" : "$base/$scfg->{pool
}/$zvol";
98 my $lu_name = $class->zfs_request($scfg, undef, 'list_lu', $object);
100 return $lu_name if $lu_name;
102 die "Could
not find lu_name
for zvol
$zvol";
105 sub zfs_add_lun_mapping_entry {
106 my ($class, $scfg, $zvol, $guid) = @_;
108 if (!defined($guid)) {
109 $guid = $class->zfs_get_lu_name($scfg, $zvol);
112 $class->zfs_request($scfg, undef, 'add_view', $guid);
116 my ($class, $scfg, $zvol) = @_;
118 my $guid = $class->zfs_get_lu_name($scfg, $zvol);
120 $class->zfs_request($scfg, undef, 'delete_lu', $guid);
124 my ($class, $scfg, $zvol) = @_;
126 my $base = $zfs_get_base->($scfg);
127 my $guid = $class->zfs_request($scfg, undef, 'create_lu', "$base/$scfg->{pool
}/$zvol");
133 my ($class, $scfg, $zvol) = @_;
135 my $base = $zfs_get_base->($scfg);
136 $class->zfs_request($scfg, undef, 'import_lu', "$base/$scfg->{pool
}/$zvol");
140 my ($class, $scfg, $zvol, $size) = @_;
142 my $guid = $class->zfs_get_lu_name($scfg, $zvol);
144 $class->zfs_request($scfg, undef, 'modify_lu', "${size
}K
", $guid);
147 sub zfs_get_lun_number {
148 my ($class, $scfg, $guid) = @_;
150 die "could
not find lun_number
for guid
$guid" if !$guid;
152 return $class->zfs_request($scfg, undef, 'list_view', $guid);
163 content => [ {images => 1}, { images => 1 }],
170 description => "iscsi provider
",
173 # this will disable write caching on comstar and istgt.
174 # it is not implemented for iet. iet blockio always operates with
175 # writethrough caching when not in readonly mode
177 description => "disable
write caching on the target
",
181 description => "target group
for comstar views
",
185 description => "host group
for comstar views
",
193 nodes => { optional => 1 },
194 disable => { optional => 1 },
195 portal => { fixed => 1 },
196 target => { fixed => 1 },
197 pool => { fixed => 1 },
198 blocksize => { fixed => 1 },
199 iscsiprovider => { fixed => 1 },
200 nowritecache => { optional => 1 },
201 sparse => { optional => 1 },
202 comstar_hg => { optional => 1 },
203 comstar_tg => { optional => 1 },
204 content => { optional => 1 },
208 # Storage implementation
211 my ($class, $scfg, $volname) = @_;
213 my ($vtype, $name, $vmid) = $class->parse_volname($volname);
215 my $target = $scfg->{target};
216 my $portal = $scfg->{portal};
218 my $guid = $class->zfs_get_lu_name($scfg, $name);
219 my $lun = $class->zfs_get_lun_number($scfg, $guid);
221 my $path = "iscsi
://$portal/$target/$lun";
223 return ($path, $vmid, $vtype);
227 my ($class, $storeid, $scfg, $volname) = @_;
229 my $snap = '__base__';
231 my ($vtype, $name, $vmid, $basename, $basevmid, $isBase) =
232 $class->parse_volname($volname);
234 die "create_base
not possible with base image
\n" if $isBase;
237 $newname =~ s/^vm-/base-/;
239 my $newvolname = $basename ? "$basename/$newname" : "$newname";
241 $class->zfs_delete_lu($scfg, $name);
242 $class->zfs_request($scfg, undef, 'rename', "$scfg->{pool
}/$name", "$scfg->{pool}/$newname");
244 my $guid = $class->zfs_create_lu($scfg, $newname);
245 $class->zfs_add_lun_mapping_entry($scfg, $newname, $guid);
247 my $running = undef; #fixme : is create_base always offline ?
249 $class->volume_snapshot($scfg, $storeid, $newname, $snap, $running);
255 my ($class, $scfg, $storeid, $volname, $vmid, $snap) = @_;
257 my $name = $class->SUPER::clone_image($scfg, $storeid, $volname, $vmid, $snap);
259 my $guid = $class->zfs_create_lu($scfg, $name);
260 $class->zfs_add_lun_mapping_entry($scfg, $name, $guid);
266 my ($class, $storeid, $scfg, $vmid, $fmt, $name, $size) = @_;
268 die "unsupported format
'$fmt'" if $fmt ne 'raw';
270 die "illegal name
'$name' - sould be
'vm-$vmid-*'\n"
271 if $name && $name !~ m/^vm-$vmid-/;
275 $volname = $class->zfs_find_free_diskname($storeid, $scfg, $vmid) if !$volname;
277 $class->zfs_create_zvol($scfg, $volname, $size);
279 my $guid = $class->zfs_create_lu($scfg, $volname);
280 $class->zfs_add_lun_mapping_entry($scfg, $volname, $guid);
286 my ($class, $storeid, $scfg, $volname, $isBase) = @_;
288 my ($vtype, $name, $vmid) = $class->parse_volname($volname);
290 $class->zfs_delete_lu($scfg, $name);
292 eval { $class->zfs_delete_zvol($scfg, $name); };
294 my $guid = $class->zfs_create_lu($scfg, $name);
295 $class->zfs_add_lun_mapping_entry($scfg, $name, $guid);
303 my ($class, $scfg, $storeid, $volname, $size, $running) = @_;
305 my $new_size = $class->SUPER::volume_resize($scfg, $storeid, $volname, $size, $running);
307 $class->zfs_resize_lu($scfg, $volname, $new_size);
312 sub volume_snapshot_rollback {
313 my ($class, $scfg, $storeid, $volname, $snap) = @_;
315 $class->zfs_delete_lu($scfg, $volname);
317 $class->zfs_request($class, $scfg, undef, 'rollback', "$scfg->{pool
}/$volname\@$snap");
319 $class->zfs_import_lu($scfg, $volname);
321 $class->zfs_add_lun_mapping_entry($scfg, $volname);
324 sub volume_has_feature {
325 my ($class, $scfg, $feature, $storeid, $volname, $snapname, $running) = @_;
328 snapshot => { current => 1, snap => 1},
329 clone => { base => 1},
330 template => { current => 1},
331 copy => { base => 1, current => 1},
334 my ($vtype, $name, $vmid, $basename, $basevmid, $isBase) =
335 $class->parse_volname($volname);
342 $key = $isBase ? 'base' : 'current';
345 return 1 if $features->{$feature}->{$key};
350 sub activate_storage {
351 my ($class, $storeid, $scfg, $cache) = @_;