lib/providers/openstack/openstack.rb in lorj-1.0.3 vs lib/providers/openstack/openstack.rb in lorj-1.0.4

- old
+ new

@@ -14,32 +14,289 @@ # See the License for the specific language governing permissions and # limitations under the License. # This class describes how to process some actions, and will do everything prior # this task to make it to work. -class Openstack < BaseDefinition - def initialize - superclass.provides([:compute, :network]) +require 'fog' +require 'uri' + +hpcloud_path = File.expand_path(File.dirname(__FILE__)) + +require File.join(hpcloud_path, 'openstack_query.rb') +require File.join(hpcloud_path, 'openstack_get.rb') +require File.join(hpcloud_path, 'openstack_delete.rb') +require File.join(hpcloud_path, 'openstack_create.rb') +require File.join(hpcloud_path, 'openstack_update.rb') + +# Defines Meta Openstack object +class Openstack + process_default :use_controller => true + + define_obj :services + # Define Data used by service + + obj_needs :data, :account_id, :mapping => :openstack_username + obj_needs :data, :account_key, :mapping => :openstack_api_key + obj_needs :data, :auth_uri, :mapping => :openstack_auth_uri + obj_needs :data, :tenant, :mapping => :openstack_tenant + obj_needs :data, ':excon_opts/:connect_timeout', :default_value => 30 + obj_needs :data, ':excon_opts/:read_timeout', :default_value => 240 + obj_needs :data, ':excon_opts/:write_timeout', :default_value => 240 + + define_obj :compute_connection + # Defines Data used by compute. + + obj_needs :data, :account_id, :mapping => :openstack_username + obj_needs :data, :account_key, :mapping => :openstack_api_key, + :decrypt => true + obj_needs :data, :auth_uri, :mapping => :openstack_auth_url + obj_needs :data, :tenant, :mapping => :openstack_tenant + obj_needs :data, :compute, :mapping => :openstack_region + + define_obj :network_connection + obj_needs :data, :account_id, :mapping => :openstack_username + obj_needs :data, :account_key, :mapping => :openstack_api_key, + :decrypt => true + obj_needs :data, :auth_uri, :mapping => :openstack_auth_url + obj_needs :data, :tenant, :mapping => :openstack_tenant + obj_needs :data, :network, :mapping => :openstack_region + + # Openstack tenants object + define_obj(:tenants, :create_e => :openstack_get_tenant) + obj_needs :CloudObject, :compute_connection + obj_needs :data, :tenant + + # Openstack Network + define_obj :network + def_hdata :network_name, :mapping => :name + def_attr_mapping :external, :router_external + + define_obj :keypairs + + undefine_attribute :id # Do not return any predefined ID + + define_obj :server_log + + # Excon::Response object type + def_attr_mapping :output, 'output' + + define_obj :security_groups + # Added tenant data to add in queries. + obj_needs :CloudObject, :tenants + + define_obj :rule + obj_needs :data, :dir, :mapping => :direction + attr_value_mapping :IN, 'ingress' + attr_value_mapping :OUT, 'egress' + + obj_needs :data, :proto, :mapping => :protocol + obj_needs :data, :port_min, :mapping => :port_range_min + obj_needs :data, :port_max, :mapping => :port_range_max + obj_needs :data, :addr_map, :mapping => :remote_ip_prefix + obj_needs :data, :sg_id, :mapping => :security_group_id + + def_attr_mapping :dir, :direction + def_attr_mapping :proto, :protocol + def_attr_mapping :port_min, :port_range_min + def_attr_mapping :port_max, :port_range_max + def_attr_mapping :addr_map, :remote_ip_prefix + def_attr_mapping :sg_id, :security_group_id + + define_data(:account_id, + :account => true, + :desc => 'Openstack Username', + :validate => /^.+/ + ) + + define_data(:account_key, + :account => true, + :desc => 'Openstack Password', + :validate => /^.+/ + ) + define_data(:auth_uri, + :account => true, + :explanation => "The authentication service is identified as '"\ + "identity' under your horizon UI - Project/Compute then "\ + 'Access & security.', + :desc => 'Openstack Authentication service URL. '\ + 'Ex: https://mycloud:5000/v2.0/tokens', + :validate => %r{^http(s)?:\/\/.*\/tokens$} + ) + define_data(:tenant, + :account => true, + :explanation => 'The Project name is shown from your horizon UI'\ + ', on top left, close to the logo', + :desc => 'Openstack Tenant Name', + :validate => /^.+/ + ) + + define_data(:compute, + :account => true, + :explanation => 'Depending on your installation, you may need to'\ + ' provide a Region name. This information shown under your '\ + 'horizon UI - close right to the project name (top left).'\ + "\nIf there is no region shown, you can ignore it.", + :desc => 'Openstack Compute Region (Ex: regionOne)' + ) + + define_data(:network, + :account => true, + :desc => 'Openstack Network Region (Ex: regionOne)', + :explanation => 'Depending on your installation, you may need to'\ + ' provide a Region name. This information shown under your '\ + 'horizon UI - close right to the project name (top left).'\ + "\nIf there is no region shown, you can ignore it." + ) + + define_obj :server + def_attr_mapping :status, :state + attr_value_mapping :create, 'BUILD' + attr_value_mapping :boot, :boot + attr_value_mapping :active, 'ACTIVE' + attr_value_mapping :active, 'ACTIVE' + + def_attr_mapping :private_ip_address, :accessIPv4 + def_attr_mapping :public_ip_address, :accessIPv4 + def_attr_mapping :image_id, [:image, 'id'] + + define_obj :router + obj_needs_optional + obj_needs :data, :router_name, :mapping => :name + + # The FORJ gateway_network_id is extracted + # from Fog::HP::Network::Router[:external_gateway_info][:network_id] + + obj_needs :data, + :external_gateway_id, + :mapping => [:external_gateway_info, 'network_id'] + + def_attr_mapping :gateway_network_id, [:external_gateway_info, 'network_id'] + + # Port attributes used specifically by openstack fog API. + define_obj :port + def_attribute :device_owner + def_attribute :network_id + + define_obj :public_ip + def_attr_mapping :server_id, :instance_id + def_attr_mapping :public_ip, :ip + + define_obj :image + def_attr_mapping :image_name, :name +end + +# Following class describe how FORJ should handle Openstack Cloud objects. +class OpenstackController + def self.def_cruds(*crud_types) + crud_types.each do |crud_type| + case crud_type + when :create, :delete + base_method(crud_type) + when :query, :get + query_method(crud_type) + when :update + update_method(crud_type) + end + end end - def compute - Fog::Compute.new( - :provider => :openstack, - :openstack_api_key => superclass.oForjAccount.get(:account_id), - :openstack_username => superclass.oForjAccount.get(:account_key), - :openstack_auth_url => superclass.oForjAccount.get(:auth_uri), - :openstack_tenant => superclass.oForjAccount.get(:tenant_id), - :openstack_region => superclass.oForjAccount.get(:compute) - ) + def self.update_method(crud_type) + define_method(crud_type) do |sObjectType, obj, hParams| + method_name = "#{crud_type}_#{sObjectType}" + if self.class.method_defined? method_name + send(method_name, obj, hParams) + else + controller_error "'%s' is not a valid object for '%s'", + sObjectType, crud_type + end + end end - def network - Fog::Network.new( - :provider => :openstack, - :openstack_api_key => superclass.oForjAccount.get(:account_id), - :openstack_username => superclass.oForjAccount.get(:account_key), - :openstack_auth_url => superclass.oForjAccount.get(:auth_uri), - :openstack_tenant => superclass.oForjAccount.get(:tenant_id), - :openstack_region => superclass.oForjAccount.get(:network) - ) + def self.query_method(crud_type) + define_method(crud_type) do |sObjectType, sCondition, hParams| + method_name = "#{crud_type}_#{sObjectType}" + if self.class.method_defined? method_name + send(method_name, hParams, sCondition) + else + controller_error "'%s' is not a valid object for '%s'", + sObjectType, crud_type + end + end + end + + def self.base_method(crud_type) + define_method(crud_type) do |sObjectType, hParams| + method_name = "#{crud_type}_#{sObjectType}" + if self.class.method_defined? method_name + send(method_name, hParams) + else + controller_error "'%s' is not a valid object for '%s'", + sObjectType, crud_type + end + end + end + + # Define the Openstack controller handlers + def_cruds :create, :delete, :get, :query, :update + + def connect(sObjectType, hParams) + case sObjectType + when :services + # Fog use URI type for auth uri: URI.parse(:auth_uri) + # Convert openstack_auth_uri to type URI + hParams[:hdata][:openstack_auth_uri] = + URI.parse(hParams[:hdata][:openstack_auth_uri]) + retrieve_result = + Fog::OpenStack.retrieve_tokens_v2(hParams[:hdata], + hParams[:excon_opts]) + creds = format_retrieve_result(retrieve_result) + return creds + when :compute_connection + Fog::Compute.new( + hParams[:hdata].merge(:provider => :openstack) + ) + when :network_connection + Fog::Network::OpenStack.new(hParams[:hdata]) + else + controller_error "'%s' is not a valid object for 'connect'", sObjectType + end + end + + def set_attr(oControlerObject, key, value) + if oControlerObject.is_a?(Excon::Response) + controller_error "No set feature for '%s'", oControlerObject.class + end + + attributes = oControlerObject.attributes + + controller_error "attribute '%s' is unknown in '%s'. Valid one are : '%s'", + key[0], + oControlerObject.class, + oControlerObject.class.attributes unless + oControlerObject.class.attributes.include?(key[0]) + + attributes.rh_set(value, key) + rescue => e + controller_error "Unable to map '%s' on '%s'. %s", + key, oControlerObject, e.message + end + + def get_attr(oControlerObject, key) + if oControlerObject.is_a?(Excon::Response) + oControlerObject.data.rh_get(:body, key) + else + attributes = oControlerObject.attributes + controller_error "attribute '%s' is unknown in '%s'."\ + " Valid one are : '%s'", + key[0], + oControlerObject.class, + oControlerObject.class.attributes unless + oControlerObject.class.attributes.include?(key[0]) + + return attributes.rh_get(key) if attributes.rh_exist?(key) + return oControlerObject.send(key[0]) if key.length == 1 + oControlerObject.send(key[0]).rh_get(key[1..-1]) + end + rescue => e + controller_error "==>Unable to map '%s'. %s", key, e.message end end