@@ -56,40 +56,93 @@ def _proxy(self, method, base_url, path, params=None, payload=None, verify=False
5656 def auth (self , url : str , cluster_alias : str , username : str ,
5757 password = None , token = None , hub_url = None , cluster_fsid = None ,
5858 prometheus_api_url = None , ssl_verify = False , ssl_certificate = None ):
59+ try :
60+ hub_fsid = mgr .get ('config' )['fsid' ]
61+ except KeyError :
62+ hub_fsid = ''
63+
5964 if password :
6065 payload = {
6166 'username' : username ,
6267 'password' : password
6368 }
64- content = self ._proxy ('POST' , url , 'api/auth' , payload = payload )
65- if 'token' not in content :
66- raise DashboardException (
67- "Could not authenticate to remote cluster" ,
68- http_status_code = 400 ,
69- component = 'dashboard' )
70-
71- cluster_token = content ['token' ]
69+ cluster_token = self .check_cluster_connection (url , payload , username ,
70+ ssl_verify , ssl_certificate )
7271
7372 self ._proxy ('PUT' , url , 'ui-api/multi-cluster/set_cors_endpoint' ,
7473 payload = {'url' : hub_url }, token = cluster_token , verify = ssl_verify ,
7574 cert = ssl_certificate )
75+
7676 fsid = self ._proxy ('GET' , url , 'api/health/get_cluster_fsid' , token = cluster_token )
7777
78+ managed_by_clusters_content = self ._proxy ('GET' , url ,
79+ 'api/settings/MANAGED_BY_CLUSTERS' ,
80+ token = cluster_token )
81+
82+ managed_by_clusters_config = managed_by_clusters_content ['value' ]
83+
84+ if managed_by_clusters_config is not None :
85+ managed_by_clusters_config .append ({'url' : hub_url , 'fsid' : hub_fsid })
86+
87+ self ._proxy ('PUT' , url , 'api/settings/MANAGED_BY_CLUSTERS' ,
88+ payload = {'value' : managed_by_clusters_config }, token = cluster_token ,
89+ verify = ssl_verify , cert = ssl_certificate )
90+
7891 # add prometheus targets
7992 prometheus_url = self ._proxy ('GET' , url , 'api/settings/PROMETHEUS_API_HOST' ,
8093 token = cluster_token )
94+
8195 _set_prometheus_targets (prometheus_url ['value' ])
8296
8397 self .set_multi_cluster_config (fsid , username , url , cluster_alias ,
8498 cluster_token , prometheus_url ['value' ],
8599 ssl_verify , ssl_certificate )
86- return
100+ return True
87101
88102 if token and cluster_fsid and prometheus_api_url :
89103 _set_prometheus_targets (prometheus_api_url )
90104 self .set_multi_cluster_config (cluster_fsid , username , url ,
91105 cluster_alias , token , prometheus_api_url ,
92106 ssl_verify , ssl_certificate )
107+ return True
108+
109+ def check_cluster_connection (self , url , payload , username , ssl_verify , ssl_certificate ):
110+ try :
111+ content = self ._proxy ('POST' , url , 'api/auth' , payload = payload ,
112+ verify = ssl_verify , cert = ssl_certificate )
113+ if 'token' not in content :
114+ raise DashboardException (msg = content ['detail' ], code = 'invalid_credentials' ,
115+ component = 'multi-cluster' )
116+
117+ user_content = self ._proxy ('GET' , url , f'api/user/{ username } ' ,
118+ token = content ['token' ])
119+
120+ if 'status' in user_content and user_content ['status' ] == '403 Forbidden' :
121+ raise DashboardException (msg = 'User is not an administrator' ,
122+ code = 'invalid_permission' , component = 'multi-cluster' )
123+ if 'roles' in user_content and 'administrator' not in user_content ['roles' ]:
124+ raise DashboardException (msg = 'User is not an administrator' ,
125+ code = 'invalid_permission' , component = 'multi-cluster' )
126+
127+ except Exception as e :
128+ if '[Errno 111] Connection refused' in str (e ):
129+ raise DashboardException (msg = 'Connection refused' ,
130+ code = 'connection_refused' , component = 'multi-cluster' )
131+ raise DashboardException (msg = str (e ), code = 'connection_failed' ,
132+ component = 'multi-cluster' )
133+
134+ cluster_token = content ['token' ]
135+
136+ managed_by_clusters_content = self ._proxy ('GET' , url , 'api/settings/MANAGED_BY_CLUSTERS' ,
137+ token = cluster_token )
138+
139+ managed_by_clusters_config = managed_by_clusters_content ['value' ]
140+
141+ if len (managed_by_clusters_config ) > 1 :
142+ raise DashboardException (msg = 'Cluster is already managed by another cluster' ,
143+ code = 'cluster_managed_by_another_cluster' ,
144+ component = 'multi-cluster' )
145+ return cluster_token
93146
94147 def set_multi_cluster_config (self , fsid , username , url , cluster_alias , token ,
95148 prometheus_url = None , ssl_verify = False , ssl_certificate = None ):
@@ -144,7 +197,7 @@ def set_config(self, config: object):
144197
145198 @Endpoint ('PUT' )
146199 @UpdatePermission
147- # pylint: disable=unused-variable
200+ # pylint: disable=W0613
148201 def reconnect_cluster (self , url : str , username = None , password = None , token = None ,
149202 ssl_verify = False , ssl_certificate = None ):
150203 multicluster_config = self .load_multi_cluster_config ()
@@ -153,24 +206,18 @@ def reconnect_cluster(self, url: str, username=None, password=None, token=None,
153206 'username' : username ,
154207 'password' : password
155208 }
156- content = self ._proxy ('POST' , url , 'api/auth' , payload = payload ,
157- verify = ssl_verify , cert = ssl_certificate )
158- if 'token' not in content :
159- raise DashboardException (
160- "Could not authenticate to remote cluster" ,
161- http_status_code = 400 ,
162- component = 'dashboard' )
163209
164- token = content ['token' ]
210+ cluster_token = self .check_cluster_connection (url , payload , username ,
211+ ssl_verify , ssl_certificate )
165212
166- if username and token :
213+ if username and cluster_token :
167214 if "config" in multicluster_config :
168215 for _ , cluster_details in multicluster_config ["config" ].items ():
169216 for cluster in cluster_details :
170217 if cluster ["url" ] == url and cluster ["user" ] == username :
171- cluster ['token' ] = token
218+ cluster ['token' ] = cluster_token
172219 Settings .MULTICLUSTER_CONFIG = multicluster_config
173- return Settings . MULTICLUSTER_CONFIG
220+ return True
174221
175222 @Endpoint ('PUT' )
176223 @UpdatePermission
@@ -189,10 +236,17 @@ def edit_cluster(self, url, cluster_alias, username):
189236 @DeletePermission
190237 def delete_cluster (self , cluster_name , cluster_user ):
191238 multicluster_config = self .load_multi_cluster_config ()
239+ try :
240+ hub_fsid = mgr .get ('config' )['fsid' ]
241+ except KeyError :
242+ hub_fsid = ''
192243 if "config" in multicluster_config :
193244 for key , value in list (multicluster_config ['config' ].items ()):
194245 if value [0 ]['name' ] == cluster_name and value [0 ]['user' ] == cluster_user :
195-
246+ cluster_url = value [0 ]['url' ]
247+ cluster_token = value [0 ]['token' ]
248+ cluster_ssl_certificate = value [0 ]['ssl_certificate' ]
249+ cluster_ssl_verify = value [0 ]['ssl_verify' ]
196250 orch_backend = mgr .get_module_option_ex ('orchestrator' , 'orchestrator' )
197251 try :
198252 if orch_backend == 'cephadm' :
@@ -204,55 +258,25 @@ def delete_cluster(self, cluster_name, cluster_user):
204258 except KeyError :
205259 pass
206260
261+ managed_by_clusters_content = self ._proxy ('GET' , cluster_url ,
262+ 'api/settings/MANAGED_BY_CLUSTERS' ,
263+ token = cluster_token )
264+
265+ managed_by_clusters_config = managed_by_clusters_content ['value' ]
266+ for cluster in managed_by_clusters_config :
267+ if cluster ['fsid' ] == hub_fsid :
268+ managed_by_clusters_config .remove (cluster )
269+
270+ self ._proxy ('PUT' , cluster_url , 'api/settings/MANAGED_BY_CLUSTERS' ,
271+ payload = {'value' : managed_by_clusters_config }, token = cluster_token ,
272+ verify = cluster_ssl_verify , cert = cluster_ssl_certificate )
273+
207274 del multicluster_config ['config' ][key ]
208275 break
209276
210277 Settings .MULTICLUSTER_CONFIG = multicluster_config
211278 return Settings .MULTICLUSTER_CONFIG
212279
213- @Endpoint ('POST' )
214- @CreatePermission
215- # pylint: disable=R0911
216- def verify_connection (self , url = None , username = None , password = None , token = None ,
217- ssl_verify = False , ssl_certificate = None ):
218- if token :
219- try :
220- payload = {
221- 'token' : token
222- }
223- content = self ._proxy ('POST' , url , 'api/auth/check' , payload = payload ,
224- verify = ssl_verify , cert = ssl_certificate )
225- if 'permissions' not in content :
226- return content ['detail' ]
227- user_content = self ._proxy ('GET' , url , f'api/user/{ username } ' ,
228- token = content ['token' ])
229- if 'status' in user_content and user_content ['status' ] == '403 Forbidden' :
230- return 'User is not an administrator'
231- except Exception as e : # pylint: disable=broad-except
232- if '[Errno 111] Connection refused' in str (e ):
233- return 'Connection refused'
234- return 'Connection failed'
235-
236- if username and password :
237- try :
238- payload = {
239- 'username' : username ,
240- 'password' : password
241- }
242- content = self ._proxy ('POST' , url , 'api/auth' , payload = payload ,
243- verify = ssl_verify , cert = ssl_certificate )
244- if 'token' not in content :
245- return content ['detail' ]
246- user_content = self ._proxy ('GET' , url , f'api/user/{ username } ' ,
247- token = content ['token' ])
248- if 'status' in user_content and user_content ['status' ] == '403 Forbidden' :
249- return 'User is not an administrator'
250- except Exception as e : # pylint: disable=broad-except
251- if '[Errno 111] Connection refused' in str (e ):
252- return 'Connection refused'
253- return 'Connection failed'
254- return 'Connection successful'
255-
256280 @Endpoint ()
257281 @ReadPermission
258282 def get_config (self ):
0 commit comments