generated from oracle/template-repo
-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
targetcli: dump iscsi and vhost info as in targetcli
Orabug: 37301968 Signed-off-by: Richard Li <[email protected]>
- Loading branch information
Showing
2 changed files
with
299 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,292 @@ | ||
# Copyright (c) 2025, Oracle and/or its affiliates. | ||
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/ | ||
""" | ||
Helpers to retrieve iscsi target info and reconstruct targetcli structure on iscsi target server. | ||
Configuration could be found under /sys/kernel/config/target/ | ||
""" | ||
import argparse | ||
from typing import Iterable | ||
|
||
from drgn import FaultError | ||
from drgn import Object | ||
from drgn import Program | ||
from drgn.helpers.linux.list import hlist_for_each_entry | ||
from drgn.helpers.linux.list import list_for_each_entry | ||
|
||
from drgn_tools.corelens import CorelensModule | ||
from drgn_tools.module import ensure_debuginfo | ||
|
||
###################################### | ||
# iscsi | ||
###################################### | ||
|
||
|
||
def for_each_iqn(prog: Program) -> Iterable[Object]: | ||
""" | ||
List tiqn from g_tiqn_list | ||
:returns: Iterator of ``struct iscsi_tiqn *`` | ||
""" | ||
tiqn_list = prog["g_tiqn_list"] | ||
|
||
return list_for_each_entry( | ||
"struct iscsi_tiqn", tiqn_list.address_of_(), "tiqn_list" | ||
) | ||
|
||
|
||
def for_each_iscsi_tpg(tiqn: Object) -> Iterable[Object]: | ||
""" | ||
Get a list of tpg from tiqn | ||
:param tiqn: ``struct iscsi_tiqn *`` | ||
:returns: Iterator of ``struct iscsi_portal_group *`` | ||
""" | ||
return list_for_each_entry( | ||
"struct iscsi_portal_group", | ||
tiqn.tiqn_tpg_list.address_of_(), | ||
"tpg_list", | ||
) | ||
|
||
|
||
def print_iscsi_info(prog) -> None: | ||
"""Dump iscsi section info""" | ||
|
||
msg = ensure_debuginfo(prog, ["target_core_mod", "iscsi_target_mod"]) | ||
if msg: | ||
print(msg) | ||
return | ||
|
||
print("o- iscsi") | ||
indent = " " | ||
for tiqn in for_each_iqn(prog): | ||
print( | ||
"{}o- {} (struct iscsi_tiqn * {})".format( | ||
indent, | ||
get_tiqn_name(tiqn), | ||
hex(tiqn.value_()), | ||
) | ||
) | ||
|
||
for tpg in for_each_iscsi_tpg(tiqn): | ||
se_tpg = tpg.tpg_se_tpg | ||
print( | ||
"{}o- {} (struct se_portal_group {})".format( | ||
indent * 2, | ||
get_tpg_name(se_tpg), | ||
hex(se_tpg.address_of_()), | ||
) | ||
) | ||
print(f"{indent * 3}o- acls") | ||
for acl in list_for_each_entry( | ||
"struct se_node_acl", | ||
se_tpg.acl_node_list.address_of_(), | ||
"acl_list", | ||
): | ||
print( | ||
"{}o- {} (struct se_node_acl * {})".format( | ||
indent * 4, | ||
get_acl_name(acl), | ||
hex(acl), | ||
) | ||
) | ||
print(f"{indent * 4}o- mapped_luns") | ||
for se_dev in hlist_for_each_entry( | ||
"struct se_dev_entry", | ||
acl.lun_entry_hlist.address_of_(), | ||
"link", | ||
): | ||
print_lun_info(se_dev.se_lun, nr_indent=5) | ||
|
||
print(f"{indent * 3}o- luns") | ||
for lun in hlist_for_each_entry( | ||
"struct se_lun", | ||
se_tpg.tpg_lun_hlist.address_of_(), | ||
"link", | ||
): | ||
print_lun_info(lun, nr_indent=4) | ||
|
||
|
||
###################################### | ||
# vhost | ||
###################################### | ||
|
||
|
||
def for_each_vhost_tpg(prog) -> Iterable[Object]: | ||
""" | ||
List vhost_scsi_tpg from vhost_scsi_list | ||
:returns: Iterator of ``struct vhost_scsi_tpg *`` | ||
""" | ||
|
||
vhost_scsi_list = prog["vhost_scsi_list"] | ||
|
||
return list_for_each_entry( | ||
"struct vhost_scsi_tpg", vhost_scsi_list.address_of_(), "tv_tpg_list" | ||
) | ||
|
||
|
||
def print_vhost_info(prog) -> None: | ||
"""Dump vhost section info""" | ||
|
||
msg = ensure_debuginfo(prog, ["vhost", "vhost_scsi", "target_core_mod"]) | ||
if msg: | ||
print(msg) | ||
return | ||
|
||
print("o- vhost") | ||
for tpg in for_each_vhost_tpg(prog): | ||
indent = " " | ||
se_tpg = tpg.se_tpg | ||
print( | ||
"{}o- {} (struct se_portal_group {}) ({})".format( | ||
indent, | ||
get_tpg_name(se_tpg), | ||
hex(se_tpg.address_of_()), | ||
get_ci_name_from_cg(tpg.tport.tport_wwn.wwn_group), | ||
) | ||
) | ||
|
||
print(f"{indent * 2}o- acls") | ||
for acl in list_for_each_entry( | ||
"struct se_node_acl", | ||
se_tpg.acl_node_list.address_of_(), | ||
"acl_list", | ||
): | ||
acl_name = get_acl_name(acl) | ||
if not acl_name: | ||
continue | ||
|
||
print( | ||
"{}o- {} (struct se_node_acl * {})".format( | ||
indent * 3, | ||
acl_name, | ||
hex(acl), | ||
) | ||
) | ||
|
||
print(f"{indent * 3}o- mapped_luns") | ||
for se_dev in hlist_for_each_entry( | ||
"struct se_dev_entry", | ||
acl.lun_entry_hlist.address_of_(), | ||
"link", | ||
): | ||
print_lun_info(se_dev.se_lun, nr_indent=4) | ||
|
||
print(f"{indent * 2}o- luns") | ||
for lun in hlist_for_each_entry( | ||
"struct se_lun", se_tpg.tpg_lun_hlist.address_of_(), "link" | ||
): | ||
print_lun_info(lun, nr_indent=3) | ||
|
||
|
||
def print_lun_info(lun: Object, nr_indent: int = 1) -> None: | ||
""" | ||
Dump lun info | ||
:param lun: ``struct se_lun *`` | ||
:param nr_indent: int indicating numbers of indentations | ||
""" | ||
print( | ||
"{}o- {} (struct se_lun * {}) \n{}o- BACKSTORE: {} \n{}o- DEVICE: {}".format( | ||
" " * nr_indent, | ||
get_lun_name(lun), | ||
hex(lun), | ||
" " * (nr_indent + 1), | ||
get_backstore_name_from_lun(lun), | ||
" " * (nr_indent + 1), | ||
get_device_path_from_lun(lun), | ||
) | ||
) | ||
|
||
|
||
def get_ci_name_from_cg(cg: Object) -> str: | ||
""" | ||
Get ci_name given a config group | ||
:param cg: ``struct config_group *`` | ||
:returns: str | ||
""" | ||
try: | ||
return cg.cg_item.ci_name.string_().decode() | ||
except FaultError: | ||
return "" | ||
|
||
|
||
def get_backstore_name_from_lun(lun: Object) -> str: | ||
""" | ||
Get backstore name given a lun | ||
:param lun: ``struct se_lun *`` | ||
:returns: str | ||
""" | ||
return get_ci_name_from_cg(lun.lun_se_dev.dev_group) | ||
|
||
|
||
def get_tpg_name(tpg: Object) -> str: | ||
""" | ||
Get tpg name | ||
:param tpg: ``struct se_portal_group`` | ||
:returns: str | ||
""" | ||
return get_ci_name_from_cg(tpg.tpg_group) | ||
|
||
|
||
def get_acl_name(acl: Object) -> str: | ||
""" | ||
Get acl name. If the name is empty, it could mean the acl is not configured or potentially corrupted. | ||
:param acl: ``struct se_node_acl *`` | ||
:returns: str | ||
""" | ||
return get_ci_name_from_cg(acl.acl_group) | ||
|
||
|
||
def get_tiqn_name(tiqn: Object) -> str: | ||
""" | ||
Get tiqn name | ||
:param tiqn: ``struct iscsi_tiqn *`` | ||
:returns: str | ||
""" | ||
return tiqn.tiqn.string_().decode() | ||
|
||
|
||
def get_lun_name(lun: Object) -> str: | ||
""" | ||
Get lun name | ||
:param lun: ``struct se_lun *`` | ||
:returns: str | ||
""" | ||
return get_ci_name_from_cg(lun.lun_group) | ||
|
||
|
||
def get_device_path_from_lun(lun: Object) -> str: | ||
""" | ||
Get block backend device path given lun | ||
:param lun: ``struct se_lun *`` | ||
:returns: str | ||
""" | ||
return lun.lun_se_dev.udev_path.string_().decode() | ||
|
||
|
||
def dump_targetcli(prog) -> None: | ||
"""Dump targetcli structure""" | ||
|
||
print_iscsi_info(prog) | ||
print_vhost_info(prog) | ||
|
||
|
||
class TargetCli(CorelensModule): | ||
""" | ||
Dump targetcli structure on iscsi target | ||
""" | ||
|
||
name = "targetcli" | ||
skip_unless_have_kmod = ["target_core_mod"] | ||
|
||
def run(self, prog: Program, args: argparse.Namespace) -> None: | ||
dump_targetcli(prog) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# Copyright (c) 2025, Oracle and/or its affiliates. | ||
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/ | ||
from drgn_tools import targetcli | ||
|
||
|
||
def test_targetcli(prog): | ||
targetcli.dump_targetcli(prog) |