mirror of
https://github.com/OpenNebula/one.git
synced 2025-01-27 14:03:40 +03:00
Merge branch 'master' into bug-847
Conflicts: src/ozones/Server/lib/OZones/AggregatedPool.rb src/ozones/Server/lib/OZones/Zones.rb
This commit is contained in:
commit
2650f81e50
@ -34,9 +34,28 @@ public:
|
||||
|
||||
~VirtualMachineTemplate(){};
|
||||
|
||||
VirtualMachineTemplate(VirtualMachineTemplate& vmt):Template(vmt){};
|
||||
VirtualMachineTemplate(VirtualMachineTemplate& vmt):Template(vmt){};
|
||||
|
||||
/**
|
||||
* Checks the template for RESTRICTED ATTRIBUTES
|
||||
* @param rs_attr the first restricted attribute found if any
|
||||
* @return true if a restricted attribute is found in the template
|
||||
*/
|
||||
bool check(string& rs_attr);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Number of restricted attributes
|
||||
*/
|
||||
const static int RS_ATTRS_LENGTH;
|
||||
|
||||
/**
|
||||
* Restricted template attributes in the form
|
||||
* 'SINGLE' or 'VECTOR/ATTR'. Restricted attributes are only
|
||||
* allowed for ONE_ADMIN Group.
|
||||
*/
|
||||
const static string RESTRICTED_ATTRIBUTES[];
|
||||
|
||||
friend class VirtualMachine;
|
||||
};
|
||||
|
||||
|
22
install.sh
22
install.sh
@ -198,6 +198,7 @@ ETC_DIRS="$ETC_LOCATION/im_kvm \
|
||||
|
||||
LIB_DIRS="$LIB_LOCATION/ruby \
|
||||
$LIB_LOCATION/ruby/OpenNebula \
|
||||
$LIB_LOCATION/ruby/zona \
|
||||
$LIB_LOCATION/ruby/cloud/ \
|
||||
$LIB_LOCATION/ruby/cloud/econe \
|
||||
$LIB_LOCATION/ruby/cloud/econe/views \
|
||||
@ -273,7 +274,8 @@ OZONES_DIRS="$OZONES_LOCATION/lib \
|
||||
OZONES_CLIENT_DIRS="$LIB_LOCATION/ruby \
|
||||
$LIB_LOCATION/ruby/OpenNebula \
|
||||
$LIB_LOCATION/ruby/cli \
|
||||
$LIB_LOCATION/ruby/cli/ozones_helper"
|
||||
$LIB_LOCATION/ruby/cli/ozones_helper \
|
||||
$LIB_LOCATION/ruby/zona"
|
||||
|
||||
LIB_ECO_CLIENT_DIRS="$LIB_LOCATION/ruby \
|
||||
$LIB_LOCATION/ruby/OpenNebula \
|
||||
@ -372,10 +374,11 @@ INSTALL_CLIENT_FILES=(
|
||||
CLI_LIB_FILES:$LIB_LOCATION/ruby/cli
|
||||
ONE_CLI_LIB_FILES:$LIB_LOCATION/ruby/cli/one_helper
|
||||
ETC_CLIENT_FILES:$ETC_LOCATION
|
||||
OZONES_LIB_CLIENT_FILES:$LIB_LOCATION/ruby
|
||||
OZONES_BIN_CLIENT_FILES:$BIN_LOCATION
|
||||
OZONES_LIB_CLIENT_CLI_FILES:$LIB_LOCATION/ruby/cli
|
||||
OZONES_LIB_CLIENT_CLI_HELPER_FILES:$LIB_LOCATION/ruby/cli/ozones_helper
|
||||
OZONES_LIB_API_FILES:$LIB_LOCATION/ruby
|
||||
OZONES_LIB_API_ZONA_FILES:$LIB_LOCATION/ruby/zona
|
||||
CLI_CONF_FILES:$ETC_LOCATION/cli
|
||||
OCA_LIB_FILES:$LIB_LOCATION/ruby
|
||||
RUBY_OPENNEBULA_LIB_FILES:$LIB_LOCATION/ruby/OpenNebula
|
||||
@ -430,10 +433,11 @@ INSTALL_OZONES_FILES=(
|
||||
OZONES_PUBLIC_IMAGES_FILES:$OZONES_LOCATION/public/images
|
||||
OZONES_PUBLIC_CSS_FILES:$OZONES_LOCATION/public/css
|
||||
OZONES_PUBLIC_JS_PLUGINS_FILES:$OZONES_LOCATION/public/js/plugins
|
||||
OZONES_LIB_CLIENT_FILES:$LIB_LOCATION/ruby
|
||||
OZONES_BIN_CLIENT_FILES:$BIN_LOCATION
|
||||
OZONES_LIB_CLIENT_CLI_FILES:$LIB_LOCATION/ruby/cli
|
||||
OZONES_LIB_CLIENT_CLI_HELPER_FILES:$LIB_LOCATION/ruby/cli/ozones_helper
|
||||
OZONES_LIB_API_FILES:$LIB_LOCATION/ruby
|
||||
OZONES_LIB_API_ZONA_FILES:$LIB_LOCATION/ruby/zona
|
||||
)
|
||||
|
||||
INSTALL_OZONES_ETC_FILES=(
|
||||
@ -1061,6 +1065,16 @@ OZONES_LIB_ZONE_FILES="src/ozones/Server/lib/OZones/Zones.rb \
|
||||
src/ozones/Server/lib/OZones/AggregatedImages.rb \
|
||||
src/ozones/Server/lib/OZones/AggregatedTemplates.rb"
|
||||
|
||||
OZONES_LIB_API_FILES="src/ozones/Client/lib/zona.rb"
|
||||
|
||||
OZONES_LIB_API_ZONA_FILES="src/ozones/Client/lib/zona/ZoneElement.rb \
|
||||
src/ozones/Client/lib/zona/OZonesPool.rb \
|
||||
src/ozones/Client/lib/zona/OZonesJSON.rb \
|
||||
src/ozones/Client/lib/zona/VDCPool.rb \
|
||||
src/ozones/Client/lib/zona/VDCElement.rb \
|
||||
src/ozones/Client/lib/zona/OZonesElement.rb \
|
||||
src/ozones/Client/lib/zona/ZonePool.rb"
|
||||
|
||||
OZONES_PUBLIC_VENDOR_JQUERY=$SUNSTONE_PUBLIC_VENDOR_JQUERY
|
||||
|
||||
OZONES_PUBLIC_VENDOR_DATATABLES=$SUNSTONE_PUBLIC_VENDOR_DATATABLES
|
||||
@ -1096,8 +1110,6 @@ OZONES_PUBLIC_JS_PLUGINS_FILES="src/ozones/Server/public/js/plugins/zones-tab.js
|
||||
src/ozones/Server/public/js/plugins/aggregated-tab.js \
|
||||
src/ozones/Server/public/js/plugins/dashboard-tab.js"
|
||||
|
||||
OZONES_LIB_CLIENT_FILES="src/ozones/Client/lib/OZonesClient.rb"
|
||||
|
||||
OZONES_LIB_CLIENT_CLI_FILES="src/ozones/Client/lib/cli/ozones_helper.rb"
|
||||
|
||||
OZONES_LIB_CLIENT_CLI_HELPER_FILES="\
|
||||
|
@ -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
|
@ -41,14 +41,13 @@ echo "$IMAGE_REPOSITORY_PATH/`echo $CANONICAL_MD5 | cut -d ' ' -f1`"
|
||||
}
|
||||
|
||||
function fs_du {
|
||||
SIZE=`$(stat -c %s $1)`
|
||||
|
||||
SIZE=`$DU -m $1 2>/dev/null`
|
||||
if [ $? -ne 0 ]; then
|
||||
SIZE=0
|
||||
else
|
||||
SIZE=$(($SIZE/1048576))
|
||||
fi
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
SIZE=0
|
||||
else
|
||||
SIZE=`echo $SIZE | cut -f1 -d' '`
|
||||
fi
|
||||
|
||||
echo "$SIZE"
|
||||
}
|
||||
echo "$SIZE"
|
||||
}
|
@ -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()
|
||||
@ -114,7 +125,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
|
||||
|
@ -77,10 +77,7 @@ module OpenNebula
|
||||
conf_file.scan(SINGLE_VARIABLE_REG) {|m|
|
||||
key=m[0].strip.upcase
|
||||
value=m[1].strip
|
||||
|
||||
# hack to skip multiline VM_TYPE values
|
||||
next if %w{NAME TEMPLATE}.include? key.upcase
|
||||
|
||||
|
||||
add_value(key, value)
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,21 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# 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. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
ONE_LOCATION=ENV["ONE_LOCATION"]
|
||||
|
||||
if !ONE_LOCATION
|
||||
@ -17,14 +33,14 @@ require 'ozones_helper/vdc_helper.rb'
|
||||
cmd=CommandParser::CmdParser.new(ARGV) do
|
||||
usage "`onevdc` command [<args>] [<options>]"
|
||||
version OpenNebulaHelper::ONE_VERSION
|
||||
|
||||
|
||||
set :format, :vdcid, "VDC ID" do |arg|
|
||||
arg.match(/^[0123456789]+$/) ? [0,arg] : [-1]
|
||||
end
|
||||
|
||||
########################################################################
|
||||
# Global Options
|
||||
########################################################################
|
||||
########################################################################
|
||||
set :option, CommandParser::OPTIONS
|
||||
|
||||
FORCE={
|
||||
@ -36,35 +52,34 @@ cmd=CommandParser::CmdParser.new(ARGV) do
|
||||
|
||||
begin
|
||||
helper = VDCHelper.new "vdc"
|
||||
rescue Exception => e
|
||||
rescue Exception => e
|
||||
warn e.message
|
||||
exit -1
|
||||
end
|
||||
|
||||
|
||||
command :create, 'Create a new VDC', :file, :options=>[FORCE] do
|
||||
helper.create_resource(args[0], options)
|
||||
end
|
||||
|
||||
|
||||
command :show, 'Show information of a particular VDC', :vdcid do
|
||||
helper.show_resource(args[0],options)
|
||||
end
|
||||
|
||||
command :list, 'Lists VDCs in the pool',
|
||||
:options=>CLIHelper::OPTIONS+OpenNebulaHelper::OPTIONS do
|
||||
|
||||
command :list, 'Lists VDCs in the pool' do
|
||||
helper.list_pool(options)
|
||||
end
|
||||
|
||||
command :delete, 'Deletes a VDC', :vdcid do
|
||||
helper.delete_resource(args[0],options)
|
||||
helper.delete_resource(args[0],options)
|
||||
end
|
||||
|
||||
command :addhost, 'Adds the set of hosts to the VDC',
|
||||
:vdcid, :range, :options=>[FORCE] do
|
||||
command :addhost, 'Adds the set of hosts to the VDC',
|
||||
:vdcid, :range, :options=>[FORCE] do
|
||||
helper.addhost(args[0], args[1], options)
|
||||
end
|
||||
|
||||
command :delhost, 'Deletes the set of hosts from the VDC',
|
||||
:vdcid, :range, :options=>[FORCE] do
|
||||
:vdcid, :range do
|
||||
helper.delhost(args[0], args[1], options)
|
||||
end
|
||||
end
|
||||
|
@ -66,56 +66,55 @@ cmd=CommandParser::CmdParser.new(ARGV) do
|
||||
zone=helper.show_resource(args[0],options)[1]
|
||||
|
||||
case args[1]
|
||||
when "host"
|
||||
aux_helper = OneHostHelper.new(
|
||||
zone['onename'] + ":" + zone['onepass'],
|
||||
zone['endpoint'],
|
||||
false)
|
||||
when "host"
|
||||
aux_helper = OneHostHelper.new(
|
||||
zone[:ONENAME] + ":" + zone[:ONEPASS],
|
||||
zone[:ENDPOINT],
|
||||
false)
|
||||
|
||||
aux_helper.list_pool(options)
|
||||
when "vm"
|
||||
aux_helper = OneVMHelper.new(
|
||||
zone['onename'] + ":" + zone['onepass'],
|
||||
zone['endpoint'],
|
||||
false)
|
||||
aux_helper.list_pool(options)
|
||||
when "vm"
|
||||
aux_helper = OneVMHelper.new(
|
||||
zone[:ONENAME] + ":" + zone[:ONEPASS],
|
||||
zone[:ENDPOINT],
|
||||
false)
|
||||
|
||||
aux_helper.list_pool(options)
|
||||
when "image"
|
||||
aux_helper = OneImageHelper.new(
|
||||
zone['onename'] + ":" + zone['onepass'],
|
||||
zone['endpoint'],
|
||||
false)
|
||||
aux_helper.list_pool(options)
|
||||
when "image"
|
||||
aux_helper = OneImageHelper.new(
|
||||
zone[:ONENAME] + ":" + zone[:ONEPASS],
|
||||
zone[:ENDPOINT],
|
||||
false)
|
||||
|
||||
aux_helper.list_pool(options)
|
||||
when "vn"
|
||||
aux_helper = OneVNetHelper.new(
|
||||
zone['onename'] + ":" + zone['onepass'],
|
||||
zone['endpoint'],
|
||||
false)
|
||||
aux_helper.list_pool(options)
|
||||
when "vn"
|
||||
aux_helper = OneVNetHelper.new(
|
||||
zone[:ONENAME] + ":" + zone[:ONEPASS],
|
||||
zone[:ENDPOINT],
|
||||
false)
|
||||
|
||||
aux_helper.list_pool(options)
|
||||
aux_helper.list_pool(options)
|
||||
|
||||
when "template"
|
||||
aux_helper = OneTemplateHelper.new(
|
||||
zone['onename'] + ":" + zone['onepass'],
|
||||
zone['endpoint'],
|
||||
false)
|
||||
when "template"
|
||||
aux_helper = OneTemplateHelper.new(
|
||||
zone[:ONENAME] + ":" + zone[:ONEPASS],
|
||||
zone[:ENDPOINT],
|
||||
false)
|
||||
|
||||
aux_helper.list_pool(options)
|
||||
aux_helper.list_pool(options)
|
||||
|
||||
when "user"
|
||||
aux_helper = OneUserHelper.new(
|
||||
zone['onename'] + ":" + zone['onepass'],
|
||||
zone['endpoint'],
|
||||
false)
|
||||
when "user"
|
||||
aux_helper = OneUserHelper.new(
|
||||
zone[:ONENAME] + ":" + zone[:ONEPASS],
|
||||
zone[:ENDPOINT],
|
||||
false)
|
||||
|
||||
aux_helper.list_pool(options)
|
||||
aux_helper.list_pool(options)
|
||||
end
|
||||
0
|
||||
end
|
||||
|
||||
command :list, 'Lists Zones in the pool',
|
||||
:options=>CLIHelper::OPTIONS+OpenNebulaHelper::OPTIONS do
|
||||
command :list, 'Lists Zones in the pool' do
|
||||
helper.list_pool(options)
|
||||
end
|
||||
|
||||
|
@ -1,280 +0,0 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
# 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 'rubygems'
|
||||
require 'uri'
|
||||
require 'net/https'
|
||||
require 'json'
|
||||
require 'OpenNebula/Configuration'
|
||||
|
||||
module OZonesClient
|
||||
class Client
|
||||
|
||||
OZONES_VERSION = <<EOT
|
||||
oZones 1.0
|
||||
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
|
||||
EOT
|
||||
|
||||
######################################################################
|
||||
# Initialize client library
|
||||
######################################################################
|
||||
def initialize(user=nil, pass=nil, endpoint_str=nil,
|
||||
timeout=nil, debug_flag=true)
|
||||
@debug = debug_flag
|
||||
@timeout = timeout
|
||||
|
||||
# Server location
|
||||
if endpoint_str
|
||||
@endpoint = endpoint_str
|
||||
elsif ENV["OZONES_URL"]
|
||||
@endpoint = ENV["OZONES_URL"]
|
||||
else
|
||||
@endpoint = "http://localhost:6121"
|
||||
end
|
||||
|
||||
# Autentication
|
||||
if user && pass
|
||||
@ozonesauth = [user, pass]
|
||||
elsif ENV['OZONES_AUTH']
|
||||
@ozonesauth=File.read(ENV['OZONES_AUTH']).strip.split(':')
|
||||
end
|
||||
|
||||
if !@ozonesauth
|
||||
raise "No authorization data present"
|
||||
end
|
||||
|
||||
if @ozonesauth.size != 2
|
||||
raise "Authorization data malformed"
|
||||
end
|
||||
end
|
||||
|
||||
#####################################
|
||||
# General Resource Request Methods #
|
||||
####################################
|
||||
|
||||
######################################################################
|
||||
# Retieves all elements on a pool
|
||||
# :zonetemplate
|
||||
######################################################################
|
||||
def get_pool(kind)
|
||||
url = URI.parse(@endpoint+"/" + kind)
|
||||
req = Net::HTTP::Get.new(url.path)
|
||||
|
||||
req.basic_auth @ozonesauth[0], @ozonesauth[1]
|
||||
|
||||
res = OZonesClient::http_start(url, @timeout) {|http|
|
||||
http.request(req)
|
||||
}
|
||||
|
||||
return OZonesClient::parse_error(res, kind)
|
||||
end
|
||||
|
||||
######################################################################
|
||||
# Post a new Resource to the relevant OZones Pool
|
||||
# :zonetemplate
|
||||
######################################################################
|
||||
def post_resource(kind, template)
|
||||
tmpl_str = File.read(template)
|
||||
post_resource_str(kind, tmpl_str)
|
||||
end
|
||||
|
||||
def post_resource_str(kind, tmpl_str)
|
||||
body_str = OZonesClient::to_body(kind, tmpl_str)
|
||||
|
||||
url = URI.parse("#{@endpoint}/#{kind}")
|
||||
|
||||
req = Net::HTTP::Post.new(url.path)
|
||||
req.body=body_str
|
||||
|
||||
req.basic_auth @ozonesauth[0], @ozonesauth[1]
|
||||
|
||||
res = OZonesClient::http_start(url, @timeout) do |http|
|
||||
http.request(req)
|
||||
end
|
||||
|
||||
return OZonesClient::parse_error(res, kind)
|
||||
end
|
||||
|
||||
def put_resource(kind, id, tmpl_str)
|
||||
body_str = OZonesClient::to_body(kind, tmpl_str)
|
||||
|
||||
url = URI.parse("#{@endpoint}/#{kind}/#{id}")
|
||||
|
||||
req = Net::HTTP::Put.new(url.path)
|
||||
req.body=body_str
|
||||
|
||||
req.basic_auth @ozonesauth[0], @ozonesauth[1]
|
||||
|
||||
res = OZonesClient::http_start(url, @timeout) do |http|
|
||||
http.request(req)
|
||||
end
|
||||
|
||||
return OZonesClient::parse_error(res, kind)
|
||||
end
|
||||
|
||||
def get_resource(kind, id)
|
||||
url = URI.parse("#{@endpoint}/#{kind}/#{id}")
|
||||
req = Net::HTTP::Get.new(url.path)
|
||||
|
||||
req.basic_auth @ozonesauth[0], @ozonesauth[1]
|
||||
|
||||
res = OZonesClient::http_start(url, @timeout) {|http|
|
||||
http.request(req)
|
||||
}
|
||||
|
||||
return OZonesClient::parse_error(res, kind)
|
||||
end
|
||||
|
||||
def delete_resource(kind, id)
|
||||
url = URI.parse("#{@endpoint}/#{kind}/#{id}")
|
||||
req = Net::HTTP::Delete.new(url.path)
|
||||
|
||||
req.basic_auth @ozonesauth[0], @ozonesauth[1]
|
||||
|
||||
res = OZonesClient::http_start(url, @timeout) {|http|
|
||||
http.request(req)
|
||||
}
|
||||
|
||||
return OZonesClient::parse_error(res, kind)
|
||||
end
|
||||
end
|
||||
|
||||
# #########################################################################
|
||||
# The Error Class represents a generic error in the OZones Client
|
||||
# library. It contains a readable representation of the error.
|
||||
# #########################################################################
|
||||
class Error
|
||||
attr_reader :message
|
||||
|
||||
# +message+ a description of the error
|
||||
def initialize(message=nil)
|
||||
@message=message
|
||||
end
|
||||
|
||||
def to_s()
|
||||
@message
|
||||
end
|
||||
end
|
||||
|
||||
# #########################################################################
|
||||
# Error handling functions
|
||||
# #########################################################################
|
||||
def self.is_error?(value)
|
||||
value.class==OZonesClient::Error
|
||||
end
|
||||
|
||||
def self.is_http_error?(value)
|
||||
value.class != Net::HTTPOK
|
||||
end
|
||||
|
||||
def self.parse_error(value, kind)
|
||||
if OZonesClient::is_error?(value)
|
||||
return value
|
||||
else
|
||||
if OZonesClient::is_http_error?(value)
|
||||
str = "Operating with #{kind.upcase} failed with HTTP error "
|
||||
str = str + "code: #{value.code}\n"
|
||||
if value.body
|
||||
# Try to extract error message
|
||||
begin
|
||||
str << "Body: " <<
|
||||
OZonesClient::parse_json(value.body,
|
||||
"error")["message"]
|
||||
rescue
|
||||
str.gsub!("\nBody:","")
|
||||
end
|
||||
end
|
||||
return OZonesClient::Error.new str
|
||||
end
|
||||
end
|
||||
return value # If it is not an error, return it as-is
|
||||
end
|
||||
|
||||
# #########################################################################
|
||||
# Starts an http connection and calls the block provided. SSL flag
|
||||
# is set if needed.
|
||||
# #########################################################################
|
||||
def self.http_start(url, timeout, &block)
|
||||
http = Net::HTTP.new(url.host, url.port)
|
||||
|
||||
if timeout
|
||||
http.read_timeout = timeout.to_i
|
||||
end
|
||||
|
||||
if url.scheme=='https'
|
||||
http.use_ssl = true
|
||||
http.verify_mode=OpenSSL::SSL::VERIFY_NONE
|
||||
end
|
||||
|
||||
begin
|
||||
http.start do |connection|
|
||||
block.call(connection)
|
||||
end
|
||||
rescue Errno::ECONNREFUSED => e
|
||||
str = "Error connecting to server (#{e.to_s}).\n"
|
||||
str << "Server: #{url.host}:#{url.port}"
|
||||
|
||||
return OZonesClient::Error.new(str)
|
||||
rescue Errno::ETIMEDOUT => e
|
||||
str = "Error timeout connecting to server (#{e.to_s}).\n"
|
||||
str << "Server: #{url.host}:#{url.port}"
|
||||
|
||||
return OZonesClient::Error.new(str)
|
||||
rescue Timeout::Error => e
|
||||
str = "Error timeout while connected to server (#{e.to_s}).\n"
|
||||
str << "Server: #{url.host}:#{url.port}"
|
||||
|
||||
return OZonesClient::Error.new(str)
|
||||
end
|
||||
end
|
||||
|
||||
##########################################################################
|
||||
# JSON & Template utils
|
||||
##########################################################################
|
||||
|
||||
def self.to_body(kind, tmpl_str)
|
||||
tmpl = OpenNebula::Configuration.new(tmpl_str)
|
||||
res = { "#{kind}" => tmpl.conf }
|
||||
|
||||
return JSON::generate(res)
|
||||
end
|
||||
|
||||
def self.parse_json(json_str, root_element)
|
||||
begin
|
||||
hash = JSON.parse(json_str)
|
||||
rescue Exception => e
|
||||
return OZonesClient::Error.new(e.message)
|
||||
end
|
||||
|
||||
if hash.has_key?(root_element)
|
||||
return hash[root_element]
|
||||
else
|
||||
return OZonesClient::Error.new("Error parsing JSON: Wrong resource type")
|
||||
end
|
||||
end
|
||||
|
||||
def self.to_json(hash_to_convert)
|
||||
begin
|
||||
JSON.pretty_generate hash_to_convert
|
||||
rescue Exception => e
|
||||
OZonesClient::Error.new(e.message)
|
||||
end
|
||||
end
|
||||
end
|
@ -14,61 +14,61 @@
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
require 'OZonesClient'
|
||||
require 'zona'
|
||||
|
||||
module OZonesHelper
|
||||
|
||||
|
||||
class OZHelper
|
||||
def initialize(user=nil, pass=nil, endpoint_str=nil,
|
||||
timeout=nil, debug_flag=true)
|
||||
@client = OZonesClient::Client.new(user,
|
||||
pass,
|
||||
endpoint_str,
|
||||
timeout,
|
||||
debug_flag)
|
||||
@client = Zona::Client.new(user,
|
||||
pass,
|
||||
endpoint_str,
|
||||
timeout,
|
||||
debug_flag)
|
||||
end
|
||||
|
||||
def create_resource(kind, template)
|
||||
rc = @client.post_resource(kind, template)
|
||||
|
||||
if OZonesClient::is_error?(rc)
|
||||
[-1, rc.message]
|
||||
rc = @client.post_resource_file(kind, template)
|
||||
|
||||
if Zona::is_error?(rc)
|
||||
[-1, rc.message]
|
||||
else
|
||||
id = get_id(rc)
|
||||
[0, "ID: #{id}"]
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def list_pool(kind, options)
|
||||
rc = @client.get_pool(kind)
|
||||
|
||||
if OZonesClient::is_error?(rc)
|
||||
[-1, rc.message]
|
||||
|
||||
if Zona::is_error?(rc)
|
||||
[-1, rc.message]
|
||||
else
|
||||
pool=OZonesClient::parse_json(rc.body, kind.upcase + "_POOL")
|
||||
format_pool(pool, options)
|
||||
pool=Zona::OZonesJSON.parse_json(rc.body, kind.upcase + "_POOL")
|
||||
format_pool(pool, options)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def show_resource(kind, id, options)
|
||||
rc = @client.get_resource(kind, id)
|
||||
|
||||
if OZonesClient::is_error?(rc)
|
||||
[-1, rc.message]
|
||||
|
||||
if Zona::is_error?(rc)
|
||||
[-1, rc.message]
|
||||
else
|
||||
resource=OZonesClient::parse_json(rc.body, kind.upcase)
|
||||
format_resource(resource, options)
|
||||
resource=Zona::OZonesJSON.parse_json(rc.body, kind.upcase)
|
||||
format_resource(resource, options)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def delete_resource(kind, id, options)
|
||||
rc = @client.delete_resource(kind, id)
|
||||
|
||||
if OZonesClient::is_error?(rc)
|
||||
[-1, rc.message]
|
||||
|
||||
if Zona::is_error?(rc)
|
||||
[-1, rc.message]
|
||||
else
|
||||
message=OZonesClient::parse_json(rc.body, "message")
|
||||
[0, "#{message}"]
|
||||
message=Zona::OZonesJSON.parse_json(rc.body, "message")
|
||||
[0, "#{message}"]
|
||||
end
|
||||
end
|
||||
|
||||
@ -78,9 +78,9 @@ module OZonesHelper
|
||||
|
||||
|
||||
def get_id(rc)
|
||||
id = rc.body.match('\"id\":(.*)$')[1].strip
|
||||
id = rc.body.match('\"ID\":(.*)$')[1].strip
|
||||
if id[-1..-1] == ","
|
||||
id = id[0..id.size-2]
|
||||
id = id[0..id.size-2]
|
||||
end
|
||||
|
||||
return id
|
||||
|
@ -19,7 +19,7 @@ require 'cli/one_helper'
|
||||
|
||||
class VDCHelper < OZonesHelper::OZHelper
|
||||
def initialize(kind, user=nil, pass=nil, endpoint_str=nil,
|
||||
timeout=nil, debug_flag=true)
|
||||
timeout=nil, debug_flag=true)
|
||||
@vdc_str = kind
|
||||
super(user, pass, endpoint_str, timeout, debug_flag)
|
||||
end
|
||||
@ -33,8 +33,8 @@ class VDCHelper < OZonesHelper::OZHelper
|
||||
|
||||
rc = @client.post_resource_str(@vdc_str, tmpl_str)
|
||||
|
||||
if OZonesClient::is_error?(rc)
|
||||
[-1, rc.message]
|
||||
if Zona::is_error?(rc)
|
||||
[-1, rc.message]
|
||||
else
|
||||
id = get_id(rc)
|
||||
[0, "ID: #{id}"]
|
||||
@ -48,7 +48,7 @@ class VDCHelper < OZonesHelper::OZHelper
|
||||
def show_resource(id, options)
|
||||
super(@vdc_str,id, options)
|
||||
end
|
||||
|
||||
|
||||
def delete_resource(id, options)
|
||||
super(@vdc_str,id, options)
|
||||
end
|
||||
@ -56,13 +56,13 @@ class VDCHelper < OZonesHelper::OZHelper
|
||||
def addhost(id, host_array, options)
|
||||
rc = @client.get_resource(@vdc_str, id)
|
||||
|
||||
if OZonesClient::is_error?(rc)
|
||||
return [-1, rc.message]
|
||||
if Zona::is_error?(rc)
|
||||
return [-1, rc.message]
|
||||
else
|
||||
vdc = OZonesClient::parse_json(rc.body, @vdc_str.upcase)
|
||||
vdc = Zona::OZonesJSON.parse_json(rc.body, @vdc_str.upcase)
|
||||
end
|
||||
|
||||
hosts = vdc['hosts'].split(',').collect!{|x| x.to_i}
|
||||
hosts = vdc[:HOSTS].split(',').collect!{|x| x.to_i}
|
||||
host_array.concat(hosts).uniq!
|
||||
|
||||
new_host = host_array.join(',')
|
||||
@ -72,37 +72,33 @@ class VDCHelper < OZonesHelper::OZHelper
|
||||
template << "FORCE=YES\n"
|
||||
end
|
||||
|
||||
rc = @client.put_resource(@vdc_str, id, template)
|
||||
rc = @client.put_resource_str(@vdc_str, id, template)
|
||||
|
||||
if OZonesClient::is_error?(rc)
|
||||
return [-1, rc.message]
|
||||
if Zona::is_error?(rc)
|
||||
return [-1, rc.message]
|
||||
end
|
||||
|
||||
[0, ""]
|
||||
end
|
||||
|
||||
|
||||
def delhost(id, host_array, options)
|
||||
rc = @client.get_resource(@vdc_str, id)
|
||||
|
||||
if OZonesClient::is_error?(rc)
|
||||
return [-1, rc.message]
|
||||
|
||||
if Zona::is_error?(rc)
|
||||
return [-1, rc.message]
|
||||
else
|
||||
vdc = OZonesClient::parse_json(rc.body, @vdc_str.upcase)
|
||||
vdc = Zona::OZonesJSON.parse_json(rc.body, @vdc_str.upcase)
|
||||
end
|
||||
|
||||
hosts = vdc['hosts'].split(',').collect!{|x| x.to_i}
|
||||
hosts = vdc[:HOSTS].split(',').collect!{|x| x.to_i}
|
||||
|
||||
new_host = (hosts - host_array).join(',')
|
||||
template = "ID=#{id}\nHOSTS=#{new_host}\n"
|
||||
|
||||
if options[:force]
|
||||
template << "FORCE=YES\n"
|
||||
end
|
||||
rc = @client.put_resource_str(@vdc_str, id, template)
|
||||
|
||||
rc = @client.put_resource(@vdc_str, id, template)
|
||||
|
||||
if OZonesClient::is_error?(rc)
|
||||
return [-1, rc.message]
|
||||
if Zona.is_error?(rc)
|
||||
return [-1, rc.message]
|
||||
end
|
||||
|
||||
[0, ""]
|
||||
@ -113,39 +109,39 @@ class VDCHelper < OZonesHelper::OZHelper
|
||||
def format_resource(vdc, options)
|
||||
str_h1="%-60s"
|
||||
str="%-10s: %-20s"
|
||||
|
||||
|
||||
CLIHelper.print_header(str_h1 % ["VDC #{vdc['name']} INFORMATION"])
|
||||
|
||||
puts str % ["ID ", vdc['id'].to_s]
|
||||
puts str % ["NAME ", vdc['name'].to_s]
|
||||
puts str % ["GROUP_ID ", vdc['group_id'].to_s]
|
||||
puts str % ["ZONEID ", vdc['zones_id'].to_s]
|
||||
puts str % ["VDCADMIN ", vdc['vdcadminname'].to_s]
|
||||
puts str % ["HOST IDs ", vdc['hosts'].to_s]
|
||||
|
||||
puts str % ["ID ", vdc[:ID].to_s]
|
||||
puts str % ["NAME ", vdc[:NAME].to_s]
|
||||
puts str % ["GROUP_ID ", vdc[:GROUP_ID].to_s]
|
||||
puts str % ["ZONEID ", vdc[:ZONES_ID].to_s]
|
||||
puts str % ["VDCADMIN ", vdc[:VDCADMINNAME].to_s]
|
||||
puts str % ["HOST IDs ", vdc[:HOSTS].to_s]
|
||||
puts
|
||||
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
def format_pool(pool, options)
|
||||
def format_pool(pool, options)
|
||||
st=CLIHelper::ShowTable.new(nil) do
|
||||
column :ID, "Identifier for VDC", :size=>4 do |d,e|
|
||||
d["id"]
|
||||
d[:ID]
|
||||
end
|
||||
|
||||
column :NAME, "Name of the VDC", :right, :size=>15 do |d,e|
|
||||
d["name"]
|
||||
d[:NAME]
|
||||
end
|
||||
|
||||
column :ZONEID, "Id of the Zone where it belongs",
|
||||
:right, :size=>40 do |d,e|
|
||||
d["zones_id"]
|
||||
column :ZONEID, "Id of the Zone where it belongs",
|
||||
:right, :size=>40 do |d,e|
|
||||
d[:ZONES_ID]
|
||||
end
|
||||
|
||||
|
||||
default :ID, :NAME, :ZONEID
|
||||
end
|
||||
st.show(pool[@vdc_str.upcase], options)
|
||||
|
||||
end
|
||||
st.show(pool[:VDC], options)
|
||||
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
@ -9,13 +9,13 @@ require 'cli/one_helper/oneuser_helper'
|
||||
|
||||
class ZonesHelper < OZonesHelper::OZHelper
|
||||
def initialize(kind, user=nil, pass=nil, endpoint_str=nil,
|
||||
timeout=nil, debug_flag=true)
|
||||
timeout=nil, debug_flag=true)
|
||||
@zone_str = kind
|
||||
super(user, pass, endpoint_str, timeout, debug_flag)
|
||||
end
|
||||
|
||||
def create_resource(template)
|
||||
super(@zone_str,template)
|
||||
super(@zone_str,template)
|
||||
end
|
||||
|
||||
def list_pool(options)
|
||||
@ -25,68 +25,68 @@ class ZonesHelper < OZonesHelper::OZHelper
|
||||
def show_resource(id, options)
|
||||
super(@zone_str,id, options)
|
||||
end
|
||||
|
||||
|
||||
def delete_resource(id, options)
|
||||
super(@zone_str,id, options)
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
def format_resource(zone, options)
|
||||
str_h1="%-61s"
|
||||
str="%-15s: %-20s"
|
||||
|
||||
CLIHelper.print_header(str_h1 % ["ZONE #{zone['name']} INFORMATION"])
|
||||
|
||||
puts str % ["ID ", zone['id'].to_s]
|
||||
puts str % ["NAME ", zone['name'].to_s]
|
||||
puts str % ["ZONE ADMIN ",zone['onename'].to_s]
|
||||
puts str % ["ZONE PASS ", zone['onepass'].to_s]
|
||||
puts str % ["ENDPOINT ", zone['endpoint'].to_s]
|
||||
puts str % ["# VDCS ", zone['vdcs'].size.to_s]
|
||||
|
||||
CLIHelper.print_header(str_h1 % ["ZONE #{zone[:NAME]} INFORMATION"])
|
||||
|
||||
puts str % ["ID ", zone[:ID].to_s]
|
||||
puts str % ["NAME ", zone[:NAME].to_s]
|
||||
puts str % ["ZONE ADMIN ",zone[:ONENAME].to_s]
|
||||
puts str % ["ZONE PASS ", zone[:ONEPASS].to_s]
|
||||
puts str % ["ENDPOINT ", zone[:ENDPOINT].to_s]
|
||||
puts str % ["# VDCS ", zone[:VDCS].size.to_s]
|
||||
puts
|
||||
|
||||
if zone['vdcs'].size == 0
|
||||
|
||||
if zone[:VDCS].size == 0
|
||||
return [0, zone]
|
||||
end
|
||||
|
||||
|
||||
CLIHelper.print_header(str_h1 % ["VDCS INFORMATION"])
|
||||
|
||||
st=CLIHelper::ShowTable.new(nil) do
|
||||
|
||||
st=CLIHelper::ShowTable.new(nil) do
|
||||
column :ID, "Identifier for VDC", :size=>4 do |d,e|
|
||||
d["id"]
|
||||
d[:ID]
|
||||
end
|
||||
|
||||
column :NAME, "Name of the VDC", :right, :size=>15 do |d,e|
|
||||
d["name"]
|
||||
d[:NAME]
|
||||
end
|
||||
|
||||
|
||||
default :ID, :NAME
|
||||
end
|
||||
|
||||
st.show(zone["vdcs"], options)
|
||||
|
||||
st.show(zone[:VDCS], options)
|
||||
|
||||
return [0, zone]
|
||||
end
|
||||
|
||||
def format_pool(pool, options)
|
||||
def format_pool(pool, options)
|
||||
st=CLIHelper::ShowTable.new(nil) do
|
||||
column :ID, "Identifier for Zone", :size=>4 do |d,e|
|
||||
d["id"]
|
||||
d[:ID]
|
||||
end
|
||||
|
||||
column :NAME, "Name of the Zone", :right, :size=>15 do |d,e|
|
||||
d["name"]
|
||||
d[:NAME]
|
||||
end
|
||||
|
||||
column :ENDPOINT, "Endpoint of the Zone", :right, :size=>40 do |d,e|
|
||||
d["endpoint"]
|
||||
d[:ENDPOINT]
|
||||
end
|
||||
|
||||
|
||||
default :ID, :NAME, :ENDPOINT
|
||||
end
|
||||
st.show(pool[@zone_str.upcase], options)
|
||||
|
||||
st.show(pool[:ZONE], options)
|
||||
|
||||
return 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
320
src/ozones/Client/lib/zona.rb
Normal file
320
src/ozones/Client/lib/zona.rb
Normal file
@ -0,0 +1,320 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
# 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 'rubygems'
|
||||
require 'uri'
|
||||
require 'net/https'
|
||||
require 'OpenNebula/Configuration'
|
||||
|
||||
require 'zona/OZonesJSON'
|
||||
|
||||
require 'zona/OZonesPool'
|
||||
require 'zona/OZonesElement'
|
||||
|
||||
require 'zona/ZonePool'
|
||||
require 'zona/ZoneElement'
|
||||
|
||||
require 'zona/VDCPool'
|
||||
require 'zona/VDCElement'
|
||||
|
||||
################################################################################
|
||||
# This module contains all the OZones API related classes and utilities.
|
||||
################################################################################
|
||||
module Zona
|
||||
|
||||
############################################################################
|
||||
# OZones Client provides functionality to send and retrieve information
|
||||
# from the OZones server side. It is used by CLI and API to handle the
|
||||
# http requests to the server and basic error control on the
|
||||
# responses.
|
||||
############################################################################
|
||||
class Client
|
||||
|
||||
# Provides current version information.
|
||||
# Should match server's oZones version.
|
||||
OZONES_VERSION = <<EOT
|
||||
oZones 1.0
|
||||
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
|
||||
EOT
|
||||
|
||||
# Initialize client instance
|
||||
# @param [String] user oZones username
|
||||
# @param [String] pass oZones password
|
||||
# @param [String] endpoint Server endpoint
|
||||
# @param [Integer] timeout client timout, defaults means no timeout
|
||||
# @param [Boolean] debug_flag produce debug information
|
||||
# @return [Client] Client instance
|
||||
def initialize(user=nil, pass=nil, endpoint_str=nil,
|
||||
timeout=nil, debug_flag=true)
|
||||
@debug = debug_flag
|
||||
@timeout = timeout
|
||||
|
||||
# Server location
|
||||
if endpoint_str
|
||||
@endpoint = endpoint_str
|
||||
elsif ENV["OZONES_URL"]
|
||||
@endpoint = ENV["OZONES_URL"]
|
||||
else
|
||||
@endpoint = "http://localhost:6121"
|
||||
end
|
||||
|
||||
# Autentication
|
||||
if user && pass
|
||||
@ozonesauth = [user, pass]
|
||||
elsif ENV['OZONES_AUTH']
|
||||
@ozonesauth=File.read(ENV['OZONES_AUTH']).strip.split(':')
|
||||
end
|
||||
|
||||
if !@ozonesauth
|
||||
raise "No authorization data present"
|
||||
end
|
||||
|
||||
if @ozonesauth.size != 2
|
||||
raise "Authorization data malformed"
|
||||
end
|
||||
end
|
||||
|
||||
# Retrieves all elements of a kind (pool)
|
||||
# @param [String] kind element kind
|
||||
# @return [String, Zone::Error] Response string or Error
|
||||
def get_pool(kind)
|
||||
url = URI.parse(@endpoint+"/" + kind)
|
||||
req = Net::HTTP::Get.new(url.path)
|
||||
|
||||
req.basic_auth @ozonesauth[0], @ozonesauth[1]
|
||||
|
||||
res = Client.http_start(url, @timeout) {|http|
|
||||
http.request(req)
|
||||
}
|
||||
|
||||
return Client.parse_error(res, kind)
|
||||
end
|
||||
|
||||
# Creates a resource from an opennebula template file
|
||||
# @param [String] kind resource kind: vdc,zone...
|
||||
# @param [String] template path to template file
|
||||
# @return [String, Zona::Error] Response string or Error
|
||||
def post_resource_file(kind, template)
|
||||
tmpl_str = File.read(template)
|
||||
post_resource_str(kind, tmpl_str)
|
||||
end
|
||||
|
||||
# Creates a resource from an OpenNebula template string
|
||||
# @param [String] kind resource kind: vdc,zone...
|
||||
# @param [String] tmpl_str OpenNebula template string
|
||||
# @return [String, Zona::Error] Response string or Error
|
||||
def post_resource_str(kind, tmpl_str)
|
||||
tmpl_json = Zona.to_body(kind, tmpl_str)
|
||||
post_resource(kind, tmpl_json)
|
||||
end
|
||||
|
||||
# Creates a resource
|
||||
# @param [String] kind resource kind: vdc, zone...
|
||||
# @param [String] tmpl_json JSON template
|
||||
# @return [String, Zona::Error] Response string or Error
|
||||
def post_resource(kind, tmpl_json)
|
||||
url = URI.parse("#{@endpoint}/#{kind}")
|
||||
|
||||
req = Net::HTTP::Post.new(url.path)
|
||||
req.body=tmpl_json
|
||||
|
||||
req.basic_auth @ozonesauth[0], @ozonesauth[1]
|
||||
|
||||
res = Client.http_start(url, @timeout) do |http|
|
||||
http.request(req)
|
||||
end
|
||||
|
||||
return Client.parse_error(res, kind)
|
||||
end
|
||||
|
||||
# Modifies a resource from an OpenNebula template string
|
||||
# @param [String] kind resource kind: vdc, zone...
|
||||
# @param [String] tmpl_str OpenNebula template string
|
||||
# @return [String, Zona::Error] Response string or Error
|
||||
def put_resource_str(kind, id, tmpl_str)
|
||||
tmpl_json = Client.to_body(kind, tmpl_str)
|
||||
put_resource(kind, id, tmpl_json)
|
||||
end
|
||||
|
||||
# Modifies a resource
|
||||
# @param [String] kind resource kind: vdc, zone...
|
||||
# @param [String] tmpl_json JSON template
|
||||
# @return [String, Zona::Error] Response string or Error
|
||||
def put_resource(kind, id, tmpl_json)
|
||||
url = URI.parse("#{@endpoint}/#{kind}/#{id}")
|
||||
|
||||
req = Net::HTTP::Put.new(url.path)
|
||||
req.body=tmpl_json
|
||||
|
||||
req.basic_auth @ozonesauth[0], @ozonesauth[1]
|
||||
|
||||
res = Client.http_start(url, @timeout) do |http|
|
||||
http.request(req)
|
||||
end
|
||||
|
||||
return Client.parse_error(res, kind)
|
||||
end
|
||||
|
||||
|
||||
# Retrieves a resource
|
||||
# @param [String] Kind resource kind: vdc, zone...
|
||||
# @param [#to_i] id resource id
|
||||
# @return [String, Zona::Error] Response string or Error
|
||||
def get_resource(kind, id)
|
||||
url = URI.parse("#{@endpoint}/#{kind}/#{id}")
|
||||
req = Net::HTTP::Get.new(url.path)
|
||||
|
||||
req.basic_auth @ozonesauth[0], @ozonesauth[1]
|
||||
|
||||
res = Client.http_start(url, @timeout) {|http|
|
||||
http.request(req)
|
||||
}
|
||||
|
||||
return Client.parse_error(res, kind)
|
||||
end
|
||||
|
||||
# Deletes a resource
|
||||
# @param [String] kind resource kind: vdc, zone...
|
||||
# @param [#to_i] id resource id
|
||||
# @return [String, Zona::Error] Response string or Error
|
||||
def delete_resource(kind, id)
|
||||
url = URI.parse("#{@endpoint}/#{kind}/#{id}")
|
||||
req = Net::HTTP::Delete.new(url.path)
|
||||
|
||||
req.basic_auth @ozonesauth[0], @ozonesauth[1]
|
||||
|
||||
res = Client.http_start(url, @timeout) {|http|
|
||||
http.request(req)
|
||||
}
|
||||
|
||||
return Client.parse_error(res, kind)
|
||||
end
|
||||
|
||||
|
||||
|
||||
private
|
||||
|
||||
|
||||
|
||||
# Starts an http connection and calls the block provided. SSL flag
|
||||
# is set if needed.
|
||||
def self.http_start(url, timeout, &block)
|
||||
http = Net::HTTP.new(url.host, url.port)
|
||||
|
||||
if timeout
|
||||
http.read_timeout = timeout.to_i
|
||||
end
|
||||
|
||||
if url.scheme=='https'
|
||||
http.use_ssl = true
|
||||
http.verify_mode=OpenSSL::SSL::VERIFY_NONE
|
||||
end
|
||||
|
||||
begin
|
||||
http.start do |connection|
|
||||
block.call(connection)
|
||||
end
|
||||
rescue Errno::ECONNREFUSED => e
|
||||
str = "Error connecting to server (#{e.to_s}).\n"
|
||||
str << "Server: #{url.host}:#{url.port}"
|
||||
return Error.new(str)
|
||||
rescue Errno::ETIMEDOUT => e
|
||||
str = "Error timeout connecting to server (#{e.to_s}).\n"
|
||||
str << "Server: #{url.host}:#{url.port}"
|
||||
return Error.new(str)
|
||||
rescue Timeout::Error => e
|
||||
str = "Error timeout while connected to server (#{e.to_s}).\n"
|
||||
str << "Server: #{url.host}:#{url.port}"
|
||||
return Error.new(str)
|
||||
rescue Errno::ENETUNREACH => e
|
||||
str = "Error trying to reach network (#{e.to_s}).\n"
|
||||
str << "Server: #{url.host}:#{url.port}"
|
||||
return Error.new(str)
|
||||
end
|
||||
end
|
||||
|
||||
# Parses a response
|
||||
# @param [String] value response string
|
||||
# @param [String] kind resource kind
|
||||
# @return [String, Zona::Error] Returns the value or Error if found
|
||||
def self.parse_error(value, kind)
|
||||
if Zona.is_error?(value)
|
||||
return value
|
||||
else
|
||||
if Zona.is_http_error?(value)
|
||||
str = "Operating with #{kind} failed with HTTP error"
|
||||
str = " " + str + "code: #{value.code}\n"
|
||||
if value.body
|
||||
# Try to extract error message
|
||||
begin
|
||||
str << "Body: " <<
|
||||
OZonesJSON.parse_json(value.body,
|
||||
"error")["message"]
|
||||
rescue
|
||||
str.gsub!("\nBody:","")
|
||||
end
|
||||
end
|
||||
return Error.new(str)
|
||||
end
|
||||
end
|
||||
value # If it is not an error, return it as-is
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
# Turns a OpenNebula template string into a JSON string
|
||||
# @param [String] kind element kind
|
||||
# @param [String] tmpl_str template
|
||||
# @return [String, Zona::Error] JSON string or Error
|
||||
def self.to_body(kind, tmpl_str)
|
||||
tmpl = OpenNebula::Configuration.new(tmpl_str)
|
||||
res = { "#{kind.upcase}" => tmpl.conf }
|
||||
|
||||
return OZonesJSON.to_json(res)
|
||||
end
|
||||
|
||||
# @return [Boolean] Returns true if instance of {Zona::Error}
|
||||
def self.is_error?(value)
|
||||
value.class==Zona::Error
|
||||
end
|
||||
|
||||
# @return [Boolean] Returns true if HTTP return code is not OK
|
||||
def self.is_http_error?(value)
|
||||
value.class != Net::HTTPOK
|
||||
end
|
||||
|
||||
# The Error Class represents a generic error in the Zona
|
||||
# library. It contains a readable representation of the error.
|
||||
class Error
|
||||
attr_reader :message
|
||||
|
||||
# @param [String] A description of the error
|
||||
def initialize(message=nil)
|
||||
@message=message
|
||||
end
|
||||
|
||||
# @return [String] Error message description
|
||||
def to_s()
|
||||
@message
|
||||
end
|
||||
end
|
||||
end
|
105
src/ozones/Client/lib/zona/OZonesElement.rb
Normal file
105
src/ozones/Client/lib/zona/OZonesElement.rb
Normal file
@ -0,0 +1,105 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
# 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. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
|
||||
module Zona
|
||||
|
||||
# Standard abstraction of an OZones element. To be inherited.
|
||||
class OZonesElement < JSONElement
|
||||
|
||||
protected
|
||||
|
||||
# Initializes an OZones Element instance. Tries to set @pe_id and @name
|
||||
# @param [Hash] hash element description
|
||||
# @param [Zona::Client] client OZones client
|
||||
# @return [String] Element's name or nil
|
||||
def initialize(hash, client)
|
||||
@client = client
|
||||
@json_hash = hash
|
||||
|
||||
@pe_id = self[:ID] ? self[:ID].to_i : nil
|
||||
@name = self[:NAME] ? self[:NAME] : nil
|
||||
end
|
||||
|
||||
# Retrieves details about an object and fills in
|
||||
# the information hash
|
||||
# @param [String] kind element kind: zone, vdc...
|
||||
# @param [String] root_element root element of the JSON object description
|
||||
# @return [Zona::Error] nil or Error
|
||||
def info(kind, root_element)
|
||||
return Error.new('ID not defined') if !@pe_id
|
||||
|
||||
rc = @client.get_resource(kind,@pe_id)
|
||||
if !Zona.is_error?(rc)
|
||||
initialize_json(rc.body,root_element)
|
||||
|
||||
rc = nil
|
||||
|
||||
@pe_id = self[:ID] ? self[:ID].to_i : nil
|
||||
@name = self[:NAME] ? self[:NAME] : nil
|
||||
|
||||
end
|
||||
rc
|
||||
end
|
||||
|
||||
# Allocates a new element from a hash description
|
||||
# @param [String] kind element kind: zone, vdc...
|
||||
# @param [Hash] tmpl_hash element template hash
|
||||
# @return [Zona::Error] nil or Error
|
||||
def allocate_hash(kind, tmpl_hash)
|
||||
allocate(kind, tmpl_hash.to_json)
|
||||
end
|
||||
|
||||
# Allocates a new element from a JSON description
|
||||
# @param [String] kind element kind: zone, vdc...
|
||||
# @param [String] tmpl_json element JSON template
|
||||
# @return [Zona::Error] nil or Error
|
||||
def allocate(kind, tmpl_json)
|
||||
rc = @client.post_resource(kind, tmpl_json)
|
||||
|
||||
if !Zona.is_error?(rc)
|
||||
initialize_json(rc.body,kind.upcase)
|
||||
@pe_id = self[:ID].to_i
|
||||
rc = nil
|
||||
end
|
||||
rc
|
||||
end
|
||||
|
||||
# Deletes current element
|
||||
# @param [String] kind element kind: zone, vdc...
|
||||
# @return [Zona::Error] nil or Error
|
||||
def delete(kind)
|
||||
return Error.new('ID not defined') if !@pe_id
|
||||
|
||||
rc = @client.delete_resource(kind,@pe_id)
|
||||
return rc if Zona.is_error?(rc)
|
||||
nil
|
||||
end
|
||||
|
||||
public
|
||||
|
||||
attr_reader :pe_id, :name
|
||||
|
||||
# Creates a new element with the custom ID
|
||||
# @param [#to_i] id element ID
|
||||
# @param [Zona::Client] client OZones Client for this element
|
||||
# @return [OZonesElement] A new element object
|
||||
def self.new_with_id(id, client=nil)
|
||||
self.new(self.build_json(id.to_i),client)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
117
src/ozones/Client/lib/zona/OZonesJSON.rb
Normal file
117
src/ozones/Client/lib/zona/OZonesJSON.rb
Normal file
@ -0,0 +1,117 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
# 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. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
|
||||
module Zona
|
||||
|
||||
require 'json'
|
||||
|
||||
# Several class methods regarding the handling of JSON descriptions
|
||||
# for the OZones utilities.
|
||||
class OZonesJSON
|
||||
|
||||
# Build an element description hash.
|
||||
# @param [String] json_str JSON description of the element
|
||||
# @param [#to_sym] root_element root element of the JSON object
|
||||
# @return [Hash,Zona::Error] The parsed JSON hash, or Error
|
||||
def self.build_json(json_str, root_element)
|
||||
begin
|
||||
parser = JSON.parser.new(json_str, {:symbolize_names => true})
|
||||
hash = parser.parse
|
||||
|
||||
root_sym = root_element.to_sym
|
||||
|
||||
if hash.has_key?(root_sym)
|
||||
return hash[root_sym]
|
||||
end
|
||||
|
||||
Error.new("Error parsing JSON:\ root element not present")
|
||||
|
||||
rescue => e
|
||||
Error.new(e.message)
|
||||
end
|
||||
end
|
||||
|
||||
# @see build_json
|
||||
def self.parse_json(json_str, root_element)
|
||||
OZonesJSON.build_json(json_str, root_element)
|
||||
end
|
||||
|
||||
# Generates a pretty JSON string from a hash
|
||||
# @param [Hash] hash_to_convert a hash to be converted
|
||||
# @return [String, Zona::Error] JSON string or Error if conversion fails
|
||||
def self.to_json(hash_to_convert)
|
||||
begin
|
||||
JSON.pretty_generate(hash_to_convert)
|
||||
rescue Exception => e
|
||||
Error.new(e.message)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# This class represents an element described by a JSON string
|
||||
# In practice, this is represented by a hash,
|
||||
# result of parsing the JSON string.
|
||||
class JSONElement
|
||||
|
||||
# Initializes an instance
|
||||
# @param [Hash] json_hash a hash with the object description
|
||||
def initialize(json_hash=nil)
|
||||
@json_hash=json_hash
|
||||
end
|
||||
|
||||
# Initializes an instance with a JSON description
|
||||
# @param [String] json_str JSON description
|
||||
# @param [#to_sym] root_element root element in the element description
|
||||
def initialize_json(json_str, root_element)
|
||||
rc = OZonesJSON.build_json(json_str,root_element)
|
||||
@json_hash = rc
|
||||
|
||||
if Zona.is_error?(rc) || (rc.size == 0)
|
||||
@json_hash=nil
|
||||
end
|
||||
end
|
||||
|
||||
# Accesses the value of a JSON element key
|
||||
# @param [#to_sym] key
|
||||
# @return [String] Value
|
||||
def [](key)
|
||||
@json_hash[key.to_sym]
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
# This class represents a collection of JSON Elements and it is itself one
|
||||
class JSONPool < JSONElement
|
||||
|
||||
# Initializes an instance
|
||||
# @param [Hash] json_hash a hash with the object description
|
||||
def initialize(json_hash=nil)
|
||||
super(json_hash)
|
||||
end
|
||||
|
||||
# Allows to iterate through the elements of a JSONPool
|
||||
# @param [Block] block a block to be called in each iteration
|
||||
def each_element(block)
|
||||
@json_hash[@element_name].each do |elem|
|
||||
block.call self.factory(elem)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
68
src/ozones/Client/lib/zona/OZonesPool.rb
Normal file
68
src/ozones/Client/lib/zona/OZonesPool.rb
Normal file
@ -0,0 +1,68 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
# 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. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
|
||||
module Zona
|
||||
|
||||
# Standard pool abstraction. To be inherited.
|
||||
class OZonesPool < JSONPool
|
||||
|
||||
protected
|
||||
|
||||
# Initializes a Pool instance
|
||||
# @param [#to_sym] pool pool name tag
|
||||
# @param [#to_sym] pool pool elements name tag
|
||||
# @param [Zona::Client] client OZones Client
|
||||
def initialize(pool,element,client)
|
||||
super(nil)
|
||||
|
||||
@client = client
|
||||
@pool_name = pool.to_sym
|
||||
@element_name = element.to_sym
|
||||
end
|
||||
|
||||
# Produces a new Pool element with the provided description
|
||||
# @param [String] element_json JSON string of the element
|
||||
# @return [String] Element's name or nil
|
||||
def factory(element_json)
|
||||
OZonesElement.new(element_json, @client)
|
||||
end
|
||||
|
||||
# Retrieves the Pool information
|
||||
# @param [String] kind pool kind: vdc, zone...
|
||||
# @return [Zona:Error] nil or Error
|
||||
def info(kind)
|
||||
rc = @client.get_pool(kind)
|
||||
|
||||
if !Zona.is_error?(rc)
|
||||
initialize_json(rc.body,@pool_name)
|
||||
rc=nil
|
||||
end
|
||||
|
||||
rc
|
||||
end
|
||||
|
||||
public
|
||||
|
||||
# Allows iteration on pools elements
|
||||
# @param [Block] block a block to call for each iteration
|
||||
def each(&block)
|
||||
each_element(block) if @json_hash
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
124
src/ozones/Client/lib/zona/VDCElement.rb
Normal file
124
src/ozones/Client/lib/zona/VDCElement.rb
Normal file
@ -0,0 +1,124 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
# 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. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
|
||||
module Zona
|
||||
|
||||
# This class describes a single VDC element. It can be used to
|
||||
# allocate, delete, add hosts, remove hosts and retrieve full information
|
||||
# for a VDC.
|
||||
class VDC < OZonesElement
|
||||
|
||||
# String describing the kind of this resource
|
||||
# Should become part of the requests to server: get /vdc/...
|
||||
VDC_KIND = "vdc"
|
||||
|
||||
# Builds minimal JSON description for a VDC
|
||||
# @param [Integer] pe_id VDC's ID
|
||||
# @return [Hash,Zona::Error] Hash description of the object, or Error
|
||||
def self.build_json(pe_id=nil)
|
||||
if pe_id
|
||||
json = "{\"VDC\":{\"ID\":#{pe_id}}}"
|
||||
else
|
||||
json = '{"VDC":{}}'
|
||||
end
|
||||
OZonesJSON.build_json(json,:VDC)
|
||||
end
|
||||
|
||||
# Initializes a VDC object instance
|
||||
# @param [Hash] hash VDC description
|
||||
# @param [Zona::Client] client OZones Client
|
||||
# @return [String] Element's name or nil
|
||||
def initialize(hash, client)
|
||||
super(hash, client)
|
||||
end
|
||||
|
||||
# Retrieves details about this object and fills in
|
||||
# the information hash
|
||||
# @return [Zona::Error] nil or Error
|
||||
def info
|
||||
super(VDC_KIND,:VDC)
|
||||
end
|
||||
|
||||
# Allocates a new element from a hash description
|
||||
# @param [Hash] template element description
|
||||
# @return [Zona::Error] nil or Error
|
||||
def allocate_hash(template)
|
||||
super(VDC_KIND,template)
|
||||
end
|
||||
|
||||
# Allocates a new element from a JSON description
|
||||
# @param [String] template element description
|
||||
# @return [Zona::Error] nil or Error
|
||||
def allocate(template)
|
||||
super(VDC_KIND,template)
|
||||
end
|
||||
|
||||
# Deletes current element
|
||||
# @return [Zona::Error] nil or Error
|
||||
def delete
|
||||
super(VDC_KIND)
|
||||
end
|
||||
|
||||
|
||||
# Adds hosts to a VDC. The specified hosts are added to the VDC's
|
||||
# current ones.
|
||||
# @param [Array<#to_i>] hosts_array array of hosts IDs
|
||||
# in the zone to be added
|
||||
# @param [Hash] options a hash of options
|
||||
# @option options [Boolean] :force allows hosts to add hosts
|
||||
# which already belong to other VDCs
|
||||
# @return [Zona::Error] nil or Error
|
||||
def addhosts(hosts_array,options={})
|
||||
return Error.new('VDC not info-ed') if !@json_hash
|
||||
|
||||
# array of hosts, integers
|
||||
hosts = self[:HOSTS].split(',').collect!{|x| x.to_i}
|
||||
hosts.concat(hosts_array).uniq!
|
||||
|
||||
new_hosts = hosts.join(',')
|
||||
template = {:ID => @pe_id, :HOSTS => new_hosts}
|
||||
template[:FORCE] = "YES" if options[:FORCE]
|
||||
|
||||
template = {:VDC => template}
|
||||
|
||||
rc = @client.put_resource(VDC_KIND,@pe_id,template.to_json)
|
||||
return rc if Zona.is_error?(rc)
|
||||
nil
|
||||
end
|
||||
|
||||
# Delete hosts from a VDC. The specified hosts are removed from the VDC.
|
||||
# @param [Array<#to_i>] hosts_array array of the VDC's hosts IDs
|
||||
# to be removed. If a host is not in the VDC, then it is ignored.
|
||||
# @return [Zona::Error] nil or Error
|
||||
def delhosts(hosts_array)
|
||||
return Error.new('VDC not info-ed') if !@json_hash
|
||||
|
||||
hosts = self[:HOSTS].split(',').collect!{|x| x.to_i}
|
||||
|
||||
new_hosts = (hosts - hosts_array).join(',')
|
||||
template = {:VDC => {:ID => @pe_id, :HOSTS => new_hosts}}
|
||||
|
||||
rc = @client.put_resource(VDC_KIND,@pe_id,template.to_json)
|
||||
return rc if Zona.is_error?(rc)
|
||||
nil
|
||||
end
|
||||
|
||||
alias :addhost :addhosts
|
||||
alias :delhost :delhosts
|
||||
|
||||
end
|
||||
end
|
46
src/ozones/Client/lib/zona/VDCPool.rb
Normal file
46
src/ozones/Client/lib/zona/VDCPool.rb
Normal file
@ -0,0 +1,46 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
# 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. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
|
||||
module Zona
|
||||
|
||||
# This class represents a set of VDCs. It allows to list the defined
|
||||
# VDCs and iterate on them.
|
||||
class VDCPool < OZonesPool
|
||||
|
||||
# String describing the kind of this resource
|
||||
VDC_POOL_KIND="vdc"
|
||||
|
||||
# Initializes a VDC Pool instance
|
||||
# @param [Zona::Client] client OZones Client
|
||||
def initialize(client)
|
||||
super(:VDC_POOL, :VDC, client)
|
||||
end
|
||||
|
||||
# Produces a new VDC element with the provided description
|
||||
# @param [String] element_json JSON string of the element
|
||||
# @return [String] Element's name or nil
|
||||
def factory(element_json)
|
||||
VDC.new(element_json,@client)
|
||||
end
|
||||
|
||||
# Retrieves the information for this pool
|
||||
# @return [Zona:Error] nil or Error
|
||||
def info
|
||||
super(VDC_POOL_KIND)
|
||||
end
|
||||
end
|
||||
end
|
74
src/ozones/Client/lib/zona/ZoneElement.rb
Normal file
74
src/ozones/Client/lib/zona/ZoneElement.rb
Normal file
@ -0,0 +1,74 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
# 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. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
|
||||
module Zona
|
||||
|
||||
# This class describes a single OZones Zone element. It can be used to
|
||||
# allocate, delete and retrieve full information for a Zone.
|
||||
class Zone < OZonesElement
|
||||
|
||||
# String describing the kind of this resource
|
||||
ZONE_KIND = "zone"
|
||||
|
||||
# Builds minimal JSON description for a Zone
|
||||
# @param [#to_i] pe_id zone's ID
|
||||
# @return [Hash,Zona::Error] Hash description of the object, or Error
|
||||
def self.build_json(pe_id=nil)
|
||||
if pe_id
|
||||
json = "{\"ZONE\":{\"ID\":#{pe_id}}}"
|
||||
else
|
||||
json = '{"ZONE":{}}'
|
||||
end
|
||||
OZonesJSON.build_json(json,:ZONE)
|
||||
end
|
||||
|
||||
# Initializes a Zone object instance
|
||||
# @param [Hash] hash zone description
|
||||
# @param [Zona::Client] client OZones Client
|
||||
# @return [String] Element's name or nil
|
||||
def initialize(hash, client)
|
||||
super(hash, client)
|
||||
end
|
||||
|
||||
# Retrieves details about this object and fills in
|
||||
# the information hash
|
||||
# @return [Zona::Error] nil or Error
|
||||
def info
|
||||
super(ZONE_KIND,:ZONE)
|
||||
end
|
||||
|
||||
# Allocates a new element from a hash description
|
||||
# @param [Hash] template element description
|
||||
# @return [Zona::Error] nil or Error
|
||||
def allocate_hash(template)
|
||||
super(ZONE_KIND,template)
|
||||
end
|
||||
|
||||
# Allocates a new element from a JSON description
|
||||
# @param [String] template element description
|
||||
# @return [Zona::Error] nil or Error
|
||||
def allocate(template)
|
||||
super(ZONE_KIND,template)
|
||||
end
|
||||
|
||||
# Deletes current element
|
||||
# @return [Zona::Error] nil or Error
|
||||
def delete
|
||||
super(ZONE_KIND)
|
||||
end
|
||||
end
|
||||
end
|
46
src/ozones/Client/lib/zona/ZonePool.rb
Normal file
46
src/ozones/Client/lib/zona/ZonePool.rb
Normal file
@ -0,0 +1,46 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
# 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. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
|
||||
module Zona
|
||||
|
||||
# This class represents a set of Zones. It allows to list the defined
|
||||
# Zones and iterate on them.
|
||||
class ZonePool < OZonesPool
|
||||
|
||||
# String describing the kind of this resource
|
||||
ZONE_POOL_KIND = "zone"
|
||||
|
||||
# Initializes a Zone Pool instance
|
||||
# @param [Zona::Client] client OZones Client
|
||||
def initialize(client)
|
||||
super(:ZONE_POOL, :ZONE, client)
|
||||
end
|
||||
|
||||
# Produces a new Zone element with the provided description
|
||||
# @param [String] element_json JSON string of the element
|
||||
# @return [String] Element's name or nil
|
||||
def factory(element_json)
|
||||
Zone.new(element_json,@client)
|
||||
end
|
||||
|
||||
# Retrieves the information for this pool
|
||||
# @return [Zona:Error] nil or Error
|
||||
def info
|
||||
super(ZONE_POOL_KIND)
|
||||
end
|
||||
end
|
||||
end
|
@ -46,7 +46,7 @@ module OZones
|
||||
def to_str
|
||||
@message
|
||||
end
|
||||
|
||||
|
||||
def to_json
|
||||
message = { :message => @message }
|
||||
error_hash = { :error => message }
|
||||
@ -54,7 +54,7 @@ module OZones
|
||||
return JSON.pretty_generate error_hash
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Returns true if the object returned by a method of the OZones
|
||||
# library is an Error
|
||||
@ -62,10 +62,8 @@ module OZones
|
||||
def self.is_error?(value)
|
||||
value.class==OZones::Error
|
||||
end
|
||||
|
||||
|
||||
def self.str_to_json(str)
|
||||
return JSON.pretty_generate({:message => str})
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
@ -15,16 +15,16 @@
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
module OZones
|
||||
|
||||
class AggregatedHosts < AggregatedPool
|
||||
|
||||
|
||||
class AggregatedHosts < AggregatedPool
|
||||
|
||||
def initialize
|
||||
super("ZONE_POOL")
|
||||
end
|
||||
|
||||
def factory(client)
|
||||
|
||||
def factory(client)
|
||||
OpenNebulaJSON::HostPoolJSON.new(client)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
@ -15,16 +15,16 @@
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
module OZones
|
||||
|
||||
class AggregatedImages < AggregatedPool
|
||||
|
||||
|
||||
class AggregatedImages < AggregatedPool
|
||||
|
||||
def initialize
|
||||
super("ZONE_POOL")
|
||||
end
|
||||
|
||||
|
||||
def factory(client)
|
||||
OpenNebulaJSON::ImagePoolJSON.new(client)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
@ -15,53 +15,52 @@
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
module OZones
|
||||
|
||||
class AggregatedPool
|
||||
include OpenNebulaJSON::JSONUtils
|
||||
|
||||
|
||||
class AggregatedPool
|
||||
include OpenNebulaJSON::JSONUtils
|
||||
|
||||
def initialize(tag)
|
||||
@tag = tag
|
||||
end
|
||||
|
||||
|
||||
def info
|
||||
@sup_aggregated_pool = Hash.new
|
||||
@sup_aggregated_pool[@tag] = Hash.new
|
||||
@sup_aggregated_pool[@tag]["ZONE"] = Array.new
|
||||
|
||||
|
||||
OZones::Zones.all.each{|zone|
|
||||
|
||||
|
||||
zone_pool_hash = Hash.new
|
||||
|
||||
|
||||
zone_pool_hash = zone.to_hash["ZONE"]
|
||||
|
||||
client = OpenNebula::Client.new(
|
||||
zone.onename + ":" + zone.onepass,
|
||||
zone.endpoint)
|
||||
|
||||
pool = factory(client)
|
||||
|
||||
|
||||
client = OpenNebula::Client.new(zone.ONENAME + ":" + zone.ONEPASS,
|
||||
zone.ENDPOINT)
|
||||
|
||||
pool = factory(client)
|
||||
|
||||
if OpenNebula.is_error?(pool)
|
||||
zone_pool_hash.merge!(pool.to_hash)
|
||||
next
|
||||
end
|
||||
|
||||
|
||||
rc = pool.info
|
||||
|
||||
if !rc
|
||||
zone_pool_hash.merge!(pool.to_hash)
|
||||
if !rc
|
||||
zone_pool_hash.merge!(pool.to_hash)
|
||||
else
|
||||
zone_pool_hash.merge!(rc.to_hash)
|
||||
end
|
||||
|
||||
|
||||
@sup_aggregated_pool[@tag]["ZONE"] << zone_pool_hash
|
||||
|
||||
}
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def to_hash
|
||||
info
|
||||
return @sup_aggregated_pool
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
@ -15,16 +15,16 @@
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
module OZones
|
||||
|
||||
class AggregatedTemplates < AggregatedPool
|
||||
|
||||
|
||||
class AggregatedTemplates < AggregatedPool
|
||||
|
||||
def initialize
|
||||
super("ZONE_POOL")
|
||||
end
|
||||
|
||||
def factory(client)
|
||||
|
||||
def factory(client)
|
||||
OpenNebulaJSON::TemplatePoolJSON.new(client)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
@ -15,16 +15,16 @@
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
module OZones
|
||||
|
||||
class AggregatedUsers < AggregatedPool
|
||||
|
||||
|
||||
class AggregatedUsers < AggregatedPool
|
||||
|
||||
def initialize
|
||||
super("ZONE_POOL")
|
||||
end
|
||||
|
||||
def factory(client)
|
||||
|
||||
def factory(client)
|
||||
OpenNebulaJSON::UserPoolJSON.new(client)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
@ -15,16 +15,16 @@
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
module OZones
|
||||
|
||||
class AggregatedVirtualMachines < AggregatedPool
|
||||
|
||||
|
||||
class AggregatedVirtualMachines < AggregatedPool
|
||||
|
||||
def initialize
|
||||
super("ZONE_POOL")
|
||||
end
|
||||
|
||||
def factory(client)
|
||||
|
||||
def factory(client)
|
||||
OpenNebulaJSON::VirtualMachinePoolJSON.new(client)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
@ -15,16 +15,16 @@
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
module OZones
|
||||
|
||||
class AggregatedVirtualNetworks < AggregatedPool
|
||||
|
||||
|
||||
class AggregatedVirtualNetworks < AggregatedPool
|
||||
|
||||
def initialize
|
||||
super("ZONE_POOL")
|
||||
end
|
||||
|
||||
def factory(client)
|
||||
|
||||
def factory(client)
|
||||
OpenNebulaJSON::VirtualNetworkPoolJSON.new(client)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
@ -15,33 +15,33 @@
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
module OZones
|
||||
|
||||
class ApacheWritter
|
||||
def initialize(file_path)
|
||||
|
||||
class ApacheWritter
|
||||
def initialize(file_path)
|
||||
@file_path = file_path
|
||||
end
|
||||
|
||||
|
||||
def update
|
||||
htaccess = "RewriteEngine On\n"
|
||||
|
||||
|
||||
OZones::Zones.all.each{|zone|
|
||||
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"
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
File.open(@file_path, 'w') {|f|
|
||||
File.open(@file_path, 'w') {|f|
|
||||
f.flock(File::LOCK_EX)
|
||||
f.write(htaccess)
|
||||
f.write(htaccess)
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -15,34 +15,34 @@
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
module OZones
|
||||
|
||||
class ProxyRules
|
||||
def initialize(type, file_path)
|
||||
|
||||
class ProxyRules
|
||||
def initialize(type, file_path)
|
||||
@type = type
|
||||
if file_path
|
||||
@file_path = file_path
|
||||
else
|
||||
else
|
||||
if !ENV["ONE_LOCATION"]
|
||||
@file_path="/var/lib/one/.htaccess"
|
||||
else
|
||||
@file_path=ENV["ONE_LOCATION"]+"/var/.htaccess"
|
||||
@file_path=ENV["ONE_LOCATION"]+"/var/.htaccess"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# Let's check for file permissions
|
||||
if !File.writable?(@file_path) and
|
||||
!File.writable?(File.dirname(@file_path))
|
||||
raise "#{@file_path} is not writable"
|
||||
if !File.writable?(@file_path) and
|
||||
!File.writable?(File.dirname(@file_path))
|
||||
raise "#{@file_path} is not writable"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def update
|
||||
case @type
|
||||
when "apache"
|
||||
apWritter = OZones::ApacheWritter.new @file_path
|
||||
apWritter.update
|
||||
when "apache"
|
||||
apWritter = OZones::ApacheWritter.new @file_path
|
||||
apWritter.update
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
@ -15,35 +15,48 @@
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
module OZones
|
||||
|
||||
class Vdc
|
||||
|
||||
class Vdc
|
||||
include DataMapper::Resource
|
||||
include OpenNebulaJSON::JSONUtils
|
||||
extend OpenNebulaJSON::JSONUtils
|
||||
|
||||
property :id, Serial
|
||||
property :name, String, :required => true, :unique => true
|
||||
property :group_id, Integer
|
||||
property :vdcadminname, String, :required => true
|
||||
property :vdcadmin_id, Integer
|
||||
property :acls, String
|
||||
property :hosts, String
|
||||
property :ID, Serial
|
||||
property :NAME, String, :required => true, :unique => true
|
||||
property :GROUP_ID, Integer
|
||||
property :VDCADMINNAME, String, :required => true
|
||||
property :VDCADMIN_ID, Integer
|
||||
property :ACLS, String
|
||||
property :HOSTS, String
|
||||
|
||||
belongs_to :zones
|
||||
|
||||
|
||||
def self.to_hash
|
||||
zonePoolHash = Hash.new
|
||||
zonePoolHash["VDC_POOL"] = Hash.new
|
||||
zonePoolHash["VDC_POOL"]["VDC"] = Array.new unless self.all.empty?
|
||||
self.all.each{|vdc|
|
||||
zonePoolHash["VDC_POOL"]["VDC"] << vdc.attributes
|
||||
# Hack! zones_ID does not respect the
|
||||
# "all capital letters" policy
|
||||
attrs = vdc.attributes.clone
|
||||
attrs[:ZONES_ID] = vdc.attributes[:zones_ID]
|
||||
attrs.delete(:zones_ID)
|
||||
|
||||
zonePoolHash["VDC_POOL"]["VDC"] << attrs
|
||||
}
|
||||
return zonePoolHash
|
||||
end
|
||||
|
||||
|
||||
def to_hash
|
||||
vdc_attributes = Hash.new
|
||||
vdc_attributes["VDC"] = attributes
|
||||
|
||||
# Hack! zones_ID does not respect the
|
||||
# "all capital letters" policy
|
||||
attrs = attributes.clone
|
||||
attrs[:ZONES_ID] = attributes[:zones_ID]
|
||||
attrs.delete(:zones_ID)
|
||||
|
||||
vdc_attributes["VDC"] = attrs
|
||||
return vdc_attributes
|
||||
end
|
||||
end
|
||||
@ -51,36 +64,36 @@ module OZones
|
||||
###########################################################################
|
||||
# This class represents a VDC able to interact with its supporting
|
||||
# OpenNebula installation through OCA. Data persistence is provided by a
|
||||
# Vdc class
|
||||
# Vdc class
|
||||
###########################################################################
|
||||
class OpenNebulaVdc
|
||||
#######################################################################
|
||||
# Constants
|
||||
#######################################################################
|
||||
VDC_ATTRS = [:vdcadminname, :vdcadminpass, :name, :hosts]
|
||||
VDC_ATTRS = [:VDCADMINNAME, :VDCADMINPASS, :NAME, :HOSTS]
|
||||
|
||||
attr_reader :vdc
|
||||
attr_reader :zone
|
||||
|
||||
#Creates an OpenNebula VDC, using its ID, vdcid and the associated zone
|
||||
def initialize(vdcid, zone = nil)
|
||||
|
||||
if vdcid != -1
|
||||
|
||||
if vdcid != -1
|
||||
@vdc = Vdc.get(vdcid)
|
||||
|
||||
|
||||
if !@vdc
|
||||
raise "VDC with id #{vdcid} not found."
|
||||
end
|
||||
|
||||
@zone = OZones::Zones.get(@vdc.zones_id)
|
||||
@zone = OZones::Zones.get(@vdc.zones_ID)
|
||||
else
|
||||
@zone = zone
|
||||
end
|
||||
|
||||
@client = OpenNebula::Client.new(
|
||||
"#{@zone.onename}:#{@zone.onepass}",
|
||||
@zone.endpoint,
|
||||
false)
|
||||
"#{@zone.ONENAME}:#{@zone.ONEPASS}",
|
||||
@zone.ENDPOINT,
|
||||
false)
|
||||
end
|
||||
|
||||
def to_json
|
||||
@ -95,31 +108,31 @@ module OZones
|
||||
VDC_ATTRS.each { |param|
|
||||
if !vdc_data[param]
|
||||
return OZones::Error.new("Error: Couldn't create vdc." \
|
||||
"Mandatory attribute '#{param}' is missing.")
|
||||
"Mandatory attribute '#{param}' is missing.")
|
||||
end
|
||||
}
|
||||
|
||||
#Create a vdc record
|
||||
@vdc = Vdc.new
|
||||
|
||||
vdcpass = Digest::SHA1.hexdigest(vdc_data.delete(:vdcadminpass))
|
||||
|
||||
vdcpass = Digest::SHA1.hexdigest(vdc_data.delete(:VDCADMINPASS))
|
||||
@vdc.attributes = vdc_data
|
||||
|
||||
# Create a group in the zone with the VDC name
|
||||
group = OpenNebula::Group.new(OpenNebula::Group.build_xml, @client)
|
||||
rc = group.allocate(@vdc.name)
|
||||
|
||||
rc = group.allocate(@vdc.NAME)
|
||||
|
||||
return rc if OpenNebula.is_error?(rc)
|
||||
|
||||
@vdc.group_id = group.id
|
||||
@vdc.GROUP_ID = group.id
|
||||
|
||||
# Create the VDC admin user in the Zone
|
||||
user = OpenNebula::User.new(OpenNebula::User.build_xml, @client)
|
||||
rc = user.allocate(@vdc.vdcadminname, vdcpass)
|
||||
rc = user.allocate(@vdc.VDCADMINNAME, vdcpass)
|
||||
|
||||
return rollback(group, nil, nil, rc) if OpenNebula.is_error?(rc)
|
||||
|
||||
@vdc.vdcadmin_id = user.id
|
||||
@vdc.VDCADMIN_ID = user.id
|
||||
|
||||
# Change primary group of the admin user to the VDC group
|
||||
rc = user.chgrp(group.id)
|
||||
@ -132,7 +145,7 @@ module OZones
|
||||
rc, acls_str = create_acls(rules)
|
||||
return rollback(group, user,acls_str,rc) if OpenNebula.is_error?(rc)
|
||||
|
||||
@vdc.acls = acls_str
|
||||
@vdc.ACLS = acls_str
|
||||
|
||||
return true
|
||||
end
|
||||
@ -150,13 +163,13 @@ module OZones
|
||||
up.info
|
||||
|
||||
up.each{|user|
|
||||
if user['GID'].to_i == @vdc.group_id
|
||||
if user['GID'].to_i == @vdc.GROUP_ID
|
||||
user.delete
|
||||
end
|
||||
}
|
||||
|
||||
# Delete the group
|
||||
OpenNebula::Group.new_with_id(@vdc.group_id, @client).delete
|
||||
OpenNebula::Group.new_with_id(@vdc.GROUP_ID, @client).delete
|
||||
|
||||
return @vdc.destroy
|
||||
end
|
||||
@ -165,18 +178,18 @@ module OZones
|
||||
def clean_bootstrap
|
||||
delete_acls
|
||||
|
||||
OpenNebula::User.new_with_id(@vdc.vdcadmin_id, @client).delete
|
||||
OpenNebula::Group.new_with_id(@vdc.group_id, @client).delete
|
||||
OpenNebula::User.new_with_id(@vdc.VDCADMIN_ID, @client).delete
|
||||
OpenNebula::Group.new_with_id(@vdc.GROUP_ID, @client).delete
|
||||
end
|
||||
|
||||
def update(host_list)
|
||||
# Delete existing host ACLs
|
||||
delete_host_acls
|
||||
|
||||
if @vdc.acls =~ /((\d+,){#{HOST_ACL_FIRST_ID}}).*/
|
||||
if @vdc.ACLS =~ /((\d+,){#{HOST_ACL_FIRST_ID}}).*/
|
||||
newacls = $1.chop
|
||||
else
|
||||
newacls = @vdc.acls.clone
|
||||
newacls = @vdc.ACLS.clone
|
||||
end
|
||||
|
||||
# Create new ACLs. TODO Rollback ACL creation
|
||||
@ -184,7 +197,7 @@ module OZones
|
||||
host_acls = get_host_acls(host_list)
|
||||
rc, acls_str = create_acls(host_acls)
|
||||
|
||||
return rc if OpenNebula.is_error?(rc)
|
||||
return rc if OpenNebula.is_error?(rc)
|
||||
|
||||
#Create the new acl string.
|
||||
newacls << "," << acls_str
|
||||
@ -194,15 +207,15 @@ module OZones
|
||||
#Update the VDC Record
|
||||
begin
|
||||
@vdc.raise_on_save_failure = true
|
||||
@vdc.hosts = host_list
|
||||
@vdc.acls = newacls
|
||||
@vdc.HOSTS = host_list
|
||||
@vdc.ACLS = newacls
|
||||
|
||||
@vdc.save
|
||||
rescue => e
|
||||
return OpenNebula::Error.new(e.message)
|
||||
end
|
||||
|
||||
return @vdc.to_json
|
||||
return @vdc.to_json
|
||||
end
|
||||
|
||||
private
|
||||
@ -212,19 +225,19 @@ module OZones
|
||||
# The ID of the first host ACL
|
||||
HOST_ACL_FIRST_ID = 3
|
||||
|
||||
# This method returns an Array of ACL strings to create them
|
||||
# This method returns an Array of ACL strings to create them
|
||||
# in the target zone
|
||||
def get_acls
|
||||
rule_str = Array.new
|
||||
|
||||
# Grant permissions to the group
|
||||
rule_str << "@#{@vdc.group_id} VM+NET+IMAGE+TEMPLATE/* " \
|
||||
"CREATE+INFO_POOL_MINE"
|
||||
rule_str << "@#{@vdc.GROUP_ID} VM+NET+IMAGE+TEMPLATE/* " \
|
||||
"CREATE+INFO_POOL_MINE"
|
||||
|
||||
# Grant permissions to the vdc admin
|
||||
rule_str << "##{@vdc.vdcadmin_id} USER/* CREATE"
|
||||
rule_str << "##{@vdc.vdcadmin_id} USER/@#{@vdc.group_id} " \
|
||||
"MANAGE+DELETE+INFO"
|
||||
rule_str << "##{@vdc.VDCADMIN_ID} USER/* CREATE"
|
||||
rule_str << "##{@vdc.VDCADMIN_ID} USER/@#{@vdc.GROUP_ID} " \
|
||||
"MANAGE+DELETE+INFO"
|
||||
|
||||
###############################################################
|
||||
#When more rules are added the class constant HOST_ACL_FIRST_ID
|
||||
@ -238,13 +251,13 @@ module OZones
|
||||
rule_str = Array.new
|
||||
|
||||
if host_list == nil
|
||||
host_list = @vdc.hosts
|
||||
end
|
||||
host_list = @vdc.HOSTS
|
||||
end
|
||||
|
||||
# Grant permissions to use the vdc hosts
|
||||
host_list.split(',').each{|hostid|
|
||||
rule_str << "@#{@vdc.group_id} HOST/##{hostid} USE"
|
||||
}
|
||||
rule_str << "@#{@vdc.GROUP_ID} HOST/##{hostid} USE"
|
||||
}
|
||||
|
||||
return rule_str
|
||||
end
|
||||
@ -254,7 +267,7 @@ module OZones
|
||||
#######################################################################
|
||||
# Deletes ACLs for the hosts
|
||||
def delete_host_acls
|
||||
host_acls = @vdc.acls.split(',')[HOST_ACL_FIRST_ID..-1]
|
||||
host_acls = @vdc.ACLS.split(',')[HOST_ACL_FIRST_ID..-1]
|
||||
|
||||
if host_acls
|
||||
host_acls.each{|acl|
|
||||
@ -263,50 +276,50 @@ module OZones
|
||||
end
|
||||
end
|
||||
|
||||
# Delete ACLs
|
||||
# Delete ACLs
|
||||
def delete_acls
|
||||
@vdc.acls.split(",").each{|acl|
|
||||
@vdc.ACLS.split(",").each{|acl|
|
||||
OpenNebula::Acl.new_with_id(acl.to_i, @client).delete
|
||||
}
|
||||
end
|
||||
|
||||
# Deletes images
|
||||
# Deletes images
|
||||
def delete_images
|
||||
ip = OpenNebula::ImagePool.new(@client)
|
||||
ip.info
|
||||
|
||||
ip.each{|image|
|
||||
image.delete if image['GID'].to_i == @vdc.group_id
|
||||
image.delete if image['GID'].to_i == @vdc.GROUP_ID
|
||||
}
|
||||
end
|
||||
|
||||
# Deletes templates
|
||||
# Deletes templates
|
||||
def delete_templates
|
||||
tp = OpenNebula::TemplatePool.new(@client)
|
||||
tp.info
|
||||
|
||||
tp.each{|template|
|
||||
template.delete if template['GID'].to_i == @vdc.group_id
|
||||
template.delete if template['GID'].to_i == @vdc.GROUP_ID
|
||||
}
|
||||
end
|
||||
|
||||
# Deletes VMs
|
||||
# Deletes VMs
|
||||
def delete_vms
|
||||
vmp = OpenNebula::VirtualMachinePool.new(@client)
|
||||
vmp.info
|
||||
|
||||
vmp.each{|vm|
|
||||
vm.delete if vm['GID'].to_i == @vdc.group_id
|
||||
vm.delete if vm['GID'].to_i == @vdc.GROUP_ID
|
||||
}
|
||||
end
|
||||
|
||||
# Deletes VNs
|
||||
# Deletes VNs
|
||||
def delete_vns
|
||||
vnp = OpenNebula::VirtualNetworkPool.new(@client)
|
||||
vnp.info
|
||||
|
||||
vnp.each{|vn|
|
||||
vnp.delete if vn['GID'].to_i == @vdc.group_id
|
||||
vnp.delete if vn['GID'].to_i == @vdc.GROUP_ID
|
||||
}
|
||||
end
|
||||
|
||||
@ -318,13 +331,13 @@ module OZones
|
||||
def rollback(group, user, acls, rc)
|
||||
group.delete
|
||||
user.delete if user
|
||||
|
||||
|
||||
if acls
|
||||
acls.chop
|
||||
acls.split(",").each{|acl|
|
||||
OpenNebula::Acl.new_with_id(acl.to_i, @client).delete
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
return rc
|
||||
end
|
||||
@ -340,7 +353,7 @@ module OZones
|
||||
rc = acl.allocate(*OpenNebula::Acl.parse_rule(rule))
|
||||
|
||||
break if OpenNebula.is_error?(rc)
|
||||
|
||||
|
||||
acls_str << acl.id.to_s << ","
|
||||
}
|
||||
|
||||
|
@ -15,28 +15,28 @@
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
module OZones
|
||||
|
||||
class Zones
|
||||
|
||||
class Zones
|
||||
include DataMapper::Resource
|
||||
include OpenNebulaJSON::JSONUtils
|
||||
extend OpenNebulaJSON::JSONUtils
|
||||
|
||||
|
||||
#######################################################################
|
||||
# Data Model for the Zone
|
||||
#######################################################################
|
||||
property :id, Serial
|
||||
property :name, String, :required => true, :unique => true
|
||||
property :onename, String, :required => true
|
||||
property :onepass, String, :required => true
|
||||
property :endpoint, String, :required => true
|
||||
property :sunsendpoint, String
|
||||
|
||||
property :ID, Serial
|
||||
property :NAME, String, :required => true, :unique => true
|
||||
property :ONENAME, String, :required => true
|
||||
property :ONEPASS, String, :required => true
|
||||
property :ENDPOINT, String, :required => true
|
||||
property :SUNSENDPOINT, String
|
||||
|
||||
has n, :vdcs
|
||||
|
||||
|
||||
#######################################################################
|
||||
# Constants
|
||||
#######################################################################
|
||||
ZONE_ATTRS = [:onename, :onepass, :endpoint, :name]
|
||||
ZONE_ATTRS = [:ONENAME, :ONEPASS, :ENDPOINT, :NAME]
|
||||
|
||||
#######################################################################
|
||||
# JSON Functions
|
||||
@ -47,20 +47,20 @@ module OZones
|
||||
zonePoolHash["ZONE_POOL"]["ZONE"] = Array.new unless self.all.empty?
|
||||
|
||||
self.all.each{|zone|
|
||||
zonePoolHash["ZONE_POOL"]["ZONE"] <<
|
||||
zone.attributes.merge({:numbervdcs => zone.vdcs.all.size})
|
||||
zonePoolHash["ZONE_POOL"]["ZONE"] <<
|
||||
zone.attributes.merge({:NUMBERVDCS => zone.vdcs.all.size})
|
||||
}
|
||||
|
||||
return zonePoolHash
|
||||
end
|
||||
|
||||
|
||||
def to_hash
|
||||
zone_attributes = Hash.new
|
||||
zone_attributes["ZONE"] = attributes
|
||||
zone_attributes["ZONE"][:vdcs] = Array.new
|
||||
zone_attributes["ZONE"][:VDCS] = Array.new
|
||||
|
||||
self.vdcs.all.each{|vdc|
|
||||
zone_attributes["ZONE"][:vdcs]<<vdc.attributes
|
||||
zone_attributes["ZONE"][:VDCS]<< vdc.attributes
|
||||
}
|
||||
|
||||
return zone_attributes
|
||||
@ -69,35 +69,33 @@ module OZones
|
||||
#######################################################################
|
||||
# Zone Data Management
|
||||
#######################################################################
|
||||
def self.create(data)
|
||||
zone_data = Hash.new
|
||||
|
||||
data.each{|key,value|
|
||||
zone_data[key.downcase.to_sym] = value
|
||||
}
|
||||
def self.create(zone_data)
|
||||
|
||||
ZONE_ATTRS.each { |param|
|
||||
if !zone_data[param]
|
||||
return OZones::Error.new("Error: Couldn't create zone. " \
|
||||
"Mandatory attribute '#{param}' is missing.")
|
||||
"Mandatory attribute '#{param}' is missing.")
|
||||
end
|
||||
}
|
||||
|
||||
# Digest and check credentials
|
||||
zone_data[:onepass] = Digest::SHA1.hexdigest(zone_data[:onepass])
|
||||
zone_data[:ONEPASS] = Digest::SHA1.hexdigest(zone_data[:ONEPASS])
|
||||
|
||||
rc = OpenNebulaZone::check_oneadmin(zone_data[:onename],
|
||||
zone_data[:onepass],
|
||||
zone_data[:endpoint])
|
||||
$stderr.puts zone_data
|
||||
|
||||
rc = OpenNebulaZone::check_oneadmin(zone_data[:ONENAME],
|
||||
zone_data[:ONEPASS],
|
||||
zone_data[:ENDPOINT])
|
||||
|
||||
if OpenNebula.is_error?(rc)
|
||||
return OZones::Error.new("Error: Couldn't create zone. "\
|
||||
"Reason: #{rc.message}")
|
||||
"Reason: #{rc.message}")
|
||||
end
|
||||
|
||||
|
||||
# Create the zone
|
||||
begin
|
||||
zone = Zones.new
|
||||
zone = Zones.new
|
||||
zone.raise_on_save_failure = true
|
||||
|
||||
zone.attributes = zone_data
|
||||
@ -108,45 +106,44 @@ module OZones
|
||||
|
||||
return zone
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
###########################################################################
|
||||
# This class represents a Zone able to interact with its supporting
|
||||
# OpenNebula installation through OCA. Data persistence is provided by a
|
||||
# Zones class
|
||||
# Zones class
|
||||
##########################################################################
|
||||
class OpenNebulaZone
|
||||
def initialize(zoneid)
|
||||
@zone = Zones.get(zoneid)
|
||||
|
||||
|
||||
if !@zone
|
||||
raise "Error: Zone with id #{zoneid} not found"
|
||||
end
|
||||
|
||||
@client = OpenNebula::Client.new(
|
||||
"#{@zone.onename}:#{@zone.onepass}",
|
||||
@zone.endpoint)
|
||||
@client = OpenNebula::Client.new("#{@zone.ONENAME}:#{@zone.ONEPASS}",
|
||||
@zone.ENDPOINT)
|
||||
end
|
||||
|
||||
|
||||
def pool_to_json(pool_kind)
|
||||
pool = case pool_kind
|
||||
when "host" then
|
||||
OpenNebulaJSON::HostPoolJSON.new(@client)
|
||||
when "image" then
|
||||
OpenNebulaJSON::ImagePoolJSON.new(@client)
|
||||
when "user" then
|
||||
OpenNebulaJSON::UserPoolJSON.new(@client)
|
||||
when "vm" then
|
||||
OpenNebulaJSON::VirtualMachinePoolJSON.new(@client)
|
||||
when "vn","vnet" then
|
||||
OpenNebulaJSON::VirtualNetworkPoolJSON.new(@client)
|
||||
when "template","vmtemplate" then
|
||||
OpenNebulaJSON::TemplatePoolJSON.new(@client)
|
||||
else
|
||||
error = OZones::Error.new("Error: Pool #{pool_kind} not " \
|
||||
"supported for zone view")
|
||||
return [404, error.to_json]
|
||||
end
|
||||
when "host" then
|
||||
OpenNebulaJSON::HostPoolJSON.new(@client)
|
||||
when "image" then
|
||||
OpenNebulaJSON::ImagePoolJSON.new(@client)
|
||||
when "user" then
|
||||
OpenNebulaJSON::UserPoolJSON.new(@client)
|
||||
when "vm" then
|
||||
OpenNebulaJSON::VirtualMachinePoolJSON.new(@client)
|
||||
when "vn","vnet" then
|
||||
OpenNebulaJSON::VirtualNetworkPoolJSON.new(@client)
|
||||
when "template","vmtemplate" then
|
||||
OpenNebulaJSON::TemplatePoolJSON.new(@client)
|
||||
else
|
||||
error = OZones::Error.new("Error: Pool #{pool_kind} not " \
|
||||
"supported for zone view")
|
||||
return [404, error.to_json]
|
||||
end
|
||||
|
||||
pool.info
|
||||
|
||||
@ -155,23 +152,23 @@ module OZones
|
||||
|
||||
def self.all_pools_to_json(pool_kind)
|
||||
pool = case pool_kind
|
||||
when "host" then
|
||||
OZones::AggregatedHosts.new
|
||||
when "image" then
|
||||
OZones::AggregatedImages.new
|
||||
when "user" then
|
||||
OZones::AggregatedUsers.new
|
||||
when "vm" then
|
||||
OZones::AggregatedVirtualMachines.new
|
||||
when "vn","vnet" then
|
||||
OZones::AggregatedVirtualNetworks.new
|
||||
when "template","vmtemplate" then
|
||||
OZones::AggregatedTemplates.new
|
||||
else
|
||||
error = OZones::Error.new("Error: Pool #{pool_kind} not" \
|
||||
" supported for aggregated zone view")
|
||||
return [404, error.to_json]
|
||||
end
|
||||
when "host" then
|
||||
OZones::AggregatedHosts.new
|
||||
when "image" then
|
||||
OZones::AggregatedImages.new
|
||||
when "user" then
|
||||
OZones::AggregatedUsers.new
|
||||
when "vm" then
|
||||
OZones::AggregatedVirtualMachines.new
|
||||
when "vn","vnet" then
|
||||
OZones::AggregatedVirtualNetworks.new
|
||||
when "template","vmtemplate" then
|
||||
OZones::AggregatedTemplates.new
|
||||
else
|
||||
error = OZones::Error.new("Error: Pool #{pool_kind} not" \
|
||||
" supported for aggregated zone view")
|
||||
return [404, error.to_json]
|
||||
end
|
||||
|
||||
return [200, pool.to_json]
|
||||
end
|
||||
|
@ -14,12 +14,12 @@
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
class Auth
|
||||
|
||||
class Auth
|
||||
|
||||
include DataMapper::Resource
|
||||
|
||||
property :id, Serial
|
||||
property :name, String, :required => true, :unique => true
|
||||
property :password, String, :required => true
|
||||
|
||||
end
|
||||
property :name, String, :required => true, :unique => true
|
||||
property :password, String, :required => true
|
||||
|
||||
end
|
||||
|
@ -35,11 +35,11 @@ class OzonesServer
|
||||
if vdc
|
||||
return [200, vdc.to_json]
|
||||
else
|
||||
return [404,
|
||||
OZones::Error.new("Error:VDC with id #{id} not found").to_json]
|
||||
return [404,
|
||||
OZones::Error.new("Error:VDC with id #{id} not found").to_json]
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
#Gets all Zones
|
||||
def get_zones
|
||||
return 200, OZones::Zones.to_json
|
||||
@ -52,8 +52,8 @@ class OzonesServer
|
||||
if zone
|
||||
return [200, zone.to_json]
|
||||
else
|
||||
return [404,
|
||||
OZones::Error.new("Error:Zone with id #{id} not found").to_json]
|
||||
return [404,
|
||||
OZones::Error.new("Error:Zone with id #{id} not found").to_json]
|
||||
end
|
||||
end
|
||||
|
||||
@ -77,39 +77,35 @@ class OzonesServer
|
||||
############################################################################
|
||||
def create_vdc (body,pr)
|
||||
#Setup POST data
|
||||
data = parse_json(body,"vdc")
|
||||
vdc_data = parse_json_sym(body,:VDC)
|
||||
|
||||
if OpenNebula.is_error?(data)
|
||||
if OpenNebula.is_error?(vdc_data)
|
||||
return [400, OZones::Error.new("Error: Couldn't update vdc. " \
|
||||
"Reason: #{data.message}.").to_json]
|
||||
"Reason: #{data.message}.").to_json]
|
||||
end
|
||||
|
||||
vdc_data = Hash.new
|
||||
|
||||
data.each{|key,value|
|
||||
vdc_data[key.downcase.to_sym] = value
|
||||
}
|
||||
|
||||
#Get the Zone that will host the VDC. And check resouces
|
||||
zoneid = vdc_data.delete(:zoneid)
|
||||
force = vdc_data.delete(:force)
|
||||
zoneid = vdc_data.delete(:ZONEID)
|
||||
force = vdc_data.delete(:FORCE)
|
||||
|
||||
if !zoneid
|
||||
return [400, OZones::Error.new("Error: Couldn't create vdc. " \
|
||||
"Mandatory attribute zoneid missing.").to_json]
|
||||
return [400,
|
||||
OZones::Error.new("Error: Couldn't create vdc. " \
|
||||
"Mandatory attribute zoneid missing.").to_json]
|
||||
end
|
||||
|
||||
zone = OZones::Zones.get(zoneid)
|
||||
if !zone
|
||||
return [404, OZones::Error.new("Error: Couldn't create vdc. " \
|
||||
"Zone #{zoneid} not found.").to_json]
|
||||
"Zone #{zoneid} not found.").to_json]
|
||||
end
|
||||
|
||||
if (!force or force.upcase!="YES") and
|
||||
!host_uniqueness?(zone, vdc_data[:hosts])
|
||||
if (!force or force.upcase!="YES") and
|
||||
!host_uniqueness?(zone, vdc_data[:HOSTS])
|
||||
|
||||
return [403, OZones::Error.new("Error: Couldn't create vdc. " \
|
||||
"Hosts are not unique, use force to override").to_json]
|
||||
return [403,
|
||||
OZones::Error.new("Error: Couldn't create vdc. " \
|
||||
"Hosts are not unique, use force to override").to_json]
|
||||
end
|
||||
|
||||
# Create de VDC
|
||||
@ -118,20 +114,21 @@ class OzonesServer
|
||||
|
||||
if OpenNebula.is_error?(rc)
|
||||
return [400, OZones::Error.new("Error: Couldn't create vdc. " \
|
||||
"Reason: #{rc.message}").to_json]
|
||||
"Reason: #{rc.message}").to_json]
|
||||
end
|
||||
|
||||
#Update the zone and save the vdc
|
||||
zone.raise_on_save_failure = true
|
||||
zone.vdcs << vdc.vdc
|
||||
|
||||
begin
|
||||
begin
|
||||
zone.save
|
||||
rescue => e
|
||||
vdc.clean_bootstrap
|
||||
|
||||
return [400, OZones::Error.new("Error: Couldn't create " \
|
||||
"vdc. Zone could not be saved: #{e.message}").to_json]
|
||||
return [400,
|
||||
OZones::Error.new("Error: Couldn't create " \
|
||||
"vdc. Zone could not be saved: #{e.message}").to_json]
|
||||
end
|
||||
|
||||
pr.update # Rewrite proxy conf file
|
||||
@ -140,11 +137,11 @@ class OzonesServer
|
||||
|
||||
def create_zone(body, pr)
|
||||
#Setup POST data
|
||||
data = parse_json(body,"zone")
|
||||
data = parse_json_sym(body,:ZONE)
|
||||
|
||||
if OpenNebula.is_error?(data)
|
||||
return [400, OZones::Error.new("Error: Couldn't update vdc. " \
|
||||
"Reason: #{data.message}.").to_json]
|
||||
"Reason: #{data.message}.").to_json]
|
||||
end
|
||||
|
||||
zone = OZones::Zones.create(data)
|
||||
@ -162,26 +159,20 @@ class OzonesServer
|
||||
############################################################################
|
||||
def update_vdc(vdc_id, body)
|
||||
#Setup PUT data
|
||||
data = parse_json(body,"vdc")
|
||||
vdc_data = parse_json_sym(body,:VDC)
|
||||
|
||||
if OpenNebula.is_error?(data)
|
||||
if OpenNebula.is_error?(vdc_data)
|
||||
return [400, OZones::Error.new("Error: Couldn't update vdc. " \
|
||||
"Reason: #{data.message}.").to_json]
|
||||
"Reason: #{data.message}.").to_json]
|
||||
end
|
||||
|
||||
vdc_data = Hash.new
|
||||
|
||||
data.each{|key,value|
|
||||
vdc_data[key.downcase.to_sym]=value
|
||||
}
|
||||
|
||||
hosts = vdc_data.delete(:hosts)
|
||||
force = vdc_data.delete(:force)
|
||||
hosts = vdc_data.delete(:HOSTS)
|
||||
force = vdc_data.delete(:FORCE)
|
||||
|
||||
# Check parameters
|
||||
if !hosts
|
||||
return [400, OZones::Error.new("Error: Couldn't update vdc. " \
|
||||
"Missing HOSTS.").to_json]
|
||||
"Missing HOSTS.").to_json]
|
||||
end
|
||||
|
||||
# Check if the referenced Vdc exists
|
||||
@ -189,25 +180,26 @@ class OzonesServer
|
||||
vdc = OZones::OpenNebulaVdc.new(vdc_id)
|
||||
rescue => e
|
||||
return [404, OZones::Error.new("Error: Couldn't update vdc. " \
|
||||
"#{e.message}").to_json]
|
||||
"#{e.message}").to_json]
|
||||
end
|
||||
|
||||
if (!force or force.upcase != "YES") and
|
||||
!host_uniqueness?(vdc.zone, hosts, vdc_id.to_i)
|
||||
|
||||
return [403, OZones::Error.new("Error: Couldn't update vdc. " \
|
||||
"Hosts are not unique, use force to override").to_json]
|
||||
if (!force or force.upcase != "YES") and
|
||||
!host_uniqueness?(vdc.zone, hosts, vdc_id.to_i)
|
||||
|
||||
return [403,
|
||||
OZones::Error.new("Error: Couldn't update vdc. " \
|
||||
"Hosts are not unique, use force to override").to_json]
|
||||
end
|
||||
|
||||
|
||||
rc = vdc.update(hosts)
|
||||
|
||||
|
||||
if !OpenNebula.is_error?(rc)
|
||||
return [200, rc]
|
||||
else
|
||||
return [500, OZones::Error.new("Error: Couldn't update vdc. " \
|
||||
" Reason: #{rc.message}").to_json]
|
||||
" Reason: #{rc.message}").to_json]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
############################################################################
|
||||
# Delete resources
|
||||
@ -218,12 +210,12 @@ class OzonesServer
|
||||
rc = vdc.destroy
|
||||
rescue => e
|
||||
return [404, OZones::Error.new("Error: Can not delete vdc. " \
|
||||
"Reason: #{e.message}").to_json]
|
||||
"Reason: #{e.message}").to_json]
|
||||
end
|
||||
|
||||
if !rc
|
||||
return [500, OZones::Error.new("Error: Couldn't delete " \
|
||||
"vdc #{id}").to_json]
|
||||
"vdc #{id}").to_json]
|
||||
else
|
||||
pr.update # Rewrite proxy conf file
|
||||
return [200, OZones.str_to_json("Vdc #{id} successfully deleted")]
|
||||
@ -236,13 +228,14 @@ class OzonesServer
|
||||
if zone
|
||||
rc = zone.destroy
|
||||
else
|
||||
return [404, OZones::Error.new("Error: Can not delete " \
|
||||
"zone. Reason: zone #{id} not found").to_json]
|
||||
return [404,
|
||||
OZones::Error.new("Error: Can not delete " \
|
||||
"zone. Reason: zone #{id} not found").to_json]
|
||||
end
|
||||
|
||||
if !rc
|
||||
return [500, OZones::Error.new("Error: Couldn't delete " \
|
||||
"zone #{id}").to_json]
|
||||
"zone #{id}").to_json]
|
||||
else
|
||||
pr.update # Rewrite proxy conf file
|
||||
return [200, OZones.str_to_json("Zone #{id} successfully deleted")]
|
||||
@ -253,15 +246,15 @@ class OzonesServer
|
||||
# Misc Helper Functions
|
||||
############################################################################
|
||||
private
|
||||
|
||||
|
||||
# Check if hosts are already include in any Vdc of the zone
|
||||
def host_uniqueness?(zone, host_list, vdc_id = -1)
|
||||
return true if host_list.empty?
|
||||
|
||||
|
||||
all_hosts = ""
|
||||
zone.vdcs.all.each{|vdc|
|
||||
if vdc.hosts != nil and !vdc.hosts.empty? and vdc.id != vdc_id
|
||||
all_hosts << ',' << vdc.hosts
|
||||
if vdc.HOSTS != nil and !vdc.HOSTS.empty? and vdc.id != vdc_id
|
||||
all_hosts << ',' << vdc.HOSTS
|
||||
end
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ if !ONE_LOCATION
|
||||
RUBY_LIB_LOCATION="/usr/lib/one/ruby"
|
||||
VAR_LOCATION="/var/lib/one"
|
||||
else
|
||||
ETC_LOCATION=ONE_LOCATION+"/etc"
|
||||
ETC_LOCATION=ONE_LOCATION+"/etc"
|
||||
LIB_LOCATION=ONE_LOCATION+"/lib"
|
||||
RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby"
|
||||
VAR_LOCATION=ONE_LOCATION+"/var"
|
||||
@ -62,7 +62,7 @@ db_url = db_type + "://" + VAR_LOCATION + "/ozones.db"
|
||||
##############################################################################
|
||||
# DB bootstrapping
|
||||
##############################################################################
|
||||
if config[:dbdebug]
|
||||
if config[:dbdebug]
|
||||
DataMapper::Logger.new($stdout, :debug)
|
||||
end
|
||||
|
||||
@ -76,22 +76,22 @@ DataMapper.auto_upgrade!
|
||||
|
||||
if Auth.all.size == 0
|
||||
if ENV['OZONES_AUTH'] && File.exist?(ENV['OZONES_AUTH'])
|
||||
credentials = IO.read(ENV['OZONES_AUTH']).strip.split(':')
|
||||
credentials = IO.read(ENV['OZONES_AUTH']).strip.split(':')
|
||||
|
||||
if credentials.length < 2
|
||||
warn "Authorization data malformed"
|
||||
exit -1
|
||||
end
|
||||
credentials[1] = Digest::SHA1.hexdigest(credentials[1])
|
||||
@auth=Auth.create({:name => credentials[0],
|
||||
:password => credentials[1]})
|
||||
@auth.save
|
||||
if credentials.length < 2
|
||||
warn "Authorization data malformed"
|
||||
exit -1
|
||||
end
|
||||
credentials[1] = Digest::SHA1.hexdigest(credentials[1])
|
||||
@auth=Auth.create({:name => credentials[0],
|
||||
:password => credentials[1]})
|
||||
@auth.save
|
||||
else
|
||||
warn "oZones admin credentials not set, missing OZONES_AUTH file."
|
||||
exit -1
|
||||
end
|
||||
else
|
||||
@auth=Auth.all.first
|
||||
@auth=Auth.all.first
|
||||
end
|
||||
|
||||
ADMIN_NAME = @auth.name
|
||||
@ -101,7 +101,7 @@ begin
|
||||
OZones::ProxyRules.new("apache",config[:htaccess])
|
||||
rescue Exception => e
|
||||
warn e.message
|
||||
exit -1
|
||||
exit -1
|
||||
end
|
||||
|
||||
|
||||
@ -122,12 +122,12 @@ helpers do
|
||||
if session[:ip] && session[:ip]==request.ip
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
auth = Rack::Auth::Basic::Request.new(request.env)
|
||||
if auth.provided? && auth.basic? && auth.credentials
|
||||
user = auth.credentials[0]
|
||||
sha1_pass = Digest::SHA1.hexdigest(auth.credentials[1])
|
||||
|
||||
|
||||
if user == ADMIN_NAME && sha1_pass == ADMIN_PASS
|
||||
return true
|
||||
end
|
||||
@ -140,7 +140,7 @@ helpers do
|
||||
if auth.provided? && auth.basic? && auth.credentials
|
||||
user = auth.credentials[0]
|
||||
sha1_pass = Digest::SHA1.hexdigest(auth.credentials[1])
|
||||
|
||||
|
||||
if user == ADMIN_NAME && sha1_pass == ADMIN_PASS
|
||||
session[:user] = user
|
||||
session[:password] = sha1_pass
|
||||
@ -170,8 +170,8 @@ end
|
||||
before do
|
||||
unless request.path=='/login' || request.path=='/'
|
||||
halt 401 unless authorized?
|
||||
|
||||
@OzonesServer = OzonesServer.new
|
||||
|
||||
@OzonesServer = OzonesServer.new
|
||||
@pr = OZones::ProxyRules.new("apache",config[:htaccess])
|
||||
end
|
||||
end
|
||||
@ -281,5 +281,3 @@ end
|
||||
delete '/zone/:id' do
|
||||
@OzonesServer.delete_zone(params[:id], @pr)
|
||||
end
|
||||
|
||||
|
||||
|
@ -416,7 +416,7 @@ function hostsListCB(req,list){
|
||||
return;
|
||||
};
|
||||
var host_json = oZones.Helper.pool("HOST",this.ZONE);
|
||||
updateHostsList(req, host_json,'#datatable_agg_hosts',this.ZONE.id,this.ZONE.name);
|
||||
updateHostsList(req, host_json,'#datatable_agg_hosts',this.ZONE.ID,this.ZONE.NAME);
|
||||
updateZonesDashboard("hosts",host_json);
|
||||
});
|
||||
}
|
||||
@ -429,7 +429,7 @@ function vmsListCB(req,list){
|
||||
return;
|
||||
};
|
||||
var vms_json = oZones.Helper.pool("VM",this.ZONE);
|
||||
updateVMsList(req, vms_json,'#datatable_agg_vms',this.ZONE.id,this.ZONE.name);
|
||||
updateVMsList(req, vms_json,'#datatable_agg_vms',this.ZONE.ID,this.ZONE.NAME);
|
||||
updateZonesDashboard("vms",vms_json);
|
||||
});
|
||||
}
|
||||
@ -442,7 +442,7 @@ function vnsListCB(req,list){
|
||||
return;
|
||||
};
|
||||
var vn_json = oZones.Helper.pool("VNET",this.ZONE);
|
||||
updateVNsList(req, vn_json,'#datatable_agg_vnets',this.ZONE.id,this.ZONE.name);
|
||||
updateVNsList(req, vn_json,'#datatable_agg_vnets',this.ZONE.ID,this.ZONE.NAME);
|
||||
updateZonesDashboard("vnets",vn_json);
|
||||
});
|
||||
}
|
||||
@ -455,7 +455,7 @@ function imagesListCB(req,list){
|
||||
return;
|
||||
};
|
||||
var image_json = oZones.Helper.pool("IMAGE",this.ZONE);
|
||||
updateImagesList(req,image_json,'#datatable_agg_images',this.ZONE.id,this.ZONE.name);
|
||||
updateImagesList(req,image_json,'#datatable_agg_images',this.ZONE.ID,this.ZONE.NAME);
|
||||
updateZonesDashboard("images",image_json);
|
||||
});
|
||||
}
|
||||
@ -468,7 +468,7 @@ function usersListCB(req,list){
|
||||
return;
|
||||
};
|
||||
var user_json = oZones.Helper.pool("USER",this.ZONE);
|
||||
updateUsersList(req,user_json,'#datatable_agg_users',this.ZONE.id,this.ZONE.name);
|
||||
updateUsersList(req,user_json,'#datatable_agg_users',this.ZONE.ID,this.ZONE.NAME);
|
||||
updateZonesDashboard("users",user_json);
|
||||
});
|
||||
}
|
||||
@ -481,7 +481,7 @@ function templatesListCB(req,list){
|
||||
return;
|
||||
};
|
||||
var template_json = oZones.Helper.pool("VMTEMPLATE",this.ZONE);
|
||||
updateTemplatesList(req,template_json,'#datatable_agg_templates',this.ZONE.id,this.ZONE.name);
|
||||
updateTemplatesList(req,template_json,'#datatable_agg_templates',this.ZONE.ID,this.ZONE.NAME);
|
||||
updateZonesDashboard("templates",template_json);
|
||||
});
|
||||
}
|
||||
|
@ -224,11 +224,11 @@ function vdcElementArray(vdc_json){
|
||||
var vdc = vdc_json.VDC;
|
||||
|
||||
return [
|
||||
'<input type="checkbox" id="vdc_'+vdc.id+'" name="selected_items" value="'+vdc.id+'"/>',
|
||||
vdc.id,
|
||||
vdc.name,
|
||||
vdc.zones_id,
|
||||
vdc.hosts ? vdc.hosts : "none"
|
||||
'<input type="checkbox" id="vdc_'+vdc.ID+'" name="selected_items" value="'+vdc.ID+'"/>',
|
||||
vdc.ID,
|
||||
vdc.NAME,
|
||||
vdc.ZONES_ID,
|
||||
vdc.HOSTS ? vdc.HOSTS : "none"
|
||||
];
|
||||
}
|
||||
|
||||
@ -253,7 +253,7 @@ function addVDCElement(req,vdc_json){
|
||||
}
|
||||
|
||||
function updateVDCElement(request, vdc_json){
|
||||
var id = vdc_json.VDC.id;
|
||||
var id = vdc_json.VDC.ID;
|
||||
var element = vdcElementArray(vdc_json);
|
||||
updateSingleElement(element,dataTable_vdcs,'#vdc_'+id);
|
||||
}
|
||||
@ -276,36 +276,36 @@ function updateVDCInfo(req,vdc_json){
|
||||
content :
|
||||
'<table id="info_vdc_table" class="info_table">\
|
||||
<thead>\
|
||||
<tr><th colspan="2">Virtual Data Center - '+vdc.name+'</th></tr>\
|
||||
<tr><th colspan="2">Virtual Data Center - '+vdc.NAME+'</th></tr>\
|
||||
</thead>\
|
||||
<tbody>\
|
||||
<tr>\
|
||||
<td class="key_td">ID</td>\
|
||||
<td class="value_td">'+vdc.id+'</td>\
|
||||
<td class="value_td">'+vdc.ID+'</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td class="key_td">Name</td>\
|
||||
<td class="value_td">'+vdc.name+'</td>\
|
||||
<td class="value_td">'+vdc.NAME+'</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td class="key_td">Zone ID</td>\
|
||||
<td class="value_td">'+vdc.zones_id+'</td>\
|
||||
<td class="value_td">'+vdc.ZONES_ID+'</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td class="key_td">Hosts</td>\
|
||||
<td class="value_td">'+(vdc.hosts? vdc.hosts : "none")+'</td>\
|
||||
<td class="value_td">'+(vdc.HOSTS? vdc.HOSTS : "none")+'</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td class="key_td">Admin name</td>\
|
||||
<td class="value_td">'+vdc.vdcadminname+'</td>\
|
||||
<td class="value_td">'+vdc.VDCADMINNAME+'</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td class="key_td">Group ID</td>\
|
||||
<td class="value_td">'+vdc.group_id+'</td>\
|
||||
<td class="value_td">'+vdc.GROUP_ID+'</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td class="key_td">ACLs</td>\
|
||||
<td class="value_td">'+vdc.acls+'</td>\
|
||||
<td class="value_td">'+vdc.ACLS+'</td>\
|
||||
</tr>\
|
||||
</tbody>\
|
||||
</table>'
|
||||
@ -461,16 +461,16 @@ function setupCreateVDCDialog(){
|
||||
};
|
||||
|
||||
var vdc_json = {
|
||||
"vdc" : {
|
||||
"name" : name,
|
||||
"zoneid" : zoneid,
|
||||
"vdcadminname" : vdcadminname,
|
||||
"vdcadminpass" : vdcadminpass,
|
||||
"force" : force
|
||||
"VDC" : {
|
||||
"NAME" : name,
|
||||
"ZONEID" : zoneid,
|
||||
"VDCADMINNAME" : vdcadminname,
|
||||
"VDCADMINPASS" : vdcadminpass,
|
||||
"FORCE" : force
|
||||
}
|
||||
};
|
||||
if (hosts.length){
|
||||
vdc_json["vdc"]["hosts"]=hosts;
|
||||
vdc_json["VDC"]["HOSTS"]=hosts;
|
||||
};
|
||||
|
||||
Sunstone.runAction("VDC.create",vdc_json);
|
||||
@ -549,15 +549,15 @@ function setupUpdateVDCDialog(){
|
||||
};
|
||||
|
||||
var vdc_json = {
|
||||
"vdc" : {
|
||||
"id": id,
|
||||
"force": force,
|
||||
"hosts": hosts
|
||||
"VDC" : {
|
||||
"ID": id,
|
||||
"FORCE": force,
|
||||
"HOSTS": ""
|
||||
}
|
||||
};
|
||||
|
||||
if (hosts.length){
|
||||
vdc_json["vdc"]["hosts"]=hosts;
|
||||
vdc_json["VDC"]["HOSTS"]=hosts;
|
||||
};
|
||||
Sunstone.runAction("VDC.update",id,vdc_json);
|
||||
dialog.dialog('close');
|
||||
|
@ -228,10 +228,10 @@ function zoneElementArray(zone_json){
|
||||
var zone = zone_json.ZONE;
|
||||
|
||||
return [
|
||||
'<input type="checkbox" id="zone_'+zone.id+'" name="selected_items" value="'+zone.id+'"/>',
|
||||
zone.id,
|
||||
zone.name,
|
||||
zone.endpoint
|
||||
'<input type="checkbox" id="zone_'+zone.ID+'" name="selected_items" value="'+zone.ID+'"/>',
|
||||
zone.ID,
|
||||
zone.NAME,
|
||||
zone.ENDPOINT
|
||||
];
|
||||
}
|
||||
|
||||
@ -281,32 +281,32 @@ function updateZoneInfo(req,zone_json){
|
||||
content :
|
||||
'<table id="info_zone_table" class="info_table">\
|
||||
<thead>\
|
||||
<tr><th colspan="2">Zone information - '+zone.name+'</th></tr>\
|
||||
<tr><th colspan="2">Zone information - '+zone.NAME+'</th></tr>\
|
||||
</thead>\
|
||||
<tbody>\
|
||||
<tr>\
|
||||
<td class="key_td">ID</td>\
|
||||
<td class="value_td">'+zone.id+'</td>\
|
||||
<td class="value_td">'+zone.ID+'</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td class="key_td">Administrator</td>\
|
||||
<td class="value_td">'+zone.onename+'</td>\
|
||||
<td class="value_td">'+zone.ONENAME+'</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td class="key_td">Password</td>\
|
||||
<td class="value_td">'+zone.onepass+'</td>\
|
||||
<td class="value_td">'+zone.ONEPASS+'</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td class="key_td">Endpoint</td>\
|
||||
<td class="value_td">'+zone.endpoint+'</td>\
|
||||
<td class="value_td">'+zone.ENDPOINT+'</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td class="key_td">Sunstone endpoint</td>\
|
||||
<td class="value_td"><a href="'+zone.sunsendpoint+'" target="_blank">'+zone.sunsendpoint+'<span class="ui-icon ui-icon-extlink" style="display:inline-block;" /></a></td>\
|
||||
<td class="value_td">'+ (zone.SUNSENDPOINT.length? '<a href="'+zone.SUNSENDPOINT+'" target="_blank">'+zone.SUNSENDPOINT+'<span class="ui-icon ui-icon-extlink" style="display:inline-block;" /></a>' : "") +'</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td class="key_td">#VDCs</td>\
|
||||
<td class="value_td">'+zone.vdcs.length+'</td>\
|
||||
<td class="value_td">'+zone.VDCS.length+'</td>\
|
||||
</tr>\
|
||||
</tbody>\
|
||||
</table>'
|
||||
@ -524,12 +524,12 @@ function updateZoneInfo(req,zone_json){
|
||||
/*End init dataTables*/
|
||||
|
||||
//Retrieve pools in the meantime
|
||||
Sunstone.runAction("Zone.host",zone.id);
|
||||
Sunstone.runAction("Zone.vmtemplate",zone.id);
|
||||
Sunstone.runAction("Zone.vms",zone.id);
|
||||
Sunstone.runAction("Zone.vnet",zone.id);
|
||||
Sunstone.runAction("Zone.image",zone.id);
|
||||
Sunstone.runAction("Zone.user",zone.id);
|
||||
Sunstone.runAction("Zone.host",zone.ID);
|
||||
Sunstone.runAction("Zone.vmtemplate",zone.ID);
|
||||
Sunstone.runAction("Zone.vms",zone.ID);
|
||||
Sunstone.runAction("Zone.vnet",zone.ID);
|
||||
Sunstone.runAction("Zone.image",zone.ID);
|
||||
Sunstone.runAction("Zone.user",zone.ID);
|
||||
}
|
||||
|
||||
|
||||
@ -559,12 +559,12 @@ function setupCreateZoneDialog(){
|
||||
}
|
||||
|
||||
var zone_json = {
|
||||
"zone": {
|
||||
"name": name,
|
||||
"endpoint": endpoint,
|
||||
"onename": onename,
|
||||
"onepass": onepass,
|
||||
"sunsendpoint" : sunsendpoint
|
||||
"ZONE": {
|
||||
"NAME": name,
|
||||
"ENDPOINT": endpoint,
|
||||
"ONENAME": onename,
|
||||
"ONEPASS": onepass,
|
||||
"SUNSENDPOINT" : sunsendpoint
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -84,7 +84,7 @@ int PoolObjectSQL::select(SqlDB *db, const string& _name, int _uid)
|
||||
set_callback(
|
||||
static_cast<Callbackable::Callback>(&PoolObjectSQL::select_cb));
|
||||
|
||||
oss << "SELECT body FROM " << table << " WHERE name = '" <<_name << "'";
|
||||
oss << "SELECT body FROM " << table << " WHERE name = '" << sql_name << "'";
|
||||
|
||||
if ( _uid != -1 )
|
||||
{
|
||||
|
@ -41,6 +41,22 @@ module OpenNebulaJSON
|
||||
end
|
||||
end
|
||||
|
||||
def parse_json_sym(json_str, root_element)
|
||||
begin
|
||||
parser = JSON.parser.new(json_str, {:symbolize_names => true})
|
||||
hash = parser.parse
|
||||
|
||||
if hash.has_key?(root_element)
|
||||
return hash[root_element]
|
||||
end
|
||||
|
||||
Error.new("Error parsing JSON:\ root element not present")
|
||||
|
||||
rescue => e
|
||||
Error.new(e.message)
|
||||
end
|
||||
end
|
||||
|
||||
def template_to_str(attributes, indent=true)
|
||||
if indent
|
||||
ind_enter="\n"
|
||||
|
@ -640,6 +640,12 @@ function setupConfirmDialogs(){
|
||||
//enhace the button look
|
||||
$('button',dialog).button();
|
||||
|
||||
//if a cancel button is pressed, we close the dialog.
|
||||
$('button.confirm_cancel',dialog).click(function(){
|
||||
$(this).parents('div:ui-dialog').dialog("close");
|
||||
return false;
|
||||
});
|
||||
|
||||
dialogs_context.append('<div id="confirm_with_select_dialog" title="Confirmation of action"></div>');
|
||||
dialog = $('div#confirm_with_select_dialog',dialogs_context);
|
||||
|
||||
|
@ -16,8 +16,6 @@
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
CONTEXT_FILE=$1
|
||||
|
||||
while (( "$#" )); do
|
||||
if [ "$#" == "1" ]; then
|
||||
DST=$1
|
||||
@ -58,12 +56,8 @@ for f in $SRC; do
|
||||
;;
|
||||
|
||||
*)
|
||||
if [ $SECURE_CONTEXT -eq 0 -o "$f" == "$CONTEXT_FILE" ]; then
|
||||
exec_and_log "cp -R $f $ISO_DIR" \
|
||||
"Error copying $f to $ISO_DIR"
|
||||
else
|
||||
log "not copying potentialy dangerous file $f"
|
||||
fi
|
||||
exec_and_log "cp -R $f $ISO_DIR" \
|
||||
"Error copying $f to $ISO_DIR"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
@ -71,4 +65,3 @@ done
|
||||
exec_and_log "$MKISOFS -o $TMP_DIR/$DST_FILE -J -R $ISO_DIR"
|
||||
exec_and_log "$SCP $TMP_DIR/$DST_FILE $DST"
|
||||
exec_and_log "rm -rf $TMP_DIR"
|
||||
|
||||
|
@ -22,10 +22,6 @@ VG_NAME=
|
||||
# Default size for logical volumes if not specified
|
||||
DEFAULT_LV_SIZE="1G"
|
||||
|
||||
# Set to 1 to disable adding files to context image other than context.sh
|
||||
# itself or http url's
|
||||
SECURE_CONTEXT=0
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Helper functions for the LVM plugin #
|
||||
# -------------------------------------------------------------------------- #
|
||||
|
@ -16,8 +16,6 @@
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
CONTEXT_FILE=$1
|
||||
|
||||
while (( "$#" )); do
|
||||
if [ "$#" == "1" ]; then
|
||||
DST=$1
|
||||
@ -27,7 +25,6 @@ while (( "$#" )); do
|
||||
shift
|
||||
done
|
||||
|
||||
|
||||
if [ -z "${ONE_LOCATION}" ]; then
|
||||
TMCOMMON=/usr/lib/one/mads/tm_common.sh
|
||||
else
|
||||
@ -55,12 +52,8 @@ for f in $SRC; do
|
||||
;;
|
||||
|
||||
*)
|
||||
if [ $SECURE_CONTEXT -eq 0 -o "$f" == "$CONTEXT_FILE" ]; then
|
||||
exec_and_log "cp -R $f $ISO_DIR" \
|
||||
"Error copying $f to $ISO_DIR"
|
||||
else
|
||||
log "not copying potentialy dangerous file $f"
|
||||
fi
|
||||
exec_and_log "cp -R $f $ISO_DIR" \
|
||||
"Error copying $f to $ISO_DIR"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
@ -69,5 +62,3 @@ exec_and_log "$MKISOFS -o $DST_PATH -J -R $ISO_DIR" \
|
||||
"Error creating iso fs"
|
||||
|
||||
exec_and_log "rm -rf $ISO_DIR"
|
||||
|
||||
|
||||
|
@ -13,7 +13,3 @@
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
# Set to 1 to disable adding files to context image other than context.sh
|
||||
# itself or http url's
|
||||
SECURE_CONTEXT=0
|
||||
|
@ -16,8 +16,6 @@
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
CONTEXT_FILE=$1
|
||||
|
||||
while (( "$#" )); do
|
||||
if [ "$#" == "1" ]; then
|
||||
DST=$1
|
||||
@ -60,12 +58,8 @@ for f in $SRC; do
|
||||
;;
|
||||
|
||||
*)
|
||||
if [ $SECURE_CONTEXT -eq 0 -o "$f" == "$CONTEXT_FILE" ]; then
|
||||
exec_and_log "cp -R $f $ISO_DIR" \
|
||||
"Error copying $f to $ISO_DIR"
|
||||
else
|
||||
log "not copying potentialy dangerous file $f"
|
||||
fi
|
||||
exec_and_log "cp -R $f $ISO_DIR" \
|
||||
"Error copying $f to $ISO_DIR"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
@ -76,4 +70,3 @@ exec_and_log "$SCP $TMP_DIR/$DST_FILE $DST" \
|
||||
"Error copying $TMP_DIR/$DST_FILE to $DST"
|
||||
exec_and_log "rm -rf $TMP_DIR" \
|
||||
"Error deleting $TMP_DIR"
|
||||
|
||||
|
@ -13,7 +13,3 @@
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
# Set to 1 to disable adding files to context image other than context.sh
|
||||
# itself or http url's
|
||||
SECURE_CONTEXT=0
|
||||
|
@ -40,7 +40,8 @@ source_files=[
|
||||
'vm_var_parser.c',
|
||||
'vm_var_syntax.cc',
|
||||
'VirtualMachinePool.cc',
|
||||
'VirtualMachineHook.cc'
|
||||
'VirtualMachineHook.cc',
|
||||
'VirtualMachineTemplate.cc'
|
||||
]
|
||||
|
||||
# Build library
|
||||
|
@ -185,13 +185,30 @@ int VirtualMachine::insert(SqlDB * db, string& error_str)
|
||||
string name;
|
||||
|
||||
SingleAttribute * attr;
|
||||
string aname;
|
||||
string value;
|
||||
ostringstream oss;
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------
|
||||
// Check template for restricted attributes
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
if ( gid != GroupPool::ONEADMIN_ID )
|
||||
{
|
||||
VirtualMachineTemplate *vt =
|
||||
static_cast<VirtualMachineTemplate *>(obj_template);
|
||||
|
||||
if (vt->check(aname))
|
||||
{
|
||||
goto error_restricted;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Set a name if the VM has not got one and VM_ID
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
oss << oid;
|
||||
value = oss.str();
|
||||
|
||||
@ -290,8 +307,14 @@ error_leases_rollback:
|
||||
release_network_leases();
|
||||
goto error_common;
|
||||
|
||||
error_restricted:
|
||||
oss << "VM Template includes a restricted attribute " << aname << ".";
|
||||
error_str = oss.str();
|
||||
goto error_common;
|
||||
|
||||
error_name_length:
|
||||
oss << "NAME is too long; max length is 128 chars.";
|
||||
error_str = oss.str();
|
||||
goto error_common;
|
||||
|
||||
error_common:
|
||||
|
84
src/vm/VirtualMachineTemplate.cc
Normal file
84
src/vm/VirtualMachineTemplate.cc
Normal file
@ -0,0 +1,84 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* 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. */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
#include "VirtualMachineTemplate.h"
|
||||
#include <vector>
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
const string VirtualMachineTemplate::RESTRICTED_ATTRIBUTES[] = {
|
||||
"CONTEXT/FILES",
|
||||
"DISK/SOURCE",
|
||||
"NIC/MAC"
|
||||
};
|
||||
|
||||
const int VirtualMachineTemplate::RS_ATTRS_LENGTH = 3;
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
bool VirtualMachineTemplate::check(string& rs_attr)
|
||||
{
|
||||
size_t pos;
|
||||
string avector, vattr;
|
||||
vector<const Attribute *> values;
|
||||
|
||||
for (int i=0; i < RS_ATTRS_LENGTH ;i++)
|
||||
{
|
||||
pos = RESTRICTED_ATTRIBUTES[i].find("/");
|
||||
|
||||
if (pos != string::npos) //Vector Attribute
|
||||
{
|
||||
int num;
|
||||
|
||||
avector = RESTRICTED_ATTRIBUTES[i].substr(0,pos);
|
||||
vattr = RESTRICTED_ATTRIBUTES[i].substr(pos+1);
|
||||
|
||||
if ((num = get(avector,values)) > 0 ) //Template contains the attr
|
||||
{
|
||||
const VectorAttribute * attr;
|
||||
|
||||
for (int j=0; j<num ; j++ )
|
||||
{
|
||||
attr = dynamic_cast<const VectorAttribute *>(values[j]);
|
||||
|
||||
if (attr == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( !attr->vector_value(vattr.c_str()).empty() )
|
||||
{
|
||||
rs_attr = RESTRICTED_ATTRIBUTES[i];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else //Single Attribute
|
||||
{
|
||||
if (get(avector,values) > 0 )
|
||||
{
|
||||
rs_attr = RESTRICTED_ATTRIBUTES[i];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user