def reports(request, certname=None): context = { 'timezones': pytz.common_timezones, 'SOURCES': AVAILABLE_SOURCES } if request.method == 'GET': if 'source' in request.GET: source = request.GET.get('source') set_server(request, source) if request.method == 'POST': request.session['django_timezone'] = request.POST['timezone'] return redirect(request.POST['return_url']) source_url, source_certs, source_verify = get_server(request) # Redirects to the events page if GET param latest is true.. if request.GET.get('latest', False): if request.GET.get('latest') == "true": latest_report_params = { 'query': { 1: '["=","certname","' + certname + '"]' }, 'order-by': { 'order-field': { 'field': 'start-time', 'order': 'desc', }, 'query-field': { 'field': 'certname' }, }, 'limit': 1, } latest_report = puppetdb.api_get( api_url=source_url, cert=source_certs, verify=source_verify, path='/reports', api_version='v4', params=puppetdb.mk_puppetdb_query(latest_report_params, request), ) report_hash = "" # If latest reports do not exist, send to the nodes page # Should only occur if the user is trying to hax their way # into a node without having the correct permission if latest_report: for report in latest_report: report_env = report['environment'] report_hash = report['hash'] return redirect('/pano/events/' + report_hash + '?report_timestamp=' + request.GET.get('report_timestamp') + '&envname=' + report_env) else: return redirect('/pano/nodes/') context['certname'] = certname context['node_facts'] = ','.join(NODES_DEFAULT_FACTS) return render(request, 'pano/reports.html', context)
def facts(request, certname=None): context = {'timezones': pytz.common_timezones, 'SOURCES': AVAILABLE_SOURCES} if request.method == 'GET': if 'source' in request.GET: source = request.GET.get('source') set_server(request, source) if request.method == 'POST': request.session['django_timezone'] = request.POST['timezone'] return redirect(request.POST['return_url']) source_url, source_certs, source_verify = get_server(request) facts_params = { 'query': { 1: '["=","certname","' + certname + '"]' }, } facts_list = puppetdb.api_get( api_url=source_url, cert=source_certs, verify=source_verify, path='facts', params=puppetdb.mk_puppetdb_query( facts_params, request), ) context['certname'] = certname context['facts_list'] = facts_list return render(request, 'pano/facts.html', context)
def reports(request, certname=None): context = {'timezones': pytz.common_timezones, 'SOURCES': AVAILABLE_SOURCES} if request.method == 'GET': if 'source' in request.GET: source = request.GET.get('source') set_server(request, source) if request.method == 'POST': request.session['django_timezone'] = request.POST['timezone'] return redirect(request.POST['return_url']) source_url, source_certs, source_verify = get_server(request) # Redirects to the events page if GET param latest is true.. if request.GET.get('latest', False): if request.GET.get('latest') == "true": request.session['report_page'] = 1 latest_report_params = { 'query': { 1: '["=","certname","' + certname + '"]' }, 'order_by': { 'order_field': { 'field': 'start_time', 'order': 'desc', }, }, 'limit': 1, } latest_report = puppetdb.api_get( api_url=source_url, cert=source_certs, verify=source_verify, path='/reports', api_version='v4', params=puppetdb.mk_puppetdb_query(latest_report_params, request), ) report_hash = "" # If latest reports do not exist, send to the nodes page # Should only occur if the user is trying to hax their way # into a node without having the correct permission if latest_report: for report in latest_report: report_env = report['environment'] report_hash = report['hash'] return redirect('/pano/events/' + report_hash + '?report_timestamp=' + request.GET.get( 'report_timestamp') + '&envname=' + report_env) else: return redirect('/pano/nodes/') if certname != request.session.get('last_shown_node', ''): request.session['last_shown_node'] = certname request.session['report_page'] = 1 context['certname'] = certname context['node_facts'] = ','.join(NODES_DEFAULT_FACTS) return render(request, 'pano/reports.html', context)
def facts(request, certname=None): context = { 'timezones': pytz.common_timezones, 'SOURCES': AVAILABLE_SOURCES } if request.method == 'GET': if 'source' in request.GET: source = request.GET.get('source') set_server(request, source) if request.method == 'POST': request.session['django_timezone'] = request.POST['timezone'] return redirect(request.POST['return_url']) source_url, source_certs, source_verify = get_server(request) facts_params = { 'query': { 1: '["=","certname","' + certname + '"]' }, } facts_list = puppetdb.api_get( api_url=source_url, cert=source_certs, verify=source_verify, path='facts', params=puppetdb.mk_puppetdb_query(facts_params, request), ) context['certname'] = certname context['facts_list'] = facts_list return render(request, 'pano/facts.html', context)
def nodes(request): results = SavedQueries.objects.filter(username=request.user.get_username()) if not results.exists(): results = False context = { 'timezones': pytz.common_timezones, 'SOURCES': AVAILABLE_SOURCES, 'saved_queries': results } if request.method == 'GET': if 'source' in request.GET: source = request.GET.get('source') set_server(request, source) elif 'load_query' in request.GET: request.session['search'] = request.GET.get( 'load_query', request.session['search']) return redirect('nodes') elif request.method == 'POST': if 'timezone' in request.POST: request.session['django_timezone'] = request.POST['timezone'] return redirect(request.POST['return_url']) else: return HttpResponseBadRequest('Invalid POST request.') return render(request, 'pano/nodes.html', context)
def nodes(request): results = SavedQueries.objects.filter(username=request.user.get_username()) if not results.exists(): results = False context = {'timezones': pytz.common_timezones, 'SOURCES': AVAILABLE_SOURCES, 'saved_queries': results} if request.method == 'GET': if 'source' in request.GET: source = request.GET.get('source') set_server(request, source) elif 'load_query' in request.GET: request.session['search'] = request.GET.get('load_query', request.session.get('search', '')) return redirect('nodes') elif 'quick_search' in request.GET: node_name = request.GET.get('quick_search') if node_name: request.session['search'] = '["and",["in","certname",["extract","certname",["select_nodes",["and",["~","certname","%s"]]]]]]' % node_name.strip() return redirect('nodes') elif request.method == 'POST': if 'timezone' in request.POST: request.session['django_timezone'] = request.POST['timezone'] return redirect(request.POST['return_url']) else: return HttpResponseBadRequest('Invalid POST request.') return render(request, 'pano/nodes.html', context)
def facts_json(request): context = {} if request.method == "GET": if "source" in request.GET: source = request.GET.get("source") set_server(request, source) if request.method == "POST": request.session["django_timezone"] = request.POST["timezone"] return redirect(request.POST["return_url"]) source_url, source_certs, source_verify = get_server(request) certname = None facts = None if "certname" in request.GET: certname = request.GET.get("certname") if "facts" in request.GET: facts = request.GET.get("facts").split(",") if not certname: context["error"] = "Certname not specified." return HttpResponse(json.dumps(context)) if facts: # validate string for illegal chars fact_query = list() for fact in facts: fact = fact.strip() # Match for characters that are not a-Z or 0-9 or _ # if theres a match illegal chars exist... regex = re.compile(r"[^aA-zZ0-9_]") matches = regex.findall(fact) if matches: context["error"] = "Illegal characters found in facts list. " context["error"] += "Facts must not match anything withddd this regex <[^aA-zZ0-9_]>." return HttpResponse(json.dumps(context)) fact_query.append('["=","name","' + fact + '"]') fact_query = ",".join(fact_query) facts_params = { "query": {1: '["and",["=","certname","' + certname + '"],["or",' + fact_query + "]]"}, "order-by": {"order_field": {"field": "name", "order": "asc"}}, } else: facts_params = { "query": {1: '["=","certname","' + certname + '"]'}, "order_by": {"order-field": {"field": "name", "order": "asc"}}, } facts_list = puppetdb.api_get( api_url=source_url, cert=source_certs, verify=source_verify, path="facts", params=puppetdb.mk_puppetdb_query(facts_params, request), ) context["certname"] = certname context["facts_list"] = facts_list return HttpResponse(json.dumps(context), content_type="application/json")
def event_analytics(request, view='summary'): context = {'timezones': pytz.common_timezones, 'SOURCES': AVAILABLE_SOURCES} if request.method == 'GET': if 'source' in request.GET: source = request.GET.get('source') set_server(request, source) if request.method == 'POST': request.session['django_timezone'] = request.POST['timezone'] return redirect(request.POST['return_url']) summary = events.get_events_summary(timespan='latest', request=request) context['summary'] = summary # Show Classes if request.GET.get('value', False): if view == 'classes': class_name = request.GET.get('value') title = "Class: %s" % class_name class_events = events.get_report(key='containing_class', value=class_name, request=request) context['events'] = class_events # Show Nodes elif view == 'nodes': node_name = request.GET.get('value') title = "Node: %s" % node_name node_events = events.get_report(key='certname', value=node_name, request=request) context['events'] = node_events # Show Resources elif view == 'resources': resource_name = request.GET.get('value') title = "Resource: %s" % resource_name resource_events = events.get_report(key='resource_title', value=resource_name, request=request) context['events'] = resource_events # Show Types elif view == 'types': type_name = request.GET.get('value') title = "Type: %s" % type_name type_events = events.get_report(key='resource_type', value=type_name, request=request) context['events'] = type_events # Show summary if none of the above matched else: sum_avail = ['classes', 'nodes', 'resources', 'types'] stat_avail = ['failed', 'noop', 'success', 'skipped' ''] show_summary = request.GET.get('show_summary', 'classes') show_status = request.GET.get('show_status', 'failed') if show_summary in sum_avail and show_status in stat_avail: title = "%s with status %s" % (show_summary.capitalize(), show_status.capitalize()) context['show_title'] = title else: title = 'Failed Classes' context['show_title'] = title return render(request, 'pano/analytics/events_details.html', context) # Add title to context context['show_title'] = title # if the above went well and did not reach the else clause we can also return the awesome. return render(request, 'pano/analytics/events_inspect.html', context)
def nodes(request): context = default_context if request.method == 'GET': if 'source' in request.GET: source = request.GET.get('source') set_server(request, source) if request.method == 'POST': request.session['django_timezone'] = request.POST['timezone'] return redirect(request.POST['return_url']) return render(request, 'pano/nodes.html', context)
def dashboard(request): context = {'timezones': pytz.common_timezones, 'SOURCES': AVAILABLE_SOURCES} if request.method == 'GET': if 'source' in request.GET: source = request.GET.get('source') set_server(request, source) if request.method == 'POST': request.session['django_timezone'] = request.POST['timezone'] return redirect(request.POST['url']) return render(request, 'pano/dashboard.html', context)
def dashboard(request): context = { 'timezones': pytz.common_timezones, 'SOURCES': AVAILABLE_SOURCES } if request.method == 'GET': if 'source' in request.GET: source = request.GET.get('source') set_server(request, source) if request.method == 'POST': request.session['django_timezone'] = request.POST['timezone'] return redirect(request.POST['url']) return render(request, 'pano/dashboard.html', context)
def radiator(request, certname=None): context = {'timezones': pytz.common_timezones, 'SOURCES': AVAILABLE_SOURCES} if request.method == 'GET': if 'source' in request.GET: source = request.GET.get('source') set_server(request, source) if request.method == 'POST': request.session['django_timezone'] = request.POST['timezone'] return redirect(request.POST['return_url']) context['certname'] = certname context['node_facts'] = ','.join(NODES_DEFAULT_FACTS) return render(request, 'pano/radiator.html', context)
def agent_logs(request, certname=None, report_hash=None): context = {'timezones': pytz.common_timezones, 'SOURCES': AVAILABLE_SOURCES} if request.method == 'GET': if 'source' in request.GET: source = request.GET.get('source') set_server(request, source) if request.method == 'POST': request.session['django_timezone'] = request.POST['timezone'] return redirect(request.POST['return_url']) context['certname'] = certname context['report_hash'] = report_hash return render(request, 'pano/report_agent_logs.html', context)
def radiator(request, certname=None): context = { 'timezones': pytz.common_timezones, 'SOURCES': AVAILABLE_SOURCES } if request.method == 'GET': if 'source' in request.GET: source = request.GET.get('source') set_server(request, source) if request.method == 'POST': request.session['django_timezone'] = request.POST['timezone'] return redirect(request.POST['return_url']) context['certname'] = certname context['node_facts'] = ','.join(NODES_DEFAULT_FACTS) return render(request, 'pano/radiator.html', context)
def catalog(request): context = { 'timezones': pytz.common_timezones, 'SOURCES': AVAILABLE_SOURCES } if request.method == 'GET': if 'source' in request.GET: source = request.GET.get('source') set_server(request, source) elif request.method == 'POST': if 'timezone' in request.POST: request.session['django_timezone'] = request.POST['timezone'] return redirect(request.POST['return_url']) else: return HttpResponseBadRequest('Invalid POST request.') return render(request, 'pano/catalogue.html', context)
def splash(request): context = default_context if request.method == 'GET': if 'source' in request.GET: source = request.GET.get('source') set_server(request, source) if request.method == 'POST': if 'timezone' in request.POST: request.session['django_timezone'] = request.POST['timezone'] return redirect(request.POST['url']) elif 'username' in request.POST and 'password' in request.POST: username = request.POST['username'] password = request.POST['password'] user = authenticate(username=username, password=password) next_url = False if 'nexturl' in request.POST: next_url = request.POST['nexturl'] if user is not None: if user.is_active: login(request, user) if next_url: return redirect(next_url) else: return redirect('dashboard') else: context['login_error'] = "Account is disabled." context['nexturl'] = next_url return render(request, 'pano/splash.html', context) else: # Return an 'invalid login' error message. context['login_error'] = "Invalid credentials" context['nexturl'] = next_url return render(request, 'pano/splash.html', context) return redirect('dashboard') user = request.user.username context['username'] = user return render(request, 'pano/splash.html', context)
def dashboard_nodes_json(request): context = {} if request.method == 'GET': if 'source' in request.GET: source = request.GET.get('source') set_server(request, source) if request.method == 'POST': request.session['django_timezone'] = request.POST['timezone'] return redirect(request.POST['return_url']) source_url, source_certs, source_verify = get_server(request) puppet_run_time = get_server(request, type='run_time') # Dashboard to show nodes of "recent, failed, unreported or changed" dashboard_show = request.GET.get('show', 'recent') events_params = { 'query': { 1: '["and",["=","latest_report?",true],["in", "certname",["extract", "certname",["select_nodes",["null?","deactivated",true]]]]]' }, 'summarize_by': 'certname', } all_nodes_params = { 'query': { 1: '["and",["=","latest_report?",true],["in", "certname",["extract", "certname",["select_nodes",["null?","deactivated",true]]]]]' }, } reports_params = { 'query': { 1: '["and",["=","latest_report?",true],["in", "certname",["extract", "certname",["select_nodes",["null?","deactivated",true]]]]]' } } nodes_params = { 'limit': 25, 'order_by': { 'order_field': { 'field': 'report_timestamp', 'order': 'desc', }, 'query_field': {'field': 'certname'}, }, } jobs = { 'all_nodes': { 'url': source_url, 'certs': source_certs, 'verify': source_verify, 'api_version': 'v4', 'id': 'all_nodes', 'path': '/nodes', 'request': request }, 'events': { 'url': source_url, 'certs': source_certs, 'verify': source_verify, 'id': 'event_counts', 'path': 'event-counts', 'api_version': 'v4', 'params': events_params, 'request': request }, 'nodes': { 'url': source_url, 'certs': source_certs, 'verify': source_verify, 'api_version': 'v4', 'id': 'nodes', 'path': '/nodes', 'params': nodes_params, 'request': request }, 'reports': { 'url': source_url, 'certs': source_certs, 'verify': source_verify, 'api_version': 'v4', 'id': 'reports', 'path': '/reports', 'params': reports_params, 'request': request }, } puppetdb_results = run_puppetdb_jobs(jobs) # Information about all active nodes in puppet all_nodes_list = puppetdb_results['all_nodes'] all_nodes_dict = {item['certname']: item for item in all_nodes_list} # All available events for the latest puppet reports event_list = puppetdb_results['event_counts'] event_dict = {item['subject']['title']: item for item in event_list} # All of the latest reports reports_list = puppetdb_results['reports'] reports_dict = {item['certname']: item for item in reports_list} # 25 Nodes node_list = puppetdb_results['nodes'] node_dict = {item['certname']: item for item in node_list} failed_list, changed_list, unreported_list, mismatch_list, pending_list = dictstatus(all_nodes_dict, reports_dict, event_dict, sort=True, sortby='latestReport', get_status='notall', puppet_run_time=puppet_run_time) pending_list = [x for x in pending_list if x not in unreported_list] changed_list = [x for x in changed_list if x not in unreported_list and x not in failed_list and x not in pending_list] failed_list = [x for x in failed_list if x not in unreported_list] unreported_list = [x for x in unreported_list if x not in failed_list] if dashboard_show == 'recent': merged_nodes_list = dictstatus( node_dict, reports_dict, event_dict, sort=False, get_status="all", puppet_run_time=puppet_run_time) elif dashboard_show == 'failed': merged_nodes_list = failed_list elif dashboard_show == 'unreported': merged_nodes_list = unreported_list elif dashboard_show == 'changed': merged_nodes_list = changed_list elif dashboard_show == 'mismatch': merged_nodes_list = mismatch_list elif dashboard_show == 'pending': merged_nodes_list = pending_list else: merged_nodes_list = dictstatus( node_dict, reports_dict, event_dict, sort=False, get_status="all", puppet_run_time=puppet_run_time) context['node_list'] = merged_nodes_list context['selected_view'] = dashboard_show return HttpResponse(json.dumps(context), content_type="application/json")
def splash(request): context = {'timezones': pytz.common_timezones, 'SOURCES': AVAILABLE_SOURCES} if request.method == 'GET': if 'source' in request.GET: source = request.GET.get('source') set_server(request, source) if request.method == 'POST': if 'timezone' in request.POST: request.session['django_timezone'] = request.POST['timezone'] return redirect(request.POST['url']) elif 'username' in request.POST and 'password' in request.POST: username = request.POST['username'] password = request.POST['password'] user = authenticate(username=username, password=password) next_url = False if 'nexturl' in request.POST: next_url = request.POST['nexturl'] if user is not None: if user.is_active: login(request, user) # Work out the permissions for this user based on ldap groups if AUTH_METHOD == 'ldap' and user.backend == 'django_auth_ldap.backend.LDAPBackend' and ENABLE_PERMISSIONS: ldap_user = user.ldap_user ldap_user_groups = ldap_user.group_dns base_query = ['["and",["or"'] for group in ldap_user_groups: results = LdapGroupPermissions.objects.filter(ldap_group_name=group) if results.exists(): value = results.values() value = value[0]['puppetdb_query'] base_query.append(value) if len(base_query) == 1: if user.is_staff or user.is_superuser: request.session['permission_filter'] = False else: request.session['permission_filter'] = None else: if user.is_staff or user.is_superuser: request.session['permission_filter'] = False else: request.session['permission_filter'] = ','.join(base_query) + ']]' if next_url: return redirect(next_url) else: return redirect('dashboard') else: context['login_error'] = "Account is disabled." context['nexturl'] = next_url return render(request, 'pano/splash.html', context) else: # Return an 'invalid login' error message. context['login_error'] = "Invalid credentials" context['nexturl'] = next_url return render(request, 'pano/splash.html', context) return redirect('dashboard') user = request.user.username context['username'] = user return render(request, 'pano/splash.html', context)
def nodes_json(request): if request.method == 'GET': if 'source' in request.GET: source = request.GET.get('source') set_server(request, source) if request.method == 'POST': request.session['django_timezone'] = request.POST['timezone'] return redirect(request.POST['return_url']) source_url, source_certs, source_verify = get_server(request) valid_sort_fields = ('certname', 'catalog_timestamp', 'report_timestamp', 'facts_timestamp', 'successes', 'noops', 'failures', 'skips') try: # If user requested to download csv formatted file. Default value is False dl_csv = request.GET.get('dl_csv', False) if dl_csv == 'true': dl_csv = True else: dl_csv = False # Add limits to session if request.GET.get('limits', False): if request.session['limits'] != int(request.GET.get('limits', 50)): request.session['limits'] = int(request.GET.get('limits', 50)) if request.session['limits'] <= 0: request.session['limits'] = 50 else: if 'limits' not in request.session: request.session['limits'] = 50 # Cur Page Number if request.GET.get('page', False): if request.session['page'] != int(request.GET.get('page', 1)): request.session['page'] = int(request.GET.get('page', 1)) if request.session['page'] <= 0: request.session['page'] = 1 else: if 'page' not in request.session: request.session['page'] = 1 # Cur sort field if request.GET.get('sortfield', False): if request.session['sortfield'] != request.GET.get('sortfield'): request.session['sortfield'] = request.GET.get('sortfield') if request.session['sortfield'] not in valid_sort_fields: request.session['sortfield'] = 'report_timestamp' else: if 'sortfield' not in request.session: request.session['sortfield'] = 'report_timestamp' # Cur sort order if request.GET.get('sortfieldby', False): avail_sortorder = ['asc', 'desc'] if request.session['sortfieldby'] != request.GET.get( 'sortfieldby'): request.session['sortfieldby'] = request.GET.get('sortfieldby') if request.session['sortfieldby'] not in avail_sortorder: request.session['sortfieldby'] = 'desc' else: if 'sortfieldby' not in request.session: request.session['sortfieldby'] = 'desc' # Search parameters takes a valid puppetdb query string if request.GET.get('search', False): if 'search' in request.session and (request.session['search'] == request.GET.get('search')): pass else: if request.GET.get('search') == 'clear_rules': request.session['sortfield'] = 'report_timestamp' request.session['sortfieldby'] = 'desc' request.session['page'] = 1 request.session['search'] = None else: request.session['page'] = 1 request.session['search'] = request.GET.get('search') else: if 'search' not in request.session: request.session['sortfield'] = 'report_timestamp' request.session['sortfieldby'] = 'desc' request.session['page'] = 1 request.session['search'] = None # Set offset request.session['offset'] = ( request.session['limits'] * request.session['page']) - request.session['limits'] except: return HttpResponseBadRequest('Oh no! Your filters were invalid.') # Valid sort field that the user can search agnaist. sort_field = request.session['sortfield'] sort_field_order = request.session['sortfieldby'] page_num = request.session['page'] if request.session['search'] is not None: node_params = { 'query': { 1: request.session['search'] }, } else: node_params = { 'query': {}, } nodes_sort_fields = [ 'certname', 'catalog_timestamp', 'report_timestamp', 'facts_timestamp' ] if sort_field in nodes_sort_fields: node_params['order_by'] = { 'order_field': { 'field': sort_field, 'order': sort_field_order, }, } if dl_csv is False: node_params['limit'] = request.session['limits'] node_params['offset'] = request.session['offset'] node_params['include_total'] = 'true' else: node_params['order_by'] = { 'order_field': { 'field': 'report_timestamp', 'order': 'desc', }, } node_sort_fields = [ 'certname', 'catalog_timestamp', 'report_timestamp', 'facts_timestamp' ] if sort_field in node_sort_fields: try: node_list, node_headers = puppetdb.api_get( api_url=source_url, cert=source_certs, verify=source_verify, path='/nodes', api_version='v4', params=puppetdb.mk_puppetdb_query(node_params, request), ) except: node_list = [] node_headers = dict() node_headers['X-Records'] = 0 else: node_list = puppetdb.api_get( api_url=source_url, cert=source_certs, verify=source_verify, path='/nodes', api_version='v4', params=puppetdb.mk_puppetdb_query(node_params, request), ) # Work out the number of pages from the xrecords response # return fields that you can sort by # for each node in the node_list, find out if the latest run has any failures # v3/event-counts --data-urlencode query='["=","latest-report?",true]' # --data-urlencode summarize-by='certname' report_params = { 'query': { 1: '["and",["=","latest_report?",true],["in", "certname",["extract", "certname",["select_nodes",["null?","deactivated",true]]]]]' }, 'summarize_by': 'certname', } status_sort_fields = ['successes', 'failures', 'skips', 'noops'] report_status_params = { 'query': { 1: '["and",["=","latest_report?",true],["in", "certname",["extract", "certname",["select_nodes",["null?","deactivated",true]]]]]' } } report_status_list = puppetdb.api_get( api_url=source_url, cert=source_certs, verify=source_verify, path='/reports', params=puppetdb.mk_puppetdb_query(report_status_params, request), api_version='v4', ) if sort_field in status_sort_fields: if request.session['search'] is not None: report_params['query'] = { 'operator': 'and', 1: request.session['search'], 2: '["=","latest_report?",true]', 3: '["in", "certname",["extract", "certname",["select_nodes",["null?","deactivated",true]]]]', } report_params['order_by'] = { 'order_field': { 'field': sort_field, 'order': sort_field_order, } } report_params['include_total'] = 'true' # Don't limit results if its CSV if dl_csv is False: report_params['limit'] = request.session['limits'] report_params['offset'] = request.session['offset'] report_list, report_headers = puppetdb.api_get( api_url=source_url, cert=source_certs, verify=source_verify, path='/event-counts', params=puppetdb.mk_puppetdb_query(report_params, request), api_version='v4', ) else: report_list = puppetdb.api_get( api_url=source_url, cert=source_certs, verify=source_verify, path='event-counts', params=puppetdb.mk_puppetdb_query(report_params, request), api_version='v4', ) # number of results depending on sort field. if sort_field in status_sort_fields: xrecords = report_headers['X-Records'] total_results = xrecords elif sort_field in nodes_sort_fields: xrecords = node_headers['X-Records'] total_results = xrecords num_pages_wdec = float(xrecords) / request.session['limits'] num_pages_wodec = float("{:.0f}".format(num_pages_wdec)) if num_pages_wdec > num_pages_wodec: num_pages = num_pages_wodec + 1 else: num_pages = num_pages_wodec # Converts lists of dicts to dicts. node_dict = {item['certname']: item for item in node_list} status_dict = {item['certname']: item for item in report_status_list} report_dict = {item['subject']['title']: item for item in report_list} if sort_field_order == 'desc': rows = dictstatus(node_dict, status_dict, report_dict, sortby=sort_field, asc=True, sort=False) sort_field_order_opposite = 'asc' elif sort_field_order == 'asc': rows = dictstatus(node_dict, status_dict, report_dict, sortby=sort_field, asc=False, sort=False) sort_field_order_opposite = 'desc' if dl_csv is True: if rows is []: pass else: # Generate a sequence of rows. The range is based on the maximum number of # rows that can be handled by a single sheet in most spreadsheet # applications. include_facts = request.GET.get('include_facts', False) csv_headers = [ 'Certname', 'Latest Catalog', 'Latest Report', 'Latest Facts', 'Success', 'Noop', 'Failure', 'Skipped' ] if include_facts is not False: merged_list_facts = [] facts = {} for fact in include_facts.split(','): # Sanitize the fact input from the user fact = fact.strip() # Add the fact name to the headers list csv_headers.append(fact) # build the params for each fact. facts_params = { 'query': { 1: '["=","name","' + fact + '"]' }, } fact_list = puppetdb.api_get( api_url=source_url, cert=source_certs, verify=source_verify, path='facts', params=puppetdb.mk_puppetdb_query(facts_params), api_version='v4', ) # Populate the facts dict with the facts we have retrieved # Convert the fact list into a fact dict! facts[fact] = { item['certname']: item for item in fact_list } i = 1 jobs = {} # Add ID to each job so that it can be assembled in # the same order after we recieve the job results # We do this via jobs so that we can get faster results. for node in rows: jobs[i] = { 'id': i, 'include_facts': include_facts.split(','), 'node': node, 'facts': facts, } i += 1 csv_results = generate_csv(jobs) rows = [] i = 1 # with the job results we can now recreate merged_list # in the order we sent them. while i <= len(csv_results): rows.append(csv_results[i]) i += 1 # Insert the csv header to the top of the list. rows.insert(0, csv_headers) pseudo_buffer = Echo() writer = csv.writer(pseudo_buffer) response = StreamingHttpResponse( (writer.writerow(row) for row in rows), content_type="text/csv") response[ 'Content-Disposition'] = 'attachment; filename="puppetdata-%s.csv"' % ( datetime.datetime.now()) return response """ c_r_s* = current request sort c_r_* = current req r_s* = requests available """ context = { 'nodeList': rows, 'total_nodes': total_results, 'c_r_page': page_num, 'c_r_limit': request.session['limits'], 'r_sfield': valid_sort_fields, 'c_r_sfield': sort_field, 'r_sfieldby': ['asc', 'desc'], 'c_r_sfieldby': sort_field_order, 'c_r_sfieldby_o': sort_field_order_opposite, 'tot_pages': '{0:g}'.format(num_pages), } return HttpResponse(json.dumps(context), content_type="application/json")
def analytics(request): context = { 'timezones': pytz.common_timezones, 'SOURCES': AVAILABLE_SOURCES } if request.method == 'GET': if 'source' in request.GET: source = request.GET.get('source') set_server(request, source) if request.method == 'POST': request.session['django_timezone'] = request.POST['timezone'] return redirect(request.POST['return_url']) source_url, source_certs, source_verify = get_server(request) events_class_params = { 'query': { 1: '["and",["=","latest_report?",true],["in","certname",["extract","certname",["select_nodes",["null?","deactivated",true]]]]]' }, 'summarize_by': 'containing_class', } events_resource_params = { 'query': { 1: '["and",["=","latest_report?",true],["in","certname",["extract","certname",["select_nodes",["null?","deactivated",true]]]]]' }, 'summarize_by': 'resource', } events_status_params = { 'query': { 1: '["and",["=","latest_report?",true],["in","certname",["extract","certname",["select_nodes",["null?","deactivated",true]]]]]' }, 'summarize_by': 'resource', } reports_runavg_params = { 'limit': 100, 'order_by': { 'order_field': { 'field': 'receive_time', 'order': 'desc', }, 'query_field': { 'field': 'certname' }, }, } jobs = { 'events_class_list': { 'url': source_url, 'certs': source_certs, 'verify': source_verify, 'id': 'events_class_list', 'path': '/event-counts', 'api_version': 'v4', 'params': events_class_params, 'request': request }, 'events_resource_list': { 'url': source_url, 'certs': source_certs, 'verify': source_verify, 'id': 'events_resource_list', 'path': '/event-counts', 'api_version': 'v4', 'params': events_resource_params, 'request': request }, 'events_status_list': { 'url': source_url, 'certs': source_certs, 'verify': source_verify, 'id': 'events_status_list', 'path': '/aggregate-event-counts', 'api_version': 'v4', 'params': events_status_params, 'request': request }, 'reports_run_avg': { 'url': source_url, 'certs': source_certs, 'verify': source_verify, 'id': 'reports_run_avg', 'path': '/reports', 'api_version': 'v4', 'params': reports_runavg_params, 'request': request }, } job_results = run_puppetdb_jobs(jobs, 4) reports_run_avg = job_results['reports_run_avg'] events_class_list = job_results['events_class_list'] events_resource_list = job_results['events_resource_list'] events_status_list = job_results['events_status_list'] num_runs_avg = len(reports_run_avg) run_avg_times = [] avg_run_time = 0 for report in reports_run_avg: run_time = "{0:.0f}".format( (json_to_datetime(report['end_time']) - json_to_datetime(report['start_time'])).total_seconds()) avg_run_time += int(run_time) run_avg_times.append(run_time) if num_runs_avg != 0: avg_run_time = "{0:.0f}".format(avg_run_time / num_runs_avg) else: avg_run_time = 0 class_event_results = [] class_resource_results = [] class_status_results = [] for item in events_class_list: class_name = item['subject']['title'] class_total = item['skips'] + item['failures'] + item['noops'] + item[ 'successes'] class_event_results.append((class_name, class_total)) for item in events_resource_list: class_name = item['subject']['type'] class_total = item['skips'] + item['failures'] + item['noops'] + item[ 'successes'] class_resource_results.append((class_name, class_total)) print(events_status_list) if events_status_list: for status, value in events_status_list[0].items(): print(status, value) if value is 0 or status == 'total' or status == 'summarize_by': continue class_status_results.append((status, value)) context['class_events'] = class_event_results context['class_status'] = class_status_results context['resource_events'] = class_resource_results context['run_times'] = run_avg_times context['run_num'] = num_runs_avg context['run_avg'] = avg_run_time return render(request, 'pano/analytics/analytics.html', context)
def facts_json(request): context = {} if request.method == 'GET': if 'source' in request.GET: source = request.GET.get('source') set_server(request, source) if request.method == 'POST': request.session['django_timezone'] = request.POST['timezone'] return redirect(request.POST['return_url']) source_url, source_certs, source_verify = get_server(request) certname = None facts = None if 'certname' in request.GET: certname = request.GET.get('certname') if 'facts' in request.GET: facts = request.GET.get('facts').split(',') if not certname: context['error'] = 'Certname not specified.' return HttpResponse(json.dumps(context)) if facts: # validate string for illegal chars fact_query = list() for fact in facts: fact = fact.strip() # Match for characters that are not a-Z or 0-9 or _ # if theres a match illegal chars exist... regex = re.compile(r'[^aA-zZ0-9_]') matches = regex.findall(fact) if matches: context['error'] = 'Illegal characters found in facts list. ' context[ 'error'] += 'Facts must not match anything withddd this regex <[^aA-zZ0-9_]>.' return HttpResponse(json.dumps(context)) fact_query.append('["=","name","' + fact + '"]') fact_query = ','.join(fact_query) facts_params = { 'query': { 1: '["and",["=","certname","' + certname + '"],["or",' + fact_query + ']]' }, 'order-by': { 'order_field': { 'field': 'name', 'order': 'asc', } } } else: facts_params = { 'query': { 1: '["=","certname","' + certname + '"]' }, 'order_by': { 'order-field': { 'field': 'name', 'order': 'asc', } } } facts_list = puppetdb.api_get( api_url=source_url, cert=source_certs, verify=source_verify, path='facts', params=puppetdb.mk_puppetdb_query(facts_params, request), ) context['certname'] = certname context['facts_list'] = facts_list return HttpResponse(json.dumps(context), content_type="application/json")
def event_analytics(request, view='summary'): context = {'timezones': pytz.common_timezones, 'SOURCES': AVAILABLE_SOURCES} if request.method == 'GET': if 'source' in request.GET: source = request.GET.get('source') set_server(request, source) if request.method == 'POST': request.session['django_timezone'] = request.POST['timezone'] return redirect(request.POST['return_url']) arrow_from = False arrow_to = False user_tz = request.session.get('django_timezone', TIME_ZONE) if request.GET.get('dt_from', False): try: dt_from = datetime.strptime(request.GET.get('dt_from'), '%Y-%m-%d %H:%M') except ValueError: err_msg = 'Invalid from date (%s) provided.' % request.GET.get('dt_from') return HttpResponseBadRequest(err_msg) arrow_from = arrow.get(dt_from, user_tz).isoformat() if request.GET.get('dt_to', False): try: dt_to = datetime.strptime(request.GET.get('dt_to'), '%Y-%m-%d %H:%M') except ValueError: err_msg = 'Invalid to date (%s) provided.' % request.GET.get('dt_to') return HttpResponseBadRequest(err_msg) arrow_to = arrow.get(dt_to, user_tz).isoformat() timespan = 'latest' # If date retrieval was alright then we can set the timespan to that of data input. if arrow_from and arrow_to: timespan = [arrow_from, arrow_to] print(timespan) # Get summary data summary = events.get_events_summary(timespan=timespan, request=request) context['summary'] = summary # Show Classes if request.GET.get('value', False): if view == 'classes': class_name = request.GET.get('value') title = "Class: %s" % class_name class_events = events.get_report(key='containing-class', value=class_name, timespan=timespan, request=request) context['events'] = class_events # Show Nodes elif view == 'nodes': node_name = request.GET.get('value') title = "Node: %s" % node_name node_events = events.get_report(key='certname', value=node_name, timespan=timespan, request=request) context['events'] = node_events # Show Resources elif view == 'resources': resource_name = request.GET.get('value') title = "Resource: %s" % resource_name resource_events = events.get_report(key='resource_title', value=resource_name, timespan=timespan, request=request) context['events'] = resource_events # Show Types elif view == 'types': type_name = request.GET.get('value') title = "Type: %s" % type_name type_events = events.get_report(key='resource_type', value=type_name, timespan=timespan, request=request) context['events'] = type_events # Show summary if none of the above matched else: sum_avail = ['classes', 'nodes', 'resources', 'types'] stat_avail = ['failed', 'noop', 'success', 'skipped' ''] show_summary = request.GET.get('show_summary', 'classes') show_status = request.GET.get('show_status', 'failed') if show_summary in sum_avail and show_status in stat_avail: title = "%s with status %s" % (show_summary.capitalize(), show_status.capitalize()) context['show_title'] = title else: title = 'Classes with status Failed' context['show_title'] = title return render(request, 'pano/analytics/events_details.html', context) # Add title to context context['show_title'] = title # if the above went well and did not reach the else clause we can also return the awesome. return render(request, 'pano/analytics/events_inspect.html', context)
def facts_json(request): context = {} if request.method == 'GET': if 'source' in request.GET: source = request.GET.get('source') set_server(request, source) if request.method == 'POST': request.session['django_timezone'] = request.POST['timezone'] return redirect(request.POST['return_url']) source_url, source_certs, source_verify = get_server(request) certname = None facts = None if 'certname' in request.GET: certname = request.GET.get('certname') if 'facts' in request.GET: facts = request.GET.get('facts').split(',') if not certname: context['error'] = 'Certname not specified.' return HttpResponse(json.dumps(context)) if facts: # validate string for illegal chars fact_query = list() for fact in facts: fact = fact.strip() # Match for characters that are not a-Z or 0-9 or _ # if theres a match illegal chars exist... regex = re.compile(r'[^aA-zZ0-9_]') matches = regex.findall(fact) if matches: context['error'] = 'Illegal characters found in facts list. ' context['error'] += 'Facts must not match anything withddd this regex <[^aA-zZ0-9_]>.' return HttpResponse(json.dumps(context)) fact_query.append('["=","name","' + fact + '"]') fact_query = ','.join(fact_query) facts_params = { 'query': { 1: '["and",["=","certname","' + certname + '"],["or",' + fact_query + ']]' }, 'order-by': { 'order_field': { 'field': 'name', 'order': 'asc', } } } else: facts_params = { 'query': { 1: '["=","certname","' + certname + '"]' }, 'order_by': { 'order-field': { 'field': 'name', 'order': 'asc', } } } facts_list = puppetdb.api_get( api_url=source_url, cert=source_certs, verify=source_verify, path='facts', params=puppetdb.mk_puppetdb_query( facts_params, request), ) context['certname'] = certname context['facts_list'] = facts_list return HttpResponse(json.dumps(context, indent=2), content_type="application/json")
def detailed_events(request, hashid=None): context = { 'timezones': pytz.common_timezones, 'SOURCES': AVAILABLE_SOURCES } if request.method == 'GET': if 'source' in request.GET: source = request.GET.get('source') set_server(request, source) if request.method == 'POST': request.session['django_timezone'] = request.POST['timezone'] return redirect(request.POST['return_url']) source_url, source_certs, source_verify = get_server(request) report_timestamp = request.GET.get('report_timestamp') events_params = { 'query': { 1: '["=","report","' + hashid + '"]' }, 'order_by': { 'order_field': { 'field': 'timestamp', 'order': 'asc', }, 'query_field': { 'field': 'certname' }, }, } events_list = puppetdb.api_get( api_url=source_url, cert=source_certs, verify=source_verify, path='/events', api_version='v4', params=puppetdb.mk_puppetdb_query(events_params), ) environment = '' certname = '' event_execution_times = [] sorted_events = None last_event_time = None last_event_title = None run_end_time = None if len(events_list) != 0: single_event = events_list[0] environment = single_event['environment'] certname = single_event['certname'] for event in events_list: event_title = event['resource_title'] event_start_time = json_to_datetime(event['timestamp']) if last_event_time is None and last_event_title is None: last_event_time = event_start_time last_event_title = event_title run_end_time = json_to_datetime(event['run_end_time']) continue else: event_exec_time = (event_start_time - last_event_time).total_seconds() add_event = (last_event_title, event_exec_time) event_execution_times.append(add_event) last_event_time = event_start_time last_event_title = event_title event_exec_time = (last_event_time - run_end_time).total_seconds() add_event = [last_event_title, event_exec_time] event_execution_times.append(add_event) sorted_events = sorted(event_execution_times, reverse=True, key=lambda field: field[1]) if len(sorted_events) > 10: sorted_events = sorted_events[:10] else: events_list = False context['certname'] = certname context['report_timestamp'] = report_timestamp context['hashid'] = hashid context['events_list'] = events_list context['event_durations'] = sorted_events context['environment'] = environment return render(request, 'pano/detailed_events.html', context)
def analytics(request): context = {'timezones': pytz.common_timezones, 'SOURCES': AVAILABLE_SOURCES} if request.method == 'GET': if 'source' in request.GET: source = request.GET.get('source') set_server(request, source) if request.method == 'POST': request.session['django_timezone'] = request.POST['timezone'] return redirect(request.POST['return_url']) source_url, source_certs, source_verify = get_server(request) events_class_params = { 'query': { 1: '["and",["=","latest_report?",true],["in","certname",["extract","certname",["select_nodes",["null?","deactivated",true]]]]]' }, 'summarize_by': 'containing_class', } events_resource_params = { 'query': { 1: '["and",["=","latest_report?",true],["in","certname",["extract","certname",["select_nodes",["null?","deactivated",true]]]]]' }, 'summarize_by': 'resource', } events_status_params = { 'query': { 1: '["and",["=","latest_report?",true],["in","certname",["extract","certname",["select_nodes",["null?","deactivated",true]]]]]' }, 'summarize_by': 'resource', } reports_runavg_params = { 'limit': 100, 'order_by': { 'order_field': { 'field': 'receive_time', 'order': 'desc', }, 'query_field': {'field': 'certname'}, }, } jobs = { 'events_class_list': { 'url': source_url, 'certs': source_certs, 'verify': source_verify, 'id': 'events_class_list', 'path': '/event-counts', 'api_version': 'v4', 'params': events_class_params, 'request': request }, 'events_resource_list': { 'url': source_url, 'certs': source_certs, 'verify': source_verify, 'id': 'events_resource_list', 'path': '/event-counts', 'api_version': 'v4', 'params': events_resource_params, 'request': request }, 'events_status_list': { 'url': source_url, 'certs': source_certs, 'verify': source_verify, 'id': 'events_status_list', 'path': '/aggregate-event-counts', 'api_version': 'v4', 'params': events_status_params, 'request': request }, 'reports_run_avg': { 'url': source_url, 'certs': source_certs, 'verify': source_verify, 'id': 'reports_run_avg', 'path': '/reports', 'api_version': 'v4', 'params': reports_runavg_params, 'request': request }, } job_results = run_puppetdb_jobs(jobs, 4) reports_run_avg = job_results['reports_run_avg'] events_class_list = job_results['events_class_list'] events_resource_list = job_results['events_resource_list'] events_status_list = job_results['events_status_list'] num_runs_avg = len(reports_run_avg) run_avg_times = [] avg_run_time = 0 for report in reports_run_avg: run_time = "{0:.0f}".format( (json_to_datetime(report['end_time']) - json_to_datetime(report['start_time'])).total_seconds()) avg_run_time += int(run_time) run_avg_times.append(run_time) if num_runs_avg != 0: avg_run_time = "{0:.0f}".format(avg_run_time / num_runs_avg) else: avg_run_time = 0 class_event_results = [] class_resource_results = [] class_status_results = [] for item in events_class_list: class_name = item['subject']['title'] class_total = item['skips'] + item['failures'] + item['noops'] + item['successes'] class_event_results.append((class_name, class_total)) for item in events_resource_list: class_name = item['subject']['type'] class_total = item['skips'] + item['failures'] + item['noops'] + item['successes'] class_resource_results.append((class_name, class_total)) print(events_status_list) if events_status_list: for status, value in events_status_list[0].items(): print(status, value) if value is 0 or status == 'total' or status == 'summarize_by': continue class_status_results.append((status, value)) context['class_events'] = class_event_results context['class_status'] = class_status_results context['resource_events'] = class_resource_results context['run_times'] = run_avg_times context['run_num'] = num_runs_avg context['run_avg'] = avg_run_time return render(request, 'pano/analytics/analytics.html', context)
def detailed_events(request, hashid=None): context = {'timezones': pytz.common_timezones, 'SOURCES': AVAILABLE_SOURCES} if request.method == 'GET': if 'source' in request.GET: source = request.GET.get('source') set_server(request, source) if request.method == 'POST': request.session['django_timezone'] = request.POST['timezone'] return redirect(request.POST['return_url']) source_url, source_certs, source_verify = get_server(request) report_timestamp = request.GET.get('report_timestamp') events_params = { 'query': { 1: '["=","report","' + hashid + '"]' }, 'order_by': { 'order_field': { 'field': 'timestamp', 'order': 'asc', }, 'query_field': {'field': 'certname'}, }, } events_list = puppetdb.api_get( api_url=source_url, cert=source_certs, verify=source_verify, path='/events', api_version='v4', params=puppetdb.mk_puppetdb_query(events_params), ) environment = '' certname = '' event_execution_times = [] sorted_events = None last_event_time = None last_event_title = None run_end_time = None if len(events_list) != 0: single_event = events_list[0] environment = single_event['environment'] certname = single_event['certname'] for event in events_list: event_title = event['resource_title'] event_start_time = json_to_datetime(event['timestamp']) if last_event_time is None and last_event_title is None: last_event_time = event_start_time last_event_title = event_title run_end_time = json_to_datetime(event['run_end_time']) continue else: event_exec_time = (event_start_time - last_event_time).total_seconds() add_event = (last_event_title, event_exec_time) event_execution_times.append(add_event) last_event_time = event_start_time last_event_title = event_title event_exec_time = (last_event_time - run_end_time).total_seconds() add_event = [last_event_title, event_exec_time] event_execution_times.append(add_event) sorted_events = sorted(event_execution_times, reverse=True, key=lambda field: field[1]) if len(sorted_events) > 10: sorted_events = sorted_events[:10] else: events_list = False context['certname'] = certname context['report_timestamp'] = report_timestamp context['hashid'] = hashid context['events_list'] = events_list context['event_durations'] = sorted_events context['environment'] = environment return render(request, 'pano/detailed_events.html', context)
def dashboard(request, certname=None): context = default_context if request.method == 'GET': if 'source' in request.GET: source = request.GET.get('source') set_server(request, source) if request.method == 'POST': request.session['django_timezone'] = request.POST['timezone'] return redirect(request.POST['url']) source_url, source_certs, source_verify = get_server(request) puppet_run_time = get_server(request, type='run_time') events_params = { 'query': { 1: '["and",["=","latest-report?",true],["in", "certname",["extract", "certname",["select-nodes",["null?","deactivated",true]]]]]' }, 'summarize-by': 'certname', } nodes_params = { 'limit': 25, 'order-by': { 'order-field': { 'field': 'report-timestamp', 'order': 'desc', }, 'query-field': {'field': 'certname'}, }, } jobs = { 'population': { 'url': source_url, 'certs': source_certs, 'verify': source_verify, 'id': 'population', 'path': '/metrics/mbean/com.puppetlabs.puppetdb.query.population:type=default,name=num-nodes', }, 'tot_resource': { 'url': source_url, 'certs': source_certs, 'verify': source_verify, 'id': 'tot_resource', 'path': '/metrics/mbean/com.puppetlabs.puppetdb.query.population:type=default,name=num-resources', }, 'avg_resource': { 'url': source_url, 'certs': source_certs, 'verify': source_verify, 'id': 'avg_resource', 'path': '/metrics/mbean/com.puppetlabs.puppetdb.query.population:type=default,name=avg-resources-per-node', }, 'all_nodes': { 'url': source_url, 'certs': source_certs, 'verify': source_verify, 'api_version': 'v4', 'id': 'all_nodes', 'path': '/nodes', }, 'events': { 'url': source_url, 'certs': source_certs, 'verify': source_verify, 'id': 'event-counts', 'path': 'event-counts', 'api_version': 'v4', 'params': events_params, }, 'nodes': { 'url': source_url, 'certs': source_certs, 'verify': source_verify, 'api_version': 'v4', 'id': 'nodes', 'path': '/nodes', 'params': nodes_params, }, } puppetdb_results = run_puppetdb_jobs(jobs) # Dashboard to show nodes of "recent, failed, unreported or changed" dashboard_show = request.GET.get('show', 'recent') # Assign vars from the completed jobs puppet_population = puppetdb_results['population'] # Total resources managed by puppet metric total_resources = puppetdb_results['tot_resource'] # Average resource per node metric avg_resource_node = puppetdb_results['avg_resource'] # Information about all active nodes in puppet all_nodes_list = puppetdb_results['all_nodes'] # All available events for the latest puppet reports event_list = puppetdb_results['event-counts'] node_list = puppetdb_results['nodes'] failed_list, changed_list, unreported_list, mismatch_list, pending_list = dictstatus(all_nodes_list, event_list, sort=True, sortby='latestReport', get_status='notall', puppet_run_time=puppet_run_time) pending_list = [x for x in pending_list if x not in unreported_list] changed_list = [x for x in changed_list if x not in unreported_list and x not in failed_list and x not in pending_list] failed_list = [x for x in failed_list if x not in unreported_list] unreported_list = [x for x in unreported_list if x not in failed_list] if dashboard_show == 'recent': merged_nodes_list = dictstatus( node_list, event_list, sort=False, get_status="all", puppet_run_time=puppet_run_time) elif dashboard_show == 'failed': merged_nodes_list = failed_list elif dashboard_show == 'unreported': merged_nodes_list = unreported_list elif dashboard_show == 'changed': merged_nodes_list = changed_list elif dashboard_show == 'failed_catalogs': merged_nodes_list = mismatch_list elif dashboard_show == 'pending': merged_nodes_list = pending_list else: merged_nodes_list = dictstatus( node_list, event_list, sort=False, get_status="all", puppet_run_time=puppet_run_time) node_unreported_count = len(unreported_list) node_fail_count = len(failed_list) node_change_count = len(changed_list) node_off_timestamps_count = len(mismatch_list) node_pending_count = len(pending_list) context['node_list'] = merged_nodes_list context['certname'] = certname context['show_nodes'] = dashboard_show context['population'] = puppet_population['Value'] context['total_resource'] = total_resources['Value'] context['avg_resource'] = "{:.2f}".format(avg_resource_node['Value']) context['failed_nodes'] = node_fail_count context['changed_nodes'] = node_change_count context['unreported_nodes'] = node_unreported_count context['weird_timestamps'] = node_off_timestamps_count context['pending_nodes'] = node_pending_count return render(request, 'pano/index.html', context)
def dashboard_json(request): context = {} if request.method == 'GET': if 'source' in request.GET: source = request.GET.get('source') set_server(request, source) if request.method == 'POST': request.session['django_timezone'] = request.POST['timezone'] return redirect(request.POST['return_url']) source_url, source_certs, source_verify = get_server(request) puppet_run_time = get_server(request, type='run_time') dashboard_show = request.GET.get('show', 'recent') events_params = { 'query': { 1: '["and",["=","latest_report?",true],["in", "certname",["extract", "certname",["select_nodes",["null?","deactivated",true]]]]]' }, 'summarize_by': 'certname', } reports_params = { 'query': { 1: '["and",["=","latest_report?",true],["in", "certname",["extract", "certname",["select_nodes",["null?","deactivated",true]]]]]' } } nodes_params = { 'limit': 25, 'order_by': { 'order_field': { 'field': 'report_timestamp', 'order': 'desc', }, 'query_field': { 'field': 'certname' }, }, } jobs = { 'tot_resource': { 'url': source_url, 'certs': source_certs, 'verify': source_verify, 'id': 'tot_resource', 'path': 'mbeans/puppetlabs.puppetdb.query.population:type=default,name=num-resources', }, 'avg_resource': { 'url': source_url, 'certs': source_certs, 'verify': source_verify, 'id': 'avg_resource', 'path': 'mbeans/puppetlabs.puppetdb.query.population:type=default,name=avg-resources-per-node', }, 'all_nodes': { 'url': source_url, 'certs': source_certs, 'verify': source_verify, 'api_version': 'v4', 'id': 'all_nodes', 'path': '/nodes', 'request': request }, 'events': { 'url': source_url, 'certs': source_certs, 'verify': source_verify, 'id': 'event_counts', 'path': '/event-counts', 'api_version': 'v4', 'params': events_params, 'request': request }, 'reports': { 'url': source_url, 'certs': source_certs, 'verify': source_verify, 'api_version': 'v4', 'id': 'reports', 'path': '/reports', 'params': reports_params, 'request': request }, 'nodes': { 'url': source_url, 'certs': source_certs, 'verify': source_verify, 'api_version': 'v4', 'id': 'nodes', 'path': '/nodes', 'params': nodes_params, 'request': request }, } puppetdb_results = run_puppetdb_jobs(jobs) # Assign vars from the completed jobs # Number of results from all_nodes is our population. puppet_population = len(puppetdb_results['all_nodes']) # Total resources managed by puppet metric total_resources = puppetdb_results['tot_resource'] # Average resource per node metric avg_resource_node = puppetdb_results['avg_resource'] # Information about all active nodes in puppet all_nodes_list = puppetdb_results['all_nodes'] all_nodes_dict = {item['certname']: item for item in all_nodes_list} # All available events for the latest puppet reports event_list = puppetdb_results['event_counts'] event_dict = {item['subject']['title']: item for item in event_list} # All of the latest reports reports_list = puppetdb_results['reports'] reports_dict = {item['certname']: item for item in reports_list} # 25 Nodes node_list = puppetdb_results['nodes'] node_dict = {item['certname']: item for item in node_list} failed_list, changed_list, unreported_list, mismatch_list, pending_list = dictstatus( all_nodes_dict, reports_dict, event_dict, sort=True, sortby='latestReport', get_status='notall', puppet_run_time=puppet_run_time) pending_list = [x for x in pending_list if x not in unreported_list] changed_list = [ x for x in changed_list if x not in unreported_list and x not in failed_list and x not in pending_list ] failed_list = [x for x in failed_list if x not in unreported_list] unreported_list = [x for x in unreported_list if x not in failed_list] node_unreported_count = len(unreported_list) node_fail_count = len(failed_list) node_change_count = len(changed_list) node_off_timestamps_count = len(mismatch_list) node_pending_count = len(pending_list) if dashboard_show == 'recent': merged_nodes_list = dictstatus(node_dict, reports_dict, event_dict, sort=False, get_status="all", puppet_run_time=puppet_run_time) elif dashboard_show == 'failed': merged_nodes_list = failed_list elif dashboard_show == 'unreported': merged_nodes_list = unreported_list elif dashboard_show == 'changed': merged_nodes_list = changed_list elif dashboard_show == 'mismatch': merged_nodes_list = mismatch_list elif dashboard_show == 'pending': merged_nodes_list = pending_list else: merged_nodes_list = dictstatus(node_dict, reports_dict, event_dict, sort=False, get_status="all", puppet_run_time=puppet_run_time) context['node_list'] = merged_nodes_list context['selected_view'] = dashboard_show context['population'] = puppet_population context['total_resource'] = total_resources['Value'] context['avg_resource'] = "{:.2f}".format(avg_resource_node['Value']) context['failed_nodes'] = node_fail_count context['changed_nodes'] = node_change_count context['unreported_nodes'] = node_unreported_count context['mismatching_timestamps'] = node_off_timestamps_count context['pending_nodes'] = node_pending_count return HttpResponse(json.dumps(context), content_type="application/json")
def event_analytics(request, view='summary'): context = { 'timezones': pytz.common_timezones, 'SOURCES': AVAILABLE_SOURCES } if request.method == 'GET': if 'source' in request.GET: source = request.GET.get('source') set_server(request, source) if request.method == 'POST': request.session['django_timezone'] = request.POST['timezone'] return redirect(request.POST['return_url']) summary = events.get_events_summary(timespan='latest', request=request) context['summary'] = summary # Show Classes if request.GET.get('value', False): if view == 'classes': class_name = request.GET.get('value') title = "Class: %s" % class_name class_events = events.get_report(key='containing_class', value=class_name, request=request) context['events'] = class_events # Show Nodes elif view == 'nodes': node_name = request.GET.get('value') title = "Node: %s" % node_name node_events = events.get_report(key='certname', value=node_name, request=request) context['events'] = node_events # Show Resources elif view == 'resources': resource_name = request.GET.get('value') title = "Resource: %s" % resource_name resource_events = events.get_report(key='resource_title', value=resource_name, request=request) context['events'] = resource_events # Show Types elif view == 'types': type_name = request.GET.get('value') title = "Type: %s" % type_name type_events = events.get_report(key='resource_type', value=type_name, request=request) context['events'] = type_events # Show summary if none of the above matched else: sum_avail = ['classes', 'nodes', 'resources', 'types'] stat_avail = ['failed', 'noop', 'success', 'skipped' ''] show_summary = request.GET.get('show_summary', 'classes') show_status = request.GET.get('show_status', 'failed') if show_summary in sum_avail and show_status in stat_avail: title = "%s with status %s" % (show_summary.capitalize(), show_status.capitalize()) context['show_title'] = title else: title = 'Failed Classes' context['show_title'] = title return render(request, 'pano/analytics/events_details.html', context) # Add title to context context['show_title'] = title # if the above went well and did not reach the else clause we can also return the awesome. return render(request, 'pano/analytics/events_inspect.html', context)
def splash(request): context = { 'timezones': pytz.common_timezones, 'SOURCES': AVAILABLE_SOURCES } if request.method == 'GET': if 'source' in request.GET: source = request.GET.get('source') set_server(request, source) if request.method == 'POST': if 'timezone' in request.POST: request.session['django_timezone'] = request.POST['timezone'] return redirect(request.POST['url']) elif 'username' in request.POST and 'password' in request.POST: username = request.POST['username'] password = request.POST['password'] user = authenticate(username=username, password=password) next_url = False if 'nexturl' in request.POST: next_url = request.POST['nexturl'] if user is not None: if user.is_active: login(request, user) # Work out the permissions for this user based on ldap groups if AUTH_METHOD == 'ldap' and user.backend == 'django_auth_ldap.backend.LDAPBackend' and ENABLE_PERMISSIONS: ldap_user = user.ldap_user ldap_user_groups = ldap_user.group_dns base_query = ['["and",["or"'] for group in ldap_user_groups: results = LdapGroupPermissions.objects.filter( ldap_group_name=group) if results.exists(): value = results.values() value = value[0]['puppetdb_query'] base_query.append(value) if len(base_query) == 1: if user.is_staff or user.is_superuser: request.session['permission_filter'] = False else: request.session['permission_filter'] = None else: if user.is_staff or user.is_superuser: request.session['permission_filter'] = False else: request.session[ 'permission_filter'] = ','.join( base_query) + ']]' if next_url: return redirect(next_url) else: return redirect('dashboard') else: context['login_error'] = "Account is disabled." context['nexturl'] = next_url return render(request, 'pano/splash.html', context) else: # Return an 'invalid login' error message. context['login_error'] = "Invalid credentials" context['nexturl'] = next_url return render(request, 'pano/splash.html', context) return redirect('dashboard') user = request.user.username context['username'] = user return render(request, 'pano/splash.html', context)
def dashboard_nodes_json(request): context = {} if request.method == 'GET': if 'source' in request.GET: source = request.GET.get('source') set_server(request, source) if request.method == 'POST': request.session['django_timezone'] = request.POST['timezone'] return redirect(request.POST['return_url']) source_url, source_certs, source_verify = get_server(request) puppet_run_time = get_server(request, type='run_time') # Dashboard to show nodes of "recent, failed, unreported or changed" dashboard_show = request.GET.get('show', 'recent') events_params = { 'query': { 1: '["and",["=","latest_report?",true],["in", "certname",["extract", "certname",["select_nodes",["null?","deactivated",true]]]]]' }, 'summarize_by': 'certname', } all_nodes_params = { 'query': { 1: '["and",["=","latest_report?",true],["in", "certname",["extract", "certname",["select_nodes",["null?","deactivated",true]]]]]' }, } reports_params = { 'query': { 1: '["and",["=","latest_report?",true],["in", "certname",["extract", "certname",["select_nodes",["null?","deactivated",true]]]]]' } } nodes_params = { 'limit': 25, 'order_by': { 'order_field': { 'field': 'report_timestamp', 'order': 'desc', }, 'query_field': { 'field': 'certname' }, }, } jobs = { 'all_nodes': { 'url': source_url, 'certs': source_certs, 'verify': source_verify, 'api_version': 'v4', 'id': 'all_nodes', 'path': '/nodes', 'request': request }, 'events': { 'url': source_url, 'certs': source_certs, 'verify': source_verify, 'id': 'event_counts', 'path': 'event-counts', 'api_version': 'v4', 'params': events_params, 'request': request }, 'nodes': { 'url': source_url, 'certs': source_certs, 'verify': source_verify, 'api_version': 'v4', 'id': 'nodes', 'path': '/nodes', 'params': nodes_params, 'request': request }, 'reports': { 'url': source_url, 'certs': source_certs, 'verify': source_verify, 'api_version': 'v4', 'id': 'reports', 'path': '/reports', 'params': reports_params, 'request': request }, } puppetdb_results = run_puppetdb_jobs(jobs) # Information about all active nodes in puppet all_nodes_list = puppetdb_results['all_nodes'] all_nodes_dict = {item['certname']: item for item in all_nodes_list} # All available events for the latest puppet reports event_list = puppetdb_results['event_counts'] event_dict = {item['subject']['title']: item for item in event_list} # All of the latest reports reports_list = puppetdb_results['reports'] reports_dict = {item['certname']: item for item in reports_list} # 25 Nodes node_list = puppetdb_results['nodes'] node_dict = {item['certname']: item for item in node_list} failed_list, changed_list, unreported_list, mismatch_list, pending_list = dictstatus( all_nodes_dict, reports_dict, event_dict, sort=True, sortby='latestReport', get_status='notall', puppet_run_time=puppet_run_time) pending_list = [x for x in pending_list if x not in unreported_list] changed_list = [ x for x in changed_list if x not in unreported_list and x not in failed_list and x not in pending_list ] failed_list = [x for x in failed_list if x not in unreported_list] unreported_list = [x for x in unreported_list if x not in failed_list] if dashboard_show == 'recent': merged_nodes_list = dictstatus(node_dict, reports_dict, event_dict, sort=False, get_status="all", puppet_run_time=puppet_run_time) elif dashboard_show == 'failed': merged_nodes_list = failed_list elif dashboard_show == 'unreported': merged_nodes_list = unreported_list elif dashboard_show == 'changed': merged_nodes_list = changed_list elif dashboard_show == 'mismatch': merged_nodes_list = mismatch_list elif dashboard_show == 'pending': merged_nodes_list = pending_list else: merged_nodes_list = dictstatus(node_dict, reports_dict, event_dict, sort=False, get_status="all", puppet_run_time=puppet_run_time) context['node_list'] = merged_nodes_list context['selected_view'] = dashboard_show return HttpResponse(json.dumps(context), content_type="application/json")
def dashboard_json(request): context = {} if request.method == 'GET': if 'source' in request.GET: source = request.GET.get('source') set_server(request, source) if request.method == 'POST': request.session['django_timezone'] = request.POST['timezone'] return redirect(request.POST['return_url']) source_url, source_certs, source_verify = get_server(request) puppet_run_time = get_server(request, type='run_time') dashboard_show = request.GET.get('show', 'recent') events_params = { 'query': { 1: '["and",["=","latest_report?",true],["in", "certname",["extract", "certname",["select_nodes",["null?","deactivated",true]]]]]' }, 'summarize_by': 'certname', } reports_params = { 'query': { 1: '["and",["=","latest_report?",true],["in", "certname",["extract", "certname",["select_nodes",["null?","deactivated",true]]]]]' } } nodes_params = { 'limit': 25, 'order_by': { 'order_field': { 'field': 'report_timestamp', 'order': 'desc', }, 'query_field': {'field': 'certname'}, }, } jobs = { 'tot_resource': { 'url': source_url, 'certs': source_certs, 'verify': source_verify, 'id': 'tot_resource', 'path': 'mbeans/puppetlabs.puppetdb.query.population:type=default,name=num-resources', }, 'avg_resource': { 'url': source_url, 'certs': source_certs, 'verify': source_verify, 'id': 'avg_resource', 'path': 'mbeans/puppetlabs.puppetdb.query.population:type=default,name=avg-resources-per-node', }, 'all_nodes': { 'url': source_url, 'certs': source_certs, 'verify': source_verify, 'api_version': 'v4', 'id': 'all_nodes', 'path': '/nodes', 'request': request }, 'events': { 'url': source_url, 'certs': source_certs, 'verify': source_verify, 'id': 'event_counts', 'path': '/event-counts', 'api_version': 'v4', 'params': events_params, 'request': request }, 'reports': { 'url': source_url, 'certs': source_certs, 'verify': source_verify, 'api_version': 'v4', 'id': 'reports', 'path': '/reports', 'params': reports_params, 'request': request }, 'nodes': { 'url': source_url, 'certs': source_certs, 'verify': source_verify, 'api_version': 'v4', 'id': 'nodes', 'path': '/nodes', 'params': nodes_params, 'request': request }, } puppetdb_results = run_puppetdb_jobs(jobs) # Assign vars from the completed jobs # Number of results from all_nodes is our population. puppet_population = len(puppetdb_results['all_nodes']) # Total resources managed by puppet metric total_resources = puppetdb_results['tot_resource'] # Average resource per node metric avg_resource_node = puppetdb_results['avg_resource'] # Information about all active nodes in puppet all_nodes_list = puppetdb_results['all_nodes'] all_nodes_dict = {item['certname']: item for item in all_nodes_list} # All available events for the latest puppet reports event_list = puppetdb_results['event_counts'] event_dict = {item['subject']['title']: item for item in event_list} # All of the latest reports reports_list = puppetdb_results['reports'] reports_dict = {item['certname']: item for item in reports_list} # 25 Nodes node_list = puppetdb_results['nodes'] node_dict = {item['certname']: item for item in node_list} failed_list, changed_list, unreported_list, mismatch_list, pending_list = dictstatus(all_nodes_dict, reports_dict, event_dict, sort=True, sortby='latestReport', get_status='notall', puppet_run_time=puppet_run_time) pending_list = [x for x in pending_list if x not in unreported_list] changed_list = [x for x in changed_list if x not in unreported_list and x not in failed_list and x not in pending_list] failed_list = [x for x in failed_list if x not in unreported_list] unreported_list = [x for x in unreported_list if x not in failed_list] node_unreported_count = len(unreported_list) node_fail_count = len(failed_list) node_change_count = len(changed_list) node_off_timestamps_count = len(mismatch_list) node_pending_count = len(pending_list) if dashboard_show == 'recent': merged_nodes_list = dictstatus( node_dict, reports_dict, event_dict, sort=False, get_status="all", puppet_run_time=puppet_run_time) elif dashboard_show == 'failed': merged_nodes_list = failed_list elif dashboard_show == 'unreported': merged_nodes_list = unreported_list elif dashboard_show == 'changed': merged_nodes_list = changed_list elif dashboard_show == 'mismatch': merged_nodes_list = mismatch_list elif dashboard_show == 'pending': merged_nodes_list = pending_list else: merged_nodes_list = dictstatus( node_dict, reports_dict, event_dict, sort=False, get_status="all", puppet_run_time=puppet_run_time) context['node_list'] = merged_nodes_list context['selected_view'] = dashboard_show context['population'] = puppet_population context['total_resource'] = total_resources['Value'] context['avg_resource'] = "{:.2f}".format(avg_resource_node['Value']) context['failed_nodes'] = node_fail_count context['changed_nodes'] = node_change_count context['unreported_nodes'] = node_unreported_count context['mismatching_timestamps'] = node_off_timestamps_count context['pending_nodes'] = node_pending_count return HttpResponse(json.dumps(context), content_type="application/json")
def nodes_json(request): if request.method == 'GET': if 'source' in request.GET: source = request.GET.get('source') set_server(request, source) if request.method == 'POST': request.session['django_timezone'] = request.POST['timezone'] return redirect(request.POST['return_url']) source_url, source_certs, source_verify = get_server(request) valid_sort_fields = ( 'certname', 'catalog_timestamp', 'report_timestamp', 'facts_timestamp', 'successes', 'noops', 'failures', 'skips') try: # If user requested to download csv formatted file. Default value is False dl_csv = request.GET.get('dl_csv', False) if dl_csv == 'true': dl_csv = True else: dl_csv = False # Add limits to session if request.GET.get('limits', False): if request.session['limits'] != int(request.GET.get('limits', 50)): request.session['limits'] = int(request.GET.get('limits', 50)) if request.session['limits'] <= 0: request.session['limits'] = 50 else: if 'limits' not in request.session: request.session['limits'] = 50 # Cur Page Number if request.GET.get('page', False): if request.session['page'] != int(request.GET.get('page', 1)): request.session['page'] = int(request.GET.get('page', 1)) if request.session['page'] <= 0: request.session['page'] = 1 else: if 'page' not in request.session: request.session['page'] = 1 # Cur sort field if request.GET.get('sortfield', False): if request.session['sortfield'] != request.GET.get('sortfield'): request.session['sortfield'] = request.GET.get('sortfield') if request.session['sortfield'] not in valid_sort_fields: request.session['sortfield'] = 'report_timestamp' else: if 'sortfield' not in request.session: request.session['sortfield'] = 'report_timestamp' # Cur sort order if request.GET.get('sortfieldby', False): avail_sortorder = ['asc', 'desc'] if request.session['sortfieldby'] != request.GET.get('sortfieldby'): request.session['sortfieldby'] = request.GET.get('sortfieldby') if request.session['sortfieldby'] not in avail_sortorder: request.session['sortfieldby'] = 'desc' else: if 'sortfieldby' not in request.session: request.session['sortfieldby'] = 'desc' # Search parameters takes a valid puppetdb query string if request.GET.get('search', False): if 'search' in request.session and (request.session['search'] == request.GET.get('search')): pass else: if request.GET.get('search') == 'clear_rules': request.session['sortfield'] = 'report_timestamp' request.session['sortfieldby'] = 'desc' request.session['page'] = 1 request.session['search'] = None else: request.session['page'] = 1 request.session['search'] = request.GET.get('search') else: if 'search' not in request.session: request.session['sortfield'] = 'report_timestamp' request.session['sortfieldby'] = 'desc' request.session['page'] = 1 request.session['search'] = None # Set offset request.session['offset'] = (request.session['limits'] * request.session['page']) - request.session[ 'limits'] except: return HttpResponseBadRequest('Oh no! Your filters were invalid.') # Valid sort field that the user can search agnaist. sort_field = request.session['sortfield'] sort_field_order = request.session['sortfieldby'] page_num = request.session['page'] if request.session['search'] is not None: node_params = { 'query': { 1: request.session['search'] }, } else: node_params = { 'query': {}, } nodes_sort_fields = ['certname', 'catalog_timestamp', 'report_timestamp', 'facts_timestamp'] if sort_field in nodes_sort_fields: node_params['order_by'] = { 'order_field': { 'field': sort_field, 'order': sort_field_order, }, } if dl_csv is False: node_params['limit'] = request.session['limits'] node_params['offset'] = request.session['offset'] node_params['include_total'] = 'true' else: node_params['order_by'] = { 'order_field': { 'field': 'report_timestamp', 'order': 'desc', }, } node_sort_fields = ['certname', 'catalog_timestamp', 'report_timestamp', 'facts_timestamp'] if sort_field in node_sort_fields: try: node_list, node_headers = puppetdb.api_get( api_url=source_url, cert=source_certs, verify=source_verify, path='/nodes', api_version='v4', params=puppetdb.mk_puppetdb_query( node_params, request), ) except: node_list = [] node_headers = dict() node_headers['X-Records'] = 0 else: node_list = puppetdb.api_get( api_url=source_url, cert=source_certs, verify=source_verify, path='/nodes', api_version='v4', params=puppetdb.mk_puppetdb_query( node_params, request), ) # Work out the number of pages from the xrecords response # return fields that you can sort by # for each node in the node_list, find out if the latest run has any failures # v3/event-counts --data-urlencode query='["=","latest-report?",true]' # --data-urlencode summarize-by='certname' report_params = { 'query': { 1: '["and",["=","latest_report?",true],["in", "certname",["extract", "certname",["select_nodes",["null?","deactivated",true]]]]]' }, 'summarize_by': 'certname', } status_sort_fields = ['successes', 'failures', 'skips', 'noops'] report_status_params = { 'query': { 1: '["and",["=","latest_report?",true],["in", "certname",["extract", "certname",["select_nodes",["null?","deactivated",true]]]]]' } } report_status_list = puppetdb.api_get( api_url=source_url, cert=source_certs, verify=source_verify, path='/reports', params=puppetdb.mk_puppetdb_query(report_status_params, request), api_version='v4', ) if sort_field in status_sort_fields: if request.session['search'] is not None: report_params['query'] = {'operator': 'and', 1: request.session['search'], 2: '["=","latest_report?",true]', 3: '["in", "certname",["extract", "certname",["select_nodes",["null?","deactivated",true]]]]', } report_params['order_by'] = { 'order_field': { 'field': sort_field, 'order': sort_field_order, } } report_params['include_total'] = 'true' # Don't limit results if its CSV if dl_csv is False: report_params['limit'] = request.session['limits'] report_params['offset'] = request.session['offset'] report_list, report_headers = puppetdb.api_get( api_url=source_url, cert=source_certs, verify=source_verify, path='/event-counts', params=puppetdb.mk_puppetdb_query(report_params, request), api_version='v4', ) else: report_list = puppetdb.api_get( api_url=source_url, cert=source_certs, verify=source_verify, path='event-counts', params=puppetdb.mk_puppetdb_query(report_params, request), api_version='v4', ) # number of results depending on sort field. if sort_field in status_sort_fields: xrecords = report_headers['X-Records'] total_results = xrecords elif sort_field in nodes_sort_fields: xrecords = node_headers['X-Records'] total_results = xrecords num_pages_wdec = float(xrecords) / request.session['limits'] num_pages_wodec = float("{:.0f}".format(num_pages_wdec)) if num_pages_wdec > num_pages_wodec: num_pages = num_pages_wodec + 1 else: num_pages = num_pages_wodec # Converts lists of dicts to dicts. node_dict = {item['certname']: item for item in node_list} status_dict = {item['certname']: item for item in report_status_list} report_dict = {item['subject']['title']: item for item in report_list} if sort_field_order == 'desc': rows = dictstatus( node_dict, status_dict, report_dict, sortby=sort_field, asc=True, sort=False) sort_field_order_opposite = 'asc' elif sort_field_order == 'asc': rows = dictstatus( node_dict, status_dict, report_dict, sortby=sort_field, asc=False, sort=False) sort_field_order_opposite = 'desc' if dl_csv is True: if rows is []: pass else: # Generate a sequence of rows. The range is based on the maximum number of # rows that can be handled by a single sheet in most spreadsheet # applications. include_facts = request.GET.get('include_facts', False) csv_headers = ['Certname', 'Latest Catalog', 'Latest Report', 'Latest Facts', 'Success', 'Noop', 'Failure', 'Skipped'] if include_facts is not False: merged_list_facts = [] facts = {} for fact in include_facts.split(','): # Sanitize the fact input from the user fact = fact.strip() # Add the fact name to the headers list csv_headers.append(fact) # build the params for each fact. facts_params = { 'query': { 1: '["=","name","' + fact + '"]' }, } fact_list = puppetdb.api_get( api_url=source_url, cert=source_certs, verify=source_verify, path='facts', params=puppetdb.mk_puppetdb_query(facts_params), api_version='v4', ) # Populate the facts dict with the facts we have retrieved # Convert the fact list into a fact dict! facts[fact] = {item['certname']: item for item in fact_list} i = 1 jobs = {} # Add ID to each job so that it can be assembled in # the same order after we recieve the job results # We do this via jobs so that we can get faster results. for node in rows: jobs[i] = { 'id': i, 'include_facts': include_facts.split(','), 'node': node, 'facts': facts, } i += 1 csv_results = generate_csv(jobs) rows = [] i = 1 # with the job results we can now recreate merged_list # in the order we sent them. while i <= len(csv_results): rows.append(csv_results[i]) i += 1 # Insert the csv header to the top of the list. rows.insert(0, csv_headers) pseudo_buffer = Echo() writer = csv.writer(pseudo_buffer) response = StreamingHttpResponse((writer.writerow(row) for row in rows), content_type="text/csv") response['Content-Disposition'] = 'attachment; filename="puppetdata-%s.csv"' % (datetime.datetime.now()) return response """ c_r_s* = current request sort c_r_* = current req r_s* = requests available """ context = { 'nodeList': rows, 'total_nodes': total_results, 'c_r_page': page_num, 'c_r_limit': request.session['limits'], 'r_sfield': valid_sort_fields, 'c_r_sfield': sort_field, 'r_sfieldby': ['asc', 'desc'], 'c_r_sfieldby': sort_field_order, 'c_r_sfieldby_o': sort_field_order_opposite, 'tot_pages': '{0:g}'.format(num_pages), } return HttpResponse(json.dumps(context), content_type="application/json")
def reports(request, certname=None): context = default_context if request.method == "GET": if "source" in request.GET: source = request.GET.get("source") set_server(request, source) if request.method == "POST": request.session["django_timezone"] = request.POST["timezone"] return redirect(request.POST["return_url"]) source_url, source_certs, source_verify = get_server(request) # Redirects to the events page if GET param latest is true.. if request.GET.get("latest", False): if request.GET.get("latest") == "true": latest_report_params = { "query": {1: '["=","certname","' + certname + '"]'}, "order-by": { "order-field": {"field": "start-time", "order": "desc"}, "query-field": {"field": "certname"}, }, "limit": 1, } latest_report = puppetdb.api_get( api_url=source_url, cert=source_certs, verify=source_verify, path="/reports", api_version="v4", params=puppetdb.mk_puppetdb_query(latest_report_params), ) report_hash = "" for report in latest_report: report_env = report["environment"] report_hash = report["hash"] return redirect( "/pano/events/" + certname + "/" + report_hash + "?report_timestamp=" + request.GET.get("report_timestamp") + "&envname=" + report_env ) page_num = int(request.GET.get("page", 0)) if page_num <= 0: offset = 0 else: offset = "{:.0f}".format(page_num * 25) reports_params = { "query": {1: '["=","certname","' + certname + '"]'}, "order-by": {"order-field": {"field": "start-time", "order": "desc"}, "query-field": {"field": "certname"}}, "limit": 25, "include-total": "true", "offset": offset, } reports_list, headers = puppetdb.api_get( api_url=source_url, cert=source_certs, verify=source_verify, path="/reports", api_version="v4", params=puppetdb.mk_puppetdb_query(reports_params), ) # Work out the number of pages from the xrecords response xrecords = headers["X-Records"] num_pages_wdec = float(xrecords) / 25 num_pages_wodec = float("{:.0f}".format(num_pages_wdec)) if num_pages_wdec > num_pages_wodec: num_pages = num_pages_wodec + 1 else: num_pages = num_pages_wodec report_status = [] for report in reports_list: found_report = False events_params = {"query": {1: '["=","report","' + report["hash"] + '"]'}, "summarize-by": "certname"} eventcount_list = puppetdb.api_get( path="event-counts", api_url=source_url, api_version="v4", params=puppetdb.mk_puppetdb_query(events_params) ) # Make list of the results for event in eventcount_list: if event["subject"]["title"] == report["certname"]: found_report = True # hashid, certname, environment, time start, time end, success, noop, failure, pending report_status.append( [ report["hash"], report["certname"], report["environment"], report["start-time"], report["end-time"], event["successes"], event["noops"], event["failures"], event["skips"], ] ) break if found_report is False: report_status.append( [ report["hash"], report["certname"], report["environment"], report["start-time"], report["end-time"], 0, 0, 0, 0, ] ) report_status = sort_tables(report_status, order=True, col=3) context["certname"] = certname context["reports"] = report_status context["curr_page"] = page_num context["tot_pages"] = "{:.0f}".format(num_pages) return render(request, "pano/reports.html", context)