This is an automated email from the ASF dual-hosted git repository.

DaanHoogland pushed a commit to branch direct-console-without-cpvm
in repository https://gitbox.apache.org/repos/asf/cloudstack.git

commit 0049da6a63833ec3e3a35dec694fea9adc133338
Author: Daan Hoogland <[email protected]>
AuthorDate: Thu Oct 8 17:38:07 2026 +0200

    console: don't require a console proxy for direct-URL consoles
---
 .../consoleproxy/ConsoleAccessManagerImpl.java     |  9 ++---
 .../consoleproxy/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 237135b5176..9014a0b814d 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 @@ public class ConsoleAccessManagerImpl extends ManagerBase 
implements ConsoleAcce
         }
 
         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 @@ public class ConsoleAccessManagerImpl extends ManagerBase 
implements ConsoleAcce
             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 97e6295da1a..416c9f0c183 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.user.AccountManager;
 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 class ConsoleAccessManagerImplTest {
         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());
+    }
 }

Reply via email to