blob: bb3c19ea7a8e409b79287c91b671e0005642ba93 [file] [log] [blame]
Alex Savatieiev9b2f6512019-02-20 18:05:00 -06001<!DOCTYPE html>
2<html lang="en">
3<head>
4 <meta charset="UTF-8">
Alex41485522019-04-12 17:26:18 -05005 <title>Nodes and Networks report</title>
6 {% include 'common_styles.j2' %}
7 {% include 'common_scripts.j2' %}
Alex Savatieiev9b2f6512019-02-20 18:05:00 -06008 <style>
Alex41485522019-04-12 17:26:18 -05009 table.cluster_nodes {
Alexc96fdd32019-10-15 12:48:59 -050010 width: 98%;
11 margin-left: 1%;
12 margin-right: 1%;
Alex Savatieiev9b2f6512019-02-20 18:05:00 -060013 }
Alex41485522019-04-12 17:26:18 -050014
15 /* Node rows*/
16 .node {
Alex836fac82019-08-22 13:36:16 -050017 font-family: "LaoSangamMN", Monaco, monospace;
18 font-size: 0.8em;
Alex41485522019-04-12 17:26:18 -050019 display: inline-block;
20 background-color: white;
21 }
Alex836fac82019-08-22 13:36:16 -050022 .collapsable {
23 font-family: "LaoSangamMN", Monaco, monospace;
24 font-size: 0.8em;
25 display: none;
26 background-color: white;
27 visibility: hidden;
28 }
29 .collapsable.in {
30 visibility: visible;
31 display: inline-block;
32 }
33
34 div.services > .collapsable.in {
35 display: table-row;
36 }
Alex41485522019-04-12 17:26:18 -050037
Alex836fac82019-08-22 13:36:16 -050038 tr.node > td, tr.collapsable > td {
Alex Savatieiev9b2f6512019-02-20 18:05:00 -060039 display: block;
Alex Savatieiev9b2f6512019-02-20 18:05:00 -060040 float: left;
Alex41485522019-04-12 17:26:18 -050041 padding: 1px;
Alex41485522019-04-12 17:26:18 -050042 margin: 2px;
Alex Savatieiev9b2f6512019-02-20 18:05:00 -060043 }
Alex1839bbf2019-08-22 17:17:21 -050044 td > .kvm_group {
45 display: grid;
46 grid-template-columns: auto auto auto;
47 padding-left: 0px;
48 padding-right: 0px;
49 margin: 1px;
50 }
Alex836fac82019-08-22 13:36:16 -050051 td > .disk_group {
52 display: grid;
Alexe9908f72020-05-19 16:04:53 -050053 grid-template-columns: 170px 40px 40px 40px 40px;
Alex836fac82019-08-22 13:36:16 -050054 padding-left: 0px;
55 padding-right: 0px;
56 margin: 1px;
Alex Savatieiev9b2f6512019-02-20 18:05:00 -060057 }
Alexe9908f72020-05-19 16:04:53 -050058 td > .ram_group {
Alex836fac82019-08-22 13:36:16 -050059 display: grid;
Alexe9908f72020-05-19 16:04:53 -050060 grid-template-columns: 40px 40px 40px 40px;
Alex836fac82019-08-22 13:36:16 -050061 padding-left: 0px;
62 padding-right: 0px;
63 margin: 1px;
64 }
Alex1839bbf2019-08-22 17:17:21 -050065 td > .net_group {
66 display: grid;
Alexe9908f72020-05-19 16:04:53 -050067 grid-template-columns: 50px 50px 40px 40px 40px;
Alex1839bbf2019-08-22 17:17:21 -050068 padding-left: 0px;
69 padding-right: 0px;
70 margin: 1px;
71 }
Alex836fac82019-08-22 13:36:16 -050072 td > .vcpu_group {
73 display: grid;
74 grid-template-columns: auto;
75 padding-left: 0px;
76 padding-right: 0px;
77 margin: 1px;
78 }
79
80 .item {
81 display: inline-grid;
82 border-width: 1px;
83 border-style: solid;
84 margin: 1px 1px 1px 1px;
85 padding: 0px 1px 0px 1px;
86 }
87
88 .status_none { border-radius: 10px; width: 8px; }
89 .status_up { border-radius: 10px; width: 8px; background-color: #393; color: #393; }
Alexe9908f72020-05-19 16:04:53 -050090 .status_down { border-radius: 10px; width: 8px; background-color: #933; color: #933; }
91 .status_skip { border-radius: 10px; width: 8px; background-color: #aaa; color: #aaa; }
92
93 .down > .col_name, .down > .col_role, .down > .col_down {
94 background-color: #fee;
95 background-image: linear-gradient(white, #fee, #fee, white);
96 margin: 0px;
97 }
98 .skip > .col_name, .skip > .col_role, .skip > .col_skip {
99 background-color: #eee;
100 background-image: linear-gradient(white, #eee, #eee, white);
101 margin: 0px;
102 }
103 .down > .col_name, .skip > .col_name { padding-left: 3px; }
104 .down > .col_role, .skip > .col_role { padding-left: 5px; }
105
Alex836fac82019-08-22 13:36:16 -0500106 .head { height: 18px; }
Alexe9908f72020-05-19 16:04:53 -0500107 .col_name { width: 90px; }
Alexc96fdd32019-10-15 12:48:59 -0500108 .col_role { width: 130px; }
109 .col_vendor { width: 70px; }
Alex836fac82019-08-22 13:36:16 -0500110 .col_release { width: 100px; }
111 .col_kernel { min-width: 100px; }
112 .col_vcpu { min-width: 40px; }
Alex1839bbf2019-08-22 17:17:21 -0500113 .col_net { min-width: 150px; }
Alexe9908f72020-05-19 16:04:53 -0500114 .col_ram { min-width: 162px; }
115 .col_disk { min-width: 290px; }
116
117 .col_down, .col_skip {
118 min-width: 1020px;
119 text-align: left;
120 font-style: italic;
121 padding-left: 50px !important;
122 color: gray;
123 }
Alex836fac82019-08-22 13:36:16 -0500124
Alexe9908f72020-05-19 16:04:53 -0500125 .col_node_notes { width: 225px; }
Alexc96fdd32019-10-15 12:48:59 -0500126 .col_cpu_notes { width: 177px; }
Alex1839bbf2019-08-22 17:17:21 -0500127
Alex836fac82019-08-22 13:36:16 -0500128 .meters {
129 display: inline-block;
130 margin: 1px;
131 }
132 .meters > .meter {
Alex41485522019-04-12 17:26:18 -0500133 display: block;
134 float: left;
Alex836fac82019-08-22 13:36:16 -0500135 border-width: 1px;
136 border-style: solid;
137 margin: 0px 1px 0px 1px;
138 padding: 0px 1px 0px 1px;
139
Alex Savatieiev9b2f6512019-02-20 18:05:00 -0600140 }
Alex1839bbf2019-08-22 17:17:21 -0500141 .kvm_id, .kvm_node, .kvm_status {
142 border-width: 0px;
143 background-color: #f0f0f0;
144 }
145 .kvm_id, .kvm_status {
146 text-align: center;
147 }
Alex836fac82019-08-22 13:36:16 -0500148 .meters > .ok, .disk_group > .ok, .ram_group > .ok{
149 border-color: #80a080;
150 background-color: #efe;
151 }
152 .meters > .warn, .disk_group > .warn, .ram_group > .warn {
153 border-color: #d3a200;
154 background-color: rgb(255, 216, 133);
155 }
156 .meters > .fail, .disk_group > .fail, .ram_group > .fail {
157 border-color: #bb0000;
158 background-color: rgb(250, 135, 135);
159 }
160 .cpu { border-color: #a0c0a0; background-color: rgb(252, 248, 248); }
Alex1839bbf2019-08-22 17:17:21 -0500161 .net { border-color: #c0c0a0; background-color: rgb(255, 255, 251); text-align: right; }
Alexe9908f72020-05-19 16:04:53 -0500162 .ram { border-color: #a0c0c0; background-color: rgb(255, 250, 250); text-align: right; }
163 .disk { border-color: #cedfdf; background-color: rgb(237, 241, 243); text-align: right; }
164 .disk_group > .path {
165 text-align: left;
166 }
Alex836fac82019-08-22 13:36:16 -0500167 .map_grid {
168 display: grid;
169 grid-template-columns: auto auto auto auto auto auto auto auto auto auto;
170 grid-column-gap: 20px;
171 padding-left: 0px;
172 padding-right: 0px;
173 margin: 1px;
174 margin-left: 20px;
175
176 }
177 .map_item {
178 display: inline-grid;
179 border-width: 0px;
180 border-style: solid;
181 margin: 1px 1px 1px 1px;
182 padding: 0px 1px 0px 1px;
183 }
184
185 .map_grid > .ok {
186 color: #80a080;
187 }
188 .map_grid > .warn {
189 color: #d3a200;
190 }
191 .map_grid > .fail {
192 color: #bb0000;
193 }
194
195 .services {
196 font-family: "LaoSangamMN", Monaco, monospace;
197 font-size: 1.1em;
198 background-color: white;
199 }
200 .service_node {
Alex836fac82019-08-22 13:36:16 -0500201 margin-bottom: 2px;
Alex1839bbf2019-08-22 17:17:21 -0500202 display: flex;
203 }
204 .service_name, .node_name {
205 text-align: center;
206 border-width: 0px;
207 border-style: solid;
208 margin: 1px 1px 1px 1px;
209 padding: 0px 1px 0px 1px;
210 min-width: 250px;
211 border-radius: 10px;
212 }
213 .node_name {
214 background-color: #ddd;
Alex836fac82019-08-22 13:36:16 -0500215 }
216 .service_grid {
217 display: grid;
218 grid-template-columns: repeat(8, auto);
219 grid-template-rows: repeat(10, auto);
220 grid-auto-flow: column;
221 grid-column-gap: 20px;
222 padding-left: 0px;
223 padding-right: 0px;
224 margin: 1px;
225 margin-left: 20px;
226 }
227 .service {
228 display: inline-grid;
229 text-align: center;
230 border-width: 0px;
231 border-style: solid;
232 margin: 1px 1px 1px 1px;
233 padding: 0px 1px 0px 1px;
234 min-width: 150px;
235 border-radius: 10px;
236 }
237
Alex1839bbf2019-08-22 17:17:21 -0500238 .service_grid > .on, .service_node > .ok {
Alex836fac82019-08-22 13:36:16 -0500239 background-color: #8c8;
240 }
Alex1839bbf2019-08-22 17:17:21 -0500241 .service_grid > .off, .service_node > .off{
Alex836fac82019-08-22 13:36:16 -0500242 background-color: #9aa;
243 }
Alex1839bbf2019-08-22 17:17:21 -0500244 .service_grid > .fail, .service_node > .fail {
Alex836fac82019-08-22 13:36:16 -0500245 background-color: rgb(250, 135, 135);
246 }
247
Alex Savatieiev9b2f6512019-02-20 18:05:00 -0600248 </style>
Alex Savatieiev9b2f6512019-02-20 18:05:00 -0600249</head>
250<body onload="init()">
251
Alex41485522019-04-12 17:26:18 -0500252<div class="header">
253 <div class="label">OpenStack release:</div>
254 <div class="text">{{ openstack_release }}</div>
255 <div class="label">MCP Version:</div>
256 <div class="text">{{ mcp_release }}</div>
Alex836fac82019-08-22 13:36:16 -0500257 <div class="label">RAM % Warning/Critical:</div>
258 <div class="text">{{ const['ram_warn'] }}/{{ const['ram_critical'] }}</div>
259 <div class="label">Disk % Warning/Critical:</div>
260 <div class="text">{{ const['disk_warn'] }}/{{ const['disk_critical'] }}</div>
Alex41485522019-04-12 17:26:18 -0500261 <div class="label date">generated on: {{ gen_date }}</div>
262</div>
263
264<div class="bar">
265 <button class="bar-item" onclick="openBar(event, 'nodes')">Nodes</button>
266 <button class="bar-item" onclick="openBar(event, 'networks')">Networks</button>
Alex41485522019-04-12 17:26:18 -0500267</div>
268
269{% macro nodes_page(nodes, id_label) %}
270<div id="{{ id_label }}" class="barcontent">
271 <h5>{{ caller() }}</h5>
272 <hr>
273 <table class="cluster_nodes">
Alex836fac82019-08-22 13:36:16 -0500274 <tr class="node">
275 <td class="status_none"></td>
276 <td class="head col_name">Name</td>
277 <td class="head col_role">Role</td>
278 <td class="head col_vendor">Virtual</td>
279 <td class="head col_release">Linux</td>
280 <td class="head col_kernel">Kernel</td>
281
282 <td class="head col_vcpu">
283 <div class="meters vcpu">
284 <div class="meter cpu">vCPU</div>
285 </div>
286 </td>
Alex1839bbf2019-08-22 17:17:21 -0500287 <td class="head col_net">
Alexe9908f72020-05-19 16:04:53 -0500288 <div class="net_group">
289 <div class="item net">vCpu</div>
290 <div class="item net">Total</div>
291 <div class="item net">Drop</div>
292 <div class="item net">Sq.</div>
293 <div class="item net">Cl.</div>
Alex1839bbf2019-08-22 17:17:21 -0500294 </div>
295 </td>
Alex836fac82019-08-22 13:36:16 -0500296 <td class="head col_ram">
Alexe9908f72020-05-19 16:04:53 -0500297 <div class="ram_group">
298 <div class="item ram">Total</div>
299 <div class="item ram">Used</div>
300 <div class="item ram">Free</div>
301 <div class="item ram">Avail.</div>
Alex836fac82019-08-22 13:36:16 -0500302 </div>
303 </td>
304 <td class="head col_disk">
Alexe9908f72020-05-19 16:04:53 -0500305 <div class="disk_group">
306 <div class="item disk path">Device path</div>
307 <div class="item disk">Total</div>
308 <div class="item disk">Used</div>
309 <div class="item disk">Free</div>
310 <div class="item disk">%</div>
Alex836fac82019-08-22 13:36:16 -0500311 </div>
312 </td>
313 </tr>
Alex41485522019-04-12 17:26:18 -0500314 {% for node in nodes.keys() | sort %}
315 {% set _ndat = nodes[node] %}
Alexe9908f72020-05-19 16:04:53 -0500316 {% set _status = _ndat['status'] | node_status_class %}
317 {% if _status == 'down' %}
318 <tr class="node down">
319 <td class="status_{{ _status }}">.</td>
320 <td class="head col_name">{{ _ndat['shortname'] }}</td>
321 <td class="head col_role">{{ _ndat['role'] }}</td>
322 <td class="head col_down" colspan="7"> ...no data collected: node is down</td>
323 </tr>
324 {% elif _status == 'skip' %}
325 <tr class="node skip">
326 <td class="status_{{ _status }}">.</td>
327 <td class="head col_name">{{ _ndat['shortname'] }}</td>
328 <td class="head col_role">{{ _ndat['role'] }}</td>
329 <td class="head col_skip" colspan="7"> ...no skipped from processing</td>
330 </tr>
331 {% else %}
Alex836fac82019-08-22 13:36:16 -0500332 <tr class="node" onclick="toggleClassByID('info_{{ node }}')" id='info_{{ node }}_button'>
333 <td class="status_{{ _ndat['status'] | node_status_class }}">.</td>
Alexe9908f72020-05-19 16:04:53 -0500334 <td class="head col_name">{{ _ndat['shortname'] }}</td>
Alex836fac82019-08-22 13:36:16 -0500335 <td class="head col_role">{{ _ndat['role'] }}</td>
Alex1839bbf2019-08-22 17:17:21 -0500336 <td class="head col_vendor">{{ _ndat['node_type'] }}</td>
Alex836fac82019-08-22 13:36:16 -0500337 <td class="head col_release">{{ _ndat['linux_arch'] }}/{{ _ndat['linux_codename'] }}</td>
338 <td class="head col_kernel">{{ _ndat['kernel'] }}</td>
339 <td class="head col_vcpu">
340 <div class="meters vcpu">
Alex1839bbf2019-08-22 17:17:21 -0500341 <div class="meter cpu">{{ _ndat['lscpu']['cpus'] }}</div>
342 </div>
343 </td>
344 <td class="head col_net">
345 <div class="net_group">
Alexe9908f72020-05-19 16:04:53 -0500346 <div class="item net">All</div>
Alex1839bbf2019-08-22 17:17:21 -0500347 <div class="item net">{{ _ndat['net_stats']['total'][0] }}</div>
348 <div class="item net">{{ _ndat['net_stats']['total'][1] }}</div>
349 <div class="item net">{{ _ndat['net_stats']['total'][2] }}</div>
350 <div class="item net">{{ _ndat['net_stats']['total'][3] }}</div>
Alex836fac82019-08-22 13:36:16 -0500351 </div>
352 </td>
353 <td class="head col_ram">
354 <div class="ram_group">
Alex1839bbf2019-08-22 17:17:21 -0500355 <div class="item ram">{{ _ndat['ram']['total'] }}</div>
356 <div class="item ram">{{ _ndat['ram']['used'] }}</div>
357 <div class="item ram">{{ _ndat['ram']['free'] }}</div>
358 <div class="item ram {{ _ndat['ram']['status'] }}">{{ _ndat['ram']['available'] }}</div>
Alex836fac82019-08-22 13:36:16 -0500359 </div>
360 </td>
361 <td class="head col_disk">
362 <div class="disk_group">
Alexe9908f72020-05-19 16:04:53 -0500363 <div class="item disk path">{{ _ndat['disk_max_dev'] }}</div>
Alex836fac82019-08-22 13:36:16 -0500364 {% for val in _ndat['disk'][_ndat['disk_max_dev']]['v'] %}
365 <div class="item disk {{ _ndat['disk'][_ndat['disk_max_dev']]['f'] }}">{{ val }}</div>
366 {% endfor %}
367 </div>
368 </td>
369 </tr>
370 <tr class="collapsable" id="info_{{ node }}">
371 <td class="status_none"></td>
Alex1839bbf2019-08-22 17:17:21 -0500372 <td class="col_node_notes" colspan="2">
373 {% if 'virsh' in _ndat %}
374 <div class="kvm_group">
375 {% for kvm_node in _ndat['virsh'].keys() | sort %}
376 <div class="item kvm_id">{{ _ndat['virsh'][kvm_node]['id'] }}</div>
377 <div class="item kvm_node">{{ kvm_node }}</div>
378 <div class="item kvm_status">{{ _ndat['virsh'][kvm_node]['status'] }}</div>
379 {% endfor %}
380 </div>
381 {% endif %}
382 </td>
383 <td class="col_cpu_notes smallgreytext" colspan="2">
384 CPU Model: {{ _ndat['lscpu']['model_name'] }} at {{ _ndat['lscpu']['cpu_mhz'] }}Mhz<br>
385 Virtualization: {{ _ndat['lscpu']['virtualization'] }}
386 </td>
Alex836fac82019-08-22 13:36:16 -0500387 <td class="col_kernel"></td>
388 <td class="col_vcpu"></td>
Alex1839bbf2019-08-22 17:17:21 -0500389 <td class="col_net">
390 <div class="net_group">
391 {% for cpu in _ndat['net_stats'].keys() | sort %}
392 <div class="item net">{{ cpu }}</div>
393 {% for val in _ndat['net_stats'][cpu] %}
394 <div class="item net">{{ val }}</div>
395 {% endfor %}
396 {% endfor %}
397 </div>
398 </td>
Alex836fac82019-08-22 13:36:16 -0500399 <td class="col_ram"></td>
400 <td class="col_disk">
401 <div class="disk_group">
402 {% for dev in _ndat['disk'].keys() | sort %}
Alexe9908f72020-05-19 16:04:53 -0500403 <div class="item disk path">{{ dev }}</div>
Alex836fac82019-08-22 13:36:16 -0500404 {% for val in _ndat['disk'][dev]['v'] %}
405 <div class="item disk {{ _ndat['disk'][dev]['f'] }}">{{ val }}</div>
406 {% endfor %}
407 {% endfor %}
408 </div>
409 </td>
Alex41485522019-04-12 17:26:18 -0500410 </tr>
Alexe9908f72020-05-19 16:04:53 -0500411 {% endif %}
Alex41485522019-04-12 17:26:18 -0500412 {% endfor %}
413 </table>
414 <hr>
415</div>
416{% endmacro %}
417
418{% macro networks_page(networks, id_label) %}
419<div id="{{ id_label }}" class="barcontent">
420 <h5>{{ caller() }}</h5>
421 <hr>
422 <table class="networks">
Alex836fac82019-08-22 13:36:16 -0500423 {% for net in map.keys() %}
424 <tr class="subnet" onclick="toggleClassByID('net_{{ net }}')" id="{{ net }}_net_button">
425 <td>{{ net }}</td>
Alex41485522019-04-12 17:26:18 -0500426 </tr>
Alex836fac82019-08-22 13:36:16 -0500427 <tr class="collapsable" id="net_{{ net }}"><td>
428 <div class="map_grid">
429 {% for node in map[net].keys() | sort %}
430 {% for d in map[net][node] %}
431 <div class="map_item name">{{ node }}</div>
432 <div class="map_item interface {{ d['interface_error'] }}">{{ d['interface'] }}</div>
Alex1839bbf2019-08-22 17:17:21 -0500433 <div class="map_item note"><pre>{{ d['interface_map'] | linebreaks }}</pre></div>
Alex836fac82019-08-22 13:36:16 -0500434 <div class="map_item ipaddr">{{ d['ip_address'] }}</div>
435 <div class="map_item ipaddr_type">{{ d['address_type'] }}</div>
436 <div class="map_item mtu {{ d['mtu_error'] }}">{{ d['rt_mtu'] }}</div>
437 <div class="map_item status {{ d['status_error'] }}">{{ d['status'] }}</div>
438 <div class="map_item gate {{ d['subnet_gateway_error'] }}">{{ d['subnet_gateway'] }}</div>
439 <div class="map_item gate">{{ d['default_gateway'] }}</div>
440 <div class="map_item error_note">{{ d['error_note'] }}</div>
441 {% endfor %}
442 {% endfor %}
443 </div>
444 </td></tr>
445 {% endfor %}
Alex41485522019-04-12 17:26:18 -0500446 </table>
447 <hr>
448</div>
449{% endmacro %}
450
451{% macro services_page(services, id_label) %}
452<div id="{{ id_label }}" class="barcontent">
453 <h5>{{ caller() }}</h5>
454 <hr>
Alex836fac82019-08-22 13:36:16 -0500455 <div class="services">
456 {% for node in nodes.keys() | sort %}
Alex1839bbf2019-08-22 17:17:21 -0500457 <div class="service_node" onclick="toggleClassByID('svc_{{ node }}')" id="svc_{{ node }}_button">
458 <div class="node_name">{{ node }}</div>
459 {% for service in nodes[node]['services'].keys() | sort -%}
460 {% if service in const['services'] %}
461 {% if not nodes[node]['services'][service] %}
462 <div class="service_name fail">{{ service }}</div>
463 {% endif %}
464 {% endif%}
465 {% endfor%}
466 </div>
Alex836fac82019-08-22 13:36:16 -0500467 <div class="collapsable" id="svc_{{ node }}">
468 <div class="service_grid">
469 {% for service in nodes[node]['services'].keys() | sort -%}
Alex1839bbf2019-08-22 17:17:21 -0500470 {% if service in const['services'] %}
Alex836fac82019-08-22 13:36:16 -0500471 {% if nodes[node]['services'][service] %}
Alex1839bbf2019-08-22 17:17:21 -0500472 <div class="service on">{{ service }}</div>
Alex836fac82019-08-22 13:36:16 -0500473 {% else %}
Alex1839bbf2019-08-22 17:17:21 -0500474 <div class="service fail">{{ service }}</div>
475 {% endif %}
476 {% endif%}
477 {% endfor %}
478 <div class="service"># Other services</div>
479 {% for service in nodes[node]['services'].keys() | sort -%}
480 {% if service not in const['services'] %}
481 {% if nodes[node]['services'][service] %}
482 <div class="service on">{{ service }}</div>
483 {% else %}
484 <div class="service off">{{ service }}</div>
485 {% endif %}
Alex836fac82019-08-22 13:36:16 -0500486 {% endif %}
487 {% endfor %}
488 </div>
489 </div>
490 {% endfor %}
491 </div>
492 <hr>
Alex41485522019-04-12 17:26:18 -0500493</div>
494{% endmacro %}
495
496<!-- Cluster nodes page -->
497{% call nodes_page(nodes, "nodes") %}
Alexe9908f72020-05-19 16:04:53 -0500498 Cluster nodes status and simple meterings in *.{{ domain }}
Alex41485522019-04-12 17:26:18 -0500499{% endcall %}
500
501<!-- Cluster nodes page -->
502{% call networks_page(networks, "networks") %}
503 Networks in the cluster
504{% endcall %}
505
506<!-- Cluster nodes page -->
507{% call services_page(services, "services") %}
508 Services status in the cluster
509{% endcall %}
510
Alex Savatieiev9b2f6512019-02-20 18:05:00 -0600511</body>
512</html>