mirror of
https://github.com/retspen/webvirtcloud
synced 2026-11-08 19:26:48 +00:00
fix(instances): VM list columns, hosts for viewers, flavor units
- On a narrow screen the grouped list hid the User, VCPU and Memory headings but not the VMs' cells, so values sat under the wrong headings; the cells now hide with their headings. Memory says MiB. - A user with the view_instances permission sees each VM's host in the list, as the host alerts already name them; the host page link stays a superuser's. - A flavor's memory and disk are labelled MiB and GiB, and each value is at least 1, so "4" is no longer saved as a 4 MiB preset by mistake.
This commit is contained in:
parent
52d00e818b
commit
b89f280076
6 changed files with 31 additions and 9 deletions
|
|
@ -10,6 +10,11 @@ from .utils import nic_macs
|
|||
|
||||
|
||||
class FlavorForm(forms.ModelForm):
|
||||
# the units the create form fills in from a flavor
|
||||
memory = forms.IntegerField(label=_("Memory (MiB)"), min_value=1)
|
||||
vcpu = forms.IntegerField(label=_("vCPUs"), min_value=1)
|
||||
disk = forms.IntegerField(label=_("Disk (GiB)"), min_value=1)
|
||||
|
||||
class Meta:
|
||||
model = Flavor
|
||||
fields = "__all__"
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
{% endif %}
|
||||
</td>
|
||||
{% if app_settings.VM_DRBD_STATUS == 'True' %}
|
||||
<td class="d-none d-sm-table-cell"></td>
|
||||
<td></td>
|
||||
{% endif %}
|
||||
{% if compute.status is True %}
|
||||
<td class="d-none d-sm-table-cell text-center">{{ compute.cpu_count }}</td>
|
||||
|
|
@ -62,7 +62,7 @@
|
|||
<br>
|
||||
{% if instance.info %}<p class="m-0 small fst-italic">{{ instance.title }}</p>{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<td class="d-none d-sm-table-cell">
|
||||
<em>
|
||||
{% if instance.userinstance_set.all.count > 0 %}
|
||||
{{ instance.userinstance_set.all.0.user }}
|
||||
|
|
@ -80,8 +80,8 @@
|
|||
{% if instance.drbd == "Primary/OK" or instance.drbd == "Secondary/OK" %}<span class="badge bg-success-subtle text-success-emphasis">{% else %}<span class="badge bg-danger-subtle text-danger-emphasis">{% endif %}{{ instance.drbd }}</span>
|
||||
</td>
|
||||
{% endif %}
|
||||
<td data-sort="{{ instance.info.3 }}">{{ instance.info.3 }}</td>
|
||||
<td data-sort="{{ instance.info.2 }}">{% if instance.info %}{% widthratio instance.info.2 1024 1 %} MB{% endif %}</td>
|
||||
<td class="d-none d-sm-table-cell" data-sort="{{ instance.info.3 }}">{{ instance.info.3 }}</td>
|
||||
<td class="d-none d-sm-table-cell" data-sort="{{ instance.info.2 }}">{% if instance.info %}{% widthratio instance.info.2 1024 1 %} MiB{% endif %}</td>
|
||||
<td class="text-nowrap">
|
||||
{% include 'instance_actions.html' %}
|
||||
</td>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
<thead>
|
||||
<tr>
|
||||
<th scope="col">{% trans 'Name' %}<br>{% trans 'Description' %}</th>
|
||||
{% if request.user.is_superuser %}
|
||||
{% if show_hosts %}
|
||||
<th scope="col">{% trans 'Host' %}<br>{% trans 'User' %}</th>
|
||||
{% endif %}
|
||||
<th scope="col">{% trans 'Status' %}</th>
|
||||
|
|
@ -26,9 +26,10 @@
|
|||
<br>
|
||||
{% if instance.info %}<p class="m-0 small font-italic">{{ instance.title }}</p>{% endif %}
|
||||
</td>
|
||||
{% if request.user.is_superuser %}
|
||||
{% if show_hosts %}
|
||||
<td>
|
||||
<a href="{% url 'overview' instance.compute.id %}">{{ instance.compute.name }}</a><br>
|
||||
{# the host pages are a superuser's #}
|
||||
{% if request.user.is_superuser %}<a href="{% url 'overview' instance.compute.id %}">{{ instance.compute.name }}</a>{% else %}{{ instance.compute.name }}{% endif %}<br>
|
||||
<small><em>
|
||||
{% if instance.userinstance_set.all.count > 0 %}
|
||||
{{ instance.userinstance_set.all.0.user }}
|
||||
|
|
@ -48,7 +49,7 @@
|
|||
</td>
|
||||
{% endif %}
|
||||
<td data-sort="{{ instance.info.3 }}">{{ instance.info.3 }}</td>
|
||||
<td data-sort="{{ instance.info.2 }}">{% if instance.info %}{% widthratio instance.info.2 1024 1 %} MB{% endif %}</td>
|
||||
<td data-sort="{{ instance.info.2 }}">{% if instance.info %}{% widthratio instance.info.2 1024 1 %} MiB{% endif %}</td>
|
||||
<td class="text-nowrap">
|
||||
{% include 'instance_actions.html' %}
|
||||
</td>
|
||||
|
|
|
|||
|
|
@ -307,3 +307,12 @@ class XmlRefusalTests(TestCase):
|
|||
|
||||
def test_a_definition_libvirt_refuses(self):
|
||||
self.assertIn("libvirt", self.post("<domain type='nope'><name>new</name><memory>1024</memory></domain>"))
|
||||
|
||||
|
||||
class FlavorFormTests(TestCase):
|
||||
def test_a_flavor_is_at_least_one_of_each_in_named_units(self):
|
||||
from instances.forms import FlavorForm
|
||||
|
||||
form = FlavorForm({"label": "tiny", "memory": "0", "vcpu": "-1", "disk": "0"})
|
||||
self.assertEqual(set(form.errors), {"memory", "vcpu", "disk"})
|
||||
self.assertEqual((form["memory"].label, form["disk"].label), ("Memory (MiB)", "Disk (GiB)"))
|
||||
|
|
|
|||
|
|
@ -61,3 +61,10 @@ class IndexHostAlertTests(TestCase):
|
|||
viewer.user_permissions.add(Permission.objects.get(codename="view_instances"))
|
||||
response = self.get(viewer, down={"other-host"})
|
||||
self.assertContains(response, "Connection Failed: no route to 10.0.0.2")
|
||||
|
||||
def test_global_viewer_sees_each_vms_host_without_the_host_page(self):
|
||||
viewer = get_user_model().objects.create_user(username="viewer2", password="pwd")
|
||||
viewer.user_permissions.add(Permission.objects.get(codename="view_instances"))
|
||||
response = self.get(viewer, down=set())
|
||||
self.assertContains(response, "mine-host")
|
||||
self.assertNotContains(response, reverse("overview", args=[self.mine.id]))
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ class ListInfoCallTests(TestCase):
|
|||
self.assertEqual(response.status_code, 200)
|
||||
return response
|
||||
|
||||
def assert_one_info_per_vm(self, response, memory="2048 MB"):
|
||||
def assert_one_info_per_vm(self, response, memory="2048 MiB"):
|
||||
self.assertEqual(len(self.domains), 2, "one proxy per VM row")
|
||||
for domain in self.domains:
|
||||
self.assertEqual(domain.info_calls, 1)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue