From 43e44040f7974064c483fa7d9bf122c48d57e8cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20and=20Javi=20Fontan?= Date: Wed, 6 Jul 2011 15:56:38 +0200 Subject: [PATCH] Feature #687: Refactor Acl and AclPool ruby OCA classes to follow the common Pool/PoolElement structure --- src/cli/one_helper/oneacl_helper.rb | 46 ++----- src/cli/oneacl | 37 +++++- src/oca/ruby/OpenNebula/Acl.rb | 198 ++++++++++++++++++---------- src/oca/ruby/OpenNebula/AclPool.rb | 40 ------ 4 files changed, 171 insertions(+), 150 deletions(-) diff --git a/src/cli/one_helper/oneacl_helper.rb b/src/cli/one_helper/oneacl_helper.rb index d82d64c6df..9b6bb7303e 100644 --- a/src/cli/one_helper/oneacl_helper.rb +++ b/src/cli/one_helper/oneacl_helper.rb @@ -24,51 +24,23 @@ class OneAclHelper < OpenNebulaHelper::OneHelper def self.conf_file "oneacl.yaml" end - - def add_rule(options, arg0, arg1=nil, arg2=nil) - aclp = OpenNebula::AclPool.new( OpenNebula::Client.new() ) - if arg2 - rc = aclp.addrule( arg0, arg1, arg2 ) +private + + def factory(id = nil) + if id + OpenNebula::Acl.new_with_id(id, @client) else - rc = aclp.addrule_with_str( arg0 ) - end - - if OpenNebula.is_error?(rc) - return [-1, rc.message] - else - if rc.class == Fixnum - puts "Rule added with ID #{rc}" if options[:verbose] - return 0 - end - return [-1, rc[:users].message] if OpenNebula.is_error?(rc[:users]) - return [-1, rc[:resources].message] if OpenNebula.is_error?( - rc[:resources]) - return [-1, rc[:rights].message] if OpenNebula.is_error?( - rc[:rights]) + xml = OpenNebula::Acl.build_xml + OpenNebula::Acl.new(xml, @client) end end - - def delete_rule(options, id) - acl = OpenNebula::AclPool.new( OpenNebula::Client.new() ) - - rc = acl.delrule( id ) - - if OpenNebula.is_error?(rc) - [-1, rc.message] - else - puts "Rule deleted" if options[:verbose] - 0 - end - end - - private def factory_pool(filter) OpenNebula::AclPool.new(@client) end - - # TODO check that @content[:resources_str] is valid + + # TODO check that @content[:resources_str] is valid def self.resource_mask(str) resource_type=str.split("/")[0] diff --git a/src/cli/oneacl b/src/cli/oneacl index 98a55278c0..f34ae18240 100755 --- a/src/cli/oneacl +++ b/src/cli/oneacl @@ -44,7 +44,9 @@ cmd = CommandParser::CmdParser.new(ARGV) do ######################################################################## # Formatters for arguments ######################################################################## - # TODO + set :format, :aclid_list, OneAclHelper.list_to_id_desc do |arg| + helper.list_to_id(arg) + end ######################################################################## # Commands @@ -55,15 +57,42 @@ cmd = CommandParser::CmdParser.new(ARGV) do EOT command :create, addrule_desc, [:user,:rulestr], [:resource, nil], [:rights, nil] do - helper.add_rule(options, args[0], args[1], args[2] ) + case args.length + when 1 + new_args=Acl.parse_rule(args[0]) + when 3 + new_args=args + else + next -1, "Wrong number of arguments, must be 1 or 3" + end + + errors=new_args.map do |arg| + if OpenNebula.is_error?(arg) + arg.message + else + nil + end + end + + errors.compact! + + if errors.length>0 + next -1, errors.join(', ') + end + + helper.create_resource(options) do |rule| + rule.allocate(*new_args) + end end delrule_desc = <<-EOT.unindent Deletes an existing ACL rule EOT - command :delete, delrule_desc, :id do - helper.delete_rule( options, args[0] ) + command :delete, delrule_desc, [:range] do + helper.perform_actions(args[0],options,"deleted") do |obj| + obj.delete + end end list_desc = <<-EOT.unindent diff --git a/src/oca/ruby/OpenNebula/Acl.rb b/src/oca/ruby/OpenNebula/Acl.rb index 48a336051e..9a0ccf940b 100644 --- a/src/oca/ruby/OpenNebula/Acl.rb +++ b/src/oca/ruby/OpenNebula/Acl.rb @@ -39,13 +39,14 @@ module OpenNebula # INFO_POOL_MINE # INSTANTIATE # CHOWN - class Acl + class Acl < PoolElement USERS = { "UID" => 0x100000000, "GID" => 0x200000000, "ALL" => 0x400000000 } + RESOURCES = { "VM" => 0x1000000000, @@ -70,121 +71,180 @@ module OpenNebula "CHOWN" => 0x100 # Auth. to change ownership of an object } - def initialize(rule_str=nil) - # Content stores numbers - @content = { - :users => 0, - :resources => 0, - :rights => 0 - } - - parse_rule(rule_str) if rule_str + # Constructor + # + # @param xml [String] must be an xml built with {#build_xml} + # @param client [Client] represents an XML-RPC connection + def initialize(xml, client) + super(xml,client) end - def parse_rule(rule_str) - begin - rule_str = rule_str.split(" ") - parse_users(rule_str[0]) - parse_resources(rule_str[1]) - parse_rights(rule_str[2]) - rescue Exception => e - @content[:users] = OpenNebula::Error.new(e.message) + # Creates an empty XML representation. It contains the id, if it is + # specified. + # + # @param pe_id [Integer] rule ID + # @param client [Client] represents an XML-RPC connection + # + # @return [String] an empty XML representation + def self.build_xml(pe_id=nil) + if pe_id + acl_xml = "#{pe_id}" + else + acl_xml = "" end + + XMLElement.build_xml(acl_xml,'ACL') end - def parse_users(users) + # Creates a new ACL rule. + # + # @param user [String] + # A string containing a hex number, e.g. 0x100000001 + # @param resource [String] + # A string containing a hex number, e.g. 0x2100000001 + # @param rights [String] + # A string containing a hex number, e.g. 0x10 + # + # @return [nil, OpenNebula::Error] nil in case of success, Error + # otherwise + def allocate(user, resource, rights) + return super( AclPool::ACL_POOL_METHODS[:addrule], + user, + resource, + rights ) + end + + # Deletes the Acl rule + # + # @return [nil, OpenNebula::Error] nil in case of success, Error + # otherwise + def delete() + super(AclPool::ACL_POOL_METHODS[:delrule]) + end + + # Does nothing, individual ACL rules info can't be retrieved from + # OpenNebula + # + # @return [nil] nil + def info() + return nil + end + + # Parses a rule string, e.g. "#5 HOST+VM/@12 INFO+CREATE+DELETE" + # + # @param rule_str [String] an ACL rule in string format + # + # @return [Array] an Array containing 3 strings (hex 64b numbers), + # or OpenNebula::Error objects + def self.parse_rule(rule_str) + ret = Array.new + + rule_str = rule_str.split(" ") + + if rule_str.length != 3 + return [OpenNebula::Error.new( + "String needs three components: User, Resource, Rights")] + end + + ret << parse_users(rule_str[0]) + ret << parse_resources(rule_str[1]) + ret << parse_rights(rule_str[2]) + + return ret + end + +private + + # Converts a string in the form [#, @, *] to a hex. number + # + # @param users [String] Users component string + # + # @return [String] A string containing a hex number + def self.parse_users(users) begin - @content[:users] = calculate_users(users) + return calculate_ids(users).to_i.to_s(16) rescue Exception => e - @content[:resources] = OpenNebula::Error.new(e.message) + return OpenNebula::Error.new(e.message) end end - def parse_resources(resources) + # Converts a resources string to a hex. number + # + # @param resources [String] Resources component string + # + # @return [String] A string containing a hex number + def self.parse_resources(resources) begin + ret = 0 resources = resources.split("/") if resources.size != 2 - @content[:resources] = OpenNebula::Error.new( - "Resource #{resources} not well formed") - return + raise "Resource '#{resources}' malformed" end resources[0].split("+").each{ |resource| if !RESOURCES[resource.upcase] - raise "Resource #{resource} malformed." + raise "Resource '#{resource}' does not exist" end - @content[:resources] += RESOURCES[resource.upcase] + ret += RESOURCES[resource.upcase] } - @content[:resources] += calculate_users(resources[1]) + ret += calculate_ids(resources[1]) + return ret.to_i.to_s(16) rescue Exception => e - @content[:resources] = OpenNebula::Error.new(e.message) + return OpenNebula::Error.new(e.message) end end - def parse_rights(rights) + # Converts a rights string to a hex. number + # + # @param rights [String] Rights component string + # + # @return [String] A string containing a hex number + def self.parse_rights(rights) begin + ret = 0 rights = rights.split("+") rights.each{ |right| - raise "Right #{right} malformed." if !RIGHTS[right.upcase] + raise "Right '#{right}' does not exist" if !RIGHTS[right.upcase] - @content[:rights] += RIGHTS[right.upcase] + ret += RIGHTS[right.upcase] } + return ret.to_i.to_s(16) rescue Exception => e - @content[:rights] = OpenNebula::Error.new(e.message) + return OpenNebula::Error.new(e.message) end end - - def calculate_users(users_str) - if users_str == "*" - return USERS["ALL"] - end + # Calculates the numeric value for a String containing an individual + # (#), group (@) or all (*) ID component + # + # @param id_str [String] Rule Id string + # + # @return [Integer] the numeric value for the given id_str + def self.calculate_ids(id_str) + raise "ID string '#{id_str}' malformed" if + !id_str.match(/^([\#@]\d+|\*)$/) value = 0 - case users_str[0..0] + case id_str[0..0] when "#" value = USERS["UID"] + users_value = id_str[1..-1].to_i + value + when "@" value = USERS["GID"] - end + users_value = id_str[1..-1].to_i + value - users_value = users_str[1..-1].to_i + value + when "*" + value = USERS["ALL"] + end return users_value end - - def users_hex_str - @content[:users].to_i.to_s(16) - end - - def resources_hex_str - @content[:resources].to_i.to_s(16) - end - - def rights_hex_str - @content[:rights].to_i.to_s(16) - end - - def is_error? - OpenNebula.is_error?(@content[:users]) || - OpenNebula.is_error?(@content[:resources]) || - OpenNebula.is_error?(@content[:rights]) || - @content[:users] == 0 || - @content[:resources] == 0 || - @content[:rights] == 0 - end - - def error - @content.each{ |part| - return part if OpenNebula.is_error?(part) - } - end - end end diff --git a/src/oca/ruby/OpenNebula/AclPool.rb b/src/oca/ruby/OpenNebula/AclPool.rb index 9b767e21c8..5f2de41e87 100644 --- a/src/oca/ruby/OpenNebula/AclPool.rb +++ b/src/oca/ruby/OpenNebula/AclPool.rb @@ -49,45 +49,5 @@ module OpenNebula # Retrieves all the Acls in the pool. super(ACL_POOL_METHODS[:info]) end - - # Adds a new ACL rule. - # - # +user+ A string containing a hex number, e.g. 0x100000001 - # +resource+ A string containing a hex number, e.g. 0x2100000001 - # +rights+ A string containing a hex number, e.g. 0x10 - def addrule(user, resource, rights) - return @client.call( ACL_POOL_METHODS[:addrule], - user, - resource, - rights ) - end - - # Adds a new ACL rule. - # - # +rule+ Rule tring - def addrule_with_str(rule_str) - rule = Acl.new rule_str - - return rule.error if rule.is_error? - - return addrule( rule.users_hex_str, - rule.resources_hex_str, - rule.rights_hex_str ) - end - - # Deletes an existing ACL rule. - # - # +id+ An existing ACL rule ID - def delrule(id) - rc = @client.call( ACL_POOL_METHODS[:delrule], id.to_i ) - - rc = nil if !OpenNebula.is_error?(rc) - - return rc - end - - private - end - end