summaryrefslogtreecommitdiffstats
path: root/src/pybind/mgr/cephadm/services/iscsi.py
blob: 127783c13e4409a8a50126a99ecabd22ec14a027 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import json
import logging
from typing import List, cast

from mgr_module import MonCommandFailed
from ceph.deployment.service_spec import IscsiServiceSpec

from orchestrator import DaemonDescription, OrchestratorError
from .cephadmservice import CephadmService, CephadmDaemonSpec
from .. import utils

logger = logging.getLogger(__name__)


class IscsiService(CephadmService):
    TYPE = 'iscsi'

    def config(self, spec: IscsiServiceSpec):
        self.mgr._check_pool_exists(spec.pool, spec.service_name())

        logger.info('Saving service %s spec with placement %s' % (
            spec.service_name(), spec.placement.pretty_str()))
        self.mgr.spec_store.save(spec)

    def create(self, daemon_spec: CephadmDaemonSpec[IscsiServiceSpec]) -> str:
        spec = daemon_spec.spec
        if spec is None:
            raise OrchestratorError(f'Unable to deploy {daemon_spec.name()}: Service not found.')
        igw_id = daemon_spec.daemon_id
        ret, keyring, err = self.mgr.check_mon_command({
            'prefix': 'auth get-or-create',
            'entity': utils.name_to_auth_entity('iscsi', igw_id),
            'caps': ['mon', 'profile rbd, '
                            'allow command "osd blacklist", '
                            'allow command "config-key get" with "key" prefix "iscsi/"',
                     'osd', 'allow rwx'],
        })

        if spec.ssl_cert:
            if isinstance(spec.ssl_cert, list):
                cert_data = '\n'.join(spec.ssl_cert)
            else:
                cert_data = spec.ssl_cert
            ret, out, err = self.mgr.mon_command({
                'prefix': 'config-key set',
                'key': f'iscsi/{utils.name_to_config_section("iscsi")}.{igw_id}/iscsi-gateway.crt',
                'val': cert_data,
            })

        if spec.ssl_key:
            if isinstance(spec.ssl_key, list):
                key_data = '\n'.join(spec.ssl_key)
            else:
                key_data = spec.ssl_key
            ret, out, err = self.mgr.mon_command({
                'prefix': 'config-key set',
                'key': f'iscsi/{utils.name_to_config_section("iscsi")}.{igw_id}/iscsi-gateway.key',
                'val': key_data,
            })

        context = {
            'client_name': '{}.{}'.format(utils.name_to_config_section('iscsi'), igw_id),
            'spec': spec
        }
        igw_conf = self.mgr.template.render('services/iscsi/iscsi-gateway.cfg.j2', context)

        daemon_spec.keyring = keyring
        daemon_spec.extra_config = {'iscsi-gateway.cfg': igw_conf}

        return self.mgr._create_daemon(daemon_spec)


    def config_dashboard(self, daemon_descrs: List[DaemonDescription]):
        def get_set_cmd_dicts(out: str) -> List[dict]:
            gateways = json.loads(out)['gateways']
            cmd_dicts = []
            for dd in daemon_descrs:
                spec = cast(IscsiServiceSpec,
                            self.mgr.spec_store.specs.get(dd.service_name(), None))
                if not spec:
                    logger.warning('No ServiceSpec found for %s', dd)
                    continue
                if not all([spec.api_user, spec.api_password]):
                    reason = 'api_user or api_password is not specified in ServiceSpec'
                    logger.warning(
                        'Unable to add iSCSI gateway to the Dashboard for %s: %s', dd, reason)
                    continue
                host = self._inventory_get_addr(dd.hostname)
                service_url = 'http://{}:{}@{}:{}'.format(
                    spec.api_user, spec.api_password, host, spec.api_port or '5000')
                gw = gateways.get(host)
                if not gw or gw['service_url'] != service_url:
                    logger.info('Adding iSCSI gateway %s to Dashboard', service_url)
                    cmd_dicts.append({
                        'prefix': 'dashboard iscsi-gateway-add',
                        'service_url': service_url,
                        'name': host
                    })
            return cmd_dicts

        self._check_and_set_dashboard(
            service_name='iSCSI',
            get_cmd='dashboard iscsi-gateway-list',
            get_set_cmd_dicts=get_set_cmd_dicts
        )