diff --git a/src/ozones/Client/lib/api/zona.rb b/src/ozones/Client/lib/api/zona.rb index f28008a4ea..a514508665 100644 --- a/src/ozones/Client/lib/api/zona.rb +++ b/src/ozones/Client/lib/api/zona.rb @@ -14,6 +14,7 @@ # limitations under the License. # #--------------------------------------------------------------------------- # + require 'rubygems' require 'uri' require 'net/https' @@ -30,10 +31,21 @@ require 'zona/ZoneElement' require 'zona/VDCPool' require 'zona/VDCElement' +################################################################################ +# This module contains all the OZones API related classes and utilities. +################################################################################ module Zona + ############################################################################ + # OZones Client provides functionality to send and retrieve information + # from the OZones server side. It is used by CLI and API to handle the + # http requests to the server and basic error control on the + # responses. + ############################################################################ class Client + # Provides current version information. + # Should match server's oZones version. OZONES_VERSION = <<EOT oZones 1.0 Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) @@ -43,9 +55,13 @@ 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 EOT - ###################################################################### - # Initialize client library - ###################################################################### + # Initialize client instance + # @param [String] user oZones username + # @param [String] pass oZones password + # @param [String] endpoint Server endpoint + # @param [Integer] timeout client timout, defaults means no timeout + # @param [Boolean] debug_flag produce debug information + # @return [Client] Client instance def initialize(user=nil, pass=nil, endpoint_str=nil, timeout=nil, debug_flag=true) @debug = debug_flag @@ -76,14 +92,9 @@ EOT end end - ##################################### - # General Resource Request Methods # - #################################### - - ###################################################################### - # Retieves all elements on a pool - # :zonetemplate - ###################################################################### + # Retrieves all elements of a kind (pool) + # @param [String] kind element kind + # @return [String, Zone::Error] Response string or Error def get_pool(kind) url = URI.parse(@endpoint+"/" + kind) req = Net::HTTP::Get.new(url.path) @@ -97,20 +108,28 @@ EOT return Client.parse_error(res, kind) end - ###################################################################### - # Post a new Resource to the relevant OZones Pool - # :zonetemplate - ###################################################################### + # Creates a resource from an opennebula template file + # @param [String] kind resource kind: vdc,zone... + # @param [String] template path to template file + # @return [String, Zona::Error] Response string or Error def post_resource_file(kind, template) tmpl_str = File.read(template) post_resource_str(kind, tmpl_str) end + # Creates a resource from an OpenNebula template string + # @param [String] kind resource kind: vdc,zone... + # @param [String] tmpl_str OpenNebula template string + # @return [String, Zona::Error] Response string or Error def post_resource_str(kind, tmpl_str) tmpl_json = Zona.to_body(kind, tmpl_str) post_resource(kind, tmpl_json) end + # Creates a resource + # @param [String] kind resource kind: vdc, zone... + # @param [String] tmpl_json JSON template + # @return [String, Zona::Error] Response string or Error def post_resource(kind, tmpl_json) url = URI.parse("#{@endpoint}/#{kind}") @@ -126,11 +145,19 @@ EOT return Client.parse_error(res, kind) end + # Modifies a resource from an OpenNebula template string + # @param [String] kind resource kind: vdc, zone... + # @param [String] tmpl_str OpenNebula template string + # @return [String, Zona::Error] Response string or Error def put_resource_str(kind, id, tmpl_str) tmpl_json = Client.to_body(kind, tmpl_str) put_resource(kind, id, tmpl_json) end + # Modifies a resource + # @param [String] kind resource kind: vdc, zone... + # @param [String] tmpl_json JSON template + # @return [String, Zona::Error] Response string or Error def put_resource(kind, id, tmpl_json) url = URI.parse("#{@endpoint}/#{kind}/#{id}") @@ -146,6 +173,11 @@ EOT return Client.parse_error(res, kind) end + + # Retrieves a resource + # @param [String] Kind resource kind: vdc, zone... + # @param [#to_i] id resource id + # @return [String, Zona::Error] Response string or Error def get_resource(kind, id) url = URI.parse("#{@endpoint}/#{kind}/#{id}") req = Net::HTTP::Get.new(url.path) @@ -159,6 +191,10 @@ EOT return Client.parse_error(res, kind) end + # Deletes a resource + # @param [String] kind resource kind: vdc, zone... + # @param [#to_i] id resource id + # @return [String, Zona::Error] Response string or Error def delete_resource(kind, id) url = URI.parse("#{@endpoint}/#{kind}/#{id}") req = Net::HTTP::Delete.new(url.path) @@ -173,10 +209,13 @@ EOT end - # ######################################################################### + + private + + + # Starts an http connection and calls the block provided. SSL flag # is set if needed. - # ######################################################################### def self.http_start(url, timeout, &block) http = Net::HTTP.new(url.host, url.port) @@ -212,6 +251,10 @@ EOT end end + # Parses a response + # @param [String] value response string + # @param [String] kind resource kind + # @return [String, Zona::Error] Returns the value or Error if found def self.parse_error(value, kind) if Zona.is_error?(value) return value @@ -237,10 +280,11 @@ EOT end - # ############################################ - # Template helpers - # ############################################ + # Turns a OpenNebula template string into a JSON string + # @param [String] kind element kind + # @param [String] tmpl_str template + # @return [String, Zona::Error] JSON string or Error def self.to_body(kind, tmpl_str) tmpl = OpenNebula::Configuration.new(tmpl_str) res = { "#{kind}" => tmpl.conf } @@ -248,33 +292,29 @@ EOT return OZonesJSON.to_json(res) end - # ######################################################################### - # Error handling functions - # ######################################################################### - + # @return [Boolean] Returns true if instance of {Zona::Error} def self.is_error?(value) value.class==Zona::Error end + # @return [Boolean] Returns true if HTTP return code is not OK def self.is_http_error?(value) value.class != Net::HTTPOK end - # ######################################################################### # The Error Class represents a generic error in the Zona # library. It contains a readable representation of the error. - # ######################################################################### class Error attr_reader :message - # +message+ a description of the error + # @param [String] A description of the error def initialize(message=nil) @message=message end + # @return [String] Error message description def to_s() @message end end - end diff --git a/src/ozones/Client/lib/api/zona/OZonesElement.rb b/src/ozones/Client/lib/api/zona/OZonesElement.rb index 2aefab0446..502b0a20d4 100644 --- a/src/ozones/Client/lib/api/zona/OZonesElement.rb +++ b/src/ozones/Client/lib/api/zona/OZonesElement.rb @@ -14,12 +14,18 @@ # limitations under the License. # #--------------------------------------------------------------------------- # + module Zona + # Standard abstraction of an OZones element. To be inherited. class OZonesElement < JSONElement protected + # Initializes an OZones Element instance. Tries to set @pe_id and @name + # @param [Hash] hash element description + # @param [Zona::Client] client OZones client + # @return [String] Element's name or nil def initialize(hash, client) @client = client @json_hash = hash @@ -28,6 +34,11 @@ module Zona @name = self["name"] ? self["name"] : nil end + # Retrieves details about an object and fills in + # the information hash + # @param [String] kind element kind: zone, vdc... + # @param [String] root_element root element of the JSON object description + # @return [Zona::Error] nil or Error def info(kind, root_element) return Error.new('ID not defined') if !@pe_id @@ -44,10 +55,18 @@ module Zona rc end + # Allocates a new element from a hash description + # @param [String] kind element kind: zone, vdc... + # @param [Hash] tmpl_hash element template hash + # @return [Zona::Error] nil or Error def allocate_hash(kind, tmpl_hash) allocate(kind, tmpl_hash.to_json) end + # Allocates a new element from a JSON description + # @param [String] kind element kind: zone, vdc... + # @param [String] tmpl_json element JSON template + # @return [Zona::Error] nil or Error def allocate(kind, tmpl_json) rc = @client.post_resource(kind, tmpl_json) @@ -59,6 +78,9 @@ module Zona rc end + # Deletes current element + # @param [String] kind element kind: zone, vdc... + # @return [Zona::Error] nil or Error def delete(kind) return Error.new('ID not defined') if !@pe_id @@ -71,6 +93,10 @@ module Zona attr_reader :pe_id, :name + # Creates a new element with the custom ID + # @param [#to_i] id element ID + # @param [Zona::Client] client OZones Client for this element + # @return [OZonesElement] A new element object def self.new_with_id(id, client=nil) self.new(self.build_json(id),client) end diff --git a/src/ozones/Client/lib/api/zona/OZonesJSON.rb b/src/ozones/Client/lib/api/zona/OZonesJSON.rb index f0a4e0a0f5..62e1ebfd19 100644 --- a/src/ozones/Client/lib/api/zona/OZonesJSON.rb +++ b/src/ozones/Client/lib/api/zona/OZonesJSON.rb @@ -19,8 +19,14 @@ module Zona require 'json' + # Several class methods regarding the handling of JSON descriptions + # for the OZones utilities. class OZonesJSON + # Build an element description hash. + # @param [String] json_str JSON description of the element + # @param [String] root_element root element of the JSON object + # @return [Hash,Zona::Error] The parsed JSON hash, or Error def self.build_json(json_str, root_element) begin parser = JSON.parser.new(json_str, {:symbolize_names => false}) @@ -37,12 +43,14 @@ module Zona end end - # Alias for compatibility + # @see build_json def self.parse_json(json_str, root_element) OZonesJSON.build_json(json_str, root_element) end - + # Generates a pretty JSON string from a hash + # @param [Hash] hash_to_convert a hash to be converted + # @return [String, Zona::Error] JSON string or Error if conversion fails def self.to_json(hash_to_convert) begin JSON.pretty_generate(hash_to_convert) @@ -53,11 +61,20 @@ module Zona end + # This class represents an element described by a JSON string + # In practice, this is represented by a hash, + # result of parsing the JSON string. class JSONElement + + # Initializes an instance + # @param [Hash] json_hash a hash with the object description def initialize(json_hash=nil) @json_hash=json_hash end + # Initializes an instance with a JSON description + # @param [String] json_str JSON description + # @param [String] root_element root element in the element description def initialize_json(json_str, root_element) rc = OZonesJSON.build_json(json_str,root_element) @json_hash = rc @@ -66,6 +83,10 @@ module Zona @json_hash=nil end end + + # Accesses the value of a JSON element key + # @param [String] key + # @return [String] Value def [](key) @json_hash[key] end @@ -73,11 +94,17 @@ module Zona end + # This class represents a collection of JSON Elements and it is itself one class JSONPool < JSONElement + + # Initializes an instance + # @param [Hash] json_hash a hash with the object description def initialize(json_hash=nil) super(json_hash) end + # Allows to iterate through the elements of a JSONPool + # @param [Block] block a block to be called in each iteration def each_element(block) @json_hash[@element_name].each do |elem| block.call self.factory(elem) diff --git a/src/ozones/Client/lib/api/zona/OZonesPool.rb b/src/ozones/Client/lib/api/zona/OZonesPool.rb index bb4a5ac6c8..7c86132c5e 100644 --- a/src/ozones/Client/lib/api/zona/OZonesPool.rb +++ b/src/ozones/Client/lib/api/zona/OZonesPool.rb @@ -14,12 +14,18 @@ # limitations under the License. # #--------------------------------------------------------------------------- # + module Zona + # Standard pool abstraction. To be inherited. class OZonesPool < JSONPool protected + # Initializes a Pool instance + # @param [String] pool pool name tag + # @param [String] pool pool elements name tag + # @param [Zona::Client] client OZones Client def initialize(pool,element,client) super(nil) @@ -28,10 +34,16 @@ module Zona @element_name = element.upcase end + # Produces a new Pool element with the provided description + # @param [String] element_json JSON string of the element + # @return [String] Element's name or nil def factory(element_json) - OZonesPoolElement.new(element_json, @client) + OZonesElement.new(element_json, @client) end + # Retrieves the Pool information + # @param [String] kind pool kind: vdc, zone... + # @return [Zona:Error] nil or Error def info(kind) rc = @client.get_pool(kind) @@ -45,6 +57,8 @@ module Zona public + # Allows iteration on pools elements + # @param [Block] block a block to call for each iteration def each(&block) each_element(block) if @json_hash end diff --git a/src/ozones/Client/lib/api/zona/VDCElement.rb b/src/ozones/Client/lib/api/zona/VDCElement.rb index 41faebc1c1..c3152f23c0 100644 --- a/src/ozones/Client/lib/api/zona/VDCElement.rb +++ b/src/ozones/Client/lib/api/zona/VDCElement.rb @@ -14,12 +14,20 @@ # limitations under the License. # #--------------------------------------------------------------------------- # + module Zona + # This class describes a single VDC element. It can be used to + # allocate, delete, add hosts, remove hosts and retrieve full information + # for a VDC. class VDC < OZonesElement + # String describing the kind of this resource VDC_KIND = "vdc" + # Builds minimal JSON description for a VDC + # @param [#to_i] pe_id VDC's ID + # @return [Hash,Zona::Error] Hash description of the object, or Error def self.build_json(pe_id=nil) if pe_id json = "{\"VDC\":{\"id\":#{pe_id}}}" @@ -29,26 +37,50 @@ module Zona OZonesJSON.build_json(json,"VDC") end + # Initializes a VDC object instance + # @param [Hash] hash VDC description + # @param [Zona::Client] client OZones Client + # @return [String] Element's name or nil def initialize(hash, client) super(hash, client) end + # Retrieves details about this object and fills in + # the information hash + # @return [Zona::Error] nil or Error def info super(VDC_KIND,"VDC") end + # Allocates a new element from a hash description + # @param [Hash] template element description + # @return [Zona::Error] nil or Error def allocate_hash(template) super(VDC_KIND,template) end + # Allocates a new element from a JSON description + # @param [String] template element description + # @return [Zona::Error] nil or Error def allocate(template) super(VDC_KIND,template) end + # Deletes current element + # @return [Zona::Error] nil or Error def delete super(VDC_KIND) end + + # Adds hosts to a VDC. The specified hosts are added to the VDC's + # current ones. + # @param [Array<#to_i>] hosts_array array of hosts IDs + # in the zone to be added + # @param [Hash] options a hash of options + # @option options [Boolean] :force allows hosts to add hosts + # which already belong to other VDCs + # @return [Zona::Error] nil or Error def addhosts(hosts_array,options={}) return Error.new('VDC not info-ed') if !@json_hash @@ -67,6 +99,10 @@ module Zona nil end + # Delete hosts from a VDC. The specified hosts are removed from the VDC. + # @param [Array<#to_i>] hosts_array array of the VDC's hosts IDs + # to be removed. If a host is not in the VDC, then it is ignored. + # @return [Zona::Error] nil or Error def delhosts(hosts_array) return Error.new('VDC not info-ed') if !@json_hash diff --git a/src/ozones/Client/lib/api/zona/VDCPool.rb b/src/ozones/Client/lib/api/zona/VDCPool.rb index 0984ba584b..ab1894b429 100644 --- a/src/ozones/Client/lib/api/zona/VDCPool.rb +++ b/src/ozones/Client/lib/api/zona/VDCPool.rb @@ -14,19 +14,31 @@ # limitations under the License. # #--------------------------------------------------------------------------- # + module Zona + # This class represents a set of VDCs. It allows to list the defined + # VDCs and iterate on them. class VDCPool < OZonesPool + + # String describing the kind of this resource VDC_POOL_KIND="vdc" + # Initializes a VDC Pool instance + # @param [Zona::Client] client OZones Client def initialize(client) super("VDC_POOL", "VDC", client) end + # Produces a new VDC element with the provided description + # @param [String] element_json JSON string of the element + # @return [String] Element's name or nil def factory(element_json) VDC.new(element_json,@client) end + # Retrieves the information for this pool + # @return [Zona:Error] nil or Error def info super(VDC_POOL_KIND) end diff --git a/src/ozones/Client/lib/api/zona/ZoneElement.rb b/src/ozones/Client/lib/api/zona/ZoneElement.rb index ce51cbeafa..ca54acd10d 100644 --- a/src/ozones/Client/lib/api/zona/ZoneElement.rb +++ b/src/ozones/Client/lib/api/zona/ZoneElement.rb @@ -14,12 +14,19 @@ # limitations under the License. # #--------------------------------------------------------------------------- # + module Zona + # This class describes a single OZones Zone element. It can be used to + # allocate, delete and retrieve full information for a Zone. class Zone < OZonesElement + # String describing the kind of this resource ZONE_KIND = "zone" + # Builds minimal JSON description for a Zone + # @param [#to_i] pe_id zone's ID + # @return [Hash,Zona::Error] Hash description of the object, or Error def self.build_json(pe_id=nil) if pe_id json = "{\"ZONE\":{\"id\":#{pe_id}}}" @@ -29,22 +36,37 @@ module Zona OZonesJSON.build_json(json,"ZONE") end + # Initializes a Zone object instance + # @param [Hash] hash zone description + # @param [Zona::Client] client OZones Client + # @return [String] Element's name or nil def initialize(hash, client) super(hash, client) end + # Retrieves details about this object and fills in + # the information hash + # @return [Zona::Error] nil or Error def info super(ZONE_KIND,"ZONE") end + # Allocates a new element from a hash description + # @param [Hash] template element description + # @return [Zona::Error] nil or Error def allocate_hash(template) super(ZONE_KIND,template) end + # Allocates a new element from a JSON description + # @param [String] template element description + # @return [Zona::Error] nil or Error def allocate(template) super(ZONE_KIND,template) end + # Deletes current element + # @return [Zona::Error] nil or Error def delete super(ZONE_KIND) end diff --git a/src/ozones/Client/lib/api/zona/ZonePool.rb b/src/ozones/Client/lib/api/zona/ZonePool.rb index 663d313a36..0a50e0c7e4 100644 --- a/src/ozones/Client/lib/api/zona/ZonePool.rb +++ b/src/ozones/Client/lib/api/zona/ZonePool.rb @@ -14,23 +14,33 @@ # limitations under the License. # #--------------------------------------------------------------------------- # + module Zona + # This class represents a set of Zones. It allows to list the defined + # Zones and iterate on them. class ZonePool < OZonesPool + # String describing the kind of this resource ZONE_POOL_KIND = "zone" + # Initializes a Zone Pool instance + # @param [Zona::Client] client OZones Client def initialize(client) super("ZONE_POOL", "ZONE", client) end + # Produces a new Zone element with the provided description + # @param [String] element_json JSON string of the element + # @return [String] Element's name or nil def factory(element_json) Zone.new(element_json,@client) end + # Retrieves the information for this pool + # @return [Zona:Error] nil or Error def info super(ZONE_POOL_KIND) end end - end