1
0
mirror of https://github.com/OpenNebula/one.git synced 2024-12-25 23:21:29 +03:00

Merge branch 'feature-789'

This commit is contained in:
Ruben S. Montero 2011-10-22 00:37:16 +02:00
commit d37865d277
35 changed files with 1475 additions and 820 deletions

View File

@ -198,6 +198,7 @@ ETC_DIRS="$ETC_LOCATION/im_kvm \
LIB_DIRS="$LIB_LOCATION/ruby \ LIB_DIRS="$LIB_LOCATION/ruby \
$LIB_LOCATION/ruby/OpenNebula \ $LIB_LOCATION/ruby/OpenNebula \
$LIB_LOCATION/ruby/zona \
$LIB_LOCATION/ruby/cloud/ \ $LIB_LOCATION/ruby/cloud/ \
$LIB_LOCATION/ruby/cloud/econe \ $LIB_LOCATION/ruby/cloud/econe \
$LIB_LOCATION/ruby/cloud/econe/views \ $LIB_LOCATION/ruby/cloud/econe/views \
@ -272,7 +273,8 @@ OZONES_DIRS="$OZONES_LOCATION/lib \
OZONES_CLIENT_DIRS="$LIB_LOCATION/ruby \ OZONES_CLIENT_DIRS="$LIB_LOCATION/ruby \
$LIB_LOCATION/ruby/OpenNebula \ $LIB_LOCATION/ruby/OpenNebula \
$LIB_LOCATION/ruby/cli \ $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_ECO_CLIENT_DIRS="$LIB_LOCATION/ruby \
$LIB_LOCATION/ruby/OpenNebula \ $LIB_LOCATION/ruby/OpenNebula \
@ -370,10 +372,11 @@ INSTALL_CLIENT_FILES=(
CLI_LIB_FILES:$LIB_LOCATION/ruby/cli CLI_LIB_FILES:$LIB_LOCATION/ruby/cli
ONE_CLI_LIB_FILES:$LIB_LOCATION/ruby/cli/one_helper ONE_CLI_LIB_FILES:$LIB_LOCATION/ruby/cli/one_helper
ETC_CLIENT_FILES:$ETC_LOCATION ETC_CLIENT_FILES:$ETC_LOCATION
OZONES_LIB_CLIENT_FILES:$LIB_LOCATION/ruby
OZONES_BIN_CLIENT_FILES:$BIN_LOCATION OZONES_BIN_CLIENT_FILES:$BIN_LOCATION
OZONES_LIB_CLIENT_CLI_FILES:$LIB_LOCATION/ruby/cli OZONES_LIB_CLIENT_CLI_FILES:$LIB_LOCATION/ruby/cli
OZONES_LIB_CLIENT_CLI_HELPER_FILES:$LIB_LOCATION/ruby/cli/ozones_helper 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 CLI_CONF_FILES:$ETC_LOCATION/cli
OCA_LIB_FILES:$LIB_LOCATION/ruby OCA_LIB_FILES:$LIB_LOCATION/ruby
RUBY_OPENNEBULA_LIB_FILES:$LIB_LOCATION/ruby/OpenNebula RUBY_OPENNEBULA_LIB_FILES:$LIB_LOCATION/ruby/OpenNebula
@ -428,10 +431,11 @@ INSTALL_OZONES_FILES=(
OZONES_PUBLIC_IMAGES_FILES:$OZONES_LOCATION/public/images OZONES_PUBLIC_IMAGES_FILES:$OZONES_LOCATION/public/images
OZONES_PUBLIC_CSS_FILES:$OZONES_LOCATION/public/css OZONES_PUBLIC_CSS_FILES:$OZONES_LOCATION/public/css
OZONES_PUBLIC_JS_PLUGINS_FILES:$OZONES_LOCATION/public/js/plugins OZONES_PUBLIC_JS_PLUGINS_FILES:$OZONES_LOCATION/public/js/plugins
OZONES_LIB_CLIENT_FILES:$LIB_LOCATION/ruby
OZONES_BIN_CLIENT_FILES:$BIN_LOCATION OZONES_BIN_CLIENT_FILES:$BIN_LOCATION
OZONES_LIB_CLIENT_CLI_FILES:$LIB_LOCATION/ruby/cli OZONES_LIB_CLIENT_CLI_FILES:$LIB_LOCATION/ruby/cli
OZONES_LIB_CLIENT_CLI_HELPER_FILES:$LIB_LOCATION/ruby/cli/ozones_helper 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=( INSTALL_OZONES_ETC_FILES=(
@ -1056,6 +1060,16 @@ OZONES_LIB_ZONE_FILES="src/ozones/Server/lib/OZones/Zones.rb \
src/ozones/Server/lib/OZones/AggregatedImages.rb \ src/ozones/Server/lib/OZones/AggregatedImages.rb \
src/ozones/Server/lib/OZones/AggregatedTemplates.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_JQUERY=$SUNSTONE_PUBLIC_VENDOR_JQUERY
OZONES_PUBLIC_VENDOR_DATATABLES=$SUNSTONE_PUBLIC_VENDOR_DATATABLES OZONES_PUBLIC_VENDOR_DATATABLES=$SUNSTONE_PUBLIC_VENDOR_DATATABLES
@ -1091,8 +1105,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/aggregated-tab.js \
src/ozones/Server/public/js/plugins/dashboard-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_FILES="src/ozones/Client/lib/cli/ozones_helper.rb"
OZONES_LIB_CLIENT_CLI_HELPER_FILES="\ OZONES_LIB_CLIENT_CLI_HELPER_FILES="\

View File

@ -77,10 +77,7 @@ module OpenNebula
conf_file.scan(SINGLE_VARIABLE_REG) {|m| conf_file.scan(SINGLE_VARIABLE_REG) {|m|
key=m[0].strip.upcase key=m[0].strip.upcase
value=m[1].strip value=m[1].strip
# hack to skip multiline VM_TYPE values
next if %w{NAME TEMPLATE}.include? key.upcase
add_value(key, value) add_value(key, value)
} }

View File

@ -1,5 +1,21 @@
#!/usr/bin/env ruby #!/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"] ONE_LOCATION=ENV["ONE_LOCATION"]
if !ONE_LOCATION if !ONE_LOCATION
@ -17,14 +33,14 @@ require 'ozones_helper/vdc_helper.rb'
cmd=CommandParser::CmdParser.new(ARGV) do cmd=CommandParser::CmdParser.new(ARGV) do
usage "`onevdc` command [<args>] [<options>]" usage "`onevdc` command [<args>] [<options>]"
version OpenNebulaHelper::ONE_VERSION version OpenNebulaHelper::ONE_VERSION
set :format, :vdcid, "VDC ID" do |arg| set :format, :vdcid, "VDC ID" do |arg|
arg.match(/^[0123456789]+$/) ? [0,arg] : [-1] arg.match(/^[0123456789]+$/) ? [0,arg] : [-1]
end end
######################################################################## ########################################################################
# Global Options # Global Options
######################################################################## ########################################################################
set :option, CommandParser::OPTIONS set :option, CommandParser::OPTIONS
FORCE={ FORCE={
@ -36,35 +52,34 @@ cmd=CommandParser::CmdParser.new(ARGV) do
begin begin
helper = VDCHelper.new "vdc" helper = VDCHelper.new "vdc"
rescue Exception => e rescue Exception => e
warn e.message warn e.message
exit -1 exit -1
end end
command :create, 'Create a new VDC', :file, :options=>[FORCE] do command :create, 'Create a new VDC', :file, :options=>[FORCE] do
helper.create_resource(args[0], options) helper.create_resource(args[0], options)
end end
command :show, 'Show information of a particular VDC', :vdcid do command :show, 'Show information of a particular VDC', :vdcid do
helper.show_resource(args[0],options) helper.show_resource(args[0],options)
end end
command :list, 'Lists VDCs in the pool', command :list, 'Lists VDCs in the pool' do
:options=>CLIHelper::OPTIONS+OpenNebulaHelper::OPTIONS do
helper.list_pool(options) helper.list_pool(options)
end end
command :delete, 'Deletes a VDC', :vdcid do command :delete, 'Deletes a VDC', :vdcid do
helper.delete_resource(args[0],options) helper.delete_resource(args[0],options)
end end
command :addhost, 'Adds the set of hosts to the VDC', command :addhost, 'Adds the set of hosts to the VDC',
:vdcid, :range, :options=>[FORCE] do :vdcid, :range, :options=>[FORCE] do
helper.addhost(args[0], args[1], options) helper.addhost(args[0], args[1], options)
end end
command :delhost, 'Deletes the set of hosts from the VDC', 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) helper.delhost(args[0], args[1], options)
end end
end end

View File

@ -66,56 +66,55 @@ cmd=CommandParser::CmdParser.new(ARGV) do
zone=helper.show_resource(args[0],options)[1] zone=helper.show_resource(args[0],options)[1]
case args[1] case args[1]
when "host" when "host"
aux_helper = OneHostHelper.new( aux_helper = OneHostHelper.new(
zone['onename'] + ":" + zone['onepass'], zone[:ONENAME] + ":" + zone[:ONEPASS],
zone['endpoint'], zone[:ENDPOINT],
false) false)
aux_helper.list_pool(options) aux_helper.list_pool(options)
when "vm" when "vm"
aux_helper = OneVMHelper.new( aux_helper = OneVMHelper.new(
zone['onename'] + ":" + zone['onepass'], zone[:ONENAME] + ":" + zone[:ONEPASS],
zone['endpoint'], zone[:ENDPOINT],
false) false)
aux_helper.list_pool(options) aux_helper.list_pool(options)
when "image" when "image"
aux_helper = OneImageHelper.new( aux_helper = OneImageHelper.new(
zone['onename'] + ":" + zone['onepass'], zone[:ONENAME] + ":" + zone[:ONEPASS],
zone['endpoint'], zone[:ENDPOINT],
false) false)
aux_helper.list_pool(options) aux_helper.list_pool(options)
when "vn" when "vn"
aux_helper = OneVNetHelper.new( aux_helper = OneVNetHelper.new(
zone['onename'] + ":" + zone['onepass'], zone[:ONENAME] + ":" + zone[:ONEPASS],
zone['endpoint'], zone[:ENDPOINT],
false) false)
aux_helper.list_pool(options) aux_helper.list_pool(options)
when "template" when "template"
aux_helper = OneTemplateHelper.new( aux_helper = OneTemplateHelper.new(
zone['onename'] + ":" + zone['onepass'], zone[:ONENAME] + ":" + zone[:ONEPASS],
zone['endpoint'], zone[:ENDPOINT],
false) false)
aux_helper.list_pool(options) aux_helper.list_pool(options)
when "user" when "user"
aux_helper = OneUserHelper.new( aux_helper = OneUserHelper.new(
zone['onename'] + ":" + zone['onepass'], zone[:ONENAME] + ":" + zone[:ONEPASS],
zone['endpoint'], zone[:ENDPOINT],
false) false)
aux_helper.list_pool(options) aux_helper.list_pool(options)
end end
0 0
end end
command :list, 'Lists Zones in the pool', command :list, 'Lists Zones in the pool' do
:options=>CLIHelper::OPTIONS+OpenNebulaHelper::OPTIONS do
helper.list_pool(options) helper.list_pool(options)
end end

View File

@ -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

View File

@ -14,61 +14,61 @@
# limitations under the License. # # limitations under the License. #
#--------------------------------------------------------------------------- # #--------------------------------------------------------------------------- #
require 'OZonesClient' require 'zona'
module OZonesHelper module OZonesHelper
class OZHelper class OZHelper
def initialize(user=nil, pass=nil, endpoint_str=nil, def initialize(user=nil, pass=nil, endpoint_str=nil,
timeout=nil, debug_flag=true) timeout=nil, debug_flag=true)
@client = OZonesClient::Client.new(user, @client = Zona::Client.new(user,
pass, pass,
endpoint_str, endpoint_str,
timeout, timeout,
debug_flag) debug_flag)
end end
def create_resource(kind, template) def create_resource(kind, template)
rc = @client.post_resource(kind, template) rc = @client.post_resource_file(kind, template)
if OZonesClient::is_error?(rc) if Zona::is_error?(rc)
[-1, rc.message] [-1, rc.message]
else else
id = get_id(rc) id = get_id(rc)
[0, "ID: #{id}"] [0, "ID: #{id}"]
end end
end end
def list_pool(kind, options) def list_pool(kind, options)
rc = @client.get_pool(kind) rc = @client.get_pool(kind)
if OZonesClient::is_error?(rc) if Zona::is_error?(rc)
[-1, rc.message] [-1, rc.message]
else else
pool=OZonesClient::parse_json(rc.body, kind.upcase + "_POOL") pool=Zona::OZonesJSON.parse_json(rc.body, kind.upcase + "_POOL")
format_pool(pool, options) format_pool(pool, options)
end end
end end
def show_resource(kind, id, options) def show_resource(kind, id, options)
rc = @client.get_resource(kind, id) rc = @client.get_resource(kind, id)
if OZonesClient::is_error?(rc) if Zona::is_error?(rc)
[-1, rc.message] [-1, rc.message]
else else
resource=OZonesClient::parse_json(rc.body, kind.upcase) resource=Zona::OZonesJSON.parse_json(rc.body, kind.upcase)
format_resource(resource, options) format_resource(resource, options)
end end
end end
def delete_resource(kind, id, options) def delete_resource(kind, id, options)
rc = @client.delete_resource(kind, id) rc = @client.delete_resource(kind, id)
if OZonesClient::is_error?(rc) if Zona::is_error?(rc)
[-1, rc.message] [-1, rc.message]
else else
message=OZonesClient::parse_json(rc.body, "message") message=Zona::OZonesJSON.parse_json(rc.body, "message")
[0, "#{message}"] [0, "#{message}"]
end end
end end
@ -78,9 +78,9 @@ module OZonesHelper
def get_id(rc) def get_id(rc)
id = rc.body.match('\"id\":(.*)$')[1].strip id = rc.body.match('\"ID\":(.*)$')[1].strip
if id[-1..-1] == "," if id[-1..-1] == ","
id = id[0..id.size-2] id = id[0..id.size-2]
end end
return id return id

View File

@ -19,7 +19,7 @@ require 'cli/one_helper'
class VDCHelper < OZonesHelper::OZHelper class VDCHelper < OZonesHelper::OZHelper
def initialize(kind, user=nil, pass=nil, endpoint_str=nil, def initialize(kind, user=nil, pass=nil, endpoint_str=nil,
timeout=nil, debug_flag=true) timeout=nil, debug_flag=true)
@vdc_str = kind @vdc_str = kind
super(user, pass, endpoint_str, timeout, debug_flag) super(user, pass, endpoint_str, timeout, debug_flag)
end end
@ -33,8 +33,8 @@ class VDCHelper < OZonesHelper::OZHelper
rc = @client.post_resource_str(@vdc_str, tmpl_str) rc = @client.post_resource_str(@vdc_str, tmpl_str)
if OZonesClient::is_error?(rc) if Zona::is_error?(rc)
[-1, rc.message] [-1, rc.message]
else else
id = get_id(rc) id = get_id(rc)
[0, "ID: #{id}"] [0, "ID: #{id}"]
@ -48,7 +48,7 @@ class VDCHelper < OZonesHelper::OZHelper
def show_resource(id, options) def show_resource(id, options)
super(@vdc_str,id, options) super(@vdc_str,id, options)
end end
def delete_resource(id, options) def delete_resource(id, options)
super(@vdc_str,id, options) super(@vdc_str,id, options)
end end
@ -56,13 +56,13 @@ class VDCHelper < OZonesHelper::OZHelper
def addhost(id, host_array, options) def addhost(id, host_array, options)
rc = @client.get_resource(@vdc_str, id) rc = @client.get_resource(@vdc_str, id)
if OZonesClient::is_error?(rc) if Zona::is_error?(rc)
return [-1, rc.message] return [-1, rc.message]
else else
vdc = OZonesClient::parse_json(rc.body, @vdc_str.upcase) vdc = Zona::OZonesJSON.parse_json(rc.body, @vdc_str.upcase)
end end
hosts = vdc['hosts'].split(',').collect!{|x| x.to_i} hosts = vdc[:HOSTS].split(',').collect!{|x| x.to_i}
host_array.concat(hosts).uniq! host_array.concat(hosts).uniq!
new_host = host_array.join(',') new_host = host_array.join(',')
@ -72,37 +72,33 @@ class VDCHelper < OZonesHelper::OZHelper
template << "FORCE=YES\n" template << "FORCE=YES\n"
end end
rc = @client.put_resource(@vdc_str, id, template) rc = @client.put_resource_str(@vdc_str, id, template)
if OZonesClient::is_error?(rc) if Zona::is_error?(rc)
return [-1, rc.message] return [-1, rc.message]
end end
[0, ""] [0, ""]
end end
def delhost(id, host_array, options) def delhost(id, host_array, options)
rc = @client.get_resource(@vdc_str, id) rc = @client.get_resource(@vdc_str, id)
if OZonesClient::is_error?(rc) if Zona::is_error?(rc)
return [-1, rc.message] return [-1, rc.message]
else else
vdc = OZonesClient::parse_json(rc.body, @vdc_str.upcase) vdc = Zona::OZonesJSON.parse_json(rc.body, @vdc_str.upcase)
end 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(',') new_host = (hosts - host_array).join(',')
template = "ID=#{id}\nHOSTS=#{new_host}\n" template = "ID=#{id}\nHOSTS=#{new_host}\n"
if options[:force] rc = @client.put_resource_str(@vdc_str, id, template)
template << "FORCE=YES\n"
end
rc = @client.put_resource(@vdc_str, id, template) if Zona.is_error?(rc)
return [-1, rc.message]
if OZonesClient::is_error?(rc)
return [-1, rc.message]
end end
[0, ""] [0, ""]
@ -113,39 +109,39 @@ class VDCHelper < OZonesHelper::OZHelper
def format_resource(vdc, options) def format_resource(vdc, options)
str_h1="%-60s" str_h1="%-60s"
str="%-10s: %-20s" str="%-10s: %-20s"
CLIHelper.print_header(str_h1 % ["VDC #{vdc['name']} INFORMATION"]) CLIHelper.print_header(str_h1 % ["VDC #{vdc['name']} INFORMATION"])
puts str % ["ID ", vdc['id'].to_s] puts str % ["ID ", vdc[:ID].to_s]
puts str % ["NAME ", vdc['name'].to_s] puts str % ["NAME ", vdc[:NAME].to_s]
puts str % ["GROUP_ID ", vdc['group_id'].to_s] puts str % ["GROUP_ID ", vdc[:GROUP_ID].to_s]
puts str % ["ZONEID ", vdc['zones_id'].to_s] puts str % ["ZONEID ", vdc[:ZONES_ID].to_s]
puts str % ["VDCADMIN ", vdc['vdcadminname'].to_s] puts str % ["VDCADMIN ", vdc[:VDCADMINNAME].to_s]
puts str % ["HOST IDs ", vdc['hosts'].to_s] puts str % ["HOST IDs ", vdc[:HOSTS].to_s]
puts puts
return 0 return 0
end end
def format_pool(pool, options) def format_pool(pool, options)
st=CLIHelper::ShowTable.new(nil) do st=CLIHelper::ShowTable.new(nil) do
column :ID, "Identifier for VDC", :size=>4 do |d,e| column :ID, "Identifier for VDC", :size=>4 do |d,e|
d["id"] d[:ID]
end end
column :NAME, "Name of the VDC", :right, :size=>15 do |d,e| column :NAME, "Name of the VDC", :right, :size=>15 do |d,e|
d["name"] d[:NAME]
end end
column :ZONEID, "Id of the Zone where it belongs", column :ZONEID, "Id of the Zone where it belongs",
:right, :size=>40 do |d,e| :right, :size=>40 do |d,e|
d["zones_id"] d[:ZONES_ID]
end end
default :ID, :NAME, :ZONEID default :ID, :NAME, :ZONEID
end end
st.show(pool[@vdc_str.upcase], options) st.show(pool[:VDC], options)
return 0 return 0
end end
end end

View File

@ -9,13 +9,13 @@ require 'cli/one_helper/oneuser_helper'
class ZonesHelper < OZonesHelper::OZHelper class ZonesHelper < OZonesHelper::OZHelper
def initialize(kind, user=nil, pass=nil, endpoint_str=nil, def initialize(kind, user=nil, pass=nil, endpoint_str=nil,
timeout=nil, debug_flag=true) timeout=nil, debug_flag=true)
@zone_str = kind @zone_str = kind
super(user, pass, endpoint_str, timeout, debug_flag) super(user, pass, endpoint_str, timeout, debug_flag)
end end
def create_resource(template) def create_resource(template)
super(@zone_str,template) super(@zone_str,template)
end end
def list_pool(options) def list_pool(options)
@ -25,68 +25,68 @@ class ZonesHelper < OZonesHelper::OZHelper
def show_resource(id, options) def show_resource(id, options)
super(@zone_str,id, options) super(@zone_str,id, options)
end end
def delete_resource(id, options) def delete_resource(id, options)
super(@zone_str,id, options) super(@zone_str,id, options)
end end
private private
def format_resource(zone, options) def format_resource(zone, options)
str_h1="%-61s" str_h1="%-61s"
str="%-15s: %-20s" str="%-15s: %-20s"
CLIHelper.print_header(str_h1 % ["ZONE #{zone['name']} INFORMATION"]) CLIHelper.print_header(str_h1 % ["ZONE #{zone[:NAME]} INFORMATION"])
puts str % ["ID ", zone['id'].to_s] puts str % ["ID ", zone[:ID].to_s]
puts str % ["NAME ", zone['name'].to_s] puts str % ["NAME ", zone[:NAME].to_s]
puts str % ["ZONE ADMIN ",zone['onename'].to_s] puts str % ["ZONE ADMIN ",zone[:ONENAME].to_s]
puts str % ["ZONE PASS ", zone['onepass'].to_s] puts str % ["ZONE PASS ", zone[:ONEPASS].to_s]
puts str % ["ENDPOINT ", zone['endpoint'].to_s] puts str % ["ENDPOINT ", zone[:ENDPOINT].to_s]
puts str % ["# VDCS ", zone['vdcs'].size.to_s] puts str % ["# VDCS ", zone[:VDCS].size.to_s]
puts puts
if zone['vdcs'].size == 0 if zone[:VDCS].size == 0
return [0, zone] return [0, zone]
end end
CLIHelper.print_header(str_h1 % ["VDCS INFORMATION"]) 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| column :ID, "Identifier for VDC", :size=>4 do |d,e|
d["id"] d[:ID]
end end
column :NAME, "Name of the VDC", :right, :size=>15 do |d,e| column :NAME, "Name of the VDC", :right, :size=>15 do |d,e|
d["name"] d[:NAME]
end end
default :ID, :NAME default :ID, :NAME
end end
st.show(zone["vdcs"], options) st.show(zone[:VDCS], options)
return [0, zone] return [0, zone]
end end
def format_pool(pool, options) def format_pool(pool, options)
st=CLIHelper::ShowTable.new(nil) do st=CLIHelper::ShowTable.new(nil) do
column :ID, "Identifier for Zone", :size=>4 do |d,e| column :ID, "Identifier for Zone", :size=>4 do |d,e|
d["id"] d[:ID]
end end
column :NAME, "Name of the Zone", :right, :size=>15 do |d,e| column :NAME, "Name of the Zone", :right, :size=>15 do |d,e|
d["name"] d[:NAME]
end end
column :ENDPOINT, "Endpoint of the Zone", :right, :size=>40 do |d,e| column :ENDPOINT, "Endpoint of the Zone", :right, :size=>40 do |d,e|
d["endpoint"] d[:ENDPOINT]
end end
default :ID, :NAME, :ENDPOINT default :ID, :NAME, :ENDPOINT
end end
st.show(pool[@zone_str.upcase], options) st.show(pool[:ZONE], options)
return 0 return 0
end end
end end

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View File

@ -46,7 +46,7 @@ module OZones
def to_str def to_str
@message @message
end end
def to_json def to_json
message = { :message => @message } message = { :message => @message }
error_hash = { :error => message } error_hash = { :error => message }
@ -54,7 +54,7 @@ module OZones
return JSON.pretty_generate error_hash return JSON.pretty_generate error_hash
end end
end end
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
# Returns true if the object returned by a method of the OZones # Returns true if the object returned by a method of the OZones
# library is an Error # library is an Error
@ -62,10 +62,8 @@ module OZones
def self.is_error?(value) def self.is_error?(value)
value.class==OZones::Error value.class==OZones::Error
end end
def self.str_to_json(str) def self.str_to_json(str)
return JSON.pretty_generate({:message => str}) return JSON.pretty_generate({:message => str})
end end
end end

View File

@ -15,16 +15,16 @@
#--------------------------------------------------------------------------- # #--------------------------------------------------------------------------- #
module OZones module OZones
class AggregatedHosts < AggregatedPool class AggregatedHosts < AggregatedPool
def initialize def initialize
super("ZONE_POOL") super("ZONE_POOL")
end end
def factory(client) def factory(client)
OpenNebulaJSON::HostPoolJSON.new(client) OpenNebulaJSON::HostPoolJSON.new(client)
end end
end end
end end

View File

@ -15,16 +15,16 @@
#--------------------------------------------------------------------------- # #--------------------------------------------------------------------------- #
module OZones module OZones
class AggregatedImages < AggregatedPool class AggregatedImages < AggregatedPool
def initialize def initialize
super("ZONE_POOL") super("ZONE_POOL")
end end
def factory(client) def factory(client)
OpenNebulaJSON::ImagePoolJSON.new(client) OpenNebulaJSON::ImagePoolJSON.new(client)
end end
end end
end end

View File

@ -15,54 +15,54 @@
#--------------------------------------------------------------------------- # #--------------------------------------------------------------------------- #
module OZones module OZones
class AggregatedPool class AggregatedPool
include OpenNebulaJSON::JSONUtils include OpenNebulaJSON::JSONUtils
def initialize(tag) def initialize(tag)
@tag = tag @tag = tag
end end
def info def info
@sup_aggregated_pool = Hash.new @sup_aggregated_pool = Hash.new
@sup_aggregated_pool[@tag] = Hash.new @sup_aggregated_pool[@tag] = Hash.new
@sup_aggregated_pool[@tag]["ZONE"] = Array.new @sup_aggregated_pool[@tag]["ZONE"] = Array.new
OZones::Zones.all.each{|zone| OZones::Zones.all.each{|zone|
zone_pool_hash = Hash.new zone_pool_hash = Hash.new
zone_pool_hash = zone.to_hash["ZONE"] zone_pool_hash = zone.to_hash["ZONE"]
client = OpenNebula::Client.new( client = OpenNebula::Client.new(
zone.onename + ":" + zone.onepass, zone.ONENAME + ":" + zone.ONEPASS,
zone.endpoint, zone.ENDPOINT,
false) false)
pool = factory(client) pool = factory(client)
if OpenNebula.is_error?(pool) if OpenNebula.is_error?(pool)
zone_pool_hash.merge!(pool.to_hash) zone_pool_hash.merge!(pool.to_hash)
next next
end end
rc = pool.info rc = pool.info
if !rc if !rc
zone_pool_hash.merge!(pool.to_hash) zone_pool_hash.merge!(pool.to_hash)
else else
zone_pool_hash.merge!(rc.to_hash) zone_pool_hash.merge!(rc.to_hash)
end end
@sup_aggregated_pool[@tag]["ZONE"] << zone_pool_hash @sup_aggregated_pool[@tag]["ZONE"] << zone_pool_hash
} }
end end
def to_hash def to_hash
info info
return @sup_aggregated_pool return @sup_aggregated_pool
end end
end end
end end

View File

@ -15,16 +15,16 @@
#--------------------------------------------------------------------------- # #--------------------------------------------------------------------------- #
module OZones module OZones
class AggregatedTemplates < AggregatedPool class AggregatedTemplates < AggregatedPool
def initialize def initialize
super("ZONE_POOL") super("ZONE_POOL")
end end
def factory(client) def factory(client)
OpenNebulaJSON::TemplatePoolJSON.new(client) OpenNebulaJSON::TemplatePoolJSON.new(client)
end end
end end
end end

View File

@ -15,16 +15,16 @@
#--------------------------------------------------------------------------- # #--------------------------------------------------------------------------- #
module OZones module OZones
class AggregatedUsers < AggregatedPool class AggregatedUsers < AggregatedPool
def initialize def initialize
super("ZONE_POOL") super("ZONE_POOL")
end end
def factory(client) def factory(client)
OpenNebulaJSON::UserPoolJSON.new(client) OpenNebulaJSON::UserPoolJSON.new(client)
end end
end end
end end

View File

@ -15,16 +15,16 @@
#--------------------------------------------------------------------------- # #--------------------------------------------------------------------------- #
module OZones module OZones
class AggregatedVirtualMachines < AggregatedPool class AggregatedVirtualMachines < AggregatedPool
def initialize def initialize
super("ZONE_POOL") super("ZONE_POOL")
end end
def factory(client) def factory(client)
OpenNebulaJSON::VirtualMachinePoolJSON.new(client) OpenNebulaJSON::VirtualMachinePoolJSON.new(client)
end end
end end
end end

View File

@ -15,16 +15,16 @@
#--------------------------------------------------------------------------- # #--------------------------------------------------------------------------- #
module OZones module OZones
class AggregatedVirtualNetworks < AggregatedPool class AggregatedVirtualNetworks < AggregatedPool
def initialize def initialize
super("ZONE_POOL") super("ZONE_POOL")
end end
def factory(client) def factory(client)
OpenNebulaJSON::VirtualNetworkPoolJSON.new(client) OpenNebulaJSON::VirtualNetworkPoolJSON.new(client)
end end
end end
end end

View File

@ -15,33 +15,33 @@
#--------------------------------------------------------------------------- # #--------------------------------------------------------------------------- #
module OZones module OZones
class ApacheWritter class ApacheWritter
def initialize(file_path) def initialize(file_path)
@file_path = file_path @file_path = file_path
end end
def update def update
htaccess = "RewriteEngine On\n" htaccess = "RewriteEngine On\n"
OZones::Zones.all.each{|zone| OZones::Zones.all.each{|zone|
zone.vdcs.all.each{|vdc| zone.vdcs.all.each{|vdc|
htaccess << "RewriteRule ^#{vdc.name} " + htaccess << "RewriteRule ^#{vdc.NAME} " +
"#{zone.endpoint} [P]\n" "#{zone.ENDPOINT} [P]\n"
if zone.sunsendpoint != nil if zone.SUNSENDPOINT != nil
htaccess << "RewriteRule ^sunstone_#{vdc.name}/(.+) " + htaccess << "RewriteRule ^sunstone_#{vdc.NAME}/(.+) " +
"#{zone.sunsendpoint}/$1 [P]\n" "#{zone.SUNSENDPOINT}/$1 [P]\n"
htaccess << "RewriteRule ^sunstone_#{vdc.name} " + htaccess << "RewriteRule ^sunstone_#{vdc.NAME} " +
"#{zone.sunsendpoint}/ [P]\n" "#{zone.SUNSENDPOINT}/ [P]\n"
end end
} }
} }
File.open(@file_path, 'w') {|f| File.open(@file_path, 'w') {|f|
f.flock(File::LOCK_EX) f.flock(File::LOCK_EX)
f.write(htaccess) f.write(htaccess)
} }
end end
end end
end end

View File

@ -15,34 +15,34 @@
#--------------------------------------------------------------------------- # #--------------------------------------------------------------------------- #
module OZones module OZones
class ProxyRules class ProxyRules
def initialize(type, file_path) def initialize(type, file_path)
@type = type @type = type
if file_path if file_path
@file_path = file_path @file_path = file_path
else else
if !ENV["ONE_LOCATION"] if !ENV["ONE_LOCATION"]
@file_path="/var/lib/one/.htaccess" @file_path="/var/lib/one/.htaccess"
else else
@file_path=ENV["ONE_LOCATION"]+"/var/.htaccess" @file_path=ENV["ONE_LOCATION"]+"/var/.htaccess"
end end
end end
# Let's check for file permissions # Let's check for file permissions
if !File.writable?(@file_path) and if !File.writable?(@file_path) and
!File.writable?(File.dirname(@file_path)) !File.writable?(File.dirname(@file_path))
raise "#{@file_path} is not writable" raise "#{@file_path} is not writable"
end end
end end
def update def update
case @type case @type
when "apache" when "apache"
apWritter = OZones::ApacheWritter.new @file_path apWritter = OZones::ApacheWritter.new @file_path
apWritter.update apWritter.update
end end
end end
end end
end end

View File

@ -15,35 +15,48 @@
#--------------------------------------------------------------------------- # #--------------------------------------------------------------------------- #
module OZones module OZones
class Vdc class Vdc
include DataMapper::Resource include DataMapper::Resource
include OpenNebulaJSON::JSONUtils include OpenNebulaJSON::JSONUtils
extend OpenNebulaJSON::JSONUtils extend OpenNebulaJSON::JSONUtils
property :id, Serial property :ID, Serial
property :name, String, :required => true, :unique => true property :NAME, String, :required => true, :unique => true
property :group_id, Integer property :GROUP_ID, Integer
property :vdcadminname, String, :required => true property :VDCADMINNAME, String, :required => true
property :vdcadmin_id, Integer property :VDCADMIN_ID, Integer
property :acls, String property :ACLS, String
property :hosts, String property :HOSTS, String
belongs_to :zones belongs_to :zones
def self.to_hash def self.to_hash
zonePoolHash = Hash.new zonePoolHash = Hash.new
zonePoolHash["VDC_POOL"] = Hash.new zonePoolHash["VDC_POOL"] = Hash.new
zonePoolHash["VDC_POOL"]["VDC"] = Array.new unless self.all.empty? zonePoolHash["VDC_POOL"]["VDC"] = Array.new unless self.all.empty?
self.all.each{|vdc| 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 return zonePoolHash
end end
def to_hash def to_hash
vdc_attributes = Hash.new 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 return vdc_attributes
end end
end end
@ -51,36 +64,36 @@ module OZones
########################################################################### ###########################################################################
# This class represents a VDC able to interact with its supporting # This class represents a VDC able to interact with its supporting
# OpenNebula installation through OCA. Data persistence is provided by a # OpenNebula installation through OCA. Data persistence is provided by a
# Vdc class # Vdc class
########################################################################### ###########################################################################
class OpenNebulaVdc class OpenNebulaVdc
####################################################################### #######################################################################
# Constants # Constants
####################################################################### #######################################################################
VDC_ATTRS = [:vdcadminname, :vdcadminpass, :name, :hosts] VDC_ATTRS = [:VDCADMINNAME, :VDCADMINPASS, :NAME, :HOSTS]
attr_reader :vdc attr_reader :vdc
attr_reader :zone attr_reader :zone
#Creates an OpenNebula VDC, using its ID, vdcid and the associated zone #Creates an OpenNebula VDC, using its ID, vdcid and the associated zone
def initialize(vdcid, zone = nil) def initialize(vdcid, zone = nil)
if vdcid != -1 if vdcid != -1
@vdc = Vdc.get(vdcid) @vdc = Vdc.get(vdcid)
if !@vdc if !@vdc
raise "VDC with id #{vdcid} not found." raise "VDC with id #{vdcid} not found."
end end
@zone = OZones::Zones.get(@vdc.zones_id) @zone = OZones::Zones.get(@vdc.zones_ID)
else else
@zone = zone @zone = zone
end end
@client = OpenNebula::Client.new( @client = OpenNebula::Client.new(
"#{@zone.onename}:#{@zone.onepass}", "#{@zone.ONENAME}:#{@zone.ONEPASS}",
@zone.endpoint, @zone.ENDPOINT,
false) false)
end end
def to_json def to_json
@ -95,31 +108,31 @@ module OZones
VDC_ATTRS.each { |param| VDC_ATTRS.each { |param|
if !vdc_data[param] if !vdc_data[param]
return OZones::Error.new("Error: Couldn't create vdc." \ return OZones::Error.new("Error: Couldn't create vdc." \
"Mandatory attribute '#{param}' is missing.") "Mandatory attribute '#{param}' is missing.")
end end
} }
#Create a vdc record #Create a vdc record
@vdc = Vdc.new @vdc = Vdc.new
vdcpass = Digest::SHA1.hexdigest(vdc_data.delete(:vdcadminpass)) vdcpass = Digest::SHA1.hexdigest(vdc_data.delete(:VDCADMINPASS))
@vdc.attributes = vdc_data @vdc.attributes = vdc_data
# Create a group in the zone with the VDC name # Create a group in the zone with the VDC name
group = OpenNebula::Group.new(OpenNebula::Group.build_xml, @client) 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) 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 # Create the VDC admin user in the Zone
user = OpenNebula::User.new(OpenNebula::User.build_xml, @client) 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) 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 # Change primary group of the admin user to the VDC group
rc = user.chgrp(group.id) rc = user.chgrp(group.id)
@ -132,7 +145,7 @@ module OZones
rc, acls_str = create_acls(rules) rc, acls_str = create_acls(rules)
return rollback(group, user,acls_str,rc) if OpenNebula.is_error?(rc) return rollback(group, user,acls_str,rc) if OpenNebula.is_error?(rc)
@vdc.acls = acls_str @vdc.ACLS = acls_str
return true return true
end end
@ -150,13 +163,13 @@ module OZones
up.info up.info
up.each{|user| up.each{|user|
if user['GID'].to_i == @vdc.group_id if user['GID'].to_i == @vdc.GROUP_ID
user.delete user.delete
end end
} }
# Delete the group # 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 return @vdc.destroy
end end
@ -165,18 +178,18 @@ module OZones
def clean_bootstrap def clean_bootstrap
delete_acls delete_acls
OpenNebula::User.new_with_id(@vdc.vdcadmin_id, @client).delete OpenNebula::User.new_with_id(@vdc.VDCADMIN_ID, @client).delete
OpenNebula::Group.new_with_id(@vdc.group_id, @client).delete OpenNebula::Group.new_with_id(@vdc.GROUP_ID, @client).delete
end end
def update(host_list) def update(host_list)
# Delete existing host ACLs # Delete existing host ACLs
delete_host_acls delete_host_acls
if @vdc.acls =~ /((\d+,){#{HOST_ACL_FIRST_ID}}).*/ if @vdc.ACLS =~ /((\d+,){#{HOST_ACL_FIRST_ID}}).*/
newacls = $1.chop newacls = $1.chop
else else
newacls = @vdc.acls.clone newacls = @vdc.ACLS.clone
end end
# Create new ACLs. TODO Rollback ACL creation # Create new ACLs. TODO Rollback ACL creation
@ -184,7 +197,7 @@ module OZones
host_acls = get_host_acls(host_list) host_acls = get_host_acls(host_list)
rc, acls_str = create_acls(host_acls) 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. #Create the new acl string.
newacls << "," << acls_str newacls << "," << acls_str
@ -194,15 +207,15 @@ module OZones
#Update the VDC Record #Update the VDC Record
begin begin
@vdc.raise_on_save_failure = true @vdc.raise_on_save_failure = true
@vdc.hosts = host_list @vdc.HOSTS = host_list
@vdc.acls = newacls @vdc.ACLS = newacls
@vdc.save @vdc.save
rescue => e rescue => e
return OpenNebula::Error.new(e.message) return OpenNebula::Error.new(e.message)
end end
return @vdc.to_json return @vdc.to_json
end end
private private
@ -212,19 +225,19 @@ module OZones
# The ID of the first host ACL # The ID of the first host ACL
HOST_ACL_FIRST_ID = 3 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 # in the target zone
def get_acls def get_acls
rule_str = Array.new rule_str = Array.new
# Grant permissions to the group # Grant permissions to the group
rule_str << "@#{@vdc.group_id} VM+NET+IMAGE+TEMPLATE/* " \ rule_str << "@#{@vdc.GROUP_ID} VM+NET+IMAGE+TEMPLATE/* " \
"CREATE+INFO_POOL_MINE" "CREATE+INFO_POOL_MINE"
# Grant permissions to the vdc admin # Grant permissions to the vdc admin
rule_str << "##{@vdc.vdcadmin_id} USER/* CREATE" rule_str << "##{@vdc.VDCADMIN_ID} USER/* CREATE"
rule_str << "##{@vdc.vdcadmin_id} USER/@#{@vdc.group_id} " \ rule_str << "##{@vdc.VDCADMIN_ID} USER/@#{@vdc.GROUP_ID} " \
"MANAGE+DELETE+INFO" "MANAGE+DELETE+INFO"
############################################################### ###############################################################
#When more rules are added the class constant HOST_ACL_FIRST_ID #When more rules are added the class constant HOST_ACL_FIRST_ID
@ -238,13 +251,13 @@ module OZones
rule_str = Array.new rule_str = Array.new
if host_list == nil if host_list == nil
host_list = @vdc.hosts host_list = @vdc.HOSTS
end end
# Grant permissions to use the vdc hosts # Grant permissions to use the vdc hosts
host_list.split(',').each{|hostid| host_list.split(',').each{|hostid|
rule_str << "@#{@vdc.group_id} HOST/##{hostid} USE" rule_str << "@#{@vdc.GROUP_ID} HOST/##{hostid} USE"
} }
return rule_str return rule_str
end end
@ -254,7 +267,7 @@ module OZones
####################################################################### #######################################################################
# Deletes ACLs for the hosts # Deletes ACLs for the hosts
def delete_host_acls 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 if host_acls
host_acls.each{|acl| host_acls.each{|acl|
@ -263,50 +276,50 @@ module OZones
end end
end end
# Delete ACLs # Delete ACLs
def 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 OpenNebula::Acl.new_with_id(acl.to_i, @client).delete
} }
end end
# Deletes images # Deletes images
def delete_images def delete_images
ip = OpenNebula::ImagePool.new(@client) ip = OpenNebula::ImagePool.new(@client)
ip.info ip.info
ip.each{|image| ip.each{|image|
image.delete if image['GID'].to_i == @vdc.group_id image.delete if image['GID'].to_i == @vdc.GROUP_ID
} }
end end
# Deletes templates # Deletes templates
def delete_templates def delete_templates
tp = OpenNebula::TemplatePool.new(@client) tp = OpenNebula::TemplatePool.new(@client)
tp.info tp.info
tp.each{|template| tp.each{|template|
template.delete if template['GID'].to_i == @vdc.group_id template.delete if template['GID'].to_i == @vdc.GROUP_ID
} }
end end
# Deletes VMs # Deletes VMs
def delete_vms def delete_vms
vmp = OpenNebula::VirtualMachinePool.new(@client) vmp = OpenNebula::VirtualMachinePool.new(@client)
vmp.info vmp.info
vmp.each{|vm| vmp.each{|vm|
vm.delete if vm['GID'].to_i == @vdc.group_id vm.delete if vm['GID'].to_i == @vdc.GROUP_ID
} }
end end
# Deletes VNs # Deletes VNs
def delete_vns def delete_vns
vnp = OpenNebula::VirtualNetworkPool.new(@client) vnp = OpenNebula::VirtualNetworkPool.new(@client)
vnp.info vnp.info
vnp.each{|vn| vnp.each{|vn|
vnp.delete if vn['GID'].to_i == @vdc.group_id vnp.delete if vn['GID'].to_i == @vdc.GROUP_ID
} }
end end
@ -318,13 +331,13 @@ module OZones
def rollback(group, user, acls, rc) def rollback(group, user, acls, rc)
group.delete group.delete
user.delete if user user.delete if user
if acls if acls
acls.chop acls.chop
acls.split(",").each{|acl| acls.split(",").each{|acl|
OpenNebula::Acl.new_with_id(acl.to_i, @client).delete OpenNebula::Acl.new_with_id(acl.to_i, @client).delete
} }
end end
return rc return rc
end end
@ -340,7 +353,7 @@ module OZones
rc = acl.allocate(*OpenNebula::Acl.parse_rule(rule)) rc = acl.allocate(*OpenNebula::Acl.parse_rule(rule))
break if OpenNebula.is_error?(rc) break if OpenNebula.is_error?(rc)
acls_str << acl.id.to_s << "," acls_str << acl.id.to_s << ","
} }

View File

@ -15,28 +15,28 @@
#--------------------------------------------------------------------------- # #--------------------------------------------------------------------------- #
module OZones module OZones
class Zones class Zones
include DataMapper::Resource include DataMapper::Resource
include OpenNebulaJSON::JSONUtils include OpenNebulaJSON::JSONUtils
extend OpenNebulaJSON::JSONUtils extend OpenNebulaJSON::JSONUtils
####################################################################### #######################################################################
# Data Model for the Zone # Data Model for the Zone
####################################################################### #######################################################################
property :id, Serial property :ID, Serial
property :name, String, :required => true, :unique => true property :NAME, String, :required => true, :unique => true
property :onename, String, :required => true property :ONENAME, String, :required => true
property :onepass, String, :required => true property :ONEPASS, String, :required => true
property :endpoint, String, :required => true property :ENDPOINT, String, :required => true
property :sunsendpoint, String property :SUNSENDPOINT, String
has n, :vdcs has n, :vdcs
####################################################################### #######################################################################
# Constants # Constants
####################################################################### #######################################################################
ZONE_ATTRS = [:onename, :onepass, :endpoint, :name] ZONE_ATTRS = [:ONENAME, :ONEPASS, :ENDPOINT, :NAME]
####################################################################### #######################################################################
# JSON Functions # JSON Functions
@ -47,20 +47,20 @@ module OZones
zonePoolHash["ZONE_POOL"]["ZONE"] = Array.new unless self.all.empty? zonePoolHash["ZONE_POOL"]["ZONE"] = Array.new unless self.all.empty?
self.all.each{|zone| self.all.each{|zone|
zonePoolHash["ZONE_POOL"]["ZONE"] << zonePoolHash["ZONE_POOL"]["ZONE"] <<
zone.attributes.merge({:numbervdcs => zone.vdcs.all.size}) zone.attributes.merge({:NUMBERVDCS => zone.vdcs.all.size})
} }
return zonePoolHash return zonePoolHash
end end
def to_hash def to_hash
zone_attributes = Hash.new zone_attributes = Hash.new
zone_attributes["ZONE"] = attributes zone_attributes["ZONE"] = attributes
zone_attributes["ZONE"][:vdcs] = Array.new zone_attributes["ZONE"][:VDCS] = Array.new
self.vdcs.all.each{|vdc| self.vdcs.all.each{|vdc|
zone_attributes["ZONE"][:vdcs]<<vdc.attributes zone_attributes["ZONE"][:VDCS]<< vdc.attributes
} }
return zone_attributes return zone_attributes
@ -69,35 +69,33 @@ module OZones
####################################################################### #######################################################################
# Zone Data Management # Zone Data Management
####################################################################### #######################################################################
def self.create(data) def self.create(zone_data)
zone_data = Hash.new
data.each{|key,value|
zone_data[key.downcase.to_sym] = value
}
ZONE_ATTRS.each { |param| ZONE_ATTRS.each { |param|
if !zone_data[param] if !zone_data[param]
return OZones::Error.new("Error: Couldn't create zone. " \ return OZones::Error.new("Error: Couldn't create zone. " \
"Mandatory attribute '#{param}' is missing.") "Mandatory attribute '#{param}' is missing.")
end end
} }
# Digest and check credentials # 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], $stderr.puts zone_data
zone_data[:onepass],
zone_data[:endpoint]) rc = OpenNebulaZone::check_oneadmin(zone_data[:ONENAME],
zone_data[:ONEPASS],
zone_data[:ENDPOINT])
if OpenNebula.is_error?(rc) if OpenNebula.is_error?(rc)
return OZones::Error.new("Error: Couldn't create zone. "\ return OZones::Error.new("Error: Couldn't create zone. "\
"Reason: #{rc.message}") "Reason: #{rc.message}")
end end
# Create the zone # Create the zone
begin begin
zone = Zones.new zone = Zones.new
zone.raise_on_save_failure = true zone.raise_on_save_failure = true
zone.attributes = zone_data zone.attributes = zone_data
@ -108,46 +106,46 @@ module OZones
return zone return zone
end end
end end
########################################################################### ###########################################################################
# This class represents a Zone able to interact with its supporting # This class represents a Zone able to interact with its supporting
# OpenNebula installation through OCA. Data persistence is provided by a # OpenNebula installation through OCA. Data persistence is provided by a
# Zones class # Zones class
########################################################################## ##########################################################################
class OpenNebulaZone class OpenNebulaZone
def initialize(zoneid) def initialize(zoneid)
@zone = Zones.get(zoneid) @zone = Zones.get(zoneid)
if !@zone if !@zone
raise "Error: Zone with id #{zoneid} not found" raise "Error: Zone with id #{zoneid} not found"
end end
@client = OpenNebula::Client.new( @client = OpenNebula::Client.new(
"#{@zone.onename}:#{@zone.onepass}", "#{@zone.ONENAME}:#{@zone.ONEPASS}",
@zone.endpoint, @zone.ENDPOINT,
false) false)
end end
def pool_to_json(pool_kind) def pool_to_json(pool_kind)
pool = case pool_kind pool = case pool_kind
when "host" then when "host" then
OpenNebulaJSON::HostPoolJSON.new(@client) OpenNebulaJSON::HostPoolJSON.new(@client)
when "image" then when "image" then
OpenNebulaJSON::ImagePoolJSON.new(@client) OpenNebulaJSON::ImagePoolJSON.new(@client)
when "user" then when "user" then
OpenNebulaJSON::UserPoolJSON.new(@client) OpenNebulaJSON::UserPoolJSON.new(@client)
when "vm" then when "vm" then
OpenNebulaJSON::VirtualMachinePoolJSON.new(@client) OpenNebulaJSON::VirtualMachinePoolJSON.new(@client)
when "vn","vnet" then when "vn","vnet" then
OpenNebulaJSON::VirtualNetworkPoolJSON.new(@client) OpenNebulaJSON::VirtualNetworkPoolJSON.new(@client)
when "template","vmtemplate" then when "template","vmtemplate" then
OpenNebulaJSON::TemplatePoolJSON.new(@client) OpenNebulaJSON::TemplatePoolJSON.new(@client)
else else
error = OZones::Error.new("Error: Pool #{pool_kind} not " \ error = OZones::Error.new("Error: Pool #{pool_kind} not " \
"supported for zone view") "supported for zone view")
return [404, error.to_json] return [404, error.to_json]
end end
pool.info pool.info
@ -156,23 +154,23 @@ module OZones
def self.all_pools_to_json(pool_kind) def self.all_pools_to_json(pool_kind)
pool = case pool_kind pool = case pool_kind
when "host" then when "host" then
OZones::AggregatedHosts.new OZones::AggregatedHosts.new
when "image" then when "image" then
OZones::AggregatedImages.new OZones::AggregatedImages.new
when "user" then when "user" then
OZones::AggregatedUsers.new OZones::AggregatedUsers.new
when "vm" then when "vm" then
OZones::AggregatedVirtualMachines.new OZones::AggregatedVirtualMachines.new
when "vn","vnet" then when "vn","vnet" then
OZones::AggregatedVirtualNetworks.new OZones::AggregatedVirtualNetworks.new
when "template","vmtemplate" then when "template","vmtemplate" then
OZones::AggregatedTemplates.new OZones::AggregatedTemplates.new
else else
error = OZones::Error.new("Error: Pool #{pool_kind} not" \ error = OZones::Error.new("Error: Pool #{pool_kind} not" \
" supported for aggregated zone view") " supported for aggregated zone view")
return [404, error.to_json] return [404, error.to_json]
end end
return [200, pool.to_json] return [200, pool.to_json]
end end

View File

@ -14,12 +14,12 @@
# limitations under the License. # # limitations under the License. #
#--------------------------------------------------------------------------- # #--------------------------------------------------------------------------- #
class Auth class Auth
include DataMapper::Resource include DataMapper::Resource
property :id, Serial property :id, Serial
property :name, String, :required => true, :unique => true property :name, String, :required => true, :unique => true
property :password, String, :required => true property :password, String, :required => true
end end

View File

@ -35,11 +35,11 @@ class OzonesServer
if vdc if vdc
return [200, vdc.to_json] return [200, vdc.to_json]
else else
return [404, return [404,
OZones::Error.new("Error:VDC with id #{id} not found").to_json] OZones::Error.new("Error:VDC with id #{id} not found").to_json]
end end
end end
#Gets all Zones #Gets all Zones
def get_zones def get_zones
return 200, OZones::Zones.to_json return 200, OZones::Zones.to_json
@ -52,8 +52,8 @@ class OzonesServer
if zone if zone
return [200, zone.to_json] return [200, zone.to_json]
else else
return [404, return [404,
OZones::Error.new("Error:Zone with id #{id} not found").to_json] OZones::Error.new("Error:Zone with id #{id} not found").to_json]
end end
end end
@ -77,39 +77,35 @@ class OzonesServer
############################################################################ ############################################################################
def create_vdc (body,pr) def create_vdc (body,pr)
#Setup POST data #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. " \ return [400, OZones::Error.new("Error: Couldn't update vdc. " \
"Reason: #{data.message}.").to_json] "Reason: #{data.message}.").to_json]
end 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 #Get the Zone that will host the VDC. And check resouces
zoneid = vdc_data.delete(:zoneid) zoneid = vdc_data.delete(:ZONEID)
force = vdc_data.delete(:force) force = vdc_data.delete(:FORCE)
if !zoneid if !zoneid
return [400, OZones::Error.new("Error: Couldn't create vdc. " \ return [400,
"Mandatory attribute zoneid missing.").to_json] OZones::Error.new("Error: Couldn't create vdc. " \
"Mandatory attribute zoneid missing.").to_json]
end end
zone = OZones::Zones.get(zoneid) zone = OZones::Zones.get(zoneid)
if !zone if !zone
return [404, OZones::Error.new("Error: Couldn't create vdc. " \ return [404, OZones::Error.new("Error: Couldn't create vdc. " \
"Zone #{zoneid} not found.").to_json] "Zone #{zoneid} not found.").to_json]
end end
if (!force or force.upcase!="YES") and if (!force or force.upcase!="YES") and
!host_uniqueness?(zone, vdc_data[:hosts]) !host_uniqueness?(zone, vdc_data[:HOSTS])
return [403, OZones::Error.new("Error: Couldn't create vdc. " \ return [403,
"Hosts are not unique, use force to override").to_json] OZones::Error.new("Error: Couldn't create vdc. " \
"Hosts are not unique, use force to override").to_json]
end end
# Create de VDC # Create de VDC
@ -118,20 +114,21 @@ class OzonesServer
if OpenNebula.is_error?(rc) if OpenNebula.is_error?(rc)
return [400, OZones::Error.new("Error: Couldn't create vdc. " \ return [400, OZones::Error.new("Error: Couldn't create vdc. " \
"Reason: #{rc.message}").to_json] "Reason: #{rc.message}").to_json]
end end
#Update the zone and save the vdc #Update the zone and save the vdc
zone.raise_on_save_failure = true zone.raise_on_save_failure = true
zone.vdcs << vdc.vdc zone.vdcs << vdc.vdc
begin begin
zone.save zone.save
rescue => e rescue => e
vdc.clean_bootstrap vdc.clean_bootstrap
return [400, OZones::Error.new("Error: Couldn't create " \ return [400,
"vdc. Zone could not be saved: #{e.message}").to_json] OZones::Error.new("Error: Couldn't create " \
"vdc. Zone could not be saved: #{e.message}").to_json]
end end
pr.update # Rewrite proxy conf file pr.update # Rewrite proxy conf file
@ -140,11 +137,11 @@ class OzonesServer
def create_zone(body, pr) def create_zone(body, pr)
#Setup POST data #Setup POST data
data = parse_json(body,"zone") data = parse_json_sym(body,:ZONE)
if OpenNebula.is_error?(data) if OpenNebula.is_error?(data)
return [400, OZones::Error.new("Error: Couldn't update vdc. " \ return [400, OZones::Error.new("Error: Couldn't update vdc. " \
"Reason: #{data.message}.").to_json] "Reason: #{data.message}.").to_json]
end end
zone = OZones::Zones.create(data) zone = OZones::Zones.create(data)
@ -162,26 +159,20 @@ class OzonesServer
############################################################################ ############################################################################
def update_vdc(vdc_id, body) def update_vdc(vdc_id, body)
#Setup PUT data #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. " \ return [400, OZones::Error.new("Error: Couldn't update vdc. " \
"Reason: #{data.message}.").to_json] "Reason: #{data.message}.").to_json]
end end
vdc_data = Hash.new hosts = vdc_data.delete(:HOSTS)
force = vdc_data.delete(:FORCE)
data.each{|key,value|
vdc_data[key.downcase.to_sym]=value
}
hosts = vdc_data.delete(:hosts)
force = vdc_data.delete(:force)
# Check parameters # Check parameters
if !hosts if !hosts
return [400, OZones::Error.new("Error: Couldn't update vdc. " \ return [400, OZones::Error.new("Error: Couldn't update vdc. " \
"Missing HOSTS.").to_json] "Missing HOSTS.").to_json]
end end
# Check if the referenced Vdc exists # Check if the referenced Vdc exists
@ -189,25 +180,26 @@ class OzonesServer
vdc = OZones::OpenNebulaVdc.new(vdc_id) vdc = OZones::OpenNebulaVdc.new(vdc_id)
rescue => e rescue => e
return [404, OZones::Error.new("Error: Couldn't update vdc. " \ return [404, OZones::Error.new("Error: Couldn't update vdc. " \
"#{e.message}").to_json] "#{e.message}").to_json]
end 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. " \ if (!force or force.upcase != "YES") and
"Hosts are not unique, use force to override").to_json] !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 end
rc = vdc.update(hosts) rc = vdc.update(hosts)
if !OpenNebula.is_error?(rc) if !OpenNebula.is_error?(rc)
return [200, rc] return [200, rc]
else else
return [500, OZones::Error.new("Error: Couldn't update vdc. " \ return [500, OZones::Error.new("Error: Couldn't update vdc. " \
" Reason: #{rc.message}").to_json] " Reason: #{rc.message}").to_json]
end end
end end
############################################################################ ############################################################################
# Delete resources # Delete resources
@ -218,12 +210,12 @@ class OzonesServer
rc = vdc.destroy rc = vdc.destroy
rescue => e rescue => e
return [404, OZones::Error.new("Error: Can not delete vdc. " \ return [404, OZones::Error.new("Error: Can not delete vdc. " \
"Reason: #{e.message}").to_json] "Reason: #{e.message}").to_json]
end end
if !rc if !rc
return [500, OZones::Error.new("Error: Couldn't delete " \ return [500, OZones::Error.new("Error: Couldn't delete " \
"vdc #{id}").to_json] "vdc #{id}").to_json]
else else
pr.update # Rewrite proxy conf file pr.update # Rewrite proxy conf file
return [200, OZones.str_to_json("Vdc #{id} successfully deleted")] return [200, OZones.str_to_json("Vdc #{id} successfully deleted")]
@ -236,13 +228,14 @@ class OzonesServer
if zone if zone
rc = zone.destroy rc = zone.destroy
else else
return [404, OZones::Error.new("Error: Can not delete " \ return [404,
"zone. Reason: zone #{id} not found").to_json] OZones::Error.new("Error: Can not delete " \
"zone. Reason: zone #{id} not found").to_json]
end end
if !rc if !rc
return [500, OZones::Error.new("Error: Couldn't delete " \ return [500, OZones::Error.new("Error: Couldn't delete " \
"zone #{id}").to_json] "zone #{id}").to_json]
else else
pr.update # Rewrite proxy conf file pr.update # Rewrite proxy conf file
return [200, OZones.str_to_json("Zone #{id} successfully deleted")] return [200, OZones.str_to_json("Zone #{id} successfully deleted")]
@ -253,15 +246,15 @@ class OzonesServer
# Misc Helper Functions # Misc Helper Functions
############################################################################ ############################################################################
private private
# Check if hosts are already include in any Vdc of the zone # Check if hosts are already include in any Vdc of the zone
def host_uniqueness?(zone, host_list, vdc_id = -1) def host_uniqueness?(zone, host_list, vdc_id = -1)
return true if host_list.empty? return true if host_list.empty?
all_hosts = "" all_hosts = ""
zone.vdcs.all.each{|vdc| zone.vdcs.all.each{|vdc|
if vdc.hosts != nil and !vdc.hosts.empty? and vdc.id != vdc_id if vdc.HOSTS != nil and !vdc.HOSTS.empty? and vdc.id != vdc_id
all_hosts << ',' << vdc.hosts all_hosts << ',' << vdc.HOSTS
end end
} }

