1
0
Fork 0
mirror of https://github.com/fog/fog.git synced 2022-11-09 13:51:43 -05:00

[bluebox] tweak into a provider/service for consistency

This commit is contained in:
geemus 2010-09-07 16:26:01 -07:00
parent ce2a9beaf4
commit 8ee2f6a484
33 changed files with 640 additions and 598 deletions

View file

@ -1,87 +1,10 @@
module Fog
class Bluebox < Fog::Service
module Bluebox
requires :bluebox_api_key, :bluebox_customer_id
extend Fog::Provider
model_path 'fog/bluebox/models'
model :flavor
collection :flavors
model :image
collection :images
model :server
collection :servers
service_path 'fog/bluebox'
service :blocks
request_path 'fog/bluebox/requests'
request :create_block
request :destroy_block
request :get_block
request :get_blocks
request :get_product
request :get_products
request :get_template
request :get_templates
request :reboot_block
class Mock
include Collections
def self.data
@data ||= Hash.new do |hash, key|
hash[key] = {}
end
end
def self.reset_data(keys=data.keys)
for key in [*keys]
data.delete(key)
end
end
def initialize(options={})
@bluebox_api_key = options[:bluebox_api_key]
@data = self.class.data[@bluebox_api_key]
end
end
class Real
include Collections
def initialize(options={})
@bluebox_api_key = options[:bluebox_api_key]
@bluebox_customer_id = options[:bluebox_customer_id]
@host = options[:bluebox_host] || "boxpanel.blueboxgrp.com"
@port = options[:bluebox_port] || 443
@scheme = options[:bluebox_scheme] || 'https'
@connection = Fog::Connection.new("#{@scheme}://#{@host}:#{@port}", options[:persistent])
end
def reload
@connection.reset
end
def request(params)
params[:headers] ||= {}
params[:headers].merge!({
'Authorization' => "Basic #{Base64.encode64([@bluebox_customer_id, @bluebox_api_key].join(':')).delete("\r\n")}"
})
begin
response = @connection.request(params.merge!({:host => @host}))
rescue Excon::Errors::Error => error
raise case error
when Excon::Errors::NotFound
Fog::Bluebox::NotFound.slurp(error)
else
error
end
end
unless response.body.empty?
response.body = JSON.parse(response.body)
end
response
end
end
end
end

View file

@ -11,7 +11,7 @@ module Bluebox
@@connections ||= Hash.new do |hash, key|
hash[key] = case key
when :blocks
Fog::Bluebox.new
Fog::Bluebox::Blocks.new
end
end
@@connections[service]
@ -21,7 +21,7 @@ module Bluebox
[:blocks]
end
for collection in Fog::Bluebox.collections
for collection in Fog::Bluebox::Blocks.collections
module_eval <<-EOS, __FILE__, __LINE__
def #{collection}
self[:blocks].#{collection}

89
lib/fog/bluebox/blocks.rb Normal file
View file

@ -0,0 +1,89 @@
module Fog
module Bluebox
class Blocks < Fog::Service
requires :bluebox_api_key, :bluebox_customer_id
model_path 'fog/bluebox/models/blocks'
model :flavor
collection :flavors
model :image
collection :images
model :server
collection :servers
request_path 'fog/bluebox/requests/blocks'
request :create_block
request :destroy_block
request :get_block
request :get_blocks
request :get_product
request :get_products
request :get_template
request :get_templates
request :reboot_block
class Mock
include Collections
def self.data
@data ||= Hash.new do |hash, key|
hash[key] = {}
end
end
def self.reset_data(keys=data.keys)
for key in [*keys]
data.delete(key)
end
end
def initialize(options={})
@bluebox_api_key = options[:bluebox_api_key]
@data = self.class.data[@bluebox_api_key]
end
end
class Real
include Collections
def initialize(options={})
@bluebox_api_key = options[:bluebox_api_key]
@bluebox_customer_id = options[:bluebox_customer_id]
@host = options[:bluebox_host] || "boxpanel.blueboxgrp.com"
@port = options[:bluebox_port] || 443
@scheme = options[:bluebox_scheme] || 'https'
@connection = Fog::Connection.new("#{@scheme}://#{@host}:#{@port}", options[:persistent])
end
def reload
@connection.reset
end
def request(params)
params[:headers] ||= {}
params[:headers].merge!({
'Authorization' => "Basic #{Base64.encode64([@bluebox_customer_id, @bluebox_api_key].join(':')).delete("\r\n")}"
})
begin
response = @connection.request(params.merge!({:host => @host}))
rescue Excon::Errors::Error => error
raise case error
when Excon::Errors::NotFound
Fog::Bluebox::NotFound.slurp(error)
else
error
end
end
unless response.body.empty?
response.body = JSON.parse(response.body)
end
response
end
end
end
end
end

View file

@ -0,0 +1,45 @@
require 'fog/model'
module Fog
module Bluebox
class Blocks
class Flavor < Fog::Model
identity :id
attribute :name
attribute :cost
attribute :description
def bits
# 64
raise StandardError.new("Figure me out!?!")
end
def cores
# # 2 quad-cores >= 2Ghz = 8 cores
# 8 * case ram
# when 256
# 1/64.0
# when 512
# 1/32.0
# when 1024
# 1/16.0
# when 2048
# 1/8.0
# when 4096
# 1/4.0
# when 8192
# 1/2.0
# when 15872
# 1
# end
raise StandardError.new("Figure me out!?!")
end
end
end
end
end

View file

@ -0,0 +1,28 @@
require 'fog/collection'
require 'fog/bluebox/models/flavor'
module Fog
module Bluebox
class Blocks
class Flavors < Fog::Collection
model Fog::Bluebox::Flavor
def all
data = connection.get_products.body
load(data)
end
def get(product_id)
response = connection.get_product(product_id)
new(response.body)
rescue Fog::Bluebox::NotFound
nil
end
end
end
end
end

View file

@ -0,0 +1,19 @@
require 'fog/model'
module Fog
module Bluebox
class Blocks
class Image < Fog::Model
identity :id
attribute :description
attribute :public
attribute :created_at, :aliases => 'created'
end
end
end
end

View file

@ -0,0 +1,28 @@
require 'fog/collection'
require 'fog/bluebox/models/image'
module Fog
module Bluebox
class Blocks
class Images < Fog::Collection
model Fog::Bluebox::Image
def all
data = connection.get_templates.body
load(data)
end
def get(template_id)
response = connection.get_template(template_id)
new(response.body)
rescue Fog::Bluebox::NotFound
nil
end
end
end
end
end

View file

@ -0,0 +1,81 @@
require 'fog/model'
module Fog
module Bluebox
class Blocks
class BlockInstantiationError < StandardError; end
class Server < Fog::Model
identity :id
attribute :memory
attribute :storage
attribute :hostname
attribute :cpu
attribute :ips
attribute :status
attribute :flavor_id
# attribute :image_id
attr_accessor :image_id
attribute :template
# Not reported by the API, but used at create time
attr_accessor :password, :ssh_key, :user
def destroy
requires :id
connection.destroy_block(@id)
true
end
def flavor
requires :flavor_id
connection.flavors.get(@flavor_id)
end
def image
requires :image_id
connection.images.get(@image_id)
end
def ready?
@status == 'running'
end
def reboot(type = 'SOFT')
requires :id
connection.reboot_block(@id, type)
true
end
def save
requires :flavor_id, :image_id
options = if !@password && !@ssh_key
raise(ArgumentError, "password or ssh_key is required for this operation")
elsif @ssh_key
{'ssh_key' => @ssh_key}
elsif @password
{'password' => @password}
end
if @user
options['user'] = @user
end
data = connection.create_block(@flavor_id, @image_id, options)
merge_attributes(data.body)
true
end
private
def product=(new_product)
@flavor_id = new_product['id']
end
end
end
end
end

View file

@ -0,0 +1,29 @@
require 'fog/collection'
require 'fog/bluebox/models/server'
module Fog
module Bluebox
class Blocks
class Servers < Fog::Collection
model Fog::Bluebox::Server
def all
data = connection.get_blocks.body
load(data)
end
def get(server_id)
if server_id && server = connection.get_block(server_id).body
new(server)
end
rescue Fog::Bluebox::NotFound
nil
end
end
end
end
end

View file

@ -1,43 +0,0 @@
require 'fog/model'
module Fog
class Bluebox
class Flavor < Fog::Model
identity :id
attribute :name
attribute :cost
attribute :description
def bits
# 64
raise StandardError.new("Figure me out!?!")
end
def cores
# # 2 quad-cores >= 2Ghz = 8 cores
# 8 * case ram
# when 256
# 1/64.0
# when 512
# 1/32.0
# when 1024
# 1/16.0
# when 2048
# 1/8.0
# when 4096
# 1/4.0
# when 8192
# 1/2.0
# when 15872
# 1
# end
raise StandardError.new("Figure me out!?!")
end
end
end
end

View file

@ -1,26 +0,0 @@
require 'fog/collection'
require 'fog/bluebox/models/flavor'
module Fog
class Bluebox
class Flavors < Fog::Collection
model Fog::Bluebox::Flavor
def all
data = connection.get_products.body
load(data)
end
def get(product_id)
response = connection.get_product(product_id)
new(response.body)
rescue Fog::Bluebox::NotFound
nil
end
end
end
end

View file

@ -1,17 +0,0 @@
require 'fog/model'
module Fog
class Bluebox
class Image < Fog::Model
identity :id
attribute :description
attribute :public
attribute :created_at, :aliases => 'created'
end
end
end

View file

@ -1,26 +0,0 @@
require 'fog/collection'
require 'fog/bluebox/models/image'
module Fog
class Bluebox
class Images < Fog::Collection
model Fog::Bluebox::Image
def all
data = connection.get_templates.body
load(data)
end
def get(template_id)
response = connection.get_template(template_id)
new(response.body)
rescue Fog::Bluebox::NotFound
nil
end
end
end
end

View file

@ -1,79 +0,0 @@
require 'fog/model'
module Fog
class Bluebox
class BlockInstantiationError < StandardError; end
class Server < Fog::Model
identity :id
attribute :memory
attribute :storage
attribute :hostname
attribute :cpu
attribute :ips
attribute :status
attribute :flavor_id
# attribute :image_id
attr_accessor :image_id
attribute :template
# Not reported by the API, but used at create time
attr_accessor :password, :ssh_key, :user
def destroy
requires :id
connection.destroy_block(@id)
true
end
def flavor
requires :flavor_id
connection.flavors.get(@flavor_id)
end
def image
requires :image_id
connection.images.get(@image_id)
end
def ready?
@status == 'running'
end
def reboot(type = 'SOFT')
requires :id
connection.reboot_block(@id, type)
true
end
def save
requires :flavor_id, :image_id
options = if !@password && !@ssh_key
raise(ArgumentError, "password or ssh_key is required for this operation")
elsif @ssh_key
{'ssh_key' => @ssh_key}
elsif @password
{'password' => @password}
end
if @user
options['user'] = @user
end
data = connection.create_block(@flavor_id, @image_id, options)
merge_attributes(data.body)
true
end
private
def product=(new_product)
@flavor_id = new_product['id']
end
end
end
end

View file

@ -1,27 +0,0 @@
require 'fog/collection'
require 'fog/bluebox/models/server'
module Fog
class Bluebox
class Servers < Fog::Collection
model Fog::Bluebox::Server
def all
data = connection.get_blocks.body
load(data)
end
def get(server_id)
if server_id && server = connection.get_block(server_id).body
new(server)
end
rescue Fog::Bluebox::NotFound
nil
end
end
end
end

View file

