Frank Kobzik has uploaded a new change for review.
Change subject: engine: Integrate SPICE-HTML5 client
......................................................................
engine: Integrate SPICE-HTML5 client
This patch integrates SPICE-HTML5 client in the engine.
It makes use of the websocket proxy integrated in I44e9870b.
Invocation by this client can be enabled in the console popup. For this
to be enabled, the websocket proxy must be set in the engine.
This patch changes configuration of websocket proxy. Now it has
following form:
protocol:host:port
- protocol (http/https): specifies the protocol behind which the
console clients (both spice and vnc) run
- host (Engine/host fqdn or ip): host on which websocket proxy runs
(set to 'Engine' if the proxy runs on the same host as the engine)
- websocket proxy port
Change-Id: I490cb57f5d23a7a763807d3bee00ea0e4c032338
Signed-off-by: Frantisek Kobzik <[email protected]>
---
M backend/manager/modules/root/src/main/webapp/WEB-INF/web.xml
M backend/manager/modules/root/src/main/webapp/ovirt-engine-novnc-main.html
A backend/manager/modules/root/src/main/webapp/ovirt-engine-spicehtml5-main.html
M
frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/CommonApplicationConstants.java
M
frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/presenter/popup/ConsolePopupPresenterWidget.java
M
frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/uicommon/NoVncImpl.java
A
frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/uicommon/SpiceHtml5Impl.java
M
frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/uicommon/UiCommonDefaultTypeResolver.java
A
frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/uicommon/WebClientConsoleInvoker.java
A
frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/uicommon/WebsocketProxyConfig.java
M
frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/utils/ConsoleUtilsImpl.java
M
frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/ConsolePopupView.java
M
frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/ConsolePopupView.ui.xml
M
frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/Configurator.java
M
frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/ConsoleUtils.java
A
frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/ISpiceHtml5.java
M
frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/SpiceConsoleModel.java
M packaging/conf/engine.conf.defaults.in
M packaging/conf/ovirt-engine-proxy.conf.in
D packaging/conf/ovirt-websocket-proxy.conf.defaults
M packaging/etc/engine-config/engine-config.properties
21 files changed, 444 insertions(+), 166 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/57/15257/1
diff --git a/backend/manager/modules/root/src/main/webapp/WEB-INF/web.xml
b/backend/manager/modules/root/src/main/webapp/WEB-INF/web.xml
index 35a2140..e87e0f4 100644
--- a/backend/manager/modules/root/src/main/webapp/WEB-INF/web.xml
+++ b/backend/manager/modules/root/src/main/webapp/WEB-INF/web.xml
@@ -85,6 +85,20 @@
<url-pattern>/ovirt-engine-novnc/*</url-pattern>
</servlet-mapping>
+ <!-- SPICE-HTML5: -->
+ <servlet>
+ <servlet-name>spicehtml5</servlet-name>
+ <servlet-class>org.ovirt.engine.core.DocsServlet</servlet-class>
+ <init-param>
+ <param-name>file</param-name>
+ <param-value>%{ENGINE_SPICE_HTML5_DIR}</param-value>
+ </init-param>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>spicehtml5</servlet-name>
+ <url-pattern>/ovirt-engine-spicehtml5/*</url-pattern>
+ </servlet-mapping>
+
<!-- SpiceX.cab -->
<servlet>
<servlet-name>SpiceX.cab</servlet-name>
diff --git
a/backend/manager/modules/root/src/main/webapp/ovirt-engine-novnc-main.html
b/backend/manager/modules/root/src/main/webapp/ovirt-engine-novnc-main.html
index 1527a9f..ff6279b 100644
--- a/backend/manager/modules/root/src/main/webapp/ovirt-engine-novnc-main.html
+++ b/backend/manager/modules/root/src/main/webapp/ovirt-engine-novnc-main.html
@@ -90,20 +90,9 @@
s.innerHTML = msg;
}
}
- function extractConnectionData(obj) {
- var chunks = obj.split(',');
-
- var retval = {
- ticket: chunks[0],
- host: chunks[1],
- port: chunks[2]
- };
-
- return retval;
- }
function connectToConsole (evt) {
- if (evt.data === null || evt.data.vncTicket === null ||
evt.data.connectionTicket === null) {
+ if (evt.data === null || evt.data.password === null ||
evt.data.connectionTicket === null) {
alert("Incorrect connection data");
return;
}
@@ -111,7 +100,7 @@
try {
var host = WebUtil.getQueryVar('host',
window.location.hostname);
var port = WebUtil.getQueryVar('port', window.location.port);
- var ticket = evt.data.vncTicket; //password
+ var password = evt.data.password;
var path = evt.data.connectionTicket;
if ((!host) || (!port)) {
@@ -129,7 +118,7 @@
'view_only': WebUtil.getQueryVar('view_only',
false),
'updateState': updateState,
'onPasswordRequired': passwordRequired});
- rfb.connect(host, port, ticket, path);
+ rfb.connect(host, port, password, path);
}catch(e) {alert(e);}
}
diff --git
a/backend/manager/modules/root/src/main/webapp/ovirt-engine-spicehtml5-main.html
b/backend/manager/modules/root/src/main/webapp/ovirt-engine-spicehtml5-main.html
new file mode 100644
index 0000000..232e655
--- /dev/null
+++
b/backend/manager/modules/root/src/main/webapp/ovirt-engine-spicehtml5-main.html
@@ -0,0 +1,164 @@
+<!--
+ Copyright (C) 2012 by Jeremy P. White <[email protected]>
+
+ This file is part of spice-html5.
+
+ spice-html5 is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ spice-html5 is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with spice-html5. If not, see <http://www.gnu.org/licenses/>.
+
+ --------------------------------------------------
+ Spice Javascript client template.
+ Refer to main.js for more detailed information
+ --------------------------------------------------
+
+-->
+
+<!doctype html>
+<html>
+ <head>
+
+ <title>Spice Javascript client</title>
+ <script src="ovirt-engine-spicehtml5/enums.js"></script>
+ <script src="ovirt-engine-spicehtml5/atKeynames.js"></script>
+ <script src="ovirt-engine-spicehtml5/utils.js"></script>
+ <script src="ovirt-engine-spicehtml5/png.js"></script>
+ <script src="ovirt-engine-spicehtml5/lz.js"></script>
+ <script src="ovirt-engine-spicehtml5/quic.js"></script>
+ <script src="ovirt-engine-spicehtml5/bitmap.js"></script>
+ <script src="ovirt-engine-spicehtml5/spicedataview.js"></script>
+ <script src="ovirt-engine-spicehtml5/spicetype.js"></script>
+ <script src="ovirt-engine-spicehtml5/spicemsg.js"></script>
+ <script src="ovirt-engine-spicehtml5/wire.js"></script>
+ <script src="ovirt-engine-spicehtml5/spiceconn.js"></script>
+ <script src="ovirt-engine-spicehtml5/display.js"></script>
+ <script src="ovirt-engine-spicehtml5/main.js"></script>
+ <script src="ovirt-engine-spicehtml5/inputs.js"></script>
+ <script src="ovirt-engine-spicehtml5/cursor.js"></script>
+ <script src="ovirt-engine-spicehtml5/thirdparty/jsbn.js"></script>
+ <script src="ovirt-engine-spicehtml5/thirdparty/rsa.js"></script>
+ <script src="ovirt-engine-spicehtml5/thirdparty/prng4.js"></script>
+ <script src="ovirt-engine-spicehtml5/thirdparty/rng.js"></script>
+ <script src="ovirt-engine-spicehtml5/thirdparty/sha1.js"></script>
+ <script src="ovirt-engine-spicehtml5/ticket.js"></script>
+ <link rel="stylesheet" type="text/css"
href="ovirt-engine-spicehtml5/spice.css" />
+
+ <script>
+ var host = null, port = null;
+ var sc;
+
+ function spice_set_cookie(name, value, days) {
+ var date, expires;
+ date = new Date();
+ date.setTime(date.getTime() + (days*24*60*60*1000));
+ expires = "; expires=" + date.toGMTString();
+ document.cookie = name + "=" + value + expires + "; path=/";
+ };
+
+ function spice_query_var(name, defvalue) {
+ var match = RegExp('[?&]' + name + '=([^&]*)')
+ .exec(window.location.search);
+ return match ?
+ decodeURIComponent(match[1].replace(/\+/g, ' '))
+ : defvalue;
+ }
+
+ function spice_error(e)
+ {
+ disconnect();
+ }
+
+ function connect()
+ {
+ }
+
+ function disconnect()
+ {
+ console.log(">> disconnect");
+ if (sc) {
+ sc.stop();
+ }
+ console.log("<< disconnect");
+ }
+
+ function connectToConsole (evt) {
+ if (evt.data === null || evt.data.password === null ||
evt.data.connectionTicket === null) {
+ alert("Incorrect connection data");
+ return;
+ }
+
+ try {
+ var host = spice_query_var('host',
window.location.hostname);
+ var port = spice_query_var('port', window.location.port);
+ var password = evt.data.password;
+ var path = evt.data.connectionTicket;
+
+ if ((!host) || (!port)) {
+ updateState('failed',
+ "Must specify host and port in URL");
+ return;
+ }
+
+ var scheme = "ws://";
+ if (window.location.protocol === "https:") {
+ scheme = "wss://";
+ }
+
+ if (sc) {
+ sc.stop();
+ }
+
+ var uri = scheme + host + ":" + port + '/' + path;
+
+ try
+ {
+ sc = new SpiceMainConn({uri: uri, screen_id:
"spice-screen", dump_id: "debug-div",
+ message_id: "message-div", password:
password, onerror: spice_error });
+ }
+ catch (e)
+ {
+ alert(e.toString());
+ disconnect();
+ }
+
+
+ }catch(e) {alert(e);}
+ }
+
+ if (window.addEventListener) {
+ // For standards-compliant web browsers
+ window.addEventListener("message", connectToConsole, false);
+ } else {
+ window.attachEvent("onmessage", connectToConsole);
+ }
+ </script>
+
+ </head>
+
+ <body>
+
+ <div id="login" style="display: none">
+ <span class="logo">SPICE</span>
+ </div>
+
+ <div id="spice-area">
+ <div id="spice-screen" class="spice-screen"></div>
+ </div>
+
+ <div id="message-div" class="spice-message" style="display:
none"></div>
+
+ <div id="debug-div" style="display: none">
+ <!-- If DUMPXXX is turned on, dumped images will go here -->
+ </div>
+
+ </body>
+</html>
diff --git
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/CommonApplicationConstants.java
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/CommonApplicationConstants.java
index f3669d7..8e47e4c 100644
---
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/CommonApplicationConstants.java
+++
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/CommonApplicationConstants.java
@@ -1180,6 +1180,9 @@
@DefaultStringValue("Browser plugin")
String browserPlugin();
+ @DefaultStringValue("SPICE HTML5 browser client")
+ String spiceHtml5();
+
@DefaultStringValue("Pass Ctrl-Alt-Del to virtual machine")
String ctrlAltDel();
@@ -1203,6 +1206,9 @@
@DefaultStringValue("No SPICE proxy defined on system level")
String spiceProxyCanBeEnabledOnlyWhenDefined();
+
+ @DefaultStringValue("SPICE HTML5 client can be used only if websocket
proxy is configured in the engine.")
+ String spiceHtml5OnlyWhenWebsocketProxySet();
@DefaultStringValue("Enable WAN Options")
String enableWanOptions();
@@ -1233,6 +1239,9 @@
@DefaultStringValue("Uses SPICE browser plugin for invoking console
session. For this you must have SPICE console plugin installed in your
browser.")
String spiceInvokePlugin();
+
+ @DefaultStringValue("Uses SPICE HTML5 client that runs inside your
browser.")
+ String spiceInvokeHtml5();
@DefaultStringValue("Console Invocation")
String consoleInvocation();
@@ -1268,4 +1277,5 @@
@DefaultStringValue("Are you sure you want to remove the following items?")
String removeConfirmationPopupMessage();
+
}
diff --git
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/presenter/popup/ConsolePopupPresenterWidget.java
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/presenter/popup/ConsolePopupPresenterWidget.java
index d1ae40f..4a3b570 100644
---
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/presenter/popup/ConsolePopupPresenterWidget.java
+++
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/presenter/popup/ConsolePopupPresenterWidget.java
@@ -48,6 +48,7 @@
HasValueChangeHandlers<Boolean> getSpiceAutoImplRadioButton();
HasValueChangeHandlers<Boolean> getSpiceNativeImplRadioButton();
HasValueChangeHandlers<Boolean> getSpicePluginImplRadioButton();
+ HasValueChangeHandlers<Boolean> getSpiceHtml5ImplRadioButton();
HasValueChangeHandlers<Boolean> getRdpAutoImplRadioButton();
HasValueChangeHandlers<Boolean> getRdpNativeImplRadioButton();
@@ -70,6 +71,8 @@
void selectSpiceImplementation(SpiceConsoleModel.ClientConsoleMode
consoleMode);
void setSpicePluginImplEnabled(boolean enabled, String reason);
+
+ void setSpiceHtml5ImplEnabled(boolean enabled, String reason);
void setRdpPluginImplEnabled(boolean enabled, String reason);
@@ -207,6 +210,8 @@
getView().setSpicePluginImplEnabled(false,
constants.spicePluginNotSupportedByBrowser());
}
+ getView().setSpiceHtml5ImplEnabled(consoleUtils.isWebsocketProxySet(),
constants.spiceHtml5OnlyWhenWebsocketProxySet());
+
if (!consoleUtils.isBrowserPluginSupported(ConsoleProtocol.RDP)) {
getView().setRdpPluginImplEnabled(false,
constants.rdpPluginNotSupportedByBrowser());
}
diff --git
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/uicommon/NoVncImpl.java
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/uicommon/NoVncImpl.java
index 8f0423a..c9bee36 100644
---
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/uicommon/NoVncImpl.java
+++
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/uicommon/NoVncImpl.java
@@ -7,8 +7,6 @@
import org.ovirt.engine.ui.frontend.AsyncQuery;
import org.ovirt.engine.ui.frontend.Frontend;
import org.ovirt.engine.ui.frontend.INewAsyncCallback;
-import org.ovirt.engine.ui.uicommonweb.Configurator;
-import org.ovirt.engine.ui.uicommonweb.TypeResolver;
import org.ovirt.engine.ui.uicommonweb.dataprovider.AsyncDataProvider;
import org.ovirt.engine.ui.uicommonweb.models.vms.INoVnc;
@@ -16,33 +14,18 @@
public class NoVncImpl extends AbstractVnc implements INoVnc {
- private boolean listensOnPostMessage = false;
- private final NoVncProxyConfig config;
- private String connectionTicket;
+ private final WebsocketProxyConfig config;
- private String getTargetOrigin() {
- return "http://" + Location.getHost(); //$NON-NLS-1$
- }
-
- public String getProxyHost() {
- return config.getProxyHost();
- }
-
- public String getProxyPort() {
- return config.getProxyPort();
- }
-
- public void setListensOnPostMessage(boolean listensOnPostMessage) {
- this.listensOnPostMessage = listensOnPostMessage;
- }
private String getClientUrl() {
- return "http://" + Location.getHost() +
"/ovirt-engine-novnc-main.html?host=" + getProxyHost() + "&port=" +
getProxyPort();//$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
+ return config.getClientProtocol() + "://" + Location.getHost() +
//$NON-NLS-1$
+ "/ovirt-engine-novnc-main.html?host=" + config.getProxyHost()
+ //$NON-NLS-1$
+ "&port=" + config.getProxyPort(); //$NON-NLS-1$
}
public NoVncImpl() {
- super();
- this.config = new NoVncProxyConfig((String)
AsyncDataProvider.getConfigValuePreConverted(ConfigurationValues.WebSocketProxy));
+ this.config = new WebsocketProxyConfig(
+ (String)
AsyncDataProvider.getConfigValuePreConverted(ConfigurationValues.WebSocketProxy));
}
@Override
@@ -54,118 +37,17 @@
public void onSuccess(Object model, Object returnValue) {
VdcQueryReturnValue queryRetVal = (VdcQueryReturnValue)
returnValue;
String signature = (String) queryRetVal.getReturnValue();
- setConnectionTicket(signature);
- invokeClientNative();
+ WebClientConsoleInvoker invoker = new
WebClientConsoleInvoker(signature,
+ getTicket(),
+ getClientUrl());
+ invoker.invokeClientNative();
}
};
- Frontend.RunQuery(VdcQueryType.SignString, new
SignStringParameters(createConnectionString()), signCallback); //$NON-NLS-1$
- }
-
- private native void invokeClientNative()/*-{
- if
([email protected]::isClientUnsupportedExplorer()())
{
- alert("NoVnc console is not supported on Internet Explorer < 10");
- }
-
- var that = this;
-
- function postVncMessage(target) {
- var dataToSend = {
- connectionTicket:
[email protected]::getConnectionTicket()(),
- vncTicket:
[email protected]::getTicket()()
- };
-
- var targetOrigin =
[email protected]::getTargetOrigin()();
- target.postMessage(dataToSend, targetOrigin);
- }
-
- var clientUrl =
[email protected]::getClientUrl()();
-
- if
([email protected]::listensOnPostMessage) {
-
[email protected]::listensOnPostMessage =
true;
- $wnd.addEventListener("message", postVncMessage, false);
- }
-
- var win = $wnd.open(clientUrl, "_blank");
- win.focus();
-
- setTimeout(function() {
- postVncMessage(win);
- }, 1000);
-
- }-*/;
-
- /**
- * Creates a string in following form:
- * "vncHost:vncPort"
- */
- private String createConnectionString() {
- StringBuilder sb = new StringBuilder();
- sb.append(getVncHost()).append(":")//$NON-NLS-1$
- .append(getVncPort());
-
- return sb.toString();
- }
-
- private void setConnectionTicket(String ticket) {
- this.connectionTicket = ticket;
- }
-
- private String getConnectionTicket() {
- return connectionTicket;
- }
-
- private boolean isClientUnsupportedExplorer() {
-
return((Configurator)TypeResolver.getInstance().resolve(Configurator.class)).isClientWindowsExplorer();
- }
-
-
- /**
- * Holder for ws-proxy related configuration.
- */
- private class NoVncProxyConfig {
- private final String configValue;
-
- private static final String HOST = "Host";//$NON-NLS-1$
- private static final String ENGINE = "Engine";//$NON-NLS-1$
-
- public NoVncProxyConfig(String configValue) {
- if (configValue == null) {
- throw new IllegalArgumentException("Config value must not be
null");//$NON-NLS-1$
- }
-
- this.configValue = configValue;
- }
-
- public String getProxyHost() {
- if (configValue.startsWith(HOST)) {
- return getVncHost(); //the proxy runs on same host as the vm
- } else if (configValue.startsWith(ENGINE)) {
- return Location.getHostName(); //the proxy runs on the engine
- } else if (matchesHostColonPort(configValue)) { //the proxy runs
on specified host:port
- return configValue.split(":")[0];//$NON-NLS-1$
- } else {
- throw new IllegalArgumentException("Illegal NoVncImpl
configuration.");//$NON-NLS-1$
- }
- }
-
- public String getProxyPort() {
- if (matchesHostColonPort(configValue)) {
- return configValue.split(":")[1];//$NON-NLS-1$
- }
-
- throw new IllegalStateException("Missing port in noVNC proxy
config: " + configValue);//$NON-NLS-1$
- }
-
- private boolean matchesHostColonPort(String s) {
- if (s == null) {
- return false;
- }
-
- return s.matches("\\S+:\\d+");//$NON-NLS-1$
- }
+ Frontend.RunQuery(VdcQueryType.SignString,
+ new
SignStringParameters(WebClientConsoleInvoker.createConnectionString(getVncHost(),
getVncPort())),
+ signCallback);
}
}
-
diff --git
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/uicommon/SpiceHtml5Impl.java
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/uicommon/SpiceHtml5Impl.java
new file mode 100644
index 0000000..aea8be1
--- /dev/null
+++
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/uicommon/SpiceHtml5Impl.java
@@ -0,0 +1,62 @@
+package org.ovirt.engine.ui.common.uicommon;
+
+import org.ovirt.engine.core.common.queries.ConfigurationValues;
+import org.ovirt.engine.core.common.queries.SignStringParameters;
+import org.ovirt.engine.core.common.queries.VdcQueryReturnValue;
+import org.ovirt.engine.core.common.queries.VdcQueryType;
+import org.ovirt.engine.ui.frontend.AsyncQuery;
+import org.ovirt.engine.ui.frontend.Frontend;
+import org.ovirt.engine.ui.frontend.INewAsyncCallback;
+import org.ovirt.engine.ui.uicommonweb.dataprovider.AsyncDataProvider;
+import org.ovirt.engine.ui.uicommonweb.models.vms.ISpiceHtml5;
+
+import com.google.gwt.user.client.Window.Location;
+
+public class SpiceHtml5Impl extends AbstractSpice implements ISpiceHtml5 {
+ private final WebsocketProxyConfig config;
+
+ public SpiceHtml5Impl() {
+ super();
+
+ this.config = new WebsocketProxyConfig(
+ (String)
AsyncDataProvider.getConfigValuePreConverted(ConfigurationValues.WebSocketProxy));
+ }
+
+ private String getClientUrl() {
+ return config.getClientProtocol() + "://" + Location.getHost() +
//$NON-NLS-1$
+ "/ovirt-engine-spicehtml5-main.html?host=" +
config.getProxyHost() + //$NON-NLS-1$
+ "&port=" + config.getProxyPort(); //$NON-NLS-1$
+ }
+
+ @Override
+ public void connect() {
+ AsyncQuery signCallback = new AsyncQuery();
+ signCallback.setModel(this);
+ signCallback.asyncCallback = new INewAsyncCallback() {
+ @Override
+ public void onSuccess(Object model, Object returnValue) {
+ VdcQueryReturnValue queryRetVal = (VdcQueryReturnValue)
returnValue;
+ String signature = (String) queryRetVal.getReturnValue();
+
+ WebClientConsoleInvoker invoker = new
WebClientConsoleInvoker(signature,
+ getPassword(),
+ getClientUrl());
+
+ invoker.invokeClientNative();
+ }
+ };
+
+ Frontend.RunQuery(VdcQueryType.SignString,
+ new
SignStringParameters(WebClientConsoleInvoker.createConnectionString(getHost(),
+ String.valueOf(port))),
+ signCallback);
+ }
+
+ @Override
+ public void install() { }
+
+ @Override
+ public boolean getIsInstalled() {
+ return true;
+ }
+}
diff --git
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/uicommon/UiCommonDefaultTypeResolver.java
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/uicommon/UiCommonDefaultTypeResolver.java
index ceae70c..fcb23f9 100644
---
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/uicommon/UiCommonDefaultTypeResolver.java
+++
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/uicommon/UiCommonDefaultTypeResolver.java
@@ -11,6 +11,7 @@
import org.ovirt.engine.ui.uicommonweb.models.vms.INoVnc;
import org.ovirt.engine.ui.uicommonweb.models.vms.IRdpNative;
import org.ovirt.engine.ui.uicommonweb.models.vms.IRdpPlugin;
+import org.ovirt.engine.ui.uicommonweb.models.vms.ISpiceHtml5;
import org.ovirt.engine.ui.uicommonweb.models.vms.ISpiceNative;
import org.ovirt.engine.ui.uicommonweb.models.vms.ISpicePlugin;
import org.ovirt.engine.ui.uicommonweb.models.vms.IVncNative;
@@ -52,6 +53,8 @@
return new SpicePluginImpl();
} else if (type == ISpiceNative.class) {
return new SpiceNativeImpl();
+ } else if (type == ISpiceHtml5.class) {
+ return new SpiceHtml5Impl();
} else if (type == IRdpPlugin.class) {
return new RdpPluginImpl();
} else if (type == IRdpNative.class) {
diff --git
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/uicommon/WebClientConsoleInvoker.java
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/uicommon/WebClientConsoleInvoker.java
new file mode 100644
index 0000000..6cd6e33
--- /dev/null
+++
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/uicommon/WebClientConsoleInvoker.java
@@ -0,0 +1,71 @@
+package org.ovirt.engine.ui.common.uicommon;
+
+import org.ovirt.engine.ui.uicommonweb.Configurator;
+import org.ovirt.engine.ui.uicommonweb.TypeResolver;
+
+public class WebClientConsoleInvoker {
+
+ private final String connectionTicket;
+ private final String password;
+ private final String clientUrl;
+ private boolean listensOnPostMessage = false;
+
+ public WebClientConsoleInvoker(String connectionTicket, String password,
String clientUrl) {
+ this.connectionTicket = connectionTicket;
+ this.password = password;
+ this.clientUrl = clientUrl;
+ }
+
+ /**
+ * Creates a host:port string
+ * @params host, port
+ * @return "host:port"
+ */
+ public static String createConnectionString(String host, String port) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(host).append(":").append(port); //$NON-NLS-1$
+ return sb.toString();
+ }
+
+ public native void invokeClientNative()/*-{
+ if
(th...@org.ovirt.engine.ui.common.uicommon.WebClientConsoleInvoker::isClientBrowserUnsupported()())
{
+ alert("This feature is not supported in your browser.");
+ }
+
+ var that = this;
+
+ var clientUrl =
th...@org.ovirt.engine.ui.common.uicommon.WebClientConsoleInvoker::clientUrl;
+
+ function postMessage(target) {
+ var dataToSend = {
+ connectionTicket:
th...@org.ovirt.engine.ui.common.uicommon.WebClientConsoleInvoker::connectionTicket,
+ password:
th...@org.ovirt.engine.ui.common.uicommon.WebClientConsoleInvoker::password
+ };
+
+ target.postMessage(dataToSend, clientUrl);
+ }
+
+
+ if
(!th...@org.ovirt.engine.ui.common.uicommon.WebClientConsoleInvoker::listensOnPostMessage)
{
+
th...@org.ovirt.engine.ui.common.uicommon.WebClientConsoleInvoker::listensOnPostMessage
= true;
+ $wnd.addEventListener("message", postMessage, false);
+ }
+
+ var win = $wnd.open(clientUrl, "_blank");
+ win.focus();
+
+ setTimeout(function() {
+ postMessage(win);
+ }, 1000);
+
+ }-*/;
+
+ private boolean isClientBrowserUnsupported() {
+ return ((Configurator)
TypeResolver.getInstance().resolve(Configurator.class)).isClientWindowsExplorer();
+ }
+
+ public void setListensOnPostMessage(boolean val) {
+ this.listensOnPostMessage = val;
+ }
+
+}
diff --git
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/uicommon/WebsocketProxyConfig.java
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/uicommon/WebsocketProxyConfig.java
new file mode 100644
index 0000000..9d99c66
--- /dev/null
+++
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/uicommon/WebsocketProxyConfig.java
@@ -0,0 +1,43 @@
+package org.ovirt.engine.ui.common.uicommon;
+
+import com.google.gwt.user.client.Window.Location;
+
+/**
+ * Holder for ws-proxy related configuration.
+ */
+public class WebsocketProxyConfig {
+ private final String configValue;
+
+ private static final String ENGINE = "Engine";//$NON-NLS-1$
+
+ public WebsocketProxyConfig(String configValue) {
+ if (!matchesProtocolColonHostColonPort(configValue)) {
+ throw new IllegalArgumentException("Config value must be in
following form: protocol:host:port");//$NON-NLS-1$
+ }
+
+ this.configValue = configValue;
+ }
+
+ public String getClientProtocol() {
+ return configValue.split(":")[0];//$NON-NLS-1$
+ }
+
+ public String getProxyHost() {
+ String val = configValue.split(":")[1];//$NON-NLS-1$
+ if (val.equals(ENGINE)) {
+ return Location.getHostName(); //the proxy runs on the engine
+ }
+ return val;
+ }
+
+ public String getProxyPort() {
+ return configValue.split(":")[2];//$NON-NLS-1$
+ }
+
+ private boolean matchesProtocolColonHostColonPort(String s) {
+ if (s == null) {
+ return false;
+ }
+ return s.matches("\\S+:\\S+:\\d+");//$NON-NLS-1$
+ }
+}
diff --git
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/utils/ConsoleUtilsImpl.java
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/utils/ConsoleUtilsImpl.java
index 3d2807e..55c52a2 100644
---
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/utils/ConsoleUtilsImpl.java
+++
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/utils/ConsoleUtilsImpl.java
@@ -213,6 +213,12 @@
}
@Override
+ public boolean isWebsocketProxySet() {
+ return configurator.isWebsocketProxySet();
+ }
+
+
+ @Override
public boolean isBrowserPluginSupported(ConsoleProtocol protocol) {
switch (protocol) {
case SPICE:
diff --git
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/ConsolePopupView.java
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/ConsolePopupView.java
index 2ef12b3..d5091c9 100644
---
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/ConsolePopupView.java
+++
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/ConsolePopupView.java
@@ -76,6 +76,10 @@
@UiField(provided = true)
@WithElementId
+ EntityModelRadioButtonEditor spiceHtml5ImplRadioButton;
+
+ @UiField(provided = true)
+ @WithElementId
EntityModelValueCheckBoxEditor<ConsoleModel> ctrlAltDel;
@UiField(provided = true)
@@ -150,6 +154,8 @@
spiceNativeImplRadioButton.setLabel(constants.nativeClient());
spicePluginImplRadioButton = new EntityModelRadioButtonEditor("2");
//$NON-NLS-1$
spicePluginImplRadioButton.setLabel(constants.browserPlugin());
+ spiceHtml5ImplRadioButton = new EntityModelRadioButtonEditor("2");
//$NON-NLS-1$
+ spiceHtml5ImplRadioButton.setLabel(constants.spiceHtml5());
rdpAutoImplRadioButton = new EntityModelRadioButtonEditor("3");
//$NON-NLS-1$
rdpAutoImplRadioButton.setLabel(constants.auto());
@@ -353,6 +359,8 @@
spiceModel.setSpiceImplementation(SpiceConsoleModel.ClientConsoleMode.Native);
} else if (spicePluginImplRadioButton.asRadioButton().getValue()) {
spiceModel.setSpiceImplementation(SpiceConsoleModel.ClientConsoleMode.Plugin);
+ } else if (spiceHtml5ImplRadioButton.asRadioButton().getValue()) {
+
spiceModel.setSpiceImplementation(SpiceConsoleModel.ClientConsoleMode.Html5);
}
}
@@ -529,6 +537,14 @@
}
@Override
+ public void setSpiceHtml5ImplEnabled(boolean enabled, String reason) {
+ spiceHtml5ImplRadioButton.setEnabled(enabled);
+ if (!enabled) {
+ spiceHtml5ImplRadioButton.setTitle(reason);
+ }
+ }
+
+ @Override
public void setRdpPluginImplEnabled(boolean enabled, String reason) {
rdpPluginImplRadioButton.setEnabled(enabled);
if (!enabled) {
@@ -543,16 +559,25 @@
spiceAutoImplRadioButton.asRadioButton().setValue(false);
spicePluginImplRadioButton.asRadioButton().setValue(false);
spiceNativeImplRadioButton.asRadioButton().setValue(true);
+ spiceHtml5ImplRadioButton.asRadioButton().setValue(false);
break;
case Plugin:
spiceAutoImplRadioButton.asRadioButton().setValue(false);
spicePluginImplRadioButton.asRadioButton().setValue(true);
spiceNativeImplRadioButton.asRadioButton().setValue(false);
+ spiceHtml5ImplRadioButton.asRadioButton().setValue(false);
+ break;
+ case Html5:
+ spiceAutoImplRadioButton.asRadioButton().setValue(false);
+ spicePluginImplRadioButton.asRadioButton().setValue(false);
+ spiceNativeImplRadioButton.asRadioButton().setValue(false);
+ spiceHtml5ImplRadioButton.asRadioButton().setValue(true);
break;
default:
spiceAutoImplRadioButton.asRadioButton().setValue(true);
spicePluginImplRadioButton.asRadioButton().setValue(false);
spiceNativeImplRadioButton.asRadioButton().setValue(false);
+ spiceHtml5ImplRadioButton.asRadioButton().setValue(false);
break;
}
}
@@ -594,6 +619,11 @@
}
@Override
+ public HasValueChangeHandlers<Boolean> getSpiceHtml5ImplRadioButton() {
+ return spiceHtml5ImplRadioButton.asRadioButton();
+ }
+
+ @Override
public HasValueChangeHandlers<Boolean> getRdpAutoImplRadioButton() {
return rdpAutoImplRadioButton.asRadioButton();
}
diff --git
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/ConsolePopupView.ui.xml
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/ConsolePopupView.ui.xml
index d275f8d..ab513d7 100644
---
a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/ConsolePopupView.ui.xml
+++
b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/view/popup/ConsolePopupView.ui.xml
@@ -59,6 +59,7 @@
<e:EntityModelRadioButtonEditor
ui:field="spiceAutoImplRadioButton" title="{constants.spiceInvokeAuto}"/>
<e:EntityModelRadioButtonEditor
ui:field="spiceNativeImplRadioButton" title="{constants.spiceInvokeNative}"/>
<e:EntityModelRadioButtonEditor
ui:field="spicePluginImplRadioButton" title="{constants.spiceInvokePlugin}"/>
+ <e:EntityModelRadioButtonEditor
ui:field="spiceHtml5ImplRadioButton" title="{constants.spiceInvokeHtml5}"/>
<g:Label ui:field="spiceTitle"
text="{constants.spiceOptions}" addStyleNames="{style.labelStyle}" />
<w:EntityModelValueCheckBoxEditor
ui:field="ctrlAltDel" />
diff --git
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/Configurator.java
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/Configurator.java
index fb681c2..6d4662f 100644
---
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/Configurator.java
+++
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/Configurator.java
@@ -371,4 +371,9 @@
}
+ public boolean isWebsocketProxySet() {
+ String websocketProxy = (String)
AsyncDataProvider.getConfigValuePreConverted(ConfigurationValues.WebSocketProxy);
+ return websocketProxy != null && !"".equals(websocketProxy) &&
!"Off".equals(websocketProxy); //$NON-NLS-1$
+ }
+
}
diff --git
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/ConsoleUtils.java
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/ConsoleUtils.java
index 1ffe69e..a11884c 100644
---
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/ConsoleUtils.java
+++
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/ConsoleUtils.java
@@ -38,4 +38,6 @@
public boolean isBrowserPluginSupported(ConsoleProtocol protocol);
public boolean isSpiceProxyDefined();
+
+ public boolean isWebsocketProxySet();
}
diff --git
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/ISpiceHtml5.java
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/ISpiceHtml5.java
new file mode 100644
index 0000000..53ad0af
--- /dev/null
+++
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/ISpiceHtml5.java
@@ -0,0 +1,5 @@
+package org.ovirt.engine.ui.uicommonweb.models.vms;
+
+public interface ISpiceHtml5 extends ISpice {
+
+}
diff --git
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/SpiceConsoleModel.java
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/SpiceConsoleModel.java
index b43882f..04f66cf 100644
---
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/SpiceConsoleModel.java
+++
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/SpiceConsoleModel.java
@@ -51,7 +51,7 @@
public class SpiceConsoleModel extends ConsoleModel implements
IFrontendMultipleQueryAsyncCallback {
- public enum ClientConsoleMode { Native, Plugin, Auto }
+ public enum ClientConsoleMode { Native, Plugin, Auto, Html5 }
public static EventDefinition SpiceDisconnectedEventDefinition;
public static EventDefinition SpiceConnectedEventDefinition;
@@ -111,6 +111,9 @@
case Plugin:
setspice((ISpice)
TypeResolver.getInstance().resolve(ISpicePlugin.class));
break;
+ case Html5:
+ setspice((ISpice)
TypeResolver.getInstance().resolve(ISpiceHtml5.class));
+ break;
default:
ISpicePlugin pluginSpice = (ISpicePlugin)
TypeResolver.getInstance().resolve(ISpicePlugin.class);
setspice(pluginSpice.detectBrowserPlugin() ? pluginSpice
diff --git a/packaging/conf/engine.conf.defaults.in
b/packaging/conf/engine.conf.defaults.in
index e1c3386..52be32b 100644
--- a/packaging/conf/engine.conf.defaults.in
+++ b/packaging/conf/engine.conf.defaults.in
@@ -35,6 +35,7 @@
ENGINE_CACHE="@ENGINE_CACHE@"
SPICE_DIR="@SPICE_DIR@"
ENGINE_NOVNC_DIR="/usr/share/novnc"
+ENGINE_SPICE_HTML5_DIR="/usr/share/spice-html5"
#
# Intervals for stoping the engine:
diff --git a/packaging/conf/ovirt-engine-proxy.conf.in
b/packaging/conf/ovirt-engine-proxy.conf.in
index a9ce1ef..9a91ef8 100644
--- a/packaging/conf/ovirt-engine-proxy.conf.in
+++ b/packaging/conf/ovirt-engine-proxy.conf.in
@@ -25,7 +25,7 @@
ProxyPass ajp://localhost:@JBOSS_AJP_PORT@/
</Location>
- <LocationMatch
^/(UserPortal($|/)|OvirtEngineWeb($|/)|webadmin($|/)|docs($|/)|ovirt-engine-novnc($|/)|ovirt-engine-novnc-main.html$|spice/|ca.crt$|engine.ssh.key.txt$|rhevm.ssh.key.txt$|ovirt-engine-style.css$|console.vv$)>
+ <LocationMatch
^/(UserPortal($|/)|OvirtEngineWeb($|/)|webadmin($|/)|docs($|/)|ovirt-engine-novnc($|/)|ovirt-engine-novnc-main.html$|ovirt-engine-spicehtml5($|/)|ovirt-engine-spicehtml5-main.html$|spice/|ca.crt$|engine.ssh.key.txt$|rhevm.ssh.key.txt$|ovirt-engine-style.css$|console.vv$)>
ProxyPassMatch ajp://localhost:@JBOSS_AJP_PORT@
<IfModule deflate_module>
AddOutputFilterByType DEFLATE text/javascript text/css text/html
text/xml text/json application/xml application/json application/x-yaml
diff --git a/packaging/conf/ovirt-websocket-proxy.conf.defaults
b/packaging/conf/ovirt-websocket-proxy.conf.defaults
deleted file mode 100644
index b1cf9e2..0000000
--- a/packaging/conf/ovirt-websocket-proxy.conf.defaults
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# This is a default configuration file for oVirt/RHEV-M websockets proxy
-#
-# Make sure you provide valid certificate and key for SSL
-#
-
-PROXY_HOST=*
-PROXY_PORT=6100
-SOURCE_IS_IPV6=False
-SSL_CERTIFICATE=
-SSL_KEY=
-FORCE_DATA_VERIFICATION=False
-CERT_FOR_DATA_VERIFICATION=
-SSL_ONLY=False
-LOG_FILE="/usr/local/var/log/ovirt-engine/ovirt-websocket-proxy.log"
-LOG_VERBOSE=False
-ENGINE_USR="/usr/local/share/ovirt-engine"
-
diff --git a/packaging/etc/engine-config/engine-config.properties
b/packaging/etc/engine-config/engine-config.properties
index 2031d89..73dbe48 100644
--- a/packaging/etc/engine-config/engine-config.properties
+++ b/packaging/etc/engine-config/engine-config.properties
@@ -263,7 +263,7 @@
ClientModeRdpDefault.description="Default RDP console invocation behavior in
the engine."
ClientModeRdpDefault.validValues=Auto,Plugin,Native
ClientModeRdpDefault.type=String
-WebSocketProxy.description="Location of Websocket proxy
Off/Host:port/Engine:port/`FQDN_or_IP`:port"
+WebSocketProxy.description="Websockets proxy settings: Off/protocol:host:port,
where protocol is eihter http or https, host is address or value 'Engine'
(proxy on engine).
WebSocketProxy.type=String
WebSocketProxyTicketValiditySeconds.description="Validity (in seconds) of
tickets issued for websocket proxy."
WebSocketProxyTicketValiditySeconds.type=Integer
--
To view, visit http://gerrit.ovirt.org/15257
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I490cb57f5d23a7a763807d3bee00ea0e4c032338
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-engine
Gerrit-Branch: master
Gerrit-Owner: Frank Kobzik <[email protected]>
_______________________________________________
Engine-patches mailing list
[email protected]
http://lists.ovirt.org/mailman/listinfo/engine-patches