1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-03-22 18:50:08 +03:00

Merge branch 'feature-200'

This commit is contained in:
Ruben S. Montero 2010-07-20 19:44:11 +02:00
commit f81e546629
45 changed files with 1654 additions and 1727 deletions

View File

@ -488,9 +488,7 @@ HOOK_SHARE_FILES="share/hooks/ebtables-xen \
COMMON_CLOUD_LIB_FILES="src/cloud/common/CloudServer.rb \
src/cloud/common/CloudClient.rb \
src/cloud/common/Configuration.rb \
src/cloud/rm/image.rb \
src/cloud/rm/repo_manager.rb"
src/cloud/common/Configuration.rb"
COMMON_CLOUD_CLIENT_LIB_FILES="src/cloud/common/CloudClient.rb"
@ -500,6 +498,7 @@ COMMON_CLOUD_CLIENT_LIB_FILES="src/cloud/common/CloudClient.rb"
ECO_LIB_FILES="src/cloud/ec2/lib/EC2QueryClient.rb \
src/cloud/ec2/lib/EC2QueryServer.rb \
src/cloud/ec2/lib/ImageEC2.rb \
src/cloud/ec2/lib/econe-server.rb"
ECO_LIB_CLIENT_FILES="src/cloud/ec2/lib/EC2QueryClient.rb"

View File

@ -1,7 +1,8 @@
#!/usr/bin/env ruby
# -------------------------------------------------------------------------- #
# Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) #
# Copyright 2002-2009, Distributed Systems Architecture Group, Universidad #
# Complutense de Madrid (dsa-research.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 #
@ -18,8 +19,7 @@
require 'pp'
require 'digest/md5'
require 'ftools'
require 'fileutils'
###########################################
# Code to test compilation/linkning flags #
@ -207,7 +207,7 @@ def gen_test_file(kind)
#fname="xmlrpc_test.cc"
full_path=dir+"/"+fname
File.makedirs(dir)
FileUtils::mkdir_p(dir)
f=open(full_path, "w")
f.write(TestCode[kind])
f.close

View File

@ -62,12 +62,12 @@ ShowTableExample={
:id => {
:name => "ID",
:size => 4,
:proc => lambda {|d,e| d["oid"] }
:proc => lambda {|d,e| d["OID"] }
},
:name => {
:name => "NAME",
:size => 8,
:proc => lambda {|d,e| d["deploy_id"] }
:proc => lambda {|d,e| d["DEPLOY_ID"] }
},
:stat => {
:name => "STAT",
@ -294,11 +294,11 @@ def get_cluster_id(name)
end
def str_running_time(data)
stime=Time.at(data["stime"].to_i)
if data["etime"]=="0"
stime=Time.at(data["STIME"].to_i)
if data["ETIME"]=="0"
etime=Time.now
else
etime=Time.at(data["etime"].to_i)
etime=Time.at(data["ETIME"].to_i)
end
dtime=Time.at(etime-stime).getgm

View File

@ -15,7 +15,6 @@
#--------------------------------------------------------------------------- #
require 'optparse'
require 'pp'
class CommandParse

View File

@ -103,7 +103,7 @@ ShowTableHost={
d.short_state_str()
}
},
:default => [:id, :name, :cluster, :rvm, :tcpu, :fcpu, :acpu, :tmem, :fmem, :stat]
}
@ -113,7 +113,7 @@ class HostShow
@hostpool=OpenNebula::HostPool.new(client)
@table=ShowTable.new(ShowTableHost)
end
def header_host_small
scr_bold
scr_underline
@ -121,7 +121,7 @@ class HostShow
scr_restore
puts ""
end
def list_short(options=nil)
res=@hostpool.info
if options
@ -141,13 +141,13 @@ class HostShow
result
end
end
def top(options=nil)
delay=1
delay=options[:delay] if options && options[:delay]
result=nil
begin
while true
scr_cls
@ -162,28 +162,28 @@ class HostShow
end
class OnehostParse < CommandParse
COMMANDS_HELP=<<-EOT
Commands:
* create (Adds a new machine to the pool)
onehost create <hostname> <im_mad> <vmm_mad> <tm_mad>
* show (Gets info from a host)
onehost show <host_id>
* delete (Removes a machine from the pool)
onehost delete <host_id>
* list (Lists machines in the pool)
onehost list
* enable (Enables host)
onehost enable <host_id>
* disable (Disables host)
onehost disable <host_id>
* top (Lists hosts continuously)
onehost top
@ -215,8 +215,8 @@ def vms_in_host?(host_id)
puts rc.message
exit -1
end
host['host_share/running_vms'].to_i
host['HOST_SHARE/RUNNING_VMS'].to_i
end
@ -234,59 +234,54 @@ when "add", "create"
check_parameters("create", 4)
host=OpenNebula::Host.new(OpenNebula::Host.build_xml, get_one_client)
result=host.allocate(ARGV[0], ARGV[1], ARGV[2], ARGV[3])
if is_successful?(result)
puts "ID: " + host.id.to_s if ops[:verbose]
exit 0
end
when "show"
check_parameters("show", 1)
#args=expand_args(ARGV)
host_id=get_host_id(ARGV[0])
host=OpenNebula::Host.new_with_id(host_id, get_one_client)
result=host.info
if is_successful?(result)
#puts host.template_str
else
puts "Error: "+result.message
exit -1
end
if !ops[:xml]
str = "%-22s: %-20s"
str_h1 = "%-80s"
print_header(str_h1, "HOST #{host_id} INFORMATION", true)
if !ops[:xml]
str = "%-22s: %-20s"
str_h1 = "%-80s"
puts str % ["ID", host[:id]]
puts str % ["NAME", host[:name]]
puts str % ["CLUSTER", host[:cluster]]
puts str % ["STATE", host.state_str]
puts str % ["IM_MAD", host[:im_mad]]
puts str % ["VM_MAD", host[:vm_mad]]
puts str % ["TM_MAD", host[:tm_mad]]
puts
print_header(str_h1, "HOST #{host_id} INFORMATION", true)
print_header(str_h1, "HOST SHARES", false)
puts str % ["MAX MEM", host['host_share/max_mem']]
puts str % ["USED MEM (REAL)", host['host_share/used_mem']]
puts str % ["USED MEM (ALLOCATED)", host['host_share/mem_usage']]
puts str % ["MAX CPU", host['host_share/max_cpu']]
puts str % ["USED CPU (REAL)", host['host_share/used_cpu']]
puts str % ["USED CPU (ALLOCATED)", host['host_share/cpu_usage']]
puts str % ["RUNNING VMS", host['host_share/running_vms']]
puts
puts str % ["ID", host.id.to_s]
puts str % ["NAME", host.name]
puts str % ["CLUSTER", host['CLUSTER']]
puts str % ["STATE", host.state_str]
puts str % ["IM_MAD", host['IM_MAD']]
puts str % ["VM_MAD", host['VM_MAD']]
puts str % ["TM_MAD", host['TM_MAD']]
puts
print_header(str_h1, "MONITORING INFORMATION", false)
print_header(str_h1, "HOST SHARES", false)
puts host.template_str
else
puts host.to_xml(true)
puts str % ["MAX MEM", host['HOST_SHARE/MAX_MEM']]
puts str % ["USED MEM (REAL)", host['HOST_SHARE/USED_MEM']]
puts str % ["USED MEM (ALLOCATED)", host['HOST_SHARE/MEM_USAGE']]
puts str % ["MAX CPU", host['HOST_SHARE/MAX_CPU']]
puts str % ["USED CPU (REAL)", host['HOST_SHARE/USED_CPU']]
puts str % ["USED CPU (ALLOCATED)", host['HOST_SHARE/CPU_USAGE']]
puts str % ["RUNNING VMS", host['HOST_SHARE/RUNNING_VMS']]
puts
print_header(str_h1, "MONITORING INFORMATION", false)
puts host.template_str
else
puts host.to_xml(true)
end
end
when "delete"
@ -295,7 +290,7 @@ when "delete"
args.each do |param|
host_id=get_host_id(param)
host = OpenNebula::Host.new_with_id(host_id,get_one_client)
rc = host.info
@ -305,7 +300,7 @@ when "delete"
exit -1
end
if host['host_share/running_vms'].to_i != 0
if host['HOST_SHARE/RUNNING_VMS'].to_i != 0
puts "Host still has associated VMs, aborting delete."
else
result=host.delete
@ -315,7 +310,7 @@ when "delete"
end
end
end
when "list"
if !ops[:xml]
hostlist=HostShow.new(get_one_client)
@ -331,7 +326,7 @@ when "top"
hostlist=HostShow.new(get_one_client)
ops[:columns]=ops[:list] if ops[:list]
result=hostlist.top(ops)
when "enable"
check_parameters("enable", 1)
args=expand_args(ARGV)
@ -361,13 +356,13 @@ when "disable"
break
end
end
else
onehost_opts.print_help
exit -1
end
if is_error?(result)
if is_error?(result)
puts "Error: " + result.message
exit -1
end

View File

