mirror of
https://github.com/retspen/webvirtcloud
synced 2026-11-08 19:26:48 +00:00
feat(computes): memory given as a share; the overview in Bootstrap cards and lists
The memory given read "24.0 GB given of 32.0 GB": long, and the share
of the host's memory, what one looks for, had to be worked out. It is
now told as the vCPUs are: the share large ("75 %", amber over 90 %,
red over 100 %), then "24.0 GB / 32.0 GB", the bar and "12.0 GB
running". The Computes list's memory column shares it.
Every card of the overview has a Bootstrap card-header with an icon:
VMs, vCPUs, Memory, Storage, CPU in use and Memory in use (with the
current reading at its right), Hardware, Software and connection. The
last two were label and value lists under indented headings; they are
list-group-flush rows now, the label at the left, the value at the
right: counts in semibold, the hypervisor's and libvirt's versions as
badges, the guest architectures as light badges, the emulator and the
connection as code. The section headings, indented by the panel's
page-header margin unlike the cards, are gone: each card names itself.
The status line and notes are not paragraphs, which the panel indents.
This commit is contained in:
parent
591ec4a1f5
commit
1284b93705
9 changed files with 162 additions and 84 deletions
|
|
@ -1,10 +1,11 @@
|
|||
{% load i18n %}
|
||||
{# the memory a host has given its VMs: given, from views.shown_capacity #}
|
||||
<div class="mb-1">{% blocktrans with all=given.assigned.all|filesizeformat memory=given.memory|filesizeformat %}{{ all }} given of {{ memory }}{% endblocktrans %}</div>
|
||||
<div class="compute-ratio {% if given.bar.over %}text-danger{% elif given.memory_percent > 90 %}text-warning-emphasis{% endif %}">{{ given.memory_percent }} %</div>
|
||||
<div class="small text-body-secondary mb-1">{{ given.assigned.all|filesizeformat }} / {{ given.memory|filesizeformat }}</div>
|
||||
<div class="cap-bar" role="img" aria-label="{% blocktrans with percent=given.memory_percent %}{{ percent }}% of the host's memory given{% endblocktrans %}"
|
||||
title="{% trans "Dark: running VMs. Light: shut-off VMs, which take their memory again when they start. Line: the host's memory." %}">
|
||||
<div class="cap-running {% if given.bar.over %}bg-danger{% endif %}" style="width: {{ given.bar.running|stringformat:".1f" }}%"></div>
|
||||
<div class="cap-stopped {% if given.bar.over %}bg-danger{% endif %}" style="width: {{ given.bar.stopped|stringformat:".1f" }}%"></div>
|
||||
<div class="cap-host" style="left: {{ given.bar.host|stringformat:".1f" }}%"></div>
|
||||
</div>
|
||||
<div class="small text-body-secondary mt-1">{% blocktrans with running=given.assigned.running|filesizeformat %}{{ running }} of it running{% endblocktrans %}</div>
|
||||
<div class="small text-body-secondary mt-1">{% blocktrans with running=given.assigned.running|filesizeformat %}{{ running }} running{% endblocktrans %}</div>
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
{% block page_heading %}{{ compute.name }}{% endblock page_heading %}
|
||||
|
||||
{% block content %}
|
||||
<p class="d-flex flex-wrap align-items-baseline column-gap-3 text-body-secondary">
|
||||
<div id="host_status" class="d-flex flex-wrap align-items-baseline column-gap-3 text-body-secondary mb-3">
|
||||
<span>
|
||||
{% if connected %}
|
||||
<span class="compute-dot bg-success" aria-hidden="true"></span> <span class="text-body">{% trans "Connected" %}</span>
|
||||
|
|
@ -23,13 +23,13 @@
|
|||
</span>
|
||||
<span class="text-break">{{ compute.hostname }}</span>
|
||||
{% if compute.details %}<span class="text-break">{{ compute.details }}</span>{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{% include "computes/host_nav.html" with section="overview" %}
|
||||
|
||||
{% if not connected %}
|
||||
<div class="alert alert-warning" role="alert">
|
||||
<p>{% trans "The panel cannot reach this host, so its VMs, capacity and load are not shown:" %} {{ compute.connection_error }}</p>
|
||||
<div class="mb-2">{% trans "The panel cannot reach this host, so its VMs, capacity and load are not shown:" %} {{ compute.connection_error }}</div>
|
||||
<a class="btn btn-sm btn-warning" href="{% url 'overview' compute.id %}">{% bs_icon 'arrow-clockwise' %} {% trans "Try again" %}</a>
|
||||
<a class="btn btn-sm btn-outline-secondary" href="{% url 'compute_update' compute.id %}">{% trans "Edit connection" %}</a>
|
||||
</div>
|
||||
|
|
@ -39,108 +39,150 @@
|
|||
<div class="alert alert-warning" role="alert">{% trans "The host's details could not be read:" %} {{ read_error }}</div>
|
||||
{% endif %}
|
||||
|
||||
<h4 class="page-header">{% trans "VMs and what they were given" %}</h4>
|
||||
{% if given %}
|
||||
<div class="row row-cols-1 row-cols-sm-2 row-cols-xl-4 g-3 mb-4">
|
||||
<div class="col">
|
||||
<div class="card h-100"><div class="card-body">
|
||||
<h5 class="card-title">{% trans "VMs" %}</h5>
|
||||
<div class="card h-100">
|
||||
<div class="card-header">{% bs_icon 'server' %} {% trans "VMs" %}</div>
|
||||
<div class="card-body">
|
||||
<div class="compute-ratio">{{ given.vm_count }}</div>
|
||||
<div class="small text-body-secondary">
|
||||
{% blocktrans with running=given.vms.running shutoff=given.vms.shutoff %}{{ running }} running, {{ shutoff }} shut off{% endblocktrans %}{% if given.vms.paused %}, {% blocktrans with paused=given.vms.paused %}{{ paused }} paused{% endblocktrans %}{% endif %}{% if given.vms.other %}, {% blocktrans with other=given.vms.other %}{{ other }} other{% endblocktrans %}{% endif %}
|
||||
</div>
|
||||
<a class="small" href="{% url 'instances' compute.id %}">{% trans "Instances" %} →</a>
|
||||
</div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="card h-100"><div class="card-body">
|
||||
<h5 class="card-title">{% trans "vCPUs" %}</h5>
|
||||
<div class="card h-100">
|
||||
<div class="card-header">{% bs_icon 'cpu' %} {% trans "vCPUs" %}</div>
|
||||
<div class="card-body">
|
||||
{% include "computes/capacity_vcpus.html" %}
|
||||
</div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="card h-100"><div class="card-body compute-memory">
|
||||
<h5 class="card-title">{% trans "Memory" %}</h5>
|
||||
<div class="card h-100">
|
||||
<div class="card-header">{% bs_icon 'memory' %} {% trans "Memory" %}</div>
|
||||
<div class="card-body compute-memory">
|
||||
{% include "computes/capacity_memory.html" %}
|
||||
</div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="card h-100"><div class="card-body compute-storage">
|
||||
<h5 class="card-title">{% trans "Storage" %}</h5>
|
||||
<div class="card h-100">
|
||||
<div class="card-header">{% bs_icon 'device-hdd' %} {% trans "Storage" %}</div>
|
||||
<div class="card-body compute-storage">
|
||||
{% include "computes/capacity_storage.html" %}
|
||||
<a class="small" href="{% url 'storages' compute.id %}">{% trans "Storages" %} →</a>
|
||||
</div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<p class="text-body-secondary">{% trans "The capacity could not be read." %}</p>
|
||||
<div class="text-body-secondary mb-4">{% trans "The capacity could not be read." %}</div>
|
||||
{% endif %}
|
||||
|
||||
{# the load is read on its own: shown also when the details could not be #}
|
||||
<h4 class="page-header">{% trans "Load" %}</h4>
|
||||
<div class="row g-3">
|
||||
<div class="col-lg-6">
|
||||
<div class="card h-100"><div class="card-body">
|
||||
<h5 class="card-title d-flex justify-content-between">{% trans "CPU in use" %} <span id="cpu_now" class="text-body-secondary">–</span></h5>
|
||||
<div class="card h-100">
|
||||
<div class="card-header d-flex justify-content-between">
|
||||
<span>{% bs_icon 'speedometer2' %} {% trans "CPU in use" %}</span> <span id="cpu_now" class="fw-semibold">–</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="chart"><canvas id="cpuChart" role="img" aria-label="{% trans "CPU in use, recent readings" %}"></canvas></div>
|
||||
</div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div class="card h-100"><div class="card-body">
|
||||
<h5 class="card-title d-flex justify-content-between">{% trans "Memory in use" %} <span id="mem_now" class="text-body-secondary">–</span></h5>
|
||||
<div class="card h-100">
|
||||
<div class="card-header d-flex justify-content-between">
|
||||
<span>{% bs_icon 'memory' %} {% trans "Memory in use" %}</span> <span id="mem_now" class="fw-semibold">–</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="chart"><canvas id="memChart" role="img" aria-label="{% trans "Memory in use, recent readings" %}"></canvas></div>
|
||||
</div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p class="small text-body-secondary mt-2 mb-4">
|
||||
<div class="small text-body-secondary mt-2 mb-4">
|
||||
{% trans "The last 10 readings, one every 5 seconds. Memory in use leaves out the host's buffers and cache." %}
|
||||
<span id="graph_state" data-updated="{% trans "Updated at %(time)s." %}"
|
||||
data-stale="{% trans "Not updated since %(time)s: the host did not answer." %}">{% trans "Waiting for the first reading." %}</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{% if host %}
|
||||
<div class="row g-4">
|
||||
<div class="row g-3 mb-4">
|
||||
<div class="col-lg-6">
|
||||
<h4 class="page-header">{% trans "Hardware" %}</h4>
|
||||
<dl class="row">
|
||||
<dt class="col-sm-5">{% trans "Hostname" %}</dt>
|
||||
<dd class="col-sm-7 text-break">{{ host.hostname }}</dd>
|
||||
<dt class="col-sm-5">{% trans "Architecture" %}</dt>
|
||||
<dd class="col-sm-7">{{ host.arch }}</dd>
|
||||
<dt class="col-sm-5">{% trans "Processor" %}</dt>
|
||||
<dd class="col-sm-7">{{ host.processor|default:"–" }}</dd>
|
||||
<dt class="col-sm-5">{% trans "Logical CPUs" %}</dt>
|
||||
<dd class="col-sm-7">{{ host.topology.cpus }}</dd>
|
||||
<dt class="col-sm-5">{% trans "Physical cores" %}</dt>
|
||||
<dd class="col-sm-7">{{ host.topology.cores|default:"–" }}</dd>
|
||||
<dt class="col-sm-5">{% trans "Sockets" %}</dt>
|
||||
<dd class="col-sm-7">{{ host.topology.sockets|default:"–" }}</dd>
|
||||
<dt class="col-sm-5">{% trans "NUMA nodes" %}</dt>
|
||||
<dd class="col-sm-7">{{ host.topology.nodes|default:"–" }}</dd>
|
||||
<dt class="col-sm-5">{% trans "Clock" %}</dt>
|
||||
<dd class="col-sm-7">{{ host.topology.mhz }} MHz</dd>
|
||||
<dt class="col-sm-5">{% trans "Memory" %}</dt>
|
||||
<dd class="col-sm-7">{{ host.memory|filesizeformat }}</dd>
|
||||
</dl>
|
||||
<div class="card h-100">
|
||||
<div class="card-header">{% bs_icon 'cpu' %} {% trans "Hardware" %}</div>
|
||||
<ul class="list-group list-group-flush">
|
||||
<li class="list-group-item d-flex justify-content-between align-items-baseline gap-3">
|
||||
<span class="text-body-secondary">{% trans "Processor" %}</span>
|
||||
<span class="text-end text-break">{{ host.processor|default:"–" }}</span>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-baseline gap-3">
|
||||
<span class="text-body-secondary">{% trans "Architecture" %}</span>
|
||||
<span class="text-end text-break">{{ host.arch }}</span>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-baseline gap-3">
|
||||
<span class="text-body-secondary">{% trans "Logical CPUs" %}</span>
|
||||
<span class="text-end text-break"><span class="fw-semibold">{{ host.topology.cpus }}</span></span>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-baseline gap-3">
|
||||
<span class="text-body-secondary">{% trans "Physical cores" %}</span>
|
||||
<span class="text-end text-break"><span class="fw-semibold">{{ host.topology.cores|default:"–" }}</span></span>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-baseline gap-3">
|
||||
<span class="text-body-secondary">{% trans "Sockets" %}</span>
|
||||
<span class="text-end text-break"><span class="fw-semibold">{{ host.topology.sockets|default:"–" }}</span></span>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-baseline gap-3">
|
||||
<span class="text-body-secondary">{% trans "NUMA nodes" %}</span>
|
||||
<span class="text-end text-break"><span class="fw-semibold">{{ host.topology.nodes|default:"–" }}</span></span>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-baseline gap-3">
|
||||
<span class="text-body-secondary">{% trans "Clock" %}</span>
|
||||
<span class="text-end text-break">{{ host.ghz }} GHz</span>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-baseline gap-3">
|
||||
<span class="text-body-secondary">{% trans "Memory" %}</span>
|
||||
<span class="text-end text-break"><span class="fw-semibold">{{ host.memory|filesizeformat }}</span></span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<h4 class="page-header">{% trans "Software and connection" %}</h4>
|
||||
<dl class="row">
|
||||
<dt class="col-sm-5">{% trans "Hypervisor" %}</dt>
|
||||
<dd class="col-sm-7">{{ host.hypervisor }} {{ host.hypervisor_version }}</dd>
|
||||
<dt class="col-sm-5">libvirt</dt>
|
||||
<dd class="col-sm-7">{{ host.libvirt_version }}</dd>
|
||||
<dt class="col-sm-5">{% trans "Emulator" %}</dt>
|
||||
<dd class="col-sm-7 text-break">{{ host.emulator|default:"–" }}</dd>
|
||||
<dt class="col-sm-5">{% trans "Guest architectures" %}</dt>
|
||||
<dd class="col-sm-7">
|
||||
{% for arch, types in host.guest_archs.items %}
|
||||
<div>{{ arch }} <span class="text-body-secondary">({{ types|join:", " }})</span></div>
|
||||
{% endfor %}
|
||||
</dd>
|
||||
<dt class="col-sm-5">{% trans "Connection" %}</dt>
|
||||
<dd class="col-sm-7 text-break">{{ host.uri }}</dd>
|
||||
</dl>
|
||||
<div class="card h-100">
|
||||
<div class="card-header">{% bs_icon 'layers' %} {% trans "Software and connection" %}</div>
|
||||
<ul class="list-group list-group-flush">
|
||||
<li class="list-group-item d-flex justify-content-between align-items-baseline gap-3">
|
||||
<span class="text-body-secondary">{% trans "Hostname" %}</span>
|
||||
<span class="text-end text-break">{{ host.hostname }}</span>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-baseline gap-3">
|
||||
<span class="text-body-secondary">{{ host.hypervisor }}</span>
|
||||
<span class="text-end text-break"><span class="badge text-bg-primary">{{ host.hypervisor_version }}</span></span>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-baseline gap-3">
|
||||
<span class="text-body-secondary">libvirt</span>
|
||||
<span class="text-end text-break"><span class="badge text-bg-primary">{{ host.libvirt_version }}</span></span>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-baseline gap-3">
|
||||
<span class="text-body-secondary">{% trans "Guest architectures" %}</span>
|
||||
<span class="text-end text-break">{% for arch, types in host.guest_archs.items %}<span class="badge text-bg-light border ms-1">{{ arch }} <span class="fw-normal text-body-secondary">{{ types|join:" · " }}</span></span>{% endfor %}</span>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-baseline gap-3">
|
||||
<span class="text-body-secondary">{% trans "Emulator" %}</span>
|
||||
<span class="text-end text-break"><code>{{ host.emulator|default:"–" }}</code></span>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-baseline gap-3">
|
||||
<span class="text-body-secondary">{% trans "Connection" %}</span>
|
||||
<span class="text-end text-break"><code>{{ host.uri }}</code></span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
|
|
|||
|
|
@ -74,8 +74,8 @@ class ComputesPageTests(TestCase):
|
|||
self.assertIn("host-one", cells[0])
|
||||
self.assertIn("2.5:1", cells[1])
|
||||
self.assertIn("40 vCPUs on 16 CPUs 24 running", cells[1])
|
||||
self.assertIn("48.0 GB given of 64.0 GB", cells[2])
|
||||
self.assertIn("32.0 GB of it running", cells[2])
|
||||
self.assertIn("75 % 48.0 GB / 64.0 GB", cells[2])
|
||||
self.assertIn("32.0 GB running", cells[2])
|
||||
self.assertIn("120.0 GB free of 500.0 GB", cells[3])
|
||||
# host-two could not be read: one cell says so
|
||||
self.assertIn("capacity could not be read", " ".join(two.text_content().split()))
|
||||
|
|
|
|||
|
|
@ -49,27 +49,26 @@ class OverviewTestCase(TestCase):
|
|||
conn.get_emulator.return_value = "/usr/libexec/qemu-kvm"
|
||||
conn.get_hypervisors_domain_types.return_value = {"i686": ["kvm", "qemu"], "x86_64": ["kvm", "qemu"]}
|
||||
page = self.page()
|
||||
self.assertIn("Connected", text(page, "//p[span]"))
|
||||
self.assertIn("rack 4", text(page, "//p[span]"))
|
||||
cards = [" ".join(" ".join(card.itertext()).split()) for card in page.xpath("//div[@class='card-body' or contains(@class,'card-body ')]")]
|
||||
self.assertIn("Connected", text(page, "//div[@id='host_status']"))
|
||||
self.assertIn("rack 4", text(page, "//div[@id='host_status']"))
|
||||
cards = [" ".join(" ".join(card.itertext()).split()) for card in page.xpath("//div[@class='card h-100']")]
|
||||
self.assertIn("VMs 6 3 running, 2 shut off, 1 paused Instances →", cards)
|
||||
self.assertTrue(any(card.startswith("vCPUs 1.5:1 12 vCPUs on 8 CPUs 6 running") for card in cards), cards)
|
||||
self.assertTrue(any("24.0 GB given of 32.0 GB" in card for card in cards), cards)
|
||||
self.assertTrue(any(card.startswith("Memory 75 % 24.0 GB / 32.0 GB") for card in cards), cards)
|
||||
self.assertTrue(any("120.0 GB free of 500.0 GB" in card for card in cards), cards)
|
||||
hardware = text(page, "//h4[.='Hardware']/following-sibling::dl")
|
||||
self.assertIn("Logical CPUs 8 Physical cores 4 Sockets 2", hardware)
|
||||
self.assertIn("NUMA nodes 2", hardware)
|
||||
software = text(page, "//h4[.='Software and connection']/following-sibling::dl")
|
||||
self.assertIn("Hypervisor QEMU 10.1.0", software)
|
||||
self.assertIn("x86_64 (kvm, qemu)", software)
|
||||
# the charts poll only for a host that was read
|
||||
hardware = text(page, "//div[@class='card-header'][normalize-space()='Hardware']/..")
|
||||
self.assertIn("Processor Xeon Architecture x86_64 Logical CPUs 8 Physical cores 4 Sockets 2 NUMA nodes 2 "
|
||||
"Clock 2.4 GHz Memory 32.0 GB", hardware)
|
||||
software = text(page, "//div[@class='card-header'][normalize-space()='Software and connection']/..")
|
||||
self.assertIn("QEMU 10.1.0 libvirt 11.10.0", software)
|
||||
self.assertIn("x86_64 kvm · qemu", software)
|
||||
self.assertTrue(page.xpath("//canvas[@id='cpuChart']"))
|
||||
|
||||
@patch("computes.views.wvmHostDetails")
|
||||
def test_a_host_the_panel_cannot_reach_keeps_its_page_with_the_reason(self, details):
|
||||
page = self.page(connected=False, given=None)
|
||||
details.assert_not_called()
|
||||
self.assertIn("Not connected", text(page, "//p[span]"))
|
||||
self.assertIn("Not connected", text(page, "//div[@id='host_status']"))
|
||||
self.assertIn("did not answer within 5 s", text(page, "//div[@role='alert']"))
|
||||
# the way back: its sections, its connection and its removal
|
||||
self.assertTrue(page.xpath("//nav[@aria-label='Host sections']"))
|
||||
|
|
@ -83,10 +82,10 @@ class OverviewTestCase(TestCase):
|
|||
details.return_value.get_lib_version.side_effect = libvirtError("cannot read the version")
|
||||
page = self.page()
|
||||
self.assertIn("cannot read the version", text(page, "//div[@role='alert']"))
|
||||
self.assertTrue(page.xpath("//h5[.='VMs']"))
|
||||
self.assertTrue(page.xpath("//div[@class='card-header'][normalize-space()='VMs']"))
|
||||
# the load is read on its own, by the charts
|
||||
self.assertTrue(page.xpath("//canvas[@id='cpuChart']"))
|
||||
self.assertFalse(page.xpath("//h4[.='Hardware']"))
|
||||
self.assertFalse(page.xpath("//div[@class='card-header'][normalize-space()='Hardware']"))
|
||||
|
||||
def test_the_list_links_the_overview_of_a_host_it_cannot_reach(self):
|
||||
with patch.object(Compute, "status", new_callable=PropertyMock, return_value=False):
|
||||
|
|
|
|||
|
|
@ -84,9 +84,10 @@ def overview(request, compute_id):
|
|||
try:
|
||||
conn = wvmHostDetails(compute.hostname, compute.login, compute.password, compute.type)
|
||||
hostname, arch, memory, _cpus, processor, uri = conn.get_node_info()
|
||||
topology = conn.get_cpu_topology()
|
||||
context["host"] = {
|
||||
"hostname": hostname, "arch": arch, "memory": memory, "processor": processor, "uri": uri,
|
||||
"topology": conn.get_cpu_topology(),
|
||||
"topology": topology, "ghz": round(topology["mhz"] / 1000, 1),
|
||||
"hypervisor": conn.wvm.getType(), "hypervisor_version": conn.get_version(),
|
||||
"libvirt_version": conn.get_lib_version(),
|
||||
"emulator": conn.get_emulator(arch), "guest_archs": conn.get_hypervisors_domain_types(),
|
||||
|
|
|
|||
8
static/icon_cache/cpu_None_None_None.svg
Normal file
8
static/icon_cache/cpu_None_None_None.svg
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" ?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-cpu" viewBox="0 0 16 16">
|
||||
|
||||
|
||||
<path d="M5 0a.5.5 0 0 1 .5.5V2h1V.5a.5.5 0 0 1 1 0V2h1V.5a.5.5 0 0 1 1 0V2h1V.5a.5.5 0 0 1 1 0V2A2.5 2.5 0 0 1 14 4.5h1.5a.5.5 0 0 1 0 1H14v1h1.5a.5.5 0 0 1 0 1H14v1h1.5a.5.5 0 0 1 0 1H14v1h1.5a.5.5 0 0 1 0 1H14a2.5 2.5 0 0 1-2.5 2.5v1.5a.5.5 0 0 1-1 0V14h-1v1.5a.5.5 0 0 1-1 0V14h-1v1.5a.5.5 0 0 1-1 0V14h-1v1.5a.5.5 0 0 1-1 0V14A2.5 2.5 0 0 1 2 11.5H.5a.5.5 0 0 1 0-1H2v-1H.5a.5.5 0 0 1 0-1H2v-1H.5a.5.5 0 0 1 0-1H2v-1H.5a.5.5 0 0 1 0-1H2A2.5 2.5 0 0 1 4.5 2V.5A.5.5 0 0 1 5 0m-.5 3A1.5 1.5 0 0 0 3 4.5v7A1.5 1.5 0 0 0 4.5 13h7a1.5 1.5 0 0 0 1.5-1.5v-7A1.5 1.5 0 0 0 11.5 3zM5 6.5A1.5 1.5 0 0 1 6.5 5h3A1.5 1.5 0 0 1 11 6.5v3A1.5 1.5 0 0 1 9.5 11h-3A1.5 1.5 0 0 1 5 9.5zM6.5 6a.5.5 0 0 0-.5.5v3a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 0-.5-.5z"/>
|
||||
|
||||
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 918 B |
8
static/icon_cache/layers_None_None_None.svg
Normal file
8
static/icon_cache/layers_None_None_None.svg
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" ?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-layers" viewBox="0 0 16 16">
|
||||
|
||||
|
||||
<path d="M8.235 1.559a.5.5 0 0 0-.47 0l-7.5 4a.5.5 0 0 0 0 .882L3.188 8 .264 9.559a.5.5 0 0 0 0 .882l7.5 4a.5.5 0 0 0 .47 0l7.5-4a.5.5 0 0 0 0-.882L12.813 8l2.922-1.559a.5.5 0 0 0 0-.882l-7.5-4zm3.515 7.008L14.438 10 8 13.433 1.562 10 4.25 8.567l3.515 1.874a.5.5 0 0 0 .47 0l3.515-1.874zM8 9.433 1.562 6 8 2.567 14.438 6z"/>
|
||||
|
||||
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 489 B |
8
static/icon_cache/memory_None_None_None.svg
Normal file
8
static/icon_cache/memory_None_None_None.svg
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" ?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-memory" viewBox="0 0 16 16">
|
||||
|
||||
|
||||
<path d="M1 3a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h4.586a1 1 0 0 0 .707-.293l.353-.353a.5.5 0 0 1 .708 0l.353.353a1 1 0 0 0 .707.293H15a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1zm.5 1h3a.5.5 0 0 1 .5.5v4a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-4a.5.5 0 0 1 .5-.5m5 0h3a.5.5 0 0 1 .5.5v4a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-4a.5.5 0 0 1 .5-.5m4.5.5a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 .5.5v4a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5zM2 10v2H1v-2zm2 0v2H3v-2zm2 0v2H5v-2zm3 0v2H8v-2zm2 0v2h-1v-2zm2 0v2h-1v-2zm2 0v2h-1v-2z"/>
|
||||
|
||||
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 656 B |
11
static/icon_cache/speedometer2_None_None_None.svg
Normal file
11
static/icon_cache/speedometer2_None_None_None.svg
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" ?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-speedometer2" viewBox="0 0 16 16">
|
||||
|
||||
|
||||
<path d="M8 4a.5.5 0 0 1 .5.5V6a.5.5 0 0 1-1 0V4.5A.5.5 0 0 1 8 4M3.732 5.732a.5.5 0 0 1 .707 0l.915.914a.5.5 0 1 1-.708.708l-.914-.915a.5.5 0 0 1 0-.707zM2 10a.5.5 0 0 1 .5-.5h1.586a.5.5 0 0 1 0 1H2.5A.5.5 0 0 1 2 10m9.5 0a.5.5 0 0 1 .5-.5h1.5a.5.5 0 0 1 0 1H12a.5.5 0 0 1-.5-.5m.754-4.246a.389.389 0 0 0-.527-.02L7.547 9.31a.91.91 0 1 0 1.302 1.258l3.434-4.297a.389.389 0 0 0-.029-.518z"/>
|
||||
|
||||
|
||||
<path fill-rule="evenodd" d="M0 10a8 8 0 1 1 15.547 2.661c-.442 1.253-1.845 1.602-2.932 1.25C11.309 13.488 9.475 13 8 13c-1.474 0-3.31.488-4.615.911-1.087.352-2.49.003-2.932-1.25A7.988 7.988 0 0 1 0 10m8-7a7 7 0 0 0-6.603 9.329c.203.575.923.876 1.68.63C4.397 12.533 6.358 12 8 12s3.604.532 4.923.96c.757.245 1.477-.056 1.68-.631A7 7 0 0 0 8 3"/>
|
||||
|
||||
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 914 B |
Loading…
Add table
Add a link
Reference in a new issue