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

Merge pull request #276 from seeingidog/stormondemandfog.

[stormondemand] Implement Stormondemand API
This commit is contained in:
Wesley Beary 2011-05-02 11:24:30 -07:00
commit 8a048c6c3f
39 changed files with 880 additions and 1 deletions

View file

@ -65,6 +65,7 @@ require 'fog/bin/local'
require 'fog/bin/new_servers'
require 'fog/bin/rackspace'
require 'fog/bin/slicehost'
require 'fog/bin/stormondemand'
require 'fog/bin/terremark'
require 'fog/bin/virtual_box'
require 'fog/bin/voxel'

View file

@ -0,0 +1,30 @@
class StormOnDemand < Fog::Bin
class << self
def class_for(key)
case key
when :compute
Fog::StormOnDemand::Compute
else
raise ArgumentError, "Unsupported #{self} service: #{key}"
end
end
def [](service)
@@connections ||= Hash.new do |hash, key|
hash[key] = case key
when :compute
Fog::Compute.new(:provider => 'StormOnDemand')
else
raise ArgumentError, "Unrecognized service: #{key.inspect}"
end
end
@@connections[service]
end
def services
Fog::StormOnDemand.services
end
end
end

View file

@ -31,6 +31,9 @@ module Fog
when 'Slicehost'
require 'fog/compute/slicehost'
Fog::Slicehost::Compute.new(attributes)
when 'StormOnDemand'
require 'fog/compute/stormondemand'
Fog::StormOnDemand::Compute.new(attributes)
when 'VirtualBox'
require 'fog/compute/virtual_box'
Fog::VirtualBox::Compute.new(attributes)

View file

@ -0,0 +1,38 @@
require 'fog/core/model'
module Fog
module StormOnDemand
class Compute
class Balancer < Fog::Model
identity :uniq_id
attribute :vip
attribute :price
attribute :name
attribute :session_persistence
attribute :ssl_termination
attribute :strategy
attribute :nodes
attribute :services
def initialize(attributes={})
super
end
def add_node(options)
requires :identity
connection.add_balancer_node({:uniq_id => identity}.merge!(options))
end
def remove_node(options)
requires :identity
connection.remove_balancer_node({:uniq_id => identity}.merge!(options))
end
end
end
end
end

View file

@ -0,0 +1,21 @@
require 'fog/core/collection'
require 'fog/compute/models/stormondemand/balancer'
module Fog
module StormOnDemand
class Compute
class Balancers < Fog::Collection
model Fog::StormOnDemand::Compute::Balancer
def all
data = connection.list_balancers.body['loadbalancers']
load(data)
end
end
end
end
end

View file

@ -0,0 +1,25 @@
require 'fog/core/model'
module Fog
module StormOnDemand
class Compute
class Config < Fog::Model
identity :id
attribute :available
attribute :description
attribute :disk
attribute :featured
attribute :memory
attribute :price
attribute :vcpu
end
def initialize(attributes={})
super
end
end
end
end

View file

@ -0,0 +1,22 @@
require 'fog/core/collection'
require 'fog/compute/models/stormondemand/config'
module Fog
module StormOnDemand
class Compute
class Configs < Fog::Collection
model Fog::StormOnDemand::Compute::Config
def all
data = connection.list_configs.body['configs']
load(data)
end
end
end
end
end

View file

@ -0,0 +1,19 @@
module Fog
module StormOnDemand
class Compute
class Real
def create_server(options = {})
request(
:expects => [200],
:method => 'GET',
:path => "/storm/server/create",
:headers => {"Content-Type" => "application/json"},
:body => {:params => options}.to_json
)
end
end
end
end
end

View file

@ -0,0 +1,20 @@
require 'fog/core/model'
module Fog
module StormOnDemand
class Compute
class Image < Fog::Model
identity :id
attribute :accnt
attribute :name
attribute :source_hostname
attribute :source_subaccnt
attribute :template
attribute :template_description
attribute :time_taken
end
end
end
end

View file

@ -0,0 +1,21 @@
require 'fog/core/collection'
require 'fog/compute/models/stormondemand/image'
module Fog
module StormOnDemand
class Compute
class Images < Fog::Collection
model Fog::StormOnDemand::Compute::Image
def all
data = connection.list_images.body['images']
load(data)
end
end
end
end
end

View file

@ -0,0 +1,19 @@
require 'fog/core/model'
module Fog
module StormOnDemand
class Compute
class PrivateIp < Fog::Model
attribute :zone
attribute :uniq_id
def initialize(attributes={})
super
end
end
end
end
end

