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

[bbg] flesh out bbg support

Added basic spec framework; changed class names to match the template fog seems to prefer

Servers tests pass; create and delete implemented.

Added an example script

Properly handle a 409 response from the API

Fixed BBG code to work with the new api endpoint changes; tweaks to the (currently nonexistent) reboot api call

Implement the reboot command for blocks
This commit is contained in:
ggoodale 2010-05-24 11:03:52 -07:00 committed by geemus
parent b9ad8ea418
commit 2a9224cfa7
32 changed files with 791 additions and 86 deletions

View file

@ -5,7 +5,7 @@ require 'yaml'
require File.join('fog', 'credentials') require File.join('fog', 'credentials')
require File.join('fog', 'bin') require File.join('fog', 'bin')
Fog.credential = (ARGV.first && :"#{ARGV.first}") || :default Fog.credential = ARGV.first ? :"#{ARGV.first}" : :default
unless Fog.credentials unless Fog.credentials
exit exit
end end
@ -16,6 +16,7 @@ require File.join('fog', 'rackspace', 'bin')
require File.join('fog', 'slicehost', 'bin') require File.join('fog', 'slicehost', 'bin')
require File.join('fog', 'terremark', 'bin') require File.join('fog', 'terremark', 'bin')
require File.join('fog', 'vcloud', 'bin') require File.join('fog', 'vcloud', 'bin')
require File.join('fog', 'bluebox', 'bin')
if ARGV.length > 1 if ARGV.length > 1
print(instance_eval(ARGV[1..-1].join(' ')).to_json) print(instance_eval(ARGV[1..-1].join(' ')).to_json)

View file

@ -0,0 +1,33 @@
#!/usr/bin/env ruby
# For example only - you'd want to use your own AMI id.
unless defined?(GENTOO_AMI)
GENTOO_AMI = 'ami-5ee70037'
end
require 'rubygems'
require 'fog'
@bluebox_api_key = "CHANGEME"
@aws_access_key_id = "CHANGEME"
@aws_secret_access_key = "CHANGEME"
@flavor_id = "94fd37a7-2606-47f7-84d5-9000deda52ae" # Block 1GB Virtual Server
@image_id = "03807e08-a13d-44e4-b011-ebec7ef2c928" # Ubuntu 10.04 x64 LTS
# Grab our current list of servers
@bbg_servers = Fog::Bluebox.new(:bluebox_api_key => @bluebox_api_key).servers
@ec2_servers = Fog::AWS::EC2.new(:aws_access_key_id => @aws_access_key_id, :aws_secret_access_key => @aws_secret_access_key).servers
# Create a new server.
@server = @bbg_servers.new(:flavor_id => @flavor_id, :image_id => @image_id,
:name => "My Server", :password => "MyPassword")
# Save the server, triggering its creation
@server.save
if @server.status == 'error'
# The create failed - create a new server on Amazon instead
@server = @ec2_servers.new(:image_id => GENTOO_AMI)
@server.save
end

View file