View File

@ -24,7 +24,7 @@ if !ONE_LOCATION
RUBY_LIB_LOCATION="/usr/lib/one/ruby" RUBY_LIB_LOCATION="/usr/lib/one/ruby"
VAR_LOCATION="/var/lib/one" VAR_LOCATION="/var/lib/one"
else else
ETC_LOCATION=ONE_LOCATION+"/etc" ETC_LOCATION=ONE_LOCATION+"/etc"
LIB_LOCATION=ONE_LOCATION+"/lib" LIB_LOCATION=ONE_LOCATION+"/lib"
RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby" RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby"
VAR_LOCATION=ONE_LOCATION+"/var" VAR_LOCATION=ONE_LOCATION+"/var"
@ -62,7 +62,7 @@ db_url = db_type + "://" + VAR_LOCATION + "/ozones.db"
############################################################################## ##############################################################################
# DB bootstrapping # DB bootstrapping
############################################################################## ##############################################################################
if config[:dbdebug] if config[:dbdebug]
DataMapper::Logger.new($stdout, :debug) DataMapper::Logger.new($stdout, :debug)
end end
@ -76,22 +76,22 @@ DataMapper.auto_upgrade!
if Auth.all.size == 0 if Auth.all.size == 0
if ENV['OZONES_AUTH'] && File.exist?(ENV['OZONES_AUTH']) 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 if credentials.length < 2
warn "Authorization data malformed" warn "Authorization data malformed"
exit -1 exit -1
end end
credentials[1] = Digest::SHA1.hexdigest(credentials[1]) credentials[1] = Digest::SHA1.hexdigest(credentials[1])
@auth=Auth.create({:name => credentials[0], @auth=Auth.create({:name => credentials[0],
:password => credentials[1]}) :password => credentials[1]})
@auth.save @auth.save
else else
warn "oZones admin credentials not set, missing OZONES_AUTH file." warn "oZones admin credentials not set, missing OZONES_AUTH file."
exit -1 exit -1
end end
else else
@auth=Auth.all.first @auth=Auth.all.first
end end
ADMIN_NAME = @auth.name ADMIN_NAME = @auth.name
@ -101,7 +101,7 @@ begin
OZones::ProxyRules.new("apache",config[:htaccess]) OZones::ProxyRules.new("apache",config[:htaccess])
rescue Exception => e rescue Exception => e
warn e.message warn e.message
exit -1 exit -1
end end
@ -122,12 +122,12 @@ helpers do
if session[:ip] && session[:ip]==request.ip if session[:ip] && session[:ip]==request.ip
return true return true
end end
auth = Rack::Auth::Basic::Request.new(request.env) auth = Rack::Auth::Basic::Request.new(request.env)
if auth.provided? && auth.basic? && auth.credentials if auth.provided? && auth.basic? && auth.credentials
user = auth.credentials[0] user = auth.credentials[0]
sha1_pass = Digest::SHA1.hexdigest(auth.credentials[1]) sha1_pass = Digest::SHA1.hexdigest(auth.credentials[1])
if user == ADMIN_NAME && sha1_pass == ADMIN_PASS if user == ADMIN_NAME && sha1_pass == ADMIN_PASS
return true return true
end end
@ -140,7 +140,7 @@ helpers do
if auth.provided? && auth.basic? && auth.credentials if auth.provided? && auth.basic? && auth.credentials
user = auth.credentials[0] user = auth.credentials[0]
sha1_pass = Digest::SHA1.hexdigest(auth.credentials[1]) sha1_pass = Digest::SHA1.hexdigest(auth.credentials[1])
if user == ADMIN_NAME && sha1_pass == ADMIN_PASS if user == ADMIN_NAME && sha1_pass == ADMIN_PASS
session[:user] = user session[:user] = user
session[:password] = sha1_pass session[:password] = sha1_pass
@ -170,8 +170,8 @@ end
before do before do
unless request.path=='/login' || request.path=='/' unless request.path=='/login' || request.path=='/'
halt 401 unless authorized? halt 401 unless authorized?
@OzonesServer = OzonesServer.new @OzonesServer = OzonesServer.new
@pr = OZones::ProxyRules.new("apache",config[:htaccess]) @pr = OZones::ProxyRules.new("apache",config[:htaccess])
end end
end end
@ -281,5 +281,3 @@ end
delete '/zone/:id' do delete '/zone/:id' do
@OzonesServer.delete_zone(params[:id], @pr) @OzonesServer.delete_zone(params[:id], @pr)
end end

