1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-03-25 02:50:08 +03:00

Merged Feature #495 branch

This commit is contained in:
Jaime Melis 2011-02-24 14:46:37 +01:00
commit 900892901c
49 changed files with 555 additions and 219 deletions

4
NOTICE
View File

@ -7,8 +7,8 @@ documentation at www.OpenNebula.org
AUTHORS
- Ruben Santiago Montero (rubensm@dacya.ucm.es)
- Ignacio Martin Llorente (llorente@dacya.ucm.es)
- Ruben Santiago Montero (rsmontero@opennebula.org)
- Ignacio Martin Llorente (imllorente@opennebula.org)
ACKNOWLEDGEMENTS

View File

@ -40,6 +40,7 @@ usage() {
echo "-d: target installation directory, if not defined it'd be root. Must be"
echo " an absolute path."
echo "-c: install client utilities: OpenNebula cli, occi and ec2 client files"
echo "-s: install OpenNebula Sunstone"
echo "-r: remove Opennebula, only useful if -d was not specified, otherwise"
echo " rm -rf \$ONE_LOCATION would do the job"
echo "-l: creates symlinks instead of copying files, useful for development"
@ -47,7 +48,7 @@ usage() {
}
#-------------------------------------------------------------------------------
TEMP_OPT=`getopt -o hkrlcu:g:d: -n 'install.sh' -- "$@"`
TEMP_OPT=`getopt -o hkrlcsu:g:d: -n 'install.sh' -- "$@"`
if [ $? != 0 ] ; then
usage
@ -60,6 +61,7 @@ INSTALL_ETC="yes"
UNINSTALL="no"
LINK="no"
CLIENT="no"
SUNSTONE="no"
ONEADMIN_USER=`id -u`
ONEADMIN_GROUP=`id -g`
SRC_DIR=$PWD
@ -70,7 +72,8 @@ while true ; do
-k) INSTALL_ETC="no" ; shift ;;
-r) UNINSTALL="yes" ; shift ;;
-l) LINK="yes" ; shift ;;
-c) CLIENT="yes" ; shift ;;
-c) CLIENT="yes"; INSTALL_ETC="no" ; shift ;;
-s) SUNSTONE="yes"; INSTALL_ETC="no" ; shift ;;
-u) ONEADMIN_USER="$2" ; shift 2;;
-g) ONEADMIN_GROUP="$2"; shift 2;;
-d) ROOT="$2" ; shift 2 ;;
@ -89,6 +92,7 @@ if [ -z "$ROOT" ] ; then
ETC_LOCATION="/etc/one"
LOG_LOCATION="/var/log/one"
VAR_LOCATION="/var/lib/one"
SUNSTONE_LOCATION="$LIB_LOCATION/sunstone"
IMAGES_LOCATION="$VAR_LOCATION/images"
RUN_LOCATION="/var/run/one"
LOCK_LOCATION="/var/lock/one"
@ -96,7 +100,19 @@ if [ -z "$ROOT" ] ; then
SHARE_LOCATION="/usr/share/one"
MAN_LOCATION="/usr/share/man/man8"
if [ "$CLIENT" = "no" ]; then
if [ "$CLIENT" = "yes" ]; then
MAKE_DIRS="$BIN_LOCATION $LIB_LOCATION"
DELETE_DIRS=""
CHOWN_DIRS=""
elif [ "$SUNSTONE" = "yes" ]; then
MAKE_DIRS="$BIN_LOCATION $LIB_LOCATION $VAR_LOCATION $SUNSTONE_LOCATION"
DELETE_DIRS="$MAKE_DIRS"
CHOWN_DIRS=""
else
MAKE_DIRS="$BIN_LOCATION $LIB_LOCATION $ETC_LOCATION $VAR_LOCATION \
$INCLUDE_LOCATION $SHARE_LOCATION \
$LOG_LOCATION $RUN_LOCATION $LOCK_LOCATION \
@ -106,12 +122,6 @@ if [ -z "$ROOT" ] ; then
$RUN_LOCATION $SHARE_DIRS"
CHOWN_DIRS="$LOG_LOCATION $VAR_LOCATION $RUN_LOCATION $LOCK_LOCATION"
else
MAKE_DIRS="$BIN_LOCATION $LIB_LOCATION"
DELETE_DIRS=""
CHOWN_DIRS=""
fi
else
@ -119,12 +129,21 @@ else
LIB_LOCATION="$ROOT/lib"
ETC_LOCATION="$ROOT/etc"
VAR_LOCATION="$ROOT/var"
SUNSTONE_LOCATION="$LIB_LOCATION/sunstone"
IMAGES_LOCATION="$VAR_LOCATION/images"
INCLUDE_LOCATION="$ROOT/include"
SHARE_LOCATION="$ROOT/share"
MAN_LOCATION="$ROOT/share/man/man8"
if [ "$CLIENT" = "no" ]; then
if [ "$CLIENT" = "yes" ]; then
MAKE_DIRS="$BIN_LOCATION $LIB_LOCATION"
DELETE_DIRS="$MAKE_DIRS"
elif [ "$SUNSTONE" = "yes" ]; then
MAKE_DIRS="$BIN_LOCATION $LIB_LOCATION $VAR_LOCATION $SUNSTONE_LOCATION"
DELETE_DIRS="$MAKE_DIRS"
else
MAKE_DIRS="$BIN_LOCATION $LIB_LOCATION $ETC_LOCATION $VAR_LOCATION \
$INCLUDE_LOCATION $SHARE_LOCATION $IMAGES_LOCATION \
$MAN_LOCATION"
@ -132,10 +151,6 @@ else
DELETE_DIRS="$MAKE_DIRS"
CHOWN_DIRS="$ROOT"
else
MAKE_DIRS="$BIN_LOCATION $LIB_LOCATION"
DELETE_DIRS="$MAKE_DIRS"
fi
CHOWN_DIRS="$ROOT"
@ -188,6 +203,16 @@ VAR_DIRS="$VAR_LOCATION/remotes \
$VAR_LOCATION/remotes/vmm/xen \
$VAR_LOCATION/remotes/vmm/kvm"
SUNSTONE_DIRS="$SUNSTONE_LOCATION/models \
$SUNSTONE_LOCATION/models/OpenNebulaJSON \
$SUNSTONE_LOCATION/public \
$SUNSTONE_LOCATION/public/js \
$SUNSTONE_LOCATION/public/js/vendor \
$SUNSTONE_LOCATION/public/css \
$SUNSTONE_LOCATION/public/css/vendor \
$SUNSTONE_LOCATION/public/images \
$SUNSTONE_LOCATION/templates"
LIB_ECO_CLIENT_DIRS="$LIB_LOCATION/ruby \
$LIB_LOCATION/ruby/OpenNebula \
$LIB_LOCATION/ruby/cloud/ \
@ -197,14 +222,19 @@ LIB_OCCI_CLIENT_DIRS="$LIB_LOCATION/ruby \
$LIB_LOCATION/ruby/OpenNebula \
$LIB_LOCATION/ruby/cloud/occi"
LIB_OCA_CLIENT_DIRS="$LIB_LOCATION/ruby \
$LIB_LOCATION/ruby/OpenNebula"
LIB_CLI_DIRS="$LIB_LOCATION/ruby \
$LIB_LOCATION/ruby/OpenNebula"
if [ "$CLIENT" = "no" ]; then
MAKE_DIRS="$MAKE_DIRS $SHARE_DIRS $ETC_DIRS $LIB_DIRS $VAR_DIRS"
else
if [ "$CLIENT" = "yes" ]; then
MAKE_DIRS="$MAKE_DIRS $LIB_ECO_CLIENT_DIRS $LIB_OCCI_CLIENT_DIRS \
$LIB_CLI_DIRS"
elif [ "$SUNSTONE" = "yes" ]; then
MAKE_DIRS="$MAKE_DIRS $SUNSTONE_DIRS $LIB_OCA_CLIENT_DIRS"
else
MAKE_DIRS="$MAKE_DIRS $SHARE_DIRS $ETC_DIRS $LIB_DIRS $VAR_DIRS $SUNSTONE_DIRS"
fi
#-------------------------------------------------------------------------------
@ -267,6 +297,24 @@ INSTALL_CLIENT_FILES=(
RUBY_OPENNEBULA_LIB_FILES:$LIB_LOCATION/ruby/OpenNebula
)
INSTALL_SUNSTONE_RUBY_FILES=(
SUNSTONE_RUBY_LIB_FILES:$LIB_LOCATION/ruby
RUBY_OPENNEBULA_LIB_FILES:$LIB_LOCATION/ruby/OpenNebula
)
INSTALL_SUNSTONE_FILES=(
SUNSTONE_FILES:$SUNSTONE_LOCATION
SUNSTONE_BIN_FILES:$BIN_LOCATION
SUNSTONE_MODELS_FILES:$SUNSTONE_LOCATION/models
SUNSTONE_MODELS_JSON_FILES:$SUNSTONE_LOCATION/models/OpenNebulaJSON
SUNSTONE_TEMPLATE_FILES:$SUNSTONE_LOCATION/templates
SUNSTONE_PUBLIC_JS_FILES:$SUNSTONE_LOCATION/public/js
SUNSTONE_PUBLIC_JS_VENDOR_FILES:$SUNSTONE_LOCATION/public/js/vendor
SUNSTONE_PUBLIC_CSS_FILES:$SUNSTONE_LOCATION/public/css
SUNSTONE_PUBLIC_CSS_VENDOR_FILES:$SUNSTONE_LOCATION/public/css/vendor
SUNSTONE_PUBLIC_IMAGES_FILES:$SUNSTONE_LOCATION/public/images
)
INSTALL_ETC_FILES=(
ETC_FILES:$ETC_LOCATION
VMM_EC2_ETC_FILES:$ETC_LOCATION/vmm_ec2
@ -646,6 +694,80 @@ CLI_BIN_FILES="src/cli/onevm \
src/cli/oneimage \
src/cli/onecluster"
#-----------------------------------------------------------------------------
# Sunstone files
#-----------------------------------------------------------------------------
SUNSTONE_FILES="src/sunstone/config.ru \
src/sunstone/sunstone-server.rb"
SUNSTONE_BIN_FILES="src/sunstone/bin/sunstone-server"
SUNSTONE_MODELS_FILES="src/sunstone/models/OpenNebulaJSON.rb \
src/sunstone/models/SunstoneServer.rb"
SUNSTONE_MODELS_JSON_FILES="src/sunstone/models/OpenNebulaJSON/ClusterJSON.rb \
src/sunstone/models/OpenNebulaJSON/HostJSON.rb \
src/sunstone/models/OpenNebulaJSON/ImageJSON.rb \
src/sunstone/models/OpenNebulaJSON/JSONUtils.rb \
src/sunstone/models/OpenNebulaJSON/PoolJSON.rb \
src/sunstone/models/OpenNebulaJSON/UserJSON.rb \
src/sunstone/models/OpenNebulaJSON/VirtualMachineJSON.rb \
src/sunstone/models/OpenNebulaJSON/VirtualNetworkJSON.rb"
SUNSTONE_TEMPLATE_FILES="src/sunstone/templates/index.html \
src/sunstone/templates/login.html"
SUNSTONE_PUBLIC_JS_FILES="src/sunstone/public/js/layout.js \
src/sunstone/public/js/login.js \
src/sunstone/public/js/one-ui_views.js \
src/sunstone/public/js/one-ui_views.templates.js \
src/sunstone/public/js/opennebula.js"
SUNSTONE_PUBLIC_JS_VENDOR_FILES="src/sunstone/public/js/vendor/base64.js \
src/sunstone/public/js/vendor/jquery-1.4.4.min.js \
src/sunstone/public/js/vendor/jquery.dataTables.min.js \
src/sunstone/public/js/vendor/jquery.jgrowl_minimized.js \
src/sunstone/public/js/vendor/jquery.layout.min-1.2.0.js \
src/sunstone/public/js/vendor/jquery-ui-1.8.7.custom.min.js"
SUNSTONE_PUBLIC_CSS_FILES="src/sunstone/public/css/application.css \
src/sunstone/public/css/demo_table_jui.css \
src/sunstone/public/css/jquery.jgrowl.css \
src/sunstone/public/css/layout.css \
src/sunstone/public/css/layout-default-latest.css \
src/sunstone/public/css/login.css"
SUNSTONE_PUBLIC_CSS_VENDOR_FILES="\
src/sunstone/public/css/vendor/jquery-ui-1.8.7.custom.css \
src/sunstone/public/css/vendor/ui-bg_flat_0_575c5b_40x100.png \
src/sunstone/public/css/vendor/ui-bg_flat_0_8f9392_40x100.png \
src/sunstone/public/css/vendor/ui-bg_flat_0_aaaaaa_40x100.png \
src/sunstone/public/css/vendor/ui-bg_flat_75_ffffff_40x100.png \
src/sunstone/public/css/vendor/ui-bg_glass_55_fbf9ee_1x400.png \
src/sunstone/public/css/vendor/ui-bg_glass_65_ffffff_1x400.png \
src/sunstone/public/css/vendor/ui-bg_glass_75_dadada_1x400.png \
src/sunstone/public/css/vendor/ui-bg_glass_75_e6e6e6_1x400.png \
src/sunstone/public/css/vendor/ui-bg_glass_95_fef1ec_1x400.png \
src/sunstone/public/css/vendor/ui-bg_highlight-soft_75_cccccc_1x100.png \
src/sunstone/public/css/vendor/ui-icons_222222_256x240.png \
src/sunstone/public/css/vendor/ui-icons_2e83ff_256x240.png \
src/sunstone/public/css/vendor/ui-icons_454545_256x240.png \
src/sunstone/public/css/vendor/ui-icons_888888_256x240.png \
src/sunstone/public/css/vendor/ui-icons_cd0a0a_256x240.png"
SUNSTONE_PUBLIC_IMAGES_FILES="src/sunstone/public/images/ajax-loader.gif \
src/sunstone/public/images/login_over.png \
src/sunstone/public/images/login.png \
src/sunstone/public/images/opennebula-sunstone-big.png \
src/sunstone/public/images/opennebula-sunstone-small.png \
src/sunstone/public/images/panel.png \
src/sunstone/public/images/pbar.gif \
src/sunstone/public/images/Refresh-icon.png"
SUNSTONE_RUBY_LIB_FILES="src/mad/ruby/CommandManager.rb \
src/oca/ruby/OpenNebula.rb"
#-----------------------------------------------------------------------------
# MAN files
#-----------------------------------------------------------------------------
@ -696,10 +818,12 @@ do_file() {
}
if [ "$CLIENT" = "no" ]; then
INSTALL_SET=${INSTALL_FILES[@]}
else
if [ "$CLIENT" = "yes" ]; then
INSTALL_SET=${INSTALL_CLIENT_FILES[@]}
elif [ "$SUNSTONE" = "yes" ]; then
INSTALL_SET="${INSTALL_SUNSTONE_RUBY_FILES[@]} ${INSTALL_SUNSTONE_FILES[@]}"
else
INSTALL_SET="${INSTALL_FILES[@]} ${INSTALL_SUNSTONE_FILES[@]}"
fi
for i in ${INSTALL_SET[@]}; do
@ -713,7 +837,7 @@ for i in ${INSTALL_SET[@]}; do
done
done
if [ "$CLIENT" = "no" -a "$INSTALL_ETC" = "yes" ] ; then
if [ "$INSTALL_ETC" = "yes" ] ; then
for i in ${INSTALL_ETC_FILES[@]}; do
SRC=$`echo $i | cut -d: -f1`
DST=`echo $i | cut -d: -f2`

124
src/sunstone/bin/sunstone-server Executable file
View File

@ -0,0 +1,124 @@
#!/bin/bash
# -------------------------------------------------------------------------- #
# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) #
# #
# 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. #
#--------------------------------------------------------------------------- #
if [ -z "$ONE_LOCATION" ]; then
SUNSTONE_PID=/var/run/one/sunstone.pid
SUNSTONE_SERVER=/usr/lib/one/sunstone/config.ru
SUNSTONE_LOCK_FILE=/var/lock/one/.sunstone.lock
SUNSTONE_LOG=/var/log/one/sunstone.log
else
SUNSTONE_PID=$ONE_LOCATION/var/sunstone.pid
SUNSTONE_SERVER=$ONE_LOCATION/lib/sunstone/config.ru
SUNSTONE_LOCK_FILE=$ONE_LOCATION/var/.sunstone.lock
SUNSTONE_LOG=$ONE_LOCATION/var/sunstone.log
fi
PORT="4567"
HOST="127.0.0.1"
usage() {
echo
echo "Usage: sunstone-server [-H host] [-p port]"
echo
echo "-H: Host for the Sunstone server, default value: localhost"
echo "-p: Port for incoming connections, default value: 4567"
}
setup()
{
if [ -f $SUNSTONE_LOCK_FILE ]; then
if [ -f $SUNSTONE_PID ]; then
SUNSTONEPID=`cat $SUNSTONE_PID`
ps $SUNSTONEPID &> /dev/null
if [ $? -eq 0 ]; then
echo "Sunstone Server is still running (PID:$SUNSTONEPID). Please try 'sunstone-server stop' first."
exit 1
fi
fi
echo "Stale .lock detected. Erasing it."
rm $SUNSTONE_LOCK_FILE
fi
}
start()
{
if [ ! -f "$SUNSTONE_SERVER" ]; then
echo "Can not find $SUNSTONE_SERVER."
exit 1
fi
# Start the sunstone daemon
touch $SUNSTONE_LOCK_FILE
rackup $SUNSTONE_SERVER -s thin -p $PORT -o $HOST -P $SUNSTONE_PID &> $SUNSTONE_LOG &
LASTRC=$?
if [ $LASTRC -ne 0 ]; then
echo "Error executing $SUNSTONE_SERVER"
exit 1
fi
sleep 1
ps $LASTPID &> /dev/null
if [ $? -ne 0 ]; then
echo "Error executing $SUNSTONE_SERVER."
exit 1
fi
echo "sunstone-server started"
}
#
# Function that stops the daemon/service
#
stop()
{
if [ ! -f $SUNSTONE_PID ]; then
echo "Couldn't find sunstone-server process pid."
exit 1
fi
# Kill the sunstone daemon
kill -INT `cat $SUNSTONE_PID` &> /dev/null
# Remove pid files
rm -f $SUNSTONE_LOCK_FILE &> /dev/null
echo "sunstone-server stopped"
}
while getopts "p:H:" OPTION
do
case $OPTION in
p) PORT=$OPTARG;;
H) HOST=$OPTARG;;
*) usage; exit 3;;
esac
done
shift $((OPTIND-1))
case "$1" in
start) setup; start;;
stop) stop;;
*) usage; exit 3;;
esac

View File

@ -19,6 +19,6 @@
# TBD Change path for intallation tree
$: << File.dirname(__FILE__)
require 'one-ui.rb'
require 'sunstone-server.rb'
run Sinatra::Application

View File

@ -14,33 +14,28 @@
# limitations under the License. #
#--------------------------------------------------------------------------- #
ONE_LOCATION = ENV["ONE_LOCATION"]
ONE_LOCATION = ENV["ONE_LOCATION"] if !ONE_LOCATION
if !ONE_LOCATION
RUBY_LIB_LOCATION = "/usr/lib/one/ruby"
VAR_LOCATION = "/var/lib/one"
else
RUBY_LIB_LOCATION = ONE_LOCATION+"/lib/ruby"
VAR_LOCATION = ONE_LOCATION+"/var"
end
$: << RUBY_LIB_LOCATION
$: << File.dirname(__FILE__)
require 'OpenNebula'
include OpenNebula
# TBD Change path for intallation tree
#require 'OpenNebulaJSON/PoolJSON'
#require 'OpenNebulaJSON/HostJSON'
#require 'OpenNebulaJSON/JSONUtils'
require 'models/OpenNebulaJSON/ClusterJSON'
require 'models/OpenNebulaJSON/HostJSON'
require 'models/OpenNebulaJSON/ImageJSON'
require 'models/OpenNebulaJSON/JSONUtils'
require 'models/OpenNebulaJSON/PoolJSON'
require 'models/OpenNebulaJSON/UserJSON'
require 'models/OpenNebulaJSON/VirtualMachineJSON'
require 'models/OpenNebulaJSON/VirtualNetworkJSON'
require 'OpenNebulaJSON/ClusterJSON'
require 'OpenNebulaJSON/HostJSON'
require 'OpenNebulaJSON/ImageJSON'
require 'OpenNebulaJSON/JSONUtils'
require 'OpenNebulaJSON/PoolJSON'
require 'OpenNebulaJSON/UserJSON'
require 'OpenNebulaJSON/VirtualMachineJSON'
require 'OpenNebulaJSON/VirtualNetworkJSON'
module OpenNebula
class Error

View File

@ -14,7 +14,7 @@
# limitations under the License. #
#--------------------------------------------------------------------------- #
require 'models/OpenNebulaJSON/JSONUtils'
require 'OpenNebulaJSON/JSONUtils'
module OpenNebulaJSON
class ClusterJSON < OpenNebula::Cluster

View File

@ -14,7 +14,7 @@
# limitations under the License. #
#--------------------------------------------------------------------------- #
require 'models/OpenNebulaJSON/JSONUtils'
require 'OpenNebulaJSON/JSONUtils'
module OpenNebulaJSON
class HostJSON < OpenNebula::Host

View File

@ -14,7 +14,7 @@
# limitations under the License. #
#--------------------------------------------------------------------------- #
require 'models/OpenNebulaJSON/JSONUtils'
require 'OpenNebulaJSON/JSONUtils'
module OpenNebulaJSON
class ImageJSON < OpenNebula::Image

View File

@ -14,7 +14,7 @@
# limitations under the License. #
#--------------------------------------------------------------------------- #
require 'models/OpenNebulaJSON/JSONUtils'
require 'OpenNebulaJSON/JSONUtils'
module OpenNebulaJSON
class HostPoolJSON < OpenNebula::HostPool; include JSONUtils; end

View File

@ -14,7 +14,7 @@
# limitations under the License. #
#--------------------------------------------------------------------------- #
require 'models/OpenNebulaJSON/JSONUtils'
require 'OpenNebulaJSON/JSONUtils'
module OpenNebulaJSON
class UserJSON < OpenNebula::User

View File

@ -14,7 +14,7 @@
# limitations under the License. #
#--------------------------------------------------------------------------- #
require 'models/OpenNebulaJSON/JSONUtils'
require 'OpenNebulaJSON/JSONUtils'
module OpenNebulaJSON
class VirtualMachineJSON < OpenNebula::VirtualMachine
@ -45,14 +45,14 @@ module OpenNebulaJSON
when "deploy" then self.deploy(action_hash['params'])
when "finalize" then self.finalize
when "hold" then self.hold
when "live_migrate" then self.live_migrate(action_hash['params'])
when "livemigrate" then self.live_migrate(action_hash['params'])
when "migrate" then self.migrate(action_hash['params'])
when "resume" then self.resume
when "release" then self.release
when "stop" then self.stop
when "suspend" then self.suspend
when "restart" then self.restart
when "save_as" then self.save_as(action_hash['params'])
when "saveas" then self.save_as(action_hash['params'])
when "shutdown" then self.shutdown
else
error_msg = "#{action_hash['perform']} action not " <<

View File

@ -14,7 +14,7 @@
# limitations under the License. #
#--------------------------------------------------------------------------- #
require 'models/OpenNebulaJSON/JSONUtils'
require 'OpenNebulaJSON/JSONUtils'
module OpenNebulaJSON
class VirtualNetworkJSON < OpenNebula::VirtualNetwork

View File