@ -209,6 +209,27 @@ Gem::Specification.new do |s|
lib/fog/aws/s3.rb lib/fog/aws/s3.rb
lib/fog/aws/simpledb.rb lib/fog/aws/simpledb.rb
lib/fog/bin.rb lib/fog/bin.rb
lib/fog/bluebox.rb
lib/fog/bluebox/bin.rb
lib/fog/bluebox/models/flavor.rb
lib/fog/bluebox/models/flavors.rb
lib/fog/bluebox/models/image.rb
lib/fog/bluebox/models/images.rb
lib/fog/bluebox/models/server.rb
lib/fog/bluebox/models/servers.rb
lib/fog/bluebox/parsers/create_block.rb
lib/fog/bluebox/parsers/get_block.rb
lib/fog/bluebox/parsers/get_blocks.rb
lib/fog/bluebox/parsers/get_flavor.rb
lib/fog/bluebox/parsers/get_flavors.rb
lib/fog/bluebox/parsers/get_images.rb
lib/fog/bluebox/requests/create_block.rb
lib/fog/bluebox/requests/destroy_block.rb
lib/fog/bluebox/requests/get_block.rb
lib/fog/bluebox/requests/get_blocks.rb
lib/fog/bluebox/requests/get_flavor.rb
lib/fog/bluebox/requests/get_flavors.rb
lib/fog/bluebox/requests/get_images.rb
lib/fog/collection.rb lib/fog/collection.rb
lib/fog/connection.rb lib/fog/connection.rb
lib/fog/credentials.rb lib/fog/credentials.rb
@ -416,6 +437,9 @@ Gem::Specification.new do |s|
spec/aws/requests/simpledb/list_domains_spec.rb spec/aws/requests/simpledb/list_domains_spec.rb
spec/aws/requests/simpledb/put_attributes_spec.rb spec/aws/requests/simpledb/put_attributes_spec.rb
spec/aws/requests/simpledb/select_spec.rb spec/aws/requests/simpledb/select_spec.rb
spec/bluebox/models/flavors_spec.rb
spec/bluebox/models/server_spec.rb
spec/bluebox/models/servers_spec.rb
spec/compact_progress_bar_formatter.rb spec/compact_progress_bar_formatter.rb
spec/lorem.txt spec/lorem.txt
spec/rackspace/models/servers/flavors_spec.rb spec/rackspace/models/servers/flavors_spec.rb

View file

@ -5,7 +5,7 @@ module Fog
def services def services
services = [] services = []
[::AWS, ::Local, ::Rackspace, ::Slicehost, ::Terremark, ::Vcloud].each do |service| [::AWS, ::Local, ::Rackspace, ::Slicehost, ::Terremark, ::Vcloud, ::Bluebox].each do |service|
if service.initialized? if service.initialized?
services << service services << service
end end

View file

@ -1,16 +1,21 @@
module Fog module Fog
module Bluebox module Bluebox
require 'fog/bluebox/models/images'
require 'fog/bluebox/requests/get_images'
require 'fog/bluebox/models/flavors'
require 'fog/bluebox/requests/get_flavors'
require 'fog/bluebox/models/flavor'
require 'fog/bluebox/requests/get_flavor'
require 'fog/bluebox/models/servers'
require 'fog/bluebox/requests/get_blocks'
require 'fog/bluebox/models/server'
require 'fog/bluebox/requests/get_block'
require 'fog/bluebox/requests/create_block'
require 'fog/bluebox/requests/destroy_block'
require 'fog/bluebox/requests/reboot_block'
def self.new(options={}) def self.new(options={})
unless @required
require 'fog/bluebox/models/templates'
require 'fog/bluebox/requests/get_templates'
require 'fog/bluebox/models/products'
require 'fog/bluebox/requests/get_products'
@required = true
end
unless options[:bluebox_api_key] unless options[:bluebox_api_key]
raise ArgumentError.new('bluebox_api_key is required to access Blue Box') raise ArgumentError.new('bluebox_api_key is required to access Blue Box')
end end
@ -50,9 +55,9 @@ module Fog
def initialize(options={}) def initialize(options={})
@bluebox_api_key = options[:bluebox_api_key] @bluebox_api_key = options[:bluebox_api_key]
@host = options[:host] || "boxpanel.blueboxgrp.com" @host = options[:bluebox_host] || "boxpanel.blueboxgrp.com"
@port = options[:port] || 443 @port = options[:bluebox_port] || 443
@scheme = options[:scheme] || 'https' @scheme = options[:bluebox_scheme] || 'https'
end end
def request(params) def request(params)
@ -67,7 +72,7 @@ module Fog
headers['Content-Type'] = 'application/xml' headers['Content-Type'] = 'application/xml'
end end
response = @connection.request({ @connection.request({
:body => params[:body], :body => params[:body],
:expects => params[:expects], :expects => params[:expects],
:headers => headers.merge!(params[:headers] || {}), :headers => headers.merge!(params[:headers] || {}),
@ -76,8 +81,6 @@ module Fog
:parser => params[:parser], :parser => params[:parser],
:path => params[:path] :path => params[:path]
}) })
response
end end
end end

