From 0049da6a63833ec3e3a35dec694fea9adc133338 Mon Sep 17 00:00:00 2001 From: Daan Hoogland Date: Thu, 8 Oct 2026 17:38:07 +0200 Subject: [PATCH] console: don't require a console proxy for direct-URL consoles --- .../ConsoleAccessManagerImpl.java | 9 ++-- .../ConsoleAccessManagerImplTest.java | 42 +++++++++++++++++++ 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/server/src/main/java/org/apache/cloudstack/consoleproxy/ConsoleAccessManagerImpl.java b/server/src/main/java/org/apache/cloudstack/consoleproxy/ConsoleAccessManagerImpl.java index 237135b5176b..9014a0b814da 100644 --- a/server/src/main/java/org/apache/cloudstack/consoleproxy/ConsoleAccessManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/consoleproxy/ConsoleAccessManagerImpl.java @@ -418,10 +418,6 @@ private ConsoleEndpoint generateAccessEndpoint(Long vmId, String sessionUuid, St } String rootUrl = managementServer.getConsoleAccessUrlRoot(vmId); - if (rootUrl == null) { - throw new CloudRuntimeException("Console access will be ready in a few minutes. Please try it again later."); - } - ConsoleEndpoint consoleEndpoint = composeConsoleAccessEndpoint(rootUrl, vm, host, clientAddress, sessionUuid, extraSecurityToken); logger.debug("The console URL is: " + consoleEndpoint.getUrl()); return consoleEndpoint; @@ -522,6 +518,11 @@ protected ConsoleEndpoint composeConsoleAccessEndpoint(String rootUrl, VirtualMa return new ConsoleEndpoint(true, result.getDirectUrl()); } + // Only consoles served through the console proxy need its URL; direct consoles do not + if (rootUrl == null) { + throw new CloudRuntimeException("Console access will be ready in a few minutes. Please try it again later."); + } + String ticket = genAccessTicket(result.getHost(), String.valueOf(result.getPort()), result.getSid(), result.getTag(), sessionUuid); ConsoleProxyPasswordBasedEncryptor encryptor = new ConsoleProxyPasswordBasedEncryptor(getEncryptorPassword()); diff --git a/server/src/test/java/org/apache/cloudstack/consoleproxy/ConsoleAccessManagerImplTest.java b/server/src/test/java/org/apache/cloudstack/consoleproxy/ConsoleAccessManagerImplTest.java index 97e6295da1a5..416c9f0c1830 100644 --- a/server/src/test/java/org/apache/cloudstack/consoleproxy/ConsoleAccessManagerImplTest.java +++ b/server/src/test/java/org/apache/cloudstack/consoleproxy/ConsoleAccessManagerImplTest.java @@ -60,6 +60,7 @@ import com.cloud.utils.Pair; import com.cloud.utils.Ternary; import com.cloud.utils.db.EntityManager; +import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.vm.ConsoleSessionVO; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineManager; @@ -787,4 +788,45 @@ public void composeConsoleAccessEndpointReturnsWithoutPersistWhenConsoleConnecti Assert.assertNull(endpoint.getWebsocketExtra()); Assert.assertNull(endpoint.getWebsocketHost()); } + + @Test + public void composeConsoleAccessEndpointReturnsDirectUrlWhenNoConsoleProxyIsAvailable() { + String url = "url"; + long vmId = 100L; + long hostId = 1L; + String sessionUuid = UUID.randomUUID().toString(); + String addr = "addr"; + ConsoleConnectionDetails details = new ConsoleConnectionDetails("password", "en", "tag", null); + details.setDirectUrl(url); + details.setModeFromExternalProtocol("direct"); + VirtualMachine vm = Mockito.mock(VirtualMachine.class); + Mockito.when(vm.getId()).thenReturn(vmId); + HostVO host = Mockito.mock(HostVO.class); + Mockito.when(host.getId()).thenReturn(hostId); + Mockito.doReturn(details).when(consoleAccessManager).getConsoleConnectionDetails(vm, host); + Mockito.doNothing().when(consoleAccessManager).persistConsoleSession(sessionUuid, vmId, hostId, addr); + + ConsoleEndpoint endpoint = consoleAccessManager.composeConsoleAccessEndpoint(null, vm, host, addr, sessionUuid, ""); + + Assert.assertTrue(endpoint.isResult()); + Assert.assertEquals(url, endpoint.getUrl()); + Mockito.verify(consoleAccessManager).persistConsoleSession(sessionUuid, vmId, hostId, addr); + } + + @Test + public void composeConsoleAccessEndpointThrowsWhenProxiedConsoleHasNoConsoleProxy() { + VirtualMachine vm = Mockito.mock(VirtualMachine.class); + HostVO host = Mockito.mock(HostVO.class); + ConsoleConnectionDetails details = new ConsoleConnectionDetails("password", "en", "tag", null); + details.setHost("192.168.1.100"); + details.setPort(5900); + Mockito.doReturn(details).when(consoleAccessManager).getConsoleConnectionDetails(vm, host); + + CloudRuntimeException exception = Assert.assertThrows(CloudRuntimeException.class, + () -> consoleAccessManager.composeConsoleAccessEndpoint(null, vm, host, "addr", "sessionUuid", "")); + + Assert.assertEquals("Console access will be ready in a few minutes. Please try it again later.", exception.getMessage()); + Mockito.verify(consoleAccessManager, Mockito.never()).persistConsoleSession(Mockito.anyString(), Mockito.anyLong(), + Mockito.anyLong(), Mockito.anyString()); + } }