@ -0,0 +1,41 @@
module Fog
module Bluebox
class Blocks
class Real
# Create a new block
#
# ==== Parameters
# * product_id<~Integer> - Id of product to create block with
# * template_id<~Integer> - Id of template to create block with
# * options<~Hash>:
# * password<~String> - Password for block
# or
# * ssh_key<~String> - ssh public key
# * username<~String> - optional, defaults to deploy
#
# ==== Returns
# * response<~Excon::Response>:
# * body<~Hash>:
# TODO
def create_block(product_id, template_id, options = {})
request(
:expects => 200,
:method => 'POST',
:path => '/api/blocks.json',
:query => {'product' => product_id, 'template' => template_id}.merge!(options)
)
end
end
class Mock
def create_block(product_id, template_id, name, password)
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -0,0 +1,34 @@
module Fog
module Bluebox
class Blocks
class Real
# Destroy a block
#
# ==== Parameters
# * block_id<~Integer> - Id of block to destroy
#
# ==== Returns
# * response<~Excon::Response>:
# * body<~Hash>:
# TODO
def destroy_block(block_id)
request(
:expects => 200,
:method => 'DELETE',
:path => "api/blocks/#{block_id}.json"
)
end
end
class Mock
def destroy_block(block_id)
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -0,0 +1,34 @@
module Fog
module Bluebox
class Blocks
class Real
# Get details of a block.
#
# ==== Parameters
# * block_id<~Integer> - Id of block to lookup
#
# ==== Returns
# * response<~Excon::Response>:
# * body<~Hash>:
# TODO
def get_block(block_id)
request(
:expects => 200,
:method => 'GET',
:path => "api/blocks/#{block_id}.json"
)
end
end
class Mock
def get_slice(id)
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -0,0 +1,36 @@
module Fog
module Bluebox
class Blocks
class Real
# Get list of blocks
#
# ==== Returns
# * response<~Excon::Response>:
# * body<~Array>:
# * 'ips'<~Array> - Ip addresses for the block
# * 'id'<~String> - Id of the block
# * 'storage'<~Integer> - Disk space quota for the block
# * 'memory'<~Integer> - RAM quota for the block
# * 'cpu'<~Float> - The fractional CPU quota for this block
# * 'hostname'<~String> - The hostname for the block
def get_blocks
request(
:expects => 200,
:method => 'GET',
:path => 'api/blocks.json'
)
end
end
class Mock
def get_slices
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -0,0 +1,34 @@
module Fog
module Bluebox
class Blocks
class Real
# Get details of a product
#
# ==== Parameters
# * product_id<~Integer> - Id of flavor to lookup
#
# ==== Returns
# * response<~Excon::Response>:
# * body<~Array>:
# TODO
def get_product(product_id)
request(
:expects => 200,
:method => 'GET',
:path => "api/block_products/#{product_id}.json"
)
end
end
class Mock
def get_product(product_id)
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -0,0 +1,33 @@
module Fog
module Bluebox
class Blocks
class Real
# Get list of products
#
# ==== Returns
# * response<~Excon::Response>:
# * body<~Array>:
# * 'id'<~String> - UUID of the product
# * 'description'<~String> - Description of the product
# * 'cost'<~Decimal> - Hourly cost of the product
def get_products
request(
:expects => 200,
:method => 'GET',
:path => 'api/block_products.json'
)
end
end
class Mock
def get_products
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -0,0 +1,34 @@
module Fog
module Bluebox
class Blocks
class Real
# Get details of a template
#
# ==== Parameters
# * template_id<~Integer> - Id of template to lookup
#
# ==== Returns
# * response<~Excon::Response>:
# * body<~Array>:
# TODO
def get_template(template_id)
request(
:expects => 200,
:method => 'GET',
:path => "api/block_templates/#{template_id}.json"
)
end
end
class Mock
def get_template(template_id)
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -0,0 +1,34 @@
module Fog
module Bluebox
class Blocks
class Real
# Get list of OS templates
#
# ==== Returns
# * response<~Excon::Response>:
# * body<~Array>:
# * 'id'<~String> - UUID of the image
# * 'description'<~String> - Description of the image
# * 'public'<~Boolean> - Public / Private image
# * 'created'<~Datetime> - Timestamp of when the image was created
def get_templates
request(
:expects => 200,
:method => 'GET',
:path => 'api/block_templates.json'
)
end
end
class Mock
def get_templates
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -0,0 +1,35 @@
module Fog
module Bluebox
class Blocks
class Real
# Reboot block
#
# ==== Parameters
# * block_id<~String> - Id of block to reboot
# * type<~String> - Type of reboot, must be in ['HARD', 'SOFT']
#
# ==== Returns
# * response<~Excon::Response>:
# * body<~Hash>:
# TODO
def reboot_block(block_id, type = 'SOFT')
request(
:expects => 200,
:method => 'PUT',
:path => "api/blocks/#{block_id}/#{'soft_' if type == 'SOFT'}reboot.json"
)
end
end
class Mock
def reboot_block(block_id, type = 'SOFT')
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -1,39 +0,0 @@
module Fog
class Bluebox
class Real
# Create a new block
#
# ==== Parameters
# * product_id<~Integer> - Id of product to create block with
# * template_id<~Integer> - Id of template to create block with
# * options<~Hash>:
# * password<~String> - Password for block
# or
# * ssh_key<~String> - ssh public key
# * username<~String> - optional, defaults to deploy
#
# ==== Returns
# * response<~Excon::Response>:
# * body<~Hash>:
# TODO
def create_block(product_id, template_id, options = {})
request(
:expects => 200,
:method => 'POST',
:path => '/api/blocks.json',
:query => {'product' => product_id, 'template' => template_id}.merge!(options)
)
end
end
class Mock
def create_block(product_id, template_id, name, password)
Fog::Mock.not_implemented
end
end
end
end

View file

