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:
parent
b9ad8ea418
commit
2a9224cfa7
32 changed files with 791 additions and 86 deletions
3
bin/fog
3
bin/fog
|
@ -5,7 +5,7 @@ require 'yaml'
|
|||
require File.join('fog', 'credentials')
|
||||
require File.join('fog', 'bin')
|
||||
|
||||
Fog.credential = (ARGV.first && :"#{ARGV.first}") || :default
|
||||
Fog.credential = ARGV.first ? :"#{ARGV.first}" : :default
|
||||
unless Fog.credentials
|
||||
exit
|
||||
end
|
||||
|
@ -16,6 +16,7 @@ require File.join('fog', 'rackspace', 'bin')
|
|||
require File.join('fog', 'slicehost', 'bin')
|
||||
require File.join('fog', 'terremark', 'bin')
|
||||
require File.join('fog', 'vcloud', 'bin')
|
||||
require File.join('fog', 'bluebox', 'bin')
|
||||
|
||||
if ARGV.length > 1
|
||||
print(instance_eval(ARGV[1..-1].join(' ')).to_json)
|
||||
|
|
33
examples/bluebox_create.rb
Normal file
33
examples/bluebox_create.rb
Normal 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
|
24
fog.gemspec
24
fog.gemspec
|
@ -209,6 +209,27 @@ Gem::Specification.new do |s|
|
|||
lib/fog/aws/s3.rb
|
||||
lib/fog/aws/simpledb.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/connection.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/put_attributes_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/lorem.txt
|
||||
spec/rackspace/models/servers/flavors_spec.rb
|
||||
|
|
|
@ -5,7 +5,7 @@ module Fog
|
|||
|
||||
def services
|
||||
services = []
|
||||
[::AWS, ::Local, ::Rackspace, ::Slicehost, ::Terremark, ::Vcloud].each do |service|
|
||||
[::AWS, ::Local, ::Rackspace, ::Slicehost, ::Terremark, ::Vcloud, ::Bluebox].each do |service|
|
||||
if service.initialized?
|
||||
services << service
|
||||
end
|
||||
|
|
|
@ -1,16 +1,21 @@
|
|||
module Fog
|
||||
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={})
|
||||
|
||||
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]
|
||||
raise ArgumentError.new('bluebox_api_key is required to access Blue Box')
|
||||
end
|
||||
|
@ -50,9 +55,9 @@ module Fog
|
|||
|
||||
def initialize(options={})
|
||||
@bluebox_api_key = options[:bluebox_api_key]
|
||||
@host = options[:host] || "boxpanel.blueboxgrp.com"
|
||||
@port = options[:port] || 443
|
||||
@scheme = options[:scheme] || 'https'
|
||||
@host = options[:bluebox_host] || "boxpanel.blueboxgrp.com"
|
||||
@port = options[:bluebox_port] || 443
|
||||
@scheme = options[:bluebox_scheme] || 'https'
|
||||
end
|
||||
|
||||
def request(params)
|
||||
|
@ -67,7 +72,7 @@ module Fog
|
|||
headers['Content-Type'] = 'application/xml'
|
||||
end
|
||||
|
||||
response = @connection.request({
|
||||
@connection.request({
|
||||
:body => params[:body],
|
||||
:expects => params[:expects],
|
||||
:headers => headers.merge!(params[:headers] || {}),
|
||||
|
@ -76,8 +81,6 @@ module Fog
|
|||
:parser => params[:parser],
|
||||
:path => params[:path]
|
||||
})
|
||||
|
||||
response
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
module Bluebox
|
||||
class << self
|
||||
|
||||
if Fog.credentials[:bluebox_api_key]
|
||||
|
||||
def initialized?
|
||||
|
@ -9,10 +10,10 @@ module Bluebox
|
|||
def [](service)
|
||||
@@connections ||= Hash.new do |hash, key|
|
||||
credentials = Fog.credentials.reject do |k,v|
|
||||
![:bluebox_api_key].include?(k)
|
||||
![:bluebox_api_key, :bluebox_host, :bluebox_port, :bluebox_scheme].include?(k)
|
||||
end
|
||||
hash[key] = case key
|
||||
when :slices
|
||||
when :blocks
|
||||
Fog::Bluebox.new(credentials)
|
||||
end
|
||||
end
|
||||
|
@ -20,15 +21,15 @@ module Bluebox
|
|||
end
|
||||
|
||||
def flavors
|
||||
self[:slices].flavors
|
||||
self[:blocks].flavors
|
||||
end
|
||||
|
||||
def images
|
||||
self[:slices].images
|
||||
self[:blocks].images
|
||||
end
|
||||
|
||||
def servers
|
||||
self[:slices].servers
|
||||
self[:blocks].servers
|
||||
end
|
||||
|
||||
else
|
||||
|
|
|
@ -3,12 +3,13 @@ require 'fog/model'
|
|||
module Fog
|
||||
module Bluebox
|
||||
|
||||
class Product < Fog::Model
|
||||
class Flavor < Fog::Model
|
||||
|
||||
identity :id
|
||||
|
||||
attribute :name
|
||||
attribute :cost
|
||||
attribute :description
|
||||
|
||||
def bits
|
||||
# 64
|
41
lib/fog/bluebox/models/flavors.rb
Normal file
41
lib/fog/bluebox/models/flavors.rb
Normal 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
|
|
@ -3,7 +3,7 @@ require 'fog/model'
|
|||
module Fog
|
||||
module Bluebox
|
||||
|
||||
class Template < Fog::Model
|
||||
class Image < Fog::Model
|
||||
|
||||
identity :id
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
require 'fog/collection'
|
||||
require 'fog/bluebox/models/template'
|
||||
require 'fog/bluebox/models/image'
|
||||
|
||||
module Fog
|
||||
module Bluebox
|
||||
|
||||
class Mock
|
||||
def images(attributes = {})
|
||||
Fog::Bluebox::Templates.new({
|
||||
Fog::Bluebox::Images.new({
|
||||
:connection => self
|
||||
}.merge!(attributes))
|
||||
end
|
||||
|
@ -14,7 +14,7 @@ module Fog
|
|||
|
||||
class Real
|
||||
def images(attributes = {})
|
||||
Fog::Bluebox::Templates.new({
|
||||
Fog::Bluebox::Images.new({
|
||||
:connection => self
|
||||
}.merge!(attributes))
|
||||
end
|
||||
|
@ -22,7 +22,7 @@ module Fog
|
|||
|
||||
class Templates < Fog::Collection
|
||||
|
||||
model Fog::Bluebox::Template
|
||||
model Fog::Bluebox::Image
|
||||
|
||||
def all
|
||||
data = connection.get_templates.body['templates']
|
|
@ -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
|
60
lib/fog/bluebox/models/server.rb
Normal file
60
lib/fog/bluebox/models/server.rb
Normal 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
|
44
lib/fog/bluebox/models/servers.rb
Normal file
44
lib/fog/bluebox/models/servers.rb
Normal 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
|
48
lib/fog/bluebox/parsers/create_block.rb
Normal file
48
lib/fog/bluebox/parsers/create_block.rb
Normal 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
|
47
lib/fog/bluebox/parsers/get_block.rb
Normal file
47
lib/fog/bluebox/parsers/get_block.rb
Normal 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
|
33
lib/fog/bluebox/parsers/get_blocks.rb
Normal file
33
lib/fog/bluebox/parsers/get_blocks.rb
Normal 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
|
33
lib/fog/bluebox/parsers/get_flavor.rb
Normal file
33
lib/fog/bluebox/parsers/get_flavor.rb
Normal 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
|
|
@ -2,24 +2,22 @@ module Fog
|
|||
module Parsers
|
||||
module Bluebox
|
||||
|
||||
class GetProducts < Fog::Parsers::Base
|
||||
class GetFlavors < Fog::Parsers::Base
|
||||
|
||||
def reset
|
||||
@product = {}
|
||||
@response = { 'products' => [] }
|
||||
@response = { 'flavors' => [] }
|
||||
end
|
||||
|
||||
def end_element(name)
|
||||
case name
|
||||
when 'cost'
|
||||
@product[name] = @value
|
||||
when 'id'
|
||||
@product[name] = @value
|
||||
when 'description'
|
||||
@product[name] = @value
|
||||
when 'record'
|
||||
@response['products'] << @product
|
||||
@response['flavors'] << @product
|
||||
@product = {}
|
||||
when 'cost'
|
||||
@product[name] = @value.to_f
|
||||
else
|
||||
@product[name] = @value
|
||||
end
|
||||
end
|
||||
|
|
@ -2,11 +2,11 @@ module Fog
|
|||
module Parsers
|
||||
module Bluebox
|
||||
|
||||
class GetTemplates < Fog::Parsers::Base
|
||||
class GetImages < Fog::Parsers::Base
|
||||
|
||||
def reset
|
||||
@template = {}
|
||||
@response = { 'templates' => [] }
|
||||
@response = { 'images' => [] }
|
||||
end
|
||||
|
||||
def end_element(name)
|
||||
|
@ -18,7 +18,7 @@ module Fog
|
|||
when 'description'
|
||||
@template[name] = @value
|
||||
when 'record'
|
||||
@response['templates'] << @template
|
||||
@response['images'] << @template
|
||||
@template = {}
|
||||
end
|
||||
end
|
49
lib/fog/bluebox/requests/create_block.rb
Normal file
49
lib/fog/bluebox/requests/create_block.rb
Normal 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
|
43
lib/fog/bluebox/requests/destroy_block.rb
Normal file
43
lib/fog/bluebox/requests/destroy_block.rb
Normal 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
|
44
lib/fog/bluebox/requests/get_block.rb
Normal file
44
lib/fog/bluebox/requests/get_block.rb
Normal 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
|
37
lib/fog/bluebox/requests/get_blocks.rb
Normal file
37
lib/fog/bluebox/requests/get_blocks.rb
Normal 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
|
42
lib/fog/bluebox/requests/get_flavor.rb
Normal file
42
lib/fog/bluebox/requests/get_flavor.rb
Normal 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
|
|
@ -2,7 +2,7 @@ module Fog
|
|||
module Bluebox
|
||||
class Real
|
||||
|
||||
require 'fog/bluebox/parsers/get_products'
|
||||
require 'fog/bluebox/parsers/get_flavors'
|
||||
|
||||
# Get list of products
|
||||
#
|
||||
|
@ -12,12 +12,12 @@ module Fog
|
|||
# * 'id'<~String> - UUID of the product
|
||||
# * 'description'<~String> - Description of the product
|
||||
# * 'cost'<~Decimal> - Hourly cost of the product
|
||||
def get_products
|
||||
def get_flavors
|
||||
request(
|
||||
:expects => 200,
|
||||
:method => 'GET',
|
||||
:parser => Fog::Parsers::Bluebox::GetProducts.new,
|
||||
:path => 'api/products.xml'
|
||||
:parser => Fog::Parsers::Bluebox::GetFlavors.new,
|
||||
:path => 'api/block_products.xml'
|
||||
)
|
||||
end
|
||||
|
||||
|
@ -25,8 +25,11 @@ module Fog
|
|||
|
||||
class Mock
|
||||
|
||||
def get_images
|
||||
raise MockNotImplemented.new("Contributions welcome!")
|
||||
def get_flavors
|
||||
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
|
|
@ -2,7 +2,7 @@ module Fog
|
|||
module Bluebox
|
||||
class Real
|
||||
|
||||
require 'fog/bluebox/parsers/get_templates'
|
||||
require 'fog/bluebox/parsers/get_images'
|
||||
|
||||
# Get list of OS templates
|
||||
#
|
||||
|
@ -13,11 +13,11 @@ module Fog
|
|||
# * 'description'<~String> - Description of the image
|
||||
# * 'public'<~Boolean> - Public / Private image
|
||||
# * 'created'<~Datetime> - Timestamp of when the image was created
|
||||
def get_templates
|
||||
def get_images
|
||||
request(
|
||||
:expects => 200,
|
||||
:method => 'GET',
|
||||
:parser => Fog::Parsers::Bluebox::GetTemplates.new,
|
||||
:parser => Fog::Parsers::Bluebox::GetImages.new,
|
||||
:path => 'api/block_templates.xml'
|
||||
)
|
||||
end
|
41
lib/fog/bluebox/requests/reboot_block.rb
Normal file
41
lib/fog/bluebox/requests/reboot_block.rb
Normal 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
|
|
@ -37,7 +37,7 @@ module Fog
|
|||
:slicehost_password: INTENTIONALLY_LEFT_BLANK
|
||||
:terremark_username: INTENTIONALLY_LEFT_BLANK
|
||||
:terremark_password: INTENTIONALLY_LEFT_BLANK
|
||||
|
||||
:bluebox_api_key: INTENTIONALLY_LEFT_BLANK
|
||||
YML
|
||||
print(yml)
|
||||
raise(ArgumentError.new("Missing Credentials"))
|
||||
|
|
14
spec/bluebox/models/flavors_spec.rb
Normal file
14
spec/bluebox/models/flavors_spec.rb
Normal 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
|
52
spec/bluebox/models/server_spec.rb
Normal file
52
spec/bluebox/models/server_spec.rb
Normal 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
|
34
spec/bluebox/models/servers_spec.rb
Normal file
34
spec/bluebox/models/servers_spec.rb
Normal 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
|
|
@ -70,6 +70,22 @@ module Slicehost
|
|||
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)
|
||||
|
|
Loading…
Add table
Reference in a new issue