mirror of
https://github.com/retspen/webvirtcloud
synced 2026-11-11 04:36:48 +00:00
feat(instances): a VM's options in one list, each saved when it can be
Settings > Options was four forms under bold sentences, most of them disabled while the VM ran. The owner chose this layout from three rendered options: one list, each row a setting with its description on the left and its control on the right: VM details (title, description), Template, primary video model, QEMU guest agent. vCPU hot plug moved to Resize > CPU, next to the vCPU counts. Codex reviewed the four forms; these are fixed: - Title, description and the video model are saved while the VM runs: they are in the persistent definition, used at the next start. - The template flag has its own form and view, set_template, for superusers and staff, and only for a shut-off VM: a running VM made a template left the quota while it kept running. Turning a template back into a VM checks the quota there, and each change is audited. The title form no longer touches the flag. - A new video model stays the primary one; the old model's memory and head settings, which are its own, go with it. - The agent and vCPU hot plug forms show the persistent definition; they showed the running VM's, so a pending change looked undone. - Enabling the guest agent adds its channel only where it is missing: saving Enabled again failed, and a channel pending the next start kept a running VM from getting one. - The agent line tells a VM that is not running, one without a channel, and a connected or not connected agent apart.
This commit is contained in:
parent
46188d3230
commit
a993c12db0
13 changed files with 272 additions and 172 deletions
|
|
@ -2165,45 +2165,47 @@ def update_console(request, pk):
|
|||
|
||||
|
||||
@require_POST
|
||||
@serialize_user_quota
|
||||
@serialize_instance_mutation
|
||||
def change_options(request, pk):
|
||||
"""The title and description of the persistent definition: they apply
|
||||
at the next start, so a running VM's are changed too."""
|
||||
instance = get_instance(request.user, pk, perm_type="change")
|
||||
try:
|
||||
userinstance = instance.userinstance_set.get(user=request.user)
|
||||
except UserInstance.DoesNotExist:
|
||||
userinstance = UserInstance(is_change=False)
|
||||
|
||||
if request.user.is_superuser or userinstance.is_change:
|
||||
# Only superusers and staff may (un)mark templates. The
|
||||
# checkbox is disabled for everyone else, and a disabled checkbox is
|
||||
# not submitted, so for them the flag must be left alone.
|
||||
if request.user.is_superuser or request.user.is_staff:
|
||||
is_template = bool(request.POST.get("is_template", False))
|
||||
# A template is not counted and cannot be started: making it a
|
||||
# VM again adds it to the owner's usage, so the quota applies.
|
||||
if instance.is_template and not is_template and not request.user.is_superuser:
|
||||
disk_sum = sum(int(disk.get("size") or 0) >> 30 for disk in instance.disks)
|
||||
quota_msg = utils.check_user_quota(request.user, 1, instance.vcpu, instance.memory, disk_sum)
|
||||
if quota_msg:
|
||||
messages.error(request, quota_refused(quota_msg, _(
|
||||
"User %(quota_msg)s quota reached, '%(instance_name)s' stays a template!"
|
||||
) % {"quota_msg": quota_msg, "instance_name": instance.name}))
|
||||
is_template = True
|
||||
instance.is_template = is_template
|
||||
instance.save(update_fields=["is_template"])
|
||||
|
||||
options = {}
|
||||
for post in request.POST:
|
||||
if post in ["title", "description"]:
|
||||
options[post] = request.POST.get(post, "")
|
||||
with audit_vm(request, instance, "edit options"):
|
||||
instance.proxy.set_options(options)
|
||||
options = {key: request.POST.get(key, "") for key in ("title", "description") if key in request.POST}
|
||||
with audit_vm(request, instance, "edit options"):
|
||||
instance.proxy.set_options(options)
|
||||
return get_safe_redirect(
|
||||
request, default=reverse("instances:instance", args=[instance.id]) + "#options"
|
||||
)
|
||||
|
||||
|
||||
@require_POST
|
||||
@serialize_user_quota
|
||||
@serialize_instance_mutation
|
||||
def set_template(request, pk):
|
||||
"""Marks a shut-off VM as a template, or a template as a VM again; only
|
||||
superusers and staff. A template is not counted and cannot be started:
|
||||
making it a VM again adds it to the owner's usage, so the quota applies."""
|
||||
instance = get_instance(request.user, pk, perm_type="change")
|
||||
if not (request.user.is_superuser or request.user.is_staff):
|
||||
raise PermissionDenied
|
||||
is_template = bool(request.POST.get("is_template"))
|
||||
if instance.proxy.get_status() != 5:
|
||||
messages.error(request, _("Shut the VM down to change whether it is a template."))
|
||||
return _back(request, pk, "options")
|
||||
if instance.is_template and not is_template and not request.user.is_superuser:
|
||||
disk_sum = sum(int(disk.get("size") or 0) >> 30 for disk in instance.disks)
|
||||
quota_msg = utils.check_user_quota(request.user, 1, instance.vcpu, instance.memory, disk_sum)
|
||||
if quota_msg:
|
||||
messages.error(request, quota_refused(quota_msg, _(
|
||||
"User %(quota_msg)s quota reached, '%(instance_name)s' stays a template!"
|
||||
) % {"quota_msg": quota_msg, "instance_name": instance.name}))
|
||||
return _back(request, pk, "options")
|
||||
with audit_vm(request, instance, "mark as template" if is_template else "unmark as template"):
|
||||
instance.is_template = is_template
|
||||
instance.save(update_fields=["is_template"])
|
||||
return _back(request, pk, "options")
|
||||
|
||||
|
||||
def getvvfile(request, pk):
|
||||
instance = get_instance(request.user, pk)
|
||||
# The .vv file contains the VNC password: same rule as the console.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue