deltacloud-core 0.4.1 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +63 -7
- data/bin/deltacloudd +29 -17
- data/config.ru +5 -3
- data/config/drivers/ec2.yaml +9 -0
- data/config/drivers/google.yaml +3 -0
- data/config/drivers/openstack.yaml +3 -0
- data/deltacloud-core.gemspec +1 -1
- data/lib/cimi/dependencies.rb +62 -0
- data/lib/cimi/helpers/cimi_helper.rb +50 -0
- data/lib/cimi/model.rb +52 -0
- data/lib/cimi/model/action.rb +24 -0
- data/lib/cimi/model/base.rb +249 -0
- data/lib/cimi/model/cloud_entry_point.rb +48 -0
- data/lib/cimi/model/entity_metadata.rb +83 -0
- data/lib/cimi/model/entity_metadata_collection.rb +31 -0
- data/lib/cimi/model/errors.rb +40 -0
- data/lib/cimi/model/machine.rb +227 -0
- data/lib/cimi/model/machine_admin.rb +59 -0
- data/lib/cimi/model/machine_admin_collection.rb +34 -0
- data/lib/cimi/model/machine_collection.rb +34 -0
- data/lib/cimi/model/machine_configuration.rb +67 -0
- data/lib/cimi/model/machine_configuration_collection.rb +34 -0
- data/lib/cimi/model/machine_image.rb +46 -0
- data/lib/cimi/model/machine_image_collection.rb +34 -0
- data/lib/cimi/model/machine_template.rb +41 -0
- data/lib/cimi/model/machine_template_collection.rb +34 -0
- data/lib/cimi/model/network.rb +69 -0
- data/lib/cimi/model/network_collection.rb +34 -0
- data/lib/cimi/model/network_configuration.rb +50 -0
- data/lib/cimi/model/network_configuration_collection.rb +34 -0
- data/lib/cimi/model/network_template.rb +26 -0
- data/lib/cimi/model/schema.rb +277 -0
- data/lib/cimi/model/volume.rb +103 -0
- data/lib/cimi/model/volume_collection.rb +34 -0
- data/lib/cimi/model/volume_configuration.rb +60 -0
- data/lib/cimi/model/volume_configuration_collection.rb +34 -0
- data/lib/cimi/model/volume_image.rb +49 -0
- data/lib/cimi/model/volume_image_collection.rb +34 -0
- data/lib/cimi/model/volume_template.rb +23 -0
- data/lib/cimi/model/volume_template_collection.rb +34 -0
- data/lib/cimi/server.rb +575 -0
- data/lib/deltacloud/base_driver/base_driver.rb +11 -1
- data/lib/deltacloud/core_ext.rb +2 -0
- data/lib/deltacloud/core_ext/array.rb +25 -0
- data/lib/deltacloud/core_ext/hash.rb +7 -0
- data/lib/deltacloud/core_ext/proc.rb +31 -0
- data/lib/deltacloud/core_ext/string.rb +15 -0
- data/lib/deltacloud/drivers/condor/condor_driver.rb +2 -1
- data/lib/deltacloud/drivers/ec2/ec2_driver.rb +32 -10
- data/lib/deltacloud/drivers/eucalyptus/eucalyptus_driver.rb +1 -1
- data/lib/deltacloud/drivers/gogrid/gogrid_driver.rb +1 -1
- data/lib/deltacloud/drivers/google/google_driver.rb +233 -0
- data/lib/deltacloud/drivers/mock/data/instances/inst0.yml +7 -2
- data/lib/deltacloud/drivers/mock/data/instances/inst1.yml +7 -2
- data/lib/deltacloud/drivers/mock/data/instances/inst2.yml +7 -2
- data/lib/deltacloud/drivers/mock/mock_client.rb +17 -0
- data/lib/deltacloud/drivers/mock/mock_driver.rb +82 -8
- data/lib/deltacloud/drivers/opennebula/opennebula_driver.rb +1 -1
- data/lib/deltacloud/drivers/openstack/openstack_driver.rb +47 -0
- data/lib/deltacloud/drivers/rackspace/rackspace_driver.rb +8 -8
- data/lib/deltacloud/drivers/rhevm/rhevm_client.rb +122 -49
- data/lib/deltacloud/drivers/rhevm/rhevm_driver.rb +42 -22
- data/lib/deltacloud/drivers/rimuhosting/rimuhosting_driver.rb +1 -1
- data/lib/deltacloud/drivers/sbc/sbc_driver.rb +3 -2
- data/lib/deltacloud/drivers/terremark/terremark_driver.rb +2 -2
- data/lib/deltacloud/drivers/vsphere/vsphere_client.rb +25 -4
- data/lib/deltacloud/drivers/vsphere/vsphere_driver.rb +35 -12
- data/lib/deltacloud/hardware_profile.rb +34 -10
- data/lib/deltacloud/helpers/application_helper.rb +3 -28
- data/lib/deltacloud/helpers/blob_stream.rb +2 -1
- data/lib/deltacloud/models.rb +2 -0
- data/lib/deltacloud/models/bucket.rb +1 -1
- data/lib/deltacloud/models/image.rb +1 -1
- data/lib/deltacloud/models/instance.rb +2 -1
- data/lib/deltacloud/models/instance_address.rb +56 -0
- data/lib/deltacloud/models/provider.rb +27 -0
- data/{server.rb → lib/deltacloud/server.rb} +72 -14
- data/lib/deltacloud/validation.rb +31 -10
- data/lib/sinatra/rabbit.rb +34 -26
- data/lib/sinatra/rack_accept.rb +5 -5
- data/lib/sinatra/rack_matrix_params.rb +6 -2
- data/lib/sinatra/rack_syslog.rb +3 -3
- data/lib/sinatra/static_assets.rb +1 -1
- data/lib/sinatra/url_for.rb +1 -7
- data/public/images/bread-bg.png +0 -0
- data/public/images/logo-wide.png +0 -0
- data/public/images/topbar-bg.png +0 -0
- data/public/javascripts/application.js +5 -0
- data/public/javascripts/cmwgapp.js +249 -0
- data/public/javascripts/jquery-1.4.2.min.js +154 -0
- data/public/javascripts/jquery.mobile-1.0rc1.min.js +170 -0
- data/public/stylesheets/images/icons-18-black.png +0 -0
- data/public/stylesheets/images/icons-18-white.png +0 -0
- data/public/stylesheets/images/icons-36-black.png +0 -0
- data/public/stylesheets/images/icons-36-white.png +0 -0
- data/public/stylesheets/jquery.mobile-1.0rc1.min.css +12 -0
- data/public/stylesheets/new.css +4 -0
- data/support/fedora/deltacloud-core.init +20 -13
- data/tests/cimi/features/step_definitions/common_steps.rb +59 -0
- data/tests/cimi/features/step_definitions/machine_images_steps.rb +0 -0
- data/tests/cimi/features/step_definitions/machines_steps.rb +99 -0
- data/tests/cimi/features/step_definitions/volumes_steps.rb +115 -0
- data/tests/cimi/features/support/env.rb +53 -0
- data/tests/common.rb +89 -11
- data/tests/core_ext/string.rb +31 -0
- data/tests/drivers/google/api_test.rb +35 -0
- data/tests/drivers/google/buckets_test.rb +116 -0
- data/tests/drivers/google/setup.rb +38 -0
- data/tests/drivers/mock/instances_test.rb +20 -5
- data/tests/drivers/openstack/api_test.rb +41 -0
- data/tests/drivers/openstack/hardware_profiles_test.rb +53 -0
- data/tests/drivers/openstack/images_test.rb +40 -0
- data/tests/drivers/openstack/instances_test.rb +163 -0
- data/tests/drivers/openstack/realms_test.rb +36 -0
- data/tests/drivers/openstack/setup.rb +20 -0
- data/tests/drivers/rackspace/buckets_test.rb +145 -0
- data/tests/drivers/rackspace/setup.rb +3 -3
- data/tests/drivers/rhevm/api_test.rb +1 -1
- data/tests/drivers/rhevm/images_test.rb +2 -2
- data/tests/drivers/rhevm/instances_test.rb +10 -12
- data/tests/drivers/rhevm/realms_test.rb +4 -4
- data/tests/drivers/rhevm/setup.rb +3 -3
- data/tests/rabbit_test.rb +1 -1
- data/views/api/show.html.haml +13 -0
- data/views/cimi/cloudEntryPoint/index.html.haml +5 -0
- data/views/cimi/cloudEntryPoint/index.xml.haml +9 -0
- data/views/cimi/collection/index.html.haml +45 -0
- data/views/cimi/collection/response.xml.haml +3 -0
- data/views/cimi/error.html.haml +31 -0
- data/views/cimi/errors/400.html.haml +41 -0
- data/views/cimi/errors/400.xml.haml +3 -0
- data/views/cimi/errors/401.html.haml +41 -0
- data/views/cimi/errors/401.xml.haml +2 -0
- data/views/cimi/errors/403.html.haml +42 -0
- data/views/cimi/errors/403.xml.haml +2 -0
- data/views/cimi/errors/404.html.haml +29 -0
- data/views/cimi/errors/404.xml.haml +2 -0
- data/views/cimi/errors/405.html.haml +29 -0
- data/views/cimi/errors/405.xml.haml +5 -0
- data/views/cimi/errors/500.html.haml +43 -0
- data/views/cimi/errors/500.xml.haml +6 -0
- data/views/cimi/errors/502.html.haml +43 -0
- data/views/cimi/errors/502.xml.haml +7 -0
- data/views/cimi/errors/backend_capability_failure.html.haml +29 -0
- data/views/cimi/layout.html.haml +32 -0
- data/views/cimi/machine_configurations/show.html.haml +159 -0
- data/views/cimi/machine_configurations/show.xml.haml +27 -0
- data/views/cimi/machine_images/show.html.haml +79 -0
- data/views/cimi/machine_images/show.xml.haml +17 -0
- data/views/cimi/machines/show.html.haml +177 -0
- data/views/cimi/machines/show.xml.haml +28 -0
- data/views/cimi/volumes/show.html.haml +68 -0
- data/views/cimi/volumes/show.xml.haml +17 -0
- data/views/drivers/show.html.haml +10 -5
- data/views/drivers/show.xml.haml +9 -4
- data/views/error.html.haml +2 -2
- data/views/errors/500.xml.haml +7 -1
- data/views/instances/index.html.haml +1 -1
- data/views/instances/new.html.haml +19 -16
- data/views/instances/show.html.haml +7 -2
- data/views/instances/show.xml.haml +8 -7
- data/views/layout.html.haml +2 -2
- data/views/storage_volumes/show.html.haml +1 -1
- metadata +296 -204
- data/public/javascripts/jquery.mobile-1.0b1.min.js +0 -146
- data/public/stylesheets/jquery.mobile-1.0b1.min.css +0 -8
@@ -14,7 +14,7 @@
|
|
14
14
|
# License for the specific language governing permissions and limitations
|
15
15
|
# under the License.
|
16
16
|
|
17
|
-
require '
|
17
|
+
require 'deltacloud/base_driver/exceptions'
|
18
18
|
|
19
19
|
module Deltacloud
|
20
20
|
|
@@ -22,6 +22,10 @@ module Deltacloud
|
|
22
22
|
|
23
23
|
include ExceptionHandler
|
24
24
|
|
25
|
+
def name
|
26
|
+
self.class.name.split('::').last.gsub('Driver', '').downcase
|
27
|
+
end
|
28
|
+
|
25
29
|
def self.exceptions(&block)
|
26
30
|
ExceptionHandler::exceptions(&block)
|
27
31
|
end
|
@@ -155,6 +159,7 @@ module Deltacloud
|
|
155
159
|
# def delete_firewall(credentials, opts)
|
156
160
|
# def create_firewall_rule(credentials, opts)
|
157
161
|
# def delete_firewall_rule(credentials, opts)
|
162
|
+
# def providers(credentials)
|
158
163
|
def realm(credentials, opts)
|
159
164
|
realms = realms(credentials, opts).first if has_capability?(:realms)
|
160
165
|
end
|
@@ -230,6 +235,11 @@ module Deltacloud
|
|
230
235
|
Thread.current[:provider] || ENV['API_PROVIDER']
|
231
236
|
end
|
232
237
|
|
238
|
+
# Return an array of the providers statically configured
|
239
|
+
# in the driver's YAML file
|
240
|
+
def configured_providers
|
241
|
+
[]
|
242
|
+
end
|
233
243
|
end
|
234
244
|
|
235
245
|
end
|
data/lib/deltacloud/core_ext.rb
CHANGED
@@ -0,0 +1,25 @@
|
|
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
|
+
class Array
|
17
|
+
def expand_opts!(more_opts)
|
18
|
+
self << {} unless last.is_a?(Hash)
|
19
|
+
last.update(more_opts)
|
20
|
+
end
|
21
|
+
|
22
|
+
def extract_opts!
|
23
|
+
last.is_a?(Hash) ? pop : {}
|
24
|
+
end
|
25
|
+
end
|
@@ -26,4 +26,11 @@ class Hash
|
|
26
26
|
#remove the original keys
|
27
27
|
self.delete_if{|k,v| remove.include?(k)}
|
28
28
|
end
|
29
|
+
|
30
|
+
# Method copied from https://github.com/rails/rails/blob/77efc20a54708ba37ba679ffe90021bf8a8d3a8a/activesupport/lib/active_support/core_ext/hash/keys.rb#L23
|
31
|
+
def symbolize_keys
|
32
|
+
keys.each { |key| self[(key.to_sym rescue key) || key] = delete(key) }
|
33
|
+
self
|
34
|
+
end
|
35
|
+
|
29
36
|
end
|
@@ -0,0 +1,31 @@
|
|
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
|
+
# Original code copied from https://gist.github.com/1417762
|
17
|
+
# Copyright 2011 Emmanuel Oga.
|
18
|
+
|
19
|
+
class Proc
|
20
|
+
|
21
|
+
Callback = Struct.new(:called, :args) do
|
22
|
+
def method_missing(name, *)
|
23
|
+
name == :"#{called}?" || (name == called && block_given? && yield(*args))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def callback(callable, *args)
|
28
|
+
call Callback.new(callable, *args)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -34,6 +34,8 @@ class String
|
|
34
34
|
|
35
35
|
def pluralize
|
36
36
|
return self + 'es' if self =~ /ess$/
|
37
|
+
return self[0, self.length-1] + "ies" if self =~ /ty$/
|
38
|
+
return self if self =~ /data$/
|
37
39
|
self + "s"
|
38
40
|
end
|
39
41
|
|
@@ -49,4 +51,17 @@ class String
|
|
49
51
|
tr("-", "_").
|
50
52
|
downcase
|
51
53
|
end
|
54
|
+
|
55
|
+
def camelize(lowercase_first_letter=nil)
|
56
|
+
s = split('_').map { |w| w.capitalize }.join
|
57
|
+
lowercase_first_letter ? s.uncapitalize : s
|
58
|
+
end
|
59
|
+
|
60
|
+
def uncapitalize
|
61
|
+
self[0, 1].downcase + self[1..-1]
|
62
|
+
end
|
63
|
+
|
64
|
+
def upcase_first
|
65
|
+
self[0, 1].upcase + self[1..-1]
|
66
|
+
end
|
52
67
|
end
|
@@ -105,7 +105,8 @@ module Deltacloud
|
|
105
105
|
:realm_id => 'default',
|
106
106
|
:instance_profile => InstanceProfile::new(instance.instance_profile.name),
|
107
107
|
:image_id => instance.image_id,
|
108
|
-
:public_addresses => [ ip_address ],
|
108
|
+
:public_addresses => [ InstanceAddress.new(ip_address) ],
|
109
|
+
:private_addresses => [],
|
109
110
|
:owner_id => instance.owner_id,
|
110
111
|
:description => instance.name,
|
111
112
|
:architecture => 'x86_64',
|
@@ -51,7 +51,7 @@ module Deltacloud
|
|
51
51
|
cpu 1
|
52
52
|
memory 0.63 * 1024
|
53
53
|
storage 160
|
54
|
-
architecture 'i386'
|
54
|
+
architecture ['i386','x86_64']
|
55
55
|
end
|
56
56
|
|
57
57
|
define_hardware_profile('m1.small') do
|
@@ -134,7 +134,7 @@ module Deltacloud
|
|
134
134
|
opts ||= {}
|
135
135
|
if opts[:id]
|
136
136
|
safely do
|
137
|
-
img_arr = ec2.describe_images(opts[:id]).collect do |image|
|
137
|
+
img_arr = ec2.describe_images([opts[:id]]).collect do |image|
|
138
138
|
convert_image(image)
|
139
139
|
end
|
140
140
|
end
|
@@ -142,7 +142,7 @@ module Deltacloud
|
|
142
142
|
end
|
143
143
|
owner_id = opts[:owner_id] || default_image_owner
|
144
144
|
safely do
|
145
|
-
img_arr = ec2.describe_images_by_owner(owner_id, default_image_type).collect do |image|
|
145
|
+
img_arr = ec2.describe_images_by_owner([owner_id], default_image_type).collect do |image|
|
146
146
|
convert_image(image)
|
147
147
|
end
|
148
148
|
end
|
@@ -231,8 +231,14 @@ module Deltacloud
|
|
231
231
|
}]
|
232
232
|
end
|
233
233
|
safely do
|
234
|
-
|
235
|
-
|
234
|
+
new_instances = ec2.launch_instances(image_id, instance_options).collect do |i|
|
235
|
+
convert_instance(i)
|
236
|
+
end
|
237
|
+
if new_instances.size == 1
|
238
|
+
new_instances.first
|
239
|
+
else
|
240
|
+
new_instances
|
241
|
+
end
|
236
242
|
end
|
237
243
|
end
|
238
244
|
|
@@ -372,7 +378,8 @@ module Deltacloud
|
|
372
378
|
safely do
|
373
379
|
s3_client = new_client(credentials, :s3)
|
374
380
|
bucket_location = opts['location']
|
375
|
-
if (bucket_location && bucket_location.size >0
|
381
|
+
if (bucket_location && bucket_location.size >0 &&
|
382
|
+
(not bucket_location.eql?(DEFAULT_REGION)) )
|
376
383
|
bucket = Aws::S3::Bucket.create(s3_client, name, true, nil, :location => bucket_location)
|
377
384
|
else
|
378
385
|
bucket = Aws::S3::Bucket.create(s3_client, name, true)
|
@@ -694,6 +701,16 @@ module Deltacloud
|
|
694
701
|
end
|
695
702
|
end
|
696
703
|
|
704
|
+
def providers(credentials, opts={})
|
705
|
+
ec2 = new_client(credentials)
|
706
|
+
providers = ec2.describe_regions.map{|r| Provider.new( {:id=>r, :name=>r,
|
707
|
+
:url=>"#{ENV['API_HOST']}:#{ENV['API_PORT']}#{settings.root_url}\;provider=#{r}" }) }
|
708
|
+
end
|
709
|
+
|
710
|
+
def configured_providers
|
711
|
+
Deltacloud::Drivers::driver_config[:ec2][:entrypoints]["ec2"].keys
|
712
|
+
end
|
713
|
+
|
697
714
|
def valid_credentials?(credentials)
|
698
715
|
retval = true
|
699
716
|
begin
|
@@ -778,7 +795,11 @@ module Deltacloud
|
|
778
795
|
|
779
796
|
def convert_instance(instance)
|
780
797
|
can_create_image = 'ebs'.eql?(instance[:root_device_type]) and 'RUNNING'.eql?(convert_state(instance[:aws_state]))
|
781
|
-
|
798
|
+
inst_profile_opts={}
|
799
|
+
if instance[:aws_instance_type] == "t1.micro"
|
800
|
+
inst_profile_opts[:hwp_architecture]=instance[:architecture]
|
801
|
+
end
|
802
|
+
Instance.new(
|
782
803
|
:id => instance[:aws_instance_id],
|
783
804
|
:name => instance[:aws_image_id],
|
784
805
|
:state => convert_state(instance[:aws_state]),
|
@@ -787,11 +808,12 @@ module Deltacloud
|
|
787
808
|
:actions => instance_actions_for(convert_state(instance[:aws_state])),
|
788
809
|
:keyname => instance[:ssh_key_name],
|
789
810
|
:launch_time => instance[:aws_launch_time],
|
790
|
-
:instance_profile => InstanceProfile.new(instance[:aws_instance_type]),
|
811
|
+
:instance_profile => InstanceProfile.new(instance[:aws_instance_type], inst_profile_opts),
|
791
812
|
:realm_id => instance[:aws_availability_zone],
|
792
|
-
:
|
793
|
-
:
|
813
|
+
:public_addresses => [InstanceAddress.new(instance[:dns_name], :type => :hostname)],
|
814
|
+
:private_addresses => [InstanceAddress.new(instance[:private_dns_name], :type => :hostname)],
|
794
815
|
:firewalls => instance[:aws_groups],
|
816
|
+
:storage_volumes => instance[:block_device_mappings].map{|vol| {vol.values.first=>vol.keys.first } },
|
795
817
|
:create_image => can_create_image
|
796
818
|
)
|
797
819
|
end
|
@@ -471,7 +471,7 @@ class GogridDriver < Deltacloud::BaseDriver
|
|
471
471
|
:realm_id => instance['ip']['datacenter']['id'],
|
472
472
|
:state => state,
|
473
473
|
:actions => instance_actions_for(state),
|
474
|
-
:public_addresses => [ instance['ip']['ip'] ],
|
474
|
+
:public_addresses => [ InstanceAddress.new(instance['ip']['ip']) ],
|
475
475
|
:private_addresses => [],
|
476
476
|
:username => instance['username'],
|
477
477
|
:password => instance['password'],
|
@@ -0,0 +1,233 @@
|
|
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 'fog'
|
17
|
+
|
18
|
+
module Deltacloud
|
19
|
+
module Drivers
|
20
|
+
module Google
|
21
|
+
|
22
|
+
class GoogleDriver < Deltacloud::BaseDriver
|
23
|
+
|
24
|
+
def supported_collections; [:buckets]
|
25
|
+
end
|
26
|
+
|
27
|
+
feature :buckets, :bucket_location
|
28
|
+
|
29
|
+
#--
|
30
|
+
# Buckets
|
31
|
+
#--
|
32
|
+
def buckets(credentials, opts={})
|
33
|
+
buckets = []
|
34
|
+
google_client = new_client(credentials)
|
35
|
+
safely do
|
36
|
+
if opts[:id]
|
37
|
+
bucket = google_client.get_bucket(opts[:id])
|
38
|
+
buckets << convert_bucket(bucket.body)
|
39
|
+
else
|
40
|
+
google_client.get_service.body['Buckets'].each do |bucket|
|
41
|
+
buckets << Bucket.new({:name => bucket['Name'], :id => bucket['Name']})
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
buckets = filter_on(buckets, :id, opts)
|
46
|
+
end
|
47
|
+
|
48
|
+
#--
|
49
|
+
# Create bucket - valid values for location {'EU','US'}
|
50
|
+
#--
|
51
|
+
def create_bucket(credentials, name, opts={})
|
52
|
+
google_client = new_client(credentials)
|
53
|
+
safely do
|
54
|
+
bucket_location = opts['location']
|
55
|
+
if (bucket_location && bucket_location.size > 0)
|
56
|
+
res = google_client.put_bucket(name, {"LocationConstraint" => opts['location']})
|
57
|
+
else
|
58
|
+
google_client.put_bucket(name)
|
59
|
+
end
|
60
|
+
#res.status should be eql 200 - but fog will explode if not all ok...
|
61
|
+
Bucket.new({ :id => name,
|
62
|
+
:name => name,
|
63
|
+
:size => 0,
|
64
|
+
:blob_list => [] })
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
#--
|
69
|
+
# Delete bucket
|
70
|
+
#--
|
71
|
+
def delete_bucket(credentials, name, opts={})
|
72
|
+
google_client = new_client(credentials)
|
73
|
+
safely do
|
74
|
+
google_client.delete_bucket(name)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
#--
|
79
|
+
# Blobs
|
80
|
+
#--
|
81
|
+
def blobs(credentials, opts={})
|
82
|
+
blobs = []
|
83
|
+
google_client = new_client(credentials)
|
84
|
+
safely do
|
85
|
+
google_blob = google_client.head_object(opts['bucket'], opts[:id]).headers
|
86
|
+
meta_hash = google_blob.inject({}){|result, (k,v)| result[k]=v if k=~/^x-goog-meta-/i ; result}
|
87
|
+
meta_hash.gsub_keys("x-goog-meta-", "")
|
88
|
+
blobs << Blob.new({ :id => opts[:id],
|
89
|
+
:bucket => opts['bucket'],
|
90
|
+
:content_length => google_blob['Content-Length'],
|
91
|
+
:content_type => google_blob['Content-Type'],
|
92
|
+
:last_modified => google_blob['Last-Modified'],
|
93
|
+
:user_metadata => meta_hash
|
94
|
+
})
|
95
|
+
|
96
|
+
end
|
97
|
+
blobs
|
98
|
+
end
|
99
|
+
|
100
|
+
def blob_data(credentials, bucket_id, blob_id, opts={})
|
101
|
+
google_client = new_client(credentials)
|
102
|
+
safely do
|
103
|
+
google_client.get_object(bucket_id, blob_id) do |chunk|
|
104
|
+
yield chunk
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
#--
|
110
|
+
# Create Blob
|
111
|
+
#--
|
112
|
+
def create_blob(credentials, bucket_id, blob_id, blob_data, opts={})
|
113
|
+
google_client = new_client(credentials)
|
114
|
+
safely do
|
115
|
+
dcloud_blob_metadata = BlobHelper::extract_blob_metadata_hash(opts)
|
116
|
+
BlobHelper::rename_metadata_headers(opts, 'x-goog-meta-')
|
117
|
+
opts['Content-Type'] = blob_data[:type]
|
118
|
+
google_client.put_object(bucket_id, blob_id, blob_data[:tempfile], opts)
|
119
|
+
Blob.new({ :id => blob_id,
|
120
|
+
:bucket => bucket_id,
|
121
|
+
:content_length => File.size(blob_data[:tempfile]).to_s,
|
122
|
+
:content_type => blob_data[:type],
|
123
|
+
:last_modified => "",
|
124
|
+
:user_metadata => dcloud_blob_metadata })
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
#params: {:user,:password,:bucket,:blob,:content_type,:content_length,:metadata}
|
129
|
+
def blob_stream_connection(params)
|
130
|
+
client = Fog::Storage.new({:provider => :google, :google_storage_access_key_id => params[:user],
|
131
|
+
:google_storage_secret_access_key => params[:password]})
|
132
|
+
google_request_uri = "https://#{client.instance_variable_get(:@host)}"
|
133
|
+
uri = URI.parse(google_request_uri)
|
134
|
+
conn_params = {} # build hash for the Fog signature method
|
135
|
+
conn_params[:headers] = {} #put the metadata here
|
136
|
+
conn_params[:host] = uri.host
|
137
|
+
conn_params[:path] = "#{params[:bucket]}/#{CGI.escape(params[:blob])}"
|
138
|
+
conn_params[:method] = "PUT"
|
139
|
+
timestamp = Fog::Time.now.to_date_header
|
140
|
+
conn_params[:headers]['Date'] = timestamp
|
141
|
+
conn_params[:headers]['Content-Type'] = params[:content_type]
|
142
|
+
metadata = params[:metadata] || {}
|
143
|
+
BlobHelper::rename_metadata_headers(metadata, 'x-goog-meta-')
|
144
|
+
metadata.each{|k,v| conn_params[:headers][k]=v}
|
145
|
+
auth_string = "GOOG1 #{params[:user]}:#{client.signature(conn_params)}"
|
146
|
+
|
147
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
148
|
+
http.use_ssl = true
|
149
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
150
|
+
request = Net::HTTP::Put.new("/#{conn_params[:path]}")
|
151
|
+
request['Host'] = conn_params[:host]
|
152
|
+
request['Date'] = conn_params[:headers]['Date']
|
153
|
+
request['Content-Type'] = conn_params[:headers]['Content-Type']
|
154
|
+
request['Content-Length'] = params[:content_length]
|
155
|
+
request['Authorization'] = auth_string
|
156
|
+
metadata.each{|k,v| request[k] = v}
|
157
|
+
return http, request
|
158
|
+
end
|
159
|
+
|
160
|
+
#--
|
161
|
+
# Delete Blob
|
162
|
+
#--
|
163
|
+
def delete_blob(credentials, bucket_id, blob_id, opts={})
|
164
|
+
google_client = new_client(credentials)
|
165
|
+
safely do
|
166
|
+
google_client.delete_object(bucket_id, blob_id)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
#-
|
171
|
+
# Blob Metadada
|
172
|
+
#-
|
173
|
+
def blob_metadata(credentials, opts = {})
|
174
|
+
google_client = new_client(credentials)
|
175
|
+
safely do
|
176
|
+
google_blob = google_client.head_object(opts['bucket'], opts[:id]).headers
|
177
|
+
meta_hash = google_blob.inject({}){|result, (k,v)| result[k]=v if k=~/^x-goog-meta-/i ; result}
|
178
|
+
meta_hash.gsub_keys("x-goog-meta-", "")
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
#-
|
183
|
+
# Update Blob Metadata
|
184
|
+
#-
|
185
|
+
def update_blob_metadata(credentials, opts={})
|
186
|
+
google_client = new_client(credentials)
|
187
|
+
safely do
|
188
|
+
meta_hash = BlobHelper::rename_metadata_headers(opts['meta_hash'], 'x-goog-meta-')
|
189
|
+
options = {'x-goog-metadata-directive'=>'REPLACE'}
|
190
|
+
options.merge!(meta_hash)
|
191
|
+
bucket = opts['bucket']
|
192
|
+
blob = opts[:id]
|
193
|
+
google_client.copy_object(bucket, blob, bucket, blob, options) #source,source,target,target,options
|
194
|
+
meta_hash.gsub_keys("x-goog-meta-", "")
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
def valid_credentials?(credentials)
|
199
|
+
begin
|
200
|
+
new_client(credentials)
|
201
|
+
rescue
|
202
|
+
return false
|
203
|
+
end
|
204
|
+
return true
|
205
|
+
end
|
206
|
+
|
207
|
+
private
|
208
|
+
|
209
|
+
def new_client(credentials)
|
210
|
+
safely do
|
211
|
+
Fog::Storage.new({ :provider => :google, :google_storage_access_key_id => credentials.user,
|
212
|
+
:google_storage_secret_access_key => credentials.password})
|
213
|
+
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
def convert_bucket(bucket)
|
218
|
+
blob_list = []
|
219
|
+
bucket['Contents'].each do |blob|
|
220
|
+
blob_list << blob['Key']
|
221
|
+
end
|
222
|
+
Bucket.new({ :id => bucket['Name'],
|
223
|
+
:name => bucket['Name'],
|
224
|
+
:size => blob_list.size,
|
225
|
+
:blob_list => blob_list
|
226
|
+
})
|
227
|
+
end
|
228
|
+
|
229
|
+
end
|
230
|
+
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|