blob: c0504e119ae5748c0c4a1c8436148246530c684c [file]
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership. The
# ASF licenses this file to you 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.
module Deltacloud::EC2
class ActionHandler
MAPPINGS = {
:describe_availability_zones => { :method => :realms, :params => { 'ZoneName.1' => :id } },
:describe_images => { :method => :images, :params => { 'ImageId.1' => :id }},
:describe_instances => { :method => :instances, :params => {'InstanceId.1' => :id } },
:describe_key_pairs => { :method => :keys, :params => {} },
:create_key_pair => { :method => :create_key, :params => { 'KeyName' => :key_name }},
:delete_key_pair => { :method => :destroy_key, :params => { 'KeyName' => :id }},
:run_instances => { :method => :create_instance, :params => { 'ImageId' => :image_id, 'InstanceType' => :hwp_id, 'Placement.AvailabilityZone' => :realm_id, 'UserData' => :user_data }},
:stop_instances => { :method => :stop_instance, :params => { 'InstanceId.1' => :id }},
:start_instances => { :method => :start_instance, :params => { 'InstanceId.1' => :id }},
:reboot_instances => { :method => :reboot_instance, :params => { 'InstanceId.1' => :id }},
:terminate_instances => { :method => :destroy_instance, :params => { 'InstanceId.1' => :id }},
}
def self.mappings
MAPPINGS
end
attr_reader :action
def initialize(action)
@action = action
end
def deltacloud_method
self.class.mappings[action.action][:method]
end
def deltacloud_method_params
parameters = action.parameters.dup
self.class.mappings[action.action][:params].inject({}) do |result, p|
result[p.last] = parameters.delete(p.first)
result.delete_if { |k,v| v.nil? }
end
end
def perform!(credentials, driver)
@result = case deltacloud_method
when :create_instance then driver.send(deltacloud_method, credentials, deltacloud_method_params.delete(:image_id), deltacloud_method_params)
when :stop_instance then instance_action(driver, deltacloud_method, credentials, deltacloud_method_params.delete(:id))
when :start_instance then instance_action(driver, deltacloud_method, credentials, deltacloud_method_params.delete(:id))
when :destroy_instance then driver.send(deltacloud_method, credentials, deltacloud_method_params.delete(:id))
when :reboot_instance then driver.send(deltacloud_method, credentials, deltacloud_method_params.delete(:id))
else driver.send(deltacloud_method, credentials, deltacloud_method_params)
end
end
# Some drivers, like RHEV-M does not return the instance object
# but just notify client that the action was executed successfully.
#
# If we not received an Instance object, then we need to do additional
# query.
#
def instance_action(driver, action, credentials, id)
instance = driver.send(action, credentials, id)
if instance.kind_of? Instance
instance
else
driver.instance(credentials, :id => id)
end
end
def to_xml(context)
ResultParser.parse(action, @result, context)
end
end
class ResultParser
include ResultHelper
attr_reader :query
attr_reader :object
attr_reader :context
def self.parse(query, result, context)
parser = new(query, result, context)
layout = "%#{query.action.to_s.camelize}Response{:xmlns => 'http://ec2.amazonaws.com/doc/2012-04-01/'}\n"+
"\t%requestId #{query.request_id}\n" +
"\t=render(:#{query.action}, object)\n"
Haml::Engine.new(layout, :filename => 'layout').render(parser)
end
def initialize(query, object, context)
@context = context
@query = query
@object = object
end
def build_xml
Converter.convert(query.action, object)
end
def render(template, obj)
template_filename = File.join(File.dirname(__FILE__), 'views', '%s.haml' % template.to_s)
Haml::Engine.new(File.read(template_filename), :filename => template_filename).render(self, :object => obj)
end
end
class QueryParser
class InvalidAction < StandardError; end
def self.parse(params, request_id)
parser = new(request_id, params)
unless parser.valid_action?
raise InvalidAction.new('Invalid action (%s)' % parser.action)
else
ActionHandler.new(parser)
end
end
attr_reader :action
attr_reader :parameters
attr_reader :version
attr_reader :expiration
attr_reader :authentication
attr_reader :request_id
def initialize(request_id, params={})
@request_id = request_id
@action = (params.delete('Action') || 'Unknown').underscore.intern
@version = params.delete('Version')
@authentication = {
:security_token => params.delete('SecurityToken'),
:access_key_id => params.delete('AWSAccessKeyId'),
:signature => {
:version => params.delete('SignatureVersion'),
:value => params.delete('Signature'),
:method => params.delete('SignatureMethod'),
:timestamp => params.delete('Timestamp')
}
}
@expiration = params.delete('Expires')
@parameters = params
end
def valid_actions
ActionHandler::mappings.keys
end
def valid_action?
return false if @action == :unknown
return false unless valid_actions.include?(@action)
true
end
end
end