1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-02-10 13:57:22 +03:00

F #2410: VM Autorefresh (#180)

Signed-off-by: Frederick Borges <fborges@opennebula.io>
This commit is contained in:
Frederick Borges 2020-09-04 10:33:13 +02:00 committed by GitHub
parent 84debc2545
commit 40ad20451a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 660 additions and 17 deletions

View File

@ -460,7 +460,8 @@ VAR_DIRS="$VAR_LOCATION/remotes \
SUNSTONE_DIRS="$SUNSTONE_LOCATION/routes \
$SUNSTONE_LOCATION/models \
$SUNSTONE_LOCATION/models/OpenNebulaJSON \
$SUNSTONE_LOCATION/views"
$SUNSTONE_LOCATION/views \
$SUNSTONE_LOCATION/services"
SUNSTONE_MINIFIED_DIRS="$SUNSTONE_LOCATION/public \
$SUNSTONE_LOCATION/public/dist \
@ -735,6 +736,7 @@ INSTALL_SUNSTONE_FILES=(
SUNSTONE_MODELS_JSON_FILES:$SUNSTONE_LOCATION/models/OpenNebulaJSON
SUNSTONE_VIEWS_FILES:$SUNSTONE_LOCATION/views
SUNSTONE_ROUTES_FILES:$SUNSTONE_LOCATION/routes
SUNSTONE_SERVICES_FILES:$SUNSTONE_LOCATION/services
)
INSTALL_SUNSTONE_PUBLIC_MINIFIED_FILES=(
@ -769,6 +771,7 @@ INSTALL_SUNSTONE_PUBLIC_MINIFIED_FILES=(
INSTALL_SUNSTONE_PUBLIC_DEV_DIR=(
SUNSTONE_PUBLIC_DEV_DIR:$SUNSTONE_LOCATION
SUNSTONE_GUAC_DEV_DIR:$SUNSTONE_LOCATION
SUNSTONE_AUTOREFRESH_DEV_DIR:$SUNSTONE_LOCATION/services/autorefresh
)
INSTALL_SUNSTONE_ETC_FILES=(
@ -898,6 +901,7 @@ RUBY_LIB_FILES="src/mad/ruby/ActionManager.rb \
src/oca/ruby/opennebula.rb \
src/sunstone/OpenNebulaVNC.rb \
src/sunstone/OpenNebulaGuac.rb \
src/sunstone/OpenNebulaAutorefresh.rb \
src/sunstone/OpenNebulaAddons.rb \
src/vmm_mad/remotes/vcenter/vcenter_driver.rb \
src/vmm_mad/remotes/nsx/nsx_driver.rb \
@ -2377,7 +2381,8 @@ SUNSTONE_FILES="src/sunstone/sunstone-server.rb \
SUNSTONE_BIN_FILES="src/sunstone/bin/sunstone-server \
src/sunstone/bin/guac-server \
src/sunstone/bin/novnc-server"
src/sunstone/bin/novnc-server\
src/sunstone/bin/autorefresh-server"
SUNSTONE_ETC_FILES="src/sunstone/etc/sunstone-server.conf \
src/sunstone/etc/sunstone-views.yaml \
@ -2451,6 +2456,8 @@ SUNSTONE_PUBLIC_JS_CONSOLE_FILES="src/sunstone/public/dist/console/vnc.js \
SUNSTONE_PUBLIC_DEV_DIR="src/sunstone/public"
SUNSTONE_AUTOREFRESH_DEV_DIR="src/sunstone/services/autorefresh"
SUNSTONE_ROUTES_FILES="src/sunstone/routes/oneflow.rb \
src/sunstone/routes/vcenter.rb \
src/sunstone/routes/support.rb \

View File

@ -0,0 +1,209 @@
# -------------------------------------------------------------------------- #
# Copyright 2002-2020, OpenNebula Project, OpenNebula Systems #
# #
# 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. #
#--------------------------------------------------------------------------- #
require 'opennebula'
##############################################################################
# Global Variables
##############################################################################
if !ONE_LOCATION
AUTOREFRESH_LOCK_FILE = "/var/lock/one/.autorefresh.lock"
else
AUTOREFRESH_LOCK_FILE = ONE_LOCATION + "/var/.autorefresh.lock"
end
KEEPALIVE_TIME = 15
LIB_LOCATION="/usr/lib/one"
SUNSTONE_SERVICES_LOCATION=LIB_LOCATION+"/sunstone/services"
##############################################################################
# Server
##############################################################################
class OpenNebulaAutorefresh
def initialize(config, logger)
# Basics
@logger = logger
# Autorefresh
@lock_file = AUTOREFRESH_LOCK_FILE
@server_ip = config[:autorefresh_ip]
@server_port = config[:autorefresh_port]
end
def start
# Launch error if Autorefresh server is running
if is_autorefresh_running?
message="Autorefresh server already running"
STDERR.puts message
@logger.info message
return false
end
config_dir = SUNSTONE_SERVICES_LOCATION + "/autorefresh"
config_file = config_dir + "/config.ru"
# Start Autorefresh server
cmd = "thin start -R #{config_file} -p #{@server_port} -a #{@server_ip}";
begin
@logger.info { "Starting Autorefresh server: #{cmd}" }
pid=start_daemon(cmd, AUTOREFRESH_LOG)
rescue Exception => e
@logger.error e.message
return false
end
begin
File.open(@lock_file, "w") do |f|
f.write(pid.to_s)
end
rescue Exception => e
@logger.error e.message
Process.kill('-KILL', pid)
return false
end
# Verify if Autorefresh server is running
sleep 1
if !is_autorefresh_running?
message="Error starting Autorefresh server"
STDERR.puts message
@logger.error message
File.delete(@lock_file) if File.exist?(@lock_file)
return false
end
STDOUT.puts "Autorefresh server started"
true
end
def stop(force=false)
pid=get_autorefresh_pid
if pid
@logger.info "Killing Autorefresh server"
signal=(force ? '-KILL' : '-TERM')
Process.kill(signal ,pid)
sleep 1
begin
Process.getpgid(pid)
Process.kill('-KILL', pid)
rescue
end
if is_autorefresh_running?
message="Autorefresh server is still running"
STDERR.puts message
logger.error message
return false
end
else
message="Autorefresh server is not running"
@logger.info message
STDERR.puts message
end
true
end
def status
if is_autorefresh_running?
STDOUT.puts "Autorefresh server is running"
true
else
STDOUT.puts "Autorefresh server is NOT running"
false
end
end
private
def is_autorefresh_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
alias_method :get_autorefresh_pid, :is_autorefresh_running?
def is_lockfile?
dn = File.dirname(@lock_file)
bn = File.basename(@lock_file)
# Due to restrictions which doesn't allow to stat the lock file
# when Sunstone is running under Apache with SELinux enabled,
# as a workaround we read content of the whole lock directory.
begin
Dir.entries(dn).include?(bn)
rescue StandardError
false
end
end
if RUBY_VERSION<'1.9'
def spawn(*args)
fork {
command=args[0..-2]
# Close stdin and point out and err to log file
$stdout.reopen(AUTOREFRESH_LOG, "a")
$stderr.reopen(AUTOREFRESH_LOG, "a")
$stdin.close
# Detach process from the parent
Process.setsid
exec(*command)
}
end
end
def start_daemon(cmd, log)
options={
:pgroup => true,
:in => :close,
[:out, :err] => [log, "a"],
:close_others => true }
params=cmd.split(" ")+[options]
pid=spawn( *params )
Process.detach(pid)
pid
end
end

View File

@ -0,0 +1,90 @@
#!/usr/bin/env ruby
# -*- coding: utf-8 -*-
# -------------------------------------------------------------------------- #
# Copyright 2002-2020, OpenNebula Project, OpenNebula Systems #
# #
# 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'
VAR_LOCATION = '/var/lib/one'
SHARE_LOCATION = '/usr/share/one'
ETC_LOCATION = '/etc/one'
RUBY_LIB_LOCATION = '/usr/lib/one/ruby'
GEMS_LOCATION = '/usr/share/one/gems'
else
VAR_LOCATION = ONE_LOCATION + '/var'
LOG_LOCATION = ONE_LOCATION + '/var'
SHARE_LOCATION = ONE_LOCATION + '/share'
ETC_LOCATION = ONE_LOCATION + '/etc'
RUBY_LIB_LOCATION = ONE_LOCATION + '/lib/ruby'
GEMS_LOCATION = ONE_LOCATION + '/share/gems'
end
AUTOREFRESH_LOG = LOG_LOCATION + "/autorefresh.log"
CONFIGURATION_FILE = ETC_LOCATION + "/sunstone-server.conf"
PLUGIN_CONFIGURATION_FILE = ETC_LOCATION + "/sunstone-plugins.yaml"
SUNSTONE_ROOT_DIR = File.dirname(__FILE__)
if File.directory?(GEMS_LOCATION)
$LOAD_PATH.reject! {|l| l =~ /vendor_ruby/ }
require 'rubygems'
Gem.use_paths(File.realpath(GEMS_LOCATION))
end
$LOAD_PATH << RUBY_LIB_LOCATION
$LOAD_PATH << RUBY_LIB_LOCATION + '/cloud'
$LOAD_PATH << SUNSTONE_ROOT_DIR
$LOAD_PATH << SUNSTONE_ROOT_DIR + '/models'
require 'logger'
require 'yaml'
require 'OpenNebulaAutorefresh'
$log=Logger.new(AUTOREFRESH_LOG)
begin
conf = YAML.load_file(CONFIGURATION_FILE)
rescue Exception => e
STDERR.puts "Error parsing config file #{CONFIGURATION_FILE}: #{e.message}"
exit 1
end
autorefresh=OpenNebulaAutorefresh.new(conf, $log)
if ARGV[0]
res=case ARGV[0].downcase.to_sym
when :start
autorefresh.start
when :stop
autorefresh.stop(true)
when :restart
autorefresh.stop(true)
sleep 1
autorefresh.start
when :status
autorefresh.status
end
if !res
STDERR.puts "Error, check #{AUTOREFRESH_LOG}"
exit(-1)
end
else
exit(-1)
end

View File

@ -26,6 +26,7 @@ if [ -z "$ONE_LOCATION" ]; then
SUNSTONE_CONF=/etc/one/sunstone-server.conf
NOVNC_SERVER=/usr/bin/novnc-server
GUACAMOLE_SERVER=/usr/bin/guac-server
AUTOREFRESH_SERVER=/usr/bin/autorefresh-server
else
SUNSTONE_PID=$ONE_LOCATION/var/sunstone.pid
SUNSTONE_SERVER=$ONE_LOCATION/lib/sunstone/sunstone-server.rb
@ -35,6 +36,7 @@ else
SUNSTONE_CONF=$ONE_LOCATION/etc/sunstone-server.conf
NOVNC_SERVER=$ONE_LOCATION/bin/novnc-server
GUACAMOLE_SERVER=$ONE_LOCATION/bin/guac-server
AUTOREFRESH_SERVER=$ONE_LOCATION/bin/autorefresh-server
fi
setup()
@ -63,10 +65,11 @@ setup()
start()
{
while getopts "ng" opt; do
while getopts "ngr" opt; do
case "${opt}" in
n) novnc=1 ;;
g) guacamole=1 ;;
r) autorefresh=1 ;;
*) echo "Invalid option: $OPTARG" 1>&2 ;;
esac
done
@ -94,6 +97,15 @@ start()
fi
fi
if [ "$autorefresh" = "1" ]; then
# Start Autorefresh server
$AUTOREFRESH_SERVER start
if [ "$?" != "0" ]; then
echo "Could not start Autorefresh server" 1>&2
fi
fi
# Start the sunstone daemon
touch $SUNSTONE_LOCK_FILE
@ -102,6 +114,7 @@ start()
$NOVNC_SERVER stop
$GUACAMOLE_SERVER stop
$AUTOREFRESH_SERVER stop
exit 1
fi
@ -113,6 +126,7 @@ start()
echo "Check $SUNSTONE_LOG_ERROR and $SUNSTONE_LOG for more information"
[ "$novnc" = "1" ] && $NOVNC_SERVER stop
[ "$guacamole" = "1" ] && $GUACAMOLE_SERVER stop
[ "$autorefresh" = "1" ] && $AUTOREFRESH_SERVER stop
exit 1
else
echo $LASTPID > $SUNSTONE_PID
@ -126,6 +140,7 @@ start()
echo "Check $SUNSTONE_LOG_ERROR and $SUNSTONE_LOG for more information"
[ "$novnc" = "1" ] && $NOVNC_SERVER stop
[ "$guacamole" = "1" ] && $GUACAMOLE_SERVER stop
[ "$autorefresh" = "1" ] && $AUTOREFRESH_SERVER stop
exit 1
fi
@ -137,10 +152,11 @@ start()
#
stop()
{
while getopts "ng" opt; do
while getopts "ngr" opt; do
case "${opt}" in
n) novnc=1 ;;
g) guacamole=1 ;;
r) autorefresh=1 ;;
*) echo "Invalid option: $OPTARG" 1>&2 ;;
esac
done
@ -151,6 +167,9 @@ stop()
# Stop guacamole server
[ "$guacamole" = "1" ] && $GUACAMOLE_SERVER stop
# Stop autorefresh server
[ "$autorefresh" = "1" ] && $AUTOREFRESH_SERVER stop
if [ ! -f $SUNSTONE_PID ]; then
echo "Couldn't find sunstone-server process pid." >&2
return 1
@ -170,16 +189,16 @@ stop()
case "$1" in
start)
setup
start -ng
start -ngr
;;
stop)
stop -ng
stop -ngr
exit $?
;;
restart)
stop -ng 2> /dev/null
stop -ngr 2> /dev/null
setup
start -ng
start -ngr
;;
start-sunstone)
setup
@ -189,7 +208,7 @@ case "$1" in
stop
;;
restart-sunstone)
stop -ng 2> /dev/null
stop -ngr 2> /dev/null
setup
start
;;

