0a1f94733155d3a31ac88e508eaf57d195b1d784
1 # -*- coding: utf-8 -*-
3 # Copyright 2021 Whitestack, LLC
4 # *************************************************************
6 # This file is part of OSM Monitoring module
7 # All Rights Reserved to Whitestack, LLC
9 # Licensed under the Apache License, Version 2.0 (the "License"); you may
10 # not use this file except in compliance with the License. You may obtain
11 # a copy of the License at
13 # http://www.apache.org/licenses/LICENSE-2.0
15 # Unless required by applicable law or agreed to in writing, software
16 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
17 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
18 # License for the specific language governing permissions and limitations
20 # For those usages not covered by the Apache License, Version 2.0 please
21 # contact: glavado@whitestack.com or fbravo@whitestack.com
25 from osm_mon
.core
.common_db
import CommonDbClient
26 from osm_mon
.core
.config
import Config
27 from osm_mon
.core
.keystone
import KeystoneConnection
28 from osm_mon
.dashboarder
.backends
.grafana
import GrafanaBackend
29 from osm_mon
import __path__
as mon_path
30 from osm_mon
.core
.utils
import find_in_list
, create_filter_from_nsr
32 log
= logging
.getLogger(__name__
)
35 class DashboarderService
:
36 def __init__(self
, config
: Config
):
38 self
.common_db
= CommonDbClient(self
.conf
)
39 self
.grafana
= GrafanaBackend(self
.conf
)
41 if bool(self
.conf
.get("keystone", "enabled")):
42 self
.keystone
= KeystoneConnection(self
.conf
)
46 def create_dashboards(self
):
47 # TODO lavado: migrate these methods to mongo change streams
48 # Lists all dashboards and OSM resources for later comparisons
49 dashboard_uids
= self
.grafana
.get_all_dashboard_uids()
50 osm_resource_uids
= []
53 # Check if keystone is the auth/projects backend and get projects from there
58 lambda project
: {"_id": project
.id, "name": project
.name
},
59 self
.keystone
.getProjects(),
63 log
.error("Cannot retrieve projects from keystone")
65 projects
.extend(self
.common_db
.get_projects())
67 # Reads existing project list and creates a dashboard for each
68 for project
in projects
:
69 project_id
= project
["_id"]
70 # Collect Project IDs for periodical dashboard clean-up
71 osm_resource_uids
.append(project_id
)
72 dashboard_path
= "{}/dashboarder/templates/project_scoped.json".format(
75 if project_id
not in dashboard_uids
:
76 project_name
= project
["name"]
77 if project_name
!= "admin":
78 # Create project folder in Grafana only if user is not admin.
79 # Admin user's dashboard will be created in default folder
80 self
.grafana
.create_grafana_folders(project_name
)
81 self
.grafana
.create_dashboard(project_id
, project_name
, dashboard_path
)
82 log
.debug("Created dashboard for Project: %s", project_id
)
84 log
.debug("Dashboard already exists")
86 # Reads existing NS list and creates a dashboard for each
87 # TODO lavado: only create for ACTIVE NSRs
88 nsrs
= self
.common_db
.get_nsrs()
91 dashboard_path
= "{}/dashboarder/templates/ns_scoped.json".format(
94 # Collect NS IDs for periodical dashboard clean-up
95 osm_resource_uids
.append(nsr_id
)
96 # Check if the NSR's VNFDs contain metrics
97 # Only one DF at the moment, support for this feature is comming in the future
98 vnfds_profiles
= nsr
["nsd"]["df"][0]["vnf-profile"]
99 for vnf_profile
in vnfds_profiles
:
101 vnfd
= self
.common_db
.get_vnfd_by_id(
102 vnf_profile
["vnfd-id"], create_filter_from_nsr(nsr
)
104 # If there are metrics, create dashboard (if exists)
105 vdu_found
= find_in_list(
106 vnfd
["vdu"], lambda a_vdu
: "monitoring-parameter" in a_vdu
109 if nsr_id
not in dashboard_uids
:
110 nsr_name
= nsr
["name"]
111 project_id
= nsr
["_admin"]["projects_read"][0]
113 # Get project details from commondb
114 project_details
= self
.common_db
.get_project(project_id
)
115 project_name
= project_details
["name"]
116 except Exception as e
:
117 # Project not found in commondb
119 # Serach project in keystone
120 for project
in projects
:
121 if project_id
== project
["_id"]:
122 project_name
= project
["name"]
124 log
.info("Project %s not found", project_id
)
125 log
.debug("Exception %s" % e
)
126 self
.grafana
.create_dashboard(
127 nsr_id
, nsr_name
, dashboard_path
, project_name
129 log
.debug("Created dashboard for NS: %s", nsr_id
)
131 log
.debug("Dashboard already exists")
134 log
.debug("NS does not has metrics")
136 log
.exception("VNFD is not valid or has been renamed")
139 # Delete obsolete dashboards
140 for dashboard_uid
in dashboard_uids
:
141 if dashboard_uid
not in osm_resource_uids
:
142 self
.grafana
.delete_dashboard(dashboard_uid
)
143 log
.debug("Deleted obsolete dashboard: %s", dashboard_uid
)
145 log
.debug("All dashboards in use")
147 def create_grafana_user(self
, user
):
148 self
.grafana
.create_grafana_users(user
)
150 def delete_non_existing_users(self
):
152 # Get users from keystone
153 users
= self
.keystone
.getUsers()
156 usernames
.append(user
.name
)
157 grafana_users
= self
.grafana
.get_grafana_users()
158 users_to_be_deleted
= list(set(grafana_users
) - set(usernames
))
159 for grafana_user
in users_to_be_deleted
:
160 self
.grafana
.delete_grafana_users(grafana_user
)
162 def create_grafana_team_member(
163 self
, project_data
, userid
=None, project_list
=None, user
=None
169 # Get user details from commondb
170 user
= self
.common_db
.get_user_by_id(userid
)
171 user_name
= user
["username"]
172 except Exception as e
:
173 # User not found in commondb
175 # Search user in keystone
176 user
= self
.keystone
.getUserById(userid
)
177 user_name
= user
.name
179 log
.info("User %s not found", userid
)
180 log
.debug("Exception %s" % e
)
182 # user-project mapping is done by osm cli
183 for proj
in project_data
:
184 project
= self
.common_db
.get_project(proj
["project"])
185 proj_name
= project
["name"]
186 role_obj
= self
.common_db
.get_role_by_id(proj
["role"])
187 is_admin
= role_obj
["permissions"].get("admin")
188 self
.grafana
.create_grafana_teams_members(
189 proj_name
, user_name
, is_admin
, project_list
192 # user-project mapping is done by osm ui
195 users_proj_list
= self
.keystone
.getProjectsById(userid
)
196 for project
in users_proj_list
:
197 proj_list
.append(project
.name
)
199 users_proj_list
= user
.get("project_role_mappings")
200 for project
in users_proj_list
:
201 proj_data
= self
.common_db
.get_project(project
["project"])
202 proj_list
.append(proj_data
["name"])
203 for proj
in project_data
:
205 # Backend authentication type is keystone
207 # Getting project and role objects from keystone using ids
208 role_obj
= self
.keystone
.getRoleById(proj
["role"])
209 proj_data
= self
.keystone
.getProjectsByProjectId(
213 "role object {} {}".format(
214 role_obj
.permissions
, proj_data
.name
217 is_admin
= role_obj
.permissions
["admin"]
219 # Getting project and role objects from keystone using names
220 role_obj
= self
.keystone
.getRoleByName(proj
["role"])[0]
221 proj_data
= self
.keystone
.getProjectsByProjectName(
224 is_admin
= role_obj
.to_dict().get("permissions").get("admin")
226 "role object {} {}".format(
227 role_obj
.to_dict(), proj_data
.name
230 proj_name
= proj_data
.name
232 # Backend authentication type is internal
234 # Getting project and role object from commondb using names
235 role_obj
= self
.common_db
.get_role_by_name(proj
["role"])
236 proj_name
= proj
["project"]
238 # Getting project and role object from commondb using ids
239 role_obj
= self
.common_db
.get_role_by_id(proj
["role"])
240 proj_data
= self
.common_db
.get_project(proj
["project"])
241 proj_name
= proj_data
["name"]
242 is_admin
= role_obj
["permissions"].get("admin")
243 self
.grafana
.create_grafana_teams_members(
244 proj_name
, user_name
, is_admin
, proj_list
247 def create_grafana_team(self
, team_name
):
248 self
.grafana
.create_grafana_teams(team_name
)
250 def delete_grafana_user(self
, user_name
):
251 self
.grafana
.delete_grafana_users(user_name
)
253 def delete_grafana_team(self
, project_name
):
254 self
.grafana
.delete_grafana_team(project_name
)
256 def update_grafana_team(self
, project_new_name
, project_old_name
):
257 self
.grafana
.update_grafana_teams(project_new_name
, project_old_name
)
259 def remove_grafana_team_members(self
, user_id
, proj_data
):
261 # Get user details from commondb
262 user
= self
.common_db
.get_user_by_id(user_id
)
263 user_name
= user
["username"]
264 except Exception as e
:
265 # User not found in commondb
267 # Find user in keystone
268 user
= self
.keystone
.getUserById(user_id
)
269 user_name
= user
.name
271 log
.info("User %s not found", user_id
)
272 log
.debug("Exception %s" % e
)
273 self
.grafana
.remove_grafana_team_member(user_name
, proj_data
)