From 506f996b1624e88dd3a973c0cee14531efb63b32 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Sat, 24 Sep 2011 19:37:27 +0200 Subject: [PATCH 1/9] feature #789: Refactor of OCA interaction in OZones. Work in progress --- src/ozones/Server/lib/OZones/Zones.rb | 148 ++++++++++++++++++-- src/ozones/Server/models/OzonesServer.rb | 165 ++++++++--------------- 2 files changed, 194 insertions(+), 119 deletions(-) diff --git a/src/ozones/Server/lib/OZones/Zones.rb b/src/ozones/Server/lib/OZones/Zones.rb index 6f4a2e167a..528ab3dfa3 100644 --- a/src/ozones/Server/lib/OZones/Zones.rb +++ b/src/ozones/Server/lib/OZones/Zones.rb @@ -19,25 +19,38 @@ module OZones class Zones include DataMapper::Resource include OpenNebulaJSON::JSONUtils - extend OpenNebulaJSON::JSONUtils - - property :id, Serial - property :name, String, :required => true, :unique => true - property :onename, String, :required => true - property :onepass, String, :required => true - property :endpoint, String, :required => true - property :sunsendpoint, String + extend OpenNebulaJSON::JSONUtils + + ####################################################################### + # Data Model for the Zone + ####################################################################### + property :id, Serial + property :name, String, :required => true, :unique => true + property :onename, String, :required => true + property :onepass, String, :required => true + property :endpoint, String, :required => true + property :sunsendpoint, String has n, :vdcs + ####################################################################### + # Constants + ####################################################################### + ZONE_ATTRS = [:onename, :onepass, :endpoint, :name] + + ####################################################################### + # JSON Functions + ####################################################################### def self.to_hash zonePoolHash = Hash.new zonePoolHash["ZONE_POOL"] = Hash.new zonePoolHash["ZONE_POOL"]["ZONE"] = Array.new unless self.all.empty? + self.all.each{|zone| zonePoolHash["ZONE_POOL"]["ZONE"] << zone.attributes.merge({:numbervdcs => zone.vdcs.all.size}) } + return zonePoolHash end @@ -45,11 +58,130 @@ module OZones zone_attributes = Hash.new zone_attributes["ZONE"] = attributes zone_attributes["ZONE"][:vdcs] = Array.new + self.vdcs.all.each{|vdc| zone_attributes["ZONE"][:vdcs]< e + return [404, OZones::Error.new(e.message).to_json] + end + else + error = OZones::Error.new("Error: #{kind} resource view " \ + "not supported") + rc = [ 404, error.to_json ] end - # TODO build the vdc retrieval - - if kind == "zone" - client = OpenNebula::Client.new( - resource.onename + ":" + resource.onepass, - resource.endpoint, - false) - - simple_pool = case aggkind - when "host" then OpenNebulaJSON::HostPoolJSON.new(client) - when "image" then OpenNebulaJSON::ImagePoolJSON.new(client) - when "user" then OpenNebulaJSON::UserPoolJSON.new(client) - when "vm" then OpenNebulaJSON::VirtualMachinePoolJSON.new(client) - when "vn","vnet" then OpenNebulaJSON::VirtualNetworkPoolJSON.new(client) - when "template","vmtemplate" then OpenNebulaJSON::TemplatePoolJSON.new(client) - else - error = OZones::Error.new( - "Error: #{aggkind} aggregated pool for #{kind} #{id} not supported") - return [404, error.to_json] - end - - simple_pool.info - - return [200, simple_pool.to_json] - end + return rc end # Get a json representation resource with local (DB) info def get_resource(kind, id) resource = retrieve_resource(kind, id) + if OZones.is_error?(resource) return [404, resource.to_json] else @@ -109,25 +89,6 @@ class OzonesServer end end - # Get hold of a object of a particular kind - def retrieve_resource(kind, id) - resource = case kind - when "vdc" then OZones::Vdc.get(id) - when "zone" then OZones::Zones.get(id) - else - return OZones::Error.new( - "Error: #{kind} resource not supported") - end - - if resource - return resource - else - return OZones::Error.new( - "Error: Resource #{kind} with id #{id} not found") - end - end - - ############################################################################ # Create resources ############################################################################ @@ -218,47 +179,14 @@ class OzonesServer end when "zone" then - zone_data=Hash.new - data.each{|key,value| - zone_data[key.downcase.to_sym]=value if key!="pool" - } - - mandatory_params = [:onename, :onepass, :endpoint, :name] - - mandatory_params.each { |param| - if !zone_data[param] - return [400, OZones::Error.new( - "Error: Couldn't create resource #{kind}. " + - "Mandatory attribute '#{param}' is missing.").to_json] - end - } - - # Digest and check credentials - zone_data[:onepass] = - Digest::SHA1.hexdigest(zone_data[:onepass]) - - rc = @ocaInt.check_oneadmin(zone_data[:onename], - zone_data[:onepass], - zone_data[:endpoint]) - - if OpenNebula.is_error?(rc) - return [400, OZones::Error.new( - "Error: Couldn't create resource #{kind}. Reason: "+ - rc.message).to_json] - end - - # Create the zone zone = OZones::Zones.create(zone_data) - rc = zone.save - if rc - pr.update # Rewrite proxy conf file - return [200, zone.to_json] - else - return [400, OZones::Error.new( - "Error: Couldn't create resource #{kind.upcase}." + - " Maybe duplicated name?").to_json] + if OZones.is_error?(zone) + return [400, zone.to_json] end + + pr.update + return [200, zone.to_json] else error = OZones::Error.new( "Error: #{kind.upcase} resource not supported") @@ -375,9 +303,7 @@ class OzonesServer end end - ############################################################################ - # Helper functions - ############################################################################ + private # Check if hosts are already include in any Vdc of the zone def host_uniqueness?(zone, host_list, vdc_id = -1) @@ -397,5 +323,22 @@ class OzonesServer return true end + # Get hold of a object of a particular kind + def retrieve_resource(kind, id) + rc = case kind + when "vdc" then + OZones::Vdc.get(id) + when "zone" then + OZones::Zones.get(id) + else + OZones::Error.new("Error: #{kind} resource not supported") + end + + if rc + return rc + else + return OZones::Error.new("Error: #{kind} with id #{id} not found") + end + end end From 2787cd8fb4d451915c07218d2a36fb6aa1f633e6 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Sun, 25 Sep 2011 00:31:48 +0200 Subject: [PATCH 2/9] feature #789: Solves minor bugs in Zones --- src/ozones/Server/models/OzonesServer.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ozones/Server/models/OzonesServer.rb b/src/ozones/Server/models/OzonesServer.rb index 5345549e16..11210ac54f 100644 --- a/src/ozones/Server/models/OzonesServer.rb +++ b/src/ozones/Server/models/OzonesServer.rb @@ -64,7 +64,7 @@ class OzonesServer case kind when "zone" begin - zone = OpenNebulaZone.new(id) + zone = OZones::OpenNebulaZone.new(id) rc = zone.pool_to_json(aggkind) rescue => e return [404, OZones::Error.new(e.message).to_json] @@ -179,7 +179,7 @@ class OzonesServer end when "zone" then - zone = OZones::Zones.create(zone_data) + zone = OZones::Zones.create(data) if OZones.is_error?(zone) return [400, zone.to_json] From fc6303a14ce6fa46e5648c1f4a20f82b8d4f15e5 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Sun, 25 Sep 2011 03:31:53 +0200 Subject: [PATCH 3/9] feature #789: Moved OCAInteration to VDC class. Update method still needs to be moved --- src/ozones/Server/lib/OZones/VDC.rb | 289 +++++++++++++++++++---- src/ozones/Server/lib/OZones/Zones.rb | 4 +- src/ozones/Server/models/OzonesServer.rb | 165 ++++++------- 3 files changed, 314 insertions(+), 144 deletions(-) diff --git a/src/ozones/Server/lib/OZones/VDC.rb b/src/ozones/Server/lib/OZones/VDC.rb index bdc23b1ae7..9e51df6da4 100644 --- a/src/ozones/Server/lib/OZones/VDC.rb +++ b/src/ozones/Server/lib/OZones/VDC.rb @@ -25,6 +25,7 @@ module OZones property :name, String, :required => true, :unique => true property :group_id, Integer property :vdcadminname, String, :required => true + property :vdcadmin_id, Integer property :acls, String property :hosts, String @@ -46,52 +47,6 @@ module OZones return vdc_attributes end - ####################################################################### - # Methods to handle the ACL list - ####################################################################### - # The ID of the first host ACL - HOST_ACL_FIRST_ID = 3 - - # This method returns an Array of ACL strings to create them - # in the target zone - def get_vdc_acls_str(user_id, group_id) - rule_str = Array.new - - # Grant permissions to the group - rule_str << "@#{group_id} VM+NET+IMAGE+TEMPLATE/* " \ - "CREATE+INFO_POOL_MINE" - - # Grant permissions to the vdc admin - rule_str << "##{user_id} USER/* CREATE" - rule_str << "##{user_id} USER/@#{group_id} MANAGE+DELETE+INFO" - - ############################################################### - #When more rules are added the class constant HOST_ACL_FIRST_ID - #must be modified - ############################################################### - - rule_str.concat(self.get_host_acls_str(group_id)) - end - - def get_host_acls_str(group_id, host_list = nil) - rule_str = Array.new - - if host_list == nil - host_list = self.hosts - end - - # Grant permissions to use the vdc hosts - host_list.split(',').each{|hostid| - rule_str << "@#{group_id} HOST/##{hostid} USE" - } - - return rule_str - end - - def get_host_acls - self.acls.split(',')[HOST_ACL_FIRST_ID..-1].collect!{|x| x.to_i} - end - # Returns the host acls as an array of strings. # The acls of the VDC are updated and the host acl ids removed def get_host_acls!(new_host_acls = nil) @@ -111,4 +66,246 @@ module OZones return acl_ids end end + + ########################################################################### + # This class represents a VDC able to interact with its supporting + # OpenNebula installation through OCA. Data persistence is provided by a + # Vdc class + ########################################################################### + class OpenNebulaVdc + ####################################################################### + # Constants + ####################################################################### + VDC_ATTRS = [:vdcadminname, :vdcadminpass, :name, :hosts] + + attr_reader :vdc + + #Creates an OpenNebula VDC, using its ID, vdcid and the associated zone + def initialize(vdcid, zone = nil) + if vdcid != -1 + @vdc = Vdc.get(vdcid) + + if !@vdc + raise "Error: VDC with id #{vdcid} not found" + end + + zone = OZones::Zones.get(@vdc.zones_id) + end + + @client = OpenNebula::Client.new( + "#{zone.onename}:#{zone.onepass}", + zone.endpoint, + false) + end + + ####################################################################### + # + ####################################################################### + def create(vdc_data) + #Check and prepare VDC data + VDC_ATTRS.each { |param| + if !vdc_data[param] + return OZones::Error.new("Error: Couldn't create vdc." \ + "Mandatory attribute '#{param}' is missing.") + end + } + + #Create a vdc record + @vdc = Vdc.new + @vdc.raise_on_save_failure = true + + vdcpass = Digest::SHA1.hexdigest(vdc_data.delete(:vdcadminpass)) + @vdc.attributes = vdc_data + puts vdc_data + + # Create a group in the zone with the VDC name + group = OpenNebula::Group.new(OpenNebula::Group.build_xml, @client) + rc = group.allocate(@vdc.name) + + return rc if OpenNebula.is_error?(rc) + + @vdc.group_id = group.id + + # Create the VDC admin user in the Zone + user = OpenNebula::User.new(OpenNebula::User.build_xml, @client) + rc = user.allocate(@vdc.vdcadminname, vdcpass) + + return rollback(group, nil, nil, rc) if OpenNebula.is_error?(rc) + + @vdc.vdcadmin_id = user.id + + # Change primary group of the admin user to the VDC group + rc = user.chgrp(group.id) + return rollback(group, user, nil, rc) if OpenNebula.is_error?(rc) + + # Add ACLs + aclp = OpenNebula::AclPool.new(@client) + rules = get_acls + + acls_str = "" + + rules.each{ |rule_str| + acl = OpenNebula::Acl.new(OpenNebula::Acl.build_xml,@client) + rc = acl.allocate(*OpenNebula::Acl.parse_rule(rule_str)) + + if OpenNebula.is_error?(rc) + return rollback(group, user, acls_str, rc) + end + + acls_str << acl.id.to_s << "," + } + + @vdc.acls = acls_str.chop + + return true + end + + def destroy + # Delete the resources from the VDC + delete_images + delete_templates + delete_vms + delete_vns + delete_acls + + # Delete users from a group + up = OpenNebula::UserPool.new(@client) + up.info + + up.each{|user| + if user['GID'].to_i == @vdc.group_id + user.delete + end + } + + # Delete the group + rc = OpenNebula::Group.new_with_id(@vdc.group_id, @client).delete + + if OpenNebula.is_error?(rc) + return rc + else + return @vdc.destroy + end + end + + private + ####################################################################### + # Functions to generate ACL Strings + ####################################################################### + # The ID of the first host ACL + HOST_ACL_FIRST_ID = 3 + + # This method returns an Array of ACL strings to create them + # in the target zone + def get_acls + rule_str = Array.new + + # Grant permissions to the group + rule_str << "@#{@vdc.group_id} VM+NET+IMAGE+TEMPLATE/* " \ + "CREATE+INFO_POOL_MINE" + + # Grant permissions to the vdc admin + rule_str << "##{@vdc.vdcadmin_id} USER/* CREATE" + rule_str << "##{@vdc.vdcadmin_id} USER/@#{@vdc.group_id} " \ + "MANAGE+DELETE+INFO" + + ############################################################### + #When more rules are added the class constant HOST_ACL_FIRST_ID + #must be modified + ############################################################### + + rule_str.concat(get_host_acls) + end + + def get_host_acls(host_list = nil) + rule_str = Array.new + + if host_list == nil + host_list = @vdc.hosts + end + + # Grant permissions to use the vdc hosts + host_list.split(',').each{|hostid| + rule_str << "@#{@vdc.group_id} HOST/##{hostid} USE" + } + + return rule_str + end + + ####################################################################### + # Functions to delete resources associated to the VDC + ####################################################################### + # Deletes ACLs for the hosts + def delete_host_acls + @vdc.acls.split(',')[HOST_ACL_FIRST_ID..-1].each{|acl| + OpenNebula::Acl.new_with_id(acl.to_i, @client).delete + } + end + + # Delete ACLs + def delete_acls + @vdc.acls.split(",").each{|acl| + OpenNebula::Acl.new_with_id(acl.to_i, @client).delete + } + end + + # Deletes images + def delete_images + ip = OpenNebula::ImagePool.new(@client) + ip.info + + ip.each{|image| + image.delete if image['GID'].to_i == @vdc.group_id + } + end + + # Deletes templates + def delete_templates + tp = OpenNebula::TemplatePool.new(@client) + tp.info + + tp.each{|template| + template.delete if template['GID'].to_i == @vdc.group_id + } + end + + # Deletes VMs + def delete_vms + vmp = OpenNebula::VirtualMachinePool.new(@client) + vmp.info + + vmp.each{|vm| + vm.delete if vm['GID'].to_i == @vdc.group_id + } + end + + # Deletes VNs + def delete_vns + vnp = OpenNebula::VirtualNetworkPool.new(@client) + vnp.info + + vnp.each{|vn| + vnp.delete if vn['GID'].to_i == @vdc.group_id + } + end + + ####################################################################### + # Misc helper functions for the class + ####################################################################### + + # Deletes resources from failed created VDC + def rollback(group, user, acls, rc) + group.delete + user.delete if user + + if acls + acls.chop + acls.split(",").each{|acl| + OpenNebula::Acl.new_with_id(acl.to_i, @client).delete + } + end + + return rc + end + end end diff --git a/src/ozones/Server/lib/OZones/Zones.rb b/src/ozones/Server/lib/OZones/Zones.rb index 528ab3dfa3..59e8878005 100644 --- a/src/ozones/Server/lib/OZones/Zones.rb +++ b/src/ozones/Server/lib/OZones/Zones.rb @@ -109,7 +109,7 @@ module OZones end ########################################################################### - # This class represents a Zone with able to interact with its supporting + # This class represents a Zone able to interact with its supporting # OpenNebula installation through OCA. Data persistence is provided by a # Zones class ########################################################################## @@ -118,7 +118,7 @@ module OZones @zone = Zones.get(zoneid) if !@zone - raise "Error: Resource zone with id #{zoneid} not found" + raise "Error: Zone with id #{zoneid} not found" end @client = OpenNebula::Client.new( diff --git a/src/ozones/Server/models/OzonesServer.rb b/src/ozones/Server/models/OzonesServer.rb index 11210ac54f..eb5e200791 100644 --- a/src/ozones/Server/models/OzonesServer.rb +++ b/src/ozones/Server/models/OzonesServer.rb @@ -80,13 +80,18 @@ class OzonesServer # Get a json representation resource with local (DB) info def get_resource(kind, id) - resource = retrieve_resource(kind, id) - - if OZones.is_error?(resource) - return [404, resource.to_json] - else - return [200, resource.to_json] + rc = 200 + res = case kind + when "vdc" then + OZones::Vdc.get(id) + when "zone" then + OZones::Zones.get(id) + else + rc = 404 + OZones::Error.new("Error: #{kind} resource not supported") end + + return [rc, res.to_json] end ############################################################################ @@ -106,78 +111,53 @@ class OzonesServer data.each{|key,value| vdc_data[key.downcase.to_sym]=value if key!="pool" } + + #Get the Zone that will host the VDC. And check resouces + zoneid = vdc_data.delete(:zoneid) + force = vdc_data.delete(:force) - mandatory_params = [:vdcadminname, :vdcadminpass, - :zoneid, :name, :hosts] + if !zoneid + return [400, OZones::Error.new("Error: Couldn't create " \ + "vdc. Mandatory attribute zoneid missing.").to_json] + end - mandatory_params.each { |param| - if !vdc_data[param] - return [400, OZones::Error.new( - "Error: Couldn't create resource #{kind}. " + - "Mandatory attribute '#{param}' is missing.").to_json] - end - } - - # Check if the referenced zone exists - zone=OZones::Zones.get(vdc_data[:zoneid]) + zone = OZones::Zones.get(zoneid) if !zone - error = OZones::Error.new("Error: Zone " + - "#{vdc_data[:zoneid]} not found, cannot create Vdc.") - return [404, error.to_json] + return [404, OZones::Error.new("Error: Couldn't create " \ + "vdc. Zone #{zoneid} not found.").to_json] end - if (!vdc_data[:force] or vdc_data[:force].upcase!="YES") and + if (!force or force.upcase!="YES") and !host_uniqueness?(zone, vdc_data[:hosts]) - return [403, OZones::Error.new( - "Error: Couldn't create resource #{kind}. " + - "Hosts are not unique, and no force option" + - " was given.").to_json] + + return [403, OZones::Error.new( "Error: Couldn't create " \ + "Hosts are not unique, use force to override").to_json] end - vdcadminname = vdc_data[:vdcadminname] - vdcadminpass = vdc_data[:vdcadminpass] - vdc_data.delete(:zoneid) - vdc_data.delete(:vdcadminpass) - vdc_data.delete(:force) + # Create de VDC + vdc = OZones::OpenNebulaVdc.new(-1,zone) + rc = vdc.create(vdc_data) - begin - vdc = OZones::Vdc.create(vdc_data) - rescue Exception => e - msg = e.message - msg["accessible in OZones::Vdc"] = "supported." - return [400, OZones::Error.new( - "Error: Couldn't create resource #{kind}." + - " #{msg}").to_json] + if OpenNebula.is_error?(rc) + return [400, OZones::Error.new("Error: Couldn't create " \ + "vdc. Reason: #{rc.message}").to_json] end - zone.vdcs << vdc - zone.save + #Update the zone and save the vdc + zone.raise_on_save_failure = true + zone.vdcs << vdc.vdc - if zone.saved? and vdc.saved? - vdcadminpass = Digest::SHA1.hexdigest(vdcadminpass) - rc = @ocaInt.create_vdc_in_zone(zone, - vdc, - vdcadminname, - vdcadminpass) - if OpenNebula.is_error?(rc) - vdc.destroy - return [400, OZones::Error.new( - "Error: Couldn't create #{kind}. Reason: " + - rc.message).to_json] - else - vdc.acls = rc[0] - vdc.group_id = rc[1] - vdc.save - - pr.update # Rewrite proxy conf file - return [200, vdc.to_json] - end - else - return [400, OZones::Error.new( - "Error: Couldn't create resource #{kind}." + - " Maybe duplicated name?").to_json] + begin + zone.save + rescue => e + #TODO Rollback VDC creation? + return [400, OZones::Error.new("Error: Couldn't create " \ + "vdc. Zone could not be saved: #{e.message}").to_json] end + pr.update # Rewrite proxy conf file + return [200, vdc.to_json] + when "zone" then zone = OZones::Zones.create(data) @@ -279,21 +259,30 @@ class OzonesServer ############################################################################ # Deletes a resource of a kind, and updates the Proxy Rules def delete_resource(kind, id, pr) - resource = retrieve_resource(kind, id) - if OZones.is_error?(resource) - return [404, resource.to_json] + case kind + when "vdc" then + begin + vdc = OZones::OpenNebulaVdc.new(id) + rc = vdc.destroy + rescue => e + return [404, OZones::Error.new("Error: Can not delete " \ + "vdc. Reason: #{e.message}").to_json] + end + when "zone" then + zone = OZones::Zones.get(id) + + if zone + rc = zone.destroy + else + return [404, OZones::Error.new("Error: Can not delete " \ + "zone. Reason: zone #{id} not found").to_json] + end + else + return [404, OZones::Error.new("Error: #{kind} resource " \ + "not supported").to_json] end - if kind == "vdc" - rc = @ocaInt.delete_vdc_in_zone(id) - if OpenNebula.is_error?(rc) - return [500, OZones::Error.new( - "Error: Couldn't delete resources from VDC with id #{id}, " + - "aborting VDC deletion. Reason:" + rc.message).to_json] - end - end - - if !resource.destroy + if !rc return [500, OZones::Error.new( "Error: Couldn't delete resource #{kind} with id #{id}").to_json] else @@ -303,6 +292,9 @@ class OzonesServer end end + ############################################################################ + # Misc Helper Functions + ############################################################################ private # Check if hosts are already include in any Vdc of the zone @@ -322,23 +314,4 @@ class OzonesServer return true end - - # Get hold of a object of a particular kind - def retrieve_resource(kind, id) - rc = case kind - when "vdc" then - OZones::Vdc.get(id) - when "zone" then - OZones::Zones.get(id) - else - OZones::Error.new("Error: #{kind} resource not supported") - end - - if rc - return rc - else - return OZones::Error.new("Error: #{kind} with id #{id} not found") - end - end - end From dec5dbd0c8df26038ce7728f71a5f8c9ee501d58 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Mon, 26 Sep 2011 17:41:46 +0200 Subject: [PATCH 4/9] feature #789: Moved update from OCAInteraction to VDC --- src/ozones/Server/lib/OZones/VDC.rb | 84 ++++++++++++++---------- src/ozones/Server/models/OzonesServer.rb | 42 ++++-------- 2 files changed, 63 insertions(+), 63 deletions(-) diff --git a/src/ozones/Server/lib/OZones/VDC.rb b/src/ozones/Server/lib/OZones/VDC.rb index 9e51df6da4..9817b3cc7c 100644 --- a/src/ozones/Server/lib/OZones/VDC.rb +++ b/src/ozones/Server/lib/OZones/VDC.rb @@ -46,25 +46,6 @@ module OZones vdc_attributes["VDC"] = attributes return vdc_attributes end - - # Returns the host acls as an array of strings. - # The acls of the VDC are updated and the host acl ids removed - def get_host_acls!(new_host_acls = nil) - acl_ids = self.acls.split(',') - vdc_acl = acl_ids.slice!(0,HOST_ACL_FIRST_ID) - - newacl = "" - vdc_acl.each{|id| - newacl << id << ',' - } - - newacl.chomp - newacl << new_host_acls if new_host_acls - - self.acls = newacl - - return acl_ids - end end ########################################################################### @@ -112,7 +93,6 @@ module OZones #Create a vdc record @vdc = Vdc.new - @vdc.raise_on_save_failure = true vdcpass = Digest::SHA1.hexdigest(vdc_data.delete(:vdcadminpass)) @vdc.attributes = vdc_data @@ -142,20 +122,10 @@ module OZones aclp = OpenNebula::AclPool.new(@client) rules = get_acls - acls_str = "" + rc, acls_str = create_acls(rules) + return rollback(group, user,acls_str,rc) if OpenNebula.is_error?(rc) - rules.each{ |rule_str| - acl = OpenNebula::Acl.new(OpenNebula::Acl.build_xml,@client) - rc = acl.allocate(*OpenNebula::Acl.parse_rule(rule_str)) - - if OpenNebula.is_error?(rc) - return rollback(group, user, acls_str, rc) - end - - acls_str << acl.id.to_s << "," - } - - @vdc.acls = acls_str.chop + @vdc.acls = acls_str return true end @@ -188,6 +158,36 @@ module OZones end end + def update(host_list) + # Delete existing host ACLs + delete_host_acls + + # Create new ACLs. TODO Rollback ACL creation + host_acls = get_host_acls(host_list) + rc, acls_str = create_acls(host_acls) + + return rc if OpenNebula.is_error?(rc) + + #Create the new acl string. + @vdc.acls =~ /((\d,){HOST_ACL_FIRST_ID}).*/ + + newacls = $1.chop + newacls << acls_str + + #Update the VDC Record + begin + @vdc.raise_on_save_failure = true + @vdc.hosts = host_list + @vdc.acls = newacls + + @vdc.save + rescue => e + return OpenNebula::Error.new(e.message) + end + + return @vdc.to_json + end + private ####################################################################### # Functions to generate ACL Strings @@ -307,5 +307,23 @@ module OZones return rc end + + # Creates an acl array of acl strings. Returns true or error and + # a comma-separated list with the new acl ids + def create_acls(acls) + acls_str = "" + rc = true + + acls.each{|rule| + acl = OpenNebula::Acl.new(OpenNebula::Acl.build_xml,@client) + rc = acl.allocate(*OpenNebula::Acl.parse_rule(rule)) + + break if OpenNebula.is_error?(rc) + + acls_str << acl.id.to_s << "," + } + + return rc, acls_str.chop + end end end diff --git a/src/ozones/Server/models/OzonesServer.rb b/src/ozones/Server/models/OzonesServer.rb index eb5e200791..562b67f4ae 100644 --- a/src/ozones/Server/models/OzonesServer.rb +++ b/src/ozones/Server/models/OzonesServer.rb @@ -189,8 +189,8 @@ class OzonesServer resource = case kind when "vdc" then - vdc_data=Hash.new - vdc_id = nil + vdc_data = Hash.new + vdc_id = nil data.each{|key,value| vdc_data[key.downcase.to_sym]=value if key!="id" vdc_id = value if key=="id" @@ -204,19 +204,12 @@ class OzonesServer end # Check if the referenced Vdc exists - vdc=OZones::Vdc.get(vdc_id) - if !vdc - error = OZones::Error.new("Error: Vdc " + - "#{vdc_id} not found, cannot update Vdc.") - return [404, error.to_json] - end - - # Get the zone where the Vdc belongs - zone=OZones::Zones.get(vdc.zones.id) - if !zone - error = OZones::Error.new("Error: Zone " + - "#{vdc.zones.id} not found, cannot update Vdc.") - return [404, error.to_json] + begin + vdc=OZones::OpenNebulaVdc.new(vdc_id, zone) + rescue + return [404, OZones::Error.new("Error: Vdc " \ + "#{vdc_id} not found, cannot update Vdc.").to_json] + end if (!vdc_data[:force] or vdc_data[:force].upcase!="YES") and @@ -227,25 +220,14 @@ class OzonesServer " was given.").to_json] end - rc = @ocaInt.update_vdc_hosts(zone, vdc, vdc_data[:hosts]) + rc = vdc.update(vdc_data[:hosts]) if !OpenNebula.is_error?(rc) - vdc.hosts = vdc_data[:hosts] - vdc.get_host_acls!(rc) - - vdc.save - - if vdc.saved? - return [200, vdc.to_json] - else - return [500, OZones::Error.new( - "Error: Couldn't update resource #{kind}.").to_json] - end - + return [200, rc] else return [500, OZones::Error.new( - "Error: Couldn't update resource #{kind.upcase}." + - " Failed to update ACLs").to_json] + "Error: Couldn't update resource #{kind.upcase}." \ + " Reason: #{rc.message}").to_json] end else error = OZones::Error.new( From b5298aea6fc8101cfdeeedde844c9d3c34bbdb66 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Mon, 26 Sep 2011 17:44:08 +0200 Subject: [PATCH 5/9] feature #789: Removed unneeded OCAInteraction library --- install.sh | 1 - src/ozones/Server/models/OCAInteraction.rb | 206 --------------------- src/ozones/Server/models/OzonesServer.rb | 5 - 3 files changed, 212 deletions(-) delete mode 100644 src/ozones/Server/models/OCAInteraction.rb diff --git a/install.sh b/install.sh index 72fb72b1d7..abfac04d70 100755 --- a/install.sh +++ b/install.sh @@ -1033,7 +1033,6 @@ OZONES_ETC_FILES="src/ozones/Server/etc/ozones-server.conf" OZONES_MODELS_FILES="src/ozones/Server/models/OzonesServer.rb \ src/ozones/Server/models/Auth.rb \ - src/ozones/Server/models/OCAInteraction.rb \ src/sunstone/models/OpenNebulaJSON/JSONUtils.rb" OZONES_TEMPLATE_FILES="src/ozones/Server/templates/index.html \ diff --git a/src/ozones/Server/models/OCAInteraction.rb b/src/ozones/Server/models/OCAInteraction.rb deleted file mode 100644 index 1b61136ae2..0000000000 --- a/src/ozones/Server/models/OCAInteraction.rb +++ /dev/null @@ -1,206 +0,0 @@ -# -------------------------------------------------------------------------- # -# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) # -# # -# Licensed under the Apache License, Version 2.0 (the "License"); you may # -# not use this file except in compliance with the License. You may obtain # -# a copy of the License at # -# # -# http://www.apache.org/licenses/LICENSE-2.0 # -# # -# Unless required by applicable law or agreed to in writing, software # -# distributed under the License is distributed on an "AS IS" BASIS, # -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -# See the License for the specific language governing permissions and # -# limitations under the License. # -#--------------------------------------------------------------------------- # - -require 'OpenNebula' - -class OCAInteraction - - # Creates a VDC (user, group, hosts) - def create_vdc_in_zone(zone, vdc, adminname, adminpass) - # Create a new client to interact with the zone - client = OpenNebula::Client.new(zone.onename + ":" + zone.onepass, - zone.endpoint, - false) - - # Create a group in the zone with the VDC name - group = OpenNebula::Group.new(OpenNebula::Group.build_xml, client) - result = group.allocate(vdc.name) - return result if OpenNebula.is_error?(result) - - # Create the VDC admin user in the Zone - user = OpenNebula::User.new(OpenNebula::User.build_xml, client) - result = user.allocate(adminname, adminpass) - return rollback(client, group, - result, user) if OpenNebula.is_error?(result) - - # Change primary group of the admin user to the VDC group - result = user.chgrp(group.id) - return rollback(client, group, - result, user) if OpenNebula.is_error?(result) - - # Add ACLs - aclp = OpenNebula::AclPool.new client - rules = vdc.get_vdc_acls_str(user.id, group.id) - - acls_str = "" - - rules.each{ |rule_str| - acl = OpenNebula::Acl.new(OpenNebula::Acl.build_xml,client) - rc = acl.allocate(*OpenNebula::Acl.parse_rule(rule_str)) - - if OpenNebula.is_error?(rc) - return rollback(client, group, rc, user, acls_str) - end - - acls_str << acl.id.to_s << "," - } - - return acls_str.chop, group.id - end - - def delete_vdc_in_zone(id) - vdc = OZones::Vdc.get(id) - zone= OZones::Zones.get(vdc.zones_id) - - # Create a new client to interact with the zone - client = OpenNebula::Client.new(zone.onename + ":" + zone.onepass, - zone.endpoint, - false) - - # Delete the resources from the VDC - delete_images(vdc.group_id, client) - delete_templates(vdc.group_id, client) - delete_vms(vdc.group_id, client) - delete_vns(vdc.group_id, client) - - # Delete ACLs - delete_acls(vdc.acls, client) - - # Delete users from a group - up = OpenNebula::UserPool.new(client) - up.info - up.each{|user| - if user['GID'].to_i == vdc.group_id - OpenNebula::User.new_with_id(user['ID'], client).delete - end - } - - # Delete the group - rc = OpenNebula::Group.new_with_id(vdc.group_id, client).delete - - if OpenNebula.is_error?(rc) - return rc - else - return nil - end - end - - def update_vdc_hosts(zone, vdc, host_list) - # Create a new client to interact with the zone - client = OpenNebula::Client.new(zone.onename + ":" + zone.onepass, - zone.endpoint, - false) - # Delete existing host ACLs - vdc.get_host_acls.each{|acl_id| - OpenNebula::Acl.new_with_id(acl_id, client).delete - } - - # Create new ACLs - acls_str = "" - host_acls = vdc.get_host_acls_str(vdc.group_id, host_list) - - host_acls.each{|rule| - acl = OpenNebula::Acl.new(OpenNebula::Acl.build_xml,client) - rc = acl.allocate(*OpenNebula::Acl.parse_rule(rule)) - - - if OpenNebula.is_error?(rc) - return rc - end - - acls_str += acl.id.to_s + "," - } - - return acls_str.chop - end - - # Creates a VDC (user, group, hosts) - def check_oneadmin(oneadminname, oneadminpass, endpoint) - # Create a new client to interact with the zone - client = OpenNebula::Client.new(oneadminname + ":" + oneadminpass, - endpoint, - false) - - hostpool=OpenNebula::HostPool.new(client) - result = hostpool.info - - return result - end - - # Deletes resources from failed created VDC - def rollback(client, group, result, user=nil, acls_str=nil) - user.delete if user - group.delete - - delete_acls(acls_str, client) - - return result - end - - # Deletes images from a group - def delete_images(groupid, client) - ip = OpenNebula::ImagePool.new(client) - ip.info - ip.each{|image| - if image['GID'].to_i == groupid - OpenNebula::Image.new_with_id(image['ID'], client).delete - end - } - end - - # Deletes templates from a group - def delete_templates(groupid, client) - tp = OpenNebula::TemplatePool.new(client) - tp.info - tp.each{|template| - if template['GID'].to_i == groupid - OpenNebula::Image.new_with_id(template['ID'], client).delete - end - } - end - - # Deletes VMs from a group - def delete_vms(groupid, client) - vmp = OpenNebula::VirtualMachinePool.new(client) - vmp.info - vmp.each{|vm| - if vm['GID'].to_i == groupid - OpenNebula::VirtualMachine.new_with_id(vm['ID'], client).delete - end - } - end - - # Deletes VNs from a group - def delete_vns(groupid, client) - vnp = OpenNebula::VirtualNetworkPool.new(client) - vnp.info - vnp.each{|vn| - if vn['GID'].to_i == groupid - OpenNebula::VirtualNetwork.new_with_id(vn['ID'], client).delete - end - } - end - - # Delete ACLs from a group - def delete_acls(acls_str, client) - if acls_str != nil && !acls_str.empty? - acls_str.split(",").each{|acl_id| - OpenNebula::Acl.new_with_id(acl_id.to_i, client).delete - } - end - end -end - diff --git a/src/ozones/Server/models/OzonesServer.rb b/src/ozones/Server/models/OzonesServer.rb index 562b67f4ae..e47a6702ac 100644 --- a/src/ozones/Server/models/OzonesServer.rb +++ b/src/ozones/Server/models/OzonesServer.rb @@ -14,17 +14,12 @@ # limitations under the License. # #--------------------------------------------------------------------------- # -require 'OCAInteraction' require 'JSONUtils' class OzonesServer include OpenNebulaJSON::JSONUtils - def initialize - @ocaInt = OCAInteraction.new - end - ############################################################################ # Get methods for the Zones and VDC interface ############################################################################ From beb5ee0db96c6e91433dc122d9829aa602a977c1 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Mon, 26 Sep 2011 23:04:50 +0200 Subject: [PATCH 6/9] feature #789: Migrating OzonesServer class. Work in progress --- src/ozones/Server/lib/OZones/VDC.rb | 1 - src/ozones/Server/lib/OZones/Zones.rb | 16 +- src/ozones/Server/models/OzonesServer.rb | 307 ++++++++++------------- src/ozones/Server/ozones-server.rb | 62 +++-- 4 files changed, 185 insertions(+), 201 deletions(-) diff --git a/src/ozones/Server/lib/OZones/VDC.rb b/src/ozones/Server/lib/OZones/VDC.rb index 9817b3cc7c..f39583e062 100644 --- a/src/ozones/Server/lib/OZones/VDC.rb +++ b/src/ozones/Server/lib/OZones/VDC.rb @@ -96,7 +96,6 @@ module OZones vdcpass = Digest::SHA1.hexdigest(vdc_data.delete(:vdcadminpass)) @vdc.attributes = vdc_data - puts vdc_data # Create a group in the zone with the VDC name group = OpenNebula::Group.new(OpenNebula::Group.build_xml, @client) diff --git a/src/ozones/Server/lib/OZones/Zones.rb b/src/ozones/Server/lib/OZones/Zones.rb index 59e8878005..723e9f2ce8 100644 --- a/src/ozones/Server/lib/OZones/Zones.rb +++ b/src/ozones/Server/lib/OZones/Zones.rb @@ -96,15 +96,17 @@ module OZones end # Create the zone - zone = super(zone_data) - rc = zone.save + begin + zone = Zones.new + zone.raise_on_save_failure = true - if rc - return zone - else - return OZones::Error.new("Error: Couldn't create zone. " \ - "Duplicated name?.") + zone.attributes = zone_data + zone.save + rescue => e + return OZones::Error.new(e.message) end + + return zone end end diff --git a/src/ozones/Server/models/OzonesServer.rb b/src/ozones/Server/models/OzonesServer.rb index e47a6702ac..9e10b643f9 100644 --- a/src/ozones/Server/models/OzonesServer.rb +++ b/src/ozones/Server/models/OzonesServer.rb @@ -23,212 +23,183 @@ class OzonesServer ############################################################################ # Get methods for the Zones and VDC interface ############################################################################ - def get_pool(kind) - rc = 200 - - pool = case kind - when "vdc" then - OZones::Vdc - when "zone" then - OZones::Zones - else - rc = 400 - OZones::Error.new("Error: #{kind} resource not supported") - end - - return [rc, pool.to_json] + # Gets all VDCs + def get_vdcs + return 200, OZones::Vdc.to_json end - # Gets an aggreageted pool for a zone or vdc - # ie All the hosts in all the Zones - def get_aggregated_pool(kind, aggkind) - case kind - when "zone" then - OZones::OpenNebulaZone::all_pools_to_json(aggkind) - else - error = OZones::Error.new("Error: Aggregated view not " \ - "supported for #{kind}") + # Gets a VDC + def get_vdc(id) + vdc = OZones::Vdc.get(id) - [404, error.to_json] + if vdc + return [200, vdc.to_json] + else + return [404, + OZones::Error.new("Error:VDC with id #{id} not found").to_json] + end + end + + #Gets all Zones + def get_zones + return 200, OZones::Zones.to_json + end + + #Gets a zone + def get_zone(id) + zone = OZones::Zones.get(id) + + if zone + return [200, zone.to_json] + else + return [404, + OZones::Error.new("Error:Zone with id #{id} not found").to_json] end end - # Gets an aggreageted pool for a zone or vdc in json - # ie All the hosts in all the Zones - def get_full_resource(kind, id, aggkind) - case kind - when "zone" - begin - zone = OZones::OpenNebulaZone.new(id) - rc = zone.pool_to_json(aggkind) - rescue => e - return [404, OZones::Error.new(e.message).to_json] - end - else - error = OZones::Error.new("Error: #{kind} resource view " \ - "not supported") - rc = [ 404, error.to_json ] - end - - return rc + # Gets an aggreageted view of a pool for all zones + def get_zones_pool(pool) + OZones::OpenNebulaZone::all_pools_to_json(pool) end - # Get a json representation resource with local (DB) info - def get_resource(kind, id) - rc = 200 - res = case kind - when "vdc" then - OZones::Vdc.get(id) - when "zone" then - OZones::Zones.get(id) - else - rc = 404 - OZones::Error.new("Error: #{kind} resource not supported") + # Gets a pool view of a given zone + def get_zone_pool(id, pool) + begin + zone = OZones::OpenNebulaZone.new(id) + return zone.pool_to_json(pool) + rescue => e + return [404, OZones::Error.new(e.message).to_json] end - - return [rc, res.to_json] end ############################################################################ # Create resources ############################################################################ - # Creates a resource of a kind, and updates the Proxy Rules - def create_resource(kind, data, body, pr) - + def create_vdc (data, body,pr) + #Setup POST data if body.size > 0 - result = parse_json(body,kind) + result = parse_json(body,"vdc") data = result if !OpenNebula.is_error?(result) end - resource = case kind - when "vdc" then - vdc_data = Hash.new - data.each{|key,value| - vdc_data[key.downcase.to_sym]=value if key!="pool" - } - - #Get the Zone that will host the VDC. And check resouces - zoneid = vdc_data.delete(:zoneid) - force = vdc_data.delete(:force) + vdc_data = Hash.new + data.each{|key,value| + vdc_data[key.downcase.to_sym] = value if key!="pool" + } + + #Get the Zone that will host the VDC. And check resouces + zoneid = vdc_data.delete(:zoneid) + force = vdc_data.delete(:force) - if !zoneid - return [400, OZones::Error.new("Error: Couldn't create " \ - "vdc. Mandatory attribute zoneid missing.").to_json] - end + if !zoneid + return [400, OZones::Error.new("Error: Couldn't create vdc. " \ + "Mandatory attribute zoneid missing.").to_json] + end - zone = OZones::Zones.get(zoneid) - if !zone - return [404, OZones::Error.new("Error: Couldn't create " \ - "vdc. Zone #{zoneid} not found.").to_json] - end + zone = OZones::Zones.get(zoneid) + if !zone + return [404, OZones::Error.new("Error: Couldn't create vdc. " \ + "Zone #{zoneid} not found.").to_json] + end - if (!force or force.upcase!="YES") and - !host_uniqueness?(zone, vdc_data[:hosts]) + if (!force or force.upcase!="YES") and + !host_uniqueness?(zone, vdc_data[:hosts]) - return [403, OZones::Error.new( "Error: Couldn't create " \ - "Hosts are not unique, use force to override").to_json] - end + return [403, OZones::Error.new("Error: Couldn't create vdc. " \ + "Hosts are not unique, use force to override").to_json] + end - # Create de VDC - vdc = OZones::OpenNebulaVdc.new(-1,zone) - rc = vdc.create(vdc_data) + # Create de VDC + vdc = OZones::OpenNebulaVdc.new(-1,zone) + rc = vdc.create(vdc_data) - if OpenNebula.is_error?(rc) - return [400, OZones::Error.new("Error: Couldn't create " \ - "vdc. Reason: #{rc.message}").to_json] - end + if OpenNebula.is_error?(rc) + return [400, OZones::Error.new("Error: Couldn't create vdc. " \ + "Reason: #{rc.message}").to_json] + end - #Update the zone and save the vdc - zone.raise_on_save_failure = true - zone.vdcs << vdc.vdc + #Update the zone and save the vdc + zone.raise_on_save_failure = true + zone.vdcs << vdc.vdc - begin - zone.save - rescue => e - #TODO Rollback VDC creation? - return [400, OZones::Error.new("Error: Couldn't create " \ - "vdc. Zone could not be saved: #{e.message}").to_json] - end + begin + zone.save + rescue => e + #TODO Rollback VDC creation + return [400, OZones::Error.new("Error: Couldn't create " \ + "vdc. Zone could not be saved: #{e.message}").to_json] + end - pr.update # Rewrite proxy conf file - return [200, vdc.to_json] - - when "zone" then - zone = OZones::Zones.create(data) - - if OZones.is_error?(zone) - return [400, zone.to_json] - end - - pr.update - return [200, zone.to_json] - else - error = OZones::Error.new( - "Error: #{kind.upcase} resource not supported") - return [404, error.to_json] - end + pr.update # Rewrite proxy conf file + return [200, vdc.to_json] end - + + def create_zone(data, body, pr) + #Setup POST data + if body.size > 0 + result = parse_json(body,"zone") + data = result if !OpenNebula.is_error?(result) + end + + zone = OZones::Zones.create(data) + + if OZones.is_error?(zone) + return [400, zone.to_json] + end + + pr.update + return [200, zone.to_json] + end + ############################################################################ # Update resources ############################################################################ - # Updates a resource of a kind, and updates the Proxy Rules if needed - def update_resource(kind, data, body, pr) - + def update_vdc(data, body, pr) + #Setup PUT data if body.size > 0 - result = parse_json(body,kind) - data = result if !OpenNebula.is_error?(result) + result = parse_json(body,"vdc") + data = result if !OpenNebula.is_error?(result) end - puts data + vdc_data = Hash.new + vdc_id = nil + data.each{|key,value| + vdc_data[key.downcase.to_sym]=value + } - resource = case kind - when "vdc" then - vdc_data = Hash.new - vdc_id = nil - data.each{|key,value| - vdc_data[key.downcase.to_sym]=value if key!="id" - vdc_id = value if key=="id" - } + vdc_id = vdc_data.delete(:id) + hosts = vdc_data.delete(:hosts) + force = vdc_data.delete(:force) - # Check parameters - if !vdc_data[:hosts] || !vdc_id - return [400, OZones::Error.new( - "Error: Couldn't update resource #{kind}. " + - "Need ID and HOSTS to update.").to_json] - end + # Check parameters + if !hosts || !vdc_id + return [400, OZones::Error.new("Error: Couldn't update vdc. " \ + "Missing ID or HOSTS.").to_json] + end - # Check if the referenced Vdc exists - begin - vdc=OZones::OpenNebulaVdc.new(vdc_id, zone) - rescue - return [404, OZones::Error.new("Error: Vdc " \ - "#{vdc_id} not found, cannot update Vdc.").to_json] + # Check if the referenced Vdc exists + begin + vdc=OZones::OpenNebulaVdc.new(vdc_id, zone) + rescue + return [404, OZones::Error.new("Error: Couldn't update vdc. " \ + "VDC #{vdc_id} not found.").to_json] + end + + if (!force or force.upcase!="YES") and + !host_uniqueness?(zone, hosts, vdc_id.to_i) - end - - if (!vdc_data[:force] or vdc_data[:force].upcase!="YES") and - !host_uniqueness?(zone, vdc_data[:hosts], vdc_id.to_i) - return [403, OZones::Error.new( - "Error: Couldn't update resource #{kind}. " + - "Hosts are not unique, and no force option" + - " was given.").to_json] - end - - rc = vdc.update(vdc_data[:hosts]) - - if !OpenNebula.is_error?(rc) - return [200, rc] - else - return [500, OZones::Error.new( - "Error: Couldn't update resource #{kind.upcase}." \ - " Reason: #{rc.message}").to_json] - end - else - error = OZones::Error.new( - "Error: #{kind.upcase} resource update not supported") - return [404, error.to_json] - end + return [403, OZones::Error.new("Error: Couldn't update vdc. " \ + "Hosts are not unique, use force to override").to_json] + end + + rc = vdc.update(hosts) + + if !OpenNebula.is_error?(rc) + return [200, rc] + else + return [500, OZones::Error.new("Error: Couldn't update vdc. " \ + " Reason: #{rc.message}").to_json] + end end ############################################################################ diff --git a/src/ozones/Server/ozones-server.rb b/src/ozones/Server/ozones-server.rb index afb31e9f50..2f1816976d 100755 --- a/src/ozones/Server/ozones-server.rb +++ b/src/ozones/Server/ozones-server.rb @@ -226,48 +226,60 @@ get '/config' do end ############################################################################## -# GET Pool information +# GETs information ############################################################################## -get '/:pool' do - @OzonesServer.get_pool(params[:pool]) +get '/vdc' do + @OzonesServer.get_vdcs +end + +get '/vdc/:id' do + @OzonesServer.get_vdc(params[:id]) +end + +get '/zone' do + @OzonesServer.get_zones +end + +get '/zone/:pool' do + @OzonesServer.get_zones_pool(params[:pool]) +end + +get '/zone/:id' do + @OzonesServer.get_zone(params[:id]) +end + +get '/zone/:id/:pool' do + @OzonesServer.get_zone_pool(params[:id], params[:pool]) end ############################################################################## -# GET Resource information +# POSTs information ############################################################################## -get %r{/(zone|vdc)/(\d+)/(\w+)} do |kind, id, aggpool| - @OzonesServer.get_full_resource(kind,id,aggpool) + +post '/vdc' do + @OzonesServer.create_vdc(params,request.body.read, @pr) end -get %r{/(zone|vdc)/(\d+)} do |kind, id| - @OzonesServer.get_resource(kind,id) -end - -get '/:pool/:aggpool' do - @OzonesServer.get_aggregated_pool(params[:pool], params[:aggpool]) -end - -############################################################################## -# Create a new Resource -############################################################################## -post '/:pool' do - @OzonesServer.create_resource(params[:pool], params, request.body.read, @pr) +post '/zone' do + @OzonesServer.create_zone(params,request.body.read, @pr) end ############################################################################## # Update Resource ############################################################################## -put '/:resource/:id' do - @OzonesServer.update_resource(params[:resource], params, - request.body.read, @pr) +put '/vdc/:id' do + @OzonesServer.update_vdc(params, request.body.read, @pr) end ############################################################################## # Delete Resource ############################################################################## -delete '/:resource/:id' do - @OzonesServer.delete_resource(params[:resource], params[:id], @pr) +delete '/vdc/:id' do + @OzonesServer.delete_vdc(params[:id], @pr) +end + +delete '/zone/:id' do + @OzonesServer.delete_zone(params[:id], @pr) end - From 9bbff1fb49df1c2e13b8ef4f9f794b21324b39f6 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Mon, 26 Sep 2011 23:58:12 +0200 Subject: [PATCH 7/9] feature #789: Completed refactor of OzoneServer class --- src/ozones/Server/models/OzonesServer.rb | 57 +++++++++++++----------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/src/ozones/Server/models/OzonesServer.rb b/src/ozones/Server/models/OzonesServer.rb index 9e10b643f9..4d82e7fd8e 100644 --- a/src/ozones/Server/models/OzonesServer.rb +++ b/src/ozones/Server/models/OzonesServer.rb @@ -205,38 +205,41 @@ class OzonesServer ############################################################################ # Delete resources ############################################################################ - # Deletes a resource of a kind, and updates the Proxy Rules - def delete_resource(kind, id, pr) - case kind - when "vdc" then - begin - vdc = OZones::OpenNebulaVdc.new(id) - rc = vdc.destroy - rescue => e - return [404, OZones::Error.new("Error: Can not delete " \ - "vdc. Reason: #{e.message}").to_json] - end - when "zone" then - zone = OZones::Zones.get(id) - - if zone - rc = zone.destroy - else - return [404, OZones::Error.new("Error: Can not delete " \ - "zone. Reason: zone #{id} not found").to_json] - end - else - return [404, OZones::Error.new("Error: #{kind} resource " \ - "not supported").to_json] + def delete_vdc(id, pr) + begin + vdc = OZones::OpenNebulaVdc.new(id) + rc = vdc.destroy + rescue => e + return [404, OZones::Error.new("Error: Can not delete vdc. " \ + "Reason: #{e.message}").to_json] end if !rc - return [500, OZones::Error.new( - "Error: Couldn't delete resource #{kind} with id #{id}").to_json] + return [500, OZones::Error.new("Error: Couldn't delete " \ + "vdc #{id}").to_json] else pr.update # Rewrite proxy conf file - return [200, OZones.str_to_json( - "Resource #{kind} with id #{id} successfully deleted")] + return [200, OZones.str_to_json("Vdc #{id} successfully deleted")] + end + end + + def delete_zone(id, pr) + + zone = OZones::Zones.get(id) + + if zone + rc = zone.destroy + else + return [404, OZones::Error.new("Error: Can not delete " \ + "zone. Reason: zone #{id} not found").to_json] + end + + if !rc + return [500, OZones::Error.new("Error: Couldn't delete " \ + "zone #{id}").to_json] + else + pr.update # Rewrite proxy conf file + return [200, OZones.str_to_json("Zone #{id} successfully deleted")] end end From da42de1d6f1ee1aa4e6c22ddb69361ad3066f39c Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Wed, 28 Sep 2011 11:23:15 +0200 Subject: [PATCH 8/9] feature #789: More work on the Ozones server refactor --- src/ozones/Client/lib/OZonesClient.rb | 15 ++++--- src/ozones/Server/lib/OZones/VDC.rb | 49 +++++++++++++-------- src/ozones/Server/lib/OZones/Zones.rb | 6 +-- src/ozones/Server/models/OzonesServer.rb | 55 +++++++++++++----------- src/ozones/Server/ozones-server.rb | 20 ++++----- 5 files changed, 85 insertions(+), 60 deletions(-) diff --git a/src/ozones/Client/lib/OZonesClient.rb b/src/ozones/Client/lib/OZonesClient.rb index 9587ea5b1f..bb015b6f63 100644 --- a/src/ozones/Client/lib/OZonesClient.rb +++ b/src/ozones/Client/lib/OZonesClient.rb @@ -95,7 +95,7 @@ EOT end def post_resource_str(kind, tmpl_str) - body_str = OZonesClient::to_body(tmpl_str) + body_str = OZonesClient::to_body(kind, tmpl_str) url = URI.parse("#{@endpoint}/#{kind}") @@ -112,7 +112,7 @@ EOT end def put_resource(kind, id, tmpl_str) - body_str = OZonesClient::to_body(tmpl_str) + body_str = OZonesClient::to_body(kind, tmpl_str) url = URI.parse("#{@endpoint}/#{kind}/#{id}") @@ -248,16 +248,19 @@ EOT # JSON & Template utils ########################################################################## - def self.to_body(tmpl_str) - body_str = "" + def self.to_body(kind, tmpl_str) + body_str = "{\n" + body_str << " \"#{kind}\": {" tmpl_str.strip.each_line{|line| line.strip! key,value = line.split("=") - body_str = body_str + key + "=" + URI.escape(value) + "&" + body_str << "\n \"#{key}\": \"#{value}\"," } + body_str.chop! - body_str = body_str[0..-1] + body_str << "\n }\n" + body_str << "}\n" end def self.parse_json(json_str, root_element) diff --git a/src/ozones/Server/lib/OZones/VDC.rb b/src/ozones/Server/lib/OZones/VDC.rb index f39583e062..bee904a431 100644 --- a/src/ozones/Server/lib/OZones/VDC.rb +++ b/src/ozones/Server/lib/OZones/VDC.rb @@ -60,25 +60,33 @@ module OZones VDC_ATTRS = [:vdcadminname, :vdcadminpass, :name, :hosts] attr_reader :vdc + attr_reader :zone #Creates an OpenNebula VDC, using its ID, vdcid and the associated zone def initialize(vdcid, zone = nil) + if vdcid != -1 @vdc = Vdc.get(vdcid) if !@vdc - raise "Error: VDC with id #{vdcid} not found" + raise "VDC with id #{vdcid} not found." end - zone = OZones::Zones.get(@vdc.zones_id) + @zone = OZones::Zones.get(@vdc.zones_id) + else + @zone = zone end @client = OpenNebula::Client.new( - "#{zone.onename}:#{zone.onepass}", - zone.endpoint, + "#{@zone.onename}:#{@zone.onepass}", + @zone.endpoint, false) end + def to_json + @vdc.to_json + end + ####################################################################### # ####################################################################### @@ -148,30 +156,37 @@ module OZones } # Delete the group - rc = OpenNebula::Group.new_with_id(@vdc.group_id, @client).delete + OpenNebula::Group.new_with_id(@vdc.group_id, @client).delete - if OpenNebula.is_error?(rc) - return rc - else - return @vdc.destroy - end + return @vdc.destroy + end + + #Cleans bootstrap operations in a zone + def clean_bootstrap + delete_acls + + OpenNebula::User.new_with_id(@vdc.vdcadmin_id, @client).delete + OpenNebula::Group.new_with_id(@vdc.group_id, @client).delete end def update(host_list) # Delete existing host ACLs delete_host_acls + @vdc.acls =~ /((\d+,){#{HOST_ACL_FIRST_ID}}).*/ + newacls = $1.chop + # Create new ACLs. TODO Rollback ACL creation - host_acls = get_host_acls(host_list) - rc, acls_str = create_acls(host_acls) + if !host_list.empty? + host_acls = get_host_acls(host_list) + rc, acls_str = create_acls(host_acls) - return rc if OpenNebula.is_error?(rc) + return rc if OpenNebula.is_error?(rc) - #Create the new acl string. - @vdc.acls =~ /((\d,){HOST_ACL_FIRST_ID}).*/ + #Create the new acl string. + newacls << "," << acls_str + end - newacls = $1.chop - newacls << acls_str #Update the VDC Record begin diff --git a/src/ozones/Server/lib/OZones/Zones.rb b/src/ozones/Server/lib/OZones/Zones.rb index 723e9f2ce8..6c1567aee6 100644 --- a/src/ozones/Server/lib/OZones/Zones.rb +++ b/src/ozones/Server/lib/OZones/Zones.rb @@ -73,12 +73,12 @@ module OZones zone_data = Hash.new data.each{|key,value| - zone_data[key.downcase.to_sym] = value if key!="pool" + zone_data[key.downcase.to_sym] = value } ZONE_ATTRS.each { |param| if !zone_data[param] - return OZones::Error.new("Error: Couldn't create zone." \ + return OZones::Error.new("Error: Couldn't create zone. " \ "Mandatory attribute '#{param}' is missing.") end } @@ -92,7 +92,7 @@ module OZones if OpenNebula.is_error?(rc) return OZones::Error.new("Error: Couldn't create zone. "\ - "Reason: #{rc.message}.") + "Reason: #{rc.message}") end # Create the zone diff --git a/src/ozones/Server/models/OzonesServer.rb b/src/ozones/Server/models/OzonesServer.rb index 57b7eb2b67..120dcfe092 100644 --- a/src/ozones/Server/models/OzonesServer.rb +++ b/src/ozones/Server/models/OzonesServer.rb @@ -75,16 +75,19 @@ class OzonesServer ############################################################################ # Create resources ############################################################################ - def create_vdc (data, body,pr) + def create_vdc (body,pr) #Setup POST data - if body.size > 0 - result = parse_json(body,"vdc") - data = result if !OpenNebula.is_error?(result) + data = parse_json(body,"vdc") + + if OpenNebula.is_error?(data) + return [400, OZones::Error.new("Error: Couldn't update vdc. " \ + "Reason: #{data.message}.").to_json] end vdc_data = Hash.new + data.each{|key,value| - vdc_data[key.downcase.to_sym] = value if key!="pool" + vdc_data[key.downcase.to_sym] = value } #Get the Zone that will host the VDC. And check resouces @@ -125,7 +128,8 @@ class OzonesServer begin zone.save rescue => e - #TODO Rollback VDC creation + vdc.clean_bootstrap + return [400, OZones::Error.new("Error: Couldn't create " \ "vdc. Zone could not be saved: #{e.message}").to_json] end @@ -134,11 +138,13 @@ class OzonesServer return [200, vdc.to_json] end - def create_zone(data, body, pr) + def create_zone(body, pr) #Setup POST data - if body.size > 0 - result = parse_json(body,"zone") - data = result if !OpenNebula.is_error?(result) + data = parse_json(body,"zone") + + if OpenNebula.is_error?(data) + return [400, OZones::Error.new("Error: Couldn't update vdc. " \ + "Reason: #{data.message}.").to_json] end zone = OZones::Zones.create(data) @@ -154,39 +160,40 @@ class OzonesServer ############################################################################ # Update resources ############################################################################ - def update_vdc(data, body, pr) + def update_vdc(vdc_id, body) #Setup PUT data - if body.size > 0 - result = parse_json(body,"vdc") - data = result if !OpenNebula.is_error?(result) + data = parse_json(body,"vdc") + + if OpenNebula.is_error?(data) + return [400, OZones::Error.new("Error: Couldn't update vdc. " \ + "Reason: #{data.message}.").to_json] end vdc_data = Hash.new - vdc_id = nil + data.each{|key,value| vdc_data[key.downcase.to_sym]=value } - vdc_id = vdc_data.delete(:id) hosts = vdc_data.delete(:hosts) force = vdc_data.delete(:force) # Check parameters - if !hosts || !vdc_id + if !hosts return [400, OZones::Error.new("Error: Couldn't update vdc. " \ - "Missing ID or HOSTS.").to_json] + "Missing HOSTS.").to_json] end # Check if the referenced Vdc exists begin - vdc=OZones::OpenNebulaVdc.new(vdc_id, zone) - rescue - return [404, OZones::Error.new("Error: Couldn't update vdc. " \ - "VDC #{vdc_id} not found.").to_json] + vdc = OZones::OpenNebulaVdc.new(vdc_id) + rescue => e + return [404, OZones::Error.new("Error: Couldn't update vdc. " \ + "#{e.message}").to_json] end - if (!force or force.upcase!="YES") and - !host_uniqueness?(zone, hosts, vdc_id.to_i) + if (!force or force.upcase != "YES") and + !host_uniqueness?(vdc.zone, hosts, vdc_id.to_i) return [403, OZones::Error.new("Error: Couldn't update vdc. " \ "Hosts are not unique, use force to override").to_json] diff --git a/src/ozones/Server/ozones-server.rb b/src/ozones/Server/ozones-server.rb index 2f1816976d..80a309a8de 100755 --- a/src/ozones/Server/ozones-server.rb +++ b/src/ozones/Server/ozones-server.rb @@ -226,7 +226,7 @@ get '/config' do end ############################################################################## -# GETs information +# GET information ############################################################################## get '/vdc' do @OzonesServer.get_vdcs @@ -240,16 +240,16 @@ get '/zone' do @OzonesServer.get_zones end -get '/zone/:pool' do - @OzonesServer.get_zones_pool(params[:pool]) +get %r{/zone/([\d]+)/([\w]+)} do + @OzonesServer.get_zone_pool(params[:captures][0], params[:captures][1]) end -get '/zone/:id' do - @OzonesServer.get_zone(params[:id]) +get %r{/zone/([\d]+)} do + @OzonesServer.get_zone(params[:captures].first) end -get '/zone/:id/:pool' do - @OzonesServer.get_zone_pool(params[:id], params[:pool]) +get %r{/zone/([\w]+)} do + @OzonesServer.get_zones_pool(params[:captures].first) end ############################################################################## @@ -257,18 +257,18 @@ end ############################################################################## post '/vdc' do - @OzonesServer.create_vdc(params,request.body.read, @pr) + @OzonesServer.create_vdc(request.body.read, @pr) end post '/zone' do - @OzonesServer.create_zone(params,request.body.read, @pr) + @OzonesServer.create_zone(request.body.read, @pr) end ############################################################################## # Update Resource ############################################################################## put '/vdc/:id' do - @OzonesServer.update_vdc(params, request.body.read, @pr) + @OzonesServer.update_vdc(params[:id], request.body.read) end ############################################################################## From d6defb6bb8b421edbc3f2958ae7ddfc6d767f631 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Fri, 30 Sep 2011 00:40:51 +0200 Subject: [PATCH 9/9] feature #789: Solves minor bugs in host update for VDC. Deals with empty host lists --- src/ozones/Server/lib/OZones/VDC.rb | 17 ++++++++++++----- src/ozones/Server/models/OzonesServer.rb | 2 ++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/ozones/Server/lib/OZones/VDC.rb b/src/ozones/Server/lib/OZones/VDC.rb index bee904a431..6c452af31f 100644 --- a/src/ozones/Server/lib/OZones/VDC.rb +++ b/src/ozones/Server/lib/OZones/VDC.rb @@ -173,8 +173,11 @@ module OZones # Delete existing host ACLs delete_host_acls - @vdc.acls =~ /((\d+,){#{HOST_ACL_FIRST_ID}}).*/ - newacls = $1.chop + if @vdc.acls =~ /((\d+,){#{HOST_ACL_FIRST_ID}}).*/ + newacls = $1.chop + else + newacls = @vdc.acls.clone + end # Create new ACLs. TODO Rollback ACL creation if !host_list.empty? @@ -251,9 +254,13 @@ module OZones ####################################################################### # Deletes ACLs for the hosts def delete_host_acls - @vdc.acls.split(',')[HOST_ACL_FIRST_ID..-1].each{|acl| - OpenNebula::Acl.new_with_id(acl.to_i, @client).delete - } + host_acls = @vdc.acls.split(',')[HOST_ACL_FIRST_ID..-1] + + if host_acls + host_acls.each{|acl| + OpenNebula::Acl.new_with_id(acl.to_i, @client).delete + } + end end # Delete ACLs diff --git a/src/ozones/Server/models/OzonesServer.rb b/src/ozones/Server/models/OzonesServer.rb index 120dcfe092..ca47d85fdf 100644 --- a/src/ozones/Server/models/OzonesServer.rb +++ b/src/ozones/Server/models/OzonesServer.rb @@ -256,6 +256,8 @@ class OzonesServer # Check if hosts are already include in any Vdc of the zone def host_uniqueness?(zone, host_list, vdc_id = -1) + return true if host_list.empty? + all_hosts = "" zone.vdcs.all.each{|vdc| if vdc.hosts != nil and !vdc.hosts.empty? and vdc.id != vdc_id