bbrowning-deltacloud-core 0.0.4-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/COPYING +176 -0
- data/Rakefile +99 -0
- data/bin/deltacloudd +120 -0
- data/config.ru +5 -0
- data/deltacloud.rb +18 -0
- data/lib/deltacloud/base_driver/base_driver.rb +229 -0
- data/lib/deltacloud/base_driver/features.rb +166 -0
- data/lib/deltacloud/base_driver/mock_driver.rb +40 -0
- data/lib/deltacloud/base_driver.rb +20 -0
- data/lib/deltacloud/drivers/ec2/ec2_driver.rb +410 -0
- data/lib/deltacloud/drivers/ec2/ec2_mock_driver.rb +170 -0
- data/lib/deltacloud/drivers/gogrid/gogrid_client.rb +50 -0
- data/lib/deltacloud/drivers/gogrid/gogrid_driver.rb +332 -0
- data/lib/deltacloud/drivers/gogrid/test.rb +13 -0
- data/lib/deltacloud/drivers/mock/data/images/img1.yml +3 -0
- data/lib/deltacloud/drivers/mock/data/images/img2.yml +3 -0
- data/lib/deltacloud/drivers/mock/data/images/img3.yml +3 -0
- data/lib/deltacloud/drivers/mock/data/instances/inst0.yml +16 -0
- data/lib/deltacloud/drivers/mock/data/instances/inst1.yml +9 -0
- data/lib/deltacloud/drivers/mock/data/instances/inst2.yml +9 -0
- data/lib/deltacloud/drivers/mock/data/storage_snapshots/snap1.yml +4 -0
- data/lib/deltacloud/drivers/mock/data/storage_snapshots/snap2.yml +4 -0
- data/lib/deltacloud/drivers/mock/data/storage_snapshots/snap3.yml +4 -0
- data/lib/deltacloud/drivers/mock/data/storage_volumes/vol1.yml +6 -0
- data/lib/deltacloud/drivers/mock/data/storage_volumes/vol2.yml +6 -0
- data/lib/deltacloud/drivers/mock/data/storage_volumes/vol3.yml +6 -0
- data/lib/deltacloud/drivers/mock/mock_driver.rb +277 -0
- data/lib/deltacloud/drivers/opennebula/cloud_client.rb +116 -0
- data/lib/deltacloud/drivers/opennebula/occi_client.rb +204 -0
- data/lib/deltacloud/drivers/opennebula/opennebula_driver.rb +241 -0
- data/lib/deltacloud/drivers/rackspace/rackspace_client.rb +130 -0
- data/lib/deltacloud/drivers/rackspace/rackspace_driver.rb +182 -0
- data/lib/deltacloud/drivers/rhevm/rhevm_driver.rb +255 -0
- data/lib/deltacloud/drivers/rimuhosting/rimuhosting_client.rb +85 -0
- data/lib/deltacloud/drivers/rimuhosting/rimuhosting_driver.rb +166 -0
- data/lib/deltacloud/drivers/terremark/terremark_driver.rb +286 -0
- data/lib/deltacloud/hardware_profile.rb +153 -0
- data/lib/deltacloud/helpers/application_helper.rb +115 -0
- data/lib/deltacloud/helpers/conversion_helper.rb +39 -0
- data/lib/deltacloud/helpers/hardware_profiles_helper.rb +35 -0
- data/lib/deltacloud/helpers.rb +5 -0
- data/lib/deltacloud/method_serializer.rb +85 -0
- data/lib/deltacloud/models/base_model.rb +59 -0
- data/lib/deltacloud/models/image.rb +27 -0
- data/lib/deltacloud/models/instance.rb +38 -0
- data/lib/deltacloud/models/instance_profile.rb +48 -0
- data/lib/deltacloud/models/key.rb +35 -0
- data/lib/deltacloud/models/realm.rb +26 -0
- data/lib/deltacloud/models/storage_snapshot.rb +27 -0
- data/lib/deltacloud/models/storage_volume.rb +28 -0
- data/lib/deltacloud/state_machine.rb +84 -0
- data/lib/deltacloud/validation.rb +70 -0
- data/lib/drivers.rb +50 -0
- data/lib/sinatra/accept_media_types.rb +128 -0
- data/lib/sinatra/lazy_auth.rb +56 -0
- data/lib/sinatra/rabbit.rb +273 -0
- data/lib/sinatra/respond_to.rb +272 -0
- data/lib/sinatra/static_assets.rb +83 -0
- data/lib/sinatra/url_for.rb +53 -0
- data/public/favicon.ico +0 -0
- data/public/images/grid.png +0 -0
- data/public/images/logo-wide.png +0 -0
- data/public/images/rails.png +0 -0
- data/public/images/topbar-bg.png +0 -0
- data/public/javascripts/application.js +32 -0
- data/public/javascripts/jquery-1.4.2.min.js +154 -0
- data/public/stylesheets/compiled/application.css +613 -0
- data/public/stylesheets/compiled/ie.css +31 -0
- data/public/stylesheets/compiled/print.css +27 -0
- data/public/stylesheets/compiled/screen.css +456 -0
- data/server.rb +354 -0
- data/support/fedora/deltacloudd +68 -0
- data/support/fedora/rubygem-deltacloud-core.spec +91 -0
- data/tests/api_test.rb +37 -0
- data/tests/hardware_profiles_test.rb +120 -0
- data/tests/images_test.rb +111 -0
- data/tests/instance_states_test.rb +52 -0
- data/tests/instances_test.rb +219 -0
- data/tests/realms_test.rb +78 -0
- data/tests/url_for_test.rb +50 -0
- data/views/accounts/index.html.haml +11 -0
- data/views/accounts/show.html.haml +30 -0
- data/views/api/show.html.haml +15 -0
- data/views/api/show.xml.haml +5 -0
- data/views/docs/collection.html.haml +37 -0
- data/views/docs/collection.xml.haml +14 -0
- data/views/docs/index.html.haml +15 -0
- data/views/docs/index.xml.haml +5 -0
- data/views/docs/operation.html.haml +31 -0
- data/views/docs/operation.xml.haml +10 -0
- data/views/errors/auth_exception.html.haml +8 -0
- data/views/errors/auth_exception.xml.haml +2 -0
- data/views/errors/backend_error.html.haml +19 -0
- data/views/errors/backend_error.xml.haml +8 -0
- data/views/errors/not_found.html.haml +6 -0
- data/views/errors/not_found.xml.haml +2 -0
- data/views/errors/validation_failure.html.haml +11 -0
- data/views/errors/validation_failure.xml.haml +7 -0
- data/views/hardware_profiles/index.html.haml +25 -0
- data/views/hardware_profiles/index.xml.haml +4 -0
- data/views/hardware_profiles/show.html.haml +19 -0
- data/views/hardware_profiles/show.xml.haml +18 -0
- data/views/images/index.html.haml +30 -0
- data/views/images/index.xml.haml +8 -0
- data/views/images/show.html.haml +21 -0
- data/views/images/show.xml.haml +5 -0
- data/views/instance_states/show.gv.erb +45 -0
- data/views/instance_states/show.html.haml +31 -0
- data/views/instance_states/show.xml.haml +8 -0
- data/views/instances/index.html.haml +30 -0
- data/views/instances/index.xml.haml +21 -0
- data/views/instances/new.html.haml +55 -0
- data/views/instances/show.html.haml +43 -0
- data/views/instances/show.xml.haml +49 -0
- data/views/keys/index.html.haml +26 -0
- data/views/keys/index.xml.haml +4 -0
- data/views/keys/new.html.haml +8 -0
- data/views/keys/show.html.haml +22 -0
- data/views/keys/show.xml.haml +20 -0
- data/views/layout.html.haml +26 -0
- data/views/realms/index.html.haml +29 -0
- data/views/realms/index.xml.haml +10 -0
- data/views/realms/show.html.haml +15 -0
- data/views/realms/show.xml.haml +9 -0
- data/views/root/index.html.haml +4 -0
- data/views/storage_snapshots/index.html.haml +20 -0
- data/views/storage_snapshots/index.xml.haml +9 -0
- data/views/storage_snapshots/show.html.haml +14 -0
- data/views/storage_snapshots/show.xml.haml +7 -0
- data/views/storage_volumes/index.html.haml +21 -0
- data/views/storage_volumes/index.xml.haml +13 -0
- data/views/storage_volumes/show.html.haml +20 -0
- data/views/storage_volumes/show.xml.haml +11 -0
- metadata +334 -0
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright (C) 2009 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
|
+
|
|
19
|
+
|
|
20
|
+
require 'deltacloud/base_driver'
|
|
21
|
+
require 'yaml'
|
|
22
|
+
|
|
23
|
+
module Deltacloud
|
|
24
|
+
module Drivers
|
|
25
|
+
module Mock
|
|
26
|
+
class MockDriver < Deltacloud::BaseDriver
|
|
27
|
+
|
|
28
|
+
( REALMS = [
|
|
29
|
+
Realm.new({
|
|
30
|
+
:id=>'us',
|
|
31
|
+
:name=>'United States',
|
|
32
|
+
:limit=>:unlimited,
|
|
33
|
+
:state=>'AVAILABLE',
|
|
34
|
+
}),
|
|
35
|
+
Realm.new({
|
|
36
|
+
:id=>'eu',
|
|
37
|
+
:name=>'Europe',
|
|
38
|
+
:limit=>:unlimited,
|
|
39
|
+
:state=>'AVAILABLE',
|
|
40
|
+
}),
|
|
41
|
+
] ) unless defined?( REALMS )
|
|
42
|
+
|
|
43
|
+
define_hardware_profile('m1-small') do
|
|
44
|
+
cpu 1
|
|
45
|
+
memory 1.7 * 1024
|
|
46
|
+
storage 160
|
|
47
|
+
architecture 'i386'
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
define_hardware_profile('m1-large') do
|
|
51
|
+
cpu 2
|
|
52
|
+
memory (7.5*1024 .. 15*1024), :default => 10 * 1024
|
|
53
|
+
storage [ 850, 1024 ]
|
|
54
|
+
architecture 'x86_64'
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
define_hardware_profile('m1-xlarge') do
|
|
58
|
+
cpu 4
|
|
59
|
+
memory (12*1024 .. 32*1024)
|
|
60
|
+
storage [ 1024, 2048, 4096 ]
|
|
61
|
+
architecture 'x86_64'
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Some clouds tell us nothing about hardware profiles (e.g., OpenNebula)
|
|
65
|
+
define_hardware_profile 'opaque'
|
|
66
|
+
|
|
67
|
+
define_instance_states do
|
|
68
|
+
start.to( :pending ) .on( :create )
|
|
69
|
+
|
|
70
|
+
pending.to( :running ) .automatically
|
|
71
|
+
|
|
72
|
+
running.to( :running ) .on( :reboot )
|
|
73
|
+
running.to( :stopped ) .on( :stop )
|
|
74
|
+
|
|
75
|
+
stopped.to( :running ) .on( :start )
|
|
76
|
+
stopped.to( :finish ) .on( :destroy )
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
feature :instances, :user_name
|
|
80
|
+
|
|
81
|
+
def initialize
|
|
82
|
+
if ENV["DELTACLOUD_MOCK_STORAGE"]
|
|
83
|
+
@storage_root = ENV["DELTACLOUD_MOCK_STORAGE"]
|
|
84
|
+
elsif ENV["USER"]
|
|
85
|
+
@storage_root = File::join("/var/tmp", "deltacloud-mock-#{ENV["USER"]}")
|
|
86
|
+
else
|
|
87
|
+
raise "Please set either the DELTACLOUD_MOCK_STORAGE or USER environment variable"
|
|
88
|
+
end
|
|
89
|
+
if ! File::directory?(@storage_root)
|
|
90
|
+
FileUtils::rm_rf(@storage_root)
|
|
91
|
+
FileUtils::mkdir_p(@storage_root)
|
|
92
|
+
data = Dir::glob(File::join(File::dirname(__FILE__), "data", "*"))
|
|
93
|
+
FileUtils::cp_r(data, @storage_root)
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def realms(credentials, opts=nil)
|
|
98
|
+
return REALMS if ( opts.nil? )
|
|
99
|
+
results = REALMS
|
|
100
|
+
results = filter_on( results, :id, opts )
|
|
101
|
+
results
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
#
|
|
105
|
+
# Images
|
|
106
|
+
#
|
|
107
|
+
|
|
108
|
+
def images(credentials, opts=nil )
|
|
109
|
+
check_credentials( credentials )
|
|
110
|
+
images = []
|
|
111
|
+
Dir[ "#{@storage_root}/images/*.yml" ].each do |image_file|
|
|
112
|
+
image = YAML.load( File.read( image_file ) )
|
|
113
|
+
image[:id] = File.basename( image_file, ".yml" )
|
|
114
|
+
image[:name] = image[:description]
|
|
115
|
+
images << Image.new( image )
|
|
116
|
+
end
|
|
117
|
+
images = filter_on( images, :id, opts )
|
|
118
|
+
images = filter_on( images, :architecture, opts )
|
|
119
|
+
if ( opts && opts[:owner_id] == 'self' )
|
|
120
|
+
images = images.select{|e| e.owner_id == credentials.user }
|
|
121
|
+
else
|
|
122
|
+
images = filter_on( images, :owner_id, opts )
|
|
123
|
+
end
|
|
124
|
+
images.sort_by{|e| [e.owner_id,e.description]}
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
#
|
|
128
|
+
# Instances
|
|
129
|
+
#
|
|
130
|
+
|
|
131
|
+
def instances(credentials, opts=nil)
|
|
132
|
+
check_credentials( credentials )
|
|
133
|
+
instances = []
|
|
134
|
+
Dir[ "#{@storage_root}/instances/*.yml" ].each do |instance_file|
|
|
135
|
+
instance = YAML.load( File.read( instance_file ) )
|
|
136
|
+
if ( instance[:owner_id] == credentials.user )
|
|
137
|
+
instance[:id] = File.basename( instance_file, ".yml" )
|
|
138
|
+
instance[:actions] = instance_actions_for( instance[:state] )
|
|
139
|
+
instances << Instance.new( instance )
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
instances = filter_on( instances, :id, opts )
|
|
143
|
+
instances = filter_on( instances, :state, opts )
|
|
144
|
+
instances
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def create_instance(credentials, image_id, opts)
|
|
148
|
+
check_credentials( credentials )
|
|
149
|
+
ids = Dir[ "#{@storage_root}/instances/*.yml" ].collect{|e| File.basename( e, ".yml" )}
|
|
150
|
+
|
|
151
|
+
count = 0
|
|
152
|
+
while true
|
|
153
|
+
next_id = "inst" + count.to_s
|
|
154
|
+
if not ids.include?(next_id)
|
|
155
|
+
break
|
|
156
|
+
end
|
|
157
|
+
count = count + 1
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
realm_id = opts[:realm_id]
|
|
161
|
+
if ( realm_id.nil? )
|
|
162
|
+
realm = realms(credentials).first
|
|
163
|
+
( realm_id = realm.id ) if realm
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
hwp = find_hardware_profile(credentials, opts[:hwp_id], image_id)
|
|
167
|
+
|
|
168
|
+
name = opts[:name] || "i-#{Time.now.to_i}"
|
|
169
|
+
|
|
170
|
+
instance = {
|
|
171
|
+
:name=>name,
|
|
172
|
+
:state=>'RUNNING',
|
|
173
|
+
:image_id=>image_id,
|
|
174
|
+
:owner_id=>credentials.user,
|
|
175
|
+
:public_addresses=>["#{image_id}.#{next_id}.public.com"],
|
|
176
|
+
:private_addresses=>["#{image_id}.#{next_id}.private.com"],
|
|
177
|
+
:instance_profile => InstanceProfile.new(hwp.name, opts),
|
|
178
|
+
:realm_id=>realm_id,
|
|
179
|
+
:actions=>instance_actions_for( 'RUNNING' )
|
|
180
|
+
}
|
|
181
|
+
File.open( "#{@storage_root}/instances/#{next_id}.yml", 'w' ) {|f|
|
|
182
|
+
YAML.dump( instance, f )
|
|
183
|
+
}
|
|
184
|
+
instance[:id] = next_id
|
|
185
|
+
Instance.new( instance )
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def start_instance(credentials, id)
|
|
189
|
+
instance_file = "#{@storage_root}/instances/#{id}.yml"
|
|
190
|
+
instance_yml = YAML.load( File.read( instance_file ) )
|
|
191
|
+
instance_yml[:state] = 'RUNNING'
|
|
192
|
+
File.open( instance_file, 'w' ) do |f|
|
|
193
|
+
f << YAML.dump( instance_yml )
|
|
194
|
+
end
|
|
195
|
+
Instance.new( instance_yml )
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def reboot_instance(credentials, id)
|
|
199
|
+
instance_file = "#{@storage_root}/instances/#{id}.yml"
|
|
200
|
+
instance_yml = YAML.load( File.read( instance_file ) )
|
|
201
|
+
instance_yml[:state] = 'RUNNING'
|
|
202
|
+
File.open( instance_file, 'w' ) do |f|
|
|
203
|
+
f << YAML.dump( instance_yml )
|
|
204
|
+
end
|
|
205
|
+
Instance.new( instance_yml )
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
def stop_instance(credentials, id)
|
|
209
|
+
instance_file = "#{@storage_root}/instances/#{id}.yml"
|
|
210
|
+
instance_yml = YAML.load( File.read( instance_file ) )
|
|
211
|
+
instance_yml[:state] = 'STOPPED'
|
|
212
|
+
File.open( instance_file, 'w' ) do |f|
|
|
213
|
+
f << YAML.dump( instance_yml )
|
|
214
|
+
end
|
|
215
|
+
Instance.new( instance_yml )
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def destroy_instance(credentials, id)
|
|
220
|
+
check_credentials( credentials )
|
|
221
|
+
FileUtils.rm( "#{@storage_root}/instances/#{id}.yml" )
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
#
|
|
225
|
+
# Storage Volumes
|
|
226
|
+
#
|
|
227
|
+
|
|
228
|
+
def storage_volumes(credentials, opts=nil)
|
|
229
|
+
check_credentials( credentials )
|
|
230
|
+
volumes = []
|
|
231
|
+
Dir[ "#{@storage_root}/storage_volumes/*.yml" ].each do |storage_volume_file|
|
|
232
|
+
storage_volume = YAML.load( File.read( storage_volume_file ) )
|
|
233
|
+
if ( storage_volume[:owner_id] == credentials.user )
|
|
234
|
+
storage_volume[:id] = File.basename( storage_volume_file, ".yml" )
|
|
235
|
+
volumes << StorageVolume.new( storage_volume )
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
volumes = filter_on( volumes, :id, opts )
|
|
239
|
+
volumes
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
#
|
|
243
|
+
# Storage Snapshots
|
|
244
|
+
#
|
|
245
|
+
|
|
246
|
+
def storage_snapshots(credentials, opts=nil)
|
|
247
|
+
check_credentials( credentials )
|
|
248
|
+
snapshots = []
|
|
249
|
+
Dir[ "#{@storage_root}/storage_snapshots/*.yml" ].each do |storage_snapshot_file|
|
|
250
|
+
storage_snapshot = YAML.load( File.read( storage_snapshot_file ) )
|
|
251
|
+
if ( storage_snapshot[:owner_id] == credentials.user )
|
|
252
|
+
storage_snapshot[:id] = File.basename( storage_snapshot_file, ".yml" )
|
|
253
|
+
snapshots << StorageSnapshot.new( storage_snapshot )
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
snapshots = filter_on( snapshots, :id, opts )
|
|
257
|
+
snapshots
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
private
|
|
261
|
+
|
|
262
|
+
def check_credentials(credentials)
|
|
263
|
+
if ( credentials.user != 'mockuser' )
|
|
264
|
+
raise Deltacloud::AuthException.new
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
if ( credentials.password != 'mockpassword' )
|
|
268
|
+
raise Deltacloud::AuthException.new
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
end
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
#--------------------------------------------------------------------------- #
|
|
2
|
+
# Copyright 2002-2009, Distributed Systems Architecture Group, Universidad
|
|
3
|
+
# Complutense de Madrid (dsa-research.org)
|
|
4
|
+
#
|
|
5
|
+
# This library is free software; you can redistribute it and/or
|
|
6
|
+
# modify it under the terms of the GNU Lesser General Public
|
|
7
|
+
# License as published by the Free Software Foundation; either
|
|
8
|
+
# version 2.1 of the License, or (at your option) any later version.
|
|
9
|
+
#
|
|
10
|
+
# This library is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
13
|
+
# Lesser General Public License for more details.
|
|
14
|
+
#
|
|
15
|
+
# You should have received a copy of the GNU Lesser General Public
|
|
16
|
+
# License along with this library; if not, write to the Free Software
|
|
17
|
+
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
18
|
+
#--------------------------------------------------------------------------- #
|
|
19
|
+
|
|
20
|
+
require 'rubygems'
|
|
21
|
+
require 'uri'
|
|
22
|
+
|
|
23
|
+
require 'net/https'
|
|
24
|
+
|
|
25
|
+
begin
|
|
26
|
+
require 'net/http/post/multipart'
|
|
27
|
+
rescue LoadError
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
###############################################################################
|
|
31
|
+
# The CloudClient module contains general functionality to implement a
|
|
32
|
+
# Cloud Client
|
|
33
|
+
###############################################################################
|
|
34
|
+
module CloudClient
|
|
35
|
+
# #########################################################################
|
|
36
|
+
# Default location for the authentication file
|
|
37
|
+
# #########################################################################
|
|
38
|
+
DEFAULT_AUTH_FILE = ENV["HOME"]+"/.one/one_auth"
|
|
39
|
+
|
|
40
|
+
# #########################################################################
|
|
41
|
+
# Gets authorization credentials from ONE_AUTH or default
|
|
42
|
+
# auth file.
|
|
43
|
+
#
|
|
44
|
+
# Raises an error if authorization is not found
|
|
45
|
+
# #########################################################################
|
|
46
|
+
def self.get_one_auth
|
|
47
|
+
if ENV["ONE_AUTH"] and !ENV["ONE_AUTH"].empty? and
|
|
48
|
+
File.file?(ENV["ONE_AUTH"])
|
|
49
|
+
one_auth=File.read(ENV["ONE_AUTH"]).strip.split(':')
|
|
50
|
+
elsif File.file?(DEFAULT_AUTH_FILE)
|
|
51
|
+
one_auth=File.read(DEFAULT_AUTH_FILE).strip.split(':')
|
|
52
|
+
else
|
|
53
|
+
raise "No authorization data present"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
raise "Authorization data malformed" if one_auth.length < 2
|
|
57
|
+
|
|
58
|
+
one_auth
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# #########################################################################
|
|
62
|
+
# Starts an http connection and calls the block provided. SSL flag
|
|
63
|
+
# is set if needed.
|
|
64
|
+
# #########################################################################
|
|
65
|
+
def self.http_start(url, &block)
|
|
66
|
+
http = Net::HTTP.new(url.host, url.port)
|
|
67
|
+
if url.scheme=='https'
|
|
68
|
+
http.use_ssl = true
|
|
69
|
+
http.verify_mode=OpenSSL::SSL::VERIFY_NONE
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
begin
|
|
73
|
+
http.start do |connection|
|
|
74
|
+
block.call(connection)
|
|
75
|
+
end
|
|
76
|
+
rescue Errno::ECONNREFUSED => e
|
|
77
|
+
str = "Error connecting to server (#{e.to_s})."
|
|
78
|
+
str << "Server: #{url.host}:#{url.port}"
|
|
79
|
+
|
|
80
|
+
return CloudClient::Error.new(str)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# #########################################################################
|
|
85
|
+
# The Error Class represents a generic error in the Cloud Client
|
|
86
|
+
# library. It contains a readable representation of the error.
|
|
87
|
+
# #########################################################################
|
|
88
|
+
class Error
|
|
89
|
+
attr_reader :message
|
|
90
|
+
|
|
91
|
+
# +message+ a description of the error
|
|
92
|
+
def initialize(message=nil)
|
|
93
|
+
@message=message
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def to_s()
|
|
97
|
+
@message
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# #########################################################################
|
|
102
|
+
# Returns true if the object returned by a method of the OpenNebula
|
|
103
|
+
# library is an Error
|
|
104
|
+
# #########################################################################
|
|
105
|
+
def self.is_error?(value)
|
|
106
|
+
value.class==CloudClient::Error
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Command line help functions
|
|
111
|
+
module CloudCLI
|
|
112
|
+
# Returns the command name
|
|
113
|
+
def cmd_name
|
|
114
|
+
File.basename($0)
|
|
115
|
+
end
|
|
116
|
+
end
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
#--------------------------------------------------------------------------- #
|
|
2
|
+
# Copyright 2002-2009, Distributed Systems Architecture Group, Universidad
|
|
3
|
+
# Complutense de Madrid (dsa-research.org)
|
|
4
|
+
#
|
|
5
|
+
# This library is free software; you can redistribute it and/or
|
|
6
|
+
# modify it under the terms of the GNU Lesser General Public
|
|
7
|
+
# License as published by the Free Software Foundation; either
|
|
8
|
+
# version 2.1 of the License, or (at your option) any later version.
|
|
9
|
+
#
|
|
10
|
+
# This library is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
13
|
+
# Lesser General Public License for more details.
|
|
14
|
+
#
|
|
15
|
+
# You should have received a copy of the GNU Lesser General Public
|
|
16
|
+
# License along with this library; if not, write to the Free Software
|
|
17
|
+
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
18
|
+
#--------------------------------------------------------------------------- #
|
|
19
|
+
|
|
20
|
+
require 'rubygems'
|
|
21
|
+
require 'uri'
|
|
22
|
+
require 'rexml/document'
|
|
23
|
+
|
|
24
|
+
require 'deltacloud/drivers/opennebula/cloud_client'
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
module OCCIClient
|
|
28
|
+
|
|
29
|
+
#####################################################################
|
|
30
|
+
# Client Library to interface with the OpenNebula OCCI Service
|
|
31
|
+
#####################################################################
|
|
32
|
+
class Client
|
|
33
|
+
|
|
34
|
+
######################################################################
|
|
35
|
+
# Initialize client library
|
|
36
|
+
######################################################################
|
|
37
|
+
def initialize(endpoint_str=nil, user=nil, pass=nil, debug_flag=true)
|
|
38
|
+
@debug = debug_flag
|
|
39
|
+
|
|
40
|
+
# Server location
|
|
41
|
+
if endpoint_str
|
|
42
|
+
@endpoint = endpoint_str
|
|
43
|
+
elsif ENV["OCCI_URL"]
|
|
44
|
+
@endpoint = ENV["OCCI_URL"]
|
|
45
|
+
else
|
|
46
|
+
@endpoint = "http://localhost:4567"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Autentication
|
|
50
|
+
if user && pass
|
|
51
|
+
@occiauth = [user, pass]
|
|
52
|
+
else
|
|
53
|
+
@occiauth = CloudClient::get_one_auth
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
if !@occiauth
|
|
57
|
+
raise "No authorization data present"
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
@occiauth[1] = Digest::SHA1.hexdigest(@occiauth[1])
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
#################################
|
|
64
|
+
# Pool Resource Request Methods #
|
|
65
|
+
#################################
|
|
66
|
+
|
|
67
|
+
######################################################################
|
|
68
|
+
# Post a new VM to the VM Pool
|
|
69
|
+
# :instance_type
|
|
70
|
+
# :xmlfile
|
|
71
|
+
######################################################################
|
|
72
|
+
def post_vms(xmlfile)
|
|
73
|
+
xml=File.read(xmlfile)
|
|
74
|
+
|
|
75
|
+
url = URI.parse(@endpoint+"/compute")
|
|
76
|
+
|
|
77
|
+
req = Net::HTTP::Post.new(url.path)
|
|
78
|
+
req.body=xml
|
|
79
|
+
|
|
80
|
+
req.basic_auth @occiauth[0], @occiauth[1]
|
|
81
|
+
|
|
82
|
+
res = CloudClient::http_start(url) do |http|
|
|
83
|
+
http.request(req)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
if CloudClient::is_error?(res)
|
|
87
|
+
return res
|
|
88
|
+
else
|
|
89
|
+
return res.body
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
######################################################################
|
|
94
|
+
# Retieves the pool of Virtual Machines
|
|
95
|
+
######################################################################
|
|
96
|
+
def get_vms
|
|
97
|
+
url = URI.parse(@endpoint+"/compute")
|
|
98
|
+
req = Net::HTTP::Get.new(url.path)
|
|
99
|
+
|
|
100
|
+
req.basic_auth @occiauth[0], @occiauth[1]
|
|
101
|
+
|
|
102
|
+
res = CloudClient::http_start(url) {|http|
|
|
103
|
+
http.request(req)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if CloudClient::is_error?(res)
|
|
107
|
+
return res
|
|
108
|
+
else
|
|
109
|
+
return res.body
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
######################################################################
|
|
114
|
+
# Retieves the pool of Images owned by the user
|
|
115
|
+
######################################################################
|
|
116
|
+
def get_images
|
|
117
|
+
url = URI.parse(@endpoint+"/storage")
|
|
118
|
+
req = Net::HTTP::Get.new(url.path)
|
|
119
|
+
|
|
120
|
+
req.basic_auth @occiauth[0], @occiauth[1]
|
|
121
|
+
|
|
122
|
+
res = CloudClient::http_start(url) {|http|
|
|
123
|
+
http.request(req)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if CloudClient::is_error?(res)
|
|
127
|
+
return res
|
|
128
|
+
else
|
|
129
|
+
return res.body
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
####################################
|
|
134
|
+
# Entity Resource Request Methods #
|
|
135
|
+
####################################
|
|
136
|
+
|
|
137
|
+
######################################################################
|
|
138
|
+
# :id VM identifier
|
|
139
|
+
######################################################################
|
|
140
|
+
def get_vm(id)
|
|
141
|
+
url = URI.parse(@endpoint+"/compute/" + id.to_s)
|
|
142
|
+
req = Net::HTTP::Get.new(url.path)
|
|
143
|
+
|
|
144
|
+
req.basic_auth @occiauth[0], @occiauth[1]
|
|
145
|
+
|
|
146
|
+
res = CloudClient::http_start(url) {|http|
|
|
147
|
+
http.request(req)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if CloudClient::is_error?(res)
|
|
151
|
+
return res
|
|
152
|
+
else
|
|
153
|
+
return res.body
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
######################################################################
|
|
158
|
+
# Puts a new Compute representation in order to change its state
|
|
159
|
+
# :xmlfile Compute OCCI xml representation
|
|
160
|
+
######################################################################
|
|
161
|
+
def put_vm(xmlfile)
|
|
162
|
+
xml=File.read(xmlfile)
|
|
163
|
+
vm_info=REXML::Document.new(xml).root.elements
|
|
164
|
+
|
|
165
|
+
url = URI.parse(@endpoint+'/compute/' + vm_info['ID'].text)
|
|
166
|
+
|
|
167
|
+
req = Net::HTTP::Put.new(url.path)
|
|
168
|
+
req.body = xml
|
|
169
|
+
|
|
170
|
+
req.basic_auth @occiauth[0], @occiauth[1]
|
|
171
|
+
|
|
172
|
+
res = CloudClient::http_start(url) do |http|
|
|
173
|
+
http.request(req)
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
if CloudClient::is_error?(res)
|
|
177
|
+
return res
|
|
178
|
+
else
|
|
179
|
+
return res.body
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
#######################################################################
|
|
184
|
+
# Retieves an Image
|
|
185
|
+
# :image_uuid Image identifier
|
|
186
|
+
######################################################################
|
|
187
|
+
def get_image(image_uuid)
|
|
188
|
+
url = URI.parse(@endpoint+"/storage/"+image_uuid)
|
|
189
|
+
req = Net::HTTP::Get.new(url.path)
|
|
190
|
+
|
|
191
|
+
req.basic_auth @occiauth[0], @occiauth[1]
|
|
192
|
+
|
|
193
|
+
res = CloudClient::http_start(url) {|http|
|
|
194
|
+
http.request(req)
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if CloudClient::is_error?(res)
|
|
198
|
+
return res
|
|
199
|
+
else
|
|
200
|
+
return res.body
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
end
|