@ -14,13 +14,20 @@
# limitations under the License. #
#--------------------------------------------------------------------------- #
# TBD Change path for intallation tree
ONE_LOCATION = ENV["ONE_LOCATION"]
if !ONE_LOCATION
LOG_LOCATION = "/var/log/one"
VAR_LOCATION = "/var/lib/one"
else
VAR_LOCATION = ONE_LOCATION+"/var"
LOG_LOCATION = ONE_LOCATION+"/var"
end
#require 'OpenNebulaJSON'
require 'models/OpenNebulaJSON'
include OpenNebulaJSON
class OneUI
class SunstoneServer
def initialize(username, password)
# TBD one_client_user(name) from CloudServer
@client = Client.new("dummy:dummy")
@ -53,9 +60,8 @@ class OneUI
############################################################################
#
############################################################################
def get_pool(kind, user_id)
user_flag = user_id=="0" ? -2 : -1
def get_pool(kind)
user_flag = -1
pool = case kind
when "cluster" then ClusterPoolJSON.new(@client)
when "host" then HostPoolJSON.new(@client)
@ -150,7 +156,11 @@ class OneUI
############################################################################
#
############################################################################
def get_configuration
def get_configuration(user_id)
if user_id != "0"
return [401, ""]
end
one_config = VAR_LOCATION + "/config"
config = Hash.new
@ -178,17 +188,24 @@ class OneUI
#
############################################################################
def get_vm_log(id)
id = id.to_s
vm_log_file = VAR_LOCATION + "/#{id}/vm.log"
resource = retrieve_resource("vm", id)
if OpenNebula.is_error?(resource)
return [404, nil]
else
if !ONE_LOCATION
vm_log_file = LOG_LOCATION + "/#{id}.log"
else
vm_log_file = LOG_LOCATION + "/#{id}/vm.log"
end
begin
log = File.read(vm_log_file)
rescue Exception => e
error = Error.new("Error: log for VM #{id} not available")
return [500, error.to_s]
begin
log = File.read(vm_log_file)
rescue Exception => e
return [200, "Log for VM #{id} not available"]
end
return [200, log]
end
return [200, log]
end
private

View File

