diff --git a/accounts/apps.py b/accounts/apps.py index 446ec40..0192800 100644 --- a/accounts/apps.py +++ b/accounts/apps.py @@ -3,59 +3,48 @@ from django.db.models.signals import post_migrate def apply_change_password(sender, **kwargs): - """ + ''' Apply new change_password permission for all users Depending on settings SHOW_PROFILE_EDIT_PASSWORD - """ + ''' from django.conf import settings from django.contrib.auth.models import Permission, User - - if hasattr(settings, "SHOW_PROFILE_EDIT_PASSWORD"): - print("\033[1m! \033[92mSHOW_PROFILE_EDIT_PASSWORD is found inside settings.py\033[0m") - print("\033[1m* \033[92mApplying permission can_change_password for all users\033[0m") + if hasattr(settings, 'SHOW_PROFILE_EDIT_PASSWORD'): + print('\033[1m! \033[92mSHOW_PROFILE_EDIT_PASSWORD is found inside settings.py\033[0m') + print('\033[1m* \033[92mApplying permission can_change_password for all users\033[0m') users = User.objects.all() - permission = Permission.objects.get(codename="change_password") + permission = Permission.objects.get(codename='change_password') if settings.SHOW_PROFILE_EDIT_PASSWORD: - print("\033[1m! \033[91mWarning!!! Setting to True for all users\033[0m") + print('\033[1m! \033[91mWarning!!! Setting to True for all users\033[0m') for user in users: user.user_permissions.add(permission) else: - print("\033[1m* \033[91mWarning!!! Setting to False for all users\033[0m") + print('\033[1m* \033[91mWarning!!! Setting to False for all users\033[0m') for user in users: user.user_permissions.remove(permission) - print("\033[1m! Don`t forget to remove the option from settings.py\033[0m") + print('\033[1m! Don`t forget to remove the option from settings.py\033[0m') def create_admin(sender, **kwargs): - """ + ''' Create initial admin user - """ + ''' from accounts.models import UserAttributes from django.contrib.auth.models import User - plan = kwargs.get("plan", []) + plan = kwargs.get('plan', []) for migration, rolled_back in plan: - if ( - migration.app_label == "accounts" - and migration.name == "0001_initial" - and not rolled_back - ): + if migration.app_label == 'accounts' and migration.name == '0001_initial' and not rolled_back: if User.objects.count() == 0: - print("\033[1m* \033[92mCreating default admin user\033[0m") - admin = User.objects.create_superuser("admin", None, "admin") - UserAttributes( - user=admin, - max_instances=-1, - max_cpus=-1, - max_memory=-1, - max_disk_size=-1, - ).save() + print('\033[1m* \033[92mCreating default admin user\033[0m') + admin = User.objects.create_superuser('admin', None, 'admin') + UserAttributes(user=admin, max_instances=-1, max_cpus=-1, max_memory=-1, max_disk_size=-1).save() break class AccountsConfig(AppConfig): - name = "accounts" - verbose_name = "Accounts" + name = 'accounts' + verbose_name = 'Accounts' def ready(self): post_migrate.connect(create_admin, sender=self) diff --git a/accounts/forms.py b/accounts/forms.py index d4c7e56..cbd3425 100644 --- a/accounts/forms.py +++ b/accounts/forms.py @@ -12,52 +12,52 @@ class UserInstanceForm(ModelForm): super(UserInstanceForm, self).__init__(*args, **kwargs) # Make user and instance fields not editable after creation - instance = getattr(self, "instance", None) + instance = getattr(self, 'instance', None) if instance and instance.id is not None: - self.fields["user"].disabled = True - self.fields["instance"].disabled = True + self.fields['user'].disabled = True + self.fields['instance'].disabled = True def clean_instance(self): - instance = self.cleaned_data["instance"] - if app_settings.ALLOW_INSTANCE_MULTIPLE_OWNER == "False": + instance = self.cleaned_data['instance'] + if app_settings.ALLOW_INSTANCE_MULTIPLE_OWNER == 'False': exists = UserInstance.objects.filter(instance=instance) if exists: - raise ValidationError(_("Instance owned by another user")) + raise ValidationError(_('Instance owned by another user')) return instance class Meta: model = UserInstance - fields = "__all__" + fields = '__all__' class ProfileForm(ModelForm): class Meta: model = get_user_model() - fields = ("first_name", "last_name", "email") + fields = ('first_name', 'last_name', 'email') class UserSSHKeyForm(ModelForm): def __init__(self, *args, **kwargs): - self.user = kwargs.pop("user", None) + self.user = kwargs.pop('user', None) self.publickeys = UserSSHKey.objects.filter(user=self.user) super().__init__(*args, **kwargs) def clean_keyname(self): for key in self.publickeys: - if self.cleaned_data["keyname"] == key.keyname: + if self.cleaned_data['keyname'] == key.keyname: raise ValidationError(_("Key name already exist")) - return self.cleaned_data["keyname"] + return self.cleaned_data['keyname'] def clean_keypublic(self): for key in self.publickeys: - if self.cleaned_data["keypublic"] == key.keypublic: + if self.cleaned_data['keypublic'] == key.keypublic: raise ValidationError(_("Public key already exist")) - if not validate_ssh_key(self.cleaned_data["keypublic"]): - raise ValidationError(_("Invalid key")) - return self.cleaned_data["keypublic"] + if not validate_ssh_key(self.cleaned_data['keypublic']): + raise ValidationError(_('Invalid key')) + return self.cleaned_data['keypublic'] def save(self, commit=True): ssh_key = super().save(commit=False) @@ -68,8 +68,8 @@ class UserSSHKeyForm(ModelForm): class Meta: model = UserSSHKey - fields = ("keyname", "keypublic") + fields = ('keyname', 'keypublic') class EmailOTPForm(Form): - email = EmailField(label=_("Email")) + email = EmailField(label=_('Email')) diff --git a/accounts/models.py b/accounts/models.py index 88cbb23..1fcc880 100644 --- a/accounts/models.py +++ b/accounts/models.py @@ -7,7 +7,7 @@ from instances.models import Instance class UserInstanceManager(models.Manager): def get_queryset(self): - return super().get_queryset().select_related("instance", "user") + return super().get_queryset().select_related('instance', 'user') class UserInstance(models.Model): @@ -20,19 +20,16 @@ class UserInstance(models.Model): objects = UserInstanceManager() def __str__(self): - return _('Instance "%(inst)s" of user %(user)s') % { - "inst": self.instance, - "user": self.user, - } + return _('Instance "%(inst)s" of user %(user)s') % {"inst": self.instance, "user": self.user} class Meta: - unique_together = ["user", "instance"] + unique_together = ['user', 'instance'] class UserSSHKey(models.Model): user = models.ForeignKey(User, on_delete=models.DO_NOTHING) - keyname = models.CharField(_("key name"), max_length=25) - keypublic = models.CharField(_("public key"), max_length=500) + keyname = models.CharField(_('key name'), max_length=25) + keypublic = models.CharField(_('public key'), max_length=500) def __str__(self): return self.keyname @@ -41,26 +38,26 @@ class UserSSHKey(models.Model): class UserAttributes(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) can_clone_instances = models.BooleanField(default=True) - max_instances = models.IntegerField( - _("max instances"), - default=2, - help_text=_("-1 for unlimited. Any integer value"), - validators=[MinValueValidator(-1)], - ) + max_instances = models.IntegerField(_('max instances'), + default=2, + help_text=_("-1 for unlimited. Any integer value"), + validators=[ + MinValueValidator(-1), + ]) max_cpus = models.IntegerField( - _("max CPUs"), + _('max CPUs'), default=2, help_text=_("-1 for unlimited. Any integer value"), validators=[MinValueValidator(-1)], ) max_memory = models.IntegerField( - _("max memory"), + _('max memory'), default=2048, help_text=_("-1 for unlimited. Any integer value"), validators=[MinValueValidator(-1)], ) max_disk_size = models.IntegerField( - _("max disk size"), + _('max disk size'), default=20, help_text=_("-1 for unlimited. Any integer value"), validators=[MinValueValidator(-1)], @@ -74,9 +71,8 @@ class PermissionSet(models.Model): """ Dummy model for holding set of permissions we need to be automatically added by Django """ - class Meta: default_permissions = () - permissions = (("change_password", _("Can change password")),) + permissions = (('change_password', _('Can change password')), ) managed = False diff --git a/accounts/templates/accounts/email/otp.html b/accounts/templates/accounts/email/otp.html index c80ec14..2833194 100644 --- a/accounts/templates/accounts/email/otp.html +++ b/accounts/templates/accounts/email/otp.html @@ -4,6 +4,4 @@ Scan this QR code to get OTP for account '{{ user }}' {% endblocktrans %}
-{% qr_from_text totp_url %} -

{% trans 'Some e-mail clients does not render SVG, also generating PNG.' %}

-{% qr_from_text totp_url size="s" image_format="png" error_correction="M" %} +{% qr_from_text totp_url %} \ No newline at end of file diff --git a/accounts/tests.py b/accounts/tests.py index 3b7ed6b..2419990 100644 --- a/accounts/tests.py +++ b/accounts/tests.py @@ -23,15 +23,15 @@ class AccountsTestCase(TestCase): # Add users for testing purposes User = get_user_model() cls.admin_user = User.objects.get(pk=1) - cls.test_user = User.objects.create_user(username="test", password="test") + cls.test_user = User.objects.create_user(username='test', password='test') # Add localhost compute cls.compute = Compute( - name="test-compute", - hostname="localhost", - login="", - password="", - details="local", + name='test-compute', + hostname='localhost', + login='', + password='', + details='local', type=4, ) cls.compute.save() @@ -45,17 +45,17 @@ class AccountsTestCase(TestCase): # Add disks for testing cls.connection.create_volume( - "default", - "test-volume", + 'default', + 'test-volume', 1, - "qcow2", + 'qcow2', False, 0, 0, ) # XML for testing vm - with open("conf/test-vm.xml", "r") as f: + with open('conf/test-vm.xml', 'r') as f: cls.xml = f.read() # Create testing vm from XML @@ -71,90 +71,80 @@ class AccountsTestCase(TestCase): super().tearDownClass() def setUp(self): - self.client.login(username="admin", password="admin") - permission = Permission.objects.get(codename="change_password") + self.client.login(username='admin', password='admin') + permission = Permission.objects.get(codename='change_password') self.test_user.user_permissions.add(permission) - self.rsa_key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC6OOdbfv27QVnSC6sKxGaHb6YFc+3gxCkyVR3cTSXE/n5BEGf8aOgBpepULWa1RZfxYHY14PlKULDygdXSdrrR2kNSwoKz/Oo4d+3EE92L7ocl1+djZbptzgWgtw1OseLwbFik+iKlIdqPsH+IUQvX7yV545ZQtAP8Qj1R+uCqkw== test@test" - self.ecdsa_key = "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBJc5xpT3R0iFJYNZbmWgAiDlHquX/BcV1kVTsnBfiMsZgU3lGaqz2eb7IBcir/dxGnsVENTTmPQ6sNcxLxT9kkQ= realgecko@archlinux" + self.rsa_key = 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC6OOdbfv27QVnSC6sKxGaHb6YFc+3gxCkyVR3cTSXE/n5BEGf8aOgBpepULWa1RZfxYHY14PlKULDygdXSdrrR2kNSwoKz/Oo4d+3EE92L7ocl1+djZbptzgWgtw1OseLwbFik+iKlIdqPsH+IUQvX7yV545ZQtAP8Qj1R+uCqkw== test@test' + self.ecdsa_key = 'ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBJc5xpT3R0iFJYNZbmWgAiDlHquX/BcV1kVTsnBfiMsZgU3lGaqz2eb7IBcir/dxGnsVENTTmPQ6sNcxLxT9kkQ= realgecko@archlinux' def test_profile(self): - response = self.client.get(reverse("accounts:profile")) + response = self.client.get(reverse('accounts:profile')) self.assertEqual(response.status_code, 200) - response = self.client.get( - reverse("accounts:account", args=[self.test_user.id]) - ) + response = self.client.get(reverse('accounts:account', args=[self.test_user.id])) self.assertEqual(response.status_code, 200) def test_account_with_otp(self): settings.OTP_ENABLED = True - response = self.client.get( - reverse("accounts:account", args=[self.test_user.id]) - ) + response = self.client.get(reverse('accounts:account', args=[self.test_user.id])) self.assertEqual(response.status_code, 200) def test_login_logout(self): client = Client() - response = client.post( - reverse("accounts:login"), {"username": "test", "password": "test"} - ) - self.assertRedirects(response, reverse("accounts:profile")) + response = client.post(reverse("accounts:login"), {"username": "test", "password": "test"}) + self.assertRedirects(response, reverse('accounts:profile')) - response = client.get(reverse("accounts:logout")) - self.assertRedirects(response, reverse("accounts:login")) + response = client.get(reverse('accounts:logout')) + self.assertRedirects(response, reverse('accounts:login')) def test_change_password(self): self.client.force_login(self.test_user) - response = self.client.get(reverse("accounts:change_password")) + response = self.client.get(reverse('accounts:change_password')) self.assertEqual(response.status_code, 200) response = self.client.post( - reverse("accounts:change_password"), + reverse('accounts:change_password'), { - "old_password": "wrongpass", - "new_password1": "newpw", - "new_password2": "newpw", + 'old_password': 'wrongpass', + 'new_password1': 'newpw', + 'new_password2': 'newpw', }, ) self.assertEqual(response.status_code, 200) response = self.client.post( - reverse("accounts:change_password"), + reverse('accounts:change_password'), { - "old_password": "test", - "new_password1": "newpw", - "new_password2": "newpw", + 'old_password': 'test', + 'new_password1': 'newpw', + 'new_password2': 'newpw', }, ) - self.assertRedirects(response, reverse("accounts:profile")) + self.assertRedirects(response, reverse('accounts:profile')) self.client.logout() - logged_in = self.client.login(username="test", password="newpw") + logged_in = self.client.login(username='test', password='newpw') self.assertTrue(logged_in) def test_user_instance_create_update_delete(self): # create - response = self.client.get( - reverse("accounts:user_instance_create", args=[self.test_user.id]) - ) + response = self.client.get(reverse('accounts:user_instance_create', args=[self.test_user.id])) self.assertEqual(response.status_code, 200) response = self.client.post( - reverse("accounts:user_instance_create", args=[self.test_user.id]), + reverse('accounts:user_instance_create', args=[self.test_user.id]), { - "user": self.test_user.id, - "instance": self.instance.id, - "is_change": False, - "is_delete": False, - "is_vnc": False, + 'user': self.test_user.id, + 'instance': self.instance.id, + 'is_change': False, + 'is_delete': False, + 'is_vnc': False, }, ) - self.assertRedirects( - response, reverse("accounts:account", args=[self.test_user.id]) - ) + self.assertRedirects(response, reverse('accounts:account', args=[self.test_user.id])) user_instance: UserInstance = UserInstance.objects.get(pk=1) self.assertEqual(user_instance.user, self.test_user) @@ -164,24 +154,20 @@ class AccountsTestCase(TestCase): self.assertEqual(user_instance.is_vnc, False) # update - response = self.client.get( - reverse("accounts:user_instance_update", args=[user_instance.id]) - ) + response = self.client.get(reverse('accounts:user_instance_update', args=[user_instance.id])) self.assertEqual(response.status_code, 200) response = self.client.post( - reverse("accounts:user_instance_update", args=[user_instance.id]), + reverse('accounts:user_instance_update', args=[user_instance.id]), { - "user": self.test_user.id, - "instance": self.instance.id, - "is_change": True, - "is_delete": True, - "is_vnc": True, + 'user': self.test_user.id, + 'instance': self.instance.id, + 'is_change': True, + 'is_delete': True, + 'is_vnc': True, }, ) - self.assertRedirects( - response, reverse("accounts:account", args=[self.test_user.id]) - ) + self.assertRedirects(response, reverse('accounts:account', args=[self.test_user.id])) user_instance: UserInstance = UserInstance.objects.get(pk=1) self.assertEqual(user_instance.user, self.test_user) @@ -191,118 +177,91 @@ class AccountsTestCase(TestCase): self.assertEqual(user_instance.is_vnc, True) # delete - response = self.client.get( - reverse("accounts:user_instance_delete", args=[user_instance.id]) - ) + response = self.client.get(reverse('accounts:user_instance_delete', args=[user_instance.id])) self.assertEqual(response.status_code, 200) - response = self.client.post( - reverse("accounts:user_instance_delete", args=[user_instance.id]) - ) - self.assertRedirects( - response, reverse("accounts:account", args=[self.test_user.id]) - ) + response = self.client.post(reverse('accounts:user_instance_delete', args=[user_instance.id])) + self.assertRedirects(response, reverse('accounts:account', args=[self.test_user.id])) # test 'next' redirect during deletion - user_instance = UserInstance.objects.create( - user=self.test_user, instance=self.instance - ) + user_instance = UserInstance.objects.create(user=self.test_user, instance=self.instance) response = self.client.post( - reverse("accounts:user_instance_delete", args=[user_instance.id]) - + "?next=" - + reverse("index") - ) - self.assertRedirects(response, reverse("index")) + reverse('accounts:user_instance_delete', args=[user_instance.id]) + '?next=' + reverse('index')) + self.assertRedirects(response, reverse('index')) def test_update_user_profile(self): self.client.force_login(self.test_user) - user = get_user_model().objects.get(username="test") - self.assertEqual(user.first_name, "") - self.assertEqual(user.last_name, "") - self.assertEqual(user.email, "") + user = get_user_model().objects.get(username='test') + self.assertEqual(user.first_name, '') + self.assertEqual(user.last_name, '') + self.assertEqual(user.email, '') - response = self.client.post( - reverse("accounts:profile"), - { - "first_name": "first name", - "last_name": "last name", - "email": "email@mail.mail", - }, - ) - self.assertRedirects(response, reverse("accounts:profile")) + response = self.client.post(reverse('accounts:profile'), { + 'first_name': 'first name', + 'last_name': 'last name', + 'email': 'email@mail.mail', + }) + self.assertRedirects(response, reverse('accounts:profile')) - user = get_user_model().objects.get(username="test") - self.assertEqual(user.first_name, "first name") - self.assertEqual(user.last_name, "last name") - self.assertEqual(user.email, "email@mail.mail") + user = get_user_model().objects.get(username='test') + self.assertEqual(user.first_name, 'first name') + self.assertEqual(user.last_name, 'last name') + self.assertEqual(user.email, 'email@mail.mail') def test_create_delete_ssh_key(self): - response = self.client.get(reverse("accounts:ssh_key_create")) + response = self.client.get(reverse('accounts:ssh_key_create')) self.assertEqual(response.status_code, 200) - response = self.client.post( - reverse("accounts:ssh_key_create"), - { - "keyname": "keyname", - "keypublic": self.rsa_key, - }, - ) - self.assertRedirects(response, reverse("accounts:profile")) + response = self.client.post(reverse('accounts:ssh_key_create'), { + 'keyname': 'keyname', + 'keypublic': self.rsa_key, + }) + self.assertRedirects(response, reverse('accounts:profile')) key = UserSSHKey.objects.get(pk=1) - self.assertEqual(key.keyname, "keyname") + self.assertEqual(key.keyname, 'keyname') self.assertEqual(key.keypublic, self.rsa_key) - response = self.client.get(reverse("accounts:ssh_key_delete", args=[1])) + response = self.client.get(reverse('accounts:ssh_key_delete', args=[1])) self.assertEqual(response.status_code, 200) - response = self.client.post(reverse("accounts:ssh_key_delete", args=[1])) - self.assertRedirects(response, reverse("accounts:profile")) + response = self.client.post(reverse('accounts:ssh_key_delete', args=[1])) + self.assertRedirects(response, reverse('accounts:profile')) def test_validate_ssh_key(self): - self.assertFalse(validate_ssh_key("")) - self.assertFalse(validate_ssh_key("ssh-rsa ABBA test@test")) - self.assertFalse(validate_ssh_key("ssh-rsa AAAABwdzZGY= test@test")) - self.assertFalse(validate_ssh_key("ssh-rsa AAA test@test")) + self.assertFalse(validate_ssh_key('')) + self.assertFalse(validate_ssh_key('ssh-rsa ABBA test@test')) + self.assertFalse(validate_ssh_key('ssh-rsa AAAABwdzZGY= test@test')) + self.assertFalse(validate_ssh_key('ssh-rsa AAA test@test')) # validate ecdsa key self.assertTrue(validate_ssh_key(self.ecdsa_key)) def test_forms(self): # raise available validation errors for maximum coverage - form = UserSSHKeyForm( - {"keyname": "keyname", "keypublic": self.rsa_key}, user=self.test_user - ) + form = UserSSHKeyForm({'keyname': 'keyname', 'keypublic': self.rsa_key}, user=self.test_user) form.save() - form = UserSSHKeyForm( - {"keyname": "keyname", "keypublic": self.rsa_key}, user=self.test_user - ) + form = UserSSHKeyForm({'keyname': 'keyname', 'keypublic': self.rsa_key}, user=self.test_user) self.assertFalse(form.is_valid()) - form = UserSSHKeyForm( - {"keyname": "keyname", "keypublic": "invalid key"}, user=self.test_user - ) + form = UserSSHKeyForm({'keyname': 'keyname', 'keypublic': 'invalid key'}, user=self.test_user) self.assertFalse(form.is_valid()) - app_settings.ALLOW_INSTANCE_MULTIPLE_OWNER = "False" - form = UserInstanceForm( - { - "user": self.admin_user.id, - "instance": self.instance.id, - "is_change": False, - "is_delete": False, - "is_vnc": False, - } - ) + app_settings.ALLOW_INSTANCE_MULTIPLE_OWNER = 'False' + form = UserInstanceForm({ + 'user': self.admin_user.id, + 'instance': self.instance.id, + 'is_change': False, + 'is_delete': False, + 'is_vnc': False, + }) form.save() - form = UserInstanceForm( - { - "user": self.test_user.id, - "instance": self.instance.id, - "is_change": False, - "is_delete": False, - "is_vnc": False, - } - ) + form = UserInstanceForm({ + 'user': self.test_user.id, + 'instance': self.instance.id, + 'is_change': False, + 'is_delete': False, + 'is_vnc': False, + }) self.assertFalse(form.is_valid()) diff --git a/accounts/urls.py b/accounts/urls.py index 2fa8e26..d98e75a 100644 --- a/accounts/urls.py +++ b/accounts/urls.py @@ -5,50 +5,29 @@ from django_otp.forms import OTPAuthenticationForm from . import views -app_name = "accounts" +app_name = 'accounts' urlpatterns = [ - path("logout/", LogoutView.as_view(template_name="logout.html"), name="logout"), - path("profile/", views.profile, name="profile"), - path("profile//", views.account, name="account"), - path("change_password/", views.change_password, name="change_password"), - path( - "user_instance/create//", - views.user_instance_create, - name="user_instance_create", - ), - path( - "user_instance//update/", - views.user_instance_update, - name="user_instance_update", - ), - path( - "user_instance//delete/", - views.user_instance_delete, - name="user_instance_delete", - ), - path("ssh_key/create/", views.ssh_key_create, name="ssh_key_create"), - path("ssh_key//delete/", views.ssh_key_delete, name="ssh_key_delete"), + path('logout/', LogoutView.as_view(template_name='logout.html'), name='logout'), + path('profile/', views.profile, name='profile'), + path('profile//', views.account, name='account'), + path('change_password/', views.change_password, name='change_password'), + path('user_instance/create//', views.user_instance_create, name='user_instance_create'), + path('user_instance//update/', views.user_instance_update, name='user_instance_update'), + path('user_instance//delete/', views.user_instance_delete, name='user_instance_delete'), + path('ssh_key/create/', views.ssh_key_create, name='ssh_key_create'), + path('ssh_key//delete/', views.ssh_key_delete, name='ssh_key_delete'), ] if settings.OTP_ENABLED: urlpatterns += [ path( - "login/", - LoginView.as_view( - template_name="accounts/otp_login.html", - authentication_form=OTPAuthenticationForm, - ), - name="login", - ), - path("email_otp/", views.email_otp, name="email_otp"), - path( - "admin_email_otp//", - views.admin_email_otp, - name="admin_email_otp", + 'login/', + LoginView.as_view(template_name='accounts/otp_login.html', authentication_form=OTPAuthenticationForm), + name='login', ), + path('email_otp/', views.email_otp, name='email_otp'), + path('admin_email_otp//', views.admin_email_otp, name='admin_email_otp'), ] else: - urlpatterns += ( - path("login/", LoginView.as_view(template_name="login.html"), name="login"), - ) + urlpatterns += path('login/', LoginView.as_view(template_name='login.html'), name='login'), diff --git a/accounts/views.py b/accounts/views.py index c4979bf..8ca3ba7 100644 --- a/accounts/views.py +++ b/accounts/views.py @@ -172,10 +172,7 @@ def email_otp(request): device = get_user_totp_device(user) send_email_with_otp(user, device) - messages.success( - request, - _("OTP Sent to %(email)s") % {"email": form.cleaned_data["email"]} - ) + messages.success(request, _("OTP Sent to %(email)s") % {"email": form.cleaned_data["email"]}) return redirect("accounts:login") return render( @@ -194,13 +191,7 @@ def admin_email_otp(request, user_id): device = get_user_totp_device(user) if user.email != "": send_email_with_otp(user, device) - messages.success( - request, - _("OTP QR code was emailed to user %(user)s") % {"user": user} - ) + messages.success(request, _("OTP QR code was emailed to user %(user)s") % {"user": user}) else: - messages.error( - request, - _("User email not set, failed to send QR code") - ) + messages.error(request, _("User email not set, failed to send QR code")) return redirect("accounts:account", user.id) diff --git a/admin/apps.py b/admin/apps.py index 86bb5bc..5bbf122 100644 --- a/admin/apps.py +++ b/admin/apps.py @@ -2,4 +2,4 @@ from django.apps import AppConfig class AdminConfig(AppConfig): - name = "admin" + name = 'admin' diff --git a/admin/models.py b/admin/models.py index 67fcdf9..b743377 100644 --- a/admin/models.py +++ b/admin/models.py @@ -7,7 +7,7 @@ class Permission(P): """ def __str__(self): - return f"{self.content_type.app_label}: {self.name}" + return f'{self.content_type.app_label}: {self.name}' class Meta: proxy = True diff --git a/admin/tests.py b/admin/tests.py index 92d261c..b030436 100644 --- a/admin/tests.py +++ b/admin/tests.py @@ -8,66 +8,62 @@ from accounts.models import UserAttributes class AdminTestCase(TestCase): def setUp(self): - self.client.login(username="admin", password="admin") + self.client.login(username='admin', password='admin') def test_group_list(self): - response = self.client.get(reverse("admin:group_list")) + response = self.client.get(reverse('admin:group_list')) self.assertEqual(response.status_code, 200) def test_groups(self): - response = self.client.get(reverse("admin:group_create")) + response = self.client.get(reverse('admin:group_create')) self.assertEqual(response.status_code, 200) - response = self.client.post( - reverse("admin:group_create"), {"name": "Test Group"} - ) - self.assertRedirects(response, reverse("admin:group_list")) + response = self.client.post(reverse('admin:group_create'), {'name': 'Test Group'}) + self.assertRedirects(response, reverse('admin:group_list')) - group = Group.objects.get(name="Test Group") + group = Group.objects.get(name='Test Group') self.assertEqual(group.id, 1) - response = self.client.get(reverse("admin:group_update", args=[1])) + response = self.client.get(reverse('admin:group_update', args=[1])) self.assertEqual(response.status_code, 200) - response = self.client.post( - reverse("admin:group_update", args=[1]), {"name": "Updated Group Test"} - ) - self.assertRedirects(response, reverse("admin:group_list")) + response = self.client.post(reverse('admin:group_update', args=[1]), {'name': 'Updated Group Test'}) + self.assertRedirects(response, reverse('admin:group_list')) group = Group.objects.get(id=1) - self.assertEqual(group.name, "Updated Group Test") + self.assertEqual(group.name, 'Updated Group Test') - response = self.client.get(reverse("admin:group_delete", args=[1])) + response = self.client.get(reverse('admin:group_delete', args=[1])) self.assertEqual(response.status_code, 200) - response = self.client.post(reverse("admin:group_delete", args=[1])) - self.assertRedirects(response, reverse("admin:group_list")) + response = self.client.post(reverse('admin:group_delete', args=[1])) + self.assertRedirects(response, reverse('admin:group_list')) with self.assertRaises(ObjectDoesNotExist): Group.objects.get(id=1) def test_user_list(self): - response = self.client.get(reverse("admin:user_list")) + response = self.client.get(reverse('admin:user_list')) self.assertEqual(response.status_code, 200) def test_users(self): - response = self.client.get(reverse("admin:user_create")) + response = self.client.get(reverse('admin:user_create')) self.assertEqual(response.status_code, 200) response = self.client.post( - reverse("admin:user_create"), + reverse('admin:user_create'), { - "username": "test", - "password": "test", - "max_instances": 1, - "max_cpus": 1, - "max_memory": 1024, - "max_disk_size": 4, + 'username': 'test', + 'password': 'test', + 'max_instances': 1, + 'max_cpus': 1, + 'max_memory': 1024, + 'max_disk_size': 4, }, ) - self.assertRedirects(response, reverse("admin:user_list")) + self.assertRedirects(response, reverse('admin:user_list')) - user = User.objects.get(username="test") + user = User.objects.get(username='test') self.assertEqual(user.id, 2) ua: UserAttributes = UserAttributes.objects.get(id=2) @@ -77,23 +73,23 @@ class AdminTestCase(TestCase): self.assertEqual(ua.max_memory, 1024) self.assertEqual(ua.max_disk_size, 4) - response = self.client.get(reverse("admin:user_update", args=[2])) + response = self.client.get(reverse('admin:user_update', args=[2])) self.assertEqual(response.status_code, 200) response = self.client.post( - reverse("admin:user_update", args=[2]), + reverse('admin:user_update', args=[2]), { - "username": "utest", - "max_instances": 2, - "max_cpus": 2, - "max_memory": 2048, - "max_disk_size": 8, + 'username': 'utest', + 'max_instances': 2, + 'max_cpus': 2, + 'max_memory': 2048, + 'max_disk_size': 8, }, ) - self.assertRedirects(response, reverse("admin:user_list")) + self.assertRedirects(response, reverse('admin:user_list')) user = User.objects.get(id=2) - self.assertEqual(user.username, "utest") + self.assertEqual(user.username, 'utest') ua: UserAttributes = UserAttributes.objects.get(id=2) self.assertEqual(ua.user_id, 2) @@ -102,23 +98,23 @@ class AdminTestCase(TestCase): self.assertEqual(ua.max_memory, 2048) self.assertEqual(ua.max_disk_size, 8) - response = self.client.get(reverse("admin:user_block", args=[2])) + response = self.client.get(reverse('admin:user_block', args=[2])) user = User.objects.get(id=2) self.assertFalse(user.is_active) - response = self.client.get(reverse("admin:user_unblock", args=[2])) + response = self.client.get(reverse('admin:user_unblock', args=[2])) user = User.objects.get(id=2) self.assertTrue(user.is_active) - response = self.client.get(reverse("admin:user_delete", args=[2])) + response = self.client.get(reverse('admin:user_delete', args=[2])) self.assertEqual(response.status_code, 200) - response = self.client.post(reverse("admin:user_delete", args=[2])) - self.assertRedirects(response, reverse("admin:user_list")) + response = self.client.post(reverse('admin:user_delete', args=[2])) + self.assertRedirects(response, reverse('admin:user_list')) with self.assertRaises(ObjectDoesNotExist): User.objects.get(id=2) def test_logs(self): - response = self.client.get(reverse("admin:logs")) + response = self.client.get(reverse('admin:logs')) self.assertEqual(response.status_code, 200) diff --git a/admin/urls.py b/admin/urls.py index 0b5ab41..205cbc0 100644 --- a/admin/urls.py +++ b/admin/urls.py @@ -3,16 +3,16 @@ from django.urls import path from . import views urlpatterns = [ - path("groups/", views.group_list, name="group_list"), - path("groups/create/", views.group_create, name="group_create"), - path("groups//update/", views.group_update, name="group_update"), - path("groups//delete/", views.group_delete, name="group_delete"), - path("users/", views.user_list, name="user_list"), - path("users/create/", views.user_create, name="user_create"), - path("users//update_password/", views.user_update_password, name="user_update_password"), - path("users//update/", views.user_update, name="user_update"), - path("users//delete/", views.user_delete, name="user_delete"), - path("users//block/", views.user_block, name="user_block"), - path("users//unblock/", views.user_unblock, name="user_unblock"), - path("logs/", views.logs, name="logs"), + path('groups/', views.group_list, name='group_list'), + path('groups/create/', views.group_create, name='group_create'), + path('groups//update/', views.group_update, name='group_update'), + path('groups//delete/', views.group_delete, name='group_delete'), + path('users/', views.user_list, name='user_list'), + path('users/create/', views.user_create, name='user_create'), + path('users//update_password/', views.user_update_password, name='user_update_password'), + path('users//update/', views.user_update, name='user_update'), + path('users//delete/', views.user_delete, name='user_delete'), + path('users//block/', views.user_block, name='user_block'), + path('users//unblock/', views.user_unblock, name='user_unblock'), + path('logs/', views.logs, name='logs'), ] diff --git a/admin/views.py b/admin/views.py index bdb2294..c920890 100644 --- a/admin/views.py +++ b/admin/views.py @@ -107,11 +107,7 @@ def user_create(request): return render( request, "admin/user_form.html", - { - "user_form": user_form, - "attributes_form": attributes_form, - "title": _("Create User"), - }, + {"user_form": user_form, "attributes_form": attributes_form, "title": _("Create User")}, ) @@ -120,9 +116,7 @@ def user_update(request, pk): user = get_object_or_404(User, pk=pk) attributes = UserAttributes.objects.get(user=user) user_form = forms.UserForm(request.POST or None, instance=user) - attributes_form = forms.UserAttributesForm( - request.POST or None, instance=attributes - ) + attributes_form = forms.UserAttributesForm(request.POST or None, instance=attributes) if user_form.is_valid() and attributes_form.is_valid(): user_form.save() attributes_form.save() @@ -132,11 +126,7 @@ def user_update(request, pk): return render( request, "admin/user_form.html", - { - "user_form": user_form, - "attributes_form": attributes_form, - "title": _("Update User"), - }, + {"user_form": user_form, "attributes_form": attributes_form, "title": _("Update User")}, ) @@ -148,10 +138,7 @@ def user_update_password(request, pk): if form.is_valid(): user = form.save() update_session_auth_hash(request, user) # Important! - messages.success( - request, - _("Password changed for %(user)s") % {"user": user.username} - ) + messages.success(request, _("Password changed for %(user)s") % {"user": user.username}) return redirect("admin:user_list") else: messages.error(request, _("Wrong Data Provided")) diff --git a/appsettings/apps.py b/appsettings/apps.py index 2a61fca..2e5909e 100644 --- a/appsettings/apps.py +++ b/appsettings/apps.py @@ -2,4 +2,4 @@ from django.apps import AppConfig class AppsettingsConfig(AppConfig): - name = "appsettings" + name = 'appsettings' diff --git a/appsettings/models.py b/appsettings/models.py index 0cfb4e7..a45827f 100644 --- a/appsettings/models.py +++ b/appsettings/models.py @@ -3,11 +3,12 @@ from django.utils.translation import gettext_lazy as _ class AppSettings(models.Model): - def choices_as_list(self): - return self.choices.split(",") - name = models.CharField(_("name"), max_length=25, null=False) - key = models.CharField(_("key"), db_index=True, max_length=50, unique=True) - value = models.CharField(_("value"), max_length=25) - choices = models.CharField(_("choices"), max_length=70) - description = models.CharField(_("description"), max_length=100, null=True) + def choices_as_list(self): + return self.choices.split(',') + + name = models.CharField(_('name'), max_length=25, null=False) + key = models.CharField(_('key'), db_index=True, max_length=50, unique=True) + value = models.CharField(_('value'), max_length=25) + choices = models.CharField(_('choices'), max_length=70) + description = models.CharField(_('description'), max_length=100, null=True) diff --git a/appsettings/views.py b/appsettings/views.py index 70b6490..4fa8ded 100644 --- a/appsettings/views.py +++ b/appsettings/views.py @@ -27,9 +27,7 @@ def appsettings(request): addlogmsg(request.user.username, "-", "", err) # Bootstrap settings related with filesystems, because of that they are excluded from other settings - appsettings = AppSettings.objects.exclude( - description__startswith="Bootstrap" - ).order_by("name") + appsettings = AppSettings.objects.exclude(description__startswith="Bootstrap").order_by("name") if request.method == "POST": if "SASS_DIR" in request.POST: @@ -37,9 +35,7 @@ def appsettings(request): sass_dir.value = request.POST.get("SASS_DIR", "") sass_dir.save() - msg = _("SASS directory path is changed. Now: %(dir)s") % { - "dir": sass_dir.value - } + msg = _("SASS directory path is changed. Now: %(dir)s") % {"dir": sass_dir.value} messages.success(request, msg) except Exception as err: msg = err @@ -51,17 +47,15 @@ def appsettings(request): if "BOOTSTRAP_THEME" in request.POST: theme = request.POST.get("BOOTSTRAP_THEME", "") scss_var = f"@import '{sass_dir.value}/wvc-theme/{theme}/variables';" - # scss_boot = f"@import '{sass_dir.value}/bootstrap/bootstrap.scss';" + #scss_boot = f"@import '{sass_dir.value}/bootstrap/bootstrap.scss';" scss_boot = f"@import '{sass_dir.value}/bootstrap-overrides.scss';" - scss_bootswatch = ( - f"@import '{sass_dir.value}/wvc-theme/{theme}/bootswatch';" - ) + scss_bootswatch = f"@import '{sass_dir.value}/wvc-theme/{theme}/bootswatch';" + + try: with open(sass_dir.value + "/wvc-main.scss", "w") as main: - main.write( - scss_var + "\n" + scss_boot + "\n" + scss_bootswatch + "\n" - ) + main.write(scss_var + "\n" + scss_boot + "\n" + scss_bootswatch + "\n") css_compressed = sass.compile( string=scss_var + "\n" + scss_boot + "\n" + scss_bootswatch, @@ -88,10 +82,7 @@ def appsettings(request): setting.value = request.POST.get(setting.key, "") setting.save() - msg = _("%(setting)s is changed. Now: %(value)s") % { - "setting": setting.name, - "value": setting.value, - } + msg = _("%(setting)s is changed. Now: %(value)s") % {"setting": setting.name, "value": setting.value} messages.success(request, msg) except Exception as err: msg = err diff --git a/computes/api/serializers.py b/computes/api/serializers.py index e79ab05..d7cd096 100644 --- a/computes/api/serializers.py +++ b/computes/api/serializers.py @@ -1,3 +1,4 @@ + from rest_framework import serializers from computes.models import Compute from vrtManager.connection import ( @@ -9,17 +10,18 @@ from vrtManager.connection import ( class ComputeSerializer(serializers.ModelSerializer): - # Use for the input. - password = serializers.CharField(style={"input_type": "password"}) + # Use for the input. + password = serializers.CharField(style={'input_type': 'password'}) # Use a radio input instead of a select input. conn_types = ( - (CONN_SSH, "SSH"), - (CONN_TCP, "TCP"), - (CONN_TLS, "TLS"), - (CONN_SOCKET, "SOCK"), + (CONN_SSH, 'SSH'), + (CONN_TCP, 'TCP'), + (CONN_TLS, 'TLS'), + (CONN_SOCKET, 'SOCK'), ) type = serializers.ChoiceField(choices=conn_types) + class Meta: model = Compute - fields = ["id", "name", "hostname", "login", "password", "type", "details"] + fields = ['id', 'name', 'hostname', 'login', 'password', 'type', 'details'] diff --git a/computes/api/viewsets.py b/computes/api/viewsets.py index df960cb..c7d8acc 100644 --- a/computes/api/viewsets.py +++ b/computes/api/viewsets.py @@ -11,13 +11,13 @@ class ComputeViewSet(viewsets.ModelViewSet): """ API endpoint that allows computes to be viewed or edited. """ - - queryset = Compute.objects.all().order_by("name") + queryset = Compute.objects.all().order_by('name') serializer_class = ComputeSerializer permission_classes = [permissions.IsAuthenticated] class ComputeArchitecturesView(viewsets.ViewSet): + def list(self, request, compute_pk=None): """ Return a list of supported host architectures. @@ -43,6 +43,7 @@ class ComputeArchitecturesView(viewsets.ViewSet): class ComputeMachinesView(viewsets.ViewSet): + def list(self, request, compute_pk=None, archs_pk=None): """ Return a list of supported host architectures. diff --git a/computes/forms.py b/computes/forms.py index 1128695..6927272 100644 --- a/computes/forms.py +++ b/computes/forms.py @@ -13,8 +13,8 @@ class TcpComputeForm(forms.ModelForm): class Meta: model = Compute - widgets = {"password": forms.PasswordInput()} - fields = "__all__" + widgets = {'password': forms.PasswordInput()} + fields = '__all__' class SshComputeForm(forms.ModelForm): @@ -23,7 +23,7 @@ class SshComputeForm(forms.ModelForm): class Meta: model = Compute - exclude = ["password"] + exclude = ['password'] class TlsComputeForm(forms.ModelForm): @@ -32,14 +32,14 @@ class TlsComputeForm(forms.ModelForm): class Meta: model = Compute - widgets = {"password": forms.PasswordInput()} - fields = "__all__" + widgets = {'password': forms.PasswordInput()} + fields = '__all__' class SocketComputeForm(forms.ModelForm): - hostname = forms.CharField(widget=forms.HiddenInput, initial="localhost") + hostname = forms.CharField(widget=forms.HiddenInput, initial='localhost') type = forms.IntegerField(widget=forms.HiddenInput, initial=CONN_SOCKET) class Meta: model = Compute - fields = ["name", "details", "hostname", "type"] + fields = ['name', 'details', 'hostname', 'type'] diff --git a/computes/models.py b/computes/models.py index f81eafa..b1c3cd1 100644 --- a/computes/models.py +++ b/computes/models.py @@ -8,11 +8,11 @@ from vrtManager.hostdetails import wvmHostDetails class Compute(Model): - name = CharField(_("name"), max_length=64, unique=True) - hostname = CharField(_("hostname"), max_length=64) - login = CharField(_("login"), max_length=20) - password = CharField(_("password"), max_length=14, blank=True, null=True) - details = CharField(_("details"), max_length=64, null=True, blank=True) + name = CharField(_('name'), max_length=64, unique=True) + hostname = CharField(_('hostname'), max_length=64) + login = CharField(_('login'), max_length=20) + password = CharField(_('password'), max_length=14, blank=True, null=True) + details = CharField(_('details'), max_length=64, null=True, blank=True) type = IntegerField() @cached_property @@ -55,7 +55,7 @@ class Compute(Model): @cached_property def ram_usage(self): - return self.proxy.get_memory_usage()["percent"] + return self.proxy.get_memory_usage()['percent'] def __str__(self): return self.name diff --git a/computes/tests.py b/computes/tests.py index 5f5cd67..7b94825 100644 --- a/computes/tests.py +++ b/computes/tests.py @@ -7,121 +7,115 @@ from .models import Compute class ComputesTestCase(TestCase): def setUp(self): - self.client.login(username="admin", password="admin") + self.client.login(username='admin', password='admin') Compute( - name="local", - hostname="localhost", - login="", - password="", - details="local", + name='local', + hostname='localhost', + login='', + password='', + details='local', type=4, ).save() def test_index(self): - response = self.client.get(reverse("computes")) + response = self.client.get(reverse('computes')) self.assertEqual(response.status_code, 200) def test_create_update_delete(self): - response = self.client.get(reverse("add_socket_host")) + response = self.client.get(reverse('add_socket_host')) self.assertEqual(response.status_code, 200) response = self.client.post( - reverse("add_socket_host"), + reverse('add_socket_host'), { - "name": "l1", - "details": "Created", - "hostname": "localhost", - "type": 4, + 'name': 'l1', + 'details': 'Created', + 'hostname': 'localhost', + 'type': 4, }, ) - self.assertRedirects(response, reverse("computes")) + self.assertRedirects(response, reverse('computes')) compute = Compute.objects.get(pk=2) - self.assertEqual(compute.name, "l1") - self.assertEqual(compute.details, "Created") + self.assertEqual(compute.name, 'l1') + self.assertEqual(compute.details, 'Created') - response = self.client.get(reverse("compute_update", args=[2])) + response = self.client.get(reverse('compute_update', args=[2])) self.assertEqual(response.status_code, 200) response = self.client.post( - reverse("compute_update", args=[2]), + reverse('compute_update', args=[2]), { - "name": "l2", - "details": "Updated", - "hostname": "localhost", - "type": 4, + 'name': 'l2', + 'details': 'Updated', + 'hostname': 'localhost', + 'type': 4, }, ) - self.assertRedirects(response, reverse("computes")) + self.assertRedirects(response, reverse('computes')) compute = Compute.objects.get(pk=2) - self.assertEqual(compute.name, "l2") - self.assertEqual(compute.details, "Updated") + self.assertEqual(compute.name, 'l2') + self.assertEqual(compute.details, 'Updated') - response = self.client.get(reverse("compute_delete", args=[2])) + response = self.client.get(reverse('compute_delete', args=[2])) self.assertEqual(response.status_code, 200) - response = self.client.post(reverse("compute_delete", args=[2])) - self.assertRedirects(response, reverse("computes")) + response = self.client.post(reverse('compute_delete', args=[2])) + self.assertRedirects(response, reverse('computes')) with self.assertRaises(ObjectDoesNotExist): Compute.objects.get(id=2) def test_overview(self): - response = self.client.get(reverse("overview", args=[1])) + response = self.client.get(reverse('overview', args=[1])) self.assertEqual(response.status_code, 200) def test_graph(self): - response = self.client.get(reverse("compute_graph", args=[1])) + response = self.client.get(reverse('compute_graph', args=[1])) self.assertEqual(response.status_code, 200) def test_instances(self): - response = self.client.get(reverse("instances", args=[1])) + response = self.client.get(reverse('instances', args=[1])) self.assertEqual(response.status_code, 200) def test_storages(self): - response = self.client.get(reverse("storages", args=[1])) + response = self.client.get(reverse('storages', args=[1])) self.assertEqual(response.status_code, 200) def test_storage(self): pass def test_default_storage_volumes(self): - response = self.client.get( - reverse("volumes", kwargs={"compute_id": 1, "pool": "default"}) - ) + response = self.client.get(reverse('volumes', kwargs={'compute_id': 1, 'pool': 'default'})) self.assertEqual(response.status_code, 200) def test_default_storage(self): - response = self.client.get( - reverse("storage", kwargs={"compute_id": 1, "pool": "default"}) - ) + response = self.client.get(reverse('storage', kwargs={'compute_id': 1, 'pool': 'default'})) self.assertEqual(response.status_code, 200) def test_networks(self): - response = self.client.get(reverse("networks", args=[1])) + response = self.client.get(reverse('networks', args=[1])) self.assertEqual(response.status_code, 200) def test_default_network(self): - response = self.client.get( - reverse("network", kwargs={"compute_id": 1, "pool": "default"}) - ) + response = self.client.get(reverse('network', kwargs={'compute_id': 1, 'pool': 'default'})) self.assertEqual(response.status_code, 200) def test_interfaces(self): - response = self.client.get(reverse("interfaces", args=[1])) + response = self.client.get(reverse('interfaces', args=[1])) self.assertEqual(response.status_code, 200) # TODO: add test for single interface def test_nwfilters(self): - response = self.client.get(reverse("nwfilters", args=[1])) + response = self.client.get(reverse('nwfilters', args=[1])) self.assertEqual(response.status_code, 200) # TODO: add test for single nwfilter def test_secrets(self): - response = self.client.get(reverse("virtsecrets", args=[1])) + response = self.client.get(reverse('virtsecrets', args=[1])) self.assertEqual(response.status_code, 200) # def test_create_instance_select_type(self): @@ -131,29 +125,19 @@ class ComputesTestCase(TestCase): # TODO: create_instance def test_machines(self): - response = self.client.get( - reverse("machines", kwargs={"compute_id": 1, "arch": "x86_64"}) - ) + response = self.client.get(reverse('machines', kwargs={'compute_id': 1, 'arch': 'x86_64'})) self.assertEqual(response.status_code, 200) def test_compute_disk_buses(self): response = self.client.get( - reverse( - "buses", - kwargs={ - "compute_id": 1, - "arch": "x86_64", - "machine": "pc", - "disk": "disk", - }, - ) - ) + reverse('buses', kwargs={ + 'compute_id': 1, + 'arch': 'x86_64', + 'machine': 'pc', + 'disk': 'disk', + })) self.assertEqual(response.status_code, 200) def test_dom_capabilities(self): - response = self.client.get( - reverse( - "domcaps", kwargs={"compute_id": 1, "arch": "x86_64", "machine": "pc"} - ) - ) + response = self.client.get(reverse('domcaps', kwargs={'compute_id': 1, 'arch': 'x86_64', 'machine': 'pc'})) self.assertEqual(response.status_code, 200) diff --git a/computes/urls.py b/computes/urls.py index 586f73f..8938107 100644 --- a/computes/urls.py +++ b/computes/urls.py @@ -9,71 +9,36 @@ from storages.views import create_volume, get_volumes, storage, storages from . import forms, views urlpatterns = [ - path("", views.computes, name="computes"), + path('', views.computes, name='computes'), + path('add_tcp_host/', views.compute_create, {'FormClass': forms.TcpComputeForm}, name='add_tcp_host'), + path('add_ssh_host/', views.compute_create, {'FormClass': forms.SshComputeForm}, name='add_ssh_host'), + path('add_tls_host/', views.compute_create, {'FormClass': forms.TlsComputeForm}, name='add_tls_host'), + path('add_socket_host/', views.compute_create, {'FormClass': forms.SocketComputeForm}, name='add_socket_host'), path( - "add_tcp_host/", - views.compute_create, - {"FormClass": forms.TcpComputeForm}, - name="add_tcp_host", - ), - path( - "add_ssh_host/", - views.compute_create, - {"FormClass": forms.SshComputeForm}, - name="add_ssh_host", - ), - path( - "add_tls_host/", - views.compute_create, - {"FormClass": forms.TlsComputeForm}, - name="add_tls_host", - ), - path( - "add_socket_host/", - views.compute_create, - {"FormClass": forms.SocketComputeForm}, - name="add_socket_host", - ), - path( - "/", - include( - [ - path("", views.overview, name="overview"), - path("update/", views.compute_update, name="compute_update"), - path("delete/", views.compute_delete, name="compute_delete"), - path("statistics", views.compute_graph, name="compute_graph"), - path("instances/", views.instances, name="instances"), - path("storages/", storages, name="storages"), - path("storage//volumes/", get_volumes, name="volumes"), - path("storage//", storage, name="storage"), - path( - "storage//create_volume/", - create_volume, - name="create_volume", - ), - path("networks/", networks, name="networks"), - path("network//", network, name="network"), - path("interfaces/", interfaces, name="interfaces"), - path("interface//", interface, name="interface"), - path("nwfilters/", nwfilters, name="nwfilters"), - path("nwfilter//", nwfilter, name="nwfilter"), - path("virtsecrets/", secrets, name="virtsecrets"), - path( - "archs//machines/", - views.get_compute_machine_types, - name="machines", - ), - path( - "archs//machines//disks//buses/", - views.get_compute_disk_buses, - name="buses", - ), - path( - "archs//machines//capabilities/", - views.get_dom_capabilities, - name="domcaps", - ), - ] - ), - ), + '/', + include([ + path('', views.overview, name='overview'), + path('update/', views.compute_update, name='compute_update'), + path('delete/', views.compute_delete, name='compute_delete'), + path('statistics', views.compute_graph, name='compute_graph'), + path('instances/', views.instances, name='instances'), + path('storages/', storages, name='storages'), + path('storage//volumes/', get_volumes, name='volumes'), + path('storage//', storage, name='storage'), + path('storage//create_volume/', create_volume, name='create_volume'), + path('networks/', networks, name='networks'), + path('network//', network, name='network'), + path('interfaces/', interfaces, name='interfaces'), + path('interface//', interface, name='interface'), + path('nwfilters/', nwfilters, name='nwfilters'), + path('nwfilter//', nwfilter, name='nwfilter'), + path('virtsecrets/', secrets, name='virtsecrets'), + path('archs//machines/', views.get_compute_machine_types, name='machines'), + path( + 'archs//machines//disks//buses/', + views.get_compute_disk_buses, + name='buses', + ), + path('archs//machines//capabilities/', views.get_dom_capabilities, name='domcaps'), + ])), ] diff --git a/computes/utils.py b/computes/utils.py index 881f5eb..05feb03 100644 --- a/computes/utils.py +++ b/computes/utils.py @@ -9,7 +9,7 @@ def refresh_instance_database(compute): Instance.objects.filter(compute=compute).exclude(name__in=domain_names).delete() Instance.objects.filter(compute=compute).exclude(uuid__in=domain_uuids).delete() # Create instances that're on host but not in DB - names = Instance.objects.filter(compute=compute).values_list("name", flat=True) + names = Instance.objects.filter(compute=compute).values_list('name', flat=True) for domain in domains: if domain.name() not in names: - Instance( compute=compute, name=domain.name(), uuid=domain.UUIDString()).save() + Instance(compute=compute, name=domain.name(), uuid=domain.UUIDString()).save() diff --git a/computes/validators.py b/computes/validators.py index dbb79ee..64458fc 100644 --- a/computes/validators.py +++ b/computes/validators.py @@ -3,9 +3,9 @@ import re from django.core.exceptions import ValidationError from django.utils.translation import gettext_lazy as _ -have_symbol = re.compile("[^a-zA-Z0-9._-]+") -wrong_ip = re.compile("^0.|^255.") -wrong_name = re.compile("[^a-zA-Z0-9._-]+") +have_symbol = re.compile('[^a-zA-Z0-9._-]+') +wrong_ip = re.compile('^0.|^255.') +wrong_name = re.compile('[^a-zA-Z0-9._-]+') def validate_hostname(value): @@ -13,14 +13,12 @@ def validate_hostname(value): wip = wrong_ip.match(value) if sym: - raise ValidationError( - _('Hostname must contain only numbers, or the domain name separated by "."') - ) + raise ValidationError(_('Hostname must contain only numbers, or the domain name separated by "."')) elif wip: - raise ValidationError(_("Wrong IP address")) + raise ValidationError(_('Wrong IP address')) def validate_name(value): - have_symbol = wrong_name.match("[^a-zA-Z0-9._-]+") + have_symbol = wrong_name.match('[^a-zA-Z0-9._-]+') if have_symbol: - raise ValidationError(_("The hostname must not contain any special characters")) + raise ValidationError(_('The hostname must not contain any special characters')) diff --git a/computes/views.py b/computes/views.py index 0883b54..7d9184b 100644 --- a/computes/views.py +++ b/computes/views.py @@ -7,12 +7,7 @@ from django.utils import timezone from libvirt import libvirtError from admin.decorators import superuser_only -from computes.forms import ( - SocketComputeForm, - SshComputeForm, - TcpComputeForm, - TlsComputeForm, -) +from computes.forms import SocketComputeForm, SshComputeForm, TcpComputeForm, TlsComputeForm from computes.models import Compute from instances.models import Instance from vrtManager.connection import ( @@ -44,8 +39,7 @@ def computes(request): def overview(request, compute_id): compute = get_object_or_404(Compute, pk=compute_id) status = ( - "true" - if connection_manager.host_is_up(compute.type, compute.hostname) is True else "false" + "true" if connection_manager.host_is_up(compute.type, compute.hostname) is True else "false" ) conn = wvmHostDetails( @@ -54,14 +48,7 @@ def overview(request, compute_id): compute.password, compute.type, ) - ( - hostname, - host_arch, - host_memory, - logical_cpu, - model_cpu, - uri_conn, - ) = conn.get_node_info() + hostname, host_arch, host_memory, logical_cpu, model_cpu, uri_conn = conn.get_node_info() hypervisor = conn.get_hypervisors_domain_types() mem_usage = conn.get_memory_usage() emulator = conn.get_emulator(host_arch) @@ -77,15 +64,9 @@ def instances(request, compute_id): compute = get_object_or_404(Compute, pk=compute_id) utils.refresh_instance_database(compute) - instances = Instance.objects.filter(compute=compute).prefetch_related( - "userinstance_set" - ) + instances = Instance.objects.filter(compute=compute).prefetch_related("userinstance_set") - return render( - request, - "computes/instances.html", - {"compute": compute, "instances": instances} - ) + return render(request, "computes/instances.html", {"compute": compute, "instances": instances}) @superuser_only diff --git a/conf/requirements.txt b/conf/requirements.txt index eac1d67..d2bf6a7 100644 --- a/conf/requirements.txt +++ b/conf/requirements.txt @@ -1,12 +1,12 @@ -Django==3.2.16 +Django==3.2.15 django_bootstrap5==22.1 django-icons==22.1 -django-login-required-middleware==0.9.0 +django-login-required-middleware==0.8 django-otp==1.1.3 -django-qr-code==3.1.1 +django-qr-code==2.3.0 gunicorn==20.1.0 libsass==0.21.0 -libvirt-python==8.8.0 +libvirt-python==8.6.0 lxml==4.9.1 qrcode==7.3.1 rwlock==0.0.7 @@ -16,7 +16,7 @@ ldap3==2.9.1 python-engineio==4.3.4 python-socketio==5.7.1 eventlet==0.33.1 -djangorestframework==3.14.0 +djangorestframework==3.13.1 drf-nested-routers==0.93.4 -drf-yasg==1.21.4 +drf-yasg==1.21.3 markdown==3.4.1 diff --git a/console/novncd b/console/novncd index 08cb51d..59ff686 100755 --- a/console/novncd +++ b/console/novncd @@ -6,9 +6,9 @@ import logging import django DIR_PATH = os.path.dirname(os.path.abspath(__file__)) -ROOT_PATH = os.path.abspath(os.path.join(DIR_PATH, "..", "")) -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "webvirtcloud.settings") -CERT = DIR_PATH + "/cert.pem" +ROOT_PATH = os.path.abspath(os.path.join(DIR_PATH, '..', '')) +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'webvirtcloud.settings') +CERT = DIR_PATH + '/cert.pem' if ROOT_PATH not in sys.path: sys.path.append(ROOT_PATH) @@ -17,8 +17,7 @@ django.setup() import re import socket - -# from six.moves import http_cookies as Cookie +#from six.moves import http_cookies as Cookie from http import cookies as Cookie from webvirtcloud.settings import WS_PORT, WS_HOST, WS_CERT from vrtManager.connection import CONN_SSH, CONN_SOCKET @@ -27,40 +26,40 @@ from optparse import OptionParser parser = OptionParser() -parser.add_option( - "-v", - "--verbose", - dest="verbose", - action="store_true", - help="Verbose mode", - default=False, -) +parser.add_option("-v", + "--verbose", + dest="verbose", + action="store_true", + help="Verbose mode", + default=False) -parser.add_option( - "-d", "--debug", dest="debug", action="store_true", help="Debug mode", default=False -) +parser.add_option("-d", + "--debug", + dest="debug", + action="store_true", + help="Debug mode", + default=False) -parser.add_option( - "-H", "--host", dest="host", action="store", help="Listen host", default=WS_HOST -) +parser.add_option("-H", + "--host", + dest="host", + action="store", + help="Listen host", + default=WS_HOST) -parser.add_option( - "-p", - "--port", - dest="port", - action="store", - help="Listen port", - default=WS_PORT or 6080, -) +parser.add_option("-p", + "--port", + dest="port", + action="store", + help="Listen port", + default=WS_PORT or 6080) -parser.add_option( - "-c", - "--cert", - dest="cert", - action="store", - help="Certificate file path", - default=WS_CERT or CERT, -) +parser.add_option("-c", + "--cert", + dest="cert", + action="store", + help="Certificate file path", + default=WS_CERT or CERT) (options, args) = parser.parse_args() @@ -75,7 +74,6 @@ else: try: from websockify import WebSocketProxy - try: from websockify import ProxyRequestHandler except ImportError: @@ -86,7 +84,7 @@ except ImportError: try: from novnc.wsproxy import WebSocketProxy except ImportError: - print("Unable to import a websockify implementation,\n please install one") + print('Unable to import a websockify implementation,\n please install one') sys.exit(1) else: USE_HANDLER = False @@ -97,20 +95,18 @@ def get_connection_infos(token): from vrtManager.instance import wvmInstance try: - temptoken = token.split("-", 1) + temptoken = token.split('-', 1) host = int(temptoken[0]) uuid = temptoken[1] instance = Instance.objects.get(compute_id=host, uuid=uuid) - conn = wvmInstance( - instance.compute.hostname, - instance.compute.login, - instance.compute.password, - instance.compute.type, - instance.name, - ) - if instance.compute.hostname.count(":"): - connhost = instance.compute.hostname.split(":")[0] - connport = instance.compute.hostname.split(":")[1] + conn = wvmInstance(instance.compute.hostname, + instance.compute.login, + instance.compute.password, + instance.compute.type, + instance.name) + if instance.compute.hostname.count(':'): + connhost = instance.compute.hostname.split(':')[0] + connport = instance.compute.hostname.split(':')[1] else: connhost = instance.compute.hostname connport = 22 @@ -121,18 +117,10 @@ def get_connection_infos(token): console_socket = conn.get_console_socket() except Exception as e: logging.error( - "Fail to retrieve console connection infos for token %s : %s" % (token, e) - ) + 'Fail to retrieve console connection infos for token %s : %s' % (token, e)) raise - return ( - connhost, - connport, - connuser, - conntype, - console_host, - console_port, - console_socket, - ) + return (connhost, connport, connuser, conntype, console_host, + console_port, console_socket) class CompatibilityMixIn(object): @@ -140,31 +128,25 @@ class CompatibilityMixIn(object): # NoVNC uses it's own convention that forward token # from the request to a cookie header, we should check # also for this behavior - hcookie = self.headers.get("cookie") + hcookie = self.headers.get('cookie') if hcookie: cookie = Cookie.SimpleCookie() - for hcookie_part in hcookie.split(";"): + for hcookie_part in hcookie.split(';'): hcookie_part = hcookie_part.lstrip() try: cookie.load(hcookie_part) except Cookie.CookieError: # NOTE(stgleb): Do not print out cookie content # for security reasons. - self.msg("Found malformed cookie") + self.msg('Found malformed cookie') else: - if "token" in cookie: - token = cookie["token"].value + if 'token' in cookie: + token = cookie['token'].value - ( - connhost, - connport, - connuser, - conntype, - console_host, - console_port, - console_socket, - ) = get_connection_infos(token) + + (connhost, connport, connuser, conntype, console_host, console_port, + console_socket) = get_connection_infos(token) cnx_debug_msg = "Connection infos :\n" cnx_debug_msg += "- connhost : '%s'\n" % connhost @@ -178,16 +160,14 @@ class CompatibilityMixIn(object): if console_socket and conntype == CONN_SOCKET: # Local socket on local host - self.msg("Try to open local socket %s" % console_socket) + self.msg('Try to open local socket %s' % console_socket) tsock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) tsock.connect(console_socket) - elif console_socket or re.match("^127\.", console_host): + elif console_socket or re.match('^127\.', console_host): # Need tunnel to physical host if conntype != CONN_SSH: - self.msg( - "Need a tunnel to access console but can't mount " - + "one because it's not a SSH host" - ) + self.msg("Need a tunnel to access console but can't mount " + + "one because it's not a SSH host") raise Exception(self.msg) try: # generate a string with all placeholders to avoid TypeErrors @@ -195,25 +175,10 @@ class CompatibilityMixIn(object): # https://github.com/retspen/webvirtmgr/pull/497 error_msg = "Try to open tunnel on %s@%s:%s on console %s:%s " error_msg += "(or socket %s)" - self.msg( - error_msg - % ( - connuser, - connhost, - connport, - console_host, - console_port, - console_socket, - ) - ) - tunnel = SSHTunnels( - connhost, - connuser, - connport, - console_host, - console_port, - console_socket, - ) + self.msg(error_msg % (connuser, connhost, connport, + console_host, console_port, console_socket)) + tunnel = SSHTunnels(connhost, connuser, connport, + console_host, console_port, console_socket) fd = tunnel.open_new() tunnel.unlock() tsock = socket.fromfd(fd, socket.AF_INET, socket.SOCK_STREAM) @@ -237,18 +202,15 @@ class CompatibilityMixIn(object): except Exception: if tunnel: self.vmsg( - "%s:%s (via %s@%s:%s) : Websocket client or Target closed" - % (console_host, console_port, connuser, connhost, connport) - ) + "%s:%s (via %s@%s:%s) : Websocket client or Target closed" % + (console_host, console_port, connuser, connhost, connport)) if tsock: tsock.shutdown(socket.SHUT_RDWR) tsock.close() tunnel.close_all() raise - if USE_HANDLER: - class NovaProxyRequestHandler(ProxyRequestHandler, CompatibilityMixIn): def msg(self, *args, **kwargs): self.log_message(*args, **kwargs) @@ -266,10 +228,9 @@ if USE_HANDLER: socket_factory = self.server.socket self._new_client(daemon, socket_factory) - else: - class NovaWebSocketProxy(WebSocketProxy, CompatibilityMixIn): + def new_client(self): """ Called after a new WebSocket connection has been established. @@ -280,44 +241,39 @@ else: self._new_client(daemon, socket_factory) - -if __name__ == "__main__": +if __name__ == '__main__': if USE_HANDLER: # Create the WebSocketProxy with NovaProxyRequestHandler handler - server = WebSocketProxy( - RequestHandlerClass=NovaProxyRequestHandler, - listen_host=options.host, - listen_port=options.port, - source_is_ipv6=False, - verbose=options.verbose, - cert=options.cert, - key=None, - ssl_only=False, - daemon=False, - record=False, - web=False, - traffic=False, - target_host="ignore", - target_port="ignore", - wrap_mode="exit", - wrap_cmd=None, - ) + server = WebSocketProxy(RequestHandlerClass=NovaProxyRequestHandler, + listen_host=options.host, + listen_port=options.port, + source_is_ipv6=False, + verbose=options.verbose, + cert=options.cert, + key=None, + ssl_only=False, + daemon=False, + record=False, + web=False, + traffic=False, + target_host='ignore', + target_port='ignore', + wrap_mode='exit', + wrap_cmd=None) else: # Create the NovaWebSockets proxy - server = NovaWebSocketProxy( - listen_host=options.host, - listen_port=options.port, - source_is_ipv6=False, - verbose=options.verbose, - cert=options.cert, - key=None, - ssl_only=False, - daemon=False, - record=False, - web=False, - target_host="ignore", - target_port="ignore", - wrap_mode="exit", - wrap_cmd=None, - ) + server = NovaWebSocketProxy(listen_host=options.host, + listen_port=options.port, + source_is_ipv6=False, + verbose=options.verbose, + cert=options.cert, + key=None, + ssl_only=False, + daemon=False, + record=False, + web=False, + target_host='ignore', + target_port='ignore', + wrap_mode='exit', + wrap_cmd=None) server.start_server() diff --git a/console/socketiod b/console/socketiod index dbd38bc..7057d9a 100755 --- a/console/socketiod +++ b/console/socketiod @@ -5,9 +5,9 @@ import logging import django DIR_PATH = os.path.dirname(os.path.abspath(__file__)) -ROOT_PATH = os.path.abspath(os.path.join(DIR_PATH, "..", "")) -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "webvirtcloud.settings") -CERT = DIR_PATH + "/cert.pem" +ROOT_PATH = os.path.abspath(os.path.join(DIR_PATH, '..', '')) +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'webvirtcloud.settings') +CERT = DIR_PATH + '/cert.pem' if ROOT_PATH not in sys.path: sys.path.append(ROOT_PATH) @@ -32,7 +32,7 @@ import tty import termios import libvirt -# from six.moves import http_cookies as Cookie +#from six.moves import http_cookies as Cookie from http import cookies as Cookie from webvirtcloud.settings import SOCKETIO_PORT, SOCKETIO_HOST from vrtManager.connection import CONN_SSH, CONN_SOCKET @@ -40,36 +40,33 @@ from optparse import OptionParser parser = OptionParser() -parser.add_option( - "-v", - "--verbose", - dest="verbose", - action="store_true", - help="Verbose mode", - default=False, -) +parser.add_option("-v", + "--verbose", + dest="verbose", + action="store_true", + help="Verbose mode", + default=False) -parser.add_option( - "-d", "--debug", dest="debug", action="store_true", help="Debug mode", default=False -) +parser.add_option("-d", + "--debug", + dest="debug", + action="store_true", + help="Debug mode", + default=False) -parser.add_option( - "-H", - "--host", - dest="host", - action="store", - help="Listen host", - default=SOCKETIO_HOST, -) +parser.add_option("-H", + "--host", + dest="host", + action="store", + help="Listen host", + default=SOCKETIO_HOST) -parser.add_option( - "-p", - "--port", - dest="port", - action="store", - help="Listen port", - default=SOCKETIO_PORT or 6081, -) +parser.add_option("-p", + "--port", + dest="port", + action="store", + help="Listen port", + default=SOCKETIO_PORT or 6081) (options, args) = parser.parse_args() @@ -88,31 +85,26 @@ sio = socketio.Server(async_mode=async_mode, cors_allowed_origins=[]) fd = None child_pid = None - def get_connection_infos(token): from instances.models import Instance from vrtManager.instance import wvmInstance try: - temptoken = token.split("-", 1) + temptoken = token.split('-', 1) host = int(temptoken[0]) uuid = temptoken[1] instance = Instance.objects.get(compute_id=host, uuid=uuid) - conn = wvmInstance( - instance.compute.hostname, - instance.compute.login, - instance.compute.password, - instance.compute.type, - instance.name, - ) + conn = wvmInstance(instance.compute.hostname, + instance.compute.login, + instance.compute.password, + instance.compute.type, + instance.name) except Exception as e: logging.error( - "Fail to retrieve console connection infos for token %s : %s" % (token, e) - ) + 'Fail to retrieve console connection infos for token %s : %s' % (token, e)) raise return (instance, conn) - def set_winsize(fd, row, col, xpix=0, ypix=0): winsize = struct.pack("HHHH", row, col, xpix, ypix) fcntl.ioctl(fd, termios.TIOCSWINSZ, winsize) @@ -131,44 +123,41 @@ def read_and_forward_pty_output(): sio.emit("pty_output", {"output": output}) else: return - + @sio.event -def resize(sid, message): +def resize(sid, message): global fd if fd: set_winsize(fd, message["rows"], message["cols"]) - @sio.event def pty_input(sid, message): global fd if fd: os.write(fd, message["input"].encode()) - @sio.event def disconnect_request(sid): sio.disconnect(sid) - @sio.event def connect(sid, environ): global fd global child_pid - hcookie = environ.get("HTTP_COOKIE") + hcookie = environ.get('HTTP_COOKIE') if hcookie: cookie = Cookie.SimpleCookie() - for hcookie_part in hcookie.split(";"): + for hcookie_part in hcookie.split(';'): hcookie_part = hcookie_part.lstrip() try: cookie.load(hcookie_part) except Cookie.CookieError: - logging.warn("Found malformed cookie") + logging.warn('Found malformed cookie') else: - if "token" in cookie: - token = cookie["token"].value + if 'token' in cookie: + token = cookie['token'].value if child_pid: # already started child process, don't start another @@ -181,15 +170,14 @@ def connect(sid, environ): if child_pid == 0: (instance, conn) = get_connection_infos(token) - uuid = conn.get_uuid() + uuid = conn.get_uuid() uri = conn.wvm.getURI() - - subprocess.run(["conf/daemon/consolecallback", uri, uuid]) + + subprocess.run(['conf/daemon/consolecallback', uri, uuid]) else: # this is the parent process fork. sio.start_background_task(target=read_and_forward_pty_output) - @sio.event def disconnect(sid): @@ -197,15 +185,13 @@ def disconnect(sid): global child_pid # kill pty process - os.kill(child_pid, signal.SIGKILL) + os.kill(child_pid,signal.SIGKILL) os.wait() # reset the variables fd = None child_pid = None - app = socketio.WSGIApp(sio) import eventlet - -eventlet.wsgi.server(eventlet.listen((options.host, int(options.port))), app) +eventlet.wsgi.server(eventlet.listen((options.host,int(options.port))), app) diff --git a/console/sshtunnels.py b/console/sshtunnels.py index 7f0376e..06f4c9d 100644 --- a/console/sshtunnels.py +++ b/console/sshtunnels.py @@ -28,19 +28,15 @@ class _TunnelScheduler(object): def _handle_queue(self): while True: - ( - lock_cb, - cb, - args, - ) = self._queue.get() + lock_cb, cb, args, = self._queue.get() lock_cb() cb(*args) def schedule(self, lock_cb, cb, *args): if not self._thread: - self._thread = threading.Thread( - name="Tunnel thread", target=self._handle_queue, args=() - ) + self._thread = threading.Thread(name="Tunnel thread", + target=self._handle_queue, + args=()) self._thread.daemon = True if not self._thread.is_alive(): self._thread.start() @@ -67,11 +63,8 @@ class _Tunnel(object): return self._closed = True - log.debug( - "Close tunnel PID=%s ERRFD=%s", - self._pid, - self._errfd and self._errfd.fileno() or None, - ) + log.debug("Close tunnel PID=%s ERRFD=%s", + self._pid, self._errfd and self._errfd.fileno() or None) # Since this is a socket object, the file descriptor is closed # when it's garbage collected. @@ -117,7 +110,8 @@ class _Tunnel(object): self._errfd = errfds[0] self._errfd.setblocking(0) - log.debug("Opened tunnel PID=%d ERRFD=%d", pid, self._errfd.fileno()) + log.debug("Opened tunnel PID=%d ERRFD=%d", + pid, self._errfd.fileno()) self._pid = pid @@ -130,7 +124,7 @@ def _make_ssh_command(connhost, connuser, connport, gaddr, gport, gsocket): argv += ["-p", str(connport)] if connuser: - argv += ["-l", connuser] + argv += ['-l', connuser] argv += [connhost] @@ -157,8 +151,8 @@ def _make_ssh_command(connhost, connuser, connport, gaddr, gport, gsocket): """else""" """ CMD="nc %(nc_params)s";""" """fi;""" - """eval "$CMD";""" % {"nc_params": nc_params} - ) + """eval "$CMD";""" % + {'nc_params': nc_params}) argv.append("sh -c") argv.append("'%s'" % nc_cmd) @@ -172,8 +166,7 @@ class SSHTunnels(object): def __init__(self, connhost, connuser, connport, gaddr, gport, gsocket): self._tunnels = [] self._sshcommand = _make_ssh_command( - connhost, connuser, connport, gaddr, gport, gsocket - ) + connhost, connuser, connport, gaddr, gport, gsocket) self._locked = False def open_new(self): diff --git a/console/views.py b/console/views.py index f530df1..43dd82e 100644 --- a/console/views.py +++ b/console/views.py @@ -17,7 +17,7 @@ from webvirtcloud.settings import ( WS_PUBLIC_PORT, SOCKETIO_PUBLIC_HOST, SOCKETIO_PUBLIC_PORT, - SOCKETIO_PUBLIC_PATH, + SOCKETIO_PUBLIC_PATH ) @@ -31,39 +31,32 @@ def console(request): if request.method == "GET": token = request.GET.get("token", "") view_type = request.GET.get("view", "lite") - view_only = request.GET.get("view_only", app_settings.CONSOLE_VIEW_ONLY.lower()) + view_only = request.GET.get( + "view_only", app_settings.CONSOLE_VIEW_ONLY.lower()) scale = request.GET.get("scale", app_settings.CONSOLE_SCALE.lower()) resize_session = request.GET.get( - "resize_session", app_settings.CONSOLE_RESIZE_SESSION.lower() - ) + "resize_session", app_settings.CONSOLE_RESIZE_SESSION.lower()) clip_viewport = request.GET.get( - "clip_viewport", app_settings.CONSOLE_CLIP_VIEWPORT.lower() - ) + "clip_viewport", app_settings.CONSOLE_CLIP_VIEWPORT.lower()) try: temptoken = token.split("-", 1) host = int(temptoken[0]) uuid = temptoken[1] - if not request.user.is_superuser and not request.user.has_perm( - "instances.view_instances" - ): + if not request.user.is_superuser and not request.user.has_perm("instances.view_instances"): try: userInstance = UserInstance.objects.get( - instance__compute_id=host, - instance__uuid=uuid, - user__id=request.user.id, + instance__compute_id=host, instance__uuid=uuid, user__id=request.user.id ) instance = Instance.objects.get(compute_id=host, uuid=uuid) except UserInstance.DoesNotExist: instance = None - console_error = _( - "User does not have permission to access console or host/instance not exist" - ) + console_error = _("User does not have permission to access console or host/instance not exist") return HttpResponseServerError(console_error) else: instance = Instance.objects.get(compute_id=host, uuid=uuid) - + conn = wvmInstance( instance.compute.hostname, instance.compute.login, @@ -90,9 +83,7 @@ def console(request): console_page = "console-" + console_type + "-" + view_type + ".html" response = render(request, console_page, locals()) elif console_type == "pty": - socketio_host = ( - SOCKETIO_PUBLIC_HOST if SOCKETIO_PUBLIC_HOST else request.get_host() - ) + socketio_host = SOCKETIO_PUBLIC_HOST if SOCKETIO_PUBLIC_HOST else request.get_host() socketio_port = SOCKETIO_PUBLIC_PORT if SOCKETIO_PUBLIC_PORT else 6081 socketio_path = SOCKETIO_PUBLIC_PATH if SOCKETIO_PUBLIC_PATH else "/" @@ -102,13 +93,9 @@ def console(request): response = render(request, "console-xterm.html", locals()) else: if console_type is None: - console_error = _( - "Fail to get console. Please check the console configuration of your VM." - ) + console_error = _("Fail to get console. Please check the console configuration of your VM.") else: - console_error = _("Console type '%(type)s' has not support") % { - "type": console_type - } + console_error = _("Console type '%(type)s' has not support") % {"type": console_type} response = render(request, "console-vnc-lite.html", locals()) response.set_cookie("token", token) diff --git a/datasource/urls.py b/datasource/urls.py index 4c8f512..cba7517 100644 --- a/datasource/urls.py +++ b/datasource/urls.py @@ -3,14 +3,8 @@ from django.urls import path from . import views urlpatterns = [ - path("openstack/", views.os_index, name="ds_openstack_index"), - path( - "openstack//meta_data.json", - views.os_metadata_json, - name="ds_openstack_metadata", - ), - path( - "openstack//user_data", views.os_userdata, name="ds_openstack_userdata" - ), - path("vdi///", views.get_vdi_url, name="vdi_url"), + path('openstack/', views.os_index, name='ds_openstack_index'), + path('openstack//meta_data.json', views.os_metadata_json, name='ds_openstack_metadata'), + path('openstack//user_data', views.os_userdata, name='ds_openstack_userdata'), + path('vdi///', views.get_vdi_url, name='vdi_url'), ] diff --git a/datasource/views.py b/datasource/views.py index ce74650..1a18ff5 100644 --- a/datasource/views.py +++ b/datasource/views.py @@ -99,13 +99,7 @@ def get_vdi_url(request, compute_id, vname): compute = get_object_or_404(Compute, pk=compute_id) try: - conn = wvmInstance( - compute.hostname, - compute.login, - compute.password, - compute.type, - vname - ) + conn = wvmInstance(compute.hostname, compute.login, compute.password, compute.type, vname) fqdn = get_hostname_by_ip(compute.hostname) url = f"{conn.get_console_type()}://{fqdn}:{conn.get_console_port()}" diff --git a/dev/requirements.txt b/dev/requirements.txt index 2007735..0e8ec79 100644 --- a/dev/requirements.txt +++ b/dev/requirements.txt @@ -1,8 +1,7 @@ -r ../conf/requirements.txt -coverage==6.5.0 -django-debug-toolbar==3.7.0 +coverage==6.4.4 +django-debug-toolbar==3.6.0 pycodestyle==2.9.1 pyflakes==2.5.0 -pylint==2.15.3 +pylint==2.14.5 yapf==0.32.0 -black \ No newline at end of file diff --git a/instances/api/serializers.py b/instances/api/serializers.py index dab19aa..7e0c0d9 100644 --- a/instances/api/serializers.py +++ b/instances/api/serializers.py @@ -4,88 +4,90 @@ from instances.models import Flavor, Instance, MigrateInstance, CreateInstance class InstanceSerializer(serializers.ModelSerializer): + class Meta: model = Instance - fields = ["id", "compute", "name", "uuid", "is_template", "created", "drbd"] + fields = ['id', 'compute', 'name', 'uuid', 'is_template', 'created', 'drbd'] class InstanceDetailsSerializer(serializers.ModelSerializer): + class Meta: model = Instance fields = [ - "id", - "compute", - "status", - "uuid", - "name", - "title", - "description", - "is_template", - "created", - "drbd", - "arch", - "machine", - "vcpu", - "memory", - "firmware", - "nvram", - "bootmenu", - "boot_order", - "disks", - "media", - "media_iso", - "snapshots", - "networks", - "console_type", - "console_port", - "console_keymap", - "console_listener_address", - "video_model", - "guest_agent_ready", - "autostart", - ] + 'id', + 'compute', + 'status', + 'uuid', + 'name', + 'title', + 'description', + 'is_template', + 'created', + 'drbd', + 'arch', + 'machine', + 'vcpu', + 'memory', + 'firmware', + 'nvram', + 'bootmenu', + 'boot_order', + 'disks', + 'media', + 'media_iso', + 'snapshots', + 'networks', + 'console_type', + 'console_port', + 'console_keymap', + 'console_listener_address', + 'video_model', + 'guest_agent_ready', + 'autostart'] class FlavorSerializer(serializers.ModelSerializer): + class Meta: model = Flavor - fields = ["label", "memory", "vcpu", "disk"] + fields = ['label', 'memory', 'vcpu', 'disk'] class CreateInstanceSerializer(serializers.ModelSerializer): firmware_choices = ( - ("", "BIOS"), - # ('UEFI', 'UEFI'), + ('', 'BIOS'), + #('UEFI', 'UEFI'), ) - firmware = serializers.ChoiceField(choices=firmware_choices) - graphics = serializers.CharField(initial="vnc") - video = serializers.CharField(initial="vga") - storage = serializers.CharField(initial="default") - cache_mode = serializers.CharField(initial="none") + firmware = serializers.ChoiceField(choices = firmware_choices) + graphics = serializers.CharField(initial='vnc') + video = serializers.CharField(initial='vga') + storage = serializers.CharField(initial='default') + cache_mode = serializers.CharField(initial='none') virtio = serializers.BooleanField(initial=True) qemu_ga = serializers.BooleanField(initial=True) class Meta: model = CreateInstance fields = [ - "name", - "firmware", - "vcpu", - "vcpu_mode", - "memory", - "networks", - "mac", - "nwfilter", - "storage", - "hdd_size", - "cache_mode", - "meta_prealloc", - "virtio", - "qemu_ga", - "console_pass", - "graphics", - "video", - "listener_addr", + 'name', + 'firmware', + 'vcpu', + 'vcpu_mode', + 'memory', + 'networks', + 'mac', + 'nwfilter', + 'storage', + 'hdd_size', + 'cache_mode', + 'meta_prealloc', + 'virtio', + 'qemu_ga', + 'console_pass', + 'graphics', + 'video', + 'listener_addr' ] @@ -93,17 +95,6 @@ class MigrateSerializer(serializers.ModelSerializer): instance = Instance.objects.all().prefetch_related("userinstance_set") live = serializers.BooleanField(initial=True) xml_del = serializers.BooleanField(initial=True) - class Meta: model = MigrateInstance - fields = [ - "instance", - "target_compute", - "live", - "xml_del", - "offline", - "autoconverge", - "compress", - "postcopy", - "unsafe", - ] + fields = ['instance', 'target_compute', 'live', 'xml_del', 'offline', 'autoconverge', 'compress', 'postcopy', 'unsafe'] diff --git a/instances/api/viewsets.py b/instances/api/viewsets.py index 9a42619..1fb06bb 100644 --- a/instances/api/viewsets.py +++ b/instances/api/viewsets.py @@ -5,15 +5,7 @@ from computes import utils from instances.models import Flavor, Instance from instances.views import get_instance from instances.utils import migrate_instance -from instances.views import ( - poweron, - powercycle, - poweroff, - force_off, - suspend, - resume, - destroy as instance_destroy, -) +from instances.views import poweron, powercycle, poweroff, force_off, suspend, resume, destroy as instance_destroy from rest_framework import status, viewsets, permissions from rest_framework.decorators import action @@ -22,39 +14,26 @@ from rest_framework.response import Response from vrtManager import util from vrtManager.create import wvmCreate -from .serializers import ( - FlavorSerializer, - InstanceSerializer, - InstanceDetailsSerializer, - MigrateSerializer, - CreateInstanceSerializer, -) - +from .serializers import FlavorSerializer, InstanceSerializer, InstanceDetailsSerializer, MigrateSerializer, CreateInstanceSerializer class InstancesViewSet(viewsets.ViewSet): """ A simple ViewSet for listing or retrieving ALL/Compute Instances. """ - permission_classes = [permissions.IsAuthenticated] - def list(self, request): if request.user.is_superuser or request.user.has_perm("instances.view_instances"): queryset = Instance.objects.all().prefetch_related("userinstance_set") else: queryset = Instance.objects.filter(userinstance__user=request.user).prefetch_related("userinstance_set") - serializer = InstanceSerializer( - queryset, - many=True, - context={"request": request} - ) + serializer = InstanceSerializer(queryset, many=True, context={'request': request}) return Response(serializer.data) def retrieve(self, request, pk=None, compute_pk=None): queryset = get_instance(request.user, pk) - serializer = InstanceSerializer(queryset, context={"request": request}) + serializer = InstanceSerializer(queryset, context={'request': request}) return Response(serializer.data) @@ -63,110 +42,94 @@ class InstanceViewSet(viewsets.ViewSet): """ A simple ViewSet for listing or retrieving Compute Instances. """ - - # serializer_class = CreateInstanceSerializer + #serializer_class = CreateInstanceSerializer permission_classes = [permissions.IsAuthenticated] - def list(self, request, compute_pk=None): compute = get_object_or_404(Compute, pk=compute_pk) utils.refresh_instance_database(compute) - + queryset = Instance.objects.filter(compute=compute).prefetch_related("userinstance_set") - serializer = InstanceSerializer( - queryset, - many=True, - context={"request": request} - ) - + serializer = InstanceSerializer(queryset, many=True, context={'request': request}) + return Response(serializer.data) + def retrieve(self, request, pk=None, compute_pk=None): queryset = get_instance(request.user, pk) - serializer = InstanceDetailsSerializer(queryset, context={"request": request}) + serializer = InstanceDetailsSerializer(queryset, context={'request': request}) return Response(serializer.data) + def destroy(self, request, pk=None, compute_pk=None): instance_destroy(request, pk) - return Response({"status": "Instance is destroyed"}) + return Response({'status': 'Instance is destroyed'}) - @action(detail=True, methods=["post"]) + @action(detail=True, methods=['post']) def poweron(self, request, pk=None): poweron(request, pk) - return Response({"status": "poweron command send"}) - - @action(detail=True, methods=["post"]) + return Response({'status': 'poweron command send'}) + + @action(detail=True, methods=['post']) def poweroff(self, request, pk=None): poweroff(request, pk) - return Response({"status": "poweroff command send"}) - - @action(detail=True, methods=["post"]) + return Response({'status': 'poweroff command send'}) + + @action(detail=True, methods=['post']) def powercycle(self, request, pk=None): powercycle(request, pk) - return Response({"status": "powercycle command send"}) - - @action(detail=True, methods=["post"]) + return Response({'status': 'powercycle command send'}) + + @action(detail=True, methods=['post']) def forceoff(self, request, pk=None): force_off(request, pk) - return Response({"status": "force off command send"}) + return Response({'status': 'force off command send'}) - @action(detail=True, methods=["post"]) + @action(detail=True, methods=['post']) def suspend(self, request, pk=None): suspend(request, pk) - return Response({"status": "suspend command send"}) + return Response({'status': 'suspend command send'}) - @action(detail=True, methods=["post"]) + @action(detail=True, methods=['post']) def resume(self, request, pk=None): resume(request, pk) - return Response({"status": "resume command send"}) - + return Response({'status': 'resume command send'}) + class MigrateViewSet(viewsets.ViewSet): """ A viewset for migrating instances. """ - serializer_class = MigrateSerializer queryset = "" def create(self, request): serializer = MigrateSerializer(data=request.data) if serializer.is_valid(): - instance = serializer.validated_data["instance"] - target_host = serializer.validated_data["target_compute"] - live = serializer.validated_data["live"] - unsafe = serializer.validated_data["unsafe"] - xml_del = serializer.validated_data["xml_del"] - offline = serializer.validated_data["offline"] - autoconverge = serializer.validated_data["autoconverge"] - postcopy = serializer.validated_data["postcopy"] - compress = serializer.validated_data["compress"] + instance = serializer.validated_data['instance'] + target_host = serializer.validated_data['target_compute'] + live = serializer.validated_data['live'] + unsafe = serializer.validated_data['unsafe'] + xml_del = serializer.validated_data['xml_del'] + offline = serializer.validated_data['offline'] + autoconverge = serializer.validated_data['autoconverge'] + postcopy = serializer.validated_data['postcopy'] + compress = serializer.validated_data['compress'] - migrate_instance( - target_host, - instance, - request.user, - live, - unsafe, - xml_del, - offline, - autoconverge, - compress, - postcopy, - ) + migrate_instance(target_host, instance, request.user, live, unsafe, xml_del, offline, autoconverge, compress, postcopy) - return Response({"status": "instance migrate is started"}) + return Response({'status': 'instance migrate is started'}) else: - return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + class FlavorViewSet(viewsets.ModelViewSet): """ API endpoint that allows flavor to be viewed. """ - - queryset = Flavor.objects.all().order_by("id") + queryset = Flavor.objects.all().order_by('id') serializer_class = FlavorSerializer permission_classes = [permissions.IsAuthenticated] @@ -175,15 +138,15 @@ class CreateInstanceViewSet(viewsets.ViewSet): """ A viewset for creating instances. """ - serializer_class = CreateInstanceSerializer queryset = "" - + def create(self, request, compute_pk=None, arch=None, machine=None): - serializer = CreateInstanceSerializer( - data=request.data, - context={"compute_pk": compute_pk, "arch": arch, "machine": machine}, - ) + serializer = CreateInstanceSerializer(data=request.data, + context = {'compute_pk': compute_pk, + 'arch': arch, + 'machine': machine + }) if serializer.is_valid(): volume_list = [] default_bus = app_settings.INSTANCE_VOLUME_DEFAULT_BUS @@ -203,14 +166,14 @@ class CreateInstanceViewSet(viewsets.ViewSet): ) path = conn.create_volume( - serializer.validated_data["storage"], - serializer.validated_data["name"], - serializer.validated_data["hdd_size"], - default_disk_format, - serializer.validated_data["meta_prealloc"], - default_disk_owner_uid, - default_disk_owner_gid, - ) + serializer.validated_data['storage'], + serializer.validated_data['name'], + serializer.validated_data['hdd_size'], + default_disk_format, + serializer.validated_data['meta_prealloc'], + default_disk_owner_uid, + default_disk_owner_gid, + ) volume = {} firmware = {} volume["device"] = "disk" @@ -226,8 +189,8 @@ class CreateInstanceViewSet(viewsets.ViewSet): volume_list.append(volume) - if "UEFI" in serializer.validated_data["firmware"]: - firmware["loader"] = (serializer.validated_data["firmware"].split(":")[1].strip()) + if "UEFI" in serializer.validated_data['firmware']: + firmware["loader"] = serializer.validated_data['firmware'].split(":")[1].strip() firmware["secure"] = "no" firmware["readonly"] = "yes" firmware["type"] = "pflash" @@ -236,26 +199,26 @@ class CreateInstanceViewSet(viewsets.ViewSet): firmware["secure"] = "yes" ret = conn.create_instance( - name=serializer.validated_data["name"], - memory=serializer.validated_data["memory"], - vcpu=serializer.validated_data["vcpu"], - vcpu_mode=serializer.validated_data["vcpu_mode"], + name=serializer.validated_data['name'], + memory=serializer.validated_data['memory'], + vcpu=serializer.validated_data['vcpu'], + vcpu_mode=serializer.validated_data['vcpu_mode'], uuid=util.randomUUID(), arch=arch, machine=machine, firmware=firmware, volumes=volume_list, - networks=serializer.validated_data["networks"], - nwfilter=serializer.validated_data["nwfilter"], - graphics=serializer.validated_data["graphics"], - virtio=serializer.validated_data["virtio"], - listener_addr=serializer.validated_data["listener_addr"], - video=serializer.validated_data["video"], - console_pass=serializer.validated_data["console_pass"], - mac=serializer.validated_data["mac"], - qemu_ga=serializer.validated_data["qemu_ga"], + networks=serializer.validated_data['networks'], + nwfilter=serializer.validated_data['nwfilter'], + graphics=serializer.validated_data['graphics'], + virtio=serializer.validated_data['virtio'], + listener_addr=serializer.validated_data['listener_addr'], + video=serializer.validated_data['video'], + console_pass=serializer.validated_data['console_pass'], + mac=serializer.validated_data['mac'], + qemu_ga=serializer.validated_data['qemu_ga'], ) msg = f"Instance {serializer.validated_data['name']} is created" - return Response({"status": msg}) + return Response({'status': msg }) else: - return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) \ No newline at end of file diff --git a/instances/apps.py b/instances/apps.py index a43c6a3..49983ac 100644 --- a/instances/apps.py +++ b/instances/apps.py @@ -3,19 +3,17 @@ from django.db.models.signals import post_migrate def migrate_can_clone_instances(sender, **kwargs): - """ + ''' Migrate can clone instances user attribute to permission - """ + ''' from django.contrib.auth.models import Permission, User - plan = kwargs.get("plan", []) + plan = kwargs.get('plan', []) for migration, rolled_back in plan: - if (migration.app_label == "instances" and migration.name == "0002_permissionset" and not rolled_back): + if migration.app_label == 'instances' and migration.name == '0002_permissionset' and not rolled_back: users = User.objects.all() - permission = Permission.objects.get(codename="clone_instances") - print( - "\033[1m* \033[92mMigrating can_clone_instaces user attribute to permission\033[0m" - ) + permission = Permission.objects.get(codename='clone_instances') + print('\033[1m* \033[92mMigrating can_clone_instaces user attribute to permission\033[0m') for user in users: if user.userattributes: if user.userattributes.can_clone_instances: @@ -24,26 +22,25 @@ def migrate_can_clone_instances(sender, **kwargs): def apply_passwordless_console(sender, **kwargs): - """ + ''' Apply new passwordless_console permission for all users - """ + ''' from django.contrib.auth import get_user_model from django.contrib.auth.models import Permission - User = get_user_model() - plan = kwargs.get("plan", []) + plan = kwargs.get('plan', []) for migration, rolled_back in plan: - if (migration.app_label == "instances" and migration.name == "0009_auto_20200717_0524" and not rolled_back): - print("\033[1m* \033[92mApplying permission passwordless_console for all users\033[0m") + if migration.app_label == 'instances' and migration.name == '0009_auto_20200717_0524' and not rolled_back: + print('\033[1m* \033[92mApplying permission passwordless_console for all users\033[0m') users = User.objects.all() - permission = Permission.objects.get(codename="passwordless_console") + permission = Permission.objects.get(codename='passwordless_console') for user in users: user.user_permissions.add(permission) class InstancesConfig(AppConfig): - name = "instances" - verbose_name = "Instances" + name = 'instances' + verbose_name = 'Instances' def ready(self): post_migrate.connect(migrate_can_clone_instances, sender=self) diff --git a/instances/forms.py b/instances/forms.py index d9f09b3..14e0a9f 100644 --- a/instances/forms.py +++ b/instances/forms.py @@ -12,7 +12,7 @@ from .models import CreateInstance, Flavor class FlavorForm(forms.ModelForm): class Meta: model = Flavor - fields = "__all__" + fields = '__all__' class ConsoleForm(forms.Form): @@ -20,25 +20,17 @@ class ConsoleForm(forms.Form): listen_on = forms.ChoiceField() generate_password = forms.BooleanField(required=False) clear_password = forms.BooleanField(required=False) - password = forms.CharField( - widget=forms.PasswordInput(render_value=True), - required=False - ) + password = forms.CharField(widget=forms.PasswordInput(render_value=True), required=False) clear_keymap = forms.BooleanField(required=False) keymap = forms.ChoiceField(required=False) def __init__(self, *args, **kwargs): super(ConsoleForm, self).__init__(*args, **kwargs) - type_choices = ( - (c, c) - for c in AppSettings.objects.get(key="QEMU_CONSOLE_DEFAULT_TYPE").choices_as_list() - ) - keymap_choices = [("auto", "Auto")] + list((c, c) for c in QEMU_KEYMAPS) - self.fields["type"] = forms.ChoiceField(choices=type_choices) - self.fields["listen_on"] = forms.ChoiceField( - choices=QEMU_CONSOLE_LISTENER_ADDRESSES - ) - self.fields["keymap"] = forms.ChoiceField(choices=keymap_choices) + type_choices = ((c, c) for c in AppSettings.objects.get(key="QEMU_CONSOLE_DEFAULT_TYPE").choices_as_list()) + keymap_choices = [('auto', 'Auto')] + list((c, c) for c in QEMU_KEYMAPS) + self.fields['type'] = forms.ChoiceField(choices=type_choices) + self.fields['listen_on'] = forms.ChoiceField(choices=QEMU_CONSOLE_LISTENER_ADDRESSES) + self.fields['keymap'] = forms.ChoiceField(choices=keymap_choices) class NewVMForm(forms.ModelForm): @@ -65,16 +57,12 @@ class NewVMForm(forms.ModelForm): # listener_addr = forms.ChoiceField(required=True, widget=forms.RadioSelect, choices=QEMU_CONSOLE_LISTENER_ADDRESSES) class Meta: model = CreateInstance - fields = "__all__" - exclude = ["compute"] + fields = '__all__' + exclude = ['compute'] def clean_name(self): - name = self.cleaned_data["name"] - have_symbol = re.match("^[a-zA-Z0-9._-]+$", name) + name = self.cleaned_data['name'] + have_symbol = re.match('^[a-zA-Z0-9._-]+$', name) if not have_symbol: - raise forms.ValidationError( - _( - "The name of the virtual machine must not contain any special characters" - ) - ) + raise forms.ValidationError(_('The name of the virtual machine must not contain any special characters')) return name diff --git a/instances/models.py b/instances/models.py index 1488b7e..222f886 100644 --- a/instances/models.py +++ b/instances/models.py @@ -10,10 +10,10 @@ from vrtManager.instance import wvmInstance class Flavor(models.Model): - label = models.CharField(_("label"), max_length=12, unique=True) - memory = models.IntegerField(_("memory")) - vcpu = models.IntegerField(_("vcpu")) - disk = models.IntegerField(_("disk")) + label = models.CharField(_('label'), max_length=12, unique=True) + memory = models.IntegerField(_('memory')) + vcpu = models.IntegerField(_('vcpu')) + disk = models.IntegerField(_('disk')) def __str__(self): return self.label @@ -21,21 +21,21 @@ class Flavor(models.Model): class InstanceManager(models.Manager): def get_queryset(self): - return super().get_queryset().select_related("compute") + return super().get_queryset().select_related('compute') class Instance(models.Model): compute = models.ForeignKey(Compute, on_delete=models.CASCADE) - name = models.CharField(_("name"), max_length=120, db_index=True) - uuid = models.CharField(_("uuid"), max_length=36, db_index=True) - is_template = models.BooleanField(_("is template"), default=False) - created = models.DateTimeField(_("created"), auto_now_add=True) - drbd = models.CharField(_("drbd"), max_length=24, default="None") + name = models.CharField(_('name'), max_length=120, db_index=True) + uuid = models.CharField(_('uuid'), max_length=36, db_index=True) + is_template = models.BooleanField(_('is template'), default=False) + created = models.DateTimeField(_('created'), auto_now_add=True) + drbd = models.CharField(_('drbd'), max_length=24, default="None") objects = InstanceManager() def __str__(self): - return f"{self.compute}/{self.name}" + return f'{self.compute}/{self.name}' @cached_property def proxy(self): @@ -173,7 +173,7 @@ class Instance(models.Model): @cached_property def snapshots(self): - return sorted(self.proxy.get_snapshot(), reverse=True, key=lambda k: k["date"]) + return sorted(self.proxy.get_snapshot(), reverse=True, key=lambda k: k['date']) @cached_property def inst_xml(self): @@ -209,59 +209,35 @@ class Instance(models.Model): class MigrateInstance(models.Model): - instance = models.ForeignKey( - Instance, - related_name="source_host", - on_delete=models.DO_NOTHING - ) - target_compute = models.ForeignKey( - Compute, - related_name="target_host", - on_delete=models.DO_NOTHING - ) + instance = models.ForeignKey(Instance, related_name='source_host', on_delete=models.DO_NOTHING) + target_compute = models.ForeignKey(Compute, related_name='target_host', on_delete=models.DO_NOTHING) - live = models.BooleanField(_("Live")) - xml_del = models.BooleanField(_("Undefine XML"), default=True) - offline = models.BooleanField(_("Offline")) - autoconverge = models.BooleanField(_("Auto Converge"), default=True) - compress = models.BooleanField(_("Compress"), default=False) - postcopy = models.BooleanField(_("Post Copy"), default=False) - unsafe = models.BooleanField(_("Unsafe"), default=False) + live = models.BooleanField(_('Live')) + xml_del = models.BooleanField(_('Undefine XML'), default=True) + offline = models.BooleanField(_('Offline')) + autoconverge = models.BooleanField(_('Auto Converge'), default=True) + compress = models.BooleanField(_('Compress'), default=False) + postcopy = models.BooleanField(_('Post Copy'), default=False) + unsafe = models.BooleanField(_('Unsafe'), default=False) class Meta: managed = False class CreateInstance(models.Model): - compute = models.ForeignKey( - Compute, - related_name="host", - on_delete=models.DO_NOTHING - ) - name = models.CharField( - max_length=64, - error_messages={"required": _("No Virtual Machine name has been entered")}, - ) + compute = models.ForeignKey(Compute, related_name='host', on_delete=models.DO_NOTHING) + name = models.CharField(max_length=64, error_messages={'required': _('No Virtual Machine name has been entered')}) firmware = models.CharField(max_length=64) - vcpu = models.IntegerField( - error_messages={"required": _("No VCPU has been entered")} - ) + vcpu = models.IntegerField(error_messages={'required': _('No VCPU has been entered')}) vcpu_mode = models.CharField(max_length=20, blank=True) disk = models.IntegerField(blank=True) - memory = models.IntegerField( - error_messages={"required": _("No RAM size has been entered")} - ) - networks = models.CharField( - max_length=256, - error_messages={"required": _("No Network pool has been choosen")}, - ) + memory = models.IntegerField(error_messages={'required': _('No RAM size has been entered')}) + networks = models.CharField(max_length=256, error_messages={'required': _('No Network pool has been choosen')}) nwfilter = models.CharField(max_length=256, blank=True) storage = models.CharField(max_length=256, blank=True) template = models.CharField(max_length=256, blank=True) images = models.CharField(max_length=256, blank=True) - cache_mode = models.CharField( - max_length=16, error_messages={"required": _("Please select HDD cache mode")} - ) + cache_mode = models.CharField(max_length=16, error_messages={'required': _('Please select HDD cache mode')}) hdd_size = models.IntegerField(blank=True) meta_prealloc = models.BooleanField(default=False, blank=True) virtio = models.BooleanField(default=True) @@ -270,15 +246,9 @@ class CreateInstance(models.Model): console_pass = models.CharField(max_length=64, blank=True) add_cdrom = models.CharField(max_length=16) add_input = models.CharField(max_length=16) - graphics = models.CharField( - max_length=16, error_messages={"required": _("Please select a graphics type")} - ) - video = models.CharField( - max_length=16, error_messages={"required": _("Please select a video driver")} - ) - listener_addr = models.CharField( - max_length=20, choices=QEMU_CONSOLE_LISTENER_ADDRESSES - ) + graphics = models.CharField(max_length=16, error_messages={'required': _('Please select a graphics type')}) + video = models.CharField(max_length=16, error_messages={'required': _('Please select a video driver')}) + listener_addr = models.CharField(max_length=20, choices=QEMU_CONSOLE_LISTENER_ADDRESSES) class Meta: managed = False @@ -288,14 +258,13 @@ class PermissionSet(models.Model): """ Dummy model for holding set of permissions we need to be automatically added by Django """ - class Meta: default_permissions = () permissions = [ - ("clone_instances", "Can clone instances"), - ("passwordless_console", _("Can access console without password")), - ("view_instances", "Can view instances"), - ("snapshot_instances", "Can snapshot instances"), + ('clone_instances', 'Can clone instances'), + ('passwordless_console', _('Can access console without password')), + ('view_instances', 'Can view instances'), + ('snapshot_instances', 'Can snapshot instances'), ] managed = False diff --git a/instances/tests.py b/instances/tests.py index ecdc96c..20e1bfc 100644 --- a/instances/tests.py +++ b/instances/tests.py @@ -25,7 +25,7 @@ class InstancesTestCase(TestCase): # Add users for testing purposes User = get_user_model() cls.admin_user = User.objects.get(pk=1) - cls.test_user = User.objects.create(username="test-user") + cls.test_user = User.objects.create(username='test-user') UserAttributes.objects.create( user=cls.test_user, max_instances=1, @@ -33,16 +33,16 @@ class InstancesTestCase(TestCase): max_memory=128, max_disk_size=1, ) - permission = Permission.objects.get(codename="clone_instances") + permission = Permission.objects.get(codename='clone_instances') cls.test_user.user_permissions.add(permission) # Add localhost compute cls.compute = Compute( - name="test-compute", - hostname="localhost", - login="", - password="", - details="local", + name='test-compute', + hostname='localhost', + login='', + password='', + details='local', type=4, ) cls.compute.save() @@ -56,16 +56,16 @@ class InstancesTestCase(TestCase): # Add disks for testing cls.connection.create_volume( - "default", - "test-volume", + 'default', + 'test-volume', 1, - "qcow2", + 'qcow2', False, 0, 0, ) # XML for testing vm - with open("conf/test-vm.xml", "r") as f: + with open('conf/test-vm.xml', 'r') as f: cls.xml = f.read() # Create testing vm from XML @@ -81,33 +81,27 @@ class InstancesTestCase(TestCase): super().tearDownClass() def setUp(self): - self.client.login(username="admin", password="admin") - self.rsa_key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC6OOdbfv27QVnSC6sKxGaHb6YFc+3gxCkyVR3cTSXE/n5BEGf8aOgBpepULWa1RZfxYHY14PlKULDygdXSdrrR2kNSwoKz/Oo4d+3EE92L7ocl1+djZbptzgWgtw1OseLwbFik+iKlIdqPsH+IUQvX7yV545ZQtAP8Qj1R+uCqkw== test@test" + self.client.login(username='admin', password='admin') + self.rsa_key = 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC6OOdbfv27QVnSC6sKxGaHb6YFc+3gxCkyVR3cTSXE/n5BEGf8aOgBpepULWa1RZfxYHY14PlKULDygdXSdrrR2kNSwoKz/Oo4d+3EE92L7ocl1+djZbptzgWgtw1OseLwbFik+iKlIdqPsH+IUQvX7yV545ZQtAP8Qj1R+uCqkw== test@test' def test_index(self): - response = self.client.get(reverse("instances:index")) + response = self.client.get(reverse('instances:index')) self.assertEqual(response.status_code, 200) self.client.force_login(self.test_user) - response = self.client.get(reverse("instances:index")) + response = self.client.get(reverse('instances:index')) self.assertEqual(response.status_code, 200) def test_create_select_type(self): - response = self.client.get( - reverse("instances:create_instance_select_type", args=[1]) - ) + response = self.client.get(reverse('instances:create_instance_select_type', args=[1])) self.assertEqual(response.status_code, 200) def test_instance_page(self): - response = self.client.get( - reverse("instances:instance", args=[self.instance.id]) - ) + response = self.client.get(reverse('instances:instance', args=[self.instance.id])) self.assertEqual(response.status_code, 200) self.client.force_login(self.test_user) - response = self.client.get( - reverse("instances:instance", args=[self.instance.id]) - ) + response = self.client.get(reverse('instances:instance', args=[self.instance.id])) self.assertRaises(Http404) # def test_create_volume(self): @@ -124,73 +118,67 @@ class InstancesTestCase(TestCase): def test_create_destroy_instance(self): # Create - response = self.client.get( - reverse( - "instances:create_instance", args=[self.compute.id, "x86_64", "q35"] - ) - ) + response = self.client.get(reverse('instances:create_instance', args=[self.compute.id, 'x86_64', 'q35'])) self.assertEqual(response.status_code, 200) response = self.client.post( - reverse( - "instances:create_instance", args=[self.compute.id, "x86_64", "q35"] - ), + reverse('instances:create_instance', args=[self.compute.id, 'x86_64', 'q35']), { - "name": "test", - "firmware": "BIOS", - "vcpu": 1, - "vcpu_mode": "host-model", - "memory": 128, - "device0": "disk", - "bus0": "virtio", - "images": "test-volume.qcow2", - "storage-control": "default", - "image-control": "test.qcow2", - "networks": "default", - "network-control": "default", - "cache_mode": "directsync", - "nwfilter": "", - "graphics": "spice", - "video": "vga", - "listener_addr": "0.0.0.0", - "console_pass": "", - "qemu_ga": False, - "virtio": True, - "create": True, + 'name': 'test', + 'firmware': 'BIOS', + 'vcpu': 1, + 'vcpu_mode': 'host-model', + 'memory': 128, + 'device0': 'disk', + 'bus0': 'virtio', + 'images': 'test-volume.qcow2', + 'storage-control': 'default', + 'image-control': 'test.qcow2', + 'networks': 'default', + 'network-control': 'default', + 'cache_mode': 'directsync', + 'nwfilter': '', + 'graphics': 'spice', + 'video': 'vga', + 'listener_addr': '0.0.0.0', + 'console_pass': '', + 'qemu_ga': False, + 'virtio': True, + 'create': True, }, ) self.assertEqual(response.status_code, 302) - instance_qs: Instance = Instance.objects.filter(name="test") + instance_qs: Instance = Instance.objects.filter(name='test') self.assertEqual(len(instance_qs), 1) instance = instance_qs[0] # Destroy - response = self.client.get(reverse("instances:destroy", args=[instance.id])) + response = self.client.get(reverse('instances:destroy', args=[instance.id])) self.assertEqual(response.status_code, 200) response = self.client.post( - reverse("instances:destroy", args=[instance.id]), + reverse('instances:destroy', args=[instance.id]), {}, # do not destroy disk image - HTTP_REFERER=reverse("index"), + HTTP_REFERER=reverse('index'), ) - self.assertRedirects(response, reverse("instances:index")) + self.assertRedirects(response, reverse('instances:index')) def test_create_from_xml(self): uuid = randomUUID() - xml = self.xml.replace("test-vm", "test-vm-xml") - xml = re.sub("\s?.*?", f"{uuid}", xml) + xml = self.xml.replace('test-vm', 'test-vm-xml') + xml = re.sub('\s?.*?', f'{uuid}', xml) response = self.client.post( - reverse("instances:create_instance_select_type", args=[self.compute.id]), + reverse('instances:create_instance_select_type', args=[self.compute.id]), { - "create_xml": True, - "dom_xml": xml, + 'create_xml': True, + 'dom_xml': xml, }, ) self.assertEqual(response.status_code, 302) - xml_instance_qs: Instance = Instance.objects.filter(name="test-vm-xml") + xml_instance_qs: Instance = Instance.objects.filter(name='test-vm-xml') self.assertEqual(len(xml_instance_qs), 1) xml_instance = xml_instance_qs[0] @@ -199,26 +187,21 @@ class InstancesTestCase(TestCase): xml_instance.proxy.start() response = self.client.post( - reverse("instances:destroy", args=[xml_instance.id]), + reverse('instances:destroy', args=[xml_instance.id]), {}, # do not delete disk image - HTTP_REFERER=reverse("index"), + HTTP_REFERER=reverse('index'), ) - self.assertRedirects(response, reverse("instances:index")) + self.assertRedirects(response, reverse('instances:index')) def test_resize_cpu(self): self.assertEqual(self.instance.vcpu, 1) self.assertEqual(self.instance.cur_vcpu, 1) - response = self.client.post( - reverse("instances:resizevm_cpu", args=[self.instance.id]), - { - "vcpu": 4, - "cur_vcpu": 2, - }, - ) - self.assertRedirects( - response, reverse("instances:instance", args=[self.instance.id]) + "#resize" - ) + response = self.client.post(reverse('instances:resizevm_cpu', args=[self.instance.id]), { + 'vcpu': 4, + 'cur_vcpu': 2, + }) + self.assertRedirects(response, reverse('instances:instance', args=[self.instance.id]) + '#resize') # reset cached properties del self.instance.vcpu @@ -232,22 +215,15 @@ class InstancesTestCase(TestCase): vcpu = self.instance.vcpu cur_vcpu = self.instance.cur_vcpu - UserInstance.objects.create( - user=self.test_user, instance=self.instance, is_change=True - ) + UserInstance.objects.create(user=self.test_user, instance=self.instance, is_change=True) self.client.force_login(self.test_user) - response = self.client.post( - reverse("instances:resizevm_cpu", args=[self.instance.id]), - { - "vcpu": 4, - "cur_vcpu": 2, - }, - ) - self.assertRedirects( - response, reverse("instances:instance", args=[self.instance.id]) + "#resize" - ) + response = self.client.post(reverse('instances:resizevm_cpu', args=[self.instance.id]), { + 'vcpu': 4, + 'cur_vcpu': 2, + }) + self.assertRedirects(response, reverse('instances:instance', args=[self.instance.id]) + '#resize') del self.instance.vcpu del self.instance.cur_vcpu @@ -260,26 +236,22 @@ class InstancesTestCase(TestCase): self.assertEqual(self.instance.memory, 128) self.assertEqual(self.instance.cur_memory, 128) - response = self.client.post( - reverse("instances:resize_memory", args=[self.instance.id]), - {"memory": 512, "cur_memory": 256}, - ) - self.assertRedirects( - response, reverse("instances:instance", args=[self.instance.id]) + "#resize" - ) + response = self.client.post(reverse('instances:resize_memory', args=[self.instance.id]), { + 'memory': 512, + 'cur_memory': 256 + }) + self.assertRedirects(response, reverse('instances:instance', args=[self.instance.id]) + '#resize') del self.instance.memory del self.instance.cur_memory self.assertEqual(self.instance.memory, 512) self.assertEqual(self.instance.cur_memory, 256) - response = self.client.post( - reverse("instances:resize_memory", args=[self.instance.id]), - {"memory_custom": 500, "cur_memory_custom": 200}, - ) - self.assertRedirects( - response, reverse("instances:instance", args=[self.instance.id]) + "#resize" - ) + response = self.client.post(reverse('instances:resize_memory', args=[self.instance.id]), { + 'memory_custom': 500, + 'cur_memory_custom': 200 + }) + self.assertRedirects(response, reverse('instances:instance', args=[self.instance.id]) + '#resize') del self.instance.memory del self.instance.cur_memory @@ -292,19 +264,15 @@ class InstancesTestCase(TestCase): memory = self.instance.memory cur_memory = self.instance.cur_memory - UserInstance.objects.create( - user=self.test_user, instance=self.instance, is_change=True - ) + UserInstance.objects.create(user=self.test_user, instance=self.instance, is_change=True) self.client.force_login(self.test_user) - response = self.client.post( - reverse("instances:resize_memory", args=[self.instance.id]), - {"memory": 512, "cur_memory": 256}, - ) - self.assertRedirects( - response, reverse("instances:instance", args=[self.instance.id]) + "#resize" - ) + response = self.client.post(reverse('instances:resize_memory', args=[self.instance.id]), { + 'memory': 512, + 'cur_memory': 256 + }) + self.assertRedirects(response, reverse('instances:instance', args=[self.instance.id]) + '#resize') del self.instance.memory del self.instance.cur_memory @@ -314,55 +282,43 @@ class InstancesTestCase(TestCase): self.assertEqual(self.instance.cur_memory, cur_memory) def test_resize_disk(self): - self.assertEqual(self.instance.disks[0]["size"], 1024**3) + self.assertEqual(self.instance.disks[0]['size'], 1024**3) - response = self.client.post( - reverse("instances:resize_disk", args=[self.instance.id]), - { - "disk_size_vda": 2, - }, - ) - self.assertRedirects( - response, reverse("instances:instance", args=[self.instance.id]) + "#resize" - ) + response = self.client.post(reverse('instances:resize_disk', args=[self.instance.id]), { + 'disk_size_vda': 2, + }) + self.assertRedirects(response, reverse('instances:instance', args=[self.instance.id]) + '#resize') del self.instance.disks - self.assertEqual(self.instance.disks[0]["size"], 2 * 1024**3) + self.assertEqual(self.instance.disks[0]['size'], 2 * 1024**3) def test_resize_disk_with_quota(self): # test for non admin user with quotas - disk_size = self.instance.disks[0]["size"] - UserInstance.objects.create( - user=self.test_user, instance=self.instance, is_change=True - ) + disk_size = self.instance.disks[0]['size'] + UserInstance.objects.create(user=self.test_user, instance=self.instance, is_change=True) self.client.force_login(self.test_user) - response = self.client.post( - reverse("instances:resize_disk", args=[self.instance.id]), - { - "disk_size_vda": 3, - }, - ) - self.assertRedirects( - response, reverse("instances:instance", args=[self.instance.id]) + "#resize" - ) + response = self.client.post(reverse('instances:resize_disk', args=[self.instance.id]), { + 'disk_size_vda': 3, + }) + self.assertRedirects(response, reverse('instances:instance', args=[self.instance.id]) + '#resize') # no changes as user reached quota del self.instance.disks - self.assertEqual(self.instance.disks[0]["size"], disk_size) + self.assertEqual(self.instance.disks[0]['size'], disk_size) def test_add_delete_new_volume(self): self.assertEqual(len(self.instance.disks), 1) response = self.client.post( - reverse("instances:add_new_vol", args=[self.instance.id]), + reverse('instances:add_new_vol', args=[self.instance.id]), { - "storage": "default", - "name": "test-volume-2", - "size": 1, + 'storage': 'default', + 'name': 'test-volume-2', + 'size': 1, }, - HTTP_REFERER=reverse("index"), + HTTP_REFERER=reverse('index'), ) self.assertEqual(response.status_code, 302) @@ -370,13 +326,13 @@ class InstancesTestCase(TestCase): self.assertEqual(len(self.instance.disks), 2) response = self.client.post( - reverse("instances:delete_vol", args=[self.instance.id]), + reverse('instances:delete_vol', args=[self.instance.id]), { - "storage": "default", - "dev": "vdb", - "name": "test-volume-2.qcow2", + 'storage': 'default', + 'dev': 'vdb', + 'name': 'test-volume-2.qcow2', }, - HTTP_REFERER=reverse("index"), + HTTP_REFERER=reverse('index'), ) self.assertEqual(response.status_code, 302) @@ -386,11 +342,11 @@ class InstancesTestCase(TestCase): def test_detach_attach_volume(self): # detach volume response = self.client.post( - reverse("instances:detach_vol", args=[self.instance.id]), + reverse('instances:detach_vol', args=[self.instance.id]), { - "dev": "vda", + 'dev': 'vda', }, - HTTP_REFERER=reverse("index"), + HTTP_REFERER=reverse('index'), ) self.assertEqual(response.status_code, 302) @@ -399,12 +355,12 @@ class InstancesTestCase(TestCase): # reattach volume response = self.client.post( - reverse("instances:add_existing_vol", args=[self.instance.id]), + reverse('instances:add_existing_vol', args=[self.instance.id]), { - "selected_storage": "default", - "vols": "test-volume.qcow2", + 'selected_storage': 'default', + 'vols': 'test-volume.qcow2', }, - HTTP_REFERER=reverse("index"), + HTTP_REFERER=reverse('index'), ) self.assertEqual(response.status_code, 302) @@ -413,18 +369,18 @@ class InstancesTestCase(TestCase): def test_edit_volume(self): response = self.client.post( - reverse("instances:edit_volume", args=[self.instance.id]), + reverse('instances:edit_volume', args=[self.instance.id]), { - "vol_path": "/var/lib/libvirt/images/test-volume.qcow2", + 'vol_path': '/var/lib/libvirt/images/test-volume.qcow2', # 'vol_shareable': False, # 'vol_readonly': False, - "vol_bus": "virtio", - "vol_bus_old": "virtio", - "vol_format": "qcow2", - "dev": "vda", - "edit_volume": True, + 'vol_bus': 'virtio', + 'vol_bus_old': 'virtio', + 'vol_format': 'qcow2', + 'dev': 'vda', + 'edit_volume': True }, - HTTP_REFERER=reverse("index"), + HTTP_REFERER=reverse('index'), ) self.assertEqual(response.status_code, 302) @@ -432,11 +388,11 @@ class InstancesTestCase(TestCase): self.assertEqual(len(self.instance.media), 1) response = self.client.post( - reverse("instances:add_cdrom", args=[self.instance.id]), + reverse('instances:add_cdrom', args=[self.instance.id]), { - "bus": "sata", + 'bus': 'sata', }, - HTTP_REFERER=reverse("index"), + HTTP_REFERER=reverse('index'), ) self.assertEqual(response.status_code, 302) @@ -457,9 +413,9 @@ class InstancesTestCase(TestCase): # detach CD-ROM drive response = self.client.post( - reverse("instances:detach_cdrom", args=[self.instance.id, "sda"]), + reverse('instances:detach_cdrom', args=[self.instance.id, 'sda']), {}, - HTTP_REFERER=reverse("index"), + HTTP_REFERER=reverse('index'), ) self.assertEqual(response.status_code, 302) @@ -470,11 +426,11 @@ class InstancesTestCase(TestCase): self.assertEqual(len(self.instance.snapshots), 0) response = self.client.post( - reverse("instances:snapshot", args=[self.instance.id]), + reverse('instances:snapshot', args=[self.instance.id]), { - "name": "test-snapshot", + 'name': 'test-snapshot', }, - HTTP_REFERER=reverse("index"), + HTTP_REFERER=reverse('index'), ) self.assertEqual(response.status_code, 302) @@ -482,20 +438,20 @@ class InstancesTestCase(TestCase): self.assertEqual(len(self.instance.snapshots), 1) response = self.client.post( - reverse("instances:revert_snapshot", args=[self.instance.id]), + reverse('instances:revert_snapshot', args=[self.instance.id]), { - "name": "test-snapshot", + 'name': 'test-snapshot', }, - HTTP_REFERER=reverse("index"), + HTTP_REFERER=reverse('index'), ) self.assertEqual(response.status_code, 302) response = self.client.post( - reverse("instances:delete_snapshot", args=[self.instance.id]), + reverse('instances:delete_snapshot', args=[self.instance.id]), { - "name": "test-snapshot", + 'name': 'test-snapshot', }, - HTTP_REFERER=reverse("index"), + HTTP_REFERER=reverse('index'), ) self.assertEqual(response.status_code, 302) @@ -506,9 +462,9 @@ class InstancesTestCase(TestCase): self.assertEqual(self.instance.autostart, 0) response = self.client.post( - reverse("instances:set_autostart", args=[self.instance.id]), + reverse('instances:set_autostart', args=[self.instance.id]), {}, - HTTP_REFERER=reverse("index"), + HTTP_REFERER=reverse('index'), ) self.assertEqual(response.status_code, 302) @@ -516,9 +472,9 @@ class InstancesTestCase(TestCase): self.assertEqual(self.instance.autostart, 1) response = self.client.post( - reverse("instances:unset_autostart", args=[self.instance.id]), + reverse('instances:unset_autostart', args=[self.instance.id]), {}, - HTTP_REFERER=reverse("index"), + HTTP_REFERER=reverse('index'), ) self.assertEqual(response.status_code, 302) @@ -529,9 +485,9 @@ class InstancesTestCase(TestCase): self.assertEqual(self.instance.bootmenu, True) response = self.client.post( - reverse("instances:unset_bootmenu", args=[self.instance.id]), + reverse('instances:unset_bootmenu', args=[self.instance.id]), {}, - HTTP_REFERER=reverse("index"), + HTTP_REFERER=reverse('index'), ) self.assertEqual(response.status_code, 302) @@ -539,9 +495,9 @@ class InstancesTestCase(TestCase): self.assertEqual(self.instance.bootmenu, False) response = self.client.post( - reverse("instances:set_bootmenu", args=[self.instance.id]), + reverse('instances:set_bootmenu', args=[self.instance.id]), {}, - HTTP_REFERER=reverse("index"), + HTTP_REFERER=reverse('index'), ) self.assertEqual(response.status_code, 302) @@ -552,9 +508,9 @@ class InstancesTestCase(TestCase): self.assertEqual(self.instance.guest_agent, False) response = self.client.post( - reverse("instances:set_guest_agent", args=[self.instance.id]), - {"guest_agent": True}, - HTTP_REFERER=reverse("index"), + reverse('instances:set_guest_agent', args=[self.instance.id]), + {'guest_agent': True}, + HTTP_REFERER=reverse('index'), ) self.assertEqual(response.status_code, 302) @@ -562,9 +518,9 @@ class InstancesTestCase(TestCase): self.assertEqual(self.instance.guest_agent, True) response = self.client.post( - reverse("instances:set_guest_agent", args=[self.instance.id]), - {"guest_agent": False}, - HTTP_REFERER=reverse("index"), + reverse('instances:set_guest_agent', args=[self.instance.id]), + {'guest_agent': False}, + HTTP_REFERER=reverse('index'), ) self.assertEqual(response.status_code, 302) @@ -572,24 +528,24 @@ class InstancesTestCase(TestCase): self.assertEqual(self.instance.guest_agent, False) def test_video_model(self): - self.assertEqual(self.instance.video_model, "vga") + self.assertEqual(self.instance.video_model, 'vga') response = self.client.post( - reverse("instances:set_video_model", args=[self.instance.id]), - {"video_model": "virtio"}, - HTTP_REFERER=reverse("index"), + reverse('instances:set_video_model', args=[self.instance.id]), + {'video_model': 'virtio'}, + HTTP_REFERER=reverse('index'), ) self.assertEqual(response.status_code, 302) del self.instance.video_model - self.assertEqual(self.instance.video_model, "virtio") + self.assertEqual(self.instance.video_model, 'virtio') def test_owner(self): self.assertEqual(UserInstance.objects.count(), 0) response = self.client.post( - reverse("instances:add_owner", args=[self.instance.id]), - {"user_id": self.admin_user.id}, - HTTP_REFERER=reverse("index"), + reverse('instances:add_owner', args=[self.instance.id]), + {'user_id': self.admin_user.id}, + HTTP_REFERER=reverse('index'), ) self.assertEqual(response.status_code, 302) self.assertEqual(UserInstance.objects.count(), 1) @@ -599,22 +555,22 @@ class InstancesTestCase(TestCase): self.assertEqual(user_instance.user_id, self.admin_user.id) # test when no multiple owners allowed - setting = AppSettings.objects.get(key="ALLOW_INSTANCE_MULTIPLE_OWNER") - setting.value = "False" + setting = AppSettings.objects.get(key='ALLOW_INSTANCE_MULTIPLE_OWNER') + setting.value = 'False' setting.save() response = self.client.post( - reverse("instances:add_owner", args=[self.instance.id]), - {"user_id": self.test_user.id}, - HTTP_REFERER=reverse("index"), + reverse('instances:add_owner', args=[self.instance.id]), + {'user_id': self.test_user.id}, + HTTP_REFERER=reverse('index'), ) self.assertEqual(response.status_code, 302) self.assertEqual(UserInstance.objects.count(), 1) response = self.client.post( - reverse("instances:del_owner", args=[self.instance.id]), - {"userinstance": user_instance.id}, - HTTP_REFERER=reverse("index"), + reverse('instances:del_owner', args=[self.instance.id]), + {'userinstance': user_instance.id}, + HTTP_REFERER=reverse('index'), ) self.assertEqual(response.status_code, 302) self.assertEqual(UserInstance.objects.count(), 0) @@ -622,41 +578,44 @@ class InstancesTestCase(TestCase): def test_clone(self): instance_count = Instance.objects.count() response = self.client.post( - reverse("instances:clone", args=[self.instance.id]), + reverse('instances:clone', args=[self.instance.id]), { - "name": "test-vm-clone", - "clone-net-mac-0": "de:ad:be:ef:de:ad", - "disk-vda": "test-clone.img", - "clone-title": "", - "clone-description": "", - "clone": "", + 'name': 'test-vm-clone', + 'clone-net-mac-0': 'de:ad:be:ef:de:ad', + 'disk-vda': 'test-clone.img', + 'clone-title': '', + 'clone-description': '', + 'clone': '', }, - HTTP_REFERER=reverse("index"), + HTTP_REFERER=reverse('index'), ) self.assertEqual(response.status_code, 302) self.assertEqual(Instance.objects.count(), instance_count + 1) - clone_qs = Instance.objects.filter(name="test-vm-clone") + clone_qs = Instance.objects.filter(name='test-vm-clone') self.assertEqual(len(clone_qs), 1) clone = clone_qs[0] - self.assertEqual(clone.proxy.get_net_devices()[0]["mac"], "de:ad:be:ef:de:ad") + self.assertEqual(clone.proxy.get_net_devices()[0]['mac'], 'de:ad:be:ef:de:ad') response = self.client.post( - reverse("instances:snapshot", args=[clone.id]), + reverse('instances:snapshot', args=[clone.id]), { - "name": "test", + 'name': 'test', }, - HTTP_REFERER=reverse("index"), + HTTP_REFERER=reverse('index'), ) self.assertEqual(response.status_code, 302) response = self.client.post( - reverse("instances:destroy", args=[clone.id]), - {"delete_disk": True, "delete_nvram": True}, - HTTP_REFERER=reverse("index"), + reverse('instances:destroy', args=[clone.id]), + { + 'delete_disk': True, + 'delete_nvram': True + }, + HTTP_REFERER=reverse('index'), ) - self.assertRedirects(response, reverse("instances:index")) + self.assertRedirects(response, reverse('instances:index')) self.assertEqual(Instance.objects.count(), instance_count) def test_clone_with_quota(self): @@ -668,16 +627,16 @@ class InstancesTestCase(TestCase): self.client.force_login(self.test_user) response = self.client.post( - reverse("instances:clone", args=[self.instance.id]), + reverse('instances:clone', args=[self.instance.id]), { - "name": "test-vm-clone", - "clone-net-mac-0": "de:ad:be:ef:de:ad", - "disk-vda": "test-clone.img", - "clone-title": "", - "clone-description": "", - "clone": "", + 'name': 'test-vm-clone', + 'clone-net-mac-0': 'de:ad:be:ef:de:ad', + 'disk-vda': 'test-clone.img', + 'clone-title': '', + 'clone-description': '', + 'clone': '', }, - HTTP_REFERER=reverse("index"), + HTTP_REFERER=reverse('index'), ) self.assertEqual(response.status_code, 302) # no new instances created as user reached quota @@ -688,104 +647,99 @@ class InstancesTestCase(TestCase): # duplicate name response = self.client.post( - reverse("instances:clone", args=[self.instance.id]), + reverse('instances:clone', args=[self.instance.id]), { - "name": "test-vm", - "clone-net-mac-0": "de:ad:be:ef:de:ad", - "disk-vda": "test.img", - "clone-title": "", - "clone-description": "", - "clone": "", + 'name': 'test-vm', + 'clone-net-mac-0': 'de:ad:be:ef:de:ad', + 'disk-vda': 'test.img', + 'clone-title': '', + 'clone-description': '', + 'clone': '', }, - HTTP_REFERER=reverse("index"), + HTTP_REFERER=reverse('index'), ) self.assertEqual(response.status_code, 302) self.assertEqual(Instance.objects.count(), instance_count) # wrong name response = self.client.post( - reverse("instances:clone", args=[self.instance.id]), + reverse('instances:clone', args=[self.instance.id]), { - "name": "!@#$", - "clone-net-mac-0": "de:ad:be:ef:de:ad", - "disk-vda": "!@#$.img", - "clone-title": "", - "clone-description": "", - "clone": "", + 'name': '!@#$', + 'clone-net-mac-0': 'de:ad:be:ef:de:ad', + 'disk-vda': '!@#$.img', + 'clone-title': '', + 'clone-description': '', + 'clone': '', }, - HTTP_REFERER=reverse("index"), + HTTP_REFERER=reverse('index'), ) self.assertEqual(response.status_code, 302) self.assertEqual(Instance.objects.count(), instance_count) # wrong mac response = self.client.post( - reverse("instances:clone", args=[self.instance.id]), + reverse('instances:clone', args=[self.instance.id]), { - "name": "test-vm-clone", - "clone-net-mac-0": "gh:ad:be:ef:de:ad", - "disk-vda": "test-clone.img", - "clone-title": "", - "clone-description": "", - "clone": "", + 'name': 'test-vm-clone', + 'clone-net-mac-0': 'gh:ad:be:ef:de:ad', + 'disk-vda': 'test-clone.img', + 'clone-title': '', + 'clone-description': '', + 'clone': '', }, - HTTP_REFERER=reverse("index"), + HTTP_REFERER=reverse('index'), ) self.assertEqual(response.status_code, 302) self.assertEqual(Instance.objects.count(), instance_count) def test_console(self): response = self.client.post( - reverse("instances:update_console", args=[self.instance.id]), - {"type": "spice", "listen_on": "0.0.0.0", "password": "", "keymap": "auto"}, - HTTP_REFERER=reverse("index"), + reverse('instances:update_console', args=[self.instance.id]), + { + 'type': 'spice', + 'listen_on': '0.0.0.0', + 'password': '', + 'keymap': 'auto' + }, + HTTP_REFERER=reverse('index'), ) self.assertEqual(response.status_code, 302) def test_status(self): - response = self.client.get(reverse("instances:status", args=[self.instance.id])) + response = self.client.get(reverse('instances:status', args=[self.instance.id])) self.assertEqual(response.status_code, 200) def test_stats(self): - response = self.client.get(reverse("instances:stats", args=[self.instance.id])) + response = self.client.get(reverse('instances:stats', args=[self.instance.id])) self.assertEqual(response.status_code, 200) def test_guess_mac_address(self): - response = self.client.get( - reverse("instances:guess_mac_address", args=[self.instance.name]) - ) + response = self.client.get(reverse('instances:guess_mac_address', args=[self.instance.name])) self.assertEqual(response.status_code, 200) def test_random_mac_address(self): - response = self.client.get(reverse("instances:random_mac_address")) + response = self.client.get(reverse('instances:random_mac_address')) self.assertEqual(response.status_code, 200) def test_guess_clone_name(self): - response = self.client.get(reverse("instances:guess_clone_name")) + response = self.client.get(reverse('instances:guess_clone_name')) self.assertEqual(response.status_code, 200) def test_sshkeys(self): - UserSSHKey.objects.create( - keyname="keyname", keypublic=self.rsa_key, user=self.test_user - ) + UserSSHKey.objects.create(keyname='keyname', keypublic=self.rsa_key, user=self.test_user) UserInstance.objects.create(user=self.test_user, instance=self.instance) - response = self.client.get( - reverse("instances:sshkeys", args=[self.instance.id]) - ) + response = self.client.get(reverse('instances:sshkeys', args=[self.instance.id])) self.assertEqual(response.status_code, 200) - response = self.client.get( - reverse("instances:sshkeys", args=[self.instance.id]) + "?plain=true" - ) + response = self.client.get(reverse('instances:sshkeys', args=[self.instance.id]) + '?plain=true') self.assertEqual(response.status_code, 200) def test_check_instance(self): - response = self.client.get( - reverse("instances:check_instance", args=["test-vm"]) - ) + response = self.client.get(reverse('instances:check_instance', args=['test-vm'])) self.assertEqual(response.status_code, 200) - self.assertJSONEqual(response.content, {"vname": "test-vm", "exists": True}) + self.assertJSONEqual(response.content, {'vname': 'test-vm', 'exists': True}) def test_start_template(self): # starting templates must fail @@ -794,10 +748,7 @@ class InstancesTestCase(TestCase): self.instance.is_template = True self.instance.save() - response = self.client.get( - reverse("instances:poweron", args=[self.instance.id]), - HTTP_REFERER=reverse("index"), - ) + response = self.client.get(reverse('instances:poweron', args=[self.instance.id]), HTTP_REFERER=reverse('index')) self.assertEqual(response.status_code, 302) del self.instance.status @@ -810,10 +761,7 @@ class InstancesTestCase(TestCase): # poweron self.assertEqual(self.instance.status, 5) - response = self.client.get( - reverse("instances:poweron", args=[self.instance.id]), - HTTP_REFERER=reverse("index"), - ) + response = self.client.get(reverse('instances:poweron', args=[self.instance.id]), HTTP_REFERER=reverse('index')) self.assertEqual(response.status_code, 302) del self.instance.status @@ -821,30 +769,21 @@ class InstancesTestCase(TestCase): self.assertEqual(self.instance.status, 1) # suspend - response = self.client.get( - reverse("instances:suspend", args=[self.instance.id]), - HTTP_REFERER=reverse("index"), - ) + response = self.client.get(reverse('instances:suspend', args=[self.instance.id]), HTTP_REFERER=reverse('index')) self.assertEqual(response.status_code, 302) del self.instance.status self.assertEqual(self.instance.status, 3) # resume - response = self.client.get( - reverse("instances:resume", args=[self.instance.id]), - HTTP_REFERER=reverse("index"), - ) + response = self.client.get(reverse('instances:resume', args=[self.instance.id]), HTTP_REFERER=reverse('index')) self.assertEqual(response.status_code, 302) del self.instance.status self.assertEqual(self.instance.status, 1) # poweroff - response = self.client.get( - reverse("instances:poweroff", args=[self.instance.id]), - HTTP_REFERER=reverse("index"), - ) + response = self.client.get(reverse('instances:poweroff', args=[self.instance.id]), HTTP_REFERER=reverse('index')) self.assertEqual(response.status_code, 302) # as no OS is installed ACPI won't work @@ -852,115 +791,107 @@ class InstancesTestCase(TestCase): self.assertEqual(self.instance.status, 1) # powercycle - response = self.client.get( - reverse("instances:powercycle", args=[self.instance.id]), - HTTP_REFERER=reverse("index"), - ) + response = self.client.get(reverse('instances:powercycle', args=[self.instance.id]), HTTP_REFERER=reverse('index')) self.assertEqual(response.status_code, 302) del self.instance.status self.assertEqual(self.instance.status, 1) # force_off - response = self.client.get( - reverse("instances:force_off", args=[self.instance.id]), - HTTP_REFERER=reverse("index"), - ) + response = self.client.get(reverse('instances:force_off', args=[self.instance.id]), HTTP_REFERER=reverse('index')) self.assertEqual(response.status_code, 302) del self.instance.status self.assertEqual(self.instance.status, 5) def test_vv_file(self): - response = self.client.get( - reverse("instances:getvvfile", args=[self.instance.id]) - ) + response = self.client.get(reverse('instances:getvvfile', args=[self.instance.id])) self.assertEqual(response.status_code, 200) def test_vcpu_hotplug(self): response = self.client.post( - reverse("instances:set_vcpu_hotplug", args=[self.instance.id]), - {"vcpu_hotplug": "True"}, - HTTP_REFERER=reverse("index"), + reverse('instances:set_vcpu_hotplug', args=[self.instance.id]), + {'vcpu_hotplug': 'True'}, + HTTP_REFERER=reverse('index'), ) self.assertEqual(response.status_code, 302) def test_change_network(self): - self.assertEqual(self.instance.networks[0]["mac"], "52:54:00:a2:3c:e7") + self.assertEqual(self.instance.networks[0]['mac'], '52:54:00:a2:3c:e7') response = self.client.post( - reverse("instances:change_network", args=[self.instance.id]), + reverse('instances:change_network', args=[self.instance.id]), { - "net-mac-0": "52:54:00:a2:3c:e8", - "net-source-0": "net:default", - "net-nwfilter-0": "", - "net-model-0": "virtio", + 'net-mac-0': '52:54:00:a2:3c:e8', + 'net-source-0': 'net:default', + 'net-nwfilter-0': '', + 'net-model-0': 'virtio', }, - HTTP_REFERER=reverse("index"), + HTTP_REFERER=reverse('index'), ) self.assertEqual(response.status_code, 302) del self.instance.networks - self.assertEqual(self.instance.networks[0]["mac"], "52:54:00:a2:3c:e8") + self.assertEqual(self.instance.networks[0]['mac'], '52:54:00:a2:3c:e8') def test_add_delete_network(self): self.assertEqual(len(self.instance.networks), 1) - net_mac = self.instance.networks[0]["mac"] + net_mac = self.instance.networks[0]['mac'] response = self.client.post( - reverse("instances:add_network", args=[self.instance.id]), + reverse('instances:add_network', args=[self.instance.id]), { - "add-net-mac": "52:54:00:a2:3c:e9", - "add-net-network": "net:default", - "add_net-nwfilter": "", + 'add-net-mac': '52:54:00:a2:3c:e9', + 'add-net-network': 'net:default', + 'add_net-nwfilter': '', }, - HTTP_REFERER=reverse("index"), + HTTP_REFERER=reverse('index'), ) self.assertEqual(response.status_code, 302) del self.instance.networks self.assertEqual(len(self.instance.networks), 2) - self.assertEqual(self.instance.networks[1]["mac"], "52:54:00:a2:3c:e9") + self.assertEqual(self.instance.networks[1]['mac'], '52:54:00:a2:3c:e9') response = self.client.post( - reverse("instances:delete_network", args=[self.instance.id]), + reverse('instances:delete_network', args=[self.instance.id]), { - "delete_network": "52:54:00:a2:3c:e9", + 'delete_network': '52:54:00:a2:3c:e9', }, - HTTP_REFERER=reverse("index"), + HTTP_REFERER=reverse('index'), ) self.assertEqual(response.status_code, 302) del self.instance.networks self.assertEqual(len(self.instance.networks), 1) - self.assertEqual(self.instance.networks[0]["mac"], net_mac) + self.assertEqual(self.instance.networks[0]['mac'], net_mac) def test_set_link_state(self): - self.assertEqual(self.instance.networks[0]["state"], "up") + self.assertEqual(self.instance.networks[0]['state'], 'up') response = self.client.post( - reverse("instances:set_link_state", args=[self.instance.id]), + reverse('instances:set_link_state', args=[self.instance.id]), { - "mac": self.instance.networks[0]["mac"], - "set_link_state": "up", + 'mac': self.instance.networks[0]['mac'], + 'set_link_state': 'up', }, - HTTP_REFERER=reverse("index"), + HTTP_REFERER=reverse('index'), ) self.assertEqual(response.status_code, 302) del self.instance.networks - self.assertEqual(self.instance.networks[0]["state"], "down") + self.assertEqual(self.instance.networks[0]['state'], 'down') def test_set_unset_qos(self): self.assertEqual(len(self.instance.qos.keys()), 0) - net_mac = self.instance.networks[0]["mac"] + net_mac = self.instance.networks[0]['mac'] response = self.client.post( - reverse("instances:set_qos", args=[self.instance.id]), + reverse('instances:set_qos', args=[self.instance.id]), { - "net-mac-0": net_mac, - "qos_direction": "inbound", - "qos_average": 1, - "qos_peak": 1, - "qos_burst": 1, + 'net-mac-0': net_mac, + 'qos_direction': 'inbound', + 'qos_average': 1, + 'qos_peak': 1, + 'qos_burst': 1, }, - HTTP_REFERER=reverse("index"), + HTTP_REFERER=reverse('index'), ) self.assertEqual(response.status_code, 302) @@ -968,12 +899,12 @@ class InstancesTestCase(TestCase): self.assertEqual(len(self.instance.qos.keys()), 1) response = self.client.post( - reverse("instances:unset_qos", args=[self.instance.id]), + reverse('instances:unset_qos', args=[self.instance.id]), { - "net-mac": net_mac, - "qos_direction": "inbound", + 'net-mac': net_mac, + 'qos_direction': 'inbound', }, - HTTP_REFERER=reverse("index"), + HTTP_REFERER=reverse('index'), ) self.assertEqual(response.status_code, 302) del self.instance.qos @@ -996,65 +927,65 @@ class InstancesTestCase(TestCase): # self.instance.proxy.force_shutdown() def test_change_options(self): - self.assertEqual(self.instance.title, "") - self.assertEqual(self.instance.description, "") + self.assertEqual(self.instance.title, '') + self.assertEqual(self.instance.description, '') response = self.client.post( - reverse("instances:change_options", args=[self.instance.id]), + reverse('instances:change_options', args=[self.instance.id]), { - "title": "test-vm-title", - "description": "test-vm description", + 'title': 'test-vm-title', + 'description': 'test-vm description', }, - HTTP_REFERER=reverse("index"), + HTTP_REFERER=reverse('index'), ) self.assertEqual(response.status_code, 302) del self.instance.title del self.instance.description - self.assertEqual(self.instance.title, "test-vm-title") - self.assertEqual(self.instance.description, "test-vm description") + self.assertEqual(self.instance.title, 'test-vm-title') + self.assertEqual(self.instance.description, 'test-vm description') def test_flavors(self): - response = self.client.get(reverse("instances:flavor_create")) + response = self.client.get(reverse('instances:flavor_create')) self.assertEqual(response.status_code, 200) response = self.client.post( - reverse("instances:flavor_create"), + reverse('instances:flavor_create'), { - "label": "test_flavor", - "memory": 256, - "vcpu": 1, - "disk": 10, + 'label': 'test_flavor', + 'memory': 256, + 'vcpu': 1, + 'disk': 10, }, - HTTP_REFERER=reverse("index"), + HTTP_REFERER=reverse('index'), ) self.assertEqual(response.status_code, 302) id = Flavor.objects.last().id - response = self.client.get(reverse("instances:flavor_update", args=[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]), + reverse('instances:flavor_update', args=[id]), { - "label": "test_flavor_", - "memory": 256, - "vcpu": 1, - "disk": 10, + 'label': 'test_flavor_', + 'memory': 256, + 'vcpu': 1, + 'disk': 10, }, - HTTP_REFERER=reverse("index"), + HTTP_REFERER=reverse('index'), ) self.assertEqual(response.status_code, 302) - response = self.client.get(reverse("instances:flavor_delete", args=[id])) + response = self.client.get(reverse('instances:flavor_delete', args=[id])) self.assertEqual(response.status_code, 200) response = self.client.post( - reverse("instances:flavor_delete", args=[id]), + reverse('instances:flavor_delete', args=[id]), {}, - HTTP_REFERER=reverse("index"), + HTTP_REFERER=reverse('index'), ) self.assertEqual(response.status_code, 302) diff --git a/instances/urls.py b/instances/urls.py index c7a74f9..de12a83 100644 --- a/instances/urls.py +++ b/instances/urls.py @@ -2,83 +2,69 @@ from django.urls import path from . import views -app_name = "instances" +app_name = 'instances' urlpatterns = [ - path("", views.index, name="index"), - 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"), - path("/powercycle/", views.powercycle, name="powercycle"), - path("/poweroff/", views.poweroff, name="poweroff"), - path("/suspend/", views.suspend, name="suspend"), - path("/resume/", views.resume, name="resume"), - path("/force_off/", views.force_off, name="force_off"), - path("/destroy/", views.destroy, name="destroy"), - path("/migrate/", views.migrate, name="migrate"), - path("/status/", views.status, name="status"), - path("/stats/", views.stats, name="stats"), - path("/osinfo/", views.osinfo, name="osinfo"), - path("/rootpasswd/", views.set_root_pass, name="rootpasswd"), - path("/add_public_key/", views.add_public_key, name="add_public_key"), - path("/resizevm_cpu/", views.resizevm_cpu, name="resizevm_cpu"), - path("/resize_memory/", views.resize_memory, name="resize_memory"), - path("/resize_disk/", views.resize_disk, name="resize_disk"), - path("/add_new_vol/", views.add_new_vol, name="add_new_vol"), - path("/delete_vol/", views.delete_vol, name="delete_vol"), - path("/add_owner/", views.add_owner, name="add_owner"), - path("/add_existing_vol/", views.add_existing_vol, name="add_existing_vol"), - path("/edit_volume/", views.edit_volume, name="edit_volume"), - path("/detach_vol/", views.detach_vol, name="detach_vol"), - path("/add_cdrom/", views.add_cdrom, name="add_cdrom"), - path("/detach_cdrom//", views.detach_cdrom, name="detach_cdrom"), - path("/unmount_iso/", views.unmount_iso, name="unmount_iso"), - path("/mount_iso/", views.mount_iso, name="mount_iso"), - path("/snapshot/", views.snapshot, name="snapshot"), - path("/delete_snapshot/", views.delete_snapshot, name="delete_snapshot"), - path("/revert_snapshot/", views.revert_snapshot, name="revert_snapshot"), - path("/set_vcpu/", views.set_vcpu, name="set_vcpu"), - path("/set_vcpu_hotplug/", views.set_vcpu_hotplug, name="set_vcpu_hotplug"), - path("/set_autostart/", views.set_autostart, name="set_autostart"), - path("/unset_autostart/", views.unset_autostart, name="unset_autostart"), - path("/set_bootmenu/", views.set_bootmenu, name="set_bootmenu"), - path("/unset_bootmenu/", views.unset_bootmenu, name="unset_bootmenu"), - path("/set_bootorder/", views.set_bootorder, name="set_bootorder"), - path("/change_xml/", views.change_xml, name="change_xml"), - path("/set_guest_agent/", views.set_guest_agent, name="set_guest_agent"), - path("/set_video_model/", views.set_video_model, name="set_video_model"), - path("/change_network/", views.change_network, name="change_network"), - path("/add_network/", views.add_network, name="add_network"), - path("/delete_network/", views.delete_network, name="delete_network"), - path("/set_link_state/", views.set_link_state, name="set_link_state"), - path("/set_qos/", views.set_qos, name="set_qos"), - path("/unset_qos/", views.unset_qos, name="unset_qos"), - path( - "/del_owner/", views.del_owner, name="del_owner" - ), # no links to this one??? - path("/clone/", views.clone, name="clone"), - path("/update_console/", views.update_console, name="update_console"), - path("/change_options/", views.change_options, name="change_options"), - path( - "/getvvfile/", views.getvvfile, name="getvvfile" - ), # no links to this one??? - path( - "create//", - views.create_instance_select_type, - name="create_instance_select_type", - ), - path( - "create////", - views.create_instance, - name="create_instance", - ), - path( - "guess_mac_address//", views.guess_mac_address, name="guess_mac_address" - ), - path("guess_clone_name/", views.guess_clone_name, name="guess_clone_name"), - path("random_mac_address/", views.random_mac_address, name="random_mac_address"), - path("check_instance//", views.check_instance, name="check_instance"), - path("/sshkeys/", views.sshkeys, name="sshkeys"), + path('', views.index, name='index'), + 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'), + path('/powercycle/', views.powercycle, name='powercycle'), + path('/poweroff/', views.poweroff, name='poweroff'), + path('/suspend/', views.suspend, name='suspend'), + path('/resume/', views.resume, name='resume'), + path('/force_off/', views.force_off, name='force_off'), + path('/destroy/', views.destroy, name='destroy'), + path('/migrate/', views.migrate, name='migrate'), + path('/status/', views.status, name='status'), + path('/stats/', views.stats, name='stats'), + path('/osinfo/', views.osinfo, name='osinfo'), + path('/rootpasswd/', views.set_root_pass, name='rootpasswd'), + path('/add_public_key/', views.add_public_key, name='add_public_key'), + path('/resizevm_cpu/', views.resizevm_cpu, name='resizevm_cpu'), + path('/resize_memory/', views.resize_memory, name='resize_memory'), + path('/resize_disk/', views.resize_disk, name='resize_disk'), + path('/add_new_vol/', views.add_new_vol, name='add_new_vol'), + path('/delete_vol/', views.delete_vol, name='delete_vol'), + path('/add_owner/', views.add_owner, name='add_owner'), + path('/add_existing_vol/', views.add_existing_vol, name='add_existing_vol'), + path('/edit_volume/', views.edit_volume, name='edit_volume'), + path('/detach_vol/', views.detach_vol, name='detach_vol'), + path('/add_cdrom/', views.add_cdrom, name='add_cdrom'), + path('/detach_cdrom//', views.detach_cdrom, name='detach_cdrom'), + path('/unmount_iso/', views.unmount_iso, name='unmount_iso'), + path('/mount_iso/', views.mount_iso, name='mount_iso'), + path('/snapshot/', views.snapshot, name='snapshot'), + path('/delete_snapshot/', views.delete_snapshot, name='delete_snapshot'), + path('/revert_snapshot/', views.revert_snapshot, name='revert_snapshot'), + path('/set_vcpu/', views.set_vcpu, name='set_vcpu'), + path('/set_vcpu_hotplug/', views.set_vcpu_hotplug, name='set_vcpu_hotplug'), + path('/set_autostart/', views.set_autostart, name='set_autostart'), + path('/unset_autostart/', views.unset_autostart, name='unset_autostart'), + path('/set_bootmenu/', views.set_bootmenu, name='set_bootmenu'), + path('/unset_bootmenu/', views.unset_bootmenu, name='unset_bootmenu'), + path('/set_bootorder/', views.set_bootorder, name='set_bootorder'), + path('/change_xml/', views.change_xml, name='change_xml'), + path('/set_guest_agent/', views.set_guest_agent, name='set_guest_agent'), + path('/set_video_model/', views.set_video_model, name='set_video_model'), + path('/change_network/', views.change_network, name='change_network'), + path('/add_network/', views.add_network, name='add_network'), + path('/delete_network/', views.delete_network, name='delete_network'), + path('/set_link_state/', views.set_link_state, name='set_link_state'), + path('/set_qos/', views.set_qos, name='set_qos'), + path('/unset_qos/', views.unset_qos, name='unset_qos'), + path('/del_owner/', views.del_owner, name='del_owner'), # no links to this one??? + path('/clone/', views.clone, name='clone'), + path('/update_console/', views.update_console, name='update_console'), + path('/change_options/', views.change_options, name='change_options'), + path('/getvvfile/', views.getvvfile, name='getvvfile'), # no links to this one??? + path('create//', views.create_instance_select_type, name='create_instance_select_type'), + path('create////', views.create_instance, name='create_instance'), + path('guess_mac_address//', views.guess_mac_address, name='guess_mac_address'), + path('guess_clone_name/', views.guess_clone_name, name='guess_clone_name'), + path('random_mac_address/', views.random_mac_address, name='random_mac_address'), + path('check_instance//', views.check_instance, name='check_instance'), + path('/sshkeys/', views.sshkeys, name='sshkeys'), ] diff --git a/instances/utils.py b/instances/utils.py index 53752b6..a7c3f44 100644 --- a/instances/utils.py +++ b/instances/utils.py @@ -38,8 +38,8 @@ def check_user_quota(user, instance, cpu, memory, disk_size): instance += user_instances.count() for usr_inst in user_instances: if connection_manager.host_is_up( - usr_inst.instance.compute.type, - usr_inst.instance.compute.hostname, + usr_inst.instance.compute.type, + usr_inst.instance.compute.hostname, ): conn = wvmInstance( usr_inst.instance.compute.hostname, @@ -51,8 +51,8 @@ def check_user_quota(user, instance, cpu, memory, disk_size): cpu += int(conn.get_vcpu()) memory += int(conn.get_memory()) for disk in conn.get_disk_devices(): - if disk["size"]: - disk_size += int(disk["size"]) >> 30 + if disk['size']: + disk_size += int(disk['size']) >> 30 if ua.max_instances > 0 and instance > ua.max_instances: msg = "instance" @@ -86,17 +86,17 @@ def get_new_disk_dev(media, disks, bus): dev_base = "sd" if disks: - existing_disk_devs = [disk["dev"] for disk in disks] + existing_disk_devs = [disk['dev'] for disk in disks] # cd-rom bus could be virtio/sata, because of that we should check it also if media: - existing_media_devs = [m["dev"] for m in media] + existing_media_devs = [m['dev'] for m in media] for al in string.ascii_lowercase: dev = dev_base + al if dev not in existing_disk_devs and dev not in existing_media_devs: return dev - raise Exception(_("None available device name")) + raise Exception(_('None available device name')) def get_network_tuple(network_source_str): @@ -104,7 +104,7 @@ def get_network_tuple(network_source_str): if len(network_source_pack) > 1: return network_source_pack[1], network_source_pack[0] else: - return network_source_pack[0], "net" + return network_source_pack[0], 'net' def migrate_instance( @@ -174,44 +174,44 @@ def refr(compute): Instance.objects.filter(compute=compute).exclude(name__in=domain_names).delete() Instance.objects.filter(compute=compute).exclude(uuid__in=domain_uuids).delete() # Create instances that're not in DB - names = Instance.objects.filter(compute=compute).values_list("name", flat=True) + names = Instance.objects.filter(compute=compute).values_list('name', flat=True) for domain in domains: if domain.name() not in names: Instance(compute=compute, name=domain.name(), uuid=domain.UUIDString()).save() def get_dhcp_mac_address(vname): - dhcp_file = str(settings.BASE_DIR) + "/dhcpd.conf" - mac = "" + dhcp_file = str(settings.BASE_DIR) + '/dhcpd.conf' + mac = '' if os.path.isfile(dhcp_file): - with open(dhcp_file, "r") as f: + with open(dhcp_file, 'r') as f: name_found = False for line in f: if "host %s." % vname in line: name_found = True if name_found and "hardware ethernet" in line: - mac = line.split(" ")[-1].strip().strip(";") + mac = line.split(' ')[-1].strip().strip(';') break return mac def get_random_mac_address(): - mac = "52:54:00:%02x:%02x:%02x" % ( - random.randint(0x00, 0xFF), - random.randint(0x00, 0xFF), - random.randint(0x00, 0xFF), + mac = '52:54:00:%02x:%02x:%02x' % ( + random.randint(0x00, 0xff), + random.randint(0x00, 0xff), + random.randint(0x00, 0xff), ) return mac -def get_clone_disk_name(disk, prefix, clone_name=""): - if not disk["image"]: +def get_clone_disk_name(disk, prefix, clone_name=''): + if not disk['image']: return None - if disk["image"].startswith(prefix) and clone_name: - suffix = disk["image"][len(prefix) :] + if disk['image'].startswith(prefix) and clone_name: + suffix = disk['image'][len(prefix):] image = f"{clone_name}{suffix}" - elif "." in disk["image"] and len(disk["image"].rsplit(".", 1)[1]) <= 7: - name, suffix = disk["image"].rsplit(".", 1) + elif "." in disk['image'] and len(disk['image'].rsplit(".", 1)[1]) <= 7: + name, suffix = disk['image'].rsplit(".", 1) image = f"{name}-clone.{suffix}" else: image = f"{disk['image']}-clone" diff --git a/instances/views.py b/instances/views.py index ef979b0..d19cba3 100644 --- a/instances/views.py +++ b/instances/views.py @@ -21,11 +21,7 @@ from django.shortcuts import get_object_or_404, redirect, render from django.urls import reverse from django.utils.translation import gettext_lazy as _ from instances.models import Instance -from libvirt import ( - VIR_DOMAIN_UNDEFINE_KEEP_NVRAM, - VIR_DOMAIN_UNDEFINE_NVRAM, - libvirtError, -) +from libvirt import VIR_DOMAIN_UNDEFINE_KEEP_NVRAM, VIR_DOMAIN_UNDEFINE_NVRAM, libvirtError from logs.views import addlogmsg from vrtManager import util from vrtManager.create import wvmCreate @@ -54,13 +50,9 @@ def index(request): if request.user.is_superuser or request.user.has_perm("instances.view_instances"): instances = Instance.objects.all().prefetch_related("userinstance_set") else: - instances = Instance.objects.filter( - userinstance__user=request.user - ).prefetch_related("userinstance_set") + instances = Instance.objects.filter(userinstance__user=request.user).prefetch_related("userinstance_set") - return render( - request, "allinstances.html", {"computes": computes, "instances": instances} - ) + return render(request, "allinstances.html", {"computes": computes, "instances": instances}) def instance(request, pk): @@ -71,9 +63,7 @@ def instance(request, pk): users = User.objects.all().order_by("username") publickeys = UserSSHKey.objects.filter(user_id=request.user.id) keymaps = settings.QEMU_KEYMAPS - console_types = AppSettings.objects.get( - key="QEMU_CONSOLE_DEFAULT_TYPE" - ).choices_as_list() + console_types = AppSettings.objects.get(key="QEMU_CONSOLE_DEFAULT_TYPE").choices_as_list() console_form = ConsoleForm( initial={ "type": instance.console_type, @@ -84,14 +74,10 @@ def instance(request, pk): ) console_listener_addresses = settings.QEMU_CONSOLE_LISTENER_ADDRESSES bottom_bar = app_settings.VIEW_INSTANCE_DETAIL_BOTTOM_BAR - allow_admin_or_not_template = ( - request.user.is_superuser or request.user.is_staff or not instance.is_template - ) + allow_admin_or_not_template = request.user.is_superuser or request.user.is_staff or not instance.is_template try: userinstance = UserInstance.objects.get( - instance__compute_id=compute.id, - instance__name=instance.name, - user__id=request.user.id, + instance__compute_id=compute.id, instance__name=instance.name, user__id=request.user.id ) except UserInstance.DoesNotExist: userinstance = None @@ -130,9 +116,7 @@ def instance(request, pk): # userinstances = UserInstance.objects.filter(instance=instance).order_by('user__username') userinstances = instance.userinstance_set.order_by("user__username") - allow_admin_or_not_template = ( - request.user.is_superuser or request.user.is_staff or not instance.is_template - ) + allow_admin_or_not_template = request.user.is_superuser or request.user.is_staff or not instance.is_template # Host resources vcpu_host = len(instance.vcpu_range) @@ -144,7 +128,7 @@ def instance(request, pk): storages_host = sorted(instance.proxy.get_storages(True)) net_models_host = instance.proxy.get_network_models() - if app_settings.VM_DRBD_STATUS == "True": + if app_settings.VM_DRBD_STATUS == 'True': instance.drbd = drbd_status(request, pk) instance.save() @@ -155,25 +139,17 @@ def status(request, pk): instance = get_instance(request.user, pk) return JsonResponse({"status": instance.proxy.get_status()}) - def drbd_status(request, pk): instance = get_instance(request.user, pk) result = "None DRBD" if instance.compute.type == 2: conn = instance.compute.login + "@" + instance.compute.hostname - remoteDrbdStatus = subprocess.run( - ["ssh", conn, "sudo", "/usr/sbin/drbdadm", "status", "&&", "exit"], - stdout=subprocess.PIPE, - text=True, - ) + remoteDrbdStatus = subprocess.run(["ssh", conn, "sudo", "/usr/sbin/drbdadm", "status", "&&", "exit"], stdout=subprocess.PIPE, text=True) if remoteDrbdStatus.stdout: try: - instanceFindDrbd = re.compile( - instance.name + "[_]*[A-Z]* role:(.+?)\n disk:(.+?)\n", - re.IGNORECASE, - ) + instanceFindDrbd = re.compile(instance.name + '[_]*[A-Z]* role:(.+?)\n disk:(.+?)\n', re.IGNORECASE) instanceDrbd = instanceFindDrbd.findall(remoteDrbdStatus.stdout) primaryCount = 0 @@ -203,7 +179,6 @@ def drbd_status(request, pk): return result - def stats(request, pk): instance = get_instance(request.user, pk) json_blk = [] @@ -217,20 +192,10 @@ def stats(request, pk): current_time = time.strftime("%H:%M:%S") for blk in blk_usage: - json_blk.append( - { - "dev": blk["dev"], - "data": [int(blk["rd"]) / 1048576, int(blk["wr"]) / 1048576], - } - ) + json_blk.append({"dev": blk["dev"], "data": [int(blk["rd"]) / 1048576, int(blk["wr"]) / 1048576]}) for net in net_usage: - json_net.append( - { - "dev": net["dev"], - "data": [int(net["rx"]) / 1048576, int(net["tx"]) / 1048576], - } - ) + json_net.append({"dev": net["dev"], "data": [int(net["rx"]) / 1048576, int(net["tx"]) / 1048576]}) return JsonResponse( { @@ -242,14 +207,12 @@ def stats(request, pk): } ) - def osinfo(request, pk): instance = get_instance(request.user, pk) results = instance.proxy.osinfo() - + return JsonResponse(results) - def guess_mac_address(request, vname): data = {"vname": vname} mac = utils.get_dhcp_mac_address(vname) @@ -269,9 +232,7 @@ def guess_clone_name(request): dhcp_file = "/srv/webvirtcloud/dhcpd.conf" prefix = app_settings.CLONE_INSTANCE_DEFAULT_PREFIX if os.path.isfile(dhcp_file): - instance_names = [ - i.name for i in Instance.objects.filter(name__startswith=prefix) - ] + instance_names = [i.name for i in Instance.objects.filter(name__startswith=prefix)] with open(dhcp_file, "r") as f: for line in f: line = line.strip() @@ -320,11 +281,7 @@ def get_instance(user, pk): instance = get_object_or_404(Instance, pk=pk) user_instances = user.userinstance_set.all().values_list("instance", flat=True) - if ( - user.is_superuser - or user.has_perm("instances.view_instances") - or instance.id in user_instances - ): + if user.is_superuser or user.has_perm("instances.view_instances") or instance.id in user_instances: return instance else: raise Http404() @@ -336,9 +293,7 @@ def poweron(request, pk): messages.warning(request, _("Templates cannot be started.")) else: instance.proxy.start() - addlogmsg( - request.user.username, instance.compute.name, instance.name, _("Power On") - ) + addlogmsg(request.user.username, instance.compute.name, instance.name, _("Power On")) return redirect(request.META.get("HTTP_REFERER")) @@ -347,18 +302,14 @@ def powercycle(request, pk): instance = get_instance(request.user, pk) instance.proxy.force_shutdown() instance.proxy.start() - addlogmsg( - request.user.username, instance.compute.name, instance.name, _("Power Cycle") - ) + addlogmsg(request.user.username, instance.compute.name, instance.name, _("Power Cycle")) return redirect(request.META.get("HTTP_REFERER")) def poweroff(request, pk): instance = get_instance(request.user, pk) instance.proxy.shutdown() - addlogmsg( - request.user.username, instance.compute.name, instance.name, _("Power Off") - ) + addlogmsg(request.user.username, instance.compute.name, instance.name, _("Power Off")) return redirect(request.META.get("HTTP_REFERER")) @@ -382,9 +333,7 @@ def resume(request, pk): def force_off(request, pk): instance = get_instance(request.user, pk) instance.proxy.force_shutdown() - addlogmsg( - request.user.username, instance.compute.name, instance.name, _("Force Off") - ) + addlogmsg(request.user.username, instance.compute.name, instance.name, _("Force Off")) return redirect(request.META.get("HTTP_REFERER")) @@ -400,9 +349,7 @@ def destroy(request, pk): instance.proxy.force_shutdown() if request.POST.get("delete_disk", ""): - snapshots = sorted( - instance.proxy.get_snapshot(), reverse=True, key=lambda k: k["date"] - ) + snapshots = sorted(instance.proxy.get_snapshot(), reverse=True, key=lambda k: k["date"]) for snapshot in snapshots: instance.proxy.snapshot_delete(snapshot["name"]) instance.proxy.delete_all_disks() @@ -413,9 +360,7 @@ def destroy(request, pk): instance.proxy.delete(VIR_DOMAIN_UNDEFINE_KEEP_NVRAM) instance.delete() - addlogmsg( - request.user.username, instance.compute.name, instance.name, _("Destroy") - ) + addlogmsg(request.user.username, instance.compute.name, instance.name, _("Destroy")) return redirect(reverse("instances:index")) return render( @@ -445,26 +390,12 @@ def migrate(request, pk): target_host = Compute.objects.get(id=compute_id) try: - utils.migrate_instance( - target_host, - instance, - request.user, - live, - unsafe, - xml_del, - offline, - autoconverge, - compress, - postcopy, - ) + utils.migrate_instance(target_host, instance, request.user, live, unsafe, xml_del, offline, autoconverge, compress, postcopy) except libvirtError as err: messages.error(request, err) migration_method = "live" if live is True else "offline" - msg = _("Instance is migrated(%(method)s) to %(hostname)s") % { - "hostname": target_host.hostname, - "method": migration_method, - } + msg = _("Instance is migrated(%(method)s) to %(hostname)s") % {"hostname": target_host.hostname, "method": migration_method} addlogmsg(request.user.username, current_host, instance.name, msg) return redirect(request.META.get("HTTP_REFERER")) @@ -488,9 +419,7 @@ def set_root_pass(request, pk): s.close() if result["return"] == "success": msg = _("Reset root password") - addlogmsg( - request.user.username, instance.compute.name, instance.name, msg - ) + addlogmsg(request.user.username, instance.compute.name, instance.name, msg) messages.success(request, msg) else: messages.error(request, result["message"]) @@ -505,11 +434,7 @@ def add_public_key(request, pk): if request.method == "POST": sshkeyid = request.POST.get("sshkeyid", "") publickey = UserSSHKey.objects.get(id=sshkeyid) - data = { - "action": "publickey", - "key": publickey.keypublic, - "vname": instance.name, - } + data = {"action": "publickey", "key": publickey.keypublic, "vname": instance.name} if instance.proxy.get_status() == 5: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) @@ -520,9 +445,7 @@ def add_public_key(request, pk): if result["return"] == "error": msg = result["message"] else: - msg = _("Installed new SSH public key %(keyname)s") % { - "keyname": publickey.keyname - } + msg = _("Installed new SSH public key %(keyname)s") % {"keyname": publickey.keyname} addlogmsg(request.user.username, instance.compute.name, instance.name, msg) if result["return"] == "success": @@ -547,13 +470,9 @@ def resizevm_cpu(request, pk): new_vcpu = request.POST.get("vcpu", "") new_cur_vcpu = request.POST.get("cur_vcpu", "") - quota_msg = utils.check_user_quota( - request.user, 0, int(new_vcpu) - vcpu, 0, 0 - ) + quota_msg = utils.check_user_quota(request.user, 0, int(new_vcpu) - vcpu, 0, 0) if not request.user.is_superuser and quota_msg: - msg = _( - "User %(quota_msg)s quota reached, cannot resize CPU of '%(instance_name)s'!" - ) % { + msg = _("User %(quota_msg)s quota reached, cannot resize CPU of '%(instance_name)s'!") % { "quota_msg": quota_msg, "instance_name": instance.name, } @@ -562,13 +481,8 @@ def resizevm_cpu(request, pk): cur_vcpu = new_cur_vcpu vcpu = new_vcpu instance.proxy.resize_cpu(cur_vcpu, vcpu) - msg = _("CPU is resized: %(old)s to %(new)s") % { - "old": cur_vcpu, - "new": vcpu, - } - addlogmsg( - request.user.username, instance.compute.name, instance.name, msg - ) + msg = _("CPU is resized: %(old)s to %(new)s") % {"old": cur_vcpu, "new": vcpu} + addlogmsg(request.user.username, instance.compute.name, instance.name, msg) messages.success(request, msg) return redirect(reverse("instances:instance", args=[instance.id]) + "#resize") @@ -593,30 +507,22 @@ def resize_memory(request, pk): new_cur_memory_custom = request.POST.get("cur_memory_custom", "") if new_cur_memory_custom: new_cur_memory = new_cur_memory_custom - quota_msg = utils.check_user_quota( - request.user, 0, 0, int(new_memory) - memory, 0 - ) + 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 = _( - "User %(quota_msg)s quota reached, cannot resize memory of '%(instance_name)s'!" - ) % { + msg = _("User %(quota_msg)s quota reached, cannot resize memory of '%(instance_name)s'!") % { "quota_msg": quota_msg, "instance_name": instance.name, } messages.error(request, msg) else: instance.proxy.resize_mem(new_cur_memory, new_memory) - msg = _( - "Memory is resized: current/max: %(old_cur)s/%(old_max)s to %(new_cur)s/%(new_max)s" - ) % { + msg = _("Memory is resized: current/max: %(old_cur)s/%(old_max)s to %(new_cur)s/%(new_max)s") % { "old_cur": cur_memory, "old_max": memory, "new_cur": new_cur_memory, "new_max": new_memory, } - addlogmsg( - request.user.username, instance.compute.name, instance.name, msg - ) + addlogmsg(request.user.username, instance.compute.name, instance.name, msg) messages.success(request, msg) return redirect(reverse("instances:instance", args=[instance.id]) + "#resize") @@ -636,21 +542,15 @@ def resize_disk(request, pk): if request.user.is_superuser or request.user.is_staff or userinstance.is_change: disks_new = list() for disk in disks: - input_disk_size = ( - int(request.POST.get("disk_size_" + disk["dev"], "0")) * 1073741824 - ) + input_disk_size = int(request.POST.get("disk_size_" + disk["dev"], "0")) * 1073741824 if input_disk_size > disk["size"] + (64 << 20): disk["size_new"] = input_disk_size disks_new.append(disk) disk_sum = sum([disk["size"] >> 30 for disk in disks_new]) disk_new_sum = sum([disk["size_new"] >> 30 for disk in disks_new]) - quota_msg = utils.check_user_quota( - request.user, 0, 0, 0, disk_new_sum - disk_sum - ) + quota_msg = utils.check_user_quota(request.user, 0, 0, 0, disk_new_sum - disk_sum) if not request.user.is_superuser and quota_msg: - msg = _( - "User %(quota_msg)s quota reached, cannot resize disks of '%(instance_name)s'!" - ) % { + msg = _("User %(quota_msg)s quota reached, cannot resize disks of '%(instance_name)s'!") % { "quota_msg": quota_msg, "instance_name": instance.name, } @@ -658,9 +558,7 @@ def resize_disk(request, pk): else: instance.proxy.resize_disk(disks_new) msg = _("Disk is resized: %(dev)s") % {"dev": disk["dev"]} - addlogmsg( - request.user.username, instance.compute.name, instance.name, msg - ) + addlogmsg(request.user.username, instance.compute.name, instance.name, msg) messages.success(request, msg) return redirect(reverse("instances:instance", args=[instance.id]) + "#resize") @@ -668,9 +566,7 @@ def resize_disk(request, pk): def add_new_vol(request, pk): instance = get_instance(request.user, pk) - allow_admin_or_not_template = ( - request.user.is_superuser or request.user.is_staff or not instance.is_template - ) + allow_admin_or_not_template = request.user.is_superuser or request.user.is_staff or not instance.is_template if allow_admin_or_not_template: media = instance.proxy.get_media_devices() @@ -711,34 +607,20 @@ def add_new_vol(request, pk): pool_type = conn_pool.get_type() disk_type = conn_pool.get_volume_type(os.path.basename(source)) - if pool_type == "rbd": + if pool_type == 'rbd': source_info = conn_pool.get_rbd_source() - else: # add more disk types to handle different pool and disk types + else: # add more disk types to handle different pool and disk types source_info = None - instance.proxy.attach_disk( - target_dev, - source, - source_info=source_info, - pool_type=pool_type, - disk_type=disk_type, - target_bus=bus, - format_type=format, - cache_mode=cache, - ) - msg = _("Attach new disk: %(name)s (%(format)s)") % { - "name": name, - "format": format, - } + instance.proxy.attach_disk(target_dev, source, source_info=source_info, pool_type=pool_type, disk_type=disk_type, target_bus=bus, format_type=format, cache_mode=cache) + msg = _("Attach new disk: %(name)s (%(format)s)") % {"name": name, "format": format} addlogmsg(request.user.username, instance.compute.name, instance.name, msg) return redirect(request.META.get("HTTP_REFERER") + "#disks") def add_existing_vol(request, pk): instance = get_instance(request.user, pk) - allow_admin_or_not_template = ( - request.user.is_superuser or request.user.is_staff or not instance.is_template - ) + allow_admin_or_not_template = request.user.is_superuser or request.user.is_staff or not instance.is_template if allow_admin_or_not_template: storage = request.POST.get("selected_storage", "") name = request.POST.get("vols", "") @@ -759,7 +641,7 @@ def add_existing_vol(request, pk): format_type = conn_create.get_volume_format_type(name) disk_type = conn_create.get_volume_type(name) pool_type = conn_create.get_type() - if pool_type == "rbd": + if pool_type == 'rbd': source_info = conn_create.get_rbd_source() path = conn_create.get_source_name() else: @@ -769,16 +651,7 @@ def add_existing_vol(request, pk): target_dev = utils.get_new_disk_dev(media, disks, bus) source = f"{path}/{name}" - instance.proxy.attach_disk( - target_dev, - source, - source_info=source_info, - pool_type=pool_type, - disk_type=disk_type, - target_bus=bus, - format_type=format_type, - cache_mode=cache, - ) + instance.proxy.attach_disk(target_dev, source, source_info=source_info, pool_type=pool_type, disk_type=disk_type, target_bus=bus, format_type=format_type, cache_mode=cache) msg = _("Attach Existing disk: %(target_dev)s") % {"target_dev": target_dev} addlogmsg(request.user.username, instance.compute.name, instance.name, msg) return redirect(request.META.get("HTTP_REFERER") + "#disks") @@ -786,9 +659,7 @@ def add_existing_vol(request, pk): def edit_volume(request, pk): instance = get_instance(request.user, pk) - allow_admin_or_not_template = ( - request.user.is_superuser or request.user.is_staff or not instance.is_template - ) + allow_admin_or_not_template = request.user.is_superuser or request.user.is_staff or not instance.is_template if "edit_volume" in request.POST and allow_admin_or_not_template: target_dev = request.POST.get("dev", "") @@ -800,16 +671,10 @@ def edit_volume(request, pk): new_bus = request.POST.get("vol_bus", bus) serial = request.POST.get("vol_serial", "") format = request.POST.get("vol_format", "") - cache = request.POST.get( - "vol_cache", app_settings.INSTANCE_VOLUME_DEFAULT_CACHE - ) + cache = request.POST.get("vol_cache", app_settings.INSTANCE_VOLUME_DEFAULT_CACHE) io = request.POST.get("vol_io_mode", app_settings.INSTANCE_VOLUME_DEFAULT_IO) - discard = request.POST.get( - "vol_discard_mode", app_settings.INSTANCE_VOLUME_DEFAULT_DISCARD - ) - zeroes = request.POST.get( - "vol_detect_zeroes", app_settings.INSTANCE_VOLUME_DEFAULT_DETECT_ZEROES - ) + discard = request.POST.get("vol_discard_mode", app_settings.INSTANCE_VOLUME_DEFAULT_DISCARD) + zeroes = request.POST.get("vol_detect_zeroes", app_settings.INSTANCE_VOLUME_DEFAULT_DETECT_ZEROES) new_target_dev = utils.get_new_disk_dev(instance.media, instance.disks, new_bus) if new_bus != bus: @@ -845,10 +710,7 @@ def edit_volume(request, pk): if not instance.proxy.get_status() == 5: messages.success( request, - _( - "Volume changes are applied. " - + "But it will be activated after shutdown" - ), + _("Volume changes are applied. " + "But it will be activated after shutdown"), ) else: messages.success(request, _("Volume is changed successfully.")) @@ -860,9 +722,7 @@ def edit_volume(request, pk): def delete_vol(request, pk): instance = get_instance(request.user, pk) - allow_admin_or_not_template = ( - request.user.is_superuser or request.user.is_staff or not instance.is_template - ) + allow_admin_or_not_template = request.user.is_superuser or request.user.is_staff or not instance.is_template if allow_admin_or_not_template: storage = request.POST.get("storage", "") conn_delete = wvmStorage( @@ -886,9 +746,7 @@ def delete_vol(request, pk): def detach_vol(request, pk): instance = get_instance(request.user, pk) - allow_admin_or_not_template = ( - request.user.is_superuser or request.user.is_staff or not instance.is_template - ) + allow_admin_or_not_template = request.user.is_superuser or request.user.is_staff or not instance.is_template if allow_admin_or_not_template: dev = request.POST.get("dev", "") @@ -902,20 +760,11 @@ def detach_vol(request, pk): def add_cdrom(request, pk): instance = get_instance(request.user, pk) - allow_admin_or_not_template = ( - request.user.is_superuser or request.user.is_staff or not instance.is_template - ) + allow_admin_or_not_template = request.user.is_superuser or request.user.is_staff or not instance.is_template if allow_admin_or_not_template: bus = request.POST.get("bus", "ide" if instance.machine == "pc" else "sata") target = utils.get_new_disk_dev(instance.media, instance.disks, bus) - instance.proxy.attach_disk( - target, - "", - disk_device="cdrom", - cache_mode="none", - target_bus=bus, - readonly=True, - ) + instance.proxy.attach_disk(target, "", disk_device="cdrom", cache_mode="none", target_bus=bus, readonly=True) msg = _("Add CD-ROM: %(target)s") % {"target": target} addlogmsg(request.user.username, instance.compute.name, instance.name, msg) @@ -924,9 +773,7 @@ def add_cdrom(request, pk): def detach_cdrom(request, pk, dev): instance = get_instance(request.user, pk) - allow_admin_or_not_template = ( - request.user.is_superuser or request.user.is_staff or not instance.is_template - ) + allow_admin_or_not_template = request.user.is_superuser or request.user.is_staff or not instance.is_template if allow_admin_or_not_template: # dev = request.POST.get('detach_cdrom', '') @@ -939,9 +786,7 @@ def detach_cdrom(request, pk, dev): def unmount_iso(request, pk): instance = get_instance(request.user, pk) - allow_admin_or_not_template = ( - request.user.is_superuser or request.user.is_staff or not instance.is_template - ) + allow_admin_or_not_template = request.user.is_superuser or request.user.is_staff or not instance.is_template if allow_admin_or_not_template: image = request.POST.get("path", "") dev = request.POST.get("umount_iso", "") @@ -954,9 +799,7 @@ def unmount_iso(request, pk): def mount_iso(request, pk): instance = get_instance(request.user, pk) - allow_admin_or_not_template = ( - request.user.is_superuser or request.user.is_staff or not instance.is_template - ) + allow_admin_or_not_template = request.user.is_superuser or request.user.is_staff or not instance.is_template if allow_admin_or_not_template: image = request.POST.get("media", "") dev = request.POST.get("mount_iso", "") @@ -969,13 +812,9 @@ def mount_iso(request, pk): def snapshot(request, pk): instance = get_instance(request.user, pk) - allow_admin_or_not_template = ( - request.user.is_superuser or request.user.is_staff or not instance.is_template - ) + allow_admin_or_not_template = request.user.is_superuser or request.user.is_staff or not instance.is_template - if allow_admin_or_not_template and request.user.has_perm( - "instances.snapshot_instances" - ): + if allow_admin_or_not_template and request.user.has_perm("instances.snapshot_instances"): name = request.POST.get("name", "") desc = request.POST.get("description", "") instance.proxy.create_snapshot(name, desc) @@ -986,12 +825,8 @@ def snapshot(request, pk): def delete_snapshot(request, pk): instance = get_instance(request.user, pk) - allow_admin_or_not_template = ( - request.user.is_superuser or request.user.is_staff or not instance.is_template - ) - if allow_admin_or_not_template and request.user.has_perm( - "instances.snapshot_instances" - ): + allow_admin_or_not_template = request.user.is_superuser or request.user.is_staff or not instance.is_template + if allow_admin_or_not_template and request.user.has_perm("instances.snapshot_instances"): snap_name = request.POST.get("name", "") instance.proxy.snapshot_delete(snap_name) msg = _("Delete snapshot: %(snap)s") % {"snap": snap_name} @@ -1001,12 +836,8 @@ def delete_snapshot(request, pk): def revert_snapshot(request, pk): instance = get_instance(request.user, pk) - allow_admin_or_not_template = ( - request.user.is_superuser or request.user.is_staff or not instance.is_template - ) - if allow_admin_or_not_template and request.user.has_perm( - "instances.snapshot_instances" - ): + allow_admin_or_not_template = request.user.is_superuser or request.user.is_staff or not instance.is_template + if allow_admin_or_not_template and request.user.has_perm("instances.snapshot_instances"): snap_name = request.POST.get("name", "") instance.proxy.snapshot_revert(snap_name) msg = _("Successful revert snapshot: ") @@ -1034,7 +865,7 @@ def set_vcpu(request, pk): @superuser_only def set_vcpu_hotplug(request, pk): instance = get_instance(request.user, pk) - status = True if request.POST.get("vcpu_hotplug", "False") == "True" else False + status = True if request.POST.get("vcpu_hotplug", "False") == 'True' else False msg = _("VCPU Hot-plug is enabled=%(status)s") % {"status": status} instance.proxy.set_vcpu_hotplug(status) addlogmsg(request.user.username, instance.compute.name, instance.name, msg) @@ -1092,10 +923,7 @@ def set_bootorder(request, pk): if not instance.proxy.get_status() == 5: messages.success( request, - _( - "Boot menu changes applied. " - + "But it will be activated after shutdown" - ), + _("Boot menu changes applied. " + "But it will be activated after shutdown"), ) else: messages.success(request, _("Boot order changed successfully.")) @@ -1151,7 +979,7 @@ def change_network(request, pk): network_data[post] = source network_data[post + "-type"] = source_type - if source_type == "iface": + if source_type == 'iface': iface = wvmInterface( instance.compute.hostname, instance.compute.login, @@ -1179,14 +1007,14 @@ def add_network(request, pk): nwfilter = request.POST.get("add-net-nwfilter") (source, source_type) = utils.get_network_tuple(request.POST.get("add-net-network")) - if source_type == "iface": + if source_type == 'iface': iface = wvmInterface( - instance.compute.hostname, - instance.compute.login, - instance.compute.password, - instance.compute.type, - source, - ) + instance.compute.hostname, + instance.compute.login, + instance.compute.password, + instance.compute.type, + source, + ) source_type = iface.get_type() instance.proxy.add_network(mac, source, source_type, nwfilter=nwfilter) @@ -1234,9 +1062,7 @@ def set_qos(request, pk): instance.proxy.set_qos(mac, qos_dir, average, peak, burst) if instance.proxy.get_status() == 5: - messages.success( - request, _("%(qos_dir)s QoS is set") % {"qos_dir": qos_dir.capitalize()} - ) + messages.success(request, _("%(qos_dir)s QoS is set") % {"qos_dir": qos_dir.capitalize()}) else: messages.success( request, @@ -1258,9 +1084,7 @@ def unset_qos(request, pk): instance.proxy.unset_qos(mac, qos_dir) if instance.proxy.get_status() == 5: - messages.success( - request, _("%(qos_dir)s QoS is deleted") % {"qos_dir": qos_dir.capitalize()} - ) + messages.success(request, _("%(qos_dir)s QoS is deleted") % {"qos_dir": qos_dir.capitalize()}) else: messages.success( request, @@ -1284,9 +1108,7 @@ def add_owner(request, pk): check_inst = UserInstance.objects.filter(instance=instance).count() if check_inst > 0: - messages.error( - request, _("Only one owner is allowed and the one already added") - ) + messages.error(request, _("Only one owner is allowed and the one already added")) else: add_user_inst = UserInstance(instance=instance, user_id=user_id) add_user_inst.save() @@ -1315,9 +1137,7 @@ def clone(request, pk): clone_data["name"] = request.POST.get("name", "") disk_sum = sum([disk["size"] >> 30 for disk in instance.disks]) - quota_msg = utils.check_user_quota( - request.user, 1, instance.vcpu, instance.memory, disk_sum - ) + quota_msg = utils.check_user_quota(request.user, 1, instance.vcpu, instance.memory, disk_sum) check_instance = Instance.objects.filter(name=clone_data["name"]) clone_data["disk_owner_uid"] = int(app_settings.INSTANCE_VOLUME_DEFAULT_OWNER_UID) @@ -1336,31 +1156,19 @@ def clone(request, pk): clone_data[disk_dev] = disk_name if not request.user.is_superuser and quota_msg: - msg = _( - "User '%(quota_msg)s' quota reached, cannot create '%(clone_name)s'!" - ) % { + msg = _("User '%(quota_msg)s' quota reached, cannot create '%(clone_name)s'!") % { "quota_msg": quota_msg, "clone_name": clone_data["name"], } messages.error(request, msg) elif check_instance: - msg = _("Instance '%(clone_name)s' already exists!") % { - "clone_name": clone_data["name"] - } + msg = _("Instance '%(clone_name)s' already exists!") % {"clone_name": clone_data["name"]} messages.error(request, msg) elif not re.match(r"^[a-zA-Z0-9-]+$", clone_data["name"]): - msg = _("Instance name '%(clone_name)s' contains invalid characters!") % { - "clone_name": clone_data["name"] - } + msg = _("Instance name '%(clone_name)s' contains invalid characters!") % {"clone_name": clone_data["name"]} messages.error(request, msg) - elif not re.match( - r"^([0-9A-F]{2})(:?[0-9A-F]{2}){5}$", - clone_data["clone-net-mac-0"], - re.IGNORECASE, - ): - msg = _("Instance MAC '%(clone_mac)s' invalid format!") % { - "clone_mac": clone_data["clone-net-mac-0"] - } + elif not re.match(r"^([0-9A-F]{2})(:?[0-9A-F]{2}){5}$", clone_data["clone-net-mac-0"], re.IGNORECASE): + msg = _("Instance MAC '%(clone_mac)s' invalid format!") % {"clone_mac": clone_data["clone-net-mac-0"]} messages.error(request, msg) else: new_instance = Instance(compute=instance.compute, name=clone_data["name"]) @@ -1368,23 +1176,15 @@ def clone(request, pk): new_uuid = instance.proxy.clone_instance(clone_data) new_instance.uuid = new_uuid new_instance.save() - user_instance = UserInstance( - instance_id=new_instance.id, user_id=request.user.id, is_delete=True - ) + user_instance = UserInstance(instance_id=new_instance.id, user_id=request.user.id, is_delete=True) user_instance.save() - msg = _("Create a clone of '%(instance_name)s'") % { - "instance_name": instance.name - } + msg = _("Create a clone of '%(instance_name)s'") % {"instance_name": instance.name} messages.success(request, msg) - addlogmsg( - request.user.username, instance.compute.name, new_instance.name, msg - ) + addlogmsg(request.user.username, instance.compute.name, new_instance.name, msg) if app_settings.CLONE_INSTANCE_AUTO_MIGRATE == "True": new_compute = Compute.objects.order_by("?").first() - utils.migrate_instance( - new_compute, new_instance, request.user, xml_del=True, offline=True - ) + utils.migrate_instance(new_compute, new_instance, request.user, xml_del=True, offline=True) return redirect(reverse("instances:instance", args=[new_instance.id])) except Exception as e: @@ -1423,9 +1223,7 @@ def update_console(request, pk): messages.error(request, msg) else: msg = _("Set VNC password") - addlogmsg( - request.user.username, instance.compute.name, instance.name, msg - ) + addlogmsg(request.user.username, instance.compute.name, instance.name, msg) if "keymap" in form.changed_data or "clear_keymap" in form.changed_data: if form.cleaned_data["clear_keymap"]: @@ -1434,23 +1232,17 @@ def update_console(request, pk): instance.proxy.set_console_keymap(form.cleaned_data["keymap"]) msg = _("Set VNC keymap") - addlogmsg( - request.user.username, instance.compute.name, instance.name, msg - ) + addlogmsg(request.user.username, instance.compute.name, instance.name, msg) if "type" in form.changed_data: instance.proxy.set_console_type(form.cleaned_data["type"]) msg = _("Set VNC type") - addlogmsg( - request.user.username, instance.compute.name, instance.name, msg - ) + addlogmsg(request.user.username, instance.compute.name, instance.name, msg) if "listen_on" in form.changed_data: instance.proxy.set_console_listener_addr(form.cleaned_data["listen_on"]) msg = _("Set VNC listen address") - addlogmsg( - request.user.username, instance.compute.name, instance.name, msg - ) + addlogmsg(request.user.username, instance.compute.name, instance.name, msg) return redirect(request.META.get("HTTP_REFERER") + "#vncsettings") @@ -1534,15 +1326,7 @@ def create_instance_select_type(request, compute_id): all_hypervisors = conn.get_hypervisors_machines() # Supported hypervisors by webvirtcloud: i686, x86_64(for now) - supported_arch = [ - "x86_64", - "i686", - "aarch64", - "armv7l", - "ppc64", - "ppc64le", - "s390x", - ] + supported_arch = ["x86_64", "i686", "aarch64", "armv7l", "ppc64", "ppc64le", "s390x"] hypervisors = [hpv for hpv in all_hypervisors.keys() if hpv in supported_arch] default_machine = app_settings.INSTANCE_MACHINE_DEFAULT_TYPE default_arch = app_settings.INSTANCE_ARCH_DEFAULT_TYPE @@ -1587,12 +1371,7 @@ def create_instance(request, compute_id, arch, machine): appsettings = AppSettings.objects.all() try: - conn = wvmCreate( - compute.hostname, - compute.login, - compute.password, - compute.type - ) + conn = wvmCreate(compute.hostname, compute.login, compute.password, compute.type) default_firmware = app_settings.INSTANCE_FIRMWARE_DEFAULT_TYPE default_cpu_mode = app_settings.INSTANCE_CPU_DEFAULT_MODE @@ -1618,7 +1397,7 @@ def create_instance(request, compute_id, arch, machine): storages = sorted(conn.get_storages(only_actives=True)) default_graphics = app_settings.QEMU_CONSOLE_DEFAULT_TYPE default_cdrom = app_settings.INSTANCE_CDROM_ADD - input_device_buses = ["default", "virtio", "usb"] + input_device_buses = ['default', 'virtio', 'usb'] default_input_device_bus = app_settings.INSTANCE_INPUT_DEFAULT_DEVICE dom_caps = conn.get_dom_capabilities(arch, machine) @@ -1658,21 +1437,13 @@ def create_instance(request, compute_id, arch, machine): meta_prealloc = True if instances: if data["name"] in instances: - raise libvirtError( - _("A virtual machine with this name already exists") - ) + raise libvirtError(_("A virtual machine with this name already exists")) if Instance.objects.filter(name__exact=data["name"]): - raise libvirtError( - _( - "There is an instance with same name. Remove it and try again!" - ) - ) + raise libvirtError(_("There is an instance with same name. Remove it and try again!")) if data["hdd_size"]: if not data["mac"]: - raise libvirtError( - _("No Virtual Machine MAC has been entered") - ) + raise libvirtError(_("No Virtual Machine MAC has been entered")) else: path = conn.create_volume( data["storage"], @@ -1700,14 +1471,10 @@ def create_instance(request, compute_id, arch, machine): elif data["template"]: templ_path = conn.get_volume_path(data["template"]) - dest_vol = conn.get_volume_path( - data["name"] + ".img", data["storage"] - ) + dest_vol = conn.get_volume_path(data["name"] + ".img", data["storage"]) if dest_vol: raise libvirtError( - _( - "Image has already exist. Please check volumes or change instance name" - ) + _("Image has already exist. Please check volumes or change instance name") ) else: clone_path = conn.clone_from_template( @@ -1734,21 +1501,15 @@ def create_instance(request, compute_id, arch, machine): is_disk_created = True else: if not data["images"]: - raise libvirtError( - _("First you need to create or select an image") - ) + raise libvirtError(_("First you need to create or select an image")) else: for idx, vol in enumerate(data["images"].split(",")): path = conn.get_volume_path(vol) volume = dict() volume["path"] = path volume["type"] = conn.get_volume_format_type(path) - volume["device"] = request.POST.get( - "device" + str(idx), "" - ) - volume["bus"] = request.POST.get( - "bus" + str(idx), "" - ) + volume["device"] = request.POST.get("device" + str(idx), "") + volume["bus"] = request.POST.get("bus" + str(idx), "") if volume["bus"] == "scsi": volume["scsi_model"] = default_scsi_disk_model volume["cache_mode"] = data["cache_mode"] @@ -1799,21 +1560,12 @@ def create_instance(request, compute_id, arch, machine): add_cdrom=data["add_cdrom"], add_input=data["add_input"], ) - create_instance = Instance( - compute_id=compute_id, name=data["name"], uuid=uuid - ) + create_instance = Instance(compute_id=compute_id, name=data["name"], uuid=uuid) create_instance.save() msg = _("Instance is created") messages.success(request, msg) - addlogmsg( - request.user.username, - create_instance.compute.name, - create_instance.name, - msg, - ) - return redirect( - reverse("instances:instance", args=[create_instance.id]) - ) + addlogmsg(request.user.username, create_instance.compute.name, create_instance.name, msg) + return redirect(reverse("instances:instance", args=[create_instance.id])) except libvirtError as lib_err: if data["hdd_size"] or len(volume_list) > 0: if is_disk_created: diff --git a/interfaces/forms.py b/interfaces/forms.py index 90c4ee0..c19ffda 100644 --- a/interfaces/forms.py +++ b/interfaces/forms.py @@ -7,33 +7,13 @@ from django.utils.translation import gettext_lazy as _ class AddInterface(forms.Form): name = forms.CharField(max_length=10, required=True) itype = forms.ChoiceField(required=True, choices=(('bridge', 'bridge'), ('ethernet', 'ethernet'))) - start_mode = forms.ChoiceField( - required=True, - choices=( - ('none', 'none'), - ('onboot', 'onboot'), - ('hotplug', 'hotplug') - ) - ) + start_mode = forms.ChoiceField(required=True, + choices=(('none', 'none'), ('onboot', 'onboot'), ('hotplug', 'hotplug'))) netdev = forms.CharField(max_length=15, required=True) - ipv4_type = forms.ChoiceField( - required=True, - choices=( - ('dhcp', 'dhcp'), - ('static', 'static'), - ('none', 'none') - ) - ) + ipv4_type = forms.ChoiceField(required=True, choices=(('dhcp', 'dhcp'), ('static', 'static'), ('none', 'none'))) ipv4_addr = forms.CharField(max_length=18, required=False) ipv4_gw = forms.CharField(max_length=15, required=False) - ipv6_type = forms.ChoiceField( - required=True, - choices=( - ('dhcp', 'dhcp'), - ('static', 'static'), - ('none', 'none') - ) - ) + ipv6_type = forms.ChoiceField(required=True, choices=(('dhcp', 'dhcp'), ('static', 'static'), ('none', 'none'))) ipv6_addr = forms.CharField(max_length=100, required=False) ipv6_gw = forms.CharField(max_length=100, required=False) stp = forms.ChoiceField(required=False, choices=(('on', 'on'), ('off', 'off'))) @@ -59,7 +39,7 @@ class AddInterface(forms.Form): def clean_ipv6_addr(self): ipv6_addr = self.cleaned_data['ipv6_addr'] - have_symbol = re.match('^[0-9a-f./:]+|^$', ipv6_addr) + have_symbol = re.match('^[0-9a-f./:]+$', ipv6_addr) if not have_symbol: raise forms.ValidationError(_('The IPv6 address must not contain any special characters')) elif len(ipv6_addr) > 100: @@ -68,7 +48,7 @@ class AddInterface(forms.Form): def clean_ipv6_gw(self): ipv6_gw = self.cleaned_data['ipv6_gw'] - have_symbol = re.match('^[0-9a-f./:]+|^$', ipv6_gw) + have_symbol = re.match('^[0-9.]+$', ipv6_gw) if not have_symbol: raise forms.ValidationError(_('The IPv6 gateway must not contain any special characters')) elif len(ipv6_gw) > 100: diff --git a/interfaces/models.py b/interfaces/models.py index ff7d7eb..c2834e8 100644 --- a/interfaces/models.py +++ b/interfaces/models.py @@ -4,14 +4,10 @@ from django.utils.translation import gettext_lazy as _ # Create your models here. class Interfaces(models.Model): - name = models.CharField( - _("name"), - max_length=20, - error_messages={"required": _("No interface name has been entered")}, - ) - type = models.CharField(_("status"), max_length=12) - state = models.CharField(_("device"), max_length=100) - mac = models.CharField(_("forward"), max_length=24) + name = models.CharField(_('name'), max_length=20, error_messages={'required': _('No interface name has been entered')}) + type = models.CharField(_('status'), max_length=12) + state = models.CharField(_('device'), max_length=100) + mac = models.CharField(_('forward'), max_length=24) class Meta: managed = False diff --git a/interfaces/templates/create_iface_block.html b/interfaces/templates/create_iface_block.html index 8583297..f5bb627 100644 --- a/interfaces/templates/create_iface_block.html +++ b/interfaces/templates/create_iface_block.html @@ -95,13 +95,13 @@
- +
- +
@@ -121,13 +121,13 @@
- +
- +
diff --git a/interfaces/views.py b/interfaces/views.py index 36e9b3e..0ef2cb6 100644 --- a/interfaces/views.py +++ b/interfaces/views.py @@ -21,12 +21,7 @@ def interfaces(request, compute_id): compute = get_object_or_404(Compute, pk=compute_id) try: - conn = wvmInterfaces( - compute.hostname, - compute.login, - compute.password, - compute.type - ) + conn = wvmInterfaces(compute.hostname, compute.login, compute.password, compute.type) ifaces = conn.get_ifaces() try: netdevs = conn.get_net_devices() @@ -34,13 +29,7 @@ def interfaces(request, compute_id): netdevs = ["eth0", "eth1"] for iface in ifaces: - interf = wvmInterface( - compute.hostname, - compute.login, - compute.password, - compute.type, - iface - ) + interf = wvmInterface(compute.hostname, compute.login, compute.password, compute.type, iface) ifaces_all.append(interf.get_details()) if request.method == "POST": @@ -86,13 +75,7 @@ def interface(request, compute_id, iface): compute = get_object_or_404(Compute, pk=compute_id) try: - conn = wvmInterface( - compute.hostname, - compute.login, - compute.password, - compute.type, - iface - ) + conn = wvmInterface(compute.hostname, compute.login, compute.password, compute.type, iface) start_mode = conn.get_start_mode() state = conn.is_active() mac = conn.get_mac() diff --git a/networks/api/serializers.py b/networks/api/serializers.py index 61f5a8d..347d1db 100644 --- a/networks/api/serializers.py +++ b/networks/api/serializers.py @@ -1,8 +1,12 @@ + from rest_framework import serializers from networks.models import Networks class NetworksSerializer(serializers.ModelSerializer): + class Meta: model = Networks - fields = ["name", "status", "device", "forward"] + fields = ['name', 'status', 'device', 'forward'] + + diff --git a/networks/forms.py b/networks/forms.py index 5c014cf..36ceed9 100644 --- a/networks/forms.py +++ b/networks/forms.py @@ -5,10 +5,7 @@ from django.utils.translation import gettext_lazy as _ class AddNetPool(forms.Form): - name = forms.CharField( - error_messages={"required": _("No pool name has been entered")}, - max_length=20 - ) + name = forms.CharField(error_messages={"required": _("No pool name has been entered")}, max_length=20) subnet = forms.CharField( error_messages={"required": _("No IPv4 subnet has been entered")}, max_length=20, @@ -30,39 +27,27 @@ class AddNetPool(forms.Form): name = self.cleaned_data["name"] have_symbol = re.match(r"^[a-zA-Z0-9\.\_\-]+$", name) if not have_symbol: - raise forms.ValidationError( - _("The pool name must not contain any special characters") - ) + raise forms.ValidationError(_("The pool name must not contain any special characters")) elif len(name) > 20: - raise forms.ValidationError( - _("The pool name must not exceed 20 characters") - ) + raise forms.ValidationError(_("The pool name must not exceed 20 characters")) return name def clean_subnet(self): subnet = self.cleaned_data["subnet"] have_symbol = re.match("^[0-9./]+$", subnet if subnet else ".") if not have_symbol: - raise forms.ValidationError( - _("The IPv4 subnet must not contain any special characters") - ) + raise forms.ValidationError(_("The IPv4 subnet must not contain any special characters")) elif len(subnet) > 20: - raise forms.ValidationError( - _("The IPv4 subnet must not exceed 20 characters") - ) + raise forms.ValidationError(_("The IPv4 subnet must not exceed 20 characters")) return subnet def clean_subnet6(self): subnet = self.cleaned_data["subnet6"] have_symbol = re.match("^[0-9a-fA-F:/]+$", subnet if subnet else ":") if not have_symbol: - raise forms.ValidationError( - _("The IPv6 subnet must not contain any special characters") - ) + raise forms.ValidationError(_("The IPv6 subnet must not contain any special characters")) elif len(subnet) > 42: - raise forms.ValidationError( - _("The IPv6 subnet must not exceed 42 characters") - ) + raise forms.ValidationError(_("The IPv6 subnet must not exceed 42 characters")) return subnet def clean_bridge_name(self): @@ -70,11 +55,7 @@ class AddNetPool(forms.Form): if self.cleaned_data["forward"] in ["bridge", "macvtap"]: have_symbol = re.match(r"^[a-zA-Z0-9\.\_\:\-]+$", bridge_name) if not have_symbol: - raise forms.ValidationError( - _("The pool bridge name must not contain any special characters") - ) + raise forms.ValidationError(_("The pool bridge name must not contain any special characters")) elif len(bridge_name) > 20: - raise forms.ValidationError( - _("The pool bridge name must not exceed 20 characters") - ) + raise forms.ValidationError(_("The pool bridge name must not exceed 20 characters")) return bridge_name diff --git a/networks/models.py b/networks/models.py index 0f272bf..c52ceff 100644 --- a/networks/models.py +++ b/networks/models.py @@ -4,14 +4,10 @@ from django.utils.translation import gettext_lazy as _ # Create your models here. class Networks(models.Model): - name = models.CharField( - _("name"), - max_length=20, - error_messages={"required": _("No network name has been entered")}, - ) - status = models.CharField(_("status"), max_length=12) - device = models.CharField(_("device"), max_length=100) - forward = models.CharField(_("forward"), max_length=24) + name = models.CharField(_('name'), max_length=20, error_messages={'required': _('No network name has been entered')}) + status = models.CharField(_('status'), max_length=12) + device = models.CharField(_('device'), max_length=100) + forward = models.CharField(_('forward'), max_length=24) class Meta: managed = False diff --git a/networks/views.py b/networks/views.py index bb95741..f40a395 100644 --- a/networks/views.py +++ b/networks/views.py @@ -43,26 +43,18 @@ def networks(request, compute_id): msg = _("Network pool name already in use") messages.error(request, msg) errors = True - if ( - data["forward"] in ["bridge", "macvtap"] - and data["bridge_name"] == "" - ): + if data["forward"] in ["bridge", "macvtap"] and data["bridge_name"] == "": messages.error(request, _("Please enter bridge/dev name")) errors = True if data["subnet"]: ipv4 = True - gateway4, netmask4, dhcp4 = network_size( - data["subnet"], data["dhcp4"] - ) + gateway4, netmask4, dhcp4 = network_size(data["subnet"], data["dhcp4"]) if data["subnet6"]: ipv6 = True - gateway6, prefix6, dhcp6 = network_size( - data["subnet6"], data["dhcp6"] - ) + gateway6, prefix6, dhcp6 = network_size(data["subnet6"], data["dhcp6"]) if prefix6 != "64": messages.error( - request, - _("For libvirt, the IPv6 network prefix must be /64"), + request, _("For libvirt, the IPv6 network prefix must be /64") ) errors = True if not errors: @@ -185,11 +177,7 @@ def network(request, compute_id, pool): try: ret_val = conn.modify_fixed_address(name, address, mac_duid, family) - messages.success( - request, - _("Fixed address operation completed for %(family)s") - % {"family": family.upper()}, - ) + messages.success(request, _("Fixed address operation completed for %(family)s") % {"family": family.upper()}) return HttpResponseRedirect(request.get_full_path()) except libvirtError as lib_err: messages.error(request, lib_err) @@ -199,10 +187,7 @@ def network(request, compute_id, pool): ip = request.POST.get("address", "") family = request.POST.get("family", "ipv4") conn.delete_fixed_address(ip, family) - messages.success( - request, - _("%(family)s Fixed Address is Deleted.") % {"family": family.upper()}, - ) + messages.success(request, _("%(family)s Fixed Address is Deleted.") % {"family": family.upper()}) return HttpResponseRedirect(request.get_full_path()) if "modify_dhcp_range" in request.POST: range_start = request.POST.get("range_start", "") @@ -210,10 +195,7 @@ def network(request, compute_id, pool): family = request.POST.get("family", "ipv4") try: conn.modify_dhcp_range(range_start, range_end, family) - messages.success( - request, - _("%(family)s DHCP Range is Changed.") % {"family": family.upper()}, - ) + messages.success(request, _("%(family)s DHCP Range is Changed.") % {"family": family.upper()}) return HttpResponseRedirect(request.get_full_path()) except libvirtError as lib_err: messages.error(request, lib_err) @@ -243,16 +225,10 @@ def network(request, compute_id, pool): if conn.is_active(): messages.success( request, - _( - "%(qos_dir)s QoS is updated. Network XML is changed. Stop and start network to activate new config" - ) - % {"qos_dir": qos_dir.capitalize()}, + _("%(qos_dir)s QoS is updated. Network XML is changed. Stop and start network to activate new config") % {"qos_dir": qos_dir.capitalize()} ) else: - messages.success( - request, - _("%(qos_dir)s QoS is set") % {"qos_dir": qos_dir.capitalize()}, - ) + messages.success(request, _("%(qos_dir)s QoS is set") % {"qos_dir": qos_dir.capitalize()}) except libvirtError as lib_err: messages.error(request, lib_err) return HttpResponseRedirect(request.get_full_path()) @@ -263,17 +239,11 @@ def network(request, compute_id, pool): if conn.is_active(): messages.success( request, - _( - "%(qos_dir)s QoS is deleted. Network XML is changed. \ - Stop and start network to activate new config" - ) - % {"qos_dir": qos_dir.capitalize()}, + _("%(qos_dir)s QoS is deleted. Network XML is changed. \ + Stop and start network to activate new config") % {"qos_dir": qos_dir.capitalize()} ) else: - messages.success( - request, - _("%(qos_dir)s QoS is deleted") % {"qos_dir": qos_dir.capitalize()}, - ) + messages.success(request, _("%(qos_dir)s QoS is deleted") % {"qos_dir": qos_dir.capitalize()}) return HttpResponseRedirect(request.get_full_path()) conn.close() diff --git a/nwfilters/views.py b/nwfilters/views.py index 6651450..527f391 100644 --- a/nwfilters/views.py +++ b/nwfilters/views.py @@ -23,12 +23,7 @@ def nwfilters(request, compute_id): compute = get_object_or_404(Compute, pk=compute_id) try: - conn = wvmNWFilters( - compute.hostname, - compute.login, - compute.password, - compute.type - ) + conn = wvmNWFilters(compute.hostname, compute.login, compute.password, compute.type) for nwf in conn.get_nwfilters(): nwfilters_all.append(conn.get_nwfilter_info(nwf)) @@ -46,27 +41,19 @@ def nwfilters(request, compute_id): for nwf in nwfilters_all: if name == nwf["name"]: - error_msg = _( - "A network filter with this name already exists" - ) + error_msg = _("A network filter with this name already exists") raise Exception(error_msg) if uuid == nwf["uuid"]: - error_msg = _( - "A network filter with this UUID already exists" - ) + error_msg = _("A network filter with this UUID already exists") raise Exception(error_msg) else: try: - msg = _("%(filter)s network filter is created") % { - "filter": name - } + msg = _("%(filter)s network filter is created") % {"filter": name} conn.create_nwfilter(xml) addlogmsg(request.user.username, compute.hostname, "", msg) except libvirtError as lib_err: messages.error(request, lib_err) - addlogmsg( - request.user.username, compute.hostname, "", lib_err - ) + addlogmsg(request.user.username, compute.hostname, "", lib_err) if "del_nwfilter" in request.POST: name = request.POST.get("nwfiltername", "") @@ -76,27 +63,18 @@ def nwfilters(request, compute_id): nwfilter_info = conn.get_nwfilter_info(name) is_conn = wvmInstances( - compute.hostname, - compute.login, - compute.password, - compute.type + compute.hostname, compute.login, compute.password, compute.type ) instances = is_conn.get_instances() for inst in instances: i_conn = wvmInstance( - compute.hostname, - compute.login, - compute.password, - compute.type, - inst, + compute.hostname, compute.login, compute.password, compute.type, inst ) dom_filterrefs = i_conn.get_filterrefs() if name in dom_filterrefs: in_use = True - msg = _( - "NWFilter is in use by %(instance)s. Cannot be deleted." - ) % {"instance": inst} + msg = _("NWFilter is in use by %(instance)s. Cannot be deleted.") % {"instance": inst} messages.error(request, msg) addlogmsg(request.user.username, compute.hostname, "", msg) i_conn.close() @@ -115,10 +93,7 @@ def nwfilters(request, compute_id): conn.clone_nwfilter(name, cln_name) nwfilters_all.append(conn.get_nwfilter_info(cln_name)) - msg = _("Cloning NWFilter %(name)s as %(clone)s") % { - "name": name, - "clone": cln_name, - } + msg = _("Cloning NWFilter %(name)s as %(clone)s") % {"name":name, "clone": cln_name} addlogmsg(request.user.username, compute.hostname, "", msg) conn.close() @@ -151,18 +126,9 @@ def nwfilter(request, compute_id, nwfltr): try: nwfilter = wvmNWFilter( - compute.hostname, - compute.login, - compute.password, - compute.type, - nwfltr - ) - conn = wvmNWFilters( - compute.hostname, - compute.login, - compute.password, - compute.type + compute.hostname, compute.login, compute.password, compute.type, nwfltr ) + conn = wvmNWFilters(compute.hostname, compute.login, compute.password, compute.type) for nwf in conn.get_nwfilters(): nwfilters_all.append(conn.get_nwfilter_info(nwf)) diff --git a/storages/forms.py b/storages/forms.py index bb1858c..64dcd3c 100644 --- a/storages/forms.py +++ b/storages/forms.py @@ -5,15 +5,9 @@ from django.utils.translation import gettext_lazy as _ class AddStgPool(forms.Form): - name = forms.CharField( - error_messages={"required": _("No pool name has been entered")}, max_length=20 - ) + name = forms.CharField(error_messages={'required': _('No pool name has been entered')}, max_length=20) stg_type = forms.CharField(max_length=10) - target = forms.CharField( - error_messages={"required": _("No path has been entered")}, - max_length=100, - required=False, - ) + target = forms.CharField(error_messages={'required': _('No path has been entered')}, max_length=100, required=False) source = forms.CharField(max_length=100, required=False) ceph_user = forms.CharField(required=False) ceph_host = forms.CharField(required=False) @@ -23,62 +17,49 @@ class AddStgPool(forms.Form): source_format = forms.CharField(required=False) def clean_name(self): - name = self.cleaned_data["name"] - have_symbol = re.match("^[a-zA-Z0-9._-]+$", name) + name = self.cleaned_data['name'] + have_symbol = re.match('^[a-zA-Z0-9._-]+$', name) if not have_symbol: - raise forms.ValidationError( - _("The pool name must not contain any special characters") - ) + raise forms.ValidationError(_('The pool name must not contain any special characters')) elif len(name) > 20: - raise forms.ValidationError( - _("The pool name must not exceed 20 characters") - ) + raise forms.ValidationError(_('The pool name must not exceed 20 characters')) return name def clean_target(self): - storage_type = self.cleaned_data["stg_type"] - target = self.cleaned_data["target"] - have_symbol = re.match("^[a-zA-Z0-9/]+$", target) - if storage_type == "dir" or storage_type == "netfs": + storage_type = self.cleaned_data['stg_type'] + target = self.cleaned_data['target'] + have_symbol = re.match('^[a-zA-Z0-9/]+$', target) + if storage_type == 'dir' or storage_type == 'netfs': if not have_symbol: - raise forms.ValidationError( - _("The target must not contain any special characters") - ) - if storage_type == "dir" or storage_type == "netfs": + raise forms.ValidationError(_('The target must not contain any special characters')) + if storage_type == 'dir' or storage_type == 'netfs': if not target: - raise forms.ValidationError(_("No path has been entered")) + raise forms.ValidationError(_('No path has been entered')) return target def clean_source(self): - storage_type = self.cleaned_data["stg_type"] - source = self.cleaned_data["source"] - have_symbol = re.match("^[a-zA-Z0-9\/]+$", source) - if storage_type == "logical" or storage_type == "netfs": + storage_type = self.cleaned_data['stg_type'] + source = self.cleaned_data['source'] + have_symbol = re.match('^[a-zA-Z0-9\/]+$', source) + if storage_type == 'logical' or storage_type == 'netfs': if not source: - raise forms.ValidationError(_("No device or path has been entered")) + raise forms.ValidationError(_('No device or path has been entered')) if not have_symbol: - raise forms.ValidationError( - _("The disk source must not contain any special characters") - ) + raise forms.ValidationError(_('The disk source must not contain any special characters')) return source class CreateVolumeForm(forms.Form): name = forms.CharField(max_length=120) - format = forms.ChoiceField( - required=True, - choices=(("qcow2", "qcow2 (recommended)"), ("qcow", "qcow"), ("raw", "raw")), - ) + format = forms.ChoiceField(required=True, choices=(('qcow2', 'qcow2 (recommended)'), ('qcow', 'qcow'), ('raw', 'raw'))) size = forms.IntegerField() meta_prealloc = forms.BooleanField(required=False) def clean_name(self): - name = self.cleaned_data["name"] - have_symbol = re.match("^[a-zA-Z0-9._-]+$", name) + name = self.cleaned_data['name'] + have_symbol = re.match('^[a-zA-Z0-9._-]+$', name) if not have_symbol: - raise forms.ValidationError( - _("The image name must not contain any special characters") - ) + raise forms.ValidationError(_('The image name must not contain any special characters')) return name @@ -86,21 +67,14 @@ class CloneImage(forms.Form): name = forms.CharField(max_length=120) image = forms.CharField(max_length=120) convert = forms.BooleanField(required=False) - format = forms.ChoiceField( - required=False, - choices=(("qcow2", "qcow2 (recommended)"), ("qcow", "qcow"), ("raw", "raw")), - ) + format = forms.ChoiceField(required=False, choices=(('qcow2', 'qcow2 (recommended)'), ('qcow', 'qcow'), ('raw', 'raw'))) meta_prealloc = forms.BooleanField(required=False) def clean_name(self): - name = self.cleaned_data["name"] - have_symbol = re.match("^[a-zA-Z0-9._-]+$", name) + name = self.cleaned_data['name'] + have_symbol = re.match('^[a-zA-Z0-9._-]+$', name) if not have_symbol: - raise forms.ValidationError( - _("The image name must not contain any special characters") - ) + raise forms.ValidationError(_('The image name must not contain any special characters')) elif len(name) > 120: - raise forms.ValidationError( - _("The image name must not exceed 120 characters") - ) + raise forms.ValidationError(_('The image name must not exceed 120 characters')) return name diff --git a/storages/models.py b/storages/models.py index bb65887..fdca3bf 100644 --- a/storages/models.py +++ b/storages/models.py @@ -3,55 +3,45 @@ from django.utils.translation import gettext_lazy as _ # Create your models here. class Storages(models.Model): - name = models.CharField( - _("name"), - max_length=20, - error_messages={"required": _("No pool name has been entered")}, - ) - status = models.IntegerField(_("status")) - type = models.CharField(_("type"), max_length=100) - size = models.IntegerField(_("size")) - volumes = models.IntegerField(_("volumes")) + name = models.CharField(_('name'), max_length=20, error_messages={'required': _('No pool name has been entered')}) + status = models.IntegerField(_('status')) + type = models.CharField(_('type'), max_length=100) + size = models.IntegerField(_('size')) + volumes = models.IntegerField(_('volumes')) class Meta: managed = False def __str__(self): - return f"{self.name}" + return f'{self.name}' class Volume(models.Model): - name = models.CharField(_("name"), max_length=128) - type = models.CharField( - _("format"), - max_length=12, - choices=(("qcow2", "qcow2 (recommended)"), ("qcow", "qcow"), ("raw", "raw")), - ) - allocation = models.IntegerField(_("allocation")) - size = models.IntegerField(_("size")) + name = models.CharField(_('name'), max_length=128) + type = models.CharField(_('format'), max_length=12, choices=(('qcow2', 'qcow2 (recommended)'), ('qcow', 'qcow'), ('raw', 'raw'))) + allocation = models.IntegerField(_('allocation')) + size = models.IntegerField(_('size')) class Meta: managed = False verbose_name_plural = "Volumes" def __str__(self): - return f"{self.name}" + return f'{self.name}' class Storage(models.Model): - state = models.IntegerField(_("state")) - size = models.IntegerField(_("size")) - free = models.IntegerField(_("free")) - status = models.CharField(_("status"), max_length=128) - path = models.CharField(_("path"), max_length=128) - type = models.CharField(_("type"), max_length=128) - autostart = models.BooleanField(_("autostart")) - volumes = models.ForeignKey( - Volume, related_name="storage_volumes", on_delete=models.DO_NOTHING - ) + state = models.IntegerField(_('state')) + size = models.IntegerField(_('size')) + free = models.IntegerField(_('free')) + status = models.CharField(_('status'), max_length=128) + path = models.CharField(_('path'), max_length=128) + type = models.CharField(_('type'), max_length=128) + autostart = models.BooleanField(_('autostart')) + volumes = models.ForeignKey(Volume, related_name="storage_volumes", on_delete=models.DO_NOTHING) class Meta: managed = False def __str__(self): - return f"{self.path}" + return f'{self.path}' diff --git a/storages/views.py b/storages/views.py index 58fb7df..3828c41 100644 --- a/storages/views.py +++ b/storages/views.py @@ -27,12 +27,7 @@ def storages(request, compute_id): errors = False try: - conn = wvmStorages( - compute.hostname, - compute.login, - compute.password, - compute.type - ) + conn = wvmStorages(compute.hostname, compute.login, compute.password, compute.type) storages = conn.get_storages_info() secrets = conn.get_secrets() @@ -50,11 +45,7 @@ def storages(request, compute_id): msg = _("You need create secret for pool") messages.error(request, msg) errors = True - if ( - not data["ceph_pool"] - and not data["ceph_host"] - and not data["ceph_user"] - ): + if not data["ceph_pool"] and not data["ceph_host"] and not data["ceph_user"]: msg = _("You need input all fields for creating ceph pool") messages.error(request, msg) errors = True @@ -78,15 +69,8 @@ def storages(request, compute_id): data["target"], ) else: - conn.create_storage( - data["stg_type"], - data["name"], - data["source"], - data["target"], - ) - return HttpResponseRedirect( - reverse("storage", args=[compute_id, data["name"]]) - ) + conn.create_storage(data["stg_type"], data["name"], data["source"], data["target"]) + return HttpResponseRedirect(reverse("storage", args=[compute_id, data["name"]])) else: for msg_err in form.errors.values(): messages.error(request, msg_err.as_text()) @@ -110,26 +94,19 @@ def storage(request, compute_id, pool): target = os.path.normpath(os.path.join(path, str(f_name))) if not target.startswith(path): raise Exception(_("Security Issues with file uploading")) - + try: with open(target, "wb+") as f: for chunk in f_name.chunks(): f.write(chunk) except FileNotFoundError: - messages.error( - request, _("File not found. Check the path variable and filename") - ) + messages.error(request, _("File not found. Check the path variable and filename")) compute = get_object_or_404(Compute, pk=compute_id) meta_prealloc = False form = CreateVolumeForm() - conn = wvmStorage( - compute.hostname, - compute.login, - compute.password, - compute.type, pool - ) + conn = wvmStorage(compute.hostname, compute.login, compute.password, compute.type, pool) storages = conn.get_storages() state = conn.is_active() @@ -170,9 +147,7 @@ def storage(request, compute_id, pool): volname = request.POST.get("volname", "") vol = conn.get_volume(volname) vol.delete(0) - messages.success( - request, _("Volume: %(vol)s is deleted.") % {"vol": volname} - ) + messages.success(request, _("Volume: %(vol)s is deleted.") % {"vol": volname}) return redirect(reverse("storage", args=[compute.id, pool])) # return HttpResponseRedirect(request.get_full_path()) if "iso_upload" in request.POST: @@ -181,10 +156,7 @@ def storage(request, compute_id, pool): messages.error(request, error_msg) else: handle_uploaded_file(path, request.FILES["file"]) - messages.success( - request, - _("ISO: %(file)s is uploaded.") % {"file": request.FILES["file"]}, - ) + messages.success(request, _("ISO: %(file)s is uploaded.") % {"file": request.FILES["file"]}) return HttpResponseRedirect(request.get_full_path()) if "cln_volume" in request.POST: form = CloneImage(request.POST) @@ -202,13 +174,10 @@ def storage(request, compute_id, pool): else: format = None try: - name = conn.clone_volume( - data["image"], data["name"], format, meta_prealloc - ) + name = conn.clone_volume(data["image"], data["name"], format, meta_prealloc) messages.success( request, - _("%(image)s image cloned as %(name)s successfully") - % {"image": data["image"], "name": name}, + _("%(image)s image cloned as %(name)s successfully") % {"image": data["image"], "name": name}, ) return HttpResponseRedirect(request.get_full_path()) except libvirtError as lib_err: @@ -233,13 +202,7 @@ def create_volume(request, compute_id, pool): compute = get_object_or_404(Compute, pk=compute_id) meta_prealloc = False - conn = wvmStorage( - compute.hostname, - compute.login, - compute.password, - compute.type, - pool - ) + conn = wvmStorage(compute.hostname, compute.login, compute.password, compute.type, pool) storages = conn.get_storages() @@ -260,9 +223,7 @@ def create_volume(request, compute_id, pool): disk_owner_uid, disk_owner_gid, ) - messages.success( - request, _("Image file %(name)s is created successfully") % {"name": name} - ) + messages.success(request, _("Image file %(name)s is created successfully") % {"name": name}) else: for msg_err in form.errors.values(): messages.error(request, msg_err.as_text()) @@ -280,13 +241,7 @@ def get_volumes(request, compute_id, pool): data = {} compute = get_object_or_404(Compute, pk=compute_id) try: - conn = wvmStorage( - compute.hostname, - compute.login, - compute.password, - compute.type, - pool - ) + conn = wvmStorage(compute.hostname, compute.login, compute.password, compute.type, pool) conn.refresh() data["vols"] = sorted(conn.get_volumes()) except libvirtError: diff --git a/virtsecrets/forms.py b/virtsecrets/forms.py index 232973a..7ae478e 100644 --- a/virtsecrets/forms.py +++ b/virtsecrets/forms.py @@ -2,10 +2,7 @@ from django import forms class AddSecret(forms.Form): - ephemeral = forms.ChoiceField(required=True, choices=(("no", "no"), ("yes", "yes"))) - private = forms.ChoiceField(required=True, choices=(("no", "no"), ("yes", "yes"))) - usage_type = forms.ChoiceField( - required=True, - choices=(("ceph", "ceph"), ("volume", "volume"), ("iscsi", "iscsi")), - ) + ephemeral = forms.ChoiceField(required=True, choices=(('no', 'no'), ('yes', 'yes'))) + private = forms.ChoiceField(required=True, choices=(('no', 'no'), ('yes', 'yes'))) + usage_type = forms.ChoiceField(required=True, choices=(('ceph', 'ceph'), ('volume', 'volume'), ('iscsi', 'iscsi'))) data = forms.CharField(max_length=100, required=True) diff --git a/virtsecrets/views.py b/virtsecrets/views.py index adf577f..d7804c6 100644 --- a/virtsecrets/views.py +++ b/virtsecrets/views.py @@ -35,12 +35,7 @@ def secrets(request, compute_id): } try: - conn = wvmSecrets( - compute.hostname, - compute.login, - compute.password, - compute.type - ) + conn = wvmSecrets(compute.hostname, compute.login, compute.password, compute.type) secrets = conn.get_secrets() for uuid in secrets: diff --git a/vrtManager/hostdetails.py b/vrtManager/hostdetails.py index 0b7c313..6ee97fb 100644 --- a/vrtManager/hostdetails.py +++ b/vrtManager/hostdetails.py @@ -42,7 +42,8 @@ class wvmHostDetails(wvmConnect): total = sum(self.wvm.getCPUStats(-1, 0).values()) diff_idle = idle - prev_idle diff_total = total - prev_total - diff_usage = (1000 * (diff_total - diff_idle) / diff_total + 5) / 10 + diff_usage = (1000 * (diff_total - diff_idle) / + diff_total + 5) / 10 prev_total = total prev_idle = idle if num == 0: @@ -60,8 +61,6 @@ class wvmHostDetails(wvmConnect): info.append(self.wvm.getInfo()[0]) # architecture info.append(self.wvm.getInfo()[1] * 1048576) # memory info.append(self.wvm.getInfo()[2]) # cpu core count - info.append( - get_xml_path(self.wvm.getSysinfo(0), func=cpu_version) - ) # cpu version + info.append(get_xml_path(self.wvm.getSysinfo(0), func=cpu_version)) # cpu version info.append(self.wvm.getURI()) # uri return info diff --git a/vrtManager/instance.py b/vrtManager/instance.py index 0ae7435..0931a98 100644 --- a/vrtManager/instance.py +++ b/vrtManager/instance.py @@ -21,7 +21,10 @@ try: VIR_MIGRATE_POSTCOPY, ) from libvirt import VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_AGENT - from libvirt_qemu import qemuAgentCommand, VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT + from libvirt_qemu import ( + qemuAgentCommand, + VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT + ) except: from libvirt import libvirtError, VIR_DOMAIN_XML_SECURE, VIR_MIGRATE_LIVE @@ -91,18 +94,7 @@ class wvmInstances(wvmConnect): dom = self.get_instance(name) dom.resume() - def moveto( - self, - conn, - name, - live, - unsafe, - undefine, - offline, - autoconverge=False, - compress=False, - postcopy=False, - ): + def moveto(self, conn, name, live, unsafe, undefine, offline, autoconverge=False, compress=False, postcopy=False): flags = VIR_MIGRATE_PERSIST_DEST if live and conn.get_status() != 5: flags |= VIR_MIGRATE_LIVE @@ -125,39 +117,29 @@ class wvmInstances(wvmConnect): dom_emulator = conn.get_dom_emulator() if dom_emulator != self.get_emulator(dom_arch): - raise libvirtError( - "Destination host emulator is different. Cannot be migrated" - ) + raise libvirtError("Destination host emulator is different. Cannot be migrated") dom.migrate(self.wvm, flags, None, None, 0) def graphics_type(self, name): inst = self.get_instance(name) - console_type = util.get_xml_path( - inst.XMLDesc(0), "/domain/devices/graphics/@type" - ) + console_type = util.get_xml_path(inst.XMLDesc(0), "/domain/devices/graphics/@type") if console_type is None: return "None" return console_type def graphics_listen(self, name): inst = self.get_instance(name) - listener_addr = util.get_xml_path( - inst.XMLDesc(0), "/domain/devices/graphics/@listen" - ) + listener_addr = util.get_xml_path(inst.XMLDesc(0), "/domain/devices/graphics/@listen") if listener_addr is None: - listener_addr = util.get_xml_path( - inst.XMLDesc(0), "/domain/devices/graphics/listen/@address" - ) + listener_addr = util.get_xml_path(inst.XMLDesc(0), "/domain/devices/graphics/listen/@address") if listener_addr is None: return "None" return listener_addr def graphics_port(self, name): inst = self.get_instance(name) - console_port = util.get_xml_path( - inst.XMLDesc(0), "/domain/devices/graphics/@port" - ) + console_port = util.get_xml_path(inst.XMLDesc(0), "/domain/devices/graphics/@port") if console_port is None: return "None" return console_port @@ -171,9 +153,7 @@ class wvmInstances(wvmConnect): def graphics_passwd(self, name): inst = self.get_instance(name) - password = util.get_xml_path( - inst.XMLDesc(VIR_DOMAIN_XML_SECURE), "/domain/devices/graphics/@passwd" - ) + password = util.get_xml_path(inst.XMLDesc(VIR_DOMAIN_XML_SECURE), "/domain/devices/graphics/@passwd") if password is None: return "None" return password @@ -187,30 +167,27 @@ class wvmInstance(wvmConnect): def osinfo(self): info_results = qemuAgentCommand( - self.instance, - '{"execute":"guest-get-osinfo"}', - VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT, - 0, - ) + self.instance, + '{"execute":"guest-get-osinfo"}', + VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT, 0 + ) timezone_results = qemuAgentCommand( - self.instance, - '{"execute":"guest-get-timezone"}', - VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT, - 0, - ) + self.instance, + '{"execute":"guest-get-timezone"}', + VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT, 0 + ) hostname_results = qemuAgentCommand( - self.instance, - '{"execute":"guest-get-host-name"}', - VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT, - 0, - ) + self.instance, + '{"execute":"guest-get-host-name"}', + VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT, 0 + ) - info_results = json.loads(info_results).get("return") + info_results = json.loads(info_results).get('return') - timezone_results = json.loads(timezone_results).get("return") - hostname_results = json.loads(hostname_results).get("return") + timezone_results = json.loads(timezone_results).get('return') + hostname_results = json.loads(hostname_results).get('return') info_results.update(timezone_results) info_results.update(hostname_results) @@ -306,11 +283,7 @@ class wvmInstance(wvmConnect): enabled = vcpu.get("enabled") hotplug = vcpu.get("hotpluggable") order = vcpu.get("order") - vcpus[vcpu_id] = { - "enabled": enabled, - "hotpluggable": hotplug, - "order": order, - } + vcpus[vcpu_id] = {"enabled": enabled, "hotpluggable": hotplug, "order": order} return vcpus @@ -409,9 +382,7 @@ class wvmInstance(wvmConnect): return if self.is_agent_ready(): - self._ip_cache["qemuga"] = self._get_interface_addresses( - VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_AGENT - ) + self._ip_cache["qemuga"] = self._get_interface_addresses(VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_AGENT) arp_flag = 3 # libvirt."VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_ARP" self._ip_cache["arp"] = self._get_interface_addresses(arp_flag) @@ -424,17 +395,9 @@ class wvmInstance(wvmConnect): interface_type = net.xpath("@type")[0] mac_inst = net.xpath("mac/@address")[0] nic_inst = net.xpath("source/@network|source/@bridge|source/@dev")[0] - target_inst = ( - "" if not net.xpath("target/@dev") else net.xpath("target/@dev")[0] - ) - link_state = ( - "up" if not net.xpath("link") else net.xpath("link/@state")[0] - ) - filterref_inst = ( - "" - if not net.xpath("filterref/@filter") - else net.xpath("filterref/@filter")[0] - ) + target_inst = "" if not net.xpath("target/@dev") else net.xpath("target/@dev")[0] + link_state = "up" if not net.xpath("link") else net.xpath("link/@state")[0] + filterref_inst = "" if not net.xpath("filterref/@filter") else net.xpath("filterref/@filter")[0] model_type = net.xpath("model/@type")[0] if net.xpath("bandwidth/inbound"): in_attr = net.xpath("bandwidth/inbound")[0] @@ -488,9 +451,7 @@ class wvmInstance(wvmConnect): dev = disk.xpath("target/@dev")[0] bus = disk.xpath("target/@bus")[0] try: - src_file = disk.xpath( - "source/@file|source/@dev|source/@name" - )[0] + src_file = disk.xpath("source/@file|source/@dev|source/@name")[0] except Exception: v = disk.xpath("source/@volume")[0] s_name = disk.xpath("source/@pool")[0] @@ -519,11 +480,7 @@ class wvmInstance(wvmConnect): readonly = True if disk.xpath("readonly") else False shareable = True if disk.xpath("shareable") else False - serial = ( - disk.xpath("serial")[0].text - if disk.xpath("serial") - else None - ) + serial = disk.xpath("serial")[0].text if disk.xpath("serial") else None try: vol = self.get_volume_by_path(src_file) @@ -584,15 +541,7 @@ class wvmInstance(wvmConnect): except: pass finally: - result.append( - { - "dev": dev, - "image": volume, - "storage": storage, - "path": src_file, - "bus": bus, - } - ) + result.append({"dev": dev, "image": volume, "storage": storage, "path": src_file, "bus": bus}) return result return util.get_xml_path(self._XMLDesc(0), func=disks) @@ -618,9 +567,7 @@ class wvmInstance(wvmConnect): elif flag == -1: # Remove os.remove(menu) else: - raise Exception( - "Unknown boot menu option, please choose one of 0:disable, 1:enable, -1:remove" - ) + raise Exception("Unknown boot menu option, please choose one of 0:disable, 1:enable, -1:remove") xmldom = ElementTree.tostring(tree).decode() self._defineXML(xmldom) @@ -667,11 +614,7 @@ class wvmInstance(wvmConnect): elif dev_type == "usb": pass - boot_order[int(idx) - 1] = { - "type": dev_type, - "dev": dev_device, - "target": dev_target, - } + boot_order[int(idx) - 1] = {"type": dev_type, "dev": dev_device, "target": dev_target} return boot_order @@ -773,7 +716,7 @@ class wvmInstance(wvmConnect): self, target_dev, source, - source_info=None, + source_info = None, pool_type="dir", target_bus="ide", disk_type="file", @@ -790,11 +733,7 @@ class wvmInstance(wvmConnect): ): additionals = "" - if ( - cache_mode is not None - and cache_mode != "default" - and disk_device != "cdrom" - ): + if cache_mode is not None and cache_mode != "default" and disk_device != "cdrom": additionals += f"cache='{cache_mode}' " if io_mode is not None and io_mode != "default": additionals += f"io='{io_mode}' " @@ -807,33 +746,31 @@ class wvmInstance(wvmConnect): if disk_device == "cdrom": xml_disk += f"" elif disk_device == "disk": - xml_disk += ( - f"" - ) + xml_disk += f"" - if disk_type == "file": + if disk_type == 'file': xml_disk += f"" - elif disk_type == "network": - if pool_type == "rbd": - auth_type = source_info.get("auth_type") - auth_user = source_info.get("auth_user") + elif disk_type == 'network': + if pool_type == 'rbd': + auth_type = source_info.get('auth_type') + auth_user = source_info.get('auth_user') auth_uuid = source_info.get("auth_uuid") xml_disk += f""" """ xml_disk += f"""""" for host in source_info.get("hosts"): - if host.get("hostport"): + if host.get('hostport'): xml_disk += f"""""" else: xml_disk += f"""""" - xml_disk += """""" + xml_disk +="""""" else: raise Exception("Not implemented disk type") else: raise Exception("Not implemented disk type") - xml_disk += f"" + xml_disk +=f"" if readonly or disk_device == "cdrom": xml_disk += """""" if shareable: @@ -850,9 +787,7 @@ class wvmInstance(wvmConnect): def detach_disk(self, target_dev): tree = etree.fromstring(self._XMLDesc(0)) - disk_el = tree.xpath("./devices/disk/target[@dev='{}']".format(target_dev))[ - 0 - ].getparent() + disk_el = tree.xpath("./devices/disk/target[@dev='{}']".format(target_dev))[0].getparent() xml_disk = etree.tostring(disk_el).decode() devices = tree.find("devices") devices.remove(disk_el) @@ -878,9 +813,7 @@ class wvmInstance(wvmConnect): detect_zeroes_mode, ): tree = etree.fromstring(self._XMLDesc(0)) - disk_el = tree.xpath("./devices/disk/target[@dev='{}']".format(target_dev))[ - 0 - ].getparent() + disk_el = tree.xpath("./devices/disk/target[@dev='{}']".format(target_dev))[0].getparent() old_disk_type = disk_el.get("type") old_disk_device = disk_el.get("device") old_driver_name = disk_el.xpath("driver/@name")[0] @@ -900,9 +833,7 @@ class wvmInstance(wvmConnect): if old_disk_device == "cdrom": xml_disk += f"" elif old_disk_device == "disk": - xml_disk += ( - f"" - ) + xml_disk += f"" xml_disk += f""" """ @@ -924,7 +855,7 @@ class wvmInstance(wvmConnect): time.sleep(1) cpu_use_now = self.instance.info()[4] diff_usage = cpu_use_now - cpu_use_ago - cpu_usage["cpu"] = 100 * diff_usage / (1 * nbcore * 10**9) + cpu_usage["cpu"] = 100 * diff_usage / (1 * nbcore * 10 ** 9) else: cpu_usage["cpu"] = 0 return cpu_usage @@ -933,7 +864,7 @@ class wvmInstance(wvmConnect): self.instance.setVcpu(str(cpu_id), enabled) def set_vcpu_hotplug(self, status, vcpus_hotplug=0): - """vcpus_hotplug = 0 make all vpus hotpluggable""" + """ vcpus_hotplug = 0 make all vpus hotpluggable """ vcpus_hotplug = int(self.get_vcpu()) if vcpus_hotplug == 0 else vcpus_hotplug if self.get_status() == 5: # shutoff if status: @@ -956,9 +887,7 @@ class wvmInstance(wvmConnect): parent.remove(vcpu) self._defineXML(etree.tostring(tree).decode()) else: - raise libvirtError( - "Please shutdown the instance then try to enable vCPU hotplug" - ) + raise libvirtError("Please shutdown the instance then try to enable vCPU hotplug") def mem_usage(self): mem_usage = {} @@ -1054,13 +983,9 @@ class wvmInstance(wvmConnect): return telnet_port def get_console_listener_addr(self): - listener_addr = util.get_xml_path( - self._XMLDesc(0), "/domain/devices/graphics/@listen" - ) + listener_addr = util.get_xml_path(self._XMLDesc(0), "/domain/devices/graphics/@listen") if listener_addr is None: - listener_addr = util.get_xml_path( - self._XMLDesc(0), "/domain/devices/graphics/listen/@address" - ) + listener_addr = util.get_xml_path(self._XMLDesc(0), "/domain/devices/graphics/listen/@address") if listener_addr is None: return "127.0.0.1" return listener_addr @@ -1096,13 +1021,9 @@ class wvmInstance(wvmConnect): return socket def get_console_type(self): - console_type = util.get_xml_path( - self._XMLDesc(0), "/domain/devices/graphics/@type" - ) + console_type = util.get_xml_path(self._XMLDesc(0), "/domain/devices/graphics/@type") if console_type is None: - console_type = util.get_xml_path( - self._XMLDesc(0), "/domain/devices/console/@type" - ) + console_type = util.get_xml_path(self._XMLDesc(0), "/domain/devices/console/@type") return console_type def set_console_type(self, console_type): @@ -1125,24 +1046,18 @@ class wvmInstance(wvmConnect): def get_console_port(self, console_type=None): if console_type is None: console_type = self.get_console_type() - port = util.get_xml_path( - self._XMLDesc(0), - "/domain/devices/graphics[@type='%s']/@port" % console_type, - ) + port = util.get_xml_path(self._XMLDesc(0), "/domain/devices/graphics[@type='%s']/@port" % console_type) return port def get_console_websocket_port(self): console_type = self.get_console_type() websocket_port = util.get_xml_path( - self._XMLDesc(0), - "/domain/devices/graphics[@type='%s']/@websocket" % console_type, + self._XMLDesc(0), "/domain/devices/graphics[@type='%s']/@websocket" % console_type ) return websocket_port def get_console_passwd(self): - return util.get_xml_path( - self._XMLDesc(VIR_DOMAIN_XML_SECURE), "/domain/devices/graphics/@passwd" - ) + return util.get_xml_path(self._XMLDesc(VIR_DOMAIN_XML_SECURE), "/domain/devices/graphics/@passwd") def set_console_passwd(self, passwd): xml = self._XMLDesc(VIR_DOMAIN_XML_SECURE) @@ -1185,15 +1100,10 @@ class wvmInstance(wvmConnect): self._defineXML(newxml) def get_console_keymap(self): - return ( - util.get_xml_path( - self._XMLDesc(VIR_DOMAIN_XML_SECURE), "/domain/devices/graphics/@keymap" - ) - or "" - ) + return util.get_xml_path(self._XMLDesc(VIR_DOMAIN_XML_SECURE), "/domain/devices/graphics/@keymap") or "" def get_video_model(self): - """:return only primary video card""" + """ :return only primary video card""" xml = self._XMLDesc(VIR_DOMAIN_XML_SECURE) tree = etree.fromstring(xml) video_models = tree.xpath("/domain/devices/video/model") @@ -1202,7 +1112,7 @@ class wvmInstance(wvmConnect): return model.get("type") def set_video_model(self, model): - """Changes only primary video card""" + """ Changes only primary video card""" xml = self._XMLDesc(VIR_DOMAIN_XML_SECURE) tree = etree.fromstring(xml) video_models = tree.xpath("/domain/devices/video/model") @@ -1298,7 +1208,7 @@ class wvmInstance(wvmConnect): self.instance.snapshotCreateXML(xml, flag) def create_snapshot(self, name, desc=None): - state = "shutoff" if self.get_status() == 5 else "running" + state = 'shutoff' if self.get_status()==5 else 'running' xml = """ %s %s @@ -1317,17 +1227,11 @@ class wvmInstance(wvmConnect): self.recover_snapshot_xml() def change_snapshot_xml(self): - xml_temp = self._XMLDesc(VIR_DOMAIN_XML_SECURE).replace( - "", - "", - ) + xml_temp = self._XMLDesc(VIR_DOMAIN_XML_SECURE).replace("","") self._defineXML(xml_temp) def recover_snapshot_xml(self): - xml_temp = self._XMLDesc(VIR_DOMAIN_XML_SECURE).replace( - "", - "", - ) + xml_temp = self._XMLDesc(VIR_DOMAIN_XML_SECURE).replace("","") self._defineXML(xml_temp) def get_snapshot(self): @@ -1335,12 +1239,8 @@ class wvmInstance(wvmConnect): snapshot_list = self.instance.snapshotListNames(0) for snapshot in snapshot_list: snap = self.instance.snapshotLookupByName(snapshot, 0) - snap_description = util.get_xml_path( - snap.getXMLDesc(0), "/domainsnapshot/description" - ) - snap_time_create = util.get_xml_path( - snap.getXMLDesc(0), "/domainsnapshot/creationTime" - ) + snap_description = util.get_xml_path(snap.getXMLDesc(0), "/domainsnapshot/description") + snap_time_create = util.get_xml_path(snap.getXMLDesc(0), "/domainsnapshot/creationTime") snapshots.append( { "date": datetime.fromtimestamp(int(snap_time_create)), @@ -1438,9 +1338,7 @@ class wvmInstance(wvmConnect): elm.set("file", clone_path) vol = self.get_volume_by_path(source_file) - vol_format = util.get_xml_path( - vol.XMLDesc(0), "/volume/target/format/@type" - ) + vol_format = util.get_xml_path(vol.XMLDesc(0), "/volume/target/format/@type") if vol_format == "qcow2" and meta_prealloc: meta_prealloc = True @@ -1475,9 +1373,7 @@ class wvmInstance(wvmConnect): elm.set("name", clone_name) vol = self.get_volume_by_path(source_name) - vol_format = util.get_xml_path( - vol.XMLDesc(0), "/volume/target/format/@type" - ) + vol_format = util.get_xml_path(vol.XMLDesc(0), "/volume/target/format/@type") vol_clone_xml = f""" @@ -1521,22 +1417,15 @@ class wvmInstance(wvmConnect): bridge_name = None return bridge_name - def add_network( - self, - mac_address, - source, - source_type="net", - model="virtio", - nwfilter=None - ): - + def add_network(self, mac_address, source, source_type="net", model="virtio", nwfilter=None): + if source_type == "net": interface_type = "network" elif source_type == "bridge": interface_type = "bridge" else: interface_type = "direct" - + # network modes not handled: default is bridge xml_iface = f""" @@ -1582,18 +1471,12 @@ class wvmInstance(wvmConnect): net_source_type = network_data.get("net-source-0-type") net_filter = network_data.get("net-nwfilter-0") net_model = network_data.get("net-model-0") - + # Remove interface first, but keep network interface XML definition # If there is an error happened while adding changed one, then add removed one to back. status = self.delete_network(net_mac) try: - self.add_network( - net_mac, - net_source, - net_source_type, - net_model, - net_filter - ) + self.add_network(net_mac, net_source, net_source_type, net_model, net_filter) except libvirtError: if status is not None: if self.get_status() == 1: @@ -1602,11 +1485,12 @@ class wvmInstance(wvmConnect): if self.get_status() == 5: self.instance.attachDeviceFlags(status, VIR_DOMAIN_AFFECT_CONFIG) + def change_network_oldway(self, network_data): - """ - change network firsh version... - will be removed if new one works as expected for all scenarios - """ + ''' + change network firsh version... + will be removed if new one works as expected for all scenarios + ''' xml = self._XMLDesc(VIR_DOMAIN_XML_SECURE) tree = ElementTree.fromstring(xml) for num, interface in enumerate(tree.findall("devices/interface")): @@ -1628,13 +1512,9 @@ class wvmInstance(wvmConnect): elif net_source_type == "iface": source.set("dev", net_source) else: - raise libvirtError( - "Unknown network type: {}".format(net_source_type) - ) + raise libvirtError("Unknown network type: {}".format(net_source_type)) else: - raise libvirtError( - "Unknown network type: {}".format(interface.get("type")) - ) + raise libvirtError("Unknown network type: {}".format(interface.get("type"))) source = interface.find("model") if net_model != "default": @@ -1735,12 +1615,7 @@ class wvmInstance(wvmConnect): out_peak = out_qos.get("peak") out_burst = out_qos.get("burst") bound_list.append( - { - "direction": "outbound", - "average": out_av, - "peak": out_peak, - "burst": out_burst, - } + {"direction": "outbound", "average": out_av, "peak": out_peak, "burst": out_burst} ) qos_values[mac[0]] = bound_list return qos_values @@ -1777,13 +1652,9 @@ class wvmInstance(wvmConnect): def unset_qos(self, mac, direction): tree = etree.fromstring(self._XMLDesc(0)) - for direct in tree.xpath( - "/domain/devices/interface/bandwidth/{}".format(direction) - ): + for direct in tree.xpath("/domain/devices/interface/bandwidth/{}".format(direction)): band_el = direct.getparent() - interface_el = ( - band_el.getparent() - ) # parent bandwidth,its parent is interface + interface_el = band_el.getparent() # parent bandwidth,its parent is interface parent_mac = interface_el.xpath("mac/@address") if parent_mac[0] == mac: band_el.remove(direct) @@ -1804,9 +1675,7 @@ class wvmInstance(wvmConnect): def remove_guest_agent(self): tree = etree.fromstring(self._XMLDesc(0)) - for target in tree.xpath( - "/domain/devices/channel[@type='unix']/target[@name='org.qemu.guest_agent.0']" - ): + for target in tree.xpath("/domain/devices/channel[@type='unix']/target[@name='org.qemu.guest_agent.0']"): parent = target.getparent() channel_xml = etree.tostring(parent).decode() if self.get_status() == 1: diff --git a/vrtManager/nwfilters.py b/vrtManager/nwfilters.py index 7e8d535..8b8d1b9 100644 --- a/vrtManager/nwfilters.py +++ b/vrtManager/nwfilters.py @@ -88,8 +88,7 @@ class wvmNWFilter(wvmConnect): tree = ElementTree.fromstring(self._XMLDesc(0)) rule_tree = tree.findall( - "./rule[@action='%s'][@direction='%s'][@priority='%s']" - % (action, direction, priority) + "./rule[@action='%s'][@direction='%s'][@priority='%s']" % (action, direction, priority) ) if rule_tree: tree.remove(rule_tree[0]) @@ -112,8 +111,7 @@ class wvmNWFilter(wvmConnect): rule_priority = rule.get("priority") rule_directives = rule.find("./") rule_tree = tree.findall( - "./rule[@action='%s'][@direction='%s'][@priority='%s']" - % (rule_action, rule_direction, rule_priority) + "./rule[@action='%s'][@direction='%s'][@priority='%s']" % (rule_action, rule_direction, rule_priority) ) if rule_tree: diff --git a/vrtManager/storage.py b/vrtManager/storage.py index b55aa5f..64f303d 100644 --- a/vrtManager/storage.py +++ b/vrtManager/storage.py @@ -15,13 +15,7 @@ class wvmStorages(wvmConnect): stg_vol = len(stg.listVolumes()) if stg_status else None stg_size = stg.info()[1] storages.append( - { - "name": pool, - "status": stg_status, - "type": stg_type, - "volumes": stg_vol, - "size": stg_size, - } + {"name": pool, "status": stg_status, "type": stg_type, "volumes": stg_vol, "size": stg_size} ) return storages @@ -53,9 +47,7 @@ class wvmStorages(wvmConnect): return stg - def create_storage_ceph( - self, stg_type, name, ceph_pool, ceph_host, ceph_user, secret - ): + def create_storage_ceph(self, stg_type, name, ceph_pool, ceph_host, ceph_user, secret): xml = f""" {name} @@ -73,9 +65,7 @@ class wvmStorages(wvmConnect): stg.create(0) stg.setAutostart(1) - def create_storage_netfs( - self, stg_type, name, netfs_host, source, source_format, target - ): + def create_storage_netfs(self, stg_type, name, netfs_host, source, source_format, target): xml = f""" {name} @@ -106,12 +96,7 @@ class wvmStorage(wvmConnect): return self.pool.name() def get_status(self): - status = [ - "Not running", - "Initializing pool, not available", - "Running normally", - "Running degraded", - ] + status = ["Not running", "Initializing pool, not available", "Running normally", "Running degraded"] try: return status[self.pool.info()[0]] except ValueError: @@ -176,28 +161,27 @@ class wvmStorage(wvmConnect): hosts_array = [] for host in doc.xpath("/pool/source/host"): - name = host.get("name") + name = host.get('name') if name: - port = host.get("port") + port = host.get('port') if port: hosts_array.append({"hostname": name, "hostport": port}) else: hosts_array.append({"hostname": name}) - name = doc.get("name") + name = doc.get('name') auth = doc.xpath("/pool/source/auth") auth_type = auth[0].get("type") auth_user = auth[0].get("username") auth_uuid = auth[0].xpath("secret/@uuid")[0] - return { + return({ "name": name, "auth_type": auth_type, "auth_user": auth_user, "auth_uuid": auth_uuid, - "hosts": hosts_array, - } - + "hosts": hosts_array + }) return util.get_xml_path(self._XMLDesc(0), func=hosts) def get_pretty_allocation(self): @@ -247,49 +231,30 @@ class wvmStorage(wvmConnect): self.refresh() vols = self.get_volumes() - return [ - { - "name": volname, - "size": self.get_volume_size(volname), - "allocation": self.get_volume_allocation(volname), - "type": self.get_volume_format_type(volname), - } - for volname in vols - ] - + return [{"name": volname, + "size": self.get_volume_size(volname), + "allocation": self.get_volume_allocation(volname), + "type": self.get_volume_format_type(volname)} for volname in vols] + def get_volume_details(self, volname): with contextlib.suppress(Exception): self.refresh() return { - "name": volname, - "size": self.get_volume_size(volname), - "allocation": self.get_volume_allocation(volname), - "type": self.get_volume_format_type(volname), + "name": volname, + "size": self.get_volume_size(volname), + "allocation": self.get_volume_allocation(volname), + "type": self.get_volume_format_type(volname), } def update_volumes(self): with contextlib.suppress(Exception): self.refresh() vols = self.get_volumes() - return [ - { - "name": volname, - "size": self.get_volume_size(volname), - "allocation": self.get_volume_allocation(volname), - "type": self.get_volume_format_type(volname), - } - for volname in vols - ] + return [{"name": volname, "size": self.get_volume_size(volname), + "allocation": self.get_volume_allocation(volname), + "type": self.get_volume_format_type(volname)} for volname in vols] - def create_volume( - self, - name, - size, - vol_fmt="qcow2", - metadata=False, - disk_owner_uid=0, - disk_owner_gid=0, - ): + def create_volume(self, name, size, vol_fmt="qcow2", metadata=False, disk_owner_uid=0, disk_owner_gid=0): size = int(size) * 1073741824 storage_type = self.get_type() alloc = size diff --git a/webvirtcloud/settings.py.template b/webvirtcloud/settings.py.template index 4d45be1..c35e24a 100644 --- a/webvirtcloud/settings.py.template +++ b/webvirtcloud/settings.py.template @@ -273,14 +273,6 @@ OTP_ENABLED = False LOGIN_REQUIRED_IGNORE_VIEW_NAMES = ["accounts:login", "accounts:email_otp"] -# EMAIL Config -EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' -EMAIL_HOST = 'smtp.gmail.com' -EMAIL_USE_TLS = True -EMAIL_PORT = 587 -EMAIL_HOST_USER = #sender's email-id -EMAIL_HOST_PASSWORD = #password associated with above email-id - # LDAP Config #