1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-01-11 05:17:41 +03:00

feature #1288: Remove previous quota drivers

This commit is contained in:
Ruben S. Montero 2012-06-10 20:40:18 +02:00
parent 981db30338
commit e793ca89e1
13 changed files with 3 additions and 1431 deletions

View File

@ -246,7 +246,6 @@ VAR_DIRS="$VAR_LOCATION/remotes \
$VAR_LOCATION/remotes/auth/ldap \
$VAR_LOCATION/remotes/auth/server_x509 \
$VAR_LOCATION/remotes/auth/server_cipher \
$VAR_LOCATION/remotes/auth/quota \
$VAR_LOCATION/remotes/auth/dummy"
SUNSTONE_DIRS="$SUNSTONE_LOCATION/models \
@ -384,7 +383,6 @@ INSTALL_FILES=(
AUTH_SERVER_CIPHER_FILES:$VAR_LOCATION/remotes/auth/server_cipher
AUTH_DUMMY_FILES:$VAR_LOCATION/remotes/auth/dummy
AUTH_PLAIN_FILES:$VAR_LOCATION/remotes/auth/plain
AUTH_QUOTA_FILES:$VAR_LOCATION/remotes/auth/quota
VMM_EXEC_KVM_SCRIPTS:$VAR_LOCATION/remotes/vmm/kvm
VMM_EXEC_XEN_SCRIPTS:$VAR_LOCATION/remotes/vmm/xen
VMM_EXEC_VMWARE_SCRIPTS:$VAR_LOCATION/remotes/vmm/vmware
@ -574,7 +572,6 @@ BIN_FILES="src/nebula/oned \
src/cli/onedatastore \
src/cli/onecluster \
src/onedb/onedb \
src/authm_mad/remotes/quota/onequota \
src/mad/utils/tty_expect \
share/scripts/one"
@ -601,7 +598,6 @@ RUBY_LIB_FILES="src/mad/ruby/ActionManager.rb \
src/mad/ruby/Ganglia.rb \
src/oca/ruby/OpenNebula.rb \
src/authm_mad/remotes/ssh/ssh_auth.rb \
src/authm_mad/remotes/quota/quota.rb \
src/authm_mad/remotes/server_x509/server_x509_auth.rb \
src/authm_mad/remotes/server_cipher/server_cipher_auth.rb \
src/authm_mad/remotes/ldap/ldap_auth.rb \
@ -732,8 +728,6 @@ AUTH_DUMMY_FILES="src/authm_mad/remotes/dummy/authenticate"
AUTH_PLAIN_FILES="src/authm_mad/remotes/plain/authenticate"
AUTH_QUOTA_FILES="src/authm_mad/remotes/quota/authorize"
#-------------------------------------------------------------------------------
# Virtual Network Manager drivers to be installed under $REMOTES_LOCATION/vnm
#-------------------------------------------------------------------------------
@ -942,7 +936,6 @@ HM_ETC_FILES="src/hm_mad/hmrc"
#-------------------------------------------------------------------------------
AUTH_ETC_FILES="src/authm_mad/remotes/server_x509/server_x509_auth.conf \
src/authm_mad/remotes/quota/quota.conf \
src/authm_mad/remotes/ldap/ldap_auth.conf \
src/authm_mad/remotes/x509/x509_auth.conf"
@ -1115,7 +1108,6 @@ ONE_CLI_LIB_FILES="src/cli/one_helper/onegroup_helper.rb \
src/cli/one_helper/oneimage_helper.rb \
src/cli/one_helper/onetemplate_helper.rb \
src/cli/one_helper/oneuser_helper.rb \
src/cli/one_helper/onequota_helper.rb \
src/cli/one_helper/onevm_helper.rb \
src/cli/one_helper/onevnet_helper.rb \
src/cli/one_helper/oneacl_helper.rb \

View File

