You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@deltacloud.apache.org by mf...@redhat.com on 2012/05/11 12:41:38 UTC
[PATCH core 1/3] EC2: Added initial support for EC2 frontend
From: Michal Fojtik <mf...@redhat.com>
Signed-off-by: Michal fojtik <mf...@redhat.com>
---
server/bin/deltacloudd | 4 +-
server/config.ru | 4 +
server/lib/ec2/helpers.rb | 29 ++++++++
server/lib/ec2/helpers/converter.rb | 140 +++++++++++++++++++++++++++++++++++
server/lib/ec2/helpers/errors.rb | 46 ++++++++++++
server/lib/ec2/query_parser.rb | 129 ++++++++++++++++++++++++++++++++
server/lib/ec2/server.rb | 59 +++++++++++++++
7 files changed, 409 insertions(+), 2 deletions(-)
create mode 100644 server/lib/ec2/helpers.rb
create mode 100644 server/lib/ec2/helpers/converter.rb
create mode 100644 server/lib/ec2/helpers/errors.rb
create mode 100644 server/lib/ec2/query_parser.rb
create mode 100644 server/lib/ec2/server.rb
diff --git a/server/bin/deltacloudd b/server/bin/deltacloudd
index 57b6c49..8eb448d 100755
--- a/server/bin/deltacloudd
+++ b/server/bin/deltacloudd
@@ -61,8 +61,8 @@ BANNER
opts.on( '-P', '--provider PROVIDER', 'Use PROVIDER (default is set in the driver)') do |provider|
ENV['API_PROVIDER'] = provider
end
- opts.on('--cimi', 'USe the DMTF CIMI frontend, not the Deltacloud frontend') do
- ENV['API_FRONTEND'] = 'cimi'
+ opts.on('-f', '--frontend FRONTEND', 'Use the different frontend, not the Deltacloud (cimi or ec2)') do |frontend|
+ ENV['API_FRONTEND'] = frontend
end
opts.on( '-c', '--config [FILE]', 'Read provider and other config from FILE (default: ~/.deltacloud/config)') do |config|
options[:config] = File::expand_path(config || DEFAULT_CONFIG)
diff --git a/server/config.ru b/server/config.ru
index 2280d0e..5deff47 100644
--- a/server/config.ru
+++ b/server/config.ru
@@ -30,6 +30,9 @@ if ENV['API_FRONTEND'] == 'deltacloud'
elsif ENV['API_FRONTEND'] == 'cimi'
API_VERSION = "1.0.0"
API_ROOT_URL = "/cloudEntryPoint"
+elsif ENV['API_FRONTEND'] == 'ec2'
+ API_VERSION = "0.1"
+ API_ROOT_URL = "/"
end
require File.join(File.dirname(__FILE__), 'lib', ENV['API_FRONTEND'], 'server.rb')
@@ -37,6 +40,7 @@ require File.join(File.dirname(__FILE__), 'lib', ENV['API_FRONTEND'], 'server.rb
frontend_klass = case ENV['API_FRONTEND']
when 'deltacloud' then Deltacloud::API
when 'cimi' then CIMI::API
+ when 'ec2' then Deltacloud::EC2::API
end
class IndexEntrypoint < Sinatra::Base
diff --git a/server/lib/ec2/helpers.rb b/server/lib/ec2/helpers.rb
new file mode 100644
index 0000000..32380fa
--- /dev/null
+++ b/server/lib/ec2/helpers.rb
@@ -0,0 +1,29 @@
+# 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
+ module EC2; end
+end
+
+require_relative './helpers/errors'
+require_relative './helpers/convertor'
+
+require_relative '../deltacloud/helpers/driver_helper'
+require_relative '../deltacloud/helpers/auth_helper'
+require_relative '../deltacloud/core_ext/string'
+require_relative '../deltacloud/core_ext/array'
+require_relative '../deltacloud/core_ext/hash'
+require_relative '../deltacloud/core_ext/integer'
+require_relative '../deltacloud/core_ext/proc'
diff --git a/server/lib/ec2/helpers/converter.rb b/server/lib/ec2/helpers/converter.rb
new file mode 100644
index 0000000..8a70fe1
--- /dev/null
+++ b/server/lib/ec2/helpers/converter.rb
@@ -0,0 +1,140 @@
+# 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 Converter
+
+ def self.convert(builder, action, result)
+ klass_name = ActionHandler::MAPPINGS[action][:method].to_s.camelize
+ klass = Converter.const_get(klass_name)
+ klass.new(builder, result).to_xml
+ end
+
+ class Base
+
+ attr_reader :xml
+ attr_reader :obj
+
+ def initialize(builder, object)
+ @xml = builder
+ @obj = object
+ end
+
+ end
+
+ class Realms < Base
+
+ def to_xml
+ xml.availabilityZoneInfo {
+ obj.each do |item|
+ xml.item {
+ xml.zoneName item.id
+ xml.zoneState item.state
+ xml.regionName item.name
+ }
+ end
+ }
+ end
+
+ end
+
+ class Images < Base
+
+ def to_xml
+ xml.imagesSet {
+ obj.each do |item|
+ xml.item {
+ xml.imageId item.id
+ xml.imageState item.state.downcase
+ xml.imageOwnerId item.owner_id
+ xml.architecture item.architecture
+ xml.imageType 'machine'
+ xml.name item.name
+ xml.description item.description
+ }
+ end
+ }
+ end
+
+ end
+
+ class CreateInstance < Base
+
+ def to_xml
+ xml.reservationId 'r-11111111'
+ xml.ownerId @obj.owner_id
+ xml.groupSet {
+ xml.item {
+ xml.groupId 'sg-11111111'
+ xml.groupName 'default'
+ }
+ }
+ Instances.new(@xml, [@obj]).instance_set
+ end
+
+ end
+
+ class Instances < Base
+
+ def instance_set
+ xml.instancesSet {
+ obj.each do |item|
+ xml.item {
+ xml.instanceId item.id
+ xml.imageId item.image_id
+ xml.instanceType item.instance_profile.name
+ xml.launchTime item.launch_time
+ xml.ipAddress item.public_addresses.first.address
+ xml.privateIpAddress item.public_addresses.first.address
+ xml.dnsName item.public_addresses.first.address
+ xml.privateDnsName item.private_addresses.first.address
+ xml.architecture item.instance_profile.architecture
+ xml.keyName item.keyname
+ xml.instanceState {
+ xml.code '16'
+ xml.name item.state.downcase
+ }
+ xml.placement {
+ xml.availabilityZone item.realm_id
+ xml.groupName
+ xml.tenancy 'default'
+ }
+ }
+ end
+ }
+ end
+
+ def to_xml
+ xml.reservationSet {
+ xml.item {
+ xml.reservationId 'r-11111111'
+ xml.ownerId 'deltacloud'
+ xml.groupSet {
+ xml.item {
+ xml.groupId 'sg-11111111'
+ xml.groupName 'default'
+ }
+ }
+ self.instance_set
+ }
+ }
+ end
+
+ end
+
+ end
+
+end
diff --git a/server/lib/ec2/helpers/errors.rb b/server/lib/ec2/helpers/errors.rb
new file mode 100644
index 0000000..7f8d610
--- /dev/null
+++ b/server/lib/ec2/helpers/errors.rb
@@ -0,0 +1,46 @@
+# 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
+ module Errors
+
+ def report_error(code)
+ error = (request.env['sinatra.error'] || @exception)
+ code = 500 if not code and not error.class.method_defined? :code
+ Nokogiri::XML::Builder.new do |xml|
+ xml.send(:Response) {
+ xml.send(:Errors) {
+ xml.send(:Code, error_for_code(code))
+ xml.send(:Message, error.respond_to?(:message) ? error.message : '')
+ }
+ xml.send(:RequestID, request_id)
+ }
+ end.to_xml
+ end
+
+ def request_id
+ Digest::MD5.hexdigest("#{request.env['REMOTE_ADDR']}#{request.env['HTTP_USER_AGENT']}#{Time.now.to_i}#{rand(250)}")
+ end
+
+ def error_for_code(code)
+ case code
+ when 401 then 'AuthFailure'
+ when 500 then 'InternalError'
+ else "Unavailable (#{code})"
+ end
+ end
+
+ end
+end
diff --git a/server/lib/ec2/query_parser.rb b/server/lib/ec2/query_parser.rb
new file mode 100644
index 0000000..7eebc9a
--- /dev/null
+++ b/server/lib/ec2/query_parser.rb
@@ -0,0 +1,129 @@
+# 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 => {} },
+ :run_instances => { :method => :create_instance, :params => { 'ImageId' => :image_id, 'InstanceType' => :hwp_id, 'Placement.AvailabilityZone' => :realm_id }}
+ }
+
+ attr_reader :action
+
+ def initialize(action)
+ @action = action
+ end
+
+ def deltacloud_method
+ MAPPINGS[action.action][:method]
+ end
+
+ def deltacloud_method_params
+ MAPPINGS[action.action][:params].inject({}) do |result, p|
+ result[p.last] = action.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)
+ else driver.send(deltacloud_method, credentials, deltacloud_method_params)
+ end
+ end
+
+ def to_xml
+ ResultParser.parse(action, @result).to_xml
+ end
+
+ end
+
+ class ResultParser
+
+ def self.parse(parser, result)
+ Nokogiri::XML::Builder.new do |xml|
+ xml.send(:"#{parser.action.to_s.camelize}Response", :xmlns => 'http://ec2.amazonaws.com/doc/2012-04-01/') {
+ xml.requestId parser.request_id
+ new(xml, parser, result).build_xml
+ }
+ end
+ end
+
+ def initialize(xml, parser, result)
+ @builder = xml
+ @parser = parser
+ @result = result
+ end
+
+ def build_xml
+ Converter.convert(@builder, @parser.action, @result)
+ end
+
+ end
+
+ class QueryParser
+
+ def self.parse(params, request_id)
+ parser = new(request_id, params)
+ unless parser.valid_action?
+ raise '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
diff --git a/server/lib/ec2/server.rb b/server/lib/ec2/server.rb
new file mode 100644
index 0000000..6586f16
--- /dev/null
+++ b/server/lib/ec2/server.rb
@@ -0,0 +1,59 @@
+# 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.
+
+require 'rubygems'
+require 'nokogiri'
+require 'sinatra/base'
+
+require_relative '../sinatra'
+require_relative './helpers'
+require_relative './query_parser'
+require_relative '../deltacloud/models'
+require_relative '../deltacloud/drivers'
+
+module Deltacloud::EC2
+ class API < Sinatra::Base
+
+ extend Deltacloud::Helpers::Drivers
+
+ use Rack::ETag
+ use Rack::CommonLogger
+
+ helpers Sinatra::AuthHelper
+ helpers Deltacloud::Helpers::Drivers
+ helpers Deltacloud::EC2::Errors
+
+ enable :xhtml
+ enable :dump_errors
+ enable :show_errors
+ enable :method_override
+ disable :show_exceptions
+
+ set :version, API_VERSION
+ set :root_url, API_ROOT_URL
+ set :root, File.join(File.dirname(__FILE__), '..', '..')
+
+ after do
+ headers 'Server' => 'Apache-Deltacloud-EC2/' + settings.version
+ end
+
+ get '/', :provides => :xml do
+ ec2_action = QueryParser.parse(params, request_id)
+ ec2_action.perform!(credentials, driver)
+ ec2_action.to_xml
+ end
+
+ end
+end
--
1.7.10.1
[PATCH core 3/3] Core: Require core_ext in config.ru
Posted by mf...@redhat.com.
From: Michal Fojtik <mf...@redhat.com>
Signed-off-by: Michal fojtik <mf...@redhat.com>
---
server/config.ru | 3 +--
server/lib/cimi/helpers.rb | 5 -----
server/lib/deltacloud/core_ext.rb | 28 ++++++++++++++++++++++++++++
server/lib/deltacloud/helpers.rb | 5 -----
server/lib/ec2/helpers.rb | 9 ++-------
5 files changed, 31 insertions(+), 19 deletions(-)
create mode 100644 server/lib/deltacloud/core_ext.rb
diff --git a/server/config.ru b/server/config.ru
index 5deff47..2b5697d 100644
--- a/server/config.ru
+++ b/server/config.ru
@@ -14,7 +14,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-# The default URL prefix (where to mount Deltacloud API)
+load './lib/deltacloud/core_ext.rb'
# The default driver is 'mock'
ENV['API_DRIVER'] ||= 'mock'
@@ -22,7 +22,6 @@ ENV['API_DRIVER'] ||= 'mock'
# Set the API frontend use ('cimi' or 'deltacloud', default is 'deltacloud')
ENV['API_FRONTEND'] ||= 'deltacloud'
-
# We need to set different API version and entrypoint location
if ENV['API_FRONTEND'] == 'deltacloud'
API_VERSION = "9.9.9"
diff --git a/server/lib/cimi/helpers.rb b/server/lib/cimi/helpers.rb
index 4535c39..a9a4926 100644
--- a/server/lib/cimi/helpers.rb
+++ b/server/lib/cimi/helpers.rb
@@ -25,11 +25,6 @@ require_relative '../deltacloud/helpers/assets_helper'
require_relative '../deltacloud/helpers/deltacloud_helper'
require_relative '../deltacloud/helpers/rabbit_helper'
require_relative '../deltacloud/helpers/rabbit_helper'
-require_relative '../deltacloud/core_ext/string'
-require_relative '../deltacloud/core_ext/array'
-require_relative '../deltacloud/core_ext/hash'
-require_relative '../deltacloud/core_ext/integer'
-require_relative '../deltacloud/core_ext/proc'
require_relative './helpers/cimi_helper'
require_relative './models'
diff --git a/server/lib/deltacloud/core_ext.rb b/server/lib/deltacloud/core_ext.rb
new file mode 100644
index 0000000..51a882a
--- /dev/null
+++ b/server/lib/deltacloud/core_ext.rb
@@ -0,0 +1,28 @@
+# 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.
+
+unless Kernel.respond_to?(:require_relative)
+ module Kernel
+ def require_relative(path)
+ require File.join(File.dirname(caller[0]), path.to_str)
+ end
+ end
+end
+
+require_relative './core_ext/string'
+require_relative './core_ext/array'
+require_relative './core_ext/hash'
+require_relative './core_ext/integer'
+require_relative './core_ext/proc'
diff --git a/server/lib/deltacloud/helpers.rb b/server/lib/deltacloud/helpers.rb
index 8e265fc..bc2ea98 100644
--- a/server/lib/deltacloud/helpers.rb
+++ b/server/lib/deltacloud/helpers.rb
@@ -19,11 +19,6 @@ require_relative 'helpers/url_helper'
require_relative 'helpers/deltacloud_helper'
require_relative 'helpers/rabbit_helper'
require_relative 'helpers/blob_stream_helper'
-require_relative 'core_ext/string'
-require_relative 'core_ext/array'
-require_relative 'core_ext/hash'
-require_relative 'core_ext/integer'
-require_relative 'core_ext/proc'
module Deltacloud::Collections
class Base < Sinatra::Base
diff --git a/server/lib/ec2/helpers.rb b/server/lib/ec2/helpers.rb
index 32380fa..d73ea47 100644
--- a/server/lib/ec2/helpers.rb
+++ b/server/lib/ec2/helpers.rb
@@ -18,12 +18,7 @@ module Deltacloud
end
require_relative './helpers/errors'
-require_relative './helpers/convertor'
-
+require_relative './helpers/converter'
require_relative '../deltacloud/helpers/driver_helper'
require_relative '../deltacloud/helpers/auth_helper'
-require_relative '../deltacloud/core_ext/string'
-require_relative '../deltacloud/core_ext/array'
-require_relative '../deltacloud/core_ext/hash'
-require_relative '../deltacloud/core_ext/integer'
-require_relative '../deltacloud/core_ext/proc'
+
--
1.7.10.1
[PATCH core 2/3] Core: Fix incompatibility between 1.9 and 1.8 ruby in listing methods
Posted by mf...@redhat.com.
From: Michal Fojtik <mf...@redhat.com>
Signed-off-by: Michal fojtik <mf...@redhat.com>
---
server/lib/deltacloud/drivers/base_driver.rb | 14 ++++++--------
1 file changed, 6 insertions(+), 8 deletions(-)
diff --git a/server/lib/deltacloud/drivers/base_driver.rb b/server/lib/deltacloud/drivers/base_driver.rb
index ab8fb1a..a100828 100644
--- a/server/lib/deltacloud/drivers/base_driver.rb
+++ b/server/lib/deltacloud/drivers/base_driver.rb
@@ -104,16 +104,13 @@ module Deltacloud
hwp = nil
if name
unless hwp = hardware_profiles(credentials, :id => name).first
- raise BackendError.new(400, "bad-hardware-profile-name",
- "Hardware profile '#{name}' does not exist", nil)
+ raise BackendError.new(StandardError.new, "Hardware profile '#{name}' does not exist")
end
else
- unless image = image(credentials, :id=>image_id)
- raise BackendError.new(400, "bad-image-id",
- "Image with ID '#{image_id}' does not exist", nil)
+ unless image = image(credentials, :id => image_id)
+ raise BackendError.new(StandardError.new, "Image with ID '#{image_id}' does not exist")
end
- hwp = hardware_profiles(credentials,
- :architecture=>image.architecture).first
+ hwp = hardware_profiles(credentials, :architecture=>image.architecture).first
end
return hwp
end
@@ -144,7 +141,8 @@ module Deltacloud
end
def has_capability?(method)
- (self.class.instance_methods - self.class.superclass.instance_methods).include? method.to_s
+ method = RUBY_VERSION =~ /^1\.9/ ? method : method.to_s
+ (self.class.instance_methods - self.class.superclass.instance_methods).include? method
end
## Capabilities
--
1.7.10.1