xref: /spdk/python/spdk/spdkcli/ui_node_iscsi.py (revision 588dfe314bb83d86effdf67ec42837b11c2620bf)
1*588dfe31SMichal Berger#  SPDX-License-Identifier: BSD-3-Clause
2*588dfe31SMichal Berger#  Copyright (C) 2018 Intel Corporation.
3*588dfe31SMichal Berger#  All rights reserved.
4*588dfe31SMichal Berger
57610bc38SKonrad Sztyberfrom configshell_fb import ExecutionError
67610bc38SKonrad Sztyberfrom ..rpc.client import JSONRPCException
77610bc38SKonrad Sztyberfrom .ui_node import UINode
87610bc38SKonrad Sztyber
97610bc38SKonrad Sztyber
107610bc38SKonrad Sztyberclass UIISCSI(UINode):
117610bc38SKonrad Sztyber    def __init__(self, parent):
127610bc38SKonrad Sztyber        UINode.__init__(self, "iscsi", parent)
137610bc38SKonrad Sztyber        self.refresh()
147610bc38SKonrad Sztyber
157610bc38SKonrad Sztyber    def refresh(self):
167610bc38SKonrad Sztyber        self._children = set([])
177610bc38SKonrad Sztyber        UIISCSIDevices(self)
187610bc38SKonrad Sztyber        UIPortalGroups(self)
197610bc38SKonrad Sztyber        UIInitiatorGroups(self)
207610bc38SKonrad Sztyber        UIISCSIConnections(self)
217610bc38SKonrad Sztyber        UIISCSIAuthGroups(self)
227610bc38SKonrad Sztyber        UIISCSIGlobalParams(self)
237610bc38SKonrad Sztyber
247610bc38SKonrad Sztyber
257610bc38SKonrad Sztyberclass UIISCSIGlobalParams(UINode):
267610bc38SKonrad Sztyber    def __init__(self, parent):
277610bc38SKonrad Sztyber        UINode.__init__(self, "global_params", parent)
287610bc38SKonrad Sztyber        self.refresh()
297610bc38SKonrad Sztyber
307610bc38SKonrad Sztyber    def refresh(self):
317610bc38SKonrad Sztyber        self._children = set([])
327610bc38SKonrad Sztyber        iscsi_global_params = self.get_root().iscsi_get_options()
337610bc38SKonrad Sztyber        if not iscsi_global_params:
347610bc38SKonrad Sztyber            return
357610bc38SKonrad Sztyber        for param, val in iscsi_global_params.items():
367610bc38SKonrad Sztyber            UIISCSIGlobalParam("%s: %s" % (param, val), self)
377610bc38SKonrad Sztyber
387610bc38SKonrad Sztyber    def ui_command_set_auth(self, g=None, d=None, r=None, m=None):
397610bc38SKonrad Sztyber        """Set CHAP authentication for discovery service.
407610bc38SKonrad Sztyber
417610bc38SKonrad Sztyber        Optional arguments:
427610bc38SKonrad Sztyber            g = chap_group: Authentication group ID for discovery session
437610bc38SKonrad Sztyber            d = disable_chap: CHAP for discovery session should be disabled
447610bc38SKonrad Sztyber            r = require_chap: CHAP for discovery session should be required
457610bc38SKonrad Sztyber            m = mutual_chap: CHAP for discovery session should be mutual
467610bc38SKonrad Sztyber        """
477610bc38SKonrad Sztyber        chap_group = self.ui_eval_param(g, "number", None)
487610bc38SKonrad Sztyber        disable_chap = self.ui_eval_param(d, "bool", None)
497610bc38SKonrad Sztyber        require_chap = self.ui_eval_param(r, "bool", None)
507610bc38SKonrad Sztyber        mutual_chap = self.ui_eval_param(m, "bool", None)
517610bc38SKonrad Sztyber        self.get_root().iscsi_set_discovery_auth(
527610bc38SKonrad Sztyber            chap_group=chap_group, disable_chap=disable_chap,
537610bc38SKonrad Sztyber            require_chap=require_chap, mutual_chap=mutual_chap)
547610bc38SKonrad Sztyber
557610bc38SKonrad Sztyber
567610bc38SKonrad Sztyberclass UIISCSIGlobalParam(UINode):
577610bc38SKonrad Sztyber    def __init__(self, param, parent):
587610bc38SKonrad Sztyber        UINode.__init__(self, param, parent)
597610bc38SKonrad Sztyber
607610bc38SKonrad Sztyber
617610bc38SKonrad Sztyberclass UIISCSIDevices(UINode):
627610bc38SKonrad Sztyber    def __init__(self, parent):
637610bc38SKonrad Sztyber        UINode.__init__(self, "target_nodes", parent)
647610bc38SKonrad Sztyber        self.scsi_devices = list()
657610bc38SKonrad Sztyber        self.refresh()
667610bc38SKonrad Sztyber
677610bc38SKonrad Sztyber    def refresh(self):
687610bc38SKonrad Sztyber        self._children = set([])
697610bc38SKonrad Sztyber        self.target_nodes = list(self.get_root().iscsi_get_target_nodes())
707610bc38SKonrad Sztyber        self.scsi_devices = list(self.get_root().scsi_get_devices())
717610bc38SKonrad Sztyber        for device in self.scsi_devices:
727610bc38SKonrad Sztyber            for node in self.target_nodes:
737610bc38SKonrad Sztyber                if hasattr(device, "device_name") and node['name'] \
747610bc38SKonrad Sztyber                        == device.device_name:
757610bc38SKonrad Sztyber                    UIISCSIDevice(device, node, self)
767610bc38SKonrad Sztyber
777610bc38SKonrad Sztyber    def delete(self, name):
787610bc38SKonrad Sztyber        self.get_root().iscsi_delete_target_node(target_node_name=name)
797610bc38SKonrad Sztyber
807610bc38SKonrad Sztyber    def ui_command_create(self, name, alias_name, bdev_name_id_pairs,
817610bc38SKonrad Sztyber                          pg_ig_mappings, queue_depth, g=None, d=None, r=None,
827610bc38SKonrad Sztyber                          m=None, h=None, t=None):
837610bc38SKonrad Sztyber        """Create target node
847610bc38SKonrad Sztyber
857610bc38SKonrad Sztyber        Positional args:
867610bc38SKonrad Sztyber           name: Target node name (ASCII)
877610bc38SKonrad Sztyber           alias_name: Target node alias name (ASCII)
887610bc38SKonrad Sztyber           bdev_name_id_pairs: List of bdev_name_id_pairs
897610bc38SKonrad Sztyber           pg_ig_mappings: List of pg_ig_mappings
907610bc38SKonrad Sztyber           queue_depth: Desired target queue depth
917610bc38SKonrad Sztyber        Optional args:
927610bc38SKonrad Sztyber           g = chap_group: Authentication group ID for this target node
937610bc38SKonrad Sztyber           d = disable_chap: CHAP authentication should be disabled for this target node
947610bc38SKonrad Sztyber           r = require_chap: CHAP authentication should be required for this target node
957610bc38SKonrad Sztyber           m = mutual_chap: CHAP authentication should be mutual/bidirectional
967610bc38SKonrad Sztyber           h = header_digest: Header Digest should be required for this target node
977610bc38SKonrad Sztyber           t = data_digest: Data Digest should be required for this target node
987610bc38SKonrad Sztyber        """
997610bc38SKonrad Sztyber        luns = []
1007610bc38SKonrad Sztyber        print("bdev_name_id_pairs: %s" % bdev_name_id_pairs)
1017610bc38SKonrad Sztyber        print("pg_ig_mappings: %s" % pg_ig_mappings)
1027610bc38SKonrad Sztyber        for u in bdev_name_id_pairs.strip().split(" "):
1037610bc38SKonrad Sztyber            bdev_name, lun_id = u.split(":")
1047610bc38SKonrad Sztyber            luns.append({"bdev_name": bdev_name, "lun_id": int(lun_id)})
1057610bc38SKonrad Sztyber        pg_ig_maps = []
1067610bc38SKonrad Sztyber        for u in pg_ig_mappings.strip().split(" "):
1077610bc38SKonrad Sztyber            pg, ig = u.split(":")
1087610bc38SKonrad Sztyber            pg_ig_maps.append({"pg_tag": int(pg), "ig_tag": int(ig)})
1097610bc38SKonrad Sztyber        queue_depth = self.ui_eval_param(queue_depth, "number", None)
1107610bc38SKonrad Sztyber        chap_group = self.ui_eval_param(g, "number", None)
1117610bc38SKonrad Sztyber        disable_chap = self.ui_eval_param(d, "bool", None)
1127610bc38SKonrad Sztyber        require_chap = self.ui_eval_param(r, "bool", None)
1137610bc38SKonrad Sztyber        mutual_chap = self.ui_eval_param(m, "bool", None)
1147610bc38SKonrad Sztyber        header_digest = self.ui_eval_param(h, "bool", None)
1157610bc38SKonrad Sztyber        data_digest = self.ui_eval_param(t, "bool", None)
1167610bc38SKonrad Sztyber        self.get_root().iscsi_create_target_node(
1177610bc38SKonrad Sztyber            name=name, alias_name=alias_name, luns=luns,
1187610bc38SKonrad Sztyber            pg_ig_maps=pg_ig_maps, queue_depth=queue_depth,
1197610bc38SKonrad Sztyber            chap_group=chap_group, disable_chap=disable_chap,
1207610bc38SKonrad Sztyber            require_chap=require_chap, mutual_chap=mutual_chap,
1217610bc38SKonrad Sztyber            header_digest=header_digest, data_digest=data_digest)
1227610bc38SKonrad Sztyber
1237610bc38SKonrad Sztyber    def ui_command_delete(self, name=None):
1247610bc38SKonrad Sztyber        """Delete a target node. If name is not specified delete all target nodes.
1257610bc38SKonrad Sztyber
1267610bc38SKonrad Sztyber        Arguments:
1277610bc38SKonrad Sztyber           name - Target node name.
1287610bc38SKonrad Sztyber        """
1297610bc38SKonrad Sztyber        self.delete(name)
1307610bc38SKonrad Sztyber
1317610bc38SKonrad Sztyber    def ui_command_delete_all(self):
1327610bc38SKonrad Sztyber        """Delete all target nodes"""
1337610bc38SKonrad Sztyber        rpc_messages = ""
1347610bc38SKonrad Sztyber        for device in self.scsi_devices:
1357610bc38SKonrad Sztyber            try:
1367610bc38SKonrad Sztyber                self.delete(device.device_name)
1377610bc38SKonrad Sztyber            except JSONRPCException as e:
1387610bc38SKonrad Sztyber                rpc_messages += e.message
1397610bc38SKonrad Sztyber        if rpc_messages:
1407610bc38SKonrad Sztyber            raise JSONRPCException(rpc_messages)
1417610bc38SKonrad Sztyber
1427610bc38SKonrad Sztyber    def ui_command_add_lun(self, name, bdev_name, lun_id=None):
1437610bc38SKonrad Sztyber        """Add lun to the target node.
1447610bc38SKonrad Sztyber
1457610bc38SKonrad Sztyber        Required args:
1467610bc38SKonrad Sztyber           name: Target node name (ASCII)
1477610bc38SKonrad Sztyber           bdev_name: bdev name
1487610bc38SKonrad Sztyber        Positional args:
1497610bc38SKonrad Sztyber           lun_id: LUN ID (integer >= 0)
1507610bc38SKonrad Sztyber        """
1517610bc38SKonrad Sztyber        if lun_id:
1527610bc38SKonrad Sztyber            lun_id = self.ui_eval_param(lun_id, "number", None)
1537610bc38SKonrad Sztyber        self.get_root().iscsi_target_node_add_lun(
1547610bc38SKonrad Sztyber            name=name, bdev_name=bdev_name, lun_id=lun_id)
1557610bc38SKonrad Sztyber
1567610bc38SKonrad Sztyber    def summary(self):
1577610bc38SKonrad Sztyber        count = 0
1587610bc38SKonrad Sztyber        for device in self.scsi_devices:
1597610bc38SKonrad Sztyber            for node in self.target_nodes:
1607610bc38SKonrad Sztyber                if hasattr(device, "device_name") and node['name'] \
1617610bc38SKonrad Sztyber                        == device.device_name:
1627610bc38SKonrad Sztyber                    count = count + 1
1637610bc38SKonrad Sztyber        return "Target nodes: %d" % count, None
1647610bc38SKonrad Sztyber
1657610bc38SKonrad Sztyber
1667610bc38SKonrad Sztyberclass UIISCSIDevice(UINode):
1677610bc38SKonrad Sztyber    def __init__(self, device, target, parent):
1687610bc38SKonrad Sztyber        UINode.__init__(self, device.device_name, parent)
1697610bc38SKonrad Sztyber        self.device = device
1707610bc38SKonrad Sztyber        self.target = target
1717610bc38SKonrad Sztyber        self.refresh()
1727610bc38SKonrad Sztyber
1737610bc38SKonrad Sztyber    def ui_command_set_auth(self, g=None, d=None, r=None, m=None):
1747610bc38SKonrad Sztyber        """Set CHAP authentication for the target node.
1757610bc38SKonrad Sztyber
1767610bc38SKonrad Sztyber        Optionals args:
1777610bc38SKonrad Sztyber           g = chap_group: Authentication group ID for this target node
1787610bc38SKonrad Sztyber           d = disable_chap: CHAP authentication should be disabled for this target node
1797610bc38SKonrad Sztyber           r = require_chap: CHAP authentication should be required for this target node
1807610bc38SKonrad Sztyber           m = mutual_chap: CHAP authentication should be mutual/bidirectional
1817610bc38SKonrad Sztyber        """
1827610bc38SKonrad Sztyber        chap_group = self.ui_eval_param(g, "number", None)
1837610bc38SKonrad Sztyber        disable_chap = self.ui_eval_param(d, "bool", None)
1847610bc38SKonrad Sztyber        require_chap = self.ui_eval_param(r, "bool", None)
1857610bc38SKonrad Sztyber        mutual_chap = self.ui_eval_param(m, "bool", None)
1867610bc38SKonrad Sztyber        self.get_root().iscsi_target_node_set_auth(
1877610bc38SKonrad Sztyber            name=self.device.device_name, chap_group=chap_group,
1887610bc38SKonrad Sztyber            disable_chap=disable_chap,
1897610bc38SKonrad Sztyber            require_chap=require_chap, mutual_chap=mutual_chap)
1907610bc38SKonrad Sztyber
1917610bc38SKonrad Sztyber    def ui_command_iscsi_target_node_add_pg_ig_maps(self, pg_ig_mappings):
1927610bc38SKonrad Sztyber        """Add PG-IG maps to the target node.
1937610bc38SKonrad Sztyber
1947610bc38SKonrad Sztyber        Args:
1957610bc38SKonrad Sztyber           pg_ig_maps: List of pg_ig_mappings, e.g. pg_tag:ig_tag pg_tag2:ig_tag2
1967610bc38SKonrad Sztyber        """
1977610bc38SKonrad Sztyber        pg_ig_maps = []
1987610bc38SKonrad Sztyber        for u in pg_ig_mappings.strip().split(" "):
1997610bc38SKonrad Sztyber            pg, ig = u.split(":")
2007610bc38SKonrad Sztyber            pg_ig_maps.append({"pg_tag": int(pg), "ig_tag": int(ig)})
2017610bc38SKonrad Sztyber        self.get_root().iscsi_target_node_add_pg_ig_maps(
2027610bc38SKonrad Sztyber            pg_ig_maps=pg_ig_maps, name=self.device.device_name)
2037610bc38SKonrad Sztyber
2047610bc38SKonrad Sztyber    def ui_command_iscsi_target_node_remove_pg_ig_maps(self, pg_ig_mappings):
2057610bc38SKonrad Sztyber        """Remove PG-IG maps from the target node.
2067610bc38SKonrad Sztyber
2077610bc38SKonrad Sztyber        Args:
2087610bc38SKonrad Sztyber           pg_ig_maps: List of pg_ig_mappings, e.g. pg_tag:ig_tag pg_tag2:ig_tag2
2097610bc38SKonrad Sztyber        """
2107610bc38SKonrad Sztyber        pg_ig_maps = []
2117610bc38SKonrad Sztyber        for u in pg_ig_mappings.strip().split(" "):
2127610bc38SKonrad Sztyber            pg, ig = u.split(":")
2137610bc38SKonrad Sztyber            pg_ig_maps.append({"pg_tag": int(pg), "ig_tag": int(ig)})
2147610bc38SKonrad Sztyber        self.get_root().iscsi_target_node_remove_pg_ig_maps(
2157610bc38SKonrad Sztyber            pg_ig_maps=pg_ig_maps, name=self.device.device_name)
2167610bc38SKonrad Sztyber
2177610bc38SKonrad Sztyber    def refresh(self):
2187610bc38SKonrad Sztyber        self._children = set([])
2197610bc38SKonrad Sztyber        UIISCSILuns(self.target['luns'], self)
2207610bc38SKonrad Sztyber        UIISCSIPgIgMaps(self.target['pg_ig_maps'], self)
2217610bc38SKonrad Sztyber        auths = {"disable_chap": self.target["disable_chap"],
2227610bc38SKonrad Sztyber                 "require_chap": self.target["require_chap"],
2237610bc38SKonrad Sztyber                 "mutual_chap": self.target["mutual_chap"],
2247610bc38SKonrad Sztyber                 "chap_group": self.target["chap_group"],
2257610bc38SKonrad Sztyber                 "data_digest": self.target["data_digest"]}
2267610bc38SKonrad Sztyber        UIISCSIAuth(auths, self)
2277610bc38SKonrad Sztyber
2287610bc38SKonrad Sztyber    def summary(self):
2297610bc38SKonrad Sztyber        return "Id: %s, QueueDepth: %s" % (self.device.id,
2307610bc38SKonrad Sztyber                                           self.target['queue_depth']), None
2317610bc38SKonrad Sztyber
2327610bc38SKonrad Sztyber
2337610bc38SKonrad Sztyberclass UIISCSIAuth(UINode):
2347610bc38SKonrad Sztyber    def __init__(self, auths, parent):
2357610bc38SKonrad Sztyber        UINode.__init__(self, "auths", parent)
2367610bc38SKonrad Sztyber        self.auths = auths
2377610bc38SKonrad Sztyber        self.refresh()
2387610bc38SKonrad Sztyber
2397610bc38SKonrad Sztyber    def summary(self):
2407610bc38SKonrad Sztyber        return "disable_chap: %s, require_chap: %s, mutual_chap: %s, chap_group: %s" % (
2417610bc38SKonrad Sztyber            self.auths['disable_chap'], self.auths['require_chap'],
2427610bc38SKonrad Sztyber            self.auths['mutual_chap'], self.auths['chap_group']), None
2437610bc38SKonrad Sztyber
2447610bc38SKonrad Sztyber
2457610bc38SKonrad Sztyberclass UIISCSILuns(UINode):
2467610bc38SKonrad Sztyber    def __init__(self, luns, parent):
2477610bc38SKonrad Sztyber        UINode.__init__(self, "luns", parent)
2487610bc38SKonrad Sztyber        self.luns = luns
2497610bc38SKonrad Sztyber        self.refresh()
2507610bc38SKonrad Sztyber
2517610bc38SKonrad Sztyber    def refresh(self):
2527610bc38SKonrad Sztyber        self._children = set([])
2537610bc38SKonrad Sztyber        for lun in self.luns:
2547610bc38SKonrad Sztyber            UIISCSILun(lun, self)
2557610bc38SKonrad Sztyber
2567610bc38SKonrad Sztyber    def summary(self):
2577610bc38SKonrad Sztyber        return "Luns: %d" % len(self.luns), None
2587610bc38SKonrad Sztyber
2597610bc38SKonrad Sztyber
2607610bc38SKonrad Sztyberclass UIISCSILun(UINode):
2617610bc38SKonrad Sztyber    def __init__(self, lun, parent):
2627610bc38SKonrad Sztyber        UINode.__init__(self, "lun %s" % lun['lun_id'], parent)
2637610bc38SKonrad Sztyber        self.lun = lun
2647610bc38SKonrad Sztyber        self.refresh()
2657610bc38SKonrad Sztyber
2667610bc38SKonrad Sztyber    def summary(self):
2677610bc38SKonrad Sztyber        return "%s" % self.lun['bdev_name'], None
2687610bc38SKonrad Sztyber
2697610bc38SKonrad Sztyber
2707610bc38SKonrad Sztyberclass UIISCSIPgIgMaps(UINode):
2717610bc38SKonrad Sztyber    def __init__(self, pg_ig_maps, parent):
2727610bc38SKonrad Sztyber        UINode.__init__(self, "pg_ig_maps", parent)
2737610bc38SKonrad Sztyber        self.pg_ig_maps = pg_ig_maps
2747610bc38SKonrad Sztyber        self.refresh()
2757610bc38SKonrad Sztyber
2767610bc38SKonrad Sztyber    def refresh(self):
2777610bc38SKonrad Sztyber        self._children = set([])
2787610bc38SKonrad Sztyber        for pg_ig in self.pg_ig_maps:
2797610bc38SKonrad Sztyber            UIISCSIPgIg(pg_ig, self)
2807610bc38SKonrad Sztyber
2817610bc38SKonrad Sztyber    def summary(self):
2827610bc38SKonrad Sztyber        return "Pg_ig_maps: %d" % len(self.pg_ig_maps), None
2837610bc38SKonrad Sztyber
2847610bc38SKonrad Sztyber
2857610bc38SKonrad Sztyberclass UIISCSIPgIg(UINode):
2867610bc38SKonrad Sztyber    def __init__(self, pg_ig, parent):
2877610bc38SKonrad Sztyber        UINode.__init__(self, "portal_group%s - initiator_group%s" %
2887610bc38SKonrad Sztyber                        (pg_ig['pg_tag'], pg_ig['ig_tag']), parent)
2897610bc38SKonrad Sztyber        self.pg_ig = pg_ig
2907610bc38SKonrad Sztyber        self.refresh()
2917610bc38SKonrad Sztyber
2927610bc38SKonrad Sztyber
2937610bc38SKonrad Sztyberclass UIPortalGroups(UINode):
2947610bc38SKonrad Sztyber    def __init__(self, parent):
2957610bc38SKonrad Sztyber        UINode.__init__(self, "portal_groups", parent)
2967610bc38SKonrad Sztyber        self.refresh()
2977610bc38SKonrad Sztyber
2987610bc38SKonrad Sztyber    def delete(self, tag):
2997610bc38SKonrad Sztyber        self.get_root().iscsi_delete_portal_group(tag=tag)
3007610bc38SKonrad Sztyber
3017610bc38SKonrad Sztyber    def ui_command_create(self, tag, portal_list):
3027610bc38SKonrad Sztyber        """Add a portal group.
3037610bc38SKonrad Sztyber
3047610bc38SKonrad Sztyber        Args:
3057610bc38SKonrad Sztyber           portals: List of portals e.g. ip:port ip2:port2
3067610bc38SKonrad Sztyber           tag: Portal group tag (unique, integer > 0)
3077610bc38SKonrad Sztyber        """
3087610bc38SKonrad Sztyber        portals = []
3097610bc38SKonrad Sztyber        for portal in portal_list.strip().split(" "):
3107610bc38SKonrad Sztyber            host = portal
3117610bc38SKonrad Sztyber            cpumask = None
3127610bc38SKonrad Sztyber            if "@" in portal:
3137610bc38SKonrad Sztyber                host, cpumask = portal.split("@")
3147610bc38SKonrad Sztyber            if ":" not in host:
3157610bc38SKonrad Sztyber                raise ExecutionError("Incorrect format of portal group. Port is missing."
3167610bc38SKonrad Sztyber                                     "Use 'help create' to see the command syntax.")
3177610bc38SKonrad Sztyber            host, port = host.rsplit(":", -1)
3187610bc38SKonrad Sztyber            portals.append({'host': host, 'port': port})
3197610bc38SKonrad Sztyber            if cpumask:
3207610bc38SKonrad Sztyber                print("WARNING: Specifying a CPU mask for portal groups is no longer supported. Ignoring.")
3217610bc38SKonrad Sztyber        tag = self.ui_eval_param(tag, "number", None)
3227610bc38SKonrad Sztyber        self.get_root().construct_portal_group(tag=tag, portals=portals, private=None, wait=None)
3237610bc38SKonrad Sztyber
3247610bc38SKonrad Sztyber    def ui_command_delete(self, tag):
3257610bc38SKonrad Sztyber        """Delete a portal group with given tag (unique, integer > 0))"""
3267610bc38SKonrad Sztyber        tag = self.ui_eval_param(tag, "number", None)
3277610bc38SKonrad Sztyber        self.delete(tag)
3287610bc38SKonrad Sztyber
3297610bc38SKonrad Sztyber    def ui_command_delete_all(self):
3307610bc38SKonrad Sztyber        """Delete all portal groups"""
3317610bc38SKonrad Sztyber        rpc_messages = ""
3327610bc38SKonrad Sztyber        for pg in self.pgs:
3337610bc38SKonrad Sztyber            try:
3347610bc38SKonrad Sztyber                self.delete(pg.tag)
3357610bc38SKonrad Sztyber            except JSONRPCException as e:
3367610bc38SKonrad Sztyber                rpc_messages += e.message
3377610bc38SKonrad Sztyber        if rpc_messages:
3387610bc38SKonrad Sztyber            raise JSONRPCException(rpc_messages)
3397610bc38SKonrad Sztyber
3407610bc38SKonrad Sztyber    def refresh(self):
3417610bc38SKonrad Sztyber        self._children = set([])
3427610bc38SKonrad Sztyber        self.pgs = list(self.get_root().iscsi_get_portal_groups())
3437610bc38SKonrad Sztyber        for pg in self.pgs:
3447610bc38SKonrad Sztyber            try:
3457610bc38SKonrad Sztyber                UIPortalGroup(pg, self)
3467610bc38SKonrad Sztyber            except JSONRPCException as e:
3477610bc38SKonrad Sztyber                self.shell.log.error(e.message)
3487610bc38SKonrad Sztyber
3497610bc38SKonrad Sztyber    def summary(self):
3507610bc38SKonrad Sztyber        return "Portal groups: %d" % len(self.pgs), None
3517610bc38SKonrad Sztyber
3527610bc38SKonrad Sztyber
3537610bc38SKonrad Sztyberclass UIPortalGroup(UINode):
3547610bc38SKonrad Sztyber    def __init__(self, pg, parent):
3557610bc38SKonrad Sztyber        UINode.__init__(self, "portal_group%s" % pg.tag, parent)
3567610bc38SKonrad Sztyber        self.pg = pg
3577610bc38SKonrad Sztyber        self.refresh()
3587610bc38SKonrad Sztyber
3597610bc38SKonrad Sztyber    def refresh(self):
3607610bc38SKonrad Sztyber        self._children = set([])
3617610bc38SKonrad Sztyber        for portal in self.pg.portals:
3627610bc38SKonrad Sztyber            UIPortal(portal['host'], portal['port'], self)
3637610bc38SKonrad Sztyber
3647610bc38SKonrad Sztyber    def summary(self):
3657610bc38SKonrad Sztyber        return "Portals: %d" % len(self.pg.portals), None
3667610bc38SKonrad Sztyber
3677610bc38SKonrad Sztyber
3687610bc38SKonrad Sztyberclass UIPortal(UINode):
3697610bc38SKonrad Sztyber    def __init__(self, host, port, parent):
3707610bc38SKonrad Sztyber        UINode.__init__(self, "host=%s, port=%s" % (
3717610bc38SKonrad Sztyber            host, port), parent)
3727610bc38SKonrad Sztyber        self.refresh()
3737610bc38SKonrad Sztyber
3747610bc38SKonrad Sztyber
3757610bc38SKonrad Sztyberclass UIInitiatorGroups(UINode):
3767610bc38SKonrad Sztyber    def __init__(self, parent):
3777610bc38SKonrad Sztyber        UINode.__init__(self, "initiator_groups", parent)
3787610bc38SKonrad Sztyber        self.refresh()
3797610bc38SKonrad Sztyber
3807610bc38SKonrad Sztyber    def delete(self, tag):
3817610bc38SKonrad Sztyber        self.get_root().iscsi_delete_initiator_group(tag=tag)
3827610bc38SKonrad Sztyber
3837610bc38SKonrad Sztyber    def ui_command_create(self, tag, initiator_list, netmask_list):
3847610bc38SKonrad Sztyber        """Add an initiator group.
3857610bc38SKonrad Sztyber
3867610bc38SKonrad Sztyber        Args:
3877610bc38SKonrad Sztyber           tag: Initiator group tag (unique, integer > 0)
3887610bc38SKonrad Sztyber           initiators: List of initiator hostnames or IP addresses
3897610bc38SKonrad Sztyber                       separated with whitespaces, e.g. 127.0.0.1 192.168.200.100
3907610bc38SKonrad Sztyber           netmasks: List of initiator netmasks separated with whitespaces,
3917610bc38SKonrad Sztyber                     e.g. 255.255.0.0 255.248.0.0
3927610bc38SKonrad Sztyber        """
3937610bc38SKonrad Sztyber        tag = self.ui_eval_param(tag, "number", None)
3947610bc38SKonrad Sztyber        self.get_root().construct_initiator_group(
3957610bc38SKonrad Sztyber            tag=tag, initiators=initiator_list.split(" "),
3967610bc38SKonrad Sztyber            netmasks=netmask_list.split(" "))
3977610bc38SKonrad Sztyber
3987610bc38SKonrad Sztyber    def ui_command_delete(self, tag):
3997610bc38SKonrad Sztyber        """Delete an initiator group.
4007610bc38SKonrad Sztyber
4017610bc38SKonrad Sztyber        Args:
4027610bc38SKonrad Sztyber           tag: Initiator group tag (unique, integer > 0)
4037610bc38SKonrad Sztyber        """
4047610bc38SKonrad Sztyber        tag = self.ui_eval_param(tag, "number", None)
4057610bc38SKonrad Sztyber        self.delete(tag)
4067610bc38SKonrad Sztyber
4077610bc38SKonrad Sztyber    def ui_command_delete_all(self):
4087610bc38SKonrad Sztyber        """Delete all initiator groups"""
4097610bc38SKonrad Sztyber        rpc_messages = ""
4107610bc38SKonrad Sztyber        for ig in self.igs:
4117610bc38SKonrad Sztyber            try:
4127610bc38SKonrad Sztyber                self.delete(ig.tag)
4137610bc38SKonrad Sztyber            except JSONRPCException as e:
4147610bc38SKonrad Sztyber                rpc_messages += e.message
4157610bc38SKonrad Sztyber        if rpc_messages:
4167610bc38SKonrad Sztyber            raise JSONRPCException(rpc_messages)
4177610bc38SKonrad Sztyber
4187610bc38SKonrad Sztyber    def ui_command_add_initiator(self, tag, initiators, netmasks):
4197610bc38SKonrad Sztyber        """Add initiators to an existing initiator group.
4207610bc38SKonrad Sztyber
4217610bc38SKonrad Sztyber        Args:
4227610bc38SKonrad Sztyber           tag: Initiator group tag (unique, integer > 0)
4237610bc38SKonrad Sztyber           initiators: List of initiator hostnames or IP addresses,
4247610bc38SKonrad Sztyber                       e.g. 127.0.0.1 192.168.200.100
4257610bc38SKonrad Sztyber           netmasks: List of initiator netmasks,
4267610bc38SKonrad Sztyber                     e.g. 255.255.0.0 255.248.0.0
4277610bc38SKonrad Sztyber        """
4287610bc38SKonrad Sztyber        tag = self.ui_eval_param(tag, "number", None)
4297610bc38SKonrad Sztyber        self.get_root().iscsi_initiator_group_add_initiators(
4307610bc38SKonrad Sztyber            tag=tag, initiators=initiators.split(" "),
4317610bc38SKonrad Sztyber            netmasks=netmasks.split(" "))
4327610bc38SKonrad Sztyber
4337610bc38SKonrad Sztyber    def ui_command_delete_initiator(self, tag, initiators=None, netmasks=None):
4347610bc38SKonrad Sztyber        """Delete initiators from an existing initiator group.
4357610bc38SKonrad Sztyber
4367610bc38SKonrad Sztyber        Args:
4377610bc38SKonrad Sztyber           tag: Initiator group tag (unique, integer > 0)
4387610bc38SKonrad Sztyber           initiators: List of initiator hostnames or IP addresses, e.g. 127.0.0.1 192.168.200.100
4397610bc38SKonrad Sztyber           netmasks: List of initiator netmasks, e.g. 255.255.0.0 255.248.0.0
4407610bc38SKonrad Sztyber        """
4417610bc38SKonrad Sztyber        tag = self.ui_eval_param(tag, "number", None)
4427610bc38SKonrad Sztyber        if initiators:
4437610bc38SKonrad Sztyber            initiators = initiators.split(" ")
4447610bc38SKonrad Sztyber        if netmasks:
4457610bc38SKonrad Sztyber            netmasks = netmasks.split(" ")
4467610bc38SKonrad Sztyber        self.get_root().iscsi_initiator_group_remove_initiators(
4477610bc38SKonrad Sztyber            tag=tag, initiators=initiators,
4487610bc38SKonrad Sztyber            netmasks=netmasks)
4497610bc38SKonrad Sztyber
4507610bc38SKonrad Sztyber    def refresh(self):
4517610bc38SKonrad Sztyber        self._children = set([])
4527610bc38SKonrad Sztyber        self.igs = list(self.get_root().iscsi_get_initiator_groups())
4537610bc38SKonrad Sztyber        for ig in self.igs:
4547610bc38SKonrad Sztyber            UIInitiatorGroup(ig, self)
4557610bc38SKonrad Sztyber
4567610bc38SKonrad Sztyber    def summary(self):
4577610bc38SKonrad Sztyber        return "Initiator groups: %d" % len(self.igs), None
4587610bc38SKonrad Sztyber
4597610bc38SKonrad Sztyber
4607610bc38SKonrad Sztyberclass UIInitiatorGroup(UINode):
4617610bc38SKonrad Sztyber    def __init__(self, ig, parent):
4627610bc38SKonrad Sztyber        UINode.__init__(self, "initiator_group%s" % ig.tag, parent)
4637610bc38SKonrad Sztyber        self.ig = ig
4647610bc38SKonrad Sztyber        self.refresh()
4657610bc38SKonrad Sztyber
4667610bc38SKonrad Sztyber    def refresh(self):
4677610bc38SKonrad Sztyber        self._children = set([])
4687610bc38SKonrad Sztyber        for initiator, netmask in zip(self.ig.initiators, self.ig.netmasks):
4697610bc38SKonrad Sztyber            UIInitiator(initiator, netmask, self)
4707610bc38SKonrad Sztyber
4717610bc38SKonrad Sztyber    def summary(self):
4727610bc38SKonrad Sztyber        return "Initiators: %d" % len(self.ig.initiators), None
4737610bc38SKonrad Sztyber
4747610bc38SKonrad Sztyber
4757610bc38SKonrad Sztyberclass UIInitiator(UINode):
4767610bc38SKonrad Sztyber    def __init__(self, initiator, netmask, parent):
4777610bc38SKonrad Sztyber        UINode.__init__(self, "hostname=%s, netmask=%s" % (initiator, netmask), parent)
4787610bc38SKonrad Sztyber        self.refresh()
4797610bc38SKonrad Sztyber
4807610bc38SKonrad Sztyber
4817610bc38SKonrad Sztyberclass UIISCSIConnections(UINode):
4827610bc38SKonrad Sztyber    def __init__(self, parent):
4837610bc38SKonrad Sztyber        UINode.__init__(self, "iscsi_connections", parent)
4847610bc38SKonrad Sztyber        self.refresh()
4857610bc38SKonrad Sztyber
4867610bc38SKonrad Sztyber    def refresh(self):
4877610bc38SKonrad Sztyber        self._children = set([])
4887610bc38SKonrad Sztyber        self.iscsicons = list(self.get_root().iscsi_get_connections())
4897610bc38SKonrad Sztyber        for ic in self.iscsicons:
4907610bc38SKonrad Sztyber            UIISCSIConnection(ic, self)
4917610bc38SKonrad Sztyber
4927610bc38SKonrad Sztyber    def summary(self):
4937610bc38SKonrad Sztyber        return "Connections: %d" % len(self.iscsicons), None
4947610bc38SKonrad Sztyber
4957610bc38SKonrad Sztyber
4967610bc38SKonrad Sztyberclass UIISCSIConnection(UINode):
4977610bc38SKonrad Sztyber    def __init__(self, ic, parent):
4987610bc38SKonrad Sztyber        UINode.__init__(self, "%s" % ic['id'], parent)
4997610bc38SKonrad Sztyber        self.ic = ic
5007610bc38SKonrad Sztyber        self.refresh()
5017610bc38SKonrad Sztyber
5027610bc38SKonrad Sztyber    def refresh(self):
5037610bc38SKonrad Sztyber        self._children = set([])
5047610bc38SKonrad Sztyber        for key, val in self.ic.items():
5057610bc38SKonrad Sztyber            if key == "id":
5067610bc38SKonrad Sztyber                continue
5077610bc38SKonrad Sztyber            UIISCSIConnectionDetails("%s: %s" % (key, val), self)
5087610bc38SKonrad Sztyber
5097610bc38SKonrad Sztyber
5107610bc38SKonrad Sztyberclass UIISCSIConnectionDetails(UINode):
5117610bc38SKonrad Sztyber    def __init__(self, info, parent):
5127610bc38SKonrad Sztyber        UINode.__init__(self, "%s" % info, parent)
5137610bc38SKonrad Sztyber        self.refresh()
5147610bc38SKonrad Sztyber
5157610bc38SKonrad Sztyber
5167610bc38SKonrad Sztyberclass UIISCSIAuthGroups(UINode):
5177610bc38SKonrad Sztyber    def __init__(self, parent):
5187610bc38SKonrad Sztyber        UINode.__init__(self, "auth_groups", parent)
5197610bc38SKonrad Sztyber        self.refresh()
5207610bc38SKonrad Sztyber
5217610bc38SKonrad Sztyber    def refresh(self):
5227610bc38SKonrad Sztyber        self._children = set([])
5237610bc38SKonrad Sztyber        self.iscsi_auth_groups = list(self.get_root().iscsi_get_auth_groups())
5247610bc38SKonrad Sztyber        if self.iscsi_auth_groups is None:
5257610bc38SKonrad Sztyber            self.iscsi_auth_groups = []
5267610bc38SKonrad Sztyber        for ag in self.iscsi_auth_groups:
5277610bc38SKonrad Sztyber            UIISCSIAuthGroup(ag, self)
5287610bc38SKonrad Sztyber
5297610bc38SKonrad Sztyber    def delete(self, tag):
5307610bc38SKonrad Sztyber        self.get_root().iscsi_delete_auth_group(tag=tag)
5317610bc38SKonrad Sztyber
5327610bc38SKonrad Sztyber    def delete_secret(self, tag, user):
5337610bc38SKonrad Sztyber        self.get_root().iscsi_auth_group_remove_secret(
5347610bc38SKonrad Sztyber            tag=tag, user=user)
5357610bc38SKonrad Sztyber
5367610bc38SKonrad Sztyber    def ui_command_create(self, tag, secrets=None):
5377610bc38SKonrad Sztyber        """Add authentication group for CHAP authentication.
5387610bc38SKonrad Sztyber
5397610bc38SKonrad Sztyber        Args:
5407610bc38SKonrad Sztyber           tag: Authentication group tag (unique, integer > 0).
5417610bc38SKonrad Sztyber        Optional args:
5427610bc38SKonrad Sztyber           secrets: Array of secrets objects separated by comma sign,
5437610bc38SKonrad Sztyber                    e.g. user:test secret:test muser:mutual_test msecret:mutual_test
5447610bc38SKonrad Sztyber        """
5457610bc38SKonrad Sztyber        tag = self.ui_eval_param(tag, "number", None)
5467610bc38SKonrad Sztyber        if secrets:
5477610bc38SKonrad Sztyber            secrets = [dict(u.split(":") for u in a.split(" "))
5487610bc38SKonrad Sztyber                       for a in secrets.split(",")]
5497610bc38SKonrad Sztyber        self.get_root().iscsi_create_auth_group(tag=tag, secrets=secrets)
5507610bc38SKonrad Sztyber
5517610bc38SKonrad Sztyber    def ui_command_delete(self, tag):
5527610bc38SKonrad Sztyber        """Delete an authentication group.
5537610bc38SKonrad Sztyber
5547610bc38SKonrad Sztyber        Args:
5557610bc38SKonrad Sztyber           tag: Authentication group tag (unique, integer > 0)
5567610bc38SKonrad Sztyber        """
5577610bc38SKonrad Sztyber        tag = self.ui_eval_param(tag, "number", None)
5587610bc38SKonrad Sztyber        self.delete(tag)
5597610bc38SKonrad Sztyber
5607610bc38SKonrad Sztyber    def ui_command_delete_all(self):
5617610bc38SKonrad Sztyber        """Delete all authentication groups."""
5627610bc38SKonrad Sztyber        rpc_messages = ""
5637610bc38SKonrad Sztyber        for iscsi_auth_group in self.iscsi_auth_groups:
5647610bc38SKonrad Sztyber            try:
5657610bc38SKonrad Sztyber                self.delete(iscsi_auth_group['tag'])
5667610bc38SKonrad Sztyber            except JSONRPCException as e:
5677610bc38SKonrad Sztyber                rpc_messages += e.message
5687610bc38SKonrad Sztyber        if rpc_messages:
5697610bc38SKonrad Sztyber            raise JSONRPCException(rpc_messages)
5707610bc38SKonrad Sztyber
5717610bc38SKonrad Sztyber    def ui_command_add_secret(self, tag, user, secret,
5727610bc38SKonrad Sztyber                              muser=None, msecret=None):
5737610bc38SKonrad Sztyber        """Add a secret to an authentication group.
5747610bc38SKonrad Sztyber
5757610bc38SKonrad Sztyber        Args:
5767610bc38SKonrad Sztyber           tag: Authentication group tag (unique, integer > 0)
5777610bc38SKonrad Sztyber           user: User name for one-way CHAP authentication
5787610bc38SKonrad Sztyber           secret: Secret for one-way CHAP authentication
5797610bc38SKonrad Sztyber        Optional args:
5807610bc38SKonrad Sztyber           muser: User name for mutual CHAP authentication
5817610bc38SKonrad Sztyber           msecret: Secret for mutual CHAP authentication
5827610bc38SKonrad Sztyber        """
5837610bc38SKonrad Sztyber        tag = self.ui_eval_param(tag, "number", None)
5847610bc38SKonrad Sztyber        self.get_root().iscsi_auth_group_add_secret(
5857610bc38SKonrad Sztyber            tag=tag, user=user, secret=secret,
5867610bc38SKonrad Sztyber            muser=muser, msecret=msecret)
5877610bc38SKonrad Sztyber
5887610bc38SKonrad Sztyber    def ui_command_delete_secret(self, tag, user):
5897610bc38SKonrad Sztyber        """Delete a secret from an authentication group.
5907610bc38SKonrad Sztyber
5917610bc38SKonrad Sztyber        Args:
5927610bc38SKonrad Sztyber           tag: Authentication group tag (unique, integer > 0)
5937610bc38SKonrad Sztyber           user: User name for one-way CHAP authentication
5947610bc38SKonrad Sztyber        """
5957610bc38SKonrad Sztyber        tag = self.ui_eval_param(tag, "number", None)
5967610bc38SKonrad Sztyber        self.delete_secret(tag, user)
5977610bc38SKonrad Sztyber
5987610bc38SKonrad Sztyber    def ui_command_delete_secret_all(self, tag):
5997610bc38SKonrad Sztyber        """Delete all secrets from an authentication group.
6007610bc38SKonrad Sztyber
6017610bc38SKonrad Sztyber        Args:
6027610bc38SKonrad Sztyber           tag: Authentication group tag (unique, integer > 0)
6037610bc38SKonrad Sztyber        """
6047610bc38SKonrad Sztyber        rpc_messages = ""
6057610bc38SKonrad Sztyber        tag = self.ui_eval_param(tag, "number", None)
6067610bc38SKonrad Sztyber        for ag in self.iscsi_auth_groups:
6077610bc38SKonrad Sztyber            if ag['tag'] == tag:
6087610bc38SKonrad Sztyber                for secret in ag['secrets']:
6097610bc38SKonrad Sztyber                    try:
6107610bc38SKonrad Sztyber                        self.delete_secret(tag, secret['user'])
6117610bc38SKonrad Sztyber                    except JSONRPCException as e:
6127610bc38SKonrad Sztyber                        rpc_messages += e.message
6137610bc38SKonrad Sztyber        if rpc_messages:
6147610bc38SKonrad Sztyber            raise JSONRPCException(rpc_messages)
6157610bc38SKonrad Sztyber
6167610bc38SKonrad Sztyber    def summary(self):
6177610bc38SKonrad Sztyber        return "Groups: %s" % len(self.iscsi_auth_groups), None
6187610bc38SKonrad Sztyber
6197610bc38SKonrad Sztyber
6207610bc38SKonrad Sztyberclass UIISCSIAuthGroup(UINode):
6217610bc38SKonrad Sztyber    def __init__(self, ag, parent):
6227610bc38SKonrad Sztyber        UINode.__init__(self, "group" + str(ag['tag']), parent)
6237610bc38SKonrad Sztyber        self.ag = ag
6247610bc38SKonrad Sztyber        self.refresh()
6257610bc38SKonrad Sztyber
6267610bc38SKonrad Sztyber    def refresh(self):
6277610bc38SKonrad Sztyber        self._children = set([])
6287610bc38SKonrad Sztyber        for secret in self.ag['secrets']:
6297610bc38SKonrad Sztyber            UISCSIAuthSecret(secret, self)
6307610bc38SKonrad Sztyber
6317610bc38SKonrad Sztyber    def summary(self):
6327610bc38SKonrad Sztyber        return "Secrets: %s" % len(self.ag['secrets']), None
6337610bc38SKonrad Sztyber
6347610bc38SKonrad Sztyber
6357610bc38SKonrad Sztyberclass UISCSIAuthSecret(UINode):
6367610bc38SKonrad Sztyber    def __init__(self, secret, parent):
6377610bc38SKonrad Sztyber        info_list = ["%s=%s" % (key, val)
6387610bc38SKonrad Sztyber                     for key, val in secret.items()]
6397610bc38SKonrad Sztyber        info_list.sort(reverse=True)
6407610bc38SKonrad Sztyber        info = ", ".join(info_list)
6417610bc38SKonrad Sztyber        UINode.__init__(self, info, parent)
6427610bc38SKonrad Sztyber        self.secret = secret
6437610bc38SKonrad Sztyber        self.refresh()
644