@ -414,22 +414,20 @@ HM_MAD = [
# valid. During this time, the driver is not used. Use 0 to disable session
# caching
#
# ENABLE_OTHER_PERMISSIONS: Whether or not to enable the permissions for
# 'other'. Users in the oneadmin group will still be able to change
# these permissions. Values: YES or NO
# ENABLE_OTHER_PERMISSIONS: Whether or not users can set the permissions for
# 'other', so publishing or sharing resources with others. Users in the oneadmin
# group will still be able to change these permissions. Values: YES or NO.
#*******************************************************************************
AUTH_MAD = [
executable = "one_auth_mad",
authn = "ssh,x509,ldap,server_cipher,server_x509"
# , authz = "quota"
]
SESSION_EXPIRATION_TIME = 900
#ENABLE_OTHER_PERMISSIONS = "YES"
#*******************************************************************************
# Restricted Attributes Configuration
#*******************************************************************************

View File

@ -1,69 +0,0 @@
#!/usr/bin/env 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. #
#--------------------------------------------------------------------------- #
ONE_LOCATION=ENV["ONE_LOCATION"]
if !ONE_LOCATION
RUBY_LIB_LOCATION="/usr/lib/one/ruby"
ETC_LOCATION="/etc/one/"
else
RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby"
ETC_LOCATION=ONE_LOCATION+"/etc/"
end
$: << RUBY_LIB_LOCATION
require 'scripts_common'
require 'OpenNebula'
require 'quota'
user_id = ARGV.shift
overall_evalutation = ARGV.pop
exit -1 if overall_evalutation.to_i == 0
quota = Quota.new
#q = {
# :cpu => 10,
# :memory => 2048,
# :storage => 100000,
# :num_vms => 5
#}
#
#quota.set(1, q)
#OpenNebula.log_debug("quotas: #{quota.get(1)}")
ARGV.each {|request|
obj, template_or_id, op, owner, acl_eval = request.split(':')
if ( obj == "TEMPLATE" && op == "USE" && ARGV.size == 1 )
rc = false
else
rc = quota.authorize(user_id, request)
end
if rc
OpenNebula.error_message rc
exit -1
end
}
#OpenNebula.log_debug("AUTHORIZE ARGS: #{ARGV.join(' ')}")
exit 0

View File

@ -1,189 +0,0 @@
#!/usr/bin/env 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. #
#--------------------------------------------------------------------------- #
ONE_LOCATION=ENV["ONE_LOCATION"]
if !ONE_LOCATION
RUBY_LIB_LOCATION="/usr/lib/one/ruby"
else
RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby"
end
$: << RUBY_LIB_LOCATION
$: << RUBY_LIB_LOCATION+"/cli"
require 'command_parser'
require 'cli_helper'
require 'one_helper'
require 'quota'
require 'pp'
QUOTA_KEYS = Quota::DB_QUOTA_SCHEMA.keys
def show_table(values, usage=nil)
size = usage ? 12 : 8
values.sort!{|v1, v2| v1[:UID]<=>v2[:UID] }
table=CLIHelper::ShowTable.new(nil, self) do
column :UID, "ONE identifier for the User", :size=>4 do |d|
d[:UID]
end
QUOTA_KEYS.each { |key|
column key, "#{key} quota", :size=>size do |d|
if usage
"#{usage[key].to_i}/#{d[key].to_i}"
else
"#{d[key].to_i}"
end
end
}
default :UID, *QUOTA_KEYS
end
table.show(values)
end
cmd=CommandParser::CmdParser.new(ARGV) do
usage "`onequota` <command> [<args>] [<options>]"
version OpenNebulaHelper::ONE_VERSION
quota = Quota.new
########################################################################
# Global Options
########################################################################
set :option, CommandParser::OPTIONS
########################################################################
# Argument Formats
########################################################################
quota_list_desc = <<-EOT.unindent
List of quota keys, comma separated.
Available quotas: #{QUOTA_KEYS.join(', ')}
EOT
set :format, :quota_list, quota_list_desc do |arg|
arg_list = arg.split(',')
rc = nil
arg_list.collect! do |elem|
sym = elem.upcase.to_sym
if !QUOTA_KEYS.include?(sym)
rc = -1, "#{elem} is not a valid quota"
break
end
sym
end
rc ? rc : [0, arg_list]
end
set :format, :value_list, "List of quota values, comma separated." do |arg|
arg_list = arg.split(',')
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
########################################################################
# Commands
########################################################################
set_desc = <<-EOT.unindent
Set a quota for a given user.
Examples:
onequota set 3 cpu 12
onequota set 4 cpu,memory,storage 8,4096,10000
EOT
command :set, set_desc, :userid, :quota_list, :value_list do
user_id, keys, values = args
if keys.length != values.length
exit_with_code -1, "The number of keys and values does not match"
end
values_hash = Hash.new
keys.each_with_index { |k,i|
values_hash[k] = values[i]
}
quota.set_quota(user_id, values_hash)
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] = 0
}
quota.set_quota(user_id, values_hash)
exit_with_code 0
end
########################################################################
delete_desc = "Delete the defined quotas for the given user"
command :delete, delete_desc, :userid do
quota.delete_quota(args[0])
exit_with_code 0
end
########################################################################
show_desc = "Show the user's quota and usage. (usage/quota)"
FORCE={
:name => "force",
:short => "-f",
:large => "--force",
:description => "Force the usage calculation instead of using the cache"
}
command :show, show_desc, :userid, :options=>[FORCE] do
user_usage = quota.get_usage(args[0],nil,options[:force])
user_quota = quota.get_quota(args[0])
show_table([user_quota], user_usage)
exit_with_code 0
end
########################################################################
list_desc = "List the defined quotas for all the users"
command :list, list_desc do
show_table(quota.get_quota)
exit_with_code 0
end
end

View File

@ -1,29 +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. #
#--------------------------------------------------------------------------- #
# Database URI
#:db: sqlite:///var/one/onequota.db
#-------------------------------------------------------------------------------
# Default quotas, these apply to all users. Leave empty to disable quota for
# a given metric.
#-------------------------------------------------------------------------------
:defaults:
:CPU:
:MEMORY:
:NUM_VMS:
:STORAGE:

View File