View File

@ -416,7 +416,7 @@ function hostsListCB(req,list){
return; return;
}; };
var host_json = oZones.Helper.pool("HOST",this.ZONE); 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); updateZonesDashboard("hosts",host_json);
}); });
} }
@ -429,7 +429,7 @@ function vmsListCB(req,list){
return; return;
}; };
var vms_json = oZones.Helper.pool("VM",this.ZONE); 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); updateZonesDashboard("vms",vms_json);
}); });
} }
@ -442,7 +442,7 @@ function vnsListCB(req,list){
return; return;
}; };
var vn_json = oZones.Helper.pool("VNET",this.ZONE); 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); updateZonesDashboard("vnets",vn_json);
}); });
} }
@ -455,7 +455,7 @@ function imagesListCB(req,list){
return; return;
}; };
var image_json = oZones.Helper.pool("IMAGE",this.ZONE); 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); updateZonesDashboard("images",image_json);
}); });
} }
@ -468,7 +468,7 @@ function usersListCB(req,list){
return; return;
}; };
var user_json = oZones.Helper.pool("USER",this.ZONE); 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); updateZonesDashboard("users",user_json);
}); });
} }
@ -481,7 +481,7 @@ function templatesListCB(req,list){
return; return;
}; };
var template_json = oZones.Helper.pool("VMTEMPLATE",this.ZONE); 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); updateZonesDashboard("templates",template_json);
}); });
} }

View File

@ -224,11 +224,11 @@ function vdcElementArray(vdc_json){
var vdc = vdc_json.VDC; var vdc = vdc_json.VDC;
return [ return [
'<input type="checkbox" id="vdc_'+vdc.id+'" name="selected_items" value="'+vdc.id+'"/>', '<input type="checkbox" id="vdc_'+vdc.ID+'" name="selected_items" value="'+vdc.ID+'"/>',
vdc.id, vdc.ID,
vdc.name, vdc.NAME,
vdc.zones_id, vdc.ZONES_ID,
vdc.hosts ? vdc.hosts : "none" vdc.HOSTS ? vdc.HOSTS : "none"
]; ];
} }
@ -253,7 +253,7 @@ function addVDCElement(req,vdc_json){
} }
function updateVDCElement(request, vdc_json){ function updateVDCElement(request, vdc_json){
var id = vdc_json.VDC.id; var id = vdc_json.VDC.ID;
var element = vdcElementArray(vdc_json); var element = vdcElementArray(vdc_json);
updateSingleElement(element,dataTable_vdcs,'#vdc_'+id); updateSingleElement(element,dataTable_vdcs,'#vdc_'+id);
} }
@ -276,36 +276,36 @@ function updateVDCInfo(req,vdc_json){
content : content :
'<table id="info_vdc_table" class="info_table">\ '<table id="info_vdc_table" class="info_table">\
<thead>\ <thead>\
<tr><th colspan="2">Virtual Data Center - '+vdc.name+'</th></tr>\ <tr><th colspan="2">Virtual Data Center - '+vdc.NAME+'</th></tr>\
</thead>\ </thead>\
<tbody>\ <tbody>\
<tr>\ <tr>\
<td class="key_td">ID</td>\ <td class="key_td">ID</td>\
<td class="value_td">'+vdc.id+'</td>\ <td class="value_td">'+vdc.ID+'</td>\
</tr>\ </tr>\
<tr>\ <tr>\
<td class="key_td">Name</td>\ <td class="key_td">Name</td>\
<td class="value_td">'+vdc.name+'</td>\ <td class="value_td">'+vdc.NAME+'</td>\
</tr>\ </tr>\
<tr>\ <tr>\
<td class="key_td">Zone ID</td>\ <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>\
<tr>\ <tr>\
<td class="key_td">Hosts</td>\ <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>\
<tr>\ <tr>\
<td class="key_td">Admin name</td>\ <td class="key_td">Admin name</td>\
<td class="value_td">'+vdc.vdcadminname+'</td>\ <td class="value_td">'+vdc.VDCADMINNAME+'</td>\
</tr>\ </tr>\
<tr>\ <tr>\
<td class="key_td">Group ID</td>\ <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>\
<tr>\ <tr>\
<td class="key_td">ACLs</td>\ <td class="key_td">ACLs</td>\
<td class="value_td">'+vdc.acls+'</td>\ <td class="value_td">'+vdc.ACLS+'</td>\
</tr>\ </tr>\
</tbody>\ </tbody>\
</table>' </table>'
@ -461,16 +461,16 @@ function setupCreateVDCDialog(){
}; };
var vdc_json = { var vdc_json = {
"vdc" : { "VDC" : {
"name" : name, "NAME" : name,
"zoneid" : zoneid, "ZONEID" : zoneid,
"vdcadminname" : vdcadminname, "VDCADMINNAME" : vdcadminname,
"vdcadminpass" : vdcadminpass, "VDCADMINPASS" : vdcadminpass,
"force" : force "FORCE" : force
} }
}; };
if (hosts.length){ if (hosts.length){
vdc_json["vdc"]["hosts"]=hosts; vdc_json["VDC"]["HOSTS"]=hosts;
}; };
Sunstone.runAction("VDC.create",vdc_json); Sunstone.runAction("VDC.create",vdc_json);
@ -549,15 +549,15 @@ function setupUpdateVDCDialog(){
}; };
var vdc_json = { var vdc_json = {
"vdc" : { "VDC" : {
"id": id, "ID": id,
"force": force, "FORCE": force,
"hosts": hosts "HOSTS": ""
} }
}; };
if (hosts.length){ if (hosts.length){
vdc_json["vdc"]["hosts"]=hosts; vdc_json["VDC"]["HOSTS"]=hosts;
}; };
Sunstone.runAction("VDC.update",id,vdc_json); Sunstone.runAction("VDC.update",id,vdc_json);
dialog.dialog('close'); dialog.dialog('close');

