Skip to content

Commit 5941ac4

Browse files
anshulgangwarrajesh-battala
authored andcommitted
CLOUDSTACK-5344 commit for console proxy rdp for hyperv
1 parent 206c35c commit 5941ac4

16 files changed

Lines changed: 765 additions & 36 deletions

File tree

plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2000,6 +2000,45 @@ public JContainer StartupCommand([FromBody]dynamic cmdArray)
20002000
}
20012001
}
20022002

2003+
// POST api/HypervResource/GetVncPortCommand
2004+
[HttpPost]
2005+
[ActionName(CloudStackTypes.GetVncPortCommand)]
2006+
public JContainer GetVncPortCommand([FromBody]dynamic cmd)
2007+
{
2008+
using (log4net.NDC.Push(Guid.NewGuid().ToString()))
2009+
{
2010+
logger.Info(CloudStackTypes.GetVncPortCommand + cmd.ToString());
2011+
2012+
string details = null;
2013+
bool result = false;
2014+
string address = null;
2015+
int port = -9;
2016+
2017+
try
2018+
{
2019+
string vmName = (string)cmd.name;
2020+
var sys = wmiCallsV2.GetComputerSystem(vmName);
2021+
address = "instanceId=" + sys.Name ;
2022+
result = true;
2023+
}
2024+
catch (Exception sysEx)
2025+
{
2026+
details = CloudStackTypes.GetVncPortAnswer + " failed due to " + sysEx.Message;
2027+
logger.Error(details, sysEx);
2028+
}
2029+
2030+
object ansContent = new
2031+
{
2032+
result = result,
2033+
details = details,
2034+
address = address,
2035+
port = port
2036+
};
2037+
2038+
return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.GetVncPortAnswer);
2039+
}
2040+
}
2041+
20032042
public static System.Net.NetworkInformation.NetworkInterface GetNicInfoFromIpAddress(string ipAddress, out string subnet)
20042043
{
20052044
System.Net.NetworkInformation.NetworkInterface[] nics = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces();

server/src/com/cloud/server/ManagementServer.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
// under the License.
1717
package com.cloud.server;
1818

19+
import com.cloud.host.DetailVO;
1920
import com.cloud.host.HostVO;
2021
import com.cloud.storage.GuestOSVO;
2122
import com.cloud.utils.Pair;
@@ -47,6 +48,8 @@ public interface ManagementServer extends ManagementService, PluggableService {
4748
*/
4849
HostVO getHostBy(long hostId);
4950

51+
DetailVO findDetail(long hostId, String name);
52+
5053
String getConsoleAccessUrlRoot(long vmId);
5154

5255
GuestOSVO getGuestOs(Long guestOsId);

server/src/com/cloud/server/ManagementServerImpl.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -854,6 +854,11 @@ public HostVO getHostBy(long hostId) {
854854
return _hostDao.findById(hostId);
855855
}
856856

857+
@Override
858+
public DetailVO findDetail(long hostId, String name) {
859+
return _detailsDao.findDetail(hostId, name);
860+
}
861+
857862
@Override
858863
public long getId() {
859864
return MacAddress.getMacAddress().toLong();

server/src/com/cloud/servlet/ConsoleProxyClientParam.java

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,11 @@ public class ConsoleProxyClientParam {
2727
private String clientTunnelUrl;
2828
private String clientTunnelSession;
2929

30+
private String hypervHost;
31+
3032
private String ajaxSessionId;
33+
private String username;
34+
private String password;
3135

3236
public ConsoleProxyClientParam() {
3337
clientHostPort = 0;
@@ -89,20 +93,20 @@ public void setClientTunnelSession(String clientTunnelSession) {
8993
this.clientTunnelSession = clientTunnelSession;
9094
}
9195

92-
public String getLocale() {
93-
return this.locale;
96+
public String getAjaxSessionId() {
97+
return ajaxSessionId;
9498
}
9599

96-
public void setLocale(String locale) {
97-
this.locale = locale;
100+
public void setAjaxSessionId(String ajaxSessionId) {
101+
this.ajaxSessionId = ajaxSessionId;
98102
}
99103

100-
public String getAjaxSessionId() {
101-
return this.ajaxSessionId;
104+
public String getLocale() {
105+
return locale;
102106
}
103107

104-
public void setAjaxSessionId(String ajaxSessionId) {
105-
this.ajaxSessionId = ajaxSessionId;
108+
public void setLocale(String locale) {
109+
this.locale = locale;
106110
}
107111

108112
public String getClientMapKey() {
@@ -111,4 +115,29 @@ public String getClientMapKey() {
111115

112116
return clientHostAddress + ":" + clientHostPort;
113117
}
118+
119+
public void setHypervHost(String host) {
120+
hypervHost = host;
121+
}
122+
123+
public String getHypervHost() {
124+
return hypervHost;
125+
}
126+
127+
public void setUsername(String username) {
128+
this.username = username;
129+
130+
}
131+
132+
public String getUsername() {
133+
return username;
134+
}
135+
136+
public void setPassword(String password) {
137+
this.password = password;
138+
}
139+
140+
public String getPassword() {
141+
return password;
142+
}
114143
}

server/src/com/cloud/servlet/ConsoleProxyServlet.java

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -328,15 +328,21 @@ static public Ternary<String, String, String> parseHostInfo(String hostInfo) {
328328

329329
s_logger.info("Parse host info returned from executing GetVNCPortCommand. host info: " + hostInfo);
330330

331-
if (hostInfo != null && hostInfo.startsWith("consoleurl")) {
332-
String tokens[] = hostInfo.split("&");
333-
334-
if (hostInfo.length() > 19 && hostInfo.indexOf('/', 19) > 19) {
335-
host = hostInfo.substring(19, hostInfo.indexOf('/', 19)).trim();
336-
tunnelUrl = tokens[0].substring("consoleurl=".length());
337-
tunnelSession = tokens[1].split("=")[1];
331+
if (hostInfo != null) {
332+
if (hostInfo.startsWith("consoleurl")) {
333+
String tokens[] = hostInfo.split("&");
334+
335+
if (hostInfo.length() > 19 && hostInfo.indexOf('/', 19) > 19) {
336+
host = hostInfo.substring(19, hostInfo.indexOf('/', 19)).trim();
337+
tunnelUrl = tokens[0].substring("consoleurl=".length());
338+
tunnelSession = tokens[1].split("=")[1];
339+
} else {
340+
host = "";
341+
}
342+
} else if (hostInfo.startsWith("instanceId")) {
343+
host = hostInfo.substring(hostInfo.indexOf('=') + 1);
338344
} else {
339-
host = "";
345+
host = hostInfo;
340346
}
341347
} else {
342348
host = hostInfo;
@@ -389,28 +395,49 @@ private String composeThumbnailUrl(String rootUrl, VirtualMachine vm, HostVO hos
389395
private String composeConsoleAccessUrl(String rootUrl, VirtualMachine vm, HostVO hostVo) {
390396
StringBuffer sb = new StringBuffer(rootUrl);
391397
String host = hostVo.getPrivateIpAddress();
398+
String username = _ms.findDetail(hostVo.getId(), "username").getValue();
399+
String password = _ms.findDetail(hostVo.getId(), "password").getValue();
392400

393401
Pair<String, Integer> portInfo = _ms.getVncPort(vm);
394402
if (s_logger.isDebugEnabled())
395403
s_logger.debug("Port info " + portInfo.first());
396404

397405
Ternary<String, String, String> parsedHostInfo = parseHostInfo(portInfo.first());
406+
int port = -1;
407+
String sid;
408+
409+
if (portInfo.second() == -9) {
410+
//for hyperv
411+
port = 2179;
412+
} else {
413+
port = portInfo.second();
414+
}
398415

416+
sid = vm.getVncPassword();
399417
UserVmDetailVO details = _userVmDetailsDao.findDetail(vm.getId(), "keyboard");
400-
String sid = vm.getVncPassword();
418+
401419
String tag = vm.getUuid();
402-
String ticket = genAccessTicket(host, String.valueOf(portInfo.second()), sid, tag);
420+
421+
String ticket = genAccessTicket(parsedHostInfo.first(), String.valueOf(port), sid, tag);
403422
ConsoleProxyPasswordBasedEncryptor encryptor = new ConsoleProxyPasswordBasedEncryptor(getEncryptorPassword());
404423
ConsoleProxyClientParam param = new ConsoleProxyClientParam();
405424
param.setClientHostAddress(parsedHostInfo.first());
406-
param.setClientHostPort(portInfo.second());
425+
param.setClientHostPort(port);
407426
param.setClientHostPassword(sid);
408427
param.setClientTag(tag);
409428
param.setTicket(ticket);
429+
410430
if (details != null) {
411431
param.setLocale(details.getValue());
412432
}
413-
if (parsedHostInfo.second() != null && parsedHostInfo.third() != null) {
433+
434+
if (portInfo.second() == -9) {
435+
//For Hyperv Clinet Host Address will send Instance id
436+
param.setHypervHost(host);
437+
param.setUsername(username);
438+
param.setPassword(password);
439+
}
440+
if (parsedHostInfo.second() != null && parsedHostInfo.third() != null) {
414441
param.setClientTunnelUrl(parsedHostInfo.second());
415442
param.setClientTunnelSession(parsedHostInfo.third());
416443
}

services/console-proxy-rdp/rdpconsole/src/main/java/common/BufferedImageCanvas.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public class BufferedImageCanvas extends Canvas {
3030
private static final long serialVersionUID = 1L;
3131

3232
// Offline screen buffer
33-
private BufferedImage offlineImage;
33+
protected BufferedImage offlineImage;
3434

3535
// Cached Graphics2D object for offline screen buffer
3636
private Graphics2D graphics;
@@ -76,4 +76,8 @@ public Graphics2D getOfflineGraphics() {
7676
return graphics;
7777
}
7878

79+
public void updateFrameBuffer(int x, int y, int w, int h) {
80+
//this method will be used to mark the dirty tiles
81+
}
82+
7983
}

services/console-proxy-rdp/rdpconsole/src/main/java/common/adapter/AwtCanvasAdapter.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,14 @@ public void handleData(ByteBuffer buf, Link link) {
7777
}
7878

7979
private void handleCopyRect(CopyRectOrder order, ByteBuffer buf) {
80-
// TODO Auto-generated method stub
8180
// Copy image
8281
canvas.getOfflineGraphics().copyArea(order.srcX, order.srcY, order.width, order.height, order.x - order.srcX, order.y - order.srcY);
8382

8483
// Request update of repainted area
84+
canvas.updateFrameBuffer(order.x, order.y, order.width, order.height);
8585
canvas.repaint(order.x, order.y, order.width, order.height);
8686

87+
8788
}
8889

8990
private void handleBitmap(BitmapOrder order, ByteBuffer buf) {
@@ -137,6 +138,7 @@ private void handleBitmap(BitmapOrder order, ByteBuffer buf) {
137138
g.drawImage(rectImage, x, y, null);
138139

139140
// Request update of repainted area
141+
canvas.updateFrameBuffer(x, y, width, height);
140142
canvas.repaint(x, y, width, height);
141143
}
142144

services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/RdpClient.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@
6363

6464
public class RdpClient extends PipelineImpl {
6565

66+
AwtMouseEventSource mouseEventSource = null;
67+
AwtKeyEventSource keyEventSource = null;
68+
6669
/**
6770
* Name of last OneTimePacket in handshake sequence.
6871
*/
@@ -333,8 +336,8 @@ protected void assembleRDPPipeline(String serverHostName, String domain, String
333336
// Main network
334337
//
335338

336-
AwtMouseEventSource mouseEventSource = new AwtMouseEventSource("mouse");
337-
AwtKeyEventSource keyEventSource = new AwtKeyEventSource("keyboard");
339+
mouseEventSource = new AwtMouseEventSource("mouse");
340+
keyEventSource = new AwtKeyEventSource("keyboard");
338341

339342
// Subscribe packet sender to various events
340343
canvas.addMouseListener(mouseEventSource);
@@ -390,4 +393,12 @@ mouseEventSource, new AwtRdpMouseAdapter("mouse_adapter"),
390393
link("client_x224_data_queue", "client_tpkt_queue", "client_tpkt_queue< queue");
391394

392395
}
396+
397+
public AwtMouseEventSource getMouseEventSource() {
398+
return mouseEventSource;
399+
}
400+
401+
public AwtKeyEventSource getKeyEventSource() {
402+
return keyEventSource;
403+
}
393404
}

services/console-proxy/server/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@
4444
<artifactId>cloud-utils</artifactId>
4545
<version>${project.version}</version>
4646
</dependency>
47+
<dependency>
48+
<groupId>rdpclient</groupId>
49+
<artifactId>cloudstack-service-console-proxy-rdpclient</artifactId>
50+
<version>${project.version}</version>
51+
</dependency>
4752
</dependencies>
4853
<build>
4954
<resources>

services/console-proxy/server/src/com/cloud/consoleproxy/ConsoleProxy.java

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -196,8 +196,8 @@ public static ConsoleProxyAuthenticationResult authenticateConsoleAccess(Console
196196
Object result;
197197
try {
198198
result =
199-
authMethod.invoke(ConsoleProxy.context, param.getClientHostAddress(), String.valueOf(param.getClientHostPort()), param.getClientTag(),
200-
param.getClientHostPassword(), param.getTicket(), new Boolean(reauthentication));
199+
authMethod.invoke(ConsoleProxy.context, param.getClientHostAddress(), String.valueOf(param.getClientHostPort()), param.getClientTag(),
200+
param.getClientHostPassword(), param.getTicket(), new Boolean(reauthentication));
201201
} catch (IllegalAccessException e) {
202202
s_logger.error("Unable to invoke authenticateConsoleAccess due to IllegalAccessException" + " for vm: " + param.getClientTag(), e);
203203
authResult.setSuccess(false);
@@ -407,7 +407,7 @@ public static ConsoleProxyClient getVncViewer(ConsoleProxyClientParam param) thr
407407
synchronized (connectionMap) {
408408
viewer = connectionMap.get(clientKey);
409409
if (viewer == null) {
410-
viewer = new ConsoleProxyVncClient();
410+
viewer = getClient(param);
411411
viewer.initClient(param);
412412
connectionMap.put(clientKey, viewer);
413413
s_logger.info("Added viewer object " + viewer);
@@ -418,7 +418,7 @@ public static ConsoleProxyClient getVncViewer(ConsoleProxyClientParam param) thr
418418
viewer.initClient(param);
419419
} else if (!param.getClientHostPassword().equals(viewer.getClientHostPassword())) {
420420
s_logger.warn("Bad sid detected(VNC port may be reused). sid in session: " + viewer.getClientHostPassword() + ", sid in request: " +
421-
param.getClientHostPassword());
421+
param.getClientHostPassword());
422422
viewer.initClient(param);
423423
}
424424
}
@@ -442,7 +442,7 @@ public static ConsoleProxyClient getAjaxVncViewer(ConsoleProxyClientParam param,
442442
ConsoleProxyClient viewer = connectionMap.get(clientKey);
443443
if (viewer == null) {
444444
authenticationExternally(param);
445-
viewer = new ConsoleProxyVncClient();
445+
viewer = getClient(param);
446446
viewer.initClient(param);
447447

448448
connectionMap.put(clientKey, viewer);
@@ -457,7 +457,7 @@ public static ConsoleProxyClient getAjaxVncViewer(ConsoleProxyClientParam param,
457457
}
458458

459459
if (param.getClientHostPassword() == null || param.getClientHostPassword().isEmpty() ||
460-
!param.getClientHostPassword().equals(viewer.getClientHostPassword()))
460+
!param.getClientHostPassword().equals(viewer.getClientHostPassword()))
461461
throw new AuthenticationException("Cannot use the existing viewer " + viewer + ": bad sid");
462462

463463
if (!viewer.isFrontEndAlive()) {
@@ -479,6 +479,14 @@ public static ConsoleProxyClient getAjaxVncViewer(ConsoleProxyClientParam param,
479479
}
480480
}
481481

482+
private static ConsoleProxyClient getClient(ConsoleProxyClientParam param) {
483+
if (param.getHypervHost() != null) {
484+
return new ConsoleProxyRdpClient();
485+
} else {
486+
return new ConsoleProxyVncClient();
487+
}
488+
}
489+
482490
public static void removeViewer(ConsoleProxyClient viewer) {
483491
synchronized (connectionMap) {
484492
for (Map.Entry<String, ConsoleProxyClient> entry : connectionMap.entrySet()) {

0 commit comments

Comments
 (0)