deltacloud-core 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +145 -0
- data/NOTICE +10 -1
- data/Rakefile +50 -2
- data/bin/deltacloudd +111 -14
- data/config/addresses.xml +14 -0
- data/config/condor.yaml +30 -0
- data/config/drivers/azure.yaml +3 -0
- data/config/drivers/condor.yaml +3 -0
- data/config/{drivers.yaml → drivers/ec2.yaml} +5 -34
- data/config/drivers/eucalyptus.yaml +8 -0
- data/config/drivers/gogrid.yaml +3 -0
- data/config/drivers/mock.yaml +3 -0
- data/config/drivers/opennebula.yaml +4 -0
- data/config/drivers/rackspace.yaml +3 -0
- data/config/drivers/rhevm.yaml +3 -0
- data/config/drivers/rimuhosting.yaml +3 -0
- data/config/drivers/sbc.yaml +2 -0
- data/config/drivers/terremark.yaml +3 -0
- data/config/drivers/vsphere.yaml +8 -0
- data/deltacloud-core.gemspec +13 -5
- data/deltacloud.rb +4 -2
- data/lib/deltacloud/backend_capability.rb +2 -2
- data/lib/deltacloud/base_driver/base_driver.rb +23 -52
- data/lib/deltacloud/base_driver/exceptions.rb +168 -0
- data/lib/deltacloud/base_driver/features.rb +31 -12
- data/lib/deltacloud/base_driver/mock_driver.rb +2 -1
- data/lib/deltacloud/core_ext/string.rb +2 -0
- data/lib/deltacloud/drivers/azure/azure_driver.rb +5 -5
- data/lib/deltacloud/drivers/condor/condor_client.rb +273 -0
- data/lib/deltacloud/drivers/condor/condor_driver.rb +236 -0
- data/lib/deltacloud/drivers/condor/ip_agents/confserver.rb +75 -0
- data/lib/deltacloud/drivers/condor/ip_agents/default.rb +84 -0
- data/lib/deltacloud/drivers/ec2/ec2_driver.rb +326 -95
- data/lib/deltacloud/drivers/ec2/ec2_mock_driver.rb +3 -3
- data/lib/deltacloud/drivers/eucalyptus/eucalyptus_driver.rb +40 -8
- data/lib/deltacloud/drivers/gogrid/gogrid_client.rb +7 -7
- data/lib/deltacloud/drivers/gogrid/gogrid_driver.rb +42 -25
- data/lib/deltacloud/drivers/mock/data/{buckets/blobs → blobs}/blob1.yml +6 -4
- data/lib/deltacloud/drivers/mock/data/{buckets/blobs → blobs}/blob2.yml +7 -5
- data/lib/deltacloud/drivers/mock/data/{buckets/blobs → blobs}/blob3.yml +6 -4
- data/lib/deltacloud/drivers/mock/data/{buckets/blobs → blobs}/blob4.yml +6 -4
- data/lib/deltacloud/drivers/mock/data/{buckets/blobs → blobs}/blob5.yml +6 -4
- data/lib/deltacloud/drivers/mock/data/buckets/bucket1.yml +7 -1
- data/lib/deltacloud/drivers/mock/data/buckets/bucket2.yml +6 -1
- data/lib/deltacloud/drivers/mock/data/images/img1.yml +6 -2
- data/lib/deltacloud/drivers/mock/data/images/img2.yml +6 -2
- data/lib/deltacloud/drivers/mock/data/images/img3.yml +6 -2
- data/lib/deltacloud/drivers/mock/data/instances/inst0.yml +11 -10
- data/lib/deltacloud/drivers/mock/data/instances/inst1.yml +14 -7
- data/lib/deltacloud/drivers/mock/data/instances/inst2.yml +14 -7
- data/lib/deltacloud/drivers/mock/data/storage_snapshots/snap1.yml +3 -2
- data/lib/deltacloud/drivers/mock/data/storage_snapshots/snap2.yml +3 -2
- data/lib/deltacloud/drivers/mock/data/storage_snapshots/snap3.yml +3 -2
- data/lib/deltacloud/drivers/mock/data/storage_volumes/vol1.yml +4 -3
- data/lib/deltacloud/drivers/mock/data/storage_volumes/vol2.yml +4 -3
- data/lib/deltacloud/drivers/mock/data/storage_volumes/vol3.yml +4 -3
- data/lib/deltacloud/drivers/mock/mock_client.rb +101 -0
- data/lib/deltacloud/drivers/mock/mock_driver.rb +367 -429
- data/lib/deltacloud/drivers/opennebula/opennebula_driver.rb +6 -0
- data/lib/deltacloud/drivers/rackspace/rackspace_driver.rb +59 -9
- data/lib/deltacloud/drivers/rhevm/rhevm_client.rb +62 -8
- data/lib/deltacloud/drivers/rhevm/rhevm_driver.rb +100 -45
- data/lib/deltacloud/drivers/rimuhosting/rimuhosting_client.rb +3 -2
- data/lib/deltacloud/drivers/rimuhosting/rimuhosting_driver.rb +8 -11
- data/lib/deltacloud/drivers/sbc/sbc_client.rb +6 -6
- data/lib/deltacloud/drivers/sbc/sbc_driver.rb +16 -0
- data/lib/deltacloud/drivers/terremark/terremark_driver.rb +17 -12
- data/lib/deltacloud/drivers/vsphere/vsphere_client.rb +140 -0
- data/lib/deltacloud/drivers/vsphere/vsphere_driver.rb +405 -0
- data/lib/deltacloud/drivers/vsphere/vsphere_filemanager.rb +182 -0
- data/lib/deltacloud/hardware_profile.rb +1 -1
- data/lib/deltacloud/helpers.rb +2 -1
- data/lib/deltacloud/helpers/application_helper.rb +92 -20
- data/lib/deltacloud/helpers/blob_stream.rb +160 -12
- data/lib/deltacloud/helpers/conversion_helper.rb +6 -2
- data/lib/deltacloud/helpers/json_helper.rb +31 -0
- data/lib/deltacloud/models/address.rb +28 -0
- data/lib/deltacloud/models/base_model.rb +5 -1
- data/lib/deltacloud/models/blob.rb +1 -1
- data/lib/deltacloud/models/bucket.rb +10 -0
- data/lib/deltacloud/models/firewall.rb +22 -0
- data/lib/deltacloud/models/firewall_rule.rb +23 -0
- data/lib/deltacloud/models/image.rb +12 -0
- data/lib/deltacloud/models/instance.rb +20 -2
- data/lib/deltacloud/models/key.rb +1 -1
- data/lib/deltacloud/runner.rb +3 -3
- data/lib/deltacloud/validation.rb +3 -7
- data/lib/drivers.rb +7 -1
- data/lib/sinatra/body_proxy.rb +34 -0
- data/lib/sinatra/lazy_auth.rb +5 -0
- data/lib/sinatra/rabbit.rb +54 -31
- data/lib/sinatra/rack_accept.rb +157 -0
- data/lib/sinatra/rack_date.rb +38 -0
- data/lib/sinatra/rack_etag.rb +2 -3
- data/lib/sinatra/rack_matrix_params.rb +51 -29
- data/lib/sinatra/rack_runtime.rb +1 -1
- data/lib/sinatra/rack_syslog.rb +86 -0
- data/lib/sinatra/url_for.rb +14 -1
- data/public/images/address.png +0 -0
- data/public/images/balancer.png +0 -0
- data/public/images/blob.png +0 -0
- data/public/images/bucket.png +0 -0
- data/public/images/cloud.png +0 -0
- data/public/images/firewall.png +0 -0
- data/public/images/image.png +0 -0
- data/public/images/key.png +0 -0
- data/public/images/machine.png +0 -0
- data/public/images/profile.png +0 -0
- data/public/images/realm.png +0 -0
- data/public/images/snapshot.png +0 -0
- data/public/images/volume.png +0 -0
- data/public/javascripts/application.js +119 -16
- data/public/javascripts/jquery.min.js +18 -0
- data/public/javascripts/jquery.mobile-1.0b1.min.js +146 -0
- data/public/stylesheets/compiled/application.css +8 -0
- data/public/stylesheets/images/ajax-loader.png +0 -0
- data/public/{images → stylesheets/images}/bread-bg.png +0 -0
- data/public/{images → stylesheets/images}/error.png +0 -0
- data/public/{images → stylesheets/images}/grid.png +0 -0
- data/public/stylesheets/images/icon-search-black.png +0 -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/{images → stylesheets/images}/logo-wide.png +0 -0
- data/public/{images → stylesheets/images}/pending.png +0 -0
- data/public/{images → stylesheets/images}/rails.png +0 -0
- data/public/{images → stylesheets/images}/running.png +0 -0
- data/public/{images → stylesheets/images}/stopped.png +0 -0
- data/public/{images → stylesheets/images}/topbar-bg.png +0 -0
- data/public/stylesheets/jquery.mobile-1.0b1.min.css +8 -0
- data/public/stylesheets/new.css +53 -0
- data/server.rb +487 -175
- data/support/condor/bash/cached_images.sh +8 -0
- data/support/condor/bash/cloud_exit_hook.sh +17 -0
- data/support/condor/bash/cloud_functions +175 -0
- data/support/condor/bash/cloud_prepare_hook.sh +20 -0
- data/support/condor/bash/libvirt_cloud_script.sh +13 -0
- data/support/condor/config/50condor_cloud.config +37 -0
- data/support/condor/config/50condor_cloud_node.config +37 -0
- data/support/condor/config/condor-cloud +2 -0
- data/support/condor/config/condor_config.local +44 -0
- data/support/fedora/deltacloud-core +48 -26
- data/support/fedora/deltacloud-core-config +26 -0
- data/support/fedora/deltacloud-core.spec +314 -68
- data/support/fedora/deltacloudd-fedora +5 -0
- data/tests/common.rb +34 -4
- data/tests/drivers/mock/api_test.rb +3 -3
- data/tests/drivers/mock/images_test.rb +12 -0
- data/tests/drivers/mock/instances_test.rb +2 -0
- data/tests/rabbit_test.rb +2 -2
- data/views/addresses/_address.html.haml +6 -0
- data/views/addresses/associate.html.haml +12 -0
- data/views/addresses/index.html.haml +9 -0
- data/views/addresses/index.xml.haml +4 -0
- data/views/addresses/show.html.haml +21 -0
- data/views/addresses/show.xml.haml +14 -0
- data/views/api/show.html.haml +6 -11
- data/views/api/show.xml.haml +2 -0
- data/views/blobs/new.html.haml +24 -23
- data/views/blobs/show.html.haml +30 -31
- data/views/buckets/index.html.haml +9 -21
- data/views/buckets/index.xml.haml +3 -7
- data/views/buckets/new.html.haml +13 -12
- data/views/buckets/show.html.haml +22 -22
- data/views/buckets/show.xml.haml +5 -3
- data/views/docs/collection.html.haml +23 -34
- data/views/docs/collection.xml.haml +2 -2
- data/views/docs/index.html.haml +9 -13
- data/views/docs/index.xml.haml +1 -1
- data/views/docs/operation.html.haml +28 -38
- data/views/docs/operation.xml.haml +1 -1
- data/views/drivers/index.html.haml +8 -13
- data/views/drivers/show.html.haml +18 -18
- data/views/error.html.haml +32 -27
- data/views/errors/400.html.haml +41 -0
- data/views/errors/{validation_failure.xml.haml → 400.xml.haml} +0 -4
- data/views/errors/401.html.haml +41 -0
- data/views/errors/{auth_exception.xml.haml → 401.xml.haml} +0 -0
- data/views/errors/403.html.haml +42 -0
- data/views/errors/{not_allowed.xml.haml → 403.xml.haml} +0 -0
- data/views/errors/404.html.haml +29 -0
- data/views/errors/{not_found.xml.haml → 404.xml.haml} +1 -1
- data/views/errors/405.html.haml +29 -0
- data/views/errors/405.xml.haml +5 -0
- data/views/errors/500.html.haml +43 -0
- data/views/errors/500.xml.haml +5 -0
- data/views/errors/502.html.haml +43 -0
- data/views/errors/{backend_error.xml.haml → 502.xml.haml} +1 -2
- data/views/errors/backend_capability_failure.html.haml +27 -9
- data/views/firewalls/index.html.haml +15 -0
- data/views/firewalls/index.xml.haml +28 -0
- data/views/firewalls/new.html.haml +11 -0
- data/views/firewalls/new_rule.html.haml +20 -0
- data/views/firewalls/show.html.haml +42 -0
- data/views/firewalls/show.xml.haml +26 -0
- data/views/hardware_profiles/index.html.haml +15 -23
- data/views/hardware_profiles/show.html.haml +22 -18
- data/views/images/index.html.haml +11 -23
- data/views/images/index.xml.haml +4 -13
- data/views/images/new.html.haml +12 -13
- data/views/images/show.html.haml +26 -20
- data/views/images/show.xml.haml +2 -1
- data/views/instance_states/show.html.haml +21 -25
- data/views/instances/index.html.haml +13 -30
- data/views/instances/index.xml.haml +2 -23
- data/views/instances/new.html.haml +83 -88
- data/views/instances/show.html.haml +53 -55
- data/views/instances/show.xml.haml +12 -10
- data/views/keys/index.html.haml +13 -24
- data/views/keys/new.html.haml +7 -7
- data/views/keys/show.html.haml +26 -21
- data/views/layout.html.haml +28 -27
- data/views/load_balancers/index.html.haml +11 -31
- data/views/load_balancers/index.xml.haml +0 -1
- data/views/load_balancers/new.html.haml +1 -1
- data/views/load_balancers/show.html.haml +33 -34
- data/views/load_balancers/show.xml.haml +2 -2
- data/views/realms/index.html.haml +11 -24
- data/views/realms/index.xml.haml +2 -8
- data/views/realms/show.html.haml +17 -15
- data/views/realms/show.xml.haml +2 -1
- data/views/storage_snapshots/index.html.haml +11 -21
- data/views/storage_snapshots/index.xml.haml +2 -5
- data/views/storage_snapshots/new.html.haml +1 -1
- data/views/storage_snapshots/show.html.haml +21 -13
- data/views/storage_snapshots/show.xml.haml +2 -1
- data/views/storage_volumes/index.html.haml +11 -34
- data/views/storage_volumes/new.html.haml +1 -1
- data/views/storage_volumes/show.html.haml +33 -27
- data/views/storage_volumes/show.xml.haml +2 -1
- metadata +266 -178
- data/lib/sinatra/respond_to.rb +0 -248
- data/support/fedora/deltacloudd +0 -128
- data/support/fedora/rubygem-deltacloud-core.spec +0 -127
- data/views/accounts/index.html.haml +0 -11
- data/views/accounts/show.html.haml +0 -30
- data/views/errors/auth_exception.html.haml +0 -8
- data/views/errors/backend_error.html.haml +0 -22
- data/views/errors/not_allowed.html.haml +0 -6
- data/views/errors/not_found.html.haml +0 -6
- data/views/errors/validation_failure.html.haml +0 -11
@@ -1,10 +1,17 @@
|
|
1
|
-
|
2
|
-
:state: RUNNING
|
3
|
-
:image_id: img3
|
4
|
-
:owner_id: mockuser
|
5
|
-
:public_addresses: [ img3.inst1.public.com ]
|
6
|
-
:private_addresses: [ img3.inst1.private.com ]
|
7
|
-
:realm_id: us
|
1
|
+
---
|
8
2
|
:instance_profile: !ruby/object:InstanceProfile
|
9
3
|
id: m1-small
|
4
|
+
:realm_id: us
|
5
|
+
:owner_id: mockuser
|
6
|
+
:public_addresses:
|
7
|
+
- img3.inst1.public.com
|
8
|
+
:private_addresses:
|
9
|
+
- img3.inst1.private.com
|
10
10
|
:create_image: true
|
11
|
+
:image_id: img3
|
12
|
+
:name: MockUserInstance
|
13
|
+
:id: inst1
|
14
|
+
:state: RUNNING
|
15
|
+
:actions:
|
16
|
+
- :reboot
|
17
|
+
- :stop
|
@@ -1,10 +1,17 @@
|
|
1
|
-
|
2
|
-
:state: RUNNING
|
3
|
-
:image_id: img1
|
4
|
-
:owner_id: anotheruser
|
5
|
-
:public_addresses: [ img1.inst2.public.com ]
|
6
|
-
:private_addresses: [ img1.inst2.private.com ]
|
7
|
-
:realm_id: us
|
1
|
+
---
|
8
2
|
:instance_profile: !ruby/object:InstanceProfile
|
9
3
|
id: m1-large
|
4
|
+
:realm_id: us
|
5
|
+
:owner_id: anotheruser
|
6
|
+
:public_addresses:
|
7
|
+
- img1.inst2.public.com
|
8
|
+
:private_addresses:
|
9
|
+
- img1.inst2.private.com
|
10
10
|
:create_image: true
|
11
|
+
:image_id: img1
|
12
|
+
:name: AnotherInstance
|
13
|
+
:id: inst2
|
14
|
+
:state: RUNNING
|
15
|
+
:actions:
|
16
|
+
- :reboot
|
17
|
+
- :stop
|
@@ -0,0 +1,101 @@
|
|
1
|
+
#
|
2
|
+
# Licensed to the Apache Software Foundation (ASF) under one or more
|
3
|
+
# contributor license agreements. See the NOTICE file distributed with
|
4
|
+
# this work for additional information regarding copyright ownership. The
|
5
|
+
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
6
|
+
# "License"); you may not use this file except in compliance with the
|
7
|
+
# License. You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
13
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
14
|
+
# License for the specific language governing permissions and limitations
|
15
|
+
# under the License.
|
16
|
+
|
17
|
+
# The mock client does a bunch of filesystem judo. It's mostly there to
|
18
|
+
# keep the driver from looking too ugly with all the File I/O
|
19
|
+
|
20
|
+
module Deltacloud::Drivers::Mock
|
21
|
+
|
22
|
+
class Client
|
23
|
+
def initialize(storage_root)
|
24
|
+
@storage_root = storage_root
|
25
|
+
@collections = []
|
26
|
+
|
27
|
+
if ! File::directory?(@storage_root)
|
28
|
+
FileUtils::rm_rf(@storage_root)
|
29
|
+
FileUtils::mkdir_p(@storage_root)
|
30
|
+
data = Dir[File::join(File::dirname(__FILE__), "data", "*")]
|
31
|
+
FileUtils::cp_r(data, @storage_root)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def dir(collection)
|
36
|
+
result = File::join(@storage_root, collection.to_s)
|
37
|
+
unless @collections.include?(collection)
|
38
|
+
FileUtils::mkdir_p(result) unless File::directory?(result)
|
39
|
+
@collections << collection
|
40
|
+
end
|
41
|
+
result
|
42
|
+
end
|
43
|
+
|
44
|
+
def file(collection, id)
|
45
|
+
File::join(dir(collection), "#{id}.yml")
|
46
|
+
end
|
47
|
+
|
48
|
+
def files(collection)
|
49
|
+
Dir[File::join(dir(collection), "*.yml")]
|
50
|
+
end
|
51
|
+
|
52
|
+
# Return the ID's of all members of +collection+
|
53
|
+
def members(collection)
|
54
|
+
files(collection).map { |f| File::basename(f, ".yml") }
|
55
|
+
end
|
56
|
+
|
57
|
+
def load(collection, id)
|
58
|
+
fname = file(collection, id)
|
59
|
+
begin
|
60
|
+
YAML.load(File.read(fname))
|
61
|
+
rescue Errno::ENOENT
|
62
|
+
nil
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def store(collection, obj)
|
67
|
+
raise "Why no obj[:id] ?" unless obj[:id]
|
68
|
+
File::open(file(collection, obj[:id]), "w") { |f| YAML.dump(obj, f) }
|
69
|
+
end
|
70
|
+
|
71
|
+
# Return the object with id +id+ of class +klass+ from the collection
|
72
|
+
# derived from the classes name
|
73
|
+
def build(klass, id)
|
74
|
+
klass.new(load(collection_name(klass), id))
|
75
|
+
end
|
76
|
+
|
77
|
+
# Return an array of hashes of all the resources in the collection
|
78
|
+
def load_all(collection)
|
79
|
+
members(collection).map { |id| load(collection, id) }
|
80
|
+
end
|
81
|
+
|
82
|
+
# Return an array of model objects of the resources in the collection
|
83
|
+
# corresponding to class. The name of the collection is derived from
|
84
|
+
# the name of the class
|
85
|
+
def build_all(klass)
|
86
|
+
load_all(collection_name(klass)).map { |hash| klass.new(hash) }
|
87
|
+
end
|
88
|
+
|
89
|
+
def destroy(collection, id)
|
90
|
+
fname = file(collection, id)
|
91
|
+
FileUtils.rm(fname) if File::exists?(fname)
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
def collection_name(klass)
|
97
|
+
klass.name.underscore.pluralize
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
@@ -17,502 +17,440 @@
|
|
17
17
|
|
18
18
|
require 'deltacloud/base_driver'
|
19
19
|
require 'yaml'
|
20
|
+
require 'deltacloud/drivers/mock/mock_client'
|
20
21
|
|
21
|
-
module Deltacloud
|
22
|
-
module Drivers
|
23
|
-
module Mock
|
24
|
-
class MockDriver < Deltacloud::BaseDriver
|
22
|
+
module Deltacloud::Drivers::Mock
|
25
23
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
24
|
+
class MockDriver < Deltacloud::BaseDriver
|
25
|
+
|
26
|
+
# If the provider is set to storage, pretend to be a storage-only
|
27
|
+
# driver
|
28
|
+
def supported_collections
|
29
|
+
if api_provider == 'storage'
|
30
|
+
[:buckets]
|
31
|
+
else
|
32
|
+
DEFAULT_COLLECTIONS + [:buckets, :keys]
|
33
|
+
end
|
34
34
|
end
|
35
|
-
end
|
36
35
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
architecture 'i386'
|
57
|
-
end
|
36
|
+
( REALMS = [
|
37
|
+
Realm.new({
|
38
|
+
:id=>'us',
|
39
|
+
:name=>'United States',
|
40
|
+
:limit=>:unlimited,
|
41
|
+
:state=>'AVAILABLE'}),
|
42
|
+
Realm.new({
|
43
|
+
:id=>'eu',
|
44
|
+
:name=>'Europe',
|
45
|
+
:limit=>:unlimited,
|
46
|
+
:state=>'AVAILABLE'}),
|
47
|
+
] ) unless defined?( REALMS )
|
48
|
+
|
49
|
+
define_hardware_profile('m1-small') do
|
50
|
+
cpu 1
|
51
|
+
memory 1.7 * 1024
|
52
|
+
storage 160
|
53
|
+
architecture 'i386'
|
54
|
+
end
|
58
55
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
56
|
+
define_hardware_profile('m1-large') do
|
57
|
+
cpu 2
|
58
|
+
memory (7.5*1024 .. 15*1024), :default => 10 * 1024
|
59
|
+
storage [ 850, 1024 ]
|
60
|
+
architecture 'x86_64'
|
61
|
+
end
|
65
62
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
63
|
+
define_hardware_profile('m1-xlarge') do
|
64
|
+
cpu 4
|
65
|
+
memory (12*1024 .. 32*1024)
|
66
|
+
storage [ 1024, 2048, 4096 ]
|
67
|
+
architecture 'x86_64'
|
68
|
+
end
|
72
69
|
|
73
|
-
|
74
|
-
|
70
|
+
# Some clouds tell us nothing about hardware profiles (e.g., OpenNebula)
|
71
|
+
define_hardware_profile 'opaque'
|
75
72
|
|
76
|
-
|
77
|
-
|
73
|
+
define_instance_states do
|
74
|
+
start.to( :pending ) .on( :create )
|
78
75
|
|
79
|
-
|
76
|
+
pending.to( :running ) .automatically
|
80
77
|
|
81
|
-
|
82
|
-
|
78
|
+
running.to( :running ) .on( :reboot )
|
79
|
+
running.to( :stopped ) .on( :stop )
|
83
80
|
|
84
|
-
|
85
|
-
|
86
|
-
|
81
|
+
stopped.to( :running ) .on( :start )
|
82
|
+
stopped.to( :finish ) .on( :destroy )
|
83
|
+
end
|
87
84
|
|
88
|
-
|
89
|
-
|
85
|
+
feature :instances, :user_name
|
86
|
+
feature :instances, :user_data
|
87
|
+
feature :instances, :authentication_key
|
90
88
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
FileUtils::rm_rf(@storage_root)
|
101
|
-
FileUtils::mkdir_p(@storage_root)
|
102
|
-
data = Dir::glob(File::join(File::dirname(__FILE__), "data", "*"))
|
103
|
-
FileUtils::cp_r(data, @storage_root)
|
89
|
+
def initialize
|
90
|
+
if ENV["DELTACLOUD_MOCK_STORAGE"]
|
91
|
+
storage_root = ENV["DELTACLOUD_MOCK_STORAGE"]
|
92
|
+
elsif ENV["USER"]
|
93
|
+
storage_root = File::join("/var/tmp", "deltacloud-mock-#{ENV["USER"]}")
|
94
|
+
else
|
95
|
+
raise "Please set either the DELTACLOUD_MOCK_STORAGE or USER environment variable"
|
96
|
+
end
|
97
|
+
@client = Client.new(storage_root)
|
104
98
|
end
|
105
|
-
end
|
106
99
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
100
|
+
def realms(credentials, opts=nil)
|
101
|
+
return REALMS if ( opts.nil? )
|
102
|
+
results = REALMS
|
103
|
+
results = filter_on( results, :id, opts )
|
104
|
+
results
|
105
|
+
end
|
113
106
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
else
|
131
|
-
images = filter_on( images, :owner_id, opts )
|
132
|
-
end
|
133
|
-
images.sort_by{|e| [e.owner_id,e.description]}
|
134
|
-
end
|
107
|
+
#
|
108
|
+
# Images
|
109
|
+
#
|
110
|
+
def images(credentials, opts=nil )
|
111
|
+
check_credentials( credentials )
|
112
|
+
images = []
|
113
|
+
images = @client.build_all(Image)
|
114
|
+
images = filter_on( images, :id, opts )
|
115
|
+
images = filter_on( images, :architecture, opts )
|
116
|
+
if ( opts && opts[:owner_id] == 'self' )
|
117
|
+
images = images.select{|e| e.owner_id == credentials.user }
|
118
|
+
else
|
119
|
+
images = filter_on( images, :owner_id, opts )
|
120
|
+
end
|
121
|
+
images.sort_by{|e| [e.owner_id,e.description]}
|
122
|
+
end
|
135
123
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
:description => opts[:description],
|
152
|
-
:architecture => 'i386',
|
153
|
-
:state => 'UP'
|
154
|
-
}
|
155
|
-
File.open( "#{@storage_root}/images/#{next_id}.yml", 'w' ) do |f|
|
156
|
-
YAML.dump( image, f )
|
124
|
+
def create_image(credentials, opts={})
|
125
|
+
check_credentials(credentials)
|
126
|
+
instance = instance(credentials, :id => opts[:id])
|
127
|
+
safely do
|
128
|
+
raise 'CreateImageNotSupported' unless instance and instance.can_create_image?
|
129
|
+
image = {
|
130
|
+
:id => opts[:name],
|
131
|
+
:name => opts[:name],
|
132
|
+
:owner_id => 'root',
|
133
|
+
:state => "AVAILABLE",
|
134
|
+
:description => opts[:description],
|
135
|
+
:architecture => 'i386'
|
136
|
+
}
|
137
|
+
@client.store(:images, image)
|
138
|
+
Image.new(image)
|
157
139
|
end
|
158
|
-
image[:id] = next_id
|
159
|
-
Image.new(image)
|
160
140
|
end
|
161
|
-
end
|
162
141
|
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
instance = YAML::load_file(instance_filename)
|
172
|
-
instance[:actions] = instance_actions_for( instance[:state] )
|
173
|
-
instance[:id] = File::basename(instance_filename, ".yml")
|
174
|
-
Instance.new(instance)
|
175
|
-
end
|
142
|
+
def destroy_image(credentials, id)
|
143
|
+
check_credentials( credentials )
|
144
|
+
@client.destroy(:images, id)
|
145
|
+
end
|
146
|
+
|
147
|
+
#
|
148
|
+
# Instances
|
149
|
+
#
|
176
150
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
instance = YAML::load_file(instance_file)
|
182
|
-
if ( instance[:owner_id] == credentials.user )
|
183
|
-
instance[:id] = File.basename( instance_file, ".yml" )
|
184
|
-
instance[:actions] = instance_actions_for( instance[:state] )
|
185
|
-
instances << Instance.new( instance )
|
151
|
+
def instance(credentials, opts={})
|
152
|
+
check_credentials( credentials )
|
153
|
+
if instance = @client.load(:instances, opts[:id])
|
154
|
+
Instance.new(instance)
|
186
155
|
end
|
187
156
|
end
|
188
|
-
instances = filter_on( instances, :id, opts )
|
189
|
-
instances = filter_on( instances, :state, opts )
|
190
|
-
instances
|
191
|
-
end
|
192
157
|
|
193
|
-
|
194
|
-
|
195
|
-
|
158
|
+
def instances(credentials, opts=nil)
|
159
|
+
check_credentials( credentials )
|
160
|
+
instances = @client.build_all(Instance)
|
161
|
+
instances = filter_on( instances, :owner_id, :owner_id => credentials.user )
|
162
|
+
instances = filter_on( instances, :id, opts )
|
163
|
+
instances = filter_on( instances, :state, opts )
|
164
|
+
instances
|
165
|
+
end
|
166
|
+
|
167
|
+
def create_instance(credentials, image_id, opts)
|
168
|
+
check_credentials( credentials )
|
169
|
+
ids = @client.members(:instances)
|
196
170
|
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
171
|
+
count = 0
|
172
|
+
while true
|
173
|
+
next_id = "inst" + count.to_s
|
174
|
+
if not ids.include?(next_id)
|
175
|
+
break
|
176
|
+
end
|
177
|
+
count = count + 1
|
202
178
|
end
|
203
|
-
count = count + 1
|
204
|
-
end
|
205
|
-
|
206
|
-
realm_id = opts[:realm_id]
|
207
|
-
if ( realm_id.nil? )
|
208
|
-
realm = realms(credentials).first
|
209
|
-
( realm_id = realm.id ) if realm
|
210
|
-
end
|
211
|
-
|
212
|
-
hwp = find_hardware_profile(credentials, opts[:hwp_id], image_id)
|
213
|
-
|
214
|
-
name = opts[:name] || "i-#{Time.now.to_i}"
|
215
|
-
|
216
|
-
instance = {
|
217
|
-
:name=>name,
|
218
|
-
:state=>'RUNNING',
|
219
|
-
:image_id=>image_id,
|
220
|
-
:owner_id=>credentials.user,
|
221
|
-
:public_addresses=>["#{image_id}.#{next_id}.public.com"],
|
222
|
-
:private_addresses=>["#{image_id}.#{next_id}.private.com"],
|
223
|
-
:instance_profile => InstanceProfile.new(hwp.name, opts),
|
224
|
-
:realm_id=>realm_id,
|
225
|
-
:create_image=>true,
|
226
|
-
:actions=>instance_actions_for( 'RUNNING' )
|
227
|
-
}
|
228
|
-
File.open( "#{@storage_root}/instances/#{next_id}.yml", 'w' ) {|f|
|
229
|
-
YAML.dump( instance, f )
|
230
|
-
}
|
231
|
-
instance[:id] = next_id
|
232
|
-
Instance.new( instance )
|
233
|
-
end
|
234
179
|
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
180
|
+
realm_id = opts[:realm_id]
|
181
|
+
if ( realm_id.nil? )
|
182
|
+
realm = realms(credentials).first
|
183
|
+
( realm_id = realm.id ) if realm
|
184
|
+
end
|
185
|
+
|
186
|
+
hwp = find_hardware_profile(credentials, opts[:hwp_id], image_id)
|
187
|
+
|
188
|
+
name = opts[:name] || "i-#{Time.now.to_i}"
|
189
|
+
|
190
|
+
instance = {
|
191
|
+
:id => next_id,
|
192
|
+
:name=>name,
|
193
|
+
:state=>'RUNNING',
|
194
|
+
:keyname => opts[:keyname],
|
195
|
+
:image_id=>image_id,
|
196
|
+
:owner_id=>credentials.user,
|
197
|
+
:public_addresses=>["#{image_id}.#{next_id}.public.com"],
|
198
|
+
:private_addresses=>["#{image_id}.#{next_id}.private.com"],
|
199
|
+
:instance_profile => InstanceProfile.new(hwp.name, opts),
|
200
|
+
:realm_id=>realm_id,
|
201
|
+
:create_image=>true,
|
202
|
+
:actions=>instance_actions_for( 'RUNNING' ),
|
203
|
+
:user_data => opts[:user_data]
|
204
|
+
}
|
205
|
+
@client.store(:instances, instance)
|
206
|
+
Instance.new( instance )
|
243
207
|
end
|
244
|
-
Instance.new( instance_yml )
|
245
|
-
end
|
246
208
|
|
247
|
-
|
248
|
-
|
249
|
-
|
209
|
+
def update_instance_state(credentials, id, state)
|
210
|
+
instance = @client.load(:instances, id)
|
211
|
+
instance[:state] = state
|
212
|
+
instance[:actions] = instance_actions_for( instance[:state] )
|
213
|
+
@client.store(:instances, instance)
|
214
|
+
Instance.new( instance )
|
215
|
+
end
|
250
216
|
|
251
|
-
|
252
|
-
|
253
|
-
|
217
|
+
def start_instance(credentials, id)
|
218
|
+
update_instance_state(credentials, id, 'RUNNING')
|
219
|
+
end
|
254
220
|
|
255
|
-
|
256
|
-
|
257
|
-
|
221
|
+
def reboot_instance(credentials, id)
|
222
|
+
update_instance_state(credentials, id, 'RUNNING')
|
223
|
+
end
|
258
224
|
|
225
|
+
def stop_instance(credentials, id)
|
226
|
+
update_instance_state(credentials, id, 'STOPPED')
|
227
|
+
end
|
259
228
|
|
260
|
-
def destroy_instance(credentials, id)
|
261
|
-
check_credentials( credentials )
|
262
|
-
FileUtils.rm( "#{@storage_root}/instances/#{id}.yml" )
|
263
|
-
end
|
264
229
|
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
def storage_volumes(credentials, opts=nil)
|
270
|
-
check_credentials( credentials )
|
271
|
-
volumes = []
|
272
|
-
Dir[ "#{@storage_root}/storage_volumes/*.yml" ].each do |storage_volume_file|
|
273
|
-
storage_volume = YAML.load( File.read( storage_volume_file ) )
|
274
|
-
if ( storage_volume[:owner_id] == credentials.user )
|
275
|
-
storage_volume[:id] = File.basename( storage_volume_file, ".yml" )
|
276
|
-
volumes << StorageVolume.new( storage_volume )
|
277
|
-
end
|
230
|
+
def destroy_instance(credentials, id)
|
231
|
+
check_credentials( credentials )
|
232
|
+
@client.destroy(:instances, id)
|
278
233
|
end
|
279
|
-
volumes = filter_on( volumes, :id, opts )
|
280
|
-
volumes
|
281
|
-
end
|
282
234
|
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
def storage_snapshots(credentials, opts=nil)
|
288
|
-
check_credentials( credentials )
|
289
|
-
snapshots = []
|
290
|
-
Dir[ "#{@storage_root}/storage_snapshots/*.yml" ].each do |storage_snapshot_file|
|
291
|
-
storage_snapshot = YAML.load( File.read( storage_snapshot_file ) )
|
292
|
-
if ( storage_snapshot[:owner_id] == credentials.user )
|
293
|
-
storage_snapshot[:id] = File.basename( storage_snapshot_file, ".yml" )
|
294
|
-
snapshots << StorageSnapshot.new( storage_snapshot )
|
295
|
-
end
|
296
|
-
end
|
297
|
-
snapshots = filter_on( snapshots, :id, opts )
|
298
|
-
snapshots
|
299
|
-
end
|
235
|
+
#
|
236
|
+
# Storage Volumes
|
237
|
+
#
|
300
238
|
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
result << Key.new(YAML::load(File.read(key_file)))
|
239
|
+
def storage_volumes(credentials, opts=nil)
|
240
|
+
check_credentials( credentials )
|
241
|
+
volumes = @client.build_all(StorageVolume)
|
242
|
+
volumes = filter_on( volumes, :id, opts )
|
243
|
+
volumes
|
307
244
|
end
|
308
|
-
result = filter_on( result, :id, opts )
|
309
|
-
result
|
310
|
-
end
|
311
245
|
|
312
|
-
|
313
|
-
|
314
|
-
|
246
|
+
#
|
247
|
+
# Storage Snapshots
|
248
|
+
#
|
315
249
|
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
:id
|
320
|
-
|
321
|
-
|
322
|
-
:pem_rsa_key => Key::generate_mock_pem
|
323
|
-
}
|
324
|
-
key_dir = File.join(@storage_root, 'keys')
|
325
|
-
if File.exists?(key_dir + "/#{key_hash[:id]}.yml")
|
326
|
-
raise Deltacloud::BackendError.new(403, self.class.to_s, "key-exists",
|
327
|
-
["Key with same name already exists"])
|
328
|
-
end
|
329
|
-
FileUtils.mkdir_p(key_dir) unless File.directory?(key_dir)
|
330
|
-
File.open(key_dir + "/#{key_hash[:id]}.yml", 'w') do |f|
|
331
|
-
f.puts(YAML::dump(key_hash))
|
332
|
-
end
|
333
|
-
return Key.new(key_hash)
|
334
|
-
end
|
250
|
+
def storage_snapshots(credentials, opts=nil)
|
251
|
+
check_credentials( credentials )
|
252
|
+
snapshots = @client.build_all(StorageSnapshot)
|
253
|
+
snapshots = filter_on(snapshots, :id, opts )
|
254
|
+
snapshots
|
255
|
+
end
|
335
256
|
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
257
|
+
def keys(credentials, opts={})
|
258
|
+
check_credentials(credentials)
|
259
|
+
result = @client.build_all(Key)
|
260
|
+
result = filter_on( result, :id, opts )
|
261
|
+
result
|
341
262
|
end
|
342
|
-
end
|
343
263
|
|
344
|
-
|
345
|
-
|
346
|
-
#--
|
347
|
-
def buckets(credentials, opts={})
|
348
|
-
check_credentials(credentials)
|
349
|
-
buckets=[]
|
350
|
-
safely do
|
351
|
-
unless (opts[:id].nil?)
|
352
|
-
bucket_file = File::join(@storage_root, 'buckets', "#{opts[:id]}.yml")
|
353
|
-
bucket = YAML.load_file(bucket_file)
|
354
|
-
bucket[:id] = opts[:id]
|
355
|
-
bucket[:name] = bucket[:id]
|
356
|
-
buckets << Bucket.new( bucket )
|
357
|
-
else
|
358
|
-
Dir[ File::join(@storage_root, 'buckets', '*.yml')].each do |bucket_file|
|
359
|
-
bucket_id = File.basename( bucket_file, ".yml" )
|
360
|
-
buckets << Bucket.new( {:id => bucket_id, :name => bucket_id } )
|
361
|
-
end
|
362
|
-
end
|
264
|
+
def key(credentials, opts={})
|
265
|
+
keys(credentials, opts).first
|
363
266
|
end
|
364
|
-
buckets = filter_on( buckets, :id, opts )
|
365
|
-
end
|
366
267
|
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
:size=>'0',
|
376
|
-
:blob_list=>[]
|
377
|
-
}
|
378
|
-
File.open( File::join(@storage_root, 'buckets', "#{name}.yml"), 'w') {|b| YAML.dump( bucket, b )}
|
379
|
-
Bucket.new(bucket)
|
380
|
-
end
|
268
|
+
def create_key(credentials, opts={})
|
269
|
+
check_credentials(credentials)
|
270
|
+
key_hash = {
|
271
|
+
:id => opts[:key_name],
|
272
|
+
:credential_type => :key,
|
273
|
+
:fingerprint => Key::generate_mock_fingerprint,
|
274
|
+
:pem_rsa_key => Key::generate_mock_pem
|
275
|
+
}
|
381
276
|
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
def delete_bucket(credentials, name, opts={})
|
386
|
-
check_credentials(credentials)
|
387
|
-
bucket = bucket(credentials, {:id => name})
|
388
|
-
unless (bucket.size == "0")
|
389
|
-
raise Deltacloud::BackendError.new(403, self.class.to_s, "bucket-not-empty", "delete operation not valid for non-empty bucket")
|
277
|
+
raise "KeyExist" if @client.load(:keys, key_hash[:id])
|
278
|
+
@client.store(:keys, key_hash)
|
279
|
+
return Key.new(key_hash)
|
390
280
|
end
|
391
|
-
|
392
|
-
|
281
|
+
|
282
|
+
def destroy_key(credentials, opts={})
|
283
|
+
key = key(credentials, opts)
|
284
|
+
@client.destroy(:keys, key.id)
|
393
285
|
end
|
394
|
-
end
|
395
286
|
|
396
|
-
#--
|
397
|
-
#
|
398
|
-
#--
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
blobs = filter_on( blobs, :id, opts )
|
287
|
+
#--
|
288
|
+
# Buckets
|
289
|
+
#--
|
290
|
+
def buckets(credentials, opts={})
|
291
|
+
check_credentials(credentials)
|
292
|
+
buckets = @client.build_all(Bucket)
|
293
|
+
blob_map = @client.load_all(:blobs).inject({}) do |map, blob|
|
294
|
+
map[blob[:bucket]] ||= []
|
295
|
+
map[blob[:bucket]] << blob[:id]
|
296
|
+
map
|
297
|
+
end
|
298
|
+
buckets.each { |bucket| bucket.blob_list = blob_map[bucket.id] }
|
299
|
+
filter_on( buckets, :id, opts )
|
410
300
|
end
|
411
|
-
end
|
412
301
|
|
413
|
-
#--
|
414
|
-
#
|
415
|
-
#--
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
302
|
+
#--
|
303
|
+
# Create bucket
|
304
|
+
#--
|
305
|
+
def create_bucket(credentials, name, opts={})
|
306
|
+
check_credentials(credentials)
|
307
|
+
bucket = {
|
308
|
+
:id => name,
|
309
|
+
:name=>name,
|
310
|
+
:size=>'0',
|
311
|
+
:blob_list=>[]
|
312
|
+
}
|
313
|
+
@client.store(:buckets, bucket)
|
314
|
+
Bucket.new(bucket)
|
315
|
+
end
|
425
316
|
|
426
|
-
#--
|
427
|
-
#
|
428
|
-
#--
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
:bucket => bucket_id,
|
436
|
-
:content_length => blob_data[:tempfile].length,
|
437
|
-
:content_type => blob_data[:type],
|
438
|
-
:last_modified => Time.now,
|
439
|
-
:user_metadata => blob_meta.gsub_keys('X_Deltacloud_Blobmeta_', ''),
|
440
|
-
:content => blob_data[:tempfile].read
|
441
|
-
}
|
442
|
-
File.open( File::join("#{@storage_root}", "buckets", "blobs", "#{blob_id}.yml"), 'w' ) {|b| YAML.dump( blob, b )}
|
443
|
-
Blob.new(blob)
|
444
|
-
end
|
317
|
+
#--
|
318
|
+
# Delete bucket
|
319
|
+
#--
|
320
|
+
def delete_bucket(credentials, name, opts={})
|
321
|
+
check_credentials(credentials)
|
322
|
+
bucket = bucket(credentials, {:id => name})
|
323
|
+
raise "BucketNotEmpty" unless (bucket.size == "0")
|
324
|
+
@client.destroy(:buckets, bucket.id)
|
325
|
+
end
|
445
326
|
|
446
|
-
#--
|
447
|
-
#
|
448
|
-
#--
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
327
|
+
#--
|
328
|
+
# Blobs
|
329
|
+
#--
|
330
|
+
def blobs(credentials, opts = {})
|
331
|
+
check_credentials(credentials)
|
332
|
+
blobs = @client.build_all(Blob)
|
333
|
+
filter_on( blobs, :bucket, :bucket => opts['bucket'] )
|
334
|
+
filter_on( blobs, :id, opts )
|
335
|
+
end
|
336
|
+
|
337
|
+
#--
|
338
|
+
# Blob content
|
339
|
+
#--
|
340
|
+
def blob_data(credentials, bucket_id, blob_id, opts = {})
|
341
|
+
check_credentials(credentials)
|
342
|
+
if blob = @client.load(:blobs, blob_id)
|
343
|
+
blob[:content].each {|part| yield part}
|
455
344
|
end
|
456
|
-
File.delete(blobfile)
|
457
345
|
end
|
458
|
-
end
|
459
346
|
|
460
|
-
#--
|
461
|
-
#
|
462
|
-
#--
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
347
|
+
#--
|
348
|
+
# Create blob
|
349
|
+
#--
|
350
|
+
def create_blob(credentials, bucket_id, blob_id, blob_data, opts={})
|
351
|
+
check_credentials(credentials)
|
352
|
+
blob_meta = BlobHelper::extract_blob_metadata_hash(opts)
|
353
|
+
blob = {
|
354
|
+
:id => blob_id,
|
355
|
+
:name => blob_id,
|
356
|
+
:bucket => bucket_id,
|
357
|
+
:content_length => blob_data[:tempfile].length,
|
358
|
+
:content_type => blob_data[:type],
|
359
|
+
:last_modified => Time.now,
|
360
|
+
:user_metadata => BlobHelper::rename_metadata_headers(blob_meta, ''),
|
361
|
+
:content => blob_data[:tempfile].read
|
362
|
+
}
|
363
|
+
@client.store(:blobs, blob)
|
364
|
+
Blob.new(blob)
|
365
|
+
end
|
474
366
|
|
475
|
-
#--
|
476
|
-
#
|
477
|
-
#--
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
blob[:user_metadata] = opts['meta_hash'].gsub_keys('HTTP[-_]X[-_]Deltacloud[-_]Blobmeta[-_]', '')
|
485
|
-
File.open(File::join("#{@storage_root}", "buckets", "blobs", "#{opts[:id]}.yml"), 'w' ) {|b| YAML.dump( blob, b )}
|
367
|
+
#--
|
368
|
+
# Delete blob
|
369
|
+
#--
|
370
|
+
def delete_blob(credentials, bucket_id, blob_id, opts={})
|
371
|
+
check_credentials(credentials)
|
372
|
+
safely do
|
373
|
+
raise "NotExistentBlob" unless @client.load(:blobs, blob_id)
|
374
|
+
@client.destroy(:blobs, blob_id)
|
375
|
+
end
|
486
376
|
end
|
487
|
-
end
|
488
377
|
|
489
|
-
|
490
|
-
|
378
|
+
#--
|
379
|
+
# Get metadata
|
380
|
+
#--
|
381
|
+
def blob_metadata(credentials, opts={})
|
491
382
|
check_credentials(credentials)
|
492
|
-
|
493
|
-
|
383
|
+
if blob = @client.load(:blobs, params[:id])
|
384
|
+
blob[:user_metadata]
|
385
|
+
else
|
386
|
+
nil
|
387
|
+
end
|
494
388
|
end
|
495
|
-
return false
|
496
|
-
end
|
497
389
|
|
498
|
-
|
390
|
+
#--
|
391
|
+
# Update metadata
|
392
|
+
#--
|
393
|
+
def update_blob_metadata(credentials, opts={})
|
394
|
+
check_credentials(credentials)
|
395
|
+
safely do
|
396
|
+
blob = @client.load(:blobs, params[:id])
|
397
|
+
return false unless blob
|
398
|
+
blob[:user_metadata] = BlobHelper::rename_metadata_headers(opts['meta_hash'], '')
|
399
|
+
@client.store(:blobs, blob)
|
400
|
+
end
|
401
|
+
end
|
499
402
|
|
500
|
-
|
501
|
-
|
502
|
-
|
403
|
+
def valid_credentials?(credentials)
|
404
|
+
begin
|
405
|
+
check_credentials(credentials)
|
406
|
+
return true
|
407
|
+
rescue
|
408
|
+
end
|
409
|
+
return false
|
503
410
|
end
|
504
|
-
end
|
505
411
|
|
506
|
-
|
507
|
-
{
|
508
|
-
:auth => [],
|
509
|
-
:error => [ /Deltacloud::BackendError/, /Errno::ENOENT/ ],
|
510
|
-
:glob => [ /Error/ ]
|
511
|
-
}
|
512
|
-
end
|
412
|
+
private
|
513
413
|
|
514
|
-
|
414
|
+
def check_credentials(credentials)
|
415
|
+
safely do
|
416
|
+
if ( credentials.user != 'mockuser' ) or ( credentials.password != 'mockpassword' )
|
417
|
+
raise 'AuthFailure'
|
418
|
+
end
|
419
|
+
end
|
420
|
+
end
|
421
|
+
|
422
|
+
exceptions do
|
423
|
+
|
424
|
+
on /AuthFailure/ do
|
425
|
+
status 401
|
426
|
+
message "Authentication Failure"
|
427
|
+
end
|
428
|
+
|
429
|
+
on /BucketNotEmpty/ do
|
430
|
+
status 403
|
431
|
+
message "Delete operation not valid for non-empty bucket"
|
432
|
+
end
|
433
|
+
|
434
|
+
on /KeyExist/ do
|
435
|
+
status 403
|
436
|
+
message "Key with same name already exists"
|
437
|
+
end
|
438
|
+
|
439
|
+
on /CreateImageNotSupported/ do
|
440
|
+
status 500
|
441
|
+
end
|
442
|
+
|
443
|
+
on /NotExistentBlob/ do
|
444
|
+
status 500
|
445
|
+
message "Could not delete a non existent blob"
|
446
|
+
end
|
447
|
+
|
448
|
+
on /Err/ do
|
449
|
+
status 500
|
450
|
+
end
|
515
451
|
|
516
452
|
end
|
453
|
+
|
517
454
|
end
|
455
|
+
|
518
456
|
end
|