return $config;
};
+# Return settings of a specific target
+my $get_target_settings = sub {
+ my ($scfg) = @_;
+
+ my $id = "$scfg->{portal}.$scfg->{target}";
+ return undef if !$SETTINGS;
+ return $SETTINGS->{$id};
+};
+
# fetches and parses targetcli config from the portal
my $parser = sub {
my ($scfg) = @_;
my $jsonconfig = JSON->new->utf8->decode($config);
my $haveTarget = 0;
- foreach my $oneTarget (@{$jsonconfig->{targets}}) {
+ foreach my $target (@{$jsonconfig->{targets}}) {
# only interested in iSCSI targets
- if ($oneTarget->{fabric} eq 'iscsi' && $oneTarget->{wwn} eq $scfg->{target}) {
- # find correct TPG
- foreach my $oneTpg (@{$oneTarget->{tpgs}}) {
- if ($oneTpg->{tag} == $tpg_tag) {
- $SETTINGS->{target} = $oneTpg;
- $haveTarget = 1;
- last;
+ next if !($target->{fabric} eq 'iscsi' && $target->{wwn} eq $scfg->{target});
+ # find correct TPG
+ foreach my $tpg (@{$target->{tpgs}}) {
+ if ($tpg->{tag} == $tpg_tag) {
+ my $res = [];
+ foreach my $lun (@{$tpg->{luns}}) {
+ my ($idx, $storage_object);
+ if ($lun->{index} =~ /^(\d+)$/) {
+ $idx = $1;
+ }
+ if ($lun->{storage_object} =~ m|^($BACKSTORE/.*)$|) {
+ $storage_object = $1;
+ }
+ die "Invalid lun definition in config!\n"
+ if !(defined($idx) && defined($storage_object));
+ push @$res, { index => $idx, storage_object => $storage_object };
}
+
+ my $id = "$scfg->{portal}.$scfg->{target}";
+ $SETTINGS->{$id}->{luns} = $res;
+ $haveTarget = 1;
+ last;
}
}
}
}
};
+# Get prefix for backstores
+my $get_backstore_prefix = sub {
+ my ($scfg) = @_;
+ my $pool = $scfg->{pool};
+ $pool =~ s/\//-/g;
+ return $pool . '-';
+};
+
# removes the given lu_name from the local list of luns
my $free_lu_name = sub {
- my ($lu_name) = @_;
- my $new;
+ my ($scfg, $lu_name) = @_;
- foreach my $lun (@{$SETTINGS->{target}->{luns}}) {
+ my $new = [];
+ my $target = $get_target_settings->($scfg);
+ foreach my $lun (@{$target->{luns}}) {
if ($lun->{storage_object} ne "$BACKSTORE/$lu_name") {
push @$new, $lun;
}
}
- $SETTINGS->{target}->{luns} = $new;
+ $target->{luns} = $new;
};
# locally registers a new lun
storage_object => "$BACKSTORE/$volname",
is_new => 1,
};
- push @{$SETTINGS->{target}->{luns}}, $conf;
+ my $target = $get_target_settings->($scfg);
+ push @{$target->{luns}}, $conf;
return $conf;
};
my $base = get_base;
if ($lunpath =~ /^$base\/$scfg->{pool}\/([\w\-]+)$/) {
$volname = $1;
+ my $prefix = $get_backstore_prefix->($scfg);
+ my $target = $get_target_settings->($scfg);
+ foreach my $lun (@{$target->{luns}}) {
+ # If we have a lun with the pool prefix matching this vol, then return this one
+ # like pool-pve-vm-100-disk-0
+ # Else, just fallback to the old name scheme which is vm-100-disk-0
+ if ($lun->{storage_object} =~ /^$BACKSTORE\/($prefix$volname)$/) {
+ return $1;
+ }
+ }
}
return $volname;
my $lun = undef;
my $object = $params[0];
- my $volname = $extract_volname->($scfg, $params[0]);
+ my $volname = $extract_volname->($scfg, $object);
+ my $target = $get_target_settings->($scfg);
- foreach my $lun (@{$SETTINGS->{target}->{luns}}) {
+ return undef if !defined($volname); # nothing to search for..
+
+ foreach my $lun (@{$target->{luns}}) {
if ($lun->{storage_object} eq "$BACKSTORE/$volname") {
return $lun->{index};
}
my $name = undef;
my $object = $params[0];
- my $volname = $extract_volname->($scfg, $params[0]);
+ my $volname = $extract_volname->($scfg, $object);
+ my $target = $get_target_settings->($scfg);
- foreach my $lun (@{$SETTINGS->{target}->{luns}}) {
+ foreach my $lun (@{$target->{luns}}) {
if ($lun->{storage_object} eq "$BACKSTORE/$volname") {
return $object;
}
my $device = $params[0];
my $volname = $extract_volname->($scfg, $device);
+ # Here we create a new device, so we didn't get the volname prefixed with the pool name
+ # as extract_volname couldn't find a matching vol yet
+ $volname = $get_backstore_prefix->($scfg) . $volname;
my $tpg = $scfg->{lio_tpg} || die "Target Portal Group not set, aborting!\n";
# step 1: create backstore for device
my $res = $execute_remote_command->($scfg, $timeout, $targetcli, @cliparams);
die $res->{msg} if !$res->{result};
- # step 2: register lun with target
+ # step 2: enable unmap support on the backstore
+ @cliparams = ($BACKSTORE . '/' . $volname, 'set', 'attribute', 'emulate_tpu=1' );
+ $res = $execute_remote_command->($scfg, $timeout, $targetcli, @cliparams);
+ die $res->{msg} if !$res->{result};
+
+ # step 3: register lun with target
# targetcli /iscsi/iqn.2018-04.at.bestsolution.somehost:target/tpg1/luns/ create /backstores/block/foobar
@cliparams = ("/iscsi/$scfg->{target}/$tpg/luns/", 'create', "$BACKSTORE/$volname" );
$res = $execute_remote_command->($scfg, $timeout, $targetcli, @cliparams);
my $tpg = $scfg->{lio_tpg} || die "Target Portal Group not set, aborting!\n";
my $path = $params[0];
- my $volname = $extract_volname->($scfg, $params[0]);
-
- foreach my $lun (@{$SETTINGS->{target}->{luns}}) {
- if ($lun->{storage_object} eq "$BACKSTORE/$volname") {
- # step 1: delete the lun
- my @cliparams = ("/iscsi/$scfg->{target}/$tpg/luns/", 'delete', "lun$lun->{index}" );
- my $res = $execute_remote_command->($scfg, $timeout, $targetcli, @cliparams);
- do {
- die $res->{msg};
- } unless $res->{result};
-
- # step 2: delete the backstore
- @cliparams = ($BACKSTORE, 'delete', $volname);
- $res = $execute_remote_command->($scfg, $timeout, $targetcli, @cliparams);
- do {
- die $res->{msg};
- } unless $res->{result};
-
- # step 3: save to be safe ...
- $execute_remote_command->($scfg, $timeout, $targetcli, 'saveconfig');
-
- # update interal cache
- $free_lu_name->($volname);
-
- last;
- }
+ my $volname = $extract_volname->($scfg, $path);
+ my $target = $get_target_settings->($scfg);
+
+ foreach my $lun (@{$target->{luns}}) {
+ next if $lun->{storage_object} ne "$BACKSTORE/$volname";
+
+ # step 1: delete the lun
+ my @cliparams = ("/iscsi/$scfg->{target}/$tpg/luns/", 'delete', "lun$lun->{index}" );
+ my $res = $execute_remote_command->($scfg, $timeout, $targetcli, @cliparams);
+ do {
+ die $res->{msg};
+ } unless $res->{result};
+
+ # step 2: delete the backstore
+ @cliparams = ($BACKSTORE, 'delete', $volname);
+ $res = $execute_remote_command->($scfg, $timeout, $targetcli, @cliparams);
+ do {
+ die $res->{msg};
+ } unless $res->{result};
+
+ # step 3: save to be safe ...
+ $execute_remote_command->($scfg, $timeout, $targetcli, 'saveconfig');
+
+ # update interal cache
+ $free_lu_name->($scfg, $volname);
+
+ last;
}
return $res->{msg};
# needed for example when the underlying ZFS volume has been resized
my $modify_lun = sub {
my ($scfg, $timeout, $method, @params) = @_;
- my $msg;
-
- $msg = $delete_lun->($scfg, $timeout, $method, @params);
- if ($msg) {
- $msg = $create_lun->($scfg, $timeout, $method, @params);
- }
-
- return $msg;
+ # Nothing to do on volume modification for LIO
+ return undef;
};
my $add_view = sub {
sub run_lun_command {
my ($scfg, $timeout, $method, @params) = @_;
- # fetch configuration from target if we haven't yet
- # or if our configuration is stale
+ # fetch configuration from target if we haven't yet or if it is stale
my $timediff = time - $SETTINGS_TIMESTAMP;
- if (!$SETTINGS || $timediff > $SETTINGS_MAXAGE) {
+ my $target = $get_target_settings->($scfg);
+ if (!$target || $timediff > $SETTINGS_MAXAGE) {
$SETTINGS_TIMESTAMP = time;
$parser->($scfg);
}