]> git.proxmox.com Git - ceph.git/blob - ceph/src/pybind/mgr/dashboard/services/iscsi_config.py
f1818c1986c2600703f5a23af0317a3595eb15ab
[ceph.git] / ceph / src / pybind / mgr / dashboard / services / iscsi_config.py
1 # -*- coding: utf-8 -*-
2
3 import json
4
5 try:
6 from urlparse import urlparse
7 except ImportError:
8 from urllib.parse import urlparse
9
10 from .. import mgr
11
12
13 class IscsiGatewayAlreadyExists(Exception):
14 def __init__(self, gateway_name):
15 super(IscsiGatewayAlreadyExists, self).__init__(
16 "iSCSI gateway '{}' already exists".format(gateway_name))
17
18
19 class IscsiGatewayDoesNotExist(Exception):
20 def __init__(self, hostname):
21 super(IscsiGatewayDoesNotExist, self).__init__(
22 "iSCSI gateway '{}' does not exist".format(hostname))
23
24
25 class InvalidServiceUrl(Exception):
26 def __init__(self, service_url):
27 super(InvalidServiceUrl, self).__init__(
28 "Invalid service URL '{}'. "
29 "Valid format: '<scheme>://<username>:<password>@<host>[:port]'.".format(service_url))
30
31
32 class ManagedByOrchestratorException(Exception):
33 def __init__(self):
34 super(ManagedByOrchestratorException, self).__init__(
35 "iSCSI configuration is managed by the orchestrator")
36
37
38 _ISCSI_STORE_KEY = "_iscsi_config"
39
40
41 class IscsiGatewaysConfig(object):
42 @classmethod
43 def _load_config_from_store(cls):
44 json_db = mgr.get_store(_ISCSI_STORE_KEY,
45 '{"gateways": {}}')
46 config = json.loads(json_db)
47 cls.update_iscsi_config(config)
48 return config
49
50 @classmethod
51 def update_iscsi_config(cls, config):
52 """
53 Since `ceph-iscsi` config v10, gateway names were renamed from host short name to FQDN.
54 If Ceph Dashboard were configured before v10, we try to update our internal gateways
55 database automatically.
56 """
57 for gateway_name, gateway_config in config['gateways'].items():
58 if '.' not in gateway_name:
59 from ..rest_client import RequestException
60 from .iscsi_client import IscsiClient # pylint: disable=cyclic-import
61 try:
62 service_url = gateway_config['service_url']
63 new_gateway_name = IscsiClient.instance(
64 service_url=service_url).get_hostname()['data']
65 if gateway_name != new_gateway_name:
66 config['gateways'][new_gateway_name] = gateway_config
67 del config['gateways'][gateway_name]
68 cls._save_config(config)
69 except RequestException:
70 # If gateway is not acessible, it should be removed manually
71 # or we will try to update automatically next time
72 continue
73
74 @classmethod
75 def _save_config(cls, config):
76 mgr.set_store(_ISCSI_STORE_KEY, json.dumps(config))
77
78 @classmethod
79 def validate_service_url(cls, service_url):
80 url = urlparse(service_url)
81 if not url.scheme or not url.hostname or not url.username or not url.password:
82 raise InvalidServiceUrl(service_url)
83
84 @classmethod
85 def add_gateway(cls, name, service_url):
86 config = cls.get_gateways_config()
87 if name in config:
88 raise IscsiGatewayAlreadyExists(name)
89 IscsiGatewaysConfig.validate_service_url(service_url)
90 config['gateways'][name] = {'service_url': service_url}
91 cls._save_config(config)
92
93 @classmethod
94 def remove_gateway(cls, name):
95 config = cls._load_config_from_store()
96 if name not in config['gateways']:
97 raise IscsiGatewayDoesNotExist(name)
98
99 del config['gateways'][name]
100 cls._save_config(config)
101
102 @classmethod
103 def get_gateways_config(cls):
104 return cls._load_config_from_store()
105
106 @classmethod
107 def get_gateway_config(cls, name):
108 config = IscsiGatewaysConfig.get_gateways_config()
109 if name not in config['gateways']:
110 raise IscsiGatewayDoesNotExist(name)
111 return config['gateways'][name]