summaryrefslogblamecommitdiffstats
path: root/pages/machines.py
blob: b750ddceb5de42f64d317e82cb40b62ca7436189 (plain) (tree)
















































































































































































































                                                                                                                           
#!/usr/bin/env python3

import dash_core_components as dcc
import dash_html_components as html
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output

import plotly.graph_objects as go

import datetime as dt
from natsort import natsorted

import db
from app import app

def layout():
    return dbc.Container(fluid=True, children=[
        dbc.Row([
            dbc.Col(width=12, lg=1, children=[
                dcc.Dropdown(
                    id='machines-days',
                    options=[{'label': '{} days'.format(d), 'value': d} for d in [7, 30, 90]],
                    value=7,
                    clearable=False
                )
            ]),
            dbc.Col(width=12, lg=3, children=[
                dcc.DatePickerSingle(
                    id='machines-date',
                    date=get_newest_date(),
                    display_format='DD-MM-YYYY',
                    max_date_allowed=get_newest_date(),
                    initial_visible_month=get_newest_date(),
                    first_day_of_week=1
                ),
            ]),
            dbc.Col(width=12, lg=6, children=[
                dcc.Dropdown(
                    id='machines-satellites',
                    options=[{'label': s, 'value': s} for s in get_satellites()],
                    multi=True,
                    value=[],
                    placeholder='All Satellites'
                )
            ])
        ]),
        dbc.Row([dbc.Col([
            dcc.Graph(id='machines-graph-location')
        ])]),
        dbc.Row([
            dbc.Col(width=12, md=6, xl=4, children=[
                dcc.Graph(id='machines-graph-ram')
            ]),
            dbc.Col(width=12, md=6, xl=4, children=[
                dcc.Graph(id='machines-graph-realcores')
            ]),
            dbc.Col(width=12, md=6, xl=4, children=[
                dcc.Graph(id='machines-graph-kvmstate')
            ]),
            dbc.Col(width=12, xl=6, children=[
                dcc.Graph(id='machines-graph-cpumodel')
            ]),
            dbc.Col(width=12, xl=6, children=[
                dcc.Graph(id='machines-graph-systemmodel')
            ])
        ])
    ])

@app.callback(Output('machines-graph-location', 'figure'),
              [Input('machines-days', 'value'),
               Input('machines-date', 'date'),
               Input('machines-satellites', 'value')])
def make_graph_location(days, date, satellites):
    dbcon = db.getConnection()
    cursor = dbcon.cursor()

    stmt = """
            SELECT m.value, m.count
            FROM reports r
            JOIN machine m ON r.id = m.report
            WHERE r.date = (SELECT date FROM reports WHERE date >= %s ORDER BY date ASC LIMIT 1)
            AND m.days = %s AND m.property = 'location'
        """
    stmt_end = """ ORDER BY m.count DESC"""

    if len(satellites) > 0:
        formatStrings = ','.join(['%s'] * len(satellites))
        cursor.execute(stmt + ' AND r.ip IN ({})'.format(formatStrings) + stmt_end, tuple([date, days] + satellites))
    else:
        cursor.execute(stmt + stmt_end, (date, days))

    data = cursor.fetchall()

    db.closeConnection(dbcon)

    figure = go.Figure()
    figure.add_trace(go.Bar(
        x=[item['value'][0:9] for item in data],
        y=[item['count'] for item in data]
    ))
    figure.update_layout(
        title_text = 'Locations'
    )
    return figure

@app.callback(Output('machines-graph-cpumodel', 'figure'),
              [Input('machines-days', 'value'),
               Input('machines-date', 'date'),
               Input('machines-satellites', 'value')])
def make_graph_cpumodel(days, date, satellites):
    return make_graph(days, date, satellites, 'cpumodel', 'CPU', typ='bar', height=600)

@app.callback(Output('machines-graph-realcores', 'figure'),
              [Input('machines-days', 'value'),
               Input('machines-date', 'date'),
               Input('machines-satellites', 'value')])
def make_graph_realcores(days, date, satellites):
    return make_graph(days, date, satellites, 'realcores', 'Cores', unit=' Cores')

@app.callback(Output('machines-graph-ram', 'figure'),
              [Input('machines-days', 'value'),
               Input('machines-date', 'date'),
               Input('machines-satellites', 'value')])
def make_graph_ram(days, date, satellites):
    return make_graph(days, date, satellites, 'ram', 'RAM', unit=' GB')

@app.callback(Output('machines-graph-systemmodel', 'figure'),
              [Input('machines-days', 'value'),
               Input('machines-date', 'date'),
               Input('machines-satellites', 'value')])
def make_graph_systemmodel(days, date, satellites):
    return make_graph(days, date, satellites, 'systemmodel', 'System Model', typ='bar', height=600)

@app.callback(Output('machines-graph-kvmstate', 'figure'),
              [Input('machines-days', 'value'),
               Input('machines-date', 'date'),
               Input('machines-satellites', 'value')])
def make_graph_kvmstate(days, date, satellites):
    return make_graph(days, date, satellites, 'kvmstate', 'KVM State')


def make_graph(days, date, satellites, prop, title, unit='', typ='pie', height=450):
    dbcon = db.getConnection()
    cursor = dbcon.cursor()

    stmt = """
            SELECT m.value, SUM(m.count) AS count
            FROM reports r
            JOIN machine m ON r.id = m.report
            WHERE r.date = (SELECT date FROM reports WHERE date >= %s ORDER BY date ASC LIMIT 1)
            AND m.days = %s AND m.property = %s
        """
    stmt_end = """ GROUP BY m.value"""

    if len(satellites) > 0:
        formatStrings = ','.join(['%s'] * len(satellites))
        cursor.execute(stmt + ' AND r.ip IN ({})'.format(formatStrings) + stmt_end, tuple([date, days, prop] + satellites))
    else:
        cursor.execute(stmt + stmt_end, (date, days, prop))

    data = cursor.fetchall()
    data = natsorted(data, key = lambda x: x['value' if typ=='pie' else 'count'])

    db.closeConnection(dbcon)

    figure = go.Figure()
    if typ == 'pie':
        figure.add_trace(go.Pie(
            labels=[item['value'] + unit for item in data],
            values=[item['count'] for item in data],
            hole=0.3,
            sort=False,
            textinfo='label',
            direction='clockwise'
        ))
    elif typ == 'bar':
        figure.add_trace(go.Bar(
            y=[item['value'] + unit for item in data],
            x=[item['count'] for item in data],
            orientation='h'
        ))
    figure.update_layout(
        title_text = title,
        height = height,
        yaxis_automargin=True
    )
    return figure

def get_satellites():
    dbcon = db.getConnection()
    cursor = dbcon.cursor()

    cursor.execute("""SELECT DISTINCT ip FROM reports""")

    data = [item['ip'] for item in cursor.fetchall()]

    db.closeConnection(dbcon)
    return data

def get_newest_date():
    dbcon = db.getConnection()
    cursor = dbcon.cursor()

    cursor.execute("""SELECT date FROM reports ORDER BY date DESC LIMIT 1""")

    data = cursor.fetchall()

    db.closeConnection(dbcon)
    return data[0]['date']