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

Jason Guiditta jguiditt at redhat.com
Wed May 20 18:20:02 UTC 2009


ACK, this works well for me.  Huge improvement with that refactor, IMO.
2 minor nits/suggestions, inline, no resend needed.

On Tue, 2009-05-19 at 16:09 -0400, Mohammed Morsi wrote:
> 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.
> +#

Minor note - in db-omatic, we have the following, which should probably
be here too:
[ -r /etc/sysconfig/ovirt-rails ] && . /etc/sysconfig/ovirt-rails

export RAILS_ENV="${RAILS_ENV:-production}"

> +
> +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()
You can drop this call since VncProxy doesnt extend anything right now
> +        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()




More information about the ovirt-devel mailing list