| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- package PVE::Storage::Custom::scstZFSPlugin;
- eval {
- require 'PVE/Storage/Custom/Shared/ZFSPluginPlus.pm';
- };
- use PVE::Storage::Custom::LunCmd::SCST;
- use Data::Dumper;
- use PVE::Tools qw(run_command);
- # inherit on the ZFSPlugin
- #use base qw(PVE::Storage::ZFSPlugin);
- @ISA = qw(PVE::Storage::Custom::Shared::ZFSPluginPlus);
- my @ssh_opts = ('-o', 'BatchMode=yes');
- my @ssh_cmd = ('/usr/bin/ssh', @ssh_opts);
- my $id_rsa_path = '/etc/pve/priv/zfs';
- # plugin configuration
- sub api {
- return 1;
- }
- sub type {
- return 'scstzfs';
- }
- sub plugindata {
- return {
- content => [ { images => 1 }, {images => 1} ]
- };
- }
- sub properties {
- return {
- nowritecache_scst => {
- description => "disable write cache on the target",
- type => 'boolean'
- },
- chap_user => {
- type => 'string'
- },
- chap_pass => {
- type => 'string'
- },
- volume_prefix => {
- type => 'string'
- },
- port => {
- type => 'int'
- },
- ini_group => {
- type => 'string'
- },
- esos => {
- type => 'int'
- }
- }
- }
- sub options {
- return {
- nodes => { optional => 1 },
- disable => { optional => 1 },
- portal => { fixed => 1 },
- target => { fixed => 1 },
- iscsiprovider => {fixed => 1},
- pool => { fixed => 1 },
- blocksize => { fixed => 1 },
- nowritecache => { optional => 1 },
- sparse => { optional => 1 },
- comstar_hg => { optional => 1 },
- comstar_tg => { optional => 1 },
- content => { optional => 1 },
- shared => { fixed => 1 },
- transport => { optional => 1, default => 'iscsi' }, #iscsi or rdma
- chap_user => { optional => 1 },
- chap_pass => { optional => 1 },
- port => { optional => 1 },
- volume_prefix => { optional => 1, default => '' }, #prefixes created volume-names - allows to share pool for multiple clusters
- ini_group => { optional => 1, default => ''},
- esos => { optional=>1, default => 0 }
- };
- }
- my $lun_cmds = {
- create_lu => 1,
- delete_lu => 1,
- import_lu => 1,
- modify_lu => 1,
- add_view => 1,
- list_view => 1,
- list_lu => 1,
- };
- # SCST-specifics
- my $zfs_get_base = sub {
- my ($scfg) = @_;
- return PVE::Storage::Custom::LunCmd::SCST::get_base;
- };
- sub zfs_get_base {
- my ($scfg) = @_;
- return $zfs_get_base->($scfg);
- }
- sub zfs_request {
- my ($class, $scfg, $timeout, $method, @params) = @_;
- $timeout = PVE::RPCEnvironment::is_worker() ? 60*60 : 10
- if !$timeout;
- my $msg = '';
- if ($lun_cmds->{$method}) {
- $msg = PVE::Storage::Custom::LunCmd::SCST::run_lun_command($scfg, $timeout, $method, @params);
- } else {
- my $target = 'root@' . $scfg->{portal};
- my $cmd = [@ssh_cmd, '-i', "$id_rsa_path/$scfg->{portal}_id_rsa", $target];
- if ($method eq 'zpool_list') {
- push @$cmd, 'zpool', 'list';
- } else {
- push @$cmd, 'zfs', $method;
- }
- push @$cmd, @params;
- my $output = sub {
- my $line = shift;
- $msg .= "$line\n";
- };
- # print Dumper($cmd);
- run_command($cmd, outfunc => $output, timeout => $timeout);
- }
- return $msg;
- }
- # we want to allow copy of snap, currently dies at line 377 in ZFSPlugin.pm
- sub volume_has_feature {
- my ($class, $scfg, $feature, $storeid, $volname, $snapname, $running) = @_;
- my $features = {
- snapshot => { current => 1, snap => 1},
- clone => { base => 1},
- template => { current => 1},
- copy => { base => 1, current => 1, snap=>1}, #added snap
- };
- my ($vtype, $name, $vmid, $basename, $basevmid, $isBase) =
- $class->parse_volname($volname);
- my $key = undef;
- if ($snapname) {
- $key = 'snap';
- } else {
- $key = $isBase ? 'base' : 'current';
- }
- return 1 if $features->{$feature}->{$key};
- return undef;
- }
- #
- # + added port, chap-auth and transport (iser)
- # + allow access to materialized snapshots
- sub path {
- my ($class, $scfg, $volname, $storeid, $snapname) = @_;
- # die "direct access to snapshots not implemented"
- # if defined($snapname);
- my ($vtype, $name, $vmid) = $class->parse_volname($volname);
- if(defined($snapname)) {
- $name = $class->materialize_snapshot($scfg,$volname,$snapname);
- }
- my $target = $scfg->{target};
- my $portal = $scfg->{portal};
- my $guid = $class->zfs_get_lu_name($scfg, $name);
- my $lun = $class->zfs_get_lun_number($scfg, $guid);
- my $transport = $scfg->{transport};
- if($transport eq 'rdma') {
- $transport = 'iser';
- } else {
- $transport = 'iscsi';
- }
- my $authString = $scfg->{chap_user} && $scfg->{chap_pass} ? "$scfg->{chap_user}%$scfg->{chap_pass}@" : '';
- my $port = $scfg->{port} ? ":$scfg->{port}" : ':3260'; #qemu-image insists on port !
- my $path = "$transport://$authString$portal$port/$target/$lun";
- return ($path, $vmid, $vtype);
- }
- # Other parts of Storage implementation is identical to ZFSPlugin and therefore not changed
- 1;
|