status.jinja2 9.9 KB
Newer Older
Daniele Venzano's avatar
Daniele Venzano committed
1
{% extends "base_user.jinja2" %}
2 3
{% block title %}Zoe system status{% endblock %}

4
{% block custom_head %}
5
    <script src="{{ static_url("Chart.min.js") }}" type="application/javascript"></script>
6 7 8 9 10 11 12
    <script>
    Chart.scaleService.updateScaleDefaults('linear', {
        ticks: {
            min: 0
        }
    });
    </script>
13 14
{% endblock %}

15 16 17
{% block content %}
<h2>Zoe system status</h2>

18 19 20 21 22 23 24 25 26 27
    <div>
    <h3 class="section">Index</h3>
    <ul>
        <li><a href="#scheduler">Scheduler</a></li>
        <li><a href="#platform">Platform</a></li>
        <li><a href="#service-distrib">Service distribution</a></li>
    </ul>
    </div>

    <h3 class="section"><a name="scheduler">Scheduler</a></h3>
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43

    <ul>
        <li>Queue length: <span id="sched_queue_len">{{ stats.queue_length }}</span></li>
        <li>Running queue length: <span id="sched_running_queue_len">{{ stats.running_length }}</span></li>
        <li>On-going clean-up threads: <span id="termination_threads_count">{{ stats.termination_threads_count }}</span></li>
    </ul>

    <h4>Queue</h4>
    <p>Service border legend:</p>
    <ul>
        <li>Green/red: service is active/inactive. Active services have been scheduled and placed.</li>
        <li>Solid/dashed: service is essential/elastic</li>
    </ul>
    <div class="scheduler_queue">
    {% for id in stats['queue'] %}
        <div class="queue_item" id="{{ id }}">
44 45 46 47 48
            {% if user.role.can_operate_others %}
            <a href="{{ reverse_url('execution_inspect', id) }}">{{ id }}</a> ({{ executions_in_queue[id].owner.username }})
            {% else %}
            {{ id }} ({{ executions_in_queue[id].owner.username }})
            {% endif %}
49 50
            {% for service in executions_in_queue[id].services %}
                {% if service.essential %}
51
                <div class="service essential {{ 'running' if not service.is_dead() }}">
52
                    {{ service['name'] }}<br/>
53 54
                    M: <script>format_bytes({{ service['resource_reservation']['memory']['min'] }});</script><br/>
                    C: {{ service['resource_reservation']['cores']['min'] }}
55 56 57 58 59
                </div>
                {% endif %}
            {% endfor %}
            {% for service in executions_in_queue[id].services %}
                {% if not service.essential %}
60
                <div class="service {{ 'running' if not service.is_dead() }}">
61
                    {{ service['name'] }}<br/>
62 63
                    M: <script>format_bytes({{ service['resource_reservation']['memory']['min'] }});</script><br/>
                    C: {{ service['resource_reservation']['cores']['min'] }}
64 65 66 67 68 69 70 71 72 73 74 75 76 77
                </div>
                {% endif %}
            {% endfor %}
        </div>
    {% endfor %}
    {% if stats['queue']|length == 0 %}
    <p>The queue is empty.</p>
    {% endif %}
    </div>

    <h4>Running queue</h4>
    <p>This queue is unsorted, all services here should be green.</p>
    <div class="scheduler_queue">
    {% for id in stats['running_queue'] %}
78 79 80 81 82 83
            <div class="queue_item" id="{{ id }}">
            {% if user.role.can_operate_others %}
            <a href="{{ reverse_url('execution_inspect', id) }}">{{ id }}</a> ({{ executions_in_queue[id].owner.username }})
            {% else %}
            {{ id }} ({{ executions_in_queue[id].owner.username }})
            {% endif %}
84 85 86 87
            {% for service in executions_in_queue[id].services %}
                {% if service.essential %}
                <div class="service essential {{ 'running' if service.status == service.ACTIVE_STATUS }}">
                    {{ service['name'] }}<br/>
88 89
                    M: <script>format_bytes({{ service['resource_reservation']['memory']['min'] }});</script><br/>
                    C: {{ service['resource_reservation']['cores']['min'] }}
90 91 92 93 94 95 96
                </div>
                {% endif %}
            {% endfor %}
            {% for service in executions_in_queue[id].services %}
                {% if not service.essential %}
                <div class="service {{ 'running' if service.status == service.ACTIVE_STATUS }}">
                    {{ service['name'] }}<br/>
97 98
                    M: <script>format_bytes({{ service['resource_reservation']['memory']['min'] }});</script><br/>
                    C: {{ service['resource_reservation']['cores']['min'] }}
99 100 101 102 103 104 105 106 107 108
                </div>
                {% endif %}
            {% endfor %}
        </div>
    {% endfor %}
    {% if stats['running_queue']|length == 0 %}
    <p>The running queue is empty.</p>
    {% endif %}
    </div>

109
    <h3 class="section"><a name="platform">Platform</a></h3>
110 111 112 113 114 115 116 117 118
    <ul>
        <li>Total containers: {{ stats.platform_stats.container_count }}</li>
        <li>Total memory: <script>format_bytes({{ stats.platform_stats.memory_total }}, 2) </script></li>
        <li>Total cores: {{ stats.platform_stats.cores_total }}</li>
    </ul>

    <div class="platform_node_detail">
    {% for node in stats.platform_stats.nodes %}
        <div class="node_detail">
