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