diff --git a/src/sunstone/OpenNebulaVNC.rb b/src/sunstone/OpenNebulaVNC.rb index 70a8525b61..1ec61c9907 100644 --- a/src/sunstone/OpenNebulaVNC.rb +++ b/src/sunstone/OpenNebulaVNC.rb @@ -27,9 +27,10 @@ class OpenNebulaVNC attr_reader :proxy_port - def initialize(config, logger, opts={ - :json_errors => true, - :token_folder_name => 'sunstone_vnc_tokens'}) + def initialize(config, logger, options = {}) + opts={ :json_errors => true, + :token_folder_name => 'sunstone_vnc_tokens'}.merge(options) + @pipe = nil @token_folder = File.join(VAR_LOCATION, opts[:token_folder_name]) @proxy_path = config[:vnc_proxy_path] @@ -38,6 +39,8 @@ class OpenNebulaVNC @wss = config[:vnc_proxy_support_wss] + @lock_file = config[:lock_file] || '/tmp/novnc.lock' + if (@wss == "yes") || (@wss == "only") || (@wss == true) @enable_wss = true @cert = config[:vnc_proxy_cert] @@ -48,21 +51,24 @@ class OpenNebulaVNC @options = opts @logger = logger - begin - Dir.mkdir(@token_folder) - rescue Exception => e - @logger.error "Cannot create token folder" - @logger.error e.message - end end def start - if @proxy_path == nil || @proxy_path.empty? - @logger.info "VNC proxy not configured" - return + if is_running? + message="VNC server already running" + STDERR.puts message + @logger.info message + return false end + if @proxy_path == nil || @proxy_path.empty? + @logger.error "VNC proxy not configured" + return false + end + + create_token_dir + proxy_options = "--target-config=#{@token_folder} " if @enable_wss @@ -75,16 +81,31 @@ class OpenNebulaVNC begin @logger.info { "Starting VNC proxy: #{cmd}" } - @pipe = IO.popen(cmd,'r') + pid=start_daemon(cmd, 'VNC_LOG') rescue Exception => e @logger.error e.message - return + return false end + + File.write(@lock_file, pid) + + sleep 1 + + if !is_running? + message="Error starting VNC proxy" + STDERR.puts message + @logger.error message + File.delete(@lock_file) if File.exist?(@lock_file) + + return false + end + + true end def proxy(vm_resource) # Check configurations and VM attributes - if !@pipe + if !is_running? return error(400, "VNC Proxy is not running") end @@ -121,12 +142,6 @@ class OpenNebulaVNC :token => random_str, } - # Delete token soon after - Thread.new do - sleep TOKEN_EXPIRE_SECONDS - delete_token(token_file) - end - return [200, info.to_json] end @@ -140,17 +155,31 @@ class OpenNebulaVNC end end - def stop - if !@pipe then return end - @logger.info "Killing VNC proxy" - Process.kill('TERM',@pipe.pid) - @pipe.close - begin - Dir.rmdir(@token_folder) - rescue => e - @logger.error "Error deleting token folder" - @logger.error e.message + def stop(force=false) + pid=get_pid + + if pid + @logger.info "Killing VNC proxy" + + signal=(force ? 'KILL' : 'TERM') + Process.kill(signal ,pid) + + sleep 1 + + if is_running? + message="The server is still running" + STDERR.puts message + logger.error message + return false + end + + delete_token_dir + else + message="The server is not running" + @logger.info message + STDERR.puts message end + true end private @@ -163,4 +192,56 @@ class OpenNebulaVNC end end + def create_token_dir + delete_token_dir + begin + Dir.mkdir(@token_folder) if !File.exist?(@token_folder) + rescue Exception => e + @logger.error "Cannot create token folder" + @logger.error e.message + end + end + + def delete_token_dir + if File.exist?(@token_folder) + begin + Dir.glob("#{@token_folder}/*").each do |file| + File.delete(file) + end + Dir.rmdir(@token_folder) + rescue => e + @logger.error "Error deleting token folder" + @logger.error e.message + end + end + end + + alias_method :get_pid, :is_running? + def is_running? + if File.exist?(@lock_file) + pid=File.read(@lock_file).strip + + if system("ps #{pid} 1> /dev/null") + return pid.to_i + end + + @logger.info "Deleting stale lock file" + File.delete(@lock_file) + end + + false + end + + def start_daemon(cmd, log) + pid=spawn(*cmd.split(" "), + :pgroup => true, + :in => :close, + [:out, :err] => [log, "a"], + :close_others => true ) + + Process.detach(pid) + + pid + end end + diff --git a/src/sunstone/novnc-server.rb b/src/sunstone/novnc-server.rb new file mode 100755 index 0000000000..995baf8444 --- /dev/null +++ b/src/sunstone/novnc-server.rb @@ -0,0 +1,78 @@ +#!/usr/bin/env ruby +# -*- coding: utf-8 -*- + +# -------------------------------------------------------------------------- # +# Copyright 2002-2013, OpenNebula Project (OpenNebula.org), C12G Labs # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +ONE_LOCATION = ENV["ONE_LOCATION"] + +if !ONE_LOCATION + LOG_LOCATION = "/var/log/one" + LOCK_LOCATION = "/var/lock/one" + VAR_LOCATION = "/var/lib/one" + ETC_LOCATION = "/etc/one" + RUBY_LIB_LOCATION = "/usr/lib/one/ruby" +else + VAR_LOCATION = ONE_LOCATION + "/var" + LOCK_LOCATION = ONE_LOCATION + "/var" + LOG_LOCATION = ONE_LOCATION + "/var" + ETC_LOCATION = ONE_LOCATION + "/etc" + RUBY_LIB_LOCATION = ONE_LOCATION+"/lib/ruby" +end + +VNC_LOCK = LOCK_LOCATION + "/novnc.lock" +VNC_LOG = LOG_LOCATION + "/novnc.log" + +CONFIGURATION_FILE = ETC_LOCATION + "/sunstone-server.conf" + +PLUGIN_CONFIGURATION_FILE = ETC_LOCATION + "/sunstone-plugins.yaml" + +SUNSTONE_ROOT_DIR = File.dirname(__FILE__) + +$: << RUBY_LIB_LOCATION +$: << RUBY_LIB_LOCATION+'/cloud' +$: << SUNSTONE_ROOT_DIR +$: << SUNSTONE_ROOT_DIR+'/models' + +require 'logger' +require 'yaml' +require 'OpenNebulaVNC' + +$log=Logger.new(VNC_LOG) + + +begin + conf = YAML.load_file(CONFIGURATION_FILE) +rescue Exception => e + STDERR.puts "Error parsing config file #{CONFIGURATION_FILE}: #{e.message}" + exit 1 +end + +vnc=OpenNebulaVNC.new(conf, $log) + +if ARGV[0] + res=case ARGV[0].downcase.to_sym + when :start + vnc.start + when :stop + vnc.stop(ARGV[1]=='--force') + end + + exit(-1) if !res +else + exit(-1) +end + diff --git a/src/sunstone/sunstone-server.rb b/src/sunstone/sunstone-server.rb index ee7d66a69e..39a4a2aaa7 100755 --- a/src/sunstone/sunstone-server.rb +++ b/src/sunstone/sunstone-server.rb @@ -104,10 +104,6 @@ set :cloud_auth, cloud_auth configure do set :run, false set :vnc, OpenNebulaVNC.new(conf, settings.logger) - settings.vnc.start() - Kernel.at_exit do - settings.vnc.stop - end end ##############################################################################