View File

@ -228,10 +228,10 @@ function zoneElementArray(zone_json){
var zone = zone_json.ZONE; var zone = zone_json.ZONE;
return [ return [
'<input type="checkbox" id="zone_'+zone.id+'" name="selected_items" value="'+zone.id+'"/>', '<input type="checkbox" id="zone_'+zone.ID+'" name="selected_items" value="'+zone.ID+'"/>',
zone.id, zone.ID,
zone.name, zone.NAME,
zone.endpoint zone.ENDPOINT
]; ];
} }
@ -281,32 +281,32 @@ function updateZoneInfo(req,zone_json){
content : content :
'<table id="info_zone_table" class="info_table">\ '<table id="info_zone_table" class="info_table">\
<thead>\ <thead>\
<tr><th colspan="2">Zone information - '+zone.name+'</th></tr>\ <tr><th colspan="2">Zone information - '+zone.NAME+'</th></tr>\
</thead>\ </thead>\
<tbody>\ <tbody>\
<tr>\ <tr>\
<td class="key_td">ID</td>\ <td class="key_td">ID</td>\
<td class="value_td">'+zone.id+'</td>\ <td class="value_td">'+zone.ID+'</td>\
</tr>\ </tr>\
<tr>\ <tr>\
<td class="key_td">Administrator</td>\ <td class="key_td">Administrator</td>\
<td class="value_td">'+zone.onename+'</td>\ <td class="value_td">'+zone.ONENAME+'</td>\
</tr>\ </tr>\
<tr>\ <tr>\
<td class="key_td">Password</td>\ <td class="key_td">Password</td>\
<td class="value_td">'+zone.onepass+'</td>\ <td class="value_td">'+zone.ONEPASS+'</td>\
</tr>\ </tr>\
<tr>\ <tr>\
<td class="key_td">Endpoint</td>\ <td class="key_td">Endpoint</td>\
<td class="value_td">'+zone.endpoint+'</td>\ <td class="value_td">'+zone.ENDPOINT+'</td>\
</tr>\ </tr>\
<tr>\ <tr>\
<td class="key_td">Sunstone endpoint</td>\ <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>\
<tr>\ <tr>\
<td class="key_td">#VDCs</td>\ <td class="key_td">#VDCs</td>\
<td class="value_td">'+zone.vdcs.length+'</td>\ <td class="value_td">'+zone.VDCS.length+'</td>\
</tr>\ </tr>\
</tbody>\ </tbody>\
</table>' </table>'
@ -524,12 +524,12 @@ function updateZoneInfo(req,zone_json){
/*End init dataTables*/ /*End init dataTables*/
//Retrieve pools in the meantime //Retrieve pools in the meantime
Sunstone.runAction("Zone.host",zone.id); Sunstone.runAction("Zone.host",zone.ID);
Sunstone.runAction("Zone.vmtemplate",zone.id); Sunstone.runAction("Zone.vmtemplate",zone.ID);
Sunstone.runAction("Zone.vms",zone.id); Sunstone.runAction("Zone.vms",zone.ID);
Sunstone.runAction("Zone.vnet",zone.id); Sunstone.runAction("Zone.vnet",zone.ID);
Sunstone.runAction("Zone.image",zone.id); Sunstone.runAction("Zone.image",zone.ID);
Sunstone.runAction("Zone.user",zone.id); Sunstone.runAction("Zone.user",zone.ID);
} }
@ -559,12 +559,12 @@ function setupCreateZoneDialog(){
} }
var zone_json = { var zone_json = {
"zone": { "ZONE": {
"name": name, "NAME": name,
"endpoint": endpoint, "ENDPOINT": endpoint,
"onename": onename, "ONENAME": onename,
"onepass": onepass, "ONEPASS": onepass,
"sunsendpoint" : sunsendpoint "SUNSENDPOINT" : sunsendpoint
} }
}; };

View File

@ -41,6 +41,22 @@ module OpenNebulaJSON
end end
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) def template_to_str(attributes, indent=true)
if indent if indent
ind_enter="\n" ind_enter="\n"