@ -1,374 +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. #
#--------------------------------------------------------------------------- #
require 'sequel'
require 'base64'
require 'yaml'
require 'uri'
require 'net/http'
class Quota
###########################################################################
# Constants with paths to relevant files and defaults
###########################################################################
ONE_LOCATION=ENV["ONE_LOCATION"]
if !ONE_LOCATION
VAR_LOCATION = "/var/lib/one"
ETC_LOCATION = "/etc/one"
else
VAR_LOCATION = ONE_LOCATION + "/var"
ETC_LOCATION = ONE_LOCATION + "/etc"
end
CONF_FILE = ETC_LOCATION + "/auth/quota.conf"
CONF = {
:db => "sqlite://#{VAR_LOCATION}/onequota.db",
:defaults => {
:CPU => nil,
:MEMORY => nil,
:NUM_VMS => nil,
:STORAGE => nil
}
}
###########################################################################
# Schema for the USAGE and QUOTA tables
###########################################################################
DB_QUOTA_SCHEMA = {
:CPU => Float,
:MEMORY => Integer,
:NUM_VMS => Integer,
:STORAGE => Integer
}
QUOTA_TABLE = :quotas
USAGE_TABLE = :usage
###########################################################################
# Usage params to calculate each quota
###########################################################################
VM_USAGE = {
:CPU => {
:proc_info => lambda {|template| template['CPU']},
:xpath => 'TEMPLATE/CPU'
},
:MEMORY => {
:proc_info => lambda {|template| template['MEMORY']},
:xpath => 'TEMPLATE/MEMORY'
},
:NUM_VMS => {
:proc_info => lambda {|template| 1 },
:xpath => 'ID',
:count => true
}
}
IMAGE_USAGE = {
:STORAGE => {
:proc_info => lambda {|template|
if template['TYPE'] == 'DATABLOCK'
template['SIZE'].to_i
elsif template['PATH']
uri = URI.parse(template['PATH'])
size = if uri.scheme.nil?
File.size(template['PATH'])
else
Net::HTTP.start(uri.host,uri.port) { |http|
http.head(uri.path)
}.content_length
end
(size.to_f / 2**20).round
elsif template['SAVED_VM_ID']
vm_id = template['SAVED_VM_ID'].to_i
disk_id = template['SAVED_DISK_ID'].to_i
client = OpenNebula::Client.new
vm = OpenNebula::VirtualMachine.new_with_id(vm_id, client)
vm.info
im_id = vm["DISK[DISK_ID=#{disk_id}]/IMAGE_ID"].to_i
im = OpenNebula::Image.new_with_id(im_id, client)
im.info
im['SIZE'].to_i
else
0
end
},
:xpath => 'SIZE'
}
}
RESOURCES = ["VM", "IMAGE"]
###########################################################################
# DB handling
###########################################################################
def initialize
conf = YAML.load_file(CONF_FILE)
@conf=CONF.merge(conf) {|key,h1,h2|
if h1.instance_of?(Hash) && h2.instance_of?(Hash)
h1.merge(h2)
else
if h2
h2
else
h1
end
end
}
@client = OpenNebula::Client.new
@db=Sequel.connect(@conf[:db])
create_table(QUOTA_TABLE)
create_table(USAGE_TABLE)
end
# Creates database quota table if it does not exist
def create_table(table)
@db.create_table?(table) do
Integer :UID
DB_QUOTA_SCHEMA.each { |key,value|
column key, value
}
primary_key :UID
index :UID
end
end
# Adds new user limits
def set(table, uid, quota={})
data=quota.delete_if{|key,value| !DB_QUOTA_SCHEMA.keys.include?(key)}
quotas=@db[table].filter(:UID => uid)
if quotas.first
quotas.update(data)
else
@db[table].insert(data.merge!(:UID => uid))
end
end
# Gets user limits
def get(table, uid=nil)
if uid
@db[table].filter(:UID => uid).first
else
@db[table].all
end
end
# Delete user limits
def delete(table, uid)
quotas=@db[table].filter(:UID => uid)
if quotas.first
quotas.delete
end
end
###########################################################################
# Quota Client
###########################################################################
def set_quota(uid, 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)
end
def delete_quota(uid)
delete(QUOTA_TABLE, uid)
end
###########################################################################
# Authorization
###########################################################################
def authorize(user_id, request)
obj, template_or_id, op, owner, acl_eval = request.split(':')
if acl_eval.to_i == 0
return "ACL evaluation denied"
end
# Check if this op needs to check the quota
return false unless with_quota?(obj, op)
template = ""
if ( obj == "TEMPLATE" )
obj = "VM"
vm_template = OpenNebula::Template.new_with_id(template_or_id, @client)
vm_template.info
vm_template.each("TEMPLATE") { |xml_elem|
template = xml_elem.to_xml
}
else
template = Base64::decode64(template_or_id)
end
check_quotas(user_id.to_i, obj, template)
end
def check_quotas(user_id, obj, template)
info = get_resources(obj, template)
total = get_usage(user_id, obj, true)
quota = get_quota(user_id)
msg = ""
separator = ""
info.each { |qname, quota_requested|
unless quota[qname] || quota[qname]==0
next
end
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
msg << " #{qname.to_s.upcase} quota exceeded "
msg << "(Quota: #{limit}, "
msg << "Used: #{used}, "
msg << "Requested: #{request})"
separator = ";"
end
}
if msg==""
return false
else
return msg.strip
end
end
def with_quota?(obj, op)
return (obj == "VM" && op == "CREATE") ||
(obj == "IMAGE" && op == "CREATE") ||
(obj == "TEMPLATE" && op == "USE")
end
###########################################################################
# 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)
resources = [resource]
else
resources = RESOURCES
end
usage = Hash.new
resources.each{ |res|
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
if params[:count]
usage[key] += 1
else
usage[key] += send(DB_QUOTA_SCHEMA[key].name.to_sym, elem)
end
end
}
}
set(USAGE_TABLE, user_id, usage) unless usage.empty?
usage.merge!(:UID => user_id)
}
else
usage = get(USAGE_TABLE, user_id)
usage ||= {:UID => user_id}
end
usage
end
# Retrieve the useful information of the template for the specified
# kind of resource
def get_resources(resource, xml_template)
template = OpenNebula::XMLElement.new
template.initialize_xml(xml_template, 'TEMPLATE')
info = Hash.new
self.class.const_get("#{resource}_USAGE").each { |key, params|
info[key] = params[:proc_info].call(template).to_i
}
info
end
# Returns a an Array than contains the elements of the resource Pool
def get_pool(resource, user_id)
pool = case resource
when "VM" then OpenNebula::VirtualMachinePool.new(@client, user_id)
when "IMAGE" then OpenNebula::ImagePool.new(@client, user_id)
end
rc = pool.info
return pool
end
end

