Permalink
Browse files

fixes #2277 - adds spice html5 support

This also adds a newer version of the web socket proxy (where we
probably need to use an external package instead of vendor it).

we still allow users to use the old XPI based spice client (which would
ensure end to end security as well) via a 'new window' button.
that window would only be allowed currently if you are on firefox on
linux.

Paired with: Amos Benari <abenari@redhat.com>
  • Loading branch information...
1 parent a38529f commit 8ffd9aee4e32aa9bd01f8cbb99be1c42ed7f8934 @ohadlevy ohadlevy committed Feb 26, 2013
Showing with 7,977 additions and 241 deletions.
  1. +8 −1 app/controllers/compute_resources_vms_controller.rb
  2. +8 −0 app/controllers/hosts_controller.rb
  3. +19 −0 app/helpers/compute_resources_vms_helper.rb
  4. +1 −0 app/helpers/hosts_helper.rb
  5. +0 −58 app/views/hosts/console.html.erb
  6. +17 −0 app/views/hosts/console/log.html.erb
  7. +20 −0 app/views/hosts/console/spice.html.erb
  8. +19 −0 app/views/hosts/console/vnc.html.erb
  9. +5 −0 extras/noVNC/websockify.py
  10. +2 −0 extras/noVNC/websockify/__init__.py
  11. +186 −124 extras/noVNC/{ → websockify}/websocket.py
  12. +153 −42 extras/noVNC/{wsproxy.py → websockify/websocketproxy.py}
  13. +1 −1 lib/foreman/model/ec2.rb
  14. +1 −2 lib/foreman/model/libvirt.rb
  15. +9 −3 lib/foreman/model/ovirt.rb
  16. +1 −1 lib/foreman/model/vmware.rb
  17. +10 −8 lib/{vnc_proxy.rb → ws_proxy.rb}
  18. +1 −1 public/javascripts/noVNC.js
  19. +52 −0 public/javascripts/spice.js
  20. +183 −0 public/javascripts/spice/atKeynames.js
  21. +51 −0 public/javascripts/spice/bitmap.js
  22. +92 −0 public/javascripts/spice/cursor.js
  23. +806 −0 public/javascripts/spice/display.js
  24. +282 −0 public/javascripts/spice/enums.js
  25. +271 −0 public/javascripts/spice/inputs.js
  26. +166 −0 public/javascripts/spice/lz.js
  27. +177 −0 public/javascripts/spice/main.js
  28. +256 −0 public/javascripts/spice/png.js
  29. +1,335 −0 public/javascripts/spice/quic.js
  30. +19 −0 public/javascripts/spice/setup.js
  31. +455 −0 public/javascripts/spice/spiceconn.js
  32. +96 −0 public/javascripts/spice/spicedataview.js
  33. +883 −0 public/javascripts/spice/spicemsg.js
  34. +480 −0 public/javascripts/spice/spicetype.js
  35. +589 −0 public/javascripts/spice/thirdparty/jsbn.js
  36. +79 −0 public/javascripts/spice/thirdparty/prng4.js
  37. +102 −0 public/javascripts/spice/thirdparty/rng.js
  38. +146 −0 public/javascripts/spice/thirdparty/rsa.js
  39. +346 −0 public/javascripts/spice/thirdparty/sha1.js
  40. +250 −0 public/javascripts/spice/ticket.js
  41. +261 −0 public/javascripts/spice/utils.js
  42. +123 −0 public/javascripts/spice/wire.js
  43. +16 −0 public/stylesheets/style.css
