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
57 map(lambda project
: {'_id': project
.id, 'name': project
.name
}, self
.keystone
.getProjects())
60 log
.error('Cannot retrieve projects from keystone')
62 projects
.extend(self
.common_db
.get_projects())
64 # Reads existing project list and creates a dashboard for each
65 for project
in projects
:
66 project_id
= project
['_id']
67 # Collect Project IDs for periodical dashboard clean-up
68 osm_resource_uids
.append(project_id
)
69 dashboard_path
= '{}/dashboarder/templates/project_scoped.json'.format(mon_path
[0])
70 if project_id
not in dashboard_uids
:
71 project_name
= project
['name']
72 if project_name
!= "admin":
73 # Create project folder in Grafana only if user is not admin.
74 # Admin user's dashboard will be created in default folder
75 self
.grafana
.create_grafana_folders(project_name
)
76 self
.grafana
.create_dashboard(project_id
, project_name
,
78 log
.debug('Created dashboard for Project: %s', project_id
)
80 log
.debug('Dashboard already exists')
82 # Reads existing NS list and creates a dashboard for each
83 # TODO lavado: only create for ACTIVE NSRs
84 nsrs
= self
.common_db
.get_nsrs()
87 dashboard_path
= '{}/dashboarder/templates/ns_scoped.json'.format(mon_path
[0])
88 # Collect NS IDs for periodical dashboard clean-up
89 osm_resource_uids
.append(nsr_id
)
90 # Check if the NSR's VNFDs contain metrics
91 # Only one DF at the moment, support for this feature is comming in the future
92 vnfds_profiles
= nsr
['nsd']["df"][0]['vnf-profile']
93 for vnf_profile
in vnfds_profiles
:
95 vnfd
= self
.common_db
.get_vnfd_by_id(vnf_profile
['vnfd-id'], create_filter_from_nsr(nsr
))
96 # If there are metrics, create dashboard (if exists)
97 vdu_found
= find_in_list(vnfd
["vdu"], lambda a_vdu
: "monitoring-parameter" in a_vdu
)
99 if nsr_id
not in dashboard_uids
:
100 nsr_name
= nsr
['name']
101 project_id
= nsr
["_admin"]["projects_read"][0]
103 # Get project details from commondb
104 project_details
= self
.common_db
.get_project(project_id
)
105 project_name
= project_details
["name"]
106 except Exception as e
:
107 # Project not found in commondb
109 # Serach project in keystone
110 for project
in projects
:
111 if project_id
== project
['_id']:
112 project_name
= project
["name"]
114 log
.info('Project %s not found', project_id
)
115 log
.debug('Exception %s' % e
)
116 self
.grafana
.create_dashboard(nsr_id
, nsr_name
,
117 dashboard_path
, project_name
)
118 log
.debug('Created dashboard for NS: %s', nsr_id
)
120 log
.debug('Dashboard already exists')
123 log
.debug('NS does not has metrics')
125 log
.exception("VNFD is not valid or has been renamed")
128 # Delete obsolete dashboards
129 for dashboard_uid
in dashboard_uids
:
130 if dashboard_uid
not in osm_resource_uids
:
131 self
.grafana
.delete_dashboard(dashboard_uid
)
132 log
.debug('Deleted obsolete dashboard: %s', dashboard_uid
)
134 log
.debug('All dashboards in use')
136 def create_grafana_user(self
, user
):
137 self
.grafana
.create_grafana_users(user
)
139 def create_grafana_team_member(self
, project_data
, userid
=None, project_list
=None, user
=None):
144 # Get user details from commondb
145 user
= self
.common_db
.get_user_by_id(userid
)
146 user_name
= user
["username"]
147 except Exception as e
:
148 # User not found in commondb
150 # Search user in keystone
151 user
= self
.keystone
.getUserById(userid
)
152 user_name
= user
.name
154 log
.info('User %s not found', userid
)
155 log
.debug('Exception %s' % e
)
157 # user-project mapping is done by osm cli
158 for proj
in project_data
:
159 project
= self
.common_db
.get_project(proj
["project"])
160 proj_name
= project
['name']
161 role_obj
= self
.common_db
.get_role_by_id(proj
["role"])
162 is_admin
= role_obj
["permissions"].get("admin")
163 self
.grafana
.create_grafana_teams_members(proj_name
, user_name
, is_admin
, project_list
)
165 # user-project mapping is done by osm ui
168 users_proj_list
= self
.keystone
.getProjectsById(userid
)
169 for project
in users_proj_list
:
170 proj_list
.append(project
.name
)
172 users_proj_list
= user
.get("project_role_mappings")
173 for project
in users_proj_list
:
174 proj_data
= self
.common_db
.get_project(project
["project"])
175 proj_list
.append(proj_data
['name'])
176 for proj
in project_data
:
178 # Backend authentication type is keystone
180 # Getting project and role objects from keystone using ids
181 role_obj
= self
.keystone
.getRoleById(proj
["role"])
182 proj_data
= self
.keystone
.getProjectsByProjectId(proj
["project"])
183 log
.info('role object {} {}'.format(role_obj
.permissions
, proj_data
.name
))
184 is_admin
= role_obj
.permissions
['admin']
186 # Getting project and role objects from keystone using names
187 role_obj
= self
.keystone
.getRoleByName(proj
["role"])[0]
188 proj_data
= self
.keystone
.getProjectsByProjectName(proj
["project"])[0]
189 is_admin
= role_obj
.to_dict().get("permissions").get('admin')
190 log
.info('role object {} {}'.format(role_obj
.to_dict(), proj_data
.name
))
191 proj_name
= proj_data
.name
193 # Backend authentication type is internal
195 # Getting project and role object from commondb using names
196 role_obj
= self
.common_db
.get_role_by_name(proj
["role"])
197 proj_name
= proj
["project"]
199 # Getting project and role object from commondb using ids
200 role_obj
= self
.common_db
.get_role_by_id(proj
["role"])
201 proj_data
= self
.common_db
.get_project(proj
["project"])
202 proj_name
= proj_data
['name']
203 is_admin
= role_obj
["permissions"].get("admin")
204 self
.grafana
.create_grafana_teams_members(proj_name
, user_name
, is_admin
, proj_list
)
206 def create_grafana_team(self
, team_name
):
207 self
.grafana
.create_grafana_teams(team_name
)
209 def delete_grafana_user(self
, user_name
):
210 self
.grafana
.delete_grafana_users(user_name
)
212 def delete_grafana_team(self
, project_name
):
213 self
.grafana
.delete_grafana_team(project_name
)
215 def update_grafana_team(self
, project_new_name
, project_old_name
):
216 self
.grafana
.update_grafana_teams(project_new_name
, project_old_name
)
218 def remove_grafana_team_members(self
, user_id
, proj_data
):
220 # Get user details from commondb
221 user
= self
.common_db
.get_user_by_id(user_id
)
222 user_name
= user
["username"]
223 except Exception as e
:
224 # User not found in commondb
226 # Find user in keystone
227 user
= self
.keystone
.getUserById(user_id
)
228 user_name
= user
.name
230 log
.info('User %s not found', user_id
)
231 log
.debug('Exception %s' % e
)
232 self
.grafana
.remove_grafana_team_member(user_name
, proj_data
)