steamcannon-deltacloud-core 0.1.1.3 → 0.1.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/deltacloudd +7 -1
- data/config.ru +19 -1
- data/deltacloud.rb +20 -1
- data/lib/deltacloud/backend_capability.rb +33 -1
- data/lib/deltacloud/base_driver.rb +1 -1
- data/lib/deltacloud/base_driver/base_driver.rb +62 -73
- data/lib/deltacloud/base_driver/features.rb +6 -6
- data/lib/deltacloud/drivers/azure/azure_driver.rb +32 -1
- data/lib/deltacloud/drivers/ec2/ec2_driver.rb +107 -23
- data/lib/deltacloud/drivers/ec2/ec2_mock_driver.rb +18 -0
- data/lib/deltacloud/drivers/gogrid/gogrid_client.rb +0 -1
- data/lib/deltacloud/drivers/gogrid/gogrid_driver.rb +20 -5
- data/lib/deltacloud/drivers/mock/mock_driver.rb +1 -1
- data/lib/deltacloud/drivers/rackspace/rackspace_client.rb +1 -1
- data/lib/deltacloud/drivers/rackspace/rackspace_driver.rb +28 -1
- data/lib/deltacloud/hardware_profile.rb +17 -0
- data/lib/deltacloud/helpers.rb +18 -0
- data/lib/deltacloud/helpers/application_helper.rb +2 -2
- data/lib/deltacloud/helpers/blob_stream.rb +5 -1
- data/lib/deltacloud/helpers/conversion_helper.rb +1 -2
- data/lib/deltacloud/helpers/hardware_profiles_helper.rb +17 -0
- data/lib/deltacloud/method_serializer.rb +1 -1
- data/lib/deltacloud/models/base_model.rb +1 -1
- data/lib/deltacloud/models/blob.rb +3 -1
- data/lib/deltacloud/models/bucket.rb +2 -1
- data/lib/deltacloud/models/image.rb +1 -1
- data/lib/deltacloud/models/instance.rb +1 -2
- data/lib/deltacloud/models/instance_profile.rb +2 -1
- data/lib/deltacloud/models/key.rb +1 -1
- data/lib/deltacloud/models/load_balancer.rb +1 -1
- data/lib/deltacloud/models/realm.rb +1 -1
- data/lib/deltacloud/models/storage_snapshot.rb +1 -1
- data/lib/deltacloud/models/storage_volume.rb +1 -1
- data/lib/deltacloud/state_machine.rb +17 -0
- data/lib/deltacloud/validation.rb +18 -0
- data/lib/drivers.rb +69 -43
- data/lib/sinatra/lazy_auth.rb +1 -1
- data/lib/sinatra/rabbit.rb +5 -5
- data/lib/sinatra/rack_driver_select.rb +29 -0
- data/server.rb +45 -16
- data/views/api/drivers.xml.haml +6 -0
- data/views/api/show.html.haml +2 -2
- data/views/api/show.xml.haml +1 -1
- data/views/buckets/index.html.haml +2 -1
- data/views/buckets/show.html.haml +4 -3
- data/views/errors/backend_error.xml.haml +1 -1
- data/views/images/index.xml.haml +5 -1
- data/views/layout.html.haml +1 -1
- metadata +6 -5
- data/lib/deltacloud/drivers/gogrid/test.rb +0 -13
@@ -1,3 +1,21 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (C) 2009,2010 Red Hat, Inc.
|
3
|
+
#
|
4
|
+
# Licensed to the Apache Software Foundation (ASF) under one or more
|
5
|
+
# contributor license agreements. See the NOTICE file distributed with
|
6
|
+
# this work for additional information regarding copyright ownership. The
|
7
|
+
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
8
|
+
# "License"); you may not use this file except in compliance with the
|
9
|
+
# License. You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
15
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
16
|
+
# License for the specific language governing permissions and limitations
|
17
|
+
# under the License.
|
18
|
+
|
1
19
|
module RightAws
|
2
20
|
class MockEc2
|
3
21
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
#
|
2
|
-
# Copyright (C) 2009 Red Hat, Inc.
|
2
|
+
# Copyright (C) 2009, 2010 Red Hat, Inc.
|
3
3
|
#
|
4
4
|
# Licensed to the Apache Software Foundation (ASF) under one or more
|
5
5
|
# contributor license agreements. See the NOTICE file distributed with
|
@@ -37,10 +37,24 @@ class GogridDriver < Deltacloud::BaseDriver
|
|
37
37
|
|
38
38
|
feature :instances, :authentication_password
|
39
39
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
40
|
+
def hardware_profiles(credentials, opts={})
|
41
|
+
client = new_client(credentials)
|
42
|
+
safely do
|
43
|
+
server_types = client.request('common/lookup/list', { 'lookup' => 'server.type' })
|
44
|
+
server_rams = client.request('common/lookup/list', { 'lookup' => 'server.ram' })
|
45
|
+
@hardware_profiles = []
|
46
|
+
server_types['list'].each do |type|
|
47
|
+
memory_values = server_rams['list'].collect do |r|
|
48
|
+
r['name'] =~ /MB$/ ? r['name'].gsub(/MB$/, '').to_i : (r['name'].gsub(/(\w{2})$/, '')).to_i*1024
|
49
|
+
end
|
50
|
+
@hardware_profiles << ::Deltacloud::HardwareProfile.new(type['name'].tr(' ', '-').downcase) do
|
51
|
+
cpu 2
|
52
|
+
memory memory_values
|
53
|
+
storage 25
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
@hardware_profiles
|
44
58
|
end
|
45
59
|
|
46
60
|
def supported_collections
|
@@ -361,6 +375,7 @@ class GogridDriver < Deltacloud::BaseDriver
|
|
361
375
|
:description=> convert_description(gg_image),
|
362
376
|
:owner_id=>gg_image['owner']['name'],
|
363
377
|
:architecture=>convert_arch(gg_image['description']),
|
378
|
+
:state => gg_image['state']['name'].upcase
|
364
379
|
} )
|
365
380
|
end
|
366
381
|
|
@@ -228,6 +228,33 @@ class RackspaceDriver < Deltacloud::BaseDriver
|
|
228
228
|
end
|
229
229
|
end
|
230
230
|
|
231
|
+
#--
|
232
|
+
# Create Blob
|
233
|
+
#--
|
234
|
+
def create_blob(credentials, bucket_id, blob_id, blob_data, opts=nil)
|
235
|
+
cf = cloudfiles_client(credentials)
|
236
|
+
#must first create the object using cloudfiles_client.create_object
|
237
|
+
#then can write using object.write(data)
|
238
|
+
object = cf.container(bucket_id).create_object(blob_id)
|
239
|
+
#blob_data is a construct with data in .tempfile and content-type in {:type}
|
240
|
+
res = object.write(blob_data[:tempfile], {'Content-Type' => blob_data[:type]})
|
241
|
+
Blob.new( { :id => object.name,
|
242
|
+
:bucket => object.container.name,
|
243
|
+
:content_length => blob_data[:tempfile].length,
|
244
|
+
:content_type => blob_data[:type],
|
245
|
+
:last_modified => ''
|
246
|
+
}
|
247
|
+
)
|
248
|
+
end
|
249
|
+
|
250
|
+
#--
|
251
|
+
# Delete Blob
|
252
|
+
#--
|
253
|
+
def delete_blob(credentials, bucket_id, blob_id, opts=nil)
|
254
|
+
cf = cloudfiles_client(credentials)
|
255
|
+
cf.container(bucket_id).delete_object(blob_id)
|
256
|
+
end
|
257
|
+
|
231
258
|
private
|
232
259
|
|
233
260
|
def convert_srv_to_instance(srv)
|
@@ -271,7 +298,7 @@ private
|
|
271
298
|
|
272
299
|
def cloudfiles_client(credentials)
|
273
300
|
safely do
|
274
|
-
CloudFiles::Connection.new(credentials.user, credentials.password)
|
301
|
+
CloudFiles::Connection.new(:username => credentials.user, :api_key => credentials.password)
|
275
302
|
end
|
276
303
|
end
|
277
304
|
|
@@ -1,3 +1,20 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (C) 2009,2010 Red Hat, Inc.
|
3
|
+
#
|
4
|
+
# Licensed to the Apache Software Foundation (ASF) under one or more
|
5
|
+
# contributor license agreements. See the NOTICE file distributed with
|
6
|
+
# this work for additional information regarding copyright ownership. The
|
7
|
+
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
8
|
+
# "License"); you may not use this file except in compliance with the
|
9
|
+
# License. You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
15
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
16
|
+
# License for the specific language governing permissions and limitations
|
17
|
+
# under the License.
|
1
18
|
|
2
19
|
module Deltacloud
|
3
20
|
class HardwareProfile
|
data/lib/deltacloud/helpers.rb
CHANGED
@@ -1,3 +1,21 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (C) 2009,2010 Red Hat, Inc.
|
3
|
+
#
|
4
|
+
# Licensed to the Apache Software Foundation (ASF) under one or more
|
5
|
+
# contributor license agreements. See the NOTICE file distributed with
|
6
|
+
# this work for additional information regarding copyright ownership. The
|
7
|
+
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
8
|
+
# "License"); you may not use this file except in compliance with the
|
9
|
+
# License. You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
15
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
16
|
+
# License for the specific language governing permissions and limitations
|
17
|
+
# under the License.
|
18
|
+
|
1
19
|
require 'deltacloud/helpers/application_helper'
|
2
20
|
require 'deltacloud/helpers/conversion_helper'
|
3
21
|
require 'deltacloud/helpers/hardware_profiles_helper'
|
@@ -1,5 +1,4 @@
|
|
1
|
-
#
|
2
|
-
# Copyright (C) 2009 Red Hat, Inc.
|
1
|
+
# Copyright (C) 2009, 2010 Red Hat, Inc.
|
3
2
|
#
|
4
3
|
# Licensed to the Apache Software Foundation (ASF) under one or more
|
5
4
|
# contributor license agreements. See the NOTICE file distributed with
|
@@ -17,6 +16,7 @@
|
|
17
16
|
# under the License.
|
18
17
|
|
19
18
|
# Methods added to this helper will be available to all templates in the application.
|
19
|
+
|
20
20
|
module ApplicationHelper
|
21
21
|
|
22
22
|
def bread_crumb
|
@@ -28,7 +28,11 @@ begin
|
|
28
28
|
#the client guess and if they can't they SHOULD default to
|
29
29
|
#'application/octet-stream' anyway as per:
|
30
30
|
#http://www.w3.org/Protocols/rfc2616/rfc2616-sec7.html#sec7.2.1
|
31
|
-
EM.next_tick { env['async.callback'].call [200, {
|
31
|
+
EM.next_tick { env['async.callback'].call [200, {
|
32
|
+
'Content-Type' => "#{params['content_type']}",
|
33
|
+
'Content-Disposition' => params["content_disposition"],
|
34
|
+
'Content-Length' => "#{params['content_length']}"}, body]
|
35
|
+
}
|
32
36
|
#call the driver from here. the driver method yields for every chunk of blob it receives. We then
|
33
37
|
#use body.call to write that chunk as received.
|
34
38
|
driver.blob_data(credentials, params[:bucket], params[:blob], params) {|chunk| body.call ["#{chunk}"]} #close blob_data block
|
@@ -1,3 +1,20 @@
|
|
1
|
+
# Copyright (C) 2009, 2010 Red Hat, Inc.
|
2
|
+
#
|
3
|
+
# Licensed to the Apache Software Foundation (ASF) under one or more
|
4
|
+
# contributor license agreements. See the NOTICE file distributed with
|
5
|
+
# this work for additional information regarding copyright ownership. The
|
6
|
+
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
7
|
+
# "License"); you may not use this file except in compliance with the
|
8
|
+
# License. You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
14
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
15
|
+
# License for the specific language governing permissions and limitations
|
16
|
+
# under the License.
|
17
|
+
|
1
18
|
module HardwareProfilesHelper
|
2
19
|
|
3
20
|
def format_hardware_property(prop)
|
@@ -1,5 +1,5 @@
|
|
1
1
|
#
|
2
|
-
# Copyright (C) 2009 Red Hat, Inc.
|
2
|
+
# Copyright (C) 2009, 2010 Red Hat, Inc.
|
3
3
|
#
|
4
4
|
# Licensed to the Apache Software Foundation (ASF) under one or more
|
5
5
|
# contributor license agreements. See the NOTICE file distributed with
|
@@ -17,10 +17,12 @@
|
|
17
17
|
# under the License.
|
18
18
|
|
19
19
|
class Blob < BaseModel
|
20
|
+
|
20
21
|
#already has an id from basemodel (for the key)
|
21
22
|
attr_accessor :bucket
|
22
23
|
attr_accessor :content_length
|
23
24
|
attr_accessor :content_type
|
24
25
|
attr_accessor :last_modified
|
25
26
|
attr_accessor :content
|
27
|
+
|
26
28
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
#
|
2
|
-
# Copyright (C) 2009 Red Hat, Inc.
|
2
|
+
# Copyright (C) 2009, 2010 Red Hat, Inc.
|
3
3
|
#
|
4
4
|
# Licensed to the Apache Software Foundation (ASF) under one or more
|
5
5
|
# contributor license agreements. See the NOTICE file distributed with
|
@@ -21,4 +21,5 @@ class Bucket < BaseModel
|
|
21
21
|
attr_accessor :name
|
22
22
|
attr_accessor :size
|
23
23
|
attr_accessor :blob_list
|
24
|
+
|
24
25
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
#
|
2
|
-
# Copyright (C) 2009 Red Hat, Inc.
|
2
|
+
# Copyright (C) 2009, 2010 Red Hat, Inc.
|
3
3
|
#
|
4
4
|
# Licensed to the Apache Software Foundation (ASF) under one or more
|
5
5
|
# contributor license agreements. See the NOTICE file distributed with
|
@@ -16,7 +16,6 @@
|
|
16
16
|
# License for the specific language governing permissions and limitations
|
17
17
|
# under the License.
|
18
18
|
|
19
|
-
|
20
19
|
class Instance < BaseModel
|
21
20
|
|
22
21
|
attr_accessor :owner_id
|
@@ -1,5 +1,5 @@
|
|
1
1
|
#
|
2
|
-
# Copyright (C) 2009 Red Hat, Inc.
|
2
|
+
# Copyright (C) 2009, 2010 Red Hat, Inc.
|
3
3
|
#
|
4
4
|
# Licensed to the Apache Software Foundation (ASF) under one or more
|
5
5
|
# contributor license agreements. See the NOTICE file distributed with
|
@@ -18,6 +18,7 @@
|
|
18
18
|
|
19
19
|
# Model to store the hardware profile applied to an instance together with
|
20
20
|
# any instance-specific overrides
|
21
|
+
|
21
22
|
class InstanceProfile < BaseModel
|
22
23
|
attr_accessor :memory
|
23
24
|
attr_accessor :storage
|
@@ -1,3 +1,20 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (C) 2009,2010 Red Hat, Inc.
|
3
|
+
#
|
4
|
+
# Licensed to the Apache Software Foundation (ASF) under one or more
|
5
|
+
# contributor license agreements. See the NOTICE file distributed with
|
6
|
+
# this work for additional information regarding copyright ownership. The
|
7
|
+
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
8
|
+
# "License"); you may not use this file except in compliance with the
|
9
|
+
# License. You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
15
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
16
|
+
# License for the specific language governing permissions and limitations
|
17
|
+
# under the License.
|
1
18
|
|
2
19
|
module Deltacloud
|
3
20
|
class StateMachine
|
@@ -1,3 +1,21 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (C) 2009,2010 Red Hat, Inc.
|
3
|
+
#
|
4
|
+
# Licensed to the Apache Software Foundation (ASF) under one or more
|
5
|
+
# contributor license agreements. See the NOTICE file distributed with
|
6
|
+
# this work for additional information regarding copyright ownership. The
|
7
|
+
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
8
|
+
# "License"); you may not use this file except in compliance with the
|
9
|
+
# License. You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
15
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
16
|
+
# License for the specific language governing permissions and limitations
|
17
|
+
# under the License.
|
18
|
+
|
1
19
|
module Deltacloud::Validation
|
2
20
|
|
3
21
|
class Failure < StandardError
|
data/lib/drivers.rb
CHANGED
@@ -1,51 +1,77 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
:instance_states,
|
18
|
-
:realms,
|
19
|
-
:storage_volumes,
|
20
|
-
:storage_snapshots
|
21
|
-
]
|
22
|
-
|
23
|
-
DRIVER=ENV['API_DRIVER'] ? ENV['API_DRIVER'].to_sym : :mock
|
24
|
-
|
25
|
-
def driver_name
|
26
|
-
DRIVERS[DRIVER][:name]
|
27
|
-
end
|
1
|
+
# Copyright (C) 2009, 2010 Red Hat, Inc.
|
2
|
+
#
|
3
|
+
# Licensed to the Apache Software Foundation (ASF) under one or more
|
4
|
+
# contributor license agreements. See the NOTICE file distributed with
|
5
|
+
# this work for additional information regarding copyright ownership. The
|
6
|
+
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
7
|
+
# "License"); you may not use this file except in compliance with the
|
8
|
+
# License. You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
14
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
15
|
+
# License for the specific language governing permissions and limitations
|
16
|
+
# under the License.
|
28
17
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
18
|
+
module Deltacloud
|
19
|
+
DRIVERS = {
|
20
|
+
:ec2 => { :name => "EC2" },
|
21
|
+
:rackspace => { :name => "Rackspace" },
|
22
|
+
:gogrid => { :name => "Gogrid" },
|
23
|
+
:rhevm => { :name => "RHEVM" },
|
24
|
+
:rimuhosting => { :name => "RimuHosting"},
|
25
|
+
:opennebula => { :name => "Opennebula", :class => "OpennebulaDriver" },
|
26
|
+
:terremark => { :name => "Terremark"},
|
27
|
+
:azure => { :name => "Azure" },
|
28
|
+
:mock => { :name => "Mock" }
|
29
|
+
}
|
33
30
|
|
34
|
-
|
35
|
-
|
36
|
-
|
31
|
+
DEFAULT_COLLECTIONS = [
|
32
|
+
:hardware_profiles,
|
33
|
+
:images,
|
34
|
+
:instances,
|
35
|
+
:instance_states,
|
36
|
+
:realms,
|
37
|
+
:storage_volumes,
|
38
|
+
:storage_snapshots
|
39
|
+
]
|
37
40
|
|
38
|
-
|
39
|
-
return File.join('deltacloud', 'drivers', DRIVER.to_s, "#{DRIVER}_driver.rb") if driver_name.eql? 'Mock'
|
40
|
-
end
|
41
|
+
DRIVER=ENV['API_DRIVER'] ? ENV['API_DRIVER'].to_sym : :mock
|
41
42
|
|
42
|
-
def
|
43
|
-
|
44
|
-
|
43
|
+
def driver_symbol
|
44
|
+
(Thread.current[:driver] || DRIVER).to_sym
|
45
|
+
end
|
46
|
+
|
47
|
+
def driver_name
|
48
|
+
DRIVERS[:"#{driver_symbol}"][:name]
|
49
|
+
end
|
45
50
|
|
46
|
-
|
47
|
-
|
51
|
+
def driver_class_name
|
52
|
+
basename = DRIVERS[:"#{driver_symbol}"][:class] || "#{driver_name}Driver"
|
53
|
+
"Deltacloud::Drivers::#{driver_name}::#{basename}"
|
48
54
|
end
|
49
55
|
|
50
|
-
|
56
|
+
def driver_source_name
|
57
|
+
File.join("deltacloud", "drivers", "#{driver_symbol}", "#{driver_symbol}_driver.rb")
|
58
|
+
end
|
59
|
+
|
60
|
+
def driver_mock_source_name
|
61
|
+
return File.join('deltacloud', 'drivers', "#{driver_symbol}",
|
62
|
+
"#{driver_symbol}_driver.rb") if driver_name.eql? 'Mock'
|
63
|
+
end
|
64
|
+
|
65
|
+
def driver
|
66
|
+
require driver_source_name
|
67
|
+
#require 'deltacloud/base_driver/mock_driver.rb'
|
68
|
+
|
69
|
+
if Sinatra::Application.environment.eql? :test
|
70
|
+
require driver_mock_source_name if driver_mock_source_name
|
71
|
+
end
|
72
|
+
|
73
|
+
@driver ||= eval( driver_class_name ).new
|
74
|
+
end
|
51
75
|
end
|
76
|
+
|
77
|
+
include Deltacloud
|