diff --git a/appsettings/migrations/0013_remove_qemu_console_default_type.py b/appsettings/migrations/0013_remove_qemu_console_default_type.py new file mode 100644 index 00000000..5ea0e4d0 --- /dev/null +++ b/appsettings/migrations/0013_remove_qemu_console_default_type.py @@ -0,0 +1,25 @@ +from django.db import migrations + + +def remove_console_type(apps, schema_editor): + """VNC is the only console type; the setting has nothing left to choose.""" + AppSettings = apps.get_model("appsettings", "AppSettings") + AppSettings.objects.using(schema_editor.connection.alias).filter(key="QEMU_CONSOLE_DEFAULT_TYPE").delete() + + +def restore_console_type(apps, schema_editor): + AppSettings = apps.get_model("appsettings", "AppSettings") + AppSettings.objects.using(schema_editor.connection.alias).get_or_create( + key="QEMU_CONSOLE_DEFAULT_TYPE", + defaults={"name": "VM Console Type", "value": "vnc", "choices": "vnc", "description": "Default console type"}, + ) + + +class Migration(migrations.Migration): + dependencies = [ + ("appsettings", "0012_remove_spice_qemu_console_type"), + ] + + operations = [ + migrations.RunPython(remove_console_type, restore_console_type), + ] diff --git a/console/sshtunnels.py b/console/sshtunnels.py index 7f0376e0..44f7a53d 100644 --- a/console/sshtunnels.py +++ b/console/sshtunnels.py @@ -14,7 +14,7 @@ import threading class _TunnelScheduler(object): """ - If the user is using Spice + SSH URI + no SSH keys, we need to + If the user is using an SSH URI without SSH keys, we need to serialize connection opening otherwise ssh-askpass gets all angry. This handles the locking and scheduling. It's only instantiated once for the whole app, because we serialize @@ -181,7 +181,7 @@ class SSHTunnels(object): self._tunnels.append(t) # socket FDs are closed when the object is garbage collected. This - # can close an FD behind spice/vnc's back which causes crashes. + # can close an FD behind the VNC client's back which causes crashes. # # Dup a bare FD for the viewer side of things, but keep the high # level socket object for the SSH side, since it simplifies things diff --git a/console/tests.py b/console/tests.py index fb783a01..5181e9d0 100644 --- a/console/tests.py +++ b/console/tests.py @@ -108,9 +108,10 @@ class ConsoleViewsTestCase(TestCase): self.assertEqual(response.context["ws_port"], 5900) @patch("console.views.wvmInstance") - def test_console_superuser_spice_deprecated(self, mock_wvm): + def test_console_unsupported_graphics_type(self, mock_wvm): + # Only VNC is supported; a VM defined elsewhere may use another type. mock_conn = MagicMock() - mock_conn.get_console_type.return_value = "spice" + mock_conn.get_console_type.return_value = "rdp" mock_conn.get_console_websocket_port.return_value = None mock_wvm.return_value = mock_conn @@ -120,7 +121,7 @@ class ConsoleViewsTestCase(TestCase): self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, "console-vnc-lite.html") - self.assertIn("SPICE", str(response.context["console_error"])) + self.assertIn("'rdp' is not supported", str(response.context["console_error"])) @override_settings(SERIAL_CONSOLE_ENABLED=True) @patch("console.views.wvmInstance") diff --git a/console/views.py b/console/views.py index 3a770556..83ba5e03 100644 --- a/console/views.py +++ b/console/views.py @@ -156,15 +156,10 @@ def console(request): console_error = _( "Fail to get console. Please check the console configuration of your VM." ) - elif console_type == "spice": - console_error = _( - "SPICE console protocol is deprecated and no longer supported. " - "Please switch VM graphics to VNC." - ) else: - console_error = _("Console type '%(type)s' has not support") % { - "type": console_type - } + console_error = _( + "Console type '%(type)s' is not supported. Please switch the VM graphics to VNC." + ) % {"type": console_type} response = render(request, "console-vnc-lite.html", locals()) # Only novncd reads this cookie; JavaScript gets the token from the page. diff --git a/instances/api/serializers.py b/instances/api/serializers.py index ee4c2272..999cfa03 100644 --- a/instances/api/serializers.py +++ b/instances/api/serializers.py @@ -52,7 +52,6 @@ class FlavorSerializer(serializers.ModelSerializer): class CreateInstanceSerializer(serializers.ModelSerializer): - graphics = serializers.CharField(initial="vnc") video = serializers.CharField(initial="vga") storage = serializers.CharField(initial="default") cache_mode = serializers.CharField(initial="none") @@ -76,7 +75,6 @@ class CreateInstanceSerializer(serializers.ModelSerializer): "virtio", "qemu_ga", "console_pass", - "graphics", "video", "listener_addr", ] diff --git a/instances/api/viewsets.py b/instances/api/viewsets.py index ce23e375..fd299c4c 100644 --- a/instances/api/viewsets.py +++ b/instances/api/viewsets.py @@ -302,7 +302,6 @@ class CreateInstanceViewSet(viewsets.ViewSet): 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"], diff --git a/instances/forms.py b/instances/forms.py index 58ed0496..38867454 100644 --- a/instances/forms.py +++ b/instances/forms.py @@ -1,6 +1,5 @@ import re -from appsettings.models import AppSettings from django import forms from django.utils.translation import gettext_lazy as _ from webvirtcloud.settings import QEMU_CONSOLE_LISTENER_ADDRESSES, QEMU_KEYMAPS @@ -15,7 +14,6 @@ class FlavorForm(forms.ModelForm): class ConsoleForm(forms.Form): - type = forms.ChoiceField(label=_("Type")) listen_on = forms.ChoiceField(label=_("Listen on")) generate_password = forms.BooleanField(label=_("Generate password"), required=False) clear_password = forms.BooleanField(label=_("Clear password"), required=False) @@ -29,12 +27,7 @@ class ConsoleForm(forms.Form): 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(label=_("Type"), choices=type_choices) self.fields["listen_on"] = forms.ChoiceField( label=_("Listen on"), choices=QEMU_CONSOLE_LISTENER_ADDRESSES diff --git a/instances/models.py b/instances/models.py index 99485724..dbeade0e 100644 --- a/instances/models.py +++ b/instances/models.py @@ -273,9 +273,6 @@ 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")} ) diff --git a/instances/templates/create_instance_w2.html b/instances/templates/create_instance_w2.html index c9593c8e..e70260c3 100644 --- a/instances/templates/create_instance_w2.html +++ b/instances/templates/create_instance_w2.html @@ -216,20 +216,6 @@ - {% if dom_caps.graphics_support == 'yes' %} -