[Ovirt-devel] [PATCH server] added ovirt vnc proxy server, to proxy vnc request to managed vms

Mohammed Morsi mmorsi at redhat.com
Tue May 19 20:09:43 UTC 2009


run on startup by default like the other ovirt services
---
 conf/ovirt-vnc-proxy                       |   49 ++++++++
 installer/modules/ovirt/manifests/ovirt.pp |    1 +
 ovirt-server.spec.in                       |    5 +
 src/vnc-proxy/vnc-proxy.rb                 |  167 ++++++++++++++++++++++++++++
 4 files changed, 222 insertions(+), 0 deletions(-)
 create mode 100755 conf/ovirt-vnc-proxy
 create mode 100755 src/vnc-proxy/vnc-proxy.rb

diff --git a/conf/ovirt-vnc-proxy b/conf/ovirt-vnc-proxy
new file mode 100755
index 0000000..b3f565f
--- /dev/null
+++ b/conf/ovirt-vnc-proxy
@@ -0,0 +1,49 @@
+#!/bin/bash
+#
+#
+# ovirt-vnc-proxy       startup script for ovirt-vnc-proxy
+#
+# chkconfig: - 97 03
+# description: ovirt-vnc-proxy proxies vnc requests to ovirt
+#    managed vms.
+#
+
+DAEMON=/usr/share/ovirt-server/vnc-proxy/vnc-proxy.rb
+
+. /etc/init.d/functions
+
+start() {
+    echo -n "Starting ovirt-vnc-proxy: "
+    daemon $DAEMON
+    RETVAL=$?
+    echo
+}
+
+stop() {
+    echo -n "Shutting down ovirt-vnc-proxy: "
+    killproc vnc-proxy.rb
+    RETVAL=$?
+    echo
+}
+
+case "$1" in
+    start)
+	start
+	;;
+    stop)
+	stop
+	;;
+    restart)
+	stop
+	start
+	;;
+    status)
+	status $DAEMON
+	RETVAL=$?
+	;;
+    *)
+      echo "Usage: ovirt-vnc-proxy {start|stop|restart|status}"
+      exit 1
+  ;;
+esac
+exit $RETVAL
diff --git a/installer/modules/ovirt/manifests/ovirt.pp b/installer/modules/ovirt/manifests/ovirt.pp
index 03a93a7..d953ebe 100644
--- a/installer/modules/ovirt/manifests/ovirt.pp
+++ b/installer/modules/ovirt/manifests/ovirt.pp
@@ -197,6 +197,7 @@ class ovirt::setup {
         firewall_rule{"http": destination_port => "80"}
         firewall_rule {"https": destination_port => '443'}
         firewall_rule {"host-browser": destination_port => '12120'}
+        firewall_rule {"vnc-proxy": destination_port => '5900'}
         firewall_rule {"qpidd": destination_port => '5672'}
         firewall_rule {"collectd": destination_port => '25826', protocol => 'udp'}
         firewall_rule {"ntpd": destination_port => '123', protocol => 'udp'}
diff --git a/ovirt-server.spec.in b/ovirt-server.spec.in
index b4f7454..ad8777b 100644
--- a/ovirt-server.spec.in
+++ b/ovirt-server.spec.in
@@ -104,6 +104,7 @@ touch %{buildroot}%{_localstatedir}/log/%{name}/db-omatic.log
 %{__install} -Dp -m0755 %{pbuild}/conf/ovirt-mongrel-rails.sysconf %{buildroot}%{_sysconfdir}/sysconfig/ovirt-mongrel-rails
 %{__install} -Dp -m0755 %{pbuild}/conf/ovirt-rails.sysconf %{buildroot}%{_sysconfdir}/sysconfig/ovirt-rails
 %{__install} -Dp -m0755 %{pbuild}/conf/ovirt-taskomatic %{buildroot}%{_initrddir}
+%{__install} -Dp -m0755 %{pbuild}/conf/ovirt-vnc-proxy %{buildroot}%{_initrddir}
 
 # copy over all of the src directory...
 %{__cp} -a %{pbuild}/src/* %{buildroot}%{app_root}
@@ -180,6 +181,7 @@ fi
 %daemon_chkconfig_post -d ovirt-host-collect
 %daemon_chkconfig_post -d ovirt-mongrel-rails
 %daemon_chkconfig_post -d ovirt-taskomatic
+%daemon_chkconfig_post -d ovirt-vnc-proxy
 
 %preun
 if [ "$1" = 0 ] ; then
@@ -188,11 +190,13 @@ if [ "$1" = 0 ] ; then
   /sbin/service ovirt-host-collect stop > /dev/null 2>&1
   /sbin/service ovirt-mongrel-rails stop > /dev/null 2>&1
   /sbin/service ovirt-taskomatic stop > /dev/null 2>&1
+  /sbin/service ovirt-vnc-proxy stop > /dev/null 2>&1
   /sbin/chkconfig --del ovirt-host-browser
   /sbin/chkconfig --del ovirt-db-omatic
   /sbin/chkconfig --del ovirt-host-collect
   /sbin/chkconfig --del ovirt-mongrel-rails
   /sbin/chkconfig --del ovirt-taskomatic
+  /sbin/chkconfig --del ovirt-vnc-proxy
 fi
 
 %files
@@ -206,6 +210,7 @@ fi
 %{_initrddir}/ovirt-host-collect
 %{_initrddir}/ovirt-mongrel-rails
 %{_initrddir}/ovirt-taskomatic
+%{_initrddir}/ovirt-vnc-proxy
 %{_sysconfdir}/cron.d/%{name}
 %config(noreplace) %{_sysconfdir}/sysconfig/ovirt-mongrel-rails
 %config(noreplace) %{_sysconfdir}/sysconfig/ovirt-rails
diff --git a/src/vnc-proxy/vnc-proxy.rb b/src/vnc-proxy/vnc-proxy.rb
new file mode 100755
index 0000000..5a1c35e
--- /dev/null
+++ b/src/vnc-proxy/vnc-proxy.rb
@@ -0,0 +1,167 @@
+#!/usr/bin/ruby
+#
+# vnc-proxy.rb
+# ovirt vnc proxy server, relays ovirt encoded
+#   vnc requests to correct node
+# Copyright (C) 2009 Red Hat, Inc.
+# Written by Mohammed Morsi <mmorsi at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA  02110-1301, USA.  A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+$: << File.join(File.dirname(__FILE__), "../dutils")
+
+require 'dutils'
+require 'daemons'
+include Daemonize
+
+###########
+
+DEFAULT_VNC_PROXY_PORT = 5900
+VM_NAME_MAX_LEN   = 250
+VNC_DATA_MAX_LEN = 800000
+
+###########
+
+# clone of the taskomatic / dbomatic logger;
+# TODO move all of these seperate implementations into a single dutils module
+class Logger
+  def format_message(severity, timestamp, progname, msg)
+    "#{severity} #{timestamp} (#{$$}) #{msg}\n"
+  end
+end
+
+$logfile = '/var/log/ovirt-server/vnc-proxy.log'
+
+###########
+
+
+class VncProxy
+
+    # initialize vnc proxy
+    def initialize()
+        super()
+        do_daemon = true
+        port = DEFAULT_VNC_PROXY_PORT
+
+        opts = OptionParser.new do |opts|
+            opts.on("-h", "--help", "Print help message") do
+                puts opts
+                exit
+            end
+            opts.on("-n", "--nodaemon", "Run interactively (useful for debugging)") do |n|
+                do_daemon = false
+            end
+            opts.on("-p", "--port", "Port to listen on") do |n|
+                port = n.to_i
+            end
+        end
+        begin
+            opts.parse!(ARGV)
+        rescue OptionParser::InvalidOption
+            puts opts
+            exit
+        end
+
+        if do_daemon
+            # same issues as w/ dbomatic / taskomatic
+            pwd = Dir.pwd
+            daemonize
+            Dir.chdir(pwd)
+            @logger = Logger.new($logfile)
+        else
+            @logger = Logger.new(STDERR)
+        end
+
+        begin
+          @server = TCPServer.open(port)
+        rescue Exception => ex
+           @logger.error "Error in vnc-proxy: #{ex}"
+           @logger.error ex.backtrace
+
+           # reraise ex, if we can't bind
+           # to port server should die
+           raise ex
+        end
+
+        @logger.info "vnc-proxy started."
+     end
+
+     # run vnc proxy
+     def run
+       continue = true
+       while(continue) do
+        begin
+         Thread.start(@server.accept) do |client|
+          begin
+             @logger.info "client accepted"
+
+             # first msg will be the vm description
+             vm_description = client.recv(VM_NAME_MAX_LEN).to_s
+             @logger.info "vm received: " + vm_description + ";"
+
+             # lookup vm
+             vm = Vm.find(:first, :conditions => [ "description = ?", vm_description ])
+             if vm && vm.state == "running"
+               # connect to node
+               @logger.info "connecting to node " + vm.host.hostname + ":" + vm.vnc_port.to_s
+               node_socket = TCPSocket.open(vm.host.hostname, vm.vnc_port)
+
+               # begin new thread to process server->client messages
+               Thread.start do
+                 @logger.debug "listening for server->client data"
+                 while(true)do
+                   node_data = node_socket.recv VNC_DATA_MAX_LEN
+                   break if node_data.size <= 0
+                   client.write node_data
+                 end
+               end
+
+               # process client -> server messages
+               @logger.debug "listening for client->server data"
+               while(true) do
+                 client_data = client.recv VNC_DATA_MAX_LEN
+                 break if client_data.size <= 0
+                 node_socket.write client_data
+               end
+
+               node_socket.close
+               @logger.info "node connection terminated"
+             end
+          rescue Exception => ex
+            @logger.error "Error w/ vnc-proxy client (non-fatal) #{ex}"
+          end
+
+          client.close
+          @logger.info "client connection terminated"
+         end
+
+        rescue Exception => ex
+          continue = false
+          @logger.error "terminating vnc proxy server #{ex}"
+        end
+       end
+
+       @server.close
+       @logger.info "server terminated"
+     end
+end
+
+def main()
+   vncproxy = VncProxy.new
+   vncproxy.run
+end
+
+main()
-- 
1.6.0.6




More information about the ovirt-devel mailing list