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:
commit
f81e546629
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -15,7 +15,6 @@
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
require 'optparse'
|
||||
require 'pp'
|
||||
|
||||
class CommandParse
|
||||
|
||||
|
113
src/cli/onehost
113
src/cli/onehost
@ -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
|
||||
|
217
src/cli/oneimage
217
src/cli/oneimage
@ -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
|
||||
|
||||
|
@ -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]
|
||||
|
100
src/cli/onevm
100
src/cli/onevm
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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]
|
||||
|
@ -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] %>
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
@ -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)
|
||||
|
@ -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>
|
||||
|
@ -11,7 +11,7 @@
|
||||
</item>
|
||||
</groupSet>
|
||||
<instancesSet>
|
||||
<% erb_vmpool.each do |vm| %>
|
||||
<% vmpool.each do |vm| %>
|
||||
<% vm.info %>
|
||||
<item>
|
||||
<instanceId>i-<%= vm.id %></instanceId>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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]
|
||||
|
||||
|
@ -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']%>
|
@ -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']%>
|
||||
|
||||
|
@ -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']%>
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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
|
||||
|
5
src/cloud/occi/share/examples/network
Normal file
5
src/cloud/occi/share/examples/network
Normal file
@ -0,0 +1,5 @@
|
||||
<NETWORK>
|
||||
<NAME>MyServiceNetwork</NAME>
|
||||
<ADDRESS>192.168.1.1</ADDRESS>
|
||||
<SIZE>200</SIZE>
|
||||
</NETWORK>
|
6
src/cloud/occi/share/examples/storage
Normal file
6
src/cloud/occi/share/examples/storage
Normal 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>
|
@ -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
|
@ -27,7 +27,7 @@ module OpenNebula
|
||||
user_xml = "<CLUSTER></CLUSTER>"
|
||||
end
|
||||
|
||||
XMLUtilsElement.initialize_xml(user_xml, 'CLUSTER')
|
||||
XMLElement.build_xml(user_xml,'CLUSTER')
|
||||
end
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -25,7 +25,7 @@ module OpenNebula
|
||||
user_xml = "<USER></USER>"
|
||||
end
|
||||
|
||||
XMLUtilsElement.initialize_xml(user_xml, 'USER')
|
||||
XMLElement.build_xml(user_xml, 'USER')
|
||||
end
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user