@ -21,20 +21,20 @@ body {
p{
margin:0 10px 10px;
}
a {
color: #000C96; text-decoration: none;
a {
color: #000C96; text-decoration: none;
}
a:hover {
color: #127FE4; text-decoration: none;
a:hover {
color: #127FE4; text-decoration: none;
}
select, button {
padding: 2px;
select, button {
padding: 2px;
}
h2 {
float:left;
font-size:20px;
margin-bottom: 5px;
h2 {
float:left;
font-size:20px;
margin-bottom: 5px;
padding-bottom: 0}
h3 {
@ -296,7 +296,7 @@ textarea:focus{
}
.remove_button {
}
tr.odd, tr.even {
@ -480,6 +480,8 @@ tr.even:hover{
cursor: pointer;
}
.ui-widget-overlay { background: #353735; opacity: .60; filter:Alpha(Opacity=60); }
.ui-tabs .ui-tabs-nav li a {
/*padding: .5em 1em;*/
padding: .3em 1em;

0
src/sunstone/public/css/jquery.jgrowl.css Executable file → Normal file
View File

0
src/sunstone/public/css/layout.css Executable file → Normal file
View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

View File

@ -59,26 +59,26 @@
/*.ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; }
.ui-widget .ui-widget { font-size: 1em; }*/
/*.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; }*/
.ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; }
.ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; }
.ui-widget-content a { color: #222222; }
.ui-widget-header { border: 1px solid #aaaaaa; background: #cccccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; }
.ui-widget-header { border: 1px solid #aaaaaa; background: #cccccc url(ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; }
.ui-widget-header a { color: #222222; }
/* Interaction states
----------------------------------*/
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #555555; }
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 url(ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #555555; }
.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555; text-decoration: none; }
.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999; background: #dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; }
.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999; background: #dadada url(ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; }
.ui-state-hover a, .ui-state-hover a:hover { color: #212121; text-decoration: none; }
.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; }
.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; }
.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; text-decoration: none; }
.ui-widget :active { outline: none; }
/* Interaction Cues
----------------------------------*/
.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; }
.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; }
.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; }
.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; }
.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; }
.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; }
.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; }
.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
@ -89,14 +89,14 @@
----------------------------------*/
/* states and images */
.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); }
.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
.ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
.ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png); }
.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
.ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); }
.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); }
.ui-icon { width: 16px; height: 16px; background-image: url(ui-icons_222222_256x240.png); }
.ui-widget-content .ui-icon {background-image: url(ui-icons_222222_256x240.png); }
.ui-widget-header .ui-icon {background-image: url(ui-icons_222222_256x240.png); }
.ui-state-default .ui-icon { background-image: url(ui-icons_888888_256x240.png); }
.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(ui-icons_454545_256x240.png); }
.ui-state-active .ui-icon {background-image: url(ui-icons_454545_256x240.png); }
.ui-state-highlight .ui-icon {background-image: url(ui-icons_2e83ff_256x240.png); }
.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(ui-icons_cd0a0a_256x240.png); }
/* positioning */
.ui-icon-carat-1-n { background-position: 0 0; }
@ -291,8 +291,8 @@
.ui-corner-all { -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; }
/* Overlays */
.ui-widget-overlay { background: #575c5b url(images/ui-bg_flat_0_575c5b_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); }
.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/*
.ui-widget-overlay { background: #575c5b url(ui-bg_flat_0_575c5b_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); }
.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/*
* jQuery UI Resizable 1.8.7
*
* Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)

View File

Before

Width:  |  Height:  |  Size: 224 B

After

Width:  |  Height:  |  Size: 224 B

View File

Before

Width:  |  Height:  |  Size: 224 B

After

Width:  |  Height:  |  Size: 224 B

View File

Before

Width:  |  Height:  |  Size: 180 B

After

Width:  |  Height:  |  Size: 180 B

View File

Before

Width:  |  Height:  |  Size: 178 B

After

Width:  |  Height:  |  Size: 178 B

View File

Before

Width:  |  Height:  |  Size: 120 B

After

Width:  |  Height:  |  Size: 120 B

View File

Before

Width:  |  Height:  |  Size: 105 B

After

Width:  |  Height:  |  Size: 105 B

View File

Before

Width:  |  Height:  |  Size: 111 B

After

Width:  |  Height:  |  Size: 111 B

View File

Before

Width:  |  Height:  |  Size: 110 B

After

Width:  |  Height:  |  Size: 110 B

View File

Before

Width:  |  Height:  |  Size: 119 B

After

Width:  |  Height:  |  Size: 119 B

View File

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 540 B

0
src/sunstone/public/js/layout.js Executable file → Normal file
View File

View File

@ -58,7 +58,15 @@ $(document).ready(function() {
refreshButtonListener(); //listen to manual refresh image clicks
confirmButtonListener(); //listen to buttons that require confirmation
confirmWithSelectListener(); //listen to buttons requiring a selector
actionButtonListener(); //listens to all simple actions (not creates)
actionButtonListener(); //listens to all simple actions (not creates)
hostInfoListener();
vMachineInfoListener();
vNetworkInfoListener();
imageInfoListener();
setupImageAttributesDialogs(); //setups the add/update/remove attr dialogs
//Jquery-ui eye-candy
@ -68,6 +76,12 @@ $(document).ready(function() {
preloadTables();
setupAutoRefresh();
tableCheckboxesListener(dataTable_hosts);
tableCheckboxesListener(dataTable_vMachines);
tableCheckboxesListener(dataTable_vNetworks);
tableCheckboxesListener(dataTable_users);
tableCheckboxesListener(dataTable_images);
$(".ui-widget-overlay").live("click", function (){
$("div:ui-dialog:visible").dialog("close");
});
@ -165,7 +179,8 @@ function initDataTables(){
"aoColumnDefs": [
{ "bSortable": false, "aTargets": ["check"] },
{ "sWidth": "60px", "aTargets": [0] },
{ "sWidth": "35px", "aTargets": [1] }
{ "sWidth": "35px", "aTargets": [1] },
{ "sWidth": "100px", "aTargets": [2] }
]
});
@ -176,8 +191,9 @@ function initDataTables(){
"sPaginationType": "full_numbers",
"aoColumnDefs": [
{ "bSortable": false, "aTargets": ["check"] },
{ "sWidth": "60px", "aTargets": [0,5,6,7] },
{ "sWidth": "35px", "aTargets": [1] }
{ "sWidth": "60px", "aTargets": [0,4,5,6,7] },
{ "sWidth": "35px", "aTargets": [1] },
{ "sWidth": "100px", "aTargets": [2] }
]
});
@ -203,7 +219,8 @@ function initDataTables(){
"aoColumnDefs": [
{ "bSortable": false, "aTargets": ["check"] },
{ "sWidth": "60px", "aTargets": [0,3] },
{ "sWidth": "35px", "aTargets": [1] }
{ "sWidth": "35px", "aTargets": [1] },
{ "sWidth": "100px", "aTargets": [2,3] }
]
});
@ -237,7 +254,7 @@ function initListButtons(){
$('.multi_action_slct').each(function(){
//prepare replacement buttons
buttonset = $('<div style="display:inline-block;" class="top_button"></div');
button1 = $('<button class="last_action_button" value="">Previous action</button>').button();
button1 = $('<button class="last_action_button action_button confirm_button confirm_with_select_button" value="">Previous action</button>').button();
button1.attr("disabled","disabled");
button2 = $('<button class="list_button" value="">See more</button>').button({
text:false,
@ -281,14 +298,12 @@ function initListButtons(){
prev_action_button.val($(this).val());
prev_action_button.removeClass("confirm_with_select_button");
prev_action_button.removeClass("confirm_button");
prev_action_button.removeClass("action_button");
prev_action_button.addClass($(this).attr("class"));
confirmButtonListener();
confirmWithSelectListener();
actionButtonListener();
prev_action_button.button("option","label",$(this).text());
prev_action_button.button("enable");
$(this).parents('ul').hide("blind",100);
return false;
//return false;
});
@ -333,11 +348,11 @@ function refreshButtonListener(){
callback = updateHostsView;
waiting_nodes(dataTable_hosts);
OpenNebula.Host.list({success: callback, error: onError});
callback = updateClustersView;
OpenNebula.Cluster.list({success: callback, error: onError});
break;
case "OpenNebula.Cluster.list":
callback = updateClustersView;
waiting_nodes(dataTable_clusters);
OpenNebula.Cluster.list({success: callback, error: onError});
//we have no cluster button for this
break;
case "OpenNebula.VM.list":
callback = updateVMachinesView;
@ -396,8 +411,7 @@ function confirmButtonListener(){
$('div#confirm_dialog button').button();
//add listeners
$('.confirm_button').click(function(){
$('.confirm_button').live("click",function(){
val=$(this).val();
tip="";
//supported cases
@ -490,8 +504,8 @@ function confirmWithSelectListener(){
});
$('div#confirm_with_select_dialog button').button();
//add listeners
$('.confirm_with_select_button').click(function(){
$( '.confirm_with_select_button').live("click",function(){
val=$(this).val();
tip="";
dataTable=null;
@ -512,7 +526,7 @@ function confirmWithSelectListener(){
dataTable="null";
select_var = clusters_select;
callback = function (){
OpenNebula.Host.list({success: updateClustersView,error: onError});
OpenNebula.Cluster.list({success: updateClustersView,error: onError});
}
break;
case "OpenNebula.VM.deploy":
@ -608,8 +622,9 @@ function confirmWithSelectListener(){
//of the element, it sends actions to OpenNebula.js. This function
//handles all the simple actions of the UI: delete, enables, disables, etc...
function actionButtonListener(){
//Listener
$('.action_button').click(function(){
$('.action_button').live("click",function(){
dataTable=null; //Which dataTable should be updated afterwards?
callback = null; //Which callback function should be used on success?
@ -727,9 +742,8 @@ function actionButtonListener(){
nodes_id.push($(this).val());
//Calling action(id,callback,error_callback)
if (extra_param!=null){ //action with two parameters
data = extra_param;
data.id = $(this).val();
(eval(action)({data: data, success: callback, error: onError}));
var data_arg = {cluster_id: extra_param, id: $(this).val()};
(eval(action)({data: data_arg, success: callback, error: onError}));
} else { //action with one parameter
(eval(action)({data:{id:$(this).val()},success: callback,error: onError}));
};
@ -798,11 +812,11 @@ function setupImageAttributesDialogs(){
<div>\
<input type="hidden" id="img_attr_action" />\
<label for="img_attr_name">Name:</label>\
<input type="text" id="img_attr_name" name="img_attr_name" value="NAME" />\
<input type="text" id="img_attr_name" name="img_attr_name" value="" />\
</div>\
<div>\
<label for="img_attr_value">Value:</label>\
<input type="text" id="img_attr_value" name="img_attr_value" value="value" />\
<input type="text" id="img_attr_value" name="img_attr_value" value="" />\
</div>\
<div>\
<button id="img_attr_proceed" value="">OK</button>\
@ -815,7 +829,7 @@ function setupImageAttributesDialogs(){
autoOpen:false,
width:400,
modal:true,
height:270,
height:200,
resizable:false,
});
@ -1034,7 +1048,7 @@ function createClusterDialog(){
//If it's successfull we refresh the list.
OpenNebula.Cluster.create({ data:cluster_json,
success: function(){
OpenNebula.Cluster.list(updateClustersView,onError)},
OpenNebula.Cluster.list({success:updateClustersView,error:onError})},
error: onError});
$create_cluster_dialog.dialog('close');
return false;
@ -1887,10 +1901,10 @@ function createVMachineDialog(){
});
$('button#create_vm_form_manual').click(function(){
template = $('#vm_template').val();
template = $('#textarea_vm_template').val();
//wrap it in the "vm" object
template = {vm: {vm_raw: template}};
template = {"vm": {"vm_raw": template}};
OpenNebula.VM.create({data: template,
success: addVMachineElement,
@ -2078,7 +2092,7 @@ function createImageDialog(){
break;
}
obj = { "image" : img_json };
OpenNebula.Image.create({data: obj,success: addImageElement,error: onError});
OpenNebula.Image.register({data: obj,success: addImageElement,error: onError});
$create_image_dialog.dialog('close');
return false;
@ -2205,9 +2219,12 @@ function updateSingleElement(element,data_table,tag){
tr = $(tag).parents('tr')[0];
position = data_table.fnGetPosition(tr);
data_table.fnUpdate(element,position,0);
$('input',data_table).trigger("change");
}
function tableCheckboxesListener(dataTable){
context = dataTable.parents('form');
last_action_b = $('.last_action_button',context);
$('.top_button, .list_button',context).button("disable");
@ -2217,13 +2234,21 @@ function tableCheckboxesListener(dataTable){
$('.new_button',context).button("enable");
//listen to changes
$('input',dataTable).click(function(){
$('input',dataTable).live("change",function(){
dataTable = $(this).parents('table').dataTable();
context = dataTable.parents('form');
last_action_b = $('.last_action_button',context);
nodes_length = $('input:checked',dataTable.fnGetNodes()).length;
nodes = dataTable.fnGetNodes();
total_length = nodes.length;
checked_length = $('input:checked',nodes).length;
if (nodes_length){
if (total_length == checked_length){
$('.check_all',dataTable).attr("checked","checked");
} else {
$('.check_all',dataTable).removeAttr("checked");
}
if (checked_length){
$('.top_button, .list_button',context).button("enable");
if (last_action_b.length && last_action_b.val().length){
last_action_b.button("enable");
@ -2241,6 +2266,7 @@ function tableCheckboxesListener(dataTable){
function deleteElement(data_table,tag){
tr = $(tag).parents('tr')[0];
data_table.fnDeleteRow(tr);
$('input',data_table).trigger("change");
}
function addElement(element,data_table){
@ -2253,18 +2279,24 @@ function hostElementArray(host_json){
if (!acpu) {acpu=100};
acpu = acpu - parseInt(host.HOST_SHARE.CPU_USAGE);
total_mem = parseInt(host.HOST_SHARE.MAX_MEM);
free_mem = parseInt(host.HOST_SHARE.FREE_MEM);
ratio_mem = Math.round(((total_mem - free_mem) / total_mem) * 100);
if (total_mem == 0) {
ratio_mem = 0;
} else {
ratio_mem = Math.round(((total_mem - free_mem) / total_mem) * 100);
}
total_cpu = parseInt(host.HOST_SHARE.MAX_CPU);
used_cpu = Math.max(total_cpu - parseInt(host.HOST_SHARE.USED_CPU),acpu);
ratio_cpu = Math.round(((total_cpu - used_cpu) / total_cpu) * 100);
if (total_cpu == 0) {
ratio_cpu = 0;
} else {
ratio_cpu = Math.round(((total_cpu - used_cpu) / total_cpu) * 100);
}
pb_mem =
'<div style="height:10px" class="ratiobar ui-progressbar ui-widget ui-widget-content ui-corner-all" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="'+ratio_mem+'">\
@ -2306,7 +2338,8 @@ function hostElementArray(host_json){
//Adds a listener to show the extended info when clicking on a row
function hostInfoListener(){
$('#tbodyhosts tr').click(function(e){
$('#tbodyhosts tr').live("click",function(e){
//do nothing if we are clicking a checkbox!
if ($(e.target).is('input')) {return true;}
@ -2327,13 +2360,17 @@ function hostInfoListener(){
//~ }
function vMachineElementArray(vm_json){
vm = vm_json.VM;
var vm = vm_json.VM;
var state = OpenNebula.Helper.resource_state("vm",vm.STATE);
if (state == "ACTIVE") {
state = OpenNebula.Helper.resource_state("vm_lcm",vm.LCM_STATE);
}
return [
'<input type="checkbox" id="vm_'+vm.ID+'" name="selected_items" value="'+vm.ID+'"/>',
vm.ID,
vm.USERNAME ? vm.USERNAME : getUserName(vm.UID),
vm.NAME,
OpenNebula.Helper.resource_state("vm",vm.STATE),
state,
vm.CPU,
humanize_size(vm.MEMORY),
vm.HISTORY ? vm.HISTORY.HOSTNAME : "--",
@ -2343,7 +2380,8 @@ function vMachineElementArray(vm_json){
//Adds a listener to show the extended info when clicking on a row
function vMachineInfoListener(){
$('#tbodyvmachines tr').click(function(e){
$('#tbodyvmachines tr').live("click", function(e){
if ($(e.target).is('input')) {return true;}
aData = dataTable_vMachines.fnGetData(this);
id = $(aData[0]).val();
@ -2354,9 +2392,9 @@ function vMachineInfoListener(){
function vNetworkElementArray(vn_json){
network = vn_json.VNET;
if (network.TOTAL_LEASES != undefined){
if (network.TOTAL_LEASES){
total_leases = network.TOTAL_LEASES;
}else if (network.LEASES.LEASE != undefined){
}else if (network.LEASES && network.LEASES.LEASE){
total_leases = network.LEASES.LEASE.length ? network.LEASES.LEASE.length : "1";
} else{
total_leases = "0";
@ -2373,7 +2411,8 @@ function vNetworkElementArray(vn_json){
}
//Adds a listener to show the extended info when clicking on a row
function vNetworkInfoListener(){
$('#tbodyvnetworks tr').click(function(e){
$('#tbodyvnetworks tr').live("click", function(e){
if ($(e.target).is('input')) {return true;}
aData = dataTable_vNetworks.fnGetData(this);
id = $(aData[0]).val();
@ -2384,10 +2423,16 @@ function vNetworkInfoListener(){
function userElementArray(user_json){
user = user_json.USER;
if (!user.NAME || user.NAME == {}){
name = "";
} else {
name = user.NAME;
}
return [
'<input type="checkbox" id="user_'+user.ID+'" name="selected_items" value="'+user.ID+'"/>',
user.ID,
user.NAME
name
]
}
@ -2407,8 +2452,9 @@ function imageElementArray(image_json){
];
}
function imageInfoListener(){
$('#tbodyimages tr').click(function(e){
function imageInfoListener(target){
$('#tbodyimages tr').live("click",function(e){
if ($(e.target).is('input')) {return true;}
aData = dataTable_images.fnGetData(this);
id = $(aData[0]).val();
@ -2461,7 +2507,9 @@ function updateImageSelect(image_list){
images_select="";
images_select += "<option value=\"\">Select an image</option>";
$.each(image_list, function(){
images_select += "<option value=\""+this.IMAGE.NAME+"\">"+this.IMAGE.NAME+"</option>";
if ((this.IMAGE.STATE < 3) && (this.IMAGE.STATE > 0)){
images_select += '<option id="img_sel_'+this.IMAGE.ID+'" value="'+this.IMAGE.NAME+'">'+this.IMAGE.NAME+'</option>';
}
});
//update static selectors
@ -2582,8 +2630,9 @@ function onError(request,error_json) {
};
//Parse known errors:
var action_error = new RegExp("^\\[(\\w+)\\] Error trying to (\\w+) (\\w+) \\[(\\w+)\\].*Reason: (.*)\.$");
var get_error = new RegExp("^\\[(\\w+)\\] Error getting (\\w+) \\[(\\w+)\\]\.$");
var action_error = /^\[(\w+)\] Error trying to (\w+) (\w+) \[(\w+)\].*Reason: (.*)\.$/;
var action_error_noid = /^\[(\w+)\] Error trying to (\w+) (\w+) (.*)\.$/;
var get_error = /^\[(\w+)\] Error getting (\w+) \[(\w+)\]\.$/;
var auth_error = /^\[(\w+)\] User \[.\] not authorized to perform (\w+) on (\w+) \[?(\w+)\]?\.?$/;
if (m = message.match(action_error)) {
@ -2592,6 +2641,11 @@ function onError(request,error_json) {
object = m[3];
id = m[4];
reason = m[5];
} else if (m = message.match(action_error_noid)) {
method = m[1];
action = m[2];
object = m[3];
reason = m[4];
} else if (m = message.match(get_error)) {
method = m[1];
action = "SHOW";
@ -2634,7 +2688,7 @@ function onError(request,error_json) {
function updateHostElement(request, host_json){
id = host_json.HOST.ID;
element = hostElementArray(host_json);
updateSingleElement(element,dataTable_hosts,'#host_'+id)
updateSingleElement(element,dataTable_hosts,'#host_'+id);
}
function deleteHostElement(req){
@ -2642,10 +2696,9 @@ function deleteHostElement(req){
}
function addHostElement(request,host_json){
id = host_json.HOST.ID;
element = hostElementArray(host_json);
addElement(element,dataTable_hosts);
hostInfoListener();
tableCheckboxesListener(dataTable_hosts);
}
function updateHostsView (request,host_list){
@ -2660,10 +2713,6 @@ function updateHostsView (request,host_list){
updateView(host_list_array,dataTable_hosts);
updateHostSelect(host_list);
updateDashboard("hosts");
//We need to re-add this listener as list has been refreshed
hostInfoListener();
tableCheckboxesListener(dataTable_hosts);
}
@ -2706,12 +2755,11 @@ function deleteVMachineElement(req){
}
function addVMachineElement(request,vm_json){
notifySubmit('OpenNebula.VM.create',vm_json.VM.ID);
id = vm_json.VM.ID;
notifySubmit('OpenNebula.VM.create',id);
element = vMachineElementArray(vm_json);
addElement(element,dataTable_vMachines);
vMachineInfoListener();
updateVMInfo(null,vm_json);
tableCheckboxesListener(dataTable_vMachines);
}
function updateVMachinesView(request, vmachine_list){
@ -2723,8 +2771,6 @@ function updateVMachinesView(request, vmachine_list){
});
updateView(vmachine_list_array,dataTable_vMachines);
vMachineInfoListener();
tableCheckboxesListener(dataTable_vMachines);
updateDashboard("vms");
}
@ -2733,17 +2779,18 @@ function updateVNetworkElement(request, vn_json){
id = vn_json.VNET.ID;
element = vNetworkElementArray(vn_json);
updateSingleElement(element,dataTable_vNetworks,'#vnetwork_'+id);
tableCheckboxesListener(dataTable_vNetworks);
}
function deleteVNetworkElement(req){
deleteElement(dataTable_vNetworks,'#vnetwork_'+req.request.data);
//How to delete vNetwork select option here?
}
function addVNetworkElement(request,vn_json){
element = vNetworkElementArray(vn_json);
addElement(element,dataTable_vNetworks);
vNetworkInfoListener();
vnetworks_select += "<option value=\""+vn_json.VNET.NAME+"\">"+vn_json.VNET.NAME+"</option>";
$('div.vm_section#networks select#NETWORK').html(vnetworks_select);
}
function updateVNetworksView(request, network_list){
@ -2756,9 +2803,7 @@ function updateVNetworksView(request, network_list){
updateView(network_list_array,dataTable_vNetworks);
updateNetworkSelect(network_list);
vNetworkInfoListener();
updateDashboard("vnets");
tableCheckboxesListener(dataTable_vNetworks);
}
@ -2766,7 +2811,6 @@ function updateUserElement(request, user_json){
id = user_json.USER.ID;
element = userElementArray(user_json);
updateSingleElement(element,dataTable_users,'#user_'+id);
tableCheckboxesListener(dataTable_users);
}
function deleteUserElement(req){
@ -2787,7 +2831,6 @@ function updateUsersView(request,users_list){
});
updateView(user_list_array,dataTable_users);
updateDashboard("users");
tableCheckboxesListener(dataTable_users);
}
@ -2795,12 +2838,27 @@ function updateImageElement(request, image_json){
id = image_json.IMAGE.ID;
element = imageElementArray(image_json);
updateSingleElement(element,dataTable_images,'#image_'+id);
tableCheckboxesListener(dataTable_images);
imageInfoListener();
if ((image_json.IMAGE.STATE < 3) &&
(image_json.IMAGE.STATE > 0) &&
($('#img_sel_'+id,images_select).length == 0)){
images_select += '<option id="img_sel_'+id+'" value="'+image_json.IMAGE.NAME+'">'+image_json.IMAGE.NAME+'</option>';
}
else {
tag = 'option#img_sel_'+id;
select = $('<select>'+images_select+'</select>');
$(tag,select).remove();
images_select = $(select).html();
}
$('div.vm_section#disks select#IMAGE').html(images_select);
}
function deleteImageElement(req){
deleteElement(dataTable_images,'#image_'+req.request.data);
tag = 'option#img_sel_'+req.request.data;
select = $('<select>'+images_select+'</select>');
$(tag,select).remove();
images_select = $(select).html();
$('div.vm_section#disks select#IMAGE').html(images_select);
}
function addImageElement(request, image_json){
@ -2817,8 +2875,6 @@ function updateImagesView(request, images_list){
updateView(image_list_array,dataTable_images);
updateImageSelect(images_list);
imageInfoListener();
tableCheckboxesListener(dataTable_images);
updateDashboard("images");
@ -2998,7 +3054,7 @@ function updateVMInfo(request,vm){
</tr>\
<tr>\
<td class="key_td">LCM State</td>\
<td class="value_td">'+OpenNebula.Helper.resource_state("vm",vm_info.LCMSTATE)+'</td>\
<td class="value_td">'+OpenNebula.Helper.resource_state("vm_lcm",vm_info.LCM_STATE)+'</td>\
</tr>\
<tr>\
<td class="key_td">Start time</td>\
@ -3006,7 +3062,7 @@ function updateVMInfo(request,vm){
</tr>\
<tr>\
<td class="key_td">Deploy ID</td>\
<td class="value_td">'+(vm_info.DEPLOY_ID ? vm_info.DEPLOY_ID : "-")+'</td>\
<td class="value_td">'+(typeof(vm_info.DEPLOY_ID) == "object" ? "-" : vm_info.DEPLOY_ID)+'</td>\
</tr>\
</table>\
<table id="vm_monitoring_table" class="info_table">\
@ -3093,14 +3149,16 @@ function updateVNetworkInfo(request,vn){
<td class="key_td">Public</td>\
<td class="value_td">'+(parseInt(vn_info.PUBLIC) ? "yes" : "no" )+'</td>\
</tr>\
</table>\
<table id="vn_leases_info_table" class="info_table">\
</table>';
if (vn_info.TEMPLATE.TYPE == "FIXED"){
rendered_info += '<table id="vn_leases_info_table" class="info_table">\
<thead>\
<tr><th colspan="2">Leases information</th></tr>\
</thead>'+
prettyPrintJSON(vn_info.LEASES)+
'</table>\
</div>\
'</table>';
}
rendered_info += '</div>\
<div id="vn_template">\
<table id="vn_template_table" class="info_table">\
<thead><tr><th colspan="2">Virtual Network template</th></tr></thead>'+
@ -3144,11 +3202,11 @@ function updateImageInfo(request,img){
</tr>\
<tr>\
<td class="key_td">Public</td>\
<td class="value_td">'+(img_info.PUBLIC ? "yes" : "no")+'</td>\
<td class="value_td">'+(parseInt(img_info.PUBLIC) ? "yes" : "no")+'</td>\
</tr>\
<tr>\
<td class="key_td">Persistent</td>\
<td class="value_td">'+(img_info.PERSISTENT ? "yes" : "no")+'</td>\
<td class="value_td">'+(parseInt(img_info.PERSISTENT) ? "yes" : "no")+'</td>\
</tr>\
<tr>\
<td class="key_td">Source</td>\
@ -3156,7 +3214,7 @@ function updateImageInfo(request,img){
</tr>\
<tr>\
<td class="key_td">State</td>\
<td class="value_td">'+img_info.STATE+'</td>\
<td class="value_td">'+OpenNebula.Helper.resource_state("image",img_info.STATE)+'</td>\
</tr>\
</table>\
</div>\

View File

@ -168,14 +168,14 @@ var hostlist_tmpl =
</div>\
<div class="action_block">\
<button class="create_cluster_button top_button new_button">+ New Cluster</button>\
<button class="confirm_with_select_button top_button new_button" value="OpenNebula.Cluster.delete">Delete cluster</button>\
<select class="multi_action_slct" id="cluster_actions_select">\
<option class="confirm_with_select_button" value="OpenNebula.Cluster.delete">Delete cluster</option>\
<option class="confirm_with_select_button" value="OpenNebula.Cluster.addhost">Add host to cluster</option>\
<option class="action_button" value="OpenNebula.Cluster.removehost">Remove host from cluster</option>\
</select>\
</div>\
<div class="action_block" style="border:none;">\
<button class="action_button top_button" value="OpenNebula.Host.delete">Delete</button>\
<button class="action_button top_button" value="OpenNebula.Host.delete">Delete host</button>\
</div>\
</div>\
<table id="datatable_hosts" class="display">\
@ -757,7 +757,7 @@ var create_vm_tmpl =
<form>\
<h3 style="margin-bottom:10px;">Write the Virtual Machine template here</h3>\
<fieldset style="border-top:none;">\
<textarea id="vm_template" style="width:100%; height:15em;"></textarea>\
<textarea id="textarea_vm_template" style="width:100%; height:15em;"></textarea>\
<div class="clear"></div>\
</fieldset>\
<fieldset>\
@ -895,7 +895,7 @@ var userlist_tmpl =
'<form id="user_form" action="" action="javascript:alert(\'js error!\');">\
<div class="action_blocks">\
<div class="action_block">\
<img src="/images/Refresh-icon.png" class="refresh_image" alt="OpenNebula.VM.list" />\
<img src="/images/Refresh-icon.png" class="refresh_image" alt="OpenNebula.User.list" />\
</div>\
<div class="action_block">\
<button class="create_user_button top_button new_button">+ New</button>\
@ -1042,10 +1042,13 @@ var create_image_tmpl =
<fieldset>\
<div class="" id="src_path_select">\
<label style="height:3em;">Path vs. source:</label>\
<input type="radio" name="src_path" id="path_img" value="path">Provide a path</input><br />\
<input type="radio" name="src_path" id="source_img" value="source">Provide a source</input><br />\
<input type="radio" name="src_path" id="datablock_img" value="datablock">Create an empty datablock</input>\
<div class="tip">Please choose path if you have a file-based image. Choose source otherwise or create an empty datablock disk.</div>\
<input type="radio" name="src_path" id="path_img" value="path" />\
<label style="float:none">Provide a path</label><br />\
<input type="radio" name="src_path" id="source_img" value="source" />\
<label style="float:none">Provide a source</label><br />\
<input type="radio" name="src_path" id="datablock_img" value="datablock" />\
<label style="float:none;vertical-align:top">Create an empty datablock</label>\
<div class="tip">Please choose path if you have a file-based image. Choose source otherwise or create an empty datablock disk.</div><br />\
</div>\
<div class="img_param">\
<label for="img_path">Path:</label>\

View File

@ -65,6 +65,25 @@ var OpenNebula = {
"DONE",
"FAILED"][value];
break;
case "VM_LCM","vm_lcm":
return ["LCM_INIT",
"PROLOG",
"BOOT",
"RUNNING",
"MIGRATE",
"SAVE_STOP",
"SAVE_SUSPEND",
"SAVE_MIGRATE",
"PROLOG_MIGRATE",
"PROLOG_RESUME",
"EPILOG_STOP",
"EPILOG",
"SHUTDOWN",
"CANCEL",
"FAILURE",
"CLEANUP",
"UNKNOWN"][value];
break;
case "IMAGE","image":
return ["INIT",
"READY",
@ -126,7 +145,9 @@ var OpenNebula = {
var p_pool = [];
pool = response[pool_name][type];
if (response[pool_name]) {
pool = response[pool_name][type];
} else { pull = null };
if (pool == null)
{
@ -267,7 +288,7 @@ var OpenNebula = {
url: "/host",
type: "POST",
dataType: "json",
data: data,
data: JSON.stringify(data),
success: function(response)
{
if (callback)

View File

@ -16,30 +16,21 @@
# limitations under the License. #
#--------------------------------------------------------------------------- #
##############################################################################
# Environment Configuration for the Server
##############################################################################
HOST = "127.0.0.1"
PORT = "4567"
##############################################################################
# Required libraries
##############################################################################
require 'rubygems'
require 'sinatra'
require 'models/OneUI'
require 'models/SunstoneServer'
##############################################################################
# Sinatra Configuration
##############################################################################
set :host, HOST
set :port, PORT
use Rack::Session::Pool
##############################################################################
# Helpers
##############################################################################
@ -54,7 +45,7 @@ helpers do
user = auth.credentials[0]
sha1_pass = Digest::SHA1.hexdigest(auth.credentials[1])
rc = OneUI.authorize(user, sha1_pass)
rc = SunstoneServer.authorize(user, sha1_pass)
if rc[1]
session["user"] = user
session["user_id"] = rc[1]
@ -86,7 +77,7 @@ before do
unless request.path=='/login' || request.path=='/'
halt 401 unless authorized?
@OneUI = OneUI.new(session["user"], session["password"])
@SunstoneServer = SunstoneServer.new(session["user"], session["password"])
end
end
@ -132,44 +123,44 @@ end
# GET Pool information
##############################################################################
get '/:pool' do
@OneUI.get_pool(params[:pool], session["user_id"])
@SunstoneServer.get_pool(params[:pool])
end
##############################################################################
# GET Resource information
##############################################################################
get '/:resource/:id' do
@OneUI.get_resource(params[:resource], params[:id])
@SunstoneServer.get_resource(params[:resource], params[:id])
end
##############################################################################
# Delete Resource
##############################################################################
delete '/:resource/:id' do
@OneUI.delete_resource(params[:resource], params[:id])
@SunstoneServer.delete_resource(params[:resource], params[:id])
end
##############################################################################
# Create a new Resource
##############################################################################
post '/:pool' do
@OneUI.create_resource(params[:pool], request.body.read)
@SunstoneServer.create_resource(params[:pool], request.body.read)
end
##############################################################################
# Perform an action on a Resource
##############################################################################
post '/:resource/:id/action' do
@OneUI.perform_action(params[:resource], params[:id], request.body.read)
@SunstoneServer.perform_action(params[:resource], params[:id], request.body.read)
end
##############################################################################
# Config and Logs
##############################################################################
get '/config' do
@OneUI.get_configuration
@SunstoneServer.get_configuration(session["user_id"])
end
get '/vm/:id/log' do
@OneUI.get_vm_log(params[:id].to_i)
@SunstoneServer.get_vm_log(params[:id])
end

View File

@ -4,18 +4,18 @@
<title>OpenNebula Admin Console</title>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="/css/demo_table_jui.css" />
<link type="text/css" href="/css/smoothness/jquery-ui-1.8.7.custom.css" rel="stylesheet" />
<link type="text/css" href="/css/vendor/jquery-ui-1.8.7.custom.css" rel="stylesheet" />
<link rel="stylesheet" type="text/css" href="/css/jquery.jgrowl.css" />
<link type="text/css" rel="stylesheet" href="/css/layout-default-latest.css" />
<link rel="stylesheet" type="text/css" href="/css/application.css" />
<link rel="stylesheet" type="text/css" href="/css/layout.css" />
<script type="text/javascript" src="/js/jquery-1.4.4.min.js"></script>
<script type="text/javascript" src="/js/jquery.jgrowl_minimized.js"></script>
<script type="text/javascript" src="/js/jquery-ui-1.8.7.custom.min.js"></script>
<script type="text/javascript" src="/js/jquery.layout.min-1.2.0.js"></script>
<script type="text/javascript" src="/js/jquery.dataTables.min.js"></script>
<!-- Vendor Libraries -->
<script type="text/javascript" src="/js/vendor/jquery-1.4.4.min.js"></script>
<script type="text/javascript" src="/js/vendor/jquery.jgrowl_minimized.js"></script>
<script type="text/javascript" src="/js/vendor/jquery-ui-1.8.7.custom.min.js"></script>
<script type="text/javascript" src="/js/vendor/jquery.layout.min-1.2.0.js"></script>
<script type="text/javascript" src="/js/vendor/jquery.dataTables.min.js"></script>
<script type="text/javascript" src="/js/opennebula.js"></script>
<script type="text/javascript" src="/js/one-ui_views.templates.js"></script>
@ -27,7 +27,6 @@
<div class="inner-center">
<div id="dashboard" class="tab"></div>
<div id="hosts" class="tab"></div>
<!--<div id="clusters" class="tab"></div>-->
<div id="virtualMachines" class="tab"></div>
<div id="virtualNetworks" class="tab"></div>
<div id="images" class="tab"></div>
@ -40,7 +39,6 @@
<ul id="navigation">
<li><a href="#dashboard">Dashboard</a></li>
<li><a href="#hosts">Hosts &amp; Clusters</a></li>
<!--<li><a href="#clusters">Clusters</a></li>-->
<li><a href="#virtualMachines">Virtual Machines</a></li>
<li><a href="#virtualNetworks">Virtual Networks</a></li>
<li><a href="#images">Images</a></li>

View File

@ -3,9 +3,12 @@
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>OpenNebula Admin Console Login</title>
<link rel="stylesheet" type="text/css" href="/css/login.css" />
<script type="text/javascript" src="/js/jquery-1.4.4.min.js"></script>
<!-- Vendor Libraries -->
<script type="text/javascript" src="/js/vendor/jquery-1.4.4.min.js"></script>
<script type="text/javascript" src="/js/vendor/base64.js"></script>
<script type="text/javascript" src="/js/opennebula.js"></script>
<script type="text/javascript" src="/js/base64.js"></script>
<script type="text/javascript" src="/js/login.js"></script>
</head>

View File

@ -4,6 +4,6 @@
"disk_id": "0",
"image_name": "new_image"
},
"perform": "save_as"
"perform": "saveas"
}
}
}

View File

@ -35,7 +35,7 @@ describe 'VirtualMachine tests' do
@action_deploy = File.read(EXAMPLES_PATH + '/vm/deploy.json')
@action_hold = File.read(EXAMPLES_PATH + '/vm/hold.json')
@action_saveas = File.read(EXAMPLES_PATH + '/vm/save_as.json')
@action_saveas = File.read(EXAMPLES_PATH + '/vm/saveas.json')
@wrong_action = File.read(EXAMPLES_PATH + '/error/wrong_action.json')
end
@ -125,7 +125,7 @@ describe 'VirtualMachine tests' do
end
############################################################################
# Save_as
# Saveas
############################################################################
it "should prepare the VirtualMachine 0 disk to be saved" do
url = '/vm/0/action'
@ -134,7 +134,7 @@ describe 'VirtualMachine tests' do
last_response.status.should eql(204)
end
it "should get VirtualMachine 0 information after save_as action" do
it "should get VirtualMachine 0 information after saveas action" do
url = '/vm/0'
get url