View file

@ -1,5 +1,6 @@
module Bluebox module Bluebox
class << self class << self
if Fog.credentials[:bluebox_api_key] if Fog.credentials[:bluebox_api_key]
def initialized? def initialized?
@ -9,10 +10,10 @@ module Bluebox
def [](service) def [](service)
@@connections ||= Hash.new do |hash, key| @@connections ||= Hash.new do |hash, key|
credentials = Fog.credentials.reject do |k,v| credentials = Fog.credentials.reject do |k,v|
![:bluebox_api_key].include?(k) ![:bluebox_api_key, :bluebox_host, :bluebox_port, :bluebox_scheme].include?(k)
end end
hash[key] = case key hash[key] = case key
when :slices when :blocks
Fog::Bluebox.new(credentials) Fog::Bluebox.new(credentials)
end end
end end
@ -20,15 +21,15 @@ module Bluebox
end end
def flavors def flavors
self[:slices].flavors self[:blocks].flavors
end end
def images def images
self[:slices].images self[:blocks].images
end end
def servers def servers
self[:slices].servers self[:blocks].servers
end end
else else

View file

@ -3,12 +3,13 @@ require 'fog/model'
module Fog module Fog
module Bluebox module Bluebox
class Product < Fog::Model class Flavor < Fog::Model
identity :id identity :id
attribute :name attribute :name
attribute :cost attribute :cost
attribute :description
def bits def bits
# 64 # 64

View file

@ -0,0 +1,41 @@
require 'fog/collection'
require 'fog/bluebox/models/flavor'
module Fog
module Bluebox
class Mock
def flavors
Fog::Bluebox::Flavors.new(:connection => self)
end
end
class Real
def flavors
Fog::Bluebox::Flavors.new(:connection => self)
end
end
class Flavors < Fog::Collection
model Fog::Bluebox::Flavor
def all
data = connection.get_flavors.body['flavors']
load(data)
end
def get(product_id)
response = connection.get_flavor(product_id)
model.new(response.body)
rescue Excon::Errors::NotFound
# Whoops - no image with that id.
nil
rescue Excon::Errors::Forbidden
nil
end
end
end
end

View file

@ -3,7 +3,7 @@ require 'fog/model'
module Fog module Fog
module Bluebox module Bluebox
class Template < Fog::Model class Image < Fog::Model
identity :id identity :id

View file

@ -1,12 +1,12 @@
require 'fog/collection' require 'fog/collection'
require 'fog/bluebox/models/template' require 'fog/bluebox/models/image'
module Fog module Fog
module Bluebox module Bluebox
class Mock class Mock
def images(attributes = {}) def images(attributes = {})
Fog::Bluebox::Templates.new({ Fog::Bluebox::Images.new({
:connection => self :connection => self
}.merge!(attributes)) }.merge!(attributes))
end end
@ -14,7 +14,7 @@ module Fog
class Real class Real
def images(attributes = {}) def images(attributes = {})
Fog::Bluebox::Templates.new({ Fog::Bluebox::Images.new({
:connection => self :connection => self
}.merge!(attributes)) }.merge!(attributes))
end end
@ -22,7 +22,7 @@ module Fog
class Templates < Fog::Collection class Templates < Fog::Collection
model Fog::Bluebox::Template model Fog::Bluebox::Image
def all def all
data = connection.get_templates.body['templates'] data = connection.get_templates.body['templates']

View file

@ -1,37 +0,0 @@
require 'fog/collection'
require 'fog/bluebox/models/product'
module Fog
module Bluebox
class Mock
def products
Fog::Bluebox::Products.new(:connection => self)
end
end
class Real
def products
Fog::Bluebox::Products.new(:connection => self)
end
end
class Products < Fog::Collection
model Fog::Bluebox::Product
def all
data = connection.get_products.body['products']
load(data)
end
def get(product_id)
connection.get_product(product_id)
rescue Excon::Errors::Forbidden
nil
end
end
end
end

