diff --git a/instances/jobs.py b/instances/jobs.py index b3dd5599..54bf23a1 100644 --- a/instances/jobs.py +++ b/instances/jobs.py @@ -124,7 +124,7 @@ def clone_data(user, instance, fields): """The clone's settings from the form fields and the source as it is now, and what it adds to the user's quota; OperationError with the reason when it cannot be made.""" - from instances.views import VOLUME_NAME_RE, quota_refused + from instances.views import VOLUME_NAME_RE data = dict() data["name"] = fields.get("name", "").strip() @@ -187,10 +187,11 @@ def clone_data(user, instance, fields): if key.startswith("disk-") and value is not None and not VOLUME_NAME_RE.fullmatch(value) ] + if not user.is_superuser and quota_msg == utils.QUOTA_UNVERIFIED: + raise util.OperationError(utils.QUOTA_UNVERIFIED_TEXT) if not user.is_superuser and quota_msg: - raise util.OperationError(quota_refused(quota_msg, _( - "User '%(quota_msg)s' quota reached, cannot create '%(clone_name)s'!" - )), quota_msg=quota_msg, clone_name=data["name"]) + raise util.OperationError(_("%(quota)s: cannot create '%(clone_name)s'."), + quota=utils.quota_message(quota_msg), clone_name=data["name"]) if check_instance: raise util.OperationError(_("Instance '%(clone_name)s' already exists!"), clone_name=data["name"]) if not re.match(r"^[a-zA-Z0-9-]+$", data["name"]): diff --git a/instances/tests/test_quota.py b/instances/tests/test_quota.py index 5d18ef3b..1466f918 100644 --- a/instances/tests/test_quota.py +++ b/instances/tests/test_quota.py @@ -12,7 +12,8 @@ from django.contrib.messages import get_messages from django.test import TestCase from django.urls import reverse from instances.models import Instance -from instances.utils import QUOTA_UNVERIFIED, check_user_quota +from instances.utils import QUOTA_UNVERIFIED, QuotaExceeded, check_user_quota, quota_message +from vrtManager.util import render from libvirt import VIR_DOMAIN_PAUSED, VIR_DOMAIN_RUNNING from operations.models import Operation from vrtManager.util import OperationError @@ -71,7 +72,7 @@ class QuotaTests(TestCase): "instances.utils.wvmInstance", side_effect=reader ) as wvm: result = check_user_quota(self.user, *delta) - return result.split(" ")[0], wvm.call_count # without the QUOTA_DEBUG detail + return getattr(result, "kind", result), wvm.call_count # a QuotaExceeded names the quota def test_vms_on_a_host_without_a_tcp_route_are_counted(self): # an ssh_config alias: the old TCP probe failed and skipped these VMs @@ -191,12 +192,15 @@ class QuotaTests(TestCase): for i in range(5): self.own(self.up, i) - for value, expected in (("True", "instance (6 > 5)"), ("False", "instance")): + with patch.object(Compute, "status", True), patch("instances.utils.wvmInstance", side_effect=vm_reader()): + exceeded = check_user_quota(self.user, 1, 0, 0, 0) + self.assertEqual(exceeded, QuotaExceeded("instance", 6, 5)) + for value, expected in (("True", "The quota of virtual machines is reached (6 > 5)"), + ("False", "The quota of virtual machines is reached")): with self.subTest(value=value): AppSettings.objects.filter(key="QUOTA_DEBUG").update(value=value) get_settings() - with patch.object(Compute, "status", True), patch("instances.utils.wvmInstance", side_effect=vm_reader()): - self.assertEqual(check_user_quota(self.user, 1, 0, 0, 0), expected) + self.assertEqual(render("%(quota)s", {"quota": quota_message(exceeded)}, str), expected) class QuotaViewTests(TestCase): @@ -228,7 +232,7 @@ class QuotaViewTests(TestCase): status=5) self.assertEqual(len(messages), 1) self.assertIn("a host of your virtual machines cannot be reached", messages[0]) - self.assertNotIn("quota reached", messages[0]) + self.assertNotIn("quota is reached", messages[0]) proxy.resize_cpu.assert_not_called() def test_running_vm_memory_charges_no_maximum_change(self): diff --git a/instances/tests/test_template_quota.py b/instances/tests/test_template_quota.py index 39de4de3..f7ff67bd 100644 --- a/instances/tests/test_template_quota.py +++ b/instances/tests/test_template_quota.py @@ -11,7 +11,7 @@ from django.contrib.messages import get_messages from django.test import TestCase from django.urls import reverse from instances.models import Instance -from instances.utils import QUOTA_UNVERIFIED +from instances.utils import QUOTA_UNVERIFIED, QuotaExceeded class TemplateFlagQuotaTests(TestCase): @@ -49,7 +49,7 @@ class TemplateFlagQuotaTests(TestCase): def test_over_quota_the_template_stays_a_template(self): Instance.objects.filter(pk=self.vm.pk).update(is_template=True) - _, messages = self.post(self.staff, is_template=False, quota="cpu") + _, messages = self.post(self.staff, is_template=False, quota=QuotaExceeded("cpu", 9, 8)) self.assertTrue(self.vm.is_template) self.assertTrue(any("quota" in m for m in messages), messages) @@ -70,6 +70,6 @@ class TemplateFlagQuotaTests(TestCase): def test_superusers_have_no_quota(self): Instance.objects.filter(pk=self.vm.pk).update(is_template=True) admin = get_user_model().objects.create_superuser("tq-admin", "tq@example.com", "pw") - check, _ = self.post(admin, is_template=False, quota="cpu") + check, _ = self.post(admin, is_template=False, quota=QuotaExceeded("cpu", 9, 8)) self.assertFalse(self.vm.is_template) check.assert_not_called() diff --git a/instances/utils.py b/instances/utils.py index 9b9b3b48..ee1ce19a 100644 --- a/instances/utils.py +++ b/instances/utils.py @@ -2,6 +2,7 @@ import os import random import re import string +from collections import namedtuple from accounts.models import UserInstance, UserAttributes from appsettings.settings import app_settings @@ -9,12 +10,13 @@ from computes.models import Compute from django.conf import settings from django.db import transaction from django.utils.translation import gettext_lazy as _ +from django.utils.translation import gettext_noop from libvirt import libvirtError from logs.audit import reason, write from operations.models import Operation from vrtManager.connection import other_hosts, wvmConnect from vrtManager.instance import wvmInstance, wvmInstances -from vrtManager.util import OperationError +from vrtManager.util import OperationError, message from .models import Instance @@ -73,13 +75,34 @@ def disk_gib(disks): # check_user_quota could not read every VM of the user: an increase is refused QUOTA_UNVERIFIED = "unverified" +QUOTA_UNVERIFIED_TEXT = gettext_noop( + "The quota cannot be checked because a host of your virtual machines cannot be reached. Nothing was changed.") + +# The quota a change would exceed: instance, cpu, memory or disk, the total it +# would make and the limit +QuotaExceeded = namedtuple("QuotaExceeded", "kind total limit") +QUOTA_REACHED = { + "instance": gettext_noop("The quota of virtual machines is reached"), + "cpu": gettext_noop("The vCPU quota is reached"), + "memory": gettext_noop("The memory quota is reached"), + "disk": gettext_noop("The disk quota is reached"), +} + + +def quota_message(exceeded): + """The quota check's result as messages, with the numbers when QUOTA_DEBUG is on.""" + reached = message(QUOTA_REACHED[exceeded.kind]) + if app_settings.QUOTA_DEBUG != "True": + return [reached] + return [message(gettext_noop("%(quota)s (%(total)s > %(limit)s)"), + quota=[reached], total=exceeded.total, limit=exceeded.limit)] @other_hosts() def check_user_quota(user, instance, cpu, memory, disk_size): """ - Which quota the user would exceed by adding these amounts (instances, - vCPUs, memory MiB, disk GiB) to their VMs, or "". A quota of -1 has no + The quota the user would exceed by adding these amounts (instances, + vCPUs, memory MiB, disk GiB) to their VMs, a QuotaExceeded, or "". A quota of -1 has no limit; 0 allows none. QUOTA_UNVERIFIED if a VM that counts cannot be read (its host is down, the VM is gone): the usage is unknown, so an increase is refused. @@ -93,8 +116,6 @@ def check_user_quota(user, instance, cpu, memory, disk_size): if instance <= 0 and cpu <= 0 and memory <= 0 and disk_size <= 0: return msg - quota_debug = app_settings.QUOTA_DEBUG == "True" - user_instances = UserInstance.objects.filter(user=user, instance__is_template=False).select_related( "instance__compute" ) @@ -106,10 +127,7 @@ def check_user_quota(user, instance, cpu, memory, disk_size): ] instance += user_instances.count() + len(clones) if ua.max_instances >= 0 and instance > ua.max_instances: - msg = "instance" - if quota_debug: - msg += f" ({instance} > {ua.max_instances})" - return msg + return QuotaExceeded("instance", instance, ua.max_instances) if ua.max_cpus < 0 and ua.max_memory < 0 and ua.max_disk_size < 0: return msg @@ -141,17 +159,11 @@ def check_user_quota(user, instance, cpu, memory, disk_size): return QUOTA_UNVERIFIED if ua.max_cpus >= 0 and cpu > ua.max_cpus: - msg = "cpu" - if quota_debug: - msg += f" ({cpu} > {ua.max_cpus})" + msg = QuotaExceeded("cpu", cpu, ua.max_cpus) if ua.max_memory >= 0 and memory > ua.max_memory: - msg = "memory" - if quota_debug: - msg += f" ({memory} > {ua.max_memory})" + msg = QuotaExceeded("memory", memory, ua.max_memory) if ua.max_disk_size >= 0 and disk_size > ua.max_disk_size: - msg = "disk" - if quota_debug: - msg += f" ({disk_size} > {ua.max_disk_size})" + msg = QuotaExceeded("disk", disk_size, ua.max_disk_size) return msg diff --git a/instances/views.py b/instances/views.py index 42cd6cc1..eed36682 100755 --- a/instances/views.py +++ b/instances/views.py @@ -36,7 +36,7 @@ from django.urls import reverse from django.template.defaultfilters import filesizeformat from django.utils import timezone from django.utils.translation import gettext as _ -from django.utils.translation import gettext_lazy +from django.utils.translation import gettext_lazy, gettext_noop from django.views.decorators.http import require_POST from libvirt import (VIR_DOMAIN_PAUSED, VIR_DOMAIN_RUNNING, @@ -657,12 +657,12 @@ def serialize_instance_mutation(func): return wrapper -def quota_refused(quota_msg, refused): - """The message for a refused change: refused is the action's own - 'User %(quota_msg)s quota reached, ...' text, already formatted.""" - if quota_msg == utils.QUOTA_UNVERIFIED: - return _("The quota cannot be checked because a host of your virtual machines cannot be reached. Nothing was changed.") - return refused +def quota_refused(quota, text, **values): + """The message for a change the quota refuses: text names the change + after %(quota)s, the quota it would exceed.""" + if quota == utils.QUOTA_UNVERIFIED: + return _(utils.QUOTA_UNVERIFIED_TEXT) + return util.render(text, {"quota": utils.quota_message(quota), **values}, _) def serialize_user_quota(func): @@ -1174,12 +1174,8 @@ def resizevm_cpu(request, pk): request.user, 0, int(new_vcpu) - vcpu, 0, 0 ) if not request.user.is_superuser and quota_msg: - msg = quota_refused(quota_msg, _( - "User %(quota_msg)s quota reached, cannot resize CPU of '%(instance_name)s'!" - ) % { - "quota_msg": quota_msg, - "instance_name": instance.name, - }) + msg = quota_refused(quota_msg, gettext_noop("%(quota)s: cannot resize the CPU of '%(instance_name)s'."), + instance_name=instance.name) messages.error(request, msg) else: cur_vcpu = new_cur_vcpu @@ -1212,12 +1208,8 @@ def resize_memory(request, pk): return redirect(reverse("instances:instance", args=[instance.id]) + "#resize") quota_msg = utils.check_user_quota(request.user, 0, 0, int(new_memory) - memory, 0) if not request.user.is_superuser and quota_msg: - msg = quota_refused(quota_msg, _( - "User %(quota_msg)s quota reached, cannot resize memory of '%(instance_name)s'!" - ) % { - "quota_msg": quota_msg, - "instance_name": instance.name, - }) + msg = quota_refused(quota_msg, gettext_noop("%(quota)s: cannot resize the memory of '%(instance_name)s'."), + instance_name=instance.name) messages.error(request, msg) else: with audit_vm(request, instance, f"set memory to {new_cur_memory} MiB (maximum {new_memory} MiB)"): @@ -1263,12 +1255,8 @@ def resize_disk(request, pk): request.user, 0, 0, 0, disk_new_sum - disk_sum ) if not request.user.is_superuser and quota_msg: - msg = quota_refused(quota_msg, _( - "User %(quota_msg)s quota reached, cannot resize disks of '%(instance_name)s'!" - ) % { - "quota_msg": quota_msg, - "instance_name": instance.name, - }) + msg = quota_refused(quota_msg, gettext_noop("%(quota)s: cannot resize the disks of '%(instance_name)s'."), + instance_name=instance.name) messages.error(request, msg) else: for disk in disks_new: @@ -2393,9 +2381,8 @@ def set_template(request, pk): quota_msg = utils.check_user_quota(request.user, 1, instance.vcpu, instance.memory, utils.disk_gib(instance.disks)) 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})) + messages.error(request, quota_refused(quota_msg, gettext_noop("%(quota)s: '%(instance_name)s' stays a template."), + 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 diff --git a/locale/tr/LC_MESSAGES/django.mo b/locale/tr/LC_MESSAGES/django.mo index 6a9c4234..9c4bfc61 100644 Binary files a/locale/tr/LC_MESSAGES/django.mo and b/locale/tr/LC_MESSAGES/django.mo differ diff --git a/locale/tr/LC_MESSAGES/django.po b/locale/tr/LC_MESSAGES/django.po index b8a256f9..d068265b 100644 --- a/locale/tr/LC_MESSAGES/django.po +++ b/locale/tr/LC_MESSAGES/django.po @@ -11,7 +11,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-11-02 21:03+0000\n" +"POT-Creation-Date: 2026-11-03 15:16+0000\n" "PO-Revision-Date: 2020-11-04 12:00+0000\n" "Last-Translator: catborise , 2020\n" "Language-Team: Turkish (https://www.transifex.com/catborise/teams/110663/" @@ -2669,43 +2669,41 @@ msgstr "Klon için belleği (MiB) tam sayı olarak girin" msgid "Choose the clone's name from the list of free names" msgstr "Klonun adını boş adlar listesinden seçin" -#: instances/jobs.py:192 +#: instances/jobs.py:193 #, python-format -msgid "User '%(quota_msg)s' quota reached, cannot create '%(clone_name)s'!" -msgstr "" -"%(quota_msg)s' Kullanıcı kotası doldu, '%(clone_name)s' in CPU su yeniden " -"boyutlandırılamıyor!" +msgid "%(quota)s: cannot create '%(clone_name)s'." +msgstr "%(quota)s: '%(clone_name)s' oluşturulamıyor." -#: instances/jobs.py:195 instances/jobs.py:532 +#: instances/jobs.py:196 instances/jobs.py:533 #, python-format msgid "Instance '%(clone_name)s' already exists!" msgstr "'%(clone_name)s' sanal makinesi zaten mevcut!" -#: instances/jobs.py:197 +#: instances/jobs.py:198 #, python-format msgid "Instance name '%(clone_name)s' contains invalid characters!" msgstr "Sanal makine adı '%(clone_name)s' geçersiz karakterler içermektedir!" -#: instances/jobs.py:200 +#: instances/jobs.py:201 #, python-format msgid "Instance MAC '%(clone_mac)s' invalid format!" msgstr "Sanal makine MAC adresi '%(clone_mac)s' geçersiz biçemde belirtilmiş!" -#: instances/jobs.py:202 +#: instances/jobs.py:203 #, python-format msgid "Disk name '%(disk_name)s' contains invalid characters!" msgstr "Disk adı '%(disk_name)s' geçersiz karakterler içeriyor!" -#: instances/jobs.py:222 +#: instances/jobs.py:223 #, python-format msgid "The clone is made, but not as asked: %(error)s" msgstr "Klon oluşturuldu, ama istendiği gibi değil: %(error)s" -#: instances/jobs.py:270 +#: instances/jobs.py:271 msgid "The VM was not defined and no volume of it was left." msgstr "Sanal makine tanımlanmadı ve ondan geriye birim kalmadı." -#: instances/jobs.py:272 +#: instances/jobs.py:273 #, python-format msgid "" "The VM was not defined; check these volumes, then resolve this job: " @@ -2714,28 +2712,28 @@ msgstr "" "Sanal makine tanımlanmadı; şu birimleri kontrol edin, sonra bu işi çözün: " "%(volumes)s" -#: instances/jobs.py:293 +#: instances/jobs.py:294 msgid "Delete snapshot" msgstr "Anlık görüntüyü sil" -#: instances/jobs.py:303 vrtManager/instance.py:2304 +#: instances/jobs.py:304 vrtManager/instance.py:2280 #, python-format msgid "The VM has no external snapshot named %(name)s" msgstr "Sanal makinede %(name)s adında harici anlık görüntü yok" -#: instances/jobs.py:316 +#: instances/jobs.py:317 msgid "Merging the snapshot" msgstr "Anlık görüntü birleştiriliyor" -#: instances/jobs.py:335 +#: instances/jobs.py:336 msgid "The VM is no longer on its compute" msgstr "Sanal makine artık kendi sunucusunda değil" -#: instances/jobs.py:338 +#: instances/jobs.py:339 msgid "libvirt is still merging the snapshot" msgstr "libvirt anlık görüntüyü hâlâ birleştiriyor" -#: instances/jobs.py:346 +#: instances/jobs.py:347 msgid "" "The snapshot is still listed and no merge runs. It cannot be told whether " "the disks changed; check the VM before deleting the snapshot again or " @@ -2745,44 +2743,44 @@ msgstr "" "değişmediği bilinemiyor; anlık görüntüyü yeniden silmeden ya da ona dönmeden " "önce sanal makineyi kontrol edin." -#: instances/jobs.py:353 +#: instances/jobs.py:354 msgid "The VM is no longer on the compute the job ran on" msgstr "Sanal makine artık işin çalıştığı sunucuda değil" -#: instances/jobs.py:359 +#: instances/jobs.py:360 msgid "Take snapshot" msgstr "Anlık görüntü al" -#: instances/jobs.py:371 vrtManager/instance.py:1900 +#: instances/jobs.py:372 vrtManager/instance.py:1876 #, python-format msgid "A snapshot named %(name)s already exists" msgstr "%(name)s adında bir anlık görüntü zaten var" -#: instances/jobs.py:383 +#: instances/jobs.py:384 msgid "Taking the snapshot" msgstr "Anlık görüntü alınıyor" -#: instances/jobs.py:396 +#: instances/jobs.py:397 msgid "libvirt is still taking the snapshot" msgstr "libvirt anlık görüntüyü hâlâ alıyor" -#: instances/jobs.py:399 +#: instances/jobs.py:400 msgid "The snapshot was not taken" msgstr "Anlık görüntü alınmadı" -#: instances/jobs.py:422 +#: instances/jobs.py:423 msgid "Revert snapshot" msgstr "Snapshota dön" -#: instances/jobs.py:451 +#: instances/jobs.py:452 msgid "Reverting the VM" msgstr "Sanal makine geri döndürülüyor" -#: instances/jobs.py:462 +#: instances/jobs.py:463 msgid "libvirt is still reverting the VM" msgstr "libvirt sanal makineyi hâlâ geri döndürüyor" -#: instances/jobs.py:466 +#: instances/jobs.py:467 msgid "" "It cannot be told whether the VM was reverted; check it, then revert again " "or resolve this job." @@ -2790,12 +2788,12 @@ msgstr "" "Sanal makinenin geri döndürülüp döndürülmediği bilinemiyor; kontrol edin, " "sonra yeniden geri döndürün ya da bu işi çözün." -#: instances/jobs.py:483 +#: instances/jobs.py:484 msgid "The VM must be running, paused or shut off to be cloned" msgstr "" "Klonlanmak için sanal makine çalışıyor, duraklatılmış ya da kapalı olmalı" -#: instances/jobs.py:484 +#: instances/jobs.py:485 #, python-format msgid "" "The guest's file systems could not be thawed (%(error)s); thaw them with: " @@ -2804,19 +2802,19 @@ msgstr "" "Konuğun dosya sistemleri çözülemedi (%(error)s); şununla çözün: virsh " "domfsthaw %(vm)s" -#: instances/jobs.py:503 +#: instances/jobs.py:504 msgid "Clone VM" msgstr "Sanal makineyi klonla" -#: instances/jobs.py:542 instances/jobs.py:549 instances/jobs.py:806 +#: instances/jobs.py:543 instances/jobs.py:550 instances/jobs.py:807 msgid "Copying disks" msgstr "Diskler kopyalanıyor" -#: instances/jobs.py:601 +#: instances/jobs.py:602 msgid "libvirt has no result of the copy" msgstr "libvirt'te kopyanın sonucu yok" -#: instances/jobs.py:612 +#: instances/jobs.py:613 #, python-format msgid "" "The copy failed: %(error)s. The guest's file systems could not be thawed " @@ -2825,11 +2823,11 @@ msgstr "" "Kopyalama başarısız oldu: %(error)s. Konuğun dosya sistemleri çözülemedi " "(%(thaw)s); şununla çözün: virsh domfsthaw %(vm)s" -#: instances/jobs.py:615 instances/jobs.py:699 +#: instances/jobs.py:616 instances/jobs.py:700 msgid "The copy failed" msgstr "Kopyalama başarısız oldu" -#: instances/jobs.py:640 +#: instances/jobs.py:641 #, python-format msgid "" "The VM is no longer on the compute the job ran on; check these volumes, then " @@ -2838,7 +2836,7 @@ msgstr "" "Sanal makine artık işin çalıştığı sunucuda değil; şu birimleri kontrol edin, " "sonra bu işi çözün: %(volumes)s" -#: instances/jobs.py:675 +#: instances/jobs.py:676 #, python-format msgid "" "A volume of the clone was being created; check these volumes, then resolve " @@ -2847,15 +2845,15 @@ msgstr "" "Klonun bir birimi oluşturuluyordu; şu birimleri kontrol edin, sonra bu işi " "çözün: %(volumes)s" -#: instances/jobs.py:679 +#: instances/jobs.py:680 msgid "The job stopped before the copy started" msgstr "İş, kopyalama başlamadan durdu" -#: instances/jobs.py:686 +#: instances/jobs.py:687 msgid "libvirt is still copying the disks" msgstr "libvirt diskleri hâlâ kopyalıyor" -#: instances/jobs.py:689 +#: instances/jobs.py:690 #, python-format msgid "" "Another backup runs on the VM; check these volumes, then resolve this job: " @@ -2864,7 +2862,7 @@ msgstr "" "Sanal makinede başka bir yedekleme çalışıyor; şu birimleri kontrol edin, " "sonra bu işi çözün: %(volumes)s" -#: instances/jobs.py:694 +#: instances/jobs.py:695 #, python-format msgid "" "libvirt has no result of the copy; check these volumes, then resolve this " @@ -2873,140 +2871,140 @@ msgstr "" "libvirt'te kopyanın sonucu yok; şu birimleri kontrol edin, sonra bu işi " "çözün: %(volumes)s" -#: instances/jobs.py:722 instances/templates/create_instance_w1.html:60 +#: instances/jobs.py:723 instances/templates/create_instance_w1.html:60 #: instances/templates/create_instance_w2.html:356 msgid "Create VM" msgstr "Sanal makine oluştur" -#: instances/jobs.py:745 instances/views.py:2481 +#: instances/jobs.py:746 instances/views.py:2468 msgid "A virtual machine with this name already exists" msgstr "Bu isimde bir sanal makine mevcut" -#: instances/jobs.py:747 +#: instances/jobs.py:748 msgid "There is an instance with same name. Remove it and try again!" msgstr "Aynı isimde başka bir sanal makine var. Onu silip yeniden deneyin!" -#: instances/jobs.py:750 +#: instances/jobs.py:751 msgid "First you need to create or select an image" msgstr "Öncelikle bir imaj oluşturun ya da mevcut bir imajı seçin" -#: instances/jobs.py:752 +#: instances/jobs.py:753 msgid "Choose one disk source: a new disk, existing volumes or a template" msgstr "" "Tek bir disk kaynağı seçin: yeni bir disk, mevcut birimler ya da bir şablon" -#: instances/jobs.py:754 +#: instances/jobs.py:755 msgid "Image has already exist. Please check volumes or change instance name" msgstr "" "İmaj zaten mevcut. Lütfen ya makine adını değişin ya da disk alanlarını " "kontrol edin" -#: instances/jobs.py:756 +#: instances/jobs.py:757 msgid "Invalid cache mode" msgstr "Geçersiz önbellek modu" -#: instances/jobs.py:758 +#: instances/jobs.py:759 #, python-format msgid "This host offers no CPU mode or model %(mode)s" msgstr "Bu sunucu %(mode)s CPU modunu veya modelini sunmuyor" -#: instances/jobs.py:760 +#: instances/jobs.py:761 #, python-format msgid "A CD-ROM cannot use the %(bus)s bus" msgstr "CD-ROM %(bus)s veri yolunu kullanamaz" -#: instances/jobs.py:763 +#: instances/jobs.py:764 msgid "The cloud-init seed is read from a CD-ROM: choose its bus" msgstr "cloud-init tohumu bir CD-ROM'dan okunur: veri yolunu seçin" -#: instances/jobs.py:766 +#: instances/jobs.py:767 msgid "The cloud-init seed needs a directory storage pool for the disk" msgstr "cloud-init tohumu, disk için bir dizin depolama havuzu gerektirir" -#: instances/jobs.py:772 +#: instances/jobs.py:773 #, python-format msgid "This host offers no firmware %(firmware)s" msgstr "Bu sunucu %(firmware)s firmware'ini sunmuyor" -#: instances/jobs.py:774 vrtManager/instance.py:3023 +#: instances/jobs.py:775 vrtManager/instance.py:2999 msgid "This host offers no TPM 2.0: install swtpm on it" msgstr "Bu sunucu TPM 2.0 sunmuyor: üzerine swtpm kurun" -#: instances/jobs.py:825 +#: instances/jobs.py:826 msgid "Writing the cloud-init seed" msgstr "cloud-init tohumu yazılıyor" -#: instances/jobs.py:832 +#: instances/jobs.py:833 msgid "Defining the VM" msgstr "Sanal makine tanımlanıyor" -#: instances/jobs.py:865 +#: instances/jobs.py:866 #, python-format msgid "%(error)s. Remove these volumes by hand: %(volumes)s" msgstr "%(error)s. Şu birimleri elle silin: %(volumes)s" -#: instances/jobs.py:890 +#: instances/jobs.py:891 #, python-format msgid "The instance is already on %(compute)s" msgstr "Sanal makine zaten %(compute)s üzerinde" -#: instances/jobs.py:892 +#: instances/jobs.py:893 #, python-format msgid "%(compute)s is not reachable" msgstr "%(compute)s sunucusuna ulaşılamıyor" -#: instances/jobs.py:894 +#: instances/jobs.py:895 #, python-format msgid "%(compute)s is the VM's own host under another name" msgstr "%(compute)s, sanal makinenin kendi sunucusunun başka bir adı" -#: instances/jobs.py:912 +#: instances/jobs.py:913 msgid "Migrate VM" msgstr "Sanal makineyi taşı" -#: instances/jobs.py:956 +#: instances/jobs.py:957 msgid "Migrating the VM" msgstr "Sanal makine taşınıyor" -#: instances/jobs.py:993 +#: instances/jobs.py:994 msgid "libvirt is still migrating the VM" msgstr "libvirt sanal makineyi hâlâ taşıyor" -#: instances/jobs.py:1000 +#: instances/jobs.py:1001 msgid "The VM stayed on the source host" msgstr "Sanal makine kaynak sunucuda kaldı" -#: instances/jobs.py:1002 +#: instances/jobs.py:1003 msgid "" "The VM is on both computes or on neither; check them, then resolve this job." msgstr "" "Sanal makine ya iki sunucuda da var ya da hiçbirinde yok; kontrol edin, " "sonra bu işi çözün." -#: instances/jobs.py:1034 +#: instances/jobs.py:1035 msgid "Move disk" msgstr "Diski taşı" -#: instances/jobs.py:1041 +#: instances/jobs.py:1042 msgid "Choose a disk of the VM" msgstr "Sanal makinenin bir diskini seçin" -#: instances/jobs.py:1065 +#: instances/jobs.py:1066 msgid "Copying the disk" msgstr "Disk kopyalanıyor" -#: instances/jobs.py:1108 +#: instances/jobs.py:1109 #, python-format msgid "Another block job runs on %(dev)s; check the VM" msgstr "" "%(dev)s üzerinde başka bir blok işi çalışıyor; sanal makineyi kontrol edin" -#: instances/jobs.py:1114 +#: instances/jobs.py:1115 #, python-format msgid "The disk stayed in %(path)s; remove %(dest)s if it is there" msgstr "Disk %(path)s içinde kaldı; varsa %(dest)s dosyasını silin" -#: instances/jobs.py:1116 +#: instances/jobs.py:1117 #, python-format msgid "The definitions of %(dev)s name %(paths)s; check the VM" msgstr "%(dev)s tanımları %(paths)s gösteriyor; sanal makineyi kontrol edin" @@ -3246,7 +3244,7 @@ msgid "Disk source" msgstr "Disk kaynağı" #: instances/templates/add_instance_volume.html:21 -#: instances/templates/create_instance_w2.html:134 instances/views.py:2500 +#: instances/templates/create_instance_w2.html:134 instances/views.py:2487 msgid "New disk" msgstr "Yeni disk" @@ -3618,7 +3616,7 @@ msgstr "Özel CPU modelleri" msgid "Size (GiB)" msgstr "Boyut (GiB)" -#: instances/templates/create_instance_w2.html:161 instances/views.py:2501 +#: instances/templates/create_instance_w2.html:161 instances/views.py:2488 msgid "Existing volumes" msgstr "Mevcut birimler" @@ -3653,7 +3651,7 @@ msgstr "Aygıt" msgid "Remove" msgstr "Kaldır" -#: instances/templates/create_instance_w2.html:194 instances/views.py:2502 +#: instances/templates/create_instance_w2.html:194 instances/views.py:2489 msgid "Clone from template" msgstr "Şablondan klonla" @@ -5781,25 +5779,54 @@ msgstr "En son satırlar, en yenisi önce." msgid "All of this VM's logs" msgstr "Bu sanal makinenin tüm logları" -#: instances/utils.py:63 +#: instances/utils.py:66 #, python-format msgid "The disk files cannot be checked on %(host)s: %(err)s" msgstr "Disk dosyaları %(host)s üzerinde denetlenemiyor: %(err)s" -#: instances/utils.py:179 +#: instances/utils.py:79 +msgid "" +"The quota cannot be checked because a host of your virtual machines cannot " +"be reached. Nothing was changed." +msgstr "" +"Sanal makinelerinizin bir sunucusuna erişilemediği için kota denetlenemiyor. " +"Hiçbir şey değiştirilmedi." + +#: instances/utils.py:85 +msgid "The quota of virtual machines is reached" +msgstr "Sanal makine kotası doldu" + +#: instances/utils.py:86 +msgid "The vCPU quota is reached" +msgstr "vCPU kotası doldu" + +#: instances/utils.py:87 +msgid "The memory quota is reached" +msgstr "Bellek kotası doldu" + +#: instances/utils.py:88 +msgid "The disk quota is reached" +msgstr "Disk kotası doldu" + +#: instances/utils.py:97 +#, python-format +msgid "%(quota)s (%(total)s > %(limit)s)" +msgstr "%(quota)s (%(total)s > %(limit)s)" + +#: instances/utils.py:193 msgid "None available device name" msgstr "Hiçbiri uygun aygıt adı değil" -#: instances/utils.py:364 +#: instances/utils.py:378 #, python-format msgid "%(hostname)s via %(address)s" msgstr "%(address)s üzerinden %(hostname)s" -#: instances/utils.py:403 +#: instances/utils.py:417 msgid "Invalid MAC address" msgstr "Geçersiz MAC adresi" -#: instances/utils.py:405 +#: instances/utils.py:419 msgid "More MAC addresses than networks" msgstr "Ağlardan daha fazla MAC adresi" @@ -5854,14 +5881,6 @@ msgstr "" msgid "The VM was moved meanwhile; try again." msgstr "Sanal makine bu arada taşındı; yeniden deneyin." -#: instances/views.py:664 -msgid "" -"The quota cannot be checked because a host of your virtual machines cannot " -"be reached. Nothing was changed." -msgstr "" -"Sanal makinelerinizin bir sunucusuna erişilemediği için kota denetlenemiyor. " -"Hiçbir şey değiştirilmedi." - #: instances/views.py:745 msgid "" "The running VM has no free PCI slot for another disk on this bus: choose the " @@ -5962,117 +5981,107 @@ msgstr "vCPU'larını değiştirmek için sanal makineyi kapatın" msgid "The current vCPUs cannot be more than the maximum" msgstr "Geçerli vCPU sayısı en fazla değerden büyük olamaz" -#: instances/views.py:1178 +#: instances/views.py:1177 #, python-format -msgid "" -"User %(quota_msg)s quota reached, cannot resize CPU of '%(instance_name)s'!" -msgstr "" -"%(quota_msg)s kullanıcısı kotası doldu, '%(instance_name)s' in CPU su " -"yeniden boyutlandırılamıyor!" +msgid "%(quota)s: cannot resize the CPU of '%(instance_name)s'." +msgstr "%(quota)s: '%(instance_name)s' CPU'su yeniden boyutlandırılamıyor." -#: instances/views.py:1189 +#: instances/views.py:1185 #, python-format msgid "vCPUs set to %(cur)s (maximum %(max)s)" msgstr "vCPU sayısı %(cur)s olarak ayarlandı (en fazla %(max)s)" -#: instances/views.py:1208 +#: instances/views.py:1204 msgid "Enter a whole number for memory" msgstr "Bellek için bir tam sayı girin" -#: instances/views.py:1211 +#: instances/views.py:1207 msgid "The current memory cannot be more than the maximum" msgstr "Geçerli bellek en fazla değerden büyük olamaz" -#: instances/views.py:1216 +#: instances/views.py:1211 #, python-format -msgid "" -"User %(quota_msg)s quota reached, cannot resize memory of " -"'%(instance_name)s'!" -msgstr "" -"%(quota_msg)s kullanıcı kotası doldu, '%(instance_name)s' in belleği yeniden " -"boyutlandırılamıyor!" +msgid "%(quota)s: cannot resize the memory of '%(instance_name)s'." +msgstr "%(quota)s: '%(instance_name)s' belleği yeniden boyutlandırılamıyor." -#: instances/views.py:1225 +#: instances/views.py:1217 #, python-format msgid "Memory set to %(cur)s MiB (maximum %(max)s MiB)" msgstr "Bellek %(cur)s MiB olarak ayarlandı (en fazla %(max)s MiB)" -#: instances/views.py:1245 +#: instances/views.py:1237 msgid "Enter disk sizes as whole GiB" msgstr "Disk boyutlarını tam GiB olarak girin" -#: instances/views.py:1249 +#: instances/views.py:1241 #, python-format msgid "%(dev)s is %(size)s: a disk cannot shrink" msgstr "%(dev)s boyutu %(size)s: disk küçültülemez" -#: instances/views.py:1257 +#: instances/views.py:1249 msgid "No disks were selected or valid for resizing." msgstr "Boyutlandırma için seçilmiş ya da geçerli disk yok." -#: instances/views.py:1267 +#: instances/views.py:1258 #, python-format -msgid "" -"User %(quota_msg)s quota reached, cannot resize disks of '%(instance_name)s'!" -msgstr "" -"%(quota_msg)s kullanıcı kotası doldu, '%(instance_name)s' in diski yeniden " -"boyutlandırılamıyor!" +msgid "%(quota)s: cannot resize the disks of '%(instance_name)s'." +msgstr "%(quota)s: '%(instance_name)s' diskleri yeniden boyutlandırılamıyor." -#: instances/views.py:1282 +#: instances/views.py:1270 #, python-format msgid "The storage pool of %(dev)s cannot resize its volumes" msgstr "%(dev)s diskinin depolama havuzu birimlerini boyutlandıramaz" -#: instances/views.py:1284 +#: instances/views.py:1272 #, python-format msgid "Disk is resized: %(dev)s" msgstr "Disk boyutu değiştirildi: %(dev)s" -#: instances/views.py:1378 +#: instances/views.py:1366 msgid "The VM's machine has no PCIe slots to add" msgstr "Sanal makinenin makine tipinde eklenecek PCIe yuvası yok" -#: instances/views.py:1383 +#: instances/views.py:1371 #, python-format msgid "%(count)s PCIe slots added" msgstr "%(count)s PCIe yuvası eklendi" -#: instances/views.py:1385 +#: instances/views.py:1373 #, python-format msgid "%(count)s PCIe slots added: the VM gets them at its next start" msgstr "" "%(count)s PCIe yuvası eklendi: sanal makine bunları sonraki başlatmasında " "alır" -#: instances/views.py:1516 +#: instances/views.py:1504 msgid "Volume changes are applied. But it will be activated after shutdown" msgstr "" "Birim değişiklikleri uygulandı. Ama yeniden başlatıldıktan sonra uygulanacak" -#: instances/views.py:1521 +#: instances/views.py:1509 msgid "Volume is changed successfully." msgstr "Birim başarıyla değiştirildi." -#: instances/views.py:1539 +#: instances/views.py:1527 #, python-format msgid "Disk %(dev)s is not a storage volume of this instance" msgstr "%(dev)s diski bu sanal makinenin bir depolama birimi değil" -#: instances/views.py:1546 +#: instances/views.py:1534 #, python-format msgid "Disk %(dev)s has a pending change; delete it once the VM is shut down" msgstr "" "%(dev)s diskinin bekleyen bir değişikliği var; sanal makine kapatıldığında " "silin" -#: instances/views.py:1561 +#: instances/views.py:1549 #, python-format msgid "Volume %(vol)s is used by another VM; detach it instead" msgstr "" "%(vol)s birimi başka bir sanal makine tarafından kullanılıyor; onun yerine " "ayırın" -#: instances/views.py:1573 +#: instances/views.py:1561 #, python-format msgid "" "The guest has not released disk %(dev)s yet; volume %(vol)s was kept. Delete " @@ -6081,57 +6090,57 @@ msgstr "" "Konuk sistem %(dev)s diskini henüz bırakmadı; %(vol)s birimi korundu. Sanal " "makine kapatıldığında depolama havuzundan silin." -#: instances/views.py:1584 +#: instances/views.py:1572 #, python-format msgid "Disk %(dev)s was detached, but its volume was kept: %(err)s" msgstr "%(dev)s diski ayrıldı, ancak birimi korundu: %(err)s" -#: instances/views.py:1610 +#: instances/views.py:1598 #, python-format msgid "This VM cannot take a CD-ROM on the %(bus)s bus now" msgstr "Bu sanal makineye şu anda %(bus)s veri yolunda CD-ROM eklenemez" -#: instances/views.py:1613 +#: instances/views.py:1601 msgid "A USB CD-ROM needs an ISO image: libvirt has no empty USB drive" msgstr "USB CD-ROM bir ISO imajı ister: libvirt boş USB sürücü desteklemiyor" -#: instances/views.py:1694 +#: instances/views.py:1682 #, python-format msgid "Pool %(pool)s was not read again: %(err)s" msgstr "%(pool)s havuzu yeniden okunamadı: %(err)s" -#: instances/views.py:1715 +#: instances/views.py:1703 #, python-format msgid "Snapshot was not deleted: %(err)s" msgstr "Anlık görüntü silinmedi: %(err)s" -#: instances/views.py:1830 +#: instances/views.py:1818 msgid "Check at least one device to boot from." msgstr "Önyükleme için en az bir aygıt işaretleyin." -#: instances/views.py:1844 +#: instances/views.py:1832 msgid "Boot order changed. It applies at the next start." msgstr "Ön yükleme sırası değiştirildi. Sonraki başlatmada uygulanır." -#: instances/views.py:1846 +#: instances/views.py:1834 msgid "Boot order changed successfully." msgstr "Ön yükleme sırası başarıyla değiştirildi." -#: instances/views.py:1866 +#: instances/views.py:1854 msgid "The XML is empty" msgstr "XML boş" -#: instances/views.py:1870 instances/views.py:2491 +#: instances/views.py:1858 instances/views.py:2478 #, python-format msgid "The XML is not well-formed: %(error)s" msgstr "XML düzgün biçimlendirilmemiş: %(error)s" -#: instances/views.py:1872 +#: instances/views.py:1860 #, python-format msgid "The XML must keep the VM's UUID %(uuid)s." msgstr "XML, sanal makinenin %(uuid)s UUID'sini korumalıdır." -#: instances/views.py:1876 +#: instances/views.py:1864 msgid "" "The definition has changed since the editor was opened. Reload the page to " "edit the current one." @@ -6139,35 +6148,35 @@ msgstr "" "Düzenleyici açıldığından beri tanım değişti. Geçerli tanımı düzenlemek için " "sayfayı yeniden yükleyin." -#: instances/views.py:1888 +#: instances/views.py:1876 msgid "The XML definition was saved." msgstr "XML tanımı kaydedildi." -#: instances/views.py:1890 +#: instances/views.py:1878 msgid "The XML definition was saved; the VM uses it from its next start." msgstr "" "XML tanımı kaydedildi; sanal makine onu sonraki başlatmasından itibaren " "kullanır." -#: instances/views.py:1971 +#: instances/views.py:1959 msgid "Select one network interface to change" msgstr "Değiştirilecek bir ağ arabirimi seçin" -#: instances/views.py:2009 +#: instances/views.py:1997 msgid "Network Device Config is changed. Please shutdown instance to activate." msgstr "" "Ağ aygıtı yapılandırması değiştirildi. Aktifleştirmek için lütfen sanal " "makineyi kapatın." -#: instances/views.py:2011 +#: instances/views.py:1999 msgid "Network device changed" msgstr "Ağ aygıtı değiştirildi" -#: instances/views.py:2023 +#: instances/views.py:2011 msgid "No network selected" msgstr "Ağ seçilmedi" -#: instances/views.py:2043 +#: instances/views.py:2031 msgid "" "The running VM has no free PCI slot for another network device: shut it down " "and add the device then; Add PCIe slots on the Disks tab gives it free ones " @@ -6177,21 +6186,21 @@ msgstr "" "aygıtı sonra ekleyin; Diskler sekmesindeki PCIe yuvaları ekle, sonraki " "başlatmadan itibaren ona boş yuvalar verir." -#: instances/views.py:2084 instances/views.py:2090 +#: instances/views.py:2072 instances/views.py:2078 msgid "The VM has it" msgstr "Sanal makinede var" -#: instances/views.py:2121 +#: instances/views.py:2109 #, python-format msgid "The host has no USB device %(device)s" msgstr "Sunucuda %(device)s USB aygıtı yok" -#: instances/views.py:2142 +#: instances/views.py:2130 #, python-format msgid "The host has no PCI device %(device)s" msgstr "Sunucuda %(device)s PCI aygıtı yok" -#: instances/views.py:2160 +#: instances/views.py:2148 #, python-format msgid "" "Removal of PCI device %(address)s requested: the guest has not let it go " @@ -6201,20 +6210,20 @@ msgstr "" "bırakmadı; bırakana ya da sanal makine durana kadar çalışan sanal makinede " "kalır." -#: instances/views.py:2205 instances/views.py:2235 +#: instances/views.py:2193 instances/views.py:2223 msgid "Select a network interface and a QoS direction" msgstr "Bir ağ arabirimi ve bir QoS yönü seçin" -#: instances/views.py:2208 vrtManager/network.py:459 +#: instances/views.py:2196 vrtManager/network.py:459 msgid "QoS rates must be whole numbers" msgstr "QoS hızları tam sayı olmalıdır" -#: instances/views.py:2215 networks/views.py:229 +#: instances/views.py:2203 networks/views.py:229 #, python-format msgid "%(qos_dir)s QoS is set" msgstr "%(qos_dir)s QoS ayarlandı" -#: instances/views.py:2220 +#: instances/views.py:2208 #, python-format msgid "" "%(qos_dir)s QoS is set. A running VM gets it after it is powered off and on." @@ -6222,12 +6231,12 @@ msgstr "" "%(qos_dir)s QoS ayarlandı. Çalışan bir sanal makine, kapatılıp açıldıktan " "sonra bunu alır." -#: instances/views.py:2242 networks/views.py:255 +#: instances/views.py:2230 networks/views.py:255 #, python-format msgid "%(qos_dir)s QoS is deleted" msgstr "%(qos_dir)s QoS silindi" -#: instances/views.py:2247 +#: instances/views.py:2235 #, python-format msgid "" "%(qos_dir)s QoS is deleted. A running VM keeps the old limit until it is " @@ -6236,21 +6245,21 @@ msgstr "" "%(qos_dir)s QoS silindi. Çalışan bir sanal makine, kapatılıp açılana kadar " "eski sınırı korur." -#: instances/views.py:2275 +#: instances/views.py:2263 msgid "Only one owner is allowed and the one already added" msgstr "Sadece bir sahibe izin verilmiştir ve bir sahip zaten eklenmiş" -#: instances/views.py:2277 +#: instances/views.py:2265 #, python-format msgid "%(user)s is already an owner" msgstr "%(user)s zaten bir sahip" -#: instances/views.py:2321 +#: instances/views.py:2309 #, python-format msgid "Console settings were not saved: %(errors)s" msgstr "Konsol ayarları kaydedilmedi: %(errors)s" -#: instances/views.py:2343 +#: instances/views.py:2331 msgid "" "Error setting console password. You should check that your instance have an " "graphic device." @@ -6258,67 +6267,65 @@ msgstr "" "Konsol parolası ayarlanırken hata oluştu. Sanal makinenin bir grafik " "aygıtına sahip olduğundan emin olunuz." -#: instances/views.py:2390 +#: instances/views.py:2378 msgid "Shut the VM down to change whether it is a template." msgstr "Şablon olup olmadığını değiştirmek için sanal makineyi kapatın." -#: instances/views.py:2397 +#: instances/views.py:2384 #, python-format -msgid "User %(quota_msg)s quota reached, '%(instance_name)s' stays a template!" -msgstr "" -"Kullanıcının %(quota_msg)s kotası doldu, '%(instance_name)s' şablon olarak " -"kalıyor!" +msgid "%(quota)s: '%(instance_name)s' stays a template." +msgstr "%(quota)s: '%(instance_name)s' şablon olarak kalıyor." -#: instances/views.py:2479 +#: instances/views.py:2466 msgid "The XML has no name" msgstr "XML'de ad yok" -#: instances/views.py:2493 webvirtcloud/middleware.py:79 +#: instances/views.py:2480 webvirtcloud/middleware.py:79 #, python-format msgid "libvirt Error - %(exception)s" msgstr "libvirt Hatası - %(exception)s" -#: instances/views.py:2500 +#: instances/views.py:2487 msgid "An empty disk of the size you set" msgstr "Belirlediğiniz boyutta boş bir disk" -#: instances/views.py:2501 +#: instances/views.py:2488 msgid "Volumes already in a pool" msgstr "Bir havuzda zaten bulunan birimler" -#: instances/views.py:2502 +#: instances/views.py:2489 msgid "A copy of a template volume" msgstr "Bir şablon biriminin kopyası" -#: instances/views.py:2591 +#: instances/views.py:2578 msgid "You haven't defined any storage pools" msgstr "Hiç bir depolama havuzu tanımlamadınız" -#: instances/views.py:2593 +#: instances/views.py:2580 msgid "You haven't defined any network pools" msgstr "Hiç bir ağ havuzu tanımlamadınız" -#: instances/views.py:2656 +#: instances/views.py:2643 msgid "Flavor Created" msgstr "Flavor Oluşturuldu" -#: instances/views.py:2664 +#: instances/views.py:2651 msgid "Create Flavor" msgstr "Kullanıcı Oluştur" -#: instances/views.py:2679 +#: instances/views.py:2666 msgid "Flavor Updated" msgstr "Flavor Güncellendi" -#: instances/views.py:2685 +#: instances/views.py:2672 msgid "Update Flavor" msgstr "Flavor Güncelle" -#: instances/views.py:2697 +#: instances/views.py:2684 msgid "Flavor Deleted" msgstr "Flavor Silindi" -#: instances/views.py:2703 +#: instances/views.py:2690 msgid "Only the size template goes; VMs made from it keep their size." msgstr "" "Yalnızca boyut şablonu silinir; ondan oluşturulan sanal makineler " @@ -7834,7 +7841,7 @@ msgstr "" msgid "%(label)s is %(state)s on this resource (since %(since)s)." msgstr "%(label)s bu kaynakta %(state)s (%(since)s beri)." -#: operations/worker.py:38 +#: operations/worker.py:40 msgid "" "libvirt's merge finished copying but never completed (for example after a " "libvirtd restart); check the VM before resolving" @@ -7843,7 +7850,7 @@ msgstr "" "libvirtd yeniden başlatıldıktan sonra); çözmeden önce sanal makineyi kontrol " "edin" -#: operations/worker.py:40 +#: operations/worker.py:42 msgid "" "The worker that ran this job stopped responding; an administrator must make " "sure it is no longer running, then resolve this job" @@ -7851,11 +7858,11 @@ msgstr "" "Bu işi çalıştıran worker yanıt vermeyi bıraktı; bir yönetici artık " "çalışmadığından emin olmalı, sonra bu işi çözmeli" -#: operations/worker.py:42 +#: operations/worker.py:44 msgid "Waiting for recovery" msgstr "Kurtarma bekleniyor" -#: operations/worker.py:393 +#: operations/worker.py:455 msgid "The worker stopped before the job changed anything" msgstr "Worker, iş herhangi bir şeyi değiştirmeden önce durdu" @@ -8445,12 +8452,12 @@ msgstr "Yükleme oturumu meşgul. Lütfen yeniden deneyin." msgid "ISO image already exists" msgstr "ISO imajı zaten mevcut" -#: storages/views.py:176 +#: storages/views.py:178 #, python-format msgid "Volume: %(vol)s is deleted." msgstr "Birim: %(vol)s silindi." -#: storages/views.py:194 +#: storages/views.py:196 #, python-format msgid "Image file %(name)s is created successfully" msgstr "İmaj dosyası %(name)s başarıyla oluşturuldu" @@ -8770,10 +8777,55 @@ msgstr "" "Eski değerin yerini hemen alır; bir parolanın şifrelediği veriler yeniden " "şifrelenmez." -#: vrtManager/connection.py:200 +#: vrtManager/connection.py:50 +msgid "Connection closed (error)" +msgstr "Bağlantı kapandı (hata)" + +#: vrtManager/connection.py:51 +msgid "Connection closed (end of file)" +msgstr "Bağlantı kapandı (dosya sonu)" + +#: vrtManager/connection.py:52 +msgid "Connection closed (keepalive timeout)" +msgstr "Bağlantı kapandı (canlı tutma zaman aşımı)" + +#: vrtManager/connection.py:53 +msgid "Connection closed (client closed)" +msgstr "Bağlantı kapandı (istemci kapattı)" + +#: vrtManager/connection.py:139 +#, python-format +msgid "" +"Connection Failed: %(host)s does not answer: %(requests)s requests still " +"wait for it" +msgstr "" +"Bağlantı başarısız: %(host)s yanıt vermiyor: %(requests)s istek hâlâ onu " +"bekliyor" + +#: vrtManager/connection.py:208 +#, python-format +msgid "Connection Failed: %(host)s did not answer within %(seconds)s s" +msgstr "Bağlantı başarısız: %(host)s %(seconds)s sn içinde yanıt vermedi" + +#: vrtManager/connection.py:218 msgid "the connection closed right after opening" msgstr "bağlantı açıldıktan hemen sonra kapandı" +#: vrtManager/connection.py:231 +#, python-format +msgid "Connection Failed: %(error)s" +msgstr "Bağlantı başarısız: %(error)s" + +#: vrtManager/connection.py:291 +#, python-format +msgid "Connection closed (%(reason)s)" +msgstr "Bağlantı kapandı (%(reason)s)" + +#: vrtManager/connection.py:433 +#, python-format +msgid "Connection Failed: %(host)s is not connected" +msgstr "Bağlantı başarısız: %(host)s bağlı değil" + #: vrtManager/instance.py:134 msgid "A running or paused VM cannot be migrated offline" msgstr "Çalışan veya duraklatılmış bir sanal makine çevrimdışı taşınamaz" @@ -8943,7 +8995,7 @@ msgstr "" "Anlık görüntü adları 1-64 harf, rakam, '.', '_' veya '-' karakterinden " "oluşur ve '.' ile başlamaz" -#: vrtManager/instance.py:1100 +#: vrtManager/instance.py:1076 msgid "" "A device other than a disk or NIC is in the boot order: change it in the XML " "editor" @@ -8951,100 +9003,100 @@ msgstr "" "Önyükleme sırasında disk veya NIC dışında bir aygıt var: bunu XML " "düzenleyicide değiştirin" -#: vrtManager/instance.py:1112 +#: vrtManager/instance.py:1088 msgid "Invalid Device Type for boot order" msgstr "Önyükleme sırası için geçersiz aygıt türü" -#: vrtManager/instance.py:1115 +#: vrtManager/instance.py:1091 #, python-format msgid "Boot device %(dev)s is not in the definition" msgstr "Önyükleme aygıtı %(dev)s tanımda yok" -#: vrtManager/instance.py:1135 +#: vrtManager/instance.py:1111 #, python-format msgid "CD-ROM %(dev)s is not in the running definition" msgstr "CD-ROM %(dev)s çalışan tanımda yok" -#: vrtManager/instance.py:1136 +#: vrtManager/instance.py:1112 #, python-format msgid "CD-ROM %(dev)s is not in the persistent definition" msgstr "CD-ROM %(dev)s kalıcı tanımda yok" -#: vrtManager/instance.py:1148 +#: vrtManager/instance.py:1124 #, python-format msgid "Media of %(dev)s changed in the running VM only: %(err)s" msgstr "%(dev)s ortamı yalnızca çalışan sanal makinede değişti: %(err)s" -#: vrtManager/instance.py:1159 +#: vrtManager/instance.py:1135 #, python-format msgid "ISO image %(image)s was not found" msgstr "ISO imajı %(image)s bulunamadı" -#: vrtManager/instance.py:1161 +#: vrtManager/instance.py:1137 #, python-format msgid "ISO image %(image)s is in more than one storage pool" msgstr "ISO imajı %(image)s birden fazla depolama havuzunda var" -#: vrtManager/instance.py:1268 +#: vrtManager/instance.py:1244 #, python-format msgid "Disk %(target_dev)s is not in the VM's definition" msgstr "Disk %(target_dev)s sanal makinenin tanımında yok" -#: vrtManager/instance.py:1396 +#: vrtManager/instance.py:1372 msgid "Please shutdown the instance then try to enable vCPU hotplug" msgstr "" "vCPU hotplug özelliğini etkinleştirmek için önce sanal makineyi kapatın" -#: vrtManager/instance.py:1859 +#: vrtManager/instance.py:1835 msgid "" "The VM has external snapshots; internal snapshots cannot be mixed with them" msgstr "" "Sanal makinenin harici anlık görüntüleri var; dahili anlık görüntüler " "bunlarla karıştırılamaz" -#: vrtManager/instance.py:1891 +#: vrtManager/instance.py:1867 msgid "A snapshot with memory is not quiesced; it keeps the whole guest state" msgstr "" "Bellekli bir anlık görüntüde dosya sistemleri dondurulmaz; tüm konuk " "durumunu saklar" -#: vrtManager/instance.py:1893 +#: vrtManager/instance.py:1869 msgid "Only a running VM's file systems can be frozen" msgstr "Yalnızca çalışan bir sanal makinenin dosya sistemleri dondurulabilir" -#: vrtManager/instance.py:1895 +#: vrtManager/instance.py:1871 msgid "The QEMU guest agent is not connected; it freezes the file systems" msgstr "QEMU konuk aracısı bağlı değil; dosya sistemlerini o dondurur" -#: vrtManager/instance.py:1898 +#: vrtManager/instance.py:1874 msgid "" "The VM has internal snapshots; external snapshots cannot be mixed with them" msgstr "" "Sanal makinenin dahili anlık görüntüleri var; harici anlık görüntüler " "bunlarla karıştırılamaz" -#: vrtManager/instance.py:1903 +#: vrtManager/instance.py:1879 msgid "Newer snapshots exist after the last revert; delete them first" msgstr "" "Son geri dönüşten sonra daha yeni anlık görüntüler var; önce onları silin" -#: vrtManager/instance.py:1906 +#: vrtManager/instance.py:1882 msgid "No snapshot is current; revert to a snapshot first" msgstr "Geçerli anlık görüntü yok; önce bir anlık görüntüye geri dönün" -#: vrtManager/instance.py:1912 +#: vrtManager/instance.py:1888 #, python-format msgid "Eject the media from %(dev)s first" msgstr "Önce %(dev)s içindeki ortamı çıkarın" -#: vrtManager/instance.py:1914 +#: vrtManager/instance.py:1890 #, python-format msgid "Disk %(dev)s is not a file; external snapshots need file disks" msgstr "" "Disk %(dev)s bir dosya değil; harici anlık görüntüler dosya diskleri " "gerektirir" -#: vrtManager/instance.py:1922 +#: vrtManager/instance.py:1898 #, python-format msgid "" "The storage pools could not be refreshed, so their free space is unknown: " @@ -9052,21 +9104,21 @@ msgid "" msgstr "" "Depolama havuzları yenilenemedi, bu yüzden boş alanları bilinmiyor: %(err)s" -#: vrtManager/instance.py:1943 +#: vrtManager/instance.py:1919 msgid "Memory is saved only from a running VM" msgstr "Bellek yalnızca çalışan bir sanal makineden kaydedilir" -#: vrtManager/instance.py:1945 +#: vrtManager/instance.py:1921 msgid "The VM has no disk to keep its memory next to" msgstr "Sanal makinenin, belleğinin yanına kaydedileceği bir diski yok" -#: vrtManager/instance.py:1949 +#: vrtManager/instance.py:1925 #, python-format msgid "%(disk)s is not in a storage pool; memory is saved only into one" msgstr "" "%(disk)s bir depolama havuzunda değil; bellek yalnızca bir havuza kaydedilir" -#: vrtManager/instance.py:1980 +#: vrtManager/instance.py:1956 #, python-format msgid "" "Storage pool %(pool)s has %(free).1f GiB free; the snapshot needs %(size).1f " @@ -9077,7 +9129,7 @@ msgstr "" "%(size).1f GiB gerektiriyor (sanal makinenin oradaki disklerinin %%" "%(percent)g kadarı, en az %(minimum)g GiB, ve kaydediliyorsa bellek)" -#: vrtManager/instance.py:1998 +#: vrtManager/instance.py:1974 msgid "" "This snapshot was taken by an older version on a UEFI VM and cannot be " "reverted; delete it instead" @@ -9085,7 +9137,7 @@ msgstr "" "Bu anlık görüntü UEFI bir sanal makinede eski bir sürümle alındı ve geri " "dönülemez; bunun yerine silin" -#: vrtManager/instance.py:2028 +#: vrtManager/instance.py:2004 #, python-format msgid "" "The revert failed twice; try again in a moment (%(error)s). The VM is " @@ -9094,7 +9146,7 @@ msgstr "" "Geri dönüş iki kez başarısız oldu; biraz sonra tekrar deneyin (%(error)s). " "Sanal makine çalışıyor." -#: vrtManager/instance.py:2030 +#: vrtManager/instance.py:2006 #, python-format msgid "" "The revert failed twice; try again in a moment (%(error)s). The VM is shut " @@ -9103,13 +9155,13 @@ msgstr "" "Geri dönüş iki kez başarısız oldu; biraz sonra tekrar deneyin (%(error)s). " "Sanal makine kapalı." -#: vrtManager/instance.py:2193 +#: vrtManager/instance.py:2169 msgid "A disk moves when its VM is defined and running, paused or shut off" msgstr "" "Bir disk, sanal makinesi tanımlıyken ve çalışırken, duraklatılmışken veya " "kapalıyken taşınır" -#: vrtManager/instance.py:2195 +#: vrtManager/instance.py:2171 msgid "" "A disk of a VM with snapshots, a saved state or a running block job does not " "move" @@ -9117,7 +9169,7 @@ msgstr "" "Anlık görüntüleri, kaydedilmiş durumu veya çalışan bir blok işi olan sanal " "makinenin diski taşınmaz" -#: vrtManager/instance.py:2203 +#: vrtManager/instance.py:2179 #, python-format msgid "" "%(dev)s is not a disk file of the VM, the same in its running and next " @@ -9126,132 +9178,132 @@ msgstr "" "%(dev)s, sanal makinenin çalışan ve sonraki başlatma tanımlarında aynı olan " "bir disk dosyası değil" -#: vrtManager/instance.py:2208 +#: vrtManager/instance.py:2184 #, python-format msgid "%(dev)s does not move: only writable raw and qcow2 disks do" msgstr "%(dev)s taşınmaz: yalnızca yazılabilir raw ve qcow2 diskler taşınır" -#: vrtManager/instance.py:2215 +#: vrtManager/instance.py:2191 #, python-format msgid "%(dev)s does not move: no storage pool has %(path)s" msgstr "%(dev)s taşınmaz: hiçbir depolama havuzunda %(path)s yok" -#: vrtManager/instance.py:2217 +#: vrtManager/instance.py:2193 #, python-format msgid "%(dev)s does not move: it has a backing file" msgstr "%(dev)s taşınmaz: temel (backing) dosyası var" -#: vrtManager/instance.py:2220 +#: vrtManager/instance.py:2196 #, python-format msgid "%(pool_name)s is not an active pool of disk files of this host" msgstr "%(pool_name)s bu sunucunun etkin bir disk dosyası havuzu değil" -#: vrtManager/instance.py:2223 +#: vrtManager/instance.py:2199 #, python-format msgid "%(dev)s is in pool %(pool_name)s already" msgstr "%(dev)s zaten %(pool_name)s havuzunda" -#: vrtManager/instance.py:2227 +#: vrtManager/instance.py:2203 #, python-format msgid "Pool %(pool_name)s already has a file %(name)s" msgstr "%(pool_name)s havuzunda zaten %(name)s dosyası var" -#: vrtManager/instance.py:2251 +#: vrtManager/instance.py:2227 #, python-format msgid "The copy of %(dev)s ended before it was complete" msgstr "%(dev)s kopyası tamamlanmadan sona erdi" -#: vrtManager/instance.py:2296 +#: vrtManager/instance.py:2272 #, python-format msgid "%(error)s; remove %(dest)s if it is there: %(cleanup_error)s" msgstr "%(error)s; varsa %(dest)s dosyasını kaldırın: %(cleanup_error)s" -#: vrtManager/instance.py:2298 +#: vrtManager/instance.py:2274 #, python-format msgid "%(error)s; the VM may use %(dest)s now: check its disk %(dev)s" msgstr "" "%(error)s; sanal makine şu anda %(dest)s dosyasını kullanıyor olabilir: " "%(dev)s diskini kontrol edin" -#: vrtManager/instance.py:2305 +#: vrtManager/instance.py:2281 #, python-format msgid "The VM has no internal snapshot named %(name)s" msgstr "Sanal makinenin %(name)s adlı dahili anlık görüntüsü yok" -#: vrtManager/instance.py:2314 +#: vrtManager/instance.py:2290 msgid "The VM has a saved state; start it or remove the saved state first" msgstr "" "Sanal makinenin kaydedilmiş durumu var; önce başlatın veya kaydedilmiş " "durumu kaldırın" -#: vrtManager/instance.py:2316 +#: vrtManager/instance.py:2292 msgid "A snapshot job is still running on this VM; try again when it ends" msgstr "" "Bu sanal makinede hâlâ bir anlık görüntü işi çalışıyor; bittiğinde tekrar " "deneyin" -#: vrtManager/instance.py:2326 +#: vrtManager/instance.py:2302 msgid "Shut the VM down to revert to an internal snapshot" msgstr "Dahili bir anlık görüntüye geri dönmek için sanal makineyi kapatın" -#: vrtManager/instance.py:2415 +#: vrtManager/instance.py:2391 msgid "Cannot clone a VM whose NVRAM is not a file" msgstr "NVRAM'i dosya olmayan bir sanal makine klonlanamaz" -#: vrtManager/instance.py:2483 +#: vrtManager/instance.py:2459 #, python-format msgid "Clone failed (%(err)s); remove these copies by hand: %(path)s" msgstr "" "Klonlama başarısız oldu (%(err)s); bu kopyaları elle kaldırın: %(path)s" -#: vrtManager/instance.py:2493 +#: vrtManager/instance.py:2469 msgid "Shut the VM down before cloning it" msgstr "Klonlamadan önce sanal makineyi kapatın" -#: vrtManager/instance.py:2547 +#: vrtManager/instance.py:2523 #, python-format msgid "Clone failed (%(err)s); remove these copies by hand: %(leftovers)s" msgstr "" "Klonlama başarısız oldu (%(err)s); bu kopyaları elle kaldırın: %(leftovers)s" -#: vrtManager/instance.py:2558 +#: vrtManager/instance.py:2534 msgid "Live clone needs libvirt 11.10 or later; shut the VM down to clone it" msgstr "" "Canlı klonlama libvirt 11.10 veya sonrasını gerektirir; klonlamak için sanal " "makineyi kapatın" -#: vrtManager/instance.py:2561 +#: vrtManager/instance.py:2537 msgid "A VM with a TPM is cloned only shut down" msgstr "TPM'i olan bir sanal makine yalnızca kapalıyken klonlanır" -#: vrtManager/instance.py:2564 +#: vrtManager/instance.py:2540 #, python-format msgid "Disk %(dev)s is not a local file; shut the VM down to clone it" msgstr "" "Disk %(dev)s yerel bir dosya değil; klonlamak için sanal makineyi kapatın" -#: vrtManager/instance.py:2566 +#: vrtManager/instance.py:2542 #, python-format msgid "Disk %(dev)s is shareable; shut the VM down to clone it" msgstr "Disk %(dev)s paylaşılabilir; klonlamak için sanal makineyi kapatın" -#: vrtManager/instance.py:2571 +#: vrtManager/instance.py:2547 #, python-format msgid "Disk %(dev)s changes at the next start; shut the VM down to clone it" msgstr "" "Disk %(dev)s sonraki başlatmada değişiyor; klonlamak için sanal makineyi " "kapatın" -#: vrtManager/instance.py:2573 +#: vrtManager/instance.py:2549 msgid "Another job is running on the VM; clone it when that ends" msgstr "Sanal makinede başka bir iş çalışıyor; o bittiğinde klonlayın" -#: vrtManager/instance.py:2586 +#: vrtManager/instance.py:2562 #, python-format msgid "Volume %(name)s already exists in storage pool %(pool)s" msgstr "%(name)s birimi %(pool)s depolama havuzunda zaten var" -#: vrtManager/instance.py:2605 +#: vrtManager/instance.py:2581 #, python-format msgid "" "Storage pool %(pool)s has %(free).1f GiB free; the clone needs %(size).1f " @@ -9261,20 +9313,20 @@ msgstr "" "gerektiriyor (kopyalanan diskler, artı bunların %%%(percent)g kadarı, en az " "%(minimum)g GiB)" -#: vrtManager/instance.py:2744 +#: vrtManager/instance.py:2720 msgid "A network interface that is a host device is removed in the XML editor" msgstr "Sunucu aygıtı olan bir ağ arabirimi XML düzenleyicide kaldırılır" -#: vrtManager/instance.py:2760 +#: vrtManager/instance.py:2736 #, python-format msgid "No network interface with MAC %(old_mac)s" msgstr "MAC adresi %(old_mac)s olan ağ arabirimi yok" -#: vrtManager/instance.py:2763 +#: vrtManager/instance.py:2739 msgid "A network interface that is a host device is changed in the XML editor" msgstr "Sunucu aygıtı olan bir ağ arabirimi XML düzenleyicide değiştirilir" -#: vrtManager/instance.py:2854 +#: vrtManager/instance.py:2830 msgid "" "A VM changes its PCI devices while it runs, or is shut off without a saved " "state" @@ -9282,14 +9334,14 @@ msgstr "" "Sanal makine PCI aygıtlarını çalışırken veya kaydedilmiş durumu olmadan " "kapalıyken değiştirir" -#: vrtManager/instance.py:2866 +#: vrtManager/instance.py:2842 #, python-format msgid "%(err)s; whether the VM has PCI device %(address)s now is not known" msgstr "" "%(err)s; sanal makinede şu anda %(address)s PCI aygıtının olup olmadığı " "bilinmiyor" -#: vrtManager/instance.py:2868 +#: vrtManager/instance.py:2844 #, python-format msgid "" "%(err)s; PCI device %(address)s: the VM is not running, its next start has it" @@ -9297,7 +9349,7 @@ msgstr "" "%(err)s; PCI aygıtı %(address)s: sanal makine çalışmıyor, sonraki başlatmada " "var" -#: vrtManager/instance.py:2870 +#: vrtManager/instance.py:2846 #, python-format msgid "" "%(err)s; PCI device %(address)s: the VM is not running, its next start does " @@ -9306,7 +9358,7 @@ msgstr "" "%(err)s; PCI aygıtı %(address)s: sanal makine çalışmıyor, sonraki başlatmada " "yok" -#: vrtManager/instance.py:2871 +#: vrtManager/instance.py:2847 #, python-format msgid "" "%(err)s; PCI device %(address)s: the running VM has it, its next start has it" @@ -9314,7 +9366,7 @@ msgstr "" "%(err)s; PCI aygıtı %(address)s: çalışan sanal makinede var, sonraki " "başlatmada var" -#: vrtManager/instance.py:2873 +#: vrtManager/instance.py:2849 #, python-format msgid "" "%(err)s; PCI device %(address)s: the running VM has it, its next start does " @@ -9323,7 +9375,7 @@ msgstr "" "%(err)s; PCI aygıtı %(address)s: çalışan sanal makinede var, sonraki " "başlatmada yok" -#: vrtManager/instance.py:2875 +#: vrtManager/instance.py:2851 #, python-format msgid "" "%(err)s; PCI device %(address)s: the running VM does not have it, its next " @@ -9332,7 +9384,7 @@ msgstr "" "%(err)s; PCI aygıtı %(address)s: çalışan sanal makinede yok, sonraki " "başlatmada var" -#: vrtManager/instance.py:2877 +#: vrtManager/instance.py:2853 #, python-format msgid "" "%(err)s; PCI device %(address)s: the running VM does not have it, its next " @@ -9341,29 +9393,29 @@ msgstr "" "%(err)s; PCI aygıtı %(address)s: çalışan sanal makinede yok, sonraki " "başlatmada yok" -#: vrtManager/instance.py:2911 +#: vrtManager/instance.py:2887 #, python-format msgid "The VM has no PCI device %(address)s" msgstr "Sanal makinede %(address)s PCI aygıtı yok" -#: vrtManager/instance.py:2929 +#: vrtManager/instance.py:2905 msgid "The VM has no USB controller" msgstr "Sanal makinede USB denetleyicisi yok" -#: vrtManager/instance.py:2948 +#: vrtManager/instance.py:2924 msgid "The VM has no such USB device" msgstr "Sanal makinede böyle bir USB aygıtı yok" -#: vrtManager/instance.py:2989 +#: vrtManager/instance.py:2965 msgid "The VM has its own RNG device: change it in the XML editor" msgstr "" "Sanal makinenin kendi RNG aygıtı var: bunu XML düzenleyicide değiştirin" -#: vrtManager/instance.py:3016 +#: vrtManager/instance.py:2992 msgid "The VM has its own TPM: change it in the XML editor" msgstr "Sanal makinenin kendi TPM'i var: bunu XML düzenleyicide değiştirin" -#: vrtManager/instance.py:3035 +#: vrtManager/instance.py:3011 #, python-format msgid "Unknown crash action %(action)s" msgstr "Bilinmeyen çökme eylemi %(action)s" diff --git a/locale/zh/LC_MESSAGES/django.mo b/locale/zh/LC_MESSAGES/django.mo index 4367d5e7..70a1bded 100644 Binary files a/locale/zh/LC_MESSAGES/django.mo and b/locale/zh/LC_MESSAGES/django.mo differ diff --git a/locale/zh/LC_MESSAGES/django.po b/locale/zh/LC_MESSAGES/django.po index c09c7aef..f617c85b 100644 --- a/locale/zh/LC_MESSAGES/django.po +++ b/locale/zh/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-11-02 21:03+0000\n" +"POT-Creation-Date: 2026-11-03 15:16+0000\n" "PO-Revision-Date: \n" "Last-Translator: \n" "Language-Team: \n" @@ -2588,69 +2588,69 @@ msgstr "请为克隆输入整数的内存(MiB)" msgid "Choose the clone's name from the list of free names" msgstr "请从可用名称列表中选择克隆的名称" -#: instances/jobs.py:192 +#: instances/jobs.py:193 #, python-format -msgid "User '%(quota_msg)s' quota reached, cannot create '%(clone_name)s'!" -msgstr "用户 '%(quota_msg)s' 配额已满,无法创建 '%(clone_name)s'!" +msgid "%(quota)s: cannot create '%(clone_name)s'." +msgstr "%(quota)s:无法创建“%(clone_name)s”。" -#: instances/jobs.py:195 instances/jobs.py:532 +#: instances/jobs.py:196 instances/jobs.py:533 #, python-format msgid "Instance '%(clone_name)s' already exists!" msgstr "虚拟机 '%(clone_name)s' 已存在!" -#: instances/jobs.py:197 +#: instances/jobs.py:198 #, python-format msgid "Instance name '%(clone_name)s' contains invalid characters!" msgstr "虚拟机名称 '%(clone_name)s' 包含无效字符!" -#: instances/jobs.py:200 +#: instances/jobs.py:201 #, python-format msgid "Instance MAC '%(clone_mac)s' invalid format!" msgstr "虚拟机 MAC '%(clone_mac)s' 格式无效!" -#: instances/jobs.py:202 +#: instances/jobs.py:203 #, python-format msgid "Disk name '%(disk_name)s' contains invalid characters!" msgstr "磁盘名称 '%(disk_name)s' 包含无效字符!" -#: instances/jobs.py:222 +#: instances/jobs.py:223 #, python-format msgid "The clone is made, but not as asked: %(error)s" msgstr "克隆已创建,但与要求不符:%(error)s" -#: instances/jobs.py:270 +#: instances/jobs.py:271 msgid "The VM was not defined and no volume of it was left." msgstr "虚拟机未定义,也没有留下它的卷。" -#: instances/jobs.py:272 +#: instances/jobs.py:273 #, python-format msgid "" "The VM was not defined; check these volumes, then resolve this job: " "%(volumes)s" msgstr "虚拟机未定义;请检查这些卷,然后处理此任务:%(volumes)s" -#: instances/jobs.py:293 +#: instances/jobs.py:294 msgid "Delete snapshot" msgstr "删除快照" -#: instances/jobs.py:303 vrtManager/instance.py:2304 +#: instances/jobs.py:304 vrtManager/instance.py:2280 #, python-format msgid "The VM has no external snapshot named %(name)s" msgstr "虚拟机没有名为 %(name)s 的外部快照" -#: instances/jobs.py:316 +#: instances/jobs.py:317 msgid "Merging the snapshot" msgstr "正在合并快照" -#: instances/jobs.py:335 +#: instances/jobs.py:336 msgid "The VM is no longer on its compute" msgstr "虚拟机已不在其计算节点上" -#: instances/jobs.py:338 +#: instances/jobs.py:339 msgid "libvirt is still merging the snapshot" msgstr "libvirt 仍在合并快照" -#: instances/jobs.py:346 +#: instances/jobs.py:347 msgid "" "The snapshot is still listed and no merge runs. It cannot be told whether " "the disks changed; check the VM before deleting the snapshot again or " @@ -2659,54 +2659,54 @@ msgstr "" "快照仍在列表中,且没有正在运行的合并。无法判断磁盘是否已更改;再次删除该快照" "或恢复到它之前,请检查虚拟机。" -#: instances/jobs.py:353 +#: instances/jobs.py:354 msgid "The VM is no longer on the compute the job ran on" msgstr "虚拟机已不在运行该任务的计算节点上" -#: instances/jobs.py:359 +#: instances/jobs.py:360 msgid "Take snapshot" msgstr "创建快照" -#: instances/jobs.py:371 vrtManager/instance.py:1900 +#: instances/jobs.py:372 vrtManager/instance.py:1876 #, python-format msgid "A snapshot named %(name)s already exists" msgstr "名为 %(name)s 的快照已存在" -#: instances/jobs.py:383 +#: instances/jobs.py:384 msgid "Taking the snapshot" msgstr "正在创建快照" -#: instances/jobs.py:396 +#: instances/jobs.py:397 msgid "libvirt is still taking the snapshot" msgstr "libvirt 仍在创建快照" -#: instances/jobs.py:399 +#: instances/jobs.py:400 msgid "The snapshot was not taken" msgstr "未创建快照" -#: instances/jobs.py:422 +#: instances/jobs.py:423 msgid "Revert snapshot" msgstr "恢复快照" -#: instances/jobs.py:451 +#: instances/jobs.py:452 msgid "Reverting the VM" msgstr "正在恢复虚拟机" -#: instances/jobs.py:462 +#: instances/jobs.py:463 msgid "libvirt is still reverting the VM" msgstr "libvirt 仍在恢复虚拟机" -#: instances/jobs.py:466 +#: instances/jobs.py:467 msgid "" "It cannot be told whether the VM was reverted; check it, then revert again " "or resolve this job." msgstr "无法判断虚拟机是否已恢复;请检查后再次恢复,或处理此任务。" -#: instances/jobs.py:483 +#: instances/jobs.py:484 msgid "The VM must be running, paused or shut off to be cloned" msgstr "虚拟机必须处于运行、暂停或关机状态才能克隆" -#: instances/jobs.py:484 +#: instances/jobs.py:485 #, python-format msgid "" "The guest's file systems could not be thawed (%(error)s); thaw them with: " @@ -2715,19 +2715,19 @@ msgstr "" "无法解冻客户机的文件系统(%(error)s);请用以下命令解冻:virsh domfsthaw " "%(vm)s" -#: instances/jobs.py:503 +#: instances/jobs.py:504 msgid "Clone VM" msgstr "克隆虚拟机" -#: instances/jobs.py:542 instances/jobs.py:549 instances/jobs.py:806 +#: instances/jobs.py:543 instances/jobs.py:550 instances/jobs.py:807 msgid "Copying disks" msgstr "正在复制磁盘" -#: instances/jobs.py:601 +#: instances/jobs.py:602 msgid "libvirt has no result of the copy" msgstr "libvirt 没有复制的结果" -#: instances/jobs.py:612 +#: instances/jobs.py:613 #, python-format msgid "" "The copy failed: %(error)s. The guest's file systems could not be thawed " @@ -2736,11 +2736,11 @@ msgstr "" "复制失败:%(error)s。无法解冻客户机的文件系统(%(thaw)s);请用以下命令解冻:" "virsh domfsthaw %(vm)s" -#: instances/jobs.py:615 instances/jobs.py:699 +#: instances/jobs.py:616 instances/jobs.py:700 msgid "The copy failed" msgstr "复制失败" -#: instances/jobs.py:640 +#: instances/jobs.py:641 #, python-format msgid "" "The VM is no longer on the compute the job ran on; check these volumes, then " @@ -2748,163 +2748,163 @@ msgid "" msgstr "" "虚拟机已不在运行该任务的计算节点上;请检查这些卷,然后处理此任务:%(volumes)s" -#: instances/jobs.py:675 +#: instances/jobs.py:676 #, python-format msgid "" "A volume of the clone was being created; check these volumes, then resolve " "this job: %(volumes)s" msgstr "克隆的一个卷正在创建中;请检查这些卷,然后处理此任务:%(volumes)s" -#: instances/jobs.py:679 +#: instances/jobs.py:680 msgid "The job stopped before the copy started" msgstr "任务在复制开始前停止" -#: instances/jobs.py:686 +#: instances/jobs.py:687 msgid "libvirt is still copying the disks" msgstr "libvirt 仍在复制磁盘" -#: instances/jobs.py:689 +#: instances/jobs.py:690 #, python-format msgid "" "Another backup runs on the VM; check these volumes, then resolve this job: " "%(volumes)s" msgstr "虚拟机上正在运行另一个备份;请检查这些卷,然后处理此任务:%(volumes)s" -#: instances/jobs.py:694 +#: instances/jobs.py:695 #, python-format msgid "" "libvirt has no result of the copy; check these volumes, then resolve this " "job: %(volumes)s" msgstr "libvirt 没有复制的结果;请检查这些卷,然后处理此任务:%(volumes)s" -#: instances/jobs.py:722 instances/templates/create_instance_w1.html:60 +#: instances/jobs.py:723 instances/templates/create_instance_w1.html:60 #: instances/templates/create_instance_w2.html:356 msgid "Create VM" msgstr "创建虚拟机" -#: instances/jobs.py:745 instances/views.py:2481 +#: instances/jobs.py:746 instances/views.py:2468 msgid "A virtual machine with this name already exists" msgstr "同名虚拟机已存在" -#: instances/jobs.py:747 +#: instances/jobs.py:748 msgid "There is an instance with same name. Remove it and try again!" msgstr "已存在同名虚拟机。请删除后重试!" -#: instances/jobs.py:750 +#: instances/jobs.py:751 msgid "First you need to create or select an image" msgstr "请先创建或选择一个镜像" -#: instances/jobs.py:752 +#: instances/jobs.py:753 msgid "Choose one disk source: a new disk, existing volumes or a template" msgstr "请选择一种磁盘来源:新磁盘、现有卷或模板" -#: instances/jobs.py:754 +#: instances/jobs.py:755 msgid "Image has already exist. Please check volumes or change instance name" msgstr "镜像已存在。请检查卷或更改虚拟机名称" -#: instances/jobs.py:756 +#: instances/jobs.py:757 msgid "Invalid cache mode" msgstr "无效的缓存模式" -#: instances/jobs.py:758 +#: instances/jobs.py:759 #, python-format msgid "This host offers no CPU mode or model %(mode)s" msgstr "此主机不提供 CPU 模式或型号 %(mode)s" -#: instances/jobs.py:760 +#: instances/jobs.py:761 #, python-format msgid "A CD-ROM cannot use the %(bus)s bus" msgstr "CD-ROM 不能使用 %(bus)s 总线" -#: instances/jobs.py:763 +#: instances/jobs.py:764 msgid "The cloud-init seed is read from a CD-ROM: choose its bus" msgstr "cloud-init 种子从 CD-ROM 读取:请选择其总线" -#: instances/jobs.py:766 +#: instances/jobs.py:767 msgid "The cloud-init seed needs a directory storage pool for the disk" msgstr "cloud-init 种子需要为磁盘使用目录类型的存储池" -#: instances/jobs.py:772 +#: instances/jobs.py:773 #, python-format msgid "This host offers no firmware %(firmware)s" msgstr "此主机不提供固件 %(firmware)s" -#: instances/jobs.py:774 vrtManager/instance.py:3023 +#: instances/jobs.py:775 vrtManager/instance.py:2999 msgid "This host offers no TPM 2.0: install swtpm on it" msgstr "此主机不提供 TPM 2.0:请在主机上安装 swtpm" -#: instances/jobs.py:825 +#: instances/jobs.py:826 msgid "Writing the cloud-init seed" msgstr "正在写入 cloud-init 种子" -#: instances/jobs.py:832 +#: instances/jobs.py:833 msgid "Defining the VM" msgstr "正在定义虚拟机" -#: instances/jobs.py:865 +#: instances/jobs.py:866 #, python-format msgid "%(error)s. Remove these volumes by hand: %(volumes)s" msgstr "%(error)s。请手动删除这些卷:%(volumes)s" -#: instances/jobs.py:890 +#: instances/jobs.py:891 #, python-format msgid "The instance is already on %(compute)s" msgstr "虚拟机已在 %(compute)s 上" -#: instances/jobs.py:892 +#: instances/jobs.py:893 #, python-format msgid "%(compute)s is not reachable" msgstr "无法连接 %(compute)s" -#: instances/jobs.py:894 +#: instances/jobs.py:895 #, python-format msgid "%(compute)s is the VM's own host under another name" msgstr "%(compute)s 是该虚拟机所在主机的另一个名称" -#: instances/jobs.py:912 +#: instances/jobs.py:913 msgid "Migrate VM" msgstr "迁移虚拟机" -#: instances/jobs.py:956 +#: instances/jobs.py:957 msgid "Migrating the VM" msgstr "正在迁移虚拟机" -#: instances/jobs.py:993 +#: instances/jobs.py:994 msgid "libvirt is still migrating the VM" msgstr "libvirt 仍在迁移虚拟机" -#: instances/jobs.py:1000 +#: instances/jobs.py:1001 msgid "The VM stayed on the source host" msgstr "虚拟机留在了源主机上" -#: instances/jobs.py:1002 +#: instances/jobs.py:1003 msgid "" "The VM is on both computes or on neither; check them, then resolve this job." msgstr "虚拟机同时位于两个计算节点上,或都不在;请检查后处理此任务。" -#: instances/jobs.py:1034 +#: instances/jobs.py:1035 msgid "Move disk" msgstr "移动磁盘" -#: instances/jobs.py:1041 +#: instances/jobs.py:1042 msgid "Choose a disk of the VM" msgstr "请选择虚拟机的一个磁盘" -#: instances/jobs.py:1065 +#: instances/jobs.py:1066 msgid "Copying the disk" msgstr "正在复制磁盘" -#: instances/jobs.py:1108 +#: instances/jobs.py:1109 #, python-format msgid "Another block job runs on %(dev)s; check the VM" msgstr "%(dev)s 上正在运行另一个块任务;请检查虚拟机" -#: instances/jobs.py:1114 +#: instances/jobs.py:1115 #, python-format msgid "The disk stayed in %(path)s; remove %(dest)s if it is there" msgstr "磁盘仍在 %(path)s;如果 %(dest)s 存在,请将其删除" -#: instances/jobs.py:1116 +#: instances/jobs.py:1117 #, python-format msgid "The definitions of %(dev)s name %(paths)s; check the VM" msgstr "%(dev)s 的定义指向 %(paths)s;请检查虚拟机" @@ -3142,7 +3142,7 @@ msgid "Disk source" msgstr "磁盘来源" #: instances/templates/add_instance_volume.html:21 -#: instances/templates/create_instance_w2.html:134 instances/views.py:2500 +#: instances/templates/create_instance_w2.html:134 instances/views.py:2487 msgid "New disk" msgstr "新磁盘" @@ -3506,7 +3506,7 @@ msgstr "自定义 CPU 型号" msgid "Size (GiB)" msgstr "大小(GiB)" -#: instances/templates/create_instance_w2.html:161 instances/views.py:2501 +#: instances/templates/create_instance_w2.html:161 instances/views.py:2488 msgid "Existing volumes" msgstr "已有卷" @@ -3541,7 +3541,7 @@ msgstr "设备" msgid "Remove" msgstr "移除" -#: instances/templates/create_instance_w2.html:194 instances/views.py:2502 +#: instances/templates/create_instance_w2.html:194 instances/views.py:2489 msgid "Clone from template" msgstr "从模板克隆" @@ -5546,25 +5546,52 @@ msgstr "最近的记录,最新的在前。" msgid "All of this VM's logs" msgstr "该虚拟机的全部日志" -#: instances/utils.py:63 +#: instances/utils.py:66 #, python-format msgid "The disk files cannot be checked on %(host)s: %(err)s" msgstr "无法在 %(host)s 上检查磁盘文件:%(err)s" -#: instances/utils.py:179 +#: instances/utils.py:79 +msgid "" +"The quota cannot be checked because a host of your virtual machines cannot " +"be reached. Nothing was changed." +msgstr "无法检查配额,因为您的某台虚拟机所在主机无法连接。未做任何更改。" + +#: instances/utils.py:85 +msgid "The quota of virtual machines is reached" +msgstr "虚拟机配额已用尽" + +#: instances/utils.py:86 +msgid "The vCPU quota is reached" +msgstr "vCPU 配额已用尽" + +#: instances/utils.py:87 +msgid "The memory quota is reached" +msgstr "内存配额已用尽" + +#: instances/utils.py:88 +msgid "The disk quota is reached" +msgstr "磁盘配额已用尽" + +#: instances/utils.py:97 +#, python-format +msgid "%(quota)s (%(total)s > %(limit)s)" +msgstr "%(quota)s(%(total)s > %(limit)s)" + +#: instances/utils.py:193 msgid "None available device name" msgstr "没有可用的设备名称" -#: instances/utils.py:364 +#: instances/utils.py:378 #, python-format msgid "%(hostname)s via %(address)s" msgstr "%(hostname)s,经由 %(address)s" -#: instances/utils.py:403 +#: instances/utils.py:417 msgid "Invalid MAC address" msgstr "无效的 MAC 地址" -#: instances/utils.py:405 +#: instances/utils.py:419 msgid "More MAC addresses than networks" msgstr "MAC 地址数量多于网络数量" @@ -5614,12 +5641,6 @@ msgstr "有主机设备的虚拟机无法迁移:目标主机可能没有这些 msgid "The VM was moved meanwhile; try again." msgstr "该虚拟机在此期间已被移动;请重试。" -#: instances/views.py:664 -msgid "" -"The quota cannot be checked because a host of your virtual machines cannot " -"be reached. Nothing was changed." -msgstr "无法检查配额,因为您的某台虚拟机所在主机无法连接。未做任何更改。" - #: instances/views.py:745 msgid "" "The running VM has no free PCI slot for another disk on this bus: choose the " @@ -5713,104 +5734,100 @@ msgstr "请关闭虚拟机以更改其 vCPU" msgid "The current vCPUs cannot be more than the maximum" msgstr "当前 vCPU 数不能超过最大值" -#: instances/views.py:1178 +#: instances/views.py:1177 #, python-format -msgid "" -"User %(quota_msg)s quota reached, cannot resize CPU of '%(instance_name)s'!" -msgstr "已达到用户 %(quota_msg)s 配额,无法调整“%(instance_name)s”的 CPU!" +msgid "%(quota)s: cannot resize the CPU of '%(instance_name)s'." +msgstr "%(quota)s:无法调整“%(instance_name)s”的 CPU。" -#: instances/views.py:1189 +#: instances/views.py:1185 #, python-format msgid "vCPUs set to %(cur)s (maximum %(max)s)" msgstr "vCPU 已设为 %(cur)s(最大 %(max)s)" -#: instances/views.py:1208 +#: instances/views.py:1204 msgid "Enter a whole number for memory" msgstr "请输入整数内存值" -#: instances/views.py:1211 +#: instances/views.py:1207 msgid "The current memory cannot be more than the maximum" msgstr "当前内存不能超过最大值" -#: instances/views.py:1216 +#: instances/views.py:1211 #, python-format -msgid "" -"User %(quota_msg)s quota reached, cannot resize memory of " -"'%(instance_name)s'!" -msgstr "已达到用户 %(quota_msg)s 配额,无法调整“%(instance_name)s”的内存!" +msgid "%(quota)s: cannot resize the memory of '%(instance_name)s'." +msgstr "%(quota)s:无法调整“%(instance_name)s”的内存。" -#: instances/views.py:1225 +#: instances/views.py:1217 #, python-format msgid "Memory set to %(cur)s MiB (maximum %(max)s MiB)" msgstr "内存已设为 %(cur)s MiB(最大 %(max)s MiB)" -#: instances/views.py:1245 +#: instances/views.py:1237 msgid "Enter disk sizes as whole GiB" msgstr "请以整数 GiB 输入磁盘大小" -#: instances/views.py:1249 +#: instances/views.py:1241 #, python-format msgid "%(dev)s is %(size)s: a disk cannot shrink" msgstr "%(dev)s 为 %(size)s:磁盘不能缩小" -#: instances/views.py:1257 +#: instances/views.py:1249 msgid "No disks were selected or valid for resizing." msgstr "未选择磁盘或没有可调整大小的有效磁盘。" -#: instances/views.py:1267 +#: instances/views.py:1258 #, python-format -msgid "" -"User %(quota_msg)s quota reached, cannot resize disks of '%(instance_name)s'!" -msgstr "已达到用户 %(quota_msg)s 配额,无法调整“%(instance_name)s”的磁盘!" +msgid "%(quota)s: cannot resize the disks of '%(instance_name)s'." +msgstr "%(quota)s:无法调整“%(instance_name)s”的磁盘。" -#: instances/views.py:1282 +#: instances/views.py:1270 #, python-format msgid "The storage pool of %(dev)s cannot resize its volumes" msgstr "%(dev)s 所在的存储池无法调整其卷的大小" -#: instances/views.py:1284 +#: instances/views.py:1272 #, python-format msgid "Disk is resized: %(dev)s" msgstr "磁盘已调整大小:%(dev)s" -#: instances/views.py:1378 +#: instances/views.py:1366 msgid "The VM's machine has no PCIe slots to add" msgstr "该虚拟机的机器类型没有可添加的 PCIe 插槽" -#: instances/views.py:1383 +#: instances/views.py:1371 #, python-format msgid "%(count)s PCIe slots added" msgstr "已添加 %(count)s 个 PCIe 插槽" -#: instances/views.py:1385 +#: instances/views.py:1373 #, python-format msgid "%(count)s PCIe slots added: the VM gets them at its next start" msgstr "已添加 %(count)s 个 PCIe 插槽:虚拟机在下次启动时获得它们" -#: instances/views.py:1516 +#: instances/views.py:1504 msgid "Volume changes are applied. But it will be activated after shutdown" msgstr "卷更改已应用,但将在关机后生效" -#: instances/views.py:1521 +#: instances/views.py:1509 msgid "Volume is changed successfully." msgstr "卷已成功更改。" -#: instances/views.py:1539 +#: instances/views.py:1527 #, python-format msgid "Disk %(dev)s is not a storage volume of this instance" msgstr "磁盘 %(dev)s 不是此虚拟机的存储卷" -#: instances/views.py:1546 +#: instances/views.py:1534 #, python-format msgid "Disk %(dev)s has a pending change; delete it once the VM is shut down" msgstr "磁盘 %(dev)s 有待生效的更改;请在虚拟机关机后删除它" -#: instances/views.py:1561 +#: instances/views.py:1549 #, python-format msgid "Volume %(vol)s is used by another VM; detach it instead" msgstr "卷 %(vol)s 正被另一台虚拟机使用;请改为分离它" -#: instances/views.py:1573 +#: instances/views.py:1561 #, python-format msgid "" "The guest has not released disk %(dev)s yet; volume %(vol)s was kept. Delete " @@ -5819,87 +5836,87 @@ msgstr "" "客户机尚未释放磁盘 %(dev)s;卷 %(vol)s 已保留。请在虚拟机关机后从存储池中删除" "它。" -#: instances/views.py:1584 +#: instances/views.py:1572 #, python-format msgid "Disk %(dev)s was detached, but its volume was kept: %(err)s" msgstr "磁盘 %(dev)s 已分离,但其卷已保留:%(err)s" -#: instances/views.py:1610 +#: instances/views.py:1598 #, python-format msgid "This VM cannot take a CD-ROM on the %(bus)s bus now" msgstr "该虚拟机现在无法在 %(bus)s 总线上添加 CD-ROM" -#: instances/views.py:1613 +#: instances/views.py:1601 msgid "A USB CD-ROM needs an ISO image: libvirt has no empty USB drive" msgstr "USB CD-ROM 需要 ISO 镜像:libvirt 不支持空的 USB 驱动器" -#: instances/views.py:1694 +#: instances/views.py:1682 #, python-format msgid "Pool %(pool)s was not read again: %(err)s" msgstr "未重新读取存储池 %(pool)s:%(err)s" -#: instances/views.py:1715 +#: instances/views.py:1703 #, python-format msgid "Snapshot was not deleted: %(err)s" msgstr "快照未删除:%(err)s" -#: instances/views.py:1830 +#: instances/views.py:1818 msgid "Check at least one device to boot from." msgstr "请至少勾选一个启动设备。" -#: instances/views.py:1844 +#: instances/views.py:1832 msgid "Boot order changed. It applies at the next start." msgstr "启动顺序已更改,将在下次启动时生效。" -#: instances/views.py:1846 +#: instances/views.py:1834 msgid "Boot order changed successfully." msgstr "启动顺序已成功更改。" -#: instances/views.py:1866 +#: instances/views.py:1854 msgid "The XML is empty" msgstr "XML 为空" -#: instances/views.py:1870 instances/views.py:2491 +#: instances/views.py:1858 instances/views.py:2478 #, python-format msgid "The XML is not well-formed: %(error)s" msgstr "XML 格式不正确:%(error)s" -#: instances/views.py:1872 +#: instances/views.py:1860 #, python-format msgid "The XML must keep the VM's UUID %(uuid)s." msgstr "XML 必须保留虚拟机的 UUID %(uuid)s。" -#: instances/views.py:1876 +#: instances/views.py:1864 msgid "" "The definition has changed since the editor was opened. Reload the page to " "edit the current one." msgstr "自打开编辑器以来定义已被更改。请重新加载页面以编辑当前定义。" -#: instances/views.py:1888 +#: instances/views.py:1876 msgid "The XML definition was saved." msgstr "XML 定义已保存。" -#: instances/views.py:1890 +#: instances/views.py:1878 msgid "The XML definition was saved; the VM uses it from its next start." msgstr "XML 定义已保存;虚拟机从下次启动起使用它。" -#: instances/views.py:1971 +#: instances/views.py:1959 msgid "Select one network interface to change" msgstr "请选择一个要更改的网络接口" -#: instances/views.py:2009 +#: instances/views.py:1997 msgid "Network Device Config is changed. Please shutdown instance to activate." msgstr "网络设备配置已更改。请关闭虚拟机以使其生效。" -#: instances/views.py:2011 +#: instances/views.py:1999 msgid "Network device changed" msgstr "网络设备已更改" -#: instances/views.py:2023 +#: instances/views.py:2011 msgid "No network selected" msgstr "未选择网络" -#: instances/views.py:2043 +#: instances/views.py:2031 msgid "" "The running VM has no free PCI slot for another network device: shut it down " "and add the device then; Add PCIe slots on the Disks tab gives it free ones " @@ -5908,21 +5925,21 @@ msgstr "" "运行中的虚拟机没有可用 PCI 插槽来添加网络设备:请关机后再添加设备。“磁盘”选项" "卡上的“添加 PCIe 插槽”可使其从下次启动起获得可用插槽。" -#: instances/views.py:2084 instances/views.py:2090 +#: instances/views.py:2072 instances/views.py:2078 msgid "The VM has it" msgstr "虚拟机已有此设备" -#: instances/views.py:2121 +#: instances/views.py:2109 #, python-format msgid "The host has no USB device %(device)s" msgstr "主机上没有 USB 设备 %(device)s" -#: instances/views.py:2142 +#: instances/views.py:2130 #, python-format msgid "The host has no PCI device %(device)s" msgstr "主机上没有 PCI 设备 %(device)s" -#: instances/views.py:2160 +#: instances/views.py:2148 #, python-format msgid "" "Removal of PCI device %(address)s requested: the guest has not let it go " @@ -5931,116 +5948,116 @@ msgstr "" "已请求移除 PCI 设备 %(address)s:客户机尚未释放它;在客户机释放或虚拟机停止之" "前,它仍保留在运行中的虚拟机中。" -#: instances/views.py:2205 instances/views.py:2235 +#: instances/views.py:2193 instances/views.py:2223 msgid "Select a network interface and a QoS direction" msgstr "请选择网络接口和 QoS 方向" -#: instances/views.py:2208 vrtManager/network.py:459 +#: instances/views.py:2196 vrtManager/network.py:459 msgid "QoS rates must be whole numbers" msgstr "QoS 速率必须为整数" -#: instances/views.py:2215 networks/views.py:229 +#: instances/views.py:2203 networks/views.py:229 #, python-format msgid "%(qos_dir)s QoS is set" msgstr "%(qos_dir)s QoS 已设置" -#: instances/views.py:2220 +#: instances/views.py:2208 #, python-format msgid "" "%(qos_dir)s QoS is set. A running VM gets it after it is powered off and on." msgstr "%(qos_dir)s QoS 已设置。运行中的虚拟机需关机再开机后才能生效。" -#: instances/views.py:2242 networks/views.py:255 +#: instances/views.py:2230 networks/views.py:255 #, python-format msgid "%(qos_dir)s QoS is deleted" msgstr "%(qos_dir)s QoS 已删除" -#: instances/views.py:2247 +#: instances/views.py:2235 #, python-format msgid "" "%(qos_dir)s QoS is deleted. A running VM keeps the old limit until it is " "powered off and on." msgstr "%(qos_dir)s QoS 已删除。运行中的虚拟机在关机再开机之前保留旧的限制。" -#: instances/views.py:2275 +#: instances/views.py:2263 msgid "Only one owner is allowed and the one already added" msgstr "只允许一个所有者,且已添加" -#: instances/views.py:2277 +#: instances/views.py:2265 #, python-format msgid "%(user)s is already an owner" msgstr "%(user)s 已是所有者" -#: instances/views.py:2321 +#: instances/views.py:2309 #, python-format msgid "Console settings were not saved: %(errors)s" msgstr "控制台设置未保存:%(errors)s" -#: instances/views.py:2343 +#: instances/views.py:2331 msgid "" "Error setting console password. You should check that your instance have an " "graphic device." msgstr "设置控制台密码出错。请检查虚拟机是否有图形设备。" -#: instances/views.py:2390 +#: instances/views.py:2378 msgid "Shut the VM down to change whether it is a template." msgstr "请关闭虚拟机以更改其是否为模板。" -#: instances/views.py:2397 +#: instances/views.py:2384 #, python-format -msgid "User %(quota_msg)s quota reached, '%(instance_name)s' stays a template!" -msgstr "已达到用户 %(quota_msg)s 配额,“%(instance_name)s”仍为模板!" +msgid "%(quota)s: '%(instance_name)s' stays a template." +msgstr "%(quota)s:“%(instance_name)s”仍为模板。" -#: instances/views.py:2479 +#: instances/views.py:2466 msgid "The XML has no name" msgstr "XML 中没有名称" -#: instances/views.py:2493 webvirtcloud/middleware.py:79 +#: instances/views.py:2480 webvirtcloud/middleware.py:79 #, python-format msgid "libvirt Error - %(exception)s" msgstr "libvirt 错误 - %(exception)s" -#: instances/views.py:2500 +#: instances/views.py:2487 msgid "An empty disk of the size you set" msgstr "按设定大小创建的空磁盘" -#: instances/views.py:2501 +#: instances/views.py:2488 msgid "Volumes already in a pool" msgstr "存储池中已有的卷" -#: instances/views.py:2502 +#: instances/views.py:2489 msgid "A copy of a template volume" msgstr "模板卷的副本" -#: instances/views.py:2591 +#: instances/views.py:2578 msgid "You haven't defined any storage pools" msgstr "您尚未定义任何存储池" -#: instances/views.py:2593 +#: instances/views.py:2580 msgid "You haven't defined any network pools" msgstr "您尚未定义任何网络池" -#: instances/views.py:2656 +#: instances/views.py:2643 msgid "Flavor Created" msgstr "规格已创建" -#: instances/views.py:2664 +#: instances/views.py:2651 msgid "Create Flavor" msgstr "创建规格" -#: instances/views.py:2679 +#: instances/views.py:2666 msgid "Flavor Updated" msgstr "规格已更新" -#: instances/views.py:2685 +#: instances/views.py:2672 msgid "Update Flavor" msgstr "更新规格" -#: instances/views.py:2697 +#: instances/views.py:2684 msgid "Flavor Deleted" msgstr "规格已删除" -#: instances/views.py:2703 +#: instances/views.py:2690 msgid "Only the size template goes; VMs made from it keep their size." msgstr "仅删除此规格;由它创建的虚拟机保持其大小。" @@ -7500,7 +7517,7 @@ msgstr "" msgid "%(label)s is %(state)s on this resource (since %(since)s)." msgstr "此资源上的%(label)s%(state)s(自 %(since)s起)。" -#: operations/worker.py:38 +#: operations/worker.py:40 msgid "" "libvirt's merge finished copying but never completed (for example after a " "libvirtd restart); check the VM before resolving" @@ -7508,18 +7525,18 @@ msgstr "" "libvirt 的合并已完成复制但从未结束(例如 libvirtd 重启后);处理前请检查虚拟" "机" -#: operations/worker.py:40 +#: operations/worker.py:42 msgid "" "The worker that ran this job stopped responding; an administrator must make " "sure it is no longer running, then resolve this job" msgstr "" "运行此任务的工作进程已停止响应;管理员必须确认它已不再运行,然后处理此任务" -#: operations/worker.py:42 +#: operations/worker.py:44 msgid "Waiting for recovery" msgstr "等待恢复" -#: operations/worker.py:393 +#: operations/worker.py:455 msgid "The worker stopped before the job changed anything" msgstr "工作进程在任务做出任何更改之前停止" @@ -8095,12 +8112,12 @@ msgstr "上传会话繁忙,请重试。" msgid "ISO image already exists" msgstr "ISO 镜像已存在" -#: storages/views.py:176 +#: storages/views.py:178 #, python-format msgid "Volume: %(vol)s is deleted." msgstr "卷 %(vol)s 已删除。" -#: storages/views.py:194 +#: storages/views.py:196 #, python-format msgid "Image file %(name)s is created successfully" msgstr "镜像文件 %(name)s 创建成功" @@ -8403,10 +8420,53 @@ msgid "" "encrypted anew." msgstr "新值会立即替换旧值;之前用口令加密的内容不会重新加密。" -#: vrtManager/connection.py:200 +#: vrtManager/connection.py:50 +msgid "Connection closed (error)" +msgstr "连接已关闭(错误)" + +#: vrtManager/connection.py:51 +msgid "Connection closed (end of file)" +msgstr "连接已关闭(文件结束)" + +#: vrtManager/connection.py:52 +msgid "Connection closed (keepalive timeout)" +msgstr "连接已关闭(保活超时)" + +#: vrtManager/connection.py:53 +msgid "Connection closed (client closed)" +msgstr "连接已关闭(客户端已关闭)" + +#: vrtManager/connection.py:139 +#, python-format +msgid "" +"Connection Failed: %(host)s does not answer: %(requests)s requests still " +"wait for it" +msgstr "连接失败:%(host)s 无响应:仍有 %(requests)s 个请求在等待它" + +#: vrtManager/connection.py:208 +#, python-format +msgid "Connection Failed: %(host)s did not answer within %(seconds)s s" +msgstr "连接失败:%(host)s 在 %(seconds)s 秒内未响应" + +#: vrtManager/connection.py:218 msgid "the connection closed right after opening" msgstr "连接在打开后立即关闭" +#: vrtManager/connection.py:231 +#, python-format +msgid "Connection Failed: %(error)s" +msgstr "连接失败:%(error)s" + +#: vrtManager/connection.py:291 +#, python-format +msgid "Connection closed (%(reason)s)" +msgstr "连接已关闭(%(reason)s)" + +#: vrtManager/connection.py:433 +#, python-format +msgid "Connection Failed: %(host)s is not connected" +msgstr "连接失败:%(host)s 未连接" + #: vrtManager/instance.py:134 msgid "A running or paused VM cannot be migrated offline" msgstr "运行中或已暂停的虚拟机不能离线迁移" @@ -8562,116 +8622,116 @@ msgid "" "with '.'" msgstr "快照名称为 1-64 个字母、数字、'.'、'_' 或 '-',且不能以 '.' 开头" -#: vrtManager/instance.py:1100 +#: vrtManager/instance.py:1076 msgid "" "A device other than a disk or NIC is in the boot order: change it in the XML " "editor" msgstr "启动顺序中有磁盘或网卡以外的设备:请在 XML 编辑器中修改" -#: vrtManager/instance.py:1112 +#: vrtManager/instance.py:1088 msgid "Invalid Device Type for boot order" msgstr "启动顺序的设备类型无效" -#: vrtManager/instance.py:1115 +#: vrtManager/instance.py:1091 #, python-format msgid "Boot device %(dev)s is not in the definition" msgstr "启动设备 %(dev)s 不在定义中" -#: vrtManager/instance.py:1135 +#: vrtManager/instance.py:1111 #, python-format msgid "CD-ROM %(dev)s is not in the running definition" msgstr "CD-ROM %(dev)s 不在运行中的定义中" -#: vrtManager/instance.py:1136 +#: vrtManager/instance.py:1112 #, python-format msgid "CD-ROM %(dev)s is not in the persistent definition" msgstr "CD-ROM %(dev)s 不在持久定义中" -#: vrtManager/instance.py:1148 +#: vrtManager/instance.py:1124 #, python-format msgid "Media of %(dev)s changed in the running VM only: %(err)s" msgstr "%(dev)s 的介质仅在运行中的虚拟机中更改:%(err)s" -#: vrtManager/instance.py:1159 +#: vrtManager/instance.py:1135 #, python-format msgid "ISO image %(image)s was not found" msgstr "未找到 ISO 镜像 %(image)s" -#: vrtManager/instance.py:1161 +#: vrtManager/instance.py:1137 #, python-format msgid "ISO image %(image)s is in more than one storage pool" msgstr "ISO 镜像 %(image)s 位于多个存储池中" -#: vrtManager/instance.py:1268 +#: vrtManager/instance.py:1244 #, python-format msgid "Disk %(target_dev)s is not in the VM's definition" msgstr "磁盘 %(target_dev)s 不在虚拟机的定义中" -#: vrtManager/instance.py:1396 +#: vrtManager/instance.py:1372 msgid "Please shutdown the instance then try to enable vCPU hotplug" msgstr "请先关闭虚拟机,再启用 vCPU 热插拔" -#: vrtManager/instance.py:1859 +#: vrtManager/instance.py:1835 msgid "" "The VM has external snapshots; internal snapshots cannot be mixed with them" msgstr "虚拟机有外部快照;内部快照不能与其混用" -#: vrtManager/instance.py:1891 +#: vrtManager/instance.py:1867 msgid "A snapshot with memory is not quiesced; it keeps the whole guest state" msgstr "含内存的快照不会静默文件系统;它保存整个客户机状态" -#: vrtManager/instance.py:1893 +#: vrtManager/instance.py:1869 msgid "Only a running VM's file systems can be frozen" msgstr "只有运行中的虚拟机的文件系统可以冻结" -#: vrtManager/instance.py:1895 +#: vrtManager/instance.py:1871 msgid "The QEMU guest agent is not connected; it freezes the file systems" msgstr "QEMU 客户机代理未连接;文件系统由它冻结" -#: vrtManager/instance.py:1898 +#: vrtManager/instance.py:1874 msgid "" "The VM has internal snapshots; external snapshots cannot be mixed with them" msgstr "虚拟机有内部快照;外部快照不能与其混用" -#: vrtManager/instance.py:1903 +#: vrtManager/instance.py:1879 msgid "Newer snapshots exist after the last revert; delete them first" msgstr "上次还原后存在更新的快照;请先删除它们" -#: vrtManager/instance.py:1906 +#: vrtManager/instance.py:1882 msgid "No snapshot is current; revert to a snapshot first" msgstr "没有当前快照;请先还原到某个快照" -#: vrtManager/instance.py:1912 +#: vrtManager/instance.py:1888 #, python-format msgid "Eject the media from %(dev)s first" msgstr "请先弹出 %(dev)s 中的介质" -#: vrtManager/instance.py:1914 +#: vrtManager/instance.py:1890 #, python-format msgid "Disk %(dev)s is not a file; external snapshots need file disks" msgstr "磁盘 %(dev)s 不是文件;外部快照需要文件磁盘" -#: vrtManager/instance.py:1922 +#: vrtManager/instance.py:1898 #, python-format msgid "" "The storage pools could not be refreshed, so their free space is unknown: " "%(err)s" msgstr "无法刷新存储池,其可用空间未知:%(err)s" -#: vrtManager/instance.py:1943 +#: vrtManager/instance.py:1919 msgid "Memory is saved only from a running VM" msgstr "只能保存运行中的虚拟机的内存" -#: vrtManager/instance.py:1945 +#: vrtManager/instance.py:1921 msgid "The VM has no disk to keep its memory next to" msgstr "虚拟机没有可存放其内存的磁盘" -#: vrtManager/instance.py:1949 +#: vrtManager/instance.py:1925 #, python-format msgid "%(disk)s is not in a storage pool; memory is saved only into one" msgstr "%(disk)s 不在存储池中;内存只能保存到存储池中" -#: vrtManager/instance.py:1980 +#: vrtManager/instance.py:1956 #, python-format msgid "" "Storage pool %(pool)s has %(free).1f GiB free; the snapshot needs %(size).1f " @@ -8681,156 +8741,156 @@ msgstr "" "存储池 %(pool)s 可用 %(free).1f GiB;快照需要 %(size).1f GiB(其中虚拟机磁盘" "的 %(percent)g%%,至少 %(minimum)g GiB,若保存内存则另加内存)" -#: vrtManager/instance.py:1998 +#: vrtManager/instance.py:1974 msgid "" "This snapshot was taken by an older version on a UEFI VM and cannot be " "reverted; delete it instead" msgstr "此快照由旧版本在 UEFI 虚拟机上创建,无法还原;请将其删除" -#: vrtManager/instance.py:2028 +#: vrtManager/instance.py:2004 #, python-format msgid "" "The revert failed twice; try again in a moment (%(error)s). The VM is " "running." msgstr "还原两次失败;请稍后重试(%(error)s)。虚拟机正在运行。" -#: vrtManager/instance.py:2030 +#: vrtManager/instance.py:2006 #, python-format msgid "" "The revert failed twice; try again in a moment (%(error)s). The VM is shut " "off." msgstr "还原两次失败;请稍后重试(%(error)s)。虚拟机已关机。" -#: vrtManager/instance.py:2193 +#: vrtManager/instance.py:2169 msgid "A disk moves when its VM is defined and running, paused or shut off" msgstr "仅当虚拟机已定义且处于运行、暂停或关机状态时才能移动磁盘" -#: vrtManager/instance.py:2195 +#: vrtManager/instance.py:2171 msgid "" "A disk of a VM with snapshots, a saved state or a running block job does not " "move" msgstr "有快照、保存的状态或正在运行块任务的虚拟机的磁盘不能移动" -#: vrtManager/instance.py:2203 +#: vrtManager/instance.py:2179 #, python-format msgid "" "%(dev)s is not a disk file of the VM, the same in its running and next " "start's definition" msgstr "%(dev)s 不是该虚拟机在运行中的定义和下次启动定义中相同的磁盘文件" -#: vrtManager/instance.py:2208 +#: vrtManager/instance.py:2184 #, python-format msgid "%(dev)s does not move: only writable raw and qcow2 disks do" msgstr "%(dev)s 不能移动:只能移动可写的 raw 和 qcow2 磁盘" -#: vrtManager/instance.py:2215 +#: vrtManager/instance.py:2191 #, python-format msgid "%(dev)s does not move: no storage pool has %(path)s" msgstr "%(dev)s 不能移动:没有存储池包含 %(path)s" -#: vrtManager/instance.py:2217 +#: vrtManager/instance.py:2193 #, python-format msgid "%(dev)s does not move: it has a backing file" msgstr "%(dev)s 不能移动:它有后备文件" -#: vrtManager/instance.py:2220 +#: vrtManager/instance.py:2196 #, python-format msgid "%(pool_name)s is not an active pool of disk files of this host" msgstr "%(pool_name)s 不是此主机上活动的磁盘文件存储池" -#: vrtManager/instance.py:2223 +#: vrtManager/instance.py:2199 #, python-format msgid "%(dev)s is in pool %(pool_name)s already" msgstr "%(dev)s 已在存储池 %(pool_name)s 中" -#: vrtManager/instance.py:2227 +#: vrtManager/instance.py:2203 #, python-format msgid "Pool %(pool_name)s already has a file %(name)s" msgstr "存储池 %(pool_name)s 中已有文件 %(name)s" -#: vrtManager/instance.py:2251 +#: vrtManager/instance.py:2227 #, python-format msgid "The copy of %(dev)s ended before it was complete" msgstr "%(dev)s 的复制在完成前结束" -#: vrtManager/instance.py:2296 +#: vrtManager/instance.py:2272 #, python-format msgid "%(error)s; remove %(dest)s if it is there: %(cleanup_error)s" msgstr "%(error)s;如果 %(dest)s 存在请将其删除:%(cleanup_error)s" -#: vrtManager/instance.py:2298 +#: vrtManager/instance.py:2274 #, python-format msgid "%(error)s; the VM may use %(dest)s now: check its disk %(dev)s" msgstr "%(error)s;虚拟机现在可能在使用 %(dest)s:请检查其磁盘 %(dev)s" -#: vrtManager/instance.py:2305 +#: vrtManager/instance.py:2281 #, python-format msgid "The VM has no internal snapshot named %(name)s" msgstr "虚拟机没有名为 %(name)s 的内部快照" -#: vrtManager/instance.py:2314 +#: vrtManager/instance.py:2290 msgid "The VM has a saved state; start it or remove the saved state first" msgstr "虚拟机有保存的状态;请先启动它或删除保存的状态" -#: vrtManager/instance.py:2316 +#: vrtManager/instance.py:2292 msgid "A snapshot job is still running on this VM; try again when it ends" msgstr "此虚拟机上仍有快照任务在运行;请在其结束后重试" -#: vrtManager/instance.py:2326 +#: vrtManager/instance.py:2302 msgid "Shut the VM down to revert to an internal snapshot" msgstr "请关闭虚拟机后再还原到内部快照" -#: vrtManager/instance.py:2415 +#: vrtManager/instance.py:2391 msgid "Cannot clone a VM whose NVRAM is not a file" msgstr "NVRAM 不是文件的虚拟机无法克隆" -#: vrtManager/instance.py:2483 +#: vrtManager/instance.py:2459 #, python-format msgid "Clone failed (%(err)s); remove these copies by hand: %(path)s" msgstr "克隆失败(%(err)s);请手动删除这些副本:%(path)s" -#: vrtManager/instance.py:2493 +#: vrtManager/instance.py:2469 msgid "Shut the VM down before cloning it" msgstr "请先关闭虚拟机再克隆" -#: vrtManager/instance.py:2547 +#: vrtManager/instance.py:2523 #, python-format msgid "Clone failed (%(err)s); remove these copies by hand: %(leftovers)s" msgstr "克隆失败(%(err)s);请手动删除这些副本:%(leftovers)s" -#: vrtManager/instance.py:2558 +#: vrtManager/instance.py:2534 msgid "Live clone needs libvirt 11.10 or later; shut the VM down to clone it" msgstr "在线克隆需要 libvirt 11.10 或更高版本;请关闭虚拟机后再克隆" -#: vrtManager/instance.py:2561 +#: vrtManager/instance.py:2537 msgid "A VM with a TPM is cloned only shut down" msgstr "带 TPM 的虚拟机只能在关机时克隆" -#: vrtManager/instance.py:2564 +#: vrtManager/instance.py:2540 #, python-format msgid "Disk %(dev)s is not a local file; shut the VM down to clone it" msgstr "磁盘 %(dev)s 不是本地文件;请关闭虚拟机后再克隆" -#: vrtManager/instance.py:2566 +#: vrtManager/instance.py:2542 #, python-format msgid "Disk %(dev)s is shareable; shut the VM down to clone it" msgstr "磁盘 %(dev)s 是可共享的;请关闭虚拟机后再克隆" -#: vrtManager/instance.py:2571 +#: vrtManager/instance.py:2547 #, python-format msgid "Disk %(dev)s changes at the next start; shut the VM down to clone it" msgstr "磁盘 %(dev)s 在下次启动时会改变;请关闭虚拟机后再克隆" -#: vrtManager/instance.py:2573 +#: vrtManager/instance.py:2549 msgid "Another job is running on the VM; clone it when that ends" msgstr "虚拟机上有另一个任务正在运行;请在其结束后再克隆" -#: vrtManager/instance.py:2586 +#: vrtManager/instance.py:2562 #, python-format msgid "Volume %(name)s already exists in storage pool %(pool)s" msgstr "卷 %(name)s 已存在于存储池 %(pool)s 中" -#: vrtManager/instance.py:2605 +#: vrtManager/instance.py:2581 #, python-format msgid "" "Storage pool %(pool)s has %(free).1f GiB free; the clone needs %(size).1f " @@ -8839,92 +8899,92 @@ msgstr "" "存储池 %(pool)s 可用 %(free).1f GiB;克隆需要 %(size).1f GiB(复制的磁盘,再" "加其 %(percent)g%%,至少 %(minimum)g GiB)" -#: vrtManager/instance.py:2744 +#: vrtManager/instance.py:2720 msgid "A network interface that is a host device is removed in the XML editor" msgstr "作为主机设备的网络接口需在 XML 编辑器中删除" -#: vrtManager/instance.py:2760 +#: vrtManager/instance.py:2736 #, python-format msgid "No network interface with MAC %(old_mac)s" msgstr "没有 MAC 为 %(old_mac)s 的网络接口" -#: vrtManager/instance.py:2763 +#: vrtManager/instance.py:2739 msgid "A network interface that is a host device is changed in the XML editor" msgstr "作为主机设备的网络接口需在 XML 编辑器中修改" -#: vrtManager/instance.py:2854 +#: vrtManager/instance.py:2830 msgid "" "A VM changes its PCI devices while it runs, or is shut off without a saved " "state" msgstr "虚拟机只能在运行时或无保存的状态的关机时更改其 PCI 设备" -#: vrtManager/instance.py:2866 +#: vrtManager/instance.py:2842 #, python-format msgid "%(err)s; whether the VM has PCI device %(address)s now is not known" msgstr "%(err)s;虚拟机现在是否有 PCI 设备 %(address)s 未知" -#: vrtManager/instance.py:2868 +#: vrtManager/instance.py:2844 #, python-format msgid "" "%(err)s; PCI device %(address)s: the VM is not running, its next start has it" msgstr "%(err)s;PCI 设备 %(address)s:虚拟机未运行,下次启动时有它" -#: vrtManager/instance.py:2870 +#: vrtManager/instance.py:2846 #, python-format msgid "" "%(err)s; PCI device %(address)s: the VM is not running, its next start does " "not have it" msgstr "%(err)s;PCI 设备 %(address)s:虚拟机未运行,下次启动时没有它" -#: vrtManager/instance.py:2871 +#: vrtManager/instance.py:2847 #, python-format msgid "" "%(err)s; PCI device %(address)s: the running VM has it, its next start has it" msgstr "%(err)s;PCI 设备 %(address)s:运行中的虚拟机有它,下次启动时有它" -#: vrtManager/instance.py:2873 +#: vrtManager/instance.py:2849 #, python-format msgid "" "%(err)s; PCI device %(address)s: the running VM has it, its next start does " "not have it" msgstr "%(err)s;PCI 设备 %(address)s:运行中的虚拟机有它,下次启动时没有它" -#: vrtManager/instance.py:2875 +#: vrtManager/instance.py:2851 #, python-format msgid "" "%(err)s; PCI device %(address)s: the running VM does not have it, its next " "start has it" msgstr "%(err)s;PCI 设备 %(address)s:运行中的虚拟机没有它,下次启动时有它" -#: vrtManager/instance.py:2877 +#: vrtManager/instance.py:2853 #, python-format msgid "" "%(err)s; PCI device %(address)s: the running VM does not have it, its next " "start does not have it" msgstr "%(err)s;PCI 设备 %(address)s:运行中的虚拟机没有它,下次启动时没有它" -#: vrtManager/instance.py:2911 +#: vrtManager/instance.py:2887 #, python-format msgid "The VM has no PCI device %(address)s" msgstr "虚拟机没有 PCI 设备 %(address)s" -#: vrtManager/instance.py:2929 +#: vrtManager/instance.py:2905 msgid "The VM has no USB controller" msgstr "虚拟机没有 USB 控制器" -#: vrtManager/instance.py:2948 +#: vrtManager/instance.py:2924 msgid "The VM has no such USB device" msgstr "虚拟机没有此 USB 设备" -#: vrtManager/instance.py:2989 +#: vrtManager/instance.py:2965 msgid "The VM has its own RNG device: change it in the XML editor" msgstr "虚拟机有自己的 RNG 设备:请在 XML 编辑器中修改" -#: vrtManager/instance.py:3016 +#: vrtManager/instance.py:2992 msgid "The VM has its own TPM: change it in the XML editor" msgstr "虚拟机有自己的 TPM:请在 XML 编辑器中修改" -#: vrtManager/instance.py:3035 +#: vrtManager/instance.py:3011 #, python-format msgid "Unknown crash action %(action)s" msgstr "未知的崩溃操作 %(action)s" diff --git a/vrtManager/connection.py b/vrtManager/connection.py index 949c4f19..85fae4f1 100644 --- a/vrtManager/connection.py +++ b/vrtManager/connection.py @@ -45,7 +45,13 @@ RETRY_AFTER = getattr(settings, "LIBVIRT_RETRY_AFTER", 30) # request (the job worker's, the consoles') are not counted: a job holds its # host for as long as it runs. HOST_REQUESTS = getattr(settings, "LIBVIRT_HOST_REQUESTS", 2) -CLOSE_REASONS = {0: "error", 1: "end of file", 2: "keepalive timeout", 3: "client closed"} +# libvirt's close reasons, one whole message each +CLOSE_REASONS = { + 0: gettext_noop("Connection closed (error)"), + 1: gettext_noop("Connection closed (end of file)"), + 2: gettext_noop("Connection closed (keepalive timeout)"), + 3: gettext_noop("Connection closed (client closed)"), +} # ssh with a connect timeout for qemu+ssh (libvirt runs the "command" binary # in place of ssh and never passes one itself) SSH_COMMAND = os.path.join(os.path.dirname(os.path.abspath(__file__)), "libvirt-ssh") @@ -130,8 +136,8 @@ def _count_on(connection): return _leave_host() if not connection.requests.acquire(timeout=CONNECT_TIMEOUT): - raise util.ConnectionFailed( - f"Connection Failed: {connection.host} does not answer: {HOST_REQUESTS} requests still wait for it") + raise util.ConnectionFailed(gettext_noop("Connection Failed: %(host)s does not answer: %(requests)s requests still wait for it"), + host=connection.host, requests=HOST_REQUESTS) _request.held = connection @@ -199,7 +205,8 @@ class wvmConnection(object): if not opening.wait(CONNECT_TIMEOUT): with self.connection_state_lock: if self._opening is opening: # still running: give up waiting, not the open - self.last_error = f"Connection Failed: {self.host} did not answer within {CONNECT_TIMEOUT} s" + self.last_error = util.message(gettext_noop("Connection Failed: %(host)s did not answer within %(seconds)s s"), + host=self.host, seconds=CONNECT_TIMEOUT) opening.abandoned = True def _open(self, opening): @@ -219,7 +226,9 @@ class wvmConnection(object): except libvirtError: pass except Exception as e: # libvirtError, or anything else from the transport - error = f"Connection Failed: {str(e)}" + # libvirt's own text stays as it is; one of ours is a message of its own + reason = [util.message(e.text, **e.values)] if isinstance(e, util.OperationError) else str(e) + error = util.message(gettext_noop("Connection Failed: %(error)s"), error=reason) finally: with self.connection_state_lock: if error is None: @@ -276,7 +285,10 @@ class wvmConnection(object): # not drop its successor. if connection is not self.connection: return - self.last_error = f"Connection closed ({CLOSE_REASONS.get(reason, reason)})" + if reason in CLOSE_REASONS: + self.last_error = util.message(CLOSE_REASONS[reason]) + else: + self.last_error = util.message(gettext_noop("Connection closed (%(reason)s)"), reason=reason) # prevent other threads from using the connection (in the future) self.connection = None @@ -417,7 +429,10 @@ class wvmConnectionManager(object): connection.connect() live = connection.alive_connection() if live is None: - raise util.ConnectionFailed(connection.last_error) + # a connection that died without a close callback leaves no error behind + error = connection.last_error or util.message(gettext_noop("Connection Failed: %(host)s is not connected"), + host=connection.host) + raise util.ConnectionFailed(error["text"], **error["values"]) return live def host_is_up(self, conn_type, hostname, timeout=1): diff --git a/vrtManager/tests/test_connection.py b/vrtManager/tests/test_connection.py index 27f32693..fb68e40e 100644 --- a/vrtManager/tests/test_connection.py +++ b/vrtManager/tests/test_connection.py @@ -194,7 +194,7 @@ class BoundedOpenTestCase(unittest.TestCase): self.assertIs(self.get()[0], new) entry._wvmConnection__connection_close_callback(new, 2) self.assertIsNone(entry.connection) - self.assertEqual(entry.last_error, "Connection closed (keepalive timeout)") + self.assertEqual(entry.last_error, {"text": "Connection closed (keepalive timeout)", "values": {}}) def test_a_connection_closed_before_it_is_published_is_an_error(self): self.release.set()