2013-01-29 15:25:06 -05:00
|
|
|
require 'fog/compute/models/server'
|
|
|
|
|
|
|
|
module Fog
|
|
|
|
module Compute
|
|
|
|
class DigitalOcean
|
2013-01-31 19:08:04 -05:00
|
|
|
|
2013-01-29 15:25:06 -05:00
|
|
|
# A DigitalOcean Droplet
|
|
|
|
#
|
|
|
|
class Server < Fog::Compute::Server
|
2013-07-10 20:41:12 -04:00
|
|
|
|
2013-01-29 15:25:06 -05:00
|
|
|
identity :id
|
|
|
|
attribute :name
|
2013-07-10 20:41:12 -04:00
|
|
|
attribute :state, :aliases => 'status'
|
2013-01-29 15:25:06 -05:00
|
|
|
attribute :image_id
|
|
|
|
attribute :region_id
|
2013-07-10 20:41:12 -04:00
|
|
|
attribute :flavor_id, :aliases => 'size_id'
|
2013-02-26 14:42:08 -05:00
|
|
|
# Not documented in their API, but
|
|
|
|
# available nevertheless
|
2013-07-21 14:09:53 -04:00
|
|
|
attribute :public_ip_address, :aliases => 'ip_address'
|
2013-01-29 15:25:06 -05:00
|
|
|
attribute :backups_active
|
|
|
|
|
2013-07-21 14:09:53 -04:00
|
|
|
attr_writer :ssh_keys
|
|
|
|
|
2013-07-29 13:10:25 -04:00
|
|
|
# Deprecated: Use public_ip_address instead.
|
|
|
|
def ip_address
|
|
|
|
Fog::Logger.warning("ip_address has been deprecated. Use public_ip_address instead")
|
|
|
|
public_ip_address
|
|
|
|
end
|
|
|
|
|
2013-01-31 19:08:04 -05:00
|
|
|
# Reboot the server (soft reboot).
|
|
|
|
#
|
|
|
|
# The preferred method of rebooting a server.
|
2013-01-29 15:25:06 -05:00
|
|
|
def reboot
|
2013-02-26 14:42:08 -05:00
|
|
|
requires :id
|
|
|
|
service.reboot_server self.id
|
2013-01-31 19:08:04 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
# Reboot the server (hard reboot).
|
|
|
|
#
|
|
|
|
# Powers the server off and then powers it on again.
|
|
|
|
def power_cycle
|
2013-02-26 14:42:08 -05:00
|
|
|
requires :id
|
|
|
|
service.power_cycle_server self.id
|
2013-01-29 15:25:06 -05:00
|
|
|
end
|
|
|
|
|
2013-01-31 19:08:04 -05:00
|
|
|
# Shutdown the server
|
|
|
|
#
|
|
|
|
# Sends a shutdown signal to the operating system.
|
|
|
|
# The server consumes resources while powered off
|
|
|
|
# so you are still charged.
|
|
|
|
#
|
|
|
|
# @see https://www.digitalocean.com/community/questions/am-i-charged-while-my-droplet-is-in-a-powered-off-state
|
2013-01-29 15:25:06 -05:00
|
|
|
def shutdown
|
2013-02-26 14:42:08 -05:00
|
|
|
requires :id
|
|
|
|
service.shutdown_server self.id
|
2013-01-31 19:08:04 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
# Power off the server
|
|
|
|
#
|
|
|
|
# Works as a power switch.
|
|
|
|
# The server consumes resources while powered off
|
|
|
|
# so you are still charged.
|
2013-07-10 20:41:12 -04:00
|
|
|
#
|
2013-01-31 19:08:04 -05:00
|
|
|
# @see https://www.digitalocean.com/community/questions/am-i-charged-while-my-droplet-is-in-a-powered-off-state
|
|
|
|
def stop
|
2013-02-26 14:42:08 -05:00
|
|
|
requires :id
|
|
|
|
service.power_off_server self.id
|
2013-01-29 15:25:06 -05:00
|
|
|
end
|
|
|
|
|
2013-01-31 19:08:04 -05:00
|
|
|
# Power on the server.
|
|
|
|
#
|
|
|
|
# The server consumes resources while powered on
|
|
|
|
# so you will be charged.
|
|
|
|
#
|
2013-07-10 20:41:12 -04:00
|
|
|
# Each time a server is spun up, even if for a few seconds,
|
2013-01-31 19:08:04 -05:00
|
|
|
# it is charged for an hour.
|
|
|
|
#
|
|
|
|
def start
|
2013-02-26 14:42:08 -05:00
|
|
|
requires :id
|
|
|
|
service.power_on_server self.id
|
2013-01-31 19:08:04 -05:00
|
|
|
end
|
|
|
|
|
2013-07-21 14:09:53 -04:00
|
|
|
def setup(credentials = {})
|
|
|
|
requires :public_ip_address
|
|
|
|
require 'net/ssh'
|
|
|
|
|
|
|
|
commands = [
|
|
|
|
%{mkdir .ssh},
|
|
|
|
%{passwd -l #{username}},
|
|
|
|
%{echo "#{Fog::JSON.encode(Fog::JSON.sanitize(attributes))}" >> ~/attributes.json}
|
|
|
|
]
|
|
|
|
if public_key
|
|
|
|
commands << %{echo "#{public_key}" >> ~/.ssh/authorized_keys}
|
|
|
|
end
|
|
|
|
|
|
|
|
# wait for aws to be ready
|
|
|
|
wait_for { sshable?(credentials) }
|
|
|
|
|
|
|
|
Fog::SSH.new(public_ip_address, username, credentials).run(commands)
|
|
|
|
end
|
|
|
|
|
2013-01-31 19:08:04 -05:00
|
|
|
# Creates the server (not to be called directly).
|
|
|
|
#
|
|
|
|
# Usually called by Fog::Collection#create
|
|
|
|
#
|
2013-06-20 15:48:39 -04:00
|
|
|
# docean = Fog::Compute.new({
|
2013-01-31 19:08:04 -05:00
|
|
|
# :provider => 'DigitalOcean',
|
|
|
|
# :digitalocean_api_key => 'key-here', # your API key here
|
|
|
|
# :digitalocean_client_id => 'client-id-here' # your client key here
|
|
|
|
# })
|
2013-06-20 15:48:39 -04:00
|
|
|
# docean.servers.create :name => 'foobar',
|
2013-01-31 19:08:04 -05:00
|
|
|
# :image_id => image_id_here,
|
|
|
|
# :flavor_id => flavor_id_here,
|
|
|
|
# :region_id => region_id_here
|
2013-07-10 20:41:12 -04:00
|
|
|
#
|
2013-01-31 19:08:04 -05:00
|
|
|
# @return [Boolean]
|
2013-01-29 15:25:06 -05:00
|
|
|
def save
|
|
|
|
raise Fog::Errors::Error.new('Resaving an existing object may create a duplicate') if persisted?
|
|
|
|
requires :name, :flavor_id, :image_id, :region_id
|
2013-03-02 19:12:40 -05:00
|
|
|
|
|
|
|
options = {}
|
|
|
|
if attributes[:ssh_key_ids]
|
2013-07-10 20:41:12 -04:00
|
|
|
options[:ssh_key_ids] = attributes[:ssh_key_ids]
|
2013-07-21 14:09:53 -04:00
|
|
|
elsif @ssh_keys
|
|
|
|
options[:ssh_key_ids] = @ssh_keys.map(&:id)
|
2013-03-02 19:12:40 -05:00
|
|
|
end
|
2013-07-10 20:41:12 -04:00
|
|
|
data = service.create_server name,
|
|
|
|
flavor_id,
|
|
|
|
image_id,
|
2013-03-02 19:12:40 -05:00
|
|
|
region_id,
|
|
|
|
options
|
2013-01-29 15:25:06 -05:00
|
|
|
merge_attributes(data.body['droplet'])
|
|
|
|
true
|
|
|
|
end
|
|
|
|
|
2013-01-31 19:08:04 -05:00
|
|
|
# Destroy the server, freeing up the resources.
|
2013-07-10 20:41:12 -04:00
|
|
|
#
|
2013-01-31 19:08:04 -05:00
|
|
|
# DigitalOcean will stop charging you for the resources
|
|
|
|
# the server was using.
|
|
|
|
#
|
|
|
|
# Once the server has been destroyed, there's no way
|
|
|
|
# to recover it so the data is irrecoverably lost.
|
|
|
|
#
|
|
|
|
# IMPORTANT: As of 2013/01/31, you should wait some time to
|
|
|
|
# destroy the server after creating it. If you try to destroy
|
|
|
|
# the server too fast, the destroy event may be lost and the
|
2013-07-10 20:41:12 -04:00
|
|
|
# server will remain running and consuming resources, so
|
2013-01-31 19:08:04 -05:00
|
|
|
# DigitalOcean will keep charging you.
|
2013-07-10 20:41:12 -04:00
|
|
|
# Double checked this with DigitalOcean staff and confirmed
|
2013-01-31 19:08:04 -05:00
|
|
|
# that it's the way it works right now.
|
|
|
|
#
|
|
|
|
# Double check the server has been destroyed!
|
2013-01-29 15:25:06 -05:00
|
|
|
def destroy
|
2013-02-26 14:42:08 -05:00
|
|
|
requires :id
|
2013-01-29 15:25:06 -05:00
|
|
|
service.destroy_server id
|
|
|
|
end
|
|
|
|
|
2013-01-31 19:08:04 -05:00
|
|
|
# Checks whether the server status is 'active'.
|
|
|
|
#
|
|
|
|
# The server transitions from 'new' to 'active' sixty to ninety
|
|
|
|
# seconds after creating it (time varies and may take more
|
|
|
|
# than 90 secs).
|
|
|
|
#
|
|
|
|
# @return [Boolean]
|
2013-01-29 15:25:06 -05:00
|
|
|
def ready?
|
2013-03-21 08:28:41 -04:00
|
|
|
state == 'active'
|
2013-01-29 15:25:06 -05:00
|
|
|
end
|
2013-01-31 19:08:04 -05:00
|
|
|
|
2013-02-26 14:42:08 -05:00
|
|
|
# DigitalOcean API does not support updating server state
|
|
|
|
def update
|
|
|
|
msg = 'DigitalOcean servers do not support updates'
|
|
|
|
raise NotImplementedError.new(msg)
|
|
|
|
end
|
|
|
|
|
2013-01-29 15:25:06 -05:00
|
|
|
end
|
2013-01-31 19:08:04 -05:00
|
|
|
|
2013-01-29 15:25:06 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|