mirror of
https://github.com/OpenNebula/one.git
synced 2025-03-21 14:50:08 +03:00
Merge branch 'feature-873'
This commit is contained in:
commit
cee35c0750
@ -99,7 +99,7 @@ cmd=CommandParser::CmdParser.new(ARGV) do
|
||||
arg_list.map! {|a| a.to_i }
|
||||
[0, arg_list]
|
||||
end
|
||||
|
||||
|
||||
set :format, :userid, OpenNebulaHelper.rname_to_id_desc("USER") do |arg|
|
||||
OpenNebulaHelper.rname_to_id(arg, "USER")
|
||||
end
|
||||
@ -130,6 +130,26 @@ cmd=CommandParser::CmdParser.new(ARGV) do
|
||||
exit_with_code 0
|
||||
end
|
||||
|
||||
########################################################################
|
||||
unset_desc = <<-EOT.unindent
|
||||
Unset a quota for a given user.
|
||||
Examples:
|
||||
onequota unset 3 cpu
|
||||
onequota unset 4 cpu,memory,storage
|
||||
EOT
|
||||
|
||||
command :unset, unset_desc, :userid, :quota_list do
|
||||
user_id, keys = args
|
||||
|
||||
values_hash = Hash.new
|
||||
keys.each_with_index { |k,i|
|
||||
values_hash[k.to_sym] = 0
|
||||
}
|
||||
|
||||
quota.set_quota(user_id, values_hash)
|
||||
exit_with_code 0
|
||||
end
|
||||
|
||||
########################################################################
|
||||
delete_desc = "Delete the defined quotas for the given user"
|
||||
|
||||
@ -140,7 +160,7 @@ cmd=CommandParser::CmdParser.new(ARGV) do
|
||||
|
||||
########################################################################
|
||||
show_desc = "Show the user's quota and usage. (usage/quota)"
|
||||
|
||||
|
||||
FORCE={
|
||||
:name => "force",
|
||||
:short => "-f",
|
||||
|
@ -154,6 +154,19 @@ class Quota
|
||||
set(QUOTA_TABLE, uid, quota)
|
||||
end
|
||||
|
||||
# Retrieves quota information for a given user
|
||||
#
|
||||
# @param [Integer, nil] uid the user id from which get the quota
|
||||
# information, if nil will retrieve the quotas for all users.
|
||||
# @return [Hash] Hash containing the quota information and the user id
|
||||
#
|
||||
# {
|
||||
# :uid => 4,
|
||||
# :cpu => 8,
|
||||
# :memory => 8064,
|
||||
# :num_vms => 4,
|
||||
# :storage => 1240019
|
||||
# }
|
||||
def get_quota(uid=nil)
|
||||
limit = get(QUOTA_TABLE, uid)
|
||||
limit ? limit : @conf[:defaults].merge!(:uid => uid)
|
||||
@ -192,14 +205,16 @@ class Quota
|
||||
msg = ""
|
||||
separator = ""
|
||||
info.each { |qname, quota_requested|
|
||||
unless quota[qname]
|
||||
unless quota[qname] || quota[qname]==0
|
||||
next
|
||||
end
|
||||
|
||||
used = send(DB_QUOTA_SCHEMA[qname].name.to_sym, total[qname])
|
||||
request = send(DB_QUOTA_SCHEMA[qname].name.to_sym, quota_requested)
|
||||
limit = send(DB_QUOTA_SCHEMA[qname].name.to_sym, quota[qname])
|
||||
spent = used + request
|
||||
type = DB_QUOTA_SCHEMA[qname].name.to_sym
|
||||
|
||||
used = send(type, total[qname])
|
||||
request = send(type, quota_requested)
|
||||
limit = send(type, quota[qname])
|
||||
spent = used + request
|
||||
|
||||
if spent > limit
|
||||
msg << separator
|
||||
@ -228,6 +243,22 @@ class Quota
|
||||
###########################################################################
|
||||
# Usage
|
||||
###########################################################################
|
||||
# Retrieves usage information for a given user
|
||||
#
|
||||
# @param [Integer] uid the user id from which get the usage information.
|
||||
# @param ["VM", "IMAGE"] resource kind of resource. If nil will return
|
||||
# the usage for all kinds of resources
|
||||
# @param [true, false] force If true will force the usage calculation
|
||||
# instead of retrieving it from the cache
|
||||
# @return [Hash] Hash containing the usage information and the user id
|
||||
#
|
||||
# {
|
||||
# :uid => 4,
|
||||
# :cpu => 8,
|
||||
# :memory => 8064,
|
||||
# :num_vms => 4,
|
||||
# :storage => 1240019
|
||||
# }
|
||||
def get_usage(user_id, resource=nil, force=false)
|
||||
if force
|
||||
if RESOURCES.include?(resource)
|
||||
@ -242,9 +273,9 @@ class Quota
|
||||
pool = get_pool(res, user_id)
|
||||
base_xpath = "/#{res}_POOL/#{resource}"
|
||||
Quota.const_get("#{res}_USAGE".to_sym).each { |key, params|
|
||||
usage[key] ||= 0
|
||||
pool.each_xpath("#{base_xpath}/#{params[:xpath]}") { |elem|
|
||||
if elem
|
||||
usage[key] ||= 0
|
||||
if params[:count]
|
||||
usage[key] += 1
|
||||
else
|
||||
|
@ -31,7 +31,7 @@ describe "Quota testing" do
|
||||
<TEMPLATE>
|
||||
<CPU>2</CPU>
|
||||
<MEMORY>128</MEMORY>
|
||||
<TEMPLATE>
|
||||
</TEMPLATE>
|
||||
EOT
|
||||
|
||||
vm_base64 = Base64::encode64(vm_template)
|
||||
@ -41,7 +41,7 @@ describe "Quota testing" do
|
||||
image_template = <<-EOT
|
||||
<TEMPLATE>
|
||||
<PATH>/etc/hosts</PATH>
|
||||
<TEMPLATE>
|
||||
</TEMPLATE>
|
||||
EOT
|
||||
|
||||
image_base64 = Base64::encode64(image_template)
|
||||
@ -52,7 +52,7 @@ describe "Quota testing" do
|
||||
<TEMPLATE>
|
||||
<CPU>2</CPU>
|
||||
<MEMORY>128</MEMORY>
|
||||
<TEMPLATE>
|
||||
</TEMPLATE>
|
||||
EOT
|
||||
|
||||
temp_base64 = Base64::encode64(temp_template)
|
||||
@ -80,10 +80,10 @@ describe "Quota testing" do
|
||||
it "should check default cache (force)" do
|
||||
usage1force = @quota.get_usage(@uid1, nil, true)
|
||||
usage1force[:uid].should eql(0)
|
||||
usage1force[:num_vms].should eql(nil)
|
||||
usage1force[:cpu].should eql(nil)
|
||||
usage1force[:memory].should eql(nil)
|
||||
usage1force[:storage].should eql(nil)
|
||||
usage1force[:num_vms].should eql(0)
|
||||
usage1force[:cpu].should eql(0)
|
||||
usage1force[:memory].should eql(0)
|
||||
usage1force[:storage].should eql(0)
|
||||
end
|
||||
|
||||
it "should authorize the user because there is no quota defined" do
|
||||
@ -106,10 +106,10 @@ describe "Quota testing" do
|
||||
it "should check the usage cache is not updated" do
|
||||
usage1cache = @quota.get_usage(@uid1)
|
||||
usage1cache[:uid].should eql(0)
|
||||
usage1cache[:num_vms].should eql(nil)
|
||||
usage1cache[:cpu].should eql(nil)
|
||||
usage1cache[:memory].should eql(nil)
|
||||
usage1cache[:storage].should eql(nil)
|
||||
usage1cache[:num_vms].should eql(0)
|
||||
usage1cache[:cpu].should eql(0.0)
|
||||
usage1cache[:memory].should eql(0)
|
||||
usage1cache[:storage].should eql(0)
|
||||
end
|
||||
|
||||
it "should check the cache (force)" do
|
||||
@ -118,7 +118,7 @@ describe "Quota testing" do
|
||||
usage1force[:num_vms].should eql(1)
|
||||
usage1force[:cpu].should eql(2.0)
|
||||
usage1force[:memory].should eql(128)
|
||||
usage1force[:storage].should eql(nil)
|
||||
usage1force[:storage].should eql(0)
|
||||
end
|
||||
|
||||
it "should check the usage cache is updated and contains the last usage" do
|
||||
@ -127,7 +127,7 @@ describe "Quota testing" do
|
||||
usage1cache[:num_vms].should eql(1)
|
||||
usage1cache[:cpu].should eql(2.0)
|
||||
usage1cache[:memory].should eql(128)
|
||||
usage1cache[:storage].should eql(nil)
|
||||
usage1cache[:storage].should eql(0)
|
||||
end
|
||||
|
||||
it "should add a new Image" do
|
||||
@ -146,7 +146,7 @@ describe "Quota testing" do
|
||||
usage1cache[:num_vms].should eql(1)
|
||||
usage1cache[:cpu].should eql(2.0)
|
||||
usage1cache[:memory].should eql(128)
|
||||
usage1cache[:storage].should eql(nil)
|
||||
usage1cache[:storage].should eql(0)
|
||||
end
|
||||
|
||||
it "should check the cache (force)" do
|
||||
@ -252,7 +252,7 @@ describe "Quota testing" do
|
||||
end
|
||||
|
||||
it "should not authorize the user because the vm quota is spent" do
|
||||
err_msg = "CPU quota exceeded (Quota: 2.4, Used: 4.0, Asked: 2.0)."
|
||||
err_msg = "CPU quota exceeded (Quota: 2.4, Used: 4.0, Requested: 2.0)"
|
||||
@quota.authorize(@uid1, @acl_vm_create).should eql(err_msg)
|
||||
@quota.authorize(@uid1, @acl_template_instantiate).should eql(err_msg)
|
||||
|
||||
@ -320,7 +320,7 @@ describe "Quota testing" do
|
||||
@quota.authorize(@uid1, @acl_vm_create).should eql(false)
|
||||
@quota.authorize(@uid1, @acl_template_instantiate).should eql(false)
|
||||
|
||||
err_msg = "STORAGE quota exceeded (Quota: 0, Used: 2000, Asked: 1474)."
|
||||
err_msg = "STORAGE quota exceeded (Quota: 0, Used: 2000, Requested: 271)"
|
||||
@quota.authorize(@uid1, @acl_image_create).should eql(err_msg)
|
||||
end
|
||||
|
||||
|
@ -22,6 +22,18 @@ require 'CloudAuth'
|
||||
# API (OCA). Any cloud implementation should derive from this class
|
||||
##############################################################################
|
||||
class CloudServer
|
||||
##########################################################################
|
||||
# Class Constants. Define the OpenNebula Error and HTTP codes mapping
|
||||
##########################################################################
|
||||
HTTP_ERROR_CODE = {
|
||||
OpenNebula::Error::EAUTHENTICATION => 401,
|
||||
OpenNebula::Error::EAUTHORIZATION => 403,
|
||||
OpenNebula::Error::ENO_EXISTS => 404,
|
||||
OpenNebula::Error::EACTION => 500,
|
||||
OpenNebula::Error::EXML_RPC_API => 500,
|
||||
OpenNebula::Error::EINTERNAL => 500,
|
||||
OpenNebula::Error::ENOTDEFINED => 500
|
||||
}
|
||||
|
||||
##########################################################################
|
||||
# Public attributes
|
||||
|
@ -27,6 +27,8 @@ require 'VirtualNetworkOCCI'
|
||||
require 'VirtualNetworkPoolOCCI'
|
||||
require 'ImageOCCI'
|
||||
require 'ImagePoolOCCI'
|
||||
require 'UserOCCI'
|
||||
require 'UserPoolOCCI'
|
||||
|
||||
require 'pp'
|
||||
|
||||
@ -36,7 +38,6 @@ require 'pp'
|
||||
# OpenNebula Engine
|
||||
##############################################################################
|
||||
class OCCIServer < CloudServer
|
||||
|
||||
# Server initializer
|
||||
# config_file:: _String_ path of the config file
|
||||
# template:: _String_ path to the location of the templates
|
||||
@ -72,7 +73,7 @@ class OCCIServer < CloudServer
|
||||
def get_computes(request)
|
||||
# --- Get User's VMs ---
|
||||
user_flag = -1
|
||||
|
||||
|
||||
vmpool = VirtualMachinePoolOCCI.new(
|
||||
self.client,
|
||||
user_flag)
|
||||
@ -99,14 +100,14 @@ class OCCIServer < CloudServer
|
||||
def get_networks(request)
|
||||
# --- Get User's VNETs ---
|
||||
user_flag = -1
|
||||
|
||||
|
||||
network_pool = VirtualNetworkPoolOCCI.new(
|
||||
self.client,
|
||||
user_flag)
|
||||
|
||||
# --- Prepare XML Response ---
|
||||
rc = network_pool.info
|
||||
|
||||
|
||||
if OpenNebula.is_error?(rc)
|
||||
if rc.message.match("Error getting")
|
||||
return rc, 404
|
||||
@ -125,14 +126,14 @@ class OCCIServer < CloudServer
|
||||
def get_storages(request)
|
||||
# --- Get User's Images ---
|
||||
user_flag = -1
|
||||
|
||||
|
||||
image_pool = ImagePoolOCCI.new(
|
||||
self.client,
|
||||
user_flag)
|
||||
|
||||
# --- Prepare XML Response ---
|
||||
rc = image_pool.info
|
||||
|
||||
|
||||
if OpenNebula.is_error?(rc)
|
||||
if rc.message.match("Error getting")
|
||||
return rc, 404
|
||||
@ -144,6 +145,24 @@ class OCCIServer < CloudServer
|
||||
return to_occi_xml(image_pool, 200)
|
||||
end
|
||||
|
||||
# Gets the pool representation of USERs
|
||||
# request:: _Hash_ hash containing the data of the request
|
||||
# [return] _String_,_Integer_ User pool representation or error,
|
||||
# status code
|
||||
def get_users(request)
|
||||
# --- Get Users Pool ---
|
||||
user_pool = UserPoolOCCI.new(self.client)
|
||||
|
||||
# --- Prepare XML Response ---
|
||||
rc = user_pool.info
|
||||
|
||||
if OpenNebula.is_error?(rc)
|
||||
return rc, CloudServer::HTTP_ERROR_CODE[rc.errno]
|
||||
end
|
||||
|
||||
return to_occi_xml(user_pool, 200)
|
||||
end
|
||||
|
||||
############################################################################
|
||||
############################################################################
|
||||
# ENTITY RESOURCE METHODS
|
||||
@ -190,7 +209,7 @@ class OCCIServer < CloudServer
|
||||
|
||||
# --- Prepare XML Response ---
|
||||
rc = vm.info
|
||||
|
||||
|
||||
if OpenNebula.is_error?(rc)
|
||||
if rc.message.match("Error getting")
|
||||
return rc, 404
|
||||
@ -232,58 +251,20 @@ class OCCIServer < CloudServer
|
||||
vm = VirtualMachineOCCI.new(
|
||||
VirtualMachine.build_xml(params[:id]),
|
||||
self.client)
|
||||
|
||||
rc = vm.info
|
||||
return rc, 400 if OpenNebula.is_error?(rc)
|
||||
|
||||
xmldoc = XMLElement.build_xml(request.body, 'COMPUTE')
|
||||
vm_info = XMLElement.new(xmldoc) if xmldoc != nil
|
||||
|
||||
# Check the number of changes in the request
|
||||
image_name = nil
|
||||
image_type = nil
|
||||
vm_info.each('DISK/SAVE_AS') { |disk|
|
||||
if image_name
|
||||
error_msg = "It is only allowed one save_as per request"
|
||||
return OpenNebula::Error.new(error_msg), 400
|
||||
end
|
||||
image_name = disk.attr('.', 'name')
|
||||
image_type = disk.attr('.', 'type')
|
||||
}
|
||||
state = vm_info['STATE']
|
||||
|
||||
if image_name && state
|
||||
error_msg = "It is not allowed to change the state and save_as" <<
|
||||
" a disk in the same request"
|
||||
return OpenNebula::Error.new(error_msg), 400
|
||||
elsif image_name
|
||||
# Get the disk id
|
||||
disk_id = vm_info.attr('DISK/SAVE_AS/..', 'id')
|
||||
if disk_id.nil?
|
||||
error_msg = "DISK id attribute not specified"
|
||||
return OpenNebula::Error.new(error_msg), 400
|
||||
end
|
||||
|
||||
disk_id = disk_id.to_i
|
||||
if vm["TEMPLATE/DISK[DISK_ID=\"#{disk_id}\"]/SAVE_AS"]
|
||||
error_msg = "The disk #{disk_id} is already" <<
|
||||
" suppossed to be saved"
|
||||
return OpenNebula::Error.new(error_msg), 400
|
||||
end
|
||||
|
||||
rc = vm.save_as(disk_id, image_name)
|
||||
if OpenNebula.is_error?(rc)
|
||||
image.delete
|
||||
return rc, 400
|
||||
end
|
||||
elsif state
|
||||
rc = vm.mk_action(state)
|
||||
return rc, 400 if OpenNebula.is_error?(rc)
|
||||
rc = vm.info
|
||||
if OpenNebula.is_error?(rc)
|
||||
return rc, CloudServer::HTTP_ERROR_CODE[rc.errno]
|
||||
end
|
||||
|
||||
# --- Prepare XML Response ---
|
||||
vm.info
|
||||
return to_occi_xml(vm, 202)
|
||||
result, code = vm.update_from_xml(request.body)
|
||||
|
||||
if OpenNebula.is_error?(result)
|
||||
return result, code
|
||||
else
|
||||
vm.info
|
||||
return to_occi_xml(vm, code)
|
||||
end
|
||||
end
|
||||
|
||||
############################################################################
|
||||
@ -324,7 +305,7 @@ class OCCIServer < CloudServer
|
||||
|
||||
# --- Prepare XML Response ---
|
||||
rc = network.info
|
||||
|
||||
|
||||
if OpenNebula.is_error?(rc)
|
||||
if rc.message.match("Error getting")
|
||||
return rc, 404
|
||||
@ -354,7 +335,7 @@ class OCCIServer < CloudServer
|
||||
|
||||
return "", 204
|
||||
end
|
||||
|
||||
|
||||
# Updates a NETWORK resource
|
||||
# request:: _Hash_ hash containing the data of the request
|
||||
# [return] _String_,_Integer_ Update confirmation msg or error,
|
||||
@ -366,10 +347,10 @@ class OCCIServer < CloudServer
|
||||
vnet = VirtualNetworkOCCI.new(
|
||||
VirtualNetwork.build_xml(params[:id]),
|
||||
self.client)
|
||||
|
||||
|
||||
rc = vnet.info
|
||||
return rc, 400 if OpenNebula.is_error?(rc)
|
||||
|
||||
|
||||
if vnet_info['PUBLIC'] == 'YES'
|
||||
rc = vnet.publish
|
||||
return rc, 400 if OpenNebula.is_error?(rc)
|
||||
@ -432,7 +413,7 @@ class OCCIServer < CloudServer
|
||||
self.client)
|
||||
|
||||
rc = image.info
|
||||
|
||||
|
||||
if OpenNebula.is_error?(rc)
|
||||
if rc.message.match("Error getting")
|
||||
return rc, 404
|
||||
@ -464,7 +445,7 @@ class OCCIServer < CloudServer
|
||||
|
||||
return "", 204
|
||||
end
|
||||
|
||||
|
||||
# Updates a STORAGE resource
|
||||
# request:: _Hash_ hash containing the data of the request
|
||||
# [return] _String_,_Integer_ Update confirmation msg or error,
|
||||
@ -476,10 +457,10 @@ class OCCIServer < CloudServer
|
||||
image = ImageOCCI.new(
|
||||
Image.build_xml(params[:id]),
|
||||
self.client)
|
||||
|
||||
|
||||
rc = image.info
|
||||
return rc, 400 if OpenNebula.is_error?(rc)
|
||||
|
||||
|
||||
if image_info['PERSISTENT'] && image_info['PUBLIC']
|
||||
error_msg = "It is not allowed more than one change per request"
|
||||
return OpenNebula::Error.new(error_msg), 400
|
||||
@ -501,4 +482,24 @@ class OCCIServer < CloudServer
|
||||
image.info
|
||||
return to_occi_xml(image, 202)
|
||||
end
|
||||
|
||||
# Get the representation of a USER
|
||||
# request:: _Hash_ hash containing the data of the request
|
||||
# [return] _String_,_Integer_ USER representation or error,
|
||||
# status code
|
||||
def get_user(request, params)
|
||||
# --- Get the USER ---
|
||||
user = UserOCCI.new(
|
||||
User.build_xml(params[:id]),
|
||||
self.client)
|
||||
|
||||
# --- Prepare XML Response ---
|
||||
rc = user.info
|
||||
|
||||
if OpenNebula.is_error?(rc)
|
||||
return rc, CloudServer::HTTP_ERROR_CODE[rc.errno]
|
||||
end
|
||||
|
||||
return to_occi_xml(user, 200)
|
||||
end
|
||||
end
|
||||
|
64
src/cloud/occi/lib/UserOCCI.rb
Normal file
64
src/cloud/occi/lib/UserOCCI.rb
Normal file
@ -0,0 +1,64 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
require 'OpenNebula'
|
||||
|
||||
include OpenNebula
|
||||
|
||||
require 'quota'
|
||||
|
||||
class UserOCCI < User
|
||||
FORCE_USAGE = true
|
||||
|
||||
OCCI_USER = %q{
|
||||
<USER href="<%= base_url %>/user/<%= self.id.to_s %>">
|
||||
<ID><%= self.id.to_s %></ID>
|
||||
<NAME><%= self.name %></NAME>
|
||||
<QUOTA>
|
||||
<% user_quota.each { |key,value|
|
||||
key_s = key.to_s.upcase
|
||||
value_i = value.to_i %>
|
||||
<<%= key_s %>><%= value_i %></<%= key_s %>>
|
||||
<% } %>
|
||||
</QUOTA>
|
||||
<USAGE>
|
||||
<% user_usage.each { |key,value|
|
||||
key_s = key.to_s.upcase
|
||||
value_i = value.to_i %>
|
||||
<<%= key_s %>><%= value_i %></<%= key_s %>>
|
||||
<% } %>
|
||||
</USAGE>
|
||||
</USER>
|
||||
}
|
||||
|
||||
# Class constructor
|
||||
def initialize(xml, client)
|
||||
super(xml, client)
|
||||
end
|
||||
|
||||
# Creates the OCCI representation of a User
|
||||
def to_occi(base_url)
|
||||
quota = Quota.new
|
||||
user_usage = quota.get_usage(self.id, nil, FORCE_USAGE)
|
||||
user_usage.delete(:uid)
|
||||
|
||||
user_quota = quota.get_quota(self.id)
|
||||
user_quota.delete(:uid)
|
||||
|
||||
occi = ERB.new(OCCI_USER)
|
||||
return occi.result(binding).gsub(/\n\s*/,'')
|
||||
end
|
||||
end
|
43
src/cloud/occi/lib/UserPoolOCCI.rb
Normal file
43
src/cloud/occi/lib/UserPoolOCCI.rb
Normal file
@ -0,0 +1,43 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
require 'OpenNebula'
|
||||
|
||||
include OpenNebula
|
||||
|
||||
class UserPoolOCCI < UserPool
|
||||
OCCI_USER_POOL = %q{
|
||||
<USER_COLLECTION>
|
||||
<% self.each{ |user| %>
|
||||
<USER href="<%= base_url %>/user/<%= user.id.to_s %>" name="<%= user.name %>"/>
|
||||
<% } %>
|
||||
</USER_COLLECTION>
|
||||
}
|
||||
|
||||
|
||||
# Creates the OCCI representation of a User Pool
|
||||
def to_occi(base_url)
|
||||
begin
|
||||
occi = ERB.new(OCCI_USER_POOL)
|
||||
occi_text = occi.result(binding)
|
||||
rescue Exception => e
|
||||
error = OpenNebula::Error.new(e.message)
|
||||
return error
|
||||
end
|
||||
|
||||
return occi_text.gsub(/\n\s*/,'')
|
||||
end
|
||||
end
|
@ -61,62 +61,48 @@ class VirtualMachineOCCI < VirtualMachine
|
||||
<% end %>
|
||||
</COMPUTE>
|
||||
}
|
||||
|
||||
|
||||
OCCI_ACTION = {
|
||||
"STOPPED" => { :from => ["ACTIVE"], :action => :stop},
|
||||
"SUSPENDED" => { :from => ["ACTIVE"], :action => :suspend},
|
||||
"RESUME" => { :from => ["STOPPED", "SUSPENDED"], :action => :resume},
|
||||
"CANCEL" => { :from => ["ACTIVE"], :action => :cancel},
|
||||
"SHUTDOWN" => { :from => ["ACTIVE"], :action => :shutdown},
|
||||
"DONE" => { :from => VM_STATE, :action => :finalize},
|
||||
}
|
||||
|
||||
# Class constructor
|
||||
def initialize(xml, client, xml_info=nil, types=nil, base=nil)
|
||||
super(xml, client)
|
||||
@vm_info = nil
|
||||
@template = nil
|
||||
@common_template = base + '/common.erb' if base
|
||||
|
||||
|
||||
if xml_info != nil
|
||||
xmldoc = XMLElement.build_xml(xml_info, 'COMPUTE')
|
||||
@vm_info = XMLElement.new(xmldoc) if xmldoc != nil
|
||||
end
|
||||
|
||||
|
||||
if @vm_info != nil
|
||||
itype = @vm_info['INSTANCE_TYPE']
|
||||
|
||||
|
||||
if itype != nil and types[itype.to_sym] != nil
|
||||
@template = base + "/#{types[itype.to_sym][:template]}"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
def mk_action(action_str)
|
||||
case action_str.downcase
|
||||
when "stopped"
|
||||
rc = self.stop
|
||||
when "suspended"
|
||||
rc = self.suspend
|
||||
when "resume"
|
||||
rc = self.resume
|
||||
when "cancel"
|
||||
rc = self.cancel
|
||||
when "shutdown"
|
||||
rc = self.shutdown
|
||||
when "done"
|
||||
rc = self.finalize
|
||||
else
|
||||
error_msg = "Invalid state"
|
||||
error = OpenNebula::Error.new(error_msg)
|
||||
return error
|
||||
end
|
||||
|
||||
return rc
|
||||
end
|
||||
|
||||
|
||||
def to_one_template()
|
||||
if @vm_info == nil
|
||||
error_msg = "Missing COMPUTE section in the XML body"
|
||||
return OpenNebula::Error.new(error_msg), 400
|
||||
end
|
||||
|
||||
|
||||
if @template == nil
|
||||
return OpenNebula::Error.new("Bad instance type"), 500
|
||||
end
|
||||
|
||||
|
||||
begin
|
||||
template = ERB.new(File.read(@common_template)).result(binding)
|
||||
template << ERB.new(File.read(@template)).result(binding)
|
||||
@ -124,10 +110,10 @@ class VirtualMachineOCCI < VirtualMachine
|
||||
error = OpenNebula::Error.new(e.message)
|
||||
return error
|
||||
end
|
||||
|
||||
|
||||
return template
|
||||
end
|
||||
|
||||
|
||||
# Creates the VMI representation of a Virtual Machine
|
||||
def to_occi(base_url)
|
||||
begin
|
||||
@ -138,9 +124,90 @@ class VirtualMachineOCCI < VirtualMachine
|
||||
return error
|
||||
end
|
||||
|
||||
|
||||
return occi_vm_text.gsub(/\n\s*/,'')
|
||||
end
|
||||
|
||||
# Update de resource from an XML representation of the COMPUTE
|
||||
# @param [String] xml_compute XML representation of the COMPUTE
|
||||
# @return [[nil, OpenNebula::Error], HTTP_CODE] If there is no error
|
||||
# the first component is nil.
|
||||
def update_from_xml(xml_compute)
|
||||
xmldoc = XMLElement.build_xml(xml_compute, 'COMPUTE')
|
||||
vm_info = XMLElement.new(xmldoc) if xmldoc != nil
|
||||
|
||||
action = nil
|
||||
args = []
|
||||
|
||||
# Check if a state change is required
|
||||
occi_state = vm_info['STATE']
|
||||
|
||||
if occi_state
|
||||
# If a state is provided
|
||||
occi_state.upcase!
|
||||
if OCCI_ACTION.keys.include?(occi_state)
|
||||
# If the requested state is one the OCCI action states
|
||||
shash = OCCI_ACTION[occi_state]
|
||||
if shash[:from].include?(state_str)
|
||||
# Action to be performed
|
||||
action = shash[:action]
|
||||
elsif occi_state != state_str
|
||||
# If the requested state is different from the resource
|
||||
# state but it does not belong to the "from" state array
|
||||
error_msg = "The state of the resource cannot be changed" \
|
||||
" from #{state_str} to #{occi_state}."
|
||||
error = OpenNebula::Error.new(error_msg)
|
||||
return error, 403
|
||||
end
|
||||
elsif !VM_STATE.include?(occi_state)
|
||||
# The requested state is not one of the OCCI action states nor
|
||||
# a resource state
|
||||
error_msg = "Invalid state: \"#{occi_state}\""
|
||||
error = OpenNebula::Error.new(error_msg)
|
||||
return error, 400
|
||||
end
|
||||
end
|
||||
|
||||
# Check if a disk image save as is required
|
||||
image_name = nil
|
||||
vm_info.each('DISK/SAVE_AS') { |save_as|
|
||||
image_name = save_as.attr('.', 'name')
|
||||
if image_name
|
||||
if action
|
||||
# Return erro if an action has been defined before
|
||||
if action == :save_as
|
||||
error_msg = "Only one disk can be saved per request"
|
||||
else
|
||||
error_msg = "Changig the state of the resource and" \
|
||||
" saving a disk is not allowed in the same request"
|
||||
end
|
||||
error = OpenNebula::Error.new(error_msg)
|
||||
return error, 403
|
||||
else
|
||||
# if no action is defined yet and a save_as is requested
|
||||
action = :save_as
|
||||
disk_id = save_as.attr('..', 'id')
|
||||
|
||||
# Params for the save_as action:
|
||||
# save_as(disk_id, image_name)
|
||||
args << disk_id.to_i
|
||||
args << image_name
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
# Perform the requested action
|
||||
if action
|
||||
rc = self.send(action, *args)
|
||||
if OpenNebula.is_error?(rc)
|
||||
return rc, CloudServer::HTTP_ERROR_CODE[rc.errno]
|
||||
else
|
||||
return nil, 202
|
||||
end
|
||||
else
|
||||
# There is no change requested
|
||||
return nil, 200
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
@ -144,6 +144,11 @@ get '/storage' do
|
||||
treat_response(result,rc)
|
||||
end
|
||||
|
||||
get '/user' do
|
||||
result,rc = @occi_server.get_users(request)
|
||||
treat_response(result,rc)
|
||||
end
|
||||
|
||||
###################################################
|
||||
# Entity Resources Methods
|
||||
###################################################
|
||||
@ -192,3 +197,8 @@ put '/storage/:id' do
|
||||
result,rc = @occi_server.put_storage(request, params)
|
||||
treat_response(result,rc)
|
||||
end
|
||||
|
||||
get '/user/:id' do
|
||||
result,rc = @occi_server.get_user(request, params)
|
||||
treat_response(result,rc)
|
||||
end
|
1
src/cloud/occi/test/fixtures/user/user.xml
vendored
Normal file
1
src/cloud/occi/test/fixtures/user/user.xml
vendored
Normal file
@ -0,0 +1 @@
|
||||
<USER href="http://localhost:4567/user/0"><ID>0</ID><NAME>oneadmin</NAME><QUOTA><CPU>0</CPU><MEMORY>0</MEMORY><NUM_VMS>0</NUM_VMS><STORAGE>0</STORAGE></QUOTA><USAGE><CPU>0</CPU><MEMORY>0</MEMORY><NUM_VMS>0</NUM_VMS><STORAGE>0</STORAGE></USAGE></USER>
|
1
src/cloud/occi/test/fixtures/user/user_collection.xml
vendored
Normal file
1
src/cloud/occi/test/fixtures/user/user_collection.xml
vendored
Normal file
@ -0,0 +1 @@
|
||||
<USER_COLLECTION><USER href="http://localhost:4567/user/0" name="oneadmin"/><USER href="http://localhost:4567/user/1" name="my_first_occi_user"/></USER_COLLECTION>
|
1
src/cloud/occi/test/fixtures/vm_save_as/newcompute.xml
vendored
Normal file
1
src/cloud/occi/test/fixtures/vm_save_as/newcompute.xml
vendored
Normal file
@ -0,0 +1 @@
|
||||
<COMPUTE href="http://localhost:4567/compute/0"><ID>0</ID><CPU>1</CPU><MEMORY>512</MEMORY><NAME>one-0</NAME><STATE>ACTIVE</STATE><DISK id="0"><STORAGE href="http://localhost:4567/storage/0" name="first_image"/><TYPE>DISK</TYPE><TARGET>hda</TARGET></DISK><DISK id="1"><STORAGE href="http://localhost:4567/storage/1" name="second_image"/><TYPE>DISK</TYPE><TARGET>hde</TARGET></DISK></COMPUTE>
|
1
src/cloud/occi/test/fixtures/vm_save_as/save_a_disk_and_change_state.xml
vendored
Normal file
1
src/cloud/occi/test/fixtures/vm_save_as/save_a_disk_and_change_state.xml
vendored
Normal file
@ -0,0 +1 @@
|
||||
<COMPUTE href="http://localhost:4567/compute/0"><ID>0</ID><CPU>1</CPU><MEMORY>512</MEMORY><NAME>one-0</NAME><STATE>SUSPENDED</STATE><DISK id="0"><STORAGE href="http://localhost:4567/storage/0" name="first_image"/><SAVE_AS name="save_as1"/><TYPE>DISK</TYPE><TARGET>hda</TARGET></DISK><DISK id="1"><STORAGE href="http://localhost:4567/storage/1" name="second_image"/><TYPE>DISK</TYPE><TARGET>hde</TARGET></DISK></COMPUTE>
|
1
src/cloud/occi/test/fixtures/vm_save_as/save_first_disk.xml
vendored
Normal file
1
src/cloud/occi/test/fixtures/vm_save_as/save_first_disk.xml
vendored
Normal file
@ -0,0 +1 @@
|
||||
<COMPUTE href="http://localhost:4567/compute/0"><ID>0</ID><CPU>1</CPU><MEMORY>512</MEMORY><NAME>one-0</NAME><STATE>ACTIVE</STATE><DISK id="0"><STORAGE href="http://localhost:4567/storage/0" name="first_image"/><SAVE_AS name="save_as1"/><TYPE>DISK</TYPE><TARGET>hda</TARGET></DISK><DISK id="1"><STORAGE href="http://localhost:4567/storage/1" name="second_image"/><TYPE>DISK</TYPE><TARGET>hde</TARGET></DISK></COMPUTE>
|
1
src/cloud/occi/test/fixtures/vm_save_as/save_second_disk.xml
vendored
Normal file
1
src/cloud/occi/test/fixtures/vm_save_as/save_second_disk.xml
vendored
Normal file
@ -0,0 +1 @@
|
||||
<COMPUTE href="http://localhost:4567/compute/0"><ID>0</ID><CPU>1</CPU><MEMORY>512</MEMORY><NAME>one-0</NAME><STATE>ACTIVE</STATE><DISK id="0"><STORAGE href="http://localhost:4567/storage/0" name="first_image"/><TYPE>DISK</TYPE><TARGET>hda</TARGET></DISK><DISK id="1"><SAVE_AS name="save_as2"/><STORAGE href="http://localhost:4567/storage/1" name="second_image"/><TYPE>DISK</TYPE><TARGET>hde</TARGET></DISK></COMPUTE>
|
1
src/cloud/occi/test/fixtures/vm_save_as/save_two_disks.xml
vendored
Normal file
1
src/cloud/occi/test/fixtures/vm_save_as/save_two_disks.xml
vendored
Normal file
@ -0,0 +1 @@
|
||||
<COMPUTE href="http://localhost:4567/compute/0"><ID>0</ID><CPU>1</CPU><MEMORY>512</MEMORY><NAME>one-0</NAME><STATE>ACTIVE</STATE><DISK id="0"><STORAGE href="http://localhost:4567/storage/0" name="first_image"/><SAVE_AS name="save_as1"/><TYPE>DISK</TYPE><TARGET>hda</TARGET></DISK><DISK id="1"><STORAGE href="http://localhost:4567/storage/1" name="second_image"/><SAVE_AS name="save_as2"/><TYPE>DISK</TYPE><TARGET>hde</TARGET></DISK></COMPUTE>
|
41
src/cloud/occi/test/spec/spec_helper.rb
Normal file
41
src/cloud/occi/test/spec/spec_helper.rb
Normal file
@ -0,0 +1,41 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
FIXTURES_PATH = File.join(File.dirname(__FILE__),'../fixtures')
|
||||
TEMPLATES_PATH = File.join(File.dirname(__FILE__),'../templates')
|
||||
|
||||
$: << File.join(File.dirname(__FILE__), '..', '..', 'lib')
|
||||
|
||||
# Load the testing libraries
|
||||
require 'rubygems'
|
||||
require 'rspec'
|
||||
require 'rack/test'
|
||||
|
||||
# Load the Sinatra app
|
||||
require 'occi-server'
|
||||
|
||||
# Make Rack::Test available to all spec contexts
|
||||
RSpec.configure do |conf|
|
||||
conf.include Rack::Test::Methods
|
||||
end
|
||||
|
||||
# Set the Sinatra environment
|
||||
set :environment, :test
|
||||
|
||||
# Add an app method for RSpec
|
||||
def app
|
||||
Sinatra::Application
|
||||
end
|
73
src/cloud/occi/test/spec/user_spec.rb
Normal file
73
src/cloud/occi/test/spec/user_spec.rb
Normal file
@ -0,0 +1,73 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
||||
|
||||
describe 'OCCI User tests' do
|
||||
before(:all) do
|
||||
@username_1 = "my_first_occi_user"
|
||||
@userpass_1 = "my_first_occi_pass"
|
||||
`oneuser create #{@username_1} #{@userpass_1}`
|
||||
end
|
||||
|
||||
it "should list the user collection" do
|
||||
basic_authorize('oneadmin','4478db59d30855454ece114e8ccfa5563d21c9bd')
|
||||
get '/user'
|
||||
|
||||
last_response.status.should eql(200)
|
||||
|
||||
xml_body = last_response.body
|
||||
|
||||
user_collection = File.read(FIXTURES_PATH + '/user/user_collection.xml')
|
||||
|
||||
xml_body.strip.should eql(user_collection.strip)
|
||||
end
|
||||
|
||||
|
||||
it "should check the error if the user collection is retrieved by a non oneadmin user" do
|
||||
basic_authorize('my_first_occi_user','c08c5a6c535b6060b7b2af34e0d2f0ffb7e63b28')
|
||||
get '/user'
|
||||
|
||||
last_response.status.should eql(403)
|
||||
end
|
||||
|
||||
it "should show the user information, no quotas and no usage" do
|
||||
basic_authorize('oneadmin','4478db59d30855454ece114e8ccfa5563d21c9bd')
|
||||
get '/user/0'
|
||||
|
||||
last_response.status.should eql(200)
|
||||
|
||||
xml_body = last_response.body
|
||||
|
||||
user = File.read(FIXTURES_PATH + '/user/user.xml')
|
||||
|
||||
xml_body.strip.should eql(user.strip)
|
||||
end
|
||||
|
||||
it "should get a 404 error when trying to get a non existing user" do
|
||||
basic_authorize('oneadmin','4478db59d30855454ece114e8ccfa5563d21c9bd')
|
||||
get '/user/99'
|
||||
|
||||
last_response.status.should eql(404)
|
||||
end
|
||||
|
||||
it "should get a 403 error when trying to get a different user" do
|
||||
basic_authorize('my_first_occi_user','c08c5a6c535b6060b7b2af34e0d2f0ffb7e63b28')
|
||||
get '/user/0'
|
||||
|
||||
last_response.status.should eql(403)
|
||||
end
|
||||
end
|
77
src/cloud/occi/test/spec/vm_saveas_spec.rb
Normal file
77
src/cloud/occi/test/spec/vm_saveas_spec.rb
Normal file
@ -0,0 +1,77 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
||||
|
||||
describe 'OCCI User tests' do
|
||||
# PREREQUISITES
|
||||
# OpenNebula installed and running using dummy drivers
|
||||
|
||||
before(:all) do
|
||||
# Starting the drivers
|
||||
sleep 2
|
||||
|
||||
system("onehost create myhost im_dummy vmm_dummy tm_dummy").should == true
|
||||
|
||||
system("oneimage create #{TEMPLATES_PATH+"/image1.template"}").should == true
|
||||
system("oneimage create #{TEMPLATES_PATH+"/image2.template"}").should == true
|
||||
|
||||
# Copying the images
|
||||
sleep 1
|
||||
|
||||
system("onevm create #{TEMPLATES_PATH+"/vm.template"}").should == true
|
||||
system("onevm deploy 0 0").should == true
|
||||
end
|
||||
|
||||
it "should show the new compute" do
|
||||
basic_authorize('oneadmin','4478db59d30855454ece114e8ccfa5563d21c9bd')
|
||||
get '/compute/0'
|
||||
|
||||
last_response.body.should == File.read(FIXTURES_PATH+"/vm_save_as/newcompute.xml")
|
||||
end
|
||||
|
||||
it "should get an error when trying to change the resource state and save a disk " do
|
||||
basic_authorize('oneadmin','4478db59d30855454ece114e8ccfa5563d21c9bd')
|
||||
body = File.read(FIXTURES_PATH+"/vm_save_as/save_a_disk_and_change_state.xml")
|
||||
put '/compute/0', body
|
||||
|
||||
last_response.status.should == 403
|
||||
end
|
||||
|
||||
it "should get an error when trying to save two disks" do
|
||||
basic_authorize('oneadmin','4478db59d30855454ece114e8ccfa5563d21c9bd')
|
||||
body = File.read(FIXTURES_PATH+"/vm_save_as/save_two_disks.xml")
|
||||
put '/compute/0', body
|
||||
|
||||
last_response.status.should == 403
|
||||
end
|
||||
|
||||
it "should save the first disk" do
|
||||
basic_authorize('oneadmin','4478db59d30855454ece114e8ccfa5563d21c9bd')
|
||||
body = File.read(FIXTURES_PATH+"/vm_save_as/save_first_disk.xml")
|
||||
put '/compute/0', body
|
||||
|
||||
last_response.status.should == 202
|
||||
end
|
||||
|
||||
it "should save the second disk" do
|
||||
basic_authorize('oneadmin','4478db59d30855454ece114e8ccfa5563d21c9bd')
|
||||
body = File.read(FIXTURES_PATH+"/vm_save_as/save_second_disk.xml")
|
||||
put '/compute/0', body
|
||||
|
||||
last_response.status.should == 202
|
||||
end
|
||||
end
|
2
src/cloud/occi/test/templates/image1.template
Normal file
2
src/cloud/occi/test/templates/image1.template
Normal file
@ -0,0 +1,2 @@
|
||||
NAME = first_image
|
||||
PATH = /etc/hosts
|
3
src/cloud/occi/test/templates/image2.template
Normal file
3
src/cloud/occi/test/templates/image2.template
Normal file
@ -0,0 +1,3 @@
|
||||
NAME = second_image
|
||||
PATH = /etc/hosts
|
||||
TYPE = DATABLOCK
|
10
src/cloud/occi/test/templates/vm.template
Normal file
10
src/cloud/occi/test/templates/vm.template
Normal file
@ -0,0 +1,10 @@
|
||||
CPU = 1
|
||||
MEMORY = 512
|
||||
|
||||
DISK = [
|
||||
IMAGE_ID = 0
|
||||
]
|
||||
|
||||
DISK = [
|
||||
IMAGE_ID = 1
|
||||
]
|
49
src/cloud/occi/test/test.sh
Executable file
49
src/cloud/occi/test/test.sh
Executable file
@ -0,0 +1,49 @@
|
||||
#!/bin/bash
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
if [ -z $ONE_LOCATION ]; then
|
||||
echo "ONE_LOCATION not defined."
|
||||
exit -1
|
||||
fi
|
||||
|
||||
VAR_LOCATION="$ONE_LOCATION/var"
|
||||
|
||||
if [ "$(ls -A $VAR_LOCATION)" ]; then
|
||||
echo "$VAR_LOCATION is not empty."
|
||||
exit -1
|
||||
fi
|
||||
|
||||
for j in `ls ./spec/*_spec.rb` ; do
|
||||
find $VAR_LOCATION -mindepth 1 ! \( -path "$VAR_LOCATION/remotes*" -o -path "$VAR_LOCATION/images" \) -delete
|
||||
|
||||
PID=$$
|
||||
|
||||
oned -f &
|
||||
sleep 2s;
|
||||
|
||||
rspec $j -f s
|
||||
CODE=$?
|
||||
|
||||
pkill -P $PID oned
|
||||
sleep 2s;
|
||||
pkill -9 -P $PID oned
|
||||
|
||||
if [ $CODE != 0 ] ; then
|
||||
exit 1
|
||||
fi
|
||||
done
|
@ -50,11 +50,22 @@ module OpenNebula
|
||||
# Any function in the OpenNebula module will return an Error
|
||||
# object in case of error.
|
||||
class Error
|
||||
attr_reader :message
|
||||
ESUCCESS = 0x0000
|
||||
EAUTHENTICATION = 0x0100
|
||||
EAUTHORIZATION = 0x0200
|
||||
ENO_EXISTS = 0x0400
|
||||
EACTION = 0x0800
|
||||
EXML_RPC_API = 0x1000
|
||||
EINTERNAL = 0x2000
|
||||
ENOTDEFINED = 0x1111
|
||||
|
||||
# +message+ a description of the error
|
||||
def initialize(message=nil)
|
||||
@message=message
|
||||
attr_reader :message, :errno
|
||||
|
||||
# +message+ Description of the error
|
||||
# +errno+ OpenNebula code error
|
||||
def initialize(message=nil, errno=0x1111)
|
||||
@message = message
|
||||
@errno = errno
|
||||
end
|
||||
|
||||
def to_str()
|
||||
@ -127,7 +138,7 @@ module OpenNebula
|
||||
response = @server.call_async("one."+action, @one_auth, *args)
|
||||
|
||||
if response[0] == false
|
||||
Error.new(response[1])
|
||||
Error.new(response[1], response[2])
|
||||
else
|
||||
response[1] #response[1..-1]
|
||||
end
|
||||
|
Loading…
x
Reference in New Issue
Block a user