From 61812612798bfabd731e80a0a483ff586e65ce55 Mon Sep 17 00:00:00 2001
From: Liam Young <liam.young@canonical.com>
Date: Fri, 20 Aug 2021 14:19:11 +0000
Subject: [PATCH] Support iscsi

ceph-iscsi does not support wallaby yet so the hirsute bundle is
unchanged.

Change-Id: I9db6557b396e86180070cbbf29f14c7814fcd357
---
 metadata.yaml            |  2 ++
 requirements.txt         |  1 +
 src/charm.py             | 38 ++++++++++++++++++++++++++++++++++++--
 tests/bundles/focal.yaml | 11 +++++++++++
 4 files changed, 50 insertions(+), 2 deletions(-)

diff --git a/metadata.yaml b/metadata.yaml
index d66e9fd..fcbb1dd 100644
--- a/metadata.yaml
+++ b/metadata.yaml
@@ -31,6 +31,8 @@ requires:
     interface: http
   radosgw-dashboard:
     interface: radosgw-user
+  iscsi-dashboard:
+    interface: ceph-iscsi-admin-access
 provides:
   grafana-dashboard:
     interface: grafana-dashboard
diff --git a/requirements.txt b/requirements.txt
index f0aa163..03eb941 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -4,3 +4,4 @@ git+https://github.com/openstack/charms.ceph#egg=charms_ceph
 git+https://opendev.org/openstack/charm-ops-openstack#egg=ops_openstack
 #git+https://opendev.org/openstack/charm-ops-interface-tls-certificates#egg=interface_tls_certificates
 git+https://github.com/gnuoy/ops-interface-tls-certificates@no-exception-for-inflight-request#egg=interface_tls_certificates
+git+https://github.com/openstack-charmers/ops-interface-ceph-iscsi-admin-access#egg=interface_ceph_iscsi_admin_access
diff --git a/src/charm.py b/src/charm.py
index d4597f3..57fc174 100755
--- a/src/charm.py
+++ b/src/charm.py
@@ -25,6 +25,7 @@ import string
 import subprocess
 import tenacity
 import ops_openstack.plugins.classes
+import interface_ceph_iscsi_admin_access.admin_access as admin_access
 import interface_dashboard
 import interface_api_endpoints
 import interface_grafana_dashboard
@@ -166,6 +167,9 @@ class CephDashboardCharm(ops_openstack.core.OSBaseCharm):
             self,
             'radosgw-dashboard',
             request_system_role=True)
+        self.iscsi_user = admin_access.CephISCSIAdminAccessRequires(
+            self,
+            'iscsi-dashboard')
         self.framework.observe(
             self.mon.on.mon_ready,
             self._configure_dashboard)
@@ -178,6 +182,9 @@ class CephDashboardCharm(ops_openstack.core.OSBaseCharm):
         self.framework.observe(
             self.radosgw_user.on.gw_user_ready,
             self._configure_dashboard)
+        self.framework.observe(
+            self.iscsi_user.on.admin_access_ready,
+            self._configure_dashboard)
         self.framework.observe(self.on.add_user_action, self._add_user_action)
         self.ingress = interface_api_endpoints.APIEndpointsRequires(
             self,
@@ -350,12 +357,16 @@ class CephDashboardCharm(ops_openstack.core.OSBaseCharm):
         return self._run_cmd(cmd)
 
     def _apply_file_setting(self, ceph_setting: str,
-                            file_contents: str) -> str:
+                            file_contents: str,
+                            extra_args: List[str] = None) -> None:
         """Apply a setting via a file"""
         with tempfile.NamedTemporaryFile(mode='w', delete=True) as _file:
             _file.write(file_contents)
             _file.flush()
-            return self._apply_setting(ceph_setting, ['-i', _file.name])
+            settings = ['-i', _file.name]
+            if extra_args:
+                settings.extend(extra_args)
+            self._apply_setting(ceph_setting, settings)
 
     def _apply_ceph_config_from_charm_config(self) -> None:
         """Read charm config and apply settings to dashboard config"""
@@ -410,6 +421,7 @@ class CephDashboardCharm(ops_openstack.core.OSBaseCharm):
                     prometheus_ep])
         self._register_dashboards()
         self._manage_radosgw()
+        self._manage_iscsigw()
         self._stored.is_started = True
         self.update_status()
 
@@ -450,6 +462,28 @@ class CephDashboardCharm(ops_openstack.core.OSBaseCharm):
                 encoding=serialization.Encoding.PEM))
         return key, cert, ca_cert
 
+    def _update_iscsigw_creds(self, creds):
+        self._apply_file_setting(
+            'iscsi-gateway-add',
+            '{}://{}:{}@{}:{}'.format(
+                creds['scheme'],
+                creds['username'],
+                creds['password'],
+                creds['host'],
+                creds['port']),
+            [creds['name']])
+
+    def _manage_iscsigw(self) -> None:
+        """Register rados gateways in dashboard db"""
+        if self.unit.is_leader():
+            creds = self.iscsi_user.get_user_creds()
+            if len(creds) < 1:
+                logging.info("No iscsi gateway creds found")
+                return
+            else:
+                for c in creds:
+                    self._update_iscsigw_creds(c)
+
     def _configure_tls(self) -> None:
         """Configure TLS."""
         logging.debug("Attempting to collect TLS config from relation")
diff --git a/tests/bundles/focal.yaml b/tests/bundles/focal.yaml
index 215364d..8a06e61 100644
--- a/tests/bundles/focal.yaml
+++ b/tests/bundles/focal.yaml
@@ -53,6 +53,11 @@ applications:
   ceph-fs:
     charm: cs:~openstack-charmers-next/ceph-fs
     num_units: 1
+  ceph-iscsi:
+    charm: cs:~openstack-charmers-next/ceph-iscsi
+    num_units: 2
+    options:
+      gateway-metadata-pool: iscsi-foo-metadata
 relations:
   - - 'ceph-osd:mon'
     - 'ceph-mon:osd'
@@ -94,3 +99,9 @@ relations:
     - 'ceph-radosgw:radosgw-user'
   - - 'ceph-mon:mds'
     - 'ceph-fs:ceph-mds'
+  - - 'ceph-mon:client'
+    - 'ceph-iscsi:ceph-client'
+  - - 'vault:certificates'
+    - 'ceph-iscsi:certificates'
+  - - 'ceph-dashboard:iscsi-dashboard'
+    - 'ceph-iscsi:admin-access'