View file

@ -0,0 +1,31 @@
require 'fog/core/collection'
require 'fog/compute/models/stormondemand/private_ip'
module Fog
module StormOnDemand
class Compute
class PrivateIps < Fog::Collection
model Fog::StormOnDemand::Compute::PrivateIp
def all
data = connection.list_private_ips.body['networks']
load(data)
end
def get(server_id)
if server_id && server = connection.get_private_ip(private_ip).body
new(server)
elsif !server_id
nil
end
rescue Excon::Errors::Forbidden
nil
end
end
end
end
end

View file

@ -0,0 +1,74 @@
require 'fog/core/model'
module Fog
module StormOnDemand
class Compute
class Server < Fog::Model
identity :uniq_id
attribute :accnt
attribute :backup_enabled
attribute :backup_plan
attribute :backup_quota
attribute :backup_size
attribute :bandwidth_quota
attribute :config_description
attribute :config_id
attribute :create_date
attribute :domain
attribute :ip
attribute :ip_count
attribute :manage_level
attribute :subaccnt
attribute :template
attribute :template_description
attribute :zone
attribute :active
attr_writer :password, :username
def initialize(attributes={})
super
end
def create(options)
data = connection.create_server(options).body['servers']
load(data)
end
def delete
requires :identity
connection.delete_server(:uniq_id => identity)
true
end
def ready?
active == 1
end
def reboot
requires :identity
connection.reboot_server(:uniq_id => identity)
true
end
def username
@username ||= 'root'
end
def clone(options)
requires :identity
connection.clone_server({:uniq_id => identity}.merge!(options))
true
end
def resize(options)
requires :identity
connection.resize_server({:uniq_id => identity}.merge!(options))
true
end
end
end
end
end

View file

@ -0,0 +1,26 @@
require 'fog/core/collection'
require 'fog/compute/models/stormondemand/server'
module Fog
module StormOnDemand
class Compute
class Servers < Fog::Collection
model Fog::StormOnDemand::Compute::Server
def all
data = connection.list_servers.body['servers']
load(data)
end
def get(uniq_id)
server = connection.get_server(:uniq_id => uniq_id).body
new(server)
end
end
end
end
end

View file

@ -0,0 +1,23 @@
require 'fog/core/model'
module Fog
module StormOnDemand
class Compute
class Stat < Fog::Model
attribute :loadavg
attribute :memory
attribute :virtual
attribute :domain
attribute :disk
attribute :uptime
def initialize(attributes={})
super
end
end
end
end
end

View file

@ -0,0 +1,22 @@
require 'fog/core/collection'
require 'fog/compute/models/stormondemand/stat'
module Fog
module StormOnDemand
class Compute
class Stats < Fog::Collection
model Fog::StormOnDemand::Compute::Stat
def get(options)
data = connection.get_stats(options).body
load(data)
rescue Excon::Errors::Forbidden
nil
end
end
end
end
end

View file

@ -0,0 +1,22 @@
require 'fog/core/model'
module Fog
module StormOnDemand
class Compute
class Template < Fog::Model
identity :id
attribute :name
attribute :description
attribute :manage_level
attribute :os
attribute :price
end
def initialize(attributes={})
super
end
end
end
end

View file

@ -0,0 +1,21 @@
require 'fog/core/collection'
require 'fog/compute/models/stormondemand/template'
module Fog
module StormOnDemand
class Compute
class Templates < Fog::Collection
model Fog::StormOnDemand::Compute::Template
def all
data = connection.list_templates.body['templates']
load(data)
end
end
end
end
end

View file

@ -0,0 +1,16 @@
module Fog
module StormOnDemand
class Compute
class Real
def add_balancer_node(options = {})
request(
:path => "/network/loadbalancer/addnode",
:body => {:params => options}.to_json
)
end
end
end
end
end

View file

@ -0,0 +1,16 @@
module Fog
module StormOnDemand
class Compute
class Real
def clone_server(options = {})
request(
:path => "/storm/server/clone",
:body => {:params => options}.to_json
)
end
end
end
end
end

View file

@ -0,0 +1,16 @@
module Fog
module StormOnDemand
class Compute
class Real
def create_server(options = {})
request(
:path => "/storm/server/create",
:body => {:params => options}.to_json
)
end
end
end
end
end

View file

@ -0,0 +1,16 @@
module Fog
module StormOnDemand
class Compute
class Real
def delete_server(options = {})
request(
:path => "/storm/server/destroy",
:body => {:params => options}.to_json
)
end
end
end
end
end