@ -1,32 +0,0 @@
module Fog
class Bluebox
class Real
# Destroy a block
#
# ==== Parameters
# * block_id<~Integer> - Id of block to destroy
#
# ==== Returns
# * response<~Excon::Response>:
# * body<~Hash>:
# TODO
def destroy_block(block_id)
request(
:expects => 200,
:method => 'DELETE',
:path => "api/blocks/#{block_id}.json"
)
end
end
class Mock
def destroy_block(block_id)
Fog::Mock.not_implemented
end
end
end
end

View file

@ -1,32 +0,0 @@
module Fog
class Bluebox
class Real
# Get details of a block.
#
# ==== Parameters
# * block_id<~Integer> - Id of block to lookup
#
# ==== Returns
# * response<~Excon::Response>:
# * body<~Hash>:
# TODO
def get_block(block_id)
request(
:expects => 200,
:method => 'GET',
:path => "api/blocks/#{block_id}.json"
)
end
end
class Mock
def get_slice(id)
Fog::Mock.not_implemented
end
end
end
end

View file

@ -1,34 +0,0 @@
module Fog
class Bluebox
class Real
# Get list of blocks
#
# ==== Returns
# * response<~Excon::Response>:
# * body<~Array>:
# * 'ips'<~Array> - Ip addresses for the block
# * 'id'<~String> - Id of the block
# * 'storage'<~Integer> - Disk space quota for the block
# * 'memory'<~Integer> - RAM quota for the block
# * 'cpu'<~Float> - The fractional CPU quota for this block
# * 'hostname'<~String> - The hostname for the block
def get_blocks
request(
:expects => 200,
:method => 'GET',
:path => 'api/blocks.json'
)
end
end
class Mock
def get_slices
Fog::Mock.not_implemented
end
end
end
end

View file

@ -1,32 +0,0 @@
module Fog
class Bluebox
class Real
# Get details of a product
#
# ==== Parameters
# * product_id<~Integer> - Id of flavor to lookup
#
# ==== Returns
# * response<~Excon::Response>:
# * body<~Array>:
# TODO
def get_product(product_id)
request(
:expects => 200,
:method => 'GET',
:path => "api/block_products/#{product_id}.json"
)
end
end
class Mock
def get_product(product_id)
Fog::Mock.not_implemented
end
end
end
end

View file

@ -1,31 +0,0 @@
module Fog
class Bluebox
class Real
# Get list of products
#
# ==== Returns
# * response<~Excon::Response>:
# * body<~Array>:
# * 'id'<~String> - UUID of the product
# * 'description'<~String> - Description of the product
# * 'cost'<~Decimal> - Hourly cost of the product
def get_products
request(
:expects => 200,
:method => 'GET',
:path => 'api/block_products.json'
)
end
end
class Mock
def get_products
Fog::Mock.not_implemented
end
end
end
end

View file

@ -1,32 +0,0 @@
module Fog
class Bluebox
class Real
# Get details of a template
#
# ==== Parameters
# * template_id<~Integer> - Id of template to lookup
#
# ==== Returns
# * response<~Excon::Response>:
# * body<~Array>:
# TODO
def get_template(template_id)
request(
:expects => 200,
:method => 'GET',
:path => "api/block_templates/#{template_id}.json"
)
end
end
class Mock
def get_template(template_id)
Fog::Mock.not_implemented
end
end
end
end

View file

@ -1,32 +0,0 @@
module Fog
class Bluebox
class Real
# Get list of OS templates
#
# ==== Returns
# * response<~Excon::Response>:
# * body<~Array>:
# * 'id'<~String> - UUID of the image
# * 'description'<~String> - Description of the image
# * 'public'<~Boolean> - Public / Private image
# * 'created'<~Datetime> - Timestamp of when the image was created
def get_templates
request(
:expects => 200,
:method => 'GET',
:path => 'api/block_templates.json'
)
end
end
class Mock
def get_templates
Fog::Mock.not_implemented
end
end
end
end

View file

@ -1,33 +0,0 @@
module Fog
class Bluebox
class Real
# Reboot block
#
# ==== Parameters
# * block_id<~String> - Id of block to reboot
# * type<~String> - Type of reboot, must be in ['HARD', 'SOFT']
#
# ==== Returns
# * response<~Excon::Response>:
# * body<~Hash>:
# TODO
def reboot_block(block_id, type = 'SOFT')
request(
:expects => 200,
:method => 'PUT',
:path => "api/blocks/#{block_id}/#{'soft_' if type == 'SOFT'}reboot.json"
)
end
end
class Mock
def reboot_block(block_id, type = 'SOFT')
Fog::Mock.not_implemented
end
end
end
end