diff --git a/accounts/__init__.py b/accounts/__init__.py index 83198231..e69de29b 100644 --- a/accounts/__init__.py +++ b/accounts/__init__.py @@ -1 +0,0 @@ -default_app_config = 'accounts.apps.AccountsConfig' diff --git a/admin/__init__.py b/admin/__init__.py index 052dc420..e69de29b 100644 --- a/admin/__init__.py +++ b/admin/__init__.py @@ -1 +0,0 @@ -default_app_config = 'admin.apps.AdminConfig' diff --git a/admin/forms.py b/admin/forms.py index 331a181d..1c526c3c 100644 --- a/admin/forms.py +++ b/admin/forms.py @@ -119,10 +119,6 @@ class UserForm(UniqueEmailMixin, forms.ModelForm): def permission_rows(self): return permission_rows(self["user_permissions"]) - def identity_has_errors(self): - return any(self.has_error(name) for name in ("username", "password", "first_name", "last_name", "email")) - - class UserCreateForm(UserForm): password = forms.CharField(widget=forms.PasswordInput) diff --git a/computes/tests/test_validators.py b/computes/tests/test_validators.py index 178fcc8e..17b97610 100644 --- a/computes/tests/test_validators.py +++ b/computes/tests/test_validators.py @@ -6,7 +6,7 @@ import unittest from django.core.exceptions import ValidationError -from computes.validators import validate_hostname, validate_login, validate_name +from computes.validators import validate_hostname, validate_login class HostnameValidatorTestCase(unittest.TestCase): @@ -46,8 +46,3 @@ class LoginValidatorTestCase(unittest.TestCase): validate_login(value) -class NameValidatorTestCase(unittest.TestCase): - def test_checks_the_value(self): - validate_name("good-name_1.2") - with self.assertRaises(ValidationError): - validate_name("bad name!") diff --git a/computes/validators.py b/computes/validators.py index 4e3620f5..d4fedc15 100644 --- a/computes/validators.py +++ b/computes/validators.py @@ -7,7 +7,6 @@ from django.utils.translation import gettext_lazy as _ # one or more dot-separated RFC 1123 labels, optional trailing dot _hostname = re.compile(r"[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*\.?") _login = re.compile(r"[A-Za-z0-9._][A-Za-z0-9._-]*") -_name = re.compile(r"[A-Za-z0-9._-]+") def validate_hostname(value): @@ -37,11 +36,6 @@ def validate_login(value): ) -def validate_name(value): - if not _name.fullmatch(value): - raise ValidationError(_("The name must not contain any special characters")) - - def validate_migration_address(value): """An IP address (no IPv6 scope) or a host name: no scheme, port or brackets.""" try: diff --git a/conf/runit/secret_generator.py b/conf/runit/secret_generator.py index 70ee032c..3183ffaf 100644 --- a/conf/runit/secret_generator.py +++ b/conf/runit/secret_generator.py @@ -1,13 +1,3 @@ import secrets -generated_key = secrets.token_urlsafe(50) - -print(''.join(generated_key)) - - -### Use for old python versions < 3.6 -##import random -##import string -# -##haystack = string.ascii_letters + string.digits + string.punctuation -##print(''.join([random.SystemRandom().choice(haystack.replace('/', '').replace('\'', '').replace('\"', '')) for _ in range(50)])) +print(secrets.token_urlsafe(50)) diff --git a/instances/__init__.py b/instances/__init__.py index bf9df051..e69de29b 100644 --- a/instances/__init__.py +++ b/instances/__init__.py @@ -1 +0,0 @@ -default_app_config = 'instances.apps.InstancesConfig' diff --git a/instances/tests/test_audit_rows.py b/instances/tests/test_audit_rows.py index 94eebe22..b7783965 100644 --- a/instances/tests/test_audit_rows.py +++ b/instances/tests/test_audit_rows.py @@ -54,8 +54,6 @@ class FlavorRowTests(TestCase): data = {"label": "tiny-a", "memory": 512, "vcpu": 1, "disk": 10} self.client.post(reverse("instances:flavor_create"), data) flavor = Flavor.objects.get(label="tiny-a") - self.client.post(reverse("instances:flavor_update", args=[flavor.pk]), {**data, "vcpu": 2}) - self.client.post(reverse("instances:flavor_update", args=[flavor.pk]), {**data, "vcpu": 2}) # no change self.client.post(reverse("instances:flavor_delete", args=[flavor.pk])) self.assertFalse(Flavor.objects.filter(label="tiny-a").exists()) @@ -71,6 +69,6 @@ class FlavorRowTests(TestCase): self.assertFalse(Flavor.objects.filter(label="huge-a").exists()) self.assertEqual([m for m, _ in rows()], [ - "Flavor tiny-a: add", "Flavor tiny-a: change vcpu", "Flavor tiny-a: delete", + "Flavor tiny-a: add", "Flavor tiny-a: delete", "Flavor huge-a: add", "Flavor huge-a: change vcpu", "Flavor huge-a: change memory", "Flavor huge-a: delete", ]) diff --git a/instances/tests/test_views.py b/instances/tests/test_views.py index 03d71f9c..b6ee2531 100644 --- a/instances/tests/test_views.py +++ b/instances/tests/test_views.py @@ -1080,21 +1080,6 @@ class InstancesTestCase(TestCase): id = Flavor.objects.last().id - response = self.client.get(reverse("instances:flavor_update", args=[id])) - self.assertEqual(response.status_code, 200) - - response = self.client.post( - reverse("instances:flavor_update", args=[id]), - { - "label": "test_flavor_", - "memory": 256, - "vcpu": 1, - "disk": 10, - }, - HTTP_REFERER=reverse("index"), - ) - self.assertEqual(response.status_code, 302) - response = self.client.get(reverse("instances:flavor_delete", args=[id])) self.assertEqual(response.status_code, 200) diff --git a/instances/urls.py b/instances/urls.py index ffd35068..ac26173c 100755 --- a/instances/urls.py +++ b/instances/urls.py @@ -10,7 +10,6 @@ urlpatterns = [ path("find_address/", views.find_address, name="find_address"), path("report.xlsx", views.vm_report, name="vm_report"), path("flavor/create/", views.flavor_create, name="flavor_create"), - path("flavor//update/", views.flavor_update, name="flavor_update"), path("flavor//delete/", views.flavor_delete, name="flavor_delete"), path("/", views.instance, name="instance"), path("/poweron/", views.poweron, name="poweron"), diff --git a/instances/views.py b/instances/views.py index 9a6b1bc7..199401bf 100755 --- a/instances/views.py +++ b/instances/views.py @@ -46,8 +46,7 @@ from libvirt import (VIR_DOMAIN_PAUSED, VIR_ERR_NO_DOMAIN, VIR_ERR_NO_SUPPORT, libvirtError) -from logs.audit import audit, audit_vm, changed_fields, failed_vm -from logs.audit import snapshot as audit_snapshot +from logs.audit import audit, audit_vm, failed_vm from operations import claims, jobs from operations.utils import HOST_BUSY, busy_message, summary from webvirtcloud.middleware import error_text, same_origin_referer @@ -2643,27 +2642,6 @@ def flavor_create(request): ) -@superuser_only -def flavor_update(request, pk): - flavor = get_object_or_404(Flavor, pk=pk) - subject, before = f"Flavor {flavor.label}", audit_snapshot(flavor) - form = FlavorForm(request.POST or None, instance=flavor) - if form.is_valid(): - with audit(request, None, subject, "change") as entry: - form.save() - fields = changed_fields(before, audit_snapshot(flavor)) - entry.action = "change " + ", ".join(fields) - entry.skip = not fields - messages.success(request, _("Flavor Updated")) - return get_safe_redirect(request, default=reverse("instances:index")) - - return render( - request, - "common/form.html", - {"form": form, "title": _("Update Flavor")}, - ) - - @superuser_only def flavor_delete(request, pk): flavor = get_object_or_404(Flavor, pk=pk) diff --git a/locale/tr/LC_MESSAGES/django.mo b/locale/tr/LC_MESSAGES/django.mo index 4bf1a925..9db11eb6 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 820a44d1..3ea7bcaa 100644 --- a/locale/tr/LC_MESSAGES/django.po +++ b/locale/tr/LC_MESSAGES/django.po @@ -202,7 +202,7 @@ msgid "User sections" msgstr "Kullanıcı bölümleri" #: accounts/templates/account.html:44 accounts/templates/account.html:52 -#: admin/forms.py:189 computes/templates/computes/list.html:30 +#: admin/forms.py:185 computes/templates/computes/list.html:30 #: computes/templates/computes/list.html:57 computes/templates/overview.html:46 msgid "VMs" msgstr "Sanal makineler" @@ -704,13 +704,13 @@ msgstr "İzinler" msgid "Groups" msgstr "Gruplar" -#: admin/forms.py:143 +#: admin/forms.py:139 #, python-format msgid "NEW_USER_DEFAULT_INSTANCES: %(name)s is not exactly one VM" msgstr "" "NEW_USER_DEFAULT_INSTANCES: %(name)s tam olarak tek bir sanal makine değil" -#: admin/forms.py:190 computes/templates/computes/list.html:58 +#: admin/forms.py:186 computes/templates/computes/list.html:58 #: computes/templates/overview.html:58 instances/forms.py:15 #: instances/templates/allinstances_index_grouped.html:16 #: instances/templates/allinstances_index_nongrouped.html:14 @@ -720,7 +720,7 @@ msgstr "" msgid "vCPUs" msgstr "vCPU" -#: admin/forms.py:191 computes/templates/computes/instances.html:49 +#: admin/forms.py:187 computes/templates/computes/instances.html:49 #: computes/templates/computes/list.html:59 computes/templates/overview.html:66 #: computes/templates/overview.html:150 #: instances/templates/allinstances_index_grouped.html:17 @@ -732,34 +732,34 @@ msgstr "vCPU" msgid "Memory" msgstr "Bellek" -#: admin/forms.py:192 instances/models.py:237 +#: admin/forms.py:188 instances/models.py:237 #: instances/templates/create_instance_w2.html:118 #: instances/templates/instances/settings_tab.html:25 #: instances/templates/instances/stats_tab.html:51 msgid "Disk" msgstr "Disk" -#: admin/forms.py:202 +#: admin/forms.py:198 msgid "No limit" msgstr "Sınır yok" -#: admin/forms.py:218 +#: admin/forms.py:214 msgid "Enter a limit or choose No limit." msgstr "Bir sınır girin ya da Sınır yok'u seçin." -#: admin/forms.py:230 +#: admin/forms.py:226 msgid "The user must change it at their next login" msgstr "Kullanıcı bir sonraki girişinde onu değiştirmek zorundadır" -#: admin/forms.py:236 +#: admin/forms.py:232 msgid "With a password" msgstr "Parolayla" -#: admin/forms.py:236 +#: admin/forms.py:232 msgid "Without a password" msgstr "Parolasız" -#: admin/forms.py:242 +#: admin/forms.py:238 msgid "A user without a password cannot be made to change it" msgstr "Parolası olmayan bir kullanıcıya parola değiştirme zorunluluğu konamaz" @@ -915,7 +915,7 @@ msgid "IP" msgstr "IP" #: admin/templates/admin/logs.html:56 admin/views.py:286 instances/states.py:19 -#: instances/views.py:415 instances/views.py:417 logs/views.py:17 +#: instances/views.py:414 instances/views.py:416 logs/views.py:17 msgid "Unknown" msgstr "Bilinmeyen" @@ -2352,11 +2352,11 @@ msgstr "Konuk mimarileri" msgid "Emulator" msgstr "Emülatör" -#: computes/validators.py:25 +#: computes/validators.py:24 msgid "Enter an IPv4 address or a host name, without a scheme, port or path" msgstr "Şema, port veya yol olmadan bir IPv4 adresi ya da sunucu adı girin" -#: computes/validators.py:36 +#: computes/validators.py:35 msgid "" "The login may contain only letters, digits, '.', '_' and '-', and may not " "start with '-'" @@ -2364,15 +2364,11 @@ msgstr "" "Kullanıcı adı yalnızca harf, rakam, '.', '_' ve '-' içerebilir ve '-' ile " "başlayamaz" -#: computes/validators.py:42 -msgid "The name must not contain any special characters" -msgstr "Ad herhangi bir özel karakter içermemelidir" - -#: computes/validators.py:53 +#: computes/validators.py:47 msgid "Enter an IP address or a host name, without a scheme or port" msgstr "Şema veya port olmadan bir IP adresi ya da sunucu adı girin" -#: computes/validators.py:60 +#: computes/validators.py:54 msgid "" "Enter the 64 hexadecimal characters of GSTFSD_KEY in the host's " "/etc/default/webvirt-gstfsd" @@ -2936,7 +2932,7 @@ msgstr "" msgid "Create VM" msgstr "Sanal makine oluştur" -#: instances/jobs.py:773 instances/jobs.py:818 instances/views.py:2459 +#: instances/jobs.py:773 instances/jobs.py:818 instances/views.py:2458 msgid "A virtual machine with this name already exists" msgstr "Bu isimde bir sanal makine mevcut" @@ -3336,7 +3332,7 @@ msgid "Disk source" msgstr "Disk kaynağı" #: instances/templates/add_instance_volume.html:21 -#: instances/templates/create_instance_w2.html:134 instances/views.py:2478 +#: instances/templates/create_instance_w2.html:134 instances/views.py:2477 msgid "New disk" msgstr "Yeni disk" @@ -3708,7 +3704,7 @@ msgstr "Özel CPU modelleri" msgid "Size (GiB)" msgstr "Boyut (GiB)" -#: instances/templates/create_instance_w2.html:161 instances/views.py:2479 +#: instances/templates/create_instance_w2.html:161 instances/views.py:2478 msgid "Existing volumes" msgstr "Mevcut birimler" @@ -3744,7 +3740,7 @@ msgstr "Aygıt" msgid "Remove" msgstr "Kaldır" -#: instances/templates/create_instance_w2.html:194 instances/views.py:2480 +#: instances/templates/create_instance_w2.html:194 instances/views.py:2479 msgid "Clone from template" msgstr "Şablondan klonla" @@ -5907,43 +5903,43 @@ msgstr "Geçersiz MAC adresi" msgid "More MAC addresses than networks" msgstr "Ağlardan daha fazla MAC adresi" -#: instances/views.py:169 +#: instances/views.py:168 msgid "Enter an IP address, a network such as 192.0.2.0/24, or a MAC address." msgstr "Bir IP adresi, 192.0.2.0/24 gibi bir ağ ya da bir MAC adresi girin." -#: instances/views.py:175 instances/views.py:209 +#: instances/views.py:174 instances/views.py:208 msgid "Too many searches are still running; try again shortly." msgstr "Çok fazla arama hâlâ çalışıyor; birazdan yeniden deneyin." -#: instances/views.py:257 +#: instances/views.py:256 #, python-format msgid "The host %(host)s of '%(name)s' cannot be reached: %(error)s" msgstr "'%(name)s' sanal makinesinin sunucusu %(host)s erişilemiyor: %(error)s" -#: instances/views.py:263 +#: instances/views.py:262 #, python-format msgid "The host of '%(name)s' cannot be reached right now." msgstr "'%(name)s' sanal makinesinin sunucusuna şu anda erişilemiyor." -#: instances/views.py:264 +#: instances/views.py:263 msgid " Jobs on it can be followed under Jobs in the menu." msgstr " Üzerindeki işler menüdeki İşler bölümünden izlenebilir." -#: instances/views.py:272 +#: instances/views.py:271 #, python-format msgid "'%(name)s' is no longer on its host." msgstr "'%(name)s' artık sunucusunda yok." -#: instances/views.py:370 +#: instances/views.py:369 msgid "There is no other host to migrate to." msgstr "Taşınacak başka bir sunucu yok." -#: instances/views.py:372 +#: instances/views.py:371 msgid "A VM migrates when it is running, paused or shut off." msgstr "" "Sanal makine çalışırken, duraklatılmışken ya da kapalıyken taşınabilir." -#: instances/views.py:374 +#: instances/views.py:373 msgid "" "A VM with snapshots cannot be migrated: its snapshots stay on this host. " "Delete them first." @@ -5951,7 +5947,7 @@ msgstr "" "Anlık görüntüsü olan bir sanal makine taşınamaz: anlık görüntüleri bu " "sunucuda kalır. Önce onları silin." -#: instances/views.py:376 +#: instances/views.py:375 msgid "" "A VM with host devices cannot be migrated: the destination may not have them." " Remove them first." @@ -5959,11 +5955,11 @@ msgstr "" "Sunucu aygıtları olan bir sanal makine taşınamaz: hedefte bu aygıtlar " "olmayabilir. Önce onları kaldırın." -#: instances/views.py:640 +#: instances/views.py:639 msgid "The VM was moved meanwhile; try again." msgstr "Sanal makine bu arada taşındı; yeniden deneyin." -#: instances/views.py:756 +#: instances/views.py:755 msgid "" "The running VM has no free PCI slot for another disk on this bus: choose the " "scsi bus if the VM has a SCSI controller, or shut the VM down and add the " @@ -5976,7 +5972,7 @@ msgstr "" "yuvaları ekle, sonraki başlatmadan itibaren ona boş yuvalar verir. Yeni bir " "birim havuzunda kalır, mevcut birim olarak eklenebilir." -#: instances/views.py:760 +#: instances/views.py:759 msgid "" "The running VM has no free PCI slot for the SCSI controller the disk needs: " "shut the VM down and add the disk then; Add PCIe slots on the Disks tab gives" @@ -5988,175 +5984,175 @@ msgstr "" "PCIe yuvaları ekle, sonraki başlatmadan itibaren ona boş yuvalar verir. Yeni " "bir birim havuzunda kalır, mevcut birim olarak eklenebilir." -#: instances/views.py:778 +#: instances/views.py:777 #, python-format msgid "Invalid disk options: %(options)s" msgstr "Geçersiz disk seçenekleri: %(options)s" -#: instances/views.py:788 instances/views.py:803 +#: instances/views.py:787 instances/views.py:802 msgid "Templates cannot be started." msgstr "Şablon makineler başlatılamaz." -#: instances/views.py:995 +#: instances/views.py:994 #, python-format msgid "Set the gstfsd key of %(compute)s first (Computes, edit the host)" msgstr "" "Önce %(compute)s sunucusunun gstfsd anahtarını ayarlayın (Sunucular, sunucuyu" " düzenle)" -#: instances/views.py:1002 instances/views.py:1020 instances/views.py:1029 +#: instances/views.py:1001 instances/views.py:1019 instances/views.py:1028 #, python-format msgid "gstfsd error: %(err)s" msgstr "gstfsd hatası: %(err)s" -#: instances/views.py:1030 +#: instances/views.py:1029 msgid "the reply is not signed with the key" msgstr "yanıt anahtarla imzalanmamış" -#: instances/views.py:1038 +#: instances/views.py:1037 msgid "Shut the VM down, or start its QEMU guest agent, and try again" msgstr "" "Sanal makineyi kapatın ya da QEMU konuk ajanını başlatın ve yeniden deneyin" -#: instances/views.py:1051 +#: instances/views.py:1050 msgid "The change may still be made when the agent answers again." msgstr "Ajan yeniden yanıt verdiğinde değişiklik yine de yapılabilir." -#: instances/views.py:1079 +#: instances/views.py:1078 msgid "Reset root password" msgstr "Root parolasını sıfırla" -#: instances/views.py:1083 +#: instances/views.py:1082 msgid "Enter a password" msgstr "Bir parola girin" -#: instances/views.py:1097 +#: instances/views.py:1096 msgid "Select an SSH public key" msgstr "Bir SSH açık anahtarı seçin" -#: instances/views.py:1119 +#: instances/views.py:1118 #, python-format msgid "Installed new SSH public key %(keyname)s" msgstr "Yeni %(keyname)s SSH açık anahtarı yüklendi" -#: instances/views.py:1139 +#: instances/views.py:1138 msgid "Enter a whole number of vCPUs" msgstr "vCPU sayısı için bir tam sayı girin" -#: instances/views.py:1143 +#: instances/views.py:1142 msgid "Shut off the VM to change its vCPUs" msgstr "vCPU'larını değiştirmek için sanal makineyi kapatın" -#: instances/views.py:1146 +#: instances/views.py:1145 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:1153 +#: instances/views.py:1152 #, python-format 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:1161 +#: instances/views.py:1160 #, 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:1180 +#: instances/views.py:1179 msgid "Enter a whole number for memory" msgstr "Bellek için bir tam sayı girin" -#: instances/views.py:1183 +#: instances/views.py:1182 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:1187 +#: instances/views.py:1186 #, python-format 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:1193 +#: instances/views.py:1192 #, 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:1213 +#: instances/views.py:1212 msgid "Enter disk sizes as whole GiB" msgstr "Disk boyutlarını tam GiB olarak girin" -#: instances/views.py:1217 +#: instances/views.py:1216 #, 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:1225 +#: instances/views.py:1224 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:1234 +#: instances/views.py:1233 #, python-format 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:1246 +#: instances/views.py:1245 #, 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:1248 +#: instances/views.py:1247 #, python-format msgid "Disk is resized: %(dev)s" msgstr "Disk boyutu değiştirildi: %(dev)s" -#: instances/views.py:1342 +#: instances/views.py:1341 msgid "The VM's machine has no PCIe slots to add" msgstr "Sanal makinenin makine tipinde eklenecek PCIe yuvası yok" -#: instances/views.py:1347 +#: instances/views.py:1346 #, python-format msgid "%(count)s PCIe slots added" msgstr "%(count)s PCIe yuvası eklendi" -#: instances/views.py:1349 +#: instances/views.py:1348 #, 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:1395 +#: instances/views.py:1394 #, python-format msgid "%(volume)s is already a disk of this VM" msgstr "%(volume)s zaten bu sanal makinenin bir diski" -#: instances/views.py:1485 +#: instances/views.py:1484 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:1490 +#: instances/views.py:1489 msgid "Volume is changed successfully." msgstr "Birim başarıyla değiştirildi." -#: instances/views.py:1508 +#: instances/views.py:1507 #, 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:1515 +#: instances/views.py:1514 #, 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:1530 +#: instances/views.py:1529 #, 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:1542 +#: instances/views.py:1541 #, python-format msgid "" "The guest has not released disk %(dev)s yet; volume %(vol)s was kept. Delete " @@ -6165,62 +6161,62 @@ 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:1553 +#: instances/views.py:1552 #, 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:1579 +#: instances/views.py:1578 #, 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:1582 +#: instances/views.py:1581 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:1587 +#: instances/views.py:1586 #, python-format msgid "%(image)s is already in a CD-ROM of this VM" msgstr "%(image)s bu sanal makinenin bir CD-ROM'unda zaten takılı" -#: instances/views.py:1668 +#: instances/views.py:1667 #, python-format msgid "Pool %(pool)s was not read again: %(err)s" msgstr "%(pool)s havuzu yeniden okunamadı: %(err)s" -#: instances/views.py:1689 +#: instances/views.py:1688 #, python-format msgid "Snapshot was not deleted: %(err)s" msgstr "Anlık görüntü silinmedi: %(err)s" -#: instances/views.py:1804 +#: instances/views.py:1803 msgid "Add at least one device to the boot order." msgstr "Ön yükleme sırasına en az bir aygıt ekleyin." -#: instances/views.py:1818 +#: instances/views.py:1817 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:1820 +#: instances/views.py:1819 msgid "Boot order changed successfully." msgstr "Ön yükleme sırası başarıyla değiştirildi." -#: instances/views.py:1840 +#: instances/views.py:1839 msgid "The XML is empty" msgstr "XML boş" -#: instances/views.py:1844 instances/views.py:2469 +#: instances/views.py:1843 instances/views.py:2468 #, python-format msgid "The XML is not well-formed: %(error)s" msgstr "XML düzgün biçimlendirilmemiş: %(error)s" -#: instances/views.py:1846 +#: instances/views.py:1845 #, 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:1850 +#: instances/views.py:1849 msgid "" "The definition has changed since the editor was opened. Reload the page to " "edit the current one." @@ -6228,40 +6224,40 @@ 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:1862 +#: instances/views.py:1861 msgid "The XML definition was saved." msgstr "XML tanımı kaydedildi." -#: instances/views.py:1864 +#: instances/views.py:1863 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:1945 +#: instances/views.py:1944 msgid "Select one network interface to change" msgstr "Değiştirilecek bir ağ arabirimi seçin" -#: instances/views.py:1983 +#: instances/views.py:1982 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:1985 +#: instances/views.py:1984 msgid "Network device changed" msgstr "Ağ aygıtı değiştirildi" -#: instances/views.py:1997 +#: instances/views.py:1996 msgid "No network selected" msgstr "Ağ seçilmedi" -#: instances/views.py:2002 +#: instances/views.py:2001 #, python-format msgid "The VM already has a network device with MAC %(mac)s" msgstr "Sanal makinede %(mac)s MAC adresli bir ağ aygıtı zaten var" -#: instances/views.py:2021 +#: instances/views.py:2020 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 " @@ -6271,21 +6267,21 @@ msgstr "" "aygıtı sonra ekleyin; Diskler sekmesindeki PCIe yuvaları ekle, sonraki " "başlatmadan itibaren ona boş yuvalar verir." -#: instances/views.py:2062 instances/views.py:2068 +#: instances/views.py:2061 instances/views.py:2067 msgid "The VM has it" msgstr "Sanal makinede var" -#: instances/views.py:2099 +#: instances/views.py:2098 #, python-format msgid "The host has no USB device %(device)s" msgstr "Sunucuda %(device)s USB aygıtı yok" -#: instances/views.py:2120 +#: instances/views.py:2119 #, python-format msgid "The host has no PCI device %(device)s" msgstr "Sunucuda %(device)s PCI aygıtı yok" -#: instances/views.py:2138 +#: instances/views.py:2137 #, python-format msgid "" "Removal of PCI device %(address)s requested: the guest has not let it go yet;" @@ -6295,20 +6291,20 @@ msgstr "" "bırakmadı; bırakana ya da sanal makine durana kadar çalışan sanal makinede " "kalır." -#: instances/views.py:2183 instances/views.py:2213 +#: instances/views.py:2182 instances/views.py:2212 msgid "Select a network interface and a QoS direction" msgstr "Bir ağ arabirimi ve bir QoS yönü seçin" -#: instances/views.py:2186 vrtManager/network.py:459 +#: instances/views.py:2185 vrtManager/network.py:454 msgid "QoS rates must be whole numbers" msgstr "QoS hızları tam sayı olmalıdır" -#: instances/views.py:2193 networks/views.py:229 +#: instances/views.py:2192 networks/views.py:229 #, python-format msgid "%(qos_dir)s QoS is set" msgstr "%(qos_dir)s QoS ayarlandı" -#: instances/views.py:2198 +#: instances/views.py:2197 #, python-format msgid "" "%(qos_dir)s QoS is set. A running VM gets it after it is powered off and on." @@ -6316,12 +6312,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:2220 networks/views.py:255 +#: instances/views.py:2219 networks/views.py:255 #, python-format msgid "%(qos_dir)s QoS is deleted" msgstr "%(qos_dir)s QoS silindi" -#: instances/views.py:2225 +#: instances/views.py:2224 #, python-format msgid "" "%(qos_dir)s QoS is deleted. A running VM keeps the old limit until it is " @@ -6330,21 +6326,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:2253 +#: instances/views.py:2252 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:2255 +#: instances/views.py:2254 #, python-format msgid "%(user)s is already an owner" msgstr "%(user)s zaten bir sahip" -#: instances/views.py:2300 +#: instances/views.py:2299 #, python-format msgid "Console settings were not saved: %(errors)s" msgstr "Konsol ayarları kaydedilmedi: %(errors)s" -#: instances/views.py:2322 +#: instances/views.py:2321 msgid "" "Error setting console password. You should check that your instance have an " "graphic device." @@ -6352,65 +6348,57 @@ msgstr "" "Konsol parolası ayarlanırken hata oluştu. Sanal makinenin bir grafik aygıtına" " sahip olduğundan emin olunuz." -#: instances/views.py:2369 +#: instances/views.py:2368 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:2375 +#: instances/views.py:2374 #, python-format msgid "%(quota)s: '%(instance_name)s' stays a template." msgstr "%(quota)s: '%(instance_name)s' şablon olarak kalıyor." -#: instances/views.py:2457 +#: instances/views.py:2456 msgid "The XML has no name" msgstr "XML'de ad yok" -#: instances/views.py:2471 webvirtcloud/middleware.py:126 +#: instances/views.py:2470 webvirtcloud/middleware.py:126 #, python-format msgid "libvirt Error - %(exception)s" msgstr "libvirt Hatası - %(exception)s" -#: instances/views.py:2478 +#: instances/views.py:2477 msgid "An empty disk of the size you set" msgstr "Belirlediğiniz boyutta boş bir disk" -#: instances/views.py:2479 +#: instances/views.py:2478 msgid "Volumes already in a pool" msgstr "Bir havuzda zaten bulunan birimler" -#: instances/views.py:2480 +#: instances/views.py:2479 msgid "A copy of a template volume" msgstr "Bir şablon biriminin kopyası" -#: instances/views.py:2569 +#: instances/views.py:2568 msgid "You haven't defined any storage pools" msgstr "Hiç bir depolama havuzu tanımlamadınız" -#: instances/views.py:2571 +#: instances/views.py:2570 msgid "You haven't defined any network pools" msgstr "Hiç bir ağ havuzu tanımlamadınız" -#: instances/views.py:2634 +#: instances/views.py:2633 msgid "Flavor Created" msgstr "Flavor Oluşturuldu" -#: instances/views.py:2642 +#: instances/views.py:2641 msgid "Create Flavor" msgstr "Kullanıcı Oluştur" -#: instances/views.py:2657 -msgid "Flavor Updated" -msgstr "Flavor Güncellendi" - -#: instances/views.py:2663 -msgid "Update Flavor" -msgstr "Flavor Güncelle" - -#: instances/views.py:2675 +#: instances/views.py:2653 msgid "Flavor Deleted" msgstr "Flavor Silindi" -#: instances/views.py:2681 +#: instances/views.py:2659 msgid "Only the size template goes; VMs made from it keep their size." msgstr "" "Yalnızca boyut şablonu silinir; ondan oluşturulan sanal makineler boyutlarını" @@ -8881,23 +8869,23 @@ msgstr "" "Eski değerin yerini hemen alır; bir parolanın şifrelediği veriler yeniden " "şifrelenmez." -#: vrtManager/connection.py:51 +#: vrtManager/connection.py:46 msgid "Connection closed (error)" msgstr "Bağlantı kapandı (hata)" -#: vrtManager/connection.py:52 +#: vrtManager/connection.py:47 msgid "Connection closed (end of file)" msgstr "Bağlantı kapandı (dosya sonu)" -#: vrtManager/connection.py:53 +#: vrtManager/connection.py:48 msgid "Connection closed (keepalive timeout)" msgstr "Bağlantı kapandı (canlı tutma zaman aşımı)" -#: vrtManager/connection.py:54 +#: vrtManager/connection.py:49 msgid "Connection closed (client closed)" msgstr "Bağlantı kapandı (istemci kapattı)" -#: vrtManager/connection.py:147 +#: vrtManager/connection.py:142 #, python-format msgid "" "Connection Failed: %(host)s does not answer: %(requests)s requests still wait" @@ -8906,26 +8894,26 @@ msgstr "" "Bağlantı başarısız: %(host)s yanıt vermiyor: %(requests)s istek hâlâ onu " "bekliyor" -#: vrtManager/connection.py:219 +#: vrtManager/connection.py:214 #, 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:230 +#: vrtManager/connection.py:225 msgid "the connection closed right after opening" msgstr "bağlantı açıldıktan hemen sonra kapandı" -#: vrtManager/connection.py:243 +#: vrtManager/connection.py:238 #, python-format msgid "Connection Failed: %(error)s" msgstr "Bağlantı başarısız: %(error)s" -#: vrtManager/connection.py:312 +#: vrtManager/connection.py:307 #, python-format msgid "Connection closed (%(reason)s)" msgstr "Bağlantı kapandı (%(reason)s)" -#: vrtManager/connection.py:455 +#: vrtManager/connection.py:450 #, python-format msgid "Connection Failed: %(host)s is not connected" msgstr "Bağlantı başarısız: %(host)s bağlı değil" @@ -9574,108 +9562,108 @@ msgstr "" "%(net)s ağı kayıtlı olandan farklı adreslerle çalışıyor; önce durdurup " "başlatın" -#: vrtManager/network.py:339 +#: vrtManager/network.py:334 #, python-format msgid "Network %(net)s has no such address" msgstr "%(net)s ağında böyle bir adres yok" -#: vrtManager/network.py:344 +#: vrtManager/network.py:339 #, python-format msgid "The range start %(address)s is not in %(subnet)s" msgstr "Aralık başlangıcı %(address)s, %(subnet)s içinde değil" -#: vrtManager/network.py:345 +#: vrtManager/network.py:340 #, python-format msgid "The range start %(address)s is not in the network" msgstr "Aralık başlangıcı %(address)s ağın içinde değil" -#: vrtManager/network.py:346 +#: vrtManager/network.py:341 #, python-format msgid "The range end %(address)s is not in %(subnet)s" msgstr "Aralık sonu %(address)s, %(subnet)s içinde değil" -#: vrtManager/network.py:347 +#: vrtManager/network.py:342 #, python-format msgid "The range end %(address)s is not in the network" msgstr "Aralık sonu %(address)s ağın içinde değil" -#: vrtManager/network.py:348 +#: vrtManager/network.py:343 #, python-format msgid "The fixed address %(address)s is not in %(subnet)s" msgstr "Sabit adres %(address)s, %(subnet)s içinde değil" -#: vrtManager/network.py:349 +#: vrtManager/network.py:344 #, python-format msgid "The fixed address %(address)s is not in the network" msgstr "Sabit adres %(address)s ağın içinde değil" -#: vrtManager/network.py:358 +#: vrtManager/network.py:353 #, python-format msgid "%(address)s is not an IP address" msgstr "%(address)s bir IP adresi değil" -#: vrtManager/network.py:363 +#: vrtManager/network.py:358 #, python-format msgid "%(address)s is the host's own address on the network" msgstr "%(address)s sunucunun bu ağdaki kendi adresi" -#: vrtManager/network.py:369 +#: vrtManager/network.py:364 #, python-format msgid "Stop network %(net)s to change its DHCP range" msgstr "DHCP aralığını değiştirmek için %(net)s ağını durdurun" -#: vrtManager/network.py:373 +#: vrtManager/network.py:368 #, python-format msgid "This address of network %(net)s has no DHCP range" msgstr "%(net)s ağının bu adresinin DHCP aralığı yok" -#: vrtManager/network.py:377 +#: vrtManager/network.py:372 #, python-format msgid "The range starts at %(start)s, after its end %(end)s" msgstr "" "Aralık, sonu olan %(end)s adresinden sonra, %(start)s adresinde başlıyor" -#: vrtManager/network.py:379 +#: vrtManager/network.py:374 #, python-format msgid "The range takes in %(address)s, the host's own address" msgstr "Aralık, sunucunun kendi adresi olan %(address)s adresini içeriyor" -#: vrtManager/network.py:388 +#: vrtManager/network.py:383 #, python-format msgid "Network %(net)s has no fixed address %(address)s" msgstr "%(net)s ağında %(address)s sabit adresi yok" -#: vrtManager/network.py:410 +#: vrtManager/network.py:405 #, python-format msgid "The fixed address %(original)s is gone meanwhile; reload the page" msgstr "" "%(original)s sabit adresi bu arada kaldırılmış; sayfayı yeniden yükleyin" -#: vrtManager/network.py:415 +#: vrtManager/network.py:410 #, python-format msgid "%(address)s is another entry's fixed address" msgstr "%(address)s başka bir kaydın sabit adresi" -#: vrtManager/network.py:417 +#: vrtManager/network.py:412 #, python-format msgid "%(mac_duid)s has another fixed address, %(other)s" msgstr "%(mac_duid)s için başka bir sabit adres var: %(other)s" -#: vrtManager/network.py:419 +#: vrtManager/network.py:414 #, python-format msgid "The name %(name)s has another fixed address, %(other)s" msgstr "%(name)s adı için başka bir sabit adres var: %(other)s" -#: vrtManager/network.py:455 +#: vrtManager/network.py:450 msgid "Direction must be inbound or outbound" msgstr "Yön gelen ya da giden olmalı" -#: vrtManager/network.py:482 +#: vrtManager/network.py:477 #, python-format msgid "The XML must define network %(net)s" msgstr "XML, %(net)s ağını tanımlamalıdır" -#: vrtManager/network.py:484 +#: vrtManager/network.py:479 msgid "The XML must keep the network's UUID" msgstr "XML, ağın UUID değerini korumalıdır" @@ -9912,7 +9900,7 @@ msgstr "" "%(vms)s sanal makinelerinin %(name)s havuzunda adıyla bağlı diskleri var ve " "artık başlamaz; önce bu diskleri ayırın" -#: vrtManager/storage.py:279 +#: vrtManager/storage.py:270 #, python-format msgid "" "Volume %(name)s is in use: a VM's disk, a backing file or a snapshot's file" @@ -9920,12 +9908,12 @@ msgstr "" "%(name)s birimi kullanımda: bir sanal makinenin diski, bir temel (backing) " "dosya ya da bir anlık görüntünün dosyası" -#: vrtManager/util.py:145 +#: vrtManager/util.py:95 #, python-format msgid "The XML is not valid: %(err)s" msgstr "XML geçerli değil: %(err)s" -#: vrtManager/util.py:147 +#: vrtManager/util.py:97 msgid "The XML may not declare a DTD" msgstr "XML bir DTD bildiremez" diff --git a/locale/zh/LC_MESSAGES/django.mo b/locale/zh/LC_MESSAGES/django.mo index f761599c..38965e94 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 937295e8..da98c7b6 100644 --- a/locale/zh/LC_MESSAGES/django.po +++ b/locale/zh/LC_MESSAGES/django.po @@ -199,7 +199,7 @@ msgid "User sections" msgstr "用户页面导航" #: accounts/templates/account.html:44 accounts/templates/account.html:52 -#: admin/forms.py:189 computes/templates/computes/list.html:30 +#: admin/forms.py:185 computes/templates/computes/list.html:30 #: computes/templates/computes/list.html:57 computes/templates/overview.html:46 msgid "VMs" msgstr "虚拟机" @@ -687,12 +687,12 @@ msgstr "权限" msgid "Groups" msgstr "用户组" -#: admin/forms.py:143 +#: admin/forms.py:139 #, python-format msgid "NEW_USER_DEFAULT_INSTANCES: %(name)s is not exactly one VM" msgstr "NEW_USER_DEFAULT_INSTANCES:%(name)s 不是唯一的一台虚拟机" -#: admin/forms.py:190 computes/templates/computes/list.html:58 +#: admin/forms.py:186 computes/templates/computes/list.html:58 #: computes/templates/overview.html:58 instances/forms.py:15 #: instances/templates/allinstances_index_grouped.html:16 #: instances/templates/allinstances_index_nongrouped.html:14 @@ -702,7 +702,7 @@ msgstr "NEW_USER_DEFAULT_INSTANCES:%(name)s 不是唯一的一台虚拟机" msgid "vCPUs" msgstr "vCPU" -#: admin/forms.py:191 computes/templates/computes/instances.html:49 +#: admin/forms.py:187 computes/templates/computes/instances.html:49 #: computes/templates/computes/list.html:59 computes/templates/overview.html:66 #: computes/templates/overview.html:150 #: instances/templates/allinstances_index_grouped.html:17 @@ -714,34 +714,34 @@ msgstr "vCPU" msgid "Memory" msgstr "内存" -#: admin/forms.py:192 instances/models.py:237 +#: admin/forms.py:188 instances/models.py:237 #: instances/templates/create_instance_w2.html:118 #: instances/templates/instances/settings_tab.html:25 #: instances/templates/instances/stats_tab.html:51 msgid "Disk" msgstr "磁盘" -#: admin/forms.py:202 +#: admin/forms.py:198 msgid "No limit" msgstr "不限" -#: admin/forms.py:218 +#: admin/forms.py:214 msgid "Enter a limit or choose No limit." msgstr "请输入限制值,或选择“不限”。" -#: admin/forms.py:230 +#: admin/forms.py:226 msgid "The user must change it at their next login" msgstr "用户必须在下次登录时修改密码" -#: admin/forms.py:236 +#: admin/forms.py:232 msgid "With a password" msgstr "使用密码" -#: admin/forms.py:236 +#: admin/forms.py:232 msgid "Without a password" msgstr "不使用密码" -#: admin/forms.py:242 +#: admin/forms.py:238 msgid "A user without a password cannot be made to change it" msgstr "没有密码的用户无法被要求修改密码" @@ -895,7 +895,7 @@ msgid "IP" msgstr "IP" #: admin/templates/admin/logs.html:56 admin/views.py:286 instances/states.py:19 -#: instances/views.py:415 instances/views.py:417 logs/views.py:17 +#: instances/views.py:414 instances/views.py:416 logs/views.py:17 msgid "Unknown" msgstr "未知" @@ -2279,25 +2279,21 @@ msgstr "客户机架构" msgid "Emulator" msgstr "模拟器" -#: computes/validators.py:25 +#: computes/validators.py:24 msgid "Enter an IPv4 address or a host name, without a scheme, port or path" msgstr "请输入 IPv4 地址或主机名,不带协议、端口或路径" -#: computes/validators.py:36 +#: computes/validators.py:35 msgid "" "The login may contain only letters, digits, '.', '_' and '-', and may not " "start with '-'" msgstr "登录名只能包含字母、数字、'.'、'_' 和 '-',且不能以 '-' 开头" -#: computes/validators.py:42 -msgid "The name must not contain any special characters" -msgstr "名称不能包含任何特殊字符" - -#: computes/validators.py:53 +#: computes/validators.py:47 msgid "Enter an IP address or a host name, without a scheme or port" msgstr "请输入 IP 地址或主机名,不带协议或端口" -#: computes/validators.py:60 +#: computes/validators.py:54 msgid "" "Enter the 64 hexadecimal characters of GSTFSD_KEY in the host's " "/etc/default/webvirt-gstfsd" @@ -2819,7 +2815,7 @@ msgstr "磁盘已复制,但无法定义克隆:%(error)s;请检查这些卷 msgid "Create VM" msgstr "创建虚拟机" -#: instances/jobs.py:773 instances/jobs.py:818 instances/views.py:2459 +#: instances/jobs.py:773 instances/jobs.py:818 instances/views.py:2458 msgid "A virtual machine with this name already exists" msgstr "同名虚拟机已存在" @@ -3207,7 +3203,7 @@ msgid "Disk source" msgstr "磁盘来源" #: instances/templates/add_instance_volume.html:21 -#: instances/templates/create_instance_w2.html:134 instances/views.py:2478 +#: instances/templates/create_instance_w2.html:134 instances/views.py:2477 msgid "New disk" msgstr "新磁盘" @@ -3571,7 +3567,7 @@ msgstr "自定义 CPU 型号" msgid "Size (GiB)" msgstr "大小(GiB)" -#: instances/templates/create_instance_w2.html:161 instances/views.py:2479 +#: instances/templates/create_instance_w2.html:161 instances/views.py:2478 msgid "Existing volumes" msgstr "已有卷" @@ -3607,7 +3603,7 @@ msgstr "设备" msgid "Remove" msgstr "移除" -#: instances/templates/create_instance_w2.html:194 instances/views.py:2480 +#: instances/templates/create_instance_w2.html:194 instances/views.py:2479 msgid "Clone from template" msgstr "从模板克隆" @@ -5613,58 +5609,58 @@ msgstr "无效的 MAC 地址" msgid "More MAC addresses than networks" msgstr "MAC 地址数量多于网络数量" -#: instances/views.py:169 +#: instances/views.py:168 msgid "Enter an IP address, a network such as 192.0.2.0/24, or a MAC address." msgstr "请输入 IP 地址、网络(如 192.0.2.0/24)或 MAC 地址。" -#: instances/views.py:175 instances/views.py:209 +#: instances/views.py:174 instances/views.py:208 msgid "Too many searches are still running; try again shortly." msgstr "仍在运行的搜索过多;请稍后再试。" -#: instances/views.py:257 +#: instances/views.py:256 #, python-format msgid "The host %(host)s of '%(name)s' cannot be reached: %(error)s" msgstr "无法连接“%(name)s”所在的主机 %(host)s:%(error)s" -#: instances/views.py:263 +#: instances/views.py:262 #, python-format msgid "The host of '%(name)s' cannot be reached right now." msgstr "目前无法连接“%(name)s”所在的主机。" -#: instances/views.py:264 +#: instances/views.py:263 msgid " Jobs on it can be followed under Jobs in the menu." msgstr " 其上的任务可在菜单的“任务”中跟踪。" -#: instances/views.py:272 +#: instances/views.py:271 #, python-format msgid "'%(name)s' is no longer on its host." msgstr "“%(name)s”已不在其主机上。" -#: instances/views.py:370 +#: instances/views.py:369 msgid "There is no other host to migrate to." msgstr "没有其他可迁移到的主机。" -#: instances/views.py:372 +#: instances/views.py:371 msgid "A VM migrates when it is running, paused or shut off." msgstr "虚拟机在运行、暂停或关机状态下均可迁移。" -#: instances/views.py:374 +#: instances/views.py:373 msgid "" "A VM with snapshots cannot be migrated: its snapshots stay on this host. " "Delete them first." msgstr "有快照的虚拟机无法迁移:其快照保留在本主机上。请先删除快照。" -#: instances/views.py:376 +#: instances/views.py:375 msgid "" "A VM with host devices cannot be migrated: the destination may not have them." " Remove them first." msgstr "有主机设备的虚拟机无法迁移:目标主机可能没有这些设备。请先移除它们。" -#: instances/views.py:640 +#: instances/views.py:639 msgid "The VM was moved meanwhile; try again." msgstr "该虚拟机在此期间已被移动;请重试。" -#: instances/views.py:756 +#: instances/views.py:755 msgid "" "The running VM has no free PCI slot for another disk on this bus: choose the " "scsi bus if the VM has a SCSI controller, or shut the VM down and add the " @@ -5674,7 +5670,7 @@ msgstr "" "运行中的虚拟机在此总线上没有可用 PCI 插槽来添加磁盘:如果虚拟机有 SCSI 控制器,请选择 scsi " "总线;或关闭虚拟机后再添加磁盘。“磁盘”选项卡上的“添加 PCIe 插槽”可使其从下次启动起获得可用插槽。新卷会保留在其存储池中,可作为现有卷挂载。" -#: instances/views.py:760 +#: instances/views.py:759 msgid "" "The running VM has no free PCI slot for the SCSI controller the disk needs: " "shut the VM down and add the disk then; Add PCIe slots on the Disks tab gives" @@ -5684,262 +5680,262 @@ msgstr "" "运行中的虚拟机没有可用 PCI 插槽来添加磁盘所需的 SCSI 控制器:请关闭虚拟机后再添加磁盘。“磁盘”选项卡上的“添加 PCIe " "插槽”可使其从下次启动起获得可用插槽。新卷会保留在其存储池中,可作为现有卷挂载。" -#: instances/views.py:778 +#: instances/views.py:777 #, python-format msgid "Invalid disk options: %(options)s" msgstr "无效的磁盘选项:%(options)s" -#: instances/views.py:788 instances/views.py:803 +#: instances/views.py:787 instances/views.py:802 msgid "Templates cannot be started." msgstr "模板无法启动。" -#: instances/views.py:995 +#: instances/views.py:994 #, python-format msgid "Set the gstfsd key of %(compute)s first (Computes, edit the host)" msgstr "请先设置 %(compute)s 的 gstfsd 密钥(计算节点,编辑该主机)" -#: instances/views.py:1002 instances/views.py:1020 instances/views.py:1029 +#: instances/views.py:1001 instances/views.py:1019 instances/views.py:1028 #, python-format msgid "gstfsd error: %(err)s" msgstr "gstfsd 错误:%(err)s" -#: instances/views.py:1030 +#: instances/views.py:1029 msgid "the reply is not signed with the key" msgstr "回复未使用该密钥签名" -#: instances/views.py:1038 +#: instances/views.py:1037 msgid "Shut the VM down, or start its QEMU guest agent, and try again" msgstr "请关闭虚拟机,或启动其 QEMU 客户机代理,然后重试" -#: instances/views.py:1051 +#: instances/views.py:1050 msgid "The change may still be made when the agent answers again." msgstr "当代理再次响应时,此更改仍可能生效。" -#: instances/views.py:1079 +#: instances/views.py:1078 msgid "Reset root password" msgstr "重置 root 密码" -#: instances/views.py:1083 +#: instances/views.py:1082 msgid "Enter a password" msgstr "请输入密码" -#: instances/views.py:1097 +#: instances/views.py:1096 msgid "Select an SSH public key" msgstr "请选择 SSH 公钥" -#: instances/views.py:1119 +#: instances/views.py:1118 #, python-format msgid "Installed new SSH public key %(keyname)s" msgstr "已安装新的 SSH 公钥 %(keyname)s" -#: instances/views.py:1139 +#: instances/views.py:1138 msgid "Enter a whole number of vCPUs" msgstr "请输入整数个 vCPU" -#: instances/views.py:1143 +#: instances/views.py:1142 msgid "Shut off the VM to change its vCPUs" msgstr "请关闭虚拟机以更改其 vCPU" -#: instances/views.py:1146 +#: instances/views.py:1145 msgid "The current vCPUs cannot be more than the maximum" msgstr "当前 vCPU 数不能超过最大值" -#: instances/views.py:1153 +#: instances/views.py:1152 #, python-format msgid "%(quota)s: cannot resize the CPU of '%(instance_name)s'." msgstr "%(quota)s:无法调整“%(instance_name)s”的 CPU。" -#: instances/views.py:1161 +#: instances/views.py:1160 #, python-format msgid "vCPUs set to %(cur)s (maximum %(max)s)" msgstr "vCPU 已设为 %(cur)s(最大 %(max)s)" -#: instances/views.py:1180 +#: instances/views.py:1179 msgid "Enter a whole number for memory" msgstr "请输入整数内存值" -#: instances/views.py:1183 +#: instances/views.py:1182 msgid "The current memory cannot be more than the maximum" msgstr "当前内存不能超过最大值" -#: instances/views.py:1187 +#: instances/views.py:1186 #, python-format msgid "%(quota)s: cannot resize the memory of '%(instance_name)s'." msgstr "%(quota)s:无法调整“%(instance_name)s”的内存。" -#: instances/views.py:1193 +#: instances/views.py:1192 #, python-format msgid "Memory set to %(cur)s MiB (maximum %(max)s MiB)" msgstr "内存已设为 %(cur)s MiB(最大 %(max)s MiB)" -#: instances/views.py:1213 +#: instances/views.py:1212 msgid "Enter disk sizes as whole GiB" msgstr "请以整数 GiB 输入磁盘大小" -#: instances/views.py:1217 +#: instances/views.py:1216 #, python-format msgid "%(dev)s is %(size)s: a disk cannot shrink" msgstr "%(dev)s 为 %(size)s:磁盘不能缩小" -#: instances/views.py:1225 +#: instances/views.py:1224 msgid "No disks were selected or valid for resizing." msgstr "未选择磁盘或没有可调整大小的有效磁盘。" -#: instances/views.py:1234 +#: instances/views.py:1233 #, python-format msgid "%(quota)s: cannot resize the disks of '%(instance_name)s'." msgstr "%(quota)s:无法调整“%(instance_name)s”的磁盘。" -#: instances/views.py:1246 +#: instances/views.py:1245 #, python-format msgid "The storage pool of %(dev)s cannot resize its volumes" msgstr "%(dev)s 所在的存储池无法调整其卷的大小" -#: instances/views.py:1248 +#: instances/views.py:1247 #, python-format msgid "Disk is resized: %(dev)s" msgstr "磁盘已调整大小:%(dev)s" -#: instances/views.py:1342 +#: instances/views.py:1341 msgid "The VM's machine has no PCIe slots to add" msgstr "该虚拟机的机器类型没有可添加的 PCIe 插槽" -#: instances/views.py:1347 +#: instances/views.py:1346 #, python-format msgid "%(count)s PCIe slots added" msgstr "已添加 %(count)s 个 PCIe 插槽" -#: instances/views.py:1349 +#: instances/views.py:1348 #, python-format msgid "%(count)s PCIe slots added: the VM gets them at its next start" msgstr "已添加 %(count)s 个 PCIe 插槽:虚拟机在下次启动时获得它们" -#: instances/views.py:1395 +#: instances/views.py:1394 #, python-format msgid "%(volume)s is already a disk of this VM" msgstr "%(volume)s 已是此虚拟机的磁盘" -#: instances/views.py:1485 +#: instances/views.py:1484 msgid "Volume changes are applied. But it will be activated after shutdown" msgstr "卷更改已应用,但将在关机后生效" -#: instances/views.py:1490 +#: instances/views.py:1489 msgid "Volume is changed successfully." msgstr "卷已成功更改。" -#: instances/views.py:1508 +#: instances/views.py:1507 #, python-format msgid "Disk %(dev)s is not a storage volume of this instance" msgstr "磁盘 %(dev)s 不是此虚拟机的存储卷" -#: instances/views.py:1515 +#: instances/views.py:1514 #, python-format msgid "Disk %(dev)s has a pending change; delete it once the VM is shut down" msgstr "磁盘 %(dev)s 有待生效的更改;请在虚拟机关机后删除它" -#: instances/views.py:1530 +#: instances/views.py:1529 #, python-format msgid "Volume %(vol)s is used by another VM; detach it instead" msgstr "卷 %(vol)s 正被另一台虚拟机使用;请改为分离它" -#: instances/views.py:1542 +#: instances/views.py:1541 #, python-format msgid "" "The guest has not released disk %(dev)s yet; volume %(vol)s was kept. Delete " "it from the storage pool once the VM is shut down." msgstr "客户机尚未释放磁盘 %(dev)s;卷 %(vol)s 已保留。请在虚拟机关机后从存储池中删除它。" -#: instances/views.py:1553 +#: instances/views.py:1552 #, python-format msgid "Disk %(dev)s was detached, but its volume was kept: %(err)s" msgstr "磁盘 %(dev)s 已分离,但其卷已保留:%(err)s" -#: instances/views.py:1579 +#: instances/views.py:1578 #, python-format msgid "This VM cannot take a CD-ROM on the %(bus)s bus now" msgstr "该虚拟机现在无法在 %(bus)s 总线上添加 CD-ROM" -#: instances/views.py:1582 +#: instances/views.py:1581 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:1587 +#: instances/views.py:1586 #, python-format msgid "%(image)s is already in a CD-ROM of this VM" msgstr "%(image)s 已在此虚拟机的某个光驱中" -#: instances/views.py:1668 +#: instances/views.py:1667 #, python-format msgid "Pool %(pool)s was not read again: %(err)s" msgstr "未重新读取存储池 %(pool)s:%(err)s" -#: instances/views.py:1689 +#: instances/views.py:1688 #, python-format msgid "Snapshot was not deleted: %(err)s" msgstr "快照未删除:%(err)s" -#: instances/views.py:1804 +#: instances/views.py:1803 msgid "Add at least one device to the boot order." msgstr "请至少向启动顺序中添加一个设备。" -#: instances/views.py:1818 +#: instances/views.py:1817 msgid "Boot order changed. It applies at the next start." msgstr "启动顺序已更改,将在下次启动时生效。" -#: instances/views.py:1820 +#: instances/views.py:1819 msgid "Boot order changed successfully." msgstr "启动顺序已成功更改。" -#: instances/views.py:1840 +#: instances/views.py:1839 msgid "The XML is empty" msgstr "XML 为空" -#: instances/views.py:1844 instances/views.py:2469 +#: instances/views.py:1843 instances/views.py:2468 #, python-format msgid "The XML is not well-formed: %(error)s" msgstr "XML 格式不正确:%(error)s" -#: instances/views.py:1846 +#: instances/views.py:1845 #, python-format msgid "The XML must keep the VM's UUID %(uuid)s." msgstr "XML 必须保留虚拟机的 UUID %(uuid)s。" -#: instances/views.py:1850 +#: instances/views.py:1849 msgid "" "The definition has changed since the editor was opened. Reload the page to " "edit the current one." msgstr "自打开编辑器以来定义已被更改。请重新加载页面以编辑当前定义。" -#: instances/views.py:1862 +#: instances/views.py:1861 msgid "The XML definition was saved." msgstr "XML 定义已保存。" -#: instances/views.py:1864 +#: instances/views.py:1863 msgid "The XML definition was saved; the VM uses it from its next start." msgstr "XML 定义已保存;虚拟机从下次启动起使用它。" -#: instances/views.py:1945 +#: instances/views.py:1944 msgid "Select one network interface to change" msgstr "请选择一个要更改的网络接口" -#: instances/views.py:1983 +#: instances/views.py:1982 msgid "Network Device Config is changed. Please shutdown instance to activate." msgstr "网络设备配置已更改。请关闭虚拟机以使其生效。" -#: instances/views.py:1985 +#: instances/views.py:1984 msgid "Network device changed" msgstr "网络设备已更改" -#: instances/views.py:1997 +#: instances/views.py:1996 msgid "No network selected" msgstr "未选择网络" -#: instances/views.py:2002 +#: instances/views.py:2001 #, python-format msgid "The VM already has a network device with MAC %(mac)s" msgstr "虚拟机已有 MAC 地址为 %(mac)s 的网络设备" -#: instances/views.py:2021 +#: instances/views.py:2020 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 " @@ -5947,137 +5943,129 @@ msgid "" msgstr "" "运行中的虚拟机没有可用 PCI 插槽来添加网络设备:请关机后再添加设备。“磁盘”选项卡上的“添加 PCIe 插槽”可使其从下次启动起获得可用插槽。" -#: instances/views.py:2062 instances/views.py:2068 +#: instances/views.py:2061 instances/views.py:2067 msgid "The VM has it" msgstr "虚拟机已有此设备" -#: instances/views.py:2099 +#: instances/views.py:2098 #, python-format msgid "The host has no USB device %(device)s" msgstr "主机上没有 USB 设备 %(device)s" -#: instances/views.py:2120 +#: instances/views.py:2119 #, python-format msgid "The host has no PCI device %(device)s" msgstr "主机上没有 PCI 设备 %(device)s" -#: instances/views.py:2138 +#: instances/views.py:2137 #, python-format msgid "" "Removal of PCI device %(address)s requested: the guest has not let it go yet;" " it stays in the running VM until it does or the VM stops." msgstr "已请求移除 PCI 设备 %(address)s:客户机尚未释放它;在客户机释放或虚拟机停止之前,它仍保留在运行中的虚拟机中。" -#: instances/views.py:2183 instances/views.py:2213 +#: instances/views.py:2182 instances/views.py:2212 msgid "Select a network interface and a QoS direction" msgstr "请选择网络接口和 QoS 方向" -#: instances/views.py:2186 vrtManager/network.py:459 +#: instances/views.py:2185 vrtManager/network.py:454 msgid "QoS rates must be whole numbers" msgstr "QoS 速率必须为整数" -#: instances/views.py:2193 networks/views.py:229 +#: instances/views.py:2192 networks/views.py:229 #, python-format msgid "%(qos_dir)s QoS is set" msgstr "%(qos_dir)s QoS 已设置" -#: instances/views.py:2198 +#: instances/views.py:2197 #, 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:2220 networks/views.py:255 +#: instances/views.py:2219 networks/views.py:255 #, python-format msgid "%(qos_dir)s QoS is deleted" msgstr "%(qos_dir)s QoS 已删除" -#: instances/views.py:2225 +#: instances/views.py:2224 #, 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:2253 +#: instances/views.py:2252 msgid "Only one owner is allowed and the one already added" msgstr "只允许一个所有者,且已添加" -#: instances/views.py:2255 +#: instances/views.py:2254 #, python-format msgid "%(user)s is already an owner" msgstr "%(user)s 已是所有者" -#: instances/views.py:2300 +#: instances/views.py:2299 #, python-format msgid "Console settings were not saved: %(errors)s" msgstr "控制台设置未保存:%(errors)s" -#: instances/views.py:2322 +#: instances/views.py:2321 msgid "" "Error setting console password. You should check that your instance have an " "graphic device." msgstr "设置控制台密码出错。请检查虚拟机是否有图形设备。" -#: instances/views.py:2369 +#: instances/views.py:2368 msgid "Shut the VM down to change whether it is a template." msgstr "请关闭虚拟机以更改其是否为模板。" -#: instances/views.py:2375 +#: instances/views.py:2374 #, python-format msgid "%(quota)s: '%(instance_name)s' stays a template." msgstr "%(quota)s:“%(instance_name)s”仍为模板。" -#: instances/views.py:2457 +#: instances/views.py:2456 msgid "The XML has no name" msgstr "XML 中没有名称" -#: instances/views.py:2471 webvirtcloud/middleware.py:126 +#: instances/views.py:2470 webvirtcloud/middleware.py:126 #, python-format msgid "libvirt Error - %(exception)s" msgstr "libvirt 错误 - %(exception)s" -#: instances/views.py:2478 +#: instances/views.py:2477 msgid "An empty disk of the size you set" msgstr "按设定大小创建的空磁盘" -#: instances/views.py:2479 +#: instances/views.py:2478 msgid "Volumes already in a pool" msgstr "存储池中已有的卷" -#: instances/views.py:2480 +#: instances/views.py:2479 msgid "A copy of a template volume" msgstr "模板卷的副本" -#: instances/views.py:2569 +#: instances/views.py:2568 msgid "You haven't defined any storage pools" msgstr "您尚未定义任何存储池" -#: instances/views.py:2571 +#: instances/views.py:2570 msgid "You haven't defined any network pools" msgstr "您尚未定义任何网络池" -#: instances/views.py:2634 +#: instances/views.py:2633 msgid "Flavor Created" msgstr "规格已创建" -#: instances/views.py:2642 +#: instances/views.py:2641 msgid "Create Flavor" msgstr "创建规格" -#: instances/views.py:2657 -msgid "Flavor Updated" -msgstr "规格已更新" - -#: instances/views.py:2663 -msgid "Update Flavor" -msgstr "更新规格" - -#: instances/views.py:2675 +#: instances/views.py:2653 msgid "Flavor Deleted" msgstr "规格已删除" -#: instances/views.py:2681 +#: instances/views.py:2659 msgid "Only the size template goes; VMs made from it keep their size." msgstr "仅删除此规格;由它创建的虚拟机保持其大小。" @@ -8427,49 +8415,49 @@ msgid "" "encrypted anew." msgstr "新值会立即替换旧值;之前用口令加密的内容不会重新加密。" -#: vrtManager/connection.py:51 +#: vrtManager/connection.py:46 msgid "Connection closed (error)" msgstr "连接已关闭(错误)" -#: vrtManager/connection.py:52 +#: vrtManager/connection.py:47 msgid "Connection closed (end of file)" msgstr "连接已关闭(文件结束)" -#: vrtManager/connection.py:53 +#: vrtManager/connection.py:48 msgid "Connection closed (keepalive timeout)" msgstr "连接已关闭(保活超时)" -#: vrtManager/connection.py:54 +#: vrtManager/connection.py:49 msgid "Connection closed (client closed)" msgstr "连接已关闭(客户端已关闭)" -#: vrtManager/connection.py:147 +#: vrtManager/connection.py:142 #, 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:219 +#: vrtManager/connection.py:214 #, python-format msgid "Connection Failed: %(host)s did not answer within %(seconds)s s" msgstr "连接失败:%(host)s 在 %(seconds)s 秒内未响应" -#: vrtManager/connection.py:230 +#: vrtManager/connection.py:225 msgid "the connection closed right after opening" msgstr "连接在打开后立即关闭" -#: vrtManager/connection.py:243 +#: vrtManager/connection.py:238 #, python-format msgid "Connection Failed: %(error)s" msgstr "连接失败:%(error)s" -#: vrtManager/connection.py:312 +#: vrtManager/connection.py:307 #, python-format msgid "Connection closed (%(reason)s)" msgstr "连接已关闭(%(reason)s)" -#: vrtManager/connection.py:455 +#: vrtManager/connection.py:450 #, python-format msgid "Connection Failed: %(host)s is not connected" msgstr "连接失败:%(host)s 未连接" @@ -9035,106 +9023,106 @@ msgid "" "it first" msgstr "网络 %(net)s 运行时的地址与其保存的地址不同;请先停止再启动它" -#: vrtManager/network.py:339 +#: vrtManager/network.py:334 #, python-format msgid "Network %(net)s has no such address" msgstr "网络 %(net)s 没有此地址" -#: vrtManager/network.py:344 +#: vrtManager/network.py:339 #, python-format msgid "The range start %(address)s is not in %(subnet)s" msgstr "范围起始 %(address)s 不在 %(subnet)s 中" -#: vrtManager/network.py:345 +#: vrtManager/network.py:340 #, python-format msgid "The range start %(address)s is not in the network" msgstr "范围起始 %(address)s 不在网络中" -#: vrtManager/network.py:346 +#: vrtManager/network.py:341 #, python-format msgid "The range end %(address)s is not in %(subnet)s" msgstr "范围结束 %(address)s 不在 %(subnet)s 中" -#: vrtManager/network.py:347 +#: vrtManager/network.py:342 #, python-format msgid "The range end %(address)s is not in the network" msgstr "范围结束 %(address)s 不在网络中" -#: vrtManager/network.py:348 +#: vrtManager/network.py:343 #, python-format msgid "The fixed address %(address)s is not in %(subnet)s" msgstr "固定地址 %(address)s 不在 %(subnet)s 中" -#: vrtManager/network.py:349 +#: vrtManager/network.py:344 #, python-format msgid "The fixed address %(address)s is not in the network" msgstr "固定地址 %(address)s 不在网络中" -#: vrtManager/network.py:358 +#: vrtManager/network.py:353 #, python-format msgid "%(address)s is not an IP address" msgstr "%(address)s 不是 IP 地址" -#: vrtManager/network.py:363 +#: vrtManager/network.py:358 #, python-format msgid "%(address)s is the host's own address on the network" msgstr "%(address)s 是主机自己在该网络上的地址" -#: vrtManager/network.py:369 +#: vrtManager/network.py:364 #, python-format msgid "Stop network %(net)s to change its DHCP range" msgstr "请停止网络 %(net)s 后再更改其 DHCP 范围" -#: vrtManager/network.py:373 +#: vrtManager/network.py:368 #, python-format msgid "This address of network %(net)s has no DHCP range" msgstr "网络 %(net)s 的此地址没有 DHCP 范围" -#: vrtManager/network.py:377 +#: vrtManager/network.py:372 #, python-format msgid "The range starts at %(start)s, after its end %(end)s" msgstr "范围起始 %(start)s 在其结束 %(end)s 之后" -#: vrtManager/network.py:379 +#: vrtManager/network.py:374 #, python-format msgid "The range takes in %(address)s, the host's own address" msgstr "范围包含主机自己的地址 %(address)s" -#: vrtManager/network.py:388 +#: vrtManager/network.py:383 #, python-format msgid "Network %(net)s has no fixed address %(address)s" msgstr "网络 %(net)s 没有固定地址 %(address)s" -#: vrtManager/network.py:410 +#: vrtManager/network.py:405 #, python-format msgid "The fixed address %(original)s is gone meanwhile; reload the page" msgstr "固定地址 %(original)s 已不存在;请重新加载页面" -#: vrtManager/network.py:415 +#: vrtManager/network.py:410 #, python-format msgid "%(address)s is another entry's fixed address" msgstr "%(address)s 是另一条目的固定地址" -#: vrtManager/network.py:417 +#: vrtManager/network.py:412 #, python-format msgid "%(mac_duid)s has another fixed address, %(other)s" msgstr "%(mac_duid)s 已有另一个固定地址 %(other)s" -#: vrtManager/network.py:419 +#: vrtManager/network.py:414 #, python-format msgid "The name %(name)s has another fixed address, %(other)s" msgstr "名称 %(name)s 已有另一个固定地址 %(other)s" -#: vrtManager/network.py:455 +#: vrtManager/network.py:450 msgid "Direction must be inbound or outbound" msgstr "方向必须是入站或出站" -#: vrtManager/network.py:482 +#: vrtManager/network.py:477 #, python-format msgid "The XML must define network %(net)s" msgstr "XML 必须定义网络 %(net)s" -#: vrtManager/network.py:484 +#: vrtManager/network.py:479 msgid "The XML must keep the network's UUID" msgstr "XML 必须保留网络的 UUID" @@ -9357,18 +9345,18 @@ msgid "" "start; detach those disks first" msgstr "虚拟机 %(vms)s 通过名称使用存储池 %(name)s 中的磁盘,将无法再启动;请先分离这些磁盘" -#: vrtManager/storage.py:279 +#: vrtManager/storage.py:270 #, python-format msgid "" "Volume %(name)s is in use: a VM's disk, a backing file or a snapshot's file" msgstr "卷 %(name)s 正在使用中:它是虚拟机的磁盘、后备文件或快照文件" -#: vrtManager/util.py:145 +#: vrtManager/util.py:95 #, python-format msgid "The XML is not valid: %(err)s" msgstr "XML 无效:%(err)s" -#: vrtManager/util.py:147 +#: vrtManager/util.py:97 msgid "The XML may not declare a DTD" msgstr "XML 不能声明 DTD" diff --git a/networks/tests/test_network_changes.py b/networks/tests/test_network_changes.py index 877c2bcb..aab99ff1 100644 --- a/networks/tests/test_network_changes.py +++ b/networks/tests/test_network_changes.py @@ -65,7 +65,7 @@ class NetworkChangeTests(SimpleTestCase): # the running one for its addresses, the saved one for its limits and the XML editor net = self.network() with patch.object(net.net, "XMLDesc", wraps=net.net.XMLDesc) as xml: - net.get_ip_networks(), net.get_network_forward(), net.get_network_mac(), net.get_qos() + net.get_ip_networks(), net.get_network_mac(), net.get_qos() net.get_bridge_device(), net.get_mode(), net.saved_xml self.assertEqual(xml.call_count, 2) diff --git a/static/js/please_wait.js b/static/js/please_wait.js index 39aabe6b..c70bb64e 100644 --- a/static/js/please_wait.js +++ b/static/js/please_wait.js @@ -6,13 +6,6 @@ function showPleaseWaitDialog() { pleaseModal.show(); backgroundJobRunning = true; } -function hidePleaseWaitDialog() { - var pleaseModal = new bootstrap.Modal(document.getElementById('pleaseWaitDialog'), { - keyboard: false - }) - pleaseModal.hide(); - backgroundJobRunning = false; -} // a form marked data-please-wait shows the dialog while it is sent document.addEventListener("submit", function (event) { if (event.target.matches("form[data-please-wait]")) showPleaseWaitDialog(); diff --git a/vrtManager/connection.py b/vrtManager/connection.py index 91b14684..190803b0 100644 --- a/vrtManager/connection.py +++ b/vrtManager/connection.py @@ -3,8 +3,6 @@ import contextlib import io import logging import os -import re -import socket import threading import time import uuid @@ -23,9 +21,6 @@ CONN_SOCKET = 4 CONN_TLS = 3 CONN_SSH = 2 CONN_TCP = 1 -TLS_PORT = 16514 -SSH_PORT = 22 -TCP_PORT = 16509 # libvirt has no timeout for opening a connection: an unreachable host # blocks for the kernel's TCP connect timeout (about 2 minutes), a daemon @@ -457,34 +452,6 @@ class wvmConnectionManager(object): raise util.ConnectionFailed(error["text"], **error["values"]) return live - def host_is_up(self, conn_type, hostname, timeout=1): - """True if the libvirt endpoint of hostname accepts a TCP (or Unix - socket) connection. This is a reachability probe only: it does not - check credentials or libvirt itself. hostname may carry a port - ("host:port", "[v6]:port").""" - if conn_type == CONN_SOCKET: - sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) - try: - sock.settimeout(timeout) - sock.connect("/var/run/libvirt/libvirt-sock") - return True - except OSError: - return False - finally: - sock.close() - default_port = {CONN_SSH: SSH_PORT, CONN_TCP: TCP_PORT, CONN_TLS: TLS_PORT}.get(conn_type) - if default_port is None: - return False - host, port = str(hostname), default_port - match = re.fullmatch(r"\[?([^\[\]]+?)\]?:(\d+)", host) - if match and (host.startswith("[") or host.count(":") == 1): - host, port = match.group(1), int(match.group(2)) - try: - with socket.create_connection((host.strip("[]"), port), timeout=timeout): - return True - except OSError: - return False - connection_manager = wvmConnectionManager( settings.LIBVIRT_KEEPALIVE_INTERVAL if hasattr(settings, "LIBVIRT_KEEPALIVE_INTERVAL") else 5, settings.LIBVIRT_KEEPALIVE_COUNT if hasattr(settings, "LIBVIRT_KEEPALIVE_COUNT") else 5, @@ -633,12 +600,6 @@ class wvmConnect(object): release = ver return f"{major}.{minor}.{release}" - def is_kvm_supported(self): - """ - :return: kvm support or not - """ - return util.is_kvm_available(self.get_cap_xml()) - def get_storages(self, only_actives=False): """ :return: list of active or all storages @@ -776,21 +737,6 @@ class wvmConnect(object): return util.get_xml_path(self.get_cap_xml(), func=machines) - def get_emulators(self): - """ - :return: host emulators list - """ - - def emulators(ctx): - result = {} - for arch in ctx.xpath("/capabilities/guest/arch"): - emulator = arch.xpath("emulator") - arch_name = arch.xpath("@name")[0] - result[arch_name] = emulator - return result - - return util.get_xml_path(self.get_cap_xml(), func=emulators) - def get_os_loaders(self, arch="x86_64", machine="pc"): """ :param arch: architecture @@ -922,12 +868,6 @@ class wvmConnect(object): """ return ["raw", "qcow", "qcow2"] - def get_file_extensions(self): - """ - :return: available image filename extensions - """ - return ["img", "qcow", "qcow2"] - def get_video_models(self, arch, machine): """ :param arch: architecture @@ -1105,15 +1045,6 @@ class wvmConnect(object): def get_network(self, net): return self.wvm.networkLookupByName(net) - def get_network_forward(self, net_name): - def get_forward(doc): - forward_mode = util.get_xpath(doc, "/network/forward/@mode") - return forward_mode or "isolated" - - net = self.get_network(net_name) - xml = net.XMLDesc(0) - return util.get_xml_path(xml, func=get_forward) - def get_nwfilter(self, name): return self.wvm.nwfilterLookupByName(name) @@ -1229,18 +1160,6 @@ class wvmConnect(object): paths += [v for v in (source.get("file"), source.get("dev"), source.get("name")) if v] return paths - def get_snapshots(self): - instance = [] - for snap_id in self.wvm.listDomainsID(): - dom = self.wvm.lookupByID(int(snap_id)) - if dom.snapshotNum(0) != 0: - instance.append(dom.name()) - for name in self.wvm.listDefinedDomains(): - dom = self.wvm.lookupByName(name) - if dom.snapshotNum(0) != 0: - instance.append(dom.name()) - return instance - def can_change_interfaces(self): """Whether the host's libvirt can define interfaces: the udev backend only reads them. The definition sent is invalid, so nothing is diff --git a/vrtManager/create.py b/vrtManager/create.py index f0f4f267..727065df 100644 --- a/vrtManager/create.py +++ b/vrtManager/create.py @@ -60,27 +60,6 @@ def get_rbd_storage_data(stg): class wvmCreate(wvmConnect): - def get_storages_images(self): - """ - Function return all images on all storages - """ - images = [] - storages = self.get_storages(only_actives=True) - for storage in storages: - stg = self.get_storage(storage) - with contextlib.suppress(Exception): - stg.refresh(0) - images.extend(img for img in stg.listVolumes() if not img.lower().endswith(".iso")) - return images - - def get_os_type(self): - """Get guest os type""" - return util.get_xml_path(self.get_cap_xml(), "/capabilities/guest/os_type") - - def get_host_arch(self): - """Get host architecture""" - return util.get_xml_path(self.get_cap_xml(), "/capabilities/host/cpu/arch") - def create_volume(self, storage, name, size, image_format, metadata=False, disk_owner_uid=0, disk_owner_gid=0): size = int(size) * 1073741824 stg = self.get_storage(storage) diff --git a/vrtManager/network.py b/vrtManager/network.py index 2c35e6ef..b274313b 100644 --- a/vrtManager/network.py +++ b/vrtManager/network.py @@ -326,11 +326,6 @@ class wvmNetwork(wvmConnect): def get_network_mac(self): return self.tree.xpath("string(mac/@address)") - def get_network_forward(self): - """Its forward mode (None: isolated) and the device it forwards through.""" - forward = self.tree.find("forward") - return [forward.get("mode"), forward.get("dev")] if forward is not None else [None, None] - def _ip(self, index): """The saved of that index, and what ip_networks tells of it.""" tree = self.config() diff --git a/vrtManager/storage.py b/vrtManager/storage.py index 81d76faf..b41a2bb2 100644 --- a/vrtManager/storage.py +++ b/vrtManager/storage.py @@ -253,15 +253,6 @@ class wvmStorage(wvmConnect): return util.get_xml_path(self._XMLDesc(0), func=hosts) - def get_pretty_allocation(self): - return util.pretty_bytes(self.get_allocation()) - - def get_pretty_available(self): - return util.pretty_bytes(self.get_available()) - - def get_pretty_capacity(self): - return util.pretty_bytes(self.get_capacity()) - def get_volumes(self): return self.pool.listVolumes() diff --git a/vrtManager/tests/test_connection.py b/vrtManager/tests/test_connection.py index daec0f5c..ebbb6cb2 100644 --- a/vrtManager/tests/test_connection.py +++ b/vrtManager/tests/test_connection.py @@ -2,7 +2,6 @@ import contextlib import os -import socket import subprocess import sys import threading @@ -21,29 +20,6 @@ from vrtManager import connection from vrtManager.connection import CONN_SSH, CONN_TCP, SSH_COMMAND, wvmConnectionManager -def closed_port(): - sock = socket.socket() - sock.bind(("127.0.0.1", 0)) - port = sock.getsockname()[1] - sock.close() - return port - - -class HostIsUpTestCase(unittest.TestCase): - def setUp(self): - self.manager = wvmConnectionManager.__new__(wvmConnectionManager) - - def test_reachable_host_is_true(self): - server = socket.socket() - server.bind(("127.0.0.1", 0)) - server.listen(1) - self.addCleanup(server.close) - self.assertIs(self.manager.host_is_up(CONN_TCP, f"127.0.0.1:{server.getsockname()[1]}"), True) - - def test_unreachable_host_is_false_not_an_exception(self): - self.assertIs(self.manager.host_is_up(CONN_TCP, f"127.0.0.1:{closed_port()}"), False) - - class ConnectionManagerTestCase(unittest.TestCase): def setUp(self): patcher = patch("vrtManager.connection.wvmEventLoop") diff --git a/vrtManager/tests/test_util.py b/vrtManager/tests/test_util.py index f53973f8..67077761 100644 --- a/vrtManager/tests/test_util.py +++ b/vrtManager/tests/test_util.py @@ -6,16 +6,10 @@ if not settings.configured: settings.configure(MAC_OUI="52:54:10") from vrtManager.util import ( - compareMAC, get_xml_path, - is_kvm_available, - pretty_bytes, - pretty_mem, - randomMAC, randomPasswd, randomUUID, validate_macaddr, - validate_uuid, vol_dev_type, vol_driver_type, xml_escape, @@ -31,38 +25,6 @@ class TestVrtManagerUtil(unittest.TestCase): # Ensure successive UUIDs are distinct self.assertNotEqual(uuid_str, randomUUID()) - def test_validate_uuid(self): - valid_dashed = "c9a646d3-9c61-4cd8-8024-f6b72a6642d9" - self.assertEqual(validate_uuid(valid_dashed), valid_dashed) - - valid_no_dash = "c9a646d39c614cd88024f6b72a6642d9" - self.assertEqual(validate_uuid(valid_no_dash), valid_dashed) - - with self.assertRaises(ValueError): - validate_uuid("invalid-uuid-too-short") - - with self.assertRaises(ValueError): - validate_uuid(12345) - - def test_random_mac(self): - mac = randomMAC() - self.assertTrue(mac.startswith("52:54:10:")) - parts = mac.split(":") - self.assertEqual(len(parts), 6) - for part in parts: - self.assertEqual(len(part), 2) - int(part, 16) # valid hex - - def test_compare_mac(self): - mac1 = "52:54:10:00:00:01" - mac2 = "52:54:10:00:00:02" - self.assertEqual(compareMAC(mac1, mac1), 0) - self.assertEqual(compareMAC(mac1, mac2), -1) - self.assertEqual(compareMAC(mac2, mac1), 1) - # Different lengths - self.assertEqual(compareMAC("52:54", "52:54:10"), -1) - self.assertEqual(compareMAC("52:54:10", "52:54"), 1) - def test_validate_macaddr(self): self.assertIsNone(validate_macaddr(None)) self.assertIsNone(validate_macaddr("52:54:10:aa:bb:cc")) @@ -103,23 +65,6 @@ class TestVrtManagerUtil(unittest.TestCase): with self.assertRaises(ValueError): get_xml_path(xml) - def test_is_kvm_available(self): - kvm_xml = "" - qemu_xml = "" - self.assertTrue(is_kvm_available(kvm_xml)) - self.assertFalse(is_kvm_available(qemu_xml)) - - def test_pretty_mem(self): - # Value in KB - self.assertEqual(pretty_mem(1024), " 1 MB") - self.assertEqual(pretty_mem(1024 * 1024), "1024 MB") - self.assertEqual(pretty_mem(16 * 1024 * 1024), "16.00 GB") - - def test_pretty_bytes(self): - # Value in Bytes - self.assertEqual(pretty_bytes(10 * 1024 * 1024), "10.00 MB") - self.assertEqual(pretty_bytes(2 * 1024 * 1024 * 1024), "2.00 GB") - def test_vol_dev_type(self): self.assertEqual(vol_dev_type("ide"), "hd") self.assertEqual(vol_dev_type("fdc"), "fd") diff --git a/vrtManager/util.py b/vrtManager/util.py index 8fd232d4..acb26262 100644 --- a/vrtManager/util.py +++ b/vrtManager/util.py @@ -1,6 +1,5 @@ from django.utils.translation import gettext_noop import ipaddress -import random import secrets import re import string @@ -8,7 +7,6 @@ import string import libvirt import lxml.etree as etree -from django.conf import settings from django.utils.translation import gettext @@ -61,22 +59,6 @@ class HostBusy(ConnectionFailed): (HOST_REQUESTS) still wait for its answers.""" -def is_kvm_available(xml): - kvm_domains = get_xml_path(xml, "//domain/@type='kvm'") - return kvm_domains > 0 - - -def randomMAC(): - """Generate a random MAC address.""" - # qemu MAC - mac = settings.MAC_OUI + ":%02x:%02x:%02x" % ( - random.randint(0x00, 0xFF), - random.randint(0x00, 0xFF), - random.randint(0x00, 0xFF), - ) - return mac - - def randomUUID(): """Generate a random UUID.""" u = [secrets.randbelow(256) for _ in range(16)] @@ -90,18 +72,6 @@ def randomPasswd(length=12, alphabet=string.ascii_letters + string.digits): return "".join([secrets.choice(alphabet) for _ in range(length)]) -def get_max_vcpus(conn, guest_type=None): - """@param conn: libvirt connection to poll for max possible vcpus - @param guest_type: optional guest type (kvm, etc.)""" - if type is None: - guest_type = conn.getType() - try: - m = conn.getMaxVcpus(guest_type.lower()) - except libvirt.libvirtError: - m = 32 - return m - - def xml_escape(xml_str): """Replaces chars ' " < > & with xml safe counterparts""" if xml_str is None: @@ -115,26 +85,6 @@ def xml_escape(xml_str): return xml_str -def compareMAC(p, q): - """Compare two MAC addresses""" - pa = p.split(":") - qa = q.split(":") - - if len(pa) != len(qa): - if p > q: - return 1 - else: - return -1 - - for i in range(len(pa)): - n = int(pa[i], 0x10) - int(qa[i], 0x10) - if n > 0: - return 1 - elif n < 0: - return -1 - return 0 - - def parse_xml(xml): """XML a user entered, read for the panel's checks: its entities not expanded, nothing fetched and no DTD; libvirt gets the text itself.""" @@ -181,41 +131,6 @@ def get_xpath(doc, path): return result -def pretty_mem(val): - val = int(val) - if val > (10 * 1024 * 1024): - return "%2.2f GB" % (val / (1024.0 * 1024.0)) - else: - return "%2.0f MB" % (val / 1024.0) - - -def pretty_bytes(val): - val = int(val) - if val > (1024 * 1024 * 1024): - return "%2.2f GB" % (val / (1024.0 * 1024.0 * 1024.0)) - else: - return "%2.2f MB" % (val / (1024.0 * 1024.0)) - - -def validate_uuid(val): - if not isinstance(val, str): - raise ValueError("UUID must be a string.") - - form = re.match("[a-fA-F0-9]{8}[-]([a-fA-F0-9]{4}[-]){3}[a-fA-F0-9]{12}$", val) - if form is None: - form = re.match("[a-fA-F0-9]{32}$", val) - if form is None: - raise ValueError( - "UUID must be a 32-digit hexadecimal number. It may take " - "the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx or may " - "omit hyphens altogether." - ) - - else: # UUID had no dashes, so add them in - val = val[0:8] + "-" + val[8:12] + "-" + val[12:16] + "-" + val[16:20] + "-" + val[20:32] - return val - - def validate_macaddr(val): if val is None: return diff --git a/webvirtcloud/common_tags.py b/webvirtcloud/common_tags.py index d9f97044..8f30ce60 100644 --- a/webvirtcloud/common_tags.py +++ b/webvirtcloud/common_tags.py @@ -24,6 +24,3 @@ def class_active(request, pattern): return "active" if re.search(pattern, request.path) else "" -@register.simple_tag -def has_perm(user, permission_codename): - return bool(user.has_perm(permission_codename)) diff --git a/webvirtcloud/settings.py.template b/webvirtcloud/settings.py.template index 209ad568..7d422e87 100644 --- a/webvirtcloud/settings.py.template +++ b/webvirtcloud/settings.py.template @@ -355,7 +355,6 @@ QEMU_KEYMAPS = [ LIBVIRT_KEEPALIVE_INTERVAL = 5 LIBVIRT_KEEPALIVE_COUNT = 5 -ALLOW_EMPTY_PASSWORD = False NEW_USER_DEFAULT_INSTANCES = [] # Days the owners of a VM that vanished from its compute are kept, in case it comes back INSTANCE_OWNERSHIP_RETENTION_DAYS = 30