View file

@ -0,0 +1,60 @@
require 'fog/model'
module Fog
module 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
# Not reported by the API, but used at create time
attr_accessor :name, :password, :hash, :text, :error
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?
raise Fog::Bluebox::BlockInstantiationError, "Error creating block #{self.id}" if @status == 'error'
@status == 'running'
end
def reboot(type = 'SOFT')
requires :id
connection.reboot_block(@id, type)
true
end
def save
requires :flavor_id, :image_id, :name, :password
data = connection.create_block(@flavor_id, @image_id, @name, @password)
merge_attributes(data.body)
true
end
end
end
end

View file

@ -0,0 +1,44 @@
require 'fog/collection'
require 'fog/bluebox/models/server'
module Fog
module Bluebox
class Mock
def servers
Fog::Bluebox::Servers.new(:connection => self)
end
end
class Real
def servers
Fog::Bluebox::Servers.new(:connection => self)
end
end
class Servers < Fog::Collection
model Fog::Bluebox::Server
def all
data = connection.get_blocks.body['blocks']
load(data)
end
def get(server_id)
if server_id && server = connection.get_block(server_id).body
new(server)
elsif !server_id
nil
end
rescue Excon::Errors::NotFound
# No server found with that id
nil
rescue Excon::Errors::Forbidden
nil
end
end
end
end

View file

@ -0,0 +1,48 @@
module Fog
module Parsers
module Bluebox
class CreateBlock < Fog::Parsers::Base
def reset
@response = {}
end
def end_element(name)
case name
when 'address'
@response['ips'] ||= []
@response['ips'] << @value
when 'memory', 'storage'
@response[name] = @value.to_i
when 'cpu'
@response[name] = @value.to_f
when 'id'
if @scope == 'product'
@response['flavor_id'] = @value
else
@response[name] = @value
end
when 'name', 'hostname', 'status', 'text', 'hash'
@response[name] = @value
when 'template'
@response['image_id'] = @value
when 'product'
@scope = nil
when 'error' # An error occurred
@response['status'] = 'error'
@response[name] = @value
end
end
def start_element(name, attrs=[])
super
case name
when 'product'
@scope = name
end
end
end
end
end
end

View file

@ -0,0 +1,47 @@
module Fog
module Parsers
module Bluebox
class GetBlock < Fog::Parsers::Base
def reset
@response = {}
end
def end_element(name)
case name
when 'address'
@response['ips'] ||= []
@response['ips'] << @value
when 'memory', 'storage'
@response[name] = @value.to_i
when 'cpu'
@response[name] = @value.to_f
when 'hostname', 'status'
@response[name] = @value
when 'id'
if @scope == 'product'
@response['flavor_id'] = @value
else
@response[name] = @value
end
when 'template'
@response['image_id'] = @value
when 'product'
@scope = nil
end
end
def start_element(name, attrs=[])
super
case name
when 'product'
@scope = name
end
end
end
end
end
end

View file

@ -0,0 +1,33 @@
module Fog
module Parsers
module Bluebox
class GetBlocks < Fog::Parsers::Base
def reset
@block = {}
@response = { 'blocks' => [] }
end
def end_element(name)
case name
when 'ip'
@block['ips'] ||= []
@block['ips'] << @value
when 'memory', 'storage'
@block[name] = @value.to_i
when 'cpu'
@block[name] = @value.to_f
when 'hostname', 'id'
@block[name] = @value
when 'record'
@response['blocks'] << @block
@block = {}
end
end
end
end
end
end

View file