View file

@ -0,0 +1,16 @@
module Fog
module StormOnDemand
class Compute
class Real
def get_server(options = {})
request(
:path => "/storm/server/details",
:body => {:params => options}.to_json
)
end
end
end
end
end

View file

@ -0,0 +1,16 @@
module Fog
module StormOnDemand
class Compute
class Real
def get_stats(options = {})
request(
:path => "/monitoring/load/stats",
:body => {:params => options}.to_json
)
end
end
end
end
end

View file

@ -0,0 +1,16 @@
module Fog
module StormOnDemand
class Compute
class Real
def list_balancers(options = {})
request(
:path => "/network/loadbalancer/list",
:body => options.to_json
)
end
end
end
end
end

View file

@ -0,0 +1,16 @@
module Fog
module StormOnDemand
class Compute
class Real
def list_configs(options = {})
request(
:path => "/storm/config/list",
:body => options.to_json
)
end
end
end
end
end

View file

@ -0,0 +1,16 @@
module Fog
module StormOnDemand
class Compute
class Real
def list_images(options = {})
request(
:path => "/server/image/list",
:body => options.to_json
)
end
end
end
end
end

View file

@ -0,0 +1,16 @@
module Fog
module StormOnDemand
class Compute
class Real
def list_private_ips(options = {})
request(
:path => "/network/private/get",
:body => options.to_json
)
end
end
end
end
end

View file

@ -0,0 +1,16 @@
module Fog
module StormOnDemand
class Compute
class Real
def list_servers(options = {})
request(
:path => "/storm/server/list",
:body => options.to_json
)
end
end
end
end
end

View file

@ -0,0 +1,16 @@
module Fog
module StormOnDemand
class Compute
class Real
def list_templates(options = {})
request(
:path => "/server/template/list",
:body => options.to_json
)
end
end
end
end
end

View file

@ -0,0 +1,16 @@
module Fog
module StormOnDemand
class Compute
class Real
def reboot_server(options = {})
request(
:path => "/storm/server/reboot",
:body => {:params => options}.to_json
)
end
end
end
end
end

View file

@ -0,0 +1,16 @@
module Fog
module StormOnDemand
class Compute
class Real
def remove_balancer_node(options = {})
request(
:path => "/network/loadbalancer/removenode",
:body => {:params => options}.to_json
)
end
end
end
end
end

View file

@ -0,0 +1,16 @@
module Fog
module StormOnDemand
class Compute
class Real
def resize_server(options = {})
request(
:path => "/storm/server/resize",
:body => {:params => options}.to_json
)
end
end
end
end
end

View file

@ -0,0 +1,122 @@
module Fog
module StormOnDemand
class Compute < Fog::Service
API_URL = 'https://api.stormondemand.com'
requires :stormondemand_username, :stormondemand_password
recognizes :stormondemand_auth_url
recognizes :provider # remove post deprecation
model_path 'fog/compute/models/stormondemand'
model :config
collection :configs
model :image
collection :images
model :server
collection :servers
model :balancer
collection :balancers
model :private_ip
collection :private_ips
model :stat
collection :stats
model :template
collection :templates
request_path 'fog/compute/requests/stormondemand'
request :clone_server
request :delete_server
request :reboot_server
request :list_servers
request :get_server
request :create_server
request :resize_server
request :remove_balancer_node
request :add_balancer_node
request :list_balancers
request :list_configs
request :list_templates
request :list_images
request :get_stats
request :list_private_ips
class Mock
def self.data
@data ||= Hash.new do |hash, key|
hash[key] = {
:last_modified => {
:images => {},
:servers => {}
},
:images => {},
:servers => {}
}
end
end
def self.reset_data(keys=data.keys)
for key in [*keys]
data.delete(key)
end
end
def initialize(options={})
@stormondemand_username = options[:stormondemand_username]
@data = self.class.data[@stormondemand_username]
end
end
class Real
def initialize(options={})
require 'json'
uri = URI.parse(options[:stormondemand_auth_url] ||= API_URL)
@host = uri.host
@path = uri.path
@port = uri.port
@scheme = uri.scheme
@stormondemand_username = options[:stormondemand_username]
@stormondemand_password = options[:stormondemand_password]
@connection = Fog::Connection.new("#{@scheme}://#{@host}:#{@port}")
end
def reload
@connection.reset
end
def request(params)
begin
response = @connection.request(params.merge!({
:headers => {
'Content-Type' => 'application/json',
'Authorization' => "Basic " + Base64.encode64("#{@stormondemand_username}:#{@stormondemand_password}").chomp
}.merge!(params[:headers] || {}),
:host => @host,
:path => "#{@path}/#{params[:path]}",
:expects => 200,
:method => :post
}))
rescue Excon::Errors::HTTPStatusError => error
raise case error
when Excon::Errors::NotFound
Fog::StormOnDemand::Compute::NotFound.slurp(error)
else
error
end
end
unless response.body.empty?
response.body = JSON.parse(response.body)
end
if response.body.keys[0] == 'error_class'
raise Fog::StormOnDemand::Compute::Error, response.body.inspect
end
response
end
end
end
end
end