View File

@ -1,26 +0,0 @@
<IMAGE_POOL>
<% images.each do |id,image| %>
<IMAGE>
<ID><%= id %></ID>
<UID><%= image[:uid] ? image[:uid] : 0 %></UID>
<GID><%= image[:gid] ? image[:gid] : 0 %></GID>
<UNAME><%= image[:uname] ? image[:uname] : 'oneadmin' %></UNAME>
<GNAME><%= image[:gname] ? image[:gname] : 'oneadmin' %></GNAME>
<NAME><%= image[:name] ? image[:name] : 'ttylinux' %></NAME>
<TYPE><%= image[:type] ? image[:type] : 0 %></TYPE>
<PUBLIC><%= image[:pub] ? image[:pub] : 0 %></PUBLIC>
<PERSISTENT><%= image[:persistent] ? image[:persistent] : 0 %></PERSISTENT>
<REGTIME>1314875019</REGTIME>
<SOURCE><%= image[:source] ? image[:source] : '/etc/hosts' %></SOURCE>
<STATE><%= image[:state] ? image[:state] : 1 %></STATE>
<SIZE><%= image[:size] ? image[:size] : 100 %></SIZE>
<RUNNING_VMS>0</RUNNING_VMS>
<TEMPLATE>
<DEV_PREFIX><![CDATA[hd]]></DEV_PREFIX>
<NAME><![CDATA[PEPE]]></NAME>
<PATH><![CDATA[/etc/hosts]]></PATH>
<TYPE><![CDATA[OS]]></TYPE>
</TEMPLATE>
</IMAGE>
<% end %>
</IMAGE_POOL>

View File

@ -1,46 +0,0 @@
<VM>
<ID><%= id %></ID>
<UID><%= vm[:uid] ? vm[:uid] : 0 %></UID>
<GID><%= vm[:gid] ? vm[:gid] : 0 %></GID>
<NAME><%= vm[:name] ? vm[:uid] : 'pepe' %></NAME>
<LAST_POLL><%= vm[:last_poll] ? vm[:last_poll] : '1309275256' %></LAST_POLL>
<STATE><%= vm[:state] ? vm[:state] : 3 %></STATE>
<LCM_STATE>3</LCM_STATE>
<STIME>1309275252</STIME>
<ETIME>0</ETIME>
<DEPLOY_ID>dummy</DEPLOY_ID>
<MEMORY><%= vm[:memory] ? vm[:memory] : 128 %></MEMORY>
<CPU><%= vm[:cpu] ? vm[:cpu] : 1 %></CPU>
<NET_TX><%= vm[:net_tx] ? vm[:net_tx] : 0 %></NET_TX>
<NET_RX><%= vm[:net_rx] ? vm[:net_rx] : 0 %></NET_RX>
<TEMPLATE>
<CPU><![CDATA[1]]></CPU>
<MEMORY><![CDATA[1024]]></MEMORY>
<NAME><![CDATA[PEPEPE]]></NAME>
<VCPU><![CDATA[1]]></VCPU>
<VMID><![CDATA[4]]></VMID>
</TEMPLATE>
<% if history = vm[:history] %>
<HISTORY_RECORDS>
<% history.each do |h| %>
<HISTORY>
<SEQ><%= h[:seq] ? h[:seq] : 0 %></SEQ>
<HOSTNAME><%= h[:hostname] ? h[:hostname] : "kvxen" %></HOSTNAME>
<VM_DIR>/Users/dmolina/trabajo/acctmoni/install/var/</VM_DIR>
<HID><%= h[:hid] ? h[:hid] : 0 %></HID>
<STIME>1309275256</STIME>
<ETIME>0</ETIME>
<VMMMAD>vmm_dummy</VMMMAD>
<TMMAD>tm_dummy</TMMAD>
<PSTIME><%= h[:pstime] ? h[:pstime] : 0 %></PSTIME>
<PETIME><%= h[:petime] ? h[:petime] : 0 %></PETIME>
<RSTIME><%= h[:rstime] ? h[:rstime] : 0 %></RSTIME>
<RETIME><%= h[:retime] ? h[:retime] : 0 %></RETIME>
<ESTIME><%= h[:estime] ? h[:estime] : 0 %></ESTIME>
<EETIME><%= h[:eetime] ? h[:eetime] : 0 %></EETIME>
<REASON><%= h[:reason] ? h[:reason] : 0 %></REASON>
</HISTORY>
<% end %>
</HISTORY_RECORDS>
<% end %>
</VM>

View File

@ -1,49 +0,0 @@
<VM_POOL>
<% vms.each do |id,vm| %>
<VM>
<ID><%= id %></ID>
<UID><%= vm[:uid] ? vm[:uid] : 0 %></UID>
<GID><%= vm[:gid] ? vm[:gid] : 0 %></GID>
<NAME><%= vm[:name] ? vm[:uid] : 'pepe' %></NAME>
<LAST_POLL><%= vm[:last_poll] ? vm[:last_poll] : '1309275256' %></LAST_POLL>
<STATE><%= vm[:state] ? vm[:state] : 3 %></STATE>
<LCM_STATE>3</LCM_STATE>
<STIME>1309275252</STIME>
<ETIME>0</ETIME>
<DEPLOY_ID>dummy</DEPLOY_ID>
<MEMORY><%= vm[:memory] ? vm[:memory] : 128 %></MEMORY>
<CPU><%= vm[:cpu] ? vm[:cpu] : 1 %></CPU>
<NET_TX><%= vm[:net_tx] ? vm[:net_tx] : 0 %></NET_TX>
<NET_RX><%= vm[:net_rx] ? vm[:net_rx] : 0 %></NET_RX>
<TEMPLATE>
<CPU><![CDATA[<%= vm[:cpu] ? vm[:cpu] : 1 %>]]></CPU>
<MEMORY><![CDATA[<%= vm[:memory] ? vm[:memory] : 128 %>]]></MEMORY>
<NAME><![CDATA[PEPEPE]]></NAME>
<VCPU><![CDATA[1]]></VCPU>
<VMID><![CDATA[4]]></VMID>
</TEMPLATE>
<% if history = vm[:history] %>
<HISTORY_RECORDS>
<% h = history.last %>
<HISTORY>
<SEQ><%= h[:seq] ? h[:seq] : 0 %></SEQ>
<HOSTNAME><%= h[:hostname] ? h[:hostname] : "kvxen" %></HOSTNAME>
<VM_DIR>/Users/dmolina/trabajo/acctmoni/install/var/</VM_DIR>
<HID><%= h[:hid] ? h[:hid] : 0 %></HID>
<STIME>1309275256</STIME>
<ETIME>0</ETIME>
<VMMMAD>vmm_dummy</VMMMAD>
<TMMAD>tm_dummy</TMMAD>
<PSTIME><%= h[:pstime] ? h[:pstime] : 0 %></PSTIME>
<PETIME><%= h[:petime] ? h[:petime] : 0 %></PETIME>
<RSTIME><%= h[:rstime] ? h[:rstime] : 0 %></RSTIME>
<RETIME><%= h[:retime] ? h[:retime] : 0 %></RETIME>
<ESTIME><%= h[:estime] ? h[:estime] : 0 %></ESTIME>
<EETIME><%= h[:eetime] ? h[:eetime] : 0 %></EETIME>
<REASON><%= h[:reason] ? h[:reason] : 0 %></REASON>
</HISTORY>
</HISTORY_RECORDS>
<% end %>
</VM>
<% end %>
</VM_POOL>

View File

@ -1,53 +0,0 @@
require 'erb'
FPATH = "./fixtures/"
class MockClient
def initialize
@vms = Hash.new
@done_vms = Hash.new
@images = Hash.new
end
def call(action, *args)
xmlrpc_action = "one."+action
case xmlrpc_action
when "one.vm.info"
id = args[0]
vm = @vms[id]
return ERB.new(File.read(FPATH+'vm.xml')).result(binding)
when "one.vmpool.info"
case args[3]
when -1
vms = @vms
return ERB.new(File.read(FPATH+'vmpool.xml')).result(binding)
when 6 then
vms = @done_vms
return ERB.new(File.read(FPATH+'vmpool.xml')).result(binding)
end
when "one.imagepool.info"
images = @images
return ERB.new(File.read(FPATH+'imagepool.xml')).result(binding)
end
end
def add_vm(id, values)
if values[:state] == 6
@done_vms[id] = values.clone
else
@vms[id] = values.clone
end
end
def delete_vm(id)
@vms.delete(id)
@vms_done.delete(id)
end
def add_image(id, values)
@images[id] = values
end
end