@ -0,0 +1,33 @@
# Response formet:
# <hash>
# <cost type="decimal">0.15</cost>
# <id>94fd37a7-2606-47f7-84d5-9000deda52ae</id>
# <description>Block 1GB Virtual Server</description>
# </hash>
module Fog
module Parsers
module Bluebox
class GetFlavor < Fog::Parsers::Base
def reset
@response = {}
end
def end_element(name)
case name
when 'hash'
# Do nothing
when 'cost'
@response[name] = @value.to_f
else
@response[name] = @value
end
end
end
end
end
end

View file

@ -2,24 +2,22 @@ module Fog
module Parsers module Parsers
module Bluebox module Bluebox
class GetProducts < Fog::Parsers::Base class GetFlavors < Fog::Parsers::Base
def reset def reset
@product = {} @product = {}
@response = { 'products' => [] } @response = { 'flavors' => [] }
end end
def end_element(name) def end_element(name)
case name case name
when 'cost'
@product[name] = @value
when 'id'
@product[name] = @value
when 'description'
@product[name] = @value
when 'record' when 'record'
@response['products'] << @product @response['flavors'] << @product
@product = {} @product = {}
when 'cost'
@product[name] = @value.to_f
else
@product[name] = @value
end end
end end

View file

@ -2,11 +2,11 @@ module Fog
module Parsers module Parsers
module Bluebox module Bluebox
class GetTemplates < Fog::Parsers::Base class GetImages < Fog::Parsers::Base
def reset def reset
@template = {} @template = {}
@response = { 'templates' => [] } @response = { 'images' => [] }
end end
def end_element(name) def end_element(name)
@ -18,7 +18,7 @@ module Fog
when 'description' when 'description'
@template[name] = @value @template[name] = @value
when 'record' when 'record'
@response['templates'] << @template @response['images'] << @template
@template = {} @template = {}
end end
end end

View file