@ -31,7 +31,6 @@ require 'OpenNebula'
require 'CommandManager'
require 'client_utilities'
require 'command_parse'
require 'ftools'
ShowTableImage={
:id => {
@ -278,23 +277,19 @@ def get_user_flags
ops
end
def get_type_and_path(image_template_file)
image_text = open(image_template_file).read
result=Hash.new
image_text.each_line {|line|
case line
when /^\s*(#.*)?$/
# skip empty or commented lines
next
when /^\s*(\w+)\s*=\s*(.*)\s*$/
name = $1.strip.upcase
if name == "PATH" || name == "TYPE" ||
name == "SIZE" || name == "FSTYPE"
result[name] = $2.strip
end
end
}
result
def get_template(template_path)
begin
template = File.read(ARGV[0])
rescue
result = OpenNebula::Error.new("Can not read template: #{ARGV[0]}")
end
if !is_successful?(result)
puts result.message
exit -1
end
return template
end
oneimage_opts=OneImageParse.new
@ -306,99 +301,59 @@ result=[false, "Unknown error"]
command=ARGV.shift
case command
when "register", "create", "add"
when "register", "create", "add"
# ---------- Get the Template ------------
check_parameters("register", 1)
# First, let's check we have everything we need in the template
template = get_template(ARGV[0])
# Get the path and type from the template file
parser_result = get_type_and_path(ARGV[0])
# ---------- Allocate the Image file ------------
if parser_result['TYPE']
type = parser_result['TYPE'].upcase
else
type = "OS"
end
image = OpenNebula::Image.new(
OpenNebula::Image.build_xml,
get_one_client)
result = image.allocate(template)
result = true
case type
when "OS", "CDROM"
if !parser_result['PATH']
result=OpenNebula::Error.new(
"Image path not present, aborting.")
elsif !File.exists?(parser_result['PATH'])
result=OpenNebula::Error.new(
"Image file could not be found, aborting.")
end
when "DATABLOCK"
if parser_result['PATH'] and !File.exists?(parser_result['PATH'])
if !parser_result['SIZE'] || !parser_result['FSTYPE']
result=OpenNebula::Error.new(
"No image file present for DATABLOCK, " +
"size and/or fstype also missing, aborting.")
end
end
end
if !is_successful?(result)
puts result.message
exit -1
end
# Perform the allocate if all goes well
image=OpenNebula::Image.new(
OpenNebula::Image.build_xml, get_one_client)
begin
template=File.read(ARGV[0])
result=image.allocate(template)
rescue
result=OpenNebula::Error.new("Can not read template: #{ARGV[0]}")
end
if !is_successful?(result)
exit -1
end
# Get the allocated image
image=OpenNebula::Image.new_with_id(image.id, get_one_client)
# ---------- Copy the Image file ------------
image.info
template=image.to_hash
template=template['IMAGE']['TEMPLATE']
# Perform the copy to the image repo if needed
if template['PATH']
if File.copy(template['PATH'], image['SOURCE'])
result = image.enable
else
result=OpenNebula::Error.new(
"Cannot copy image, aborting.")
image.delete
end
elsif parser_result['SIZE'] and parser_result['FSTYPE']
local_command=LocalCommand.run(
"dd if=/dev/zero of=#{image['SOURCE']} ibs=1 count=1 " \
"obs=1048576 oseek=#{parser_result['SIZE']}")
if local_command.code!=0
result=OpenNebula::Error.new(
"Cannot create datablock, aborting.")
image.delete
else
local_command=LocalCommand.run(
"mkfs -t #{parser_result['FSTYPE']} -F #{image['SOURCE']}")
if local_command.code!=0
result=OpenNebula::Error.new(
"Cannot format datablock, aborting.")
image.delete
else
image.enable
end
end
if image['TEMPLATE/PATH']
file_path = image['TEMPLATE/PATH']
if !File.exists?(file_path)
error_msg = "Image file could not be found, aborting."
result = OpenNebula::Error.new(error_msg)
end
result = image.copy(file_path, image['SOURCE'])
elsif image['TEMPLATE/SIZE'] and
image['TEMPLATE/FSTYPE'] and
image['TEMPLATE/TYPE'] == 'DATABLOCK'
result = image.mk_datablock(
image['TEMPLATE/SIZE'],
image['TEMPLATE/FSTYPE'],
image['SOURCE'])
else
error_msg = "Image not present, aborting."
result = OpenNebula::Error.new(error_msg)
end
if is_successful?(result)
image.enable
puts "ID: " + image.id.to_s if ops[:verbose]
exit 0
end
else
image.delete
end
when "update"
check_parameters("update", 3)
@ -493,42 +448,44 @@ when "show"
image_id=get_image_id(param)
image=OpenNebula::Image.new_with_id(image_id, get_one_client)
image.info
if !ops[:xml]
str="%-15s: %-20s"
str_h1="%-80s"
print_header(str_h1, "IMAGE #{image[:id]} INFORMATION", true)
puts str % ["ID", image[:id]]
puts str % ["NAME", image[:name]]
puts str % ["TYPE", image.type_str]
result = image.info
value=image[:regtime].to_i
if value==0
value='-'
else
value=Time.at(value).strftime("%m/%d %H:%M:%S")
end
puts str % ["REGISTER TIME", value]
if image[:public].to_i == 1
public_str = "Yes"
else
public_str = "No"
end
puts str % ["PUBLIC", public_str]
puts str % ["SOURCE", image[:source]]
puts str % ["STATE", image.short_state_str]
puts str % ["RUNNING_VMS", image[:runningvms]]
if is_successful?(result)
if !ops[:xml]
str="%-15s: %-20s"
str_h1="%-80s"
print_header(str_h1, "IMAGE #{image[:id]} INFORMATION", true)
puts str % ["ID", image.id.to_s]
puts str % ["NAME", image.name]
puts str % ["TYPE", image.type_str]
value=image['REGTIME'].to_i
if value==0
value='-'
else
value=Time.at(value).strftime("%m/%d %H:%M:%S")
end
puts str % ["REGISTER TIME", value]
if image['PUBLIC'].to_i == 1
public_str = "Yes"
else
public_str = "No"
end
puts str % ["PUBLIC", public_str]
puts str % ["SOURCE", image['SOURCE']]
puts str % ["STATE", image.short_state_str]
puts str % ["RUNNING_VMS", image['RUNNING_VMS']]
puts
puts
print_header(str_h1,"IMAGE TEMPLATE",false)
print_header(str_h1,"IMAGE TEMPLATE",false)
puts image.template_str
else
puts image.to_xml
puts image.template_str
else
puts image.to_xml
end
end
end

View File

@ -51,7 +51,7 @@ ShowTableUP={
:desc => "password of the user",
:size => 50,
:left => true,
:proc => lambda {|d,e| d[:password] }
:proc => lambda {|d,e| d['PASSWORD'] }
},
:default => [:id, :user, :password]

View File

@ -68,14 +68,14 @@ ShowTableVM={
:desc => "CPU percentage used by the VM",
:size => 3,
:proc => lambda {|d,e|
d["cpu"]
d["CPU"]
}
},
:mem => {
:name => "MEM",
:desc => "Memory used by the VM",
:size => 7,
:proc => lambda {|d,e| d["memory"] }
:proc => lambda {|d,e| d["MEMORY"] }
},
:hostname => {
:name => "HOSTNAME",
@ -100,26 +100,26 @@ ShowTableHistory={
:name => "ID",
:desc => "ONE identifier for the VM",
:size => 4,
:proc => lambda {|d,e| d["id"] }
:proc => lambda {|d,e| d["ID"] }
},
:seq => {
:name => "SEQ",
:desc => "Sequence number",
:size => 3,
:proc => lambda {|d,e| d["seq"] }
:proc => lambda {|d,e| d["SEQ"] }
},
:hostname => {
:name => "HOSTNAME",
:desc => "Name of the host where the VM was submited",
:size => 15,
:proc => lambda {|d,e| d["host_name"] }
:proc => lambda {|d,e| d["HOST_NAME"] }
},
:stime => {
:name => "STIME",
:desc => "Start time",
:size => 14,
:proc => lambda {|d,e|
t=Time.at(d["stime"].to_i)
t=Time.at(d["STIME"].to_i)
t.strftime("%m/%d %H:%M:%S")
}
},
@ -128,10 +128,10 @@ ShowTableHistory={
:desc => "End time",
:size => 14,
:proc => lambda {|d,e|
if d["etime"].to_i==0
if d["ETIME"].to_i==0
"--"
else
t=Time.at(d["etime"].to_i)
t=Time.at(d["ETIME"].to_i)
t.strftime("%m/%d %H:%M:%S")
end
}
@ -141,7 +141,7 @@ ShowTableHistory={
:desc => "Total time",
:size => 11,
:proc => lambda {|d,e|
d["time"]
d["TIME"]
}
},
:reason => {
@ -149,7 +149,7 @@ ShowTableHistory={
:desc => "Reason for state change",
:size => "6",
:proc => lambda {|d,e|
OpenNebula::VirtualMachine.get_reason(d["reason"])
OpenNebula::VirtualMachine.get_reason(d["REASON"])
}
},
@ -234,12 +234,12 @@ class VmShow
def get_vm_history(vm)
{
'id' => vm.id,
'seq' => vm['history/seq'],
'host_name' => vm['history/hostname'],
'stime' => vm['history/stime'],
'etime' => vm['history/etime'],
'seq' => vm['HISTORY/SEQ'],
'host_name' => vm['HISTORY/HOSTNAME'],
'stime' => vm['HISTORY/STIME'],
'etime' => vm['HISTORY/ETIME'],
'time' => str_running_time(vm),
'reason' => vm['history/reason']
'reason' => vm['HISTORY/REASON']
}
end
@ -274,7 +274,7 @@ class VmShow
def list_vm_history_array(ids, options=nil)
get_vms_history(ids).each {|vm|
puts "History for VM #{vm['id']}"
puts "History for VM #{vm['ID']}"
puts
list_vm_history(vm, options)
puts
@ -680,45 +680,47 @@ when "show"
vm_id=get_vm_id(param)
vm=OpenNebula::VirtualMachine.new_with_id(vm_id, get_one_client)
vm.info
result=vm.info
if is_successful?(result)
if !ops[:xml]
str="%-15s: %-20s"
str_h1="%-80s"
if !ops[:xml]
str="%-15s: %-20s"
str_h1="%-80s"
print_header(str_h1, "VIRTUAL MACHINE #{vm['ID']} INFORMATION",
true)
print_header(str_h1, "VIRTUAL MACHINE #{vm[:id]} INFORMATION", true)
puts str % ["ID", vm.id.to_s]
puts str % ["NAME", vm.name]
puts str % ["STATE", vm.state_str]
puts str % ["LCM_STATE", vm.lcm_state_str]
puts str % ["ID", vm[:id]]
puts str % ["NAME", vm[:name]]
puts str % ["STATE", vm.state_str]
puts str % ["LCM_STATE", vm.lcm_state_str]
value=vm['STIME'].to_i
if value==0
value='-'
else
value=Time.at(value).strftime("%m/%d %H:%M:%S")
end
puts str % ["START TIME", value]
value=vm[:stime].to_i
if value==0
value='-'
value=vm['ETIME'].to_i
if value==0
value='-'
else
value=Time.at(value).strftime("%m/%d %H:%M:%S")
end
puts str % ["END TIME", value]
value=vm['DEPLOY_ID']
puts str % ["DEPLOY ID:", value=="" ? "-" : value]
puts
print_header(str_h1,"VIRTUAL MACHINE TEMPLATE",false)
puts vm.template_str
else
value=Time.at(value).strftime("%m/%d %H:%M:%S")
puts vm.to_xml(true)
end
puts str % ["START TIME", value]
value=vm[:etime].to_i
if value==0
value='-'
else
value=Time.at(value).strftime("%m/%d %H:%M:%S")
end
puts str % ["END TIME", value]
value=vm[:deploy_id]
puts str % ["DEPLOY ID:", value=="" ? "-" : value]
puts
print_header(str_h1,"VIRTUAL MACHINE TEMPLATE",false)
puts vm.template_str
else
puts vm.to_xml(true)
end
end
else

View File

@ -58,10 +58,10 @@ ShowTableVN={
:desc => "NType of virtual network",
:size => 6,
:proc => lambda {|d,e|
if(d["type"] == "0")
if(d["TYPE"] == "0")
return "Ranged"
else
if (d["type"] == "1")
if (d["TYPE"] == "1")
return "Fixed"
end
end
@ -77,7 +77,7 @@ ShowTableVN={
:name => "BRIDGE",
:desc => "Bridge associated to the virtual network",
:size => 6,
:proc => lambda {|d,e| d["bridge"] }
:proc => lambda {|d,e| d["BRIDGE"] }
},
:public => {
:name => "PUBLIC",
@ -217,7 +217,7 @@ when "show"
puts str % ["ID: ",vn.id.to_s]
puts str % ["UID: ",vn["UID"]]
if vn[:public].to_i == 1
if vn['PUBLIC'].to_i == 1
public_str = "Y"
else
public_str = "N"

View File

@ -14,7 +14,6 @@
# limitations under the License. #
#--------------------------------------------------------------------------- #
require 'repo_manager'
require 'Configuration'
require 'OpenNebula'
require 'pp'
@ -32,7 +31,7 @@ class CloudServer
attr_reader :one_client
# Initializes the Cloud server based on a config file
# config_file:: _String_ for the server. MUST include the following
# config_file:: _String_ for the server. MUST include the following
# variables:
# USER
# PASSWORD
@ -44,7 +43,7 @@ class CloudServer
# --- Load the Cloud Server configuration file ---
@config = Configuration.new(config_file)
@instance_types = Hash.new
if @config[:vm_type].kind_of?(Array)
@ -55,13 +54,8 @@ class CloudServer
@instance_types[@config[:vm_type]['NAME']]=@config[:vm_type]
end
# --- Start a Repository Manager ---
@rm = RepoManager.new(@config[:database])
Image.image_dir = @config[:image_dir]
# --- Start an OpenNebula Session ---
@one_client = Client.new()
@user_pool = UserPool.new(@one_client)
end
@ -78,7 +72,7 @@ class CloudServer
puts "--------------------------------------"
puts " Registered Instance Types "
puts "--------------------------------------"
pp @instance_types
pp @instance_types
end
###########################################################################
@ -86,44 +80,22 @@ class CloudServer
###########################################################################
# Generates an OpenNebula Session for the given user
# user:: _Hash_ the user information
# [return] an OpenNebula client session
def one_client_user(user)
# user:: _Hash_ the user information
# [return] an OpenNebula client session
def one_client_user(name, password)
client = Client.new("dummy:dummy")
client.one_auth = "#{user[:name]}:#{user[:password]}"
client.one_auth = "#{name}:#{password}"
return client
end
# Authenticates a user
# name:: _String_ of the user
# password:: _String_ of the user
# [return] true if authenticated
def authenticate?(name, password)
user = get_user(name)
return user && user.password == password
end
# Gets the data associated with a user
# name:: _String_ the name of the user
# [return] _Hash_ with the user data
def get_user(name)
user = nil
def get_user_password(name)
@user_pool.info
@user_pool.each{ |u|
if u.name==name
user=Hash.new
user[:id] = u.id
user[:name] = u.name
user[:password] = u[:password]
end
}
return user
end
return @user_pool["USER[NAME=\"#{name}\"]/PASSWORD"]
end
###########################################################################
# Repository Methods
@ -134,18 +106,52 @@ class CloudServer
# path:: _String_ path of the tmp file
# metadata:: Additional metadata for the file
# [return] _Image_ Newly created image object
def add_image(uid, file, metadata={})
image = @rm.add(uid,file.path,metadata)
file.unlink
def add_image(image, file=nil)
if file
if file[:tempfile]
file_path = file[:tempfile].path
else
error_msg = "Image not present, aborting."
error = OpenNebula::Error.new(error_msg)
return error
end
return image
end
if !File.exists?(file_path)
error_msg = "Image file could not be found, aborting."
error = OpenNebula::Error.new(error_msg)
return error
end
end
# Gets an image from the repository
# image_id:: _Integer_ Image identifier
# [return] _Image_ Image object
def get_image(image_id)
return @rm.get(image_id)
# ---------- Allocate the Image file ------------
rc = image.allocate(image.to_one_template)
if OpenNebula.is_error?(rc)
return rc
end
# ---------- Copy the Image file ------------
image.info
if file_path
rc = image.copy(file_path, image['SOURCE'])
file[:tempfile].unlink
elsif image['TEMPLATE/SIZE'] and
image['TEMPLATE/FSTYPE'] and
image['TEMPLATE/TYPE'] == 'DATABLOCK'
rc = image.mk_datablock(
image['TEMPLATE/SIZE'],
image['TEMPLATE/FSTYPE'],
image['SOURCE'])
end
if OpenNebula.is_error?(rc)
image.delete
return rc
end
return nil
end
end

View File

@ -115,16 +115,21 @@ end
images = rc['imagesSet']['item']
fmt = "%-4s %-36s %s"
fmt = "%-8s %-20s %-30s %-40s %s"
if headers
puts fmt % ["Owner", "ImageId", "Location"]
puts fmt % ["Owner", "ImageId", "Status", "Visibility", "Location"]
puts "------------------------------------------------------------------------------"
end
if images
images.each { |img|
puts fmt % [img['imageOwnerId'],img['imageId'],img['imageLocation']]
if img['isPublic'] == 'true'
visibility = "public"
elsif img['isPublic'] == 'false'
visibility = "private"
end
puts fmt % [img['imageOwnerId'],img['imageId'], img['imageState'], visibility,img['imageLocation']]
}
end

View File

@ -1,7 +1,3 @@
# OpenNebula administrator user
USER=oneadmin
PASSWORD=<PUT HERE ONEADMIN PASS>
# OpenNebula sever contact information
ONE_XMLRPC=http://localhost:2633/RPC2
@ -12,9 +8,5 @@ PORT=4567
# SSL proxy that serves the API (set if is being used)
#SSL_SERVER=fqdm.of.the.server
# Configuration for the image repository
DATABASE=<PUT HERE ONELOCATION/var/econe.db
IMAGE_DIR=<PUT HERE PATH TO EXISTING IMAGE DIRECTORY>
# VM types allowed and its template file (inside templates directory)
VM_TYPE=[NAME=m1.small, TEMPLATE=m1.small.erb]

View File

@ -11,14 +11,11 @@ MEMORY = 256
# root = sda1,
# kernel_cmd = "ro xencons=tty console=tty1"]
DISK = [ source = <%= erb_vm_info[:img_path] %>,
clone = no,
target = sda1,
readonly = no]
DISK = [ IMAGE_ID = <%= erb_vm_info[:img_id] %> ]
NIC=[NETWORK="Public EC2"]
IMAGE_ID = <%= erb_vm_info[:img_id] %>
IMAGE_ID = <%= erb_vm_info[:ec2_img_id] %>
INSTANCE_TYPE = <%= erb_vm_info[:instance_type ]%>
<% if erb_vm_info[:user_data] %>

View File

@ -19,11 +19,14 @@ require 'sinatra'
require 'erb'
require 'time'
require 'AWS'
require 'CloudServer'
require 'base64'
require 'CloudServer'
require 'ImageEC2'
###############################################################################
# The EC2Query Server implements a EC2 compatible server based on the
# The EC2Query Server implements a EC2 compatible server based on the
# OpenNebula Engine
###############################################################################
class EC2QueryServer < CloudServer
@ -64,7 +67,7 @@ class EC2QueryServer < CloudServer
super(config_file)
@config.add_configuration_value("TEMPLATE_LOCATION",template)
@config.add_configuration_value("VIEWS",views)
if @config[:ssl_server]
@server_host=@config[:ssl_server]
else
@ -83,21 +86,165 @@ class EC2QueryServer < CloudServer
# EC2 protocol authentication function
# params:: of the request
# [return] true if authenticated
def authenticate?(params,env)
user = get_user(params['AWSAccessKeyId'])
return false if !user
def authenticate(params,env)
password = get_user_password(params['AWSAccessKeyId'])
return nil if !password
signature = case params['SignatureVersion']
when "1" then signature_version_1(params.clone, user[:password])
when "2" then signature_version_2(params,
user[:password],
when "1" then signature_version_1(params.clone, password)
when "2" then signature_version_2(params,
password,
env,
false)
end
return params['Signature']==signature
if params['Signature']==signature
return one_client_user(params['AWSAccessKeyId'], password)
else
return nil
end
end
###########################################################################
# Repository Interface
###########################################################################
def upload_image(params, one_client)
image = ImageEC2.new(Image.build_xml, one_client)
rc = add_image(image, params['file'])
if OpenNebula.is_error?(rc)
return OpenNebula::Error.new('Unsupported'),400
end
erb_version = params['Version']
response = ERB.new(File.read(@config[:views]+"/register_image.erb"))
return response.result(binding), 200
end
def register_image(params, one_client)
# Get the Image ID
tmp, img=params['ImageLocation'].split('-')
image = Image.new(Image.build_xml(img.to_i), one_client)
# Enable the new Image
rc = image.info
if OpenNebula.is_error?(rc)
return OpenNebula::Error.new('InvalidAMIID.NotFound'), 400
end
image.enable
erb_version = params['Version']
response = ERB.new(File.read(@config[:views]+"/register_image.erb"))
return response.result(binding), 200
end
def describe_images(params, one_client)
user_flag=-1
impool = ImagePool.new(one_client, user_flag)
impool.info
erb_user_name = params['AWSAccessKeyId']
erb_version = params['Version']
response = ERB.new(File.read(@config[:views]+"/describe_images.erb"))
return response.result(binding), 200
end
###########################################################################
# Instance Interface
###########################################################################
def run_instances(params, one_client)
# Get the instance type and path
if params['InstanceType'] != nil
instance_type_name = params['InstanceType']
instance_type = @instance_types[instance_type_name]
if instance_type != nil
path = @config[:template_location] + "/#{instance_type['TEMPLATE']}"
end
end
# Get the image
tmp, img=params['ImageId'].split('-')
# Build the VM
erb_vm_info=Hash.new
erb_vm_info[:img_id] = img.to_i
erb_vm_info[:ec2_img_id] = params['ImageId']
erb_vm_info[:instance_type] = instance_type_name
erb_vm_info[:template] = path
erb_vm_info[:user_data] = params['UserData']
template = ERB.new(File.read(erb_vm_info[:template]))
template_text = template.result(binding)
# Start the VM.
vm = VirtualMachine.new(VirtualMachine.build_xml, one_client)
rc = vm.allocate(template_text)
if OpenNebula::is_error?(rc)
return OpenNebula::Error.new('Unsupported'),400
end
vm.info
erb_vm_info[:vm_id]=vm.id
erb_vm_info[:vm]=vm
erb_user_name = params['AWSAccessKeyId']
erb_version = params['Version']
response = ERB.new(File.read(@config[:views]+"/run_instances.erb"))
return response.result(binding), 200
end
def describe_instances(params, one_client)
user_flag=-1
vmpool = VirtualMachinePool.new(one_client, user_flag)
vmpool.info
erb_version = params['Version']
erb_user_name = params['AWSAccessKeyId']
response = ERB.new(File.read(@config[:views]+"/describe_instances.erb"))
return response.result(binding), 200
end
def terminate_instances(params, one_client)
# Get the VM ID
vmid=params['InstanceId.1']
vmid=params['InstanceId.01'] if !vmid
tmp, vmid=vmid.split('-') if vmid[0]==?i
vm = VirtualMachine.new(VirtualMachine.build_xml(vmid),one_client)
rc = vm.info
return OpenNebula::Error.new('Unsupported'),400 if OpenNebula::is_error?(rc)
if vm.status == 'runn'
rc = vm.shutdown
else
rc = vm.finalize
end
return OpenNebula::Error.new('Unsupported'),400 if OpenNebula::is_error?(rc)
erb_version = params['Version']
response =ERB.new(File.read(@config[:views]+"/terminate_instances.erb"))
return response.result(binding), 200
end
private
# Calculates signature version 1
def signature_version_1(params, secret_key, digest='sha1')
params.delete('Signature')
@ -110,197 +257,47 @@ class EC2QueryServer < CloudServer
b64sig = Base64.b64encode(digest)
return b64sig.strip
end
# Calculates signature version 2
# Calculates signature version 2
def signature_version_2(params, secret_key, env, urlencode=true)
signature_params = params.reject { |key,value|
signature_params = params.reject { |key,value|
key=='Signature' or key=='file' }
server_str = @server_host
server_str = server_str + ":" + @server_port unless %w{2008-12-01 2009-11-30}.include? params["Version"]
server_str = @server_host
server_str = server_str + ":" + @server_port unless %w{2008-12-01 2009-11-30}.include? params["Version"]
canonical_str = AWS.canonical_string(signature_params,
server_str,
env['REQUEST_METHOD'])
canonical_str = AWS.canonical_string(signature_params,
server_str,
env['REQUEST_METHOD'])
# Use the correct signature strength
sha_strength = case params['SignatureMethod']
when "HmacSHA1" then 'sha1'
when "HmacSHA256" then 'sha256'
else 'sha1'
end
sha_strength = case params['SignatureMethod']
when "HmacSHA1" then 'sha1'
when "HmacSHA256" then 'sha256'
else 'sha1'
end
digest = OpenSSL::Digest::Digest.new(sha_strength)
b64hmac =
digest = OpenSSL::Digest::Digest.new(sha_strength)
b64hmac =
Base64.encode64(
OpenSSL::HMAC.digest(digest, secret_key, canonical_str)).gsub("\n","")
if urlencode
OpenSSL::HMAC.digest(digest, secret_key, canonical_str)).gsub("\n","")
if urlencode
return CGI::escape(b64hmac)
else
else
return b64hmac
end
end
###########################################################################
# Repository Interface
###########################################################################
def upload_image(params)
user = get_user(params['AWSAccessKeyId'])
image = add_image(user[:id],params["file"][:tempfile])
erb_img_id = image.id
erb_version = params['Version']
response = ERB.new(File.read(@config[:views]+"/register_image.erb"))
return response.result(binding), 200
end
def register_image(params)
user = get_user(params['AWSAccessKeyId'])
image = get_image(params['ImageLocation'])
if !image
return OpenNebula::Error.new('InvalidAMIID.NotFound'), 400
elsif user[:id] != image[:owner]
return OpenNebula::Error.new('AuthFailure'), 400
end
erb_img_id=image.id
erb_version = params['Version']
response = ERB.new(File.read(@config[:views]+"/register_image.erb"))
return response.result(binding), 200
end
def describe_images(params)
erb_user = get_user(params['AWSAccessKeyId'])
erb_images = Image.filter(:owner => erb_user[:id])
erb_version = params['Version']
response = ERB.new(File.read(@config[:views]+"/describe_images.erb"))
return response.result(binding), 200
end
###########################################################################
# Instance Interface
###########################################################################
def run_instances(params)
# Get the instance type
instance_type_name = params['InstanceType']
instance_type = @instance_types[instance_type_name]
return OpenNebula::Error.new('Unsupported'),400 if !instance_type
# Get the image
tmp, img=params['ImageId'].split('-')
image = get_image(img.to_i)
return OpenNebula::Error.new('InvalidAMIID.NotFound'),400 if !image
# Get the user
user = get_user(params['AWSAccessKeyId'])
one_client = one_client_user(user)
erb_user_name = user[:name]
# Build the VM
erb_vm_info=Hash.new
erb_vm_info[:img_path] = image.path
erb_vm_info[:img_id] = params['ImageId']
erb_vm_info[:instance_type] = instance_type_name
erb_vm_info[:template] = @config[:template_location] +
"/#{instance_type['TEMPLATE']}"
erb_vm_info[:user_data] = params['UserData']
template = ERB.new(File.read(erb_vm_info[:template]))
template_text = template.result(binding)
#Start the VM.
vm = VirtualMachine.new(VirtualMachine.build_xml, one_client)
rc = vm.allocate(template_text)
return OpenNebula::Error.new('Unsupported'),400 if OpenNebula::is_error?(rc)
vm.info
erb_vm_info[:vm_id]=vm.id
erb_vm_info[:vm]=vm
erb_version = params['Version']
response = ERB.new(File.read(@config[:views]+"/run_instances.erb"))
return response.result(binding), 200
end
def describe_instances(params)
# Get the user
user = get_user(params['AWSAccessKeyId'])
one_client = one_client_user(user)
erb_user_name = user[:name]
if user[:id]==0
user_flag=-2
else
user_flag=-1
end
erb_vmpool = VirtualMachinePool.new(one_client, user_flag)
erb_vmpool.info
erb_version = params['Version']
response = ERB.new(File.read(@config[:views]+"/describe_instances.erb"))
return response.result(binding), 200
end
def terminate_instances(params)
# Get the user
user = get_user(params['AWSAccessKeyId'])
one_client = one_client_user(user)
vmid=params['InstanceId.1']
vmid=params['InstanceId.01'] if !vmid
tmp, vmid=vmid.split('-') if vmid[0]==?i
erb_vm = VirtualMachine.new(VirtualMachine.build_xml(vmid),one_client)
rc = erb_vm.info
return OpenNebula::Error.new('Unsupported'),400 if OpenNebula::is_error?(rc)
if erb_vm.status == 'runn'
rc = erb_vm.shutdown
else
rc = erb_vm.finalize
end
return OpenNebula::Error.new('Unsupported'),400 if OpenNebula::is_error?(rc)
erb_version = params['Version']
response =ERB.new(File.read(@config[:views]+"/terminate_instances.erb"))
return response.result(binding), 200
end
private
###########################################################################
# Helper functions
###########################################################################
def render_state(vm)
ec2_state = EC2_STATES[ONE_STATES[vm.status]]
return "<code>#{ec2_state[:code]}</code>
return "<code>#{ec2_state[:code]}</code>
<name>#{ec2_state[:name]}</name>"
end

View File

@ -14,53 +14,22 @@
# limitations under the License. #
#--------------------------------------------------------------------------- #
require 'rubygems'
require 'fileutils'
require 'sequel'
require 'logger'
require 'uuid'
require 'OpenNebula'
module OpenNebula
class RepoManager
def initialize(rm_db=nil)
raise "DB not defined" if !rm_db
@db=Sequel.sqlite(rm_db)
include OpenNebula
require 'image'
Image.initialize_table
ImageAcl.initialize_table
end
def add(owner, path, metadata={})
Image.create_image(owner, path, metadata)
end
def get(image_id)
Image[:id => image_id]
end
def update(image_id, metadata)
image=get(image_id)
image.update(metadata)
end
end
class ImageEC2 < Image
end
=begin
OpenNebula::Image.create_image(10, 'repo_manager.rb',
:name => 'nombre',
:noexiste => 'nada'
)
=end
if $0 == __FILE__
rm=OpenNebula::RepoManager.new
img=rm.add_image(rand(100), 'image.rb',
:name => 'nombre',
:description => 'desc')
puts img.to_xml
end
ONE_IMAGE = %q{
NAME = "ec2-<%= uuid %>"
TYPE = OS
}.gsub(/^ /, '')
def to_one_template()
uuid = UUID.generate
one = ERB.new(ONE_IMAGE)
return one.result(binding)
end
end

View File

@ -59,7 +59,9 @@ set :port, $econe_server.config[:port]
##############################################################################
before do
if !$econe_server.authenticate?(params,env)
@client = $econe_server.authenticate(params,env)
if @client.nil?
error 400, error_xml("AuthFailure", 0)
end
end
@ -92,27 +94,28 @@ helpers do
end
post '/' do
do_http_request(params)
do_http_request(params, @client)
end
get '/' do
do_http_request(params)
do_http_request(params, @client)
end
def do_http_request(params)
def do_http_request(params, client)
case params['Action']
when 'UploadImage'
result,rc = $econe_server.upload_image(params)
result,rc = $econe_server.upload_image(params, client)
when 'RegisterImage'
result,rc = $econe_server.register_image(params)
result,rc = $econe_server.register_image(params, client)
when 'DescribeImages'
result,rc = $econe_server.describe_images(params)
result,rc = $econe_server.describe_images(params, client)
when 'RunInstances'
result,rc = $econe_server.run_instances(params)
result,rc = $econe_server.run_instances(params, client)
when 'DescribeInstances'
result,rc = $econe_server.describe_instances(params)
result,rc = $econe_server.describe_instances(params, client)
when 'TerminateInstances'
result,rc = $econe_server.terminate_instances(params)
result,rc = $econe_server.terminate_instances(params, client)
end
if OpenNebula::is_error?(result)

View File

@ -1,16 +1,25 @@
<?xml version="1.0"?>
<DescribeImagesResponse xmlns="http://ec2.amazonaws.com/doc/<%= erb_version %>/">
<imagesSet>
<% for image in erb_images %>
<item>
<imageId>ami-<%= sprintf('%08i', image.id) %></imageId>
<imageLocation><%= image.path.gsub(/^\//,'') %></imageLocation>
<imageState>available</imageState>
<imageOwnerId><%= erb_user[:name] %></imageOwnerId>
<isPublic>false</isPublic>
<architecture>i386</architecture>
<imageType>machine</imageType>
</item>
<% end %>
</imagesSet>
<DescribeImagesResponse xmlns="http://ec2.amazonaws.com/doc/<%=erb_version%>/">
<imagesSet>
<% impool.each do |im| %>
<% im.info %>
<item>
<imageId>ami-<%= sprintf('%08i', im.id) %></imageId>
<imageLocation><%= im['SOURCE'].split('/').last %></imageLocation>
<% if im['STATE'] == '4' %>
<imageState>deregistered</imageState>
<% elsif im['STATE'] == '2' %>
<imageState>available</imageState>
<% end %>
<imageOwnerId><%= erb_user_name %></imageOwnerId>
<% if im['PUBLIC'] == '0' %>
<isPublic>false</isPublic>
<% elsif im['PUBLIC'] == '1' %>
<isPublic>true</isPublic>
<% end %>
<architecture>i386</architecture>
<imageType>machine</imageType>
</item>
<% end %>
</imagesSet>
</DescribeImagesResponse>

View File

@ -11,7 +11,7 @@
</item>
</groupSet>
<instancesSet>
<% erb_vmpool.each do |vm| %>
<% vmpool.each do |vm| %>
<% vm.info %>
<item>
<instanceId>i-<%= vm.id %></instanceId>

View File

@ -1,3 +1,3 @@
<RegisterImageResponse xmlns="http://ec2.amazonaws.com/doc/<%= erb_version %>/">
<imageId><%= erb_img_id %></imageId>
<imageId>ami-<%= sprintf('%08i', image.id) %></imageId>
</RegisterImageResponse>

View File

@ -1,13 +1,13 @@
<TerminateInstancesResponse xmlns="http://ec2.amazonaws.com/doc/<%= erb_version %>/">
<instancesSet>
<item>
<instanceId>i-<%= erb_vm.id %></instanceId>
<instanceId>i-<%= vm.id %></instanceId>
<shutdownState>
<code>32</code>
<name>shutting-down</name>
</shutdownState>
<previousState>
<%= render_state(erb_vm) %>
<%= render_state(vm) %>
</previousState>
</item>
</instancesSet>

View File

@ -31,7 +31,7 @@ $: << RUBY_LIB_LOCATION+"/cloud"
COMMANDS_HELP=<<-EOT
** Synopsis
occi-storage
Manages OCCI storage resource
** Usage
@ -40,7 +40,7 @@ occi-storage <COMMAND> [OPTIONS] [PARAMETERS]
COMMANDS
create <occi xml file>
creates a new storage resource described by the provided
creates a new storage resource described by the provided
<occi xml file>
list
@ -81,8 +81,8 @@ EOT
require 'occi/OCCIClient'
require 'CloudClient'
require 'getoptlong'
require "rexml/document"
require 'rexml/document'
require 'pp'
include CloudCLI
opts = GetoptLong.new(
@ -120,12 +120,12 @@ begin
when '--debug'
debug = true
when '--multipart'
curb = false
curb = false
end
end
rescue Exception => e
exit(-1)
end
end
if !ARGV[0]
puts "#{cmd_name}: [COMMAND] not present"
@ -158,16 +158,22 @@ case ARGV[0].downcase
when 'show'
image_id = ARGV[1]
if !image_id
if !image_id
puts "#{cmd_name} show: missing storage id parameter"
exit(-1)
end
rc = occi_client.get_image(image_id)
when 'delete'
puts 'Delete not yet implemented'
exit(-1)
image_id = ARGV[1]
if !image_id
puts "#{cmd_name} show: missing storage id parameter"
exit(-1)
end
rc = occi_client.delete_image(image_id)
else
puts "Command #{ARGV[0]} not valid."
@ -176,22 +182,22 @@ end
if CloudClient::is_error?(rc)
puts rc.to_s()
else
else
begin
doc = REXML::Document.new(rc)
rescue REXML::ParseException => e
puts e.message
puts e.message
exit(-1)
end
xml = doc.root
if xml.nil?
puts rc
exit(-1)
end
str = ""
REXML::Formatters::Pretty.new(4).write(xml,str)
puts "\n" + str + "\n "
puts "\n" + str + "\n "
end

View File

@ -1,7 +1,3 @@
# OpenNebula administrator user
USER=oneadmin
PASSWORD=<PUT HERE ONEADMIN PASS>
# OpenNebula server contact information
ONE_XMLRPC=http://localhost:2633/RPC2
@ -12,18 +8,10 @@ PORT=4567
# SSL proxy that serves the API (set if is being used)
#SSL_SERVER=https://localhost:443
# Configuration for the image repository
DATABASE=<ONELOCATION>/var/occi.db
IMAGE_DIR=<PATH TO EXISTING IMAGE DIRECTORY>
# Configuration for OpenNebula's Virtual Networks
BRIDGE=<NAME OF DEFAULT BRIDGE>
# Default format for FS
FS_FORMAT=ext3
# VM types allowed and its template file (inside templates directory)
VM_TYPE=[NAME=small, TEMPLATE=small.erb]
VM_TYPE=[NAME=medium, TEMPLATE=medium.erb]
VM_TYPE=[NAME=large, TEMPLATE=large.erb]

View File

@ -1,55 +1,40 @@
NAME = <%= vm_info['NAME']%>
#
# Virtual Machine Template generated for large instance types. Adjust this
# by setting the desired capacity (CPU,MEMORY) or adding specific
# attributes for your cloud (e.g. OS). You should not need to change the DISK
# and NIC sections
#
CPU = 8
MEMORY = 8192
OS = [ kernel = /vmlinuz,
initrd = /initrd.img,
root = sda1,
kernel_cmd = "ro xencons=tty console=tty1"]
<% if vm_info['STORAGE']
vm_info['STORAGE'].each do |key, image|
image=[image].flatten
case key
when "SWAP"
image.each do |img|
%>
DISK = [ type = "swap",
size=<%= img['size']%>,
target=<%= img['dev']%> ]
<%
end
when "DISK"
image.each do |img|
%>
DISK = [ type = "disk",
target=<%= img['dev']%>,
source=<%= img['source']%>,
image_id=<%= img['image']%> ]
<%
end
when "FS"
image.each do |img|
%>
DISK = [ type = "fs",
target=<%= img['dev']%>,
size=<%= img['size']%>,
format=<%= @config[:fs_format]||"ext3"%> ]
<% end %>
<% end %>
<% end %>
<% end %>
<% if vm_info['NETWORK'] and vm_info['NETWORK']['NIC'] %>
<% vm_info['NETWORK']['NIC'].each do |nic| %>
NIC = [
<% if nic['ip'] %>
IP=<%= nic['ip'] %>,
<% end %>
NETWORK="<%= nic['network']%>",
NETWORK_ID=<%= nic['network_id'] %>
]
<% end %>
<% end %>
INSTANCE_TYPE = <%= vm_info[:instance_type ]%>
NAME = <%= @vm_info['NAME'] %>
<% if @vm_info['DISK'] %>
<% @vm_info.each('DISK') do |disk| %>
<% if disk['STORAGE'] && disk.attr('STORAGE','href') %>
DISK = [ IMAGE_ID = <%= disk.attr('STORAGE','href').split('/').last %>
<% if disk['OVERWRITE'] %>
,OVERWRITE = "yes"
<% end %>
<% if disk['SAVE_AS'] %>
,SAVE_AS = "<%= disk['SAVE_AS'] %>"
<% end %>
]
<% end %>
<% end %>
<% end %>
<% if @vm_info['NIC'] %>
<% @vm_info.each('NIC') do |nic| %>
<% if nic['NETWORK'] && nic.attr('NETWORK','href') %>
NIC = [ NETWORK_ID = <%= nic.attr('NETWORK','href').split('/').last %>
<% if nic['IP'] %>
,IP = <%= nic['IP'] %>
<% end %>
]
<% end %>
<% end %>
<% end %>
INSTANCE_TYPE = <%= @vm_info['INSTANCE_TYPE']%>

View File

@ -1,55 +1,41 @@
NAME = <%= vm_info['NAME']%>
#
# Virtual Machine Template generated for medium instance types. Adjust this
# by setting the desired capacity (CPU,MEMORY) or adding specific
# attributes for your cloud (e.g. OS). You should not need to change the DISK
# and NIC sections
#
CPU = 4
MEMORY = 4096
OS = [ kernel = /vmlinuz,
initrd = /initrd.img,
root = sda1,
kernel_cmd = "ro xencons=tty console=tty1"]
<% if vm_info['STORAGE']
vm_info['STORAGE'].each do |key, image|
image=[image].flatten
case key
when "SWAP"
image.each do |img|
%>
DISK = [ type = "swap",
size=<%= img['size']%>,
target=<%= img['dev']%> ]
<%
end
when "DISK"
image.each do |img|
%>
DISK = [ type = "disk",
target=<%= img['dev']%>,
source=<%= img['source']%>,
image_id=<%= img['image']%> ]
<%
end
when "FS"
image.each do |img|
%>
DISK = [ type = "fs",
target=<%= img['dev']%>,
size=<%= img['size']%>,
format=<%= @config[:fs_format]||"ext3"%> ]
<% end %>
<% end %>
<% end %>
<% end %>
<% if vm_info['NETWORK'] and vm_info['NETWORK']['NIC'] %>
<% vm_info['NETWORK']['NIC'].each do |nic| %>
NIC = [
<% if nic['ip'] %>
IP=<%= nic['ip'] %>,
<% end %>
NETWORK="<%= nic['network']%>",
NETWORK_ID=<%= nic['network_id'] %>
]
<% end %>
<% end %>
INSTANCE_TYPE = <%= vm_info[:instance_type ]%>
NAME = <%= @vm_info['NAME'] %>
<% if @vm_info['DISK'] %>
<% @vm_info.each('DISK') do |disk| %>
<% if disk['STORAGE'] && disk.attr('STORAGE','href') %>
DISK = [ IMAGE_ID = <%= disk.attr('STORAGE','href').split('/').last %>
<% if disk['OVERWRITE'] %>
,OVERWRITE = "yes"
<% end %>
<% if disk['SAVE_AS'] %>
,SAVE_AS = "<%= disk['SAVE_AS'] %>"
<% end %>
]
<% end %>
<% end %>
<% end %>
<% if @vm_info['NIC'] %>
<% @vm_info.each('NIC') do |nic| %>
<% if nic['NETWORK'] && nic.attr('NETWORK','href') %>
NIC = [ NETWORK_ID = <%= nic.attr('NETWORK','href').split('/').last %>
<% if nic['IP'] %>
,IP = <%= nic['IP'] %>
<% end %>
]
<% end %>
<% end %>
<% end %>
INSTANCE_TYPE = <%= @vm_info['INSTANCE_TYPE']%>

View File

@ -1,55 +1,41 @@
NAME = <%= vm_info['NAME']%>
#
# Virtual Machine Template generated for small instance types. Adjust this
# by setting the desired capacity (CPU,MEMORY) or adding specific
# attributes for your cloud (e.g. OS). You should not need to change the DISK
# and NIC sections
#
CPU = 1
MEMORY = 1024
OS = [ kernel = /vmlinuz,
initrd = /initrd.img,
root = sda1,
kernel_cmd = "ro xencons=tty console=tty1"]
<% if vm_info['STORAGE']
vm_info['STORAGE'].each do |key, image|
image=[image].flatten
case key
when "SWAP"
image.each do |img|
%>
DISK = [ type = "swap",
size=<%= img['size']%>,
target=<%= img['dev']%> ]
<%
end
when "DISK"
image.each do |img|
%>
DISK = [ type = "disk",
target=<%= img['dev']%>,
source=<%= img['source']%>,
image_id=<%= img['image']%> ]
<%
end
when "FS"
image.each do |img|
%>
DISK = [ type = "fs",
target=<%= img['dev']%>,
size=<%= img['size']%>,
format=<%= @config[:fs_format]||"ext3"%> ]
<% end %>
<% end %>
<% end %>
<% end %>
<% if vm_info['NETWORK'] and vm_info['NETWORK']['NIC'] %>
<% vm_info['NETWORK']['NIC'].each do |nic| %>
NIC = [
<% if nic['ip'] %>
IP=<%= nic['ip'] %>,
<% end %>
NETWORK="<%= nic['network']%>",
NETWORK_ID=<%= nic['network_id'] %>
]
<% end %>
<% end %>
INSTANCE_TYPE = <%= vm_info[:instance_type ]%>
NAME = <%= @vm_info['NAME'] %>
<% if @vm_info['DISK'] %>
<% @vm_info.each('DISK') do |disk| %>
<% if disk['STORAGE'] && disk.attr('STORAGE','href') %>
DISK = [ IMAGE_ID = <%= disk.attr('STORAGE','href').split('/').last %>
<% if disk['OVERWRITE'] %>
,OVERWRITE = "yes"
<% end %>
<% if disk['SAVE_AS'] %>
,SAVE_AS = "<%= disk['SAVE_AS'] %>"
<% end %>
]
<% end %>
<% end %>
<% end %>
<% if @vm_info['NIC'] %>
<% @vm_info.each('NIC') do |nic| %>
<% if nic['NETWORK'] && nic.attr('NETWORK','href') %>
NIC = [ NETWORK_ID = <%= nic.attr('NETWORK','href').split('/').last %>
<% if nic['IP'] %>
,IP = <%= nic['IP'] %>
<% end %>
]
<% end %>
<% end %>
<% end %>
INSTANCE_TYPE = <%= @vm_info['INSTANCE_TYPE']%>

View File

@ -15,24 +15,85 @@
#--------------------------------------------------------------------------- #
require 'OpenNebula'
require 'erb'
include OpenNebula
module ImageOCCI
class ImageOCCI < Image
OCCI_IMAGE = %q{
<DISK>
<ID><%= self.id %></ID>
<NAME><%= name %></NAME>
<SIZE><%= ((size/1024)/1024).to_s %></SIZE>
<URL><%= description %></URL>
</DISK>
<STORAGE href="<%= base_url %>/storage/<%= self.id.to_s %>">
<ID><%= self.id.to_s %></ID>
<NAME><%= self.name %></NAME>
<% if self['TEMPLATE/TYPE'] != nil %>
<TYPE><%= self['TEMPLATE/TYPE'] %></TYPE>
<% end %>
<% if self['TEMPLATE/DESCRIPTION'] != nil %>
<DESCRIPTION><%= self['TEMPLATE/DESCRIPTION'] %></DESCRIPTION>
<% end %>
<% if size != nil %>
<SIZE><%= size %></SIZE>
<% end %>
</STORAGE>
}
ONE_IMAGE = %q{
NAME = "<%= @image_info['NAME'] %>"
<% if @image_info['DESCRIPTION'] != nil %>
DESCRIPTION = "<%= @image_info['DESCRIPTION'] %>"
<% end %>
<% if @image_info['TYPE'] != nil %>
TYPE = <%= @image_info['TYPE'] %>
<% end %>
<% if @image_info['FSTYPE'] != nil %>
FSTYPE = <%= @image_info['FSTYPE'] %>
<% end %>
<% if @image_info['SIZE'] != nil %>
SIZE = <%= @image_info['SIZE'] %>
<% end %>
}.gsub(/^ /, '')
# Class constructor
def initialize(xml, client, xml_info=nil)
super(xml, client)
@image_info = nil
if xml_info != nil
xmldoc = XMLElement.build_xml(xml_info, 'STORAGE')
@image_info = XMLElement.new(xmldoc) if xmldoc != nil
end
end
# Creates the OCCI representation of an Image
def to_occi()
def to_occi(base_url)
size = nil
begin
if self['TEMPLATE/SOURCE'] != nil
size = File.stat(self['TEMPLATE/SOURCE']).size
end
rescue Exception => e
error = OpenNebula::Error.new(e.message)
return error
end
occi = ERB.new(OCCI_IMAGE)
return occi.result(binding).gsub(/\n\s*/,'')
end
def to_one_template()
if @image_info == nil
error_msg = "Missing STORAGE section in the XML body"
error = OpenNebula::Error.new(error_msg)
return error
end
if @image_info['NAME'] == nil
error_msg = "Missing Image NAME in the XML DISK section"
error = OpenNebula::Error.new(error_msg)
return error
end
one = ERB.new(ONE_IMAGE)
return one.result(binding)
end
end

View File

@ -16,25 +16,29 @@
require 'OpenNebula'
include OpenNebula
class ImagePoolOCCI
class ImagePoolOCCI < ImagePool
OCCI_IMAGE_POOL = %q{
<STORAGE><%
for image in @images do %>
<DISK href="<%= base_url%>/storage/<%= image[:id] %>"/><%
end %>
</STORAGE>
<STORAGE_COLLECTION>
<% self.each{ |im| %>
<STORAGE href="<%= base_url %>/storage/<%= im.id.to_s %>" name="<%= im.name %>"/>
<% } %>
</STORAGE_COLLECTION>
}
def initialize(user_id)
@images=Image.filter(:owner => user_id)
end
# Creates the OCCI representation of a Virtual Machine Pool
def to_occi(base_url)
occi = ERB.new(OCCI_IMAGE_POOL)
return occi.result(binding).gsub(/\n\s*/,'')
begin
occi = ERB.new(OCCI_IMAGE_POOL)
occi_text = occi.result(binding)
rescue Exception => e
error = OpenNebula::Error.new(e.message)
return error
end
return occi_text.gsub(/\n\s*/,'')
end
end

View File

@ -17,27 +17,27 @@
#--------------------------------------------------------------------------- #
require 'rubygems'
require 'crack'
require 'rexml/document'
require 'uri'
require 'CloudClient'
module OCCIClient
#####################################################################
# Client Library to interface with the OpenNebula OCCI Service
#####################################################################
class Client
class Client
######################################################################
# Initialize client library
######################################################################
def initialize(endpoint_str=nil, user=nil, pass=nil,
def initialize(endpoint_str=nil, user=nil, pass=nil,
timeout=nil, debug_flag=true)
@debug = debug_flag
@timeout = timeout
# Server location
if endpoint_str
@endpoint = endpoint_str
@ -46,25 +46,25 @@ module OCCIClient
else
@endpoint = "http://localhost:4567"
end
# Autentication
if user && pass
@occiauth = [user, pass]
else
@occiauth = CloudClient::get_one_auth
end
if !@occiauth
raise "No authorization data present"
end
@occiauth[1] = Digest::SHA1.hexdigest(@occiauth[1])
end
#################################
# Pool Resource Request Methods #
#################################
######################################################################
# Post a new VM to the VM Pool
# :instance_type
@ -72,14 +72,14 @@ module OCCIClient
######################################################################
def post_vms(xmlfile)
xml=File.read(xmlfile)
url = URI.parse(@endpoint+"/compute")
req = Net::HTTP::Post.new(url.path)
req.body=xml
req.basic_auth @occiauth[0], @occiauth[1]
res = CloudClient::http_start(url, @timeout) do |http|
http.request(req)
end
@ -90,88 +90,92 @@ module OCCIClient
return res.body
end
end
######################################################################
# Retieves the pool of Virtual Machines
######################################################################
def get_vms
url = URI.parse(@endpoint+"/compute")
req = Net::HTTP::Get.new(url.path)
req.basic_auth @occiauth[0], @occiauth[1]
res = CloudClient::http_start(url, @timeout) {|http|
http.request(req)
}
if CloudClient::is_error?(res)
return res
else
return res.body
end
end
######################################################################
# Post a new Network to the VN Pool
# :xmlfile xml description of the Virtual Network
######################################################################
def post_network(xmlfile)
xml=File.read(xmlfile)
url = URI.parse(@endpoint+"/network")
req = Net::HTTP::Post.new(url.path)
req.body=xml
req.basic_auth @occiauth[0], @occiauth[1]
res = CloudClient::http_start(url, @timeout) do |http|
http.request(req)
end
if CloudClient::is_error?(res)
return res
else
return res.body
end
end
######################################################################
# Retieves the pool of Virtual Networks
######################################################################
def get_networks
url = URI.parse(@endpoint+"/network")
req = Net::HTTP::Get.new(url.path)
req.basic_auth @occiauth[0], @occiauth[1]
res = CloudClient::http_start(url, @timeout) {|http|
http.request(req)
}
if CloudClient::is_error?(res)
return res
else
return res.body
end
end
######################################################################
# Post a new Image to the Image Pool
# :xmlfile
######################################################################
def post_image(xmlfile, curb=true)
xml=File.read(xmlfile)
image_info=Crack::XML.parse(xml)
file_path = image_info['DISK']['URL']
m=file_path.match(/^\w+:\/\/(.*)$/)
if m
xml = File.read(xmlfile)
image_info = REXML::Document.new(xml).root
if image_info.elements['URL'] == nil
return CloudClient::Error.new("Can not find URL")
end
file_path = image_info.elements['URL'].text
m = file_path.match(/^\w+:\/\/(.*)$/)
if m
file_path="/"+m[1]
end
if curb and CURL_LOADED
curl=Curl::Easy.new(@endpoint+"/storage")
@ -179,7 +183,7 @@ module OCCIClient
curl.userpwd = "#{@occiauth[0]}:#{@occiauth[1]}"
curl.verbose = true if @debug
curl.multipart_form_post = true
begin
curl.http_post(
Curl::PostField.content('occixml', xml),
@ -188,116 +192,46 @@ module OCCIClient
rescue Exception => e
return CloudClient::Error.new(e.message)
end
return curl.body_str
else
file=File.open(file_path)
params=Hash.new
params["file"]=UploadIO.new(file,
'application/octet-stream', file_path)
params['occixml'] = xml
url = URI.parse(@endpoint+"/storage")
req = Net::HTTP::Post::Multipart.new(url.path, params)
req.basic_auth @occiauth[0], @occiauth[1]
res = CloudClient::http_start(url, @timeout) do |http|
http.request(req)
end
file.close
pp res
if CloudClient::is_error?(res)
return res
else
return res.body
end
end
end
end
######################################################################
# Retieves the pool of Images owned by the user
######################################################################
def get_images
url = URI.parse(@endpoint+"/storage")
req = Net::HTTP::Get.new(url.path)
req.basic_auth @occiauth[0], @occiauth[1]
res = CloudClient::http_start(url, @timeout) {|http|
http.request(req)
}
if CloudClient::is_error?(res)
return res
else
return res.body
end
end
####################################
# Entity Resource Request Methods #
####################################
######################################################################
# :id VM identifier
######################################################################
def get_vm(id)
url = URI.parse(@endpoint+"/compute/" + id.to_s)
req = Net::HTTP::Get.new(url.path)
req.basic_auth @occiauth[0], @occiauth[1]
res = CloudClient::http_start(url, @timeout) {|http|
http.request(req)
}
if CloudClient::is_error?(res)
return res
else
return res.body
end
end
######################################################################
# Puts a new Compute representation in order to change its state
# :xmlfile Compute OCCI xml representation
######################################################################
def put_vm(xmlfile)
xml=File.read(xmlfile)
vm_info=Crack::XML.parse(xml)
url = URI.parse(@endpoint+'/compute/' + vm_info['COMPUTE']['ID'])
req = Net::HTTP::Put.new(url.path)
req.body = xml
req.basic_auth @occiauth[0], @occiauth[1]
res = CloudClient::http_start(url, @timeout) do |http|
http.request(req)
end
if CloudClient::is_error?(res)
return res
else
return res.body
end
end
####################################################################
# :id Compute identifier
####################################################################
def delete_vm(id)
url = URI.parse(@endpoint+"/compute/" + id.to_s)
req = Net::HTTP::Delete.new(url.path)
req.basic_auth @occiauth[0], @occiauth[1]
res = CloudClient::http_start(url, @timeout) {|http|
http.request(req)
}
@ -308,7 +242,83 @@ module OCCIClient
return res.body
end
end
####################################
# Entity Resource Request Methods #
####################################
######################################################################
# :id VM identifier
######################################################################
def get_vm(id)
url = URI.parse(@endpoint+"/compute/" + id.to_s)
req = Net::HTTP::Get.new(url.path)
req.basic_auth @occiauth[0], @occiauth[1]
res = CloudClient::http_start(url, @timeout) {|http|
http.request(req)
}
if CloudClient::is_error?(res)
return res
else
return res.body
end
end
######################################################################
# Puts a new Compute representation in order to change its state
# :xmlfile Compute OCCI xml representation
######################################################################
def put_vm(xmlfile)
xml = File.read(xmlfile)
vm_info = REXML::Document.new(xml).root
if vm_info.elements['ID'] == nil
return CloudClient::Error.new("Can not find VM_ID")
end
vm_id = vm_info.elements['ID'].text
url = URI.parse(@endpoint+'/compute/' + vm_id)
req = Net::HTTP::Put.new(url.path)
req.body = xml
req.basic_auth @occiauth[0], @occiauth[1]
res = CloudClient::http_start(url, @timeout) do |http|
http.request(req)
end
if CloudClient::is_error?(res)
return res
else
return res.body
end
end
####################################################################
# :id Compute identifier
####################################################################
def delete_vm(id)
url = URI.parse(@endpoint+"/compute/" + id.to_s)
req = Net::HTTP::Delete.new(url.path)
req.basic_auth @occiauth[0], @occiauth[1]
res = CloudClient::http_start(url, @timeout) {|http|
http.request(req)
}
if CloudClient::is_error?(res)
return res
else
return res.body
end
end
######################################################################
# Retrieves a Virtual Network
# :id Virtual Network identifier
@ -316,9 +326,9 @@ module OCCIClient
def get_network(id)
url = URI.parse(@endpoint+"/network/" + id.to_s)
req = Net::HTTP::Get.new(url.path)
req.basic_auth @occiauth[0], @occiauth[1]
res = CloudClient::http_start(url, @timeout) {|http|
http.request(req)
}
@ -329,16 +339,16 @@ module OCCIClient
return res.body
end
end
######################################################################
# :id VM identifier
######################################################################
def delete_network(id)
url = URI.parse(@endpoint+"/network/" + id.to_s)
req = Net::HTTP::Delete.new(url.path)
req.basic_auth @occiauth[0], @occiauth[1]
res = CloudClient::http_start(url, @timeout) {|http|
http.request(req)
}
@ -349,7 +359,7 @@ module OCCIClient
return res.body
end
end
#######################################################################
# Retieves an Image
# :image_uuid Image identifier
@ -357,9 +367,29 @@ module OCCIClient
def get_image(image_uuid)
url = URI.parse(@endpoint+"/storage/"+image_uuid)
req = Net::HTTP::Get.new(url.path)
req.basic_auth @occiauth[0], @occiauth[1]
res = CloudClient::http_start(url, @timeout) {|http|
http.request(req)
}
if CloudClient::is_error?(res)
return res
else
return res.body
end
end
######################################################################
# :id VM identifier
######################################################################
def delete_image(id)
url = URI.parse(@endpoint+"/storage/" + id.to_s)
req = Net::HTTP::Delete.new(url.path)
req.basic_auth @occiauth[0], @occiauth[1]
res = CloudClient::http_start(url, @timeout) {|http|
http.request(req)
}

View File

@ -31,473 +31,333 @@ require 'VirtualNetworkPoolOCCI'
require 'ImageOCCI'
require 'ImagePoolOCCI'
include ImageOCCI
require 'pp'
##############################################################################
# The OCCI Server provides an OCCI implementation based on the
# The OCCI Server provides an OCCI implementation based on the
# OpenNebula Engine
##############################################################################
class OCCIServer < CloudServer
# Server initializer
# config_file:: _String_ path of the config file
# template:: _String_ path to the location of the templates
# template:: _String_ path to the location of the templates
def initialize(config_file,template)
super(config_file)
@config.add_configuration_value("TEMPLATE_LOCATION",template)
if @config[:ssl_server]
@base_url=@config[:ssl_server]
else
@base_url="http://#{@config[:server]}:#{@config[:port]}"
end
print_configuration
end
# Authorization function
# requestenv:: _Hash_ Hash containing the environment of the request
# [return] _Boolean_ Whether the user is authorized or not
def authenticate?(requestenv)
auth ||= Rack::Auth::Basic::Request.new(requestenv)
if !(auth.provided? && auth.basic? && auth.credentials)
return false
end
user = get_user(requestenv, auth)
if user
if user[:password] == auth.credentials[1]
return true
end
else
return false
end
end
# Retrieve the user crendentials
# requestenv:: _Hash_ Hash containing the environment of the request
# [return] _User_ User structure
def get_user(requestenv, auth=nil)
auth = Rack::Auth::Basic::Request.new(requestenv) if !auth
super(auth.credentials.first)
end
# Retrieve a client with the user credentials
# requestenv:: _Hash_ Hash containing the environment of the request
# [return] _Client_ client with the user credentials
def get_client(requestenv)
user = get_user(requestenv)
return one_client_user(user)
end
###################################################
# Pool Resources methods
###################################################
# Post a new compute to the COMPUTE pool
# request:: _Hash_ hash containing the data of the request
# [return] _String_,_Integer_ COMPUTE Representation or error, status code
def post_compute(request)
# Get client with user credentials
client = get_client(request.env)
if request.body
vm_info=Crack::XML.parse(request.body.read)
else
error = OpenNebula::Error.new(
"OCCI XML representation of VM not present")
return error, 400
end
auth = Rack::Auth::Basic::Request.new(requestenv)
vm_info=vm_info['COMPUTE']
disks=vm_info['STORAGE']
disks['DISK']=[disks['DISK']].flatten if disks and disks['DISK']
disks['DISK'].each{|disk|
next if !disk['image']
image = get_image(disk['image'])
if !image
error = OpenNebula::Error.new(
"Invalid image (#{disk['image']}) referred")
return error, 400
end
disk['source']=image.path
} if disks and disks['DISK']
vm_info['STORAGE']=disks
if vm_info['NETWORK'] and vm_info['NETWORK']['NIC']
if vm_info['NETWORK']['NIC'].class==Array
nics=vm_info['NETWORK']['NIC']
else
nics=[vm_info['NETWORK']['NIC']]
end
nics.each{|nic|
next if nic==nil
vn=VirtualNetwork.new(
VirtualNetwork.build_xml(nic['network']),
client)
vn.info
vn_xml=Crack::XML.parse(vn.to_xml)
if !vn_xml['VNET']['NAME']
error = OpenNebula::Error.new(
"Invalid network referred")
return error, 400
end
nic['network_id']=nic['network']
nic['network']=vn_xml['VNET']['NAME'].strip
} if nics
vm_info['NETWORK']['NIC']=nics
end
instance_type_name=vm_info['INSTANCE_TYPE']
instance_type=@instance_types[instance_type_name]
if !instance_type
error = OpenNebula::Error.new("Bad instance type")
return error, 400
end
vm_info[:instance_type]=instance_type_name
template=ERB.new(File.read(
@config[:template_location]+"/#{instance_type['TEMPLATE']}"))
template_text=template.result(binding)
vm=VirtualMachineOCCI.new(
VirtualMachine.build_xml,
client)
response=vm.allocate(template_text)
if OpenNebula.is_error?(response)
return response, 400
else
vm.info
return vm.to_occi(@base_url), 201
end
return one_client_user(auth.credentials[0], auth.credentials[1])
end
# Prepare the OCCI XML Response
# resource:: _Pool_ or _PoolElement_ that represents a OCCI resource
# [return] _String_,_Integer_ Resource Representation or error, status code
def to_occi_xml(resource, code)
xml_response = resource.to_occi(@base_url)
return xml_response, 500 if OpenNebula.is_error?(xml_response)
return xml_response, code
end
############################################################################
############################################################################
# POOL RESOURCE METHODS
############################################################################
############################################################################
# Gets the pool representation of COMPUTES
# request:: _Hash_ hash containing the data of the request
# [return] _String_,_Integer_ Pool Representation or error, status code
def get_computes(request)
# Get client with user credentials
client = get_client(request.env)
# --- Get User's VMs ---
user_flag = -1
vmpool = VirtualMachinePoolOCCI.new(
get_client(request.env),
user_flag)
# Just show resources from the user making the request
user_flag = -1
# --- Prepare XML Response ---
rc = vmpool.info
return rc, 404 if OpenNebula.is_error?(rc)
vmpool = VirtualMachinePoolOCCI.new(client,user_flag)
vmpool.info
# OCCI conversion
begin
compute_xml = vmpool.to_occi(@base_url)
return compute_xml, 200
rescue Exception => e
error = OpenNebula::Error.new(e.message)
return error, 500
end
return to_occi_xml(vmpool, 200)
end
# Gets the pool representation of NETWORKS
# request:: _Hash_ hash containing the data of the request
# [return] _String_,_Integer_ Network pool representation or error,
# => status code
def get_networks(request)
# --- Get User's VNETs ---
user_flag = -1
network_pool = VirtualNetworkPoolOCCI.new(
get_client(request.env),
user_flag)
# --- Prepare XML Response ---
rc = network_pool.info
return rc, 404 if OpenNebula.is_error?(rc)
return to_occi_xml(network_pool, 200)
end
# Gets the pool representation of STORAGES
# request:: _Hash_ hash containing the data of the request
# [return] _String_,_Integer_ Image pool representation or error,
# status code
def get_storages(request)
# --- Get User's Images ---
user_flag = -1
image_pool = ImagePoolOCCI.new(
get_client(request.env),
user_flag)
# --- Prepare XML Response ---
rc = image_pool.info
return rc, 404 if OpenNebula.is_error?(rc)
return to_occi_xml(image_pool, 200)
end
############################################################################
############################################################################
# ENTITY RESOURCE METHODS
############################################################################
############################################################################
############################################################################
# COMPUTE Methods
############################################################################
# Post a new compute to the COMPUTE pool
# request:: _Hash_ hash containing the data of the request
# [return] _String_,_Integer_ COMPUTE Representation or error, status code
def post_compute(request)
# --- Create the new Instance ---
vm = VirtualMachineOCCI.new(
VirtualMachine.build_xml,
get_client(request.env),
request.body.read,
@instance_types,
@config[:template_location])
# --- Generate the template and Allocate the new Instance ---
template = vm.to_one_template
return template, 500 if OpenNebula.is_error?(template)
rc = vm.allocate(template)
return rc, 500 if OpenNebula.is_error?(rc)
# --- Prepare XML Response ---
vm.info
return to_occi_xml(vm, 201)
end
# Get the representation of a COMPUTE resource
# request:: _Hash_ hash containing the data of the request
# [return] _String_,_Integer_ COMPUTE representation or error,
# status code
def get_compute(request, params)
# --- Get the VM ---
vm = VirtualMachineOCCI.new(
VirtualMachine.build_xml(params[:id]),
get_client(request.env))
# --- Prepare XML Response ---
rc = vm.info
return rc, 404 if OpenNebula::is_error?(rc)
return to_occi_xml(vm, 200)
end
# Deletes a COMPUTE resource
# request:: _Hash_ hash containing the data of the request
# [return] _String_,_Integer_ Delete confirmation msg or error,
# status code
def delete_compute(request, params)
# --- Get the VM ---
vm = VirtualMachineOCCI.new(
VirtualMachine.build_xml(params[:id]),
get_client(request.env))
# --- Finalize the VM ---
result = vm.finalize
return result, 500 if OpenNebula::is_error?(result)
return "", 204
end
# Updates a COMPUTE resource
# request:: _Hash_ hash containing the data of the request
# [return] _String_,_Integer_ Update confirmation msg or error,
# status code
def put_compute(request, params)
xmldoc = XMLElement.build_xml(request.body, 'COMPUTE')
vm_info = XMLElement.new(xmldoc) if xmldoc != nil
# --- Get the VM and Action on it ---
if vm_info['STATE'] != nil
vm = VirtualMachineOCCI.new(
VirtualMachine.build_xml(params[:id]),
get_client(request.env))
rc = vm.mk_action(vm_info['STATE'])
return rc, 400 if OpenNebula.is_error?(rc)
else
error_msg = "State not defined in the OCCI XML"
error = OpenNebula::Error.new(error_msg)
return error, 400
end
# --- Prepare XML Response ---
vm.info
return to_occi_xml(vm, 202)
end
############################################################################
# NETWORK Methods
############################################################################
# Post a new network to the NETWORK pool
# request:: _Hash_ hash containing the data of the request
# [return] _String_,_Integer_ Network Representation or error, status code
def post_network(request)
# Get client with user credentials
client = get_client(request.env)
# Info retrieval from post params
if request.body
network_info=Crack::XML.parse(request.body.read)
else
error_msg = "OCCI XML representation of Virtual Network" +
" not present in the request"
error = OpenNebula::Error.new(error_msg)
return error, 400
end
# Allocate the VirtualNetwork
# --- Create the new Instance ---
network = VirtualNetworkOCCI.new(
VirtualNetwork.build_xml,
client)
get_client(request.env),
request.body,
@config[:bridge])
begin
vntemplate = network.to_one_template(
network_info['NETWORK'],
@config[:bridge])
rc = network.allocate(vntemplate)
# --- Generate the template and Allocate the new Instance ---
template = network.to_one_template
return template, 500 if OpenNebula.is_error?(template)
if OpenNebula::is_error?(rc)
return rc, 404
end
rc = network.allocate(template)
return rc, 500 if OpenNebula.is_error?(rc)
network.info
network_xml = network.to_occi
return network_xml, 201
rescue Exception => e
error_msg = "Error creating the Virtual Network:" + e.to_s
error_msg = ".Reason:" + rc if rc
error = OpenNebula::Error.new(error_msg)
return error, 500
end
# --- Prepare XML Response ---
network.info
return to_occi_xml(network, 201)
end
# Gets the pool representation of NETWORKS
# request:: _Hash_ hash containing the data of the request
# [return] _String_,_Integer_ Network pool representation or error,
# => status code
def get_networks(request)
# Get client with user credentials
client = get_client(request.env)
# Info retrieval
network_pool = VirtualNetworkPoolOCCI.new(client)
network_pool.info
# OCCI conversion
begin
network_pool.to_occi(@base_url)
rescue Exception => e
error = OpenNebula::Error.new(e.message)
return error, 500
end
end
# Post a new image to the STORAGE pool
# request:: _Hash_ hash containing the data of the request
# [return] _String_,_Integer_ Image representation or error, status code
def post_storage(request)
# Info retrieval from post params
if request.params['occixml']
image_info=Crack::XML.parse(request.params['occixml'])
else
error_msg = "OCCI XML representation of Image" +
" not present in the request"
error = OpenNebula::Error.new(error_msg)
return error, 400
end
if request.params['file']
file=request.params["file"]
else
error_msg = "File not present in the request"
error = OpenNebula::Error.new(error_msg)
return error, 400
end
user = get_user(request.env)
# tmpfile where the file is stored
f_tmp=file[:tempfile]
img=add_image(user[:id], f_tmp, {:name=>image_info['DISK']['NAME'],
:description=>image_info['DISK']['URL']})
img.extend(ImageOCCI)
xml_response = img.to_occi
return xml_response, 201
end
# Gets the pool representation of STORAGES
# request:: _Hash_ hash containing the data of the request
# [return] _String_,_Integer_ Image pool representation or error,
# status code
def get_storages(request)
# Retrieve images owned by this user
user = get_user(request.env)
image_pool = ImagePoolOCCI.new(user[:id])
return image_pool.to_occi(@base_url), 200
end
###################################################
# Entity Resources methods
###################################################
# Get the representation of a COMPUTE resource
# request:: _Hash_ hash containing the data of the request
# [return] _String_,_Integer_ COMPUTE representation or error,
# status code
def get_compute(request, params)
# Get client with user credentials
client = get_client(request.env)
vm = VirtualMachineOCCI.new(
VirtualMachine.build_xml(params[:id]),
client)
result=vm.info
if OpenNebula::is_error?(result)
return result, 404
end
begin
return vm.to_occi(@base_url), 200
rescue Exception => e
error_msg = "Error converting COMPUTE resource to OCCI format"
error_msg = "\n Reason: " + e.message
error = OpenNebula::Error.new(error_msg)
return error, 500
end
end
# Deletes a COMPUTE resource
# request:: _Hash_ hash containing the data of the request
# [return] _String_,_Integer_ Delete confirmation msg or error,
# status code
def delete_compute(request, params)
# Get client with user credentials
client = get_client(request.env)
vm = VirtualMachineOCCI.new(
VirtualMachine.build_xml(params[:id]),
client)
result = vm.finalize
if OpenNebula::is_error?(result)
return result, 500
else
return "", 204
end
end
# Updates a COMPUTE resource
# request:: _Hash_ hash containing the data of the request
# [return] _String_,_Integer_ Update confirmation msg or error,
# status code
def put_compute(request, params)
# Get client with user credentials
client = get_client(request.env)
if request.body
vm_info=Crack::XML.parse(request.body.read)
else
error_msg = "OCCI XML representation of VM not present"
error = OpenNebula::Error.new(error_msg)
return error, 400
end
vm=VirtualMachineOCCI.new(
VirtualMachine.build_xml(params[:id]),
client)
if !vm_info['COMPUTE']['STATE']
error_msg = "State not defined in the OCCI XML"
error = OpenNebula::Error.new(error_msg)
return error, 400
end
case vm_info['COMPUTE']['STATE'].downcase
when "stopped"
rc = vm.stop
when "suspended"
rc = vm.suspend
when "resume"
rc = vm.resume
when "cancel"
rc = vm.cancel
when "shutdown"
rc = vm.shutdown
when "done"
rc = vm.finalize
else
error_msg = "Invalid state"
error = OpenNebula::Error.new(error_msg)
return error, 400
end
if OpenNebula.is_error?(rc)
return rc, 400
else
vm.info
response_text = vm.to_occi(@base_url)
return response_text, 202
end
end
# Retrieves a NETWORK resource
# request:: _Hash_ hash containing the data of the request
# [return] _String_,_Integer_ NETWORK occi representation or error,
# status code
# [return] _String_,_Integer_ NETWORK occi representation or error,
# status code
def get_network(request, params)
# Get client with user credentials
client = get_client(request.env)
vn = VirtualNetworkOCCI.new(
VirtualNetwork.build_xml(params[:id]),
client)
result=vn.info
# --- Get the VNET ---
network = VirtualNetworkOCCI.new(
VirtualNetwork.build_xml(params[:id]),
get_client(request.env))
if OpenNebula::is_error?(result)
return result, 404
end
# --- Prepare XML Response ---
rc = network.info
return rc, 404 if OpenNebula::is_error?(rc)
begin
return vn.to_occi, 200
rescue Exception => e
error = OpenNebula::Error.new(e.message)
return error, 500
end
return to_occi_xml(network, 200)
end
# Deletes a NETWORK resource
# request:: _Hash_ hash containing the data of the request
# [return] _String_,_Integer_ Delete confirmation msg or error,
# status code
# [return] _String_,_Integer_ Delete confirmation msg or error,
# status code
def delete_network(request, params)
# Get client with user credentials
client = get_client(request.env)
vn = VirtualNetworkOCCI.new(
VirtualNetwork.build_xml(params[:id]),
client)
# --- Get the VNET ---
network = VirtualNetworkOCCI.new(
VirtualNetwork.build_xml(params[:id]),
get_client(request.env))
result = vn.delete
if OpenNebula::is_error?(result)
return result, 500
else
return "", 204
end
# --- Delete the VNET ---
rc = network.delete
return rc, 500 if OpenNebula::is_error?(rc)
return "", 204
end
############################################################################
# STORAGE Methods
############################################################################
# Post a new image to the STORAGE pool
# request:: _Hash_ hash containing the data of the request
# [return] _String_,_Integer_ Image representation or error, status code
def post_storage(request)
# --- Check OCCI XML from POST ---
if request.params['occixml'] == nil
error_msg = "OCCI XML representation of Image" +
" not present in the request"
error = OpenNebula::Error.new(error_msg)
return error, 400
end
# --- Create and Add the new Image ---
image = ImageOCCI.new(
Image.build_xml,
get_client(request.env),
request.params['occixml'])
rc = add_image(image, request.params['file'])
return rc, 500 if OpenNebula.is_error?(rc)
# --- Enable the new Image ---
rc = image.enable
return rc, 500 if OpenNebula.is_error?(rc)
# --- Prepare XML Response ---
return to_occi_xml(image, 201)
end
# Get a STORAGE resource
# request:: _Hash_ hash containing the data of the request
# [return] _String_,_Integer_ STORAGE occi representation or error,
# status code
# [return] _String_,_Integer_ STORAGE occi representation or error,
# status code
def get_storage(request, params)
# Get client with user credentials
client = get_client(request.env)
image=get_image(params[:id])
# --- Get the Image ---
image = ImageOCCI.new(
Image.build_xml(params[:id]),
get_client(request.env))
if image
image.extend(ImageOCCI)
return image.to_occi, 200
else
msg="Disk with id = \"" + params[:id] + "\" not found"
error = OpenNebula::Error.new(msg)
return error, 404
end
rc = image.info
return rc, 404 if OpenNebula::is_error?(rc)
# --- Prepare XML Response ---
return to_occi_xml(image, 200)
end
# Deletes a STORAGE resource (Not yet implemented)
# request:: _Hash_ hash containing the data of the request
# [return] _String_,_Integer_ Delete confirmation msg or error,
# status code
# [return] _String_,_Integer_ Delete confirmation msg or error,
# status code
def delete_storage(request, params)
error = OpenNebula::Error.new("Not yet implemented")
return error, 501
# --- Get the Image ---
image = ImageOCCI.new(
Image.build_xml(params[:id]),
get_client(request.env))
# --- Delete the Image ---
rc = image.delete
return rc, 500 if OpenNebula::is_error?(rc)
return "", 204
end
end

View File

@ -1,54 +1,139 @@
# -------------------------------------------------------------------------- #
# Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
require 'OpenNebula'
include OpenNebula
class VirtualMachineOCCI < VirtualMachine
OCCI_VM = %q{
<COMPUTE>
<ID><%= id.to_s%></ID>
<NAME><%= self['NAME']%></NAME>
<STATE><%= state_str %></STATE>
<% if template['DISK']!=nil
%><STORAGE><%
template['DISK'].each do |disk|
next if !disk
case disk['TYPE']
when "swap"%>
<DISK type="swap" size="<%= disk['SIZE']%>" dev="<%= disk['TARGET']%>"/><% when "fs" %>
<DISK type="fs" size="<%= disk['SIZE']%>" format="<%= disk['FORMAT']%>" dev="<%= disk['TARGET']%>"/><%
else %>
<DISK type="disk" href="<%= base_url%>/storage/<%= disk['IMAGE_ID']%>" dev="<%= disk['TARGET']%>"/><%
end
end %>
</STORAGE>
<% end
if template['NIC']
%><NETWORK><%
template['NIC'].each do |nic|
next if !nic %>
<NIC href="<%= base_url%>/network/<%= nic['VNID']%>"<% if nic['IP'] %> ip="<%= nic['IP']%>"<% end %>/><%
end
%>
</NETWORK><%
end
if template['INSTANCE_TYPE'] %>
<INSTANCE_TYPE><%=template['INSTANCE_TYPE']%></INSTANCE_TYPE><%
end %>
</COMPUTE>
<COMPUTE href="<%= base_url %>/compute/<%= self.id.to_s %>">
<ID><%= self.id.to_s%></ID>
<NAME><%= self.name%></NAME>
<% if self['TEMPLATE/INSTANCE_TYPE'] %>
<INSTANCE_TYPE><%= self['TEMPLATE/INSTANCE_TYPE'] %></INSTANCE_TYPE>
<% end %>
<STATE><%= self.state_str %></STATE>
<% if self['TEMPLATE/DISK'] %>
<% self.each('TEMPLATE/DISK') do |disk| %>
<DISK>
<STORAGE href="<%= base_url %>/storage/<%= disk['IMAGE_ID'] %>" name="<%= disk['IMAGE'] %>"/>
<TYPE><%= disk['TYPE'] %></TYPE>
<TARGET><%= disk['TARGET'] %></TARGET>
<% if disk['CLONE']=='NO' %>
<OVERWRITE/>
<% end %>
<% if disk['SAVE_AS'] %>
<SAVE_AS><%= disk['SAVE_AS'] %></SAVE_AS>
<% end %>
</DISK>
<% end %>
<% end %>
<% if self['TEMPLATE/NIC'] %>
<% self.each('TEMPLATE/NIC') do |nic| %>
<NIC>
<NETWORK href="<%= base_url %>/network/<%= nic['NETWORK_ID'] %>" name="<%= nic['NETWORK'] %>"/>
<% if nic['IP'] %>
<IP><%= nic['IP'] %></IP>
<% end %>
<% if nic['MAC'] %>
<MAC><%= nic['MAC'] %></MAC>
<% end %>
</NIC>
<% end %>
<% end %>
</COMPUTE>
}
# Class constructor
def initialize(xml, client, xml_info = nil, types=nil, base=nil)
super(xml, client)
@vm_info = nil
@template = nil
if xml_info != nil
xmldoc = XMLElement.build_xml(xml_info, 'COMPUTE')
@vm_info = XMLElement.new(xmldoc) if xmldoc != nil
end
if @vm_info != nil
itype = @vm_info['INSTANCE_TYPE']
if itype != nil and types[itype] != nil
@template = base + "/#{types[itype]['TEMPLATE']}"
end
end
end
def mk_action(action_str)
case action_str.downcase
when "stopped"
rc = self.stop
when "suspended"
rc = self.suspend
when "resume"
rc = self.resume
when "cancel"
rc = self.cancel
when "shutdown"
rc = self.shutdown
when "done"
rc = self.finalize
else
error_msg = "Invalid state"
error = OpenNebula::Error.new(error_msg)
return error
end
return rc
end
def to_one_template()
if @vm_info == nil
error_msg = "Missing COMPUTE section in the XML body"
return OpenNebula::Error.new(error_msg), 400
end
if @template == nil
return OpenNebula::Error.new("Bad instance type"), 500
end
begin
template = ERB.new(File.read(@template))
template_text = template.result(binding)
rescue Exception => e
error = OpenNebula::Error.new(e.message)
return error
end
return template_text
end
# Creates the VMI representation of a Virtual Machine
def to_occi(base_url)
# Let's parse the template
template=self.to_hash
template=template['VM']['TEMPLATE']
template['DISK']=[template['DISK']].flatten if template['DISK']
template['NIC']=[template['NIC']].flatten if template['NIC']
occi = ERB.new(OCCI_VM)
return occi.result(binding).gsub(/\n\s*/,'')
begin
occi_vm = ERB.new(OCCI_VM)
occi_vm_text = occi_vm.result(binding)
rescue Exception => e
error = OpenNebula::Error.new(e.message)
return error
end
return occi_vm_text.gsub(/\n\s*/,'')
end
end

View File

@ -1,26 +1,44 @@
# -------------------------------------------------------------------------- #
# Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
require 'OpenNebula'
include OpenNebula
class VirtualMachinePoolOCCI < VirtualMachinePool
OCCI_VM_POOL = %q{
<COMPUTES><%
if pool_hash['VM_POOL'] != nil
vmlist=[pool_hash['VM_POOL']['VM']].flatten
vmlist.each{|vm| %>
<COMPUTE href="<%= base_url %>/compute/<%= vm['ID'].strip %>"/><%
}
end %>
</COMPUTES>
<COMPUTE_COLLECTION>
<% self.each{ |vm| %>
<COMPUTE href="<%= base_url %>/compute/<%= vm.id.to_s %>" name="<%= vm.name %>"/>
<% } %>
</COMPUTE_COLLECTION>
}
# Creates the OCCI representation of a Virtual Machine Pool
def to_occi(base_url)
pool_hash=to_hash
occi = ERB.new(OCCI_VM_POOL)
return occi.result(binding).gsub(/\n\s*/,'')
begin
occi = ERB.new(OCCI_VM_POOL)
occi_text = occi.result(binding)
rescue Exception => e
error = OpenNebula::Error.new(e.message)
return error
end
return occi_text.gsub(/\n\s*/,'')
end
end

View File

@ -15,38 +15,64 @@
#--------------------------------------------------------------------------- #
require 'OpenNebula'
require 'erb'
include OpenNebula
class VirtualNetworkOCCI < VirtualNetwork
OCCI_NETWORK = %q{
<NETWORK>
<ID><%= vn_hash['VNET']['ID'].strip %></ID>
<NAME><%= vn_hash['VNET']['NAME'].strip %></NAME>
<ADDRESS><%= vn_hash['VNET']['TEMPLATE']['NETWORK_ADDRESS'].strip %></ADDRESS>
<SIZE><%= vn_hash['VNET']['TEMPLATE']['NETWORK_SIZE'].strip %></SIZE>
<NETWORK href="<%= base_url %>/network/<%= self.id.to_s %>">
<ID><%= self.id.to_s %></ID>
<NAME><%= self.name %></NAME>
<ADDRESS><%= self['TEMPLATE/NETWORK_ADDRESS'] %></ADDRESS>
<% if self['TEMPLATE/NETWORK_SIZE'] %>
<SIZE><%= self['TEMPLATE/NETWORK_SIZE'] %></SIZE>
<% end %>
</NETWORK>
}
ONE_NETWORK = %q{
NAME = <%= network_hash['NAME'] %>
NAME = <%= @vnet_info['NAME'] %>
TYPE = RANGED
BRIDGE = <%= bridge %>
NETWORK_ADDRESS = <%= network_hash['ADDRESS'] %>
NETWORK_SIZE = <%= network_hash['SIZE'] %>
<% if @bridge %>
BRIDGE = <%= @bridge %>
<% end %>
NETWORK_ADDRESS = <%= @vnet_info['ADDRESS'] %>
NETWORK_SIZE = <%= @vnet_info['SIZE']%>
}.gsub(/^ /, '')
# Creates the OCCI representation of a Virtual Network
def to_occi()
vn_hash = to_hash
# Class constructor
def initialize(xml, client, xml_info=nil, bridge=nil)
super(xml, client)
@bridge = bridge
@vnet_info = nil
occi = ERB.new(OCCI_NETWORK)
return occi.result(binding).gsub(/\n\s*/,'')
if xml_info != nil
xmldoc = XMLElement.build_xml(xml_info, 'NETWORK')
@vnet_info = XMLElement.new(xmldoc) if xmldoc != nil
end
end
def to_one_template(network_hash, bridge)
one = ERB.new(ONE_NETWORK)
return one.result(binding)
# Creates the OCCI representation of a Virtual Network
def to_occi(base_url)
begin
occi = ERB.new(OCCI_NETWORK)
occi_text = occi.result(binding)
rescue Exception => e
error = OpenNebula::Error.new(e.message)
return error
end
return occi_text.gsub(/\n\s*/,'')
end
def to_one_template()
if @vnet_info == nil
error_msg = "Missing NETWORK section in the XML body"
error = OpenNebula::Error.new(error_msg)
return error
end
one = ERB.new(ONE_NETWORK)
return one.result(binding)
end
end

View File

@ -1,25 +1,42 @@
# -------------------------------------------------------------------------- #
# Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
require 'OpenNebula'
include OpenNebula
class VirtualNetworkPoolOCCI < VirtualNetworkPool
OCCI_NETWORK_POOL = %q{
<NETWORKS><%
if network_pool_hash['VNET_POOL'] != nil
vnlist=[network_pool_hash['VNET_POOL']['VNET']].flatten
vnlist.each{|network|%>
<NETWORK href="<%= base_url %>/network/<%= network['ID'].strip
%>"/><%
}
end %>
</NETWORKS>
<NETWORK_COLLECTION>
<% self.each{ |vn| %>
<NETWORK href="<%= base_url %>/network/<%= vn.id.to_s %>" name="<%= vn.name %>"/>
<% } %>
</NETWORK_COLLECTION>
}
# Creates the OCCI representation of a Virtual Network
def to_occi(base_url)
network_pool_hash=to_hash
occi = ERB.new(OCCI_NETWORK_POOL)
return occi.result(binding).gsub(/\n\s*/,'')
# Creates the OCCI representation of a Virtual Machine Pool
def to_occi(base_url)begin
occi = ERB.new(OCCI_NETWORK_POOL)
occi_text = occi.result(binding)
rescue Exception => e
error = OpenNebula::Error.new(e.message)
return error
end
return occi_text.gsub(/\n\s*/,'')
end
end
end

View File

@ -15,7 +15,7 @@
#--------------------------------------------------------------------------- #
##############################################################################
# The OCCI Server provides compatible server based on the
# The OCCI Server provides compatible server based on the
# OpenNebula Engine
##############################################################################
@ -26,7 +26,7 @@ ONE_LOCATION=ENV["ONE_LOCATION"]
if !ONE_LOCATION
RUBY_LIB_LOCATION="/usr/lib/one/ruby"
TEMPLATE_LOCATION="/etc/one/occi_templates"
TEMPLATE_LOCATION="/etc/one/occi_templates"
CONFIGURATION_FILE = "/etc/one/occi-server.conf"
else
RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby"
@ -61,22 +61,15 @@ set :port, $occi_server.config[:port]
# Helpers
##############################################################################
# Authentication
before do
if !$occi_server.authenticate?(request.env)
halt 401, 'Invalid credentials'
end
end
# Response treatment
helpers do
def treat_response(result,rc)
if OpenNebula::is_error?(result)
halt rc, result.message
end
status rc
result
result
end
end
@ -88,12 +81,12 @@ end
# Pool Resources methods
###################################################
post '/compute' do
result,rc = $occi_server.post_compute(request)
post '/compute' do
result,rc = $occi_server.post_compute(request)
treat_response(result,rc)
end
get '/compute' do
get '/compute' do
result,rc = $occi_server.get_computes(request)
treat_response(result,rc)
end
@ -122,7 +115,7 @@ end
# Entity Resources Methods
###################################################
get '/compute/:id' do
get '/compute/:id' do
result,rc = $occi_server.get_compute(request, params)
treat_response(result,rc)
end
@ -134,20 +127,20 @@ end
put '/compute/:id' do
result,rc = $occi_server.put_compute(request, params)
treat_response(result,rc)
treat_response(result,rc)
end
get '/network/:id' do
get '/network/:id' do
result,rc = $occi_server.get_network(request, params)
treat_response(result,rc)
end
delete '/network/:id' do
result,rc = $occi_server.delete_network(request, params)
treat_response(result,rc)
treat_response(result,rc)
end
get '/storage/:id' do
get '/storage/:id' do
result,rc = $occi_server.get_storage(request, params)
treat_response(result,rc)
end

View File

@ -0,0 +1,5 @@
<NETWORK>
<NAME>MyServiceNetwork</NAME>
<ADDRESS>192.168.1.1</ADDRESS>
<SIZE>200</SIZE>
</NETWORK>

View File

@ -0,0 +1,6 @@
<STORAGE>
<NAME>Ubuntu Desktop</NAME>
<DESCRIPTION>Ubuntu 10.04 desktop for students.</DESCRIPTION>
<TYPE>OS</TYPE>
<URL>file:///images/ubuntu/jaunty.img</URL>
</STORAGE>

View File

@ -1,182 +0,0 @@
# -------------------------------------------------------------------------- #
# Copyright 2002-2010, 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 OpenNebula
class Image < Sequel::Model
plugin :schema
plugin :hook_class_methods
# Creates the database table asociated with the model. It first
# checks for table existence before creating it so it is reasonably
# safe to call it when you load the library.
def self.initialize_table
set_schema do
primary_key :id, :type => Integer
int :owner
varchar :name
varchar :description
varchar :path
int :size
varchar :md5
end
create_table unless table_exists?
end
# Makes sure the image is deleted from the repository after
# the record is deleted. Make sure that you use destroy and not
# delete as delete method does not call hooks.
before_destroy do
FileUtils.rm(self.path)
end
# Specifies the directory where images will be stored
# dir:: _String_ directory where the images are stored
def self.image_dir=(dir)
@@image_dir=dir
end
# Strips out non user writable columns
# metadata:: _Hash_ hash containing the data to add to the db
# [return] _Hash_ clean metadata
def self.sanitize_metadata(metadata)
metadata.reject {|key,value|
![:name, :description].include? key
}
end
# Creates a new Image object, fills it, copies the image
# to the repository and saves to the database
# owner:: _Integer_ identifier of the user that owns this image
# path:: _String_ place where to copy the image from
# metadata:: _Hash_ extra data to add to the image, like name and description
# [return] _Image_ newly created image
def self.create_image(owner, path, metadata={})
sanitized_metadata=sanitize_metadata(metadata)
data={
:owner => owner,
}.merge(sanitized_metadata)
image=Image.new(data)
image.save
# TODO: make copy or movement configurable
image.copy_image(path, true)
image.get_image_info
image.save
image
# set metadata
end
def identifier
self.id
end
# Updates the image with the metadata provided. Currently only
# name and description can be changed
def change_metadata(metadata)
update(Image.sanitize_metadata(metadata))
end
# Copies the image from the source path to the image repository.
# Its name will be the image id. It also stores its new location
# in the object.
def copy_image(path, move=false)
if move
FileUtils.mv(path, image_path)
else
FileUtils.cp(path, image_path)
end
self.path=image_path
end
# Returns the filename and path of the image file associated with
# this Image object.
def image_path
@@image_dir||='images'
File.join(@@image_dir, self.id.to_s)
end
# Extracts md5 and size from the image file and stores these data
# in the object.
def get_image_info
self.md5=`md5sum #{image_path}`.split.first
self.size=File.size(image_path)
end
# Adds a user to the list of allowed users of this image
def add_acl(user)
acl=ImageAcl.new({:image_id => self.id, :user => user})
acl.save
end
# Deletes a user fom the list of allowed users of this image
def del_acl(user)
acl=ImageAcl[:image_id => self.id, :user => user]
acl.destroy if acl
end
# Checks if a user has permissions to use this image
def has_permission?(user)
return true if self.owner==user
ImageAcl[:image_id => self.id, :user => user]!=nil
end
# Returns the xml representation of the image.
def to_xml
xml="<IMAGE>\n"
xml<<" <ID>#{id}</ID>\n"
xml<<" <OWNER>#{owner}</OWNER>\n"
xml<<" <NAME>#{name}</NAME>\n"
xml<<" <DESCRIPTION>#{description}</DESCRIPTION>\n"
xml<<" <PATH>#{path}</PATH>\n"
xml<<" <SIZE>#{size}</SIZE>\n"
xml<<" <MD5>#{md5}</MD5>\n"
xml<<"</IMAGE>\n"
end
# Like to_xml but does not show image file path data
def to_xml_lite
xml="<IMAGE>\n"
xml<<" <ID>#{id}</ID>\n"
xml<<" <OWNER>#{owner}</OWNER>\n"
xml<<" <NAME>#{name}</NAME>\n"
xml<<" <DESCRIPTION>#{description}</DESCRIPTION>\n"
xml<<" <SIZE>#{size}</SIZE>\n"
xml<<" <MD5>#{md5}</MD5>\n"
xml<<"</IMAGE>\n"
end
end
class ImageAcl < Sequel::Model
plugin :schema
def self.initialize_table
set_schema do
primary_key :id, :type => Integer
varchar :image_id
int :user
end
create_table unless table_exists?
end
end
end

View File

@ -27,7 +27,7 @@ module OpenNebula
user_xml = "<CLUSTER></CLUSTER>"
end
XMLUtilsElement.initialize_xml(user_xml, 'CLUSTER')
XMLElement.build_xml(user_xml,'CLUSTER')
end
# ---------------------------------------------------------------------

View File

@ -36,7 +36,7 @@ module OpenNebula
host_xml = "<HOST></HOST>"
end
XMLUtilsElement.initialize_xml(host_xml, 'HOST')
XMLElement.build_xml(host_xml, 'HOST')
end
#######################################################################
@ -91,7 +91,7 @@ module OpenNebula
SHORT_HOST_STATES[state_str]
end
# Returns the cluster of the Host
# Returns the cluster of the Host
def cluster
self['CLUSTER']
end
@ -103,7 +103,7 @@ module OpenNebula
rc = @client.call(HOST_METHODS[:enable], @pe_id, enabled)
rc = nil if !OpenNebula.is_error?(rc)
return rc
end
end

View File

@ -1,4 +1,5 @@
require 'OpenNebula/Pool'
require 'fileutils'
module OpenNebula
class Image < PoolElement
@ -14,7 +15,7 @@ module OpenNebula
:publish => "image.publish",
:delete => "image.delete"
}
IMAGE_STATES=%w{INIT LOCKED READY USED DISABLED}
SHORT_IMAGE_STATES={
@ -24,7 +25,7 @@ module OpenNebula
"USED" => "used",
"DISABLED" => "disa"
}
IMAGE_TYPES=%w{OS CDROM DATABLOCK}
SHORT_IMAGE_TYPES={
@ -47,7 +48,7 @@ module OpenNebula
image_xml = "<IMAGE></IMAGE>"
end
XMLUtilsElement.initialize_xml(image_xml, 'IMAGE')
XMLElement.build_xml(image_xml,'IMAGE')
end
# Class constructor
@ -55,12 +56,13 @@ module OpenNebula
super(xml,client)
@client = client
@immanager = ImageManager.new
end
#######################################################################
# XML-RPC Methods for the Image Object
#######################################################################
def info()
super(IMAGE_METHODS[:info], 'IMAGE')
end
@ -68,27 +70,27 @@ module OpenNebula
def allocate(description)
super(IMAGE_METHODS[:allocate],description)
end
def update(name, value)
super(IMAGE_METHODS[:update], name, value)
end
def remove_attr(name)
do_rm_attr(name)
end
def enable
set_enabled(true)
set_enabled(true)
end
def disable
set_enabled(false)
set_enabled(false)
end
def publish
set_publish(true)
end
def unpublish
set_publish(false)
end
@ -96,7 +98,19 @@ module OpenNebula
def delete()
super(IMAGE_METHODS[:delete])
end
def copy(path, source)
@immanager.copy(path, source)
end
def mk_datablock(size, fstype, source)
rc = @immanager.dd(size, source)
return rc if OpenNebula.is_error?(rc)
@immanager.mkfs(fstype, source)
end
#######################################################################
# Helpers to get Image information
#######################################################################
@ -115,7 +129,7 @@ module OpenNebula
def short_state_str
SHORT_IMAGE_STATES[state_str]
end
# Returns the type of the Image (numeric value)
def type
self['TYPE'].to_i
@ -129,9 +143,10 @@ module OpenNebula
# Returns the state of the Image (string value)
def short_type_str
SHORT_IMAGE_TYPES[type_str]
end
end
private
def set_enabled(enabled)
return Error.new('ID not defined') if !@pe_id
@ -140,7 +155,7 @@ module OpenNebula
return rc
end
def set_publish(published)
return Error.new('ID not defined') if !@pe_id
@ -149,15 +164,76 @@ module OpenNebula
return rc
end
def do_rm_attr(name)
return Error.new('ID not defined') if !@pe_id
rc = @client.call(IMAGE_METHODS[:rmattr], @pe_id, name)
rc = nil if !OpenNebula.is_error?(rc)
return rc
return rc
end
end
class ImageManager
# ---------------------------------------------------------------------
# Constants and Class Methods
# ---------------------------------------------------------------------
FS_UTILS = {
:dd => "/bin/dd",
:mkfs => "/bin/mkfs"
}
def copy(path, source)
if source.nil? or path.nil?
return OpenNebula::Error.new("copy Image: missing parameters.")
end
begin
FileUtils.copy(path, source)
rescue Exception => e
return OpenNebula::Error.new(e.message)
end
return nil
end
def dd(size, source)
if source.nil? or size.nil?
return OpenNebula::Error.new("dd Image: missing parameters.")
end
command = ""
command << FS_UTILS[:dd]
command << " if=/dev/zero of=#{source} ibs=1 count=1"
command << " obs=1048576 oseek=#{size}"
local_command=LocalCommand.run(command)
if local_command.code!=0
return OpenNebula::Error.new("dd Image: in dd command.")
end
return nil
end
def mkfs(fstype, source)
if source.nil? or fstype.nil?
return OpenNebula::Error.new("mkfs Image: missing parameters.")
end
command = ""
command << FS_UTILS[:mkfs]
command << " -t #{fstype} -F #{source}"
local_command=LocalCommand.run(command)
if local_command.code!=0
return OpenNebula::Error.new("mkfs Image: in mkfs command.")
end
return nil
end
end
end

View File

@ -2,9 +2,9 @@
module OpenNebula
# The Pool class represents a generic OpenNebula Pool in XML format
# and provides the basic functionality to handle the Pool elements
class Pool
class Pool < XMLPool
include Enumerable
include XMLUtilsPool
protected
@ -12,18 +12,19 @@ module OpenNebula
#element:: _String_ XML name of the Pool elements
#client:: _Client_ represents a XML-RPC connection
def initialize(pool,element,client)
super(nil)
@pool_name = pool.upcase
@element_name = element.upcase
@client = client
@xml = nil
@client = client
@hash = nil
end
# Default Factory Method for the Pools. The factory method returns an
# suitable PoolElement object. Each Pool MUST implement the
# suitable PoolElement object. Each Pool MUST implement the
# corresponding factory method
# element_xml:: _XML_ XML element describing the pool element
# element_xml:: _XML_ XML element describing the pool element
# [return] a PoolElement object
def factory(element_xml)
OpenNebula::PoolElement.new(element_xml,client)
@ -37,15 +38,15 @@ module OpenNebula
# representation in XML format
# xml_method:: _String_ the name of the XML-RPC method
# args:: _Array_ with additional arguments for the info call
# [return] nil in case of success or an Error object
# [return] nil in case of success or an Error object
def info(xml_method,*args)
rc = @client.call(xml_method,*args)
if !OpenNebula.is_error?(rc)
@xml = initialize_xml(rc)
initialize_xml(rc,@pool_name)
rc = nil
end
return rc
end
@ -63,23 +64,22 @@ module OpenNebula
str = ""
REXML::Formatters::Pretty.new(1).write(@xml,str)
return str
return str
end
end
# The PoolElement Class represents a generic element of a Pool in
# XML format
class PoolElement
include XMLUtilsElement
class PoolElement < XMLElement
protected
# node:: _XML_is a XML element that represents the Pool element
# node:: _XML_is a XML element that represents the Pool element
# client:: _Client_ represents a XML-RPC connection
def initialize(node, client)
@xml = node
@client = client
@hash = nil
if self['ID']
@pe_id = self['ID'].to_i
else
@ -96,16 +96,16 @@ module OpenNebula
# detailed information in XML format
# xml_method:: _String_ the name of the XML-RPC method
# root_element:: _String_ Base XML element
# [return] nil in case of success or an Error object
# [return] nil in case of success or an Error object
def info(xml_method, root_element)
return Error.new('ID not defined') if !@pe_id
rc = @client.call(xml_method,@pe_id)
if !OpenNebula.is_error?(rc)
@xml = XMLUtilsElement::initialize_xml(rc, root_element)
initialize_xml(rc, root_element)
rc = nil
@pe_id = self['ID'].to_i if self['ID']
@name = self['NAME'] if self['NAME']
end
@ -114,11 +114,11 @@ module OpenNebula
end
# Calls to the corresponding allocate method to create a new element
# in the OpenNebula core
# in the OpenNebula core
# xml_method:: _String_ the name of the XML-RPC method
# args:: _Array_ additional arguments including the template for the
# new element
# [return] nil in case of success or an Error object
# new element
# [return] nil in case of success or an Error object
def allocate(xml_method, *args)
rc = @client.call(xml_method, *args)
@ -129,13 +129,13 @@ module OpenNebula
return rc
end
# Calls to the corresponding update method to modify
# the object's template
# xml_method:: _String_ the name of the XML-RPC method
# name:: _String_ the name of the property to be modified
# value:: _String_ the new value of the property to be modified
# [return] nil in case of success or an Error object
# [return] nil in case of success or an Error object
def update(xml_method, name, value)
return Error.new('ID not defined') if !@pe_id
@ -146,9 +146,9 @@ module OpenNebula
end
# Calls to the corresponding delete method to remove this element
# from the OpenNebula core
# from the OpenNebula core
# xml_method:: _String_ the name of the XML-RPC method
# [return] nil in case of success or an Error object
# [return] nil in case of success or an Error object
def delete(xml_method)
return Error.new('ID not defined') if !@pe_id
@ -159,20 +159,20 @@ module OpenNebula
end
public
# Creates new element specifying its id
# id:: identifyier of the element
# client:: initialized OpenNebula::Client object
def self.new_with_id(id, client=nil)
self.new(self.build_xml(id), client)
end
# Returns element identifier
# [return] _Integer_ the PoolElement ID
# [return] _Integer_ the PoolElement ID
def id
@pe_id
end
# Gets element name
# [return] _String_ the PoolElement name
def name
@ -183,8 +183,8 @@ module OpenNebula
def to_str
str = ""
REXML::Formatters::Pretty.new(1).write(@xml,str)
return str
return str
end
end
end

View File

@ -25,7 +25,7 @@ module OpenNebula
user_xml = "<USER></USER>"
end
XMLUtilsElement.initialize_xml(user_xml, 'USER')
XMLElement.build_xml(user_xml, 'USER')
end
# ---------------------------------------------------------------------

View File

@ -12,9 +12,9 @@ module OpenNebula
:migrate => "vm.migrate",
:deploy => "vm.deploy"
}
VM_STATE=%w{INIT PENDING HOLD ACTIVE STOPPED SUSPENDED DONE FAILED}
LCM_STATE=%w{LCM_INIT PROLOG BOOT RUNNING MIGRATE SAVE_STOP SAVE_SUSPEND
SAVE_MIGRATE PROLOG_MIGRATE PROLOG_RESUME EPILOG_STOP EPILOG
SHUTDOWN CANCEL FAILURE DELETE UNKNOWN}
@ -72,8 +72,8 @@ module OpenNebula
else
vm_xml = "<VM></VM>"
end
XMLUtilsElement.initialize_xml(vm_xml, 'VM')
XMLElement.build_xml(vm_xml, 'VM')
end
def VirtualMachine.get_reason(reason)
@ -88,7 +88,7 @@ module OpenNebula
#######################################################################
def initialize(xml, client)
super(xml,client)
@element_name = "VM"
@client = client
end
@ -110,7 +110,7 @@ module OpenNebula
rc = @client.call(VM_METHODS[:deploy], @pe_id, host_id.to_i)
rc = nil if !OpenNebula.is_error?(rc)
return rc
end
@ -155,7 +155,7 @@ module OpenNebula
rc = @client.call(VM_METHODS[:migrate], @pe_id, host_id.to_i, false)
rc = nil if !OpenNebula.is_error?(rc)
return rc
end
@ -164,14 +164,14 @@ module OpenNebula
rc = @client.call(VM_METHODS[:migrate], @pe_id, host_id.to_i, true)
rc = nil if !OpenNebula.is_error?(rc)
return rc
end
#######################################################################
# Helpers to get VirtualMachine information
#######################################################################
# Returns the VM state of the VirtualMachine (numeric value)
def state
self['STATE'].to_i

View File

@ -26,7 +26,7 @@ module OpenNebula
vn_xml = "<VNET></VNET>"
end
XMLUtilsElement.initialize_xml(vn_xml, 'VNET')
XMLElement.build_xml(vn_xml, 'VNET')
end
# Class constructor
@ -39,7 +39,7 @@ module OpenNebula
#######################################################################
# XML-RPC Methods for the Virtual Network Object
#######################################################################
def info()
super(VN_METHODS[:info], 'VNET')
end
@ -47,11 +47,11 @@ module OpenNebula
def allocate(description)
super(VN_METHODS[:allocate],description)
end
def publish
set_publish(true)
end
def unpublish
set_publish(false)
end
@ -59,7 +59,7 @@ module OpenNebula
def delete()
super(VN_METHODS[:delete])
end
private
def set_publish(published)
return Error.new('ID not defined') if !@pe_id
@ -69,6 +69,6 @@ module OpenNebula
return rc
end
end
end

View File

@ -7,7 +7,7 @@ module OpenNebula
rescue LoadError
NOKOGIRI=false
end
# Require crack library if present, otherwise don't bother
# This is just for OCCI use
begin
@ -17,46 +17,109 @@ module OpenNebula
###########################################################################
# The XMLUtilsElement module provides an abstraction of the underlying
# XML parser engine. It provides XML-related methods for the Pool Elements
# XML parser engine. It provides XML-related methods for the Pool Elements
###########################################################################
module XMLUtilsElement
class XMLElement
def initialize(xml=nil)
@xml = xml
end
# Initialize a XML document for the element
# xml:: _String_ the XML document of the object
# root_element:: _String_ Base xml element
# [return] _XML_ object for the underlying XML engine
def self.initialize_xml(xml, root_element)
def initialize_xml(xml, root_element)
if NOKOGIRI
Nokogiri::XML(xml).xpath("/#{root_element}")
@xml = Nokogiri::XML(xml).xpath("/#{root_element}")
if @xml.size == 0
@xml = nil
end
else
REXML::Document.new(xml).root
@xml = REXML::Document.new(xml).root
if @xml.name != root_element
@xml = nil
end
end
end
# Builds a XML document
# xml:: _String_ the XML document of the object
# root_element:: _String_ Base xml element
# [return] _XML_ object for the underlying XML engine
def self.build_xml(xml, root_element)
if NOKOGIRI
doc = Nokogiri::XML(xml).xpath("/#{root_element}")
else
doc = REXML::Document.new(xml).root
end
return doc
end
# Extract an element from the XML description of the PoolElement.
# key::_String_ The name of the element
# [return] _String_ the value of the element
# [return] _String_ the value of the element
# Examples:
# ['VID'] # gets VM id
# ['HISTORY/HOSTNAME'] # get the hostname from the history
def [](key)
if NOKOGIRI
element=@xml.xpath(key.to_s.upcase)
element=@xml.xpath(key.to_s)
if element.size == 0
return nil
end
else
element=@xml.elements[key.to_s.upcase]
element=@xml.elements[key.to_s]
end
if element
if element
element.text
end
end
# Gets an attribute from an elemenT
# key:: _String_ xpath for the element
# name:: _String_ name of the attribute
def attr(key,name)
value = nil
if NOKOGIRI
element=@xml.xpath(key.to_s.upcase)
if element.size == 0
return nil
end
attribute = element.attr(name)
value = attribute.text if attribute != nil
else
element=@xml.elements[key.to_s.upcase]
value = element.attributes[name] if element != nil
end
return value
end
# Iterates over every Element in the XPath and calls the block with a
# a XMLElement
# block:: _Block_
def each(xpath_str,&block)
if NOKOGIRI
@xml.xpath(xpath_str).each { |pelem|
block.call XMLElement.new(pelem)
}
else
@xml.elements.each(xpath_str) { |pelem|
block.call XMLElement.new(pelem)
}
end
end
def template_str(indent=true)
template_like_str('TEMPLATE', indent)
end
def template_like_str(root_element, indent=true)
if NOKOGIRI
xml_template=@xml.xpath(root_element).to_s
@ -64,7 +127,7 @@ module OpenNebula
else
rexml=@xml.elements[root_element]
end
if indent
ind_enter="\n"
ind_tab=' '
@ -72,7 +135,7 @@ module OpenNebula
ind_enter=''
ind_tab=' '
end
str=rexml.collect {|n|
if n.class==REXML::Element
str_line=""
@ -93,13 +156,18 @@ module OpenNebula
str_line
end
}.compact.join("\n")
str
end
def to_hash
def to_hash
if !@hash && @xml
@hash=Crack::XML.parse(to_xml)
begin
@hash = Crack::XML.parse(to_xml)
rescue Exception => e
error = OpenNebula::Error.new(e.message)
return error
end
end
return @hash
end
@ -111,34 +179,26 @@ module OpenNebula
str = ""
if pretty
REXML::Formatters::Pretty.new(1).write(@xml,str)
else
else
REXML::Formatters::Default.new.write(@xml,str)
end
str
end
end
end
###########################################################################
# The XMLUtilsPool module provides an abstraction of the underlying
# XML parser engine. It provides XML-related methods for the Pools
# XML parser engine. It provides XML-related methods for the Pools
###########################################################################
module XMLUtilsPool
class XMLPool < XMLElement
#Initialize a XML document for the element
#xml:: _String_ the XML document of the object
#[return] _XML_ object for the underlying XML engine
def initialize_xml(xml)
if NOKOGIRI
Nokogiri::XML(xml).xpath("/#{@pool_name}")
else
xml=REXML::Document.new(xml).root
end
def initialize(xml=nil)
super(xml)
end
#Executes the given block for each element of the Pool
#block:: _Block_
#block:: _Block_
def each_element(block)
if NOKOGIRI
@xml.xpath(
@ -153,27 +213,14 @@ module OpenNebula
end
end
def to_xml(pretty=false)
if NOKOGIRI
@xml.to_xml
else
str = ""
if pretty
REXML::Formatters::Pretty.new(1).write(@xml,str)
else
REXML::Formatters::Default.new.write(@xml,str)
end
str
end
end
def to_hash
def to_hash
if !@hash && @xml
@hash=Crack::XML.parse(to_xml)
end
return @hash
end
end
end