diff --git a/src/cloud/common/CloudServer.rb b/src/cloud/common/CloudServer.rb index a76a6a5040..74b2d62985 100755 --- a/src/cloud/common/CloudServer.rb +++ b/src/cloud/common/CloudServer.rb @@ -14,7 +14,6 @@ # limitations under the License. # #--------------------------------------------------------------------------- # -require 'repo_manager' require 'Configuration' require 'OpenNebula' require 'pp' @@ -55,11 +54,6 @@ 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() @@ -124,6 +118,31 @@ class CloudServer return user end + def xml_to_hash(xml) + begin + hash = Crack::XML.parse(xml) + rescue Exception => e + error = OpenNebula::Error.new(e.message) + return error + end + + return hash + end + + def get_template_path(instance_type_name) + if instance_type_name.nil? + instance_type=@instance_types.first + end + + instance_type=@instance_types[instance_type_name] + + if !instance_type + error = OpenNebula::Error.new("Bad instance type") + return error + end + + return @config[:template_location]+"/#{instance_type['TEMPLATE']}" + end ########################################################################### # Repository Methods @@ -134,18 +153,58 @@ 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 + + if !File.exists?(file_path) + error_msg = "Image file could not be found, aborting." + error = OpenNebula::Error.new(error_msg) + return error + end + end + + template = image.to_one_template - return image + rc = image.allocate(template) + if OpenNebula.is_error?(rc) + return rc + end + + # Copy the Image file + image.info + template=image.to_hash + template=template['IMAGE']['TEMPLATE'] + + if file_path + rc = image.copy(file_path, image['SOURCE']) + file[:tempfile].unlink + elsif template['SIZE'] and template['FSTYPE'] + rc = image.mk_datablock( + template['SIZE'], + template['FSTYPE'], + image['SOURCE']) + end + + if OpenNebula.is_error?(rc) + image.delete + return rc + end + + return nil 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) + return nil end end diff --git a/src/cloud/occi/bin/occi-storage b/src/cloud/occi/bin/occi-storage index 3e6e2dbf0d..93b6436d3f 100755 --- a/src/cloud/occi/bin/occi-storage +++ b/src/cloud/occi/bin/occi-storage @@ -82,7 +82,7 @@ require 'occi/OCCIClient' require 'CloudClient' require 'getoptlong' require "rexml/document" - +require 'pp' include CloudCLI opts = GetoptLong.new( @@ -166,8 +166,14 @@ case ARGV[0].downcase 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." diff --git a/src/cloud/occi/etc/templates/large.erb b/src/cloud/occi/etc/templates/large.erb index b88a916363..cbc429b343 100644 --- a/src/cloud/occi/etc/templates/large.erb +++ b/src/cloud/occi/etc/templates/large.erb @@ -1,55 +1,34 @@ -NAME = <%= vm_info['NAME']%> - 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['DISK'].each do |disk| %> + <% if disk['STORAGE'] && disk['STORAGE']['href'] %> + DISK = [ IMAGE_ID = <%= disk['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['NIC'].each do |nic| %> + <% if nic['NETWORK'] && nic['NETWORK']['href'] %> + NIC = [ NETWORK_ID = <%= nic['NETWORK']['href'].split('/').last %>, + <% if nic['IP'] %> + IP = <%= nic['IP'] %> + <% end %> + ] + <% end %> + <% end %> +<% end %> + +INSTANCE_TYPE = <%= vm_info['INSTANCE_TYPE']%> diff --git a/src/cloud/occi/lib/ImageOCCI.rb b/src/cloud/occi/lib/ImageOCCI.rb index 781423a5c9..acee97b1eb 100755 --- a/src/cloud/occi/lib/ImageOCCI.rb +++ b/src/cloud/occi/lib/ImageOCCI.rb @@ -15,24 +15,82 @@ #--------------------------------------------------------------------------- # require 'OpenNebula' -require 'erb' include OpenNebula -module ImageOCCI +class ImageOCCI < Image OCCI_IMAGE = %q{ - <%= self.id %> - <%= name %> - <%= ((size/1024)/1024).to_s %> - <%= description %> + <%= self.id.to_s %> + <%= self.name %> + <% if template['TYPE'] %> + <%= template['TYPE'] %> + <% end %> + <% if template['DESCRIPTION'] %> + <%= template['DESCRIPTION'] %> + <% end %> + <% if size %> + <%= size %> + <% end %> } + ONE_IMAGE = %q{ + NAME = "<%= image_info['NAME'] %>" + <% if image_info['DESCRIPTION'] %> + DESCRIPTION = "<%= image_info['DESCRIPTION'] %>" + <% end %> + <% if image_info['TYPE'] %> + TYPE = <%= image_info['TYPE'] %> + <% end %> + <% if image_info['FSTYPE'] %> + FSTYPE = <%= image_info['FSTYPE'] %> + <% end %> + <% if image_info['SIZE'] %> + SIZE = <%= image_info['SIZE'] %> + <% end %> + }.gsub(/^ /, '') + + # Class constructor + def initialize(image_info, xml, client) + super(xml, client) + + @image_info = image_info + end + # Creates the OCCI representation of an Image def to_occi() + image_hash = self.to_hash + return image_hash, 500 if OpenNebula.is_error?(image_hash) + + template = image_hash['IMAGE']['TEMPLATE'] + begin + size = File.stat(template['SOURCE']).size if template['SOURCE'] + 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['STORAGE'] + image_info = @image_info['STORAGE'] + if !image_info['NAME'] + error_msg = "Missing Image NAME in the XML DISK section" + error = OpenNebula::Error.new(error_msg) + return error + end + else + error_msg = "Missing STORAGE section in the XML body" + error = OpenNebula::Error.new(error_msg) + return error + end + + one = ERB.new(ONE_IMAGE) + return one.result(binding) + end end diff --git a/src/cloud/occi/lib/ImagePoolOCCI.rb b/src/cloud/occi/lib/ImagePoolOCCI.rb index 596c139575..ebc73dd0b3 100755 --- a/src/cloud/occi/lib/ImagePoolOCCI.rb +++ b/src/cloud/occi/lib/ImagePoolOCCI.rb @@ -16,25 +16,35 @@ require 'OpenNebula' - include OpenNebula -class ImagePoolOCCI +class ImagePoolOCCI < ImagePool OCCI_IMAGE_POOL = %q{ - <% - for image in @images do %> - <% - end %> - + + <% if pool_hash['IMAGE_POOL'] && pool_hash['IMAGE_POOL']['IMAGE'] %> + <% imagelist=[pool_hash['IMAGE_POOL']['IMAGE']].flatten %> + <% imagelist.each{ |image| %> + + <% } %> + <% end %> + } - - 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*/,'') + pool_hash = self.to_hash + return pool_hash, 500 if OpenNebula.is_error?(pool_hash) + + 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 diff --git a/src/cloud/occi/lib/OCCIClient.rb b/src/cloud/occi/lib/OCCIClient.rb index ab94afe059..25e29edc74 100755 --- a/src/cloud/occi/lib/OCCIClient.rb +++ b/src/cloud/occi/lib/OCCIClient.rb @@ -164,7 +164,7 @@ module OCCIClient xml=File.read(xmlfile) image_info=Crack::XML.parse(xml) - file_path = image_info['DISK']['URL'] + file_path = image_info['STORAGE']['URL'] m=file_path.match(/^\w+:\/\/(.*)$/) @@ -210,7 +210,7 @@ module OCCIClient end file.close - + pp res if CloudClient::is_error?(res) return res else @@ -370,5 +370,25 @@ module OCCIClient 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) + } + + if CloudClient::is_error?(res) + return res + else + return res.body + end + end end end diff --git a/src/cloud/occi/lib/OCCIServer.rb b/src/cloud/occi/lib/OCCIServer.rb index 4e46eef40c..8b10e079fc 100755 --- a/src/cloud/occi/lib/OCCIServer.rb +++ b/src/cloud/occi/lib/OCCIServer.rb @@ -31,7 +31,7 @@ require 'VirtualNetworkPoolOCCI' require 'ImageOCCI' require 'ImagePoolOCCI' -include ImageOCCI +require 'pp' ############################################################################## @@ -102,153 +102,110 @@ class OCCIServer < CloudServer # 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 + # --- Get client with user credentials --- client = get_client(request.env) + # --- Check OCCI XML from POST --- if request.body - vm_info=Crack::XML.parse(request.body.read) + vm_info = xml_to_hash(request.body.read) + return vm_info, 400 if OpenNebula.is_error?(vm_info) else - error = OpenNebula::Error.new( - "OCCI XML representation of VM not present") + error_msg = "OCCI XML representation of VM not present" + error = OpenNebula::Error.new(error_msg) return error, 400 end - 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 + # --- Get Template Path --- + if vm_info['COMPUTE'] + template_path = get_template_path( + vm_info['COMPUTE']['INSTANCE_TYPE']) 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( + return template_path, 500 if OpenNebula.is_error?(template_path) + + vm_info['TEMPLATE_PATH'] = template_path + + # --- Create the new Instance --- + vm = VirtualMachineOCCI.new( + vm_info, 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 + # --- 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 + xml_response = vm.to_occi(@base_url) + return xml_response, 500 if OpenNebula.is_error?(xml_response) + + return xml_response, 201 end # 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 + # --- Get client with user credentials --- client = get_client(request.env) - # Just show resources from the user making the request + # --- Get User's VMs --- user_flag = -1 - - 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 + vmpool = VirtualMachinePoolOCCI.new(client, user_flag) + + rc = vmpool.info + return rc, 404 if OpenNebula.is_error?(rc) + + # --- Prepare XML Response --- + xml_response = vmpool.to_occi(@base_url) + return xml_response, 500 if OpenNebula.is_error?(xml_response) + + return xml_response, 201 end # 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 + # --- Get client with user credentials --- client = get_client(request.env) - - # Info retrieval from post params + + # --- Check OCCI XML from POST --- if request.body - network_info=Crack::XML.parse(request.body.read) + network_info = xml_to_hash(request.body.read) + return network_info, 400 if OpenNebula.is_error?(network_info) else - error_msg = "OCCI XML representation of Virtual Network" + - " not present in the request" - error = OpenNebula::Error.new(error_msg) - return error, 400 + error_msg = "OCCI XML representation of VNET not present" + error = OpenNebula::Error.new(error_msg) + return error, 400 end - # Allocate the VirtualNetwork + + if network_info['NETWORK'] + network_info['NETWORK']['BRIDGE'] = @config[:bridge] + end + + # --- Create the new Instance --- network = VirtualNetworkOCCI.new( - VirtualNetwork.build_xml, - client) + network_info, + VirtualNetwork.build_xml, + client) - 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 + xml_response = network.to_occi + return xml_response, 500 if OpenNebula.is_error?(xml_response) + + return xml_response, 201 end # Gets the pool representation of NETWORKS @@ -256,54 +213,52 @@ class OCCIServer < CloudServer # [return] _String_,_Integer_ Network pool representation or error, # => status code def get_networks(request) - # Get client with user credentials + # --- Get client with user credentials --- client = get_client(request.env) + + # --- Get User's VNETs --- + user_flag = -1 + network_pool = VirtualNetworkPoolOCCI.new(client, user_flag) - # 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 + rc = network_pool.info + return rc, 404 if OpenNebula.is_error?(rc) + + # --- Prepare XML Response --- + xml_response = network_pool.to_occi(@base_url) + return xml_response, 500 if OpenNebula.is_error?(xml_response) + + return xml_response, 201 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 + # Get client with user credentials + client = get_client(request.env) + + # --- Check OCCI XML from POST --- if request.params['occixml'] - image_info=Crack::XML.parse(request.params['occixml']) + image_info = xml_to_hash(request.params['occixml']) + return image_info, 400 if OpenNebula.is_error?(image_info) else error_msg = "OCCI XML representation of Image" + " not present in the request" - error = OpenNebula::Error.new(error_msg) + error = OpenNebula::Error.new(error_msg) return error, 400 end + + # --- Create and Add the new Image --- + image = ImageOCCI.new(image_info, Image.build_xml, client) - 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 + rc = add_image(image, request.params['file']) + return rc, 500 if OpenNebula.is_error?(rc) - return xml_response, 201 + # --- Enable the new Image --- + rc = image.enable + return rc, 500 if OpenNebula.is_error?(rc) + + return image.to_occi, 201 end # Gets the pool representation of STORAGES @@ -311,11 +266,21 @@ class OCCIServer < CloudServer # [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 + # --- Get client with user credentials --- + client = get_client(request.env) + + # --- Get User's Images --- + user_flag = -1 + image_pool = ImagePoolOCCI.new(client, user_flag) + + result = image_pool.info + return result, 404 if OpenNebula.is_error?(result) + + # --- Prepare XML Response --- + xml_response = image_pool.to_occi(@base_url) + return xml_response, 500 if OpenNebula.is_error?(xml_response) + + return xml_response, 201 end ################################################### @@ -327,27 +292,23 @@ class OCCIServer < CloudServer # [return] _String_,_Integer_ COMPUTE representation or error, # status code def get_compute(request, params) - # Get client with user credentials + # --- Get client with user credentials --- client = get_client(request.env) - + + # --- Get the VM --- vm = VirtualMachineOCCI.new( - VirtualMachine.build_xml(params[:id]), - client) + nil, + VirtualMachine.build_xml(params[:id]), + client) - result=vm.info + result = vm.info + return result, 404 if OpenNebula::is_error?(result) - 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 + # --- Prepare XML Response --- + xml_response = vm.to_occi(@base_url) + return xml_response, 500 if OpenNebula.is_error?(xml_response) + + return xml_response, 201 end # Deletes a COMPUTE resource @@ -355,20 +316,20 @@ class OCCIServer < CloudServer # [return] _String_,_Integer_ Delete confirmation msg or error, # status code def delete_compute(request, params) - # Get client with user credentials + # --- Get client with user credentials --- client = get_client(request.env) vm = VirtualMachineOCCI.new( + nil, VirtualMachine.build_xml(params[:id]), client) + # --- Finalize the VM --- result = vm.finalize + pp result + return result, 500 if OpenNebula::is_error?(result) - if OpenNebula::is_error?(result) - return result, 500 - else - return "", 204 - end + return "", 204 end # Updates a COMPUTE resource @@ -376,53 +337,40 @@ class OCCIServer < CloudServer # [return] _String_,_Integer_ Update confirmation msg or error, # status code def put_compute(request, params) - # Get client with user credentials + # --- Get client with user credentials --- client = get_client(request.env) - + + # --- Check OCCI XML from POST --- if request.body - vm_info=Crack::XML.parse(request.body.read) + vm_info = xml_to_hash(request.body.read) + return vm_info, 400 if OpenNebula.is_error?(vm_info) else error_msg = "OCCI XML representation of VM not present" - error = OpenNebula::Error.new(error_msg) + 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) + # --- Get the VM and Action on it --- + if vm_info['COMPUTE'] && vm_info['COMPUTE']['STATE'] + vm = VirtualMachineOCCI.new( + vm_info, + VirtualMachine.build_xml(params[:id]), + client) + + rc = vm.mk_action(vm_info['COMPUTE']['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 - - 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 + + # --- Prepare XML Response --- + vm.info + xml_response = vm.to_occi(@base_url) + return xml_response, 500 if OpenNebula.is_error?(xml_response) + + return xml_response, 202 end # Retrieves a NETWORK resource @@ -430,25 +378,23 @@ class OCCIServer < CloudServer # [return] _String_,_Integer_ NETWORK occi representation or error, # status code def get_network(request, params) - # Get client with user credentials + # --- Get client with user credentials --- client = get_client(request.env) + + # --- Get the VM --- + vn = VirtualNetworkOCCI.new( + nil, + VirtualNetwork.build_xml(params[:id]), + client) + + result = vn.info + return result, 404 if OpenNebula::is_error?(result) + + # --- Prepare XML Response --- + xml_response = vn.to_occi + return xml_response, 500 if OpenNebula.is_error?(xml_response) - vn = VirtualNetworkOCCI.new( - VirtualNetwork.build_xml(params[:id]), - client) - - result=vn.info - - if OpenNebula::is_error?(result) - return result, 404 - end - - begin - return vn.to_occi, 200 - rescue Exception => e - error = OpenNebula::Error.new(e.message) - return error, 500 - end + return xml_response, 200 end # Deletes a NETWORK resource @@ -456,20 +402,19 @@ class OCCIServer < CloudServer # [return] _String_,_Integer_ Delete confirmation msg or error, # status code def delete_network(request, params) - # Get client with user credentials + # --- Get client with user credentials --- client = get_client(request.env) vn = VirtualNetworkOCCI.new( + nil, VirtualNetwork.build_xml(params[:id]), client) - + + # --- Delete the VNET --- result = vn.delete - - if OpenNebula::is_error?(result) - return result, 500 - else - return "", 204 - end + return result, 500 if OpenNebula::is_error?(result) + + return "", 204 end # Get a STORAGE resource @@ -477,19 +422,20 @@ class OCCIServer < CloudServer # [return] _String_,_Integer_ STORAGE occi representation or error, # status code def get_storage(request, params) - # Get client with user credentials + # --- Get client with user credentials --- client = get_client(request.env) - - image=get_image(params[:id]) - 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 + # --- Get the Image --- + image = ImageOCCI.new(nil, Image.build_xml(params[:id]), client) + + result = image.info + return result, 404 if OpenNebula::is_error?(result) + + # --- Prepare XML Response --- + xml_response = image.to_occi + return xml_response, 500 if OpenNebula.is_error?(xml_response) + + return xml_response, 200 end # Deletes a STORAGE resource (Not yet implemented) @@ -497,7 +443,15 @@ class OCCIServer < CloudServer # [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 client with user credentials --- + client = get_client(request.env) + + image = ImageOCCI.new(nil, Image.build_xml(params[:id]), client) + + # --- Delete the Image --- + result = image.delete + return result, 500 if OpenNebula::is_error?(result) + + return "", 204 end end diff --git a/src/cloud/occi/lib/VirtualMachineOCCI.rb b/src/cloud/occi/lib/VirtualMachineOCCI.rb index 3b0923de50..1f9954cab6 100755 --- a/src/cloud/occi/lib/VirtualMachineOCCI.rb +++ b/src/cloud/occi/lib/VirtualMachineOCCI.rb @@ -1,3 +1,19 @@ +# -------------------------------------------------------------------------- # +# 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 @@ -5,50 +21,111 @@ include OpenNebula class VirtualMachineOCCI < VirtualMachine OCCI_VM = %q{ - <%= id.to_s%> - <%= self['NAME']%> - <%= state_str %> - <% if template['DISK']!=nil - %><% - template['DISK'].each do |disk| - next if !disk - case disk['TYPE'] - when "swap"%> - <% when "fs" %> - <% - else %> - <% - end - end %> - - <% end - if template['NIC'] - %><% - template['NIC'].each do |nic| - next if !nic %> - ip="<%= nic['IP']%>"<% end %>/><% - end - %> - <% - end - if template['INSTANCE_TYPE'] %> - <%=template['INSTANCE_TYPE']%><% - end %> + <%= self.id.to_s%> + <%= self.name%> + <% if template['INSTANCE_TYPE'] %> + <%= template['INSTANCE_TYPE'] %> + <% end %> + <%= self.state_str %> + <% if template['DISK'] %> + <% template['DISK'].each do |disk| %> + + + <%= disk['NAME'] %> + <%= disk['TYPE'] %> + <%= disk['TARGET'] %> + <% if disk['CLONE'] %> + + <% end %> + <% if disk['SAVE_AS'] %> + <%= disk['SAVE_AS'] %> + <% end %> + + <% end %> + <% end %> + <% if template['NIC'] %> + <% template['NIC'].each do |nic| %> + + + <% if nic['IP'] %> + <%= nic['IP'] %> + <% end %> + + <% end %> + <% end %> } + # Class constructor + def initialize(vm_info, xml, client) + super(xml, client) + + @vm_info = vm_info + 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['COMPUTE'] + vm_info = @vm_info['COMPUTE'] + vm_info['DISK'] = [vm_info['DISK']].flatten if vm_info['DISK'] + vm_info['NIC'] = [vm_info['NIC']].flatten if vm_info['NIC'] + else + error_msg = "Missing COMPUTE section in the XML body" + error = OpenNebula::Error.new(error_msg) + return error, 400 + end + + begin + template = ERB.new(File.read(@vm_info['TEMPLATE_PATH'])) + 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'] + vm_hash = self.to_hash + return vm_hash, 500 if OpenNebula.is_error?(vm_hash) + + template = vm_hash['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 diff --git a/src/cloud/occi/lib/VirtualMachinePoolOCCI.rb b/src/cloud/occi/lib/VirtualMachinePoolOCCI.rb index 2488f491b1..40f2910a0d 100755 --- a/src/cloud/occi/lib/VirtualMachinePoolOCCI.rb +++ b/src/cloud/occi/lib/VirtualMachinePoolOCCI.rb @@ -1,26 +1,50 @@ +# -------------------------------------------------------------------------- # +# 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{ - <% - if pool_hash['VM_POOL'] != nil - vmlist=[pool_hash['VM_POOL']['VM']].flatten - vmlist.each{|vm| %> - <% - } - end %> - + + <% if pool_hash['VM_POOL'] && pool_hash['VM_POOL']['VM'] %> + <% vmlist=[pool_hash['VM_POOL']['VM']].flatten %> + <% vmlist.each{ |vm| %> + + <% } %> + <% end %> + } # 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*/,'') + pool_hash = self.to_hash + return pool_hash, 500 if OpenNebula.is_error?(pool_hash) + + 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 diff --git a/src/cloud/occi/lib/VirtualNetworkOCCI.rb b/src/cloud/occi/lib/VirtualNetworkOCCI.rb index 7da7094b14..b2a46e415b 100755 --- a/src/cloud/occi/lib/VirtualNetworkOCCI.rb +++ b/src/cloud/occi/lib/VirtualNetworkOCCI.rb @@ -15,38 +15,64 @@ #--------------------------------------------------------------------------- # require 'OpenNebula' -require 'erb' include OpenNebula class VirtualNetworkOCCI < VirtualNetwork OCCI_NETWORK = %q{ - <%= vn_hash['VNET']['ID'].strip %> - <%= vn_hash['VNET']['NAME'].strip %> -
<%= vn_hash['VNET']['TEMPLATE']['NETWORK_ADDRESS'].strip %>
- <%= vn_hash['VNET']['TEMPLATE']['NETWORK_SIZE'].strip %> + <%= self.id.to_s %> + <%= self.name %> +
<%= template['NETWORK_ADDRESS'] %>
+ <% if template['NETWORK_SIZE'] %> + <%= template['NETWORK_SIZE'] %> + <% end %>
} 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'] %> + BRIDGE = <%= vnet_info['BRIDGE'] %> + 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(vnet_info, xml, client) + super(xml, client) - occi = ERB.new(OCCI_NETWORK) - return occi.result(binding).gsub(/\n\s*/,'') + @vnet_info = vnet_info 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() + vn_hash = self.to_hash + return vn_hash, 500 if OpenNebula.is_error?(vn_hash) + + template = vn_hash['VNET']['TEMPLATE'] + + 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['NETWORK'] + vnet_info = @vnet_info['NETWORK'] + else + error_msg = "Missing STORAGE 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 diff --git a/src/cloud/occi/lib/VirtualNetworkPoolOCCI.rb b/src/cloud/occi/lib/VirtualNetworkPoolOCCI.rb index 3f640e100a..da1941271a 100755 --- a/src/cloud/occi/lib/VirtualNetworkPoolOCCI.rb +++ b/src/cloud/occi/lib/VirtualNetworkPoolOCCI.rb @@ -1,25 +1,49 @@ +# -------------------------------------------------------------------------- # +# 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{ - <% - if network_pool_hash['VNET_POOL'] != nil - vnlist=[network_pool_hash['VNET_POOL']['VNET']].flatten - vnlist.each{|network|%> - <% - } - end %> - + + <% if pool_hash['VNET_POOL'] && pool_hash['VNET_POOL']['VNET'] %> + <% vnlist=[pool_hash['VNET_POOL']['VNET']].flatten %> + <% vnlist.each{ |vn| %> + + <% } %> + <% end %> + } - # 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) + pool_hash = self.to_hash + return pool_hash, 500 if OpenNebula.is_error?(pool_hash) + + 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 \ No newline at end of file diff --git a/src/cloud/occi/lib/occi-server.rb b/src/cloud/occi/lib/occi-server.rb index f42af095fa..81da9ce723 100755 --- a/src/cloud/occi/lib/occi-server.rb +++ b/src/cloud/occi/lib/occi-server.rb @@ -72,6 +72,8 @@ end helpers do def treat_response(result,rc) if OpenNebula::is_error?(result) + pp 'siiii' + pp rc halt rc, result.message end diff --git a/src/oca/ruby/OpenNebula/XMLUtils.rb b/src/oca/ruby/OpenNebula/XMLUtils.rb index 6ee470d0f3..a0dfe43539 100644 --- a/src/oca/ruby/OpenNebula/XMLUtils.rb +++ b/src/oca/ruby/OpenNebula/XMLUtils.rb @@ -99,7 +99,12 @@ module OpenNebula 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