@ -0,0 +1,49 @@
module Fog
module Bluebox
class Real
require 'fog/bluebox/parsers/create_block'
# Get list of slices
# ==== Parameters
# * flavor_id<~Integer> - Id of flavor to create slice with
# * image_id<~Integer> - Id of image to create slice with
# * name<~String> - Name of slice
#
# ==== Returns
# * response<~Excon::Response>:
# * body<~Array>:
# * 'addresses'<~Array> - Ip addresses for the slice
# * 'backup-id'<~Integer> - Id of backup slice was booted from
# * 'bw-in'<~Integer> - Incoming bandwidth total for current billing cycle, in Gigabytes
# * 'bw-out'<~Integer> - Outgoing bandwidth total for current billing cycle, in Gigabytes
# * 'flavor-id'<~Integer> - Id of flavor slice was booted from
# * 'id'<~Integer> - Id of the slice
# * 'image-id'<~Integer> - Id of image slice was booted from
# * 'name'<~String> - Name of the slice
# * 'progress'<~Integer> - Progress of current action, in percentage
# * 'root-password'<~String> - Root password of slice
# * 'status'<~String> - Current status of the slice
def create_block(flavor_id, image_id, name, password)
response = request(
:body => %Q{<?xml version="1.0" encoding="UTF-8"?><block><product type="string">#{flavor_id}</product><template type="string">#{image_id}</template><name>#{name}</name><password>#{password}</password></block>}, # ["template=#{image_id}","product=#{flavor_id}"].join("\n"),
:expects => [200, 409],
:method => 'POST',
:parser => Fog::Parsers::Bluebox::CreateBlock.new,
:path => '/api/blocks.xml'
)
response
end
end
class Mock
def create_block(flavor_id, image_id, name, password)
raise MockNotImplemented.new("Contributions welcome!")
end
end
end
end

View file

@ -0,0 +1,43 @@
module Fog
module Bluebox
class Real
# Get list of slices
# ==== Parameters
# * flavor_id<~Integer> - Id of flavor to create slice with
# * image_id<~Integer> - Id of image to create slice with
# * name<~String> - Name of slice
#
# ==== Returns
# * response<~Excon::Response>:
# * body<~Array>:
# * 'addresses'<~Array> - Ip addresses for the slice
# * 'backup-id'<~Integer> - Id of backup slice was booted from
# * 'bw-in'<~Integer> - Incoming bandwidth total for current billing cycle, in Gigabytes
# * 'bw-out'<~Integer> - Outgoing bandwidth total for current billing cycle, in Gigabytes
# * 'flavor-id'<~Integer> - Id of flavor slice was booted from
# * 'id'<~Integer> - Id of the slice
# * 'image-id'<~Integer> - Id of image slice was booted from
# * 'name'<~String> - Name of the slice
# * 'progress'<~Integer> - Progress of current action, in percentage
# * 'root-password'<~String> - Root password of slice
# * 'status'<~String> - Current status of the slice
def destroy_block(block_id)
request(
:expects => 200,
:method => 'DELETE',
:path => "api/blocks/#{block_id}.xml"
)
end
end
class Mock
def destroy_block(block_id)
raise MockNotImplemented.new("Contributions welcome!")
end
end
end
end

View file

@ -0,0 +1,44 @@
module Fog
module Bluebox
class Real
require 'fog/bluebox/parsers/get_block'
# Get details of a block. We do this by looking at the
#
# ==== Parameters
# * slice_id<~Integer> - Id of slice to lookup
#
# ==== Returns
# * response<~Excon::Response>:
# * body<~Hash>:
# * 'addresses'<~Array> - Ip addresses for the slice
# * 'backup-id'<~Integer> - Id of backup slice was booted from
# * 'bw-in'<~Float> - Incoming bandwidth total for current billing cycle, in Gigabytes
# * 'bw-out'<~Float> - Outgoing bandwidth total for current billing cycle, in Gigabytes
# * 'flavor_id'<~Integer> - Id of flavor slice was booted from
# * 'id'<~Integer> - Id of the slice
# * 'image-id'<~Integer> - Id of image slice was booted from
# * 'name'<~String> - Name of the slice
# * 'progress'<~Integer> - Progress of current action, in percentage
# * 'status'<~String> - Current status of the slice
def get_block(block_id)
request(
:expects => 200,
:method => 'GET',
:parser => Fog::Parsers::Bluebox::GetBlock.new,
:path => "api/blocks/#{block_id}.xml"
)
end
end
class Mock
def get_slice(id)
raise MockNotImplemented.new("Contributions welcome!")
end
end
end
end

View file

@ -0,0 +1,37 @@
module Fog
module Bluebox
class Real
require 'fog/bluebox/parsers/get_blocks'
# 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',
:parser => Fog::Parsers::Bluebox::GetBlocks.new,
:path => 'api/blocks.xml'
)
end
end
class Mock
def get_slices
raise MockNotImplemented.new("Contributions welcome!")
end
end
end
end

View file

@ -0,0 +1,42 @@
module Fog
module Bluebox
class Real
require 'fog/bluebox/parsers/get_flavor'
# Get details of a flavor
#
# ==== Parameters
# * flavor_id<~Integer> - Id of flavor to lookup
#
# ==== Returns
# * response<~Excon::Response>:
# * body<~Array>:
# * 'id'<~Integer> - Id of the flavor
# * 'name'<~String> - Name of the flavor
# * 'price'<~Integer> - Price in cents
# * 'ram'<~Integer> - Amount of ram for the flavor
def get_flavor(flavor_id)
request(
:expects => 200,
:method => 'GET',
:parser => Fog::Parsers::Bluebox::GetFlavor.new,
:path => "api/block_products/#{flavor_id}.xml"
)
end
end
class Mock
def get_flavor(flavor_id)
if flavor_id == "0"
nil
else
Flavor.new(:cost => 0.15, :description => "Test product", :id => "94fd37a7-2606-47f7-84d5-9000deda52ae", :name => "Bob's Haus o' Servers")
end
end
end
end
end

View file

