From: Ricardo Marques Date: Fri, 29 Mar 2019 13:35:07 +0000 (+0000) Subject: mgr/dashboard: Optimize target edition when a portal is removed X-Git-Tag: v14.2.3~64^2~2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=83ef771312ea5ab4a3cc5f553126c7f4afc92723;p=ceph.git mgr/dashboard: Optimize target edition when a portal is removed Fixes: https://tracker.ceph.com/issues/38794 Signed-off-by: Ricardo Marques (cherry picked from commit f345fe3f1093204af9a1783a619efbaf966c1bc7) --- diff --git a/src/pybind/mgr/dashboard/controllers/iscsi.py b/src/pybind/mgr/dashboard/controllers/iscsi.py index b58ef66a9f2e..562a77f3d106 100644 --- a/src/pybind/mgr/dashboard/controllers/iscsi.py +++ b/src/pybind/mgr/dashboard/controllers/iscsi.py @@ -279,7 +279,7 @@ class IscsiTarget(RESTController): deleted_groups = [] for group_id in list(target_config['groups'].keys()): if IscsiTarget._group_deletion_required(target, new_target_iqn, new_target_controls, - new_portals, new_groups, group_id, new_clients, + new_groups, group_id, new_clients, new_disks): deleted_groups.append(group_id) IscsiClient.instance(gateway_name=gateway_name).delete_group(target_iqn, @@ -287,22 +287,29 @@ class IscsiTarget(RESTController): TaskManager.current_task().inc_progress(task_progress_inc) for client_iqn in list(target_config['clients'].keys()): if IscsiTarget._client_deletion_required(target, new_target_iqn, new_target_controls, - new_portals, new_clients, client_iqn, + new_clients, client_iqn, new_groups, deleted_groups): IscsiClient.instance(gateway_name=gateway_name).delete_client(target_iqn, client_iqn) TaskManager.current_task().inc_progress(task_progress_inc) for image_id in target_config['disks']: if IscsiTarget._target_lun_deletion_required(target, new_target_iqn, - new_target_controls, new_portals, + new_target_controls, new_disks, image_id): IscsiClient.instance(gateway_name=gateway_name).delete_target_lun(target_iqn, image_id) pool, image = image_id.split('/', 1) IscsiClient.instance(gateway_name=gateway_name).delete_disk(pool, image) TaskManager.current_task().inc_progress(task_progress_inc) - if IscsiTarget._target_deletion_required(target, new_target_iqn, new_target_controls, - new_portals): + old_portals_by_host = IscsiTarget._get_portals_by_host(target['portals']) + new_portals_by_host = IscsiTarget._get_portals_by_host(new_portals) + for old_portal_host, old_portal_ip_list in old_portals_by_host.items(): + if IscsiTarget._target_portal_deletion_required(old_portal_host, + old_portal_ip_list, + new_portals_by_host): + IscsiClient.instance(gateway_name=gateway_name).delete_gateway(target_iqn, + old_portal_host) + if IscsiTarget._target_deletion_required(target, new_target_iqn, new_target_controls): IscsiClient.instance(gateway_name=gateway_name).delete_target(target_iqn) TaskManager.current_task().set_progress(task_progress_end) return IscsiClient.instance(gateway_name=gateway_name).get_config() @@ -315,10 +322,9 @@ class IscsiTarget(RESTController): return None @staticmethod - def _group_deletion_required(target, new_target_iqn, new_target_controls, new_portals, + def _group_deletion_required(target, new_target_iqn, new_target_controls, new_groups, group_id, new_clients, new_disks): - if IscsiTarget._target_deletion_required(target, new_target_iqn, new_target_controls, - new_portals): + if IscsiTarget._target_deletion_required(target, new_target_iqn, new_target_controls): return True new_group = IscsiTarget._get_group(new_groups, group_id) if not new_group: @@ -329,14 +335,14 @@ class IscsiTarget(RESTController): # Check if any client inside this group has changed for client_iqn in new_group['members']: if IscsiTarget._client_deletion_required(target, new_target_iqn, new_target_controls, - new_portals, new_clients, client_iqn, + new_clients, client_iqn, new_groups, []): return True # Check if any disk inside this group has changed for disk in new_group['disks']: image_id = '{}/{}'.format(disk['pool'], disk['image']) if IscsiTarget._target_lun_deletion_required(target, new_target_iqn, - new_target_controls, new_portals, + new_target_controls, new_disks, image_id): return True return False @@ -349,10 +355,9 @@ class IscsiTarget(RESTController): return None @staticmethod - def _client_deletion_required(target, new_target_iqn, new_target_controls, new_portals, + def _client_deletion_required(target, new_target_iqn, new_target_controls, new_clients, client_iqn, new_groups, deleted_groups): - if IscsiTarget._target_deletion_required(target, new_target_iqn, new_target_controls, - new_portals): + if IscsiTarget._target_deletion_required(target, new_target_iqn, new_target_controls): return True new_client = deepcopy(IscsiTarget._get_client(new_clients, client_iqn)) if not new_client: @@ -378,10 +383,9 @@ class IscsiTarget(RESTController): return None @staticmethod - def _target_lun_deletion_required(target, new_target_iqn, new_target_controls, new_portals, + def _target_lun_deletion_required(target, new_target_iqn, new_target_controls, new_disks, image_id): - if IscsiTarget._target_deletion_required(target, new_target_iqn, new_target_controls, - new_portals): + if IscsiTarget._target_deletion_required(target, new_target_iqn, new_target_controls): return True new_disk = IscsiTarget._get_disk(new_disks, image_id) if not new_disk: @@ -392,13 +396,19 @@ class IscsiTarget(RESTController): return False @staticmethod - def _target_deletion_required(target, new_target_iqn, new_target_controls, new_portals): + def _target_portal_deletion_required(old_portal_host, old_portal_ip_list, new_portals_by_host): + if old_portal_host not in new_portals_by_host: + return True + if sorted(old_portal_ip_list) != sorted(new_portals_by_host[old_portal_host]): + return True + return False + + @staticmethod + def _target_deletion_required(target, new_target_iqn, new_target_controls): if target['target_iqn'] != new_target_iqn: return True if target['target_controls'] != new_target_controls: return True - if target['portals'] != new_portals: - return True return False @staticmethod @@ -503,11 +513,12 @@ class IscsiTarget(RESTController): if not target_config: IscsiClient.instance(gateway_name=gateway_name).create_target(target_iqn, target_controls) - for host, ip_list in portals_by_host.items(): + for host, ip_list in portals_by_host.items(): + if not target_config or host not in target_config['portals']: IscsiClient.instance(gateway_name=gateway_name).create_gateway(target_iqn, host, ip_list) - TaskManager.current_task().inc_progress(task_progress_inc) + TaskManager.current_task().inc_progress(task_progress_inc) targetauth_action = ('enable_acl' if acl_enabled else 'disable_acl') IscsiClient.instance(gateway_name=gateway_name).update_targetauth(target_iqn, targetauth_action) diff --git a/src/pybind/mgr/dashboard/services/iscsi_client.py b/src/pybind/mgr/dashboard/services/iscsi_client.py index 520b4ca30c78..4d6115c31f5d 100644 --- a/src/pybind/mgr/dashboard/services/iscsi_client.py +++ b/src/pybind/mgr/dashboard/services/iscsi_client.py @@ -109,6 +109,11 @@ class IscsiClient(RestClient): def get_gatewayinfo(self, request=None): return request() + @RestClient.api_delete('/api/gateway/{target_iqn}/{gateway_name}') + def delete_gateway(self, target_iqn, gateway_name, request=None): + logger.debug("iSCSI: Deleting gateway: %s/%s", target_iqn, gateway_name) + return request() + @RestClient.api_put('/api/disk/{pool}/{image}') def create_disk(self, pool, image, backstore, request=None): logger.debug("iSCSI[%s] Creating disk: %s/%s", self.gateway_name, pool, image) diff --git a/src/pybind/mgr/dashboard/tests/test_iscsi.py b/src/pybind/mgr/dashboard/tests/test_iscsi.py index e371ef368622..c3c6c159c5c7 100644 --- a/src/pybind/mgr/dashboard/tests/test_iscsi.py +++ b/src/pybind/mgr/dashboard/tests/test_iscsi.py @@ -553,6 +553,12 @@ class IscsiClientMock(object): "portal_ip_address": ip_address[0] } + def delete_gateway(self, target_iqn, gateway_name): + target_config = self.config['targets'][target_iqn] + portal_config = target_config['portals'][gateway_name] + target_config['ip_list'].remove(portal_config['portal_ip_address']) + target_config['portals'].pop(gateway_name) + def create_disk(self, pool, image, backstore): image_id = '{}/{}'.format(pool, image) self.config['disks'][image_id] = {