deltacloud-core 1.0.5 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +10 -2
- data/bin/deltacloudd +10 -10
- data/config.ru +2 -1
- data/config/drivers/digitalocean.yaml +3 -0
- data/deltacloud-core.gemspec +13 -6
- data/lib/cimi/collections.rb +1 -1
- data/lib/cimi/collections/address_templates.rb +27 -3
- data/lib/cimi/collections/addresses.rb +1 -1
- data/lib/cimi/collections/base.rb +1 -0
- data/lib/cimi/collections/cloud_entry_point.rb +4 -0
- data/lib/cimi/collections/credentials.rb +2 -2
- data/lib/cimi/collections/machine_images.rb +20 -0
- data/lib/cimi/collections/machine_templates.rb +72 -0
- data/lib/cimi/collections/machines.rb +50 -41
- data/lib/cimi/collections/network_ports.rb +3 -3
- data/lib/cimi/collections/networks.rb +4 -4
- data/lib/cimi/collections/resource_metadata.rb +1 -1
- data/lib/cimi/collections/volume_configurations.rb +25 -0
- data/lib/cimi/collections/volume_images.rb +21 -1
- data/lib/cimi/collections/volume_templates.rb +69 -0
- data/lib/cimi/collections/volumes.rb +5 -10
- data/lib/cimi/dependencies.rb +0 -1
- data/lib/cimi/helpers.rb +4 -1
- data/lib/cimi/helpers/cimi_helper.rb +62 -0
- data/lib/cimi/helpers/database_helper.rb +95 -0
- data/lib/cimi/models.rb +15 -1
- data/lib/cimi/models/address.rb +10 -5
- data/lib/cimi/models/address_template.rb +67 -3
- data/lib/cimi/models/base.rb +8 -5
- data/lib/cimi/models/cloud_entry_point.rb +6 -1
- data/lib/cimi/models/collection.rb +9 -4
- data/lib/cimi/models/disk.rb +6 -1
- data/lib/cimi/models/errors.rb +8 -0
- data/lib/cimi/models/machine.rb +68 -42
- data/lib/cimi/models/machine_configuration.rb +2 -2
- data/lib/cimi/models/machine_image.rb +41 -6
- data/lib/cimi/models/machine_template.rb +58 -0
- data/lib/cimi/models/machine_volume.rb +51 -3
- data/lib/cimi/models/resource_metadata.rb +88 -25
- data/lib/cimi/models/schema.rb +19 -5
- data/lib/cimi/models/volume.rb +66 -30
- data/lib/cimi/models/volume_configuration.rb +53 -21
- data/lib/cimi/models/volume_image.rb +24 -9
- data/lib/cimi/models/volume_template.rb +61 -0
- data/lib/cimi/server.rb +0 -6
- data/lib/db.rb +82 -0
- data/lib/db/address_template.rb +15 -0
- data/lib/db/entity.rb +22 -0
- data/lib/db/machine_template.rb +10 -0
- data/lib/db/provider.rb +13 -0
- data/lib/db/volume_configuration.rb +10 -0
- data/lib/db/volume_template.rb +10 -0
- data/lib/deltacloud/collections/addresses.rb +1 -1
- data/lib/deltacloud/collections/base.rb +12 -1
- data/lib/deltacloud/collections/buckets.rb +41 -8
- data/lib/deltacloud/collections/drivers.rb +1 -1
- data/lib/deltacloud/collections/firewalls.rb +2 -2
- data/lib/deltacloud/collections/images.rb +1 -1
- data/lib/deltacloud/collections/instances.rb +7 -1
- data/lib/deltacloud/collections/keys.rb +1 -1
- data/lib/deltacloud/collections/load_balancers.rb +4 -4
- data/lib/deltacloud/collections/storage_snapshots.rb +5 -1
- data/lib/deltacloud/collections/storage_volumes.rb +7 -3
- data/lib/deltacloud/drivers/base_driver.rb +10 -9
- data/lib/deltacloud/drivers/cimi_features.rb +42 -0
- data/lib/deltacloud/drivers/digitalocean/digitalocean_driver.rb +307 -0
- data/lib/deltacloud/drivers/ec2/ec2_driver.rb +40 -14
- data/lib/deltacloud/drivers/exceptions.rb +8 -0
- data/lib/deltacloud/drivers/features.rb +19 -2
- data/lib/deltacloud/drivers/fgcp/fgcp_client.rb +11 -0
- data/lib/deltacloud/drivers/fgcp/fgcp_driver.rb +83 -11
- data/lib/deltacloud/drivers/gogrid/gogrid_client.rb +1 -1
- data/lib/deltacloud/drivers/mock/mock_client.rb +2 -4
- data/lib/deltacloud/drivers/mock/mock_driver.rb +29 -0
- data/lib/deltacloud/drivers/openstack/openstack_driver.rb +153 -36
- data/lib/deltacloud/drivers/rackspace/anti_cache_monkey_patch.rb +20 -0
- data/lib/deltacloud/drivers/rackspace/rackspace_driver.rb +1 -0
- data/lib/deltacloud/drivers/rhevm/rhevm_driver.rb +30 -12
- data/lib/deltacloud/drivers/sbc/sbc_client.rb +0 -1
- data/lib/deltacloud/drivers/sbc/sbc_driver.rb +5 -1
- data/lib/deltacloud/drivers/vsphere/vsphere_client.rb +1 -1
- data/lib/deltacloud/drivers/vsphere/vsphere_driver.rb +19 -9
- data/lib/deltacloud/helpers/blob_stream_helper.rb +42 -3
- data/lib/deltacloud/helpers/deltacloud_helper.rb +31 -14
- data/lib/deltacloud/models/address.rb +9 -0
- data/lib/deltacloud/models/base_model.rb +4 -0
- data/lib/deltacloud/models/blob.rb +12 -0
- data/lib/deltacloud/models/bucket.rb +9 -0
- data/lib/deltacloud/models/firewall.rb +13 -1
- data/lib/deltacloud/models/firewall_rule.rb +14 -0
- data/lib/deltacloud/models/hardware_profile.rb +14 -0
- data/lib/deltacloud/models/image.rb +15 -0
- data/lib/deltacloud/models/instance.rb +40 -1
- data/lib/deltacloud/models/instance_address.rb +9 -0
- data/lib/deltacloud/models/key.rb +15 -0
- data/lib/deltacloud/models/load_balancer.rb +20 -0
- data/lib/deltacloud/models/metric.rb +15 -0
- data/lib/deltacloud/models/provider.rb +8 -0
- data/lib/deltacloud/models/realm.rb +9 -0
- data/lib/deltacloud/models/state_machine.rb +8 -0
- data/lib/deltacloud/models/storage_snapshot.rb +11 -0
- data/lib/deltacloud/models/storage_volume.rb +24 -0
- data/lib/deltacloud/server.rb +1 -3
- data/lib/deltacloud/version.rb +2 -1
- data/lib/deltacloud_rack.rb +1 -1
- data/tests/cimi/db/database_helper_test.rb +190 -0
- data/tests/cimi/db/db_helper.rb +30 -0
- data/tests/cimi/db/schema_test.rb +94 -0
- data/tests/cimi/model/collection_spec.rb +0 -1
- data/tests/cimi/model/machine_spec.rb +17 -0
- data/tests/cimi/spec_helper.rb +3 -2
- data/tests/deltacloud/collections/buckets_collection_test.rb +3 -0
- data/tests/deltacloud/collections/drivers_collection_test.rb +10 -0
- data/tests/deltacloud/collections/hardware_profiles_collection_test.rb +4 -0
- data/tests/deltacloud/collections/images_collection_test.rb +4 -0
- data/tests/deltacloud/collections/instances_collection_test.rb +14 -1
- data/tests/deltacloud/collections/keys_collection_test.rb +4 -0
- data/tests/deltacloud/collections/realms_collection_test.rb +47 -0
- data/tests/deltacloud/collections/storage_snapshots_collection_test.rb +47 -0
- data/tests/deltacloud/collections/storage_volumes_collection_test.rb +47 -0
- data/tests/deltacloud/common.rb +15 -0
- data/tests/deltacloud/deltacloud_helper_test.rb +0 -4
- data/tests/deltacloud/launcher_test.rb +108 -0
- data/tests/drivers/ec2/buckets_test.rb +2 -1
- data/tests/drivers/mock/buckets_test.rb +27 -0
- data/tests/drivers/mock/instances_test.rb +6 -0
- data/tests/drivers/openstack/common.rb +1 -1
- data/tests/drivers/openstack/hardware_profiles_test.rb +2 -1
- data/tests/drivers/openstack/instances_test.rb +18 -17
- data/tests/drivers/rhevm/common.rb +1 -0
- data/tests/drivers/rhevm/images_test.rb +1 -1
- data/tests/drivers/rhevm/instance_test.rb +7 -7
- data/tests/helpers/rack/rack_matrix_params_test.rb +0 -2
- data/tests/test_helper.rb +2 -1
- data/views/errors/403.xml.haml +6 -0
- data/views/errors/409.html.haml +47 -0
- data/views/errors/409.xml.haml +11 -0
- data/views/errors/502.html.haml +6 -5
- data/views/images/show.xml.haml +3 -2
- data/views/instances/new.html.haml +1 -1
- metadata +77 -30
@@ -39,7 +39,7 @@ module Deltacloud::Collections
|
|
39
39
|
halt 404 unless @driver
|
40
40
|
respond_to do |format|
|
41
41
|
format.xml { haml :"drivers/show" }
|
42
|
-
format.json { @driver.to_json }
|
42
|
+
format.json { { :driver => @driver.merge(:id => params[:id]) }.to_json }
|
43
43
|
format.html { haml :"drivers/show" }
|
44
44
|
end
|
45
45
|
end
|
@@ -66,7 +66,7 @@ module Deltacloud::Collections
|
|
66
66
|
respond_to do |format|
|
67
67
|
format.xml { haml :"firewalls/show" }
|
68
68
|
format.html { haml :"firewalls/show" }
|
69
|
-
format.json {
|
69
|
+
format.json { JSON::dump(:firewall => @firewall.to_hash(self)) }
|
70
70
|
end
|
71
71
|
end
|
72
72
|
end
|
@@ -109,7 +109,7 @@ module Deltacloud::Collections
|
|
109
109
|
respond_to do |format|
|
110
110
|
format.xml { haml :"firewalls/show" }
|
111
111
|
format.html { haml :"firewalls/show" }
|
112
|
-
format.json {
|
112
|
+
format.json { JSON::dump(:firewall => @firewall.to_hash(self) ) }
|
113
113
|
end
|
114
114
|
end
|
115
115
|
end
|
@@ -50,7 +50,7 @@ module Deltacloud::Collections
|
|
50
50
|
response['Location'] = image_url(@image.id)
|
51
51
|
respond_to do |format|
|
52
52
|
format.xml { haml :"images/show" }
|
53
|
-
format.json {
|
53
|
+
format.json { JSON::dump(:image => @image.to_hash(self)) }
|
54
54
|
format.html { haml :"images/show" }
|
55
55
|
end
|
56
56
|
end
|
@@ -60,7 +60,13 @@ module Deltacloud::Collections
|
|
60
60
|
status 201 # Created
|
61
61
|
respond_to do |format|
|
62
62
|
format.xml { haml :"instances/#{action_handler}" }
|
63
|
-
format.json
|
63
|
+
format.json do
|
64
|
+
if @elements
|
65
|
+
JSON::dump(:instances => @elements.map { |i| i.to_hash(self) })
|
66
|
+
elsif @instance and @instance.id
|
67
|
+
JSON::dump(:instance => @instance.to_hash(self))
|
68
|
+
end
|
69
|
+
end
|
64
70
|
format.html do
|
65
71
|
if @elements
|
66
72
|
haml :"instances/index"
|
@@ -42,7 +42,7 @@ module Deltacloud::Collections
|
|
42
42
|
respond_to do |format|
|
43
43
|
format.xml { haml :"keys/show", :ugly => true }
|
44
44
|
format.html { haml :"keys/show" }
|
45
|
-
format.json {
|
45
|
+
format.json { JSON::dump(:key => @key.to_hash(self)) }
|
46
46
|
end
|
47
47
|
end
|
48
48
|
end
|
@@ -41,7 +41,7 @@ module Deltacloud::Collections
|
|
41
41
|
@unregistered_instances = all_instances - @registered_instances
|
42
42
|
respond_to do |format|
|
43
43
|
format.xml { haml :'load_balancers/show' }
|
44
|
-
format.json {
|
44
|
+
format.json { JSON::dump(:load_balancer => @load_balancer.to_hash(self)) }
|
45
45
|
format.html { haml :'load_balancers/show' }
|
46
46
|
end
|
47
47
|
end
|
@@ -59,7 +59,7 @@ module Deltacloud::Collections
|
|
59
59
|
response['Location'] = load_balancer_url(@load_balancer.id)
|
60
60
|
respond_to do |format|
|
61
61
|
format.xml { haml :"load_balancers/show" }
|
62
|
-
format.json {
|
62
|
+
format.json { JSON::dump(:load_balancer => @load_balancer.to_hash(self)) }
|
63
63
|
format.html { redirect load_balancer_url(@load_balancer.id)}
|
64
64
|
end
|
65
65
|
end
|
@@ -73,7 +73,7 @@ module Deltacloud::Collections
|
|
73
73
|
@load_balancer = driver.load_balancer(credentials, :id => params[:id])
|
74
74
|
respond_to do |format|
|
75
75
|
format.xml { haml :'load_balancers/show' }
|
76
|
-
format.json {
|
76
|
+
format.json { JSON::dump(:load_balancer => @load_balancer.to_hash(self) ) }
|
77
77
|
format.html { redirect load_balancer_url(@load_balancer.id)}
|
78
78
|
end
|
79
79
|
end
|
@@ -87,7 +87,7 @@ module Deltacloud::Collections
|
|
87
87
|
@load_balancer = driver.load_balancer(credentials, :id => params[:id])
|
88
88
|
respond_to do |format|
|
89
89
|
format.xml { haml :'load_balancers/show' }
|
90
|
-
format.json {
|
90
|
+
format.json { JSON::dump(:load_balancer => @load_balancer.to_hash(self)) }
|
91
91
|
format.html { redirect load_balancer_url(@load_balancer.id) }
|
92
92
|
end
|
93
93
|
end
|
@@ -31,7 +31,11 @@ module Deltacloud::Collections
|
|
31
31
|
@storage_snapshot = driver.create_storage_snapshot(credentials, params)
|
32
32
|
status 201 # Created
|
33
33
|
response['Location'] = storage_snapshot_url(@storage_snapshot.id)
|
34
|
-
|
34
|
+
respond_to do |format|
|
35
|
+
format.xml { haml :"storage_snapshots/show" }
|
36
|
+
format.html { haml :"storage_snapshots/show" }
|
37
|
+
format.json { xml_to_json "storage_snapshots/show" }
|
38
|
+
end
|
35
39
|
end
|
36
40
|
end
|
37
41
|
|
@@ -16,6 +16,8 @@
|
|
16
16
|
module Deltacloud::Collections
|
17
17
|
class StorageVolumes < Base
|
18
18
|
|
19
|
+
include Deltacloud::Features
|
20
|
+
|
19
21
|
set :capability, lambda { |m| driver.respond_to? m }
|
20
22
|
check_features :for => lambda { |c, f| driver.class.has_feature?(c, f) }
|
21
23
|
|
@@ -37,6 +39,8 @@ module Deltacloud::Collections
|
|
37
39
|
param :snapshot_id, :string, :optional
|
38
40
|
param :capacity, :string, :optional
|
39
41
|
param :realm_id, :string, :optional
|
42
|
+
param :name, :string, :optional
|
43
|
+
param :description, :string, :optional
|
40
44
|
control do
|
41
45
|
@storage_volume = driver.create_storage_volume(credentials, params)
|
42
46
|
status 201
|
@@ -44,7 +48,7 @@ module Deltacloud::Collections
|
|
44
48
|
respond_to do |format|
|
45
49
|
format.xml { haml :"storage_volumes/show" }
|
46
50
|
format.html { haml :"storage_volumes/show" }
|
47
|
-
format.json {
|
51
|
+
format.json { JSON::dump(:storage_volume => @storage_volume.to_hash(self)) }
|
48
52
|
end
|
49
53
|
end
|
50
54
|
end
|
@@ -59,7 +63,7 @@ module Deltacloud::Collections
|
|
59
63
|
respond_to do |format|
|
60
64
|
format.html { redirect(storage_volume_url(params[:id]))}
|
61
65
|
format.xml { haml :"storage_volumes/show" }
|
62
|
-
format.json {
|
66
|
+
format.json { JSON::dump(:storage_volume => @storage_volume.to_hash(self)) }
|
63
67
|
end
|
64
68
|
end
|
65
69
|
end
|
@@ -75,7 +79,7 @@ module Deltacloud::Collections
|
|
75
79
|
respond_to do |format|
|
76
80
|
format.html { redirect(storage_volume_url(params[:id]))}
|
77
81
|
format.xml { haml :"storage_volumes/show" }
|
78
|
-
format.json {
|
82
|
+
format.json { JSON::dump(:storage_volume => @storage_volume.to_hash(self)) }
|
79
83
|
end
|
80
84
|
end
|
81
85
|
end
|
@@ -19,6 +19,7 @@ module Deltacloud
|
|
19
19
|
require_relative '../core_ext.rb'
|
20
20
|
require_relative './exceptions.rb'
|
21
21
|
require_relative './features.rb'
|
22
|
+
require_relative './cimi_features.rb'
|
22
23
|
require_relative '../models/state_machine.rb'
|
23
24
|
|
24
25
|
class BaseDriver
|
@@ -26,7 +27,7 @@ module Deltacloud
|
|
26
27
|
include Exceptions
|
27
28
|
|
28
29
|
STATE_MACHINE_OPTS = {
|
29
|
-
:all_states => [:start, :pending, :running, :stopping, :stopped, :finish],
|
30
|
+
:all_states => [:start, :pending, :running, :stopping, :stopped, :finish, :error],
|
30
31
|
:all_actions => [:create, :reboot, :stop, :start, :destroy]
|
31
32
|
} unless defined?(STATE_MACHINE_OPTS)
|
32
33
|
|
@@ -38,7 +39,6 @@ module Deltacloud
|
|
38
39
|
@features ||= {}
|
39
40
|
end
|
40
41
|
|
41
|
-
|
42
42
|
def self.feature(collection, feature_name)
|
43
43
|
return if has_feature?(collection, feature_name)
|
44
44
|
constraints[collection] ||= {}
|
@@ -60,6 +60,10 @@ module Deltacloud
|
|
60
60
|
features.has_key?(collection) and features[collection].include?(feature_name)
|
61
61
|
end
|
62
62
|
|
63
|
+
def has_feature?(collection, feature_name)
|
64
|
+
self.class.has_feature?(collection, feature_name)
|
65
|
+
end
|
66
|
+
|
63
67
|
def name
|
64
68
|
self.class.name.split('::').last.gsub('Driver', '').downcase
|
65
69
|
end
|
@@ -102,18 +106,15 @@ module Deltacloud
|
|
102
106
|
|
103
107
|
def find_hardware_profile(credentials, profile_id, image_id)
|
104
108
|
hwp = nil
|
105
|
-
if
|
109
|
+
if profile_id
|
106
110
|
unless hwp = hardware_profile(credentials, profile_id)
|
107
|
-
raise
|
108
|
-
"Hardware profile '#{name}' does not exist", nil)
|
111
|
+
raise Exceptions.exception_from_status(400, "Hardware profile '#{profile_id}' does not exists.")
|
109
112
|
end
|
110
113
|
else
|
111
114
|
unless image = image(credentials, :id=>image_id)
|
112
|
-
raise
|
113
|
-
"Image with ID '#{image_id}' does not exist", nil)
|
115
|
+
raise Exceptions.exception_from_status(400, "Image #{image_id} does not exists.")
|
114
116
|
end
|
115
|
-
hwp = hardware_profiles(credentials,
|
116
|
-
:architecture=>image.architecture).first
|
117
|
+
hwp = hardware_profiles(credentials, :architecture => image.architecture).first
|
117
118
|
end
|
118
119
|
return hwp
|
119
120
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# Licensed to the Apache Software Foundation (ASF) under one or more
|
2
|
+
# contributor license agreements. See the NOTICE file distributed with
|
3
|
+
# this work for additional information regarding copyright ownership. The
|
4
|
+
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
5
|
+
# "License"); you may not use this file except in compliance with the
|
6
|
+
# License. You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
12
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
13
|
+
# License for the specific language governing permissions and limitations
|
14
|
+
# under the License.
|
15
|
+
|
16
|
+
module CIMI
|
17
|
+
module Features
|
18
|
+
|
19
|
+
def self.included(k)
|
20
|
+
current_features = features
|
21
|
+
k.instance_eval do
|
22
|
+
features(¤t_features)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.features(&block)
|
27
|
+
block_given? ? @features = block : @features || Proc.new{}
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
features do
|
32
|
+
feature :default_initial_state, :for => :machines do
|
33
|
+
description "Indicates what the default initial state of a new Machine "
|
34
|
+
end
|
35
|
+
|
36
|
+
feature :initial_states, :for => :machines do
|
37
|
+
description "Indicates the list of allowable initial states"
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,307 @@
|
|
1
|
+
# Licensed to the Apache Software Foundation (ASF) under one or more
|
2
|
+
# contributor license agreements. See the NOTICE file distributed with
|
3
|
+
# this work for additional information regarding copyright ownership. The
|
4
|
+
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
5
|
+
# "License"); you may not use this file except in compliance with the
|
6
|
+
# License. You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
12
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
13
|
+
# License for the specific language governing permissions and limitations
|
14
|
+
# under the License.
|
15
|
+
|
16
|
+
require 'restclient'
|
17
|
+
|
18
|
+
module Deltacloud
|
19
|
+
module Drivers
|
20
|
+
module Digitalocean
|
21
|
+
class DigitaloceanDriver < Deltacloud::BaseDriver
|
22
|
+
|
23
|
+
feature :instances, :user_name
|
24
|
+
feature :images, :owner_id
|
25
|
+
|
26
|
+
define_hardware_profile '66' do
|
27
|
+
cpu 1
|
28
|
+
memory 512
|
29
|
+
storage 20 * 1024
|
30
|
+
architecture ['i386', 'x86_64']
|
31
|
+
end
|
32
|
+
|
33
|
+
define_hardware_profile '63' do
|
34
|
+
cpu 1
|
35
|
+
memory 1024
|
36
|
+
storage 30 * 1024
|
37
|
+
architecture ['i386', 'x86_64']
|
38
|
+
end
|
39
|
+
|
40
|
+
define_hardware_profile '62' do
|
41
|
+
cpu 2
|
42
|
+
memory 2 * 1024
|
43
|
+
storage 40 * 1024
|
44
|
+
architecture ['i386', 'x86_64']
|
45
|
+
end
|
46
|
+
|
47
|
+
define_hardware_profile '64' do
|
48
|
+
cpu 2
|
49
|
+
memory 4 * 1024
|
50
|
+
storage 60 * 1024
|
51
|
+
architecture ['i386', 'x86_64']
|
52
|
+
end
|
53
|
+
|
54
|
+
define_hardware_profile '65' do
|
55
|
+
cpu 4
|
56
|
+
memory 8 * 1024
|
57
|
+
storage 80 * 1024
|
58
|
+
architecture ['i386', 'x86_64']
|
59
|
+
end
|
60
|
+
|
61
|
+
define_hardware_profile '61' do
|
62
|
+
cpu 8
|
63
|
+
memory 16 * 1024
|
64
|
+
storage 160 * 1024
|
65
|
+
architecture ['i386', 'x86_64']
|
66
|
+
end
|
67
|
+
|
68
|
+
define_hardware_profile '60' do
|
69
|
+
cpu 12
|
70
|
+
memory 32 * 1024
|
71
|
+
storage 320 * 1024
|
72
|
+
architecture ['i386', 'x86_64']
|
73
|
+
end
|
74
|
+
|
75
|
+
define_hardware_profile '70' do
|
76
|
+
cpu 16
|
77
|
+
memory 48 * 1024
|
78
|
+
storage 480 * 1024
|
79
|
+
architecture ['i386', 'x86_64']
|
80
|
+
end
|
81
|
+
|
82
|
+
define_hardware_profile '69' do
|
83
|
+
cpu 16
|
84
|
+
memory 64 * 1024
|
85
|
+
storage 640 * 1024
|
86
|
+
architecture ['i386', 'x86_64']
|
87
|
+
end
|
88
|
+
|
89
|
+
define_hardware_profile '68' do
|
90
|
+
cpu 24
|
91
|
+
memory 96 * 1024
|
92
|
+
storage 960 * 1024
|
93
|
+
architecture ['i386', 'x86_64']
|
94
|
+
end
|
95
|
+
|
96
|
+
define_instance_states do
|
97
|
+
start.to( :pending ) .on( :create )
|
98
|
+
pending.to( :running ) .automatically
|
99
|
+
running.to( :running ) .on( :reboot )
|
100
|
+
running.to( :stopping ) .on( :stop )
|
101
|
+
running.to( :finish ) .on( :destroy )
|
102
|
+
stopped.to( :running ) .on( :start )
|
103
|
+
stopping.to( :stopped ) .automatically
|
104
|
+
stopped.to( :finish ) .automatically
|
105
|
+
error.from(:running, :pending, :stopping)
|
106
|
+
end
|
107
|
+
|
108
|
+
def realms(credentials, opts={})
|
109
|
+
safely do
|
110
|
+
new_client(credentials).get('regions')['regions'].map do |r|
|
111
|
+
Realm.new(
|
112
|
+
:id => r['id'],
|
113
|
+
:name => r['name'],
|
114
|
+
:state => 'AVAILABLE',
|
115
|
+
:limit => :unlimited
|
116
|
+
)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
# By default images will return list of 'all' images available
|
122
|
+
# to launch.
|
123
|
+
# With 'owner_id' you can filter them using 'global' and 'my_images'
|
124
|
+
# values to get less images.
|
125
|
+
#
|
126
|
+
def images(credentials, opts={})
|
127
|
+
unless opts[:id]
|
128
|
+
filter = opts[:owner_id] ? { :filter => opts[:owner_id] } : {}
|
129
|
+
img_arr = safely do
|
130
|
+
new_client(credentials).get('images', filter)['images'].map do |i|
|
131
|
+
convert_image(credentials, i)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
filter_on( img_arr, :architecture, opts )
|
135
|
+
else
|
136
|
+
safely do
|
137
|
+
[convert_image(
|
138
|
+
credentials,
|
139
|
+
new_client(credentials).get('images/%s' % opts[:id])['image']
|
140
|
+
)]
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
# You can only destroy images you own.
|
146
|
+
#
|
147
|
+
def destroy_image(credentials, image_id)
|
148
|
+
safely do
|
149
|
+
new_client(credentials).get('images/%s/destroy', image_id)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def instances(credentials, opts={})
|
154
|
+
inst_arr = safely do
|
155
|
+
new_client(credentials).get('droplets')['droplets'].map do |i|
|
156
|
+
convert_instance(credentials.user, i)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
filter_on inst_arr, :state, opts
|
160
|
+
end
|
161
|
+
|
162
|
+
def instance(credentials, opts={})
|
163
|
+
safely do
|
164
|
+
convert_instance(
|
165
|
+
credentials.user,
|
166
|
+
new_client(credentials).get("droplets/#{opts[:id]}")["droplet"]
|
167
|
+
)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def create_instance(credentials, image_id, opts={})
|
172
|
+
safely do
|
173
|
+
client = new_client(credentials)
|
174
|
+
args = { :image_id => image_id }
|
175
|
+
args.merge!(:region_id => opts[:realm_id]) if opts[:realm_id]
|
176
|
+
args.merge!(:size_id => opts[:hwp_id]) if opts[:hwp_id]
|
177
|
+
args.merge!(:name => opts[:name] || "inst#{Time.now.to_i}")
|
178
|
+
convert_instance(
|
179
|
+
credentials.user,
|
180
|
+
client.get("droplets/new", args)['droplet']
|
181
|
+
)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def destroy_instance(credentials, instance_id)
|
186
|
+
safely do
|
187
|
+
new_client(credentials).get("droplets/#{instance_id}/destroy/")
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def stop_instance(credentials, instance_id)
|
192
|
+
safely do
|
193
|
+
new_client(credentials).get("droplets/#{instance_id}/shutdown")
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def start_instance(credentials, instance_id)
|
198
|
+
safely do
|
199
|
+
new_client(credentials).get("droplets/#{instance_id}/power_on/")
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
def reboot_instance(credentials, instance_id)
|
204
|
+
safely do
|
205
|
+
new_client(credentials).get("droplets/#{instance_id}/reboot/")
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
exceptions do
|
210
|
+
|
211
|
+
on(/InternalServerError/) do
|
212
|
+
status 502
|
213
|
+
end
|
214
|
+
|
215
|
+
on(/No .*Found/) do
|
216
|
+
status 404
|
217
|
+
end
|
218
|
+
|
219
|
+
on(/An invalid/) do
|
220
|
+
status 400
|
221
|
+
end
|
222
|
+
|
223
|
+
end
|
224
|
+
|
225
|
+
private
|
226
|
+
|
227
|
+
class Client
|
228
|
+
|
229
|
+
API_URL = "https://api.digitalocean.com/"
|
230
|
+
attr_reader :credentials
|
231
|
+
|
232
|
+
def initialize(credentials)
|
233
|
+
@credentials = credentials
|
234
|
+
@resource = RestClient::Resource.new(API_URL)
|
235
|
+
end
|
236
|
+
|
237
|
+
def get(uri, opts={})
|
238
|
+
opts.merge!(
|
239
|
+
:client_id => credentials.user,
|
240
|
+
:api_key => credentials.password
|
241
|
+
)
|
242
|
+
result = @resource[uri].get(:params => opts)
|
243
|
+
json_result = JSON::parse(result)
|
244
|
+
if json_result['status'] != 'OK'
|
245
|
+
p result
|
246
|
+
error_message = json_result['error_message'] || json_result['status']
|
247
|
+
raise error_message
|
248
|
+
end
|
249
|
+
json_result
|
250
|
+
end
|
251
|
+
|
252
|
+
end
|
253
|
+
|
254
|
+
def new_client(credentials)
|
255
|
+
Client.new(credentials)
|
256
|
+
end
|
257
|
+
|
258
|
+
def extract_arch_from_name(name)
|
259
|
+
return 'x86_64' if name.include? 'x64'
|
260
|
+
return 'i386' if name.include? 'x32'
|
261
|
+
end
|
262
|
+
|
263
|
+
def convert_state(status)
|
264
|
+
case status
|
265
|
+
when 'active' then 'RUNNING'
|
266
|
+
when 'archive', 'new', 'pending' then 'PENDING'
|
267
|
+
when 'off' then 'STOPPED'
|
268
|
+
else status.upcase
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
def convert_instance(user, i)
|
273
|
+
state = convert_state(i['status'] || 'pending')
|
274
|
+
address = i['ip_address'].nil? ?
|
275
|
+
[] : [InstanceAddress.new(i['ip_address'])]
|
276
|
+
|
277
|
+
Instance.new(
|
278
|
+
:id => i['id'].to_s,
|
279
|
+
:name => i['name'],
|
280
|
+
:image_id => i['image_id'],
|
281
|
+
:realm_id => i['region_id'],
|
282
|
+
:instance_profile => InstanceProfile.new(i['size_id']),
|
283
|
+
:state => state,
|
284
|
+
:public_addresses => address,
|
285
|
+
:private_addresses => [],
|
286
|
+
:owner_id => user,
|
287
|
+
:create_image => false,
|
288
|
+
:actions => instance_actions_for(state)
|
289
|
+
)
|
290
|
+
end
|
291
|
+
|
292
|
+
def convert_image(credentials, i)
|
293
|
+
Image.new(
|
294
|
+
:id => i['id'].to_s,
|
295
|
+
:name => i['name'],
|
296
|
+
:description => i['distribution'],
|
297
|
+
:owner_id => 'global',
|
298
|
+
:state => 'AVAILABLE',
|
299
|
+
:architecture => extract_arch_from_name(i['name']),
|
300
|
+
:hardware_profiles => hardware_profiles(credentials)
|
301
|
+
)
|
302
|
+
end
|
303
|
+
|
304
|
+
end
|
305
|
+
end
|
306
|
+
end
|
307
|
+
end
|