View File

@ -257,4 +257,12 @@
# This change the thresholds of dashboard resource usage
:threshold_min: 0
:threshold_low: 33
:threshold_high: 66
:threshold_high: 66
################################################################################
# Autorefresh websocket configuration
################################################################################
:zeromq_server: tcp://localhost:2101
:autorefresh_ip: 127.0.0.1
:autorefresh_port: 2346

View File

@ -21,6 +21,7 @@ include OpenNebulaJSON
require 'OpenNebulaVNC'
require 'OpenNebulaGuac'
require 'OpenNebulaAutorefresh'
require 'OpenNebulaAddons'
require 'OpenNebulaJSON/JSONUtils'
#include JSONUtils

View File

@ -39,6 +39,7 @@ define(function(require) {
var Menu = require('utils/menu');
var Locale = require('utils/locale');
var UserAndZoneTemplate = require('hbs!sunstone/user_and_zone');
var Websocket = require("utils/websocket");
var _commonDialogs = [
require('utils/dialogs/confirm'),
@ -73,6 +74,8 @@ define(function(require) {
Sunstone.showTab(PROVISION_TAB_ID);
}
Websocket.start();
$('#loading').hide();
});

View File

@ -181,6 +181,9 @@ define(function(require) {
},
"isExtendedVmInfo": _config["system_config"] && _config["system_config"]["get_extended_vm_info"] && _config["system_config"]["get_extended_vm_info"] === "true",
"isLogEnabled": _config["zone_id"] === _config["id_own_federation"] ? true : false,
"autorefreshWSS": _config["system_config"]["autorefresh_wss"],
"autorefreshIP": _config["system_config"]["autorefresh_ip"],
"autorefreshPort": _config["system_config"]["autorefresh_port"],
};
return Config;

View File

@ -811,7 +811,7 @@ define(function(require) {
return context.data("element");
};
var _insertPanels = function(tabName, info, contextTabId, context) {
var _insertPanels = function(tabName, info, contextTabId, context, autorefresh=false) {
var context = context || $(".sunstone-info", $("#" + tabName));
context.data("element", info[Object.keys(info)[0]]);
@ -885,10 +885,12 @@ define(function(require) {
context.html(html);
$.each(SunstoneCfg["tabs"][tabName]["panelInstances"], function(panelName, panel) {
panel.setup(context);
if (!autorefresh || panelName == "vm_info_tab"){
panel.setup(context);
if(isRefresh && prevPanelStates[panelName] && panel.setState){
panel.setState( prevPanelStates[panelName], context );
if(isRefresh && prevPanelStates[panelName] && panel.setState){
panel.setState( prevPanelStates[panelName], context );
}
}
});
@ -914,6 +916,11 @@ define(function(require) {
}
};
var _autorefreshVM = function(tabName, info, contextTabId, context) {
_insertPanels(tabName, info, contextTabId, context, true);
};
//Runs a predefined action. Wraps the calls to opennebula.js and
//can be use to run action depending on conditions and notify them
//if desired. Returns 1 if some problem has been detected: i.e
@ -1358,6 +1365,7 @@ define(function(require) {
"insertTabs": _insertTabs,
"insertPanels": _insertPanels,
"autorefreshVM": _autorefreshVM,
"getElementRightInfo": _getElementRightInfo,
"showTab": _showTab,

View File

@ -27,6 +27,7 @@ define(function(require) {
var TemplateTableVcenter = require("utils/panel/template-table");
var OpenNebula = require("opennebula");
var Navigation = require("utils/navigation");
var Websocket = require("utils/websocket");
/*
TEMPLATES
@ -169,5 +170,8 @@ define(function(require) {
}
TemplateTable.setup(strippedTemplate, RESOURCE, this.element.ID, context, unshownValues, strippedTemplateVcenter);
TemplateTableVcenter.setup(strippedTemplateVcenter, RESOURCE, this.element.ID, context, unshownValues, strippedTemplate);
Websocket.subscribe(this.element.ID);
}
});

View File

@ -33,12 +33,12 @@
{{{renameTrHTML}}}
<tr>
<td class="key_td">{{tr "State"}}</td>
<td class="value_td">{{stateStr}}</td>
<td id="state_value" class="value_td">{{stateStr}}</td>
<td></td>
</tr>
<tr>
<td class="key_td">{{tr "LCM State"}}</td>
<td class="value_td">{{lcmStateStr}}</td>
<td id="lcm_state_value" class="value_td">{{lcmStateStr}}</td>
<td></td>
</tr>
<tr>

View File

@ -0,0 +1,116 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2020, OpenNebula Project, OpenNebula Systems */
/* */
/* 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. */
/* -------------------------------------------------------------------------- */
define(function (require) {
var Config = require("sunstone-config");
var Sunstone = require('sunstone');
// user config
const wss = Config.autorefreshWSS || 'ws';
const port = Config.autorefreshPort || 2346;
const host = Config.autorefreshIP || '127.0.0.1';
var address = wss + "://" + host + ":" + port;
var ws = new WebSocket(address);
var csrftoken;
var _start = function () {
ws.addEventListener('open', function (event) {
//console.log("Connected to websocket");
ws.readyState = 1;
// Send CSRF token
var msg = {
"STATE": ws.readyState,
"ACTION": "authenticate",
"DATA": {
"csrf-token": csrftoken,
},
}
ws.send(JSON.stringify(msg));
});
// Listen for messages
ws.addEventListener('message', function (event) {
var vm_info = JSON.parse(event.data);
// console.log(vm_info);
var response = { "VM": vm_info.HOOK_MESSAGE.VM };
var request = {
"request": {
"data": [response.ID],
"method": "show",
"resource": "VM"
}
}
// update VM
var TAB_ID = "vms-tab";
var tab = $('#' + TAB_ID);
Sunstone.getDataTable(TAB_ID).updateElement(request, response);
if (Sunstone.rightInfoVisible(tab) && vm_info.HOOK_MESSAGE.RESOURCE_ID == Sunstone.rightInfoResourceId(tab)) {
Sunstone.autorefreshVM(TAB_ID, response);
}
if (vm_info.HOOK_MESSAGE.STATE == "DONE"){
Sunstone.getDataTable(TAB_ID).waitingNodes();
Sunstone.runAction("VM.list", {force: true});
}
});
// Close Socket when close browser or tab.
window.onbeforeunload = function () {
_close();
};
};
var _subscribe = function (vm_id, context) {
var msg = {
"SUBSCRIBE": true,
"VM": vm_id
}
ws.send(JSON.stringify(msg));
};
var _unsubscribe = function (vm_id) {
var msg = {
"SUBSCRIBE": false,
"VM": vm_id
}
ws.send(JSON.stringify(msg));
};
var _close = function () {
ws.onclose = function () { }; // disable onclose handler first
ws.close()
};
var websocket = {
"start": _start,
"subscribe": _subscribe,
"unsubscribe": _unsubscribe,
"close": _close
};
return websocket;
});

View File

@ -0,0 +1,123 @@
# -------------------------------------------------------------------------- #
# Copyright 2002-2020, OpenNebula Project, OpenNebula Systems #
# #
# 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. #
#--------------------------------------------------------------------------- #
require 'faye/websocket'
require 'eventmachine'
require 'json'
require 'active_support/core_ext/hash'
require 'ffi-rzmq'
require 'base64'
##############################################################################
# Global Variables
##############################################################################
@context = ZMQ::Context.new(1)
@subscriber = @context.socket(ZMQ::SUB)
@clients = []
@zeromq_server = ""
KEEPALIVE_TIME = 15
CONFIGURATION_FILE = ETC_LOCATION + '/sunstone-server.conf'
##############################################################################
# Methods
##############################################################################
# Reads the configuration file and creates the zeromq server ip
def get_zeroMQ_server_ip()
begin
$conf = YAML.load_file(CONFIGURATION_FILE)
rescue Exception => e
STDERR.puts "Error parsing config file #{CONFIGURATION_FILE}: #{e.message}"
exit 1
end
puts $conf[:zeromq_server]
@zeromq_server = $conf[:zeromq_server]
end
# Configures the ZeroMQ connection to recieve `event` notifications
def configure_zeroMQ(event="VM")
@subscriber.setsockopt(ZMQ::SUBSCRIBE, "EVENT #{event}")
@subscriber.connect(@zeromq_server)
puts "Subscribed to #{event}"
end
# Broadcast event to all clients
def broadcast_message(message)
@clients.each do |client|
client.send(message)
end
end
# Gets the ZeroMQ incomming messages and broadcast
# them to all clients connected
def get_zeroMQ_messages()
key = ''
content = ''
@subscriber.recv_string(key)
@subscriber.recv_string(content)
mensaje = Hash.from_xml(Base64.decode64(content)).to_json
puts "key: #{key}"
if (key != '')
broadcast_message(mensaje)
end
end
##############################################################################
# Server
##############################################################################
get_zeroMQ_server_ip()
configure_zeroMQ()
# Create a thread to get ZeroMQ messages
Thread.new do
loop do
get_zeroMQ_messages()
end
end
Autorefresh = lambda do |env|
if Faye::WebSocket.websocket?(env)
ws = Faye::WebSocket.new(env, nil, {ping: KEEPALIVE_TIME })
ws.on :open do |event|
puts "New client registered: #{ws.object_id}"
@clients << ws
end
ws.on :message do |event|
puts "New message received: #{event.data}"
end
ws.on :close do |event|
puts "Client #{ws.object_id} disconnected. Reason: #{event.reason}"
@clients.delete(ws)
end
# Return async Rack response
ws.rack_response
else
# Normal HTTP request
[401, { 'Content-Type' => 'text/plain' }, ['Unauthorized']]
end
end

View File

@ -0,0 +1,35 @@
# -------------------------------------------------------------------------- #
# Copyright 2002-2020, OpenNebula Project, OpenNebula Systems #
# #
# 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
ETC_LOCATION = '/etc/one'
SUNSTONE_LOCATION = '/usr/lib/one/sunstone'
else
ETC_LOCATION = ONE_LOCATION + '/etc'
SUNSTONE_LOCATION = ONE_LOCATION + '/lib/sunstone'
end
SUNSTONE_SERVICES = SUNSTONE_LOCATION + '/services'
require SUNSTONE_SERVICES + '/autorefresh/autorefresh-server'
Faye::WebSocket.load_adapter('thin')
run Autorefresh

View File

@ -262,6 +262,16 @@ configure do
set :erb, :trim => '-'
end
#start Autorefresh server
$autorefresh = OpenNebulaAutorefresh.new($conf, logger)
configure do
set :run, false
set :autorefresh, $autorefresh
set :erb, :trim => '-'
end
$addons = OpenNebulaAddons.new(logger)
DEFAULT_TABLE_ORDER = "desc"
@ -462,6 +472,9 @@ helpers do
session[:default_view] = $views_config.available_views(session[:user], session[:user_gname]).first
end
autorefresh_wss = $conf[:autorefresh_support_wss]
session[:autorefresh_wss] = autorefresh_wss == 'yes'? 'wss' : 'ws'
# end user options
# secure cookies

View File

@ -53,7 +53,11 @@
'max_upload_file_size' : <%= $conf[:max_upload_file_size] ? $conf[:max_upload_file_size] : "undefined" %>,
'leases' : <%= $conf[:leases] ? $conf[:leases].to_json : "null" %>,
'mapped_ips' : '<%= $conf[:mapped_ips] ? $conf[:mapped_ips] : false %>',
'get_extended_vm_info': '<%= $conf[:get_extended_vm_info] ? $conf[:get_extended_vm_info] : false %>'
'get_extended_vm_info': '<%= $conf[:get_extended_vm_info] ? $conf[:get_extended_vm_info] : false %>',
'autorefresh_wss': '<%= session[:autorefresh_wss] %>',
'autorefresh_ip': '<%= $conf[:autorefresh_ip] %>',
'autorefresh_port': '<%= $conf[:autorefresh_port] %>',
},
'view' : view,
'available_views' : available_views,