@ -2,7 +2,7 @@ module Fog
module Bluebox module Bluebox
class Real class Real
require 'fog/bluebox/parsers/get_products' require 'fog/bluebox/parsers/get_flavors'
# Get list of products # Get list of products
# #
@ -12,12 +12,12 @@ module Fog
# * 'id'<~String> - UUID of the product # * 'id'<~String> - UUID of the product
# * 'description'<~String> - Description of the product # * 'description'<~String> - Description of the product
# * 'cost'<~Decimal> - Hourly cost of the product # * 'cost'<~Decimal> - Hourly cost of the product
def get_products def get_flavors
request( request(
:expects => 200, :expects => 200,
:method => 'GET', :method => 'GET',
:parser => Fog::Parsers::Bluebox::GetProducts.new, :parser => Fog::Parsers::Bluebox::GetFlavors.new,
:path => 'api/products.xml' :path => 'api/block_products.xml'
) )
end end
@ -25,8 +25,11 @@ module Fog
class Mock class Mock
def get_images def get_flavors
raise MockNotImplemented.new("Contributions welcome!") response = Excon::Response.new
response.status = 200
response.body = { 'flavors' => [{:cost => 0.15, :description => "Test product", :id => "94fd37a7-2606-47f7-84d5-9000deda52ae", :name => "Bob's Haus o' Servers"}]}
response
end end
end end

View file

@ -2,7 +2,7 @@ module Fog
module Bluebox module Bluebox
class Real class Real
require 'fog/bluebox/parsers/get_templates' require 'fog/bluebox/parsers/get_images'
# Get list of OS templates # Get list of OS templates
# #
@ -13,11 +13,11 @@ module Fog
# * 'description'<~String> - Description of the image # * 'description'<~String> - Description of the image
# * 'public'<~Boolean> - Public / Private image # * 'public'<~Boolean> - Public / Private image
# * 'created'<~Datetime> - Timestamp of when the image was created # * 'created'<~Datetime> - Timestamp of when the image was created
def get_templates def get_images
request( request(
:expects => 200, :expects => 200,
:method => 'GET', :method => 'GET',
:parser => Fog::Parsers::Bluebox::GetTemplates.new, :parser => Fog::Parsers::Bluebox::GetImages.new,
:path => 'api/block_templates.xml' :path => 'api/block_templates.xml'
) )
end end

View file

@ -0,0 +1,41 @@
module Fog
module Bluebox
class Real
# Reboot slice
# ==== Parameters
# * slice_id<~String> - Id of server to reboot
# * type<~String> - Type of reboot, must be in ['HARD', 'SOFT']
#
# ==== Returns
# * response<~Excon::Response>:
# * body<~Hash>:
# * 'addresses'<~Array> - Ip addresses for the slice
# * 'backup-id'<~Integer> - Id of backup slice was booted from
# * 'bw-in'<~Float> - Incoming bandwidth total for current billing cycle, in Gigabytes
# * 'bw-out'<~Float> - Outgoing bandwidth total for current billing cycle, in Gigabytes
# * 'flavor_id'<~Integer> - Id of flavor slice was booted from
# * 'id'<~Integer> - Id of the slice
# * 'image-id'<~Integer> - Id of image slice was booted from
# * 'name'<~String> - Name of the slice
# * 'progress'<~Integer> - Progress of current action, in percentage
# * 'status'<~String> - Current status of the slice
def reboot_block(block_id, type = 'SOFT')
request(
:expects => 200,
:method => 'PUT',
:path => "api/blocks/#{block_id}/#{'soft_' if type == 'SOFT'}reboot.xml"
)
end
end
class Mock
def get_block(id)
raise MockNotImplemented.new("Contributions welcome!")
end
end
end
end

View file

@ -37,7 +37,7 @@ module Fog
:slicehost_password: INTENTIONALLY_LEFT_BLANK :slicehost_password: INTENTIONALLY_LEFT_BLANK
:terremark_username: INTENTIONALLY_LEFT_BLANK :terremark_username: INTENTIONALLY_LEFT_BLANK
:terremark_password: INTENTIONALLY_LEFT_BLANK :terremark_password: INTENTIONALLY_LEFT_BLANK
:bluebox_api_key: INTENTIONALLY_LEFT_BLANK
YML YML
print(yml) print(yml)
raise(ArgumentError.new("Missing Credentials")) raise(ArgumentError.new("Missing Credentials"))