View file

@ -90,6 +90,8 @@ An alternate file may be used by placing its path in the FOG_RC environment vari
:rackspace_servicenet:
:rackspace_cdn_ssl:
:slicehost_password:
:stormondemand_username:
:stormondemand_password:
:terremark_username:
:terremark_password:
:voxel_api_key:

View file

@ -18,6 +18,7 @@ require 'fog/providers/local'
require 'fog/providers/new_servers'
require 'fog/providers/rackspace'
require 'fog/providers/slicehost'
require 'fog/providers/stormondemand'
require 'fog/providers/virtual_box'
require 'fog/providers/voxel'
require 'fog/providers/zerigo'

View file

@ -0,0 +1,12 @@
require 'fog/core'
module Fog
module StormOnDemand
extend Fog::Provider
service(:compute, 'compute/stormondemand')
end
end

View file

@ -0,0 +1,64 @@
Shindo.tests('StormOnDemand::Compute | server requests', ['stormondemand']) do
@server_format = {
'uniq_id' => String,
'accnt' => String,
'backup_enabled' => String,
'backup_plan' => String,
'backup_size' => String,
'backup_quota' => String,
'bandwidth_quota' => Integer,
'config_description' => String,
'config_id' => String,
'domain' => String,
'ip' => String,
'ip_count' => String,
'subaccnt' => String,
'template' => NilClass,
'template_description' => String,
'manage_level' => NilClass,
'zone' => Hash,
'active' => Integer,
'create_date' => String
}
@servers_format = {
'servers' => [@server_format]
}
tests('success') do
@uniq_id = nil
@name = "fog-test#{Time.now.to_i}.com"
tests("#create_server(:backup_enabled => 0, :config_id => 114, :domain => '#{@name}', :template => 'CENTOSUNMANAGED', :ip_count => 1, :password => 'B92bxfijsdK3!')").formats(@server_format) do
pending if Fog.mocking?
data = StormOnDemand[:compute].create_server(:backup_enabled => 0, :config_id => 114, :domain => @name, :template => 'CENTOSUNMANAGED', :ip_count => 1, :password => 'B92bxfijsdK3!').body
@uniq_id = data['uniq_id']
data
end
tests('#list_servers').formats(@servers_format) do
pending if Fog.mocking?
StormOnDemand[:compute].list_servers.body
end
unless Fog.mocking?
StormOnDemand[:compute].servers.get(:uniq_id => @uniq_id).wait_for { ready? }
end
tests("#delete_server(:uniq_id => #{@uniq_id})").succeeds do
pending if Fog.mocking?
StormOnDemand[:compute].delete_server(@uniq_id)
end
end
tests('failure') do
tests('#delete_server(0)').raises(Fog::StormOnDemand::Compute::Error) do
pending if Fog.mocking?
StormOnDemand[:compute].delete_server(0)
end
end
end

View file

@ -8,7 +8,7 @@ def lorem_file
end
# check to see which credentials are available and add others to the skipped tags list
all_providers = ['aws', 'bluebox', 'brightbox', 'dnsimple', 'ecloud', 'gogrid', 'google', 'linode', 'local', 'newservers', 'rackspace', 'slicehost', 'voxel', 'zerigo']
all_providers = ['aws', 'bluebox', 'brightbox', 'dnsimple', 'ecloud', 'gogrid', 'google', 'linode', 'local', 'newservers', 'rackspace', 'slicehost', 'stormondemand', 'voxel', 'zerigo']
available_providers = Fog.providers.map {|provider| provider.downcase}
for provider in (all_providers - available_providers)
Formatador.display_line("[yellow]Skipping tests for [bold]#{provider}[/] [yellow]due to lacking credentials (add some to '~/.fog' to run them)[/]")