119 120 121 122 123 124
        <div class="node_name">
            {{ node['name'] }}
            {% if node['status'] == 'offline' %}
                (node is offline/unreachable)
            {% endif %}
        </div>
125
        <div class="container_count">{{ node['container_count'] }} containers</div>
126 127 128 129 130 131 132 133 134
        {% if node['labels']|length > 0 %}
        <div class="container_count">Labels:
            {% for label in node['labels'] %}
            {{ label }}&nbsp;
            {% endfor %}
        </div>
        {% else %}
        <div class="container_count">No labels</div>
        {% endif %}
135 136 137 138

        <div class="plot-container">
            <p>Memory</p>
            <div class="pie-plots">
139
                <canvas class="node_status_canvas" id="{{ node.name }}-mem"></canvas>
140
            </div>
141
        </div>
142 143 144
        <script>
        data = {
            datasets: [{
145
                label: 'Memory',
146 147
                data: [{{ node['memory_reserved'] }}, {{ node['memory_allocated'] }}, {{ node['memory_in_use'] }}],
                backgroundColor: ['rgba(0, 169, 225, 1.0)', 'rgba(53, 51, 144, 1.0)', 'rgba(145, 192, 46, 1.0)']
148
            }],
149
            'labels': ['Reserved', 'Allocated', 'In use']
150
        };
151
        ctx = document.getElementById("{{ node.name }}-mem").getContext('2d');
152
        new Chart(ctx,{
153
            type: 'bar',
154 155 156
            data: data,
            options: {
                animation: {
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
                    duration: 0
                },
                responsiveAnimationDuration: 0,
                scales: {
                    yAxes: [{
                        ticks: {
                            callback: function(value, index, values) {
                                return format_bytes_ret(value);
                            },
                            max: {{ node['memory_total'] }}
                        }
                    }]
                },
                legend: {
                    display: false
                },
                tooltips: {
                    callbacks: {
                        label: function(tooltipItem, data) {
                            return format_bytes_ret(tooltipItem.yLabel);
                        }
                    }
179 180 181 182 183 184 185 186
                }
            }
        });
        </script>

        <div class="plot-container">
            <p>Cores</p>
            <div class="pie-plots">
187
                <canvas class="node_status_canvas" id="{{ node.name }}-cpu"></canvas>
188
            </div>
189
        </div>
190 191 192
        <script>
        data = {
            datasets: [{
193
                label: 'Cores',
Daniele Venzano's avatar
Daniele Venzano committed
194
                data: [{{ '%0.2f'|format(node['cores_reserved']|float) }}, {{ '%0.2f'|format(node['cores_allocated']|float) }}, {{ '%0.2f'|format(node['cores_in_use']|float) }}],
195
                backgroundColor: ['rgba(0, 169, 225, 1.0)', 'rgba(53, 51, 144, 1.0)', 'rgba(145, 192, 46, 1.0)']
196
            }],
197
            'labels': ['Reserved', 'Allocated', 'In use']
198
        };
199
        ctx = document.getElementById("{{ node.name }}-cpu").getContext('2d');
200
        new Chart(ctx,{
201
            type: 'bar',
202 203 204
            data: data,
            options: {
                animation: {
205 206 207 208 209 210 211 212 213 214 215 216 217
                    duration: 0
                },
                responsiveAnimationDuration: 0,
                scales: {
                    yAxes: [{
                        ticks: {
                            max: {{ node['cores_total'] }},
                            stepSize: 8
                        }
                    }]
                },
                legend: {
                    display: false
218 219 220 221
                }
            }
        });
        </script>
222 223 224 225
        </div>
    {% endfor %}
    </div>

226
    <h3 class="section"><a name="service-distrib">Service distribution</a></h3>
227
    <p>Services marked with a green border are essential, elastic ones have no border.</p>
228 229 230 231
    <table class="service-distrib">
    <thead>
    <tr>
        <th class="cell-host">Host</th>
232
        <th colspan="{{ max_service_count }}">Services and allocated resources</th>
233 234 235 236 237 238
    </tr>
    </thead>
    <tbody>
    {% for node in stats.platform_stats.nodes %}
    <tr>
        <td class="cell-host">{{ node.name }}</td>
239
        {% for service in services_per_node[node.name] %}
Daniele Venzano's avatar
Daniele Venzano committed
240
            {% if service.backend_status == "started" %}
241 242
            <td class="{{ 'running' if service.essential }}">
                {% if user.role.can_operate_others %}
243
                    <a href="{{ reverse_url('execution_inspect', service['execution_id']) }}">{{ service['execution_id'] }}:{{ service['name'] }}</a>
244 245 246 247 248
                {% else %}
                    {{ service['name'] }}
                {% endif %}
                (M: <script>format_bytes({{ node.service_stats[service['id']]['mem_limit'] }});</script> C: {{ '%0.2f'|format(node.service_stats[service['id']]['core_limit']|float) }})
            </td>
Daniele Venzano's avatar
Daniele Venzano committed
249
            {% endif %}
250 251 252 253 254 255 256 257 258 259 260 261
        {% endfor %}
    </tr>
    {% endfor %}
    </tbody>
    </table>

    <script>
    function refresh_page() {
        document.location.reload();
    }
    setInterval(refresh_page, 15000);
    </script>
262
{% endblock %}