View File

@ -1,31 +0,0 @@
ONE_LOCATION = ENV['ONE_LOCATION']
if !ONE_LOCATION
RUBY_LIB_LOCATION="/usr/lib/one/ruby"
else
RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby"
end
$: << RUBY_LIB_LOCATION
$: << './helper'
$: << '.'
$: << '..'
require 'mock_client'
require 'OpenNebula'
require 'quota'
class Quota
def set_client(client)
@client = client
end
def rm_and_set_testdb
`rm -f /tmp/onequota_test.db`
@db=Sequel.connect("sqlite:///tmp/onequota_test.db")
create_table(QUOTA_TABLE)
create_table(USAGE_TABLE)
end
end

View File

@ -1,343 +0,0 @@
$: << '.'
require 'helper/test_helper'
describe "Quota testing" do
before(:all) do
@mock_client = MockClient.new
@quota = Quota.new
@quota.set_client(@mock_client)
@quota.rm_and_set_testdb
@uid1 = 0
@quota1 = {
:CPU => 2.4,
:MEMORY => 1024,
:NUM_VMS => 4,
:STORAGE => 10000
}
@uid2 = 1
@quota2 = {
:CPU => 1.2,
:MEMORY => 512,
:NUM_VMS => 2,
:STORAGE => 5000
}
# Generate VM ACL request
vm_template = <<-EOT
<TEMPLATE>
<CPU>2</CPU>
<MEMORY>128</MEMORY>
</TEMPLATE>
EOT
vm_base64 = Base64::encode64(vm_template)
@acl_vm_create = "VM:#{vm_base64}:CREATE:0:1:1"
# Generate IMAGE ACL request
image_template = <<-EOT
<TEMPLATE>
<PATH>/etc/hosts</PATH>
</TEMPLATE>
EOT
image_base64 = Base64::encode64(image_template)
@acl_image_create = "IMAGE:#{image_base64}:CREATE:0:1:1"
# Generate TEMPLATE ACL request
temp_template = <<-EOT
<TEMPLATE>
<CPU>2</CPU>
<MEMORY>128</MEMORY>
</TEMPLATE>
EOT
temp_base64 = Base64::encode64(temp_template)
@acl_template_instantiate = "TEMPLATE:#{temp_base64}:INSTANTIATE:0:1:1"
end
it "should check default quotas" do
quota1 = @quota.get_quota(@uid1)
quota1[:UID].should eql(0)
quota1[:NUM_VMS].should eql(nil)
quota1[:CPU].should eql(nil)
quota1[:MEMORY].should eql(nil)
quota1[:STORAGE].should eql(nil)
end
it "should check default usage cache" 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)
end
it "should check default cache (force)" do
usage1force = @quota.get_usage(@uid1, nil, true)
usage1force[:UID].should eql(0)
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
@quota.authorize(@uid1, @acl_vm_create).should eql(false)
@quota.authorize(@uid1, @acl_image_create).should eql(false)
@quota.authorize(@uid1, @acl_template_instantiate).should eql(false)
end
it "should add a new VM" do
values = {
:CPU => 2,
:MEMORY => 128,
:UID => 2,
:GID => 4,
}
@mock_client.add_vm(0, values)
end
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(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
usage1force = @quota.get_usage(@uid1, nil, true)
usage1force[:UID].should eql(0)
usage1force[:NUM_VMS].should eql(1)
usage1force[:CPU].should eql(2.0)
usage1force[:MEMORY].should eql(128)
usage1force[:STORAGE].should eql(0)
end
it "should check the usage cache is updated and contains the last usage" do
usage1cache = @quota.get_usage(@uid1)
usage1cache[:UID].should eql(0)
usage1cache[:NUM_VMS].should eql(1)
usage1cache[:CPU].should eql(2.0)
usage1cache[:MEMORY].should eql(128)
usage1cache[:STORAGE].should eql(0)
end
it "should add a new Image" do
values = {
:UID => 2,
:GID => 4,
:SIZE => 1000
}
@mock_client.add_image(0, values)
end
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(1)
usage1cache[:CPU].should eql(2.0)
usage1cache[:MEMORY].should eql(128)
usage1cache[:STORAGE].should eql(0)
end
it "should check the cache (force)" do
usage1force = @quota.get_usage(@uid1, nil, true)
usage1force[:UID].should eql(0)
usage1force[:NUM_VMS].should eql(1)
usage1force[:CPU].should eql(2.0)
usage1force[:MEMORY].should eql(128)
usage1force[:STORAGE].should eql(1000)
end
it "should check the usage cache is updated and contains the last usage" do
usage1cache = @quota.get_usage(@uid1)
usage1cache[:UID].should eql(0)
usage1cache[:NUM_VMS].should eql(1)
usage1cache[:CPU].should eql(2.0)
usage1cache[:MEMORY].should eql(128)
usage1cache[:STORAGE].should eql(1000)
end
it "should add a second VM" do
values = {
:CPU => 2,
:MEMORY => 128,
:UID => 2,
:GID => 4,
}
@mock_client.add_vm(1, values)
end
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(1)
usage1cache[:CPU].should eql(2.0)
usage1cache[:MEMORY].should eql(128)
usage1cache[:STORAGE].should eql(1000)
end
it "should check the cache (force)" do
usage1force = @quota.get_usage(@uid1, nil, true)
usage1force[:UID].should eql(0)
usage1force[:NUM_VMS].should eql(1*2)
usage1force[:CPU].should eql(2.0*2)
usage1force[:MEMORY].should eql(128*2)
usage1force[:STORAGE].should eql(1000)
end
it "should check the usage cache is updated and contains the last usage" do
usage1cache = @quota.get_usage(@uid1)
usage1cache[:UID].should eql(0)
usage1cache[:NUM_VMS].should eql(1*2)
usage1cache[:CPU].should eql(2.0*2)
usage1cache[:MEMORY].should eql(128*2)
usage1cache[:STORAGE].should eql(1000)
end
it "should add a second Image" do
values = {
:UID => 2,
:GID => 4,
:SIZE => 1000
}
@mock_client.add_image(1, values)
end
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(1*2)
usage1cache[:CPU].should eql(2.0*2)
usage1cache[:MEMORY].should eql(128*2)
usage1cache[:STORAGE].should eql(1000)
end
it "should check the cache (force)" do
usage1force = @quota.get_usage(@uid1, nil, true)
usage1force[:UID].should eql(0)
usage1force[:NUM_VMS].should eql(1*2)
usage1force[:CPU].should eql(2.0*2)
usage1force[:MEMORY].should eql(128*2)
usage1force[:STORAGE].should eql(1000*2)
end
it "should check the usage cache is updated and contains the last usage" do
usage1cache = @quota.get_usage(@uid1)
usage1cache[:UID].should eql(0)
usage1cache[:NUM_VMS].should eql(1*2)
usage1cache[:CPU].should eql(2.0*2)
usage1cache[:MEMORY].should eql(128*2)
usage1cache[:STORAGE].should eql(1000*2)
end
it "should add a new quota and check it" do
@quota.set_quota(@uid1, @quota1)
quota = @quota.get_quota(@uid1)
@quota1.each{ |key,value|
quota[key].should eql(value)
}
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, Requested: 2.0)"
@quota.authorize(@uid1, @acl_vm_create).should eql(err_msg)
@quota.authorize(@uid1, @acl_template_instantiate).should eql(err_msg)
@quota.authorize(@uid1, @acl_image_create).should eql(false)
end
it "should add a new quota for another user and check it" do
@quota.set_quota(@uid2, @quota2)
quota = @quota.get_quota(@uid2)
@quota2.each{ |key,value|
quota[key].should eql(value)
}
end
it "should list all the defined quotas" do
quotas = @quota.get_quota
quotas.each { |quota|
if quota[:UID] == @uid1
@quota1.each{ |key,value|
quota[key].should eql(value)
}
elsif quota[:UID] == @uid2
@quota2.each{ |key,value|
quota[key].should eql(value)
}
end
}
end
it "should update the first user quota and check it" do
new_quota = Hash.new
@quota1.each { |key,value|
new_quota[key] = value*3
}
@quota.set_quota(@uid1, new_quota)
quota = @quota.get_quota(@uid1)
new_quota.each{ |key,value|
quota[key] == value
}
end
it "should authorize the user because the quota is not spent" do
@quota.authorize(@uid1, @acl_vm_create).should eql(false)
@quota.authorize(@uid1, @acl_image_create).should eql(false)
@quota.authorize(@uid1, @acl_template_instantiate).should eql(false)
end
it "should update the first user quota and check it" do
new_quota = {
:STORAGE => 0
}
@quota.set_quota(@uid1, new_quota)
quota = @quota.get_quota(@uid1)
quota[:STORAGE].should eql(new_quota[:STORAGE])
end
it "should not authorize the user because the image quota is spent" 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, Requested: 271)"
@quota.authorize(@uid1, @acl_image_create).should eql(err_msg)
end
it "should delete the quota and check it" do
@quota.delete_quota(@uid1)
quota1 = @quota.get_quota(@uid1)
quota1[:UID].should eql(0)
quota1[:NUM_VMS].should eql(nil)
quota1[:CPU].should eql(nil)
quota1[:MEMORY].should eql(nil)
quota1[:STORAGE].should eql(nil)
end
it "should authorize the user because the quota was deleted" do
@quota.authorize(@uid1, @acl_vm_create).should eql(false)
@quota.authorize(@uid1, @acl_image_create).should eql(false)
@quota.authorize(@uid1, @acl_template_instantiate).should eql(false)
end
end