@@ -52,7 +52,14 @@ def destroy
def console
@console = @compute_resource.console @vm.identity
- render "hosts/console"
+ render case @console[:type]
+ when 'spice'
+ "hosts/console/spice"
+ when 'vnc'
+ "hosts/console/vnc"
+ else
+ "hosts/console/log"
+ end
rescue => e
process_error :redirect => compute_resource_vm_path(@compute_resource, @vm.identity), :error_msg => "Failed to set console: #{e}", :object => @vm
end
@@ -218,6 +218,14 @@ def power
def console
return unless @host.compute_resource
@console = @host.compute_resource.console @host.uuid
+ render case @console[:type]
+ when 'spice'
+ "hosts/console/spice"
+ when 'vnc'
+ "hosts/console/vnc"
+ else
+ "hosts/console/log"
+ end
rescue => e
process_error :redirect => :back, :error_msg => "Failed to set console: #{e}"
end
@@ -23,4 +23,23 @@ def prop method, title = nil
end
end
+ def supports_spice_xpi?
+ user_agent = request.env['HTTP_USER_AGENT']
+ user_agent =~ /linux/i && user_agent =~ /firefox/i
+ end
+
+ def spice_data_attributes(console)
+ options = {
+ :port => console[:proxy_port],
+ :password => console[:password]
+ }
+ options.merge!(
+ :address => console[:address],
+ :secure_port => console[:secure_port],
+ :ca_cert => URI.escape(console[:ca_cert]),
+ :title => "#{console[:name]} - Press Shift-F12 to release the cursor."
+ ) if supports_spice_xpi?
+ options
+ end
+
end
@@ -1,6 +1,7 @@
module HostsHelper
include OperatingsystemsHelper
include HostsAndHostgroupsHelper
+ include ComputeResourcesVmsHelper
def last_report_column(record)
time = record.last_report? ? time_ago_in_words(record.last_report.getlocal) +" ago": ""
@@ -1,58 +0,0 @@
-<!--SPICE Console-->
-<% if @console[:secure_port] -%>
- <script type="text/javascript">
- function connectvm()
- {
- var pluginobj = document.embeds[0];
- pluginobj.hostIP = String("<%= @console[:address] %>");
- pluginobj.SecurePort = String("<%= @console[:secure_port] %>");
- pluginobj.Password = String("<%= @console[:ticket] %>");
- pluginobj.TrustStore = String("<%= @console[:ca_cert] %>");
- pluginobj.SSLChannels = String("all");
- pluginobj.fullScreen = false;
- pluginobj.Title = String('<%= "#{@console[:name]} - Press Shift-F12 to release the cursor." %>');
- pluginobj.connect();
- }
- $(function () { connectvm(); });
- </script>
- <embed type="application/x-spice" height=0 width=0>
-<!--VNC Console-->
-<% elsif @console[:proxy_port] -%>
- <%= content_for(:head) { javascript_tag "var INCLUDE_URI = '#{javascript_path("noVNC").sub(/\.js.*$/,"/")}';" } %>
- <%= javascript 'noVNC/vnc', 'noVNC/ui', 'noVNC' %>
-
- <div id='vnc' data-port='<%= @console[:proxy_port] %>' data-password='<%= @console[:password] %>'>
-
- <div id="noVNC_status_bar" class="row" style="margin-bottom:18px;">
- <div id="noVNC_status" class="span7 label" >Loading</div>
- <div id="noVNC_buttons">
- <input type=button value="Ctrl-Alt-Del" id="sendCtrlAltDelButton" class="fr btn" >
- </div>
- <%= link_to_if_authorized("Back to host", hash_for_host_path(:id => @host), :title => "Back to host" , :class => 'fr btn') if @host %>
- </div>
-
- <canvas id="noVNC_canvas" width="640px" height="20px" class="clearfix ca">
- Canvas not supported.
- </canvas>
- </div>
-<!--Text Console-->
-<% else -%>
- <div class="row">
- <% search_bar "Generated #{time_ago_in_words @console['timestamp']} ago" %>
- <% if @host %>
- <% title_actions link_to_if_authorized("Back to host", hash_for_host_path(:id => @host), :title => "Back to host" , :class => 'fr btn') %>
- <% title "Console output for #{@host}" %>
- <% end %>
- </div>
- <% if @host && (@host.installed_at.nil? or (@console['timestamp'] - @host.installed_at < 5.minutes)) -%>
- <div class='alert'>
- <a class="close" href="#" data-dismiss="alert">&times;</a>
- Console output may be out of date
- </div>
- <% end -%>
- <pre class="pre-scrollable">
- <code>
- <%= @console['output'] %>
- </code>
- </pre>
-<% end -%>
@@ -0,0 +1,17 @@
+<div class="row">
+ <% search_bar "Generated #{time_ago_in_words @console['timestamp']} ago" %>
+ <%= title_actions(link_to_if_authorized("Back to host", hash_for_host_path(:id => @host), :title => "Back to host", :class => 'btn')) if @host %>
+ <% title "#{@console[:name]}" %>
+</div>
+<% if @host && (@host.installed_at.nil? or (@console['timestamp'] - @host.installed_at < 5.minutes)) -%>
+ <div class='alert'>
+ <a class="close" href="#" data-dismiss="alert">&times;</a>
+ Console output may be out of date
+ </div>
+<% end -%>
+<pre class="pre-scrollable">
+ <code>
+ <%= @console['output'] %>
+ </code>
+</pre>
+
@@ -0,0 +1,20 @@
+<%= javascript 'spice/setup', 'spice' %>
+<% title "#{@console[:name]}" %>
+<%= title_actions(
+ button_group(link_to("Ctrl-Alt-Del", "#", :id => "sendCtrlAltDelButton", :onclick => 'sendCtrlAltDel()', :class => "btn"),
+ if supports_spice_xpi?
+ link_to("New window", "#", :id => "disconnect", :class => "btn", :onclick => 'connectXPI()', :title => "Open Spice in a new window")
+ end,
+ if @host
+ link_to_if_authorized("Back to host", hash_for_host_path(:id => @host), :title => "Back to host", :class => 'btn')
+ end
+ )) %>
+
+<%# TODO: when rails 3.2 merge is done uncomment the following %>
+<%# tag(:div id =>'spice-area' data => spice_data_attributes(@console) %>
+<div id='spice-area' <%= spice_data_attributes(@console).map {|k,v| "data-#{k}=#{v}"}.join(' ') %>>
+ <div class="console-status">
+ <div id="spice-status" class="span7 label"><%= "Connecting (unencrypted) to: #{@console[:name]}" %></div>
+ </div>
+ <div id="spice-screen" class="console-screen"> </div>
+</div>
@@ -0,0 +1,19 @@
+<%= content_for(:head) { javascript_tag "var INCLUDE_URI = '#{javascript_path("noVNC").sub(/\.js.*$/, "/")}';" } %>
+<%= javascript 'noVNC/vnc', 'noVNC/ui', 'noVNC' %>
+<% title "#{@console[:name]}" %>
+<%= title_actions(
+ button_group(link_to("Ctrl-Alt-Del", "#", :id => "sendCtrlAltDelButton", :class => "btn"),
+ if @host
+ link_to_if_authorized("Back to host", hash_for_host_path(:id => @host), :title => "Back to host", :class => 'btn')
+ end
+ ) ) %>
+<div id='vnc' data-port='<%= @console[:proxy_port] %>' data-password='<%= @console[:password] %>'>
+
+ <div id="noVNC_status_bar" class="console-status">
+ <div id="noVNC_status" class="span7 label">Loading ...</div>
+ </div>
+
+ <canvas id="noVNC_canvas" class="console-screen">
+ Canvas not supported.
+ </canvas>
+</div>
@@ -0,0 +1,5 @@
+#!/usr/bin/python
+
+import websockify
+
+websockify.websocketproxy.websockify_init()
@@ -0,0 +1,2 @@
+from websocket import *
+from websocketproxy import *
Oops, something went wrong.

0 comments on commit 8ffd9ae

Please sign in to comment.