mirror of
https://github.com/fog/fog.git
synced 2022-11-09 13:51:43 -05:00
Revert "Moving Rackspace logic to fog-rackspace"
This reverts commit d6ecb19d24
.
Conflicts:
fog.gemspec
This commit is contained in:
parent
909cb31571
commit
72e52e70be
609 changed files with 36246 additions and 1 deletions
|
@ -84,7 +84,7 @@ Collections share basic CRUD type operations, such as:
|
|||
As an example, we'll try initializing and persisting a Rackspace Cloud server:
|
||||
|
||||
```ruby
|
||||
require 'fog/rackspace'
|
||||
require 'fog'
|
||||
|
||||
compute = Fog::Compute.new(
|
||||
:provider => 'Rackspace',
|
||||
|
|
|
@ -44,6 +44,7 @@ require 'fog/linode'
|
|||
require 'fog/local'
|
||||
require 'fog/bare_metal_cloud'
|
||||
require 'fog/ninefold'
|
||||
require 'fog/rackspace'
|
||||
require 'fog/rage4'
|
||||
require 'fog/riakcs'
|
||||
require 'fog/openstack'
|
||||
|
|
|
@ -76,6 +76,7 @@ require 'fog/bin/linode'
|
|||
require 'fog/bin/local'
|
||||
require 'fog/bin/bare_metal_cloud'
|
||||
require 'fog/bin/ninefold'
|
||||
require 'fog/bin/rackspace'
|
||||
require 'fog/bin/rage4'
|
||||
require 'fog/bin/riakcs'
|
||||
require 'fog/bin/openstack'
|
||||
|
|
81
lib/fog/bin/rackspace.rb
Normal file
81
lib/fog/bin/rackspace.rb
Normal file
|
@ -0,0 +1,81 @@
|
|||
class Rackspace < Fog::Bin
|
||||
class << self
|
||||
def class_for(key)
|
||||
case key
|
||||
when :auto_scale
|
||||
Fog::Rackspace::AutoScale
|
||||
when :block_storage
|
||||
Fog::Rackspace::BlockStorage
|
||||
when :cdn
|
||||
Fog::CDN::Rackspace
|
||||
when :compute
|
||||
Fog::Compute::Rackspace
|
||||
when :compute_v2
|
||||
Fog::Compute::RackspaceV2
|
||||
when :storage
|
||||
Fog::Storage::Rackspace
|
||||
when :load_balancers
|
||||
Fog::Rackspace::LoadBalancers
|
||||
when :dns
|
||||
Fog::DNS::Rackspace
|
||||
when :identity
|
||||
Fog::Rackspace::Identity
|
||||
when :databases
|
||||
Fog::Rackspace::Databases
|
||||
when :monitoring
|
||||
Fog::Rackspace::Monitoring
|
||||
when :queues
|
||||
Fog::Rackspace::Queues
|
||||
when :networking
|
||||
Fog::Rackspace::Networking
|
||||
else
|
||||
raise ArgumentError, "Unrecognized service: #{key}"
|
||||
end
|
||||
end
|
||||
|
||||
def [](service)
|
||||
@@connections ||= Hash.new do |hash, key|
|
||||
hash[key] = case key
|
||||
when :auto_scale
|
||||
Fog::Rackspace::AutoScale.new
|
||||
when :cdn
|
||||
Fog::Logger.warning("Rackspace[:cdn] is not recommended, use CDN[:rackspace] for portability")
|
||||
Fog::CDN.new(:provider => 'Rackspace')
|
||||
when :compute
|
||||
Fog::Logger.warning("Rackspace[:compute] is not recommended, use Compute[:rackspace] for portability")
|
||||
Fog::Compute.new(:provider => 'Rackspace')
|
||||
when :compute_v2
|
||||
Fog::Logger.warning("Rackspace[:compute] is not recommended, use Compute[:rackspace] for portability")
|
||||
Fog::Compute.new(:provider => 'Rackspace', :version => 'v2')
|
||||
when :dns
|
||||
Fog::DNS.new(:provider => 'Rackspace')
|
||||
when :load_balancers
|
||||
Fog::Rackspace::LoadBalancers.new
|
||||
when :storage
|
||||
Fog::Logger.warning("Rackspace[:storage] is not recommended, use Storage[:rackspace] for portability")
|
||||
Fog::Storage.new(:provider => 'Rackspace')
|
||||
when :identity
|
||||
Fog::Logger.warning("Rackspace[:identity] is not recommended, use Identity[:rackspace] for portability")
|
||||
Fog::Identity.new(:provider => 'Rackspace')
|
||||
when :databases
|
||||
Fog::Rackspace::Databases.new
|
||||
when :block_storage
|
||||
Fog::Rackspace::BlockStorage.new
|
||||
when :monitoring
|
||||
Fog::Rackspace::Monitoring.new
|
||||
when :queues
|
||||
Fog::Rackspace::Queues.new
|
||||
when :networking
|
||||
Fog::Rackspace::Networking.new
|
||||
else
|
||||
raise ArgumentError, "Unrecognized service: #{key.inspect}"
|
||||
end
|
||||
end
|
||||
@@connections[service]
|
||||
end
|
||||
|
||||
def services
|
||||
Fog::Rackspace.services
|
||||
end
|
||||
end
|
||||
end
|
13
lib/fog/rackspace.rb
Normal file
13
lib/fog/rackspace.rb
Normal file
|
@ -0,0 +1,13 @@
|
|||
require 'fog/rackspace/auto_scale'
|
||||
require 'fog/rackspace/block_storage'
|
||||
require 'fog/rackspace/cdn'
|
||||
require 'fog/rackspace/compute'
|
||||
require 'fog/rackspace/compute_v2'
|
||||
require 'fog/rackspace/databases'
|
||||
require 'fog/rackspace/dns'
|
||||
require 'fog/rackspace/identity'
|
||||
require 'fog/rackspace/load_balancers'
|
||||
require 'fog/rackspace/monitoring'
|
||||
require 'fog/rackspace/queues'
|
||||
require 'fog/rackspace/storage'
|
||||
require 'fog/rackspace/networking'
|
134
lib/fog/rackspace/auto_scale.rb
Normal file
134
lib/fog/rackspace/auto_scale.rb
Normal file
|
@ -0,0 +1,134 @@
|
|||
require 'fog/rackspace/core'
|
||||
|
||||
module Fog
|
||||
module Rackspace
|
||||
class AutoScale < Fog::Service
|
||||
include Fog::Rackspace::Errors
|
||||
|
||||
class ServiceError < Fog::Rackspace::Errors::ServiceError; end
|
||||
class InternalServerError < Fog::Rackspace::Errors::InternalServerError; end
|
||||
|
||||
class BadRequest < Fog::Rackspace::Errors::BadRequest
|
||||
attr_reader :validation_errors
|
||||
|
||||
def self.slurp(error, service=nil)
|
||||
if error && error.response
|
||||
status_code = error.response.status
|
||||
if error.response.body
|
||||
body = Fog::JSON.decode(error.response.body)
|
||||
message = "#{body['type']} - #{body['message']}"
|
||||
details = error.response.body['details']
|
||||
end
|
||||
end
|
||||
|
||||
new_error = new(message)
|
||||
new_error.set_backtrace(error.backtrace)
|
||||
new_error.instance_variable_set(:@validation_errors, details)
|
||||
new_error.instance_variable_set(:@status_code, status_code)
|
||||
new_error.set_transaction_id(error, service)
|
||||
new_error
|
||||
end
|
||||
end
|
||||
|
||||
requires :rackspace_username, :rackspace_api_key
|
||||
recognizes :rackspace_auth_url
|
||||
recognizes :rackspace_region
|
||||
recognizes :rackspace_auto_scale_url
|
||||
|
||||
model_path 'fog/rackspace/models/auto_scale'
|
||||
model :group
|
||||
collection :groups
|
||||
model :group_config
|
||||
model :launch_config
|
||||
|
||||
model :policy
|
||||
collection :policies
|
||||
|
||||
model :webhook
|
||||
collection :webhooks
|
||||
|
||||
request_path 'fog/rackspace/requests/auto_scale'
|
||||
request :list_groups
|
||||
request :create_group
|
||||
request :get_group
|
||||
request :delete_group
|
||||
request :get_group_state
|
||||
request :pause_group_state
|
||||
request :resume_group_state
|
||||
|
||||
request :get_group_config
|
||||
request :update_group_config
|
||||
request :get_launch_config
|
||||
request :update_launch_config
|
||||
|
||||
request :list_policies
|
||||
request :create_policy
|
||||
request :get_policy
|
||||
request :update_policy
|
||||
request :delete_policy
|
||||
request :execute_policy
|
||||
|
||||
request :execute_anonymous_webhook
|
||||
|
||||
request :get_webhook
|
||||
request :list_webhooks
|
||||
request :create_webhook
|
||||
request :update_webhook
|
||||
request :delete_webhook
|
||||
|
||||
class Mock < Fog::Rackspace::Service
|
||||
def initialize(options)
|
||||
@rackspace_api_key = options[:rackspace_api_key]
|
||||
end
|
||||
|
||||
def request(params)
|
||||
Fog::Mock.not_implemented
|
||||
end
|
||||
end
|
||||
|
||||
class Real < Fog::Rackspace::Service
|
||||
def initialize(options = {})
|
||||
@options = options
|
||||
@options[:connection_options] ||= {}
|
||||
@options[:persistent] ||= false
|
||||
|
||||
authenticate
|
||||
|
||||
@connection = Fog::Core::Connection.new(endpoint_uri.to_s, @options[:persistent], @options[:connection_options])
|
||||
end
|
||||
|
||||
def request(params, parse_json = true, &block)
|
||||
super(params, parse_json, &block)
|
||||
rescue Excon::Errors::NotFound => error
|
||||
raise NotFound.slurp(error, self)
|
||||
rescue Excon::Errors::BadRequest => error
|
||||
raise BadRequest.slurp(error, self)
|
||||
rescue Excon::Errors::InternalServerError => error
|
||||
raise InternalServerError.slurp(error, self)
|
||||
rescue Excon::Errors::HTTPStatusError => error
|
||||
raise ServiceError.slurp(error, self)
|
||||
end
|
||||
|
||||
def endpoint_uri(service_endpoint_url=nil)
|
||||
@uri = super(@options[:rackspace_auto_scale_url], :rackspace_auto_scale_url)
|
||||
end
|
||||
|
||||
def authenticate(options={})
|
||||
super(select_options([:rackspace_username, :rackspace_api_key, :rackspace_auth_url, :connection_options]))
|
||||
end
|
||||
|
||||
def service_name
|
||||
:autoscale
|
||||
end
|
||||
|
||||
def request_id_header
|
||||
"x-response-id"
|
||||
end
|
||||
|
||||
def region
|
||||
@options[:rackspace_region]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
175
lib/fog/rackspace/block_storage.rb
Normal file
175
lib/fog/rackspace/block_storage.rb
Normal file
|
@ -0,0 +1,175 @@
|
|||
require 'fog/rackspace/core'
|
||||
|
||||
module Fog
|
||||
module Rackspace
|
||||
class BlockStorage < Fog::Service
|
||||
include Fog::Rackspace::Errors
|
||||
|
||||
class IdentifierTaken < Fog::Errors::Error; end
|
||||
class ServiceError < Fog::Rackspace::Errors::ServiceError; end
|
||||
class InternalServerError < Fog::Rackspace::Errors::InternalServerError; end
|
||||
class BadRequest < Fog::Rackspace::Errors::BadRequest; end
|
||||
|
||||
DFW_ENDPOINT = 'https://dfw.blockstorage.api.rackspacecloud.com/v1'
|
||||
LON_ENDPOINT = 'https://lon.blockstorage.api.rackspacecloud.com/v1'
|
||||
ORD_ENDPOINT = 'https://ord.blockstorage.api.rackspacecloud.com/v1'
|
||||
|
||||
requires :rackspace_api_key, :rackspace_username
|
||||
recognizes :rackspace_auth_url
|
||||
recognizes :rackspace_endpoint
|
||||
recognizes :rackspace_region
|
||||
recognizes :rackspace_block_storage_url
|
||||
|
||||
model_path 'fog/rackspace/models/block_storage'
|
||||
model :volume
|
||||
collection :volumes
|
||||
|
||||
model :volume_type
|
||||
collection :volume_types
|
||||
|
||||
model :snapshot
|
||||
collection :snapshots
|
||||
|
||||
request_path 'fog/rackspace/requests/block_storage'
|
||||
request :create_volume
|
||||
request :delete_volume
|
||||
request :get_volume
|
||||
request :list_volumes
|
||||
|
||||
request :get_volume_type
|
||||
request :list_volume_types
|
||||
|
||||
request :create_snapshot
|
||||
request :delete_snapshot
|
||||
request :get_snapshot
|
||||
request :list_snapshots
|
||||
|
||||
class Mock < Fog::Rackspace::Service
|
||||
include Fog::Rackspace::MockData
|
||||
|
||||
def initialize(options = {})
|
||||
@rackspace_api_key = options[:rackspace_api_key]
|
||||
end
|
||||
|
||||
def request(params)
|
||||
Fog::Mock.not_implemented
|
||||
end
|
||||
|
||||
def response(params={})
|
||||
body = params[:body] || {}
|
||||
status = params[:status] || 200
|
||||
headers = params[:headers] || {}
|
||||
|
||||
response = Excon::Response.new(:body => body, :headers => headers, :status => status)
|
||||
if params.key?(:expects) && ![*params[:expects]].include?(response.status)
|
||||
raise(Excon::Errors.status_error(params, response))
|
||||
else response
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Real < Fog::Rackspace::Service
|
||||
def initialize(options = {})
|
||||
@rackspace_api_key = options[:rackspace_api_key]
|
||||
@rackspace_username = options[:rackspace_username]
|
||||
@rackspace_auth_url = options[:rackspace_auth_url]
|
||||
@rackspace_must_reauthenticate = false
|
||||
@connection_options = options[:connection_options] || {}
|
||||
setup_custom_endpoint(options)
|
||||
|
||||
authenticate
|
||||
|
||||
deprecation_warnings(options)
|
||||
|
||||
@persistent = options[:persistent] || false
|
||||
@connection = Fog::Core::Connection.new(endpoint_uri.to_s, @persistent, @connection_options)
|
||||
end
|
||||
|
||||
def request(params, parse_json = true)
|
||||
super
|
||||
rescue Excon::Errors::NotFound => error
|
||||
raise NotFound.slurp(error, self)
|
||||
rescue Excon::Errors::BadRequest => error
|
||||
raise BadRequest.slurp(error, self)
|
||||
rescue Excon::Errors::InternalServerError => error
|
||||
raise InternalServerError.slurp(error, self)
|
||||
rescue Excon::Errors::HTTPStatusError => error
|
||||
raise ServiceError.slurp(error, self)
|
||||
end
|
||||
|
||||
def authenticate(options={})
|
||||
super({
|
||||
:rackspace_api_key => @rackspace_api_key,
|
||||
:rackspace_username => @rackspace_username,
|
||||
:rackspace_auth_url => @rackspace_auth_url,
|
||||
:connection_options => @connection_options
|
||||
})
|
||||
end
|
||||
|
||||
def service_name
|
||||
:cloudBlockStorage
|
||||
end
|
||||
|
||||
def region
|
||||
@rackspace_region
|
||||
end
|
||||
|
||||
def request_id_header
|
||||
"X-Compute-Request-Id"
|
||||
end
|
||||
|
||||
def endpoint_uri(service_endpoint_url=nil)
|
||||
@uri = super(@rackspace_endpoint || service_endpoint_url, :rackspace_block_storage_url)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def setup_custom_endpoint(options)
|
||||
@rackspace_endpoint = Fog::Rackspace.normalize_url(options[:rackspace_block_storage_url] || options[:rackspace_endpoint])
|
||||
|
||||
if v2_authentication?
|
||||
case @rackspace_endpoint
|
||||
when DFW_ENDPOINT
|
||||
@rackspace_endpoint = nil
|
||||
@rackspace_region = :dfw
|
||||
when ORD_ENDPOINT
|
||||
@rackspace_endpoint = nil
|
||||
@rackspace_region = :ord
|
||||
when LON_ENDPOINT
|
||||
@rackspace_endpoint = nil
|
||||
@rackspace_region = :lon
|
||||
else
|
||||
@rackspace_region = options[:rackspace_region]
|
||||
end
|
||||
else
|
||||
#if we are using auth1 and the endpoint is not set, default to DFW_ENDPOINT for historical reasons
|
||||
@rackspace_endpoint ||= DFW_ENDPOINT
|
||||
end
|
||||
end
|
||||
|
||||
def deprecation_warnings(options)
|
||||
Fog::Logger.deprecation("The :rackspace_endpoint option is deprecated. Please use :rackspace_block_storage_url for custom endpoints") if options[:rackspace_endpoint]
|
||||
|
||||
if [DFW_ENDPOINT, ORD_ENDPOINT, LON_ENDPOINT].include?(@rackspace_endpoint) && v2_authentication?
|
||||
regions = @identity_service.service_catalog.display_service_regions(service_name)
|
||||
Fog::Logger.deprecation("Please specify region using :rackspace_region rather than :rackspace_endpoint. Valid region for :rackspace_region are #{regions}.")
|
||||
end
|
||||
end
|
||||
|
||||
def append_tenant_v1(credentials)
|
||||
account_id = credentials['X-Server-Management-Url'].match(/.*\/([\d]+)$/)[1]
|
||||
|
||||
endpoint = @rackspace_endpoint || credentials['X-Server-Management-Url'] || DFW_ENDPOINT
|
||||
@uri = URI.parse(endpoint)
|
||||
@uri.path = "#{@uri.path}/#{account_id}"
|
||||
end
|
||||
|
||||
def authenticate_v1(options)
|
||||
credentials = Fog::Rackspace.authenticate(options, @connection_options)
|
||||
append_tenant_v1 credentials
|
||||
@auth_token = credentials['X-Auth-Token']
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
198
lib/fog/rackspace/cdn.rb
Normal file
198
lib/fog/rackspace/cdn.rb
Normal file
|
@ -0,0 +1,198 @@
|
|||
require 'fog/rackspace/core'
|
||||
|
||||
module Fog
|
||||
module CDN
|
||||
class Rackspace < Fog::Service
|
||||
requires :rackspace_api_key, :rackspace_username
|
||||
recognizes :rackspace_auth_url, :persistent, :rackspace_cdn_ssl, :rackspace_region, :rackspace_cdn_url
|
||||
|
||||
request_path 'fog/rackspace/requests/cdn'
|
||||
request :get_containers
|
||||
request :head_container
|
||||
request :post_container
|
||||
request :put_container
|
||||
request :delete_object
|
||||
|
||||
module Base
|
||||
URI_HEADERS = {
|
||||
"X-Cdn-Ios-Uri" => :ios_uri,
|
||||
"X-Cdn-Uri" => :uri,
|
||||
"X-Cdn-Streaming-Uri" => :streaming_uri,
|
||||
"X-Cdn-Ssl-Uri" => :ssl_uri
|
||||
}.freeze
|
||||
|
||||
def apply_options(options)
|
||||
# api_key and username missing from instance variable sets
|
||||
@rackspace_api_key = options[:rackspace_api_key]
|
||||
@rackspace_username = options[:rackspace_username]
|
||||
|
||||
@connection_options = options[:connection_options] || {}
|
||||
@rackspace_auth_url = options[:rackspace_auth_url]
|
||||
@rackspace_cdn_url = options[:rackspace_cdn_url]
|
||||
@rackspace_region = options[:rackspace_region]
|
||||
end
|
||||
|
||||
def service_name
|
||||
:cloudFilesCDN
|
||||
end
|
||||
|
||||
def region
|
||||
@rackspace_region
|
||||
end
|
||||
|
||||
def request_id_header
|
||||
"X-Trans-Id"
|
||||
end
|
||||
|
||||
# Returns true if CDN service is enabled
|
||||
# @return [Boolean]
|
||||
def enabled?
|
||||
@enabled
|
||||
end
|
||||
|
||||
def endpoint_uri(service_endpoint_url=nil)
|
||||
@uri = super(@rackspace_cdn_url || service_endpoint_url, :rackspace_cdn_url)
|
||||
end
|
||||
|
||||
# Publish container to CDN
|
||||
# @param [Fog::Storage::Rackspace::Directory] container directory to publish
|
||||
# @param [Boolean] publish If true directory is published. If false directory is unpublished.
|
||||
# @return [Hash] hash containing urls for published container
|
||||
# @raise [Fog::Storage::Rackspace::NotFound] - HTTP 404
|
||||
# @raise [Fog::Storage::Rackspace::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Storage::Rackspace::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Storage::Rackspace::ServiceError]
|
||||
def publish_container(container, publish = true)
|
||||
enabled = publish ? 'True' : 'False'
|
||||
response = put_container(container.key, 'X-Cdn-Enabled' => enabled)
|
||||
return {} unless publish
|
||||
urls_from_headers(response.headers)
|
||||
end
|
||||
|
||||
# Returns hash of urls for container
|
||||
# @param [Fog::Storage::Rackspace::Directory] container to retrieve urls for
|
||||
# @return [Hash] hash containing urls for published container
|
||||
# @raise [Fog::Storage::Rackspace::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Storage::Rackspace::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Storage::Rackspace::ServiceError]
|
||||
# @note If unable to find container or container is not published this method will return an empty hash.
|
||||
def urls(container)
|
||||
begin
|
||||
response = head_container(container.key)
|
||||
return {} unless response.headers['X-Cdn-Enabled'] == 'True'
|
||||
urls_from_headers response.headers
|
||||
rescue Fog::Service::NotFound
|
||||
{}
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def urls_from_headers(headers)
|
||||
h = {}
|
||||
URI_HEADERS.keys.each do | header |
|
||||
key = URI_HEADERS[header]
|
||||
h[key] = headers[header]
|
||||
end
|
||||
h
|
||||
end
|
||||
end
|
||||
|
||||
class Mock < Fog::Rackspace::Service
|
||||
include Base
|
||||
|
||||
def self.data
|
||||
@data ||= Hash.new do |hash, key|
|
||||
hash[key] = {}
|
||||
end
|
||||
end
|
||||
|
||||
def self.reset
|
||||
@data = nil
|
||||
end
|
||||
|
||||
def initialize(options={})
|
||||
apply_options(options)
|
||||
authenticate(options)
|
||||
@enabled = !! endpoint_uri
|
||||
end
|
||||
|
||||
def data
|
||||
self.class.data[@rackspace_username]
|
||||
end
|
||||
|
||||
def purge(object)
|
||||
return true if object.is_a? Fog::Storage::Rackspace::File
|
||||
raise Fog::Errors::NotImplemented.new("#{object.class} does not support CDN purging") if object
|
||||
end
|
||||
|
||||
def reset_data
|
||||
self.class.data.delete(@rackspace_username)
|
||||
end
|
||||
end
|
||||
|
||||
class Real < Fog::Rackspace::Service
|
||||
include Base
|
||||
|
||||
def initialize(options={})
|
||||
apply_options(options)
|
||||
authenticate(options)
|
||||
@enabled = false
|
||||
@persistent = options[:persistent] || false
|
||||
|
||||
if endpoint_uri
|
||||
@connection = Fog::Core::Connection.new(endpoint_uri.to_s, @persistent, @connection_options)
|
||||
@enabled = true
|
||||
end
|
||||
end
|
||||
|
||||
# Resets CDN connection
|
||||
def reload
|
||||
@cdn_connection.reset
|
||||
end
|
||||
|
||||
# Purges File
|
||||
# @param [Fog::Storage::Rackspace::File] file to be purged from the CDN
|
||||
# @raise [Fog::Errors::NotImplemented] returned when non file parameters are specified
|
||||
def purge(file)
|
||||
unless file.is_a? Fog::Storage::Rackspace::File
|
||||
raise Fog::Errors::NotImplemented.new("#{object.class} does not support CDN purging") if object
|
||||
end
|
||||
|
||||
delete_object file.directory.key, file.key
|
||||
true
|
||||
end
|
||||
|
||||
def request(params, parse_json = true)
|
||||
super
|
||||
rescue Excon::Errors::NotFound => error
|
||||
raise Fog::Storage::Rackspace::NotFound.slurp(error, self)
|
||||
rescue Excon::Errors::BadRequest => error
|
||||
raise Fog::Storage::Rackspace::BadRequest.slurp(error, self)
|
||||
rescue Excon::Errors::InternalServerError => error
|
||||
raise Fog::Storage::Rackspace::InternalServerError.slurp(error, self)
|
||||
rescue Excon::Errors::HTTPStatusError => error
|
||||
raise Fog::Storage::Rackspace::ServiceError.slurp(error, self)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def authenticate_v1(options)
|
||||
credentials = Fog::Rackspace.authenticate(options, @connection_options)
|
||||
endpoint_uri credentials['X-CDN-Management-Url']
|
||||
@auth_token = credentials['X-Auth-Token']
|
||||
end
|
||||
|
||||
# Fix for invalid auth_token, likely after 24 hours.
|
||||
def authenticate(options={})
|
||||
super({
|
||||
:rackspace_api_key => @rackspace_api_key,
|
||||
:rackspace_username => @rackspace_username,
|
||||
:rackspace_auth_url => @rackspace_auth_url,
|
||||
:connection_options => @connection_options
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
256
lib/fog/rackspace/compute.rb
Normal file
256
lib/fog/rackspace/compute.rb
Normal file
|
@ -0,0 +1,256 @@
|
|||
require 'fog/rackspace/core'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class Rackspace < Fog::Service
|
||||
include Fog::Rackspace::Errors
|
||||
|
||||
class ServiceError < Fog::Rackspace::Errors::ServiceError; end
|
||||
class InternalServerError < Fog::Rackspace::Errors::InternalServerError; end
|
||||
class BadRequest < Fog::Rackspace::Errors::BadRequest; end
|
||||
|
||||
requires :rackspace_api_key, :rackspace_username
|
||||
recognizes :rackspace_auth_url, :rackspace_servicenet, :persistent
|
||||
recognizes :rackspace_auth_token, :rackspace_management_url, :rackspace_compute_v1_url, :rackspace_region
|
||||
|
||||
model_path 'fog/rackspace/models/compute'
|
||||
model :flavor
|
||||
collection :flavors
|
||||
model :image
|
||||
collection :images
|
||||
model :server
|
||||
collection :servers
|
||||
|
||||
request_path 'fog/rackspace/requests/compute'
|
||||
request :confirm_resized_server
|
||||
request :create_image
|
||||
request :create_server
|
||||
request :delete_image
|
||||
request :delete_server
|
||||
request :get_flavor_details
|
||||
request :get_image_details
|
||||
request :get_server_details
|
||||
request :list_addresses
|
||||
request :list_private_addresses
|
||||
request :list_public_addresses
|
||||
request :list_flavors
|
||||
request :list_flavors_detail
|
||||
request :list_images
|
||||
request :list_images_detail
|
||||
request :list_servers
|
||||
request :list_servers_detail
|
||||
request :reboot_server
|
||||
request :revert_resized_server
|
||||
request :resize_server
|
||||
request :server_action
|
||||
request :update_server
|
||||
|
||||
class Mock < Fog::Rackspace::Service
|
||||
def self.data
|
||||
@data ||= Hash.new do |hash, key|
|
||||
hash[key] = {
|
||||
:last_modified => {
|
||||
:images => {},
|
||||
:servers => {}
|
||||
},
|
||||
:servers => {},
|
||||
:images => {
|
||||
112 =>
|
||||
{'id' => 112,
|
||||
'status' => "ACTIVE",
|
||||
'updated' => "2011-04-21T10:24:01-05:00",
|
||||
'name' => "Ubuntu 10.04 LTS"},
|
||||
100 =>
|
||||
{'id' => 100,
|
||||
'status' => "ACTIVE",
|
||||
'updated' => "2011-09-12T09:09:23-05:00",
|
||||
'name' => "Arch 2011.10"},
|
||||
31 =>
|
||||
{'id' => 31,
|
||||
'status' => "ACTIVE",
|
||||
'updated' => "2010-01-26T12:07:44-06:00",
|
||||
'name' => "Windows Server 2008 SP2 x86"},
|
||||
108 =>
|
||||
{'id' => 108,
|
||||
'status' => "ACTIVE",
|
||||
'updated' => "2011-11-01T08:32:30-05:00",
|
||||
'name' => "Gentoo 11.0"},
|
||||
109 =>
|
||||
{'id' => 109,
|
||||
'status' => "ACTIVE",
|
||||
'updated' => "2011-11-03T06:28:56-05:00",
|
||||
'name' => "openSUSE 12"},
|
||||
89 =>
|
||||
{'id' => 89,
|
||||
'status' => "ACTIVE",
|
||||
'updated' => "2011-10-04T08:39:34-05:00",
|
||||
'name' => "Windows Server 2008 R2 x64 - SQL2K8R2 Web"},
|
||||
24 =>
|
||||
{'id' => 24,
|
||||
'status' => "ACTIVE",
|
||||
'updated' => "2010-01-26T12:07:04-06:00",
|
||||
'name' => "Windows Server 2008 SP2 x64"},
|
||||
110 =>
|
||||
{'id' => 110,
|
||||
'status' => "ACTIVE",
|
||||
'updated' => "2011-08-17T05:11:30-05:00",
|
||||
'name' => "Red Hat Enterprise Linux 5.5"},
|
||||
57 =>
|
||||
{'id' => 57,
|
||||
'status' => "ACTIVE",
|
||||
'updated' => "2010-09-17T07:16:25-05:00",
|
||||
'name' => "Windows Server 2008 SP2 x64 - MSSQL2K8R2"},
|
||||
85 =>
|
||||
{'id' => 85,
|
||||
'status' => "ACTIVE",
|
||||
'updated' => "2010-01-26T12:07:17-06:00",
|
||||
'name' => "Windows Server 2008 R2 x64"},
|
||||
111 =>
|
||||
{'id' => 111,
|
||||
'status' => "ACTIVE",
|
||||
'updated' => "2011-09-12T10:53:12-05:00",
|
||||
'name' => "Red Hat Enterprise Linux 6"},
|
||||
120 =>
|
||||
{'id' => 120,
|
||||
'status' => "ACTIVE",
|
||||
'updated' => "2012-01-03T04:39:05-06:00",
|
||||
'name' => "Fedora 16"},
|
||||
119 =>
|
||||
{'id' => 119,
|
||||
'status' => "ACTIVE",
|
||||
'updated' => "2011-11-03T08:55:15-05:00",
|
||||
'name' => "Ubuntu 11.10"},
|
||||
116 =>
|
||||
{'id' => 116,
|
||||
'status' => "ACTIVE",
|
||||
'updated' => "2011-08-17T05:11:30-05:00",
|
||||
'name' => "Fedora 15"},
|
||||
56 =>
|
||||
{'id' => 56,
|
||||
'status' => "ACTIVE",
|
||||
'updated' => "2010-09-17T07:12:56-05:00",
|
||||
'name' => "Windows Server 2008 SP2 x86 - MSSQL2K8R2"},
|
||||
114 =>
|
||||
{'id' => 114,
|
||||
'status' => "ACTIVE",
|
||||
'updated' => "2011-08-17T05:11:30-05:00",
|
||||
'name' => "CentOS 5.6"},
|
||||
86 =>
|
||||
{'id' => 86,
|
||||
'status' => "ACTIVE",
|
||||
'updated' => "2010-09-17T07:19:20-05:00",
|
||||
'name' => "Windows Server 2008 R2 x64 - MSSQL2K8R2"},
|
||||
115 =>
|
||||
{'id' => 115,
|
||||
'status' => "ACTIVE",
|
||||
'updated' => "2011-08-17T05:11:30-05:00",
|
||||
'name' => "Ubuntu 11.04"},
|
||||
103 =>
|
||||
{'id' => 103,
|
||||
'status' => "ACTIVE",
|
||||
'updated' => "2011-08-17T05:11:30-05:00",
|
||||
'name' => "Debian 5 (Lenny)"},
|
||||
104 =>
|
||||
{'id' => 104,
|
||||
'status' => "ACTIVE",
|
||||
'updated' => "2011-08-17T05:11:30-05:00",
|
||||
'name' => "Debian 6 (Squeeze)"},
|
||||
118 =>
|
||||
{'id' => 118,
|
||||
'status' => "ACTIVE",
|
||||
'updated' => "2011-08-17T05:11:30-05:00",
|
||||
'name' => "CentOS 6.0"}
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def self.reset
|
||||
@data = nil
|
||||
end
|
||||
|
||||
def initialize(options={})
|
||||
@rackspace_username = options[:rackspace_username]
|
||||
end
|
||||
|
||||
def data
|
||||
self.class.data[@rackspace_username]
|
||||
end
|
||||
|
||||
def reset_data
|
||||
self.class.data.delete(@rackspace_username)
|
||||
end
|
||||
end
|
||||
|
||||
class Real < Fog::Rackspace::Service
|
||||
def initialize(options={})
|
||||
@rackspace_api_key = options[:rackspace_api_key]
|
||||
@rackspace_username = options[:rackspace_username]
|
||||
@rackspace_auth_url = options[:rackspace_auth_url]
|
||||
@rackspace_servicenet = options[:rackspace_servicenet]
|
||||
@rackspace_auth_token = options[:rackspace_auth_token]
|
||||
@rackspace_endpoint = Fog::Rackspace.normalize_url(options[:rackspace_compute_v1_url] || options[:rackspace_management_url])
|
||||
@connection_options = options[:connection_options] || {}
|
||||
authenticate
|
||||
Excon.defaults[:ssl_verify_peer] = false if service_net?
|
||||
@persistent = options[:persistent] || false
|
||||
@connection = Fog::Core::Connection.new(endpoint_uri.to_s, @persistent, @connection_options)
|
||||
end
|
||||
|
||||
def reload
|
||||
@connection.reset
|
||||
end
|
||||
|
||||
def request(params, parse_json = true)
|
||||
super
|
||||
rescue Excon::Errors::NotFound => error
|
||||
raise NotFound.slurp(error, self)
|
||||
rescue Excon::Errors::BadRequest => error
|
||||
raise BadRequest.slurp(error, self)
|
||||
rescue Excon::Errors::InternalServerError => error
|
||||
raise InternalServerError.slurp(error, self)
|
||||
rescue Excon::Errors::HTTPStatusError => error
|
||||
raise ServiceError.slurp(error, self)
|
||||
end
|
||||
|
||||
def service_net?
|
||||
@rackspace_servicenet == true
|
||||
end
|
||||
|
||||
def authenticate(options={})
|
||||
super({
|
||||
:rackspace_api_key => @rackspace_api_key,
|
||||
:rackspace_username => @rackspace_username,
|
||||
:rackspace_auth_url => @rackspace_auth_url,
|
||||
:connection_options => @connection_options
|
||||
})
|
||||
end
|
||||
|
||||
def service_name
|
||||
:cloudServers
|
||||
end
|
||||
|
||||
def region
|
||||
@rackspace_region
|
||||
end
|
||||
|
||||
def endpoint_uri(service_endpoint_url=nil)
|
||||
return @uri if @uri
|
||||
super(@rackspace_endpoint || service_endpoint_url, :rackspace_compute_v1_url)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def deprecation_warnings(options)
|
||||
Fog::Logger.deprecation("The :rackspace_management_url option is deprecated. Please use :rackspace_compute_v1_url for custom endpoints") if options[:rackspace_management_url]
|
||||
end
|
||||
|
||||
def authenticate_v1(options)
|
||||
credentials = Fog::Rackspace.authenticate(options, @connection_options)
|
||||
endpoint_uri credentials['X-Server-Management-Url']
|
||||
@auth_token = credentials['X-Auth-Token']
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
250
lib/fog/rackspace/compute_v2.rb
Normal file
250
lib/fog/rackspace/compute_v2.rb
Normal file
|
@ -0,0 +1,250 @@
|
|||
require 'fog/rackspace/core'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class RackspaceV2 < Fog::Service
|
||||
include Fog::Rackspace::Errors
|
||||
|
||||
class ServiceError < Fog::Rackspace::Errors::ServiceError; end
|
||||
class InternalServerError < Fog::Rackspace::Errors::InternalServerError; end
|
||||
class BadRequest < Fog::Rackspace::Errors::BadRequest; end
|
||||
|
||||
class InvalidStateException < ::RuntimeError
|
||||
attr_reader :desired_state
|
||||
attr_reader :current_state
|
||||
|
||||
def initialize(desired_state, current_state)
|
||||
@desired_state = desired_state
|
||||
@current_state = current_state
|
||||
end
|
||||
end
|
||||
|
||||
class InvalidServerStateException < InvalidStateException
|
||||
def to_s
|
||||
"Server should have transitioned to '#{desired_state}' not '#{current_state}'"
|
||||
end
|
||||
end
|
||||
|
||||
class InvalidImageStateException < InvalidStateException
|
||||
def to_s
|
||||
"Image should have transitioned to '#{desired_state}' not '#{current_state}'"
|
||||
end
|
||||
end
|
||||
|
||||
DFW_ENDPOINT = 'https://dfw.servers.api.rackspacecloud.com/v2'
|
||||
ORD_ENDPOINT = 'https://ord.servers.api.rackspacecloud.com/v2'
|
||||
LON_ENDPOINT = 'https://lon.servers.api.rackspacecloud.com/v2'
|
||||
|
||||
requires :rackspace_username, :rackspace_api_key
|
||||
recognizes :rackspace_endpoint
|
||||
recognizes :rackspace_auth_url
|
||||
recognizes :rackspace_auth_token
|
||||
recognizes :rackspace_region
|
||||
recognizes :rackspace_compute_url
|
||||
|
||||
model_path 'fog/rackspace/models/compute_v2'
|
||||
|
||||
model :server
|
||||
collection :servers
|
||||
|
||||
model :flavor
|
||||
collection :flavors
|
||||
|
||||
model :image
|
||||
collection :images
|
||||
|
||||
model :attachment
|
||||
collection :attachments
|
||||
|
||||
model :network
|
||||
collection :networks
|
||||
|
||||
model :key_pair
|
||||
collection :key_pairs
|
||||
|
||||
model :virtual_interface
|
||||
collection :virtual_interfaces
|
||||
|
||||
request_path 'fog/rackspace/requests/compute_v2'
|
||||
request :list_servers
|
||||
request :get_server
|
||||
request :create_server
|
||||
request :update_server
|
||||
request :delete_server
|
||||
request :change_server_password
|
||||
request :reboot_server
|
||||
request :rebuild_server
|
||||
request :resize_server
|
||||
request :confirm_resize_server
|
||||
request :revert_resize_server
|
||||
request :rescue_server
|
||||
request :unrescue_server
|
||||
request :list_addresses
|
||||
request :list_addresses_by_network
|
||||
|
||||
request :create_image
|
||||
request :list_images
|
||||
request :list_images_detail
|
||||
request :get_image
|
||||
request :delete_image
|
||||
|
||||
request :list_flavors
|
||||
request :list_flavors_detail
|
||||
request :get_flavor
|
||||
|
||||
request :attach_volume
|
||||
request :get_attachment
|
||||
request :list_attachments
|
||||
request :delete_attachment
|
||||
|
||||
request :list_metadata
|
||||
request :set_metadata
|
||||
request :update_metadata
|
||||
request :get_metadata_item
|
||||
request :set_metadata_item
|
||||
request :delete_metadata_item
|
||||
|
||||
request :list_networks
|
||||
request :get_network
|
||||
request :create_network
|
||||
request :delete_network
|
||||
|
||||
request :list_keypairs
|
||||
request :create_keypair
|
||||
request :delete_keypair
|
||||
request :get_keypair
|
||||
|
||||
request :list_virtual_interfaces
|
||||
request :create_virtual_interface
|
||||
request :delete_virtual_interface
|
||||
|
||||
class Mock < Fog::Rackspace::Service
|
||||
include Fog::Rackspace::MockData
|
||||
|
||||
def initialize(options)
|
||||
@rackspace_api_key = options[:rackspace_api_key]
|
||||
end
|
||||
|
||||
def request(params)
|
||||
Fog::Mock.not_implemented
|
||||
end
|
||||
|
||||
def response(params={})
|
||||
body = params[:body] || {}
|
||||
status = params[:status] || 200
|
||||
headers = params[:headers] || {}
|
||||
|
||||
response = Excon::Response.new(:body => body, :headers => headers, :status => status)
|
||||
if params.key?(:expects) && ![*params[:expects]].include?(response.status)
|
||||
raise(Excon::Errors.status_error(params, response))
|
||||
else response
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Real < Fog::Rackspace::Service
|
||||
def initialize(options = {})
|
||||
@rackspace_api_key = options[:rackspace_api_key]
|
||||
@rackspace_username = options[:rackspace_username]
|
||||
@rackspace_auth_url = options[:rackspace_auth_url]
|
||||
setup_custom_endpoint(options)
|
||||
@rackspace_must_reauthenticate = false
|
||||
@connection_options = options[:connection_options] || {}
|
||||
|
||||
authenticate
|
||||
|
||||
deprecation_warnings(options)
|
||||
|
||||
@persistent = options[:persistent] || false
|
||||
@connection = Fog::Core::Connection.new(endpoint_uri.to_s, @persistent, @connection_options)
|
||||
end
|
||||
|
||||
def request(params, parse_json = true)
|
||||
super
|
||||
rescue Excon::Errors::NotFound => error
|
||||
raise NotFound.slurp(error, self)
|
||||
rescue Excon::Errors::BadRequest => error
|
||||
raise BadRequest.slurp(error, self)
|
||||
rescue Excon::Errors::InternalServerError => error
|
||||
raise InternalServerError.slurp(error, self)
|
||||
rescue Excon::Errors::HTTPStatusError => error
|
||||
raise ServiceError.slurp(error, self)
|
||||
end
|
||||
|
||||
def authenticate(options={})
|
||||
super({
|
||||
:rackspace_api_key => @rackspace_api_key,
|
||||
:rackspace_username => @rackspace_username,
|
||||
:rackspace_auth_url => @rackspace_auth_url,
|
||||
:connection_options => @connection_options
|
||||
})
|
||||
end
|
||||
|
||||
def service_name
|
||||
:cloudServersOpenStack
|
||||
end
|
||||
|
||||
def request_id_header
|
||||
"x-compute-request-id"
|
||||
end
|
||||
|
||||
def region
|
||||
@rackspace_region
|
||||
end
|
||||
|
||||
def endpoint_uri(service_endpoint_url=nil)
|
||||
@uri = super(@rackspace_endpoint || service_endpoint_url, :rackspace_compute_url)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def setup_custom_endpoint(options)
|
||||
@rackspace_endpoint = Fog::Rackspace.normalize_url(options[:rackspace_compute_url] || options[:rackspace_endpoint])
|
||||
|
||||
if v2_authentication?
|
||||
case @rackspace_endpoint
|
||||
when DFW_ENDPOINT
|
||||
@rackspace_endpoint = nil
|
||||
@rackspace_region = :dfw
|
||||
when ORD_ENDPOINT
|
||||
@rackspace_endpoint = nil
|
||||
@rackspace_region = :ord
|
||||
when LON_ENDPOINT
|
||||
@rackspace_endpoint = nil
|
||||
@rackspace_region = :lon
|
||||
else
|
||||
# we are actually using a custom endpoint
|
||||
@rackspace_region = options[:rackspace_region]
|
||||
end
|
||||
else
|
||||
#if we are using auth1 and the endpoint is not set, default to DFW_ENDPOINT for historical reasons
|
||||
@rackspace_endpoint ||= DFW_ENDPOINT
|
||||
end
|
||||
end
|
||||
|
||||
def deprecation_warnings(options)
|
||||
Fog::Logger.deprecation("The :rackspace_endpoint option is deprecated. Please use :rackspace_compute_url for custom endpoints") if options[:rackspace_endpoint]
|
||||
|
||||
if [DFW_ENDPOINT, ORD_ENDPOINT, LON_ENDPOINT].include?(@rackspace_endpoint) && v2_authentication?
|
||||
regions = @identity_service.service_catalog.display_service_regions(service_name)
|
||||
Fog::Logger.deprecation("Please specify region using :rackspace_region rather than :rackspace_endpoint. Valid regions for :rackspace_region are #{regions}.")
|
||||
end
|
||||
end
|
||||
|
||||
def append_tenant_v1(credentials)
|
||||
account_id = credentials['X-Server-Management-Url'].match(/.*\/([\d]+)$/)[1]
|
||||
|
||||
endpoint = @rackspace_endpoint || credentials['X-Server-Management-Url'] || DFW_ENDPOINT
|
||||
@uri = URI.parse(endpoint)
|
||||
@uri.path = "#{@uri.path}/#{account_id}"
|
||||
end
|
||||
|
||||
def authenticate_v1(options)
|
||||
credentials = Fog::Rackspace.authenticate(options, @connection_options)
|
||||
append_tenant_v1 credentials
|
||||
@auth_token = credentials['X-Auth-Token']
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
147
lib/fog/rackspace/core.rb
Normal file
147
lib/fog/rackspace/core.rb
Normal file
|
@ -0,0 +1,147 @@
|
|||
require 'fog/core'
|
||||
require 'fog/json'
|
||||
require 'fog/rackspace/mock_data'
|
||||
require 'fog/rackspace/service'
|
||||
require 'fog/rackspace/errors'
|
||||
|
||||
module Fog
|
||||
module Rackspace
|
||||
extend Fog::Provider
|
||||
|
||||
US_AUTH_ENDPOINT = 'https://identity.api.rackspacecloud.com/v2.0' unless defined? US_AUTH_ENDPOINT
|
||||
UK_AUTH_ENDPOINT = 'https://lon.identity.api.rackspacecloud.com/v2.0' unless defined? UK_AUTH_ENDPOINT
|
||||
|
||||
module Errors
|
||||
class ServiceError < Fog::Errors::Error
|
||||
attr_reader :response_data, :status_code, :transaction_id
|
||||
|
||||
def to_s
|
||||
status = status_code ? "HTTP #{status_code}" : "HTTP <Unknown>"
|
||||
"[#{status} | #{transaction_id}] #{super}"
|
||||
end
|
||||
|
||||
def self.slurp(error, service=nil)
|
||||
data = nil
|
||||
message = nil
|
||||
status_code = nil
|
||||
|
||||
if error.response
|
||||
status_code = error.response.status
|
||||
unless error.response.body.empty?
|
||||
begin
|
||||
data = Fog::JSON.decode(error.response.body)
|
||||
message = extract_message(data)
|
||||
rescue => e
|
||||
Fog::Logger.warning("Received exception '#{e}' while decoding>> #{error.response.body}")
|
||||
message = error.response.body
|
||||
data = error.response.body
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
new_error = super(error, message)
|
||||
new_error.instance_variable_set(:@response_data, data)
|
||||
new_error.instance_variable_set(:@status_code, status_code)
|
||||
new_error.set_transaction_id(error, service)
|
||||
new_error
|
||||
end
|
||||
|
||||
def set_transaction_id(error, service)
|
||||
return unless service && service.respond_to?(:request_id_header) && error.response
|
||||
@transaction_id = error.response.headers[service.request_id_header]
|
||||
end
|
||||
|
||||
def self.extract_message(data)
|
||||
if data.is_a?(Hash)
|
||||
message = data.values.first['message'] if data.values.first.is_a?(Hash)
|
||||
message ||= data['message']
|
||||
end
|
||||
message || data.inspect
|
||||
end
|
||||
end
|
||||
|
||||
class InternalServerError < ServiceError; end
|
||||
class Conflict < ServiceError; end
|
||||
class ServiceUnavailable < ServiceError; end
|
||||
class MethodNotAllowed < ServiceError; end
|
||||
class BadRequest < ServiceError
|
||||
attr_reader :validation_errors
|
||||
|
||||
def to_s
|
||||
"#{super} - #{validation_errors}"
|
||||
end
|
||||
|
||||
def self.slurp(error, service=nil)
|
||||
new_error = super(error)
|
||||
unless new_error.response_data.nil? or new_error.response_data['badRequest'].nil?
|
||||
new_error.instance_variable_set(:@validation_errors, new_error.response_data['badRequest']['validationErrors'])
|
||||
end
|
||||
|
||||
status_code = error.response ? error.response.status : nil
|
||||
new_error.instance_variable_set(:@status_code, status_code)
|
||||
new_error.set_transaction_id(error, service)
|
||||
new_error
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
service(:auto_scale, 'AutoScale')
|
||||
service(:block_storage, 'BlockStorage')
|
||||
service(:cdn, 'CDN')
|
||||
service(:compute, 'Compute')
|
||||
service(:compute_v2, 'Compute v2')
|
||||
service(:dns, 'DNS')
|
||||
service(:storage, 'Storage')
|
||||
service(:load_balancers, 'LoadBalancers')
|
||||
service(:identity, 'Identity')
|
||||
service(:databases, 'Databases')
|
||||
service(:monitoring, 'Monitoring')
|
||||
service(:queues, 'Queues')
|
||||
service(:networking, 'Networking')
|
||||
|
||||
def self.authenticate(options, connection_options = {})
|
||||
rackspace_auth_url = options[:rackspace_auth_url]
|
||||
rackspace_auth_url ||= options[:rackspace_endpoint] == Fog::Compute::RackspaceV2::LON_ENDPOINT ? UK_AUTH_ENDPOINT : US_AUTH_ENDPOINT
|
||||
url = rackspace_auth_url.match(/^https?:/) ? \
|
||||
rackspace_auth_url : 'https://' + rackspace_auth_url
|
||||
uri = URI.parse(url)
|
||||
connection = Fog::Core::Connection.new(url, false, connection_options)
|
||||
@rackspace_api_key = options[:rackspace_api_key]
|
||||
@rackspace_username = options[:rackspace_username]
|
||||
response = connection.request({
|
||||
:expects => [200, 204],
|
||||
:headers => {
|
||||
'X-Auth-Key' => @rackspace_api_key,
|
||||
'X-Auth-User' => @rackspace_username
|
||||
},
|
||||
:method => 'GET',
|
||||
:path => (uri.path and not uri.path.empty?) ? uri.path : 'v1.0'
|
||||
})
|
||||
response.headers.reject do |key, value|
|
||||
!['X-Server-Management-Url', 'X-Storage-Url', 'X-CDN-Management-Url', 'X-Auth-Token'].include?(key)
|
||||
end
|
||||
end
|
||||
|
||||
def self.json_response?(response)
|
||||
return false unless response && response.headers
|
||||
response.get_header('Content-Type') =~ %r{application/json}i ? true : false
|
||||
end
|
||||
|
||||
def self.normalize_url(endpoint)
|
||||
return nil unless endpoint
|
||||
str = endpoint.chomp " "
|
||||
str = str.chomp "/"
|
||||
str.downcase
|
||||
end
|
||||
|
||||
# CGI.escape, but without special treatment on spaces
|
||||
def self.escape(str,extra_exclude_chars = '')
|
||||
# '-' is a special character inside a regex class so it must be first or last.
|
||||
# Add extra excludes before the final '-' so it always remains trailing, otherwise
|
||||
# an unwanted range is created by mistake.
|
||||
str.gsub(/([^a-zA-Z0-9_.#{extra_exclude_chars}-]+)/) do
|
||||
'%' + $1.unpack('H2' * $1.bytesize).join('%').upcase
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
164
lib/fog/rackspace/databases.rb
Normal file
164
lib/fog/rackspace/databases.rb
Normal file
|
@ -0,0 +1,164 @@
|
|||
require 'fog/rackspace/core'
|
||||
|
||||
module Fog
|
||||
module Rackspace
|
||||
class Databases < Fog::Service
|
||||
include Fog::Rackspace::Errors
|
||||
|
||||
class ServiceError < Fog::Rackspace::Errors::ServiceError; end
|
||||
class InternalServerError < Fog::Rackspace::Errors::InternalServerError; end
|
||||
class BadRequest < Fog::Rackspace::Errors::BadRequest; end
|
||||
|
||||
DFW_ENDPOINT = 'https://dfw.databases.api.rackspacecloud.com/v1.0'
|
||||
LON_ENDPOINT = 'https://lon.databases.api.rackspacecloud.com/v1.0'
|
||||
ORD_ENDPOINT = 'https://ord.databases.api.rackspacecloud.com/v1.0'
|
||||
|
||||
requires :rackspace_api_key, :rackspace_username
|
||||
recognizes :rackspace_auth_url
|
||||
recognizes :rackspace_auth_token
|
||||
recognizes :rackspace_endpoint
|
||||
recognizes :rackspace_region
|
||||
recognizes :rackspace_database_url
|
||||
|
||||
model_path 'fog/rackspace/models/databases'
|
||||
model :flavor
|
||||
collection :flavors
|
||||
model :instance
|
||||
collection :instances
|
||||
model :database
|
||||
collection :databases
|
||||
model :user
|
||||
collection :users
|
||||
|
||||
request_path 'fog/rackspace/requests/databases'
|
||||
request :list_flavors
|
||||
request :get_flavor
|
||||
|
||||
request :list_instances
|
||||
request :get_instance
|
||||
request :create_instance
|
||||
request :delete_instance
|
||||
request :check_root_user
|
||||
request :enable_root_user
|
||||
request :restart_instance
|
||||
request :resize_instance
|
||||
request :resize_instance_volume
|
||||
|
||||
request :list_databases
|
||||
request :create_database
|
||||
request :delete_database
|
||||
|
||||
request :list_users
|
||||
request :create_user
|
||||
request :delete_user
|
||||
request :grant_user_access
|
||||
request :revoke_user_access
|
||||
|
||||
class Mock < Fog::Rackspace::Service
|
||||
def request(params)
|
||||
Fog::Mock.not_implemented
|
||||
end
|
||||
end
|
||||
|
||||
class Real < Fog::Rackspace::Service
|
||||
def service_name
|
||||
:cloudDatabases
|
||||
end
|
||||
|
||||
def region
|
||||
@rackspace_region
|
||||
end
|
||||
|
||||
def initialize(options = {})
|
||||
@rackspace_api_key = options[:rackspace_api_key]
|
||||
@rackspace_username = options[:rackspace_username]
|
||||
@rackspace_auth_url = options[:rackspace_auth_url]
|
||||
@rackspace_must_reauthenticate = false
|
||||
@connection_options = options[:connection_options] || {}
|
||||
setup_custom_endpoint(options)
|
||||
|
||||
authenticate
|
||||
|
||||
deprecation_warnings(options)
|
||||
|
||||
@persistent = options[:persistent] || false
|
||||
@connection = Fog::Core::Connection.new(endpoint_uri.to_s, @persistent, @connection_options)
|
||||
end
|
||||
|
||||
def request(params, parse_json = true)
|
||||
super
|
||||
rescue Excon::Errors::NotFound => error
|
||||
raise NotFound.slurp(error, self)
|
||||
rescue Excon::Errors::BadRequest => error
|
||||
raise BadRequest.slurp(error, self)
|
||||
rescue Excon::Errors::InternalServerError => error
|
||||
raise InternalServerError.slurp(error, self)
|
||||
rescue Excon::Errors::HTTPStatusError => error
|
||||
raise ServiceError.slurp(error, self)
|
||||
end
|
||||
|
||||
def endpoint_uri(service_endpoint_url=nil)
|
||||
@uri = super(@rackspace_endpoint || service_endpoint_url, :rackspace_database_url)
|
||||
end
|
||||
|
||||
def authenticate(options={})
|
||||
super({
|
||||
:rackspace_api_key => @rackspace_api_key,
|
||||
:rackspace_username => @rackspace_username,
|
||||
:rackspace_auth_url => @rackspace_auth_url,
|
||||
:connection_options => @connection_options
|
||||
})
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def setup_custom_endpoint(options)
|
||||
@rackspace_endpoint = Fog::Rackspace.normalize_url(options[:rackspace_database_url] || options[:rackspace_endpoint])
|
||||
|
||||
if v2_authentication?
|
||||
case @rackspace_endpoint
|
||||
when DFW_ENDPOINT
|
||||
@rackspace_endpoint = nil
|
||||
@rackspace_region = :dfw
|
||||
when ORD_ENDPOINT
|
||||
@rackspace_endpoint = nil
|
||||
@rackspace_region = :ord
|
||||
when LON_ENDPOINT
|
||||
@rackspace_endpoint = nil
|
||||
@rackspace_region = :lon
|
||||
else
|
||||
# we are actually using a custom endpoint
|
||||
@rackspace_region = options[:rackspace_region]
|
||||
end
|
||||
else
|
||||
#if we are using auth1 and the endpoint is not set, default to DFW_ENDPOINT for historical reasons
|
||||
@rackspace_endpoint ||= DFW_ENDPOINT
|
||||
end
|
||||
end
|
||||
|
||||
def deprecation_warnings(options)
|
||||
Fog::Logger.deprecation("The :rackspace_endpoint option is deprecated. Please use :rackspace_database_url for custom endpoints") if options[:rackspace_endpoint]
|
||||
|
||||
if [DFW_ENDPOINT, ORD_ENDPOINT, LON_ENDPOINT].include?(@rackspace_endpoint) && v2_authentication?
|
||||
regions = @identity_service.service_catalog.display_service_regions(service_name)
|
||||
Fog::Logger.deprecation("Please specify region using :rackspace_region rather than :rackspace_endpoint. Valid region for :rackspace_region are #{regions}.")
|
||||
end
|
||||
end
|
||||
|
||||
def append_tenant_v1(credentials)
|
||||
account_id = credentials['X-Server-Management-Url'].match(/.*\/([\d]+)$/)[1]
|
||||
|
||||
endpoint = @rackspace_endpoint || credentials['X-Server-Management-Url'] || DFW_ENDPOINT
|
||||
@uri = URI.parse(endpoint)
|
||||
@uri.path = "#{@uri.path}/#{account_id}"
|
||||
end
|
||||
|
||||
def authenticate_v1(options)
|
||||
credentials = Fog::Rackspace.authenticate(options, @connection_options)
|
||||
append_tenant_v1 credentials
|
||||
@auth_token = credentials['X-Auth-Token']
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
172
lib/fog/rackspace/dns.rb
Normal file
172
lib/fog/rackspace/dns.rb
Normal file
|
@ -0,0 +1,172 @@
|
|||
require 'fog/rackspace/core'
|
||||
|
||||
module Fog
|
||||
module DNS
|
||||
class Rackspace < Fog::Service
|
||||
include Fog::Rackspace::Errors
|
||||
|
||||
class ServiceError < Fog::Rackspace::Errors::ServiceError; end
|
||||
class InternalServerError < Fog::Rackspace::Errors::InternalServerError; end
|
||||
class BadRequest < Fog::Rackspace::Errors::BadRequest; end
|
||||
class Conflict < Fog::Rackspace::Errors::Conflict; end
|
||||
class ServiceUnavailable < Fog::Rackspace::Errors::ServiceUnavailable; end
|
||||
|
||||
class CallbackError < Fog::Errors::Error
|
||||
attr_reader :response, :message, :details
|
||||
def initialize(response)
|
||||
@response = response
|
||||
@message = response.body['error']['message']
|
||||
@details = response.body['error']['details']
|
||||
end
|
||||
end
|
||||
|
||||
US_ENDPOINT = 'https://dns.api.rackspacecloud.com/v1.0'
|
||||
UK_ENDPOINT = 'https://lon.dns.api.rackspacecloud.com/v1.0'
|
||||
|
||||
requires :rackspace_api_key, :rackspace_username
|
||||
recognizes :rackspace_auth_url, :rackspace_auth_token, :rackspace_dns_endpoint, :rackspace_dns_url, :rackspace_region
|
||||
|
||||
model_path 'fog/rackspace/models/dns'
|
||||
model :record
|
||||
collection :records
|
||||
model :zone
|
||||
collection :zones
|
||||
|
||||
request_path 'fog/rackspace/requests/dns'
|
||||
#TODO - Import/Export, modify multiple domains, modify multiple records
|
||||
request :callback
|
||||
request :list_domains
|
||||
request :list_domain_details
|
||||
request :modify_domain
|
||||
request :create_domains
|
||||
request :remove_domain
|
||||
request :remove_domains
|
||||
request :list_subdomains
|
||||
request :list_records
|
||||
request :list_record_details
|
||||
request :modify_record
|
||||
request :remove_record
|
||||
request :remove_records
|
||||
request :add_records
|
||||
|
||||
class Mock < Fog::Rackspace::Service
|
||||
def initialize(options={})
|
||||
@rackspace_api_key = options[:rackspace_api_key]
|
||||
@rackspace_username = options[:rackspace_username]
|
||||
@rackspace_auth_url = options[:rackspace_auth_url]
|
||||
@connection_options = options[:connection_options] || {}
|
||||
end
|
||||
|
||||
def self.data
|
||||
@data ||= {
|
||||
}
|
||||
end
|
||||
|
||||
def self.reset
|
||||
@data = nil
|
||||
end
|
||||
|
||||
def data
|
||||
self.class.data
|
||||
end
|
||||
|
||||
def reset_data
|
||||
self.class.reset
|
||||
end
|
||||
end
|
||||
|
||||
class Real < Fog::Rackspace::Service
|
||||
def service_name
|
||||
:cloudDNS
|
||||
end
|
||||
|
||||
def region
|
||||
#Note: DNS does not currently support multiple regions
|
||||
@rackspace_region
|
||||
end
|
||||
|
||||
def initialize(options={})
|
||||
@rackspace_api_key = options[:rackspace_api_key]
|
||||
@rackspace_username = options[:rackspace_username]
|
||||
@rackspace_auth_url = options[:rackspace_auth_url]
|
||||
@connection_options = options[:connection_options] || {}
|
||||
@rackspace_endpoint = Fog::Rackspace.normalize_url(options[:rackspace_dns_url] || options[:rackspace_dns_endpoint])
|
||||
@rackspace_region = options[:rackspace_region]
|
||||
|
||||
authenticate
|
||||
|
||||
deprecation_warnings(options)
|
||||
|
||||
@persistent = options[:persistent] || false
|
||||
@connection = Fog::Core::Connection.new(endpoint_uri.to_s, @persistent, @connection_options)
|
||||
end
|
||||
|
||||
def endpoint_uri(service_endpoint_url=nil)
|
||||
@uri = super(@rackspace_endpoint || service_endpoint_url, :rackspace_dns_url)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def request(params, parse_json = true)
|
||||
super
|
||||
rescue Excon::Errors::NotFound => error
|
||||
raise NotFound.slurp(error, self)
|
||||
rescue Excon::Errors::BadRequest => error
|
||||
raise BadRequest.slurp(error, self)
|
||||
rescue Excon::Errors::InternalServerError => error
|
||||
raise InternalServerError.slurp(error, self)
|
||||
rescue Excon::Errors::ServiceUnavailable => error
|
||||
raise ServiceUnavailable.slurp(error, self)
|
||||
rescue Excon::Errors::Conflict => error
|
||||
raise Conflict.slurp(error, self)
|
||||
rescue Excon::Errors::HTTPStatusError => error
|
||||
raise ServiceError.slurp(error, self)
|
||||
end
|
||||
|
||||
def array_to_query_string(arr)
|
||||
return "" unless arr
|
||||
query_array = arr.map do | k, v |
|
||||
val_str = v.is_a?(Array) ? v.join(",") : v.to_s
|
||||
"#{k}=#{val_str}"
|
||||
end
|
||||
|
||||
query_array.join('&')
|
||||
end
|
||||
|
||||
def validate_path_fragment(name, fragment)
|
||||
if fragment.nil? or fragment.to_s.empty?
|
||||
raise ArgumentError.new("#{name} cannot be null or empty")
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def deprecation_warnings(options)
|
||||
Fog::Logger.deprecation("The :rackspace_dns_endpoint option is deprecated. Please use :rackspace_dns_url for custom endpoints") if options[:rackspace_dns_endpoint]
|
||||
end
|
||||
|
||||
def setup_endpoint(credentials)
|
||||
account_id = credentials['X-Server-Management-Url'].match(/.*\/([\d]+)$/)[1]
|
||||
|
||||
@uri = URI.parse(@rackspace_endpoint || US_ENDPOINT)
|
||||
@uri.path = "#{@uri.path}/#{account_id}"
|
||||
end
|
||||
|
||||
def authenticate_v1(options)
|
||||
credentials = Fog::Rackspace.authenticate(options, @connection_options)
|
||||
setup_endpoint credentials
|
||||
@auth_token = credentials['X-Auth-Token']
|
||||
end
|
||||
|
||||
def authenticate(options={})
|
||||
super({
|
||||
:rackspace_api_key => @rackspace_api_key,
|
||||
:rackspace_username => @rackspace_username,
|
||||
:rackspace_auth_url => @rackspace_auth_url,
|
||||
:connection_options => @connection_options
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
503
lib/fog/rackspace/docs/auto_scale.md
Normal file
503
lib/fog/rackspace/docs/auto_scale.md
Normal file
|
@ -0,0 +1,503 @@
|
|||
#Auto Scale (AutoScale)
|
||||
|
||||
This document explains how to get started using Auto Scale with Fog. It assumes you have read the [Getting Started with Fog and the Rackspace Open Cloud](getting_started.md) document.
|
||||
|
||||
## Basic Concepts
|
||||
|
||||
Auto Scale is a service that enables you to scale your application by adding or removing servers based on monitoring events, a schedule, or arbitrary webhooks.
|
||||
|
||||
Auto Scale functions by linking three services:
|
||||
|
||||
* Monitoring (such as Monitoring as a Service)
|
||||
* Auto Scale
|
||||
* Servers and Load Balancers
|
||||
|
||||
|
||||
## Workflow
|
||||
|
||||
A scaling group is monitored by Rackspace Cloud Monitoring. When Monitoring triggers an alarm for high utilization within the Autoscaling group, a webhook is triggered. The webhook calls the Auto Scale service, which consults a policy in accordance with the webhook. The policy determines how many additional Cloud Servers should be added or removed in accordance with the alarm.
|
||||
|
||||
Alarms may trigger scaling up or scaling down. Scale-down events always remove the oldest server in the group.
|
||||
|
||||
Cooldowns allow you to ensure that you don't scale up or down too fast. When a scaling policy runs, both the scaling policy cooldown and the group cooldown start. Any additional requests to the group are discarded while the group cooldown is active. Any additional requests to the specific policy are discarded when the policy cooldown is active.
|
||||
|
||||
It is important to remember that Auto Scale does not configure anything within a server. This means that all images should be self-provisioning. It is up to you to make sure that your services are configured to function properly when the server is started. We recommend using something like Chef, Salt, or Puppet.
|
||||
|
||||
|
||||
## Starting irb console
|
||||
|
||||
Start by executing the following command:
|
||||
|
||||
irb
|
||||
|
||||
Once `irb` has launched you need to require the Fog library.
|
||||
|
||||
If using Ruby 1.8.x execute:
|
||||
|
||||
require 'rubygems'
|
||||
require 'fog'
|
||||
|
||||
If using Ruby 1.9.x execute:
|
||||
|
||||
require 'fog'
|
||||
|
||||
## Create Service
|
||||
|
||||
Next, create a connection to Auto Scale:
|
||||
|
||||
Using a US-based account:
|
||||
|
||||
service = Fog::Rackspace::AutoScale.new (
|
||||
:rackspace_username => RACKSPACE_USER_NAME, # Your Rackspace Username
|
||||
:rackspace_api_key => RACKSPACE_API, # Your Rackspace API key
|
||||
:rackspace_region => :ord,
|
||||
:connection_options => {} # Optional
|
||||
)
|
||||
|
||||
Using a UK-based account:
|
||||
|
||||
service = Fog::Rackspace::AutoScale.new (
|
||||
:rackspace_username => RACKSPACE_USER_NAME, # Your Rackspace Username
|
||||
:rackspace_api_key => RACKSPACE_API, # Your Rackspace API key
|
||||
:rackspace_auth_url => Fog::Rackspace::UK_AUTH_ENDPOINT,
|
||||
:rackspace_region => :lon,
|
||||
:connection_options => {} # Optional
|
||||
)
|
||||
|
||||
To learn more about obtaining cloud credentials refer to the [Getting Started with Fog and the Rackspace Open Cloud](getting_started.md) document.
|
||||
|
||||
By default `Fog::Rackspace::AutoScale` will authenticate against the US authentication endpoint. You can specify alternative authentication endpoints using the key `:rackspace_auth_url`. Please refer to [Alternate Authentication Endpoints](http://docs.rackspace.com/auth/api/v2.0/auth-client-devguide/content/Endpoints-d1e180.html) for a list of alternative Rackspace authentication endpoints.
|
||||
|
||||
Alternative regions are specified using the key `:rackspace_region `. A list of regions available for Auto Scale can be found by executing the following:
|
||||
|
||||
identity_service = Fog::Identity.new({
|
||||
:provider => 'Rackspace', # Rackspace Fog provider
|
||||
:rackspace_username => RACKSPACE_USER_NAME, # Your Rackspace Username
|
||||
:rackspace_api_key => RACKSPACE_API, # Your Rackspace API key
|
||||
:rackspace_auth_url => Fog::Rackspace::UK_AUTH_ENDPOINT # Not specified for US Cloud
|
||||
})
|
||||
|
||||
identity_service.service_catalog.display_service_regions :autoscale
|
||||
|
||||
Rackspace Private Cloud installations can skip specifying a region and directly specify their custom service endpoints using the key `:rackspace_auto_scale_url`.
|
||||
|
||||
|
||||
**Note**: A`Fog::Rackspace::AutoScale` instance is needed for the desired region.
|
||||
|
||||
### Optional Connection Parameters
|
||||
|
||||
Fog supports passing additional connection parameters to its underlying HTTP library (Excon) using the `:connection_options` parameter.
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:connect_timeout</td>
|
||||
<td>Connection timeout (default: 60 seconds)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:read_timeout</td>
|
||||
<td>Read timeout for connection (default: 60 seconds)</td> </tr>
|
||||
<tr>
|
||||
<td>:write_timeout</td>
|
||||
<td>Write timeout for connection (default: 60 seconds)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:proxy</td>
|
||||
<td>Proxy for HTTP and HTTPS connections</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:ssl_ca_path</td>
|
||||
<td>Path to SSL certificate authorities</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:ssl_ca_file</td>
|
||||
<td>SSL certificate authority file</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:ssl_verify_peer</td>
|
||||
<td>SSL verify peer (default: true)</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
## Fog Abstractions
|
||||
|
||||
Fog provides both a **model** and **request** abstraction. The request abstraction provides the most efficient interface and the model abstraction wraps the request abstraction to provide a convenient `ActiveModel`-like interface.
|
||||
|
||||
### Request Layer
|
||||
|
||||
The request abstraction maps directly to the [Auto Scale API](http://docs.rackspace.com//cas/api/v1.0/autoscale-devguide/content/API_Operations.html). It provides the most efficient interface to the Rackspace Open Cloud.
|
||||
|
||||
To see a list of requests supported by the service:
|
||||
|
||||
service.requests
|
||||
|
||||
This returns:
|
||||
|
||||
:list_groups, :create_group, :get_group, :delete_group, :get_group_state, :pause_group_state, :resume_group_state, :get_group_config, :update_group_config, :get_launch_config, :update_launch_config, :list_policies, :create_policy, :get_policy, :update_policy, :delete_policy, :execute_policy, :execute_anonymous_webhook, :get_webhook, :list_webhooks, :create_webhook, :update_webhook, :delete_webhook
|
||||
|
||||
|
||||
#### Example Request
|
||||
|
||||
To request a list of Auto Scale groups:
|
||||
|
||||
response = service.list_groups
|
||||
|
||||
This returns in the following `Excon::Response`:
|
||||
|
||||
#<Excon::Response:0x007fd3ea78af08 @data={:body=>{"groups_links"=>[], "groups"=>[{"paused"=>false, "desiredCapacity"=>0, "links"=>[{"href"=>"https://ord.autoscale.api.rackspacecloud.com/v1.0/555/groups/b45e6107-26ca-4a93-869d-46bf20005df3/", "rel"=>"self"}], "active"=>[], "pendingCapacity"=>0, "activeCapacity"=>0, "id"=>"b45e6107-26ca-4a93-869d-46bf20005df3", "name"=>"fog-scailing-group"}]}, :headers=>{"Content-Type"=>"application/json", "Via"=>"1.1 Repose (Repose/2.8.2)", "x-response-id"=>"4c2a8f70-a7da-479a-bf69-6882b5b6346e", "Date"=>"Fri, 27 Sep 2013 15:38:10 GMT", "Transfer-Encoding"=>"chunked", "Server"=>"Jetty(8.0.y.z-SNAPSHOT)"}, :status=>200, :remote_ip=>"162.209.41.103"}, @body="{\"groups_links\": [], \"groups\": [{\"paused\": false, \"desiredCapacity\": 0, \"links\": [{\"href\": \"https://ord.autoscale.api.rackspacecloud.com/v1.0/555/groups/b45e6107-26ca-4a93-869d-46bf20005df3/\", \"rel\": \"self\"}], \"active\": [], \"pendingCapacity\": 0, \"activeCapacity\": 0, \"id\": \"b45e6107-26ca-4a93-869d-46bf20005df3\", \"name\": \"fog-scailing-group\"}]}", @headers={"Content-Type"=>"application/json", "Via"=>"1.1 Repose (Repose/2.8.2)", "x-response-id"=>"4c2a8f70-a7da-479a-bf69-6882b5b6346e", "Date"=>"Fri, 27 Sep 2013 15:38:10 GMT", "Transfer-Encoding"=>"chunked", "Server"=>"Jetty(8.0.y.z-SNAPSHOT)"}, @status=200, @remote_ip="162.209.41.103">
|
||||
|
||||
To view the status of the response:
|
||||
|
||||
response.status
|
||||
|
||||
**Note**: Fog is aware of valid HTTP response statuses for each request type. If an unexpected HTTP response status occurs, Fog will raise an exception.
|
||||
|
||||
To view response body:
|
||||
|
||||
response.body
|
||||
|
||||
returns:
|
||||
|
||||
{"groups_links"=>[], "groups"=>[{"paused"=>false, "desiredCapacity"=>0, "links"=>[{"href"=>"https://ord.autoscale.api.rackspacecloud.com/v1.0/555/groups/b45e6107-26ca-4a93-869d-46bf20005df3/", "rel"=>"self"}], "active"=>[], "pendingCapacity"=>0, "activeCapacity"=>0, "id"=>"b45e6107-26ca-4a93-869d-46bf20005df3", "name"=>"fog-scailing-group"}]}
|
||||
|
||||
|
||||
To learn more about Auto Scale request methods refer to [rdoc](http://rubydoc.info/gems/fog/Fog/Rackspace/AutoScale/Real). To learn more about Excon refer to [Excon GitHub repo](https://github.com/geemus/excon).
|
||||
|
||||
### Model Layer
|
||||
|
||||
Fog models behave in a manner similar to `ActiveModel`. Models will generally respond to `create`, `save`, `persisted?`, `destroy`, `reload` and `attributes` methods. Additionally, fog will automatically create attribute accessors.
|
||||
|
||||
Here is a summary of common model methods:
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Method</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>create</td>
|
||||
<td>
|
||||
Accepts hash of attributes and creates object.<br>
|
||||
Note: creation is a non-blocking call and you will be required to wait for a valid state before using resulting object.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>save</td>
|
||||
<td>Saves object.<br>
|
||||
Note: not all objects support updating object.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>persisted?</td>
|
||||
<td>Returns true if the object has been persisted.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>destroy</td>
|
||||
<td>
|
||||
Destroys object.<br>
|
||||
Note: this is a non-blocking call and object deletion might not be instantaneous.
|
||||
</td>
|
||||
<tr>
|
||||
<td>reload</td>
|
||||
<td>Updates object with latest state from service.</td>
|
||||
<tr>
|
||||
<td>ready?</td>
|
||||
<td>Returns true if object is in a ready state and able to perform actions. This method will raise an exception if object is in an error state.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>attributes</td>
|
||||
<td>Returns a hash containing the list of model attributes and values.</td>
|
||||
</tr>
|
||||
<td>identity</td>
|
||||
<td>
|
||||
Returns the identity of the object.<br>
|
||||
Note: This might not always be equal to object.id.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>wait_for</td>
|
||||
<td>This method periodically reloads model and then yields to specified block until block returns true or a timeout occurs.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
The remainder of this document details the model abstraction.
|
||||
|
||||
## The Scaling Group
|
||||
|
||||
* The **Scaling Group** is the basic unit of automatic scaling. It determines the minimum and maximum number of servers that exist at any time for the group, the cooldown period between scaling events, the configuration for each new server, the load balancer to add these servers to (optional), and any policies that are used for this group.
|
||||
|
||||
### List Scaling Groups
|
||||
|
||||
To retrieve the list of your scaling groups:
|
||||
|
||||
service.groups
|
||||
|
||||
This returns a collection of `Fog::Rackspace::AutoScale::Group` objects:
|
||||
|
||||
<Fog::Rackspace::AutoScale::Groups
|
||||
[
|
||||
<Fog::Rackspace::AutoScale::Group
|
||||
id="b45e6107-26ca-4a93-869d-46bf20005df3",
|
||||
links=[{"href"=>"https://ord.autoscale.api.rackspacecloud.com/v1.0/555/groups/b45e6107-26ca-4a93-869d-46bf20005df3/", "rel"=>"self"}]
|
||||
>
|
||||
]
|
||||
>
|
||||
|
||||
To view the [launch configuration](#launch-configurations) for a group execute the following:
|
||||
|
||||
groups = service.groups
|
||||
group = group.first
|
||||
group.launch_config
|
||||
|
||||
This returns a `Fog::Rackspace::AutoScale::LaunchConfig`:
|
||||
|
||||
<Fog::Rackspace::AutoScale::LaunchConfig
|
||||
group= <Fog::Rackspace::AutoScale::Group
|
||||
id="b45e6107-26ca-4a93-869d-46bf20005df3",
|
||||
links=[{"href"=>"https://ord.autoscale.api.rackspacecloud.com/v1.0/5555/groups/b45e6107-26ca-4a93-869d-46bf20005df3/", "rel"=>"self"}]
|
||||
>,
|
||||
type="launch_server",
|
||||
args={"loadBalancers"=>[{"port"=>8080, "loadBalancerId"=>9099}], "server"=>{"name"=>"autoscale_server", "imageRef"=>"0d589460-f177-4b0f-81c1-8ab8903ac7d8", "flavorRef"=>"2", "OS-DCF =>diskConfig"=>"AUTO", "metadata"=>{"build_config"=>"core", "meta_key_1"=>"meta_value_1", "meta_key_2"=>"meta_value_2"}, "networks"=>[{"uuid"=>"11111111-1111-1111-1111-111111111111"}, {"uuid"=>"00000000-0000-0000-0000-000000000000"}], "personality"=>[{"path"=>"/root/.csivh", "contents"=>"VGhpcyBpcyBhIHRlc3QgZmlsZS4="}]}}
|
||||
>
|
||||
|
||||
### Getting the Current State of a Scaling Group
|
||||
|
||||
It is sometimes helpful to determine what the current state of a scaling group is in terms of whether it is scaling up, scaling down, or stable.
|
||||
|
||||
To see your group's current state execute the following:
|
||||
|
||||
group.state
|
||||
|
||||
This returns the following:
|
||||
|
||||
{"paused"=>false, "desiredCapacity"=>0, "links"=>[{"href"=>"https://ord.autoscale.api.rackspacecloud.com/v1.0/555/groups/b45e6107-26ca-4a93-869d-46bf20005df3/", "rel"=>"self"}], "active"=>[], "pendingCapacity"=>0, "activeCapacity"=>0, "id"=>"b45e6107-26ca-4a93-869d-46bf20005df3", "name"=>"fog-scailing-group"}
|
||||
|
||||
The `active` key holds a list of the IDs of the servers created as part of this scaling group. The `paused` key shows whether or not the scaling group's response to alarms is active or not. There are 3 'capacity'-related keys: `activeCapacity`, `desiredCapacity`, and `pendingCapacity`:
|
||||
|
||||
Key | Represents
|
||||
---- | ----
|
||||
**activeCapacity** | The number of active servers that are part of this scaling group
|
||||
**desiredCapacity** | The target number of servers for this scaling group, based on the combination of configuration settings and monitoring alarm responses
|
||||
**pendingCapacity** | The number of servers which are in the process of being created (when positive) or destroyed (when negative).
|
||||
|
||||
### Pausing a Scaling Group's Policies
|
||||
|
||||
To pause a scaling group's execution:
|
||||
|
||||
group.pause
|
||||
|
||||
There is a corresponding `resume` method to resume execution:
|
||||
|
||||
group.resume
|
||||
|
||||
### Creating a Scaling Group
|
||||
|
||||
There are many options available to you when creating a scaling group. In order to ease the burden, a builder is provided.
|
||||
|
||||
To create a scaling group with the builder you first include the builder in your script:
|
||||
|
||||
require 'fog/rackspace/models/auto_scale/group_builder'
|
||||
|
||||
And then use the builder as follows:
|
||||
|
||||
INTERNET = '00000000-0000-0000-0000-000000000000'
|
||||
SERVICE_NET = '11111111-1111-1111-1111-111111111111'
|
||||
|
||||
attributes = {
|
||||
:server_name => "testgroup",
|
||||
:image => my_image,
|
||||
:flavor => 3,
|
||||
:networks => [INTERNET, SERVICE_NET],
|
||||
:personality => [
|
||||
{
|
||||
"path" => "/root/.csivh",
|
||||
"contents" => "VGhpcyBpcyBhIHRlc3QgZmlsZS4="
|
||||
}
|
||||
],
|
||||
:max_entities => 3,
|
||||
:min_entities => 2,
|
||||
:cooldown => 600,
|
||||
:name => "MyScalingGroup",
|
||||
:metadata => { "created_by" => "autoscale sample script" },
|
||||
:load_balancers => {
|
||||
:port => 80,
|
||||
:loadBalancerId => 1234
|
||||
}
|
||||
:launch_config_type => :launch_server
|
||||
}
|
||||
|
||||
group = Fog::Rackspace::AutoScale::GroupBuilder.build(service, attributes)
|
||||
group.save
|
||||
|
||||
This creates the scaling group with the name `MyScalingGroup`, and returns a `Fog::Rackspace::AutoScale::Group` object representing the new group. Since the `:min_entities` is 2, it immediately creates 2 servers for the group, based on the image whose ID is in the variable `my_image`. When they are created, they are then added to the load balancer whose ID is `1234`, and receive requests on port 80.
|
||||
|
||||
Note that the `:server_name` parameter represents a base string to which Autoscale prepends a 10-character prefix to create a unique name for each server. The prefix always begins with 'as' and is followed by 8 random hex digits and a dash (-). For example, if you set the server_name to 'testgroup', and the scaling group creates 3 servers, their names would look like these:
|
||||
|
||||
as5defddd4-testgroup
|
||||
as92e512fe-testgroup
|
||||
asedcf7587-testgroup
|
||||
|
||||
**Note**: You will see need to add policies to trigger auto scaling operations. See [Policies Section](#policies) for more information.
|
||||
|
||||
#### Parameters
|
||||
Parameter | Required | Default | Notes
|
||||
---- | ---- | ---- | ----
|
||||
**:name** | yes | |
|
||||
**:cooldown** | yes | | Period in seconds after a scaling event in which further events are ignored
|
||||
**:min_entities** | yes | |
|
||||
**:max_entities** | yes | |
|
||||
**:launch_config_type** | yes | | Only option currently is`:launch_server`
|
||||
**:flavor** | yes | | Flavor to use for each server that is launched. This can be a `Fog::Compute::RackspaceV2::Flavor` or an ID.
|
||||
**:server_name** | yes | | The base name for servers created by Autoscale.
|
||||
**:image** | yes | | This can be a `Fog::Compute::RackspaceV2::Image` or an id. This is the image that all new servers are created from.
|
||||
**:disk_config** | no | MANUAL | Determines if the server's disk is partitioned to the full size of the flavor ('AUTO') or just to the size of the image ('MANUAL').
|
||||
**:server_metadata** | no | | Arbitrary key-value pairs you want to associate with your servers.
|
||||
**:personality** | no | | Small text files that are created on the new servers. _Personality_ is discussed in the [Rackspace Cloud Servers documentation](http://docs.rackspace.com/servers/api/v2/cs-devguide/content/Server_Personality-d1e2543.html)
|
||||
**:networks** | no | | Any array of networks to which you want to attach new servers. See the [Create Servers documentation](http://docs.rackspace.com/servers/api/v2/cs-devguide/content/CreateServers.html) for standard network IDs.
|
||||
**:load_balancers** | no | | Either a hash of {:port, :loadBalancerId} or a `Fog::Rackspace::LoadBalancers::LoadBalancer` object.
|
||||
|
||||
### Updating a Scaling Configuration Group
|
||||
|
||||
A group's scaling configuration can be updated via the `Fog::Rackspace::AutoScale::GroupConfig` object. You can retrieve this object by executing the following:
|
||||
|
||||
group_config = group.group_config
|
||||
|
||||
Available options on `group_config` include `:max_entities`, `:name`, `:cooldown`, `:min_entities`, `:metadata`. To update a scaling group, pass one or more of these as keyword arguments. For example, to change the cooldown period to 2 minutes and increase the maximum entities to 16, you call:
|
||||
|
||||
group_config.cooldown = 120
|
||||
group_config.max_entities = 16
|
||||
group_config.save
|
||||
|
||||
**Note**: If you pass any metadata values in this call, it must be the full set of metadata for the scaling group, since the underlying API call **overwrites** any existing metadata.
|
||||
|
||||
### Deleting a Scaling Group
|
||||
|
||||
To remove a scaling group, call its `destroy` method:
|
||||
|
||||
group.destroy
|
||||
|
||||
Note: you cannot delete a scaling group that has active servers in it. You must first delete the servers by setting the `min_entities` and `max_entities` to zero:
|
||||
|
||||
group_config = group.group_config
|
||||
group_config.min_entities = 0
|
||||
group_config.max_entities = 0
|
||||
group_config.save
|
||||
|
||||
Once the servers are deleted you can then delete the scaling group.
|
||||
|
||||
## Launch Configurations
|
||||
|
||||
Each scaling group has an associated **launch configuration**. This determines the properties of servers that are created in response to a scaling event.
|
||||
|
||||
The `:server_name` represents a base string to which Autoscale prepends a 10-character prefix. The prefix always begins with 'as' and is followed by 8 random hex digits and a dash (-). For example, if you set the `server_name` to 'testgroup', and the scaling group creates 3 servers, their names would look like these:
|
||||
|
||||
as5defddd4-testgroup
|
||||
as92e512fe-testgroup
|
||||
asedcf7587-testgroup
|
||||
|
||||
To retrieve the launch config:
|
||||
|
||||
launch_config = group.launch_config
|
||||
|
||||
The launch configuration contains two attributes `:type` and `:args`. The only launch type currently available for Auto Scale is `:launch_server`. The `args` attribute contains a hash with the launch server configuration options as follows:
|
||||
|
||||
{"server"=>{
|
||||
"name"=>"autoscale_server",
|
||||
"imageRef"=>"66448837-1a58-4bd2-a647-9f3272f36263",
|
||||
"flavorRef"=>"2",
|
||||
"networks"=>[{"uuid"=>"00000000-0000-0000-0000-000000000000"}, {"uuid"=>"11111111-1111-1111-1111-111111111111"}],
|
||||
"personality"=>[{"path"=>"/root/.csivh", "contents"=>"VGhpcyBpcyBhIHRlc3QgZmlsZS4="}],
|
||||
"OS-DCF =>diskConfig"=>"MANUAL",
|
||||
"metadata"=>{}}}
|
||||
|
||||
Changes to the args attribute can be saved by executing the `save` method on the `launch_config`. For example if you wanted to change the disk configuration to `AUTO`, you would do the following:
|
||||
|
||||
launch_config.args["server"]["OS-DCF =>diskConfig"] = "AUTO"
|
||||
launch_config.save
|
||||
|
||||
**Note**: If you pass any metadata values in this call, it must be the full set of metadata for the launch configuration, since the underlying API call **overwrites** any existing metadata.
|
||||
|
||||
## Policies
|
||||
|
||||
When an alarm is triggered in Cloud Monitoring, it calls the webhook associated with a particular policy. The policy is designed to update the scaling group to increase or decrease the number of servers in response to the particular alarm.
|
||||
|
||||
To list the policies for a given scaling group use the following:
|
||||
|
||||
policies = group.policies
|
||||
|
||||
### Creating a Policy
|
||||
|
||||
To add a policy to a scaling group use the following:
|
||||
|
||||
group.policies.create :name => 'Scale by one server', :cooldown => 360, :type => 'webhook', :change => 1
|
||||
|
||||
#### Parameters
|
||||
Parameter | Required | Default | Notes
|
||||
---- | ---- | ---- | ----
|
||||
**:name** | yes | |
|
||||
**:type** | yes | | This can be "webhook", "schedule" or "cloud monitoring"
|
||||
**:cooldown** | yes | | Period in seconds after a policy execution in which further events are ignored. This is separate from the overall cooldown for the scaling group.
|
||||
**:change** | no | | Can be positive or negative, which makes this a scale-up or scale-down policy, respectively. If this value is specified you can not specify `:change_percent`.
|
||||
**:change_percent** | no | | The percentage change to the autoscale group's number of units. If this value is specified you can not specify `:change`.
|
||||
**:args** | no | | This is used to specify schedule parameters. Please refer to [Policy documentation](http://docs-internal-staging.rackspace.com/cas/api/v1.0/autoscale-devguide/content/POST_createPolicies_v1.0__tenantId__groups__groupId__policies_Policies.html) for more information.
|
||||
|
||||
### Updating a Policy
|
||||
|
||||
You may update a policy at any time, passing in any or all of the above parameters to change that value. For example, to change the cooldown to 60 seconds, and the number of servers to remove to 3, call:
|
||||
|
||||
policy.cooldown = 60
|
||||
policy.change = 3
|
||||
policy.save
|
||||
|
||||
### Executing a Policy
|
||||
|
||||
You don't need to wait for an alarm to be triggered in Cloud Monitoring in order to execute a particular policy. If desired, you may do so manually by calling the policy's `execute` method:
|
||||
|
||||
policy.execute
|
||||
|
||||
### Deleting a Policy
|
||||
|
||||
To remove a policy, call its `destroy` method:
|
||||
|
||||
policy.destroy
|
||||
|
||||
## Webhooks
|
||||
|
||||
When an alarm is triggered in Cloud Monitoring, it calls the associated webhook, which in turn causes the policy for that webhook to be executed.
|
||||
|
||||
To list the webhooks for a given policy:
|
||||
|
||||
webhooks = policy.webhooks
|
||||
|
||||
|
||||
### Creating a Webhook
|
||||
|
||||
To add a webhook to a policy:
|
||||
|
||||
webhook = policy.webhooks.create :name => 'my-webhook'
|
||||
|
||||
|
||||
The `:name` parameter is required; the `:metadata` parameter is optional. You can retrieve the webhook by executing:
|
||||
|
||||
webhook.execution_url
|
||||
|
||||
### Updating a Webhook
|
||||
|
||||
You may update a webhook at any time to change either its name or its metadata:
|
||||
|
||||
webhook.name = 'webhook1'
|
||||
webhook.metadata = {
|
||||
:owner => 'webteam'
|
||||
}
|
||||
webhook.save
|
||||
|
||||
**Note**: If you pass any metadata values in this call, it must be the full set of metadata for the Webhook, since the underlying API call **overwrites** any existing metadata.
|
||||
|
||||
### Deleting a webhook
|
||||
|
||||
When you wish to remove a webhook, call its `destroy` method:
|
||||
|
||||
webhook.destroy
|
417
lib/fog/rackspace/docs/block_storage.md
Normal file
417
lib/fog/rackspace/docs/block_storage.md
Normal file
|
@ -0,0 +1,417 @@
|
|||
#Cloud Block Storage (BlockStorage)
|
||||
|
||||
This document explains how to get started using Cloud Block Storage with Fog. It assumes you have read the [Getting Started with Fog and the Rackspace Open Cloud](getting_started.md) document.
|
||||
|
||||
## Starting irb console
|
||||
Start by executing the following command:
|
||||
|
||||
irb
|
||||
|
||||
Once `irb` has launched you need to require the Fog library.
|
||||
|
||||
If using Ruby 1.8.x execute:
|
||||
|
||||
require 'rubygems'
|
||||
require 'fog'
|
||||
|
||||
If using Ruby 1.9.x execute:
|
||||
|
||||
require 'fog'
|
||||
|
||||
## Create Service
|
||||
|
||||
Next, create a connection to Cloud Block Storage:
|
||||
|
||||
Using a US-based account:
|
||||
|
||||
service = Fog::Rackspace::BlockStorage.new({
|
||||
:rackspace_username => RACKSPACE_USER_NAME, # Your Rackspace Username
|
||||
:rackspace_api_key => RACKSPACE_API, # Your Rackspace API key
|
||||
:rackspace_region => :ord, # Defaults to :dfw
|
||||
:connection_options => {} # Optional
|
||||
})
|
||||
|
||||
Using a UK-based account:
|
||||
|
||||
service = Fog::Rackspace::BlockStorage.new({
|
||||
:rackspace_username => RACKSPACE_USER_NAME, # Your Rackspace Username
|
||||
:rackspace_api_key => RACKSPACE_API, # Your Rackspace API key
|
||||
:rackspace_auth_url => Fog::Rackspace::UK_AUTH_ENDPOINT,
|
||||
:rackspace_region => :lon,
|
||||
:connection_options => {} # Optional
|
||||
})
|
||||
|
||||
To learn more about obtaining cloud credentials refer to the [Getting Started with Fog and the Rackspace Open Cloud](getting_started.md) document.
|
||||
|
||||
By default `Fog::Rackspace::BlockStorage` will authenticate against the US authentication endpoint and connect to the DFW region. You can specify alternative authentication endpoints using the key `:rackspace_auth_url`. Please refer to [Alternate Authentication Endpoints](http://docs.rackspace.com/auth/api/v2.0/auth-client-devguide/content/Endpoints-d1e180.html) for a list of alternative Rackspace authentication endpoints.
|
||||
|
||||
Alternative regions are specified using the key `:rackspace_region `. A list of regions available for Cloud Block Storage can be found by executing the following:
|
||||
|
||||
identity_service = Fog::Identity({
|
||||
:provider => 'Rackspace', # Rackspace Fog provider
|
||||
:rackspace_username => RACKSPACE_USER_NAME, # Your Rackspace Username
|
||||
:rackspace_api_key => RACKSPACE_API, # Your Rackspace API key
|
||||
:rackspace_auth_url => Fog::Rackspace::UK_AUTH_ENDPOINT # Not specified for US Cloud
|
||||
})
|
||||
|
||||
identity_service.service_catalog.display_service_regions :cloudBlockStorage
|
||||
|
||||
Rackspace Private Cloud installations can skip specifying a region and directly specify their custom service endpoints using the key `:rackspace_block_storage_url`.
|
||||
|
||||
**Note**: A`Fog::Rackspace::BlockStorage` instance is needed for the desired region.
|
||||
|
||||
### Optional Connection Parameters
|
||||
|
||||
Fog supports passing additional connection parameters to its underlying HTTP library (Excon) using the `:connection_options` parameter.
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:connect_timeout</td>
|
||||
<td>Connection timeout (default: 60 seconds)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:read_timeout</td>
|
||||
<td>Read timeout for connection (default: 60 seconds)</td> </tr>
|
||||
<tr>
|
||||
<td>:write_timeout</td>
|
||||
<td>Write timeout for connection (default: 60 seconds)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:proxy</td>
|
||||
<td>Proxy for HTTP and HTTPS connections</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:ssl_ca_path</td>
|
||||
<td>Path to SSL certificate authorities</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:ssl_ca_file</td>
|
||||
<td>SSL certificate authority file</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:ssl_verify_peer</td>
|
||||
<td>SSL verify peer (default: true)</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
## Fog Abstractions
|
||||
|
||||
Fog provides both a **model** and **request** abstraction. The request abstraction provides the most efficient interface and the model abstraction wraps the request abstraction to provide a convenient `ActiveModel` like interface.
|
||||
|
||||
### Request Layer
|
||||
|
||||
The request abstraction maps directly to the [Cloud Block Storage API](http://docs.rackspace.com/cbs/api/v1.0/cbs-devguide/content/overview.html). It provides the most efficient interface to the Rackspace Open Cloud.
|
||||
|
||||
To see a list of requests supported by the service:
|
||||
|
||||
service.requests
|
||||
|
||||
This returns:
|
||||
|
||||
:create_volume, :delete_volume, :get_volume, :list_volumes, :get_volume_type, :list_volume_types, :create_snapshot, :delete_snapshot, :get_snapshot, :list_snapshots
|
||||
|
||||
|
||||
#### Example Request
|
||||
|
||||
To request a list of volume types:
|
||||
|
||||
response = service.list_volume_types
|
||||
|
||||
This returns in the following `Excon::Response`:
|
||||
|
||||
<Excon::Response:0x10a708fb8 @remote_ip="72.32.164.210", @body="{\"volume_types\": [{\"extra_specs\": {}, \"name\": \"SATA\", \"id\": 1}, {\"extra_specs\": {}, \"name\": \"SSD\", \"id\": 2}]}", @status=200, @headers={"Date"=>"Mon, 18 Mar 2013 20:26:03 GMT", "Content-Length"=>"109", "Content-Type"=>"application/json", "X-Compute-Request-Id"=>"req-9c2093d4-8a41-4d8b-a069-114470d1a0dd"}, @data={:status=>200, :headers=>{"Date"=>"Mon, 18 Mar 2013 20:26:03 GMT", "Content-Length"=>"109", "Content-Type"=>"application/json", "X-Compute-Request-Id"=>"req-9c2093d4-8a41-4d8b-a069-114470d1a0dd"}, :remote_ip=>"72.32.164.210", :body=>{"volume_types"=>[{"name"=>"SATA", "id"=>1, "extra_specs"=>{}}, {"name"=>"SSD", "id"=>2, "extra_specs"=>{}}]}}>
|
||||
|
||||
To view the status of the response:
|
||||
|
||||
response.status
|
||||
|
||||
**Note**: Fog is aware of valid HTTP response statuses for each request type. If an unexpected HTTP response status occurs, Fog will raise an exception.
|
||||
|
||||
To view response body:
|
||||
|
||||
response.body
|
||||
|
||||
This will return:
|
||||
|
||||
{"volume_types"=>[{"name"=>"SATA", "id"=>1, "extra_specs"=>{}}, {"name"=>"SSD", "id"=>2, "extra_specs"=>{}}]}
|
||||
|
||||
|
||||
To learn more about Cloud Block Storage request methods refer to [rdoc](http://rubydoc.info/gems/fog/Fog/Rackspace/BlockStorage/Real). To learn more about Excon refer to [Excon GitHub repo](https://github.com/geemus/excon).
|
||||
|
||||
### Model Layer
|
||||
|
||||
Fog models behave in a manner similar to `ActiveModel`. Models will generally respond to `create`, `save`, `persisted?`, `destroy`, `reload` and `attributes` methods. Additionally, fog will automatically create attribute accessors.
|
||||
|
||||
Here is a summary of common model methods:
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Method</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>create</td>
|
||||
<td>
|
||||
Accepts hash of attributes and creates object.<br>
|
||||
Note: creation is a non-blocking call and you will be required to wait for a valid state before using resulting object.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>save</td>
|
||||
<td>Saves object.<br>
|
||||
Note: not all objects support updating object.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>persisted?</td>
|
||||
<td>Returns true if the object has been persisted.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>destroy</td>
|
||||
<td>
|
||||
Destroys object.<br>
|
||||
Note: this is a non-blocking call and object deletion might not be instantaneous.
|
||||
</td>
|
||||
<tr>
|
||||
<td>reload</td>
|
||||
<td>Updates object with latest state from service.</td>
|
||||
<tr>
|
||||
<td>ready?</td>
|
||||
<td>Returns true if object is in a ready state and able to perform actions. This method will raise an exception if object is in an error state.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>attributes</td>
|
||||
<td>Returns a hash containing the list of model attributes and values.</td>
|
||||
</tr>
|
||||
<td>identity</td>
|
||||
<td>
|
||||
Returns the identity of the object.<br>
|
||||
Note: This might not always be equal to object.id.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>wait_for</td>
|
||||
<td>This method periodically reloads model and then yields to specified block until block returns true or a timeout occurs.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
The remainder of this document details the model abstraction.
|
||||
|
||||
|
||||
## List Volume Types
|
||||
|
||||
To retrieve a list of volume types:
|
||||
|
||||
service.volume_types
|
||||
|
||||
This returns a collection of `Fog::Rackspace::BlockStorage::VolumeType` models:
|
||||
|
||||
<Fog::Rackspace::BlockStorage::VolumeTypes
|
||||
[
|
||||
<Fog::Rackspace::BlockStorage::VolumeType
|
||||
id=1,
|
||||
name="SATA",
|
||||
extra_specs={}
|
||||
>,
|
||||
<Fog::Rackspace::BlockStorage::VolumeType
|
||||
id=2,
|
||||
name="SSD",
|
||||
extra_specs={}
|
||||
>
|
||||
]
|
||||
>
|
||||
|
||||
## List Volumes
|
||||
|
||||
To retrieve a list of volumes:
|
||||
|
||||
service.volumes
|
||||
|
||||
This returns a collection of `Fog::Rackspace::BlockStorage::Volume` models:
|
||||
|
||||
<Fog::Rackspace::BlockStorage::Volumes
|
||||
[
|
||||
<Fog::Rackspace::BlockStorage::Volume
|
||||
id="a53a532f-546c-4da3-8c2d-b26be1046630",
|
||||
created_at="2013-03-19T14:19:16.000000",
|
||||
state="available",
|
||||
display_name="fog-ssd",
|
||||
display_description=nil,
|
||||
size=100,
|
||||
attachments=[],
|
||||
volume_type="SSD",
|
||||
availability_zone="nova"
|
||||
>,
|
||||
<Fog::Rackspace::BlockStorage::Volume
|
||||
id="e2359473-9933-483f-90df-deb4a9fb25ae",
|
||||
created_at="2013-03-19T14:16:45.000000",
|
||||
state="available",
|
||||
display_name="fog-example",
|
||||
display_description=nil,
|
||||
size=100,
|
||||
attachments=[],
|
||||
volume_type="SATA",
|
||||
availability_zone="nova"
|
||||
>
|
||||
]
|
||||
>
|
||||
|
||||
## Get Volume
|
||||
|
||||
To retrieve an individual volume:
|
||||
|
||||
service.volume.get "fog-example"
|
||||
|
||||
This returns a `Fog::Rackspace::BlockStorage::Volume`:
|
||||
|
||||
<Fog::Rackspace::BlockStorage::Volume
|
||||
id="e2359473-9933-483f-90df-deb4a9fb25ae",
|
||||
created_at="2013-03-19T14:16:45.000000",
|
||||
state="available",
|
||||
display_name="fog-example",
|
||||
display_description=nil,
|
||||
size=100,
|
||||
attachments=[],
|
||||
volume_type="SATA",
|
||||
availability_zone="nova"
|
||||
>
|
||||
|
||||
## Create Volume
|
||||
|
||||
To create a volume:
|
||||
|
||||
volume = service.volumes.create(:size => 100, :display_name => 'fog-ssd', :volume_type => 'SSD')
|
||||
|
||||
This will return a `Fog::Rackspace::BlockStorage::Volume`:
|
||||
|
||||
<Fog::Rackspace::BlockStorage::Volume
|
||||
id="a53a532f-546c-4da3-8c2d-b26be1046630",
|
||||
created_at="2013-03-19T14:19:16.000000",
|
||||
state="available",
|
||||
display_name="fog-ssd",
|
||||
display_description=nil,
|
||||
size=100,
|
||||
attachments=[],
|
||||
volume_type="SSD",
|
||||
availability_zone="nova"
|
||||
>
|
||||
|
||||
**Note**: The `:size` parameter is the only required parameter and is in gigabytes. Volumes must be a minimum of 100 GB.
|
||||
|
||||
### Additional Parameters
|
||||
|
||||
The `create` method also supports the following key values:
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:display_name</td>
|
||||
<td>The name of the volume.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:display_description</td>
|
||||
<td>A description of the volume.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:snapshot_id</td>
|
||||
<td>The optional snapshot from which to create a volume.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:volume_type</td>
|
||||
<td>The type of volume to create. Refer to <a href="#list-volume-types">List Volume Types</a> section for valid types. SATA is the default volume type.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
## Attach Volume
|
||||
|
||||
Please refer to the [Attach Volume](compute_v2.md#attach-volume) section in the [Next Generation Cloud Servers™ (compute_v2)](compute_v2.md) documentation.
|
||||
|
||||
## Detach Volume
|
||||
|
||||
Please refer to the [Detach Volume](compute_v2.md#detach-volume) section in the [Next Generation Cloud Servers™ (compute_v2)](compute_v2.md) documentation.
|
||||
|
||||
|
||||
## Delete Volume
|
||||
|
||||
To delete a volume:
|
||||
|
||||
volume.destroy
|
||||
|
||||
**Note**: You cannot delete a volume until all of its dependent snapshots have been deleted.
|
||||
|
||||
## List Snapshots
|
||||
|
||||
To retrieve a list of snapshots:
|
||||
|
||||
service.snapshots
|
||||
|
||||
To retrieve a list of snapshots for a given volume:
|
||||
|
||||
volume.snapshots
|
||||
|
||||
## Create Snapshot
|
||||
|
||||
A snapshot is a point-in-time copy of a volume. Each subsequent snapshot will be the difference between the previous snapshot and the current volume.
|
||||
|
||||
To create a snapshot of a given volume:
|
||||
|
||||
volume.create_snapshot :display_name => 'initial-snapshot'
|
||||
|
||||
**Note**: All writes to the volume should be flushed before creating the snapshot, either by unmounting any file systems on the volume or by detaching the volume.
|
||||
|
||||
### Additional Parameters
|
||||
|
||||
The `create_snapshot` method also supports the following key values:
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:display_name</td>
|
||||
<td>The name of the snapshot.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:display_description</td>
|
||||
<td>A description of the snapshot.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:force</td>
|
||||
<td>If set to true, snapshot will be taken even if volume is still mounted.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
## Delete Snapshot
|
||||
|
||||
To delete a snapshot:
|
||||
|
||||
snapshot.destroy
|
||||
|
||||
## Examples
|
||||
|
||||
Example code using Cloud Block Storage can be found [here](https://github.com/fog/fog/tree/master/lib/fog/rackspace/examples).
|
||||
|
||||
## Additional Resources
|
||||
|
||||
* [fog.io](http://fog.io/)
|
||||
* [Fog rdoc](http://rubydoc.info/gems/fog/)
|
||||
* [Fog Github repo](https://github.com/fog/fog)
|
||||
* [Fog Github Issues](https://github.com/fog/fog/issues)
|
||||
* [Excon Github repo](https://github.com/geemus/excon)
|
||||
* [Cloud Block Storage API](http://docs.rackspace.com/cbs/api/v1.0/cbs-devguide/content/index.html)
|
||||
|
||||
## Support and Feedback
|
||||
|
||||
Your feedback is appreciated! If you have specific issues with the **fog** SDK, you should file an [issue via Github](https://github.com/fog/fog/issues).
|
||||
|
||||
For general feedback and support requests, send an email to: <sdk-support@rackspace.com>.
|
719
lib/fog/rackspace/docs/compute_v2.md
Normal file
719
lib/fog/rackspace/docs/compute_v2.md
Normal file
|
@ -0,0 +1,719 @@
|
|||
#Next Generation Cloud Servers™ (compute_v2)
|
||||
|
||||
This document explains how to get started using Next Generation Cloud Servers with Fog. It assumes you have read the [Getting Started with Fog and the Rackspace Open Cloud](getting_started.md) document.
|
||||
|
||||
**Note**: Fog also provides an interface to First Gen Cloud Servers™ (compute). The compute interface is deprecated and should only be used if you need to interact with our first generation cloud. Fog determines the appropriate interface based on the `:version` parameter. See [Create Service](#create-service) section for more information.
|
||||
|
||||
## Starting irb console
|
||||
|
||||
Start by executing the following command:
|
||||
|
||||
irb
|
||||
|
||||
Once `irb` has launched you need to require the Fog library.
|
||||
|
||||
If using Ruby 1.8.x execute:
|
||||
|
||||
require 'rubygems'
|
||||
require 'fog'
|
||||
|
||||
If using Ruby 1.9.x execute:
|
||||
|
||||
require 'fog'
|
||||
|
||||
## Create Service
|
||||
|
||||
Next, create a connection to the Next Gen Cloud Servers:
|
||||
|
||||
Using a US-based account:
|
||||
|
||||
service = Fog::Compute.new({
|
||||
:provider => 'Rackspace', # Rackspace Fog provider
|
||||
:rackspace_username => RACKSPACE_USER_NAME, # Your Rackspace Username
|
||||
:rackspace_api_key => RACKSPACE_API, # Your Rackspace API key
|
||||
:version => :v2, # Use Next Gen Cloud Servers
|
||||
:rackspace_region => :ord, # Defaults to :dfw
|
||||
:connection_options => {} # Optional
|
||||
})
|
||||
|
||||
Using a UK-based account:
|
||||
|
||||
service = Fog::Compute.new({
|
||||
:provider => 'Rackspace', # Rackspace Fog provider
|
||||
:rackspace_username => RACKSPACE_USER_NAME, # Your Rackspace Username
|
||||
:rackspace_api_key => RACKSPACE_API, # Your Rackspace API key
|
||||
:version => :v2, # Use Next Gen Cloud Servers
|
||||
:rackspace_auth_url => Fog::Rackspace::UK_AUTH_ENDPOINT,
|
||||
:rackspace_region => :lon,
|
||||
:connection_options => {} # Optional
|
||||
})
|
||||
|
||||
To learn more about obtaining cloud credentials refer to the [Getting Started with Fog and the Rackspace Open Cloud](getting_started.md) document.
|
||||
|
||||
By default `Fog::Compute` will authenticate against the US authentication endpoint and connect to the DFW region. You can specify alternative authentication endpoints using the key `:rackspace_auth_url`. Please refer to [Alternate Authentication Endpoints](http://docs.rackspace.com/auth/api/v2.0/auth-client-devguide/content/Endpoints-d1e180.html) for a list of alternative Rackspace authentication endpoints.
|
||||
|
||||
Alternative regions are specified using the key `:rackspace_region `. A list of regions available for Cloud Servers can be found by executing the following:
|
||||
|
||||
identity_service = Fog::Identity({
|
||||
:provider => 'Rackspace', # Rackspace Fog provider
|
||||
:rackspace_username => RACKSPACE_USER_NAME, # Your Rackspace Username
|
||||
:rackspace_api_key => RACKSPACE_API, # Your Rackspace API key
|
||||
:rackspace_auth_url => Fog::Rackspace::UK_AUTH_ENDPOINT # Not specified for US Cloud
|
||||
})
|
||||
|
||||
identity_service.service_catalog.display_service_regions :cloudServersOpenStack
|
||||
|
||||
Rackspace Private Cloud installations can skip specifying a region and directly specify their custom service endpoints using the key `:rackspace_compute_url`.
|
||||
|
||||
**Note**: A`Fog::Compute` instance is needed for the desired region.
|
||||
|
||||
### Optional Connection Parameters
|
||||
|
||||
Fog supports passing additional connection parameters to its underlying HTTP library (Excon) using the `:connection_options` parameter.
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:connect_timeout</td>
|
||||
<td>Connection timeout (default: 60 seconds)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:read_timeout</td>
|
||||
<td>Read timeout for connection (default: 60 seconds)</td> </tr>
|
||||
<tr>
|
||||
<td>:write_timeout</td>
|
||||
<td>Write timeout for connection (default: 60 seconds)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:proxy</td>
|
||||
<td>Proxy for HTTP and HTTPS connections</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:ssl_ca_path</td>
|
||||
<td>Path to SSL certificate authorities</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:ssl_ca_file</td>
|
||||
<td>SSL certificate authority file</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:ssl_verify_peer</td>
|
||||
<td>SSL verify peer (default: true)</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
## Fog Abstractions
|
||||
|
||||
Fog provides both a **model** and **request** abstraction. The request abstraction provides the most efficient interface and the model abstraction wraps the request abstraction to provide a convenient `ActiveModel` like interface.
|
||||
|
||||
### Request Layer
|
||||
|
||||
The request abstraction maps directly to the [Next Gen Cloud Servers API](http://docs.rackspace.com/servers/api/v2/cs-devguide/content/ch_preface.html). It provides the most efficient interface to the Rackspace Open Cloud.
|
||||
|
||||
To see a list of requests supported by the service:
|
||||
|
||||
service.requests
|
||||
|
||||
This returns:
|
||||
|
||||
:list_servers, :get_server, :create_server, :update_server, :delete_server, :change_server_password, :reboot_server, :rebuild_server, :resize_server, :confirm_resize_server, :revert_resize_server, :list_images, :get_image, :list_flavors, :get_flavor, :attach_volume, :get_attachment, :list_attachments, :delete_attachment
|
||||
|
||||
|
||||
#### Example Request
|
||||
|
||||
To request a list of flavors:
|
||||
|
||||
response = service.list_flavors
|
||||
|
||||
This returns in the following `Excon::Response`:
|
||||
|
||||
<Excon::Response:0x007fe4b2ea2f38 @body={"flavors"=>[{"id"=>"2", "links"=>[{"href"=>"https://ord.servers.api.rackspacecloud.com/v2/772045/flavors/2", "rel"=>"self"}, {"href"=>"https://ord.servers.api.rackspacecloud.com/772045/flavors/2", "rel"=>"bookmark"}], "name"=>"512MB Standard Instance"}, {"id"=>"3", "links"=>[{"href"=>"https://ord.servers.api.rackspacecloud.com/v2/772045/flavors/3", "rel"=>"self"}, {"href"=>"https://ord.servers.api.rackspacecloud.com/772045/flavors/3", "rel"=>"bookmark"}], "name"=>"1GB Standard Instance"}, {"id"=>"4", "links"=>[{"href"=>"https://ord.servers.api.rackspacecloud.com/v2/772045/flavors/4", "rel"=>"self"}, {"href"=>"https://ord.servers.api.rackspacecloud.com/772045/flavors/4", "rel"=>"bookmark"}], "name"=>"2GB Standard Instance"}, {"id"=>"5", "links"=>[{"href"=>"https://ord.servers.api.rackspacecloud.com/v2/772045/flavors/5", "rel"=>"self"}, {"href"=>"https://ord.servers.api.rackspacecloud.com/772045/flavors/5", "rel"=>"bookmark"}], "name"=>"4GB Standard Instance"}, {"id"=>"6", "links"=>[{"href"=>"https://ord.servers.api.rackspacecloud.com/v2/772045/flavors/6", "rel"=>"self"}, {"href"=>"https://ord.servers.api.rackspacecloud.com/772045/flavors/6", "rel"=>"bookmark"}], "name"=>"8GB Standard Instance"}, {"id"=>"7", "links"=>[{"href"=>"https://ord.servers.api.rackspacecloud.com/v2/772045/flavors/7", "rel"=>"self"}, {"href"=>"https://ord.servers.api.rackspacecloud.com/772045/flavors/7", "rel"=>"bookmark"}], "name"=>"15GB Standard Instance"}, {"id"=>"8", "links"=>[{"href"=>"https://ord.servers.api.rackspacecloud.com/v2/772045/flavors/8", "rel"=>"self"}, {"href"=>"https://ord.servers.api.rackspacecloud.com/772045/flavors/8", "rel"=>"bookmark"}], "name"=>"30GB Standard Instance"}]}, @headers={"Date"=>"Mon, 21 Jan 2013 16:14:45 GMT", "Content-Length"=>"1697", "Content-Type"=>"application/json", "X-Compute-Request-Id"=>"req-0a1e8532-19b3-4993-8b48-cf2d9efe078c", "Server"=>"Jetty(8.0.y.z-SNAPSHOT)"}, @status=200>
|
||||
|
||||
To view the status of the response:
|
||||
|
||||
response.status
|
||||
|
||||
**Note**: Fog is aware of valid HTTP response statuses for each request type. If an unexpected HTTP response status occurs, Fog will raise an exception.
|
||||
|
||||
To view response body:
|
||||
|
||||
response.body
|
||||
|
||||
This will return:
|
||||
|
||||
{"flavors"=>[{"id"=>"2", "links"=>[{"href"=>"https://ord.servers.api.rackspacecloud.com/v2/772045/flavors/2", "rel"=>"self"}, {"href"=>"https://ord.servers.api.rackspacecloud.com/772045/flavors/2", "rel"=>"bookmark"}], "name"=>"512MB Standard Instance"}, {"id"=>"3", "links"=>[{"href"=>"https://ord.servers.api.rackspacecloud.com/v2/772045/flavors/3", "rel"=>"self"}, {"href"=>"https://ord.servers.api.rackspacecloud.com/772045/flavors/3", "rel"=>"bookmark"}], "name"=>"1GB Standard Instance"}, {"id"=>"4", "links"=>[{"href"=>"https://ord.servers.api.rackspacecloud.com/v2/772045/flavors/4", "rel"=>"self"}, {"href"=>"https://ord.servers.api.rackspacecloud.com/772045/flavors/4", "rel"=>"bookmark"}], "name"=>"2GB Standard Instance"}, {"id"=>"5", "links"=>[{"href"=>"https://ord.servers.api.rackspacecloud.com/v2/772045/flavors/5", "rel"=>"self"}, {"href"=>"https://ord.servers.api.rackspacecloud.com/772045/flavors/5", "rel"=>"bookmark"}], "name"=>"4GB Standard Instance"}, {"id"=>"6", "links"=>[{"href"=>"https://ord.servers.api.rackspacecloud.com/v2/772045/flavors/6", "rel"=>"self"}, {"href"=>"https://ord.servers.api.rackspacecloud.com/772045/flavors/6", "rel"=>"bookmark"}], "name"=>"8GB Standard Instance"}, {"id"=>"7", "links"=>[{"href"=>"https://ord.servers.api.rackspacecloud.com/v2/772045/flavors/7", "rel"=>"self"}, {"href"=>"https://ord.servers.api.rackspacecloud.com/772045/flavors/7", "rel"=>"bookmark"}], "name"=>"15GB Standard Instance"}, {"id"=>"8", "links"=>[{"href"=>"https://ord.servers.api.rackspacecloud.com/v2/772045/flavors/8", "rel"=>"self"}, {"href"=>"https://ord.servers.api.rackspacecloud.com/772045/flavors/8", "rel"=>"bookmark"}], "name"=>"30GB Standard Instance"}]}
|
||||
|
||||
|
||||
To learn more about Compute request methods refer to [rdoc](http://rubydoc.info/gems/fog/Fog/Compute/Rackspace/Real). To learn more about Excon refer to [Excon GitHub repo](https://github.com/geemus/excon).
|
||||
|
||||
### Model Layer
|
||||
|
||||
Fog models behave in a manner similar to `ActiveModel`. Models will generally respond to `create`, `save`, `persisted?`, `destroy`, `reload` and `attributes` methods. Additionally, fog will automatically create attribute accessors.
|
||||
|
||||
Here is a summary of common model methods:
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Method</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>create</td>
|
||||
<td>
|
||||
Accepts hash of attributes and creates object.<br>
|
||||
Note: creation is a non-blocking call and you will be required to wait for a valid state before using resulting object.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>save</td>
|
||||
<td>Saves object.<br>
|
||||
Note: not all objects support updating object.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>persisted?</td>
|
||||
<td>Returns true if the object has been persisted.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>destroy</td>
|
||||
<td>
|
||||
Destroys object.<br>
|
||||
Note: this is a non-blocking call and object deletion might not be instantaneous.
|
||||
</td>
|
||||
<tr>
|
||||
<td>reload</td>
|
||||
<td>Updates object with latest state from service.</td>
|
||||
<tr>
|
||||
<td>ready?</td>
|
||||
<td>Returns true if object is in a ready state and able to perform actions. This method will raise an exception if object is in an error state.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>attributes</td>
|
||||
<td>Returns a hash containing the list of model attributes and values.</td>
|
||||
</tr>
|
||||
<td>identity</td>
|
||||
<td>
|
||||
Returns the identity of the object.<br>
|
||||
Note: This might not always be equal to object.id.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>wait_for</td>
|
||||
<td>This method periodically reloads model and then yields to specified block until block returns true or a timeout occurs.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
The remainder of this document details the model abstraction.
|
||||
|
||||
## List Images
|
||||
|
||||
To retrieve a list of available images:
|
||||
|
||||
service.images
|
||||
|
||||
This returns a collection of `Fog::Compute::RackspaceV2::Image` models:
|
||||
|
||||
<Fog::Compute::RackspaceV2::Images
|
||||
[
|
||||
<Fog::Compute::RackspaceV2::Image
|
||||
id="8a3a9f96-b997-46fd-b7a8-a9e740796ffd",
|
||||
name="Ubuntu 12.10 (Quantal Quetzal)",
|
||||
created=nil,
|
||||
updated=nil,
|
||||
state=nil,
|
||||
user_id=nil,
|
||||
tenant_id=nil,
|
||||
progress=nil,
|
||||
minDisk=nil,
|
||||
minRam=nil,
|
||||
metadata=nil,
|
||||
disk_config=nil,
|
||||
links=[{"href"=>"https://ord.servers.api.rackspacecloud.com/v2/772045/images/8a3a9f96-b997-46fd-b7a8-a9e740796ffd", "rel"=>"self"}, {"href"=>"https://ord.servers.api.rackspacecloud.com/772045/images/8a3a9f96-b997-46fd-b7a8-a9e740796ffd", "rel"=>"bookmark"}, {"href"=>"https://ord.images.api.rackspacecloud.com/772045/images/8a3a9f96-b997-46fd-b7a8-a9e740796ffd", "type"=>"application/vnd.openstack.image", "rel"=>"alternate"}]
|
||||
>,
|
||||
<Fog::Compute::RackspaceV2::Image
|
||||
id="992ba82c-083b-4eed-9c26-c54473686466",
|
||||
name="Windows Server 2012 + SharePoint Foundation 2013 with SQL Server 2012 Standard",
|
||||
created=nil,
|
||||
updated=nil,
|
||||
state=nil,
|
||||
user_id=nil,
|
||||
tenant_id=nil,
|
||||
progress=nil,
|
||||
minDisk=nil,
|
||||
minRam=nil,
|
||||
metadata=nil,
|
||||
disk_config=nil,
|
||||
links=[{"href"=>"https://ord.servers.api.rackspacecloud.com/v2/772045/images/992ba82c-083b-4eed-9c26-c54473686466", "rel"=>"self"}, {"href"=>"https://ord.servers.api.rackspacecloud.com/772045/images/992ba82c-083b-4eed-9c26-c54473686466", "rel"=>"bookmark"}, {"href"=>"https://ord.images.api.rackspacecloud.com/772045/images/992ba82c-083b-4eed-9c26-c54473686466", "type"=>"application/vnd.openstack.image", "rel"=>"alternate"}]
|
||||
>,
|
||||
…
|
||||
|
||||
## Get Image
|
||||
|
||||
To retrieve individual image:
|
||||
|
||||
service.images.get "8a3a9f96-b997-46fd-b7a8-a9e740796ffd"
|
||||
|
||||
This returns an `Fog::Compute::RackspaceV2::Image` instance:
|
||||
|
||||
<Fog::Compute::RackspaceV2::Image
|
||||
id="8a3a9f96-b997-46fd-b7a8-a9e740796ffd",
|
||||
name="Ubuntu 12.10 (Quantal Quetzal)",
|
||||
created="2012-11-27T15:27:08Z",
|
||||
updated="2012-11-28T14:35:21Z",
|
||||
state="ACTIVE",
|
||||
user_id=nil,
|
||||
tenant_id=nil,
|
||||
progress=100,
|
||||
minDisk=10,
|
||||
minRam=512,
|
||||
metadata={"os_distro"=>"ubuntu", "com.rackspace__1__visible_core"=>"1", "com.rackspace__1__build_rackconnect"=>"1", "auto_disk_config"=>"True", "com.rackspace__1__options"=>"0", "image_type"=>"base", "org.openstack__1__os_version"=>"12.10", "os_version"=>"12.10", "rax_options"=>"0", "com.rackspace__1__visible_rackconnect"=>"1", "org.openstack__1__os_distro"=>"org.ubuntu", "com.rackspace__1__visible_managed"=>"1", "com.rackspace__1__build_core"=>"1", "arch"=>"x86-64", "os_type"=>"linux", "org.openstack__1__architecture"=>"x64", "com.rackspace__1__build_managed"=>"1"},
|
||||
disk_config="AUTO",
|
||||
links=[{"href"=>"https://ord.servers.api.rackspacecloud.com/v2/772045/images/8a3a9f96-b997-46fd-b7a8-a9e740796ffd", "rel"=>"self"}, {"href"=>"https://ord.servers.api.rackspacecloud.com/772045/images/8a3a9f96-b997-46fd-b7a8-a9e740796ffd", "rel"=>"bookmark"}, {"href"=>"https://ord.images.api.rackspacecloud.com/772045/images/8a3a9f96-b997-46fd-b7a8-a9e740796ffd", "type"=>"application/vnd.openstack.image", "rel"=>"alternate"}]
|
||||
>
|
||||
|
||||
## List Flavors
|
||||
|
||||
To retrieve a list of available flavors:
|
||||
|
||||
service.flavors
|
||||
|
||||
This returns a collection of `Fog::Compute::RackspaceV2::Flavor` models:
|
||||
|
||||
<Fog::Compute::RackspaceV2::Flavors
|
||||
[
|
||||
<Fog::Compute::RackspaceV2::Flavor
|
||||
id="2",
|
||||
name="512MB Standard Instance",
|
||||
ram=nil,
|
||||
disk=nil,
|
||||
vcpus=nil,
|
||||
links=[{"href"=>"https://dfw.servers.api.rackspacecloud.com/v2/772045/flavors/2", "rel"=>"self"}, {"href"=>"https://dfw.servers.api.rackspacecloud.com/772045/flavors/2", "rel"=>"bookmark"}]
|
||||
>,
|
||||
<Fog::Compute::RackspaceV2::Flavor
|
||||
id="3",
|
||||
name="1GB Standard Instance",
|
||||
ram=nil,
|
||||
disk=nil,
|
||||
vcpus=nil,
|
||||
links=[{"href"=>"https://dfw.servers.api.rackspacecloud.com/v2/772045/flavors/3", "rel"=>"self"}, {"href"=>"https://dfw.servers.api.rackspacecloud.com/772045/flavors/3", "rel"=>"bookmark"}]
|
||||
>,
|
||||
…
|
||||
|
||||
|
||||
## Get Flavor
|
||||
|
||||
To retrieve individual flavor:
|
||||
|
||||
service.flavor.get 2
|
||||
|
||||
This returns a `Fog::Compute::RackspaceV2::Flavor` instance:
|
||||
|
||||
<Fog::Compute::RackspaceV2::Flavor
|
||||
id="2",
|
||||
name="512MB Standard Instance",
|
||||
ram=512,
|
||||
disk=20,
|
||||
vcpus=1,
|
||||
links=[{"href"=>"https://dfw.servers.api.rackspacecloud.com/v2/772045/flavors/2", "rel"=>"self"}, {"href"=>"https://dfw.servers.api.rackspacecloud.com/772045/flavors/2", "rel"=>"bookmark"}]
|
||||
>
|
||||
|
||||
|
||||
## List Servers
|
||||
|
||||
To retrieve a list of available servers:
|
||||
|
||||
service.servers
|
||||
|
||||
This returns a collection of `Fog::Compute::RackspaceV2::Servers` models:
|
||||
|
||||
<Fog::Compute::RackspaceV2::Servers
|
||||
[
|
||||
<Fog::Compute::RackspaceV2::Server
|
||||
id="6a273531-8ee4-4bef-ad1a-baca963f8bbb",
|
||||
name="rax-example",
|
||||
created="2013-01-17T22:28:14Z",
|
||||
updated="2013-01-17T22:31:19Z",
|
||||
host_id="7361c18d94a9933039dae57ae07b0a39fdb39ea3775a25329086531f",
|
||||
state="ACTIVE",
|
||||
progress=100,
|
||||
user_id="296063",
|
||||
tenant_id="772045",
|
||||
links=[{"href"=>"https://dfw.servers.api.rackspacecloud.com/v2/772045/servers/6a273531-8ee4-4bef-ad1a-baca963f8bbb", "rel"=>"self"}, {"href"=>"https://dfw.servers.api.rackspacecloud.com/772045/servers/6a273531-8ee4-4bef-ad1a-baca963f8bbb", "rel"=>"bookmark"}],
|
||||
metadata={},
|
||||
personality=nil,
|
||||
ipv4_address="198.101.255.186",
|
||||
ipv6_address="2001:4800:780e:0510:0fe1:75e8:ff04:c4a0",
|
||||
disk_config="AUTO",
|
||||
bandwidth=[],
|
||||
addresses={"public"=>[{"version"=>4, "addr"=>"198.101.255.186"}, {"version"=>6, "addr"=>"2001:4800:780e:0510:0fe1:75e8:ff04:c4a0"}], "private"=>[{"version"=>4, "addr"=>"10.180.22.165"}]},
|
||||
flavor_id="2",
|
||||
image_id="33e21646-43ed-407e-9dbf-7c7873fccd9a"
|
||||
>,
|
||||
…
|
||||
|
||||
## Get Server
|
||||
|
||||
To return an individual server:
|
||||
|
||||
service.servers.get "6a273531-8ee4-4bef-ad1a-baca963f8bbb"
|
||||
|
||||
This returns a `Fog::Compute::RackspaceV2::Server` instance:
|
||||
|
||||
<Fog::Compute::RackspaceV2::Servers
|
||||
[
|
||||
<Fog::Compute::RackspaceV2::Server
|
||||
id="6a273531-8ee4-4bef-ad1a-baca963f8bbb",
|
||||
name="rax-example",
|
||||
created="2013-01-17T22:28:14Z",
|
||||
updated="2013-01-17T22:31:19Z",
|
||||
host_id="7361c18d94a9933039dae57ae07b0a39fdb39ea3775a25329086531f",
|
||||
state="ACTIVE",
|
||||
progress=100,
|
||||
user_id="296063",
|
||||
tenant_id="772045",
|
||||
links=[{"href"=>"https://dfw.servers.api.rackspacecloud.com/v2/772045/servers/6a273531-8ee4-4bef-ad1a-baca963f8bbb", "rel"=>"self"}, {"href"=>"https://dfw.servers.api.rackspacecloud.com/772045/servers/6a273531-8ee4-4bef-ad1a-baca963f8bbb", "rel"=>"bookmark"}],
|
||||
metadata={},
|
||||
personality=nil,
|
||||
ipv4_address="198.101.255.186",
|
||||
ipv6_address="2001:4800:780e:0510:0fe1:75e8:ff04:c4a0",
|
||||
disk_config="AUTO",
|
||||
bandwidth=[],
|
||||
addresses={"public"=>[{"version"=>4, "addr"=>"198.101.255.186"}, {"version"=>6, "addr"=>"2001:4800:780e:0510:0fe1:75e8:ff04:c4a0"}], "private"=>[{"version"=>4, "addr"=>"10.180.22.165"}]},
|
||||
flavor_id="2",
|
||||
image_id="33e21646-43ed-407e-9dbf-7c7873fccd9a"
|
||||
>,
|
||||
...
|
||||
|
||||
## Create Server
|
||||
|
||||
If you are interested in creating a server utilizing ssh key authenication, you are recommended to use [bootstrap](#bootstrap) method.
|
||||
|
||||
To create a server:
|
||||
|
||||
flavor = service.flavors.first
|
||||
image = service.images.first
|
||||
server = service.servers.create(:name => 'fog-doc', :flavor_id => flavor.id, :image_id => image.id)
|
||||
|
||||
**Note**: The `:name`, `:flavor_id`, and `image_id` attributes are required for server creation.
|
||||
|
||||
This will return a `Fog::Compute::RackspaceV2::Server` instance:
|
||||
|
||||
<Fog::Compute::RackspaceV2::Server
|
||||
id="8ff308a6-e04a-4602-b991-ed526ab3b6be",
|
||||
name="fog-server",
|
||||
created=nil,
|
||||
updated=nil,
|
||||
host_id=nil,
|
||||
state=nil,
|
||||
progress=nil,
|
||||
user_id=nil,
|
||||
tenant_id=nil,
|
||||
links=[{"href"=>"https://dfw.servers.api.rackspacecloud.com/v2/772045/servers/8ff308a6-e04a-4602-b991-ed526ab3b6be", "rel"=>"self"}, {"href"=>"https://dfw.servers.api.rackspacecloud.com/772045/servers/8ff308a6-e04a-4602-b991-ed526ab3b6be", "rel"=>"bookmark"}],
|
||||
metadata=nil,
|
||||
personality=nil,
|
||||
ipv4_address=nil,
|
||||
ipv6_address=nil,
|
||||
disk_config="AUTO",
|
||||
bandwidth=nil,
|
||||
addresses=nil,
|
||||
flavor_id=2,
|
||||
image_id="3afe97b2-26dc-49c5-a2cc-a2fc8d80c001"
|
||||
>
|
||||
|
||||
Notice that your server contains several `nil` attributes. To see the latest status, reload the instance as follows:
|
||||
|
||||
server.reload
|
||||
|
||||
You can see that the server is currently 17% built:
|
||||
|
||||
Fog::Compute::RackspaceV2::Server
|
||||
id="8ff308a6-e04a-4602-b991-ed526ab3b6be",
|
||||
name="fog-server",
|
||||
created="2013-01-18T16:15:41Z",
|
||||
updated="2013-01-18T16:16:14Z",
|
||||
host_id="775837108e45aa3f2a58527c9c3b6160838078e83148f07906c933ca",
|
||||
state="BUILD",
|
||||
progress=17,
|
||||
user_id="296063",
|
||||
tenant_id="772045",
|
||||
links=[{"href"=>"https://dfw.servers.api.rackspacecloud.com/v2/772045/servers/8ff308a6-e04a-4602-b991-ed526ab3b6be", "rel"=>"self"}, {"href"=>"https://dfw.servers.api.rackspacecloud.com/772045/servers/8ff308a6-e04a-4602-b991-ed526ab3b6be", "rel"=>"bookmark"}],
|
||||
metadata={},
|
||||
personality=nil,
|
||||
ipv4_address="",
|
||||
ipv6_address="",
|
||||
disk_config="AUTO",
|
||||
bandwidth=[],
|
||||
addresses={"public"=>[{"version"=>4, "addr"=>"198.61.209.78"}, {"version"=>6, "addr"=>"2001:4800:7810:0512:0fe1:75e8:ff04:94e4"}], "private"=>[{"version"=>4, "addr"=>"10.181.13.198"}]},
|
||||
flavor_id="2",
|
||||
image_id="3afe97b2-26dc-49c5-a2cc-a2fc8d80c001"
|
||||
>
|
||||
|
||||
You will be unable to perform any actions to this server until it reaches an `ACTIVE` state. Since this is true for most server actions, Fog provides the convenience method `wait_for`.
|
||||
|
||||
Fog can wait for the server to become ready as follows:
|
||||
|
||||
server.wait_for { ready? }
|
||||
|
||||
**Note**: The `Fog::Compute::RackspaceV2::Server` instance returned from the create method contains a `password` attribute. The `password` attribute will NOT be present in subsequent retrievals either through `service.servers` or `server.servers.get my_server_id`.
|
||||
|
||||
### Additional Parameters
|
||||
|
||||
The `create` method also supports the following key values:
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:disk_config</td>
|
||||
<td>The disk configuration value (AUTO or MANUAL). Refer to Next Gen Server API documentation - <a href="http://docs.rackspace.com/servers/api/v2/cs-devguide/content/ch_extensions.html#diskconfig_attribute">Disk Configuration Extension</a>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:metadata</td>
|
||||
<td>Hash containing server metadata.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:personality</td>
|
||||
<td>Array of files to be injected onto the server. Please refer to the Fog <a href="http://rubydoc.info/github/fog/fog/Fog/Compute/RackspaceV2/Server:personality">personality </a> API documentation for further information.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:config_drive</td>
|
||||
<td>Whether a read-only configuration drive is attached. Refer to Next Gen Server API documentation - <a
|
||||
href="http://docs.rackspace.com/servers/api/v2/cs-devguide/content/config_drive_ext.html">Config Drive Extension</a>.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
## Bootstrap
|
||||
|
||||
In addition to the `create` method, Fog provides a `bootstrap` method which creates a server and then performs the following actions via ssh:
|
||||
|
||||
1. Create `ROOT_USER/.ssh/authorized_keys` file using the ssh key specified in `:public_key_path`.
|
||||
2. Lock password for root user using `passwd -l root`.
|
||||
3. Create `ROOT_USER/attributes.json` file with the contents of `server.attributes`.
|
||||
4. Create `ROOT_USER/metadata.json` file with the contents of `server.metadata`.
|
||||
|
||||
**Note**: Unlike the `create` method, `bootstrap` is blocking method call. If non-blocking behavior is desired, developers should use the `:personality` parameter on the `create` method.
|
||||
|
||||
The following example demonstrates bootstraping a server:
|
||||
|
||||
service.servers.bootstrap :name => 'bootstrap-server',
|
||||
:flavor_id => service.flavors.first.id,
|
||||
:image_id => service.images.find {|img| img.name =~ /Ubuntu/}.id,
|
||||
:public_key_path => '~/.ssh/fog_rsa.pub',
|
||||
:private_key_path => '~/.ssh/fog_rsa'
|
||||
|
||||
**Note**: The `:name`, `:flavor_id`, `:image_id`, `:public_key_path`, `:private_key_path` are required for the `bootstrap` method.
|
||||
|
||||
The `bootstrap` method uses the same additional parameters as the `create` method. Refer to the [Additional Parameters](#additional-parameters) section for more information.
|
||||
|
||||
## SSH
|
||||
|
||||
Once a server has been created and set up for ssh key authentication, fog can execute remote commands as follows:
|
||||
|
||||
result = server.ssh ['pwd']
|
||||
|
||||
This will return the following:
|
||||
|
||||
[#<Fog::SSH::Result:0x1108241d0 @stderr="", @status=0, @stdout="/root\r\n", @command="pwd">]
|
||||
|
||||
**Note**: SSH key authentication can be set up using `bootstrap` method or by using the `:personality` attribute on the `:create` method. See [Bootstrap](#bootstrap) or [Create Server](#create-server) for more information.
|
||||
|
||||
## Update Server
|
||||
|
||||
Next Gen Cloud Servers support updating the following attributes `name`, `access_ipv4_address`, and `access_ipv6_address`.
|
||||
|
||||
To update these attributes:
|
||||
|
||||
server.name = "batman"
|
||||
server.access_ipv4_address = "10.0.0.1"
|
||||
server.access_ipv6_address = "fdbb:1717:4533:7c89:0:0:0:1"
|
||||
server.save
|
||||
|
||||
Additional information about server access addresses can be found [here](http://docs.rackspace.com/servers/api/v2/cs-devguide/content/Server_Primary_Addresses-d1e2558.html).
|
||||
|
||||
**Note**: Updating the server name does not change the host name. Names are not guaranteed to be unique.
|
||||
|
||||
## Delete Server
|
||||
|
||||
To delete a server:
|
||||
|
||||
server.destroy
|
||||
|
||||
**Note**: The server is not immediately destroyed, but it does occur shortly there after.
|
||||
|
||||
## Metadata
|
||||
|
||||
You can access metadata as an attribute on both `Fog::Compute::RackspaceV2::Server` and `Fog::Compute::RackspaceV2::Metadata::Image`. You can specify metadata during creation of a server or an image. Please refer to [Create Server](#create-server) or [Create Image](#create-image) sections for more information.
|
||||
|
||||
This example demonstrates how to iterate through a server's metadata:
|
||||
|
||||
server.metadata.each {|metadatum| puts "#{metadatum.key}: #{metadatum.value}" }
|
||||
|
||||
You can update and retrieve metadata in a manner similar to a hash:
|
||||
|
||||
server.metadata["os_type"]
|
||||
|
||||
server.metadata["installed_ruby"] = "MRI 1.9.3"
|
||||
|
||||
Metadata also responds to `save` and `reload` as follows:
|
||||
|
||||
server.metadata.save
|
||||
|
||||
server.metadata.reload
|
||||
|
||||
|
||||
## Change Admin Password
|
||||
|
||||
To change the administrator password:
|
||||
|
||||
server.change_admin_password "superSecure"
|
||||
|
||||
## Reboot
|
||||
|
||||
To perform a soft reboot:
|
||||
|
||||
server.reboot
|
||||
|
||||
To perform a hard reboot:
|
||||
|
||||
server.reboot 'HARD'
|
||||
|
||||
## Rebuild
|
||||
|
||||
Rebuild removes all data on the server and replaces it with the specified image. The id and all IP addresses remain the same.
|
||||
|
||||
To rebuild a server:
|
||||
|
||||
image = service.images.first
|
||||
server.rebuild image.id
|
||||
|
||||
Additionally, the `rebuild` method will take a second parameter containing a hash with the following values:
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:name</td>
|
||||
<td>Name of Server</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:flavorRef</td>
|
||||
<td>Flavor id</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:accessIPv4</td>
|
||||
<td>IPv4 access address</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:accessIPv6</td>
|
||||
<td>IPv6 access address</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:metadata</td>
|
||||
<td>Hash containing server metadata</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:personality</td>
|
||||
<td>File path and contents. Refer to Next Gen Server API documentation - <a href="http://docs.rackspace.com/servers/api/v2/cs-devguide/content/Server_Personality-d1e2543.html">Server Personality</a>. </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:disk_config</td>
|
||||
<td>The disk configuration value (AUTO or MANUAL). Refer to Next Gen Server API documentation - <a href="http://docs.rackspace.com/servers/api/v2/cs-devguide/content/ch_extensions.html#diskconfig_attribute">Disk Configuration Extension</a>.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
## Resize
|
||||
|
||||
Resizing a server allows you to change the resources dedicated to the server.
|
||||
|
||||
To resize a server:
|
||||
|
||||
flavor_id = service.flavor[2].id
|
||||
server.resize flavor_id #flavor_id should be your desired flavor
|
||||
|
||||
During the resize process the server will have a state of `RESIZE`. Once a server has completed resizing it will be in a `VERIFY_RESIZE` state.
|
||||
|
||||
You can use Fog's `wait_for` method to wait for this state as follows:
|
||||
|
||||
server.wait_for { ready?('VERIFY_RESIZE', ['ACTIVE', 'ERROR']) }
|
||||
|
||||
|
||||
In this case, `wait_for` is waiting for the server to become `VERIFY_READY` and will raise an exception if we enter an `ACTIVE` or `ERROR` state.
|
||||
|
||||
Once a server enters the `VERIFY_RESIZE` we will need to call `confirm_resize` to confirm the server was properly resized or `revert_resize` to rollback to the old size/flavor.
|
||||
|
||||
**Note:** A server will automatically confirm resize after 24 hours.
|
||||
|
||||
To confirm resize:
|
||||
|
||||
server.confirm_resize
|
||||
|
||||
To revert to previous size/flavor:
|
||||
|
||||
server.revert_resize
|
||||
|
||||
|
||||
## Create Image
|
||||
|
||||
To create an image of your server:
|
||||
|
||||
image = server.create_image "back-image-#{server.name}", :metadata => { :environment => 'development' }
|
||||
|
||||
You can use the second parameter to specify image metadata. This is an optional parameter.
|
||||
|
||||
During the imaging process, the image state will be `SAVING`. The image is ready for use when when state `ACTIVE` is reached. Fog can use `wait_for` to wait for an active state as follows:
|
||||
|
||||
image.wait_for { ready? }
|
||||
|
||||
## List Attached Volumes
|
||||
To list Cloud Block Volumes attached to server:
|
||||
|
||||
server.attachments
|
||||
|
||||
## Attach Volume
|
||||
To attach volume using the volume id:
|
||||
|
||||
server.attach_volume "0e7a706c-340d-48b3-802d-192850387f93"
|
||||
|
||||
If the volume id is unknown you can look it up using the Cloud Block Storage service. Start by creating a `cbs_service` similar to our Compute Service:
|
||||
|
||||
cbs_service = Fog::Rackspace::BlockStorage.new({
|
||||
:rackspace_username => RACKSPACE_USER_NAME, # Your Rackspace Username
|
||||
:rackspace_api_key => RACKSPACE_API # Your Rackspace API key
|
||||
})
|
||||
|
||||
volume = cbs_service.volumes.first
|
||||
server.attach_volume volume, "/dev/xvdb" # name of device on server is optional
|
||||
|
||||
The `attach_volume` method accepts a volume id `String` or `Fog::Rackspace::BlockStorage::Volume` instance. This example also demonstrates passing in the optional device name. Valid device names are `/dev/xvd[a-p]`.
|
||||
|
||||
## Detach Volume
|
||||
To detach a volume:
|
||||
|
||||
server.attachments.first.detach
|
||||
|
||||
## Examples
|
||||
|
||||
Example code using Next Gen Cloud Servers can be found [here](https://github.com/fog/fog/tree/master/lib/fog/rackspace/examples).
|
||||
|
||||
## Additional Resources
|
||||
|
||||
* [fog.io](http://fog.io/)
|
||||
* [Fog rdoc](http://rubydoc.info/gems/fog/)
|
||||
* [Fog Github repo](https://github.com/fog/fog)
|
||||
* [Fog Github Issues](https://github.com/fog/fog/issues)
|
||||
* [Excon Github repo](https://github.com/geemus/excon)
|
||||
* [Next Gen Cloud Servers API](http://docs.rackspace.com/servers/api/v2/cs-devguide/content/ch_preface.html)
|
||||
|
||||
## Support and Feedback
|
||||
|
||||
Your feedback is appreciated! If you have specific issues with the **fog** SDK, you should file an [issue via Github](https://github.com/fog/fog/issues).
|
||||
|
||||
For general feedback and support requests, send an email to: <sdk-support@rackspace.com>.
|
||||
|
88
lib/fog/rackspace/docs/getting_started.md
Normal file
88
lib/fog/rackspace/docs/getting_started.md
Normal file
|
@ -0,0 +1,88 @@
|
|||
# Getting Started with Fog and the Rackspace Cloud
|
||||
|
||||
This document explains how to get started using Fog with the [Rackspace Cloud](http://www.rackspace.com/cloud/).
|
||||
|
||||
## Requirements
|
||||
|
||||
### Ruby
|
||||
|
||||
Fog officially supports Ruby 2.1.1, 2.1.0, 2.0.0, 1.9.3, 1.9.2, and 1.8.7 (also known as Matz Ruby Interpreter or MRI). While not officially supported, fog has been known to work with Rubinus and JRuby.
|
||||
|
||||
Ruby 1.9.3 is suggested for new projects. For information on installing Ruby please refer to the [Ruby download page](http://www.ruby-lang.org/en/downloads/).
|
||||
|
||||
### RubyGems
|
||||
|
||||
RubyGems is required to access the Fog gem. For information on installing RubyGems, please refer to [RubyGems download page](http://rubygems.org/pages/download).
|
||||
|
||||
### Bundler (optional)
|
||||
|
||||
Bundler helps manage gem dependencies and is recommended for new projects. For more information about bundler, please refer to the [bundler documentation](http://gembundler.com/).
|
||||
|
||||
## Credentials
|
||||
|
||||
To obtain credentials for the US Rackspace Cloud, please sign up for an account at [US Rackspace Open Cloud](https://cart.rackspace.com/cloud/). Once an account is created, you can login to the [Cloud Control Panel (US)](https://mycloud.rackspace.com/), find your credentials by clicking on your username in the top right corner, and then select API keys.
|
||||
|
||||
Likewise, you can create an account on our UK Rackspace Open Cloud by signing up at [UK Rackspace Open Cloud](https://buyonline.rackspace.co.uk/cloud/userinfo?type=normal) and then logging into [Cloud Control Panel (UK)](https://mycloud.rackspace.co.uk/).
|
||||
|
||||
You will use the credentials when you explore fog services in the [Next Steps](#next-steps) section.
|
||||
|
||||
## Installation
|
||||
|
||||
To install Fog via RubyGems run the following command:
|
||||
|
||||
$ gem install fog
|
||||
|
||||
To install Fog via Bundler add `gem 'fog'` to your `Gemfile`. This is a sample `Gemfile` to install Fog:
|
||||
|
||||
source 'https://rubygems.org'
|
||||
|
||||
gem 'fog'
|
||||
|
||||
After creating your `Gemfile` execute the following command to install the libraries:
|
||||
|
||||
bundle install
|
||||
|
||||
## Next Steps
|
||||
|
||||
Now that you have installed Fog and obtained your credentials, you are ready to begin exploring the capabilities of the Rackspace Open Cloud and Fog using `irb`.
|
||||
|
||||
Start by executing the following command:
|
||||
|
||||
irb
|
||||
|
||||
Once `irb` has launched you will need to require the Fog library.
|
||||
|
||||
If using Ruby 1.8.x execute the following command:
|
||||
|
||||
require 'rubygems'
|
||||
require 'fog'
|
||||
|
||||
If using Ruby 1.9.x execute the following command:
|
||||
|
||||
require 'fog'
|
||||
|
||||
You should now be able to execute the following command to see a list of services Fog provides for the Rackspace Open Cloud:
|
||||
|
||||
Fog::Rackspace.services
|
||||
|
||||
These services can be explored in further depth in the following documents:
|
||||
|
||||
* [Next Generation Cloud Servers™ (compute_v2)](compute_v2.md)
|
||||
* [Cloud Files™ (storage)](storage.md)
|
||||
* [Cloud Block Storage (block_storage)](block_storage.md)
|
||||
* [Auto Scale (auto_scale)](auto_scale.md)
|
||||
* [Queues](queues.md)
|
||||
|
||||
**Note**: The compute service provides an interface to the First Geneneration Cloud Servers™ (compute). This service is deprecated. Users are encouraged to use Next Geneneration Cloud Servers™ (compute_v2).
|
||||
|
||||
## Additional Resources
|
||||
* [fog.io](http://fog.io)
|
||||
* [Fog rdoc](http://rubydoc.info/gems/fog)
|
||||
* [Fog Github repo](https://github.com/fog/fog)
|
||||
* [Release Notes](https://github.com/fog/fog/blob/master/changelog.txt)
|
||||
* [developer.rackspace.com](http://developer.rackspace.com/)
|
||||
|
||||
## Support and Feedback
|
||||
Your feedback is appreciated! If you have specific issues with the **fog** SDK, you should file an [issue via Github](https://github.com/fog/fog/issues).
|
||||
|
||||
For general feedback and support requests, send an email to: <sdk-support@rackspace.com>.
|
315
lib/fog/rackspace/docs/networking.md
Normal file
315
lib/fog/rackspace/docs/networking.md
Normal file
|
@ -0,0 +1,315 @@
|
|||
#Networking (neutron)
|
||||
|
||||
This document explains how to get started using Networking with Fog. It assumes you have read the [Getting Started with Fog and the Rackspace Open Cloud](getting_started.md) document.
|
||||
|
||||
## Starting irb console
|
||||
|
||||
Start by executing the following command:
|
||||
|
||||
irb
|
||||
|
||||
Once `irb` has launched you need to require the Fog library.
|
||||
|
||||
If using Ruby 1.8.x execute:
|
||||
|
||||
require 'rubygems'
|
||||
require 'fog'
|
||||
|
||||
If using Ruby 1.9.x execute:
|
||||
|
||||
require 'fog'
|
||||
|
||||
## Create Service
|
||||
|
||||
Next, create a connection to Rackspace's Networking API:
|
||||
|
||||
Using a US-based account:
|
||||
|
||||
service = Fog::Rackspace::Networking.new({
|
||||
:rackspace_username => RACKSPACE_USER_NAME, # Your Rackspace Username
|
||||
:rackspace_api_key => RACKSPACE_API, # Your Rackspace API key
|
||||
:rackspace_region => :ord, # Defaults to :dfw
|
||||
})
|
||||
|
||||
Using a UK-based account:
|
||||
|
||||
service = Fog::Compute.new({
|
||||
:rackspace_username => RACKSPACE_USER_NAME, # Your Rackspace Username
|
||||
:rackspace_api_key => RACKSPACE_API, # Your Rackspace API key
|
||||
:rackspace_auth_url => Fog::Rackspace::UK_AUTH_ENDPOINT,
|
||||
:rackspace_region => :lon,
|
||||
})
|
||||
|
||||
To learn more about obtaining cloud credentials refer to the [Getting Started with Fog and the Rackspace Open Cloud](getting_started.md) document.
|
||||
|
||||
By default `Fog::Rackspace::Networking` will authenticate against the US authentication endpoint and connect to the DFW region. You can specify alternative authentication endpoints using the key `:rackspace_auth_url`. Please refer to [Alternate Authentication Endpoints](http://docs.rackspace.com/auth/api/v2.0/auth-client-devguide/content/Endpoints-d1e180.html) for a list of alternative Rackspace authentication endpoints.
|
||||
|
||||
Alternative regions are specified using the key `:rackspace_region `. A list of regions available for Cloud Servers can be found by executing the following:
|
||||
|
||||
identity_service = Fog::Identity({
|
||||
:provider => 'Rackspace', # Rackspace Fog provider
|
||||
:rackspace_username => RACKSPACE_USER_NAME, # Your Rackspace Username
|
||||
:rackspace_api_key => RACKSPACE_API, # Your Rackspace API key
|
||||
:rackspace_auth_url => Fog::Rackspace::UK_AUTH_ENDPOINT # Not specified for US Cloud
|
||||
})
|
||||
|
||||
identity_service.service_catalog.display_service_regions :cloudServersOpenStack
|
||||
|
||||
### Optional Connection Parameters
|
||||
|
||||
Fog supports passing additional connection parameters to its underlying HTTP library (Excon) using the `:connection_options` parameter.
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:connect_timeout</td>
|
||||
<td>Connection timeout (default: 60 seconds)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:read_timeout</td>
|
||||
<td>Read timeout for connection (default: 60 seconds)</td> </tr>
|
||||
<tr>
|
||||
<td>:write_timeout</td>
|
||||
<td>Write timeout for connection (default: 60 seconds)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:proxy</td>
|
||||
<td>Proxy for HTTP and HTTPS connections</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:ssl_ca_path</td>
|
||||
<td>Path to SSL certificate authorities</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:ssl_ca_file</td>
|
||||
<td>SSL certificate authority file</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:ssl_verify_peer</td>
|
||||
<td>SSL verify peer (default: true)</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
## Fog Abstractions
|
||||
|
||||
Fog provides both a **model** and **request** abstraction. The request abstraction provides the most efficient interface and the model abstraction wraps the request abstraction to provide a convenient `ActiveModel` like interface.
|
||||
|
||||
### Request Layer
|
||||
|
||||
The request abstraction maps directly to the [Networking API](http://docs.rackspace.com/networks/api/v2/cn-gettingstarted/content/ch_overview.html). It provides the most efficient interface to the Rackspace Networking
|
||||
|
||||
To see a list of requests supported by the service:
|
||||
|
||||
service.requests
|
||||
|
||||
This returns:
|
||||
|
||||
[:list_networks, :get_network, :create_network, :delete_network, :list_virtual_interfaces, :create_virtual_interface, :delete_virtual_interface]
|
||||
|
||||
#### Example Request
|
||||
|
||||
To request a list of flavors:
|
||||
|
||||
response = service.list_networks
|
||||
|
||||
This returns in the following `Excon::Response`:
|
||||
|
||||
<Excon::Response:0x0000010231acd8 @data={:body=>{"networks"=>[{"cidr"=>"192.168.0.0/24", "id"=>"08df79ae-b714-425c-ba25-91b0a8a78b9e", "label"=>"something"}, {"cidr"=>"192.168.0.0/24", "id"=>"eb3ed4b8-21d4-478e-9ae4-a35c0cc0437c", "label"=>"something"}, {"id"=>"00000000-0000-0000-0000-000000000000", "label"=>"public"}, {"id"=>"11111111-1111-1111-1111-111111111111", "label"=>"private"}]}, :headers=>{"Content-Type"=>"application/json", "Via"=>"1.1 Repose (Repose/2.12)", "Content-Length"=>"341", "Date"=>"Thu, 23 Oct 2014 20:53:41 GMT", "x-compute-request-id"=>"req-d34ab53c-45ed-433f-8a9d-b3341896b7e5", "Server"=>"Jetty(8.0.y.z-SNAPSHOT)"}, :status=>200, :remote_ip=>"162.209.116.128", :local_port=>60153, :local_address=>"192.168.1.65"}, @body="{\"networks\": [{\"cidr\": \"192.168.0.0/24\", \"id\": \"08df79ae-b714-425c-ba25-91b0a8a78b9e\", \"label\": \"something\"}, {\"cidr\": \"192.168.0.0/24\", \"id\": \"eb3ed4b8-21d4-478e-9ae4-a35c0cc0437c\", \"label\": \"something\"}, {\"id\": \"00000000-0000-0000-0000-000000000000\", \"label\": \"public\"}, {\"id\": \"11111111-1111-1111-1111-111111111111\", \"label\": \"private\"}]}", @headers={"Content-Type"=>"application/json", "Via"=>"1.1 Repose (Repose/2.12)", "Content-Length"=>"341", "Date"=>"Thu, 23 Oct 2014 20:53:41 GMT", "x-compute-request-id"=>"req-d34ab53c-45ed-433f-8a9d-b3341896b7e5", "Server"=>"Jetty(8.0.y.z-SNAPSHOT)"}, @status=200, @remote_ip="162.209.116.128", @local_port=60153, @local_address="192.168.1.65">
|
||||
|
||||
To view the status of the response:
|
||||
|
||||
response.status
|
||||
|
||||
**Note**: Fog is aware of valid HTTP response statuses for each request type. If an unexpected HTTP response status occurs, Fog will raise an exception.
|
||||
|
||||
To view response body:
|
||||
|
||||
response.body
|
||||
|
||||
This will return:
|
||||
|
||||
{"networks"=>[{"cidr"=>"192.168.0.0/24", "id"=>"08df79ae-b714-425c-ba25-91b0a8a78b9e", "label"=>"something"}, {"cidr"=>"192.168.0.0/24", "id"=>"eb3ed4b8-21d4-478e-9ae4-a35c0cc0437c", "label"=>"something"}, {"id"=>"00000000-0000-0000-0000-000000000000", "label"=>"public"}, {"id"=>"11111111-1111-1111-1111-111111111111", "label"=>"private"}]}
|
||||
|
||||
To learn more about Networking request methods refer to [rdoc](http://www.rubydoc.info/gems/fog/Fog/Rackspace/Networking/Real). To learn more about Excon refer to [Excon GitHub repo](https://github.com/geemus/excon).
|
||||
|
||||
### Model Layer
|
||||
|
||||
Fog models behave in a manner similar to `ActiveModel`. Models will generally respond to `create`, `save`, `persisted?`, `destroy`, `reload` and `attributes` methods. Additionally, fog will automatically create attribute accessors.
|
||||
|
||||
Here is a summary of common model methods:
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Method</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>create</td>
|
||||
<td>
|
||||
Accepts hash of attributes and creates object.<br>
|
||||
Note: creation is a non-blocking call and you will be required to wait for a valid state before using resulting object.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>save</td>
|
||||
<td>Saves object.<br>
|
||||
Note: not all objects support updating object.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>persisted?</td>
|
||||
<td>Returns true if the object has been persisted.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>destroy</td>
|
||||
<td>
|
||||
Destroys object.<br>
|
||||
Note: this is a non-blocking call and object deletion might not be instantaneous.
|
||||
</td>
|
||||
<tr>
|
||||
<td>reload</td>
|
||||
<td>Updates object with latest state from service.</td>
|
||||
<tr>
|
||||
<td>ready?</td>
|
||||
<td>Returns true if object is in a ready state and able to perform actions. This method will raise an exception if object is in an error state.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>attributes</td>
|
||||
<td>Returns a hash containing the list of model attributes and values.</td>
|
||||
</tr>
|
||||
<td>identity</td>
|
||||
<td>
|
||||
Returns the identity of the object.<br>
|
||||
Note: This might not always be equal to object.id.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>wait_for</td>
|
||||
<td>This method periodically reloads model and then yields to specified block until block returns true or a timeout occurs.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
The remainder of this document details the model abstraction.
|
||||
|
||||
## List Networks
|
||||
|
||||
To retrieve a list of available networks:
|
||||
|
||||
service.networks
|
||||
|
||||
This returns a collection of `Fog::Rackspace::Networking::Network` models:
|
||||
|
||||
<Fog::Rackspace::Networking::Networks
|
||||
[
|
||||
<Fog::Rackspace::Networking::Network
|
||||
id="08df79ae-b714-425c-ba25-91b0a8a78b9e",
|
||||
label="something",
|
||||
cidr="192.168.0.0/24"
|
||||
>,
|
||||
<Fog::Rackspace::Networking::Network
|
||||
id="eb3ed4b8-21d4-478e-9ae4-a35c0cc0437c",
|
||||
label="something",
|
||||
cidr="192.168.0.0/24"
|
||||
>,
|
||||
<Fog::Rackspace::Networking::Network
|
||||
id="00000000-0000-0000-0000-000000000000",
|
||||
label="public",
|
||||
cidr=nil
|
||||
>,
|
||||
<Fog::Rackspace::Networking::Network
|
||||
id="11111111-1111-1111-1111-111111111111",
|
||||
label="private",
|
||||
cidr=nil
|
||||
>
|
||||
]
|
||||
>
|
||||
|
||||
## Create Network
|
||||
|
||||
Create a network:
|
||||
|
||||
service.networks.create(label: "new_network", cidr: "192.168.0.0/24")
|
||||
|
||||
|
||||
## Get Network
|
||||
|
||||
To retrieve individual network:
|
||||
|
||||
service.networks.get "8a3a9f96-b997-46fd-b7a8-a9e740796ffd"
|
||||
|
||||
This returns an `Fog::Rackspace::Networking::Network` instance:
|
||||
|
||||
<Fog::Rackspace::Networking::Network
|
||||
id="08df79ae-b714-425c-ba25-91b0a8a78b9e",
|
||||
label="new_network",
|
||||
cidr="192.168.0.0/24"
|
||||
>
|
||||
|
||||
## Delete Network
|
||||
|
||||
To delete a network:
|
||||
|
||||
network.destroy
|
||||
|
||||
**Note**: The network is not immediately destroyed, but it does occur shortly there after.
|
||||
|
||||
## List Virtual Interfaces
|
||||
|
||||
To retrieve a list of available virtual interfaces:
|
||||
|
||||
service.virtual_interfaces.all(server: <server obj, or server id>)
|
||||
|
||||
This returns a collection of `Fog::Rackspace::Networking::VirtualInterface` models:
|
||||
|
||||
<Fog::Rackspace::Networking::VirtualInterfaces
|
||||
[
|
||||
<Fog::Rackspace::Networking::VirtualInterface
|
||||
id="f063815f-e576-450e-92bd-ff3aeeeb11e0",
|
||||
mac_address="BC:76:4E:20:A9:16",
|
||||
ip_addresses=[{"network_id"=>"11111111-1111-1111-1111-111111111111", "network_label"=>"private", "address"=>"10.176.12.249"}]
|
||||
>,
|
||||
<Fog::Rackspace::Networking::VirtualInterface
|
||||
id="f8196e20-788b-4447-80a5-32ca8fc9622f",
|
||||
mac_address="BC:76:4E:20:A8:56",
|
||||
ip_addresses=[{"network_id"=>"08df79ae-b714-425c-ba25-91b0a8a78b9e", "network_label"=>"new_network", "address"=>"192.168.0.1"}]
|
||||
>
|
||||
]
|
||||
>
|
||||
|
||||
## Create Virtual Interface
|
||||
|
||||
Create a virtual interface:
|
||||
|
||||
service.virtual_interfaces.create(network: <network_id>, server: <server_id>)
|
||||
|
||||
## Delete Virtual Interface
|
||||
|
||||
To delete a virtual interface:
|
||||
|
||||
vis = service.virtual_interfaces.all(server: <server obj, or server id>)
|
||||
vis.first.destroy
|
||||
|
||||
**Note**: The virtual interface is not immediately destroyed, but it does occur shortly there after.
|
||||
|
||||
## Examples
|
||||
|
||||
Example code using Networking can be found [here](https://github.com/fog/fog/tree/master/lib/fog/rackspace/examples).
|
||||
|
||||
## Additional Resources
|
||||
|
||||
* [fog.io](http://fog.io/)
|
||||
* [Fog rdoc](http://rubydoc.info/gems/fog/)
|
||||
* [Fog Github repo](https://github.com/fog/fog)
|
||||
* [Fog Github Issues](https://github.com/fog/fog/issues)
|
||||
* [Excon Github repo](https://github.com/geemus/excon)
|
||||
* [Rackspace Networking API](http://docs.rackspace.com/networking/api/v2/cs-devguide/content/ch_preface.html)
|
||||
|
||||
## Support and Feedback
|
||||
|
||||
Your feedback is appreciated! If you have specific issues with the **fog** SDK, you should file an [issue via Github](https://github.com/fog/fog/issues).
|
||||
|
||||
For general feedback and support requests, send an email to: <sdk-support@rackspace.com>.
|
||||
|
312
lib/fog/rackspace/docs/queues.md
Normal file
312
lib/fog/rackspace/docs/queues.md
Normal file
|
@ -0,0 +1,312 @@
|
|||
#Cloud Queues (queues)
|
||||
|
||||
This document explains how to get started using queues with Fog. It assumes you have read the [Getting Started with Fog and the Rackspace Open Cloud](getting_started.md) document.
|
||||
|
||||
## Basic Concepts
|
||||
|
||||
Cloud Queues is an open source, scalable, and highly available message and notifications service, based on the OpenStack Marconi project. Users of this service can create and manage a producer-consumer or a publisher-subscriber model. Unlimited queues and messages give users the flexibility they need to create powerful web applications in the cloud.
|
||||
|
||||
It consists of a few basic components: queues, messages, claims, and statistics. In the producer-consumer model, users create queues in which producers, or servers, can post messages. Workers, or consumers, can then claim those messages and delete them after they complete the actions associated with the messages. A single claim can contain multiple messages, and administrators can query claims for status.
|
||||
|
||||
In the publisher-subscriber model, messages are posted to a queue as in the producer-consumer model, but messages are never claimed. Instead, subscribers, or watchers, send GET requests to pull all messages that have been posted since their last request. In this model, a message remains in the queue, unclaimed, until the message's time to live (TTL) has expired.
|
||||
|
||||
In both of these models, administrators can get queue statistics that display the most recent and oldest messages, the number of unclaimed messages, and more.
|
||||
|
||||
## Starting irb console
|
||||
|
||||
Start by executing the following command:
|
||||
|
||||
irb
|
||||
|
||||
Once `irb` has launched you need to require the Fog library as follows:
|
||||
|
||||
require 'fog'
|
||||
|
||||
## Create Service
|
||||
|
||||
Next, create a connection to queue service:
|
||||
|
||||
Using a US-based account:
|
||||
|
||||
service = Fog::Rackspace::Queues(
|
||||
:rackspace_username => RACKSPACE_USER_NAME, # Your Rackspace Username
|
||||
:rackspace_api_key => RACKSPACE_API, # Your Rackspace API key
|
||||
:rackspace_region => :ord, # Your desired region
|
||||
:rackspace_queues_client_id => CLIENT_ID, # Your client ID
|
||||
:connection_options => {} # Optional connection options
|
||||
)
|
||||
|
||||
Using a UK-based account:
|
||||
|
||||
service = Fog::Rackspace::Queues(
|
||||
:rackspace_username => RACKSPACE_USER_NAME, # Your Rackspace Username
|
||||
:rackspace_api_key => RACKSPACE_API, # Your Rackspace API key
|
||||
:rackspace_auth_url => Fog::Rackspace::UK_AUTH_ENDPOINT,
|
||||
:rackspace_region => :lon, # Your desired region
|
||||
:rackspace_queues_client_id => CLIENT_ID', # Your client ID
|
||||
:connection_options => {} # Optional connection options
|
||||
)
|
||||
|
||||
To learn more about obtaining cloud credentials refer to the [Getting Started with Fog and the Rackspace Open Cloud](getting_started.md) document.
|
||||
|
||||
### Authentication Endpoint
|
||||
|
||||
By default `Fog::Rackspace::Queues` will authenticate against the US authentication endpoint. You can specify alternative authentication endpoints using the key `:rackspace_auth_url`. Please refer to [Alternate Authentication Endpoints](http://docs.rackspace.com/auth/api/v2.0/auth-client-devguide/content/Endpoints-d1e180.html) for a list of alternative Rackspace authentication endpoints.
|
||||
|
||||
### Regions
|
||||
|
||||
Alternative regions are specified using the key `:rackspace_region `. A list of regions available for cloud queues can be found by executing the following:
|
||||
|
||||
identity_service = Fog::Identity({
|
||||
:provider => 'Rackspace', # Rackspace Fog provider
|
||||
:rackspace_username => RACKSPACE_USER_NAME, # Your Rackspace Username
|
||||
:rackspace_api_key => RACKSPACE_API, # Your Rackspace API key
|
||||
:rackspace_auth_url => Fog::Rackspace::UK_AUTH_ENDPOINT # Not specified for US Cloud
|
||||
})
|
||||
|
||||
identity_service.service_catalog.display_service_regions :queues
|
||||
|
||||
### Private Cloud
|
||||
|
||||
Rackspace Private Cloud installations can skip specifying a region and directly specify their custom service endpoints using the key `:rackspace_queues_url`.
|
||||
|
||||
**Note**: A`Fog::Rackspace::Queues` instance is needed for the desired region.
|
||||
|
||||
### Client ID
|
||||
|
||||
The Rackspace Queue service requires that every client define a client id to help identify messages and claims specific to the client. This client id should take the form of a UUID and can be generated using fog as follows:
|
||||
|
||||
Fog::UUID.uuid
|
||||
|
||||
If the client id is omitted fog will generate one for you.
|
||||
|
||||
### Optional Connection Parameters
|
||||
|
||||
Fog supports passing additional connection parameters to its underlying HTTP library (Excon) using the `:connection_options` parameter.
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:connect_timeout</td>
|
||||
<td>Connection timeout (default: 60 seconds)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:read_timeout</td>
|
||||
<td>Read timeout for connection (default: 60 seconds)</td> </tr>
|
||||
<tr>
|
||||
<td>:write_timeout</td>
|
||||
<td>Write timeout for connection (default: 60 seconds)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:proxy</td>
|
||||
<td>Proxy for HTTP and HTTPS connections</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:ssl_ca_path</td>
|
||||
<td>Path to SSL certificate authorities</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:ssl_ca_file</td>
|
||||
<td>SSL certificate authority file</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:ssl_verify_peer</td>
|
||||
<td>SSL verify peer (default: true)</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
## Fog Abstractions
|
||||
|
||||
Fog provides both a **model** and **request** abstraction. The request abstraction provides the most efficient interface and the model abstraction wraps the request abstraction to provide a convenient `ActiveModel`-like interface.
|
||||
|
||||
### Request Layer
|
||||
|
||||
The request abstraction maps directly to the [Queue API](http://docs.rackspace.com/queues/api/v1.0/cq-devguide/content/overview.html). It provides the most efficient interface to the Rackspace Open Cloud.
|
||||
|
||||
To see a list of requests supported by the service:
|
||||
|
||||
service.requests
|
||||
|
||||
This returns:
|
||||
|
||||
:list_queues, :get_queue, :create_queue, :delete_queue, :get_queue_stats, :list_messages, :get_message, :create_message, :delete_message, :create_claim, :get_claim, :update_claim, :delete_claim
|
||||
|
||||
|
||||
#### Example Request
|
||||
|
||||
To request a list of queues:
|
||||
|
||||
response = service.list_queues
|
||||
|
||||
This returns in the following `Excon::Response`:
|
||||
|
||||
#<Excon::Response:0x007feddda06e00 @data={:body=>{"queues"=>[{"href"=>"/v1/queues/demo-queue", "name"=>"demo-queue"}], "links"=>[{"href"=>"/v1/queues?marker=demo-queue", "rel"=>"next"}]}, :headers=>{"Content-Length"=>"119", "Content-Type"=>"application/json; charset=utf-8", "Content-Location"=>"/v1/queues", "X-Project-ID"=>"5551212"}, :status=>200, :remote_ip=>"10.10.0.1"}, @body="{\"queues\": [{\"href\": \"/v1/queues/demo-queue\", \"name\": \"demo-queue\"}], \"links\": [{\"href\": \"/v1/queues?marker=demo-queue\", \"rel\": \"next\"}]}", @headers={"Content-Length"=>"119", "Content-Type"=>"application/json; charset=utf-8", "Content-Location"=>"/v1/queues", "X-Project-ID"=>"5551212"}, @status=200, @remote_ip="10.10.0.1">
|
||||
|
||||
To view the status of the response:
|
||||
|
||||
response.status
|
||||
|
||||
**Note**: Fog is aware of valid HTTP response statuses for each request type. If an unexpected HTTP response status occurs, Fog will raise an exception.
|
||||
|
||||
To view response body:
|
||||
|
||||
response.body
|
||||
|
||||
This returns:
|
||||
|
||||
{"queues"=>[{"href"=>"/v1/queues/demo-queue", "name"=>"demo-queue"}], "links"=>[{"href"=>"/v1/queues?marker=demo-queue", "rel"=>"next"}]}
|
||||
|
||||
|
||||
To learn more about queue request methods refer to [rdoc](http://rubydoc.info/gems/fog/Fog/Rackspace/Queues/Real). To learn more about Excon refer to [Excon GitHub repo](https://github.com/geemus/excon).
|
||||
|
||||
### Model Layer
|
||||
|
||||
Fog models behave in a manner similar to `ActiveModel`. Models will generally respond to `create`, `save`, `persisted?`, `destroy`, `reload` and `attributes` methods. Additionally, fog will automatically create attribute accessors.
|
||||
|
||||
Here is a summary of common model methods:
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Method</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>create</td>
|
||||
<td>
|
||||
Accepts hash of attributes and creates object.<br>
|
||||
Note: creation is a non-blocking call and you will be required to wait for a valid state before using resulting object.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>save</td>
|
||||
<td>Saves object.<br>
|
||||
Note: not all objects support updating object.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>persisted?</td>
|
||||
<td>Returns true if the object has been persisted.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>destroy</td>
|
||||
<td>
|
||||
Destroys object.<br>
|
||||
Note: this is a non-blocking call and object deletion might not be instantaneous.
|
||||
</td>
|
||||
<tr>
|
||||
<td>reload</td>
|
||||
<td>Updates object with latest state from service.</td>
|
||||
<tr>
|
||||
<td>ready?</td>
|
||||
<td>Returns true if object is in a ready state and able to perform actions. This method will raise an exception if object is in an error state.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>attributes</td>
|
||||
<td>Returns a hash containing the list of model attributes and values.</td>
|
||||
</tr>
|
||||
<td>identity</td>
|
||||
<td>
|
||||
Returns the identity of the object.<br>
|
||||
Note: This might not always be equal to object.id.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>wait_for</td>
|
||||
<td>This method periodically reloads model and then yields to specified block until block returns true or a timeout occurs.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
The remainder of this document details the model abstraction.
|
||||
|
||||
## Create Queue
|
||||
|
||||
Queues require a unique name. If you try to create a queue with a name that already exists, fog will throw a `Fog::Rackspace::Queues::ServiceError` exception with a 204 status code.
|
||||
|
||||
To create a queue named demo-queue
|
||||
|
||||
begin
|
||||
queue = service.queues.create :name => 'demo-queue'
|
||||
rescue Fog::Rackspace::Queues::ServiceError => e
|
||||
if e.status_code == 204
|
||||
# duplicate queue exists
|
||||
end
|
||||
end
|
||||
|
||||
## Posting a Message to a Queue
|
||||
|
||||
Messages can be any type of data, as long as they do not exceed 256 KB in length. Typical message bodies range from simple values, to a chunk of XML, or a list of JSON values. Fog handles the JSON-encoding required to post the message.
|
||||
|
||||
You can post a message a message to your queue as follows:
|
||||
|
||||
queue.messages.create :body => 'The laces were out!', :ttl => 360
|
||||
|
||||
You must supply both a body and a value for `ttl`. The value of `ttl` must be between 60 and 1209600 seconds (one minute to 14 days).
|
||||
|
||||
## Listing Messages in a Queue
|
||||
|
||||
To list messages:
|
||||
|
||||
queue.messages
|
||||
|
||||
You can change the behavior by setting the follow attributes on the messages collection:
|
||||
|
||||
Parameter | Default | Effect
|
||||
---- | ---- | ----
|
||||
**echo** | `true` | When `true`, your own messages are included.
|
||||
**include_claimed** | `false` | By default, only unclaimed messages are returned. Pass this as `true` to get all messages, claimed or not.
|
||||
**marker** | `nil` | Used for pagination.
|
||||
**limit** | `10` | The maximum number of messages to return. Note that you may receive fewer than the specified limit if there aren't that many available messages in the queue.
|
||||
|
||||
For example, to include claimed messages:
|
||||
|
||||
queue.messages.include_claimed = true
|
||||
queue.messages
|
||||
|
||||
## Claiming Messages in a Queue
|
||||
|
||||
Claiming messages is how workers processing a queue mark messages as being handled by that worker, avoiding having two workers process the same message.
|
||||
|
||||
Messages can be claimed and processed as follows:
|
||||
|
||||
claims = queue.claims.create :ttl => 300, :grace => 100, :limit => 10
|
||||
|
||||
The parameters for this call are described in the following table:
|
||||
|
||||
Parameter | Default | Notes
|
||||
---- | ---- | ----
|
||||
**ttl** | | The ttl attribute specifies how long the server waits before releasing the claim. The ttl value must be between 60 and 43200 seconds (12 hours).
|
||||
**grace** | | The grace attribute specifies the message grace period in seconds. The value of the grace period must be between 60 and 43200 seconds (12 hours). To deal with workers that have stopped responding (for up to 1209600 seconds or 14 days, including claim lifetime), the server extends the lifetime of claimed messages to be at least as long as the lifetime of the claim itself, plus the specified grace period. If a claimed message would normally live longer than the grace period, its expiration is not adjusted.
|
||||
**limit** | 10 | The number of messages to claim. The maximum number of messages you may claim at once is 20.
|
||||
|
||||
If the claim is successful it will return a `Fog::Rackspace::Queues::Claims` object; if there are not any available messages it will return `false`.
|
||||
|
||||
To iterate through the claimed messages:
|
||||
|
||||
claim.messages.each do |message|
|
||||
# process message here
|
||||
message.destroy
|
||||
end
|
||||
|
||||
**Note:** You will want to call the `destroy` method on the message after processing to insure it is not processed more than once.
|
||||
|
||||
## Renewing a Claim
|
||||
|
||||
Once a claim has been made, if the TTL and grace period expire, the claim is automatically released and the messages are made available for others to claim. If you have a long-running process and want to ensure that this does not happen in the middle of the process, you should update the claim with one or both of a TTL or grace period. Updating resets the age of the claim, restarting the TTL for the claim. To update a claim, call:
|
||||
|
||||
claim.ttl = 360
|
||||
claim.grace = 360
|
||||
claim.save
|
||||
|
||||
## Refreshing a Claim
|
||||
|
||||
If you have a `Fog::Rackspace::Queues::claims` object, keep in mind that it is not a live window into the status of the claim; rather, it is a snapshot of the claim at the time the object was created. To refresh it with the latest information, call its `reload` method. This refreshes all of its attributes with the most current status of the claim.
|
||||
|
||||
|
||||
## Releasing a Claim
|
||||
|
||||
If you have a claim on several messages and must abandon processing of those messages for any reason, you should release the claim so that those messages can be processed by other workers as soon as possible, instead of waiting for the claim's TTL to expire. When you release a claim, the claimed messages are immediately made available in the queue for other workers to claim. To release a claim, call:
|
||||
|
||||
claim.destroy
|
557
lib/fog/rackspace/docs/storage.md
Normal file
557
lib/fog/rackspace/docs/storage.md
Normal file
|
@ -0,0 +1,557 @@
|
|||
#Cloud Files™ (storage)
|
||||
|
||||
This document explains how to get started using Cloud Files with Fog. It assumes you have read the [Getting Started with Fog and the Rackspace Open Cloud](getting_started.md) document.
|
||||
|
||||
|
||||
## Starting irb console
|
||||
|
||||
Start by executing the following command:
|
||||
|
||||
irb
|
||||
|
||||
Once `irb` has launched you need to require the Fog library.
|
||||
|
||||
If using Ruby 1.8.x execute:
|
||||
|
||||
require 'rubygems'
|
||||
require 'fog'
|
||||
|
||||
If using Ruby 1.9.x execute:
|
||||
|
||||
require 'fog'
|
||||
|
||||
## Create Service
|
||||
|
||||
Next, create a connection to Cloud Files.
|
||||
|
||||
Using a US-based account:
|
||||
|
||||
service = Fog::Storage.new({
|
||||
:provider => 'Rackspace', # Rackspace Fog provider
|
||||
:rackspace_username => RACKSPACE_USER_NAME, # Your Rackspace Username
|
||||
:rackspace_api_key => RACKSPACE_API, # Your Rackspace API key
|
||||
:rackspace_region => :ord, # Defaults to :dfw
|
||||
:connection_options => {} # Optional
|
||||
})
|
||||
|
||||
Using a UK-based account:
|
||||
|
||||
service = Fog::Storage.new({
|
||||
:provider => 'Rackspace', # Rackspace Fog provider
|
||||
:rackspace_username => RACKSPACE_USER_NAME, # Your Rackspace Username
|
||||
:rackspace_api_key => RACKSPACE_API, # Your Rackspace API key
|
||||
:rackspace_auth_url => Fog::Rackspace::UK_AUTH_ENDPOINT,
|
||||
:rackspace_region => :lon,
|
||||
:connection_options => {} # Optional
|
||||
})
|
||||
|
||||
To learn more about obtaining cloud credentials refer to the [Getting Started with Fog and the Rackspace Open Cloud](getting_started.md) document.
|
||||
|
||||
By default `Fog::Storage` will authenticate against the US authentication endpoint and connect to the DFW region. You can specify alternative authentication endpoints using the key `:rackspace_auth_url`. Please refer to [Alternate Authentication Endpoints](http://docs.rackspace.com/auth/api/v2.0/auth-client-devguide/content/Endpoints-d1e180.html) for a list of alternative Rackspace authentication endpoints.
|
||||
|
||||
Alternative regions are specified using the key `:rackspace_region `. A list of regions available for Cloud Files can be found by executing the following:
|
||||
|
||||
identity_service = Fog::Identity({
|
||||
:provider => 'Rackspace', # Rackspace Fog provider
|
||||
:rackspace_username => RACKSPACE_USER_NAME, # Your Rackspace Username
|
||||
:rackspace_api_key => RACKSPACE_API, # Your Rackspace API key
|
||||
:rackspace_auth_url => Fog::Rackspace::UK_AUTH_ENDPOINT # Not specified for US Cloud
|
||||
})
|
||||
|
||||
identity_service.service_catalog.display_service_regions :cloudFiles
|
||||
|
||||
Rackspace Private Cloud installations can skip specifying a region and directly specify their custom service endpoints using the keys `:rackspace_storage_url` and `:rackspace_cdn_url`.
|
||||
|
||||
**Note**: A`Fog::Storage` instance is needed for the desired region.
|
||||
|
||||
### Optional Service Parameters
|
||||
|
||||
The Storage service supports the following additional parameters:
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:rackspace_servicenet</td>
|
||||
<td>If set to true, the service will access Cloud Files using the internal Rackspace ServiceNet. This option should only be used for internal network connections.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:rackspace_cdn_ssl</td>
|
||||
<td>If set to true, the public_url method will return the SSL based URLs.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:persistent</td>
|
||||
<td>If set to true, the service will use a persistent connection.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:rackspace_storage_url</td>
|
||||
<td>The endpoint for the Cloud Files service. By default, Fog::Storage will pick the appropriate endpoint for region. This option will typically only be used for Rackspace Private Cloud Access.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:rackspace_cdn_url</td>
|
||||
<td>The endpoint for the CDN service. By default, Fog::Storage pick the appropriate endpoint for region. This option will typically only be used for Rackspace Private Cloud Access.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
### Optional Connection Parameters
|
||||
|
||||
Fog supports passing additional connection parameters to its underlying HTTP library (Excon) using the `:connection_options` parameter.
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:connect_timeout</td>
|
||||
<td>Connection timeout (default: 60 seconds)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:read_timeout</td>
|
||||
<td>Read timeout for connection (default: 60 seconds)</td> </tr>
|
||||
<tr>
|
||||
<td>:write_timeout</td>
|
||||
<td>Write timeout for connection (default: 60 seconds)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:proxy</td>
|
||||
<td>Proxy for HTTP and HTTPS connections</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:ssl_ca_path</td>
|
||||
<td>Path to SSL certificate authorities</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:ssl_ca_file</td>
|
||||
<td>SSL certificate authority file</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:ssl_verify_peer</td>
|
||||
<td>SSL verify peer (default: true)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:chunk_size</td>
|
||||
<td>The chunk size in bytes used for block transfers. By default, Fog uses 1 MB chunks.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
## Fog Abstractions
|
||||
|
||||
Fog provides both a **model** and **request** abstraction. The request abstraction provides the most efficient interface and the model abstraction wraps the request abstraction to provide a convenient `ActiveModel` like interface.
|
||||
|
||||
### Request Layer
|
||||
|
||||
The request abstraction maps directly to the [Cloud Files API](http://docs.rackspace.com/files/api/v1/cf-devguide/content/Overview-d1e70.html). It provides the most efficient interface to the Rackspace Open Cloud.
|
||||
|
||||
To see a list of requests supported by the storage service:
|
||||
|
||||
service.requests
|
||||
|
||||
This returns:
|
||||
|
||||
:copy_object, :delete_container, :delete_object, :get_container, :get_containers, :get_object, :get_object_https_url, :head_container, :head_containers, :head_object, :put_container, :put_object, :put_object_manifest, :post_set_meta_temp_url_key
|
||||
|
||||
To see a list of requests supported by the CDN service:
|
||||
|
||||
service.cdn.requests
|
||||
|
||||
This returns:
|
||||
|
||||
:get_containers, :head_container, :post_container, :put_container, :delete_object
|
||||
|
||||
|
||||
#### Example Request
|
||||
|
||||
To request a view account details:
|
||||
|
||||
response = service.head_containers
|
||||
|
||||
This returns in the following `Excon::Response`:
|
||||
|
||||
#<Excon::Response:0x10283fc68 @headers={"X-Account-Bytes-Used"=>"2563554", "Date"=>"Thu, 21 Feb 2013 21:57:02 GMT", "X-Account-Meta-Temp-Url-Key"=>"super_secret_key", "X-Timestamp"=>"1354552916.82056", "Content-Length"=>"0", "Content-Type"=>"application/json; charset=utf-8", "X-Trans-Id"=>"txe934924374a744c8a6c40dd8f29ab94a", "Accept-Ranges"=>"bytes", "X-Account-Container-Count"=>"7", "X-Account-Object-Count"=>"5"}, @status=204, @body="">
|
||||
|
||||
To view the status of the response:
|
||||
|
||||
response.status
|
||||
|
||||
**Note**: Fog is aware of the valid HTTP response statuses for each request type. If an unexpected HTTP response status occurs, Fog will raise an exception.
|
||||
|
||||
To view response headers:
|
||||
|
||||
response.headers
|
||||
|
||||
This will return:
|
||||
|
||||
{"X-Account-Bytes-Used"=>"2563554", "Date"=>"Thu, 21 Feb 2013 21:57:02 GMT", "X-Account-Meta-Temp-Url-Key"=>"super_secret_key", "X-Timestamp"=>"1354552916.82056", "Content-Length"=>"0", "Content-Type"=>"application/json; charset=utf-8", "X-Trans-Id"=>"txe934924374a744c8a6c40dd8f29ab94a", "Accept-Ranges"=>"bytes", "X-Account-Container-Count"=>"7", "X-Account-Object-Count"=>"5"}
|
||||
|
||||
|
||||
To learn more about `Fog::Storage` request methods refer to [rdoc](http://rubydoc.info/gems/fog/Fog/Storage/Rackspace/Real). To learn more about Excon refer to [Excon GitHub repo](https://github.com/geemus/excon).
|
||||
|
||||
### Model Layer
|
||||
|
||||
Fog models behave in a manner similar to `ActiveModel`. Models will generally respond to `create`, `save`, `destroy`, `reload` and `attributes` methods. Additionally, fog will automatically create attribute accessors.
|
||||
|
||||
Here is a summary of common model methods:
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Method</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>create</td>
|
||||
<td>
|
||||
Accepts hash of attributes and creates object.<br>
|
||||
Note: creation is a non-blocking call and you will be required to wait for a valid state before using resulting object.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>save</td>
|
||||
<td>Saves object.<br>
|
||||
Note: not all objects support updating object.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>destroy</td>
|
||||
<td>
|
||||
Destroys object.<br>
|
||||
Note: this is a non-blocking call and object deletion might not be instantaneous.
|
||||
</td>
|
||||
<tr>
|
||||
<td>reload</td>
|
||||
<td>Updates object with latest state from service.</td>
|
||||
<tr>
|
||||
<td>attributes</td>
|
||||
<td>Returns a hash containing the list of model attributes and values.</td>
|
||||
</tr>
|
||||
<td>identity</td>
|
||||
<td>
|
||||
Returns the identity of the object.<br>
|
||||
Note: This might not always be equal to object.id.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
The remainder of this document details the model abstraction.
|
||||
|
||||
**Note:** Fog refers to Rackspace Cloud containers as directories.
|
||||
|
||||
## List Directories
|
||||
|
||||
To retrieve a list of directories:
|
||||
|
||||
service.directories
|
||||
|
||||
This returns a collection of `Fog::Storage::Rackspace::Directory` models:
|
||||
|
||||
<Fog::Storage::Rackspace::Directories
|
||||
[
|
||||
<Fog::Storage::Rackspace::Directory
|
||||
key="blue",
|
||||
bytes=434266,
|
||||
count=1,
|
||||
cdn_cname=nil
|
||||
>,
|
||||
<Fog::Storage::Rackspace::Directory
|
||||
key="brown",
|
||||
bytes=761879,
|
||||
count=1,
|
||||
cdn_cname=nil
|
||||
>,
|
||||
...
|
||||
|
||||
## Get Directory
|
||||
|
||||
To retrieve a specific directory:
|
||||
|
||||
service.directories.get "blue"
|
||||
|
||||
**Note** As a general rule, only use `get` when you want to iterate over the contents of a `Directory`
|
||||
|
||||
This call is similar to...
|
||||
|
||||
service.directories.new :key => "blue"
|
||||
|
||||
... except the `get` method makes an HTTP call that returns metadata for up to the first 10,000 files. **This can be slow!**
|
||||
|
||||
This returns a `Fog::Storage::Rackspace::Directory` instance:
|
||||
|
||||
<Fog::Storage::Rackspace::Directory
|
||||
key="blue",
|
||||
bytes=434266,
|
||||
count=1,
|
||||
cdn_cname=nil
|
||||
>
|
||||
|
||||
## Create Directory
|
||||
|
||||
To create a directory:
|
||||
|
||||
service.directories.create :key => 'backups'
|
||||
|
||||
To create a directory utilizing CDN:
|
||||
|
||||
service.directories.create :key => 'web-assets', :public => true
|
||||
|
||||
### Additional Parameters
|
||||
|
||||
The `create` method also supports the following key values:
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:metadata</td>
|
||||
<td>Hash containing directory metadata.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
## Update Directory
|
||||
|
||||
Cloud Files supports updating the `public` attribute to enable/disable CDN.
|
||||
|
||||
To update this attribute:
|
||||
|
||||
directory.public = false
|
||||
directory.save
|
||||
|
||||
## Delete Directory
|
||||
|
||||
To delete a directory:
|
||||
|
||||
directory.destroy
|
||||
|
||||
**Note**: Directory must be empty before it can be deleted.
|
||||
|
||||
## List Files
|
||||
|
||||
To list files in a directory:
|
||||
|
||||
directory.files
|
||||
|
||||
**Note**: File contents is not downloaded until `body` attribute is called.
|
||||
|
||||
## Upload Files
|
||||
|
||||
To upload a file into a directory:
|
||||
|
||||
file = directory.files.create :key => 'space.jpg', :body => File.open "space.jpg"
|
||||
|
||||
**Note**: For files larger than 5 GB please refer to the [Upload Large Files](#upload_large_files) section.
|
||||
|
||||
If you only need a `Directory` so that you can create a file (as above), you can accomplish this without
|
||||
an HTTP call as below:
|
||||
|
||||
dir = service.directories.new :key => "blue"
|
||||
file = dir.files.new(...)
|
||||
file.save
|
||||
|
||||
This will **not** retrieve the metadata for files in the `Directory`.
|
||||
|
||||
However, if the `Directory` does not already exist in Cloud Files, the `save` call will return with a 404.
|
||||
|
||||
In this case, you will need to `save` the `Directory` first...
|
||||
|
||||
dir.save
|
||||
|
||||
... before you can...
|
||||
|
||||
file.save
|
||||
|
||||
### Additional Parameters
|
||||
|
||||
The `create` method also supports the following key values:
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:content_type</td>
|
||||
<td>The content type of the object. Cloud Files will attempt to auto detect this value if omitted.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:access_control_allow_origin</td>
|
||||
<td>URLs can make Cross Origin Requests. Format is http://www.example.com. Separate URLs with a space. An asterisk (*) allows all. Please refer to <a href="http://docs.rackspace.com/files/api/v1/cf-devguide/content/CORS_Container_Header-d1e1300.html">CORS Container Headers</a> for more information.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:origin</td>
|
||||
<td>The origin is the URI of the object's host.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:etag</td>
|
||||
<td>The MD5 checksum of your object's data. If specified, Cloud Files will validate the integrity of the uploaded object.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:metadata</td>
|
||||
<td>Hash containing file metadata.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
## Upload Large Files
|
||||
|
||||
Cloud Files requires files larger than 5 GB to be uploaded into segments along with an accompanying manifest file. All of the segments must be uploaded to the same container.
|
||||
|
||||
SEGMENT_LIMIT = 5368709119.0 # 5GB -1
|
||||
BUFFER_SIZE = 1024 * 1024 # 1MB
|
||||
|
||||
File.open(file_name) do |f|
|
||||
segment = 0
|
||||
until file.eof?
|
||||
segment += 1
|
||||
offset = 0
|
||||
|
||||
# upload segment to cloud files
|
||||
segment_suffix = segment.to_s.rjust(10, '0')
|
||||
service.put_object("my_container", "large_file/#{segment_suffix}", nil) do
|
||||
if offset <= SEGMENT_LIMIT - BUFFER_SIZE
|
||||
buf = file.read(BUFFER_SIZE).to_s
|
||||
offset += buf.size
|
||||
buf
|
||||
else
|
||||
''
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# write manifest file
|
||||
service.put_object_manifest("my_container", "large_file", 'X-Object-Manifest' => "my_container/large_file/")
|
||||
|
||||
Segmented files are downloaded like ordinary files. See [Download Files](#download-files) section for more information.
|
||||
|
||||
## Download Files
|
||||
|
||||
The most efficient way to download files from a private or public directory is as follows:
|
||||
|
||||
File.open('downloaded-file.jpg', 'w') do | f |
|
||||
directory.files.get("my_big_file.jpg") do | data, remaining, content_length |
|
||||
f.syswrite data
|
||||
end
|
||||
end
|
||||
|
||||
This will download and save the file in 1 MB chunks. The chunk size can be changed by passing the parameter `:chunk_size` into the `:connection_options` hash in the service constructor.
|
||||
|
||||
**Note**: The `body` attribute of file will be empty if a file has been downloaded using this method.
|
||||
|
||||
If a file object has already been loaded into memory, you can save it as follows:
|
||||
|
||||
File.open('germany.jpg', 'w') {|f| f.write(file_object.body) }
|
||||
|
||||
**Note**: This method is more memory intensive as the entire object is loaded into memory before saving the file as in the example above.
|
||||
|
||||
|
||||
## Accessing Files Through CDN
|
||||
|
||||
The CDN service offers several different URLs to access your files.
|
||||
|
||||
The simplest is with the default container URL. This can be accessed as follows:
|
||||
|
||||
file.public_url
|
||||
|
||||
For a more user-friendly URL, you can create a CNAME DNS record pointing to the URL generated by the `public_url` method. Then set the CNAME on the `Directory` object using the attribute `cdn_cname`. Note, that the `cdn_cname` attribute does not persist and will need to be specified every time a directory object is retrieved.
|
||||
|
||||
To access the file using SSL, you need to specify the option `:rackspace_cdn_ssl => true` when creating `Fog::Storage` service. This will cause the `public_url` method to return the SSL-secured URL.
|
||||
|
||||
To stream content use the following:
|
||||
|
||||
file.streaming_url
|
||||
|
||||
To stream video for iOS devices without needing to convert your video use the following:
|
||||
|
||||
file.ios_url
|
||||
|
||||
|
||||
## Metadata
|
||||
|
||||
You can access metadata as an attribute on both `Fog::Storage::Rackspace::Directory` and `Fog::Storage::Rackspace::File`.
|
||||
|
||||
This example demonstrates how to iterate through a directory's metadata:
|
||||
|
||||
directory.metadata.each_pair {|metadatum| puts "#{metadatum.key}: #{metadatum.value}" }
|
||||
|
||||
You can update and retrieve metadata in a manner similar to a hash:
|
||||
|
||||
directory.metadata[:thumbnails]
|
||||
|
||||
file.metadata[:environment] = "development"
|
||||
|
||||
Directory metadata is saved when the directory is saved and file metadata is set when the file is saved:
|
||||
|
||||
directory.save
|
||||
|
||||
file.save
|
||||
|
||||
Metadata is reloaded when directory or file is reloaded:
|
||||
|
||||
directory.reload
|
||||
|
||||
file.reload
|
||||
|
||||
## Copy File
|
||||
|
||||
Cloud Files supports copying files. To copy files into a container named "trip" with a name of "europe.jpg" do the following:
|
||||
|
||||
file.copy("trip", "europe.jpg")
|
||||
|
||||
To move or rename a file, perform a copy operation and then delete the old file:
|
||||
|
||||
file.copy("trip", "germany.jpg")
|
||||
file.destroy
|
||||
|
||||
## Delete File
|
||||
|
||||
To delete a file:
|
||||
|
||||
file.destroy
|
||||
|
||||
## CDN Purge
|
||||
|
||||
To immediately remove a file from the CDN network use the following:
|
||||
|
||||
file.purge_from_cdn
|
||||
|
||||
You may only purge up to 25 objects per day and thus this should only be used in situations where there could be serious personal, business, or security consequences if the object remained in the CDN. To purge a directory, please contact Rackspace support.
|
||||
|
||||
**Note**: You may only **PURGE** up to 25 objects per day. Any attempt to purge more than this will result in a 498 status code error (Rate Limited).
|
||||
|
||||
## Account Information
|
||||
|
||||
To view Cloud Files usage execute the following:
|
||||
|
||||
service.account
|
||||
|
||||
This returns a `Fog::Storage::Rackspace::Account` instance:
|
||||
|
||||
<Fog::Storage::Rackspace::Account
|
||||
meta_temp_url_key="lkkl23jl2j3",
|
||||
container_count=13,
|
||||
bytes_used=2563554,
|
||||
object_count=5
|
||||
>
|
||||
|
||||
## Examples
|
||||
|
||||
Example code using Cloud Files can be found [here](https://github.com/fog/fog/tree/master/lib/fog/rackspace/examples).
|
||||
|
||||
## Additional Resources
|
||||
|
||||
* [fog.io](http://fog.io/)
|
||||
* [Fog rdoc](http://rubydoc.info/gems/fog/)
|
||||
* [Fog Github repo](https://github.com/fog/fog)
|
||||
* [Fog Github Issues](https://github.com/fog/fog/issues)
|
||||
* [Excon Github repo](https://github.com/geemus/excon)
|
||||
* [Cloud Files API](http://docs.rackspace.com/files/api/v1/cf-devguide/content/Overview-d1e70.html)
|
||||
|
||||
## Support and Feedback
|
||||
|
||||
Your feedback is appreciated! If you have specific issues with the **fog** SDK, you should file an [issue via Github](https://github.com/fog/fog/issues).
|
||||
|
||||
For general feedback and support requests, send an email to: <sdk-support@rackspace.com>.
|
33
lib/fog/rackspace/errors.rb
Normal file
33
lib/fog/rackspace/errors.rb
Normal file
|
@ -0,0 +1,33 @@
|
|||
module Fog
|
||||
module Rackspace
|
||||
module Errors
|
||||
def self.included(mod)
|
||||
mod.class_eval <<-'EOS', __FILE__, __LINE__
|
||||
class NotFound < Fog::Service::NotFound
|
||||
attr_reader :region, :status_code, :transaction_id
|
||||
|
||||
def to_s
|
||||
status = status_code ? "HTTP #{status_code}" : "HTTP <Unknown>"
|
||||
message = region ? "resource not found in #{region} region" : super
|
||||
"[#{status} | #{transaction_id}] #{message}"
|
||||
end
|
||||
|
||||
def self.slurp(error, service=nil)
|
||||
exception = NotFound.new
|
||||
exception.instance_variable_set(:@region, service.region) if service && service.respond_to?(:region)
|
||||
exception.instance_variable_set(:@status_code, error.response.status) rescue nil
|
||||
exception.set_transaction_id(error, service)
|
||||
exception
|
||||
end
|
||||
|
||||
def set_transaction_id(error, service)
|
||||
return unless service && service.respond_to?(:request_id_header) && error.response
|
||||
@transaction_id = error.response.headers[service.request_id_header]
|
||||
end
|
||||
|
||||
end
|
||||
EOS
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
47
lib/fog/rackspace/examples/README.md
Normal file
47
lib/fog/rackspace/examples/README.md
Normal file
|
@ -0,0 +1,47 @@
|
|||
# Getting Started Examples
|
||||
|
||||
## Download
|
||||
|
||||
Examples using the Rackspace Open Cloud and Fog can be found in the [fog repository](https://github.com/fog/fog) under the directory `fog/lib/fog/rackspace/examples`.
|
||||
|
||||
This repository can be downloaded via `git` by executing the following:
|
||||
|
||||
git clone git://github.com/fog/fog.git
|
||||
|
||||
Optionally you can download a zip by clicking on this [link](https://github.com/fog/fog/archive/master.zip).
|
||||
|
||||
## Requirements
|
||||
|
||||
Examples require the following:
|
||||
|
||||
* Rackspace Open Cloud account
|
||||
* Ruby 1.8.x or 1.9.x
|
||||
* `fog` gem
|
||||
|
||||
For more information please refer to the [Getting Started with Fog and the Rackspace Open Cloud](https://github.com/fog/fog/blob/master/lib/fog/rackspace/docs/getting_started.md) document.
|
||||
|
||||
## Credentials
|
||||
|
||||
Examples will prompt for Rackspace Open Cloud credentials. Prompts can be skipped by creating a `.fog` file in the user's home directory. This is an example of a `.fog` file for the Rackspace Open Cloud:
|
||||
|
||||
default:
|
||||
rackspace_username: RACKSPACE_USERNAME
|
||||
rackspace_api_key: RACKSPACE_API_KEY
|
||||
|
||||
**Note:** Replace capitalized values with the appropriate credential information.
|
||||
|
||||
## Executing
|
||||
|
||||
To execute scripts using `bundler`:
|
||||
|
||||
bundle exec ruby <script>
|
||||
|
||||
To execute scripts without `bundler`:
|
||||
|
||||
ruby <script>
|
||||
|
||||
## Support and Feedback
|
||||
|
||||
Your feedback is appreciated! If you have specific issues with the **fog** SDK, developers should file an [issue via Github](https://github.com/fog/fog/issues).
|
||||
|
||||
For general feedback and support requests, send an email to: <sdk-support@rackspace.com>.
|
66
lib/fog/rackspace/examples/auto_scale/add_policy.rb
Normal file
66
lib/fog/rackspace/examples/auto_scale/add_policy.rb
Normal file
|
@ -0,0 +1,66 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
# This example demonstrates adding a poicy to an auto scaling group with the Rackpace Open Cloud
|
||||
|
||||
require 'fog'
|
||||
|
||||
def get_user_input(prompt)
|
||||
print "#{prompt}: "
|
||||
gets.chomp
|
||||
end
|
||||
|
||||
def get_user_input_as_int(prompt)
|
||||
str = get_user_input(prompt)
|
||||
str.to_i
|
||||
end
|
||||
|
||||
# Use username defined in ~/.fog file, if absent prompt for username.
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_username
|
||||
Fog.credentials[:rackspace_username] || get_user_input("Enter Rackspace Username")
|
||||
end
|
||||
|
||||
# Use api key defined in ~/.fog file, if absent prompt for api key
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_api_key
|
||||
Fog.credentials[:rackspace_api_key] || get_user_input("Enter Rackspace API key")
|
||||
end
|
||||
|
||||
def select_group(groups)
|
||||
abort "\nThere are not any scaling groups in the Chicago region. Try running create_scaling_group.rb\n\n" if groups.empty?
|
||||
|
||||
puts "\nSelect Group For New Policy:\n\n"
|
||||
groups.each_with_index do |group, i|
|
||||
config = group.group_config
|
||||
puts "\t #{i}. #{config.name}"
|
||||
end
|
||||
|
||||
select_str = get_user_input "\nEnter Group Number"
|
||||
groups[select_str.to_i]
|
||||
end
|
||||
|
||||
# create auto scaling service
|
||||
auto_scale_service = Fog::Rackspace::AutoScale.new({
|
||||
:rackspace_username => rackspace_username,
|
||||
:rackspace_api_key => rackspace_api_key,
|
||||
:rackspace_region => :ord # Use Chicago Region
|
||||
})
|
||||
|
||||
# retrieve list of scaling groups
|
||||
groups = auto_scale_service.groups
|
||||
|
||||
# prompt group
|
||||
group = select_group(groups)
|
||||
|
||||
# prompt for policy name
|
||||
policy_name = get_user_input "Enter name for policy"
|
||||
|
||||
# prompt for cool down period for policy
|
||||
cooldown = get_user_input_as_int "Enter cool down period in seconds"
|
||||
|
||||
# prompt for change increment
|
||||
change = get_user_input_as_int "Enter change increment"
|
||||
|
||||
group.policies.create :name => policy_name, :cooldown => cooldown, :type => 'webhook', :change => change
|
||||
|
||||
puts "\nPolicy #{policy_name} was successfully added to group"
|
74
lib/fog/rackspace/examples/auto_scale/add_webhook.rb
Normal file
74
lib/fog/rackspace/examples/auto_scale/add_webhook.rb
Normal file
|
@ -0,0 +1,74 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
# This example demonstrates adding a webhook to an auto scaling group with the Rackpace Open Cloud
|
||||
|
||||
require 'fog'
|
||||
|
||||
def get_user_input(prompt)
|
||||
print "#{prompt}: "
|
||||
gets.chomp
|
||||
end
|
||||
|
||||
# Use username defined in ~/.fog file, if absent prompt for username.
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_username
|
||||
Fog.credentials[:rackspace_username] || get_user_input("Enter Rackspace Username")
|
||||
end
|
||||
|
||||
# Use api key defined in ~/.fog file, if absent prompt for api key
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_api_key
|
||||
Fog.credentials[:rackspace_api_key] || get_user_input("Enter Rackspace API key")
|
||||
end
|
||||
|
||||
def select_group(groups)
|
||||
abort "\nThere are no groups in the Chicago region. Try running create_scaling_group.rb\n\n" if groups.empty?
|
||||
|
||||
puts "\nSelect Group With Policy:\n\n"
|
||||
groups.each_with_index do |group, i|
|
||||
config = group.group_config
|
||||
puts "\t #{i}. #{config.name}"
|
||||
end
|
||||
|
||||
select_str = get_user_input "\nEnter Group Number"
|
||||
groups[select_str.to_i]
|
||||
end
|
||||
|
||||
def select_policy(policies)
|
||||
abort "\nThere are no policies for this scaling group. Try running add_policy.rb\n\n" if policies.empty?
|
||||
|
||||
puts "\nSelect Policy Triggered By Webhook:\n\n"
|
||||
policies.each_with_index do |policy, i|
|
||||
puts "\t #{i}. #{policy.name}"
|
||||
end
|
||||
|
||||
select_str = get_user_input "\nEnter Policy Number"
|
||||
policies[select_str.to_i]
|
||||
end
|
||||
|
||||
# create auto scaling service
|
||||
auto_scale_service = Fog::Rackspace::AutoScale.new({
|
||||
:rackspace_username => rackspace_username,
|
||||
:rackspace_api_key => rackspace_api_key,
|
||||
:rackspace_region => :ord # Use Chicago Region
|
||||
})
|
||||
|
||||
# retrieve list of scaling groups
|
||||
groups = auto_scale_service.groups
|
||||
|
||||
# prompt for group
|
||||
group = select_group(groups)
|
||||
|
||||
# retrieve list of policies for group
|
||||
policies = group.policies
|
||||
|
||||
# prompt for policy to delete
|
||||
policy = select_policy(policies)
|
||||
|
||||
# prompt for webhook name
|
||||
webhook_name = get_user_input "Enter name for webhook"
|
||||
|
||||
# create webhook
|
||||
webhook = policy.webhooks.create :name => webhook_name
|
||||
|
||||
puts "\nWebhook #{webhook.name} was successfully added - #{webhook.execution_url}"
|
111
lib/fog/rackspace/examples/auto_scale/create_scaling_group.rb
Normal file
111
lib/fog/rackspace/examples/auto_scale/create_scaling_group.rb
Normal file
|
@ -0,0 +1,111 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
# This example demonstrates creating an auto scaling group with the Rackpace Open Cloud
|
||||
|
||||
require 'fog'
|
||||
require 'fog/rackspace/models/auto_scale/group_builder'
|
||||
|
||||
# UUID for INTERNET
|
||||
INTERNET = '00000000-0000-0000-0000-000000000000'
|
||||
|
||||
# UUID for Rackspace's service net
|
||||
SERVICE_NET = '11111111-1111-1111-1111-111111111111'
|
||||
|
||||
def get_user_input(prompt)
|
||||
print "#{prompt}: "
|
||||
gets.chomp
|
||||
end
|
||||
|
||||
def get_user_input_as_int(prompt)
|
||||
str = get_user_input(prompt)
|
||||
str.to_i
|
||||
end
|
||||
|
||||
# Use username defined in ~/.fog file, if absent prompt for username.
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_username
|
||||
Fog.credentials[:rackspace_username] || get_user_input("Enter Rackspace Username")
|
||||
end
|
||||
|
||||
# Use api key defined in ~/.fog file, if absent prompt for api key
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_api_key
|
||||
Fog.credentials[:rackspace_api_key] || get_user_input("Enter Rackspace API key")
|
||||
end
|
||||
|
||||
def select_image(images)
|
||||
puts "\nSelect Image For Server:\n\n"
|
||||
images.each_with_index do |image, i|
|
||||
puts "\t #{i}. #{image.name}"
|
||||
end
|
||||
|
||||
select_str = get_user_input "\nEnter Image Number"
|
||||
images[select_str.to_i]
|
||||
end
|
||||
|
||||
# create auto scaling service
|
||||
auto_scale_service = Fog::Rackspace::AutoScale.new({
|
||||
:rackspace_username => rackspace_username,
|
||||
:rackspace_api_key => rackspace_api_key,
|
||||
:rackspace_region => :ord # Use Chicago Region
|
||||
})
|
||||
|
||||
# create Next Generation Cloud Server service to get list of flavors
|
||||
compute_service = Fog::Compute.new({
|
||||
:provider => 'rackspace',
|
||||
:rackspace_username => rackspace_username,
|
||||
:rackspace_api_key => rackspace_api_key,
|
||||
:version => :v2, # Use Next Gen Cloud Servers
|
||||
:rackspace_region => :ord # Use Chicago Region
|
||||
})
|
||||
|
||||
# prompt for scaling group name
|
||||
scaling_group_name = get_user_input "Enter name of scaling group"
|
||||
|
||||
# prompt for cool down period
|
||||
cooldown = get_user_input_as_int "Enter cool down period in seconds"
|
||||
|
||||
# prompt for miniumum number of entities
|
||||
min_entities = get_user_input_as_int "Enter minimum number of servers"
|
||||
|
||||
# prompt for max number of entities
|
||||
max_entities = get_user_input_as_int "Enter maximum number of servers"
|
||||
|
||||
# retrieve list of images from computer service
|
||||
print "Loading available server images...."
|
||||
images = compute_service.images.all
|
||||
puts "[DONE]"
|
||||
|
||||
# prompt for server image
|
||||
image = select_image(images)
|
||||
|
||||
# pick first server flavor
|
||||
flavor = compute_service.flavors.first
|
||||
|
||||
attributes = {
|
||||
:server_name => "autoscale_server",
|
||||
:image => image,
|
||||
:flavor => flavor,
|
||||
:networks => [INTERNET, SERVICE_NET],
|
||||
:personality => [
|
||||
{
|
||||
"path" => "/root/.csivh",
|
||||
"contents" => "VGhpcyBpcyBhIHRlc3QgZmlsZS4="
|
||||
}
|
||||
],
|
||||
:max_entities => max_entities,
|
||||
:min_entities => min_entities,
|
||||
:cooldown => cooldown,
|
||||
:name => scaling_group_name,
|
||||
:metadata => { "created_by" => "autoscale sample script" },
|
||||
:launch_config_type => :launch_server
|
||||
}
|
||||
|
||||
# Use builder to create group
|
||||
group = Fog::Rackspace::AutoScale::GroupBuilder.build(auto_scale_service, attributes)
|
||||
|
||||
# save the built group
|
||||
group.save
|
||||
|
||||
puts "\nScaling Group #{scaling_group_name} (#{group.id}) was created!"
|
||||
puts "State: #{group.state}"
|
71
lib/fog/rackspace/examples/auto_scale/delete_policy.rb
Normal file
71
lib/fog/rackspace/examples/auto_scale/delete_policy.rb
Normal file
|
@ -0,0 +1,71 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
# This example demonstrates deleting an auto scaling policy with the Rackpace Open Cloud
|
||||
|
||||
require 'fog'
|
||||
|
||||
def get_user_input(prompt)
|
||||
print "#{prompt}: "
|
||||
gets.chomp
|
||||
end
|
||||
|
||||
# Use username defined in ~/.fog file, if absent prompt for username.
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_username
|
||||
Fog.credentials[:rackspace_username] || get_user_input("Enter Rackspace Username")
|
||||
end
|
||||
|
||||
# Use api key defined in ~/.fog file, if absent prompt for api key
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_api_key
|
||||
Fog.credentials[:rackspace_api_key] || get_user_input("Enter Rackspace API key")
|
||||
end
|
||||
|
||||
def select_group(groups)
|
||||
abort "\nThere are no groups in the Chicago region. Try running create_scaling_group.rb\n\n" if groups.empty?
|
||||
|
||||
puts "\nSelect Group With Policy:\n\n"
|
||||
groups.each_with_index do |group, i|
|
||||
config = group.group_config
|
||||
puts "\t #{i}. #{config.name}"
|
||||
end
|
||||
|
||||
select_str = get_user_input "\nEnter Group Number"
|
||||
groups[select_str.to_i]
|
||||
end
|
||||
|
||||
def select_policy(policies)
|
||||
abort "\nThere are no policies for this scaling group. Try running add_policy.rb\n\n" if policies.empty?
|
||||
|
||||
puts "\nSelect Policy To Delete:\n\n"
|
||||
policies.each_with_index do |policies, i|
|
||||
puts "\t #{i}. #{policies.name}"
|
||||
end
|
||||
|
||||
select_str = get_user_input "\nEnter Policy Number"
|
||||
policies[select_str.to_i]
|
||||
end
|
||||
|
||||
# create auto scaling service
|
||||
auto_scale_service = Fog::Rackspace::AutoScale.new({
|
||||
:rackspace_username => rackspace_username,
|
||||
:rackspace_api_key => rackspace_api_key,
|
||||
:rackspace_region => :ord # Use Chicago Region
|
||||
})
|
||||
|
||||
# retrieve list of scaling groups
|
||||
groups = auto_scale_service.groups
|
||||
|
||||
# prompt for group
|
||||
group = select_group(groups)
|
||||
|
||||
# retrieve list of policies for group
|
||||
policies = group.policies
|
||||
|
||||
# prompt for policy to delete
|
||||
policy = select_policy(policies)
|
||||
|
||||
# delete policy
|
||||
policy.destroy
|
||||
|
||||
puts "\nPolicy '#{policy.name}' has been destroyed\n\n"
|
|
@ -0,0 +1,59 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
# This example demonstrates deleting an auto scaling group with the Rackpace Open Cloud
|
||||
|
||||
require 'fog'
|
||||
|
||||
def get_user_input(prompt)
|
||||
print "#{prompt}: "
|
||||
gets.chomp
|
||||
end
|
||||
|
||||
# Use username defined in ~/.fog file, if absent prompt for username.
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_username
|
||||
Fog.credentials[:rackspace_username] || get_user_input("Enter Rackspace Username")
|
||||
end
|
||||
|
||||
# Use api key defined in ~/.fog file, if absent prompt for api key
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_api_key
|
||||
Fog.credentials[:rackspace_api_key] || get_user_input("Enter Rackspace API key")
|
||||
end
|
||||
|
||||
def select_group(groups)
|
||||
abort "\nThere are not any groups to delete in the Chicago region. Try running create_scaling_group.rb\n\n" if groups.empty?
|
||||
|
||||
puts "\nSelect Group To Delete:\n\n"
|
||||
groups.each_with_index do |group, i|
|
||||
config = group.group_config
|
||||
puts "\t #{i}. #{config.name}"
|
||||
end
|
||||
|
||||
select_str = get_user_input "\nEnter Group Number"
|
||||
groups[select_str.to_i]
|
||||
end
|
||||
|
||||
# create auto scaling service
|
||||
auto_scale_service = Fog::Rackspace::AutoScale.new({
|
||||
:rackspace_username => rackspace_username,
|
||||
:rackspace_api_key => rackspace_api_key,
|
||||
:rackspace_region => :ord # Use Chicago Region
|
||||
})
|
||||
|
||||
# retrieve list of scaling groups
|
||||
groups = auto_scale_service.groups
|
||||
|
||||
# prompt for group to delete
|
||||
group = select_group(groups)
|
||||
|
||||
# min_entities and max_entities must be 0 before deleting group
|
||||
config = group.group_config
|
||||
config.min_entities = 0
|
||||
config.max_entities = 0
|
||||
config.save
|
||||
|
||||
# delete group
|
||||
group.destroy
|
||||
|
||||
puts "\nScaling Group '#{config.name}' has been destroyed\n\n"
|
89
lib/fog/rackspace/examples/auto_scale/delete_webhook.rb
Normal file
89
lib/fog/rackspace/examples/auto_scale/delete_webhook.rb
Normal file
|
@ -0,0 +1,89 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
# This example demonstrates delete a webhook from an auto scaling group with the Rackpace Open Cloud
|
||||
|
||||
require 'fog'
|
||||
|
||||
def get_user_input(prompt)
|
||||
print "#{prompt}: "
|
||||
gets.chomp
|
||||
end
|
||||
|
||||
# Use username defined in ~/.fog file, if absent prompt for username.
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_username
|
||||
Fog.credentials[:rackspace_username] || get_user_input("Enter Rackspace Username")
|
||||
end
|
||||
|
||||
# Use api key defined in ~/.fog file, if absent prompt for api key
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_api_key
|
||||
Fog.credentials[:rackspace_api_key] || get_user_input("Enter Rackspace API key")
|
||||
end
|
||||
|
||||
def select_group(groups)
|
||||
abort "\nThere are no groups in the Chicago region. Try running create_scaling_group.rb\n\n" if groups.empty?
|
||||
|
||||
puts "\nSelect Group With Policy:\n\n"
|
||||
groups.each_with_index do |group, i|
|
||||
config = group.group_config
|
||||
puts "\t #{i}. #{config.name}"
|
||||
end
|
||||
|
||||
select_str = get_user_input "\nEnter Group Number"
|
||||
groups[select_str.to_i]
|
||||
end
|
||||
|
||||
def select_policy(policies)
|
||||
abort "\nThere are no policies for this scaling group. Try running add_policy.rb\n\n" if policies.empty?
|
||||
|
||||
puts "\nSelect Policy With Webhook:\n\n"
|
||||
policies.each_with_index do |policy, i|
|
||||
puts "\t #{i}. #{policy.name}"
|
||||
end
|
||||
|
||||
select_str = get_user_input "\nEnter Policy Number"
|
||||
policies[select_str.to_i]
|
||||
end
|
||||
|
||||
def select_webhook(webhooks)
|
||||
abort "\nThere are no webhooks for this policy. Try running add_webhook.rb\n\n" if webhooks.empty?
|
||||
|
||||
puts "\nSelect Webhook:\n\n"
|
||||
webhooks.each_with_index do |webhook, i|
|
||||
puts "\t #{i}. #{webhook.name}"
|
||||
end
|
||||
|
||||
select_str = get_user_input "\nEnter Webhook Number"
|
||||
webhooks[select_str.to_i]
|
||||
end
|
||||
|
||||
# create auto scaling service
|
||||
auto_scale_service = Fog::Rackspace::AutoScale.new({
|
||||
:rackspace_username => rackspace_username,
|
||||
:rackspace_api_key => rackspace_api_key,
|
||||
:rackspace_region => :ord # Use Chicago Region
|
||||
})
|
||||
|
||||
# retrieve list of scaling groups
|
||||
groups = auto_scale_service.groups
|
||||
|
||||
# prompt for group
|
||||
group = select_group(groups)
|
||||
|
||||
# retrieve list of policies for group
|
||||
policies = group.policies
|
||||
|
||||
# prompt for policy
|
||||
policy = select_policy(policies)
|
||||
|
||||
# retrieve list of webhooks for policy
|
||||
webhooks = policy.webhooks
|
||||
|
||||
# prompt for webhook
|
||||
webhook = select_webhook(webhooks)
|
||||
|
||||
# delete webhook
|
||||
webhook.destroy
|
||||
|
||||
puts "Webhook '#{webhook.name} was destroyed"
|
116
lib/fog/rackspace/examples/block_storage/create_snapshot.rb
Normal file
116
lib/fog/rackspace/examples/block_storage/create_snapshot.rb
Normal file
|
@ -0,0 +1,116 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
# This example demonstrates creating a snapshot from a Cloud Block Storage volume with the Rackpace Open Cloud
|
||||
|
||||
require 'rubygems' #required for Ruby 1.8.x
|
||||
require 'fog'
|
||||
|
||||
def get_user_input(prompt)
|
||||
print "\n#{prompt}: "
|
||||
gets.chomp
|
||||
end
|
||||
|
||||
def select_server(servers)
|
||||
abort "\nThere are not any servers in the Chicago region. Try running create_server.rb\n\n" if servers.empty?
|
||||
|
||||
puts "\nSelect Server For Volume Detachment:\n\n"
|
||||
servers.each_with_index do |server, i|
|
||||
puts "\t #{i}. #{server.name} [#{server.public_ip_address}]"
|
||||
end
|
||||
|
||||
delete_str = get_user_input "\nEnter Server Number"
|
||||
servers[delete_str.to_i]
|
||||
end
|
||||
|
||||
def select_attachment(attachments)
|
||||
abort "\nThis server does not contain any volumes in the Chicago region. Try running server_attachments.rb\n\n" if attachments.empty?
|
||||
|
||||
puts "\nSelect Volume To Detach:\n\n"
|
||||
attachments.each_with_index do |attachment, i|
|
||||
puts "\t #{i}. #{attachment.device}"
|
||||
end
|
||||
|
||||
delete_str = get_user_input "\nEnter Volume Number"
|
||||
attachments[delete_str.to_i]
|
||||
end
|
||||
|
||||
# Use username defined in ~/.fog file, if absent prompt for username.
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_username
|
||||
Fog.credentials[:rackspace_username] || get_user_input("Enter Rackspace Username")
|
||||
end
|
||||
|
||||
# Use api key defined in ~/.fog file, if absent prompt for api key
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_api_key
|
||||
Fog.credentials[:rackspace_api_key] || get_user_input("Enter Rackspace API key")
|
||||
end
|
||||
|
||||
#create Next Generation Cloud Server service
|
||||
compute_service = Fog::Compute.new({
|
||||
:provider => 'rackspace',
|
||||
:rackspace_username => rackspace_username,
|
||||
:rackspace_api_key => rackspace_api_key,
|
||||
:version => :v2, # Use Next Gen Cloud Servers
|
||||
:rackspace_region => :ord #Use Chicago Region
|
||||
})
|
||||
|
||||
#create Cloud Block Storage service
|
||||
cbs_service = Fog::Rackspace::BlockStorage.new({
|
||||
:rackspace_username => rackspace_username,
|
||||
:rackspace_api_key => rackspace_api_key,
|
||||
:rackspace_region => :ord #Use Chicago Region
|
||||
})
|
||||
|
||||
# retrieve list of servers
|
||||
servers = compute_service.servers
|
||||
|
||||
# prompt user for server
|
||||
server = select_server(servers)
|
||||
|
||||
# get attached volumes --also know as attachments
|
||||
attachments = server.attachments
|
||||
|
||||
# prompt user for volume to detach
|
||||
attachment = select_attachment(attachments)
|
||||
|
||||
# prompt for snapshot name
|
||||
snapshot_name = get_user_input "Enter Snapshot Name"
|
||||
|
||||
puts "\n\n"
|
||||
puts "******************** NOTE ******************************************"
|
||||
puts "* Volume must be unmounted from operating system before detaching. *"
|
||||
puts "* This script assumes volume has been unmounted. *"
|
||||
puts "********************************************************************\n\n"
|
||||
|
||||
volume = cbs_service.volumes.get attachment.volume_id
|
||||
|
||||
# The snapshot process requires all writes to be flushed to disk. This requires unmounting the file systems or detaching the volume.
|
||||
puts "Detaching Volume #{volume.display_name}"
|
||||
attachment.detach
|
||||
|
||||
volume.wait_for { ready? }
|
||||
|
||||
puts "Now Creating Snapshot #{snapshot_name}"
|
||||
snapshot = cbs_service.snapshots.create :display_name => snapshot_name, :volume_id => attachment.volume_id
|
||||
|
||||
begin
|
||||
# Check every 5 seconds to see if snapshot is in the available state (ready?).
|
||||
# If the available has not been built in 5 minutes (600 seconds) an exception will be raised.
|
||||
snapshot.wait_for(600, 5) do
|
||||
print "."
|
||||
STDOUT.flush
|
||||
ready?
|
||||
end
|
||||
|
||||
puts "[DONE]\n\n"
|
||||
|
||||
puts "Re-attaching Volume #{volume.display_name}"
|
||||
attachment.save
|
||||
|
||||
rescue Fog::Errors::TimeoutError
|
||||
puts "[TIMEOUT]\n\n"
|
||||
|
||||
puts "The snapshot #{snapshot.display_name} is still being preformed and is taking longer to complete than expected."
|
||||
puts "You can continute to monitor the process through the web console at https://mycloud.rackspace.com/\n\n"
|
||||
end
|
58
lib/fog/rackspace/examples/block_storage/create_volume.rb
Normal file
58
lib/fog/rackspace/examples/block_storage/create_volume.rb
Normal file
|
@ -0,0 +1,58 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
# This example demonstrates creating Cloud Block Storage volume with the Rackpace Open Cloud
|
||||
|
||||
require 'rubygems' #required for Ruby 1.8.x
|
||||
require 'fog'
|
||||
|
||||
def get_user_input(prompt)
|
||||
print "\n#{prompt}: "
|
||||
gets.chomp
|
||||
end
|
||||
|
||||
def select_volume_type(volume_types)
|
||||
puts "\nSelect Volume Type:\n\n"
|
||||
volume_types.each_with_index do |volume_type, i|
|
||||
puts "\t #{i}. #{volume_type.name}"
|
||||
end
|
||||
|
||||
selected_str = get_user_input "Enter Volume Type Number"
|
||||
volume_types[selected_str.to_i]
|
||||
end
|
||||
|
||||
# Use username defined in ~/.fog file, if absent prompt for username.
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_username
|
||||
Fog.credentials[:rackspace_username] || get_user_input("Enter Rackspace Username")
|
||||
end
|
||||
|
||||
# Use api key defined in ~/.fog file, if absent prompt for api key
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_api_key
|
||||
Fog.credentials[:rackspace_api_key] || get_user_input("Enter Rackspace API key")
|
||||
end
|
||||
|
||||
# create Cloud Block Storage service
|
||||
service = Fog::Rackspace::BlockStorage.new({
|
||||
:rackspace_username => rackspace_username,
|
||||
:rackspace_api_key => rackspace_api_key,
|
||||
:rackspace_region => :ord #Use Chicago Region
|
||||
})
|
||||
|
||||
# retrieve list of volume types
|
||||
volume_types = service.volume_types
|
||||
|
||||
#prompt user for volume type
|
||||
volume_type = select_volume_type(volume_types)
|
||||
|
||||
# prompt for volume size
|
||||
volume_size = get_user_input "Enter Size of Volume (100 GB Minimum)"
|
||||
|
||||
# prompt for name of volume
|
||||
volume_name = get_user_input "Enter Name for Volume"
|
||||
|
||||
#create volume
|
||||
volume = service.volumes.create(:size => volume_size, :display_name => volume_name, :volume_type => volume_type.name)
|
||||
|
||||
puts "\nVolume #{volume_name} is being created.\n\n"
|
||||
puts "To delete the volume please execute the delete_volume.rb script\n\n"
|
53
lib/fog/rackspace/examples/block_storage/delete_volume.rb
Normal file
53
lib/fog/rackspace/examples/block_storage/delete_volume.rb
Normal file
|
@ -0,0 +1,53 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
# This example demonstrates deleting Cloud Block Storage volume with the Rackpace Open Cloud
|
||||
|
||||
require 'rubygems' #required for Ruby 1.8.x
|
||||
require 'fog'
|
||||
|
||||
def get_user_input(prompt)
|
||||
print "\n#{prompt}: "
|
||||
gets.chomp
|
||||
end
|
||||
|
||||
def select_volume(volumes)
|
||||
abort "\nThere are not any volumes to delete in the Chicago region. Try running create_volume.rb\n\n" if volumes.empty?
|
||||
|
||||
puts "\nSelect Volume:\n\n"
|
||||
volumes.each_with_index do |volume, i|
|
||||
puts "\t #{i}. #{volume.display_name}"
|
||||
end
|
||||
|
||||
selected_str = get_user_input "Enter Volume Type Number"
|
||||
volumes[selected_str.to_i]
|
||||
end
|
||||
|
||||
# Use username defined in ~/.fog file, if absent prompt for username.
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_username
|
||||
Fog.credentials[:rackspace_username] || get_user_input("Enter Rackspace Username")
|
||||
end
|
||||
|
||||
# Use api key defined in ~/.fog file, if absent prompt for api key
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_api_key
|
||||
Fog.credentials[:rackspace_api_key] || get_user_input("Enter Rackspace API key")
|
||||
end
|
||||
|
||||
# create Cloud Block Storage service
|
||||
service = Fog::Rackspace::BlockStorage.new({
|
||||
:rackspace_username => rackspace_username,
|
||||
:rackspace_api_key => rackspace_api_key,
|
||||
:rackspace_region => :ord #Use Chicago Region
|
||||
})
|
||||
|
||||
# retrieve list of volumes
|
||||
volumes = service.volumes
|
||||
|
||||
# prompt user for volume
|
||||
volume = select_volume(volumes)
|
||||
|
||||
# delete volume
|
||||
volume.destroy
|
||||
|
||||
puts "\nVolume #{volume.display_name} is being destroyed.\n\n"
|
96
lib/fog/rackspace/examples/compute_v2/bootstrap_server.rb
Normal file
96
lib/fog/rackspace/examples/compute_v2/bootstrap_server.rb
Normal file
|
@ -0,0 +1,96 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
# This example demonstrates creating a server with the Rackpace Open Cloud
|
||||
|
||||
require 'rubygems' #required for Ruby 1.8.x
|
||||
require 'fog'
|
||||
require 'base64' #required to encode files for personality functionality
|
||||
require 'sshkey' #required to generate ssh keys. 'gem install sshkey'
|
||||
|
||||
def get_user_input(prompt)
|
||||
print "#{prompt}: "
|
||||
gets.chomp
|
||||
end
|
||||
|
||||
# Use username defined in ~/.fog file, if absent prompt for username.
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_username
|
||||
Fog.credentials[:rackspace_username] || get_user_input("Enter Rackspace Username")
|
||||
end
|
||||
|
||||
# Use api key defined in ~/.fog file, if absent prompt for api key
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_api_key
|
||||
Fog.credentials[:rackspace_api_key] || get_user_input("Enter Rackspace API key")
|
||||
end
|
||||
|
||||
# Generates a ssh key using the SSHKey library. The private key is avaialble via
|
||||
# the '.private_key' and the public key is avaialble via '.ssh_public_key'
|
||||
def generate_ssh_key
|
||||
SSHKey.generate
|
||||
end
|
||||
|
||||
# create Next Generation Cloud Server service
|
||||
service = Fog::Compute.new({
|
||||
:provider => 'rackspace',
|
||||
:rackspace_username => rackspace_username,
|
||||
:rackspace_api_key => rackspace_api_key,
|
||||
:version => :v2, # Use Next Gen Cloud Servers
|
||||
:rackspace_region => :ord #Use Chicago Region
|
||||
})
|
||||
|
||||
# pick the first flavor
|
||||
flavor = service.flavors.first
|
||||
|
||||
# pick the first Ubuntu image we can find
|
||||
image = service.images.find {|image| image.name =~ /Ubuntu/}
|
||||
|
||||
# prompt for server name
|
||||
server_name = get_user_input "\nEnter Server Name"
|
||||
|
||||
# generate the ssh key
|
||||
ssh_key = generate_ssh_key
|
||||
|
||||
# reload flavor in order to retrieve all of its attributes
|
||||
flavor.reload
|
||||
|
||||
puts "\nNow creating server '#{server_name}' the following with specifications:\n"
|
||||
puts "\t* #{flavor.ram} MB RAM"
|
||||
puts "\t* #{flavor.disk} GB"
|
||||
puts "\t* #{flavor.vcpus} CPU(s)"
|
||||
puts "\t* #{image.name}"
|
||||
puts "\n"
|
||||
|
||||
begin
|
||||
# bootstrap server
|
||||
server = service.servers.bootstrap :name => server_name,
|
||||
:flavor_id => flavor.id,
|
||||
:image_id => image.id,
|
||||
:private_key => ssh_key.private_key,
|
||||
:public_key => ssh_key.ssh_public_key
|
||||
|
||||
if server.ready?
|
||||
puts "[DONE]\n\n"
|
||||
|
||||
puts "The server has been successfully created.\n"
|
||||
puts "Write the following ssh keys to you ~/.ssh directory in order to log in\n\n"
|
||||
puts "+++++++++++PRIVATE_KEY (~/.ssh/fog_key)++++++++++++"
|
||||
puts ssh_key.private_key
|
||||
puts "++++++++++PUBLIC_KEY (~/.ssh/fog_key.pub)++++++++++"
|
||||
puts ssh_key.ssh_public_key
|
||||
puts "+++++++++++++++++++++++++++++++++++++++++++++++++++i\n\n"
|
||||
|
||||
puts "You can then log into the server using the following command\n"
|
||||
puts "ssh #{server.username}@#{server.public_ip_address}\n\n"
|
||||
else
|
||||
puts "An error occured, please try again"
|
||||
end
|
||||
|
||||
rescue Fog::Errors::TimeoutError
|
||||
puts "[TIMEOUT]\n\n"
|
||||
|
||||
puts "This server is currently #{server.progress}% into the build process and is taking longer to complete than expected."
|
||||
puts "You can continute to monitor the build process through the web console at https://mycloud.rackspace.com/\n\n"
|
||||
end
|
||||
|
||||
puts "To delete the server please execute the delete_server.rb script\n\n"
|
59
lib/fog/rackspace/examples/compute_v2/create_image.rb
Normal file
59
lib/fog/rackspace/examples/compute_v2/create_image.rb
Normal file
|
@ -0,0 +1,59 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
# This example demonstrates creating a server image with the Rackpace Open Cloud
|
||||
|
||||
require 'rubygems' #required for Ruby 1.8.x
|
||||
require 'fog'
|
||||
|
||||
def get_user_input(prompt)
|
||||
print "#{prompt}: "
|
||||
gets.chomp
|
||||
end
|
||||
|
||||
def select_server(servers)
|
||||
abort "\nThere are not any servers available to image in the Chicago region. Try running create_server.rb\n\n" if servers.empty?
|
||||
|
||||
puts "\nSelect Server To Image:\n\n"
|
||||
servers.each_with_index do |server, i|
|
||||
puts "\t #{i}. #{server.name} [#{server.public_ip_address}]"
|
||||
end
|
||||
|
||||
selected_str = get_user_input "\nEnter Server Number"
|
||||
servers[selected_str.to_i]
|
||||
end
|
||||
|
||||
# Use username defined in ~/.fog file, if absent prompt for username.
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_username
|
||||
Fog.credentials[:rackspace_username] || get_user_input("Enter Rackspace Username")
|
||||
end
|
||||
|
||||
# Use api key defined in ~/.fog file, if absent prompt for api key
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_api_key
|
||||
Fog.credentials[:rackspace_api_key] || get_user_input("Enter Rackspace API key")
|
||||
end
|
||||
|
||||
# create Next Generation Cloud Server service
|
||||
service = Fog::Compute.new({
|
||||
:provider => 'rackspace',
|
||||
:rackspace_username => rackspace_username,
|
||||
:rackspace_api_key => rackspace_api_key,
|
||||
:version => :v2, # Use Next Gen Cloud Servers
|
||||
:rackspace_region => :ord #Use Chicago Region
|
||||
})
|
||||
|
||||
# retrieve list of servers
|
||||
servers = service.servers
|
||||
|
||||
# prompt user for server
|
||||
server = select_server(servers)
|
||||
|
||||
# prompt user for image name
|
||||
image_name = get_user_input "Enter Image Name"
|
||||
|
||||
# creates image for server
|
||||
server.create_image image_name
|
||||
|
||||
puts "\nImage #{image_name} is being created for server #{server.name}.\n\n"
|
||||
puts "To delete the image please execute the delete_image.rb script\n\n"
|
81
lib/fog/rackspace/examples/compute_v2/create_network.rb
Normal file
81
lib/fog/rackspace/examples/compute_v2/create_network.rb
Normal file
|
@ -0,0 +1,81 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
# This example demonstrates creating a private network and attaching it to a new server with the Rackpace Open Cloud
|
||||
|
||||
require 'rubygems' #required for Ruby 1.8.x
|
||||
require 'fog'
|
||||
|
||||
# UUID for INTERNET
|
||||
INTERNET = '00000000-0000-0000-0000-000000000000'
|
||||
|
||||
# UUID for Rackspace's service net
|
||||
SERVICE_NET = '11111111-1111-1111-1111-111111111111'
|
||||
|
||||
def get_user_input(prompt)
|
||||
print "#{prompt}: "
|
||||
gets.chomp
|
||||
end
|
||||
|
||||
# Use username defined in ~/.fog file, if absent prompt for username.
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_username
|
||||
Fog.credentials[:rackspace_username] || get_user_input("Enter Rackspace Username")
|
||||
end
|
||||
|
||||
# Use api key defined in ~/.fog file, if absent prompt for api key
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_api_key
|
||||
Fog.credentials[:rackspace_api_key] || get_user_input("Enter Rackspace API key")
|
||||
end
|
||||
|
||||
# create Next Generation Cloud Server service
|
||||
service = Fog::Compute.new({
|
||||
:provider => 'rackspace',
|
||||
:rackspace_username => rackspace_username,
|
||||
:rackspace_api_key => rackspace_api_key,
|
||||
:version => :v2, # Use Next Gen Cloud Servers
|
||||
:rackspace_region => :ord #Use Chicago Region
|
||||
})
|
||||
|
||||
#create private network called my_private_net with an ip range between 192.168.0.1 - 192.168.0.255 (Note this will accept IPv6 CIDRs as well)
|
||||
net = service.networks.create :label => 'my_private_net', :cidr => '192.168.0.0/24'
|
||||
|
||||
puts "\nCreating #{net.label} Network with CIDR #{net.cidr}"
|
||||
|
||||
# pick the first flavor
|
||||
flavor = service.flavors.first
|
||||
|
||||
# pick the first Ubuntu image we can find
|
||||
image = service.images.find {|image| image.name =~ /Ubuntu/}
|
||||
|
||||
# Create a server called alphabits connected our private network as well as the internet
|
||||
server = service.servers.create :name => 'alphabits',
|
||||
:flavor_id => flavor.id,
|
||||
:image_id => image.id,
|
||||
:networks => [net.id, INTERNET]
|
||||
|
||||
puts "\nNow creating server '#{server.name}' connected the the Internet and '#{net.label}'\n"
|
||||
|
||||
begin
|
||||
# Check every 5 seconds to see if server is in the active state (ready?).
|
||||
# If the server has not been built in 5 minutes (600 seconds) an exception will be raised.
|
||||
server.wait_for(600, 5) do
|
||||
print "."
|
||||
STDOUT.flush
|
||||
ready?
|
||||
end
|
||||
|
||||
puts "[DONE]\n\n"
|
||||
|
||||
puts "The server has been successfully created, to login onto the server:\n\n"
|
||||
puts "\t ssh #{server.username}@#{server.public_ip_address}\n\n"
|
||||
|
||||
rescue Fog::Errors::TimeoutError
|
||||
puts "[TIMEOUT]\n\n"
|
||||
|
||||
puts "This server is currently #{server.progress}% into the build process and is taking longer to complete than expected."
|
||||
puts "You can continute to monitor the build process through the web console at https://mycloud.rackspace.com/\n\n"
|
||||
end
|
||||
|
||||
puts "The #{server.username} password is #{server.password}\n\n"
|
||||
puts "To delete the server and private network please execute the delete_network.rb script\n\n"
|
87
lib/fog/rackspace/examples/compute_v2/create_server.rb
Normal file
87
lib/fog/rackspace/examples/compute_v2/create_server.rb
Normal file
|
@ -0,0 +1,87 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
# This example demonstrates creating a server with the Rackpace Open Cloud
|
||||
|
||||
require 'rubygems' #required for Ruby 1.8.x
|
||||
require 'fog'
|
||||
require "base64" #required to encode files for personality functionality
|
||||
|
||||
def get_user_input(prompt)
|
||||
print "#{prompt}: "
|
||||
gets.chomp
|
||||
end
|
||||
|
||||
# Use username defined in ~/.fog file, if absent prompt for username.
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_username
|
||||
Fog.credentials[:rackspace_username] || get_user_input("Enter Rackspace Username")
|
||||
end
|
||||
|
||||
# Use api key defined in ~/.fog file, if absent prompt for api key
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_api_key
|
||||
Fog.credentials[:rackspace_api_key] || get_user_input("Enter Rackspace API key")
|
||||
end
|
||||
|
||||
# create Next Generation Cloud Server service
|
||||
service = Fog::Compute.new({
|
||||
:provider => 'rackspace',
|
||||
:rackspace_username => rackspace_username,
|
||||
:rackspace_api_key => rackspace_api_key,
|
||||
:version => :v2, # Use Next Gen Cloud Servers
|
||||
:rackspace_region => :ord #Use Chicago Region
|
||||
})
|
||||
|
||||
# pick the first flavor
|
||||
flavor = service.flavors.first
|
||||
|
||||
# pick the first Ubuntu image we can find
|
||||
image = service.images.find {|image| image.name =~ /Ubuntu/}
|
||||
|
||||
# prompt for server name
|
||||
server_name = get_user_input "\nEnter Server Name"
|
||||
|
||||
# create server
|
||||
server = service.servers.create :name => server_name,
|
||||
:flavor_id => flavor.id,
|
||||
:image_id => image.id,
|
||||
:metadata => { 'fog_sample' => 'true'},
|
||||
:personality => [{
|
||||
:path => '/root/fog.txt',
|
||||
:contents => Base64.encode64('Fog was here!')
|
||||
}]
|
||||
|
||||
# reload flavor in order to retrieve all of its attributes
|
||||
flavor.reload
|
||||
|
||||
puts "\nNow creating server '#{server.name}' the following with specifications:\n"
|
||||
puts "\t* #{flavor.ram} MB RAM"
|
||||
puts "\t* #{flavor.disk} GB"
|
||||
puts "\t* #{flavor.vcpus} CPU(s)"
|
||||
puts "\t* #{image.name}"
|
||||
|
||||
puts "\n"
|
||||
|
||||
begin
|
||||
# Check every 5 seconds to see if server is in the active state (ready?).
|
||||
# If the server has not been built in 5 minutes (600 seconds) an exception will be raised.
|
||||
server.wait_for(600, 5) do
|
||||
print "."
|
||||
STDOUT.flush
|
||||
ready?
|
||||
end
|
||||
|
||||
puts "[DONE]\n\n"
|
||||
|
||||
puts "The server has been successfully created, to login onto the server:\n\n"
|
||||
puts "\t ssh #{server.username}@#{server.public_ip_address}\n\n"
|
||||
|
||||
rescue Fog::Errors::TimeoutError
|
||||
puts "[TIMEOUT]\n\n"
|
||||
|
||||
puts "This server is currently #{server.progress}% into the build process and is taking longer to complete than expected."
|
||||
puts "You can continute to monitor the build process through the web console at https://mycloud.rackspace.com/\n\n"
|
||||
end
|
||||
|
||||
puts "The #{server.username} password is #{server.password}\n\n"
|
||||
puts "To delete the server please execute the delete_server.rb script\n\n"
|
60
lib/fog/rackspace/examples/compute_v2/delete_image.rb
Normal file
60
lib/fog/rackspace/examples/compute_v2/delete_image.rb
Normal file
|
@ -0,0 +1,60 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
# This example demonstrates deleting a server image with the Rackpace Open Cloud
|
||||
|
||||
require 'rubygems' #required for Ruby 1.8.x
|
||||
require 'fog'
|
||||
|
||||
def get_user_input(prompt)
|
||||
print "#{prompt}: "
|
||||
gets.chomp
|
||||
end
|
||||
|
||||
def select_image(snapshot_images)
|
||||
abort "\nThere are not any images to delete in the Chicago region. Try running create_image.rb\n\n" if snapshot_images.empty?
|
||||
|
||||
puts "\nSelect Image To Delete:\n\n"
|
||||
snapshot_images.each_with_index do |image, i|
|
||||
puts "\t #{i}. #{image.name}"
|
||||
end
|
||||
|
||||
delete_str = get_user_input "\nEnter Image Number"
|
||||
snapshot_images[delete_str.to_i]
|
||||
end
|
||||
|
||||
# Use username defined in ~/.fog file, if absent prompt for username.
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_username
|
||||
Fog.credentials[:rackspace_username] || get_user_input("Enter Rackspace Username")
|
||||
end
|
||||
|
||||
# Use api key defined in ~/.fog file, if absent prompt for api key
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_api_key
|
||||
Fog.credentials[:rackspace_api_key] || get_user_input("Enter Rackspace API key")
|
||||
end
|
||||
|
||||
# create Next Generation Cloud Server service
|
||||
service = Fog::Compute.new({
|
||||
:provider => 'rackspace',
|
||||
:rackspace_username => rackspace_username,
|
||||
:rackspace_api_key => rackspace_api_key,
|
||||
:version => :v2, # Use Next Gen Cloud Servers
|
||||
:rackspace_region => :ord #Use Chicago Region
|
||||
})
|
||||
|
||||
# retrieve list of images
|
||||
images = service.images
|
||||
|
||||
# select all of the snapshot type images. base images are not user deletable
|
||||
snapshot_images = images.select do |image|
|
||||
image.metadata["image_type"] == "snapshot"
|
||||
end
|
||||
|
||||
# prompt user for image to delete
|
||||
image = select_image(snapshot_images)
|
||||
|
||||
# delete image
|
||||
image.destroy
|
||||
|
||||
puts "\n#{image.name} has been destroyed\n\n"
|
78
lib/fog/rackspace/examples/compute_v2/delete_network.rb
Normal file
78
lib/fog/rackspace/examples/compute_v2/delete_network.rb
Normal file
|
@ -0,0 +1,78 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
# This example demonstrates deletes a private network and attaching it to a new server with the Rackpace Open Cloud
|
||||
|
||||
require 'rubygems' #required for Ruby 1.8.x
|
||||
require 'fog'
|
||||
|
||||
def wait_for_server_deletion(server)
|
||||
begin
|
||||
server.wait_for { state = 'DELETED' }
|
||||
rescue Fog::Compute::RackspaceV2::NotFound => e
|
||||
# do nothing
|
||||
end
|
||||
end
|
||||
|
||||
# I have notice that cloud networks is slow to acknowledge deleted servers. This method tries to mitigate this.
|
||||
def delete_network(network)
|
||||
attempt = 0
|
||||
begin
|
||||
network.destroy
|
||||
rescue Fog::Compute::RackspaceV2::ServiceError => e
|
||||
if attempt == 3
|
||||
puts "Unable to delete #{network.label}"
|
||||
return false
|
||||
end
|
||||
puts "Network #{network.label} Delete Fail Attempt #{attempt}- #{e.inspect}"
|
||||
attempt += 1
|
||||
sleep 60
|
||||
retry
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
def get_user_input(prompt)
|
||||
print "#{prompt}: "
|
||||
gets.chomp
|
||||
end
|
||||
|
||||
# Use username defined in ~/.fog file, if absent prompt for username.
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_username
|
||||
Fog.credentials[:rackspace_username] || get_user_input("Enter Rackspace Username")
|
||||
end
|
||||
|
||||
# Use api key defined in ~/.fog file, if absent prompt for api key
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_api_key
|
||||
Fog.credentials[:rackspace_api_key] || get_user_input("Enter Rackspace API key")
|
||||
end
|
||||
|
||||
# create Next Generation Cloud Server service
|
||||
service = Fog::Compute.new({
|
||||
:provider => 'rackspace',
|
||||
:rackspace_username => rackspace_username,
|
||||
:rackspace_api_key => rackspace_api_key,
|
||||
:version => :v2, # Use Next Gen Cloud Servers
|
||||
:rackspace_region => :ord #Use Chicago Region
|
||||
})
|
||||
|
||||
# NOTE: The network must not be connected to any servers before deletion
|
||||
|
||||
# Find alpha bits server
|
||||
server = service.servers.find {|s| s.name == 'alphabits'}
|
||||
|
||||
puts "\n"
|
||||
if server
|
||||
puts "Deleting alphabits server..."
|
||||
server.destroy
|
||||
else
|
||||
puts "Unable to find server alphabits"
|
||||
end
|
||||
|
||||
wait_for_server_deletion(server)
|
||||
|
||||
network = service.networks.find {|n| n.label == 'my_private_net'}
|
||||
delete_network(network)
|
||||
|
||||
puts "The network '#{network.label}' has been successfully deleted"
|
55
lib/fog/rackspace/examples/compute_v2/delete_server.rb
Normal file
55
lib/fog/rackspace/examples/compute_v2/delete_server.rb
Normal file
|
@ -0,0 +1,55 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
# This example demonstrates how to delete servers with Fog and the Rackspace Open Cloud
|
||||
|
||||
require 'rubygems' #required for Ruby 1.8.x
|
||||
require 'fog'
|
||||
|
||||
def get_user_input(prompt)
|
||||
print "#{prompt}: "
|
||||
gets.chomp
|
||||
end
|
||||
|
||||
def select_server(servers)
|
||||
abort "\nThere are not any servers to delete in the Chicago region. Try running create_server.rb\n\n" if servers.empty?
|
||||
|
||||
puts "\nSelect Server To Delete:\n\n"
|
||||
servers.each_with_index do |server, i|
|
||||
puts "\t #{i}. #{server.name} [#{server.public_ip_address}]"
|
||||
end
|
||||
|
||||
delete_str = get_user_input "\nEnter Server Number"
|
||||
servers[delete_str.to_i]
|
||||
end
|
||||
|
||||
# Use username defined in ~/.fog file, if absent prompt for username.
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_username
|
||||
Fog.credentials[:rackspace_username] || get_user_input("Enter Rackspace Username")
|
||||
end
|
||||
|
||||
# Use api key defined in ~/.fog file, if absent prompt for api key
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_api_key
|
||||
Fog.credentials[:rackspace_api_key] || get_user_input("Enter Rackspace API key")
|
||||
end
|
||||
|
||||
#create Next Generation Cloud Server service
|
||||
service = Fog::Compute.new({
|
||||
:provider => 'rackspace',
|
||||
:rackspace_username => rackspace_username,
|
||||
:rackspace_api_key => rackspace_api_key,
|
||||
:version => :v2, # Use Next Gen Cloud Servers
|
||||
:rackspace_region => :ord #Use Chicago Region
|
||||
})
|
||||
|
||||
#retrieve list of servers
|
||||
servers = service.servers
|
||||
|
||||
#prompt user for server
|
||||
server = select_server(servers)
|
||||
|
||||
#destroy server
|
||||
server.destroy
|
||||
|
||||
puts "\nServer #{server.name} has been destroyed\n"
|
93
lib/fog/rackspace/examples/compute_v2/detach_volume.rb
Normal file
93
lib/fog/rackspace/examples/compute_v2/detach_volume.rb
Normal file
|
@ -0,0 +1,93 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
# This example demonstrates working with server and volumes on the Rackpace Open Cloud
|
||||
|
||||
require 'rubygems' #required for Ruby 1.8.x
|
||||
require 'fog'
|
||||
|
||||
def get_user_input(prompt)
|
||||
print "#{prompt}: "
|
||||
gets.chomp
|
||||
end
|
||||
|
||||
def select_server(servers)
|
||||
abort "\nThere are not any servers in the Chicago region. Try running create_server.rb\n\n" if servers.empty?
|
||||
|
||||
puts "\nSelect Server For Volume Detachment:\n\n"
|
||||
servers.each_with_index do |server, i|
|
||||
puts "\t #{i}. #{server.name} [#{server.public_ip_address}]"
|
||||
end
|
||||
|
||||
delete_str = get_user_input "\nEnter Server Number"
|
||||
servers[delete_str.to_i]
|
||||
end
|
||||
|
||||
def select_attachment(attachments)
|
||||
abort "\nThis server does not contain any volumes in the Chicago region. Try running server_attachments.rb\n\n" if attachments.empty?
|
||||
|
||||
puts "\nSelect Volume To Detach:\n\n"
|
||||
attachments.each_with_index do |attachment, i|
|
||||
puts "\t #{i}. #{attachment.device}"
|
||||
end
|
||||
|
||||
delete_str = get_user_input "\nEnter Volume Number"
|
||||
attachments[delete_str.to_i]
|
||||
end
|
||||
|
||||
# Use username defined in ~/.fog file, if absent prompt for username.
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_username
|
||||
Fog.credentials[:rackspace_username] || get_user_input("Enter Rackspace Username")
|
||||
end
|
||||
|
||||
# Use api key defined in ~/.fog file, if absent prompt for api key
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_api_key
|
||||
Fog.credentials[:rackspace_api_key] || get_user_input("Enter Rackspace API key")
|
||||
end
|
||||
|
||||
#create Next Generation Cloud Server service
|
||||
compute_service = Fog::Compute.new({
|
||||
:provider => 'rackspace',
|
||||
:rackspace_username => rackspace_username,
|
||||
:rackspace_api_key => rackspace_api_key,
|
||||
:version => :v2, # Use Next Gen Cloud Servers
|
||||
:rackspace_region => :ord #Use Chicago Region
|
||||
})
|
||||
|
||||
cbs_service = Fog::Rackspace::BlockStorage.new({
|
||||
:rackspace_username => rackspace_username,
|
||||
:rackspace_api_key => rackspace_api_key,
|
||||
:rackspace_region => :ord #Use Chicago Region
|
||||
})
|
||||
|
||||
# retrieve list of servers
|
||||
servers = compute_service.servers
|
||||
|
||||
# prompt user for server
|
||||
server = select_server(servers)
|
||||
|
||||
# get attached volumes --also know as attachments
|
||||
attachments = server.attachments
|
||||
|
||||
# prompt user for volume to detach
|
||||
attachment = select_attachment(attachments)
|
||||
|
||||
volume = cbs_service.volumes.get attachment.volume_id
|
||||
puts "Detaching Volume #{volume.display_name} From Server #{server.name}"
|
||||
attachment.detach
|
||||
|
||||
puts "\n"
|
||||
delete_confirm = get_user_input "Would You Like To Destroy Volume #{volume.display_name} (y/n)"
|
||||
if delete_confirm.downcase == 'y'
|
||||
# wait for server to finish detaching before attempting to delete
|
||||
volume.wait_for(600) do
|
||||
print "."
|
||||
STDOUT.flush
|
||||
ready? && attachments.empty?
|
||||
end
|
||||
|
||||
volume.destroy
|
||||
|
||||
puts "\n\nThe Volume Has been Destroyed"
|
||||
end
|
106
lib/fog/rackspace/examples/compute_v2/resize_server.rb
Normal file
106
lib/fog/rackspace/examples/compute_v2/resize_server.rb
Normal file
|
@ -0,0 +1,106 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
# This example demonstrates how to resize servers with Fog and the Rackspace Open Cloud
|
||||
|
||||
require 'rubygems' #required for Ruby 1.8.x
|
||||
require 'fog'
|
||||
|
||||
def get_user_input(prompt)
|
||||
print "#{prompt}: "
|
||||
gets.chomp
|
||||
end
|
||||
|
||||
def select_flavor(flavors, server)
|
||||
puts "\nSelect New Flavor Size:\n\n"
|
||||
flavors.each_with_index do |flavor, i|
|
||||
next if server.flavor_id == flavor.id
|
||||
puts "\t #{i}. #{flavor.name}"
|
||||
end
|
||||
|
||||
selected_flavor_str = get_user_input "\nEnter Flavor Number"
|
||||
flavors[selected_flavor_str.to_i]
|
||||
end
|
||||
|
||||
def select_server(servers)
|
||||
abort "\nThere are not any servers to resize in the Chicago region. Try running create_server.rb\n\n" if servers.empty?
|
||||
|
||||
puts "\nSelect Server Resize:\n\n"
|
||||
servers.each_with_index do |server, i|
|
||||
puts "\t #{i}. #{server.name} [#{server.public_ip_address}]"
|
||||
end
|
||||
|
||||
selected_str = get_user_input "\nEnter Server Number"
|
||||
servers[selected_str.to_i]
|
||||
end
|
||||
|
||||
# Use username defined in ~/.fog file, if absent prompt for username.
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_username
|
||||
Fog.credentials[:rackspace_username] || get_user_input("Enter Rackspace Username")
|
||||
end
|
||||
|
||||
# Use api key defined in ~/.fog file, if absent prompt for api key
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_api_key
|
||||
Fog.credentials[:rackspace_api_key] || get_user_input("Enter Rackspace API key")
|
||||
end
|
||||
|
||||
#create Next Generation Cloud Server service
|
||||
service = Fog::Compute.new({
|
||||
:provider => 'rackspace',
|
||||
:rackspace_username => rackspace_username,
|
||||
:rackspace_api_key => rackspace_api_key,
|
||||
:version => :v2, # Use Next Gen Cloud Servers
|
||||
:rackspace_region => :ord #Use Chicago Region
|
||||
})
|
||||
|
||||
#retrieve list of servers
|
||||
servers = service.servers
|
||||
|
||||
#prompt user for server
|
||||
server = select_server(servers)
|
||||
|
||||
# retrieve list of avaliable flavors
|
||||
flavors = service.flavors
|
||||
|
||||
# prompt user for flavor
|
||||
selected_flavor = select_flavor(flavors, server)
|
||||
|
||||
# resize server
|
||||
server.resize selected_flavor.id
|
||||
|
||||
puts "\n"
|
||||
|
||||
# wait for the resize process to start
|
||||
server.wait_for { ready?('RESIZE') }
|
||||
|
||||
begin
|
||||
# Check every 5 seconds to see if server is in the VERIFY_RESIZE state.
|
||||
# If the server has not been built in 5 minutes (600 seconds) an exception will be raised.
|
||||
server.wait_for(1200, 5) do
|
||||
print "."
|
||||
STDOUT.flush
|
||||
ready?('VERIFY_RESIZE', ['ACTIVE', 'ERROR'])
|
||||
end
|
||||
puts "[DONE]\n\n"
|
||||
|
||||
puts "Server Has Been Successfully Resized!"
|
||||
action = get_user_input "Press 'C' To Confirm Or 'R' to Revert Resize (R/C)"
|
||||
|
||||
case action.upcase
|
||||
when 'C'
|
||||
puts "\nConfirming Resize Operation"
|
||||
server.confirm_resize
|
||||
when 'R'
|
||||
puts "\nReverting Resize Operation"
|
||||
server.revert_resize
|
||||
else
|
||||
puts "\nUnrecognized Input. Exiting."
|
||||
end
|
||||
|
||||
rescue Fog::Errors::TimeoutError
|
||||
puts "[TIMEOUT]\n\n"
|
||||
|
||||
puts "This server is currently #{server.progress}% into the resize process and is taking longer to complete than expected."
|
||||
puts "You can continute to monitor the build process through the web console at https://mycloud.rackspace.com/\n\n"
|
||||
end
|
68
lib/fog/rackspace/examples/compute_v2/server_attachments.rb
Normal file
68
lib/fog/rackspace/examples/compute_v2/server_attachments.rb
Normal file
|
@ -0,0 +1,68 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
# This example demonstrates working with server and volumes on the Rackpace Open Cloud
|
||||
|
||||
require 'rubygems' #required for Ruby 1.8.x
|
||||
require 'fog'
|
||||
|
||||
def get_user_input(prompt)
|
||||
print "#{prompt}: "
|
||||
gets.chomp
|
||||
end
|
||||
|
||||
def select_server(servers)
|
||||
abort "\nThere are not any servers in the Chicago region. Try running create_server.rb\n\n" if servers.empty?
|
||||
|
||||
puts "\nSelect Server For Attachment:\n\n"
|
||||
servers.each_with_index do |server, i|
|
||||
puts "\t #{i}. #{server.name} [#{server.public_ip_address}]"
|
||||
end
|
||||
|
||||
delete_str = get_user_input "\nEnter Server Number"
|
||||
servers[delete_str.to_i]
|
||||
end
|
||||
|
||||
# Use username defined in ~/.fog file, if absent prompt for username.
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_username
|
||||
Fog.credentials[:rackspace_username] || get_user_input("Enter Rackspace Username")
|
||||
end
|
||||
|
||||
# Use api key defined in ~/.fog file, if absent prompt for api key
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_api_key
|
||||
Fog.credentials[:rackspace_api_key] || get_user_input("Enter Rackspace API key")
|
||||
end
|
||||
|
||||
#create Next Generation Cloud Server service
|
||||
compute_service = Fog::Compute.new({
|
||||
:provider => 'rackspace',
|
||||
:rackspace_username => rackspace_username,
|
||||
:rackspace_api_key => rackspace_api_key,
|
||||
:version => :v2, # Use Next Gen Cloud Servers
|
||||
:rackspace_region => :ord #Use Chicago Region
|
||||
})
|
||||
|
||||
cbs_service = Fog::Rackspace::BlockStorage.new({
|
||||
:rackspace_username => rackspace_username,
|
||||
:rackspace_api_key => rackspace_api_key,
|
||||
:rackspace_region => :ord #Use Chicago Region
|
||||
})
|
||||
|
||||
# retrieve list of servers
|
||||
servers = compute_service.servers
|
||||
|
||||
# prompt user for server
|
||||
server = select_server(servers)
|
||||
|
||||
# prompt for volume name
|
||||
volume_name = get_user_input "Enter Volume Name"
|
||||
|
||||
puts "\nCreating Volume\n"
|
||||
volume = cbs_service.volumes.create(:size => 100, :display_name => volume_name)
|
||||
|
||||
puts "\nAttaching volume\n"
|
||||
attachment = server.attach_volume volume
|
||||
|
||||
puts "\nVolume #{volume.display_name} has been attached to #{server.name} on device #{attachment.device}\n\n"
|
||||
puts "To detach volume please execute the detach_volume.rb script\n\n"
|
83
lib/fog/rackspace/examples/compute_v2/server_metadata.rb
Normal file
83
lib/fog/rackspace/examples/compute_v2/server_metadata.rb
Normal file
|
@ -0,0 +1,83 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
# This example demonstrates working with server metadata on the Rackpace Open Cloud
|
||||
|
||||
require 'rubygems' #required for Ruby 1.8.x
|
||||
require './lib/fog'
|
||||
|
||||
# Use username defined in ~/.fog file, if absent prompt for username.
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_username
|
||||
Fog.credentials[:rackspace_username] || get_user_input("Enter Rackspace Username")
|
||||
end
|
||||
|
||||
# Use api key defined in ~/.fog file, if absent prompt for api key
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_api_key
|
||||
Fog.credentials[:rackspace_api_key] || get_user_input("Enter Rackspace API key")
|
||||
end
|
||||
|
||||
def print_metadata(server)
|
||||
server.metadata.each do |metadatum|
|
||||
puts "\t#{metadatum.key}: #{metadatum.value}"
|
||||
end
|
||||
puts "\n"
|
||||
end
|
||||
|
||||
#create Next Generation Cloud Server service
|
||||
service = Fog::Compute.new({
|
||||
:provider => 'rackspace',
|
||||
:rackspace_username => rackspace_username,
|
||||
:rackspace_api_key => rackspace_api_key,
|
||||
:version => :v2, # Use Next Gen Cloud Servers
|
||||
:rackspace_region => :ord #Use Chicago Region
|
||||
})
|
||||
|
||||
# Pick the first flavor
|
||||
flavor = service.flavors.first
|
||||
|
||||
# Pick the first Ubuntu image we can find
|
||||
image = service.images.find {|image| image.name =~ /Ubuntu/}
|
||||
|
||||
#create server
|
||||
server = service.servers.create :name => 'meta-cumulus',
|
||||
:flavor_id => flavor.id,
|
||||
:image_id => image.id,
|
||||
:metadata => { 'color' => 'red'}
|
||||
|
||||
puts "Waiting for server to be created\n"
|
||||
server.wait_for(600, 5) do
|
||||
print "."
|
||||
STDOUT.flush
|
||||
ready?
|
||||
end
|
||||
|
||||
puts "[DONE]\n\n"
|
||||
|
||||
puts "Initial Metadata\n"
|
||||
print_metadata(server)
|
||||
|
||||
puts "Adding New Metadata\n"
|
||||
server.metadata["environment"] = "demo"
|
||||
print_metadata(server)
|
||||
|
||||
puts "Updating Existing Metadata\n"
|
||||
server.metadata["color"] = "blue"
|
||||
print_metadata(server)
|
||||
|
||||
puts "Saving Metadata Changes\n"
|
||||
server.metadata.save
|
||||
|
||||
puts "Reload Metadata\n"
|
||||
server.metadata.reload
|
||||
print_metadata(server)
|
||||
|
||||
puts "Delete Metadata"
|
||||
metadatum = server.metadata.find {|metadataum| metadataum.key == 'environment'}
|
||||
metadatum.destroy
|
||||
|
||||
puts "Reload Metadata"
|
||||
server.metadata.reload
|
||||
print_metadata(server)
|
||||
|
||||
puts "To delete the server please execute the delete_server.rb script\n\n"
|
60
lib/fog/rackspace/examples/queues/claim_messages.rb
Normal file
60
lib/fog/rackspace/examples/queues/claim_messages.rb
Normal file
|
@ -0,0 +1,60 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
# This example demonstrates claiming messages with the Rackpace Open Cloud
|
||||
|
||||
require 'rubygems' #required for Ruby 1.8.x
|
||||
require 'fog'
|
||||
|
||||
def get_user_input(prompt)
|
||||
print "#{prompt}: "
|
||||
gets.chomp
|
||||
end
|
||||
|
||||
def select_queue(queues)
|
||||
abort "\nThere are not any queues the Chicago region. Try running create_queue.rb\n\n" if queues.empty?
|
||||
|
||||
puts "\nSelect Queue To Delete:\n\n"
|
||||
queues.each_with_index do |queue, i|
|
||||
puts "\t #{i}. #{queue.name}"
|
||||
end
|
||||
|
||||
delete_str = get_user_input "\nEnter Queue Number"
|
||||
queues[delete_str.to_i]
|
||||
end
|
||||
|
||||
# Use username defined in ~/.fog file, if absent prompt for username.
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_username
|
||||
Fog.credentials[:rackspace_username] || get_user_input("Enter Rackspace Username")
|
||||
end
|
||||
|
||||
# Use api key defined in ~/.fog file, if absent prompt for api key
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_api_key
|
||||
Fog.credentials[:rackspace_api_key] || get_user_input("Enter Rackspace API key")
|
||||
end
|
||||
|
||||
# create Queue Service
|
||||
service = Fog::Rackspace::Queues.new({
|
||||
:rackspace_username => rackspace_username,
|
||||
:rackspace_api_key => rackspace_api_key,
|
||||
:rackspace_region => :ord #Use Chicago Region
|
||||
})
|
||||
|
||||
# retrieve list of queues
|
||||
queues = service.queues
|
||||
|
||||
# prompt for queue
|
||||
queue = select_queue(queues)
|
||||
|
||||
# prompt for number of messages to claim
|
||||
num_claims = get_user_input "Enter Number of Messages to Claim"
|
||||
|
||||
# Claim messages
|
||||
claim = queue.claims.create :ttl => 300, :grace => 100, :limit => num_claims
|
||||
|
||||
puts "The following messages have been claimed for the next 5 minutes [#{claim.id}]"
|
||||
|
||||
claim.messages.each do |message|
|
||||
puts "\t[#{message.id}] #{message.body[0..50]}"
|
||||
end
|
45
lib/fog/rackspace/examples/queues/create_queue.rb
Normal file
45
lib/fog/rackspace/examples/queues/create_queue.rb
Normal file
|
@ -0,0 +1,45 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
# This example demonstrates creating a queue with the Rackpace Open Cloud
|
||||
|
||||
require 'rubygems' #required for Ruby 1.8.x
|
||||
require 'fog'
|
||||
|
||||
def get_user_input(prompt)
|
||||
print "#{prompt}: "
|
||||
gets.chomp
|
||||
end
|
||||
|
||||
# Use username defined in ~/.fog file, if absent prompt for username.
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_username
|
||||
Fog.credentials[:rackspace_username] || get_user_input("Enter Rackspace Username")
|
||||
end
|
||||
|
||||
# Use api key defined in ~/.fog file, if absent prompt for api key
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_api_key
|
||||
Fog.credentials[:rackspace_api_key] || get_user_input("Enter Rackspace API key")
|
||||
end
|
||||
|
||||
# create Queue Service
|
||||
service = Fog::Rackspace::Queues.new({
|
||||
:rackspace_username => rackspace_username,
|
||||
:rackspace_api_key => rackspace_api_key,
|
||||
:rackspace_region => :ord #Use Chicago Region
|
||||
})
|
||||
|
||||
#prompt for queue name
|
||||
queue_name = get_user_input "Enter name for queue"
|
||||
|
||||
begin
|
||||
# create queue
|
||||
queue = service.queues.create :name => queue_name
|
||||
puts "Queue #{queue_name} was successfully created"
|
||||
|
||||
puts "To delete the queue please execute the delete_queue.rb script\n\n"
|
||||
rescue Fog::Rackspace::Queues::ServiceError => e
|
||||
if e.status_code == 204
|
||||
puts "Queue #{queue_name} already exists"
|
||||
end
|
||||
end
|
71
lib/fog/rackspace/examples/queues/delete_message.rb
Normal file
71
lib/fog/rackspace/examples/queues/delete_message.rb
Normal file
|
@ -0,0 +1,71 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
# This example demonstrates deleting a message with the Rackpace Open Cloud
|
||||
|
||||
require 'rubygems' #required for Ruby 1.8.x
|
||||
require 'fog'
|
||||
|
||||
def get_user_input(prompt)
|
||||
print "#{prompt}: "
|
||||
gets.chomp
|
||||
end
|
||||
|
||||
def select_queue(queues)
|
||||
abort "\nThere are not any queues in the Chicago region. Try running create_queue.rb\n\n" if queues.empty?
|
||||
|
||||
puts "\nSelect Queue To Delete:\n\n"
|
||||
queues.each_with_index do |queue, i|
|
||||
puts "\t #{i}. #{queue.name}"
|
||||
end
|
||||
|
||||
delete_str = get_user_input "\nEnter Queue Number"
|
||||
queues[delete_str.to_i]
|
||||
end
|
||||
|
||||
def select_message(messages)
|
||||
abort "\nThere are not any messages in the Chicago region. Try running post_message.rb\n\n" if messages.empty?
|
||||
|
||||
puts "\nSelect Message To Delete:\n\n"
|
||||
messages.each_with_index do |message, i|
|
||||
puts "\t #{i}. [#{message.id}] #{message.body[0..50]}"
|
||||
end
|
||||
|
||||
delete_str = get_user_input "\nEnter Message Number"
|
||||
messages[delete_str.to_i]
|
||||
end
|
||||
|
||||
# Use username defined in ~/.fog file, if absent prompt for username.
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_username
|
||||
Fog.credentials[:rackspace_username] || get_user_input("Enter Rackspace Username")
|
||||
end
|
||||
|
||||
# Use api key defined in ~/.fog file, if absent prompt for api key
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_api_key
|
||||
Fog.credentials[:rackspace_api_key] || get_user_input("Enter Rackspace API key")
|
||||
end
|
||||
|
||||
# create Queue Service
|
||||
service = Fog::Rackspace::Queues.new({
|
||||
:rackspace_username => rackspace_username,
|
||||
:rackspace_api_key => rackspace_api_key,
|
||||
:rackspace_region => :ord #Use Chicago Region
|
||||
})
|
||||
|
||||
# retrieve list of queues
|
||||
queues = service.queues
|
||||
|
||||
# prompt for queue
|
||||
queue = select_queue(queues)
|
||||
|
||||
#retrieve list of messages
|
||||
messages = queue.messages
|
||||
|
||||
# prompt for message
|
||||
message = select_message(messages)
|
||||
|
||||
# delete message
|
||||
message.destroy
|
||||
|
||||
puts "\nMessage #{message.id} has been destroyed\n"
|
53
lib/fog/rackspace/examples/queues/delete_queue.rb
Normal file
53
lib/fog/rackspace/examples/queues/delete_queue.rb
Normal file
|
@ -0,0 +1,53 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
# This example demonstrates deleting a queue with the Rackpace Open Cloud
|
||||
|
||||
require 'rubygems' #required for Ruby 1.8.x
|
||||
require 'fog'
|
||||
|
||||
def get_user_input(prompt)
|
||||
print "#{prompt}: "
|
||||
gets.chomp
|
||||
end
|
||||
|
||||
def select_queue(queues)
|
||||
abort "\nThere are not any queues to delete in the Chicago region. Try running create_queue.rb\n\n" if queues.empty?
|
||||
|
||||
puts "\nSelect Queue To Delete:\n\n"
|
||||
queues.each_with_index do |queue, i|
|
||||
puts "\t #{i}. #{queue.name}"
|
||||
end
|
||||
|
||||
delete_str = get_user_input "\nEnter Queue Number"
|
||||
queues[delete_str.to_i]
|
||||
end
|
||||
|
||||
# Use username defined in ~/.fog file, if absent prompt for username.
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_username
|
||||
Fog.credentials[:rackspace_username] || get_user_input("Enter Rackspace Username")
|
||||
end
|
||||
|
||||
# Use api key defined in ~/.fog file, if absent prompt for api key
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_api_key
|
||||
Fog.credentials[:rackspace_api_key] || get_user_input("Enter Rackspace API key")
|
||||
end
|
||||
|
||||
# create Queue Service
|
||||
service = Fog::Rackspace::Queues.new({
|
||||
:rackspace_username => rackspace_username,
|
||||
:rackspace_api_key => rackspace_api_key,
|
||||
:rackspace_region => :ord #Use Chicago Region
|
||||
})
|
||||
|
||||
# retrieve list of queues
|
||||
queues = service.queues
|
||||
|
||||
# prompt for queue to delete
|
||||
queue = select_queue(queues)
|
||||
|
||||
# delete queue
|
||||
queue.destroy
|
||||
|
||||
puts "\nQueue #{queue.name} has been destroyed\n"
|
64
lib/fog/rackspace/examples/queues/list_messages.rb
Normal file
64
lib/fog/rackspace/examples/queues/list_messages.rb
Normal file
|
@ -0,0 +1,64 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
# This example demonstrates listing messages in a queue with the Rackpace Open Cloud
|
||||
|
||||
require 'rubygems' #required for Ruby 1.8.x
|
||||
require 'fog'
|
||||
|
||||
def get_user_input(prompt)
|
||||
print "#{prompt}: "
|
||||
gets.chomp
|
||||
end
|
||||
|
||||
def get_user_boolean(prompt)
|
||||
str = get_user_input(prompt)
|
||||
return false unless str
|
||||
str.match(/y(es)?/i) ? true : false
|
||||
end
|
||||
|
||||
def select_queue(queues)
|
||||
abort "\nThere are not any queues to post a message to in the Chicago region. Try running create_queue.rb\n\n" if queues.empty?
|
||||
|
||||
puts "\nSelect Queue:\n\n"
|
||||
queues.each_with_index do |queue, i|
|
||||
puts "\t #{i}. #{queue.name}"
|
||||
end
|
||||
|
||||
delete_str = get_user_input "\nEnter Queue Number"
|
||||
queues[delete_str.to_i]
|
||||
end
|
||||
|
||||
# Use username defined in ~/.fog file, if absent prompt for username.
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_username
|
||||
Fog.credentials[:rackspace_username] || get_user_input("Enter Rackspace Username")
|
||||
end
|
||||
|
||||
# Use api key defined in ~/.fog file, if absent prompt for api key
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_api_key
|
||||
Fog.credentials[:rackspace_api_key] || get_user_input("Enter Rackspace API key")
|
||||
end
|
||||
|
||||
# create Queue Service
|
||||
service = Fog::Rackspace::Queues.new({
|
||||
:rackspace_username => rackspace_username,
|
||||
:rackspace_api_key => rackspace_api_key,
|
||||
:rackspace_region => :ord #Use Chicago Region
|
||||
})
|
||||
|
||||
# retrieve list of queues
|
||||
queues = service.queues
|
||||
|
||||
# prompt for queue to delete
|
||||
queue = select_queue(queues)
|
||||
|
||||
queue.messages.echo = get_user_boolean "Do you want to include your own messages? [y/N]"
|
||||
|
||||
queue.messages.include_claimed = get_user_boolean "Do you want to include claimed messages? [y/N]"
|
||||
|
||||
puts "\n\nThe following messages are in the '#{queue.name}' queue:\n\n"
|
||||
|
||||
queue.messages.each do |message|
|
||||
puts message.inspect
|
||||
end
|
59
lib/fog/rackspace/examples/queues/post_message.rb
Normal file
59
lib/fog/rackspace/examples/queues/post_message.rb
Normal file
|
@ -0,0 +1,59 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
# This example demonstrates posting a message to a queue with the Rackpace Open Cloud
|
||||
|
||||
require 'rubygems' #required for Ruby 1.8.x
|
||||
require 'fog'
|
||||
|
||||
def get_user_input(prompt)
|
||||
print "#{prompt}: "
|
||||
gets.chomp
|
||||
end
|
||||
|
||||
def select_queue(queues)
|
||||
abort "\nThere are not any queues to post a message to in the Chicago region. Try running create_queue.rb\n\n" if queues.empty?
|
||||
|
||||
puts "\nSelect Queue:\n\n"
|
||||
queues.each_with_index do |queue, i|
|
||||
puts "\t #{i}. #{queue.name}"
|
||||
end
|
||||
|
||||
delete_str = get_user_input "\nEnter Queue Number"
|
||||
queues[delete_str.to_i]
|
||||
end
|
||||
|
||||
# Use username defined in ~/.fog file, if absent prompt for username.
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_username
|
||||
Fog.credentials[:rackspace_username] || get_user_input("Enter Rackspace Username")
|
||||
end
|
||||
|
||||
# Use api key defined in ~/.fog file, if absent prompt for api key
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_api_key
|
||||
Fog.credentials[:rackspace_api_key] || get_user_input("Enter Rackspace API key")
|
||||
end
|
||||
|
||||
# create Queue Service
|
||||
service = Fog::Rackspace::Queues.new({
|
||||
:rackspace_username => rackspace_username,
|
||||
:rackspace_api_key => rackspace_api_key,
|
||||
:rackspace_region => :ord #Use Chicago Region
|
||||
})
|
||||
|
||||
# retrieve list of queues
|
||||
queues = service.queues
|
||||
|
||||
# prompt for queue to delete
|
||||
queue = select_queue(queues)
|
||||
|
||||
# prompt for queue message
|
||||
message = get_user_input "Enter Queue Message"
|
||||
|
||||
# time to live TTL = 1 hour
|
||||
ttl = 3600
|
||||
|
||||
# post message to queue
|
||||
queue.messages.create :body => message, :ttl => ttl
|
||||
|
||||
puts "The message has been successfully posted"
|
43
lib/fog/rackspace/examples/storage/create_cdn_directory.rb
Normal file
43
lib/fog/rackspace/examples/storage/create_cdn_directory.rb
Normal file
|
@ -0,0 +1,43 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
# This example demonstrates creating a container with CDN on the Rackpace Open Cloud
|
||||
|
||||
require 'rubygems' #required for Ruby 1.8.x
|
||||
require 'fog'
|
||||
|
||||
def get_user_input(prompt)
|
||||
print "#{prompt}: "
|
||||
gets.chomp
|
||||
end
|
||||
|
||||
# Use username defined in ~/.fog file, if absent prompt for username.
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_username
|
||||
Fog.credentials[:rackspace_username] || get_user_input("Enter Rackspace Username")
|
||||
end
|
||||
|
||||
# Use api key defined in ~/.fog file, if absent prompt for api key
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_api_key
|
||||
Fog.credentials[:rackspace_api_key] || get_user_input("Enter Rackspace API key")
|
||||
end
|
||||
|
||||
# create Cloud Files service
|
||||
service = Fog::Storage.new({
|
||||
:provider => 'Rackspace',
|
||||
:rackspace_username => rackspace_username,
|
||||
:rackspace_api_key => rackspace_api_key,
|
||||
:rackspace_region => :ord #Use Chicago Region
|
||||
})
|
||||
|
||||
# prompt for directory name
|
||||
directory_name = get_user_input "\nEnter name of directory to create"
|
||||
|
||||
# create directory
|
||||
directory = service.directories.create :key => directory_name, :public => true
|
||||
|
||||
# reload directory to refresh information
|
||||
directory.reload
|
||||
|
||||
puts "\nDirectory #{directory.key} was created."
|
||||
puts "To delete the container please execute the delete_directory.rb script\n\n"
|
|
@ -0,0 +1,43 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
# This example demonstrates creating a container with the Rackpace Open Cloud
|
||||
|
||||
require 'rubygems' #required for Ruby 1.8.x
|
||||
require 'fog'
|
||||
|
||||
def get_user_input(prompt)
|
||||
print "#{prompt}: "
|
||||
gets.chomp
|
||||
end
|
||||
|
||||
# Use username defined in ~/.fog file, if absent prompt for username.
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_username
|
||||
Fog.credentials[:rackspace_username] || get_user_input("Enter Rackspace Username")
|
||||
end
|
||||
|
||||
# Use api key defined in ~/.fog file, if absent prompt for api key
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_api_key
|
||||
Fog.credentials[:rackspace_api_key] || get_user_input("Enter Rackspace API key")
|
||||
end
|
||||
|
||||
# create Cloud Files service
|
||||
service = Fog::Storage.new({
|
||||
:provider => 'Rackspace',
|
||||
:rackspace_username => rackspace_username,
|
||||
:rackspace_api_key => rackspace_api_key,
|
||||
:rackspace_region => :ord #Use Chicago Region
|
||||
})
|
||||
|
||||
# prompt for directory name
|
||||
directory_name = get_user_input "\nEnter name of directory to create"
|
||||
|
||||
# create directory
|
||||
directory = service.directories.create :key => directory_name
|
||||
|
||||
# reload directory to refresh information
|
||||
directory.reload
|
||||
|
||||
puts "\n Directory #{directory.key} was created."
|
||||
puts "To delete the container please execute the delete_directory.rb script\n\n"
|
62
lib/fog/rackspace/examples/storage/delete_directory.rb
Normal file
62
lib/fog/rackspace/examples/storage/delete_directory.rb
Normal file
|
@ -0,0 +1,62 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
# This example demonstrates deleting a container with the Rackpace Open Cloud
|
||||
|
||||
require 'rubygems' #required for Ruby 1.8.x
|
||||
require 'fog'
|
||||
|
||||
def get_user_input(prompt)
|
||||
print "#{prompt}: "
|
||||
gets.chomp
|
||||
end
|
||||
|
||||
def select_directory(directories)
|
||||
abort "\nThere are not any directories to delete in the Chicago region. Try running create_directory.rb\n\n" if directories.empty?
|
||||
|
||||
puts "\nSelect Directory To Delete:\n\n"
|
||||
directories.each_with_index do |dir, i|
|
||||
puts "\t #{i}. #{dir.key} [#{dir.count} objects]"
|
||||
end
|
||||
|
||||
delete_str = get_user_input "\nEnter Directory Number"
|
||||
directories[delete_str.to_i]
|
||||
end
|
||||
|
||||
# Use username defined in ~/.fog file, if absent prompt for username.
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_username
|
||||
Fog.credentials[:rackspace_username] || get_user_input("Enter Rackspace Username")
|
||||
end
|
||||
|
||||
# Use api key defined in ~/.fog file, if absent prompt for api key
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_api_key
|
||||
Fog.credentials[:rackspace_api_key] || get_user_input("Enter Rackspace API key")
|
||||
end
|
||||
|
||||
# create Cloud Files service
|
||||
service = Fog::Storage.new({
|
||||
:provider => 'Rackspace',
|
||||
:rackspace_username => rackspace_username,
|
||||
:rackspace_api_key => rackspace_api_key,
|
||||
:rackspace_region => :ord #Use Chicago Region
|
||||
})
|
||||
|
||||
# retrieve directories
|
||||
directories = service.directories
|
||||
|
||||
# prompt for directory
|
||||
directory = select_directory(directories)
|
||||
|
||||
puts "\nNow deleting #{directory.key}"
|
||||
|
||||
# delete files if necessary
|
||||
directory.files.each do |f|
|
||||
puts "\tDeleting file #{f.key}"
|
||||
f.destroy
|
||||
end
|
||||
|
||||
# delete directory
|
||||
directory.destroy
|
||||
|
||||
puts "\tDone\n\n"
|
70
lib/fog/rackspace/examples/storage/delete_file.rb
Normal file
70
lib/fog/rackspace/examples/storage/delete_file.rb
Normal file
|
@ -0,0 +1,70 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
# This example demonstrates deleting a file from a container with the Rackpace Open Cloud
|
||||
|
||||
require 'rubygems' #required for Ruby 1.8.x
|
||||
require 'fog'
|
||||
|
||||
def get_user_input(prompt)
|
||||
print "#{prompt}: "
|
||||
gets.chomp
|
||||
end
|
||||
|
||||
def select_directory(directories)
|
||||
abort "\nThere are not any directories with files to delete in the Chicago region. Try running create_file.rb\n\n" if directories.empty?
|
||||
|
||||
puts "\nSelect Directory:\n\n"
|
||||
directories.each_with_index do |dir, i|
|
||||
puts "\t #{i}. #{dir.key} [#{dir.count} objects]"
|
||||
end
|
||||
|
||||
delete_str = get_user_input "\nEnter Directory Number"
|
||||
directories[delete_str.to_i]
|
||||
end
|
||||
|
||||
def select_file(files)
|
||||
puts "\nSelect File:\n\n"
|
||||
files.each_with_index do |file, i|
|
||||
puts "\t #{i}. #{file.key}"
|
||||
end
|
||||
|
||||
delete_str = get_user_input "\nEnter File Number"
|
||||
files[delete_str.to_i]
|
||||
end
|
||||
|
||||
# Use username defined in ~/.fog file, if absent prompt for username.
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_username
|
||||
Fog.credentials[:rackspace_username] || get_user_input("Enter Rackspace Username")
|
||||
end
|
||||
|
||||
# Use api key defined in ~/.fog file, if absent prompt for api key
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_api_key
|
||||
Fog.credentials[:rackspace_api_key] || get_user_input("Enter Rackspace API key")
|
||||
end
|
||||
|
||||
# create Cloud Files service
|
||||
service = Fog::Storage.new({
|
||||
:provider => 'Rackspace',
|
||||
:rackspace_username => rackspace_username,
|
||||
:rackspace_api_key => rackspace_api_key,
|
||||
:rackspace_region => :ord #Use Chicago Region
|
||||
})
|
||||
|
||||
# retrieve directories with files
|
||||
directories = service.directories.select {|s| s.count > 0}
|
||||
|
||||
# prompt for directory
|
||||
directory = select_directory(directories)
|
||||
|
||||
# list of files for directory
|
||||
files = directory.files
|
||||
|
||||
# prompt for file to delete
|
||||
file = select_file(files)
|
||||
|
||||
# delete file
|
||||
file.destroy
|
||||
|
||||
puts "\nFile #{file.key} was successfully deleted"
|
75
lib/fog/rackspace/examples/storage/download_file.rb
Normal file
75
lib/fog/rackspace/examples/storage/download_file.rb
Normal file
|
@ -0,0 +1,75 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
# This example demonstrates downloading a file with the Rackpace Open Cloud
|
||||
|
||||
require 'rubygems' #required for Ruby 1.8.x
|
||||
require 'fog'
|
||||
|
||||
def get_user_input(prompt)
|
||||
print "#{prompt}: "
|
||||
gets.chomp
|
||||
end
|
||||
|
||||
def select_directory(directories)
|
||||
abort "\nThere are not any directories with files in the Chicago region. Try running create_file.rb\n\n" if directories.empty?
|
||||
|
||||
puts "\nSelect Directory:\n\n"
|
||||
directories.each_with_index do |dir, i|
|
||||
puts "\t #{i}. #{dir.key} [#{dir.count} objects]"
|
||||
end
|
||||
|
||||
delete_str = get_user_input "\nEnter Directory Number"
|
||||
directories[delete_str.to_i]
|
||||
end
|
||||
|
||||
def select_file(files)
|
||||
puts "\nSelect File:\n\n"
|
||||
files.each_with_index do |file, i|
|
||||
puts "\t #{i}. #{file.key}"
|
||||
end
|
||||
|
||||
delete_str = get_user_input "\nEnter File Number"
|
||||
files[delete_str.to_i]
|
||||
end
|
||||
|
||||
# Use username defined in ~/.fog file, if absent prompt for username.
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_username
|
||||
Fog.credentials[:rackspace_username] || get_user_input("Enter Rackspace Username")
|
||||
end
|
||||
|
||||
# Use api key defined in ~/.fog file, if absent prompt for api key
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_api_key
|
||||
Fog.credentials[:rackspace_api_key] || get_user_input("Enter Rackspace API key")
|
||||
end
|
||||
|
||||
# create Cloud Files service
|
||||
service = Fog::Storage.new({
|
||||
:provider => 'Rackspace',
|
||||
:rackspace_username => rackspace_username,
|
||||
:rackspace_api_key => rackspace_api_key,
|
||||
:rackspace_region => :ord #Use Chicago Region
|
||||
})
|
||||
|
||||
# retrieve directories with files
|
||||
directories = service.directories.select {|s| s.count > 0}
|
||||
|
||||
# prompt for directory
|
||||
directory = select_directory(directories)
|
||||
|
||||
# list of files for directory
|
||||
files = directory.files
|
||||
|
||||
# prompt for file to download
|
||||
file = select_file(files)
|
||||
|
||||
# download file
|
||||
filename = File.join(File.dirname(__FILE__), "downloaded-#{file.key}")
|
||||
File.open(filename, 'w') do | f |
|
||||
directory.files.get(file.key) do | data, remaining, content_length |
|
||||
f.syswrite data
|
||||
end
|
||||
end
|
||||
|
||||
puts "\nFile #{file.key} was successfully downloaded to #{filename}"
|
1
lib/fog/rackspace/examples/storage/lorem.txt
Normal file
1
lib/fog/rackspace/examples/storage/lorem.txt
Normal file
|
@ -0,0 +1 @@
|
|||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
76
lib/fog/rackspace/examples/storage/storage_metadata.rb
Normal file
76
lib/fog/rackspace/examples/storage/storage_metadata.rb
Normal file
|
@ -0,0 +1,76 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
# This example demonstrates creating a file on the CDN network with the Rackpace Open Cloud
|
||||
|
||||
require 'rubygems' #required for Ruby 1.8.x
|
||||
require 'fog'
|
||||
|
||||
# Use username defined in ~/.fog file, if absent prompt for username.
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_username
|
||||
Fog.credentials[:rackspace_username] || get_user_input("Enter Rackspace Username")
|
||||
end
|
||||
|
||||
# Use api key defined in ~/.fog file, if absent prompt for api key
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_api_key
|
||||
Fog.credentials[:rackspace_api_key] || get_user_input("Enter Rackspace API key")
|
||||
end
|
||||
|
||||
def print_metadata(object)
|
||||
object.metadata.each_pair do |key, value|
|
||||
puts "\t#{key}: #{value}"
|
||||
end
|
||||
puts "\n"
|
||||
end
|
||||
|
||||
# create Cloud Files service
|
||||
service = Fog::Storage.new({
|
||||
:provider => 'Rackspace',
|
||||
:rackspace_username => rackspace_username,
|
||||
:rackspace_api_key => rackspace_api_key,
|
||||
:rackspace_region => :ord #Use Chicago Region
|
||||
})
|
||||
|
||||
# create directory
|
||||
puts "Creating directory 'metadata-tester'"
|
||||
directory = service.directories.create :key => "metadata-tester"
|
||||
|
||||
# initial metadata
|
||||
puts "Initial Container Metadata\n"
|
||||
print_metadata directory
|
||||
|
||||
# adding metadata
|
||||
puts "Adding Container Metadata"
|
||||
directory.metadata["environment"] = "demo"
|
||||
directory.save
|
||||
print_metadata directory
|
||||
|
||||
# update metadata
|
||||
puts "Updating Container Metadata"
|
||||
directory.metadata["environment"] = "test"
|
||||
directory.save
|
||||
print_metadata directory
|
||||
|
||||
# upload file
|
||||
puts "Uploading file"
|
||||
upload_file = File.join(File.dirname(__FILE__), "lorem.txt")
|
||||
file = directory.files.create :key => 'sample.txt', :body => File.open(upload_file, "r")
|
||||
|
||||
# initial metadata
|
||||
puts "Initial File Metadata\n"
|
||||
print_metadata file
|
||||
|
||||
# adding metadata
|
||||
puts "Adding File Metadata"
|
||||
file.metadata["preview"] = "true"
|
||||
file.save
|
||||
print_metadata file
|
||||
|
||||
# update metadata
|
||||
puts "Updating File Metadata"
|
||||
file.metadata["preview"] = "false"
|
||||
file.save
|
||||
print_metadata file
|
||||
|
||||
puts "To delete the directory and file please execute the delete_directory.rb script\n\n"
|
44
lib/fog/rackspace/examples/storage/upload_file.rb
Normal file
44
lib/fog/rackspace/examples/storage/upload_file.rb
Normal file
|
@ -0,0 +1,44 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
# This example demonstrates creating a file on the CDN network with the Rackpace Open Cloud
|
||||
|
||||
require 'rubygems' #required for Ruby 1.8.x
|
||||
require 'fog'
|
||||
|
||||
def get_user_input(prompt)
|
||||
print "#{prompt}: "
|
||||
gets.chomp
|
||||
end
|
||||
|
||||
# Use username defined in ~/.fog file, if absent prompt for username.
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_username
|
||||
Fog.credentials[:rackspace_username] || get_user_input("Enter Rackspace Username")
|
||||
end
|
||||
|
||||
# Use api key defined in ~/.fog file, if absent prompt for api key
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_api_key
|
||||
Fog.credentials[:rackspace_api_key] || get_user_input("Enter Rackspace API key")
|
||||
end
|
||||
|
||||
# create Cloud Files service
|
||||
service = Fog::Storage.new({
|
||||
:provider => 'Rackspace',
|
||||
:rackspace_username => rackspace_username,
|
||||
:rackspace_api_key => rackspace_api_key,
|
||||
:rackspace_region => :ord #Use Chicago Region
|
||||
})
|
||||
|
||||
# prompt for directory name
|
||||
directory_name = get_user_input "\nEnter name of directory to create"
|
||||
|
||||
# create directory with CDN service
|
||||
directory = service.directories.create :key => directory_name, :public => true
|
||||
|
||||
# upload file
|
||||
upload_file = File.join(File.dirname(__FILE__), "lorem.txt")
|
||||
file = directory.files.create :key => 'sample.txt', :body => File.open(upload_file, "r")
|
||||
|
||||
puts "You should be able to view this file via CDN at #{file.public_url}"
|
||||
puts "To delete the container and associated file please execute the delete_directory.rb script\n\n"
|
101
lib/fog/rackspace/examples/storage/upload_large_files.rb
Normal file
101
lib/fog/rackspace/examples/storage/upload_large_files.rb
Normal file
|
@ -0,0 +1,101 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
# This example demonstrates uploading large files in segments
|
||||
|
||||
require 'rubygems' #required for Ruby 1.8.x
|
||||
require 'fog'
|
||||
|
||||
# Size of segment. The Rackspace cloud currently requires files larger than 5GB to be segmented so we will choose 5GB -1 for a size
|
||||
# http://docs.rackspace.com/files/api/v1/cf-devguide/content/Large_Object_Creation-d1e2019.html
|
||||
SEGMENT_LIMIT = 5368709119.0
|
||||
|
||||
# Size of buffer to use for transfers. Use Excon's default chunk size and if that's not avaliable we will default to 1 MB
|
||||
BUFFER_SIZE = Excon.defaults[:chunk_size] || 1024 * 1024
|
||||
|
||||
def get_user_input(prompt)
|
||||
print "\n#{prompt}: "
|
||||
gets.chomp
|
||||
end
|
||||
|
||||
def select_directory(directories)
|
||||
abort "\nThere are not any directories in the Chicago region. Try running create_private_directory.rb\n\n" if directories.empty?
|
||||
|
||||
puts "\nSelect Directory:\n\n"
|
||||
directories.each_with_index do |dir, i|
|
||||
puts "\t #{i}. #{dir.key} [#{dir.count} objects]"
|
||||
end
|
||||
|
||||
select_str = get_user_input "Enter Directory Number"
|
||||
directories[select_str.to_i]
|
||||
end
|
||||
|
||||
# Use username defined in ~/.fog file, if absent prompt for username.
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_username
|
||||
Fog.credentials[:rackspace_username] || get_user_input("Enter Rackspace Username")
|
||||
end
|
||||
|
||||
# Use api key defined in ~/.fog file, if absent prompt for api key
|
||||
# For more details on ~/.fog refer to http://fog.io/about/getting_started.html
|
||||
def rackspace_api_key
|
||||
Fog.credentials[:rackspace_api_key] || get_user_input("Enter Rackspace API key")
|
||||
end
|
||||
|
||||
# create Cloud Files service
|
||||
service = Fog::Storage.new({
|
||||
:provider => 'Rackspace',
|
||||
:rackspace_username => rackspace_username,
|
||||
:rackspace_api_key => rackspace_api_key,
|
||||
:rackspace_region => :ord
|
||||
})
|
||||
|
||||
# retrieve directories with files
|
||||
directories = service.directories
|
||||
|
||||
# prompt for directory
|
||||
directory = select_directory(directories)
|
||||
|
||||
# prompt for file name
|
||||
file_name = get_user_input "Enter full path of file to upload"
|
||||
segment_name = File.basename(file_name)
|
||||
|
||||
File.open(file_name) do |f|
|
||||
num_segments = (f.stat.size / SEGMENT_LIMIT).round + 1
|
||||
puts "\nThis upload of '#{file_name}' will require #{num_segments} segment(s) and 1 manifest file\n"
|
||||
|
||||
segment = 0
|
||||
until f.eof?
|
||||
segment += 1
|
||||
offset = 0
|
||||
|
||||
# upload segment to cloud files
|
||||
segment_suffix = segment.to_s.rjust(10, '0')
|
||||
print "\n\tUploading segment #{segment_suffix} "
|
||||
service.put_object(directory.key, "#{segment_name}/#{segment_suffix}", nil) do
|
||||
if offset <= SEGMENT_LIMIT - BUFFER_SIZE
|
||||
print "."
|
||||
buf = f.read(BUFFER_SIZE).to_s
|
||||
offset += buf.size
|
||||
buf
|
||||
else
|
||||
''
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
puts "\n\n\tWriting manifest #{segment_name}\n\n"
|
||||
service.put_object_manifest(directory.key, segment_name, 'X-Object-Manifest' => "#{directory.key}/#{segment_name}/" )
|
||||
|
||||
puts <<-NOTE
|
||||
You should now be able to download #{segment_name} from the cloud control panel or using the following code:
|
||||
|
||||
directory = service.directories.get('#{directory.key}')
|
||||
File.open('downloaded_#{segment_name}', 'w') do | f |
|
||||
directory.files.get('#{segment_name}') do | data, remaining, content_length |
|
||||
print "."
|
||||
f.write data
|
||||
end
|
||||
end
|
||||
|
||||
NOTE
|
83
lib/fog/rackspace/identity.rb
Normal file
83
lib/fog/rackspace/identity.rb
Normal file
|
@ -0,0 +1,83 @@
|
|||
require 'fog/rackspace/core'
|
||||
|
||||
module Fog
|
||||
module Rackspace
|
||||
class Identity < Fog::Service
|
||||
US_ENDPOINT = 'https://identity.api.rackspacecloud.com/v2.0'
|
||||
UK_ENDPOINT = 'https://lon.identity.api.rackspacecloud.com/v2.0'
|
||||
|
||||
requires :rackspace_username, :rackspace_api_key
|
||||
recognizes :rackspace_auth_url, :rackspace_region
|
||||
|
||||
model_path 'fog/rackspace/models/identity'
|
||||
model :user
|
||||
collection :users
|
||||
model :role
|
||||
collection :roles
|
||||
model :credential
|
||||
collection :credentials
|
||||
model :tenant
|
||||
collection :tenants
|
||||
model :service_catalog
|
||||
|
||||
request_path 'fog/rackspace/requests/identity'
|
||||
request :create_token
|
||||
|
||||
request :list_users
|
||||
request :list_user_roles
|
||||
request :list_credentials
|
||||
request :list_tenants
|
||||
request :get_user_by_id
|
||||
request :get_user_by_name
|
||||
request :create_user
|
||||
request :update_user
|
||||
request :delete_user
|
||||
|
||||
module Common
|
||||
attr_reader :service_catalog, :auth_token
|
||||
|
||||
def authenticate(options={})
|
||||
data = self.create_token(@rackspace_username, @rackspace_api_key).body
|
||||
@service_catalog = ServiceCatalog.from_response(self, data)
|
||||
@auth_token = data['access']['token']['id']
|
||||
end
|
||||
|
||||
def apply_options(options)
|
||||
@rackspace_username = options[:rackspace_username]
|
||||
@rackspace_api_key = options[:rackspace_api_key]
|
||||
@rackspace_region = options[:rackspace_region]
|
||||
@rackspace_auth_url = options[:rackspace_auth_url] || US_ENDPOINT
|
||||
|
||||
@uri = URI.parse(@rackspace_auth_url)
|
||||
@host = @uri.host
|
||||
@path = @uri.path
|
||||
@port = @uri.port
|
||||
@scheme = @uri.scheme
|
||||
@persistent = options[:persistent] || false
|
||||
@connection_options = options[:connection_options] || {}
|
||||
end
|
||||
end
|
||||
|
||||
class Mock < Fog::Rackspace::Service
|
||||
include Common
|
||||
|
||||
def initialize(options={})
|
||||
apply_options(options)
|
||||
|
||||
authenticate
|
||||
end
|
||||
end
|
||||
|
||||
class Real < Fog::Rackspace::Service
|
||||
include Common
|
||||
|
||||
def initialize(options={})
|
||||
apply_options(options)
|
||||
@connection = Fog::Core::Connection.new(@uri.to_s, @persistent, @connection_options)
|
||||
|
||||
authenticate
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
206
lib/fog/rackspace/load_balancers.rb
Normal file
206
lib/fog/rackspace/load_balancers.rb
Normal file
|
@ -0,0 +1,206 @@
|
|||
require 'fog/rackspace/core'
|
||||
|
||||
module Fog
|
||||
module Rackspace
|
||||
class LoadBalancers < Fog::Service
|
||||
include Fog::Rackspace::Errors
|
||||
|
||||
#These references exist for backwards compatibility
|
||||
class ServiceError < Fog::Rackspace::Errors::ServiceError; end
|
||||
class InternalServerError < Fog::Rackspace::Errors::InternalServerError; end
|
||||
class BadRequest < Fog::Rackspace::Errors::BadRequest; end
|
||||
|
||||
DFW_ENDPOINT = 'https://dfw.loadbalancers.api.rackspacecloud.com/v1.0'
|
||||
ORD_ENDPOINT = 'https://ord.loadbalancers.api.rackspacecloud.com/v1.0'
|
||||
LON_ENDPOINT = 'https://lon.loadbalancers.api.rackspacecloud.com/v1.0'
|
||||
|
||||
requires :rackspace_api_key, :rackspace_username
|
||||
recognizes :rackspace_auth_url
|
||||
recognizes :rackspace_auth_token
|
||||
recognizes :rackspace_lb_endpoint
|
||||
recognizes :rackspace_load_balancers_url
|
||||
recognizes :rackspace_region
|
||||
|
||||
model_path 'fog/rackspace/models/load_balancers'
|
||||
collection :load_balancers
|
||||
model :load_balancer
|
||||
collection :nodes
|
||||
model :node
|
||||
collection :virtual_ips
|
||||
model :virtual_ip
|
||||
collection :access_rules
|
||||
model :access_rule
|
||||
|
||||
request_path 'fog/rackspace/requests/load_balancers'
|
||||
request :get_ssl_termination
|
||||
request :set_ssl_termination
|
||||
request :remove_ssl_termination
|
||||
request :create_load_balancer
|
||||
request :get_load_balancer
|
||||
request :list_load_balancers
|
||||
request :update_load_balancer
|
||||
request :delete_load_balancer
|
||||
request :create_node
|
||||
request :list_nodes
|
||||
request :get_node
|
||||
request :update_node
|
||||
request :delete_node
|
||||
request :delete_nodes
|
||||
request :create_virtual_ip
|
||||
request :list_virtual_ips
|
||||
request :delete_virtual_ip
|
||||
request :list_protocols
|
||||
request :list_algorithms
|
||||
request :get_connection_logging
|
||||
request :set_connection_logging
|
||||
request :get_content_caching
|
||||
request :set_content_caching
|
||||
request :create_access_rule
|
||||
request :list_access_rules
|
||||
request :delete_access_rule
|
||||
request :delete_all_access_rules
|
||||
request :get_session_persistence
|
||||
request :set_session_persistence
|
||||
request :remove_session_persistence
|
||||
request :get_connection_throttling
|
||||
request :remove_connection_throttling
|
||||
request :set_connection_throttling
|
||||
request :get_monitor
|
||||
request :set_monitor
|
||||
request :remove_monitor
|
||||
request :get_usage
|
||||
request :get_load_balancer_usage
|
||||
request :get_error_page
|
||||
request :set_error_page
|
||||
request :remove_error_page
|
||||
request :get_stats
|
||||
|
||||
module Shared
|
||||
def algorithms
|
||||
list_algorithms.body['algorithms'].map { |i| i['name'] }
|
||||
end
|
||||
|
||||
def protocols
|
||||
list_protocols.body['protocols']
|
||||
end
|
||||
|
||||
def usage(options = {})
|
||||
get_usage(options).body
|
||||
end
|
||||
end
|
||||
|
||||
class Mock < Fog::Rackspace::Service
|
||||
include Shared
|
||||
|
||||
def initialize(options={})
|
||||
@rackspace_api_key = options[:rackspace_api_key]
|
||||
@rackspace_username = options[:rackspace_username]
|
||||
@rackspace_auth_url = options[:rackspace_auth_url]
|
||||
end
|
||||
end
|
||||
|
||||
class Real < Fog::Rackspace::Service
|
||||
include Shared
|
||||
|
||||
def initialize(options={})
|
||||
@rackspace_api_key = options[:rackspace_api_key]
|
||||
@rackspace_username = options[:rackspace_username]
|
||||
@rackspace_auth_url = options[:rackspace_auth_url]
|
||||
@rackspace_must_reauthenticate = false
|
||||
@connection_options = options[:connection_options] || {}
|
||||
|
||||
setup_custom_endpoint(options)
|
||||
|
||||
authenticate
|
||||
|
||||
deprecation_warnings(options)
|
||||
|
||||
@persistent = options[:persistent] || false
|
||||
@connection = Fog::Core::Connection.new(endpoint_uri.to_s, @persistent, @connection_options)
|
||||
end
|
||||
|
||||
def request(params, parse_json = true)
|
||||
super
|
||||
rescue Excon::Errors::NotFound => error
|
||||
raise NotFound.slurp(error, self)
|
||||
rescue Excon::Errors::BadRequest => error
|
||||
raise BadRequest.slurp(error, self)
|
||||
rescue Excon::Errors::InternalServerError => error
|
||||
raise InternalServerError.slurp(error, self)
|
||||
rescue Excon::Errors::HTTPStatusError => error
|
||||
raise ServiceError.slurp(error, self)
|
||||
end
|
||||
|
||||
def authenticate(options={})
|
||||
super({
|
||||
:rackspace_api_key => @rackspace_api_key,
|
||||
:rackspace_username => @rackspace_username,
|
||||
:rackspace_auth_url => @rackspace_auth_url,
|
||||
:connection_options => @connection_options
|
||||
})
|
||||
end
|
||||
|
||||
def service_name
|
||||
:cloudLoadBalancers
|
||||
end
|
||||
|
||||
def region
|
||||
@rackspace_region
|
||||
end
|
||||
|
||||
def endpoint_uri(service_endpoint_url=nil)
|
||||
@uri = super(@rackspace_endpoint || service_endpoint_url, :rackspace_load_balancers_url)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def setup_custom_endpoint(options)
|
||||
@rackspace_endpoint = Fog::Rackspace.normalize_url(options[:rackspace_load_balancers_url] || options[:rackspace_lb_endpoint])
|
||||
|
||||
if v2_authentication?
|
||||
case @rackspace_endpoint
|
||||
when DFW_ENDPOINT
|
||||
@rackspace_endpoint = nil
|
||||
@rackspace_region = :dfw
|
||||
when ORD_ENDPOINT
|
||||
@rackspace_endpoint = nil
|
||||
@rackspace_region = :ord
|
||||
when LON_ENDPOINT
|
||||
@rackspace_endpoint = nil
|
||||
@rackspace_region = :lon
|
||||
else
|
||||
# we are actually using a custom endpoint
|
||||
@rackspace_region = options[:rackspace_region]
|
||||
end
|
||||
else
|
||||
#if we are using auth1 and the endpoint is not set, default to DFW_ENDPOINT for historical reasons
|
||||
@rackspace_endpoint ||= DFW_ENDPOINT
|
||||
end
|
||||
end
|
||||
|
||||
def deprecation_warnings(options)
|
||||
Fog::Logger.deprecation("The :rackspace_lb_endpoint option is deprecated. Please use :rackspace_load_balancers_url for custom endpoints") if options[:rackspace_lb_endpoint]
|
||||
|
||||
if [DFW_ENDPOINT, ORD_ENDPOINT, LON_ENDPOINT].include?(@rackspace_endpoint) && v2_authentication?
|
||||
regions = @identity_service.service_catalog.display_service_regions(service_name)
|
||||
Fog::Logger.deprecation("Please specify region using :rackspace_region rather than :rackspace_endpoint. Valid regions for :rackspace_region are #{regions}.")
|
||||
end
|
||||
end
|
||||
|
||||
def append_tenant_v1(credentials)
|
||||
account_id = credentials['X-Server-Management-Url'].match(/.*\/([\d]+)$/)[1]
|
||||
|
||||
endpoint = @rackspace_endpoint || credentials['X-Server-Management-Url'] || DFW_ENDPOINT
|
||||
@uri = URI.parse(endpoint)
|
||||
@uri.path = "#{@uri.path}/#{account_id}"
|
||||
end
|
||||
|
||||
def authenticate_v1(options)
|
||||
credentials = Fog::Rackspace.authenticate(options, @connection_options)
|
||||
append_tenant_v1 credentials
|
||||
@auth_token = credentials['X-Auth-Token']
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
252
lib/fog/rackspace/mock_data.rb
Normal file
252
lib/fog/rackspace/mock_data.rb
Normal file
|
@ -0,0 +1,252 @@
|
|||
module Fog
|
||||
module Rackspace
|
||||
module MockData
|
||||
NOT_FOUND_ID = "NOT-FOUND"
|
||||
|
||||
def data
|
||||
@@data ||= Hash.new do |hash, key|
|
||||
hash[key] = begin
|
||||
|
||||
#Compute V2
|
||||
flavor_id = Fog.credentials[:rackspace_flavor_id] ||= '3'
|
||||
image_id = Fog.credentials[:rackspace_image_id] ||= Fog::Rackspace::MockData.uuid
|
||||
image_name = Fog::Mock.random_letters(6)
|
||||
network_id = Fog::Rackspace::MockData.uuid
|
||||
user_id = Fog::Mock.random_numbers(6).to_s
|
||||
|
||||
flavor = {
|
||||
"OS-FLV-EXT-DATA:ephemeral" => 4,
|
||||
"disk" => 20,
|
||||
"id" => flavor_id,
|
||||
"links" => [
|
||||
{
|
||||
"href" => "https://dfw.servers.api.rackspacecloud.com/v2/010101/flavors/#{flavor_id}",
|
||||
"rel" => "self"
|
||||
},
|
||||
{
|
||||
"href" => "https://dfw.servers.api.rackspacecloud.com/010101/flavors/#{flavor_id}",
|
||||
"rel" => "bookmark"
|
||||
}
|
||||
],
|
||||
"name" => "512MB Standard Instance",
|
||||
"ram" => 512,
|
||||
"rxtx_factor" => 2.0,
|
||||
"swap" => 512,
|
||||
"vcpus" => 1,
|
||||
}
|
||||
|
||||
image = {
|
||||
"OS-DCF:diskConfig" => "AUTO",
|
||||
"created" => "2012-02-28T19:38:57Z",
|
||||
"id" => image_id,
|
||||
"name" => image_name,
|
||||
"links" => [
|
||||
{
|
||||
"href" => "https://dfw.servers.api.rackspacecloud.com/v2/010101/images/#{image_id}",
|
||||
"rel" => "self"
|
||||
},
|
||||
{
|
||||
"href" => "https://dfw.servers.api.rackspacecloud.com/010101/images/#{image_id}",
|
||||
"rel" => "bookmark"
|
||||
},
|
||||
{
|
||||
"href" => "https://dfw.servers.api.rackspacecloud.com/010101/images/#{image_id}",
|
||||
"rel" => "alternate",
|
||||
"type" => "application/vnd.openstack.image"
|
||||
}
|
||||
],
|
||||
"metadata" => {
|
||||
"arch" => "x86-64",
|
||||
"auto_disk_config" => "True",
|
||||
"com.rackspace__1__build_core" => "1",
|
||||
"com.rackspace__1__build_managed" => "0",
|
||||
"com.rackspace__1__build_rackconnect" => "0",
|
||||
"com.rackspace__1__options" => "0",
|
||||
"com.rackspace__1__visible_core" => "1",
|
||||
"com.rackspace__1__visible_managed" => "0",
|
||||
"com.rackspace__1__visible_rackconnect" => "0",
|
||||
"image_type" => "base",
|
||||
"org.openstack__1__architecture" => "x64",
|
||||
"org.openstack__1__os_distro" => "org.ubuntu",
|
||||
"org.openstack__1__os_version" => "11.10",
|
||||
"os_distro" => "ubuntu",
|
||||
"os_type" => "linux",
|
||||
"os_version" => "11.10",
|
||||
"rax_managed" => "false",
|
||||
"rax_options" => "0"
|
||||
},
|
||||
"minDisk" => 10,
|
||||
"minRam" => 256,
|
||||
"progress" => 100,
|
||||
"status" => "ACTIVE",
|
||||
"updated" => "2012-02-28T19:39:05Z"
|
||||
}
|
||||
|
||||
network = {
|
||||
'id' => network_id,
|
||||
'label' => 'network label',
|
||||
'cidr' => '192.168.0.0/24'
|
||||
}
|
||||
|
||||
key_pair = {
|
||||
'public_key' => "ssh-rsa ".concat(Fog::Mock.random_letters(372)).concat(" Generated by Nova\n"),
|
||||
'private_key' => "-----BEGIN RSA PRIVATE KEY-----\n".concat(Fog::Mock.random_letters(1635)).concat("\n-----END RSA PRIVATE KEY-----\n"),
|
||||
'user_id' => user_id,
|
||||
'name' => Fog::Mock.random_letters(32),
|
||||
'fingerprint' => "00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00"
|
||||
}
|
||||
|
||||
#Block Storage
|
||||
volume_type1_id = Fog::Mock.random_numbers(3).to_s
|
||||
volume_type2_id = Fog::Mock.random_numbers(3).to_s
|
||||
|
||||
volume_type1 = {
|
||||
"id" => volume_type1_id,
|
||||
"name" => "SATA",
|
||||
"extra_specs" => {},
|
||||
}
|
||||
|
||||
volume_type2 = {
|
||||
"id" => volume_type2_id,
|
||||
"name" => "SSD",
|
||||
"extra_specs" => {},
|
||||
}
|
||||
|
||||
#AutoScale
|
||||
launch_config = {
|
||||
"args" => {
|
||||
"loadBalancers" => [
|
||||
{
|
||||
"port" => 8080,
|
||||
"loadBalancerId" => 9099
|
||||
}
|
||||
],
|
||||
"server" => {
|
||||
"name" => "autoscale_server",
|
||||
"imageRef" => "0d589460-f177-4b0f-81c1-8ab8903ac7d8",
|
||||
"flavorRef" => "2",
|
||||
"OS-DCF =>diskConfig" => "AUTO",
|
||||
"metadata" => {
|
||||
"build_config" => "core",
|
||||
"meta_key_1" => "meta_value_1",
|
||||
"meta_key_2" => "meta_value_2"
|
||||
},
|
||||
"networks" => [
|
||||
{
|
||||
"uuid" => "11111111-1111-1111-1111-111111111111"
|
||||
},
|
||||
{
|
||||
"uuid" => "00000000-0000-0000-0000-000000000000"
|
||||
}
|
||||
],
|
||||
"personality" => [
|
||||
{
|
||||
"path" => "/root/.csivh",
|
||||
"contents" => "VGhpcyBpcyBhIHRlc3QgZmlsZS4="
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"type" => "launch_server"
|
||||
}
|
||||
|
||||
group_config = {
|
||||
"max_entities" => 10,
|
||||
"cooldown" => 360,
|
||||
"name" => "testscalinggroup198547",
|
||||
"min_entities" => 0,
|
||||
"metadata" => {
|
||||
"gc_meta_key_2" => "gc_meta_value_2",
|
||||
"gc_meta_key_1" => "gc_meta_value_1"
|
||||
}
|
||||
}
|
||||
|
||||
policy = {
|
||||
"cooldown" => 0,
|
||||
"type" => "webhook",
|
||||
"name" => "scale up by 1",
|
||||
"change" => 1
|
||||
}
|
||||
|
||||
webhook = {
|
||||
"name" => "webhook name",
|
||||
"metadata" => {'foo' => 'bar'}
|
||||
}
|
||||
|
||||
mock_data = {
|
||||
#Compute V2
|
||||
:flavors => Hash.new { |h,k| h[k] = flavor unless [NOT_FOUND_ID, '0'].include?(k) },
|
||||
:images => Hash.new { |h,k| h[k] = image unless [NOT_FOUND_ID, '0'].include?(k) },
|
||||
:networks => Hash.new { |h,k| h[k] = network unless [NOT_FOUND_ID, '0'].include?(k) },
|
||||
:keys => [],
|
||||
:keypair => key_pair,
|
||||
:keypairs => [],
|
||||
:servers => {},
|
||||
|
||||
#Block Storage
|
||||
:volumes => {},
|
||||
:snapshots => {},
|
||||
:volume_attachments => [],
|
||||
:volume_types => {volume_type1_id => volume_type1, volume_type2_id => volume_type2},
|
||||
|
||||
#Autoscale
|
||||
:autoscale_groups => {}
|
||||
}
|
||||
|
||||
# seed with initial data
|
||||
mock_data[:flavors][flavor_id] = flavor
|
||||
mock_data[:images][image_id] = image
|
||||
mock_data[:networks][network_id] = network
|
||||
|
||||
mock_data
|
||||
end
|
||||
end[@rackspace_api_key]
|
||||
end
|
||||
|
||||
def self.uuid
|
||||
[8,4,4,4,12].map{|i| Fog::Mock.random_hex(i)}.join("-")
|
||||
end
|
||||
|
||||
def self.ipv4_address
|
||||
4.times.map{ Fog::Mock.random_numbers(3) }.join(".")
|
||||
end
|
||||
|
||||
def self.ipv6_address
|
||||
8.times.map { Fog::Mock.random_hex(4) }.join(":")
|
||||
end
|
||||
|
||||
def self.keep(hash, *keys)
|
||||
{}.tap do |kept|
|
||||
keys.each{|k| kept[k]= hash[k] if hash.key?(k)}
|
||||
end
|
||||
end
|
||||
|
||||
def self.slice(hash, *keys)
|
||||
hash.dup.tap do |sliced|
|
||||
keys.each{|k| sliced.delete(k)}
|
||||
end
|
||||
end
|
||||
|
||||
def self.zulu_time
|
||||
Time.now.strftime("%Y-%m-%dT%H:%M:%SZ")
|
||||
end
|
||||
|
||||
def self.stringify(message)
|
||||
case message
|
||||
when Symbol
|
||||
message.to_s
|
||||
when Hash
|
||||
result = Hash.new
|
||||
message.each do |key, value|
|
||||
nk = stringify(key)
|
||||
nv = stringify(value)
|
||||
result[nk] = nv
|
||||
end
|
||||
result
|
||||
else
|
||||
message
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
214
lib/fog/rackspace/models/auto_scale/group.rb
Normal file
214
lib/fog/rackspace/models/auto_scale/group.rb
Normal file
|
@ -0,0 +1,214 @@
|
|||
require 'fog/core/model'
|
||||
require 'fog/rackspace/models/auto_scale/group_config'
|
||||
require 'fog/rackspace/models/auto_scale/launch_config'
|
||||
require 'fog/rackspace/models/auto_scale/policies'
|
||||
|
||||
module Fog
|
||||
module Rackspace
|
||||
class AutoScale
|
||||
class Group < Fog::Model
|
||||
# @!attribute [r] id
|
||||
# @return [String] The autoscale group's id
|
||||
identity :id
|
||||
|
||||
# @!attribute [r] links
|
||||
# @return [Array] group links.
|
||||
attribute :links
|
||||
|
||||
# Gets the group configuration for this autoscale group. The configuration describes the
|
||||
# minimum number of entities in the group, the maximum number of entities in the group,
|
||||
# the global cooldown time for the group, and other metadata.
|
||||
#
|
||||
# @return [Fog::Rackspace::AutoScale::GroupConfiguration] group_config if found
|
||||
#
|
||||
# @raise [Fog::Rackspace::AutoScale:::NotFound] - HTTP 404
|
||||
# @raise [Fog::Rackspace::AutoScale:::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Rackspace::AutoScale:::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Rackspace::AutoScale:::ServiceError]
|
||||
#
|
||||
# @see http://docs.rackspace.com/cas/api/v1.0/autoscale-devguide/content/GET_getGroupConfig_v1.0__tenantId__groups__groupId__config_Configurations.html
|
||||
def group_config
|
||||
if attributes[:group_config].nil? && persisted?
|
||||
data = service.get_group_config(identity)
|
||||
attributes[:group_config] = load_model('GroupConfig', data.body['groupConfiguration'])
|
||||
end
|
||||
attributes[:group_config]
|
||||
end
|
||||
|
||||
# Sets the configuration when this object is populated.
|
||||
#
|
||||
# @param object [Hash<String, String>] Object which will stock the object
|
||||
def group_config=(object = {})
|
||||
if object.is_a?(Hash)
|
||||
attributes[:group_config] = load_model('GroupConfig', object)
|
||||
else
|
||||
attributes[:group_config] = object
|
||||
end
|
||||
end
|
||||
|
||||
# Gets the launch configuration for this autoscale group. The launch configuration describes
|
||||
# the details of how to create a server, from what image to create a server, which load balancers
|
||||
# to join the server to, which networks to add the server to, and other metadata.
|
||||
#
|
||||
# @return [Fog::Rackspace::AutoScale::LaunchConfiguration] group_config if found
|
||||
#
|
||||
# @raise [Fog::Rackspace::AutoScale:::NotFound] - HTTP 404
|
||||
# @raise [Fog::Rackspace::AutoScale:::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Rackspace::AutoScale:::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Rackspace::AutoScale:::ServiceError]
|
||||
#
|
||||
# @see http://docs.rackspace.com/cas/api/v1.0/autoscale-devguide/content/GET_getLaunchConfig_v1.0__tenantId__groups__groupId__launch_Configurations.html
|
||||
def launch_config
|
||||
if attributes[:launch_config].nil? && persisted?
|
||||
data = service.get_launch_config(identity)
|
||||
attributes[:launch_config] = load_model('LaunchConfig', data.body['launchConfiguration'])
|
||||
end
|
||||
attributes[:launch_config]
|
||||
end
|
||||
|
||||
# Sets the configuration when this object is populated.
|
||||
#
|
||||
# @param object [Hash<String, String>] Object which will stock the object
|
||||
def launch_config=(object={})
|
||||
if object.is_a?(Hash)
|
||||
attributes[:launch_config] = load_model('LaunchConfig', object)
|
||||
else
|
||||
attributes[:launch_config] = object
|
||||
end
|
||||
end
|
||||
|
||||
# For the specified autoscaling group, this operation returns a list of the scaling policies
|
||||
# that are available to the group. Each policy is described in terms of an ID, name, type,
|
||||
# adjustment, cooldown time, and links.
|
||||
#
|
||||
# @return [Fog::Rackspace::AutoScale::Policies] policies
|
||||
#
|
||||
# @see http://docs.rackspace.com/cas/api/v1.0/autoscale-devguide/content/GET_getPolicies_v1.0__tenantId__groups__groupId__policies_Policies.html
|
||||
def policies
|
||||
return @policies if @policies
|
||||
if persisted?
|
||||
@policies = load_model('Policies')
|
||||
else
|
||||
@policies = Fog::Rackspace::AutoScale::Policies.new(:service => service, :group => self)
|
||||
@policies.clear
|
||||
end
|
||||
@policies
|
||||
# return nil unless persisted?
|
||||
# @policies ||= load_model('Policies')
|
||||
end
|
||||
|
||||
# Creates group
|
||||
# * requires attributes: :launch_config, :group_config, :policies
|
||||
#
|
||||
# @return [Boolean] returns true if group is being created
|
||||
#
|
||||
# @raise [Fog::Rackspace::AutoScale:::NotFound] - HTTP 404
|
||||
# @raise [Fog::Rackspace::AutoScale:::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Rackspace::AutoScale:::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Rackspace::AutoScale:::ServiceError]
|
||||
#
|
||||
# @see Groups#create
|
||||
# @see http://docs.rackspace.com/cas/api/v1.0/autoscale-devguide/content/POST_createGroup_v1.0__tenantId__groups_Groups.html
|
||||
def save
|
||||
requires :launch_config, :group_config, :policies
|
||||
raise Fog::Errors::Error.new("You should update launch_config and group_config directly") if persisted?
|
||||
|
||||
launch_config_hash = {
|
||||
'args' => launch_config.args,
|
||||
'type' => launch_config.type
|
||||
}
|
||||
group_config_hash = {
|
||||
'name' => group_config.name,
|
||||
'cooldown' => group_config.cooldown,
|
||||
'maxEntities' => group_config.max_entities,
|
||||
'minEntities' => group_config.min_entities
|
||||
}
|
||||
group_config_hash['metadata'] = group_config.metadata if group_config.metadata
|
||||
|
||||
data = service.create_group(launch_config_hash, group_config_hash, policies)
|
||||
merge_attributes(data.body['group'])
|
||||
true
|
||||
end
|
||||
|
||||
# Destroy the group
|
||||
#
|
||||
# @return [Boolean] returns true if group has started deleting
|
||||
#
|
||||
# @raise [Fog::Rackspace::AutoScale:::NotFound] - HTTP 404
|
||||
# @raise [Fog::Rackspace::AutoScale:::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Rackspace::AutoScale:::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Rackspace::AutoScale:::ServiceError]
|
||||
#
|
||||
# @see http://docs.rackspace.com/cas/api/v1.0/autoscale-devguide/content/DELETE_deleteGroup_v1.0__tenantId__groups__groupId__Groups.html
|
||||
def destroy
|
||||
requires :identity
|
||||
service.delete_group(identity)
|
||||
true
|
||||
end
|
||||
|
||||
# Get the current state of the autoscale group
|
||||
#
|
||||
# @return [String] the state of the group
|
||||
#
|
||||
# @raise [Fog::Rackspace::AutoScale:::NotFound] - HTTP 404
|
||||
# @raise [Fog::Rackspace::AutoScale:::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Rackspace::AutoScale:::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Rackspace::AutoScale:::ServiceError]
|
||||
#
|
||||
# @see http://docs.rackspace.com/cas/api/v1.0/autoscale-devguide/content/GET_getGroupState_v1.0__tenantId__groups__groupId__state_Groups.html
|
||||
def state
|
||||
requires :identity
|
||||
data = service.get_group_state(identity)
|
||||
data.body['group']
|
||||
end
|
||||
|
||||
# This operation pauses all execution of autoscaling policies.
|
||||
#
|
||||
# @note NOT IMPLEMENTED YET
|
||||
# @return [Boolean] returns true if paused
|
||||
#
|
||||
# @raise [Fog::Rackspace::AutoScale:::NotFound] - HTTP 404
|
||||
# @raise [Fog::Rackspace::AutoScale:::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Rackspace::AutoScale:::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Rackspace::AutoScale:::ServiceError]
|
||||
#
|
||||
# @see http://docs.rackspace.com/cas/api/v1.0/autoscale-devguide/content/POST_pauseGroup_v1.0__tenantId__groups__groupId__pause_Groups.html
|
||||
def pause
|
||||
requires :identity
|
||||
data = service.pause_group_state(identity)
|
||||
true
|
||||
end
|
||||
|
||||
# This operation resumes all execution of autoscaling policies.
|
||||
#
|
||||
# @note NOT IMPLEMENTED YET
|
||||
# @return [Boolean] returns true if resumed
|
||||
#
|
||||
# @raise [Fog::Rackspace::AutoScale:::NotFound] - HTTP 404
|
||||
# @raise [Fog::Rackspace::AutoScale:::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Rackspace::AutoScale:::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Rackspace::AutoScale:::ServiceError]
|
||||
#
|
||||
# @see http://docs.rackspace.com/cas/api/v1.0/autoscale-devguide/content/POST_resumeGroup_v1.0__tenantId__groups__groupId__resume_Groups.html
|
||||
def resume
|
||||
requires :identity
|
||||
data = service.resume_group_state(identity)
|
||||
true
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def load_model(class_name, attrs = nil)
|
||||
model = Fog::Rackspace::AutoScale.const_get(class_name).new({
|
||||
:service => @service,
|
||||
:group => self
|
||||
})
|
||||
if service && attrs
|
||||
model.merge_attributes(attrs)
|
||||
end
|
||||
model
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
86
lib/fog/rackspace/models/auto_scale/group_builder.rb
Normal file
86
lib/fog/rackspace/models/auto_scale/group_builder.rb
Normal file
|
@ -0,0 +1,86 @@
|
|||
require 'fog/core/model'
|
||||
require 'fog/rackspace/models/auto_scale/group_config'
|
||||
require 'fog/rackspace/models/auto_scale/launch_config'
|
||||
require 'fog/rackspace/models/auto_scale/policies'
|
||||
|
||||
module Fog
|
||||
module Rackspace
|
||||
class AutoScale
|
||||
class GroupBuilder
|
||||
class << self
|
||||
def build(service, attributes)
|
||||
service.groups.new :group_config => build_group_config(attributes), :launch_config => build_server_launch_config(attributes)
|
||||
end
|
||||
|
||||
def build_group_config(attributes)
|
||||
Fog::Rackspace::AutoScale::GroupConfig.new :max_entities => attributes[:max_entities],
|
||||
:min_entities => attributes[:min_entities],
|
||||
:cooldown => attributes[:cooldown],
|
||||
:name => attributes[:name],
|
||||
:metadata => attributes[:metadata] || {}
|
||||
end
|
||||
|
||||
def build_server_launch_config(attributes)
|
||||
return nil unless attributes[:launch_config_type] == :launch_server
|
||||
args = {"server" => build_server_template(attributes) }
|
||||
args["loadBalancers"] = build_load_balancers(attributes) if attributes[:load_balancers]
|
||||
|
||||
Fog::Rackspace::AutoScale::LaunchConfig.new :type => :launch_server, :args => args
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def build_load_balancers(attributes)
|
||||
return nil unless attributes[:load_balancers]
|
||||
|
||||
load_balancers = attributes[:load_balancers].is_a?(Array) ? attributes[:load_balancers] : [attributes[:load_balancers]]
|
||||
load_balancers.map do |obj|
|
||||
obj.is_a?(Hash) ? obj : load_balancer_to_hash(obj)
|
||||
end
|
||||
end
|
||||
|
||||
def load_balancer_to_hash(lb)
|
||||
raise ArgumentError.new("Expected LoadBalancer") unless lb.respond_to?(:id) && lb.respond_to?(:port)
|
||||
{
|
||||
"port" => lb.port,
|
||||
"loadBalancerId" => lb.id
|
||||
}
|
||||
end
|
||||
|
||||
def build_server_template(attributes)
|
||||
image_id = get_id(:image, attributes)
|
||||
flavor_id = get_id(:flavor, attributes)
|
||||
|
||||
server_template = {
|
||||
"name" => attributes[:server_name],
|
||||
"imageRef" => image_id,
|
||||
"flavorRef" => flavor_id,
|
||||
"OS-DCF =>diskConfig" => attributes[:disk_config] || "MANUAL",
|
||||
"metadata" => attributes[:server_metadata] || {}
|
||||
}
|
||||
|
||||
server_template["personality"] = attributes[:personality] if attributes[:personality]
|
||||
server_template["user_data"] = [attributes[:user_data]].pack('m') if attributes[:user_data]
|
||||
server_template["config_drive"] = 'true' if attributes[:config_drive]
|
||||
server_template["networks"] = networks_to_hash(attributes[:networks]) if attributes[:networks]
|
||||
server_template
|
||||
end
|
||||
|
||||
def model?(obj)
|
||||
obj.class.ancestors.include?(Fog::Model)
|
||||
end
|
||||
|
||||
def get_id(type, attributes)
|
||||
id = attributes["#{type}_id".to_sym]
|
||||
type_key = type.to_sym
|
||||
id ||= model?(attributes[type_key]) ? attributes[type_key].id : attributes[type_key]
|
||||
end
|
||||
|
||||
def networks_to_hash(networks)
|
||||
networks.map {|n| {"uuid" => n}}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
76
lib/fog/rackspace/models/auto_scale/group_config.rb
Normal file
76
lib/fog/rackspace/models/auto_scale/group_config.rb
Normal file
|
@ -0,0 +1,76 @@
|
|||
require 'fog/core/model'
|
||||
|
||||
module Fog
|
||||
module Rackspace
|
||||
class AutoScale
|
||||
class GroupConfig < Fog::Model
|
||||
# @!attribute [r] group
|
||||
# @return [Fog::Rackspace::AutoScale::Group] The parent group
|
||||
attribute :group
|
||||
|
||||
# @!attribute [r] name
|
||||
# @return [String] The name of the group
|
||||
attribute :name
|
||||
|
||||
# @!attribute [r] cooldown
|
||||
# @return [String] The group's cooldown
|
||||
attribute :cooldown
|
||||
|
||||
# @!attribute [r] min_entities
|
||||
# @return [Fixnum] The minimum amount of units which should exist in the group
|
||||
attribute :min_entities, :aliases => 'minEntities'
|
||||
|
||||
# @!attribute [r] max_entities
|
||||
# @return [Fixnum] The maximum amount of units which should exist in the group
|
||||
attribute :max_entities, :aliases => 'maxEntities'
|
||||
|
||||
# @!attribute [r] metadata
|
||||
# @return [Hash] The group's metadata
|
||||
attribute :metadata
|
||||
|
||||
# Update this group's configuration
|
||||
#
|
||||
# @return [Boolean] returns true if group config has been updated
|
||||
#
|
||||
# @raise [Fog::Rackspace::AutoScale:::NotFound] - HTTP 404
|
||||
# @raise [Fog::Rackspace::AutoScale:::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Rackspace::AutoScale:::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Rackspace::AutoScale:::ServiceError]
|
||||
#
|
||||
# @see http://docs.rackspace.com/cas/api/v1.0/autoscale-devguide/content/PUT_putGroupConfig_v1.0__tenantId__groups__groupId__config_Configurations.html
|
||||
def update
|
||||
options = {}
|
||||
options['name'] = name unless name.nil?
|
||||
options['cooldown'] = cooldown unless cooldown.nil?
|
||||
options['minEntities'] = min_entities
|
||||
options['maxEntities'] = max_entities
|
||||
options['metadata'] = metadata unless metadata.nil?
|
||||
|
||||
service.update_group_config(group.id, options)
|
||||
true
|
||||
end
|
||||
|
||||
# Saves group configuration.
|
||||
# This method will only save existing group configurations. New group configurations are created when a scaling group is created
|
||||
#
|
||||
# @return [Boolean] true if group config was saved
|
||||
def save
|
||||
if group.id
|
||||
update
|
||||
true
|
||||
else
|
||||
raise "New #{self.class} are created when a new Fog::Rackspace::AutoScale::Group is created"
|
||||
end
|
||||
end
|
||||
|
||||
# Reloads group configuration
|
||||
def reload
|
||||
if group.id
|
||||
data = service.get_group_config(group.id)
|
||||
merge_attributes data.body['groupConfiguration']
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
45
lib/fog/rackspace/models/auto_scale/groups.rb
Normal file
45
lib/fog/rackspace/models/auto_scale/groups.rb
Normal file
|
@ -0,0 +1,45 @@
|
|||
require 'fog/core/collection'
|
||||
require 'fog/rackspace/models/auto_scale/group'
|
||||
|
||||
module Fog
|
||||
module Rackspace
|
||||
class AutoScale
|
||||
class Groups < Fog::Collection
|
||||
model Fog::Rackspace::AutoScale::Group
|
||||
|
||||
# Returns list of autoscale groups
|
||||
#
|
||||
# @return [Fog::Rackspace::AutoScale::Groups] Retrieves a list groups.
|
||||
#
|
||||
# @raise [Fog::Rackspace::AutoScale:::NotFound] - HTTP 404
|
||||
# @raise [Fog::Rackspace::AutoScale:::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Rackspace::AutoScale:::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Rackspace::AutoScale:::ServiceError]
|
||||
#
|
||||
# @see http://docs.rackspace.com/cas/api/v1.0/autoscale-devguide/content/GET_getGroups_v1.0__tenantId__groups_Groups.html
|
||||
def all
|
||||
data = service.list_groups.body['groups']
|
||||
load(data)
|
||||
end
|
||||
|
||||
# Returns an individual autoscale group
|
||||
#
|
||||
# @return [Fog::Rackspace::AutoScale::Group] Retrieves a list groups.
|
||||
# @return nil if not found
|
||||
#
|
||||
# @raise [Fog::Rackspace::AutoScale:::NotFound] - HTTP 404
|
||||
# @raise [Fog::Rackspace::AutoScale:::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Rackspace::AutoScale:::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Rackspace::AutoScale:::ServiceError]
|
||||
#
|
||||
# @see http://docs.rackspace.com/cas/api/v1.0/autoscale-devguide/content/GET_getGroupManifest_v1.0__tenantId__groups__groupId__Groups.html
|
||||
def get(group_id)
|
||||
data = service.get_group(group_id).body['group']
|
||||
new(data)
|
||||
rescue Fog::Rackspace::AutoScale::NotFound
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
61
lib/fog/rackspace/models/auto_scale/launch_config.rb
Normal file
61
lib/fog/rackspace/models/auto_scale/launch_config.rb
Normal file
|
@ -0,0 +1,61 @@
|
|||
require 'fog/core/model'
|
||||
|
||||
module Fog
|
||||
module Rackspace
|
||||
class AutoScale
|
||||
class LaunchConfig < Fog::Model
|
||||
# @!attribute [r] group
|
||||
# @return [Fog::Rackspace::AutoScale::Group] The parent group
|
||||
attribute :group
|
||||
|
||||
# @!attribute [r] type
|
||||
# @return [Fog::Rackspace::AutoScale::Group] The type of operation (usually "launch_server")
|
||||
attribute :type
|
||||
|
||||
# @!attribute [r] args
|
||||
# @return [Fog::Rackspace::AutoScale::Group] The arguments for the operation
|
||||
attribute :args
|
||||
|
||||
# Update this group's launch configuration
|
||||
#
|
||||
# @return [Boolean] returns true if launch config has been updated
|
||||
#
|
||||
# @raise [Fog::Rackspace::AutoScale:::NotFound] - HTTP 404
|
||||
# @raise [Fog::Rackspace::AutoScale:::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Rackspace::AutoScale:::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Rackspace::AutoScale:::ServiceError]
|
||||
#
|
||||
# @see http://docs.rackspace.com/cas/api/v1.0/autoscale-devguide/content/PUT_putLaunchConfig_v1.0__tenantId__groups__groupId__launch_Configurations.html
|
||||
def update
|
||||
options = {}
|
||||
options['type'] = type unless type.nil?
|
||||
options['args'] = args unless args.nil?
|
||||
|
||||
service.update_launch_config(group.id, options)
|
||||
true
|
||||
end
|
||||
|
||||
# Saves group launch configuration.
|
||||
# This method will only save existing group configurations. New group configurations are created when a scaling group is created
|
||||
#
|
||||
# @return [Boolean] true if launch group was saved
|
||||
def save
|
||||
if group.id
|
||||
update
|
||||
true
|
||||
else
|
||||
raise "New #{self.class} are created when a new Fog::Rackspace::AutoScale::Group is created"
|
||||
end
|
||||
end
|
||||
|
||||
# Reloads group launch configuration
|
||||
def reload
|
||||
if group.id
|
||||
data = service.get_launch_config(group.id)
|
||||
merge_attributes data.body['launchConfiguration']
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
65
lib/fog/rackspace/models/auto_scale/policies.rb
Normal file
65
lib/fog/rackspace/models/auto_scale/policies.rb
Normal file
|
@ -0,0 +1,65 @@
|
|||
require 'fog/core/collection'
|
||||
require 'fog/rackspace/models/auto_scale/policy'
|
||||
|
||||
module Fog
|
||||
module Rackspace
|
||||
class AutoScale
|
||||
class Policies < Fog::Collection
|
||||
model Fog::Rackspace::AutoScale::Policy
|
||||
|
||||
attr_accessor :group
|
||||
|
||||
# Returns list of autoscale policies
|
||||
#
|
||||
# @return [Fog::Rackspace::AutoScale::Policies] Retrieves policies
|
||||
#
|
||||
# @raise [Fog::Rackspace::AutoScale:::NotFound] - HTTP 404
|
||||
# @raise [Fog::Rackspace::AutoScale:::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Rackspace::AutoScale:::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Rackspace::AutoScale:::ServiceError]
|
||||
#
|
||||
# @see http://docs.rackspace.com/cas/api/v1.0/autoscale-devguide/content/GET_getPolicies_v1.0__tenantId__groups__groupId__policies_Policies.html
|
||||
def all
|
||||
data = service.list_policies(group.id).body['policies']
|
||||
load(data)
|
||||
end
|
||||
|
||||
# Returns an individual autoscale policy
|
||||
#
|
||||
# @return [Fog::Rackspace::AutoScale::Group] Retrieves a policy
|
||||
# @return nil if not found
|
||||
#
|
||||
# @raise [Fog::Rackspace::AutoScale:::NotFound] - HTTP 404
|
||||
# @raise [Fog::Rackspace::AutoScale:::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Rackspace::AutoScale:::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Rackspace::AutoScale:::ServiceError]
|
||||
#
|
||||
# @see http://docs.rackspace.com/cas/api/v1.0/autoscale-devguide/content/GET_getPolicy_v1.0__tenantId__groups__groupId__policies__policyId__Policies.html
|
||||
def get(policy_id)
|
||||
data = service.get_policy(group.id, policy_id).body['policy']
|
||||
new(data)
|
||||
rescue Fog::Rackspace::AutoScale::NotFound
|
||||
nil
|
||||
end
|
||||
|
||||
# Create an autoscale policy
|
||||
#
|
||||
# @return [Fog::Rackspace::AutoScale::Policy] Returns the new policy
|
||||
#
|
||||
# @raise [Fog::Rackspace::AutoScale:::NotFound] - HTTP 404
|
||||
# @raise [Fog::Rackspace::AutoScale:::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Rackspace::AutoScale:::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Rackspace::AutoScale:::ServiceError]
|
||||
#
|
||||
# @see http://docs.rackspace.com/cas/api/v1.0/autoscale-devguide/content/POST_createPolicies_v1.0__tenantId__groups__groupId__policies_Policies.html
|
||||
def create(attributes = {})
|
||||
super(attributes)
|
||||
end
|
||||
|
||||
def new(attributes = {})
|
||||
super({:group => group}.merge(attributes))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
220
lib/fog/rackspace/models/auto_scale/policy.rb
Normal file
220
lib/fog/rackspace/models/auto_scale/policy.rb
Normal file
|
@ -0,0 +1,220 @@
|
|||
require 'fog/core/model'
|
||||
require 'fog/rackspace/models/auto_scale/webhooks'
|
||||
|
||||
module Fog
|
||||
module Rackspace
|
||||
class AutoScale
|
||||
class Policy < Fog::Model
|
||||
# @!attribute [r] id
|
||||
# @return [String] The policy id
|
||||
identity :id
|
||||
|
||||
# @!attribute [r] group
|
||||
# @return [Group] The autoscale group
|
||||
attribute :group
|
||||
|
||||
# @!attribute [r] links
|
||||
# @return [Array] Policy links
|
||||
attribute :links
|
||||
|
||||
# @!attribute [r] name
|
||||
# @return [String] The policy's name
|
||||
attribute :name
|
||||
|
||||
# @!attribute [r] change
|
||||
# @return [Fixnum] The fixed change to the autoscale group's number of units
|
||||
attribute :change
|
||||
|
||||
# @!attribute [r] changePercent
|
||||
# @return [Fixnum] The percentage change to the autoscale group's number of units
|
||||
attribute :change_percent, :aliases => 'changePercent'
|
||||
|
||||
# @!attribute [r] cooldown
|
||||
# @return [Fixnum] The policy's cooldown
|
||||
attribute :cooldown
|
||||
|
||||
# @!attribute [r] type
|
||||
# @note Can only be "webhook", "schedule" or "cloud_monitoring"
|
||||
# @return [String] The policy's type
|
||||
attribute :type
|
||||
|
||||
# @!attribute [r] args
|
||||
# @example See below:
|
||||
# - "cron": "23 * * * *"
|
||||
# - "at": "2013-06-05T03:12Z"
|
||||
# - "check": {
|
||||
# "label": "Website check 1",
|
||||
# "type": "remote.http",
|
||||
# "details": {
|
||||
# "url": "http://www.example.com",
|
||||
# "method": "GET"
|
||||
# },
|
||||
# "monitoring_zones_poll": [
|
||||
# "mzA"
|
||||
# ],
|
||||
# "timeout": 30,
|
||||
# "period": 100,
|
||||
# "target_alias": "default"
|
||||
# },
|
||||
# "alarm_criteria": {
|
||||
# "criteria": "if (metric[\"duration\"] >= 2) { return new AlarmStatus(OK); } return new AlarmStatus(CRITICAL);"
|
||||
# }
|
||||
#
|
||||
# @return [String] Arguments used for the policy
|
||||
attribute :args
|
||||
|
||||
# @!attribute [r] desiredCapacity
|
||||
# @return [Fixnum] The desired capacity of the group
|
||||
attribute :desired_capacity, :aliases => 'desiredCapacity'
|
||||
|
||||
# Basic sanity check to make sure attributes are valid
|
||||
#
|
||||
# @raise ArgumentError If no type is set
|
||||
# @raise ArgumentError If args attribute is missing required keys (if type == 'schedule')
|
||||
|
||||
# @return [Boolean] Returns true if the check passes
|
||||
def check_attributes
|
||||
raise ArgumentError, "This #{self.name} resource requires the #{type} argument" if type.nil?
|
||||
|
||||
if type == 'schedule'
|
||||
raise ArgumentError, "This #{self.name} resource requires the args[cron] OR args[at] argument" if args['cron'].nil? && args['at'].nil?
|
||||
end
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
def group=(group)
|
||||
attributes[:group] = group.is_a?(Group) ? group : service.groups.new(:id => group)
|
||||
end
|
||||
|
||||
# Creates policy
|
||||
# * requires attributes: :name, :type, :cooldown
|
||||
#
|
||||
# @return [Boolean] returns true if policy is being created
|
||||
#
|
||||
# @raise [Fog::Rackspace::AutoScale:::NotFound] - HTTP 404
|
||||
# @raise [Fog::Rackspace::AutoScale:::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Rackspace::AutoScale:::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Rackspace::AutoScale:::ServiceError]
|
||||
#
|
||||
# @see Policies#create
|
||||
# @see http://docs.rackspace.com/cas/api/v1.0/autoscale-devguide/content/POST_createPolicies_v1.0__tenantId__groups__groupId__policies_Policies.html
|
||||
def create
|
||||
requires :name, :type, :cooldown
|
||||
|
||||
check_attributes
|
||||
|
||||
options = {}
|
||||
options['name'] = name unless name.nil?
|
||||
options['change'] = change unless change.nil?
|
||||
options['changePercent'] = change_percent unless change_percent.nil?
|
||||
options['cooldown'] = cooldown unless cooldown.nil?
|
||||
options['type'] = type unless type.nil?
|
||||
options['desiredCapacity'] = desired_capacity unless desired_capacity.nil?
|
||||
|
||||
if type == 'schedule'
|
||||
options['args'] = args
|
||||
end
|
||||
|
||||
data = service.create_policy(group.id, options)
|
||||
merge_attributes(data.body['policies'][0])
|
||||
true
|
||||
end
|
||||
|
||||
# Updates the policy
|
||||
#
|
||||
# @return [Boolean] returns true if policy has started updating
|
||||
#
|
||||
# @raise [Fog::Rackspace::AutoScale:::NotFound] - HTTP 404
|
||||
# @raise [Fog::Rackspace::AutoScale:::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Rackspace::AutoScale:::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Rackspace::AutoScale:::ServiceError]
|
||||
#
|
||||
# @see http://docs.rackspace.com/cas/api/v1.0/autoscale-devguide/content/PUT_putPolicy_v1.0__tenantId__groups__groupId__policies__policyId__Policies.html
|
||||
def update
|
||||
requires :identity
|
||||
|
||||
check_attributes
|
||||
|
||||
options = {}
|
||||
options['name'] = name unless name.nil?
|
||||
options['change'] = change unless change.nil?
|
||||
options['changePercent'] = change_percent unless change_percent.nil?
|
||||
options['cooldown'] = cooldown unless cooldown.nil?
|
||||
options['type'] = type unless type.nil?
|
||||
options['desiredCapacity'] = desired_capacity unless desired_capacity.nil?
|
||||
|
||||
if type == 'schedule'
|
||||
options['args'] = args
|
||||
end
|
||||
|
||||
data = service.update_policy(group.id, identity, options)
|
||||
merge_attributes(data.body)
|
||||
true
|
||||
end
|
||||
|
||||
# Saves the policy
|
||||
# Creates policy if it is new, otherwise it will update it
|
||||
# @return [Boolean] true if policy has saved
|
||||
def save
|
||||
if persisted?
|
||||
update
|
||||
else
|
||||
create
|
||||
end
|
||||
true
|
||||
end
|
||||
|
||||
# Destroy the policy
|
||||
#
|
||||
# @return [Boolean] returns true if policy has started deleting
|
||||
#
|
||||
# @raise [Fog::Rackspace::AutoScale:::NotFound] - HTTP 404
|
||||
# @raise [Fog::Rackspace::AutoScale:::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Rackspace::AutoScale:::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Rackspace::AutoScale:::ServiceError]
|
||||
#
|
||||
# @see http://docs.rackspace.com/cas/api/v1.0/autoscale-devguide/content/DELETE_deletePolicy_v1.0__tenantId__groups__groupId__policies__policyId__Policies.html
|
||||
def destroy
|
||||
requires :identity
|
||||
service.delete_policy(group.id, identity)
|
||||
true
|
||||
end
|
||||
|
||||
# Executes the scaling policy
|
||||
#
|
||||
# @return [Boolean] returns true if policy has been executed
|
||||
#
|
||||
# @raise [Fog::Rackspace::AutoScale:::NotFound] - HTTP 404
|
||||
# @raise [Fog::Rackspace::AutoScale:::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Rackspace::AutoScale:::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Rackspace::AutoScale:::ServiceError]
|
||||
#
|
||||
# @see http://docs.rackspace.com/cas/api/v1.0/autoscale-devguide/content/POST_executePolicy_v1.0__tenantId__groups__groupId__policies__policyId__execute_Policies.html
|
||||
def execute
|
||||
requires :identity
|
||||
service.execute_policy(group.id, identity)
|
||||
true
|
||||
end
|
||||
|
||||
# Gets the associated webhooks for this policy
|
||||
#
|
||||
# @return [Fog::Rackspace::AutoScale::Webhooks] returns Webhooks
|
||||
#
|
||||
# @raise [Fog::Rackspace::AutoScale:::NotFound] - HTTP 404
|
||||
# @raise [Fog::Rackspace::AutoScale:::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Rackspace::AutoScale:::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Rackspace::AutoScale:::ServiceError]
|
||||
def webhooks
|
||||
requires :identity
|
||||
|
||||
@webhooks ||= Fog::Rackspace::AutoScale::Webhooks.new({
|
||||
:service => service,
|
||||
:policy => self,
|
||||
:group => group
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
116
lib/fog/rackspace/models/auto_scale/webhook.rb
Normal file
116
lib/fog/rackspace/models/auto_scale/webhook.rb
Normal file
|
@ -0,0 +1,116 @@
|
|||
require 'fog/core/model'
|
||||
|
||||
module Fog
|
||||
module Rackspace
|
||||
class AutoScale
|
||||
class Webhook < Fog::Model
|
||||
# @!attribute [r] id
|
||||
# @return [String] The webhook id
|
||||
identity :id
|
||||
|
||||
# @!attribute [r] group
|
||||
# @return [String] The associated group
|
||||
attribute :group
|
||||
|
||||
# @!attribute [r] policy
|
||||
# @return [String] The associated policy
|
||||
attribute :policy
|
||||
|
||||
# @!attribute [r] name
|
||||
# @return [String] The webhook name
|
||||
attribute :name
|
||||
|
||||
# @!attribute [r] metadata
|
||||
# @return [Hash] The metadata
|
||||
attribute :metadata
|
||||
|
||||
# @!attribute [r] links
|
||||
# @return [Array] The webhook links
|
||||
attribute :links
|
||||
|
||||
# Create webhook
|
||||
# * requires attribute: :name
|
||||
#
|
||||
# @return [Boolean] returns true if webhook is being created
|
||||
#
|
||||
# @raise [Fog::Rackspace::AutoScale:::NotFound] - HTTP 404
|
||||
# @raise [Fog::Rackspace::AutoScale:::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Rackspace::AutoScale:::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Rackspace::AutoScale:::ServiceError]
|
||||
#
|
||||
# @see Webhooks#create
|
||||
# @see
|
||||
def create
|
||||
requires :name
|
||||
|
||||
options = {}
|
||||
options['name'] = name if name
|
||||
options['metadata'] = metadata if metadata
|
||||
|
||||
data = service.create_webhook(group.id, policy.id, options)
|
||||
merge_attributes(data.body['webhooks'][0])
|
||||
true
|
||||
end
|
||||
|
||||
# Updates the webhook
|
||||
#
|
||||
# @return [Boolean] returns true if webhook has started updating
|
||||
#
|
||||
# @raise [Fog::Rackspace::AutoScale:::NotFound] - HTTP 404
|
||||
# @raise [Fog::Rackspace::AutoScale:::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Rackspace::AutoScale:::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Rackspace::AutoScale:::ServiceError]
|
||||
#
|
||||
# @see http://docs.rackspace.com/cas/api/v1.0/autoscale-devguide/content/PUT_putWebhook_v1.0__tenantId__groups__groupId__policies__policyId__webhooks__webhookId__Webhooks.html
|
||||
def update
|
||||
requires :identity
|
||||
|
||||
options = {
|
||||
'name' => name,
|
||||
'metadata' => metadata
|
||||
}
|
||||
|
||||
data = service.update_webhook(group.id, policy.id, identity, options)
|
||||
merge_attributes(data.body)
|
||||
true
|
||||
end
|
||||
|
||||
# Saves the webhook
|
||||
# Creates hook if it is new, otherwise it will update it
|
||||
# @return [Boolean] true if policy has saved
|
||||
def save
|
||||
if persisted?
|
||||
update
|
||||
else
|
||||
create
|
||||
end
|
||||
true
|
||||
end
|
||||
|
||||
# Destroy the webhook
|
||||
#
|
||||
# @return [Boolean] returns true if webhook has started deleting
|
||||
#
|
||||
# @raise [Fog::Rackspace::AutoScale:::NotFound] - HTTP 404
|
||||
# @raise [Fog::Rackspace::AutoScale:::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Rackspace::AutoScale:::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Rackspace::AutoScale:::ServiceError]
|
||||
#
|
||||
# @see http://docs.rackspace.com/cas/api/v1.0/autoscale-devguide/content/DELETE_deleteWebhook_v1.0__tenantId__groups__groupId__policies__policyId__webhooks__webhookId__Webhooks.html
|
||||
def destroy
|
||||
requires :identity
|
||||
service.delete_webhook(group.id, policy.id, identity)
|
||||
true
|
||||
end
|
||||
|
||||
# Retrieves the URL for anonymously executing the policy webhook
|
||||
# @return [String] the URL
|
||||
def execution_url
|
||||
requires :links
|
||||
link = links.find { |l| l['rel'] == 'capability' }
|
||||
link['href'] rescue nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
62
lib/fog/rackspace/models/auto_scale/webhooks.rb
Normal file
62
lib/fog/rackspace/models/auto_scale/webhooks.rb
Normal file
|
@ -0,0 +1,62 @@
|
|||
require 'fog/core/collection'
|
||||
require 'fog/rackspace/models/auto_scale/webhook'
|
||||
|
||||
module Fog
|
||||
module Rackspace
|
||||
class AutoScale
|
||||
class Webhooks < Fog::Collection
|
||||
model Fog::Rackspace::AutoScale::Webhook
|
||||
|
||||
attr_accessor :group
|
||||
attr_accessor :policy
|
||||
|
||||
# Returns list of autoscale webhooks
|
||||
#
|
||||
# @return [Fog::Rackspace::AutoScale::Policies] Retrieves webhooks
|
||||
#
|
||||
# @raise [Fog::Rackspace::AutoScale:::NotFound] - HTTP 404
|
||||
# @raise [Fog::Rackspace::AutoScale:::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Rackspace::AutoScale:::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Rackspace::AutoScale:::ServiceError]
|
||||
def all
|
||||
data = service.list_webhooks(group.id, policy.id).body['webhooks']
|
||||
load(data)
|
||||
end
|
||||
|
||||
# Returns an individual webhook
|
||||
#
|
||||
# @return [Fog::Rackspace::AutoScale::Webhook] Retrieves a webhook
|
||||
# @return nil if not found
|
||||
#
|
||||
# @raise [Fog::Rackspace::AutoScale:::NotFound] - HTTP 404
|
||||
# @raise [Fog::Rackspace::AutoScale:::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Rackspace::AutoScale:::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Rackspace::AutoScale:::ServiceError]
|
||||
#
|
||||
# @see http://docs.rackspace.com/cas/api/v1.0/autoscale-devguide/content/GET_getWebhook_v1.0__tenantId__groups__groupId__policies__policyId__webhooks__webhookId__Webhooks.html
|
||||
def get(webhook_id)
|
||||
data = service.get_webhook(group.id, policy.id, webhook_id).body['webhook']
|
||||
new(data)
|
||||
rescue Fog::Rackspace::AutoScale::NotFound
|
||||
nil
|
||||
end
|
||||
|
||||
# Create a webhook
|
||||
#
|
||||
# @return [Fog::Rackspace::AutoScale::Webhook] Returns the new webhook
|
||||
#
|
||||
# @raise [Fog::Rackspace::AutoScale:::NotFound] - HTTP 404
|
||||
# @raise [Fog::Rackspace::AutoScale:::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Rackspace::AutoScale:::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Rackspace::AutoScale:::ServiceError]
|
||||
def create(attributes = {})
|
||||
super(attributes)
|
||||
end
|
||||
|
||||
def new(attributes = {})
|
||||
super({:group => group, :policy => policy}.merge(attributes))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
89
lib/fog/rackspace/models/block_storage/snapshot.rb
Normal file
89
lib/fog/rackspace/models/block_storage/snapshot.rb
Normal file
|
@ -0,0 +1,89 @@
|
|||
require 'fog/core/model'
|
||||
|
||||
module Fog
|
||||
module Rackspace
|
||||
class BlockStorage
|
||||
class Snapshot < Fog::Model
|
||||
AVAILABLE = 'available'
|
||||
CREATING = 'creating'
|
||||
DELETING = 'deleting'
|
||||
ERROR = 'error'
|
||||
ERROR_DELETING = 'error_deleting'
|
||||
|
||||
# @!attribute [r] id
|
||||
# @return [String] The snapshot id
|
||||
identity :id
|
||||
|
||||
# @!attribute [r] created_at
|
||||
# @return [String] snapshot creation time
|
||||
attribute :created_at, :aliases => 'createdAt'
|
||||
|
||||
# @!attribute [r] state
|
||||
# @return [String] snapshot status
|
||||
attribute :state, :aliases => 'status'
|
||||
|
||||
# @!attribute [rw] display_name
|
||||
# @return [String] display name of snapshot
|
||||
attribute :display_name
|
||||
|
||||
# @!attribute [rw] display_description
|
||||
# @return [String] display description of snapshot
|
||||
attribute :display_description
|
||||
|
||||
# @!attribute [rw] size
|
||||
# @return [String] size of snapshot
|
||||
attribute :size
|
||||
|
||||
# @!attribute [rw] volume_id
|
||||
# @return [String] the volume_id of the snapshot
|
||||
attribute :volume_id
|
||||
|
||||
# @!attribute [r] availability_zone
|
||||
# @return [String] region of the snapshot
|
||||
attribute :availability_zone
|
||||
|
||||
# Returns true if the snapshot is in a ready state
|
||||
# @return [Boolean] returns true if snapshot is in a ready state
|
||||
def ready?
|
||||
state == AVAILABLE
|
||||
end
|
||||
|
||||
# Creates the snapshot
|
||||
# @param force [Boolean] Set to true to force service to create snapshot
|
||||
# @raise [Fog::Rackspace::BlockStorage::IdentifierTaken] if the snapshot has been previously saved.
|
||||
# @return [Boolean] returns true if snapshot is being created
|
||||
# @raise [Fog::Rackspace::BlockStorage::NotFound] - HTTP 404
|
||||
# @raise [Fog::Rackspace::BlockStorage::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Rackspace::BlockStorage::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Rackspace::BlockStorage::ServiceError]
|
||||
# @note A snapshot object cannot be updated
|
||||
# @note All writes to the volume should be flushed before creating the snapshot, either by un-mounting any file systems on the volume or by detaching the volume.
|
||||
# @see http://docs.rackspace.com/cbs/api/v1.0/cbs-devguide/content/POST_createSnapshot__v1__tenant_id__snapshots.html
|
||||
def save(force = false)
|
||||
requires :volume_id
|
||||
raise IdentifierTaken.new('Resaving may cause a duplicate snapshot to be created') if persisted?
|
||||
data = service.create_snapshot(volume_id, {
|
||||
:display_name => display_name,
|
||||
:display_description => display_description,
|
||||
:force => force
|
||||
})
|
||||
merge_attributes(data.body['snapshot'])
|
||||
true
|
||||
end
|
||||
|
||||
# Destroys snapshot
|
||||
# @return [Boolean] returns true if snapshot was deleted
|
||||
# @raise [Fog::Rackspace::BlockStorage::NotFound] - HTTP 404
|
||||
# @raise [Fog::Rackspace::BlockStorage::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Rackspace::BlockStorage::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Rackspace::BlockStorage::ServiceError]
|
||||
# @see http://docs.rackspace.com/cbs/api/v1.0/cbs-devguide/content/DELETE_deleteSnapshot__v1__tenant_id__snapshots.html
|
||||
def destroy
|
||||
requires :identity
|
||||
service.delete_snapshot(identity)
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
39
lib/fog/rackspace/models/block_storage/snapshots.rb
Normal file
39
lib/fog/rackspace/models/block_storage/snapshots.rb
Normal file
|
@ -0,0 +1,39 @@
|
|||
require 'fog/core/collection'
|
||||
require 'fog/rackspace/models/block_storage/snapshot'
|
||||
|
||||
module Fog
|
||||
module Rackspace
|
||||
class BlockStorage
|
||||
class Snapshots < Fog::Collection
|
||||
model Fog::Rackspace::BlockStorage::Snapshot
|
||||
|
||||
# Returns list of snapshots
|
||||
# @return [Fog::Rackspace::BlockStorage::Snapshots] Retrieves a snapshots
|
||||
# @raise [Fog::Rackspace::BlockStorage::NotFound] - HTTP 404
|
||||
# @raise [Fog::Rackspace::BlockStorage::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Rackspace::BlockStorage::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Rackspace::BlockStorage::ServiceError]
|
||||
# @see http://docs.rackspace.com/cbs/api/v1.0/cbs-devguide/content/GET_getSnapshotsSimple__v1__tenant_id__snapshots.html
|
||||
def all
|
||||
data = service.list_snapshots.body['snapshots']
|
||||
load(data)
|
||||
end
|
||||
|
||||
# Retrieves snapshot
|
||||
# @param [String] snapshot_id for snapshot to be returned
|
||||
# @return [Fog::Rackspace::BlockStorage::Volume]
|
||||
# @raise [Fog::Rackspace::BlockStorage::NotFound] - HTTP 404
|
||||
# @raise [Fog::Rackspace::BlockStorage::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Rackspace::BlockStorage::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Rackspace::BlockStorage::ServiceError]
|
||||
# @see http://docs.rackspace.com/cbs/api/v1.0/cbs-devguide/content/GET_getSnapshot__v1__tenant_id__snapshots.html
|
||||
def get(snapshot_id)
|
||||
data = service.get_snapshot(snapshot_id).body['snapshot']
|
||||
new(data)
|
||||
rescue Fog::Rackspace::BlockStorage::NotFound
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
134
lib/fog/rackspace/models/block_storage/volume.rb
Normal file
134
lib/fog/rackspace/models/block_storage/volume.rb
Normal file
|
@ -0,0 +1,134 @@
|
|||
require 'fog/core/model'
|
||||
|
||||
module Fog
|
||||
module Rackspace
|
||||
class BlockStorage
|
||||
class Volume < Fog::Model
|
||||
AVAILABLE = 'available'
|
||||
ATTACHING = 'attaching'
|
||||
CREATING = 'creating'
|
||||
DELETING = 'deleting'
|
||||
ERROR = 'error'
|
||||
ERROR_DELETING = 'error_deleting'
|
||||
IN_USE = 'in-use'
|
||||
|
||||
# @!attribute [r] id
|
||||
# @return [String] The volume id
|
||||
identity :id
|
||||
|
||||
# @!attribute [r] created_at
|
||||
# @return [String] volume creation date
|
||||
attribute :created_at, :aliases => 'createdAt'
|
||||
|
||||
# @!attribute [r] state
|
||||
# @return [String] volume status
|
||||
attribute :state, :aliases => 'status'
|
||||
|
||||
# @!attribute [rw] display_name
|
||||
# @return [String] display name of volume
|
||||
attribute :display_name
|
||||
|
||||
# @!attribute [rw] display_description
|
||||
# @return [String] display description of volume
|
||||
attribute :display_description
|
||||
|
||||
# @!attribute [rw] size
|
||||
# @return [String] size of the volume in GB (100 GB minimum)
|
||||
attribute :size
|
||||
|
||||
# @!attribute [r] attachments
|
||||
# @return [Array<Hash>] returns an array of hashes containing attachment information
|
||||
attribute :attachments
|
||||
|
||||
# @!attribute [rw] volume_type
|
||||
# @return [String] type of volume
|
||||
attribute :volume_type
|
||||
|
||||
# @!attribute [r] availability_zone
|
||||
# @return [String] region of the volume
|
||||
attribute :availability_zone
|
||||
|
||||
# @!attribute [rw] image_id
|
||||
# @return [String] The ID of an image used to create a bootable volume.
|
||||
attribute :image_id, :aliases => ['image', 'imageRef'], :squash => 'id'
|
||||
|
||||
# Returns true if the volume is in a ready state
|
||||
# @return [Boolean] returns true if volume is in a ready state
|
||||
def ready?
|
||||
state == AVAILABLE
|
||||
end
|
||||
|
||||
# Returns true if the volume is attached
|
||||
# @return [Boolean] true if the volume is attached
|
||||
def attached?
|
||||
state == IN_USE
|
||||
end
|
||||
|
||||
# Returns a list of snapshots associated with the volume
|
||||
# @return [Fog::Rackspace::BlockStorage::Snapshots]
|
||||
# @raise [Fog::Rackspace::BlockStorage::NotFound] - HTTP 404
|
||||
# @raise [Fog::Rackspace::BlockStorage::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Rackspace::BlockStorage::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Rackspace::BlockStorage::ServiceError]
|
||||
def snapshots
|
||||
service.snapshots.select { |s| s.volume_id == identity }
|
||||
end
|
||||
|
||||
# Creates a snapshot from the current volume
|
||||
# @param [Hash] options
|
||||
# @option options [String] :display_name of snapshot
|
||||
# @option options [String] :display_description of snapshot
|
||||
# @option options [Boolean] :force - If set to true, snapshot will be taken even if volume is still mounted.
|
||||
# @return [Fog::Rackspace::BlockStorage::Snapshot]
|
||||
# @raise [Fog::Rackspace::BlockStorage::NotFound] - HTTP 404
|
||||
# @raise [Fog::Rackspace::BlockStorage::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Rackspace::BlockStorage::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Rackspace::BlockStorage::ServiceError]
|
||||
# @note All writes to the volume should be flushed before creating the snapshot, either by un-mounting any file systems on the volume or by detaching the volume.
|
||||
# @see http://docs.rackspace.com/cbs/api/v1.0/cbs-devguide/content/POST_createSnapshot__v1__tenant_id__snapshots.html
|
||||
def create_snapshot(options={})
|
||||
requires :identity
|
||||
service.snapshots.create(options.merge(:volume_id => identity))
|
||||
end
|
||||
|
||||
# Creates volume
|
||||
# @raise [Fog::Rackspace::BlockStorage::IdentifierTaken] if the volume has been previously saved.
|
||||
# @return [Boolean] returns true if volume was successfully created
|
||||
# @raise [Fog::Rackspace::BlockStorage::NotFound] - HTTP 404
|
||||
# @raise [Fog::Rackspace::BlockStorage::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Rackspace::BlockStorage::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Rackspace::BlockStorage::ServiceError]
|
||||
# @note A volume object cannot be updated
|
||||
# @see http://docs.rackspace.com/cbs/api/v1.0/cbs-devguide/content/POST_createVolume__v1__tenant_id__volumes.html
|
||||
def save
|
||||
requires :size
|
||||
raise IdentifierTaken.new('Resaving may cause a duplicate volume to be created') if persisted?
|
||||
data = service.create_volume(size, {
|
||||
:display_name => display_name,
|
||||
:display_description => display_description,
|
||||
:volume_type => volume_type,
|
||||
:availability_zone => availability_zone,
|
||||
:snapshot_id => attributes[:snapshot_id],
|
||||
:image_id => attributes[:image_id]
|
||||
})
|
||||
merge_attributes(data.body['volume'])
|
||||
true
|
||||
end
|
||||
|
||||
# Destroys Volume
|
||||
# @return [Boolean] returns true if volume was deleted
|
||||
# @raise [Fog::Rackspace::BlockStorage::NotFound] - HTTP 404
|
||||
# @raise [Fog::Rackspace::BlockStorage::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Rackspace::BlockStorage::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Rackspace::BlockStorage::ServiceError]
|
||||
# @note You cannot delete a volume until all of its dependent snaphosts have been deleted.
|
||||
# @see http://docs.rackspace.com/cbs/api/v1.0/cbs-devguide/content/DELETE_deleteVolume__v1__tenant_id__volumes.html
|
||||
def destroy
|
||||
requires :identity
|
||||
service.delete_volume(identity)
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
19
lib/fog/rackspace/models/block_storage/volume_type.rb
Normal file
19
lib/fog/rackspace/models/block_storage/volume_type.rb
Normal file
|
@ -0,0 +1,19 @@
|
|||
require 'fog/core/model'
|
||||
|
||||
module Fog
|
||||
module Rackspace
|
||||
class BlockStorage
|
||||
class VolumeType < Fog::Model
|
||||
# @!attribute [r] id
|
||||
# @return [String] The volume type id
|
||||
identity :id
|
||||
|
||||
# @!attribute [r] name
|
||||
# @return [String] The name of the volume type
|
||||
attribute :name
|
||||
|
||||
attribute :extra_specs
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
39
lib/fog/rackspace/models/block_storage/volume_types.rb
Normal file
39
lib/fog/rackspace/models/block_storage/volume_types.rb
Normal file
|
@ -0,0 +1,39 @@
|
|||
require 'fog/core/collection'
|
||||
require 'fog/rackspace/models/block_storage/volume_type'
|
||||
|
||||
module Fog
|
||||
module Rackspace
|
||||
class BlockStorage
|
||||
class VolumeTypes < Fog::Collection
|
||||
model Fog::Rackspace::BlockStorage::VolumeType
|
||||
|
||||
# Returns list of volume types
|
||||
# @return [Fog::Rackspace::BlockStorage::VolumeTypes] Retrieves a list volume types.
|
||||
# @raise [Fog::Rackspace::BlockStorage::NotFound] - HTTP 404
|
||||
# @raise [Fog::Rackspace::BlockStorage::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Rackspace::BlockStorage::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Rackspace::BlockStorage::ServiceError]
|
||||
# @see http://docs.rackspace.com/cbs/api/v1.0/cbs-devguide/content/GET_getVolumeTypes__v1__tenant_id__types.html
|
||||
def all
|
||||
data = service.list_volume_types.body['volume_types']
|
||||
load(data)
|
||||
end
|
||||
|
||||
# Retrieves volume type
|
||||
# @param [String] volume_type_id for volume_type to be returned
|
||||
# @return [Fog::Rackspace::BlockStorage::VolumeType]
|
||||
# @raise [Fog::Rackspace::BlockStorage::NotFound] - HTTP 404
|
||||
# @raise [Fog::Rackspace::BlockStorage::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Rackspace::BlockStorage::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Rackspace::BlockStorage::ServiceError]
|
||||
# @see http://docs.rackspace.com/cbs/api/v1.0/cbs-devguide/content/GET_getVolumeType__v1__tenant_id__types.html
|
||||
def get(volume_type_id)
|
||||
data = service.get_volume_type(volume_type_id).body['volume_type']
|
||||
new(data)
|
||||
rescue Fog::Rackspace::BlockStorage::NotFound
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
39
lib/fog/rackspace/models/block_storage/volumes.rb
Normal file
39
lib/fog/rackspace/models/block_storage/volumes.rb
Normal file
|
@ -0,0 +1,39 @@
|
|||
require 'fog/core/collection'
|
||||
require 'fog/rackspace/models/block_storage/volume'
|
||||
|
||||
module Fog
|
||||
module Rackspace
|
||||
class BlockStorage
|
||||
class Volumes < Fog::Collection
|
||||
model Fog::Rackspace::BlockStorage::Volume
|
||||
|
||||
# Returns list of volumes
|
||||
# @return [Fog::Rackspace::BlockStorage::Volumes] Retrieves a volumes
|
||||
# @raise [Fog::Rackspace::BlockStorage::NotFound] - HTTP 404
|
||||
# @raise [Fog::Rackspace::BlockStorage::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Rackspace::BlockStorage::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Rackspace::BlockStorage::ServiceError]
|
||||
# @see http://docs.rackspace.com/cbs/api/v1.0/cbs-devguide/content/GET_getVolumesSimple__v1__tenant_id__volumes.html
|
||||
def all
|
||||
data = service.list_volumes.body['volumes']
|
||||
load(data)
|
||||
end
|
||||
|
||||
# Retrieves volume
|
||||
# @param [String] volume_id for snapshot to be returned
|
||||
# @return [Fog::Rackspace::BlockStorage::Volume]
|
||||
# @raise [Fog::Rackspace::BlockStorage::NotFound] - HTTP 404
|
||||
# @raise [Fog::Rackspace::BlockStorage::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Rackspace::BlockStorage::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Rackspace::BlockStorage::ServiceError]
|
||||
# @see http://docs.rackspace.com/cbs/api/v1.0/cbs-devguide/content/GET_getVolume__v1__tenant_id__volumes.html
|
||||
def get(volume_id)
|
||||
data = service.get_volume(volume_id).body['volume']
|
||||
new(data)
|
||||
rescue Fog::Rackspace::BlockStorage::NotFound
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
42
lib/fog/rackspace/models/compute/flavor.rb
Normal file
42
lib/fog/rackspace/models/compute/flavor.rb
Normal file
|
@ -0,0 +1,42 @@
|
|||
require 'fog/core/model'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class Rackspace
|
||||
class Flavor < Fog::Model
|
||||
identity :id
|
||||
|
||||
attribute :disk
|
||||
attribute :name
|
||||
attribute :ram
|
||||
|
||||
def bits
|
||||
64
|
||||
end
|
||||
|
||||
def cores
|
||||
# Each server is assigned 4 virtual cores and
|
||||
# given a percentage of CPU cycles based on size
|
||||
4 * 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
|
||||
when 30720
|
||||
2
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
24
lib/fog/rackspace/models/compute/flavors.rb
Normal file
24
lib/fog/rackspace/models/compute/flavors.rb
Normal file
|
@ -0,0 +1,24 @@
|
|||
require 'fog/core/collection'
|
||||
require 'fog/rackspace/models/compute/flavor'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class Rackspace
|
||||
class Flavors < Fog::Collection
|
||||
model Fog::Compute::Rackspace::Flavor
|
||||
|
||||
def all
|
||||
data = service.list_flavors_detail.body['flavors']
|
||||
load(data)
|
||||
end
|
||||
|
||||
def get(flavor_id)
|
||||
data = service.get_flavor_details(flavor_id).body['flavor']
|
||||
new(data)
|
||||
rescue Fog::Compute::Rackspace::NotFound
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
44
lib/fog/rackspace/models/compute/image.rb
Normal file
44
lib/fog/rackspace/models/compute/image.rb
Normal file
|
@ -0,0 +1,44 @@
|
|||
require 'fog/core/model'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class Rackspace
|
||||
class Image < Fog::Model
|
||||
identity :id
|
||||
|
||||
attribute :name
|
||||
attribute :created_at, :aliases => 'created'
|
||||
attribute :updated_at, :aliases => 'updated'
|
||||
attribute :progress
|
||||
attribute :status
|
||||
attribute :server_id, :aliases => 'serverId'
|
||||
|
||||
def server=(new_server)
|
||||
requires :id
|
||||
|
||||
self.server_id = new_server.id
|
||||
end
|
||||
|
||||
def destroy
|
||||
requires :id
|
||||
|
||||
service.delete_image(id)
|
||||
true
|
||||
end
|
||||
|
||||
def ready?
|
||||
status == 'ACTIVE'
|
||||
end
|
||||
|
||||
def save
|
||||
raise Fog::Errors::Error.new('Resaving an existing object may create a duplicate') if persisted?
|
||||
requires :server_id
|
||||
|
||||
data = service.create_image(server_id, 'name' => name)
|
||||
merge_attributes(data.body['image'])
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
31
lib/fog/rackspace/models/compute/images.rb
Normal file
31
lib/fog/rackspace/models/compute/images.rb
Normal file
|
@ -0,0 +1,31 @@
|
|||
require 'fog/core/collection'
|
||||
require 'fog/rackspace/models/compute/image'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class Rackspace
|
||||
class Images < Fog::Collection
|
||||
model Fog::Compute::Rackspace::Image
|
||||
|
||||
attribute :server
|
||||
|
||||
def all
|
||||
data = service.list_images_detail.body['images']
|
||||
models = load(data)
|
||||
if server
|
||||
self.replace(self.select {|image| image.server_id == server.id})
|
||||
else
|
||||
models
|
||||
end
|
||||
end
|
||||
|
||||
def get(image_id)
|
||||
data = service.get_image_details(image_id).body['image']
|
||||
new(data)
|
||||
rescue Fog::Compute::Rackspace::NotFound
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
102
lib/fog/rackspace/models/compute/server.rb
Normal file
102
lib/fog/rackspace/models/compute/server.rb
Normal file
|
@ -0,0 +1,102 @@
|
|||
require 'fog/compute/models/server'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class Rackspace
|
||||
class Server < Fog::Compute::Server
|
||||
identity :id
|
||||
|
||||
attribute :addresses
|
||||
attribute :flavor_id, :aliases => 'flavorId', :type => :integer
|
||||
attribute :host_id, :aliases => 'hostId'
|
||||
attribute :image_id, :aliases => 'imageId', :type => :integer
|
||||
attribute :metadata
|
||||
attribute :name
|
||||
attribute :personality
|
||||
attribute :progress
|
||||
attribute :state, :aliases => 'status'
|
||||
|
||||
attr_reader :password
|
||||
|
||||
def initialize(attributes={})
|
||||
self.flavor_id ||= 1 # 256 server
|
||||
self.image_id ||= 49 # Ubuntu 10.04 LTS 64bit
|
||||
super
|
||||
end
|
||||
|
||||
def destroy
|
||||
requires :id
|
||||
service.delete_server(id)
|
||||
true
|
||||
end
|
||||
|
||||
def flavor
|
||||
requires :flavor_id
|
||||
service.flavors.get(flavor_id)
|
||||
end
|
||||
|
||||
def image
|
||||
requires :image_id
|
||||
service.images.get(image_id)
|
||||
end
|
||||
|
||||
def images
|
||||
requires :id
|
||||
service.images(:server => self)
|
||||
end
|
||||
|
||||
def private_ip_address
|
||||
addresses['private'].first
|
||||
end
|
||||
|
||||
def public_ip_address
|
||||
addresses['public'].first
|
||||
end
|
||||
|
||||
def ready?
|
||||
self.state == 'ACTIVE'
|
||||
end
|
||||
|
||||
def reboot(type = 'SOFT')
|
||||
requires :id
|
||||
service.reboot_server(id, type)
|
||||
true
|
||||
end
|
||||
|
||||
def save(options = {})
|
||||
raise Fog::Errors::Error.new('Resaving an existing object may create a duplicate') if persisted?
|
||||
requires :flavor_id, :image_id
|
||||
options = {
|
||||
'metadata' => metadata,
|
||||
'name' => name,
|
||||
'personality' => personality
|
||||
}
|
||||
options = options.reject {|key, value| value.nil?}
|
||||
data = service.create_server(flavor_id, image_id, options)
|
||||
merge_attributes(data.body['server'])
|
||||
true
|
||||
end
|
||||
|
||||
def setup(credentials = {})
|
||||
requires :ssh_ip_address, :identity, :public_key, :username
|
||||
Fog::SSH.new(ssh_ip_address, username, credentials).run([
|
||||
%{mkdir .ssh},
|
||||
%{echo "#{public_key}" >> ~/.ssh/authorized_keys},
|
||||
%{passwd -l #{username}},
|
||||
%{echo "#{Fog::JSON.encode(attributes)}" >> ~/attributes.json},
|
||||
%{echo "#{Fog::JSON.encode(metadata)}" >> ~/metadata.json}
|
||||
])
|
||||
rescue Errno::ECONNREFUSED
|
||||
sleep(1)
|
||||
retry
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def adminPass=(new_admin_pass)
|
||||
@password = new_admin_pass
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
32
lib/fog/rackspace/models/compute/servers.rb
Normal file
32
lib/fog/rackspace/models/compute/servers.rb
Normal file
|
@ -0,0 +1,32 @@
|
|||
require 'fog/core/collection'
|
||||
require 'fog/rackspace/models/compute/server'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class Rackspace
|
||||
class Servers < Fog::Collection
|
||||
model Fog::Compute::Rackspace::Server
|
||||
|
||||
def all
|
||||
data = service.list_servers_detail.body['servers']
|
||||
load(data)
|
||||
end
|
||||
|
||||
def bootstrap(new_attributes = {})
|
||||
server = create(new_attributes)
|
||||
server.wait_for { ready? }
|
||||
server.setup(:password => server.password)
|
||||
server
|
||||
end
|
||||
|
||||
def get(server_id)
|
||||
if server = service.get_server_details(server_id).body['server']
|
||||
new(server)
|
||||
end
|
||||
rescue Fog::Compute::Rackspace::NotFound
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
61
lib/fog/rackspace/models/compute_v2/attachment.rb
Normal file
61
lib/fog/rackspace/models/compute_v2/attachment.rb
Normal file
|
@ -0,0 +1,61 @@
|
|||
require 'fog/core/model'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class RackspaceV2
|
||||
class Attachment < Fog::Model
|
||||
# @!attribute [r] server_id
|
||||
# @return [String] The server id
|
||||
attribute :server_id, :aliases => 'serverId'
|
||||
|
||||
# @!attribute [r] volume_id
|
||||
# @return [String] The volume id
|
||||
attribute :volume_id, :aliases => 'volumeId'
|
||||
|
||||
# @!attribute [r] device
|
||||
# @return [String]device name of the device /dev/xvd[a-p]
|
||||
attribute :device
|
||||
|
||||
def initialize(new_attributes = {})
|
||||
super(new_attributes)
|
||||
server_id = server.id if server #server id should come from collection
|
||||
self
|
||||
end
|
||||
|
||||
# Attaches volume to volume to server.
|
||||
# Requires :server_id, :volume_id, and device to be populated
|
||||
# @return [Boolean] true if volume is attaching
|
||||
# @raise [Fog::Compute::RackspaceV2::NotFound] - HTTP 404
|
||||
# @raise [Fog::Compute::RackspaceV2::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Compute::RackspaceV2::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Compute::RackspaceV2::ServiceError]
|
||||
# @see http://docs.rackspace.com/servers/api/v2/cs-devguide/content/Attach_Volume_to_Server.html
|
||||
def save
|
||||
requires :server_id, :volume_id, :device
|
||||
data = service.attach_volume(server_id, volume_id, device)
|
||||
merge_attributes(data.body['volumeAttachment'])
|
||||
true
|
||||
end
|
||||
|
||||
# Detaches volume from server
|
||||
# @return [Boolean] true if volume is detaching
|
||||
# @raise [Fog::Compute::RackspaceV2::NotFound] - HTTP 404
|
||||
# @raise [Fog::Compute::RackspaceV2::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Compute::RackspaceV2::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Compute::RackspaceV2::ServiceError]
|
||||
# @see http://docs.rackspace.com/servers/api/v2/cs-devguide/content/Delete_Volume_Attachment.html
|
||||
def destroy
|
||||
requires :server_id, :volume_id
|
||||
service.delete_attachment(server_id, volume_id)
|
||||
true
|
||||
end
|
||||
alias_method :detach, :destroy
|
||||
|
||||
private
|
||||
def server
|
||||
collection.server
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
38
lib/fog/rackspace/models/compute_v2/attachments.rb
Normal file
38
lib/fog/rackspace/models/compute_v2/attachments.rb
Normal file
|
@ -0,0 +1,38 @@
|
|||
require 'fog/core/collection'
|
||||
require 'fog/rackspace/models/compute_v2/attachment'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class RackspaceV2
|
||||
class Attachments < Fog::Collection
|
||||
model Fog::Compute::RackspaceV2::Attachment
|
||||
|
||||
attr_accessor :server
|
||||
|
||||
# Retrieves attachments belonging to server
|
||||
# @return [Fog::Compute::RackspaceV2::Attachments] list of attachments
|
||||
# @raise [Fog::Compute::RackspaceV2::NotFound] - HTTP 404
|
||||
# @raise [Fog::Compute::RackspaceV2::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Compute::RackspaceV2::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Compute::RackspaceV2::ServiceError]
|
||||
# @see Server#attachments
|
||||
def all
|
||||
data = service.list_attachments(server.id).body['volumeAttachments']
|
||||
load(data)
|
||||
end
|
||||
|
||||
# Retrieves attachment belonging to server
|
||||
# @param [String] volume_id
|
||||
# @return [Fog::Compute::RackspaceV2::Attachment] attachment for volume id
|
||||
# @raise [Fog::Compute::RackspaceV2::NotFound] - HTTP 404
|
||||
# @raise [Fog::Compute::RackspaceV2::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Compute::RackspaceV2::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Compute::RackspaceV2::ServiceError]
|
||||
def get(volume_id)
|
||||
data = service.get_attachment(server.id, volume_id).body['volumeAttachment']
|
||||
data && new(data)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
33
lib/fog/rackspace/models/compute_v2/flavor.rb
Normal file
33
lib/fog/rackspace/models/compute_v2/flavor.rb
Normal file
|
@ -0,0 +1,33 @@
|
|||
require 'fog/core/model'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class RackspaceV2
|
||||
class Flavor < Fog::Model
|
||||
# @!attribute [r] id
|
||||
# @return [String] The flavor id
|
||||
identity :id
|
||||
|
||||
# @!attribute [r] name
|
||||
# @return [String] flavor name
|
||||
attribute :name
|
||||
|
||||
# @!attribute [r] rame
|
||||
# @return [Fixnum] ram in MB
|
||||
attribute :ram
|
||||
|
||||
# @!attribute [r] disk
|
||||
# @return [String] disk space in GB
|
||||
attribute :disk
|
||||
|
||||
# @!attribute [r] vcpus
|
||||
# @return [Fixnum] number of virtual CPUs
|
||||
attribute :vcpus
|
||||
|
||||
# @!attribute [r] links
|
||||
# @return [Array] flavor links.
|
||||
attribute :links
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
39
lib/fog/rackspace/models/compute_v2/flavors.rb
Normal file
39
lib/fog/rackspace/models/compute_v2/flavors.rb
Normal file
|
@ -0,0 +1,39 @@
|
|||
require 'fog/core/collection'
|
||||
require 'fog/rackspace/models/compute_v2/flavor'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class RackspaceV2
|
||||
class Flavors < Fog::Collection
|
||||
model Fog::Compute::RackspaceV2::Flavor
|
||||
|
||||
# Retrieves information for all available flavors
|
||||
# @return [Fog::Compute::RackspaceV2::Flavors] list of flavors
|
||||
# @raise [Fog::Compute::RackspaceV2::NotFound] - HTTP 404
|
||||
# @raise [Fog::Compute::RackspaceV2::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Compute::RackspaceV2::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Compute::RackspaceV2::ServiceError]
|
||||
# @note Fog's currentl implementation only returns 1000 flavors.
|
||||
def all
|
||||
data = service.list_flavors_detail.body['flavors']
|
||||
load(data)
|
||||
end
|
||||
|
||||
# Retrieve image
|
||||
# @param [String] flavor_id id of flavor
|
||||
# @return [Fog::Compute::RackspaceV2::Flavor] flavor
|
||||
# @raise [Fog::Compute::RackspaceV2::NotFound] - HTTP 404
|
||||
# @raise [Fog::Compute::RackspaceV2::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Compute::RackspaceV2::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Compute::RackspaceV2::ServiceError]
|
||||
# @see http://docs.rackspace.com/servers/api/v2/cs-devguide/content/Get_Flavor_Details-d1e4317.html
|
||||
def get(flavor_id)
|
||||
data = service.get_flavor(flavor_id).body['flavor']
|
||||
new(data)
|
||||
rescue Fog::Compute::RackspaceV2::NotFound
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
117
lib/fog/rackspace/models/compute_v2/image.rb
Normal file
117
lib/fog/rackspace/models/compute_v2/image.rb
Normal file
|
@ -0,0 +1,117 @@
|
|||
require 'fog/core/model'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class RackspaceV2
|
||||
class Image < Fog::Model
|
||||
UNKNOWN = 'UNKNOWN'
|
||||
ACTIVE = 'ACTIVE'
|
||||
SAVING = 'SAVING'
|
||||
ERROR = 'ERROR'
|
||||
DELETED = 'DELETED'
|
||||
|
||||
# @!attribute [r] id
|
||||
# @return [String] The server id
|
||||
identity :id
|
||||
|
||||
# @!attribute [r] name
|
||||
# @return [String] The image name.
|
||||
attribute :name
|
||||
|
||||
# @!attribute [r] created
|
||||
# @return [String] The time stamp for the creation date.
|
||||
attribute :created
|
||||
|
||||
# @!attribute [r] updated
|
||||
# @return [String] The time stamp for the last update.
|
||||
attribute :updated
|
||||
|
||||
# @!attribute [r] state
|
||||
# @return [String] image status.
|
||||
attribute :state, :aliases => 'status'
|
||||
|
||||
# @!attribute [r] user_id
|
||||
# @return [String] The user Id.
|
||||
attribute :user_id
|
||||
|
||||
# @!attribute [r] tenant_id
|
||||
# @return [String] The tenant Id.
|
||||
attribute :tenant_id
|
||||
|
||||
# @!attribute [r] progress
|
||||
# @return [Fixnum] The build completion progress, as a percentage. Value is from 0 to 100.
|
||||
attribute :progress
|
||||
|
||||
attribute :minDisk
|
||||
attribute :minRam
|
||||
|
||||
# @!attribute [rw] disk_config
|
||||
# @return [String<AUTO, MANUAL>] The disk configuration value.
|
||||
# @see http://docs.rackspace.com/servers/api/v2/cs-devguide/content/ch_extensions.html#diskconfig_attribute
|
||||
#
|
||||
# The disk configuration value.
|
||||
# * AUTO - The server is built with a single partition the size of the target flavor disk. The file system is automatically adjusted to fit the entire partition.
|
||||
# This keeps things simple and automated. AUTO is valid only for images and servers with a single partition that use the EXT3 file system.
|
||||
# This is the default setting for applicable Rackspace base images.
|
||||
#
|
||||
# * MANUAL - The server is built using whatever partition scheme and file system is in the source image. If the target flavor disk is larger,
|
||||
# the remaining disk space is left unpartitioned. This enables images to have non-EXT3 file systems, multiple partitions,
|
||||
# and so on, and enables you to manage the disk configuration.
|
||||
attribute :disk_config, :aliases => 'OS-DCF:diskConfig'
|
||||
|
||||
# @!attribute [r] links
|
||||
# @return [Array] image links.
|
||||
attribute :links
|
||||
|
||||
def initialize(attributes={})
|
||||
@service = attributes[:service]
|
||||
super
|
||||
end
|
||||
|
||||
# Image metadata
|
||||
# @return [Fog::Compute::RackspaceV2::Metadata] Collection of Fog::Compute::RackspaceV2::Metadatum objects containing metadata key value pairs.
|
||||
def metadata
|
||||
@metadata ||= begin
|
||||
Fog::Compute::RackspaceV2::Metadata.new({
|
||||
:service => service,
|
||||
:parent => self
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
# Set server metadata
|
||||
# @param [Hash] hash contains key value pairs
|
||||
def metadata=(hash={})
|
||||
metadata.from_hash(hash)
|
||||
end
|
||||
|
||||
# Is image is in ready state
|
||||
# @param [String] ready_state By default state is ACTIVE
|
||||
# @param [Array,String] error_states By default state is ERROR
|
||||
# @return [Boolean] returns true if server is in a ready state
|
||||
# @raise [Fog::Compute::RackspaceV2::NotFound] - HTTP 404
|
||||
# @raise [Fog::Compute::RackspaceV2::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Compute::RackspaceV2::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Compute::RackspaceV2::ServiceError]
|
||||
# @raise [Fog::Compute::RackspaceV2::InvalidImageStateException] if server state is an error state
|
||||
def ready?(ready_state = ACTIVE, error_states=[ERROR])
|
||||
if error_states
|
||||
error_states = Array(error_states)
|
||||
raise InvalidImageStateException.new(ready_state, state) if error_states.include?(state)
|
||||
end
|
||||
state == ready_state
|
||||
end
|
||||
|
||||
# Destroy image
|
||||
# @raise [Fog::Compute::RackspaceV2::NotFound] - HTTP 404
|
||||
# @raise [Fog::Compute::RackspaceV2::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Compute::RackspaceV2::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Compute::RackspaceV2::ServiceError]
|
||||
def destroy
|
||||
requires :identity
|
||||
service.delete_image(identity)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
73
lib/fog/rackspace/models/compute_v2/images.rb
Normal file
73
lib/fog/rackspace/models/compute_v2/images.rb
Normal file
|
@ -0,0 +1,73 @@
|
|||
require 'fog/core/collection'
|
||||
require 'fog/rackspace/models/compute_v2/image'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class RackspaceV2
|
||||
class Images < Fog::Collection
|
||||
# @!attribute [rw] name
|
||||
# @return [String] Given a string value x, filters the list of images by image name.
|
||||
attribute :name
|
||||
|
||||
# @!attribute [rw] status
|
||||
# @return [String] Given a string value x, filters the list of images by status.
|
||||
# @note Possible values are ACTIVE, DELETED, ERROR, SAVING, and UNKNOWN.
|
||||
attribute :status
|
||||
|
||||
# @!attribute [rw] marker
|
||||
# @return [String] Given a string value x, return object names greater in value than the specified marker.
|
||||
# @see http://docs.rackspace.com/files/api/v1/cf-devguide/content/List_Large_Number_of_Objects-d1e1521.html
|
||||
attribute :marker
|
||||
|
||||
# @!attribute [rw] limit
|
||||
# @return [Integer] For an integer value n, limits the number of results to at most n values.
|
||||
# @see http://docs.rackspace.com/files/api/v1/cf-devguide/content/List_Large_Number_of_Objects-d1e1521.html
|
||||
attribute :limit
|
||||
|
||||
# @!attribute [rw] type
|
||||
# @return [String] Given a string value x, filters the list of images by type.
|
||||
# @note Valid values are BASE and SNAPSHOT
|
||||
attribute :type
|
||||
|
||||
model Fog::Compute::RackspaceV2::Image
|
||||
|
||||
# Returns list of images
|
||||
# @return [Fog::Compute::RackspaceV2::Images] Retrieves a list images.
|
||||
# @raise [Fog::Compute::RackspaceV2::NotFound] - HTTP 404
|
||||
# @raise [Fog::Compute::RackspaceV2::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Compute::RackspaceV2::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Compute::RackspaceV2::ServiceError]
|
||||
# @note Fog's current implementation only returns 1000 images.
|
||||
# @see http://docs.rackspace.com/servers/api/v2/cs-devguide/content/List_Images-d1e4435.html
|
||||
def all(options = {})
|
||||
options = {
|
||||
'name' => name,
|
||||
'status' => status,
|
||||
'marker' => marker,
|
||||
'limit' => limit,
|
||||
'type' => type
|
||||
}.merge!(options)
|
||||
merge_attributes(options)
|
||||
|
||||
data = service.list_images_detail(options).body['images']
|
||||
load(data)
|
||||
end
|
||||
|
||||
# Retrieve image
|
||||
# @param [String] image_id id of image
|
||||
# @return [Fog::Compute::RackspaceV2:Image] image
|
||||
# @raise [Fog::Compute::RackspaceV2::NotFound] - HTTP 404
|
||||
# @raise [Fog::Compute::RackspaceV2::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Compute::RackspaceV2::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Compute::RackspaceV2::ServiceError]
|
||||
# @see http://docs.rackspace.com/servers/api/v2/cs-devguide/content/Get_Image_Details-d1e4848.html
|
||||
def get(image_id)
|
||||
data = service.get_image(image_id).body['image']
|
||||
new(data)
|
||||
rescue Fog::Compute::RackspaceV2::NotFound
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
54
lib/fog/rackspace/models/compute_v2/key_pair.rb
Normal file
54
lib/fog/rackspace/models/compute_v2/key_pair.rb
Normal file
|
@ -0,0 +1,54 @@
|
|||
require 'fog/core/model'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class RackspaceV2
|
||||
class KeyPair < Fog::Model
|
||||
# @!attribute [rw] name
|
||||
# @return [String] the keypair name
|
||||
identity :name
|
||||
|
||||
# @!attribute [r] public_key
|
||||
# @return [String] the public key
|
||||
attribute :public_key
|
||||
|
||||
# @!attribute [r] private_key
|
||||
# @return [String] the private key
|
||||
attribute :private_key
|
||||
|
||||
# @!attribute [r] user_id
|
||||
# @return [String] the user_id associated to
|
||||
attribute :user_id
|
||||
|
||||
# @!attribute [r] fingerprint
|
||||
# @return [String] unique fingerprint
|
||||
attribute :fingerprint
|
||||
|
||||
# Creates a keypair
|
||||
# @return [Boolean] true if the keypair is successfully created
|
||||
# @raise [Fog::Compute::RackspaceV2::NotFound]
|
||||
# @raise [Fog::Compute::RackspaceV2::BadRequest]
|
||||
# @raise [Fog::Compute::RackspaceV2::InternalServerError]
|
||||
# @raise [Fog::Compute::RackspaceV2::ServiceError]
|
||||
def save
|
||||
requires :name
|
||||
data = service.create_keypair(name, attributes)
|
||||
merge_attributes(data.body['keypair'])
|
||||
data.body['keypair']['name'] == name
|
||||
end
|
||||
|
||||
# Destroys a keypair
|
||||
# @return [Boolean] true if the keypair is successfully deleted
|
||||
# @raise [Fog::Compute::RackspaceV2::NotFound]
|
||||
# @raise [Fog::Compute::RackspaceV2::BadRequest]
|
||||
# @raise [Fog::Compute::RackspaceV2::InternalServerError]
|
||||
# @raise [Fog::Compute::RackspaceV2::ServiceError]
|
||||
def destroy
|
||||
requires :identity
|
||||
service.delete_keypair(identity)
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
40
lib/fog/rackspace/models/compute_v2/key_pairs.rb
Normal file
40
lib/fog/rackspace/models/compute_v2/key_pairs.rb
Normal file
|
@ -0,0 +1,40 @@
|
|||
require 'fog/core/collection'
|
||||
require 'fog/rackspace/models/compute_v2/key_pair'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class RackspaceV2
|
||||
class KeyPairs < Fog::Collection
|
||||
model Fog::Compute::RackspaceV2::KeyPair
|
||||
|
||||
# Fetch the list of known keypairs
|
||||
# @return [Fog::Compute::RackspaceV2::Keypairs] the retreived keypairs
|
||||
# @raise [Fog::Compute::RackspaceV2::NotFound]
|
||||
# @raise [Fog::Compute::RackspaceV2::BadRequest]
|
||||
# @raise [Fog::Compute::RackspaceV2::InternalServerError]
|
||||
# @raise [Fog::Compute::RackspaceV2::ServiceError]
|
||||
def all
|
||||
data = []
|
||||
service.list_keypairs.body['keypairs'].each do |kp|
|
||||
data << kp['keypair'] if kp['keypair']
|
||||
end
|
||||
load(data)
|
||||
end
|
||||
|
||||
# Fetch keypair details
|
||||
# @param [String] key_name name of the key to request
|
||||
# @return [Fog::Compute::RackspaceV2::Keypair] the requested keypair or 'nil' when not found
|
||||
# @raise [Fog::Compute::RackspaceV2::BadRequest]
|
||||
# @raise [Fog::Compute::RackspaceV2::InternalServerError]
|
||||
# @raise [Fog::Compute::RackspaceV2::ServiceError]
|
||||
def get(key_name)
|
||||
begin
|
||||
new(service.get_keypair(key_name).body['keypair'])
|
||||
rescue Fog::Compute::RackspaceV2::NotFound
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
40
lib/fog/rackspace/models/compute_v2/meta_parent.rb
Normal file
40
lib/fog/rackspace/models/compute_v2/meta_parent.rb
Normal file
|
@ -0,0 +1,40 @@
|
|||
module Fog
|
||||
module Compute
|
||||
class RackspaceV2
|
||||
module MetaParent
|
||||
# Parent of metadata
|
||||
# @return [#parent] parent of metadata
|
||||
def parent
|
||||
@parent
|
||||
end
|
||||
|
||||
# Sets parent of metadata
|
||||
# @param [#parent] new_parent of metadata
|
||||
def parent=(new_parent)
|
||||
@parent = new_parent
|
||||
end
|
||||
|
||||
# Collection type for parent
|
||||
# @return [String] collection type
|
||||
# @raise [RuntimeError] raises excpetion if collection type for parent is unknown
|
||||
def collection_name
|
||||
if parent.class == Fog::Compute::RackspaceV2::Image
|
||||
return "images"
|
||||
elsif parent.class == Fog::Compute::RackspaceV2::Server
|
||||
return "servers"
|
||||
else
|
||||
raise "Metadata is not supported for this model type."
|
||||
end
|
||||
end
|
||||
|
||||
# Converts metadata to hash
|
||||
# @return [Hash] hash containing key value pairs for metadata
|
||||
def metas_to_hash(metas)
|
||||
hash = {}
|
||||
metas.each { |meta| hash[meta.key] = meta.value }
|
||||
hash
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
108
lib/fog/rackspace/models/compute_v2/metadata.rb
Normal file
108
lib/fog/rackspace/models/compute_v2/metadata.rb
Normal file
|
@ -0,0 +1,108 @@
|
|||
require 'fog/core/collection'
|
||||
require 'fog/rackspace/models/compute_v2/meta_parent'
|
||||
require 'fog/rackspace/models/compute_v2/metadatum'
|
||||
require 'fog/rackspace/models/compute_v2/image'
|
||||
require 'fog/rackspace/models/compute_v2/server'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class RackspaceV2
|
||||
class Metadata < Fog::Collection
|
||||
model Fog::Compute::RackspaceV2::Metadatum
|
||||
|
||||
include Fog::Compute::RackspaceV2::MetaParent
|
||||
|
||||
# Retrieves all of the metadata from server
|
||||
# @return [Fog::Compute::RackspaceV2::Metadatum] list of metadatum
|
||||
# @raise [Fog::Compute::RackspaceV2::NotFound] - HTTP 404
|
||||
# @raise [Fog::Compute::RackspaceV2::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Compute::RackspaceV2::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Compute::RackspaceV2::ServiceError]
|
||||
def all
|
||||
requires :parent
|
||||
return unless parent.identity
|
||||
data = service.list_metadata(collection_name, parent.id).body['metadata']
|
||||
from_hash(data)
|
||||
end
|
||||
|
||||
# Retrieves specific metadata from server
|
||||
# @param [String] key for metadatum
|
||||
# @return [Fog::Compute::RackspaceV2::Metadatum] metadatum
|
||||
# @raise [Fog::Compute::RackspaceV2::NotFound] - HTTP 404
|
||||
# @raise [Fog::Compute::RackspaceV2::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Compute::RackspaceV2::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Compute::RackspaceV2::ServiceError]
|
||||
def get(key)
|
||||
requires :parent
|
||||
data = service.get_metadata_item(collection_name, parent.id, key).body["meta"]
|
||||
datum = data.first
|
||||
new(:key => datum[0], :value => datum[1])
|
||||
rescue Fog::Compute::RackspaceV2::NotFound
|
||||
nil
|
||||
end
|
||||
|
||||
# Retrieve specific value for key from Metadata.
|
||||
# * If key is of type String, this method will return the value of the metadatum
|
||||
# * If key is of type Fixnum, this method will return a Fog::Compute::RackspaceV2::Metadatum object (legacy)
|
||||
# @param [#key] key
|
||||
# @return [#value]
|
||||
def [](key)
|
||||
return super(key) if key.is_a?(Integer)
|
||||
return nil unless key
|
||||
datum = self.find {|datum| datum.key == key || datum.key == key.to_sym }
|
||||
datum ? datum.value : nil
|
||||
end
|
||||
|
||||
# Set value for key.
|
||||
# * If key is of type String, this method will set/add the value to Metadata
|
||||
# * If key is of type Fixnum, this method will set a Fog::Compute::RackspaceV2::Metadatum object (legacy)
|
||||
# @param [#key] key
|
||||
# @return [String]
|
||||
def []=(key, value)
|
||||
return super(key,value) if key.is_a?(Integer)
|
||||
return nil unless key
|
||||
datum = self.find {|datum| datum.key == key || datum.key == key.to_sym }
|
||||
if datum
|
||||
datum.value = value
|
||||
else
|
||||
self << Fog::Compute::RackspaceV2::Metadatum.new(:key => key, :value => value, :service => service, :parent => parent)
|
||||
end
|
||||
value
|
||||
end
|
||||
|
||||
# Saves the current metadata on server
|
||||
# @raise [Fog::Compute::RackspaceV2::NotFound] - HTTP 404
|
||||
# @raise [Fog::Compute::RackspaceV2::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Compute::RackspaceV2::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Compute::RackspaceV2::ServiceError]
|
||||
def save
|
||||
requires :parent
|
||||
service.set_metadata(collection_name, parent.id, to_hash)
|
||||
end
|
||||
|
||||
# Creates new metadata
|
||||
def new(attributes = {})
|
||||
super({ :parent => parent }.merge!(attributes))
|
||||
end
|
||||
|
||||
# Resets metadata using data from hash
|
||||
# @param hash hash containing key value pairs used to populate metadata.
|
||||
# @note This will remove existing data
|
||||
def from_hash(hash)
|
||||
return unless hash
|
||||
metas = []
|
||||
hash.each_pair {|k,v| metas << {:key => k, :value => v} }
|
||||
load(metas)
|
||||
end
|
||||
|
||||
# Converts metadata object to hash
|
||||
# @return [Hash] hash of metadata key value pairs
|
||||
def to_hash
|
||||
h = {}
|
||||
self.each { |datum| h[datum.key] = datum.value }
|
||||
h
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
39
lib/fog/rackspace/models/compute_v2/metadatum.rb
Normal file
39
lib/fog/rackspace/models/compute_v2/metadatum.rb
Normal file
|
@ -0,0 +1,39 @@
|
|||
require 'fog/core/model'
|
||||
require 'fog/rackspace/models/compute_v2/meta_parent'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class RackspaceV2
|
||||
class Metadatum < Fog::Model
|
||||
include Fog::Compute::RackspaceV2::MetaParent
|
||||
|
||||
identity :key
|
||||
attribute :value
|
||||
|
||||
# Remove metadatum from server
|
||||
# @return [Boolean] return true if metadatum is deleting
|
||||
# @raise [Fog::Compute::RackspaceV2::NotFound] - HTTP 404
|
||||
# @raise [Fog::Compute::RackspaceV2::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Compute::RackspaceV2::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Compute::RackspaceV2::ServiceError]
|
||||
def destroy
|
||||
requires :identity
|
||||
service.delete_metadata_item(collection_name, parent.id, key)
|
||||
true
|
||||
end
|
||||
|
||||
# Save metadatum on server
|
||||
# @return [Boolean] return true if metadatum is saving
|
||||
# @raise [Fog::Compute::RackspaceV2::NotFound] - HTTP 404
|
||||
# @raise [Fog::Compute::RackspaceV2::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Compute::RackspaceV2::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Compute::RackspaceV2::ServiceError]
|
||||
def save
|
||||
requires :identity, :value
|
||||
service.set_metadata_item(collection_name, parent.id, key, value)
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
27
lib/fog/rackspace/models/compute_v2/network.rb
Normal file
27
lib/fog/rackspace/models/compute_v2/network.rb
Normal file
|
@ -0,0 +1,27 @@
|
|||
module Fog
|
||||
module Compute
|
||||
class RackspaceV2
|
||||
class Network < Fog::Model
|
||||
identity :id
|
||||
|
||||
attribute :label
|
||||
attribute :cidr
|
||||
|
||||
def save
|
||||
requires :label, :cidr
|
||||
|
||||
data = service.create_network(label, cidr)
|
||||
merge_attributes(data.body['network'])
|
||||
true
|
||||
end
|
||||
|
||||
def destroy
|
||||
requires :identity
|
||||
|
||||
service.delete_network(identity)
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
23
lib/fog/rackspace/models/compute_v2/networks.rb
Normal file
23
lib/fog/rackspace/models/compute_v2/networks.rb
Normal file
|
@ -0,0 +1,23 @@
|
|||
require 'fog/rackspace/models/compute_v2/network'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class RackspaceV2
|
||||
class Networks < Fog::Collection
|
||||
model Fog::Compute::RackspaceV2::Network
|
||||
|
||||
def all
|
||||
data = service.list_networks.body['networks']
|
||||
load(data)
|
||||
end
|
||||
|
||||
def get(id)
|
||||
data = service.get_network(id).body['network']
|
||||
new(data)
|
||||
rescue Fog::Compute::RackspaceV2::NotFound
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
631
lib/fog/rackspace/models/compute_v2/server.rb
Normal file
631
lib/fog/rackspace/models/compute_v2/server.rb
Normal file
|
@ -0,0 +1,631 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
require 'fog/compute/models/server'
|
||||
require 'fog/rackspace/models/compute_v2/metadata'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class RackspaceV2
|
||||
class Server < Fog::Compute::Server
|
||||
# States
|
||||
ACTIVE = 'ACTIVE'
|
||||
BUILD = 'BUILD'
|
||||
DELETED = 'DELETED'
|
||||
ERROR = 'ERROR'
|
||||
HARD_REBOOT = 'HARD_REBOOT'
|
||||
MIGRATING = 'MIGRATING'
|
||||
PASSWORD = 'PASSWORD'
|
||||
REBOOT = 'REBOOT'
|
||||
REBUILD = 'REBUILD'
|
||||
RESCUE = 'RESCUE'
|
||||
RESIZE = 'RESIZE'
|
||||
REVERT_RESIZE = 'REVERT_RESIZE'
|
||||
SUSPENDED = 'SUSPENDED'
|
||||
UNKNOWN = 'UNKNOWN'
|
||||
VERIFY_RESIZE = 'VERIFY_RESIZE'
|
||||
|
||||
# @!attribute [r] id
|
||||
# @return [String] The server id
|
||||
identity :id
|
||||
|
||||
# @!attribute [rw] name
|
||||
# @return [String] The server name.
|
||||
attribute :name
|
||||
|
||||
# @!attribute [r] created
|
||||
# @return [String] The time stamp for the creation date.
|
||||
attribute :created
|
||||
|
||||
# @!attribute [r] updated
|
||||
# @return [String] The time stamp for the last update.
|
||||
attribute :updated
|
||||
|
||||
# @!attribute [r] host Id
|
||||
# The host Id.
|
||||
# The compute provisioning algorithm has an anti-affinity property that attempts to spread customer VMs across hosts.
|
||||
# Under certain situations, VMs from the same customer might be placed on the same host.
|
||||
# hostId represents the host your server runs on and can be used to determine this scenario if it is relevant to your application.
|
||||
# HostId is unique per account and is not globally unique.
|
||||
# @return [String] host id.
|
||||
attribute :host_id, :aliases => 'hostId'
|
||||
|
||||
# @!attribute [r] state
|
||||
# @return [String] server status.
|
||||
# @see http://docs.rackspace.com/servers/api/v2/cs-devguide/content/List_Servers-d1e2078.html#server_status
|
||||
attribute :state, :aliases => 'status'
|
||||
|
||||
# @!attribute [r] state_ext
|
||||
# @return [String] server (extended) status.
|
||||
# @see http://docs.rackspace.com/servers/api/v2/cs-devguide/content/List_Servers-d1e2078.html#server_status
|
||||
attribute :state_ext, :aliases => 'OS-EXT-STS:task_state'
|
||||
|
||||
# @!attribute [r] progress
|
||||
# @return [Fixnum] The build completion progress, as a percentage. Value is from 0 to 100.
|
||||
attribute :progress
|
||||
|
||||
# @!attribute [r] user_id
|
||||
# @return [String] The user Id.
|
||||
attribute :user_id
|
||||
|
||||
# @!attribute [r] tenant_id
|
||||
# @return [String] The tenant Id.
|
||||
attribute :tenant_id
|
||||
|
||||
# @!attribute [r] links
|
||||
# @return [Array] Server links.
|
||||
attribute :links
|
||||
|
||||
# @!attribute [rw] personality
|
||||
# @note This attribute is only used for server creation. This field will be nil on subsequent retrievals.
|
||||
# @return [Hash] Hash containing data to inject into the file system of the cloud server instance during server creation.
|
||||
# @example To inject fog.txt into file system
|
||||
# :personality => [{ :path => '/root/fog.txt',
|
||||
# :contents => Base64.encode64('Fog was here!')
|
||||
# }]
|
||||
# @see #create
|
||||
# @see http://docs.rackspace.com/servers/api/v2/cs-devguide/content/Server_Personality-d1e2543.html
|
||||
attribute :personality
|
||||
|
||||
# @!attribute [rw] ipv4_address
|
||||
# @return [String] The public IP version 4 access address.
|
||||
# @note This field will populate once the server is ready to use.
|
||||
# @see http://docs.rackspace.com/servers/api/v2/cs-devguide/content/Server_Primary_Addresses-d1e2558.html
|
||||
attribute :ipv4_address, :aliases => 'accessIPv4'
|
||||
|
||||
# @!attribute [rw] ipv6_address
|
||||
# @return [String] The public IP version 6 access address.
|
||||
# @note This field will populate once the server is ready to use.
|
||||
# @see http://docs.rackspace.com/servers/api/v2/cs-devguide/content/Server_Primary_Addresses-d1e2558.html
|
||||
attribute :ipv6_address, :aliases => 'accessIPv6'
|
||||
|
||||
# @!attribute [rw] disk_config
|
||||
# @return [String<AUTO, MANUAL>] The disk configuration value.
|
||||
# @see http://docs.rackspace.com/servers/api/v2/cs-devguide/content/ch_extensions.html#diskconfig_attribute
|
||||
#
|
||||
# The disk configuration value.
|
||||
# * AUTO - The server is built with a single partition the size of the target flavor disk. The file system is automatically adjusted to fit the entire partition.
|
||||
# This keeps things simple and automated. AUTO is valid only for images and servers with a single partition that use the EXT3 file system.
|
||||
# This is the default setting for applicable Rackspace base images.
|
||||
#
|
||||
# * MANUAL - The server is built using whatever partition scheme and file system is in the source image. If the target flavor disk is larger,
|
||||
# the remaining disk space is left unpartitioned. This enables images to have non-EXT3 file systems, multiple partitions,
|
||||
# and so on, and enables you to manage the disk configuration.
|
||||
attribute :disk_config, :aliases => 'OS-DCF:diskConfig'
|
||||
|
||||
# @!attribute [rw] config_drive_ext
|
||||
# @return [Boolean] whether a read-only configuration drive is attached
|
||||
# @see http://docs.rackspace.com/servers/api/v2/cs-devguide/content/config_drive_ext.html
|
||||
attribute :config_drive
|
||||
|
||||
# @!attribute [rw] user_data
|
||||
# @return [Boolean] User-data
|
||||
# @see http://docs.rackspace.com/servers/api/v2/cs-devguide/content/config_drive_ext.html
|
||||
attribute :user_data
|
||||
|
||||
# @!attribute [r] bandwidth
|
||||
# @return [Array] The amount of bandwidth used for the specified audit period.
|
||||
# @see http://docs.rackspace.com/servers/api/v2/cs-devguide/content/ch_extensions.html#bandwidth_extension
|
||||
attribute :bandwidth, :aliases => 'rax-bandwidth:bandwidth'
|
||||
|
||||
# @!attribute [r] address
|
||||
# @return [Hash<String, Array[Hash]>] IP addresses allocated for server by network
|
||||
# @example
|
||||
# {
|
||||
# "public" => [
|
||||
# {"version"=>4, "addr"=>"166.78.105.63"},
|
||||
# {"version"=>6, "addr"=>"2001:4801:7817:0072:0fe1:75e8:ff10:61a9"}
|
||||
# ],
|
||||
# "private"=> [{"version"=>4, "addr"=>"10.177.18.209"}]
|
||||
# }
|
||||
attribute :addresses
|
||||
|
||||
# @!attribute [r] flavor_id
|
||||
# @return [String] The flavor Id.
|
||||
# @see http://docs.rackspace.com/servers/api/v2/cs-devguide/content/List_Flavors-d1e4188.html
|
||||
attribute :flavor_id, :aliases => 'flavor', :squash => 'id'
|
||||
|
||||
# @!attribute [r] image_id
|
||||
# @return [String] The image Id.
|
||||
# @see http://docs.rackspace.com/servers/api/v2/cs-devguide/content/List_Images-d1e4435.html
|
||||
attribute :image_id, :aliases => 'image', :squash => 'id'
|
||||
|
||||
# @!attribute [w] boot_volume_id
|
||||
# @return [String] The ID of a bootable volume from the BlockStorage service.
|
||||
# @see http://developer.openstack.org/api-ref-compute-v2-ext.html#ext-os-block-device-mapping-v2-boot
|
||||
attribute :boot_volume_id
|
||||
|
||||
# @!attribute [w] boot_image_id
|
||||
# @return [String] The ID of an image to create a bootable volume from.
|
||||
# @see http://developer.openstack.org/api-ref-compute-v2-ext.html#ext-os-block-device-mapping-v2-boot
|
||||
attribute :boot_image_id
|
||||
|
||||
# @!attribute [rw] password
|
||||
# @return [String] Password for system adminstrator account.
|
||||
# @see http://docs.rackspace.com/servers/api/v2/cs-devguide/content/Server_Passwords-d1e2510.html
|
||||
# @note Can be set while creating a server, but use change_admin_password instead of save/update for changes.
|
||||
attribute :password
|
||||
|
||||
# @!attribute [rw] key_name
|
||||
# @return [String] The name of the key_pair used for server.
|
||||
# @note The key_pair/key_name is used to specify the keypair used for server creation. It is not populated by cloud servers.
|
||||
attribute :key_name
|
||||
|
||||
def initialize(attributes={})
|
||||
@service = attributes[:service]
|
||||
super
|
||||
end
|
||||
|
||||
alias_method :access_ipv4_address, :ipv4_address
|
||||
alias_method :access_ipv4_address=, :ipv4_address=
|
||||
alias_method :access_ipv6_address, :ipv6_address
|
||||
alias_method :access_ipv6_address=, :ipv6_address=
|
||||
|
||||
# Server metadata
|
||||
# @return [Fog::Compute::RackspaceV2::Metadata] metadata key value pairs.
|
||||
def metadata
|
||||
@metadata ||= begin
|
||||
Fog::Compute::RackspaceV2::Metadata.new({
|
||||
:service => service,
|
||||
:parent => self
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
# Set server metadata
|
||||
# @param [Hash] hash contains key value pairs
|
||||
def metadata=(hash={})
|
||||
metadata.from_hash(hash)
|
||||
end
|
||||
|
||||
# Returns the key pair based on the key_name of the server
|
||||
# @return [KeyPair]
|
||||
# @note The key_pair/key_name is used to specify the keypair used for server creation. It is not populated by cloud servers.
|
||||
def key_pair
|
||||
requires :key_name
|
||||
|
||||
service.key_pairs.get(key_name)
|
||||
end
|
||||
|
||||
# Sets the key_pair used by the server.
|
||||
# @param new_keypair [KeyPair] key_pair object for server
|
||||
# @note The key_pair/key_name is used to specify the keypair used for server creation. It is not populated by cloud servers.
|
||||
def key_pair=(new_keypair)
|
||||
if new_keypair.is_a?(String)
|
||||
Fog::Logger.deprecation("#key_pair= should be used to set KeyPair objects. Please use #key_name method instead")
|
||||
self.key_name = new_keypair
|
||||
else
|
||||
self.key_name = new_keypair && new_keypair.name
|
||||
end
|
||||
end
|
||||
|
||||
# Saves the server.
|
||||
# Creates server if it is new, otherwise it will update server attributes name, accessIPv4, and accessIPv6.
|
||||
# @return [Boolean] true if server has started saving
|
||||
def save(options = {})
|
||||
if persisted?
|
||||
update
|
||||
else
|
||||
create(options)
|
||||
end
|
||||
true
|
||||
end
|
||||
|
||||
# Creates server
|
||||
# * requires attributes: service:, :name, :image_id, and :flavor_id
|
||||
# * optional attributes :disk_config, :metadata, :personality, :config_drive, :boot_volume_id, :boot_image_id
|
||||
# * :image_id should be "" if :boot_volume_id or :boot_image_id are provided.
|
||||
# @return [Boolean] returns true if server is being created
|
||||
# @raise [Fog::Compute::RackspaceV2::NotFound] - HTTP 404
|
||||
# @raise [Fog::Compute::RackspaceV2::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Compute::RackspaceV2::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Compute::RackspaceV2::ServiceError]
|
||||
# @note You should use servers.create to create servers instead calling this method directly
|
||||
# @see Servers#create
|
||||
# @see http://docs.rackspace.com/servers/api/v2/cs-devguide/content/CreateServers.html
|
||||
#
|
||||
# * State Transitions
|
||||
# * BUILD -> ACTIVE
|
||||
# * BUILD -> ERROR (on error)
|
||||
def create(options)
|
||||
requires :name, :image_id, :flavor_id
|
||||
modified_options = Marshal.load(Marshal.dump(options))
|
||||
|
||||
if attributes[:keypair]
|
||||
Fog::Logger.deprecation(":keypair has been depreciated. Please use :key_name instead.")
|
||||
modified_options[:key_name] = attributes[:keypair]
|
||||
end
|
||||
|
||||
modified_options[:password] ||= attributes[:password] unless password.nil?
|
||||
modified_options[:networks] ||= attributes[:networks]
|
||||
modified_options[:disk_config] = disk_config unless disk_config.nil?
|
||||
modified_options[:metadata] = metadata.to_hash unless @metadata.nil?
|
||||
modified_options[:personality] = personality unless personality.nil?
|
||||
modified_options[:config_drive] = config_drive unless config_drive.nil?
|
||||
modified_options[:user_data] = user_data_encoded unless user_data_encoded.nil?
|
||||
modified_options[:key_name] ||= attributes[:key_name]
|
||||
modified_options[:boot_volume_id] ||= attributes[:boot_volume_id]
|
||||
modified_options[:boot_image_id] ||= attributes[:boot_image_id]
|
||||
|
||||
if modified_options[:networks]
|
||||
modified_options[:networks].map! { |id| { :uuid => id } }
|
||||
end
|
||||
|
||||
data = service.create_server(name, image_id, flavor_id, 1, 1, modified_options)
|
||||
merge_attributes(data.body['server'])
|
||||
true
|
||||
end
|
||||
|
||||
# Updates server
|
||||
# This will update :name, :accessIPv4, and :accessIPv6 attributes.
|
||||
# @note If you edit the server name, the server host name does not change. Also, server names are not guaranteed to be unique.
|
||||
# @return true if update has started updating
|
||||
# @raise [Fog::Compute::RackspaceV2::NotFound] - HTTP 404
|
||||
# @raise [Fog::Compute::RackspaceV2::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Compute::RackspaceV2::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Compute::RackspaceV2::ServiceError]
|
||||
# @see http://docs.rackspace.com/servers/api/v2/cs-devguide/content/ServerUpdate.html
|
||||
#
|
||||
# * State Transition
|
||||
# * ACTIVE -> ACTIVE
|
||||
def update
|
||||
requires :identity
|
||||
options = {
|
||||
'name' => name,
|
||||
'accessIPv4' => ipv4_address,
|
||||
'accessIPv6' => ipv6_address
|
||||
}
|
||||
|
||||
data = service.update_server(identity, options)
|
||||
merge_attributes(data.body['server'])
|
||||
true
|
||||
end
|
||||
|
||||
# Destroy the server
|
||||
# @return [Boolean] returns true if server has started deleting
|
||||
# @raise [Fog::Compute::RackspaceV2::NotFound] - HTTP 404
|
||||
# @raise [Fog::Compute::RackspaceV2::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Compute::RackspaceV2::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Compute::RackspaceV2::ServiceError]
|
||||
# @see http://docs.rackspace.com/servers/api/v2/cs-devguide/content/Delete_Server-d1e2883.html
|
||||
#
|
||||
# * Status Transition:
|
||||
# * ACTIVE -> DELETED
|
||||
# * ERROR -> DELETED
|
||||
def destroy
|
||||
requires :identity
|
||||
service.delete_server(identity)
|
||||
true
|
||||
end
|
||||
|
||||
# Server flavor
|
||||
# @return [Fog::Compute::RackspaceV2::Flavor] server flavor
|
||||
# @raise [Fog::Compute::RackspaceV2::NotFound] - HTTP 404
|
||||
# @raise [Fog::Compute::RackspaceV2::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Compute::RackspaceV2::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Compute::RackspaceV2::ServiceError]
|
||||
def flavor
|
||||
requires :flavor_id
|
||||
@flavor ||= service.flavors.get(flavor_id)
|
||||
end
|
||||
|
||||
# Server image
|
||||
# @return [Fog::Compute::RackspaceV2::Image] server image
|
||||
# @raise [Fog::Compute::RackspaceV2::NotFound] - HTTP 404
|
||||
# @raise [Fog::Compute::RackspaceV2::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Compute::RackspaceV2::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Compute::RackspaceV2::ServiceError]
|
||||
def image
|
||||
requires :image_id
|
||||
@image ||= service.images.get(image_id)
|
||||
end
|
||||
|
||||
# Creates Image from server. Once complete, a new image is available that you can use to rebuild or create servers.
|
||||
# @param name [String] name of image to create
|
||||
# @param options [Hash]:
|
||||
# @option options [Hash<String, String>] metadata hash of containing metadata key value pairs.
|
||||
# @return [Fog::ComputeRackspaceV2::Image] image being created
|
||||
# @raise [Fog::Compute::RackspaceV2::NotFound] - HTTP 404
|
||||
# @raise [Fog::Compute::RackspaceV2::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Compute::RackspaceV2::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Compute::RackspaceV2::ServiceError]
|
||||
# @see http://docs.rackspace.com/servers/api/v2/cs-devguide/content/Create_Image-d1e4655.html
|
||||
#
|
||||
# * State Transition:
|
||||
# * SAVING -> ACTIVE
|
||||
# * SAVING -> ERROR (on error)
|
||||
def create_image(name, options = {})
|
||||
requires :identity
|
||||
response = service.create_image(identity, name, options)
|
||||
begin
|
||||
image_id = response.headers["Location"].match(/\/([^\/]+$)/)[1]
|
||||
Fog::Compute::RackspaceV2::Image.new(:collection => service.images, :service => service, :id => image_id)
|
||||
rescue
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
# Attached Cloud Block Volumes
|
||||
# @return [Fog::Compute::RackspaceV2::Attachments] attached Cloud Block Volumes
|
||||
# @raise [Fog::Compute::RackspaceV2::NotFound] - HTTP 404
|
||||
# @raise [Fog::Compute::RackspaceV2::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Compute::RackspaceV2::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Compute::RackspaceV2::ServiceError]
|
||||
# @see http://docs.rackspace.com/servers/api/v2/cs-devguide/content/List_Volume_Attachments.html
|
||||
def attachments
|
||||
@attachments ||= begin
|
||||
Fog::Compute::RackspaceV2::Attachments.new({
|
||||
:service => service,
|
||||
:server => self
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
# Attaches Cloud Block Volume
|
||||
# @param [Fog::Rackspace::BlockStorage::Volume, String] volume object or the volume id of volume to mount
|
||||
# @param [String] device name of the device /dev/xvd[a-p] (optional)
|
||||
# @return [Fog::Compute::RackspaceV2::Attachment] resulting attachment object
|
||||
# @raise [Fog::Compute::RackspaceV2::NotFound] - HTTP 404
|
||||
# @raise [Fog::Compute::RackspaceV2::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Compute::RackspaceV2::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Compute::RackspaceV2::ServiceError]
|
||||
# @see http://docs.rackspace.com/servers/api/v2/cs-devguide/content/Attach_Volume_to_Server.html
|
||||
def attach_volume(volume, device=nil)
|
||||
requires :identity
|
||||
volume_id = volume.is_a?(String) ? volume : volume.id
|
||||
attachments.create(:server_id => identity, :volume_id => volume_id, :device => device)
|
||||
end
|
||||
|
||||
# Server's private IPv4 address
|
||||
# @return [String] private IPv4 address
|
||||
def private_ip_address
|
||||
addresses['private'].select{|a| a["version"] == 4}[0]["addr"] rescue ''
|
||||
end
|
||||
|
||||
# Server's public IPv4 address
|
||||
# @return [String] public IPv4 address
|
||||
def public_ip_address
|
||||
ipv4_address
|
||||
end
|
||||
|
||||
# Is server is in ready state
|
||||
# @param [String] ready_state By default state is ACTIVE
|
||||
# @param [Array,String] error_states By default state is ERROR
|
||||
# @return [Boolean] returns true if server is in a ready state
|
||||
# @raise [Fog::Compute::RackspaceV2::InvalidServerStateException] if server state is an error state
|
||||
def ready?(ready_state = ACTIVE, error_states=[ERROR])
|
||||
if error_states
|
||||
error_states = Array(error_states)
|
||||
raise InvalidServerStateException.new(ready_state, state) if error_states.include?(state)
|
||||
end
|
||||
state == ready_state
|
||||
end
|
||||
|
||||
# Reboot server
|
||||
# @param [String<SOFT, HARD>] type 'SOFT' will do a soft reboot. 'HARD' will do a hard reboot.
|
||||
# @return [Boolean] returns true if server is being rebooted
|
||||
# @raise [Fog::Compute::RackspaceV2::NotFound] - HTTP 404
|
||||
# @raise [Fog::Compute::RackspaceV2::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Compute::RackspaceV2::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Compute::RackspaceV2::ServiceError]
|
||||
# @see http://docs.rackspace.com/servers/api/v2/cs-devguide/content/Reboot_Server-d1e3371.html
|
||||
#
|
||||
# * State transition:
|
||||
# * ACTIVE -> REBOOT -> ACTIVE (soft reboot)
|
||||
# * ACTIVE -> HARD_REBOOT -> ACTIVE (hard reboot)
|
||||
def reboot(type = 'SOFT')
|
||||
requires :identity
|
||||
service.reboot_server(identity, type)
|
||||
self.state = type == 'SOFT' ? REBOOT : HARD_REBOOT
|
||||
true
|
||||
end
|
||||
|
||||
# Rebuild removes all data on the server and replaces it with the specified image. The id and all IP addresses remain the same.
|
||||
# @param [String] image_id image to use for rebuild
|
||||
# @return [Boolean] returns true if rebuild is in process
|
||||
# @raise [Fog::Compute::RackspaceV2::NotFound] - HTTP 404
|
||||
# @raise [Fog::Compute::RackspaceV2::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Compute::RackspaceV2::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Compute::RackspaceV2::ServiceError]
|
||||
# @see http://docs.rackspace.com/servers/api/v2/cs-devguide/content/Rebuild_Server-d1e3538.html
|
||||
#
|
||||
# * Status Transition:
|
||||
# * ACTIVE -> REBUILD -> ACTIVE
|
||||
# * ACTIVE -> REBUILD -> ERROR (on error)
|
||||
def rebuild(image_id, options={})
|
||||
requires :identity
|
||||
service.rebuild_server(identity, image_id, options)
|
||||
self.state = REBUILD
|
||||
true
|
||||
end
|
||||
|
||||
# Resize existing server to a different flavor, in essence, scaling the server up or down. The original server is saved for a period of time to allow rollback if there is a problem. All resizes should be tested and explicitly confirmed, at which time the original server is removed. All resizes are automatically confirmed after 24 hours if they are not confirmed or reverted.
|
||||
# @param [String] flavor_id to resize
|
||||
# @return [Boolean] returns true if resize is in process
|
||||
# @raise [Fog::Compute::RackspaceV2::NotFound] - HTTP 404
|
||||
# @raise [Fog::Compute::RackspaceV2::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Compute::RackspaceV2::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Compute::RackspaceV2::ServiceError]
|
||||
# @note All resizes are automatically confirmed after 24 hours if you do not explicitly confirm or revert the resize.
|
||||
# @see http://docs.rackspace.com/servers/api/v2/cs-devguide/content/Resize_Server-d1e3707.html
|
||||
# @see #confirm_resize
|
||||
# @see #revert_resize
|
||||
#
|
||||
# * Status Transition:
|
||||
# * ACTIVE -> QUEUE_RESIZE -> PREP_RESIZE -> VERIFY_RESIZE
|
||||
# * ACTIVE -> QUEUE_RESIZE -> ACTIVE (on error)
|
||||
def resize(flavor_id)
|
||||
requires :identity
|
||||
service.resize_server(identity, flavor_id)
|
||||
self.state = RESIZE
|
||||
true
|
||||
end
|
||||
|
||||
# Confirms server resize operation
|
||||
# @return [Boolean] returns true if resize has been confirmed
|
||||
# @raise [Fog::Compute::RackspaceV2::NotFound] - HTTP 404
|
||||
# @raise [Fog::Compute::RackspaceV2::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Compute::RackspaceV2::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Compute::RackspaceV2::ServiceError]
|
||||
# @note All resizes are automatically confirmed after 24 hours if you do not explicitly confirm or revert the resize.
|
||||
# @see http://docs.rackspace.com/servers/api/v2/cs-devguide/content/Confirm_Resized_Server-d1e3868.html
|
||||
# @see #resize
|
||||
#
|
||||
# * Status Transition:
|
||||
# * VERIFY_RESIZE -> ACTIVE
|
||||
# * VERIFY_RESIZE -> ERROR (on error)å
|
||||
def confirm_resize
|
||||
requires :identity
|
||||
service.confirm_resize_server(identity)
|
||||
true
|
||||
end
|
||||
|
||||
# Reverts server resize operation
|
||||
# @return [Boolean] returns true if resize is being reverted
|
||||
# @raise [Fog::Compute::RackspaceV2::NotFound] - HTTP 404
|
||||
# @raise [Fog::Compute::RackspaceV2::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Compute::RackspaceV2::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Compute::RackspaceV2::ServiceError]
|
||||
# @note All resizes are automatically confirmed after 24 hours if you do not explicitly confirm or revert the resize.
|
||||
# @see http://docs.rackspace.com/servers/api/v2/cs-devguide/content/Revert_Resized_Server-d1e4024.html
|
||||
# @see #resize
|
||||
#
|
||||
# * Status Transition:
|
||||
# * VERIFY_RESIZE -> ACTIVE
|
||||
# * VERIFY_RESIZE -> ERROR (on error)
|
||||
def revert_resize
|
||||
requires :identity
|
||||
service.revert_resize_server(identity)
|
||||
true
|
||||
end
|
||||
|
||||
# Place existing server into rescue mode, allowing for offline editing of configuration. The original server's disk is attached to a new instance of the same base image for a period of time to facilitate working within rescue mode. The original server will be automatically restored after 90 minutes.
|
||||
# @return [Boolean] returns true if call to put server in rescue mode reports success
|
||||
# @raise [Fog::Rackspace::Errors::NotFound] - HTTP 404
|
||||
# @raise [Fog::Rackspace::Errors::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Rackspace::Errors::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Rackspace::Errors::ServiceError]
|
||||
# @note Rescue mode is only guaranteed to be active for 90 minutes.
|
||||
# @see http://docs.rackspace.com/servers/api/v2/cs-devguide/content/rescue_mode.html
|
||||
# @see #unrescue
|
||||
#
|
||||
# * Status Transition:
|
||||
# * ACTIVE -> PREP_RESCUE -> RESCUE
|
||||
def rescue
|
||||
requires :identity
|
||||
data = service.rescue_server(identity)
|
||||
merge_attributes(data.body)
|
||||
true
|
||||
end
|
||||
|
||||
# Remove existing server from rescue mode.
|
||||
# @return [Boolean] returns true if call to remove server from rescue mode reports success
|
||||
# @raise [Fog::Rackspace::Errors::NotFound] - HTTP 404
|
||||
# @raise [Fog::Rackspace::Errors::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Rackspace::Errors::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Rackspace::Errors::ServiceError]
|
||||
# @note Rescue mode is only guaranteed to be active for 90 minutes.
|
||||
# @see http://docs.rackspace.com/servers/api/v2/cs-devguide/content/exit_rescue_mode.html
|
||||
# @see #rescue
|
||||
#
|
||||
# * Status Transition:
|
||||
# * PREP_UNRESCUE -> ACTIVE
|
||||
def unrescue
|
||||
requires :identity
|
||||
service.unrescue_server(identity)
|
||||
self.state = ACTIVE
|
||||
true
|
||||
end
|
||||
|
||||
# Change admin password
|
||||
# @param [String] password The administrator password.
|
||||
# @return [Boolean] returns true if operation was scheduled
|
||||
# @raise [Fog::Compute::RackspaceV2::NotFound] - HTTP 404
|
||||
# @raise [Fog::Compute::RackspaceV2::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Compute::RackspaceV2::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Compute::RackspaceV2::ServiceError]
|
||||
# @note Though Rackspace does not enforce complexity requirements for the password, the operating system might. If the password is not complex enough, the server might enter an ERROR state.
|
||||
# @see http://docs.rackspace.com/servers/api/v2/cs-devguide/content/Change_Password-d1e3234.html
|
||||
#
|
||||
# * Status Transition:
|
||||
# * ACTIVE -> PASSWORD -> ACTIVE
|
||||
# * ACTIVE -> PASSWORD -> ERROR (on error)
|
||||
def change_admin_password(password)
|
||||
requires :identity
|
||||
service.change_server_password(identity, password)
|
||||
self.state = PASSWORD
|
||||
self.password = password
|
||||
true
|
||||
end
|
||||
|
||||
# Setup server for SSH access
|
||||
# @see Servers#bootstrap
|
||||
def setup(credentials = {})
|
||||
requires :ssh_ip_address, :identity, :public_key, :username
|
||||
|
||||
retried_disconnect = false
|
||||
|
||||
commands = [
|
||||
%{mkdir .ssh},
|
||||
%{echo "#{public_key}" >> ~/.ssh/authorized_keys},
|
||||
password_lock,
|
||||
%{echo "#{Fog::JSON.encode(attributes)}" >> ~/attributes.json},
|
||||
%{echo "#{Fog::JSON.encode(metadata)}" >> ~/metadata.json}
|
||||
]
|
||||
commands.compact
|
||||
|
||||
self.password = nil if password_lock
|
||||
|
||||
Fog::SSH.new(ssh_ip_address, username, credentials).run(commands)
|
||||
rescue Errno::ECONNREFUSED
|
||||
sleep(1)
|
||||
retry
|
||||
# Ubuntu 12.04 images seem to be disconnecting during the ssh setup process.
|
||||
# This rescue block is an effort to address that issue.
|
||||
rescue Net::SSH::Disconnect
|
||||
unless retried_disconnect
|
||||
retried_disconnect = true
|
||||
sleep(1)
|
||||
retry
|
||||
end
|
||||
end
|
||||
|
||||
def virtual_interfaces
|
||||
@virtual_interfaces ||= Fog::Compute::RackspaceV2::VirtualInterfaces.new :server => self, :service => service
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def adminPass=(new_admin_pass)
|
||||
self.password = new_admin_pass
|
||||
end
|
||||
|
||||
def password_lock
|
||||
"passwd -l #{username}" unless attributes[:no_passwd_lock]
|
||||
end
|
||||
|
||||
def user_data_encoded
|
||||
self.user_data.nil? ? nil : [self.user_data].pack('m')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
64
lib/fog/rackspace/models/compute_v2/servers.rb
Normal file
64
lib/fog/rackspace/models/compute_v2/servers.rb
Normal file
|
@ -0,0 +1,64 @@
|
|||
require 'fog/core/collection'
|
||||
require 'fog/rackspace/models/compute_v2/server'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class RackspaceV2
|
||||
class Servers < Fog::Collection
|
||||
model Fog::Compute::RackspaceV2::Server
|
||||
|
||||
# Returns list of servers
|
||||
# @return [Fog::Compute::RackspaceV2::Servers] Retrieves a list servers.
|
||||
# @raise [Fog::Compute::RackspaceV2::NotFound] - HTTP 404
|
||||
# @raise [Fog::Compute::RackspaceV2::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Compute::RackspaceV2::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Compute::RackspaceV2::ServiceError]
|
||||
# @note Fog's current implementation only returns 1000 servers
|
||||
# @note The filter parameter on the method is just to maintain compatability with other providers that support filtering.
|
||||
# @see http://docs.rackspace.com/servers/api/v2/cs-devguide/content/List_Servers-d1e2078.html
|
||||
def all(filters = {})
|
||||
data = service.list_servers.body['servers']
|
||||
load(data)
|
||||
end
|
||||
|
||||
# Creates a new server and populates ssh keys
|
||||
# @return [Fog::Compute::RackspaceV2::Server]
|
||||
# @raise [Fog::Compute::RackspaceV2::NotFound] - HTTP 404
|
||||
# @raise [Fog::Compute::RackspaceV2::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Compute::RackspaceV2::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Compute::RackspaceV2::ServiceError]
|
||||
# @note This method is compatible with Cloud Servers utlizing RackConnect ***if and only if***
|
||||
# provided the attribute "no_passwd_lock" set to *true*.
|
||||
# @example
|
||||
# service.servers.bootstrap :name => 'bootstrap-server',
|
||||
# :flavor_id => service.flavors.first.id,
|
||||
# :image_id => service.images.find {|img| img.name =~ /Ubuntu/}.id,
|
||||
# :public_key_path => '~/.ssh/fog_rsa.pub',
|
||||
# :private_key_path => '~/.ssh/fog_rsa'
|
||||
#
|
||||
# @raise [Fog::Compute::RackspaceV2::InvalidServerStateException] if server state is an error state
|
||||
def bootstrap(new_attributes = {})
|
||||
server = create(new_attributes)
|
||||
server.wait_for { ready? && !public_ip_address.empty? }
|
||||
server.setup(:password => server.password)
|
||||
server
|
||||
end
|
||||
|
||||
# Retrieves server
|
||||
# @param [String] server_id for server to be returned
|
||||
# @return [Fog::Compute::RackspaceV2:Server]
|
||||
# @raise [Fog::Compute::RackspaceV2::NotFound] - HTTP 404
|
||||
# @raise [Fog::Compute::RackspaceV2::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Compute::RackspaceV2::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Compute::RackspaceV2::ServiceError]
|
||||
# @see http://docs.rackspace.com/servers/api/v2/cs-devguide/content/Get_Server_Details-d1e2623.html
|
||||
def get(server_id)
|
||||
data = service.get_server(server_id).body['server']
|
||||
new(data)
|
||||
rescue Fog::Compute::RackspaceV2::NotFound
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
85
lib/fog/rackspace/models/compute_v2/virtual_interface.rb
Normal file
85
lib/fog/rackspace/models/compute_v2/virtual_interface.rb
Normal file
|
@ -0,0 +1,85 @@
|
|||
require 'fog/core/collection'
|
||||
require 'fog/rackspace/models/compute_v2/virtual_interface'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class RackspaceV2
|
||||
class VirtualInterface < Fog::Model
|
||||
# @!attribute [r] id
|
||||
# @return [String] The virtual interface id
|
||||
identity :id
|
||||
|
||||
# @!attribute [r] mac_address
|
||||
# @return [String] The Media Access Control (MAC) address for the virtual interface.
|
||||
# A MAC address is a unique identifier assigned to network interfaces for communications on the physical network segment.
|
||||
attribute :mac_address
|
||||
|
||||
# @!attribute [r] ip_addresses
|
||||
# @return [Array<Hash>] returns an array of hashes containing information about allocated ip addresses and their associated networks
|
||||
# @example
|
||||
# [
|
||||
# {
|
||||
# "address": "2001:4800:7810:0512:d87b:9cbc:ff04:850c",
|
||||
# "network_id": "ba122b32-dbcc-4c21-836e-b701996baeb3",
|
||||
# "network_label": "public"
|
||||
# },
|
||||
# {
|
||||
# "address": "64.49.226.149",
|
||||
# "network_id": "ba122b32-dbcc-4c21-836e-b701996baeb3",
|
||||
# "network_label": "public"
|
||||
# }
|
||||
# ]
|
||||
attribute :ip_addresses
|
||||
|
||||
# Saves the virtual interface.
|
||||
# This method can only create a virtual interface. Attempting to update interface will result an exception
|
||||
# @return [Boolean] true if virtual interface has been saved
|
||||
def save(attributes = {})
|
||||
if persisted?
|
||||
raise Fog::Errors::Error.new("This virtual interface has already been created and it cannot be updated")
|
||||
else
|
||||
create
|
||||
end
|
||||
true
|
||||
end
|
||||
|
||||
# Creates Virtual interface for server
|
||||
# * requires attributes: :network
|
||||
# @return [Boolean] returns true if virtual network interface is being created
|
||||
# @raise [Fog::Compute::RackspaceV2::NotFound] - HTTP 404
|
||||
# @raise [Fog::Compute::RackspaceV2::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Compute::RackspaceV2::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Compute::RackspaceV2::ServiceError]
|
||||
# @example To create a virtual interface;
|
||||
# my_server.virtual_interfaces.create :network => my_network
|
||||
# @see http://docs.rackspace.com/servers/api/v2/cn-devguide/content/api_create_virtual_interface.html
|
||||
def create
|
||||
data = service.create_virtual_interface(server_id, network_id)
|
||||
merge_attributes(data.body['virtual_interfaces'].first)
|
||||
end
|
||||
|
||||
# Destroy the virtual interface
|
||||
# @return [Boolean] returns true if virtual interface has been destroyed
|
||||
# @raise [Fog::Compute::RackspaceV2::NotFound] - HTTP 404
|
||||
# @raise [Fog::Compute::RackspaceV2::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Compute::RackspaceV2::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Compute::RackspaceV2::ServiceError]
|
||||
# @see http://docs.rackspace.com/servers/api/v2/cn-devguide/content/delete_virt_interface_api.html
|
||||
def destroy
|
||||
service.delete_virtual_interface(server_id, id)
|
||||
true
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def server_id
|
||||
attributes[:server].is_a?(Server) ? attributes[:server].id : attributes[:server]
|
||||
end
|
||||
|
||||
def network_id
|
||||
attributes[:network].is_a?(Network) ? attributes[:network].id : attributes[:network]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
46
lib/fog/rackspace/models/compute_v2/virtual_interfaces.rb
Normal file
46
lib/fog/rackspace/models/compute_v2/virtual_interfaces.rb
Normal file
|
@ -0,0 +1,46 @@
|
|||
require 'fog/core/collection'
|
||||
require 'fog/rackspace/models/compute_v2/virtual_interface'
|
||||
require 'fog/rackspace/models/compute_v2/server'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class RackspaceV2
|
||||
class VirtualInterfaces < Fog::Collection
|
||||
model Fog::Compute::RackspaceV2::VirtualInterface
|
||||
|
||||
attr_reader :server
|
||||
|
||||
def server=(obj)
|
||||
if obj.is_a?(Server)
|
||||
@server = obj
|
||||
else
|
||||
@server = Fog::Compute::RackspaceV2::Server.new :id => obj, :service => service
|
||||
end
|
||||
end
|
||||
|
||||
# Returns list of virtual interfaces for a server
|
||||
# @return [Fog::Compute::RackspaceV2::Servers] Retrieves a list virtual interfaces for server.
|
||||
# @raise [Fog::Compute::RackspaceV2::NotFound] - HTTP 404
|
||||
# @raise [Fog::Compute::RackspaceV2::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Compute::RackspaceV2::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Compute::RackspaceV2::ServiceError]
|
||||
# @note Fog's current implementation only returns 1000 servers
|
||||
# @note The filter parameter on the method is just to maintain compatability with other providers that support filtering.
|
||||
# @see http://docs.rackspace.com/servers/api/v2/cs-devguide/content/List_Servers-d1e2078.html
|
||||
# @see Fog::Compute::RackspaceV2::Server#virtual_interfaces
|
||||
def all
|
||||
raise "Please access this collection via Server#virtual_interfaces" unless self.server
|
||||
|
||||
data = service.list_virtual_interfaces(server.id).body['virtual_interfaces']
|
||||
objects = load(data)
|
||||
objects.each {|obj| obj.attributes[:server] = self.server}
|
||||
objects
|
||||
end
|
||||
|
||||
def new(attributes = {})
|
||||
super({ :server => server }.merge(attributes))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
43
lib/fog/rackspace/models/databases/database.rb
Normal file
43
lib/fog/rackspace/models/databases/database.rb
Normal file
|
@ -0,0 +1,43 @@
|
|||
require 'fog/core/model'
|
||||
|
||||
module Fog
|
||||
module Rackspace
|
||||
class Databases
|
||||
class Database < Fog::Model
|
||||
identity :name
|
||||
|
||||
attribute :character_set
|
||||
attribute :collate
|
||||
|
||||
def save
|
||||
requires :identity, :instance
|
||||
service.create_database(instance.identity, identity, :character_set => character_set, :collate => collate)
|
||||
true
|
||||
end
|
||||
|
||||
def destroy
|
||||
requires :identity, :instance
|
||||
service.delete_database(instance.identity, identity)
|
||||
true
|
||||
end
|
||||
|
||||
def grant_access_for(user)
|
||||
requires :identity, :instance
|
||||
service.grant_user_access(instance.identity, user, name)
|
||||
end
|
||||
|
||||
def revoke_access_for(user)
|
||||
requires :identity, :instance
|
||||
service.revoke_user_access(instance.identity, user, name)
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
def instance
|
||||
collection.instance
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
30
lib/fog/rackspace/models/databases/databases.rb
Normal file
30
lib/fog/rackspace/models/databases/databases.rb
Normal file
|
@ -0,0 +1,30 @@
|
|||
require 'fog/core/collection'
|
||||
require 'fog/rackspace/models/databases/database'
|
||||
|
||||
module Fog
|
||||
module Rackspace
|
||||
class Databases
|
||||
class Databases < Fog::Collection
|
||||
model Fog::Rackspace::Databases::Database
|
||||
|
||||
attr_accessor :instance
|
||||
|
||||
def all
|
||||
load(retrieve_databases)
|
||||
end
|
||||
|
||||
def get(database_name)
|
||||
data = retrieve_databases.find { |database| database['name'] == database_name }
|
||||
data && new(data)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def retrieve_databases
|
||||
requires :instance
|
||||
data = service.list_databases(instance.id).body['databases']
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue