From 6f3471648d99cf9b19bc99b87f6b0c0dc91fd8f5 Mon Sep 17 00:00:00 2001 From: Ricardo Marques Date: Thu, 24 Jan 2019 13:41:53 +0000 Subject: [PATCH] mgr/dashboard: iSCSI discovery authentication API Fixes: https://tracker.ceph.com/issues/38017 Signed-off-by: Ricardo Marques --- src/pybind/mgr/dashboard/controllers/iscsi.py | 38 +++++++++++++++- .../mgr/dashboard/services/iscsi_client.py | 16 +++++++ src/pybind/mgr/dashboard/tests/test_iscsi.py | 45 ++++++++++++++++++- 3 files changed, 95 insertions(+), 4 deletions(-) diff --git a/src/pybind/mgr/dashboard/controllers/iscsi.py b/src/pybind/mgr/dashboard/controllers/iscsi.py index 504aca8a5fc..de643fbc455 100644 --- a/src/pybind/mgr/dashboard/controllers/iscsi.py +++ b/src/pybind/mgr/dashboard/controllers/iscsi.py @@ -11,7 +11,7 @@ import rados import rbd from . import ApiController, UiApiController, RESTController, BaseController, Endpoint,\ - ReadPermission, Task + ReadPermission, UpdatePermission, Task from .. import mgr from ..rest_client import RequestException from ..security import Scope @@ -22,7 +22,7 @@ from ..tools import TaskManager @UiApiController('/iscsi', Scope.ISCSI) -class Iscsi(BaseController): +class IscsiUi(BaseController): @Endpoint() @ReadPermission @@ -58,6 +58,40 @@ class Iscsi(BaseController): return sorted(portals, key=lambda p: '{}.{}'.format(p['name'], p['ip_addresses'])) +@ApiController('/iscsi', Scope.ISCSI) +class Iscsi(BaseController): + + @Endpoint('GET', 'discoveryauth') + @UpdatePermission + def get_discoveryauth(self): + return self._get_discoveryauth() + + @Endpoint('PUT', 'discoveryauth') + @UpdatePermission + def set_discoveryauth(self, user, password, mutual_user, mutual_password): + IscsiClient.instance().update_discoveryauth(user, password, mutual_user, mutual_password) + return self._get_discoveryauth() + + def _get_discoveryauth(self): + config = IscsiClient.instance().get_config() + user = '' + password = '' + chap = config['discovery_auth']['chap'] + if chap: + user, password = chap.split('/') + mutual_user = '' + mutual_password = '' + chap_mutual = config['discovery_auth']['chap_mutual'] + if chap_mutual: + mutual_user, mutual_password = chap_mutual.split('/') + return { + 'user': user, + 'password': password, + 'mutual_user': mutual_user, + 'mutual_password': mutual_password + } + + def iscsi_target_task(name, metadata, wait_for=2.0): return Task("iscsi/target/{}".format(name), metadata, wait_for) diff --git a/src/pybind/mgr/dashboard/services/iscsi_client.py b/src/pybind/mgr/dashboard/services/iscsi_client.py index 41f2b64f309..d6f42ed3c1d 100644 --- a/src/pybind/mgr/dashboard/services/iscsi_client.py +++ b/src/pybind/mgr/dashboard/services/iscsi_client.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- +# pylint: disable=too-many-public-methods from __future__ import absolute_import import json @@ -163,3 +164,18 @@ class IscsiClient(RestClient): def delete_group(self, target_iqn, group_name, request=None): logger.debug("iSCSI: Deleting group: %s/%s", target_iqn, group_name) return request() + + @RestClient.api_put('/api/discoveryauth') + def update_discoveryauth(self, user, password, mutual_user, mutual_password, request=None): + logger.debug("iSCSI: Updating discoveryauth: %s/%s/%s/%s", user, password, mutual_user, + mutual_password) + chap = '' + if user and password: + chap = '{}/{}'.format(user, password) + chap_mutual = '' + if mutual_user and mutual_password: + chap_mutual = '{}/{}'.format(mutual_user, mutual_password) + return request({ + 'chap': chap, + 'chap_mutual': chap_mutual + }) diff --git a/src/pybind/mgr/dashboard/tests/test_iscsi.py b/src/pybind/mgr/dashboard/tests/test_iscsi.py index 9c5970775b8..b3818b850e9 100644 --- a/src/pybind/mgr/dashboard/tests/test_iscsi.py +++ b/src/pybind/mgr/dashboard/tests/test_iscsi.py @@ -3,7 +3,7 @@ import mock from .helper import ControllerTestCase from .. import mgr -from ..controllers.iscsi import IscsiTarget +from ..controllers.iscsi import Iscsi, IscsiTarget from ..services.iscsi_client import IscsiClient @@ -13,14 +13,43 @@ class IscsiTest(ControllerTestCase): def setup_server(cls): mgr.rados.side_effect = None # pylint: disable=protected-access + Iscsi._cp_config['tools.authenticate.on'] = False IscsiTarget._cp_config['tools.authenticate.on'] = False - cls.setup_controllers([IscsiTarget]) + cls.setup_controllers([Iscsi, IscsiTarget]) def setUp(self): # pylint: disable=protected-access IscsiClientMock._instance = IscsiClientMock() IscsiClient.instance = IscsiClientMock.instance + def test_enable_discoveryauth(self): + discoveryauth = { + 'user': 'myiscsiusername', + 'password': 'myiscsipassword', + 'mutual_user': 'myiscsiusername2', + 'mutual_password': 'myiscsipassword2' + } + self._put('/api/iscsi/discoveryauth', discoveryauth) + self.assertStatus(200) + self.assertJsonBody(discoveryauth) + self._get('/api/iscsi/discoveryauth') + self.assertStatus(200) + self.assertJsonBody(discoveryauth) + + def test_disable_discoveryauth(self): + discoveryauth = { + 'user': '', + 'password': '', + 'mutual_user': '', + 'mutual_password': '' + } + self._put('/api/iscsi/discoveryauth', discoveryauth) + self.assertStatus(200) + self.assertJsonBody(discoveryauth) + self._get('/api/iscsi/discoveryauth') + self.assertStatus(200) + self.assertJsonBody(discoveryauth) + def test_list_empty(self): self._get('/api/iscsi/target') self.assertStatus(200) @@ -506,3 +535,15 @@ class IscsiClientMock(object): 'node3': ['192.168.100.203'] } return {'data': ips[self.gateway_name]} + + def update_discoveryauth(self, user, password, mutual_user, mutual_password): + chap = '' + if user and password: + chap = '{}/{}'.format(user, password) + chap_mutual = '' + if mutual_user and mutual_password: + chap_mutual = '{}/{}'.format(mutual_user, mutual_password) + self.config['discovery_auth'] = { + 'chap': chap, + 'chap_mutual': chap_mutual + }