Skip to content

Commit 8d3aa9a

Browse files
committed
update iscsi.py module
- Add a new class to supporting iscsi with the multi targets. - Update the create_iSCSI function. Signed-off-by: Houqi (Nick) Zuo <hzuo@redhat.com>
1 parent 4ff7f3d commit 8d3aa9a

1 file changed

Lines changed: 172 additions & 1 deletion

File tree

virttest/iscsi.py

Lines changed: 172 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
from __future__ import division
1111

12+
import ast
1213
import logging
1314
import os
1415
import re
@@ -833,5 +834,175 @@ def create_iSCSI(params, root_dir=data_dir.get_tmp_dir()):
833834
)
834835
iscsi_instance = IscsiTGT(params, root_dir)
835836
else:
836-
iscsi_instance = IscsiLIO(params, root_dir)
837+
iscsi_instance = (
838+
MultiTargetsIscsiLIO(params, root_dir)
839+
if not params.get("target") and params.get("targets_luns")
840+
else IscsiLIO(params, root_dir)
841+
)
837842
return iscsi_instance
843+
844+
845+
class MultiTargetsIscsiLIO(IscsiLIO):
846+
"""
847+
Iscsi class supporting multi-targets for the LIO backend used in RHEL7.
848+
"""
849+
850+
def __init__(self, params, root_dir):
851+
"""
852+
Init the object based on the params and root_dir.
853+
Note: 'targets_luns' in params is introduced at this class.
854+
The structure of 'targets_luns':
855+
targets_luns =
856+
{
857+
${target01}: {
858+
${lun01} : {"emulated_image": ..., ...},
859+
${lun02} : {"emulated_image": ..., ...},
860+
},
861+
${target02}: {
862+
${lun01} : {"emulated_image": ..., ...},
863+
${lun02} : {"emulated_image": ..., ...},
864+
},
865+
...
866+
}
867+
If there's only one lun without any special assigned requests,
868+
lun should be set to "default_lun", for example:
869+
targets_luns = { ${target01}: { "default_lun": {...}}}
870+
871+
:param params: parameters dict for iSCSI
872+
:param root_dir: path for image
873+
"""
874+
self._targets_luns = ast.literal_eval(params.get("targets_luns"))
875+
# stores the iscsiLIO objects based on each targets
876+
self._targets_mapping = {}
877+
# param_in_lun = (
878+
# "emulated_image",
879+
# "image_size",
880+
# "iscsi_lun_attrs",
881+
# )
882+
for target in self._targets_luns.keys():
883+
single_target_param = params.copy()
884+
for lun in self._targets_luns[target].keys():
885+
single_target_param.update(self._targets_luns[target][lun])
886+
single_target_param["target"] = target
887+
single_target_param["iscsi_backend"] = "fileio"
888+
self._targets_mapping[target] = IscsiLIO(single_target_param, root_dir)
889+
if lun not in ("default_lun",):
890+
self._targets_mapping[target].luns = lun
891+
892+
def query_targets(self, emulated_image=None, lun=None):
893+
"""
894+
Dynamically filter the targets from image name given and lun given.
895+
896+
:param emulated_image: the image name. If none, do NOT check emulated_image
897+
:type emulated_image: string
898+
:param lun: the lun. If none, do NOT check lun
899+
:type lun: string
900+
901+
:return: the targets in list or []
902+
:rtype: list
903+
"""
904+
cmd = "targetcli ls /iscsi 1"
905+
target_info = process.run(cmd).stdout_text
906+
targets = re.findall(r"iqn[\.]\S+:\S+", target_info)
907+
908+
filtered_targets = []
909+
for target in targets:
910+
cmd = "targetcli ls /iscsi/%s/tpg1/luns" % target
911+
luns_info = process.run(cmd).stdout_text
912+
if (
913+
(not emulated_image and not lun)
914+
or (emulated_image and not lun and emulated_image + ")" in luns_info)
915+
or (
916+
emulated_image
917+
and lun
918+
and emulated_image + ")" in luns_info
919+
and " " + lun + " " in luns_info
920+
)
921+
):
922+
filtered_targets.append(target)
923+
return filtered_targets
924+
925+
def set_chap_auth_target(self, target=None):
926+
"""
927+
set up authentication information for every single initiator,
928+
which provides the capability to define common login information
929+
for all Endpoints in a TPG
930+
931+
:param target: the target.
932+
:type target: string
933+
"""
934+
for key in self._targets_mapping.keys():
935+
if not target or key == target:
936+
self._targets_mapping[key].set_chap_auth_target()
937+
938+
def export_target(self, target=None):
939+
"""
940+
Export target(s) in localhost for emulated iscsi.
941+
942+
:param target: the target.
943+
:type target: string
944+
"""
945+
for key in self._targets_mapping.keys():
946+
if not target or key == target:
947+
self._targets_mapping[key].export_target()
948+
949+
def delete_target(self, target=None):
950+
"""
951+
Delete target(s) from host.
952+
953+
:param target: the target.
954+
:type target: string
955+
"""
956+
for key in self._targets_mapping.keys():
957+
if not target or key == target:
958+
self._targets_mapping[key].delete_target()
959+
960+
def login(self, target=None):
961+
"""
962+
Login target.
963+
964+
:param target: the target.
965+
:type target: string
966+
"""
967+
if target:
968+
self._targets_mapping[target].login()
969+
else:
970+
LOG.error("The target can't be None!")
971+
972+
def cleanup(self, target=None, confirmed=False):
973+
"""
974+
Clean up env after iscsi used.
975+
976+
:param target: the target.
977+
:type target: string
978+
:param confirmed: switch for cleanup all iscsi config
979+
:type confirmed: bool
980+
"""
981+
for key in self._targets_mapping.keys():
982+
if not target or key == target:
983+
self._targets_mapping[key].cleanup(confirmed)
984+
985+
def logout(self, target=None):
986+
"""
987+
Logout from target.
988+
989+
:param target: the target.
990+
:type target: string
991+
"""
992+
if self._targets_mapping[target].logged_in():
993+
iscsi_logout(self.target)
994+
995+
def logged_in(self, target=None):
996+
"""
997+
Check if the session is login or not.
998+
999+
:param target: the target.
1000+
:type target: string
1001+
1002+
:return: logged in or not
1003+
:rtype: bool
1004+
"""
1005+
if target:
1006+
return self._targets_mapping[target].logged_in()
1007+
else:
1008+
LOG.error("The target can't be None!")

0 commit comments

Comments
 (0)