diff --git a/install.sh b/install.sh index 772aaadee9..52a312ab3d 100755 --- a/install.sh +++ b/install.sh @@ -1095,8 +1095,7 @@ ETC_CLIENT_FILES="src/cli/etc/group.default" # Sunstone files #----------------------------------------------------------------------------- -SUNSTONE_FILES="src/sunstone/config.ru \ - src/sunstone/sunstone-server.rb \ +SUNSTONE_FILES="src/sunstone/sunstone-server.rb \ src/sunstone/OpenNebulaVNC.rb" SUNSTONE_BIN_FILES="src/sunstone/bin/sunstone-server" @@ -1241,8 +1240,7 @@ src/sunstone/public/locale/ru/ru_datatable.txt" # Ozones files #----------------------------------------------------------------------------- -OZONES_FILES="src/ozones/Server/config.ru \ - src/ozones/Server/ozones-server.rb" +OZONES_FILES="src/ozones/Server/ozones-server.rb" OZONES_BIN_FILES="src/ozones/Server/bin/ozones-server" @@ -1448,6 +1446,9 @@ if [ "$UNINSTALL" = "no" ] ; then for d in $MAKE_DIRS; do mkdir -p $DESTDIR$d done + + # Remove old migrators + rm $LIB_LOCATION/ruby/onedb/*.rb fi # --- Install/Uninstall files --- diff --git a/share/etc/oned.conf b/share/etc/oned.conf index 400d07ab12..b98bdf288e 100644 --- a/share/etc/oned.conf +++ b/share/etc/oned.conf @@ -80,9 +80,9 @@ MAC_PREFIX = "02:00" #******************************************************************************* # DataStore Configuration #******************************************************************************* -# DATASTORE_LOCATION: Path for Datastores in the hosts. It IS the same all the -# hosts in the cluster. DATASTORE_LOCATION IS ONLY FOR THE HOSTS AND *NOT* THE -# FRONT-END. It defaults to /var/lib/one/datastores (or +# DATASTORE_LOCATION: Path for Datastores in the hosts. It IS the same for all +# the hosts in the cluster. DATASTORE_LOCATION IS ONLY FOR THE HOSTS AND *NOT* +# THE FRONT-END. It defaults to /var/lib/one/datastores (or # $ONE_LOCATION/var/datastores in self-contained mode) # # DEFAULT_IMAGE_TYPE: This can take values diff --git a/src/authm/AuthManager.cc b/src/authm/AuthManager.cc index 348782c68a..6201ba33e2 100644 --- a/src/authm/AuthManager.cc +++ b/src/authm/AuthManager.cc @@ -429,7 +429,7 @@ void AuthManager::notify_request(int auth_id,bool result,const string& message) void AuthManager::load_mads(int uid) { ostringstream oss; - const VectorAttribute * vattr; + const VectorAttribute * vattr = 0; int rc; string name; AuthManagerDriver * authm_driver = 0; @@ -438,7 +438,10 @@ void AuthManager::load_mads(int uid) NebulaLog::log("AuM",Log::INFO,oss); - vattr = static_cast(mad_conf[0]); + if ( mad_conf.size() > 0 ) + { + vattr = static_cast(mad_conf[0]); + } if ( vattr == 0 ) { diff --git a/src/cli/one_helper/oneuser_helper.rb b/src/cli/one_helper/oneuser_helper.rb index 82a060b44e..2b1a532919 100644 --- a/src/cli/one_helper/oneuser_helper.rb +++ b/src/cli/one_helper/oneuser_helper.rb @@ -34,7 +34,7 @@ class OneUserHelper < OpenNebulaHelper::OneHelper begin password = File.read(arg).split("\n").first rescue - return -1, "Can not read file: #{arg}" + return -1, "Cannot read file: #{arg}" end else password = arg.dup diff --git a/src/cloud/common/CloudAuth.rb b/src/cloud/common/CloudAuth.rb index 23331f79f8..b6203a11ea 100644 --- a/src/cloud/common/CloudAuth.rb +++ b/src/cloud/common/CloudAuth.rb @@ -39,11 +39,12 @@ class CloudAuth # Tokens will be generated if time > EXPIRE_TIME - EXPIRE_MARGIN EXPIRE_MARGIN = 300 - attr_reader :client, :token + attr_reader :client, :token, :logger # conf a hash with the configuration attributes as symbols - def initialize(conf) + def initialize(conf, logger=nil) @conf = conf + @logger = logger @token_expiration_time = Time.now.to_i + EXPIRE_DELTA diff --git a/src/cloud/common/CloudServer.rb b/src/cloud/common/CloudServer.rb index ec3b86134d..9e3883ad1a 100755 --- a/src/cloud/common/CloudServer.rb +++ b/src/cloud/common/CloudServer.rb @@ -37,7 +37,7 @@ class CloudServer ########################################################################## # Public attributes ########################################################################## - attr_reader :config + attr_reader :config, :logger # Initializes the Cloud server based on a config file # config_file:: _String_ for the server. MUST include the following @@ -45,9 +45,10 @@ class CloudServer # AUTH # VM_TYPE # XMLRPC - def initialize(config) + def initialize(config, logger=nil) # --- Load the Cloud Server configuration file --- @config = config + @logger = logger end # # Prints the configuration of the server @@ -82,3 +83,54 @@ class CloudServer return false end end + +module CloudLogger + require 'logger' + + DEBUG_LEVEL = [ + Logger::ERROR, # 0 + Logger::WARN, # 1 + Logger::INFO, # 2 + Logger::DEBUG # 3 + ] + + # Mon Feb 27 06:02:30 2012 [Clo] [E]: Error message example + MSG_FORMAT = %{%s [%s]: %s\n} + + # Mon Feb 27 06:02:30 2012 + DATE_FORMAT = "%a %b %d %H:%M:%S %Y" + + # Patch logger class to be compatible with Rack::CommonLogger + class ::Logger + def write(msg) + info msg.chop + end + end + + def enable_logging(path=nil, debug_level=3) + path ||= $stdout + logger = ::Logger.new(path) + logger.level = DEBUG_LEVEL[debug_level] + logger.formatter = proc do |severity, datetime, progname, msg| + MSG_FORMAT % [ + datetime.strftime(DATE_FORMAT), + severity[0..0], + msg ] + end + + # Add the logger instance to the Sinatra settings + set :logger, logger + + # The logging will be configured in Rack, not in Sinatra + disable :logging + + # Use the logger instance in the Rack methods + use Rack::CommonLogger, logger + + helpers do + def logger + settings.logger + end + end + end +end diff --git a/src/cloud/ec2/bin/econe-server b/src/cloud/ec2/bin/econe-server index 2071c168d7..5b1d23a9f2 100755 --- a/src/cloud/ec2/bin/econe-server +++ b/src/cloud/ec2/bin/econe-server @@ -53,7 +53,7 @@ setup() start() { if [ ! -f "$ECONE_SERVER" ]; then - echo "Can not find $ECONE_SERVER." + echo "Cannot find $ECONE_SERVER." exit 1 fi diff --git a/src/cloud/ec2/etc/econe.conf b/src/cloud/ec2/etc/econe.conf index 679d5fb6e9..f9ba61e670 100644 --- a/src/cloud/ec2/etc/econe.conf +++ b/src/cloud/ec2/etc/econe.conf @@ -34,6 +34,9 @@ # x509, for x509 certificate encryption of tokens :core_auth: cipher +# 0 = ERROR, 1 = WARNING, 2 = INFO, 3 = DEBUG +:debug_level: 3 + # VM types allowed and its template file (inside templates directory) :instance_types: :m1.small: diff --git a/src/cloud/ec2/lib/EC2QueryServer.rb b/src/cloud/ec2/lib/EC2QueryServer.rb index 4e2abd1072..66c14ad2a0 100644 --- a/src/cloud/ec2/lib/EC2QueryServer.rb +++ b/src/cloud/ec2/lib/EC2QueryServer.rb @@ -61,8 +61,8 @@ class EC2QueryServer < CloudServer ########################################################################### - def initialize(client, config) - super(config) + def initialize(client, config, logger) + super(config, logger) @client = client end diff --git a/src/cloud/ec2/lib/econe-server.rb b/src/cloud/ec2/lib/econe-server.rb index 0a8ccc1d98..0d20b59cc4 100644 --- a/src/cloud/ec2/lib/econe-server.rb +++ b/src/cloud/ec2/lib/econe-server.rb @@ -20,19 +20,23 @@ ONE_LOCATION=ENV["ONE_LOCATION"] if !ONE_LOCATION - RUBY_LIB_LOCATION = "/usr/lib/one/ruby" + LOG_LOCATION = "/var/log/one" VAR_LOCATION = "/var/lib/one" - CONFIGURATION_FILE = "/etc/one/econe.conf" - TEMPLATE_LOCATION = "/etc/one/ec2query_templates" + ETC_LOCATION = "/etc/one" + RUBY_LIB_LOCATION = "/usr/lib/one/ruby" else - RUBY_LIB_LOCATION = ONE_LOCATION+"/lib/ruby" - VAR_LOCATION = ONE_LOCATION+"/var" - CONFIGURATION_FILE = ONE_LOCATION+"/etc/econe.conf" - TEMPLATE_LOCATION = ONE_LOCATION+"/etc/ec2query_templates" + VAR_LOCATION = ONE_LOCATION + "/var" + LOG_LOCATION = ONE_LOCATION + "/var" + ETC_LOCATION = ONE_LOCATION + "/etc" + RUBY_LIB_LOCATION = ONE_LOCATION+"/lib/ruby" end -VIEWS_LOCATION = RUBY_LIB_LOCATION + "/cloud/econe/views" -EC2_AUTH = VAR_LOCATION + "/.one/ec2_auth" +EC2_AUTH = VAR_LOCATION + "/.one/ec2_auth" +EC2_LOG = LOG_LOCATION + "/econe-server.log" +CONFIGURATION_FILE = ETC_LOCATION + "/occi-server.conf" + +TEMPLATE_LOCATION = ETC_LOCATION + "/occi_templates" +VIEWS_LOCATION = RUBY_LIB_LOCATION + "/cloud/econe/views" $: << RUBY_LIB_LOCATION $: << RUBY_LIB_LOCATION+"/cloud" @@ -57,12 +61,13 @@ include OpenNebula begin conf = YAML.load_file(CONFIGURATION_FILE) rescue Exception => e - puts "Error parsing config file #{CONFIGURATION_FILE}: #{e.message}" + STDERR.puts "Error parsing config file #{CONFIGURATION_FILE}: #{e.message}" exit 1 end conf[:template_location] = TEMPLATE_LOCATION conf[:views] = VIEWS_LOCATION +conf[:debug_level] ||= 3 CloudServer.print_configuration(conf) @@ -70,21 +75,28 @@ CloudServer.print_configuration(conf) # Sinatra Configuration ############################################################################## set :config, conf -set :bind, settings.config[:server] -set :port, settings.config[:port] + +include CloudLogger +enable_logging EC2_LOG, settings.config[:debug_level].to_i if CloudServer.is_port_open?(settings.config[:server], settings.config[:port]) - puts "Port busy, please shutdown the service or move econe server port." - exit 1 + settings.logger.error { + "Port #{settings.config[:port]} busy, please shutdown " << + "the service or move occi server port." + } + exit -1 end +set :bind, settings.config[:server] +set :port, settings.config[:port] + begin ENV["ONE_CIPHER_AUTH"] = EC2_AUTH - cloud_auth = CloudAuth.new(settings.config) + cloud_auth = CloudAuth.new(settings.config, settings.logger) rescue => e - puts "Error initializing authentication system" - puts e.message + settings.logger.error {"Error initializing authentication system"} + settings.logger.error {e.message} exit -1 end @@ -116,6 +128,7 @@ before do params['econe_path'] = settings.econe_path username = settings.cloud_auth.auth(request.env, params) rescue Exception => e + logger.error {e.message} error 500, error_xml("AuthFailure", 0) end @@ -123,7 +136,7 @@ before do error 401, error_xml("AuthFailure", 0) else client = settings.cloud_auth.client(username) - @econe_server = EC2QueryServer.new(client, settings.config) + @econe_server = EC2QueryServer.new(client, settings.config, settings.logger) end end @@ -179,6 +192,7 @@ def do_http_request(params) end if OpenNebula::is_error?(result) + logger.error(result.message) error rc, error_xml(result.message, 0) end diff --git a/src/cloud/occi/bin/occi-server b/src/cloud/occi/bin/occi-server index c7306756c7..5218f42e77 100755 --- a/src/cloud/occi/bin/occi-server +++ b/src/cloud/occi/bin/occi-server @@ -53,7 +53,7 @@ setup() start() { if [ ! -x "$OCCI_SERVER" ]; then - echo "Can not find $OCCI_SERVER." + echo "Cannot find $OCCI_SERVER." exit 1 fi diff --git a/src/cloud/occi/etc/occi-server.conf b/src/cloud/occi/etc/occi-server.conf index 7d42afbf3d..5ab9849e09 100644 --- a/src/cloud/occi/etc/occi-server.conf +++ b/src/cloud/occi/etc/occi-server.conf @@ -34,8 +34,8 @@ # x509, for x509 certificate encryption of tokens :core_auth: cipher -# Life-time in seconds for token renewal (that used to handle OpenNebula auths) -:token_expiration_delta: 1800 +# 0 = ERROR, 1 = WARNING, 2 = INFO, 3 = DEBUG +:debug_level: 3 # VM types allowed and its template file (inside templates directory) :instance_types: diff --git a/src/cloud/occi/lib/OCCIClient.rb b/src/cloud/occi/lib/OCCIClient.rb index 4b30b9fb2c..c600599a18 100755 --- a/src/cloud/occi/lib/OCCIClient.rb +++ b/src/cloud/occi/lib/OCCIClient.rb @@ -131,7 +131,7 @@ module OCCIClient file_path="/"+m[1] end elsif !image_info.elements['TYPE'] == "DATABLOCK" - return CloudClient::Error.new("Can not find URL") + return CloudClient::Error.new("Cannot find URL") end if curb @@ -316,7 +316,7 @@ module OCCIClient end if info.elements['ID'] == nil - return CloudClient::Error.new("Can not find RESOURCE ID") + return CloudClient::Error.new("Cannot find RESOURCE ID") end resource_id = info.elements['ID'].text diff --git a/src/cloud/occi/lib/OCCIServer.rb b/src/cloud/occi/lib/OCCIServer.rb index 193132c30b..a3102da56c 100755 --- a/src/cloud/occi/lib/OCCIServer.rb +++ b/src/cloud/occi/lib/OCCIServer.rb @@ -52,8 +52,8 @@ class OCCIServer < CloudServer # Server initializer # config_file:: _String_ path of the config file # template:: _String_ path to the location of the templates - def initialize(client, config) - super(config) + def initialize(client, config, logger) + super(config, logger) if config[:ssl_server] @base_url=config[:ssl_server] @@ -81,10 +81,10 @@ class OCCIServer < CloudServer ############################################################################ def get_collections(request) - xml_resp = "\n" + xml_resp = "" - COLLECTIONS.each { |c| - xml_resp << "\t<#{c.upcase}_COLLECTION href=\"#{@base_url}/#{c}\">\n" + COLLECTIONS.sort.each { |c| + xml_resp << "<#{c.upcase}_COLLECTION href=\"#{@base_url}/#{c}\"/>" } xml_resp << "" @@ -97,7 +97,7 @@ class OCCIServer < CloudServer <%= name.to_s %> <%= name.to_s %> - <% opts.each { |elem, value| + <% opts.sort{|k1,k2| k1[0].to_s<=>k2[0].to_s}.each { |elem, value| next if elem==:template str = elem.to_s.upcase %> <<%= str %>><%= value %>> @@ -106,9 +106,11 @@ class OCCIServer < CloudServer } def get_instance_types(request) - xml_resp = "\n" + xml_resp = "" - @config[:instance_types].each { |name, opts| + @config[:instance_types].sort { |k1,k2| + k1[0].to_s<=>k2[0].to_s + }.each { |name, opts| if request.params['verbose'] begin occi_it = ERB.new(INSTANCE_TYPE) @@ -120,7 +122,7 @@ class OCCIServer < CloudServer xml_resp << occi_it.gsub(/\n\s*/,'') else - xml_resp << "\t\n" + xml_resp << "" end } @@ -163,7 +165,7 @@ class OCCIServer < CloudServer return rc, CloudServer::HTTP_ERROR_CODE[rc.errno] end - return to_occi_xml(vmpool, :status=>200, :verbose=>request.params['verbose']) + return to_occi_xml(vmpool, :code=>200, :verbose=>request.params['verbose']) end @@ -183,7 +185,7 @@ class OCCIServer < CloudServer return rc, CloudServer::HTTP_ERROR_CODE[rc.errno] end - return to_occi_xml(network_pool, :status=>200, :verbose=>request.params['verbose']) + return to_occi_xml(network_pool, :code=>200, :verbose=>request.params['verbose']) end # Gets the pool representation of STORAGES @@ -202,7 +204,7 @@ class OCCIServer < CloudServer return rc, CloudServer::HTTP_ERROR_CODE[rc.errno] end - return to_occi_xml(image_pool, :status=>200, :verbose=>request.params['verbose']) + return to_occi_xml(image_pool, :code=>200, :verbose=>request.params['verbose']) end # Gets the pool representation of USERs @@ -219,7 +221,7 @@ class OCCIServer < CloudServer return rc, CloudServer::HTTP_ERROR_CODE[rc.errno] end - return to_occi_xml(user_pool, :status=>200, :verbose=>request.params['verbose']) + return to_occi_xml(user_pool, :code=>200, :verbose=>request.params['verbose']) end ############################################################################ @@ -255,7 +257,7 @@ class OCCIServer < CloudServer # --- Prepare XML Response --- vm.info - return to_occi_xml(vm, :status=>201) + return to_occi_xml(vm, :code=>201) end # Get the representation of a COMPUTE resource @@ -274,7 +276,7 @@ class OCCIServer < CloudServer return rc, CloudServer::HTTP_ERROR_CODE[rc.errno] end - return to_occi_xml(vm, :status=>200) + return to_occi_xml(vm, :code=>200) end # Deletes a COMPUTE resource @@ -317,7 +319,7 @@ class OCCIServer < CloudServer return result, code else vm.info - return to_occi_xml(vm, :status=>code) + return to_occi_xml(vm, :code=>code) end end @@ -347,7 +349,7 @@ class OCCIServer < CloudServer # --- Prepare XML Response --- network.info - return to_occi_xml(network, :status=>201) + return to_occi_xml(network, :code=>201) end # Retrieves a NETWORK resource @@ -365,7 +367,7 @@ class OCCIServer < CloudServer return rc, CloudServer::HTTP_ERROR_CODE[rc.errno] end - return to_occi_xml(network, :status=>200) + return to_occi_xml(network, :code=>200) end # Deletes a NETWORK resource @@ -411,7 +413,7 @@ class OCCIServer < CloudServer # --- Prepare XML Response --- vnet.info - return to_occi_xml(vnet, :status=>202) + return to_occi_xml(vnet, :code=>202) end ############################################################################ @@ -457,7 +459,7 @@ class OCCIServer < CloudServer end # --- Prepare XML Response --- - return to_occi_xml(image, :status=>201) + return to_occi_xml(image, :code=>201) end # Get a STORAGE resource @@ -476,7 +478,7 @@ class OCCIServer < CloudServer end # --- Prepare XML Response --- - return to_occi_xml(image, :status=>200) + return to_occi_xml(image, :code=>200) end # Deletes a STORAGE resource (Not yet implemented) @@ -530,7 +532,7 @@ class OCCIServer < CloudServer # --- Prepare XML Response --- image.info - return to_occi_xml(image, :status=>202) + return to_occi_xml(image, :code=>202) end # Get the representation of a USER @@ -549,7 +551,7 @@ class OCCIServer < CloudServer return rc, CloudServer::HTTP_ERROR_CODE[rc.errno] end - return to_occi_xml(user, :status=>200) + return to_occi_xml(user, :code=>200) end ############################################################################ @@ -566,7 +568,7 @@ class OCCIServer < CloudServer return [404, error] end - vnc_proxy = OpenNebulaVNC.new(config,{:json_errors => false}) + vnc_proxy = OpenNebulaVNC.new(config, logger, {:json_errors => false}) return vnc_proxy.start(vm) end @@ -574,7 +576,8 @@ class OCCIServer < CloudServer begin OpenNebulaVNC.stop(pipe) rescue Exception => e - return [500, e.message] + logger.error {e.message} + return [500, "Error stopping VNC. Please check server logs."] end return [200,nil] diff --git a/src/cloud/occi/lib/occi-server.rb b/src/cloud/occi/lib/occi-server.rb index 10b814e5f2..851d58dc5c 100755 --- a/src/cloud/occi/lib/occi-server.rb +++ b/src/cloud/occi/lib/occi-server.rb @@ -25,18 +25,22 @@ ONE_LOCATION=ENV["ONE_LOCATION"] if !ONE_LOCATION - RUBY_LIB_LOCATION="/usr/lib/one/ruby" + LOG_LOCATION = "/var/log/one" VAR_LOCATION = "/var/lib/one" - TEMPLATE_LOCATION="/etc/one/occi_templates" - CONFIGURATION_FILE = "/etc/one/occi-server.conf" + ETC_LOCATION = "/etc/one" + RUBY_LIB_LOCATION = "/usr/lib/one/ruby" else - RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby" - VAR_LOCATION = ONE_LOCATION+"/var" - TEMPLATE_LOCATION=ONE_LOCATION+"/etc/occi_templates" - CONFIGURATION_FILE = ONE_LOCATION+"/etc/occi-server.conf" + VAR_LOCATION = ONE_LOCATION + "/var" + LOG_LOCATION = ONE_LOCATION + "/var" + ETC_LOCATION = ONE_LOCATION + "/etc" + RUBY_LIB_LOCATION = ONE_LOCATION+"/lib/ruby" end -OCCI_AUTH = VAR_LOCATION + "/.one/occi_auth" +OCCI_AUTH = VAR_LOCATION + "/.one/occi_auth" +OCCI_LOG = LOG_LOCATION + "/occi-server.log" +CONFIGURATION_FILE = ETC_LOCATION + "/occi-server.conf" + +TEMPLATE_LOCATION = ETC_LOCATION + "/occi_templates" $: << RUBY_LIB_LOCATION $: << RUBY_LIB_LOCATION+"/cloud/occi" @@ -59,42 +63,55 @@ require 'CloudAuth' include OpenNebula ############################################################################## -# Parse Configuration file +# Configuration ############################################################################## +# Set Configuration settings begin conf = YAML.load_file(CONFIGURATION_FILE) rescue Exception => e - puts "Error parsing config file #{CONFIGURATION_FILE}: #{e.message}" + STDERR.puts "Error parsing config file #{CONFIGURATION_FILE}: #{e.message}" exit 1 end conf[:template_location] = TEMPLATE_LOCATION +conf[:debug_level] ||= 3 CloudServer.print_configuration(conf) -############################################################################## -# Sinatra Configuration -############################################################################## +set :config, conf + + +# Enable Logger +include CloudLogger +enable_logging OCCI_LOG, settings.config[:debug_level].to_i + + +# Set Sinatra configuration use Rack::Session::Pool, :key => 'occi' + set :public, Proc.new { File.join(root, "ui/public") } set :views, settings.root + '/ui/views' -set :config, conf if CloudServer.is_port_open?(settings.config[:server], settings.config[:port]) - puts "Port busy, please shutdown the service or move occi server port." - exit + settings.logger.error { + "Port #{settings.config[:port]} busy, please shutdown " << + "the service or move occi server port." + } + exit -1 end set :bind, settings.config[:server] set :port, settings.config[:port] + +# Create CloudAuth begin ENV["ONE_CIPHER_AUTH"] = OCCI_AUTH - cloud_auth = CloudAuth.new(settings.config) + cloud_auth = CloudAuth.new(settings.config, settings.logger) rescue => e - puts "Error initializing authentication system" - puts e.message + settings.logger.error {"Error initializing authentication system"} + settings.logger.error {e.message} exit -1 end @@ -110,17 +127,21 @@ before do begin username = settings.cloud_auth.auth(request.env, params) rescue Exception => e - error 500, e.message + logger.error {e.message} + error 500, "" end else username = session[:user] end if username.nil? #unable to authenticate + logger.error {"User not authorized"} error 401, "" else client = settings.cloud_auth.client(username) - @occi_server = OCCIServer.new(client, settings.config) + @occi_server = OCCIServer.new(client, + settings.config, + settings.logger) end end end @@ -147,20 +168,24 @@ helpers do begin username = settings.cloud_auth.auth(request.env, params) rescue Exception => e - error 500, e.message + logger.error {e.message} + error 500, "" end if username.nil? + logger.error {"User not authorized"} error 401, "" else client = settings.cloud_auth.client(username) - @occi_server = OCCIServer.new(client, settings.config) + @occi_server = OCCIServer.new(client, + settings.config, + settings.logger) user_id = OpenNebula::User::SELF user = OpenNebula::User.new_with_id(user_id, client) rc = user.info if OpenNebula.is_error?(rc) - # Add a log message + logger.error {rc.message} return [500, ""] end @@ -190,6 +215,7 @@ helpers do def treat_response(result,rc) if OpenNebula::is_error?(result) + logger.error {result.message} halt rc, result.message end diff --git a/src/cloud/occi/lib/ui/public/css/login.css b/src/cloud/occi/lib/ui/public/css/login.css index 2fdd890a84..b58bacd20f 100644 --- a/src/cloud/occi/lib/ui/public/css/login.css +++ b/src/cloud/occi/lib/ui/public/css/login.css @@ -132,12 +132,19 @@ div#login input#login_btn:hover { } .error_message { + width: 400px; + margin-left: auto; + margin-right: auto; display: none; position: relative; top: 80px; - font-family: Arial, Helvetica, sans-serif; - color:red; - font-size:1.6em; + font-size:1.0em; +} + +#login_spinner { + left: 44px; + position: relative; + top: 2px; } #label_remember { diff --git a/src/cloud/occi/lib/ui/public/js/login.js b/src/cloud/occi/lib/ui/public/js/login.js index 721200f945..363fb781fd 100644 --- a/src/cloud/occi/lib/ui/public/js/login.js +++ b/src/cloud/occi/lib/ui/public/js/login.js @@ -24,14 +24,20 @@ function auth_error(req, error){ switch (status){ case 401: - $("#one_error").hide(); - $("#auth_error").fadeIn("slow"); + $("#error_box").text("Invalid username or password"); break; case 500: - $("#auth_error").hide(); - $("#one_error").fadeIn("slow"); + $("#error_box").text("OpenNebula is not running or there was a server exception. Please check the server logs."); break; + case 0: + $("#error_box").text("No answer from server. Is it running?"); + break; + default: + $("#error_box").text("Unexpected error. Status "+status+". Check the server logs."); + }; + $("#error_box").fadeIn("slow"); + $("#login_spinner").hide(); } function authenticate(){ @@ -40,6 +46,9 @@ function authenticate(){ password = Crypto.SHA1(password); var remember = $("#check_remember").is(":checked"); + $("#error_box").fadeOut("slow"); + $("#login_spinner").show(); + var obj = { data: {username: username, password: password}, remember: remember, @@ -70,4 +79,5 @@ $(document).ready(function(){ }; $("input#username.box").focus(); + $("#login_spinner").hide(); }); diff --git a/src/cloud/occi/lib/ui/public/js/occi.js b/src/cloud/occi/lib/ui/public/js/occi.js index a818fe8008..a841b00ded 100644 --- a/src/cloud/occi/lib/ui/public/js/occi.js +++ b/src/cloud/occi/lib/ui/public/js/occi.js @@ -189,7 +189,7 @@ var OCCI = { $.ajax({ url: resource.toLowerCase(), type: "GET", - data: {timeout: timeout}, + data: {timeout: timeout, verbose: true}, dataType: "xml ONEjson", success: function(response){ var res = {}; diff --git a/src/cloud/occi/lib/ui/public/js/plugins/compute.js b/src/cloud/occi/lib/ui/public/js/plugins/compute.js index 5613a1b3a2..99402b25a0 100644 --- a/src/cloud/occi/lib/ui/public/js/plugins/compute.js +++ b/src/cloud/occi/lib/ui/public/js/plugins/compute.js @@ -153,13 +153,6 @@ var vm_actions = { error: onError }, - "VM.showstate" : { - type: "single", - call: OCCI.VM.show, - callback: updateVMStateCB, - error: onError - }, - "VM.refresh" : { type: "custom", call : function (){ @@ -178,7 +171,7 @@ var vm_actions = { "VM.suspend" : { type: "multiple", call: OCCI.VM.suspend, - callback: updateVMStateCB, + callback: updateVMachineElement, elements: vmElements, error: onError, notify: true @@ -187,7 +180,7 @@ var vm_actions = { "VM.resume" : { type: "multiple", call: OCCI.VM.resume, - callback: updateVMStateCB, + callback: updateVMachineElement, elements: vmElements, error: onError, notify: true @@ -196,7 +189,7 @@ var vm_actions = { "VM.stop" : { type: "multiple", call: OCCI.VM.stop, - callback: updateVMStateCB, + callback: updateVMachineElement, elements: vmElements, error: onError, notify: true @@ -214,7 +207,7 @@ var vm_actions = { "VM.shutdown" : { type: "multiple", call: OCCI.VM.shutdown, - callback: updateVMStateCB, + callback: updateVMachineElement, elements: vmElements, error: onError, notify: true @@ -223,7 +216,7 @@ var vm_actions = { "VM.cancel" : { type: "multiple", call: OCCI.VM.cancel, - callback: updateVMStateCB, + callback: updateVMachineElement, elements: vmElements, error: onError, notify: true @@ -240,7 +233,7 @@ var vm_actions = { "VM.saveas" : { type: "single", call: OCCI.VM.saveas, - callback: updateVMStateCB, + callback: updateVMachineElement, error:onError }, @@ -259,7 +252,7 @@ var vm_actions = { }; var options = ""; for (var i = 0; i'+type+''; }; $('#dialog select#instance_type').html(options); @@ -423,7 +416,7 @@ function vMachineElementArray(vm_json){ return [ '', id, - name + VMStateBulletStr(vm_json) + name ]; } @@ -473,16 +466,15 @@ function updateVMachinesView(request, vmachine_list){ $.each(vmachine_list,function(){ el_array = vMachineElementArray(this); vmachine_list_array.push(el_array); - Sunstone.runAction("VM.showstate",el_array[1]); }); updateView(vmachine_list_array,dataTable_vMachines); updateDashboard("vms",vmachine_list); }; -function updateVMStateCB(request,vm){ +function VMStateBulletStr(vm){ var vm_state = vm.COMPUTE.STATE; - var state_html = vm_state; + var state_html = ""; switch (vm_state) { case "INIT": case "PENDING": @@ -499,13 +491,8 @@ function updateVMStateCB(request,vm){ state_html = ''+vm_state+''; break; }; - - var tag = 'input#vm_'+vm.COMPUTE.ID; - var array = vMachineElementArray(vm); - array[2] = state_html + array[2]; - updateSingleElement(array,dataTable_vMachines,tag); -}; - + return state_html; +} // Refreshes the information panel for a VM function updateVMInfo(request,vm){ diff --git a/src/cloud/occi/lib/ui/templates/login.html b/src/cloud/occi/lib/ui/templates/login.html index 82b80c0785..8bf6d0c005 100644 --- a/src/cloud/occi/lib/ui/templates/login.html +++ b/src/cloud/occi/lib/ui/templates/login.html @@ -3,7 +3,7 @@ OpenNebula Self-Service Login - + @@ -28,11 +28,7 @@
-
- Invalid username or password -
-
- OpenNebula is not running +
@@ -46,7 +42,7 @@ - + retrieving
diff --git a/src/cloud/occi/test/fixtures/compute/empty.xml b/src/cloud/occi/test/fixtures/compute/empty.xml new file mode 100644 index 0000000000..17ef393d05 --- /dev/null +++ b/src/cloud/occi/test/fixtures/compute/empty.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/cloud/occi/test/fixtures/compute/first_compute.xml b/src/cloud/occi/test/fixtures/compute/first_compute.xml new file mode 100644 index 0000000000..4824a2b00e --- /dev/null +++ b/src/cloud/occi/test/fixtures/compute/first_compute.xml @@ -0,0 +1,20 @@ + + 0 + + oneadmin + 1 + 1024 + Compute + small + PENDING + + + DISK + hde + + + + 192.168.1.1 + 02:00:c0:a8:01:01 + + diff --git a/src/cloud/occi/test/fixtures/compute/first_compute_done.xml b/src/cloud/occi/test/fixtures/compute/first_compute_done.xml new file mode 100644 index 0000000000..46bd2c8352 --- /dev/null +++ b/src/cloud/occi/test/fixtures/compute/first_compute_done.xml @@ -0,0 +1,20 @@ + + 0 + + oneadmin + 1 + 1024 + Compute + small + DONE + + + DISK + hde + + + + 192.168.1.1 + 02:00:c0:a8:01:01 + + diff --git a/src/cloud/occi/test/fixtures/compute/second_compute.xml b/src/cloud/occi/test/fixtures/compute/second_compute.xml new file mode 100644 index 0000000000..ee057ed43e --- /dev/null +++ b/src/cloud/occi/test/fixtures/compute/second_compute.xml @@ -0,0 +1,20 @@ + + 1 + + users + 1 + 1024 + Compute2 + small + PENDING + + + DISK + hde + + + + 192.168.2.1 + 02:00:c0:a8:02:01 + + diff --git a/src/cloud/occi/test/fixtures/compute/second_compute_done.xml b/src/cloud/occi/test/fixtures/compute/second_compute_done.xml new file mode 100644 index 0000000000..e73c28ba3b --- /dev/null +++ b/src/cloud/occi/test/fixtures/compute/second_compute_done.xml @@ -0,0 +1,20 @@ + + 1 + + users + 1 + 1024 + Compute2 + small + DONE + + + DISK + hde + + + + 192.168.2.1 + 02:00:c0:a8:02:01 + + diff --git a/src/cloud/occi/test/fixtures/instance_type/extended.xml b/src/cloud/occi/test/fixtures/instance_type/extended.xml new file mode 100644 index 0000000000..f774763320 --- /dev/null +++ b/src/cloud/occi/test/fixtures/instance_type/extended.xml @@ -0,0 +1,20 @@ + + + large + large + 8 + 8192 + + + medium + medium + 4 + 4096 + + + small + small + 1 + 1024 + + diff --git a/src/cloud/occi/test/fixtures/instance_type/list.xml b/src/cloud/occi/test/fixtures/instance_type/list.xml new file mode 100644 index 0000000000..135ae70491 --- /dev/null +++ b/src/cloud/occi/test/fixtures/instance_type/list.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/cloud/occi/test/fixtures/network/empty.xml b/src/cloud/occi/test/fixtures/network/empty.xml new file mode 100644 index 0000000000..c96d82e6ed --- /dev/null +++ b/src/cloud/occi/test/fixtures/network/empty.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/cloud/occi/test/fixtures/network/first_net.xml b/src/cloud/occi/test/fixtures/network/first_net.xml new file mode 100644 index 0000000000..24b388783d --- /dev/null +++ b/src/cloud/occi/test/fixtures/network/first_net.xml @@ -0,0 +1,11 @@ + + 0 + Network + + oneadmin + Network of the user my_first_occi_user +
192.168.1.1
+ 125 + 0 + NO +
diff --git a/src/cloud/occi/test/fixtures/network/second_net.xml b/src/cloud/occi/test/fixtures/network/second_net.xml new file mode 100644 index 0000000000..9cad2d9594 --- /dev/null +++ b/src/cloud/occi/test/fixtures/network/second_net.xml @@ -0,0 +1,11 @@ + + 1 + Network2 + + users + Network of the user my_second_occi_user +
192.168.2.1
+ 125 + 0 + NO +
diff --git a/src/cloud/occi/test/fixtures/root.xml b/src/cloud/occi/test/fixtures/root.xml new file mode 100644 index 0000000000..38843f0418 --- /dev/null +++ b/src/cloud/occi/test/fixtures/root.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/cloud/occi/test/fixtures/storage/empty.xml b/src/cloud/occi/test/fixtures/storage/empty.xml new file mode 100644 index 0000000000..622d314777 --- /dev/null +++ b/src/cloud/occi/test/fixtures/storage/empty.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/cloud/occi/test/fixtures/storage/first_storage.xml b/src/cloud/occi/test/fixtures/storage/first_storage.xml new file mode 100644 index 0000000000..c24bea57ae --- /dev/null +++ b/src/cloud/occi/test/fixtures/storage/first_storage.xml @@ -0,0 +1,13 @@ + + 0 + Storage + + oneadmin + READY + DATABLOCK + Storage of the user my_first_occi_user + 100 + ext3 + NO + NO + diff --git a/src/cloud/occi/test/fixtures/storage/second_storage.xml b/src/cloud/occi/test/fixtures/storage/second_storage.xml new file mode 100644 index 0000000000..defd5b1a56 --- /dev/null +++ b/src/cloud/occi/test/fixtures/storage/second_storage.xml @@ -0,0 +1,13 @@ + + 1 + Storage2 + + users + READY + DATABLOCK + Storage of the user my_second_occi_user + 100 + ext3 + NO + NO + diff --git a/src/cloud/occi/test/spec/occi_spec.rb b/src/cloud/occi/test/spec/occi_spec.rb new file mode 100644 index 0000000000..ba35ae94dd --- /dev/null +++ b/src/cloud/occi/test/spec/occi_spec.rb @@ -0,0 +1,283 @@ +# -------------------------------------------------------------------------- # +# Copyright 2002-2012, 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. # +#--------------------------------------------------------------------------- # + +require File.expand_path(File.dirname(__FILE__) + '/spec_helper') + +# The following methods are helpers defined in spec_helper +# - compare_xml +# - get_fixture +# - network_template +# - storage_template +# - compute_template + +describe 'OCCI tests' do + before(:all) do + @user_oneadmin = "my_first_occi_user" + `oneuser create #{@user_oneadmin} my_pass`.scan(/^ID: (\d+)/) { |uid| + `oneuser show #{uid.first}`.scan(/PASSWORD\s*:\s*(\w*)/) { |password| + @user_pass = password.first.strip + } + + `oneuser chgrp #{uid.first} 0` + } + + @user_users = "my_second_occi_user" + `oneuser create #{@user_users} my_pass2`.scan(/^ID: (\d+)/) { |uid| + `oneuser show #{uid.first}`.scan(/PASSWORD\s*:\s*(\w*)/) { |password| + @user_pass2 = password.first.strip + } + } + + # Define BRIDGE attirbute in network.erb, otherwise the NETWORK creation will + `sed -i.bck "s%^#\\(BRIDGE = \\).*$%\\1 br0%" $ONE_LOCATION/etc/occi_templates/network.erb` + end + + describe "with a user of the oneadmin group" do + before(:each) do + basic_authorize(@user_oneadmin, @user_pass) + end + + it "should retrieve the list of collections" do + get '/' + compare_xml(last_response.body, get_fixture('/root.xml')) + last_response.status.should == 200 + end + + it "should retrieve the list of INSTANCE_TYPEs" do + get '/instance_type' + compare_xml(last_response.body, get_fixture('/instance_type/list.xml')) + last_response.status.should == 200 + end + + it "should retrieve the extended list of INSTANCE_TYPEs" do + get '/instance_type', {'verbose'=>true} + compare_xml(last_response.body, get_fixture('/instance_type/extended.xml')) + last_response.status.should == 200 + end + + context "for NETWORK" do + it "should retrieve the empty list" do + get '/network' + compare_xml(last_response.body, get_fixture('/network/empty.xml')) + last_response.status.should == 200 + end + + it "should create a new NETWORK" do + network = { + :name => "Network", + :description => "Network of the user #{@user_oneadmin}", + :address => "192.168.1.0", + :size => "100", + :pubic => "YES" + } + + post '/network', network_template(network) + compare_xml(last_response.body, get_fixture('/network/first_net.xml')) + last_response.status.should == 201 + end + + it "should retrieve the NETWORK with ID 0" do + get '/network/0' + compare_xml(last_response.body, get_fixture('/network/first_net.xml')) + last_response.status.should == 200 + end + end + + context "for STORAGE" do + it "should retrieve the empty list" do + get '/storage' + compare_xml(last_response.body, get_fixture('/storage/empty.xml')) + last_response.status.should == 200 + end + + it "should create a new STORAGE, type DATABLOCK. This request waits until the IMAGE is ready in OpenNebula" do + storage = { + :name => "Storage", + :description => "Storage of the user #{@user_oneadmin}", + :type => "DATABLOCK", + :size => "100", + :fstype => "ext3" + } + + post '/storage', {'occixml' => storage_template(storage)} + compare_xml(last_response.body, get_fixture('/storage/first_storage.xml')) + last_response.status.should == 201 + end + + it "should retrieve the STORAGE with ID 0" do + get '/storage/0' + compare_xml(last_response.body, get_fixture('/storage/first_storage.xml')) + last_response.status.should == 200 + end + end + + context "for COMPUTE" do + it "should retrieve the empty list" do + get '/compute' + compare_xml(last_response.body, get_fixture('/compute/empty.xml')) + last_response.status.should == 200 + end + + it "should create a new COMPUTE using the previous NETWORK (ID=0) and STORAGE(ID=0)" do + compute = { + :name => "Compute", + :instance_type => "small", + :disk => [ {:storage => '0'} ], + :nic => [ {:network => '0'} ] + } + + post '/compute', compute_template(compute) + compare_xml(last_response.body, get_fixture('/compute/first_compute.xml')) + last_response.status.should == 201 + end + + it "should retrieve the COMPUTE with ID 0" do + get '/compute/0' + compare_xml(last_response.body, get_fixture('/compute/first_compute.xml')) + last_response.status.should == 200 + end + + it "should terminate (DONE) the COMPUTE with ID 0" do + compute = { + :id => "0", + :state => "DONE" + } + + put '/compute/0', compute_action(compute) + compare_xml(last_response.body, get_fixture('/compute/first_compute_done.xml')) + last_response.status.should == 202 + end + end + end + + describe "with a user of the users group" do + before(:each) do + basic_authorize(@user_users, @user_pass2) + end + + it "should retrieve the list of collections" do + get '/' + compare_xml(last_response.body, get_fixture('/root.xml')) + last_response.status.should == 200 + end + + it "should retrieve the list of INSTANCE_TYPEs" do + get '/instance_type' + compare_xml(last_response.body, get_fixture('/instance_type/list.xml')) + last_response.status.should == 200 + end + + it "should retrieve the extended list of INSTANCE_TYPEs" do + get '/instance_type', {'verbose'=>true} + compare_xml(last_response.body, get_fixture('/instance_type/extended.xml')) + last_response.status.should == 200 + end + + context "for NETWORK" do + it "should retrieve the empty list" do + get '/network' + compare_xml(last_response.body, get_fixture('/network/empty.xml')) + last_response.status.should == 200 + end + + it "should create a new NETWORK" do + network = { + :name => "Network2", + :description => "Network of the user #{@user_users}", + :address => "192.168.2.0", + :size => "100", + :pubic => "YES" + } + + post '/network', network_template(network) + compare_xml(last_response.body, get_fixture('/network/second_net.xml')) + last_response.status.should == 201 + end + + it "should retrieve the NETWORK with ID 1" do + get '/network/1' + compare_xml(last_response.body, get_fixture('/network/second_net.xml')) + last_response.status.should == 200 + end + end + + context "for STORAGE" do + it "should retrieve the empty list" do + get '/storage' + compare_xml(last_response.body, get_fixture('/storage/empty.xml')) + last_response.status.should == 200 + end + + it "should create a new STORAGE, type DATABLOCK. This request waits until the IMAGE is ready in OpenNebula" do + storage = { + :name => "Storage2", + :description => "Storage of the user #{@user_users}", + :type => "DATABLOCK", + :size => "100", + :fstype => "ext3" + } + + post '/storage', {'occixml' => storage_template(storage)} + compare_xml(last_response.body, get_fixture('/storage/second_storage.xml')) + last_response.status.should == 201 + end + + it "should retrieve the STORAGE with ID 1" do + get '/storage/1' + compare_xml(last_response.body, get_fixture('/storage/second_storage.xml')) + last_response.status.should == 200 + end + end + + context "for COMPUTE" do + it "should retrieve the empty list" do + get '/compute' + compare_xml(last_response.body, get_fixture('/compute/empty.xml')) + last_response.status.should == 200 + end + + it "should create a new COMPUTE using the previous NETWORK (ID=1) and STORAGE(ID=1)" do + compute = { + :name => "Compute2", + :instance_type => "small", + :disk => [ {:storage => '1'} ], + :nic => [ {:network => '1'} ] + } + + post '/compute', compute_template(compute) + compare_xml(last_response.body, get_fixture('/compute/second_compute.xml')) + last_response.status.should == 201 + end + + it "should retrieve the COMPUTE with ID 1" do + get '/compute/1' + compare_xml(last_response.body, get_fixture('/compute/second_compute.xml')) + last_response.status.should == 200 + end + + it "should terminate (DONE) the COMPUTE with ID 1" do + compute = { + :id => "1", + :state => "DONE" + } + + put '/compute/1', compute_action(compute) + compare_xml(last_response.body, get_fixture('/compute/second_compute_done.xml')) + last_response.status.should == 202 + end + end + end +end \ No newline at end of file diff --git a/src/cloud/occi/test/spec/spec.opts b/src/cloud/occi/test/spec/spec.opts new file mode 100644 index 0000000000..ad561bd258 --- /dev/null +++ b/src/cloud/occi/test/spec/spec.opts @@ -0,0 +1,4 @@ +--colour +--format progress +--loadby mtime +--reverse \ No newline at end of file diff --git a/src/cloud/occi/test/spec/spec_helper.rb b/src/cloud/occi/test/spec/spec_helper.rb index b2a2917a97..0d7423a2fc 100644 --- a/src/cloud/occi/test/spec/spec_helper.rb +++ b/src/cloud/occi/test/spec/spec_helper.rb @@ -24,6 +24,8 @@ require 'rubygems' require 'rspec' require 'rack/test' +require 'rexml/document' + # Load the Sinatra app require 'occi-server' @@ -39,3 +41,153 @@ set :environment, :test def app Sinatra::Application end + + + +def get_fixture(path) + File.read(FIXTURES_PATH + path).strip +end + + +def compare_xml(a, b) + a = REXML::Document.new(a.to_s) + b = REXML::Document.new(b.to_s) + + normalized = Class.new(REXML::Formatters::Pretty) do + def write_text(node, output) + super(node.to_s.strip, output) + end + end + + normalized.new(indentation=0,ie_hack=false).write(node=a, a_normalized='') + normalized.new(indentation=0,ie_hack=false).write(node=b, b_normalized='') + + a_normalized.should == b_normalized +end + + +OCCI_NETWORK = %q{ + + <% if hash[:name] %> + <%= hash[:name] %> + <% end %> + + <% if hash[:description] %> + <%= hash[:description] %> + <% end %> + + <% if hash[:address] %> +
<%= hash[:address] %>
+ <% end %> + + <% if hash[:size] %> + <%= hash[:size] %> + <% end %> + + <% if hash[:public] %> + <%= hash[:public] %> + <% end %> +
+} + +def network_template(hash) + ERB.new(OCCI_NETWORK).result(binding) +end + +OCCI_IMAGE = %q{ + + <% if hash[:name] %> + <%= hash[:name] %> + <% end %> + + <% if hash[:type] %> + <%= hash[:type] %> + <% end %> + + <% if hash[:description] %> + <%= hash[:description] %> + <% end %> + + <% if hash[:size] %> + <%= hash[:size] %> + <% end %> + + <% if hash[:fstype] %> + <%= hash[:fstype] %> + <% end %> + + <% if hash[:public] %> + <%= hash[:public] %> + <% end %> + + <% if hash[:persistent] %> + <%= hash[:persistent] %> + <% end %> + +} + +def storage_template(hash) + ERB.new(OCCI_IMAGE).result(binding) +end + +OCCI_VM = %q{ + + <% if hash[:name] %> + <%= hash[:name] %> + <% end %> + + <% if hash[:instance_type] %> + + <% end %> + + <% if hash[:disk] %> + <% hash[:disk].each { |disk| %> + + <% if disk[:storage] %> + + <% end %> + + <% } %> + <% end %> + + <% if hash[:nic] %> + <% hash[:nic].each { |nic| %> + + <% if nic[:network] %> + + <% end %> + <% if nic[:ip] %> + <%= nic[:ip] %> + <% end %> + + <% } %> + <% end %> + + <% if hash[:context] %> + + <% hash[:context].each { |key, value| %> + <<%= key.to_s.upcase %>><%= value %>> + <% } %> + + <% end %> + +} + +OCCI_VM_ACTION = %q{ + + <% if hash[:id] %> + <%= hash[:id] %> + <% end %> + <% if hash[:state] %> + <%= hash[:state] %> + <% end %> + +} + +def compute_template(hash) + ERB.new(OCCI_VM).result(binding) +end + +def compute_action(hash) + ERB.new(OCCI_VM_ACTION).result(binding) +end diff --git a/src/datastore_mad/remotes/libfs.sh b/src/datastore_mad/remotes/libfs.sh index 76a91c6227..a4d180a94c 100644 --- a/src/datastore_mad/remotes/libfs.sh +++ b/src/datastore_mad/remotes/libfs.sh @@ -23,7 +23,7 @@ # @param $3 - Safe dirs # @param $4 - Umask for new file creation (default: 0007) # @return sets the following environment variables -# - RESTRICTED_DIRS: Paths that can not be used to register images +# - RESTRICTED_DIRS: Paths that cannot be used to register images # - SAFE_DIRS: Paths that are safe to specify image paths # - BASE_PATH: Path where the images will be stored #------------------------------------------------------------------------------ diff --git a/src/dm/DispatchManagerActions.cc b/src/dm/DispatchManagerActions.cc index f945c98944..4907ed7194 100644 --- a/src/dm/DispatchManagerActions.cc +++ b/src/dm/DispatchManagerActions.cc @@ -664,7 +664,7 @@ int DispatchManager::resubmit(int vid) { case VirtualMachine::SUSPENDED: NebulaLog::log("DiM",Log::ERROR, - "Can not resubmit a suspended VM. Resume it first"); + "Cannot resubmit a suspended VM. Resume it first"); rc = -2; break; @@ -688,7 +688,7 @@ int DispatchManager::resubmit(int vid) break; case VirtualMachine::DONE: NebulaLog::log("DiM",Log::ERROR, - "Can not resubmit a VM already in DONE state"); + "Cannot resubmit a VM already in DONE state"); rc = -2; break; } diff --git a/src/group/GroupPool.cc b/src/group/GroupPool.cc index a476669b06..b12cda200f 100644 --- a/src/group/GroupPool.cc +++ b/src/group/GroupPool.cc @@ -22,7 +22,7 @@ /* -------------------------------------------------------------------------- */ /* There are two default groups boostrapped by the core: */ -/* - oneadmin can not be removed */ +/* - oneadmin cannot be removed */ /* - users to place regular users by default */ /* The first 100 group IDs are reserved for system groups. Regular ones start */ /* from ID 100 */ diff --git a/src/hm/HookManager.cc b/src/hm/HookManager.cc index 8555d1c4ad..f49a21ea92 100644 --- a/src/hm/HookManager.cc +++ b/src/hm/HookManager.cc @@ -49,12 +49,15 @@ void HookManager::load_mads(int uid) { HookManagerDriver * hm_mad; ostringstream oss; - const VectorAttribute * vattr; + const VectorAttribute * vattr = 0; int rc; NebulaLog::log("HKM",Log::INFO,"Loading Hook Manager driver."); - vattr = static_cast(mad_conf[0]); + if ( mad_conf.size() > 0 ) + { + vattr = static_cast(mad_conf[0]); + } if ( vattr == 0 ) { diff --git a/src/host/test/HostPoolTest.cc b/src/host/test/HostPoolTest.cc index d3e81a802d..9f02041dfc 100644 --- a/src/host/test/HostPoolTest.cc +++ b/src/host/test/HostPoolTest.cc @@ -267,7 +267,7 @@ public: CPPUNIT_ASSERT( oid_1 == -1 ); CPPUNIT_ASSERT( rc == oid_1 ); - // the hostname can not be repeated if the drivers change + // the hostname cannot be repeated if the drivers change rc = hp->allocate(&oid_1, names[0], im_mad_2, diff --git a/src/im_mad/remotes/vmware.d/vmware.rb b/src/im_mad/remotes/vmware.d/vmware.rb index b4c061656c..ea6920571e 100755 --- a/src/im_mad/remotes/vmware.d/vmware.rb +++ b/src/im_mad/remotes/vmware.d/vmware.rb @@ -106,7 +106,7 @@ conf = YAML::load(File.read(CONF_FILE)) rc, data = do_action("virsh -c #{@uri} --readonly nodeinfo") if rc == false - exit info + exit data end data.split(/\n/).each{|line| diff --git a/src/image/ImageManager.cc b/src/image/ImageManager.cc index e0fc6789ff..52c3ab9df8 100644 --- a/src/image/ImageManager.cc +++ b/src/image/ImageManager.cc @@ -50,12 +50,15 @@ void ImageManager::load_mads(int uid) { ImageManagerDriver * imagem_mad; ostringstream oss; - const VectorAttribute * vattr; + const VectorAttribute * vattr = 0; int rc; NebulaLog::log("ImM",Log::INFO,"Loading Image Manager driver."); - vattr = static_cast(mad_conf[0]); + if ( mad_conf.size() > 0 ) + { + vattr = static_cast(mad_conf[0]); + } if ( vattr == 0 ) { diff --git a/src/image/ImageManagerActions.cc b/src/image/ImageManagerActions.cc index 3b41c8d2c2..ad1b8e2627 100644 --- a/src/image/ImageManagerActions.cc +++ b/src/image/ImageManagerActions.cc @@ -95,7 +95,7 @@ int ImageManager::acquire_image(Image *img, string& error) case Image::USED: if (img->isPersistent()) { - error = "Cannot aquire persistent image, it is already in use"; + error = "Cannot acquire persistent image, it is already in use"; rc = -1; } else @@ -106,15 +106,15 @@ int ImageManager::acquire_image(Image *img, string& error) break; case Image::DISABLED: - error = "Cannot aquire image, it is disabled"; + error = "Cannot acquire image, it is disabled"; rc = -1; break; case Image::LOCKED: - error = "Cannot aquire image, it is locked"; + error = "Cannot acquire image, it is locked"; rc = -1; break; case Image::ERROR: - error = "Cannot aquire image, it is in an error state"; + error = "Cannot acquire image, it is in an error state"; rc = -1; break; default: @@ -276,13 +276,13 @@ int ImageManager::delete_image(int iid, const string& ds_data) if ( img->get_running() != 0 ) { img->unlock(); - return -1; //Can not remove images in use + return -1; //Cannot remove images in use } break; case Image::USED: img->unlock(); - return -1; //Can not remove images in use + return -1; //Cannot remove images in use break; case Image::INIT: diff --git a/src/mad/Mad.cc b/src/mad/Mad.cc index 98388228ee..e33c04cfdb 100644 --- a/src/mad/Mad.cc +++ b/src/mad/Mad.cc @@ -239,13 +239,13 @@ int Mad::start() error_exec: oss.str(""); - oss << "Can not load driver " << executable << ", " << strerror(errno); + oss << "Cannot load driver " << executable << ", " << strerror(errno); NebulaLog::log("MAD", Log::ERROR, oss); exit(-1); error_dup2: oss.str(""); - oss << "Can not duplicate descriptors, " << strerror(errno); + oss << "Cannot duplicate descriptors, " << strerror(errno); NebulaLog::log("MAD", Log::ERROR, oss); exit(-1); @@ -275,7 +275,7 @@ error_attributes: error_pipes: oss.str(""); - oss << "Can not create driver pipes, " << strerror(errno); + oss << "Cannot create driver pipes, " << strerror(errno); NebulaLog::log("MAD", Log::ERROR, oss); return -1; } diff --git a/src/nebula/oned.cc b/src/nebula/oned.cc index 3076c9f4fe..cfe7968607 100644 --- a/src/nebula/oned.cc +++ b/src/nebula/oned.cc @@ -127,7 +127,7 @@ int main(int argc, char **argv) if( fd == -1) { - cerr<< "Error: Can not start oned, opening lock file " << lockfile + cerr<< "Error: Cannot start oned, opening lock file " << lockfile << endl; exit(-1); @@ -186,7 +186,7 @@ int main(int argc, char **argv) return 0; error_chdir: - cerr << "Error: can not change to dir " << wd << "\n"; + cerr << "Error: cannot change to dir " << wd << "\n"; unlink(lockfile.c_str()); exit(-1); diff --git a/src/oca/java/test/oned.conf b/src/oca/java/test/oned.conf index de3fdf51df..7e88254166 100644 --- a/src/oca/java/test/oned.conf +++ b/src/oca/java/test/oned.conf @@ -6,7 +6,7 @@ # Daemon configuration attributes #------------------------------------------------------------------------------- # MANAGER_TIMER: Time in seconds the core uses to evaluate periodical functions. -# HOST_MONITORING_INTERVAL and VM_POLLING_INTERVAL can not have smaller values +# HOST_MONITORING_INTERVAL and VM_POLLING_INTERVAL cannot have smaller values # than MANAGER_TIMER. # # HOST_MONITORING_INTERVAL: Time in seconds between host monitorization. diff --git a/src/oca/ruby/OpenNebula/Group.rb b/src/oca/ruby/OpenNebula/Group.rb index 74d56ddbf3..3fa5a9a41c 100644 --- a/src/oca/ruby/OpenNebula/Group.rb +++ b/src/oca/ruby/OpenNebula/Group.rb @@ -69,7 +69,7 @@ module OpenNebula # Creates ACLs for the group. The ACL rules are described in a file def create_acls(filename = GROUP_DEFAULT) if !File.readable?(filename) - return -1, "Can not read deafult ACL file for group" + return -1, "Cannot read deafult ACL file for group" end msg = String.new diff --git a/src/onedb/test/oned_mysql.conf b/src/onedb/test/oned_mysql.conf index 164abeaf5d..7275333b2c 100644 --- a/src/onedb/test/oned_mysql.conf +++ b/src/onedb/test/oned_mysql.conf @@ -6,7 +6,7 @@ # Daemon configuration attributes #------------------------------------------------------------------------------- # MANAGER_TIMER: Time in seconds the core uses to evaluate periodical functions. -# HOST_MONITORING_INTERVAL and VM_POLLING_INTERVAL can not have smaller values +# HOST_MONITORING_INTERVAL and VM_POLLING_INTERVAL cannot have smaller values # than MANAGER_TIMER. # # HOST_MONITORING_INTERVAL: Time in seconds between host monitorization. @@ -390,7 +390,7 @@ HM_MAD = [ #-------------------------------- ebtables Hook--------------------------------- # You can use these two hooks to isolate networks at the ethernet level so the -# traffic generated in different virtual networks can not be seen in others. +# traffic generated in different virtual networks cannot be seen in others. # # All the network configuration will be done in the cluster nodes, these are the # additional requisites: diff --git a/src/onedb/test/oned_sqlite.conf b/src/onedb/test/oned_sqlite.conf index e8a6aca4f9..09f4189ba0 100644 --- a/src/onedb/test/oned_sqlite.conf +++ b/src/onedb/test/oned_sqlite.conf @@ -6,7 +6,7 @@ # Daemon configuration attributes #------------------------------------------------------------------------------- # MANAGER_TIMER: Time in seconds the core uses to evaluate periodical functions. -# HOST_MONITORING_INTERVAL and VM_POLLING_INTERVAL can not have smaller values +# HOST_MONITORING_INTERVAL and VM_POLLING_INTERVAL cannot have smaller values # than MANAGER_TIMER. # # HOST_MONITORING_INTERVAL: Time in seconds between host monitorization. @@ -390,7 +390,7 @@ HM_MAD = [ #-------------------------------- ebtables Hook--------------------------------- # You can use these two hooks to isolate networks at the ethernet level so the -# traffic generated in different virtual networks can not be seen in others. +# traffic generated in different virtual networks cannot be seen in others. # # All the network configuration will be done in the cluster nodes, these are the # additional requisites: diff --git a/src/ozones/Client/bin/onevdc b/src/ozones/Client/bin/onevdc index b584c7fb6f..1fb688a2b2 100755 --- a/src/ozones/Client/bin/onevdc +++ b/src/ozones/Client/bin/onevdc @@ -61,11 +61,12 @@ cmd=CommandParser::CmdParser.new(ARGV) do helper.create_resource(args[0], options) end - command :show, 'Show information of a particular VDC', :vdcid do + command :show, 'Show information of a particular VDC', :vdcid, + :options => OZonesHelper::JSON do helper.show_resource(args[0],options) end - command :list, 'Lists VDCs in the pool' do + command :list, 'Lists VDCs in the pool', :options => OZonesHelper::JSON do helper.list_pool(options) end diff --git a/src/ozones/Client/bin/onezone b/src/ozones/Client/bin/onezone index af922e7bcb..5eae35012e 100755 --- a/src/ozones/Client/bin/onezone +++ b/src/ozones/Client/bin/onezone @@ -71,8 +71,16 @@ cmd=CommandParser::CmdParser.new(ARGV) do onezone show 4 host EOT - command :show, show_desc, :zoneid, [:resource, nil] do - zone=helper.show_resource(args[0],options)[1] + command :show, show_desc, :zoneid, [:resource, nil], + :options => OZonesHelper::JSON do + zone = helper.show_resource(args[0],options)[1] + + #manually print here + if options[:json] + puts zone + end + + if !args[1] then next 0 end case args[1] when "host" @@ -87,35 +95,41 @@ cmd=CommandParser::CmdParser.new(ARGV) do aux_helper = OneTemplateHelper.new when "user" aux_helper = OneUserHelper.new - else - puts "\n:!: Pool #{args[1]} doesn't exist or is not supported\n\n" - next 0 + else + puts "\n:!: Pool #{args[1]} doesn't exist or is not supported\n\n" + next 0 end - pool_hash_data = helper.get_resource_pool("zone", zone[:ID], args[1]) + pool_hash_data = helper.get_resource_pool("zone", args[0], args[1], + options) - if pool_hash_data[0] != 0 - puts "\nError retrieving information for pool #{args[1]}. Reason: " + pool_hash_data[1] + "\n\n" + if pool_hash_data[0] != 0 + puts "\nError retrieving information for pool #{args[1]}. Reason: " + pool_hash_data[1] + "\n\n" next 0 - end + end - if !pool_hash_data[1] - next 0 + if !pool_hash_data[1] + next 0 + end + + if options[:json] + puts pool_hash_data[1] + next 0 end if pool_hash_data[1].is_a?(Hash) pool_hash_data[1]=[Hash.transform_keys_to_strings(pool_hash_data[1])] - else - pool_hash_data[1].each{|hash| hash.replace(Hash.transform_keys_to_strings(hash))} + else + pool_hash_data[1].each{|hash| hash.replace(Hash.transform_keys_to_strings(hash))} end table = aux_helper.format_pool(options) - table.show(pool_hash_data[1]) + table.show(pool_hash_data[1]) 0 end - command :list, 'Lists Zones in the pool' do + command :list, 'Lists Zones in the pool', :options=>OZonesHelper::JSON do helper.list_pool(options) end diff --git a/src/ozones/Client/lib/cli/ozones_helper.rb b/src/ozones/Client/lib/cli/ozones_helper.rb index 6ce320b5e8..cf13653354 100644 --- a/src/ozones/Client/lib/cli/ozones_helper.rb +++ b/src/ozones/Client/lib/cli/ozones_helper.rb @@ -18,6 +18,15 @@ require 'zona' module OZonesHelper + #Specific ozones CLI options + + JSON={ + :name => "json", + :short => "-j", + :large => "--json", + :description => "Show the resource in JSON format" + } + class OZHelper def initialize(user=nil, pass=nil, endpoint_str=nil, timeout=nil, debug_flag=true) @@ -45,8 +54,13 @@ module OZonesHelper if Zona::is_error?(rc) [-1, rc.message] else - pool=Zona::OZonesJSON.parse_json(rc.body, kind.upcase + "_POOL") - format_pool(pool, options) + if options[:json] + [0, rc.body] + else + resource_str = kind.upcase + "_POOL" + pool=Zona::OZonesJSON.parse_json(rc.body, resource_str) + format_pool(pool, options) + end end end @@ -56,18 +70,26 @@ module OZonesHelper if Zona::is_error?(rc) [-1, rc.message] else - resource=Zona::OZonesJSON.parse_json(rc.body, kind.upcase) - format_resource(resource, options) + if options[:json] + [0, rc.body] + else + resource=Zona::OZonesJSON.parse_json(rc.body, kind.upcase) + format_resource(resource, options) + end end end - def get_resource_pool(kind, id, pool) + def get_resource_pool(kind, id, pool, options) rc = @client.get_resource_pool(kind, id, pool) if Zona::is_error?(rc) [-1, rc.message] else - [0 , Zona::OZonesJSON.parse_json(rc.body, pool.upcase+"_POOL")[pool.upcase.to_sym]] + if options[:json] + [0, rc.body] + else + [0 , Zona::OZonesJSON.parse_json(rc.body, pool.upcase+"_POOL")[pool.upcase.to_sym]] + end end end diff --git a/src/ozones/Server/bin/ozones-server b/src/ozones/Server/bin/ozones-server index 7d71a28d8f..720aad1742 100755 --- a/src/ozones/Server/bin/ozones-server +++ b/src/ozones/Server/bin/ozones-server @@ -19,14 +19,14 @@ if [ -z "$ONE_LOCATION" ]; then OZONES_PID=/var/run/one/ozones.pid OZONES_LOCATION=/usr/lib/one/ozones - OZONES_SERVER=$OZONES_LOCATION/config.ru + OZONES_SERVER=$OZONES_LOCATION/ozones-server.rb OZONES_LOCK_FILE=/var/lock/one/.ozones.lock OZONES_LOG=/var/log/one/ozones-server.log OZONES_CONF=/etc/one/ozones-server.conf else OZONES_PID=$ONE_LOCATION/var/ozones.pid OZONES_LOCATION=$ONE_LOCATION/lib/ozones - OZONES_SERVER=$OZONES_LOCATION/config.ru + OZONES_SERVER=$OZONES_LOCATION/ozones-server.rb OZONES_LOCK_FILE=$ONE_LOCATION/var/.ozones.lock OZONES_LOG=$ONE_LOCATION/var/ozones-server.log OZONES_CONF=$ONE_LOCATION/etc/ozones-server.conf @@ -54,33 +54,30 @@ setup() start() { if [ ! -f "$OZONES_SERVER" ]; then - echo "Can not find $OZONES_SERVER." - exit 1 - fi - - HOST=`cat $OZONES_CONF|grep ^\:host\:|cut -d' ' -f 2` - PORT=`cat $OZONES_CONF|grep ^\:port\:|cut -d' ' -f 2` - - lsof -i:$PORT &> /dev/null - if [ $? -eq 0 ]; then - echo "The port $PORT is being used. Please specify a different one." + echo "Cannot find $OZONES_SERVER." exit 1 fi # Start the ozones daemon touch $OZONES_LOCK_FILE - rackup $OZONES_SERVER -s thin -p $PORT -o $HOST \ - -P $OZONES_PID &> $OZONES_LOG & + ruby $OZONES_SERVER > $OZONES_LOG 2>&1 & + LASTPID=$! + if [ $? -ne 0 ]; then + echo "Error executing $OZONES_SERVER, please check the log $OZONES_LOG" + exit 1 + else + echo $LASTPID > $OZONES_PID + fi sleep 2 - ps -p $(cat $OZONES_PID 2>/dev/null) > /dev/null 2>&1 + ps $LASTPID &> /dev/null if [ $? -ne 0 ]; then echo "Error executing $OZONES_SERVER, please check the log $OZONES_LOG" exit 1 fi - echo "ozones-server listening on $HOST:$PORT" + echo "ozones-server started" } # diff --git a/src/ozones/Server/config.ru b/src/ozones/Server/config.ru deleted file mode 100644 index b5e2604dee..0000000000 --- a/src/ozones/Server/config.ru +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/ruby - -# -------------------------------------------------------------------------- # -# Copyright 2002-2012, 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. # -#--------------------------------------------------------------------------- # - -$: << File.dirname(__FILE__) - -require 'ozones-server.rb' - -run Sinatra::Application diff --git a/src/ozones/Server/etc/ozones-server.conf b/src/ozones/Server/etc/ozones-server.conf index 022158205e..1fa3f0695b 100644 --- a/src/ozones/Server/etc/ozones-server.conf +++ b/src/ozones/Server/etc/ozones-server.conf @@ -19,13 +19,17 @@ ############################################## ###################### -# DB Options +# DB Options ###################### :databasetype: sqlite +#:databaseserver: dbuser:dbpassword@localhost #:htaccess: /var/www/.htaccess :dbdebug: no +# 0 = ERROR, 1 = WARNING, 2 = INFO, 3 = DEBUG +:debug_level: 3 + ##################### # Server Configuration ##################### diff --git a/src/ozones/Server/lib/OZones/ApacheWritter.rb b/src/ozones/Server/lib/OZones/ApacheWritter.rb index 327874a2e4..ca3ae1fdd3 100644 --- a/src/ozones/Server/lib/OZones/ApacheWritter.rb +++ b/src/ozones/Server/lib/OZones/ApacheWritter.rb @@ -28,12 +28,20 @@ module OZones zone.vdcs.all.each{|vdc| htaccess << "RewriteRule ^#{vdc.NAME} " + "#{zone.ENDPOINT} [P]\n" + if zone.SUNSENDPOINT != nil htaccess << "RewriteRule ^sunstone_#{vdc.NAME}/(.+) " + "#{zone.SUNSENDPOINT}/$1 [P]\n" htaccess << "RewriteRule ^sunstone_#{vdc.NAME} " + "#{zone.SUNSENDPOINT}/ [P]\n" end + + if zone.SELFENDPOINT != nil + htaccess << "RewriteRule ^self_#{vdc.NAME}/(.+) " + + "#{zone.SELFENDPOINT}/$1 [P]\n" + htaccess << "RewriteRule ^self_#{vdc.NAME} " + + "#{zone.SELFENDPOINT}/ [P]\n" + end } } diff --git a/src/ozones/Server/lib/OZones/Zones.rb b/src/ozones/Server/lib/OZones/Zones.rb index 5c1230945f..6e9aae9db7 100644 --- a/src/ozones/Server/lib/OZones/Zones.rb +++ b/src/ozones/Server/lib/OZones/Zones.rb @@ -30,6 +30,7 @@ module OZones property :ONEPASS, String, :required => true property :ENDPOINT, String, :required => true property :SUNSENDPOINT, String + property :SELFENDPOINT, String has n, :vdcs diff --git a/src/ozones/Server/models/OzonesServer.rb b/src/ozones/Server/models/OzonesServer.rb index 835d78b8f9..4b7a952af5 100644 --- a/src/ozones/Server/models/OzonesServer.rb +++ b/src/ozones/Server/models/OzonesServer.rb @@ -14,13 +14,16 @@ # limitations under the License. # #--------------------------------------------------------------------------- # +require 'CloudServer' + require 'JSONUtils' -class OzonesServer +class OzonesServer < CloudServer include OpenNebulaJSON::JSONUtils - def initialize(cipher) + def initialize(cipher, config, logger) + super(config, logger) #Set cipher for Zone classes OZones::Zones.cipher = cipher end @@ -214,7 +217,7 @@ class OzonesServer vdc = OZones::OpenNebulaVdc.new(id) rc = vdc.destroy rescue => e - return [404, OZones::Error.new("Error: Can not delete vdc. " \ + return [404, OZones::Error.new("Error: Cannot delete vdc. " \ "Reason: #{e.message}").to_json] end @@ -234,7 +237,7 @@ class OzonesServer rc = zone.destroy else return [404, - OZones::Error.new("Error: Can not delete " \ + OZones::Error.new("Error: Cannot delete " \ "zone. Reason: zone #{id} not found").to_json] end diff --git a/src/ozones/Server/ozones-server.rb b/src/ozones/Server/ozones-server.rb index 84dc77d9b7..70eb42323a 100755 --- a/src/ozones/Server/ozones-server.rb +++ b/src/ozones/Server/ozones-server.rb @@ -19,19 +19,25 @@ ONE_LOCATION=ENV["ONE_LOCATION"] if !ONE_LOCATION - ETC_LOCATION="/etc/one" - LIB_LOCATION="/usr/lib/one" - RUBY_LIB_LOCATION="/usr/lib/one/ruby" - VAR_LOCATION="/var/lib/one" + LOG_LOCATION = "/var/log/one" + VAR_LOCATION = "/var/lib/one" + ETC_LOCATION = "/etc/one" + LIB_LOCATION = "/usr/lib/one" + RUBY_LIB_LOCATION = "/usr/lib/one/ruby" else - ETC_LOCATION=ONE_LOCATION+"/etc" - LIB_LOCATION=ONE_LOCATION+"/lib" - RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby" - VAR_LOCATION=ONE_LOCATION+"/var" + VAR_LOCATION = ONE_LOCATION + "/var" + LOG_LOCATION = ONE_LOCATION + "/var" + ETC_LOCATION = ONE_LOCATION + "/etc" + LIB_LOCATION = ONE_LOCATION+"/lib" + RUBY_LIB_LOCATION = ONE_LOCATION+"/lib/ruby" end +OZONES_LOG = LOG_LOCATION + "/ozones-server.log" +CONFIGURATION_FILE = ETC_LOCATION + "/ozones-server.conf" + $: << LIB_LOCATION + "/sunstone/models" $: << RUBY_LIB_LOCATION +$: << RUBY_LIB_LOCATION+'/cloud' $: << LIB_LOCATION+'/ozones/models' $: << LIB_LOCATION+'/ozones/lib' $: << RUBY_LIB_LOCATION+"/cli" @@ -52,12 +58,46 @@ require 'OzonesServer' ############################################################################## # Read configuration ############################################################################## -config_data=File.read(ETC_LOCATION+'/ozones-server.conf') -config=YAML::load(config_data) +begin + config=YAML::load_file(CONFIGURATION_FILE) +rescue Exception => e + warn "Error parsing config file #{CONFIGURATION_FILE}: #{e.message}" + exit 1 +end + +config[:debug_level] ||= 3 + +CloudServer.print_configuration(config) db_type = config[:databasetype] -db_url = db_type + "://" + VAR_LOCATION + "/ozones.db" +case db_type + when "sqlite" then + db_url = db_type + "://" + VAR_LOCATION + "/ozones.db" + when "mysql","postgres" then + if config[:databaseserver].nil? + warn "DB server needed for this type of DB backend" + exit -1 + end + + db_url = db_type + "://" + config[:databaseserver] + "/ozones" + else + warn "DB type #{db_type} not recognized" + exit -1 +end + +############################################################################## +# Sinatra Configuration +############################################################################## +set :config, config +set :bind, config[:host] +set :port, config[:port] + +use Rack::Session::Pool, :key => 'ozones' + +#Enable logger +include CloudLogger +enable_logging OZONES_LOG, settings.config[:debug_level].to_i ############################################################################## # DB bootstrapping @@ -79,7 +119,7 @@ if Auth.all.size == 0 credentials = IO.read(ENV['OZONES_AUTH']).strip.split(':') if credentials.length < 2 - warn "Authorization data malformed" + settings.logger.error {"Authorization data malformed"} exit -1 end credentials[1] = Digest::SHA1.hexdigest(credentials[1]) @@ -87,7 +127,8 @@ if Auth.all.size == 0 :password => credentials[1]}) @auth.save else - warn "oZones admin credentials not set, missing OZONES_AUTH file." + error_m = "oZones admin credentials not set, missing OZONES_AUTH file." + settings.logger.error { error_m } exit -1 end else @@ -100,19 +141,10 @@ ADMIN_PASS = @auth.password begin OZones::ProxyRules.new("apache",config[:htaccess]) rescue Exception => e - warn e.message + settings.logger {e.message} exit -1 end - -############################################################################## -# Sinatra Configuration -############################################################################## -use Rack::Session::Pool, :key => 'ozones' -set :bind, config[:host] -set :port, config[:port] -set :show_exceptions, false - ############################################################################## # Helpers ############################################################################## @@ -144,10 +176,11 @@ helpers do return [204, ""] else + logger.info {"User not authorized login attempt"} return [401, ""] end end - + logger.error {"Authentication settings wrong or not provided"} return [401, ""] end @@ -168,7 +201,9 @@ before do end end - @OzonesServer = OzonesServer.new(session[:key]) + @OzonesServer = OzonesServer.new(session[:key], + settings.config, + settings.logger) @pr = OZones::ProxyRules.new("apache",config[:htaccess]) end end diff --git a/src/ozones/Server/public/css/login.css b/src/ozones/Server/public/css/login.css index 1ea3b09872..217c8c12ca 100644 --- a/src/ozones/Server/public/css/login.css +++ b/src/ozones/Server/public/css/login.css @@ -133,12 +133,19 @@ div#login input#login_btn:hover { } .error_message { + width: 400px; + margin-left: auto; + margin-right: auto; display: none; position: relative; top: 80px; - font-family: Arial, Helvetica, sans-serif; - color:red; - font-size:1.6em; + font-size:1.0em; +} + +#login_spinner { + left: 44px; + position: relative; + top: 2px; } #label_remember { diff --git a/src/ozones/Server/public/js/login.js b/src/ozones/Server/public/js/login.js index 70b26a3011..1ddc1ecd61 100644 --- a/src/ozones/Server/public/js/login.js +++ b/src/ozones/Server/public/js/login.js @@ -23,15 +23,21 @@ function auth_error(req, error){ var status = error.error.http_status; switch (status){ - case 401: - $("#one_error").hide(); - $("#auth_error").fadeIn("slow"); - break; - case 500: - $("#auth_error").hide(); - $("#one_error").fadeIn("slow"); - break; - } + case 401: + $("#error_box").text("Invalid username or password"); + break; + case 500: + $("#error_box").text("OpenNebula is not running or there was a server exception. Please check the server logs."); + break; + case 0: + $("#error_box").text("No answer from server. Is it running?"); + break; + default: + $("#error_box").text("Unexpected error. Status "+status+". Check the server logs."); + + }; + $("#error_box").fadeIn("slow"); + $("#login_spinner").hide(); } function authenticate(){ @@ -39,6 +45,9 @@ function authenticate(){ var password = $("#password").val(); var remember = $("#check_remember").is(":checked"); + $("#error_box").fadeOut("slow"); + $("#login_spinner").show(); + oZones.Auth.login({ data: {username: username , password: password} , remember: remember @@ -61,4 +70,5 @@ $(document).ready(function(){ }; $("input#username.box").focus(); + $("#login_spinner").hide(); }); diff --git a/src/ozones/Server/public/js/plugins/vdcs-tab.js b/src/ozones/Server/public/js/plugins/vdcs-tab.js index 2077aa5e2e..4a4f8cbb1f 100644 --- a/src/ozones/Server/public/js/plugins/vdcs-tab.js +++ b/src/ozones/Server/public/js/plugins/vdcs-tab.js @@ -282,12 +282,14 @@ function updateVDCInfo(req,vdc_json){ var zone_host = ""; var zone_port = ""; var sun_link = ""; + var self_link = ""; var zone_match = zone_endpoint.match(/^https?:\/\/([\w.-]+):(\d+)\/([\W\w]+)$/); if (zone_match){ zone_host = zone_match[1]; zone_port = zone_match[2]; sun_link = "http://" + zone_host +"/sunstone_"+ vdc.NAME+"/"; + self_link = "http://" + zone_host +"/self_"+ vdc.NAME+"/"; }; var info_tab = { @@ -330,6 +332,10 @@ function updateVDCInfo(req,vdc_json){ Sunstone public link\ '+(sun_link.length? ''+sun_link+'' : "")+'\ \ + \ + SelfService public link\ + '+(self_link.length? ''+self_link+'' : "")+'\ + \ \ ONE_XMLPRC (to export for CLI access)\ \ @@ -501,12 +507,10 @@ function setupCreateVDCDialog(){ "ZONEID" : zoneid, "VDCADMINNAME" : vdcadminname, "VDCADMINPASS" : vdcadminpass, - "FORCE" : force + "FORCE" : force, + "HOSTS" : hosts } }; - if (hosts.length){ - vdc_json["VDC"]["HOSTS"]=hosts; - }; Sunstone.runAction("VDC.create",vdc_json); dialog.dialog('close'); @@ -516,6 +520,10 @@ function setupCreateVDCDialog(){ function openCreateVDCDialog(){ var dialog = $('div#create_vdc_dialog') + if (!zones_select){ + notifyError(tr("No zones defined: You need to create at least 1 zone before creating an VDC")); + return false; + }; $('select#zoneid',dialog).html(zones_select); $('select#zoneid',dialog).trigger("change"); $('#vdc_available_hosts_list',dialog).empty(); diff --git a/src/ozones/Server/public/js/plugins/zones-tab.js b/src/ozones/Server/public/js/plugins/zones-tab.js index 4fbb8daeb4..d7430e75ad 100644 --- a/src/ozones/Server/public/js/plugins/zones-tab.js +++ b/src/ozones/Server/public/js/plugins/zones-tab.js @@ -53,6 +53,12 @@ var create_zone_tmpl = /\ \
\ + \ + ://\ + :\ + /\ + \ +
\ \ \
\ @@ -310,8 +316,12 @@ function updateZoneInfo(req,zone_json){ '+zone.ENDPOINT+'\ \ \ - Sunstone endpoint\ -'+ (zone.SUNSENDPOINT.length? ''+zone.SUNSENDPOINT+'' : "") +'\ + Sunstone endpoint\ + '+ (zone.SUNSENDPOINT.length? ''+zone.SUNSENDPOINT+'' : "") +'\ + \ + \ + SelfService endpoint\ + '+ (zone.SELFENDPOINT.length? ''+zone.SELFENDPOINT+'' : "") +'\ \ \ #VDCs\ @@ -557,11 +567,17 @@ function setupCreateZoneDialog(){ var endpoint_port = $('#endpoint_port',this).val(); var onename = $('#onename',this).val(); var onepass = $('#onepass',this).val(); + var se = $('#sunsendpoint',this).val(); var se_ptc = $('#sunsendpoint_ptc',this).val(); var se_port = $('#sunsendpoint_port',this).val(); var se_path = $('#sunsendpoint_path',this).val(); + var ss = $('#selfsendpoint',this).val(); + var ss_ptc = $('#selfsendpoint_ptc',this).val(); + var ss_port = $('#selfsendpoint_port',this).val(); + var ss_path = $('#selfsendpoint_path',this).val(); + if (!name.length || !endpoint.length || !onename.length || !onepass.length){ notifyError("Please fill in all fields"); @@ -575,13 +591,18 @@ function setupCreateZoneDialog(){ se = se_ptc + "://" + se + ":" + se_port + "/" + se_path; + if (ss.length) + ss = ss_ptc + "://" + ss + ":" + ss_port + + "/" + ss_path; + var zone_json = { "ZONE": { "NAME": name, "ENDPOINT": endpoint, "ONENAME": onename, "ONEPASS": onepass, - "SUNSENDPOINT" : se + "SUNSENDPOINT" : se, + "SELFENDPOINT" : ss, } }; diff --git a/src/ozones/Server/templates/login.html b/src/ozones/Server/templates/login.html index 6038b56e55..d1001aaaa4 100644 --- a/src/ozones/Server/templates/login.html +++ b/src/ozones/Server/templates/login.html @@ -3,7 +3,7 @@ OpenNebula oZones Login - + @@ -24,11 +24,7 @@
-
- Invalid username or password -
-
- OpenNebula is not running +
@@ -42,6 +38,7 @@ + retrieving
diff --git a/src/ozones/Server/test/Rakefile b/src/ozones/Server/test/Rakefile deleted file mode 100644 index 1cc32ded2d..0000000000 --- a/src/ozones/Server/test/Rakefile +++ /dev/null @@ -1,9 +0,0 @@ -require 'rake' -require 'spec/rake/spectask' - -desc "Run all tests with RCov" -Spec::Rake::SpecTask.new('test_with_rcov') do |t| - t.spec_files = FileList['spec/*_spec.rb'] - t.rcov = true - t.rcov_opts = ['--exclude', '/Library'] -end \ No newline at end of file diff --git a/src/ozones/Server/test/examples/pool/vdcpool0.json b/src/ozones/Server/test/examples/pool/vdcpool0.json deleted file mode 100644 index 568adf4dd9..0000000000 --- a/src/ozones/Server/test/examples/pool/vdcpool0.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "vdcpool": { - "vdc": [ - { - "hosts": "testhostvdc0n0,testhostvdc0n1,testhostvdc0n2", - "zones_id": 1, - "name": "testvdc0", - "id": 1 - }, - { - "hosts": "testhostvdc1n0", - "zones_id": 1, - "name": "testvdc1", - "id": 2 - } - ] - } -} \ No newline at end of file diff --git a/src/ozones/Server/test/examples/pool/vdcpool1deleted.json b/src/ozones/Server/test/examples/pool/vdcpool1deleted.json deleted file mode 100644 index 4f0d258aa9..0000000000 --- a/src/ozones/Server/test/examples/pool/vdcpool1deleted.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "vdcpool": { - "vdc": [ - { - "hosts": "testhostvdc0n0,testhostvdc0n1,testhostvdc0n2", - "zones_id": 1, - "name": "testvdc0", - "id": 1 - } - ] - } -} \ No newline at end of file diff --git a/src/ozones/Server/test/examples/pool/zonepool0.json b/src/ozones/Server/test/examples/pool/zonepool0.json deleted file mode 100644 index 05b79f2255..0000000000 --- a/src/ozones/Server/test/examples/pool/zonepool0.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "zonepool": { - "zone": [ - { - "onename": "oneadmin", - "onepass": "opennebula", - "endpoint": "http://localhost:2633/RPC2", - "numbervdcs": 2, - "name": "testzone0", - "id": 1 - }, - { - "onename": "testname", - "onepass": "testpass", - "endpoint": "http://remoteserver:2633/RPC2", - "numbervdcs": 0, - "name": "testzone1", - "id": 2 - } - ] - } -} \ No newline at end of file diff --git a/src/ozones/Server/test/examples/pool/zonepool1deleted.json b/src/ozones/Server/test/examples/pool/zonepool1deleted.json deleted file mode 100644 index dbd66dca25..0000000000 --- a/src/ozones/Server/test/examples/pool/zonepool1deleted.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "zonepool": { - "zone": [ - { - "onename": "oneadmin", - "onepass": "opennebula", - "endpoint": "http://localhost:2633/RPC2", - "numbervdcs": 2, - "name": "testzone0", - "id": 1 - } - ] - } -} \ No newline at end of file diff --git a/src/ozones/Server/test/examples/vdc/vdc0.json b/src/ozones/Server/test/examples/vdc/vdc0.json deleted file mode 100644 index 6deb95903d..0000000000 --- a/src/ozones/Server/test/examples/vdc/vdc0.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "vdc": { - "hosts": "5,7,9", - "zones_id": 1, - "name": "testvdc0", - "id": 1 - } -} \ No newline at end of file diff --git a/src/ozones/Server/test/examples/vdc/vdc0.template b/src/ozones/Server/test/examples/vdc/vdc0.template deleted file mode 100644 index b2e7e3d4f3..0000000000 --- a/src/ozones/Server/test/examples/vdc/vdc0.template +++ /dev/null @@ -1,5 +0,0 @@ -NAME=testvdc0 -ZONEID=1 -HOSTS=5,7,9 -VDCADMINNAME=adminname -VDCADMINPASS=adminpass diff --git a/src/ozones/Server/test/examples/vdc/vdc1.template b/src/ozones/Server/test/examples/vdc/vdc1.template deleted file mode 100644 index 4566505bbb..0000000000 --- a/src/ozones/Server/test/examples/vdc/vdc1.template +++ /dev/null @@ -1,5 +0,0 @@ -NAME=testvdc1 -HOSTS=8 -ZONEID=1 -VDCADMINNAME=othername -VDCADMINPASS=otherpass \ No newline at end of file diff --git a/src/ozones/Server/test/examples/vdc/vdc2nozone.template b/src/ozones/Server/test/examples/vdc/vdc2nozone.template deleted file mode 100644 index 946c43c46c..0000000000 --- a/src/ozones/Server/test/examples/vdc/vdc2nozone.template +++ /dev/null @@ -1,3 +0,0 @@ -NAME=testvdcnozone -HOSTS=3,7 -ZONEID=5 \ No newline at end of file diff --git a/src/ozones/Server/test/examples/zone/zone0.json b/src/ozones/Server/test/examples/zone/zone0.json deleted file mode 100644 index 3577998a60..0000000000 --- a/src/ozones/Server/test/examples/zone/zone0.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "zone": { - "onename": "oneadmin", - "onepass": "opennebula", - "endpoint": "http://localhost:2633/RPC2", - "name": "testzone0", - "id": 1, - "vdcs": [ - { - "hosts": "testhostvdc0n0,testhostvdc0n1,testhostvdc0n2", - "zones_id": 1, - "name": "testvdc0", - "id": 1 - }, - { - "hosts": "testhostvdc1n0", - "zones_id": 1, - "name": "testvdc1", - "id": 2 - } - ] - } -} \ No newline at end of file diff --git a/src/ozones/Server/test/examples/zone/zone0.template b/src/ozones/Server/test/examples/zone/zone0.template deleted file mode 100644 index acad3af06e..0000000000 --- a/src/ozones/Server/test/examples/zone/zone0.template +++ /dev/null @@ -1,4 +0,0 @@ -NAME=testzone0 -ENDPOINT=http://localhost:2633/RPC2 -ONENAME=oneadmin -ONEPASS=opennebula \ No newline at end of file diff --git a/src/ozones/Server/test/examples/zone/zone1.template b/src/ozones/Server/test/examples/zone/zone1.template deleted file mode 100644 index 4c1459667c..0000000000 --- a/src/ozones/Server/test/examples/zone/zone1.template +++ /dev/null @@ -1,4 +0,0 @@ -NAME=testzone1 -ENDPOINT=http://remoteserver:2633/RPC2 -ONENAME=testname -ONEPASS=testpass \ No newline at end of file diff --git a/src/ozones/Server/test/spec/pools_spec.rb b/src/ozones/Server/test/spec/pools_spec.rb deleted file mode 100644 index 4fd7667c7c..0000000000 --- a/src/ozones/Server/test/spec/pools_spec.rb +++ /dev/null @@ -1,133 +0,0 @@ -# -------------------------------------------------------------------------- # -# Copyright 2002-2012, 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. # -#--------------------------------------------------------------------------- # - -# Load libraries -require 'rubygems' -require 'spec' -require 'json' -require File.dirname(__FILE__) + "/../../../Client/lib/OZonesClient.rb" - -EXAMPLES_PATH = File.dirname(__FILE__) + "/../examples/" - -describe 'OZones Pool' do - before(:all) do - @client_launched = true - - begin - @ozones_client = OZonesClient::Client.new("http://localhost:6121") - rescue Exception => e - @client_launched = false - end - - @client_launched.should == true - - rc = @ozones_client.post_resource( - "zone",EXAMPLES_PATH + '/zone/zone0.template') - rc.class.should_not eql(OZonesClient::Error) - - rc = @ozones_client.post_resource( - "zone",EXAMPLES_PATH + '/zone/zone1.template') - rc.class.should_not eql(OZonesClient::Error) - - rc = @ozones_client.post_resource( - "vdc",EXAMPLES_PATH + '/vdc/vdc0.template') - rc.class.should_not eql(OZonesClient::Error) - - rc = @ozones_client.post_resource( - "vdc",EXAMPLES_PATH + '/vdc/vdc1.template') - rc.class.should_not eql(OZonesClient::Error) - - end - - it "should be able to retrieve the zone pool" do - zonepool = @ozones_client.get_pool("zone") - zonepool.class.should eql(Net::HTTPOK) - zonepool.body.should eql( - File.read(EXAMPLES_PATH+'/pool/zonepool0.json')) - end - - it "should be able to retrieve the vdc pool" do - vdcpool = @ozones_client.get_pool("vdc") - vdcpool.class.should eql(Net::HTTPOK) - vdcpool.body.should eql( - File.read(EXAMPLES_PATH+'/pool/vdcpool0.json')) - end - - it "should be able to retrieve a particular zone" do - zone0 = @ozones_client.get_resource("zone",1) - zone0.class.should eql(Net::HTTPOK) - zone0.body.should eql( - File.read(EXAMPLES_PATH+'/zone/zone0.json')) - end - - it "should be able to retrieve a particular vdc" do - vdc0 = @ozones_client.get_resource("vdc",1) - vdc0.class.should eql(Net::HTTPOK) - vdc0.body.should eql( - File.read(EXAMPLES_PATH+'/vdc/vdc0.json')) - end - - it "should fail on zone recreation (with the same name)" do - rc = @ozones_client.post_resource( - "zone",EXAMPLES_PATH + '/zone/zone0.template') - rc.class.should eql(OZonesClient::Error) - end - - it "should fail on vdc recreation (with the same name)" do - rc = @ozones_client.post_resource( - "vdc",EXAMPLES_PATH + '/vdc/vdc0.template') - rc.class.should eql(OZonesClient::Error) - end - - it "should fail on vdc creation with no existing zone" do - rc = @ozones_client.post_resource( - "vdc",EXAMPLES_PATH + - '/vdc/vdc2nozone.template') - rc.class.should eql(OZonesClient::Error) - end - - it "should allow deleting a zone" do - rc = @ozones_client.delete_resource("zone",2) - rc.class.should eql(Net::HTTPOK) - # Zone pool shouldn't account for the deleted zone - zonepool = @ozones_client.get_pool("zone") - zonepool.class.should eql(Net::HTTPOK) - zonepool.body.should eql( - File.read(EXAMPLES_PATH+ - '/pool/zonepool1deleted.json')) - end - - it "should allow deleting a vdc" do - rc = @ozones_client.delete_resource("vdc",2) - rc.class.should eql(Net::HTTPOK) - # Zone pool shouldn't account for the deleted zone - vdcpool = @ozones_client.get_pool("vdc") - vdcpool.class.should eql(Net::HTTPOK) - vdcpool.body.should eql( - File.read(EXAMPLES_PATH+ - '/pool/vdcpool1deleted.json')) - end - - it "should fail on non existing zone deletion" do - rc = @ozones_client.delete_resource("zone",5) - rc.class.should eql(OZonesClient::Error) - end - - it "should fail on non existing vdc deletion" do - rc = @ozones_client.delete_resource("vdc",5) - rc.class.should eql(OZonesClient::Error) - end -end diff --git a/src/ozones/Server/test/test.sh b/src/ozones/Server/test/test.sh deleted file mode 100755 index 98fa138442..0000000000 --- a/src/ozones/Server/test/test.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/bash - -# -------------------------------------------------------------------------- # -# Copyright 2002-2012, 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. # -#--------------------------------------------------------------------------- # - - -VAR_LOCATION="$PWD/var" -OZONES_LOCATION="$PWD/../" - -mkdir -p $VAR_LOCATION - -if [ "$(ls -A $VAR_LOCATION)" ]; then - echo "$VAR_LOCATION is not empty." - exit -1 -fi - -rm -rf coverage_server - -rcov --exclude /Library --exclude /Users/tinova/.gem -o coverage_server `which rackup` -- $OZONES_LOCATION/config.ru -s thin -p 6121 -o localhost &> server.log & -RCOVPID=$! -sleep 5 - -rake test_with_rcov -CODE=$? - -kill $RCOVPID -sleep 2s; - -if [ $CODE != 0 ] ; then - exit 1 -fi - -find $VAR_LOCATION -mindepth 1 -delete diff --git a/src/ozones/test/etc/oned.conf.a b/src/ozones/test/etc/oned.conf.a new file mode 100644 index 0000000000..4b63ff1534 --- /dev/null +++ b/src/ozones/test/etc/oned.conf.a @@ -0,0 +1,57 @@ +HOST_MONITORING_INTERVAL = 600 +#HOST_PER_INTERVAL = 15 + +VM_POLLING_INTERVAL = 600 +#VM_PER_INTERVAL = 5 + +#VM_DIR=/srv/cloud/one/var + +SCRIPTS_REMOTE_DIR=/var/tmp/one + +PORT = 2666 + +DB = [ backend = "sqlite" ] + +VNC_BASE_PORT = 5900 + +DEBUG_LEVEL = 3 + +NETWORK_SIZE = 254 + +MAC_PREFIX = "02:00" + +DEFAULT_IMAGE_TYPE = "OS" +DEFAULT_DEVICE_PREFIX = "hd" + + +IM_MAD = [ name="im_dummy", executable="one_im_dummy"] + +VM_MAD = [ name="vmm_dummy", executable="one_vmm_dummy", type="xml" ] + +TM_MAD = [ + name = "tm_dummy", + executable = "one_tm", + arguments = "tm_dummy/tm_dummy.conf" ] + +IMAGE_MAD = [ + executable = "one_image", + arguments = "fs -t 15" ] + +HM_MAD = [ + executable = "one_hm" ] + +AUTH_MAD = [ + executable = "one_auth_mad", + arguments = "--authn ssh,x509,ldap,server_cipher,server_x509" +# arguments = "--authz quota --authn ssh,x509,ldap,server_cipher,server_x509" +] + +SESSION_EXPIRATION_TIME = 900 + +VM_RESTRICTED_ATTR = "CONTEXT/FILES" +VM_RESTRICTED_ATTR = "DISK/SOURCE" +VM_RESTRICTED_ATTR = "NIC/MAC" +VM_RESTRICTED_ATTR = "NIC/VLAN_ID" +VM_RESTRICTED_ATTR = "RANK" + +IMAGE_RESTRICTED_ATTR = "SOURCE" diff --git a/src/ozones/test/etc/oned.conf.b b/src/ozones/test/etc/oned.conf.b index c7f90b798d..589cf164ba 100644 --- a/src/ozones/test/etc/oned.conf.b +++ b/src/ozones/test/etc/oned.conf.b @@ -1,30 +1,57 @@ -#******************************************************************************* -# OpenNebula Configuration file -#******************************************************************************* - -# General - HOST_MONITORING_INTERVAL = 600 +#HOST_PER_INTERVAL = 15 + VM_POLLING_INTERVAL = 600 +#VM_PER_INTERVAL = 5 + +#VM_DIR=/srv/cloud/one/var + SCRIPTS_REMOTE_DIR=/var/tmp/one -PORT=2637 + +PORT = 2667 + DB = [ backend = "sqlite" ] + VNC_BASE_PORT = 5900 -DEBUG_LEVEL=3 + +DEBUG_LEVEL = 3 + NETWORK_SIZE = 254 + MAC_PREFIX = "02:00" + DEFAULT_IMAGE_TYPE = "OS" DEFAULT_DEVICE_PREFIX = "hd" -# Dummy IM_MAD = [ name="im_dummy", executable="one_im_dummy"] -VM_MAD = [ name="vmm_dummy",executable="one_vmm_dummy", type="xml" ] -TM_MAD = [ name="tm_dummy", executable="one_tm", arguments ="tm_dummy/tm_dummy.conf" ] -# Image -IMAGE_MAD = [ executable = "one_image", arguments = "fs -t 15" ] +VM_MAD = [ name="vmm_dummy", executable="one_vmm_dummy", type="xml" ] -# Hook -HM_MAD = [ executable = "one_hm" ] +TM_MAD = [ + name = "tm_dummy", + executable = "one_tm", + arguments = "tm_dummy/tm_dummy.conf" ] +IMAGE_MAD = [ + executable = "one_image", + arguments = "fs -t 15" ] + +HM_MAD = [ + executable = "one_hm" ] + +AUTH_MAD = [ + executable = "one_auth_mad", + arguments = "--authn ssh,x509,ldap,server_cipher,server_x509" +# arguments = "--authz quota --authn ssh,x509,ldap,server_cipher,server_x509" +] + +SESSION_EXPIRATION_TIME = 900 + +VM_RESTRICTED_ATTR = "CONTEXT/FILES" +VM_RESTRICTED_ATTR = "DISK/SOURCE" +VM_RESTRICTED_ATTR = "NIC/MAC" +VM_RESTRICTED_ATTR = "NIC/VLAN_ID" +VM_RESTRICTED_ATTR = "RANK" + +IMAGE_RESTRICTED_ATTR = "SOURCE" diff --git a/src/ozones/test/examples/pool/vdcpool0.json b/src/ozones/test/examples/pool/vdcpool0.json new file mode 100644 index 0000000000..1401a09b5b --- /dev/null +++ b/src/ozones/test/examples/pool/vdcpool0.json @@ -0,0 +1,36 @@ +{ + "VDC_POOL": { + "VDC": [ + { + "ID": 1, + "ACLS": "2,3,4,5,6,7", + "HOSTS": "1,2,3", + "NAME": "vdcA", + "ZONES_ID": 1, + "GROUP_ID": 100, + "VDCADMINNAME": "vdcadminA", + "VDCADMIN_ID": 2 + }, + { + "ID": 2, + "ACLS": "2,3,4,5", + "HOSTS": "1", + "NAME": "vdcB", + "ZONES_ID": 2, + "GROUP_ID": 100, + "VDCADMINNAME": "vdcadminB", + "VDCADMIN_ID": 2 + }, + { + "ID": 3, + "ACLS": "8,9,10,11", + "HOSTS": "4", + "NAME": "vdcC", + "ZONES_ID": 1, + "GROUP_ID": 101, + "VDCADMINNAME": "vdcadminC", + "VDCADMIN_ID": 3 + } + ] + } +} \ No newline at end of file diff --git a/src/ozones/test/examples/pool/vdcpool_deleted.json b/src/ozones/test/examples/pool/vdcpool_deleted.json new file mode 100644 index 0000000000..bd6fd87e84 --- /dev/null +++ b/src/ozones/test/examples/pool/vdcpool_deleted.json @@ -0,0 +1,26 @@ +{ + "VDC_POOL": { + "VDC": [ + { + "ID": 1, + "ACLS": "2,3,4,5,6,7", + "HOSTS": "1,2,3", + "NAME": "vdcA", + "ZONES_ID": 1, + "GROUP_ID": 100, + "VDCADMINNAME": "vdcadminA", + "VDCADMIN_ID": 2 + }, + { + "ID": 2, + "ACLS": "2,3,4,5", + "HOSTS": "1", + "NAME": "vdcB", + "ZONES_ID": 2, + "GROUP_ID": 100, + "VDCADMINNAME": "vdcadminB", + "VDCADMIN_ID": 2 + } + ] + } +} \ No newline at end of file diff --git a/src/ozones/test/examples/pool/zonepool0.json b/src/ozones/test/examples/pool/zonepool0.json new file mode 100644 index 0000000000..1eaf1751fa --- /dev/null +++ b/src/ozones/test/examples/pool/zonepool0.json @@ -0,0 +1,26 @@ +{ + "ZONE_POOL": { + "ZONE": [ + { + "ID": 1, + "ENDPOINT": "http://localhost:2666/RPC2", + "NUMBERVDCS": 0, + "SUNSENDPOINT": "http://localhost:9869", + "NAME": "zoneA", + "SELFENDPOINT": null, + "ONENAME": "oneadminA", + "ONEPASS": "OkqWM2aSqbM/nlrdHGv3OA==" + }, + { + "ID": 2, + "ENDPOINT": "http://localhost:2667/RPC2", + "NUMBERVDCS": 0, + "SUNSENDPOINT": null, + "NAME": "zoneB", + "SELFENDPOINT": null, + "ONENAME": "oneadminB", + "ONEPASS": "8Si8vlo2P3qn5/SNxkMkDg==" + } + ] + } +} \ No newline at end of file diff --git a/src/ozones/test/examples/pool/zonepool_deleted.json b/src/ozones/test/examples/pool/zonepool_deleted.json new file mode 100644 index 0000000000..6ec991ee16 --- /dev/null +++ b/src/ozones/test/examples/pool/zonepool_deleted.json @@ -0,0 +1,16 @@ +{ + "ZONE_POOL": { + "ZONE": [ + { + "ID": 1, + "ENDPOINT": "http://localhost:2666/RPC2", + "NUMBERVDCS": 0, + "SUNSENDPOINT": "http://localhost:9869", + "NAME": "zoneA", + "SELFENDPOINT": null, + "ONENAME": "oneadminA", + "ONEPASS": "OkqWM2aSqbM/nlrdHGv3OA==" + } + ] + } +} \ No newline at end of file diff --git a/src/ozones/test/examples/vdc/vdc0.json b/src/ozones/test/examples/vdc/vdc0.json new file mode 100644 index 0000000000..b716f24472 --- /dev/null +++ b/src/ozones/test/examples/vdc/vdc0.json @@ -0,0 +1,12 @@ +{ + "VDC": { + "ID": 1, + "ACLS": "2,3,4,5,6,7", + "HOSTS": "1,2,3", + "NAME": "vdcA", + "ZONES_ID": 1, + "GROUP_ID": 100, + "VDCADMINNAME": "vdcadminA", + "VDCADMIN_ID": 2 + } +} \ No newline at end of file diff --git a/src/ozones/test/examples/zone/zone0.json b/src/ozones/test/examples/zone/zone0.json new file mode 100644 index 0000000000..6b8d182e36 --- /dev/null +++ b/src/ozones/test/examples/zone/zone0.json @@ -0,0 +1,14 @@ +{ + "ZONE": { + "ID": 1, + "ENDPOINT": "http://localhost:2666/RPC2", + "SUNSENDPOINT": "http://localhost:9869", + "VDCS": [ + + ], + "NAME": "zoneA", + "SELFENDPOINT": null, + "ONENAME": "oneadminA", + "ONEPASS": "OkqWM2aSqbM/nlrdHGv3OA==" + } +} \ No newline at end of file diff --git a/src/ozones/test/spec/VDCManagement_spec.rb b/src/ozones/test/spec/VDCManagement_spec.rb index 03b8c32c82..35be54b574 100644 --- a/src/ozones/test/spec/VDCManagement_spec.rb +++ b/src/ozones/test/spec/VDCManagement_spec.rb @@ -29,89 +29,116 @@ require 'command_parser' require 'ozones_helper/zones_helper.rb' require 'ozones_helper/vdc_helper.rb' +TESTS_PATH = File.dirname(__FILE__)+"/../" + module OZones describe "oZones server regarding VDCs" do before(:all) do - @zonehelper = + @zonehelper = ZonesHelper.new("zone", "ozonesadmin","ozonespassword") - @vdchelper = - VDCHelper.new("vdc", "ozonesadmin","ozonespassword") - + @vdchelper = + VDCHelper.new("vdc", "ozonesadmin","ozonespassword") + @clientA = OpenNebula::Client.new(File.read( - File.dirname(__FILE__)+"/../etc/one_auth_a"), - "http://localhost:2636/RPC2") - + TESTS_PATH+"etc/one_auth_a"), + "http://localhost:2666/RPC2") + @clientB = OpenNebula::Client.new(File.read( - File.dirname(__FILE__)+"/../etc/one_auth_b"), - "http://localhost:2637/RPC2") - + TESTS_PATH+"etc/one_auth_b"), + "http://localhost:2667/RPC2") + hostA=OpenNebula::Host.new(OpenNebula::Host.build_xml, @clientA) - hostA.allocate("hostA1","im_dummy","vmm_dummy","tm_dummy") - hostA.allocate("hostA2","im_dummy","vmm_dummy","tm_dummy") - hostA.allocate("hostA3","im_dummy","vmm_dummy","tm_dummy") - hostA.allocate("hostA4","im_dummy","vmm_dummy","tm_dummy") - + hostA.allocate("hostA1","im_dummy","vmm_dummy","tm_dummy","dummy") + hostA.allocate("hostA2","im_dummy","vmm_dummy","tm_dummy","dummy") + hostA.allocate("hostA3","im_dummy","vmm_dummy","tm_dummy","dummy") + hostA.allocate("hostA4","im_dummy","vmm_dummy","tm_dummy","dummy") + hostB=OpenNebula::Host.new(OpenNebula::Host.build_xml, @clientB) - hostB.allocate("hostB1","im_dummy","vmm_dummy","tm_dummy") - hostB.allocate("hostB2","im_dummy","vmm_dummy","tm_dummy") - hostB.allocate("hostB3","im_dummy","vmm_dummy","tm_dummy") + hostB.allocate("hostB1","im_dummy","vmm_dummy","tm_dummy","dummy") + hostB.allocate("hostB2","im_dummy","vmm_dummy","tm_dummy","dummy") + hostB.allocate("hostB3","im_dummy","vmm_dummy","tm_dummy","dummy") end - + it "should be able to create a couple of zones" do - @zonehelper.create_resource(File.dirname(__FILE__)+ - "/../templates/zoneA.template")[0].should eql(0) - @zonehelper.create_resource(File.dirname(__FILE__)+ - "/../templates/zoneB.template")[0].should eql(0) - end - - it "should be able to create one vdc with the apropiate ONE resources" do - @vdchelper.create_resource(File.dirname(__FILE__)+ - "/../templates/vdcA.template")[0].should eql(0) - + rc = @zonehelper.create_resource(TESTS_PATH+"templates/zoneA.template") + rc[0].should eql(0) + rc = @zonehelper.create_resource(TESTS_PATH+"templates/zoneB.template") + rc[0].should eql(0) + end + + it "should be able to create one vdc with apropiate ONE resources" do + @vdchelper.create_resource(TESTS_PATH+"templates/vdcA.template", + {:force => false})[0].should eql(0) + upool = OpenNebula::UserPool.new(@clientA) upool.info userExist=false - upool.each{|user| + upool.each{|user| if user['NAME'] == "vdcadminA" userExist=true end } - + userExist.should eql(true) - + gpool = OpenNebula::GroupPool.new(@clientA) gpool.info groupExist=false - gpool.each{|group| + gpool.each{|group| if group['NAME'] == "vdcA" groupExist=true end - } - + } + groupExist.should eql(true) - + apool = OpenNebula::AclPool.new(@clientA) apool.info # TODO check ACLs end - - it "should be able to create a couple of VDCs" do - @vdchelper.create_resource(File.dirname(__FILE__)+ - "/../templates/vdcB.template")[0].should eql(0) - @vdchelper.create_resource(File.dirname(__FILE__)+ - "/../templates/vdcC.template")[0].should eql(0) - end - - it "should fail when creating an existing VDC" do - @vdchelper.create_resource(File.dirname(__FILE__)+ - "/../templates/vdcA.template")[0].should eql(-1) - end - - it "should fail when creating a VDC upon a non existing zone" do - @vdchelper.create_resource(File.dirname(__FILE__)+ - "/../templates/vdc.no.zone.template")[0].should eql(-1) - end - + + it "should be able to create a couple of VDCs" do + @vdchelper.create_resource(TESTS_PATH+"templates/vdcB.template", + {:force => false})[0].should eql(0) + @vdchelper.create_resource(TESTS_PATH+"templates/vdcC.template", + {:force => false})[0].should eql(0) + end + + it "should fail when creating an existing VDC" do + @vdchelper.create_resource(TESTS_PATH+"templates/vdcA.template", + {:force => false})[0].should eql(-1) + end + + it "should fail when creating a VDC upon a non existing zone" do + @vdchelper.create_resource(TESTS_PATH+"templates/vdc.no.zone.template", + {:force => false})[0].should eql(-1) + end + + it "should be able to retrieve the vdc pool" do + vdcpool = @vdchelper.list_pool({:json => true}) + vdcpool[0].should eql(0) + vdcpool[1].should eql(File.read(TESTS_PATH+"examples/pool/vdcpool0.json")) + end + + it "should be able to retrieve a particular vdc" do + vdc = @vdchelper.show_resource(1, {:json => true}) + vdc[0].should eql(0) + vdc[1].should eql(File.read(TESTS_PATH+"examples/vdc/vdc0.json")) + end + + it "should allow deleting a vdc" do + rc = @vdchelper.delete_resource(3, {}) + rc[0].should eql(0) + rc = @vdchelper.list_pool({:json => true}) + rc[0].should eql(0) + rc[1].should eql(File.read(TESTS_PATH+ + "examples/pool/vdcpool_deleted.json")) + end + + it "should fail on non-existing vdc deletion" do + rc = @vdchelper.delete_resource(7, {}) + rc[0].should eql(-1) + end end end diff --git a/src/ozones/test/spec/ZoneManagement_spec.rb b/src/ozones/test/spec/ZoneManagement_spec.rb index cf18a2d1ed..e60e5caf11 100644 --- a/src/ozones/test/spec/ZoneManagement_spec.rb +++ b/src/ozones/test/spec/ZoneManagement_spec.rb @@ -28,36 +28,71 @@ $: << RUBY_LIB_LOCATION+"/cli" require 'command_parser' require 'ozones_helper/zones_helper.rb' +TESTS_PATH = File.dirname(__FILE__)+"/../" + module OZones describe "oZones server regarding zones" do before(:all) do - @helper = ZonesHelper.new("zone", "ozonesadmin","ozonespassword") - @badhelper = ZonesHelper.new("zone", "wronguser","wrongpassword") + @helper = ZonesHelper.new("zone", "ozonesadmin","ozonespassword") + @badhelper = ZonesHelper.new("zone", "wronguser","wrongpassword") end - + it "should be able to create a couple of zones" do - @helper.create_resource(File.dirname(__FILE__)+ - "/../templates/zoneA.template")[0].should eql(0) - @helper.create_resource(File.dirname(__FILE__)+ - "/../templates/zoneB.template")[0].should eql(0) - end - + rc = @helper.create_resource(TESTS_PATH+"templates/zoneA.template") + rc[0].should eql(0) + + @helper.create_resource(TESTS_PATH+"templates/zoneB.template") + rc[0].should eql(0) + end + it "should fail with wrong zones templates" do - @helper.create_resource(File.dirname(__FILE__)+ - "/../templates/zone.wrong.credentials.template")[0].should eql(-1) - @helper.create_resource(File.dirname(__FILE__)+ - "/../templates/zone.wrong.endpoint.template")[0].should eql(-1) - end - + templ_path = "templates/zone.wrong.credentials.template" + rc = @helper.create_resource(TESTS_PATH+templ_path) + rc[0].should eql(-1) + + templ_path = "templates/zone.wrong.endpoint.template" + rc = @helper.create_resource(TESTS_PATH+templ_path) + rc[0].should eql(-1) + end + it "should fail when creating zones with existing name" do - @helper.create_resource(File.dirname(__FILE__)+ - "/../templates/zoneA.template")[0].should eql(-1) - end - + rc = @helper.create_resource(TESTS_PATH+"templates/zoneA.template") + rc[0].should eql(-1) + end + it "should refuse unauthorized requests" do - @badhelper.create_resource(File.dirname(__FILE__)+ - "/../templates/zoneA.template")[0].should eql(-1) - end + rc = @badhelper.create_resource(TESTS_PATH+ + "templates/zoneA.template") + rc[0].should eql(-1) + end + + it "should be able to retrieve the zone pool" do + zonepool = @helper.list_pool({:json => true}) + zonepool[0].should eql(0) + zonepool[1].should eql(File.read(TESTS_PATH+ + "examples/pool/zonepool0.json")) + end + + it "should be able to retrieve a particular zone" do + zone = @helper.show_resource(1,{:json => true}) + zone[0].should eql(0) + zone[1].should eql(File.read(TESTS_PATH+"examples/zone/zone0.json")) + end + + it "should allow deleting a zone" do + rc = @helper.delete_resource(2, {}) + rc[0].should eql(0) + rc = @helper.list_pool({:json => true}) + rc[0].should eql(0) + rc[1].should eql(File.read(TESTS_PATH+ + "examples/pool/zonepool_deleted.json")) + end + + it "should fail on non existing zone deletion" do + rc = @helper.delete_resource(7, {}) + rc[0].should eql(-1) + end + end -end \ No newline at end of file +end diff --git a/src/ozones/test/templates/vdcC.template b/src/ozones/test/templates/vdcC.template index 31fbb6c4a0..47c2b9148b 100644 --- a/src/ozones/test/templates/vdcC.template +++ b/src/ozones/test/templates/vdcC.template @@ -2,4 +2,4 @@ NAME=vdcC VDCADMINNAME=vdcadminC VDCADMINPASS=vdcpassC ZONEID=1 -HOSTS=3 \ No newline at end of file +HOSTS=4 diff --git a/src/ozones/test/templates/zoneA.template b/src/ozones/test/templates/zoneA.template index 35b6adfb5f..bd92fcb475 100644 --- a/src/ozones/test/templates/zoneA.template +++ b/src/ozones/test/templates/zoneA.template @@ -1,5 +1,5 @@ NAME=zoneA ONENAME=oneadminA ONEPASS=opennebulaA -ENDPOINT=http://localhost:2636/RPC2 -SUNSENDPOINT=http://localhost:9869 \ No newline at end of file +ENDPOINT=http://localhost:2666/RPC2 +SUNSENDPOINT=http://localhost:9869 diff --git a/src/ozones/test/templates/zoneB.template b/src/ozones/test/templates/zoneB.template index 3eb7b9348b..9aa9cdda36 100644 --- a/src/ozones/test/templates/zoneB.template +++ b/src/ozones/test/templates/zoneB.template @@ -1,4 +1,4 @@ NAME=zoneB ONENAME=oneadminB ONEPASS=opennebulaB -ENDPOINT=http://localhost:2637/RPC2 \ No newline at end of file +ENDPOINT=http://localhost:2667/RPC2 diff --git a/src/ozones/test/test.sh b/src/ozones/test/test.sh index 963032dcf2..d6de0d2f42 100755 --- a/src/ozones/test/test.sh +++ b/src/ozones/test/test.sh @@ -35,8 +35,7 @@ for j in `ls ./spec/*_spec.rb` ; do OZONES_AUTH=$PWD/etc/ozones_auth ONE_LOCATION=$ONE_LOCATION_A oneA/bin/ozones-server start sleep 5 - - ONE_LOCATION=$ONE_LOCATION_A spec $j -f s + ONE_LOCATION=$ONE_LOCATION_A rspec $j -f s CODE=$? if [ $CODE != 0 ] ; then @@ -52,18 +51,7 @@ for j in `ls ./spec/*_spec.rb` ; do done if (($CODE == 0)); then - # Terminate ONEs - ONE_LOCATION=$ONE_LOCATION_A oneA/bin/one stop - ONE_LOCATION=$ONE_LOCATION_B oneB/bin/one stop - - # Stop oZones - ONE_LOCATION=$ONE_LOCATION_A oneA/bin/ozones-server stop - # Delete directories rm -rf oneA rm -rf oneB -fi - - - - +fi \ No newline at end of file diff --git a/src/pool/PoolObjectSQL.cc b/src/pool/PoolObjectSQL.cc index 2a1706b171..fc45b17dd1 100644 --- a/src/pool/PoolObjectSQL.cc +++ b/src/pool/PoolObjectSQL.cc @@ -172,7 +172,7 @@ int PoolObjectSQL::replace_template(const string& tmpl_str, string& error) if ( new_tmpl == 0 ) { - error = "Can not allocate a new template"; + error = "Cannot allocate a new template"; return -1; } diff --git a/src/rm/RequestManager.cc b/src/rm/RequestManager.cc index 34a14a82e0..9d2099ea18 100644 --- a/src/rm/RequestManager.cc +++ b/src/rm/RequestManager.cc @@ -114,7 +114,7 @@ int RequestManager::setup_socket() { ostringstream oss; - oss << "Can not open server socket: " << strerror(errno); + oss << "Cannot open server socket: " << strerror(errno); NebulaLog::log("ReM",Log::ERROR,oss); return -1; @@ -126,7 +126,7 @@ int RequestManager::setup_socket() { ostringstream oss; - oss << "Can not set socket options: " << strerror(errno); + oss << "Cannot set socket options: " << strerror(errno); NebulaLog::log("ReM",Log::ERROR,oss); close(socket_fd); @@ -146,7 +146,7 @@ int RequestManager::setup_socket() { ostringstream oss; - oss << "Can not bind to port " << port << " : " << strerror(errno); + oss << "Cannot bind to port " << port << " : " << strerror(errno); NebulaLog::log("ReM",Log::ERROR,oss); close(socket_fd); diff --git a/src/rm/RequestManagerDelete.cc b/src/rm/RequestManagerDelete.cc index 9466768c30..34ec4d0393 100644 --- a/src/rm/RequestManagerDelete.cc +++ b/src/rm/RequestManagerDelete.cc @@ -91,7 +91,7 @@ void RequestManagerDelete::request_execute(xmlrpc_c::paramList const& paramList, if ( rc != 0 ) { failure_response(INTERNAL, - request_error("Can not delete "+object_name(auth_object),error_msg), + request_error("Cannot delete "+object_name(auth_object),error_msg), att); return; } @@ -163,7 +163,7 @@ int ImageDelete::drop(int oid, PoolObjectSQL * object, string& error_msg) if ( ds == 0 ) { - error_msg = "Datastore no longer exists can not remove image"; + error_msg = "Datastore no longer exists cannot remove image"; return -1; } @@ -199,7 +199,7 @@ int UserDelete::drop(int oid, PoolObjectSQL * object, string& error_msg) if (oid == 0) { - error_msg = "oneadmin can not be deleted."; + error_msg = "oneadmin cannot be deleted."; object->unlock(); return -1; diff --git a/src/rm/RequestManagerUpdateTemplate.cc b/src/rm/RequestManagerUpdateTemplate.cc index 07226eb0b6..1c8988ccbb 100644 --- a/src/rm/RequestManagerUpdateTemplate.cc +++ b/src/rm/RequestManagerUpdateTemplate.cc @@ -54,7 +54,7 @@ void RequestManagerUpdateTemplate::request_execute( if ( rc != 0 ) { failure_response(INTERNAL, - request_error("Can not update template",error_str), + request_error("Cannot update template",error_str), att); object->unlock(); diff --git a/src/rm/RequestManagerVirtualMachine.cc b/src/rm/RequestManagerVirtualMachine.cc index 82c3f91640..59ef25b9ef 100644 --- a/src/rm/RequestManagerVirtualMachine.cc +++ b/src/rm/RequestManagerVirtualMachine.cc @@ -160,7 +160,7 @@ int RequestManagerVirtualMachine::add_history(VirtualMachine * vm, if ( rc != 0 ) { failure_response(INTERNAL, - request_error("Can not update virtual machine history",""), + request_error("Cannot update virtual machine history",""), att); return -1; @@ -442,7 +442,7 @@ void VirtualMachineSaveDisk::request_execute(xmlrpc_c::paramList const& paramLis if ( iid_orig == -1 ) { failure_response(INTERNAL, - request_error("Can not used selected DISK", error_str), + request_error("Cannot use selected DISK", error_str), att); return; } diff --git a/src/sunstone/OpenNebulaVNC.rb b/src/sunstone/OpenNebulaVNC.rb index 71c92b6fe2..8d0285c079 100644 --- a/src/sunstone/OpenNebulaVNC.rb +++ b/src/sunstone/OpenNebulaVNC.rb @@ -21,7 +21,7 @@ require 'OpenNebula' # This class provides support for launching and stopping a websockify proxy # class OpenNebulaVNC - def initialize(config, opt={:json_errors => true}) + def initialize(config, logger, opt={:json_errors => true}) @proxy_path = config[:vnc_proxy_path] @proxy_base_port = config[:vnc_proxy_base_port].to_i @@ -36,6 +36,7 @@ class OpenNebulaVNC end @options = opt + @logger = logger end # Start a VNC proxy @@ -71,7 +72,7 @@ class OpenNebulaVNC cmd ="#{@proxy_path} #{proxy_options} #{proxy_port} #{host}:#{vnc_port}" begin - $stderr.puts("Starting vnc proxy: #{cmd}") + @logger.info { "Starting vnc proxy: #{cmd}" } pipe = IO.popen(cmd) rescue Exception => e return [500, OpenNebula::Error.new(e.message).to_json] diff --git a/src/sunstone/bin/sunstone-server b/src/sunstone/bin/sunstone-server index 155ff26260..171a8a6938 100755 --- a/src/sunstone/bin/sunstone-server +++ b/src/sunstone/bin/sunstone-server @@ -53,7 +53,7 @@ setup() start() { if [ ! -f "$SUNSTONE_SERVER" ]; then - echo "Can not find $SUNSTONE_SERVER." + echo "Cannot find $SUNSTONE_SERVER." exit 1 fi diff --git a/src/sunstone/config.ru b/src/sunstone/config.ru deleted file mode 100644 index aa4380a728..0000000000 --- a/src/sunstone/config.ru +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/ruby - -# -------------------------------------------------------------------------- # -# Copyright 2002-2012, 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. # -#--------------------------------------------------------------------------- # - -$: << File.dirname(__FILE__) - -require 'sunstone-server.rb' - -run Sinatra::Application diff --git a/src/sunstone/etc/sunstone-server.conf b/src/sunstone/etc/sunstone-server.conf index bcc7e8225f..cddab640a1 100644 --- a/src/sunstone/etc/sunstone-server.conf +++ b/src/sunstone/etc/sunstone-server.conf @@ -1,6 +1,9 @@ # OpenNebula sever contact information :one_xmlrpc: http://localhost:2633/RPC2 +# 0 = ERROR, 1 = WARNING, 2 = INFO, 3 = DEBUG +:debug_level: 3 + # Server Configuration :host: 127.0.0.1 :port: 9869 diff --git a/src/sunstone/models/SunstoneServer.rb b/src/sunstone/models/SunstoneServer.rb index 165f758669..6696d7f436 100644 --- a/src/sunstone/models/SunstoneServer.rb +++ b/src/sunstone/models/SunstoneServer.rb @@ -14,6 +14,8 @@ # limitations under the License. # #--------------------------------------------------------------------------- # +require 'CloudServer' + require 'OpenNebulaJSON' include OpenNebulaJSON @@ -22,14 +24,15 @@ require 'OpenNebulaVNC' require 'OpenNebulaJSON/JSONUtils' include JSONUtils -class SunstoneServer +class SunstoneServer < CloudServer # FLAG that will filter the elements retrieved from the Pools POOL_FILTER = Pool::INFO_ALL # Secs to sleep between checks to see if image upload to repo is finished IMAGE_POLL_SLEEP_TIME = 5 - def initialize(client) + def initialize(client, config, logger) + super(config, logger) @client = client end @@ -194,7 +197,8 @@ class SunstoneServer begin log = File.read(vm_log_file) rescue Exception => e - return [200, "Log for VM #{id} not available"] + msg = "Log for VM #{id} not available" + return [200, {:vm_log => msg}.to_json] end return [200, {:vm_log => log}.to_json] @@ -210,7 +214,7 @@ class SunstoneServer return [404, resource.to_json] end - vnc_proxy = OpenNebulaVNC.new(config) + vnc_proxy = OpenNebulaVNC.new(config, logger) return vnc_proxy.start(resource) end @@ -221,7 +225,8 @@ class SunstoneServer begin OpenNebulaVNC.stop(pipe) rescue Exception => e - error = Error.new(e.message) + logger.error {e.message} + error = Error.new("Error stopping VNC. Please check server logs.") return [500, error.to_json] end diff --git a/src/sunstone/public/css/login.css b/src/sunstone/public/css/login.css index 9c92aa9279..d275f49a57 100644 --- a/src/sunstone/public/css/login.css +++ b/src/sunstone/public/css/login.css @@ -134,10 +134,17 @@ div#login input#login_btn:hover { .error_message { display: none; position: relative; + width:400px; + margin-left: auto; + margin-right: auto; top: 80px; - font-family: Arial, Helvetica, sans-serif; - color:red; - font-size:1.6em; + font-size:1.0em; +} + +#login_spinner { + left: 44px; + position: relative; + top: 2px; } #label_remember { diff --git a/src/sunstone/public/js/login.js b/src/sunstone/public/js/login.js index 953f46aa1f..6b460d35c0 100644 --- a/src/sunstone/public/js/login.js +++ b/src/sunstone/public/js/login.js @@ -24,14 +24,19 @@ function auth_error(req, error){ switch (status){ case 401: - $("#one_error").hide(); - $("#auth_error").fadeIn("slow"); + $("#error_box").text("Invalid username or password"); break; case 500: - $("#auth_error").hide(); - $("#one_error").fadeIn("slow"); + $("#error_box").text("OpenNebula is not running or there was a server exception. Please check the server logs."); break; + case 0: + $("#error_box").text("No answer from server. Is it running?"); + break; + default: + $("#error_box").text("Unexpected error. Status "+status+". Check the server logs."); }; + $("#error_box").fadeIn("slow"); + $("#login_spinner").hide(); } function authenticate(){ @@ -39,6 +44,9 @@ function authenticate(){ var password = $("#password").val(); var remember = $("#check_remember").is(":checked"); + $("#error_box").fadeOut("slow"); + $("#login_spinner").show(); + OpenNebula.Auth.login({ data: {username: username , password: password} , remember: remember @@ -61,4 +69,5 @@ $(document).ready(function(){ }; $("input#username.box").focus(); + $("#login_spinner").hide(); }); diff --git a/src/sunstone/public/js/plugins/users-tab.js b/src/sunstone/public/js/plugins/users-tab.js index a9d35c164f..19d48435e1 100644 --- a/src/sunstone/public/js/plugins/users-tab.js +++ b/src/sunstone/public/js/plugins/users-tab.js @@ -131,9 +131,11 @@ var user_actions = { "User.passwd" : { type: "multiple", call: OpenNebula.User.passwd, - //nocallback + callback: function(req,res){ + notifyMessage(tr("Change password successful")); + }, elements: userElements, - error: onError + error: onError, }, "User.chgrp" : { type: "multiple", @@ -492,6 +494,7 @@ function popUpCreateUserDialog(){ function popUpUpdatePasswordDialog(){ + $('#new_password',$update_pw_dialog).val(""); $update_pw_dialog.dialog('open'); } diff --git a/src/sunstone/sunstone-server.rb b/src/sunstone/sunstone-server.rb index 2e09422136..21230aa0f5 100755 --- a/src/sunstone/sunstone-server.rb +++ b/src/sunstone/sunstone-server.rb @@ -32,7 +32,9 @@ else end SUNSTONE_AUTH = VAR_LOCATION + "/.one/sunstone_auth" +SUNSTONE_LOG = LOG_LOCATION + "/sunstone.log" CONFIGURATION_FILE = ETC_LOCATION + "/sunstone-server.conf" + PLUGIN_CONFIGURATION_FILE = ETC_LOCATION + "/sunstone-plugins.yaml" SUNSTONE_ROOT_DIR = File.dirname(__FILE__) @@ -54,27 +56,42 @@ require 'CloudAuth' require 'SunstoneServer' require 'SunstonePlugins' + +############################################################################## +# Configuration +############################################################################## + begin conf = YAML.load_file(CONFIGURATION_FILE) rescue Exception => e - puts "Error parsing config file #{CONFIGURATION_FILE}: #{e.message}" + STDERR.puts "Error parsing config file #{CONFIGURATION_FILE}: #{e.message}" exit 1 end -############################################################################## -# Sinatra Configuration -############################################################################## -use Rack::Session::Pool, :key => 'sunstone' +conf[:debug_level] ||= 3 + +CloudServer.print_configuration(conf) + +#Sinatra configuration + set :config, conf set :bind, settings.config[:host] set :port, settings.config[:port] +use Rack::Session::Pool, :key => 'sunstone' + +# Enable logger + +include CloudLogger +enable_logging SUNSTONE_LOG, settings.config[:debug_level].to_i + begin ENV["ONE_CIPHER_AUTH"] = SUNSTONE_AUTH cloud_auth = CloudAuth.new(settings.config) rescue => e - puts "Error initializing authentication system" - puts e.message + settings.logger.error { + "Error initializing authentication system" } + settings.logger.error { e.message } exit -1 end @@ -93,10 +110,12 @@ helpers do settings.cloud_auth.update_userpool_cache result = settings.cloud_auth.auth(request.env, params) rescue Exception => e - error 500, e.message + error 500, "" + logger.error { e.message } end if result.nil? + logger.info { "Unauthorized login attempt" } return [401, ""] else client = settings.cloud_auth.client(result) @@ -105,7 +124,7 @@ helpers do user = OpenNebula::User.new_with_id(user_id, client) rc = user.info if OpenNebula.is_error?(rc) - # Add a log message + logger.error { rc.message } return [500, ""] end @@ -157,7 +176,9 @@ before do halt 401 unless authorized? @SunstoneServer = SunstoneServer.new( - settings.cloud_auth.client(session[:user])) + settings.cloud_auth.client(session[:user]), + settings.config, + settings.logger) end end @@ -244,7 +265,10 @@ end post '/config' do begin body = JSON.parse(request.body.read) - rescue + rescue Exception => e + msg = "Error parsing configuration JSON" + logger.error { msg } + logger.error { e.message } [500, OpenNebula::Error.new(msg).to_json] end diff --git a/src/sunstone/templates/login.html b/src/sunstone/templates/login.html index c942f3184f..1dc5352d14 100644 --- a/src/sunstone/templates/login.html +++ b/src/sunstone/templates/login.html @@ -3,6 +3,7 @@ OpenNebula Sunstone Login + @@ -25,11 +26,7 @@
-
- Invalid username or password -
-
- OpenNebula is not running +
@@ -43,6 +40,7 @@ + retrieving
diff --git a/src/tm/TransferManager.cc b/src/tm/TransferManager.cc index d3d1212d84..13af39a96b 100644 --- a/src/tm/TransferManager.cc +++ b/src/tm/TransferManager.cc @@ -1288,14 +1288,17 @@ void TransferManager::load_mads(int uid) int rc; string name; - const VectorAttribute * vattr; + const VectorAttribute * vattr = 0; TransferManagerDriver * tm_driver = 0; oss << "Loading Transfer Manager driver."; NebulaLog::log("TM",Log::INFO,oss); - vattr = static_cast(mad_conf[0]); + if ( mad_conf.size() > 0 ) + { + vattr = static_cast(mad_conf[0]); + } if ( vattr == 0 ) { diff --git a/src/tm/TransferManagerDriver.cc b/src/tm/TransferManagerDriver.cc index 6eb1e2b8c6..f50388ec7b 100644 --- a/src/tm/TransferManagerDriver.cc +++ b/src/tm/TransferManagerDriver.cc @@ -142,7 +142,7 @@ void TransferManagerDriver::protocol( getline(is,info); os.str(""); - os << "Error excuting image transfer script"; + os << "Error executing image transfer script"; if (!info.empty() && info[0] != '-') { diff --git a/src/tm_mad/vmware/functions.sh b/src/tm_mad/vmware/functions.sh index d55effbd78..e66d89ee44 100644 --- a/src/tm_mad/vmware/functions.sh +++ b/src/tm_mad/vmware/functions.sh @@ -24,7 +24,7 @@ function fix_iso { if [ $? -eq 0 ]; then bname=`basename $dst_path` exec_and_log "ln -s $bname $dst_path/$bname.iso" \ - "Can not link ISO file." + "Cannot link ISO file." fi fi } diff --git a/src/vm/VirtualMachine.cc b/src/vm/VirtualMachine.cc index 5d5595b7f4..38fd4100f0 100644 --- a/src/vm/VirtualMachine.cc +++ b/src/vm/VirtualMachine.cc @@ -183,7 +183,7 @@ int VirtualMachine::select(SqlDB * db) return 0; error_previous_history: - ose << "Can not get previous history record (seq:" << history->seq + ose << "Cannot get previous history record (seq:" << history->seq << ") for VM id: " << oid; log("ONE", Log::ERROR, ose); @@ -380,7 +380,7 @@ int VirtualMachine::parse_context(string& error_str) if (str == 0) { - NebulaLog::log("ONE",Log::ERROR, "Can not marshall CONTEXT"); + NebulaLog::log("ONE",Log::ERROR, "Cannot marshall CONTEXT"); return -1; } @@ -535,9 +535,7 @@ int VirtualMachine::automatic_requirements(string& error_str) ostringstream oss; string requirements; string cluster_id; - bool error = false; - - oss << "Incompatible cluster IDs."; + string vatt_cluster_id; // Get cluster id from all DISK vector attributes @@ -552,23 +550,16 @@ int VirtualMachine::automatic_requirements(string& error_str) continue; } - string vatt_cluster_id = vatt->vector_value("CLUSTER_ID"); + vatt_cluster_id = vatt->vector_value("CLUSTER_ID"); if ( !vatt_cluster_id.empty() ) { - oss << endl << "DISK [" << i << "]: IMAGE [" - << vatt->vector_value("IMAGE_ID") << "] from DATASTORE [" - << vatt->vector_value("DATASTORE_ID") << "] requires CLUSTER [" - << vatt_cluster_id << "]"; + if ( cluster_id != vatt_cluster_id ) + { + goto error; + } - if ( cluster_id.empty() ) - { - cluster_id = vatt_cluster_id; - } - else if ( cluster_id != vatt_cluster_id ) - { - error = true; - } + cluster_id = vatt_cluster_id; } } @@ -586,32 +577,19 @@ int VirtualMachine::automatic_requirements(string& error_str) continue; } - string vatt_cluster_id = vatt->vector_value("CLUSTER_ID"); + vatt_cluster_id = vatt->vector_value("CLUSTER_ID"); if ( !vatt_cluster_id.empty() ) { - oss << endl << "NIC [" << i << "]: NETWORK [" - << vatt->vector_value("NETWORK_ID") << "] requires CLUSTER [" - << vatt_cluster_id << "]"; + if ( cluster_id != vatt_cluster_id ) + { + goto error; + } - if ( cluster_id.empty() ) - { - cluster_id = vatt_cluster_id; - } - else if ( cluster_id != vatt_cluster_id ) - { - error = true; - } + cluster_id = vatt_cluster_id; } } - if ( error == true ) - { - error_str = oss.str(); - - return -1; - } - if ( !cluster_id.empty() ) { oss.str(""); @@ -628,6 +606,63 @@ int VirtualMachine::automatic_requirements(string& error_str) } return 0; + +error: + + oss << "Incompatible cluster IDs."; + + // Get cluster id from all DISK vector attributes + + v_attributes.clear(); + num_vatts = obj_template->get("DISK",v_attributes); + + for(int i=0; i(v_attributes[i]); + + if ( vatt == 0 ) + { + continue; + } + + vatt_cluster_id = vatt->vector_value("CLUSTER_ID"); + + if ( !vatt_cluster_id.empty() ) + { + oss << endl << "DISK [" << i << "]: IMAGE [" + << vatt->vector_value("IMAGE_ID") << "] from DATASTORE [" + << vatt->vector_value("DATASTORE_ID") << "] requires CLUSTER [" + << vatt_cluster_id << "]"; + } + } + + // Get cluster id from all NIC vector attributes + + v_attributes.clear(); + num_vatts = obj_template->get("NIC",v_attributes); + + for(int i=0; i(v_attributes[i]); + + if ( vatt == 0 ) + { + continue; + } + + vatt_cluster_id = vatt->vector_value("CLUSTER_ID"); + + if ( !vatt_cluster_id.empty() ) + { + oss << endl << "NIC [" << i << "]: NETWORK [" + << vatt->vector_value("NETWORK_ID") << "] requires CLUSTER [" + << vatt_cluster_id << "]"; + } + } + + error_str = oss.str(); + + return -1; } /* ------------------------------------------------------------------------ */ @@ -920,15 +955,15 @@ int VirtualMachine::get_disk_images(string& error_str) return 0; error_max_os: - error_str = "VM can not use more than one OS image."; + error_str = "VM cannot use more than one OS image."; goto error_common; error_max_cd: - error_str = "VM can not use more than one CDROM image."; + error_str = "VM cannot use more than one CDROM image."; goto error_common; error_max_db: - error_str = "VM can not use more than 10 DATABLOCK images."; + error_str = "VM cannot use more than 10 DATABLOCK images."; goto error_common; error_common: @@ -1216,7 +1251,7 @@ error_saved: goto error_common; error_image_id: - oss << "The DISK " << disk_id << "does not have a valid IMAGE_ID."; + oss << "The DISK " << disk_id << " does not have a valid IMAGE_ID."; goto error_common; error_not_found: diff --git a/src/vm/VirtualMachinePool.cc b/src/vm/VirtualMachinePool.cc index 6c5031389b..206d2b4cb4 100644 --- a/src/vm/VirtualMachinePool.cc +++ b/src/vm/VirtualMachinePool.cc @@ -170,7 +170,7 @@ VirtualMachinePool::VirtualMachinePool(SqlDB * db, { ostringstream oss; - oss << "Unkown VM_HOOK " << on << ". Hook not registered!"; + oss << "Unknown VM_HOOK " << on << ". Hook not registered!"; NebulaLog::log("VM",Log::WARNING,oss); } } diff --git a/src/vmm_mad/ec2/one_vmm_ec2.rb b/src/vmm_mad/ec2/one_vmm_ec2.rb index a4ce862b05..dbcd250245 100755 --- a/src/vmm_mad/ec2/one_vmm_ec2.rb +++ b/src/vmm_mad/ec2/one_vmm_ec2.rb @@ -185,7 +185,7 @@ class EC2Driver < VirtualMachineDriver return unless ec2_info if !ec2_value(ec2_info, 'AMI') - msg = "Can not find AMI in deployment file" + msg = "Cannot find AMI in deployment file" send_message(ACTION[:deploy], RESULT[:failure], id, msg) return end @@ -294,7 +294,7 @@ private if !local_dfile send_message(ACTION[:deploy],RESULT[:failure],id, - "Can not open deployment file #{local_dfile}") + "Cannot open deployment file #{local_dfile}") return end @@ -322,7 +322,7 @@ private ec2 = all_ec2_elements[0] else send_message(ACTION[:deploy],RESULT[:failure],id, - "Can not find EC2 element in deployment file "<< + "Cannot find EC2 element in deployment file "<< "#{local_dfile} or couldn't find any EC2 site matching "<< "one of the template.") return diff --git a/src/vmm_mad/exec/one_vmm_exec.rb b/src/vmm_mad/exec/one_vmm_exec.rb index 3570203cef..bd53cfe49e 100755 --- a/src/vmm_mad/exec/one_vmm_exec.rb +++ b/src/vmm_mad/exec/one_vmm_exec.rb @@ -259,7 +259,7 @@ class ExecDriver < VirtualMachineDriver if !local_dfile || File.zero?(local_dfile) send_message(ACTION[:deploy],RESULT[:failure],id, - "Can not open deployment file #{local_dfile}") + "Cannot open deployment file #{local_dfile}") return end diff --git a/src/vmm_mad/remotes/vmware/vmware_driver.rb b/src/vmm_mad/remotes/vmware/vmware_driver.rb index 570b7b0b81..c5be771f11 100644 --- a/src/vmm_mad/remotes/vmware/vmware_driver.rb +++ b/src/vmm_mad/remotes/vmware/vmware_driver.rb @@ -167,7 +167,7 @@ class VMwareDriver # Define the VM dfile = File.dirname(File.dirname(checkpoint)) + "/deployment.0" rescue => e - OpenNebula.log_error("Can not open checkpoint #{e.message}") + OpenNebula.log_error("Cannot open checkpoint #{e.message}") exit -1 end