diff --git a/bin/fog b/bin/fog index 19e59f67e..f50a17042 100755 --- a/bin/fog +++ b/bin/fog @@ -17,7 +17,7 @@ module AWS credential = (ARGV.first && :"#{ARGV.first}") || :default if Fog.credentials[:aws_access_key_id] && Fog.credentials[:aws_secret_access_key] - def ready? + def initialized? true end @@ -74,7 +74,7 @@ module AWS else - def ready? + def initialized? false end @@ -86,7 +86,7 @@ module Rackspace class << self if Fog.credentials[:rackspace_api_key] && Fog.credentials[:rackspace_username] - def ready? + def initialized? true end @@ -119,7 +119,7 @@ module Rackspace else - def ready? + def initialized? false end @@ -131,7 +131,7 @@ module Slicehost class << self if Fog.credentials[:slicehost_password] - def ready? + def initialized? true end @@ -162,10 +162,35 @@ module Slicehost else - def ready? + def initialized? + false + end + + end + end +end + +module Terremark + class << self + if Fog.credentials[:terremark_password] && Fog.credentials[:terremark_username] + + def initialized? true end + def [](service) + @@connections ||= Hash.new do |hash, key| + credentials = Fog.credentials.reject do |k,v| + ![:terremark_username, :terremark_password].include?(k) + end + hash[key] = case key + when :vcloud + Fog::Terremark.new(credentials) + end + end + @@connections[service] + end + end end end @@ -176,7 +201,7 @@ module Fog def services services = [] [::AWS, ::Rackspace, ::Slicehost].each do |service| - if service.ready? + if service.initialized? services << service end end diff --git a/lib/fog.rb b/lib/fog.rb index 1d9424213..c9ce3ae68 100644 --- a/lib/fog.rb +++ b/lib/fog.rb @@ -38,6 +38,7 @@ module Fog load "fog/aws.rb" load "fog/rackspace.rb" load "fog/slicehost.rb" + load "fog/terremark.rb" end def self.credential=(new_credential) @@ -69,6 +70,8 @@ module Fog :rackspace_api_key: INTENTIONALLY_LEFT_BLANK :rackspace_username: INTENTIONALLY_LEFT_BLANK :slicehost_password: INTENTIONALLY_LEFT_BLANK + :terremark_username: INTENTIONALLY_LEFT_BLANK + :terremark_password: INTENTIONALLY_LEFT_BLANK YML print(yml) diff --git a/lib/fog/terremark.rb b/lib/fog/terremark.rb new file mode 100644 index 000000000..0d20a896d --- /dev/null +++ b/lib/fog/terremark.rb @@ -0,0 +1,61 @@ +module Fog + class Terremark + + def self.reload + load 'fog/terremark/parsers/get_catalog.rb' + load 'fog/terremark/parsers/get_organization.rb' + load 'fog/terremark/parsers/get_organizations.rb' + load 'fog/terremark/parsers/get_vdc.rb' + + load 'fog/terremark/requests/get_catalog.rb' + load 'fog/terremark/requests/get_organization.rb' + load 'fog/terremark/requests/get_organizations.rb' + load 'fog/terremark/requests/get_vdc.rb' + end + + def initialize(options={}) + unless @terremark_password = options[:terremark_password] + raise ArgumentError.new('terremark_password is required to access terremark') + end + unless @terremark_username = options[:terremark_username] + raise ArgumentError.new('terremark_username is required to access terremark') + end + @host = options[:host] || "services.vcloudexpress.terremark.com" + @path = options[:path] || "/api/v0.8" + @port = options[:port] || 443 + @scheme = options[:scheme] || 'https' + + @cookie = get_organizations.headers['Set-Cookie'] + end + + private + + def request(params) + @connection = Fog::Connection.new("#{@scheme}://#{@host}:#{@port}") + headers = {} + if @cookie + headers.merge!('Cookie' => @cookie) + end + response = @connection.request({ + :body => params[:body], + :expects => params[:expects], + :headers => headers.merge!(params[:headers] || {}), + :host => @host, + :method => params[:method], + :parser => params[:parser], + :path => "#{@path}/#{params[:path]}" + }) + end + + if Fog.mocking? + + srand(Time.now.to_i) + + class Mock + end + + end + + end +end +Fog::Terremark.reload diff --git a/lib/fog/terremark/parsers/get_catalog.rb b/lib/fog/terremark/parsers/get_catalog.rb new file mode 100644 index 000000000..4a36e4daa --- /dev/null +++ b/lib/fog/terremark/parsers/get_catalog.rb @@ -0,0 +1,43 @@ +module Fog + module Parsers + module Terremark + + class GetCatalog < Fog::Parsers::Base + + def reset + @response = { 'CatalogItems' => [] } + end + + def start_element(name, attributes) + @value = '' + case name + when 'CatalogItem' + catalog_item = {} + until attributes.empty? + catalog_item[attributes.shift] = attributes.shift + end + @response['CatalogItems'] << catalog_item + when 'Catalog' + catalog = {} + until attributes.empty? + if attributes.first.is_a?(Array) + catalog[attributes.first.first] = attributes.shift.last + else + catalog[attributes.shift] = attributes.shift + end + end + @response['name'] = catalog['name'] + end + end + + def end_element(name) + if name == 'Description' + @response[name] = @value + end + end + + end + + end + end +end diff --git a/lib/fog/terremark/parsers/get_organization.rb b/lib/fog/terremark/parsers/get_organization.rb new file mode 100644 index 000000000..b4fe6b6d0 --- /dev/null +++ b/lib/fog/terremark/parsers/get_organization.rb @@ -0,0 +1,44 @@ +module Fog + module Parsers + module Terremark + + class GetOrganization < Fog::Parsers::Base + + def reset + @response = { 'links' => [] } + end + + def start_element(name, attributes) + @value = '' + case name + when 'Link' + link = {} + until attributes.empty? + link[attributes.shift] = attributes.shift + end + @response['links'] << link + when 'Org' + org = {} + until attributes.empty? + if attributes.first.is_a?(Array) + org[attributes.first.first] = attributes.shift.last + else + org[attributes.shift] = attributes.shift + end + end + @response['href'] = org['href'] + @response['name'] = org['name'] + end + end + + def end_element(name) + if name == 'Description' + @response[name] = @value + end + end + + end + + end + end +end diff --git a/lib/fog/terremark/parsers/get_organizations.rb b/lib/fog/terremark/parsers/get_organizations.rb new file mode 100644 index 000000000..9e0463f9e --- /dev/null +++ b/lib/fog/terremark/parsers/get_organizations.rb @@ -0,0 +1,26 @@ +module Fog + module Parsers + module Terremark + + class GetOrganizations < Fog::Parsers::Base + + def reset + @response = { 'OrgList' => [] } + end + + def start_element(name, attributes) + @value = '' + if name == 'Org' + organization = {} + until attributes.empty? + organization[attributes.shift] = attributes.shift + end + @response['OrgList'] << organization + end + end + + end + + end + end +end diff --git a/lib/fog/terremark/parsers/get_vdc.rb b/lib/fog/terremark/parsers/get_vdc.rb new file mode 100644 index 000000000..b78f02972 --- /dev/null +++ b/lib/fog/terremark/parsers/get_vdc.rb @@ -0,0 +1,105 @@ +module Fog + module Parsers + module Terremark + + class GetVdc < Fog::Parsers::Base + + def reset + @in_storage_capacity = false + @in_cpu = false + @in_memory = false + @in_instantiated_vms_quota = false + @in_deployed_vms_quota = false + @response = { + 'links' => [], + 'AvailableNetworks' => [], + 'ComputeCapacity' => { + 'Cpu' => {}, + 'DeployedVmsQuota' => {}, + 'InstantiatedVmsQuota' => {}, + 'Memory' => {} + }, + 'StorageCapacity' => {}, + 'ResourceEntities' => {} + } + end + + def start_element(name, attributes) + @value = '' + case name + when 'Cpu' + @in_cpu = true + when 'DeployedVmsQuota' + @in_deployed_vms_quota = true + when 'InstantiatedVmsQuota' + @in_instantiated_vms_quota = true + when 'Link' + link = {} + until attributes.empty? + link[attributes.shift] = attributes.shift + end + @response['links'] << link + when 'Memory' + @in_memory = true + when 'Network' + network = {} + until attributes.empty? + network[attributes.shift] = attributes.shift + end + @response['AvailableNetworks'] << network + when 'ResourceEntity' + resource_entity = {} + until attributes.empty? + resource_entity[attributes.shift] = attributes.shift + end + @response['ResourceEntity'] << resource_entity + when 'StorageCapacity' + @in_storage_capacity = true + when 'Vdc' + vdc = {} + until attributes.empty? + if attributes.first.is_a?(Array) + vdc[attributes.first.first] = attributes.shift.last + else + vdc[attributes.shift] = attributes.shift + end + end + @response['href'] = vdc['href'] + @response['name'] = vdc['name'] + end + end + + def end_element(name) + case name + when 'Allocated', 'Limit', 'Units', 'Used' + if @in_cpu + @response['Compute Capacity']['Cpu'][name] = @value + elsif @in_deployed_vms_quota + @response['Compute Capacity']['DeployedVmsQuota'][name] = @value + elsif @in_instantiated_vms_quota + @response['Compute Capacity']['InstantiatedVmsQuota'][name] = @value + elsif @in_memory + @response['Compute Capacity']['Memory'][name] = @value + elsif @in_storage_capacity + @response['StorageCapacity'][name] = @value + end + when 'Cpu' + @in_cpu = false + when 'DeployedVmsQuota' + @in_deployed_vms_quota = false + when 'InstantiatedVmsQuota' + @in_instantiated_vms_quota = false + when 'Memory' + @in_memory = false + when 'StorageCapacity' + @in_storage_capacity = false + when 'Type' + @response[name] = @value + end + end + + end + + end + end +end diff --git a/lib/fog/terremark/requests/get_catalog.rb b/lib/fog/terremark/requests/get_catalog.rb new file mode 100644 index 000000000..0c148a474 --- /dev/null +++ b/lib/fog/terremark/requests/get_catalog.rb @@ -0,0 +1,44 @@ +unless Fog.mocking? + + module Fog + class Terremark + + # Get details of a catalog + # + # ==== Parameters + # * vdc_id<~Integer> - Id of vdc to view catalog for + # + # ==== Returns + # * response<~Excon::Response>: + # * body<~Hash>: + # * 'CatalogItems'<~Array> + # * 'href'<~String> - linke to item + # * 'name'<~String> - name of item + # * 'type'<~String> - type of item + # * 'description'<~String> - Description of catalog + # * 'name'<~String> - Name of catalog + def get_catalog(vdc_id) + request( + :expects => 200, + :method => 'GET', + :parser => Fog::Parsers::Terremark::GetCatalog.new, + :path => "vdc/#{vdc_id}/catalog" + ) + end + + end + end + +else + + module Fog + class Terremark + + def get_catalog(vdc_id) + raise MockNotImplemented.new("Contributions welcome!") + end + + end + end + +end diff --git a/lib/fog/terremark/requests/get_organization.rb b/lib/fog/terremark/requests/get_organization.rb new file mode 100644 index 000000000..8e0fd2ec5 --- /dev/null +++ b/lib/fog/terremark/requests/get_organization.rb @@ -0,0 +1,46 @@ +unless Fog.mocking? + + module Fog + class Terremark + + # Get details of an organization + # + # ==== Parameters + # * organization_id<~Integer> - Id of organization to lookup + # + # ==== Returns + # * response<~Excon::Response>: + # * body<~Hash>: + # * 'description'<~String> - Description of organization + # * 'links'<~Array> - An array of links to entities in the organization + # * 'href'<~String> - location of link + # * 'name'<~String> - name of link + # * 'rel'<~String> - action to perform + # * 'type'<~String> - type of link + # * 'name'<~String> - Name of organization + def get_organization(organization_id) + response = request( + :expects => 200, + :method => 'GET', + :parser => Fog::Parsers::Terremark::GetOrganization.new, + :path => "org/#{organization_id}" + ) + response + end + + end + end + +else + + module Fog + class Terremark + + def get_organization(organization_id) + raise MockNotImplemented.new("Contributions welcome!") + end + + end + end + +end diff --git a/lib/fog/terremark/requests/get_organizations.rb b/lib/fog/terremark/requests/get_organizations.rb new file mode 100644 index 000000000..7d0f9861e --- /dev/null +++ b/lib/fog/terremark/requests/get_organizations.rb @@ -0,0 +1,42 @@ +unless Fog.mocking? + + module Fog + class Terremark + + # Get list of organizations + # + # ==== Returns + # * response<~Excon::Response>: + # * body<~Array>: + # * 'description'<~String> - Description of organization + # * 'links'<~Array> - An array of links to entities in the organization + # * 'name'<~String> - Name of organization + def get_organizations + request({ + :body => '', + :expects => 200, + :headers => { + 'Authorization' => "Basic #{Base64.encode64("#{@terremark_username}:#{@terremark_password}").chomp!}" + }, + :method => 'POST', + :parser => Fog::Parsers::Terremark::GetOrganizations.new, + :path => 'login' + }) + end + + end + end + +else + + module Fog + class Terremark + + def get_organizations + raise MockNotImplemented.new("Contributions welcome!") + end + + end + end + +end diff --git a/lib/fog/terremark/requests/get_vdc.rb b/lib/fog/terremark/requests/get_vdc.rb new file mode 100644 index 000000000..d39cbb4c6 --- /dev/null +++ b/lib/fog/terremark/requests/get_vdc.rb @@ -0,0 +1,47 @@ +unless Fog.mocking? + + module Fog + class Terremark + + # Get details of a vdc + # + # ==== Parameters + # * vdc_id<~Integer> - Id of vdc to lookup + # + # ==== Returns + # * response<~Excon::Response>: + # * body<~Hash>: + + # FIXME + + # * 'CatalogItems'<~Array> + # * 'href'<~String> - linke to item + # * 'name'<~String> - name of item + # * 'type'<~String> - type of item + # * 'description'<~String> - Description of catalog + # * 'name'<~String> - Name of catalog + def get_vdc(vdc_id) + request( + :expects => 200, + :method => 'GET', + :parser => Fog::Parsers::Terremark::GetVdc.new, + :path => "vdc/#{vdc_id}" + ) + end + + end + end + +else + + module Fog + class Terremark + + def get_vdc(vdc_id) + raise MockNotImplemented.new("Contributions welcome!") + end + + end + end + +end