View File

@ -1,209 +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. #
#--------------------------------------------------------------------------- #
require 'cli_helper'
class OneQuotaHelper
#---------------------------------------------------------------------------
# Tables to format user quotas
#---------------------------------------------------------------------------
TABLE_DS = CLIHelper::ShowTable.new(nil, self) do
column :"DATASTORE ID", "", :left, :size=>12 do |d|
d["ID"] if !d.nil?
end
column :"IMAGES (used)", "", :right, :size=>14 do |d|
d["IMAGES_USED"] if !d.nil?
end
column :"IMAGES (limit)", "", :right, :size=>14 do |d|
d["IMAGES"] if !d.nil?
end
column :"SIZE (used)", "", :right, :size=>14 do |d|
d["SIZE_USED"] if !d.nil?
end
column :"SIZE (limit)", "", :right, :size=>14 do |d|
d["SIZE"] if !d.nil?
end
end
TABLE_NET = CLIHelper::ShowTable.new(nil, self) do
column :"NETWORK ID", "", :left, :size=>12 do |d|
d["ID"] if !d.nil?
end
column :"LEASES (used)", "", :right, :size=>14 do |d|
d["LEASES_USED"] if !d.nil?
end
column :"LEASES (limit)", "", :right, :size=>14 do |d|
d["LEASES"] if !d.nil?
end
end
TABLE_VM = CLIHelper::ShowTable.new(nil, self) do
column :"VMS", "", :left, :size=>12 do |d|
d["VMS"] if !d.nil?
end
column :"MEMORY (used)", "", :right, :size=>14 do |d|
d["MEMORY_USED"] if !d.nil?
end
column :"MEMORY (limit)", "", :right, :size=>14 do |d|
d["MEMORY"] if !d.nil?
end
column :"CPU (used)", "", :right, :size=>14 do |d|
d["CPU_USED"] if !d.nil?
end
column :"CPU (limit)", "", :right, :size=>14 do |d|
d["CPU"] if !d.nil?
end
end
TABLE_IMG = CLIHelper::ShowTable.new(nil, self) do
column :"IMAGE ID", "", :left, :size=>12 do |d|
d["ID"] if !d.nil?
end
column :"RVMS (used)", "", :right, :size=>14 do |d|
d["RVMS_USED"] if !d.nil?
end
column :"RVMS (limit)", "", :right, :size=>14 do |d|
d["RVMS"] if !d.nil?
end
end
HELP_QUOTA = <<-EOT.unindent
#-----------------------------------------------------------------------
# Supported quota limits:
#
# DATASTORE = [
# ID = <ID of the datastore>
# IMAGES = <Max. number of images in the datastore>
# SIZE = <Max. storage capacity (Mb) used in the datastore>
# ]
#
# VM = [
# VMS = <Max. number of VMs>
# MEMORY = <Max. allocated memory (Mb)>
# CPU = <Max. allocated CPU>
# ]
#
# NETWORK = [
# ID = <ID of the network>
# LEASES = <Max. number of IP leases from the network>
# ]
#
# IMAGE = [
# ID = <ID of the image>
# RVMS = <Max. number of VMs using the image>
# ]
#
# In any quota 0 means unlimited. The usage counters "*_USED" are
# shown for information purposes and will NOT be modified.
#-----------------------------------------------------------------------
EOT
# Edits the quota template of a resource
# @param resource [PoolElement] to get the current info from
# @param path [String] path to the new contents. If nil a editor will be
# used
# @return [String] contents of the new quotas
def self.set_quota(resource, path)
str = ""
if path.nil?
require 'tempfile'
tmp = Tempfile.new('one-cli')
path = tmp.path
rc = resource.info
if OpenNebula.is_error?(rc)
puts rc.message
exit -1
end
tmp << HELP_QUOTA
tmp << resource.template_like_str("DATASTORE_QUOTA") << "\n"
tmp << resource.template_like_str("VM_QUOTA") << "\n"
tmp << resource.template_like_str("NETWORK_QUOTA") << "\n"
tmp << resource.template_like_str("IMAGE_QUOTA") << "\n"
tmp.close
editor_path = ENV["EDITOR"] ? ENV["EDITOR"] : EDITOR_PATH
system("#{editor_path} #{path}")
unless $?.exitstatus == 0
puts "Editor not defined"
exit -1
end
str = File.read(path)
File.unlink(path)
else
str = File.read(path)
end
str
end
# Outputs formated quota information to stdout
# @param qh [Hash] with the quotas for a given resource
#
def self.format_quota(qh)
str_h1="%-80s"
puts
CLIHelper.print_header(str_h1 % "RESOURCE USAGE & QUOTAS",false)
puts
ds_quotas = [qh['DATASTORE_QUOTA']['DATASTORE']].flatten
if !ds_quotas[0].nil?
TABLE_DS.show(ds_quotas, {})
puts
end
vm_quotas = [qh['VM_QUOTA']['VM']].flatten
if !vm_quotas[0].nil?
TABLE_VM.show(vm_quotas, {})
puts
end
net_quotas = [qh['NETWORK_QUOTA']['NETWORK']].flatten
if !net_quotas[0].nil?
TABLE_NET.show(net_quotas, {})
puts
end
image_quotas = [qh['IMAGE_QUOTA']['IMAGE']].flatten
if !image_quotas[0].nil?
TABLE_IMG.show(image_quotas, {})
end
end
end