View file

@ -0,0 +1,14 @@
require File.dirname(__FILE__) + '/../../spec_helper'
require File.dirname(__FILE__) + '/../../shared_examples/flavors_examples'
describe 'Fog::Bluebox::Flavors' do
it_should_behave_like "Flavors"
subject { @flavor = @flavors.all.first }
before(:each) do
@flavors = Bluebox[:blocks].flavors
end
end

View file

@ -0,0 +1,52 @@
require File.dirname(__FILE__) + '/../../spec_helper'
require File.dirname(__FILE__) + '/../../shared_examples/server_examples'
describe 'Fog::Bluebox::Server' do
it_should_behave_like "Server"
# flavor 1 = 256, image 3 = gentoo 2008.0
subject {
@flavor_id = "94fd37a7-2606-47f7-84d5-9000deda52ae" # Block 1GB Virtual Server
@image_id = "03807e08-a13d-44e4-b011-ebec7ef2c928" # Ubuntu 10.04 x64 LTS
@server = @servers.new(:flavor_id => @flavor_id, :image_id => @image_id, :name => Time.now.to_i.to_s, :password => "chunkybacon")
@server
}
before(:each) do
@servers = Bluebox[:blocks].servers
end
after(:each) do
if @server && !@server.new_record?
@server.wait_for { ready? }
@server.destroy.should be_true
end
end
describe "#initialize" do
it "should remap attributes from parser" do
server = @servers.new({
'ips' => 'ips',
'image_id' => 'image_id',
'flavor_id' => 'flavor_id',
'cpu' => 'cpu',
'memory' => 'memory',
'storage' => 'storage',
'hostname' => 'hostname',
'status' => 'status'
})
server.ips.should == 'ips'
server.flavor_id.should == 'flavor_id'
server.image_id.should == 'image_id'
server.cpu.should == 'cpu'
server.memory.should == 'memory'
server.storage.should == 'storage'
server.hostname.should == 'hostname'
server.status.should == 'status'
end
end
end

View file

@ -0,0 +1,34 @@
require File.dirname(__FILE__) + '/../../spec_helper'
require File.dirname(__FILE__) + '/../../shared_examples/servers_examples'
describe 'Fog::Bluebox::Servers' do
it_should_behave_like "Servers"
it "should have the proper status after a create call" do
subject.save
new_server = @servers.get(subject.id)
subject.status.should == "queued"
new_server.status.should == "queued"
end
# flavor 1 = 256, image 3 = gentoo 2008.0
subject {
@flavor_id = "94fd37a7-2606-47f7-84d5-9000deda52ae" # Block 1GB Virtual Server
@image_id = "03807e08-a13d-44e4-b011-ebec7ef2c928" # Ubuntu 10.04 x64 LTS
@server = @servers.new(:flavor_id => @flavor_id, :image_id => @image_id, :name => Time.now.to_i.to_s, :password => "chunkybacon")
@server
}
before(:each) do
@servers = Bluebox[:blocks].servers
end
after(:each) do
if @server && !@server.new_record?
@server.wait_for { ready? }
@server.destroy.should be_true
end
end
end

View file

@ -70,6 +70,22 @@ module Slicehost
end end
end end
module Bluebox
class << self
def [](service)
@@connections ||= Hash.new do |hash, key|
credentials = Fog.credentials.reject do |k, v|
![:bluebox_api_key, :bluebox_host, :bluebox_port, :bluebox_scheme].include?(k)
end
hash[key] = case key
when :blocks
Fog::Bluebox.new(credentials)
end
end
@@connections[service]
end
end
end
def eventually(max_delay = 16, &block) def eventually(max_delay = 16, &block)