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
@@ -8,11 +8,16 @@
|
|
8
8
|
- :stop
|
9
9
|
:owner_id: mockuser
|
10
10
|
:public_addresses:
|
11
|
-
-
|
11
|
+
- !ruby/object:InstanceAddress
|
12
|
+
address: img1.inst0.public.com
|
13
|
+
address_type: :hostname
|
12
14
|
:private_addresses:
|
13
|
-
-
|
15
|
+
- !ruby/object:InstanceAddress
|
16
|
+
address: img1.inst0.private.com
|
17
|
+
address_type: :hostname
|
14
18
|
:create_image: true
|
15
19
|
:image_id: img1
|
16
20
|
:name: Mock Instance With Profile Change
|
17
21
|
:id: inst0
|
18
22
|
:state: RUNNING
|
23
|
+
:storage_volumes: []
|
@@ -4,9 +4,13 @@
|
|
4
4
|
:realm_id: us
|
5
5
|
:owner_id: mockuser
|
6
6
|
:public_addresses:
|
7
|
-
-
|
7
|
+
- !ruby/object:InstanceAddress
|
8
|
+
address: img1.inst1.public.com
|
9
|
+
address_type: :hostname
|
8
10
|
:private_addresses:
|
9
|
-
-
|
11
|
+
- !ruby/object:InstanceAddress
|
12
|
+
address: img1.inst1.private.com
|
13
|
+
address_type: :hostname
|
10
14
|
:create_image: true
|
11
15
|
:image_id: img3
|
12
16
|
:name: MockUserInstance
|
@@ -15,3 +19,4 @@
|
|
15
19
|
:actions:
|
16
20
|
- :reboot
|
17
21
|
- :stop
|
22
|
+
:storage_volumes: []
|
@@ -4,9 +4,13 @@
|
|
4
4
|
:realm_id: us
|
5
5
|
:owner_id: anotheruser
|
6
6
|
:public_addresses:
|
7
|
-
-
|
7
|
+
- !ruby/object:InstanceAddress
|
8
|
+
address: img1.inst2.public.com
|
9
|
+
address_type: :hostname
|
8
10
|
:private_addresses:
|
9
|
-
-
|
11
|
+
- !ruby/object:InstanceAddress
|
12
|
+
address: img1.inst2.private.com
|
13
|
+
address_type: :hostname
|
10
14
|
:create_image: true
|
11
15
|
:image_id: img1
|
12
16
|
:name: AnotherInstance
|
@@ -15,3 +19,4 @@
|
|
15
19
|
:actions:
|
16
20
|
- :reboot
|
17
21
|
- :stop
|
22
|
+
:storage_volumes: []
|
@@ -91,6 +91,23 @@ module Deltacloud::Drivers::Mock
|
|
91
91
|
FileUtils.rm(fname) if File::exists?(fname)
|
92
92
|
end
|
93
93
|
|
94
|
+
def load_all_cimi(model_name)
|
95
|
+
model_files = Dir[File::join(cimi_dir(model_name), "*.json")]
|
96
|
+
model_files.map{|f| File.read(f)}
|
97
|
+
end
|
98
|
+
|
99
|
+
def load_cimi(model_name, id)
|
100
|
+
File.read(cimi_file(model_name, id))
|
101
|
+
end
|
102
|
+
|
103
|
+
def cimi_file(collection, id)
|
104
|
+
File::join(cimi_dir(collection), "#{id}.json")
|
105
|
+
end
|
106
|
+
|
107
|
+
def cimi_dir(collection)
|
108
|
+
File::join(@storage_root, "cimi", collection.to_s)
|
109
|
+
end
|
110
|
+
|
94
111
|
private
|
95
112
|
|
96
113
|
def collection_name(klass)
|
@@ -15,10 +15,11 @@
|
|
15
15
|
# under the License.
|
16
16
|
|
17
17
|
|
18
|
-
require 'deltacloud/base_driver'
|
19
18
|
require 'yaml'
|
20
|
-
require 'deltacloud/drivers/mock/mock_client'
|
21
19
|
require 'base64'
|
20
|
+
require 'etc'
|
21
|
+
require 'deltacloud/base_driver'
|
22
|
+
require 'deltacloud/drivers/mock/mock_client'
|
22
23
|
|
23
24
|
module Deltacloud::Drivers::Mock
|
24
25
|
|
@@ -55,8 +56,8 @@ module Deltacloud::Drivers::Mock
|
|
55
56
|
end
|
56
57
|
|
57
58
|
define_hardware_profile('m1-large') do
|
58
|
-
cpu
|
59
|
-
memory (
|
59
|
+
cpu (1..6)
|
60
|
+
memory ( 7680.. 15*1024), :default => 10 * 1024
|
60
61
|
storage [ 850, 1024 ]
|
61
62
|
architecture 'x86_64'
|
62
63
|
end
|
@@ -90,7 +91,7 @@ module Deltacloud::Drivers::Mock
|
|
90
91
|
def initialize
|
91
92
|
if ENV["DELTACLOUD_MOCK_STORAGE"]
|
92
93
|
storage_root = ENV["DELTACLOUD_MOCK_STORAGE"]
|
93
|
-
elsif
|
94
|
+
elsif Etc.getlogin
|
94
95
|
storage_root = File::join("/var/tmp", "deltacloud-mock-#{ENV["USER"]}")
|
95
96
|
else
|
96
97
|
raise "Please set either the DELTACLOUD_MOCK_STORAGE or USER environment variable"
|
@@ -195,8 +196,8 @@ module Deltacloud::Drivers::Mock
|
|
195
196
|
:keyname => opts[:keyname],
|
196
197
|
:image_id=>image_id,
|
197
198
|
:owner_id=>credentials.user,
|
198
|
-
:public_addresses=>["#{image_id}.#{next_id}.public.com"],
|
199
|
-
:private_addresses=>["#{image_id}.#{next_id}.private.com"],
|
199
|
+
:public_addresses=>[ InstanceAddress.new("#{image_id}.#{next_id}.public.com", :type => :hostname) ],
|
200
|
+
:private_addresses=>[ InstanceAddress.new("#{image_id}.#{next_id}.private.com", :type => :hostname) ],
|
200
201
|
:instance_profile => InstanceProfile.new(hwp.name, opts),
|
201
202
|
:realm_id=>realm_id,
|
202
203
|
:create_image=>true,
|
@@ -236,7 +237,6 @@ module Deltacloud::Drivers::Mock
|
|
236
237
|
#
|
237
238
|
# Storage Volumes
|
238
239
|
#
|
239
|
-
|
240
240
|
def storage_volumes(credentials, opts=nil)
|
241
241
|
check_credentials( credentials )
|
242
242
|
volumes = @client.build_all(StorageVolume)
|
@@ -244,6 +244,36 @@ module Deltacloud::Drivers::Mock
|
|
244
244
|
volumes
|
245
245
|
end
|
246
246
|
|
247
|
+
def create_storage_volume(credentials, opts=nil)
|
248
|
+
check_credentials(credentials)
|
249
|
+
opts ||= {}
|
250
|
+
opts[:capacity] ||= "1"
|
251
|
+
volume = {
|
252
|
+
:id => "Volume#{Time.now.to_i}",
|
253
|
+
:created => Time.now.to_s,
|
254
|
+
:state => "AVAILABLE",
|
255
|
+
:capacity => opts[:capacity],
|
256
|
+
}
|
257
|
+
@client.store(:storage_volumes, volume)
|
258
|
+
StorageVolume.new(volume)
|
259
|
+
end
|
260
|
+
|
261
|
+
def destroy_storage_volume(credentials, opts=nil)
|
262
|
+
check_credentials(credentials)
|
263
|
+
@client.destroy(:storage_volumes, opts[:id])
|
264
|
+
end
|
265
|
+
|
266
|
+
#opts: {:id=,:instance_id,:device}
|
267
|
+
def attach_storage_volume(credentials, opts)
|
268
|
+
check_credentials(credentials)
|
269
|
+
attach_volume_instance(opts[:id], opts[:device], opts[:instance_id])
|
270
|
+
end
|
271
|
+
|
272
|
+
def detach_storage_volume(credentials, opts)
|
273
|
+
check_credentials(credentials)
|
274
|
+
detach_volume_instance(opts[:id], opts[:instance_id])
|
275
|
+
end
|
276
|
+
|
247
277
|
#
|
248
278
|
# Storage Snapshots
|
249
279
|
#
|
@@ -410,6 +440,17 @@ module Deltacloud::Drivers::Mock
|
|
410
440
|
return false
|
411
441
|
end
|
412
442
|
|
443
|
+
def networks(credentials, opts={})
|
444
|
+
check_credentials(credentials)
|
445
|
+
if opts[:id].nil?
|
446
|
+
networks = @client.load_all_cimi(:network).map{|net| CIMI::Model::Network.from_json(net)}
|
447
|
+
networks.map{|net|convert_cimi_network(net,opts[:env])}.flatten
|
448
|
+
else
|
449
|
+
network = CIMI::Model::Network.from_json(@client.load_cimi(:network, opts[:id]))
|
450
|
+
convert_cimi_network(network, opts[:env])
|
451
|
+
end
|
452
|
+
end
|
453
|
+
|
413
454
|
private
|
414
455
|
|
415
456
|
def check_credentials(credentials)
|
@@ -420,6 +461,39 @@ module Deltacloud::Drivers::Mock
|
|
420
461
|
end
|
421
462
|
end
|
422
463
|
|
464
|
+
def attach_volume_instance(volume_id, device, instance_id)
|
465
|
+
volume = @client.load(:storage_volumes, volume_id)
|
466
|
+
instance = @client.load(:instances, instance_id)
|
467
|
+
volume[:instance_id] = instance_id
|
468
|
+
volume[:device] = device
|
469
|
+
volume[:state] = "IN-USE"
|
470
|
+
instance[:storage_volumes] ||= []
|
471
|
+
instance[:storage_volumes] << {volume_id=>device}
|
472
|
+
@client.store(:storage_volumes, volume)
|
473
|
+
@client.store(:instances, instance)
|
474
|
+
StorageVolume.new(volume)
|
475
|
+
end
|
476
|
+
|
477
|
+
def detach_volume_instance(volume_id, instance_id)
|
478
|
+
volume = @client.load(:storage_volumes, volume_id)
|
479
|
+
instance = @client.load(:instances, instance_id)
|
480
|
+
volume[:instance_id] = nil
|
481
|
+
device = volume[:device]
|
482
|
+
volume[:device] = nil
|
483
|
+
volume[:state] = "AVAILABLE"
|
484
|
+
instance[:storage_volumes].delete({volume_id => device}) unless instance[:storage_volumes].nil?
|
485
|
+
@client.store(:storage_volumes, volume)
|
486
|
+
@client.store(:instances, instance)
|
487
|
+
StorageVolume.new(volume)
|
488
|
+
end
|
489
|
+
|
490
|
+
def convert_cimi_network(network, context)
|
491
|
+
uri=context.network_url(network.name)
|
492
|
+
network.uri=uri
|
493
|
+
network.operations.each{|op| op.href=uri}
|
494
|
+
network
|
495
|
+
end
|
496
|
+
|
423
497
|
exceptions do
|
424
498
|
|
425
499
|
on /AuthFailure/ do
|
@@ -190,7 +190,7 @@ class OpennebulaDriver < Deltacloud::BaseDriver
|
|
190
190
|
|
191
191
|
networks = []
|
192
192
|
(computehash['NETWORK'].each do |n|
|
193
|
-
networks << n.attributes['ip']
|
193
|
+
networks << InstanceAddress.new(n.attributes['ip'])
|
194
194
|
end) unless computehash['NETWORK'].nil?
|
195
195
|
|
196
196
|
Instance.new( {
|
@@ -0,0 +1,47 @@
|
|
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
|
+
|
17
|
+
require 'deltacloud/drivers/rackspace/rackspace_driver.rb'
|
18
|
+
module Deltacloud
|
19
|
+
module Drivers
|
20
|
+
module Openstack
|
21
|
+
class OpenstackDriver < Rackspace::RackspaceDriver
|
22
|
+
|
23
|
+
feature :instances, :user_name
|
24
|
+
feature :instances, :authentication_password
|
25
|
+
feature :instances, :user_files
|
26
|
+
|
27
|
+
define_instance_states do
|
28
|
+
start.to( :pending ) .on( :create )
|
29
|
+
pending.to( :running ) .automatically
|
30
|
+
running.to( :running ) .on( :reboot )
|
31
|
+
running.to( :shutting_down ) .on( :stop )
|
32
|
+
shutting_down.to( :stopped ) .automatically
|
33
|
+
stopped.to( :finish ) .automatically
|
34
|
+
end
|
35
|
+
|
36
|
+
def new_client(credentials)
|
37
|
+
safely do
|
38
|
+
CloudServers::Connection.new(:username => credentials.user, :api_key => credentials.password, :auth_url => api_provider)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
private :new_client
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
@@ -356,8 +356,7 @@ class RackspaceDriver < Deltacloud::BaseDriver
|
|
356
356
|
return http, request
|
357
357
|
end
|
358
358
|
|
359
|
-
private
|
360
|
-
|
359
|
+
private
|
361
360
|
|
362
361
|
def new_client(credentials)
|
363
362
|
safely do
|
@@ -366,10 +365,11 @@ private
|
|
366
365
|
end
|
367
366
|
|
368
367
|
def convert_container(cf_container)
|
368
|
+
blob_list=cf_container.objects
|
369
369
|
Bucket.new({ :id => cf_container.name,
|
370
370
|
:name => cf_container.name,
|
371
|
-
:size =>
|
372
|
-
:blob_list =>
|
371
|
+
:size => blob_list.size,
|
372
|
+
:blob_list => blob_list
|
373
373
|
})
|
374
374
|
end
|
375
375
|
|
@@ -394,8 +394,8 @@ private
|
|
394
394
|
:architecture => 'x86_64',
|
395
395
|
:image_id => server.imageId.to_s,
|
396
396
|
:instance_profile => InstanceProfile::new(server.flavorId.to_s),
|
397
|
-
:public_addresses => server.addresses[:public],
|
398
|
-
:private_addresses => server.addresses[:private],
|
397
|
+
:public_addresses => server.addresses[:public].collect { |ip| InstanceAddress.new(ip) },
|
398
|
+
:private_addresses => server.addresses[:private].collect { |ip| InstanceAddress.new(ip) },
|
399
399
|
:username => 'root',
|
400
400
|
:password => password ? password : nil
|
401
401
|
)
|
@@ -415,8 +415,8 @@ private
|
|
415
415
|
:architecture => 'x86_64',
|
416
416
|
:image_id => server[:imageId].to_s,
|
417
417
|
:instance_profile => InstanceProfile::new(server[:flavorId].to_s),
|
418
|
-
:public_addresses => server[:addresses][:public],
|
419
|
-
:private_addresses => server[:addresses][:private]
|
418
|
+
:public_addresses => server[:addresses][:public].collect { |ip| InstanceAddress.new(ip) },
|
419
|
+
:private_addresses => server[:addresses][:private].collect { |ip| InstanceAddress.new(ip) }
|
420
420
|
)
|
421
421
|
inst.create_image = 'RUNNING'.eql?(inst.state)
|
422
422
|
inst.actions = instance_actions_for(inst.state)
|
@@ -15,7 +15,6 @@
|
|
15
15
|
#
|
16
16
|
|
17
17
|
require 'rubygems'
|
18
|
-
require 'base64'
|
19
18
|
require 'restclient'
|
20
19
|
require 'nokogiri'
|
21
20
|
require 'digest/md5'
|
@@ -45,10 +44,11 @@ module RHEVM
|
|
45
44
|
|
46
45
|
class Client
|
47
46
|
|
48
|
-
attr_reader :credentials, :api_entrypoint
|
47
|
+
attr_reader :credentials, :api_entrypoint, :datacenter_id
|
49
48
|
|
50
|
-
def initialize(username, password, api_entrypoint)
|
49
|
+
def initialize(username, password, api_entrypoint, datacenter_id=nil)
|
51
50
|
@credentials = { :username => username, :password => password }
|
51
|
+
@datacenter_id = datacenter_id
|
52
52
|
@api_entrypoint = api_entrypoint
|
53
53
|
end
|
54
54
|
|
@@ -59,24 +59,37 @@ module RHEVM
|
|
59
59
|
headers.merge!(auth_header)
|
60
60
|
if opts[:id]
|
61
61
|
vm = Client::parse_response(RHEVM::client(@api_entrypoint)["/vms/%s" % opts[:id]].get(headers)).root
|
62
|
+
return [] unless current_datacenter.cluster_ids.include?((vm/'cluster').first[:id])
|
62
63
|
[ RHEVM::VM::new(self, vm)]
|
63
64
|
else
|
64
65
|
Client::parse_response(RHEVM::client(@api_entrypoint)["/vms"].get(headers)).xpath('/vms/vm').collect do |vm|
|
66
|
+
next unless current_datacenter.cluster_ids.include?((vm/'cluster').first[:id])
|
65
67
|
RHEVM::VM::new(self, vm)
|
66
|
-
end
|
68
|
+
end.compact
|
67
69
|
end
|
68
70
|
end
|
69
71
|
|
70
72
|
def vm_action(id, action, headers={})
|
71
73
|
headers.merge!(auth_header)
|
72
|
-
headers.merge!({
|
73
|
-
|
74
|
-
|
75
|
-
})
|
74
|
+
headers.merge!({:accept => 'application/xml'})
|
75
|
+
vm = vms(:id => id)
|
76
|
+
raise RHEVMBackendException::new("Requested VM not found in datacenter #{self.current_datacenter.id}") if vm.empty?
|
76
77
|
if action==:delete
|
77
78
|
RHEVM::client(@api_entrypoint)["/vms/%s" % id].delete(headers)
|
78
79
|
else
|
79
|
-
|
80
|
+
headers.merge!({ :content_type => 'application/xml' })
|
81
|
+
begin
|
82
|
+
client_response = RHEVM::client(@api_entrypoint)["/vms/%s/%s" % [id, action]].post('<action/>', headers)
|
83
|
+
rescue
|
84
|
+
if $!.is_a?(RestClient::BadRequest)
|
85
|
+
fault = (Nokogiri::XML($!.http_body)/'//fault/detail')
|
86
|
+
fault = fault.text.gsub(/\[|\]/, '') if fault
|
87
|
+
end
|
88
|
+
fault ||= $!.message
|
89
|
+
raise RHEVMBackendException::new(fault)
|
90
|
+
end
|
91
|
+
xml_response = Client::parse_response(client_response)
|
92
|
+
|
80
93
|
return false if (xml_response/'action/status').first.text.strip.upcase!="COMPLETE"
|
81
94
|
end
|
82
95
|
return true
|
@@ -89,7 +102,11 @@ module RHEVM
|
|
89
102
|
}
|
90
103
|
headers.merge!(auth_header)
|
91
104
|
result_xml = Nokogiri::XML(RHEVM::client(@api_entrypoint)["/"].get(headers))
|
92
|
-
(result_xml/'
|
105
|
+
if (result_xml/'api/system_version').empty?
|
106
|
+
(result_xml/'/api/product_info/version').first[:major].strip == major
|
107
|
+
else
|
108
|
+
(result_xml/'/api/system_version').first[:major].strip == major
|
109
|
+
end
|
93
110
|
end
|
94
111
|
|
95
112
|
def cluster_version?(cluster_id, major)
|
@@ -102,13 +119,25 @@ module RHEVM
|
|
102
119
|
(result_xml/'/cluster/version').first[:major].strip == major
|
103
120
|
end
|
104
121
|
|
122
|
+
def capability?(name)
|
123
|
+
headers = {
|
124
|
+
:content_type => 'application/xml',
|
125
|
+
:accept => 'application/xml'
|
126
|
+
}
|
127
|
+
headers.merge!(auth_header)
|
128
|
+
result_xml = Nokogiri::XML(RHEVM::client(@api_entrypoint)["/capabilities"].get(headers))
|
129
|
+
!(result_xml/"/capabilities/version/custom_properties/custom_property[@name='#{name}']").empty?
|
130
|
+
end
|
131
|
+
|
105
132
|
def create_vm(template_id, opts={})
|
106
133
|
opts ||= {}
|
134
|
+
templ = template(template_id)
|
135
|
+
raise RHEVMBackendException::new("Requested VM not found in datacenter #{self.current_datacenter.id}") unless templ
|
107
136
|
builder = Nokogiri::XML::Builder.new do
|
108
137
|
vm {
|
109
138
|
name opts[:name] || "i-#{Time.now.to_i}"
|
110
139
|
template_(:id => template_id)
|
111
|
-
|
140
|
+
cluster_(:id => opts[:realm_id].nil? ? templ.cluster.id : opts[:realm_id])
|
112
141
|
type_ opts[:hwp_id] || 'desktop'
|
113
142
|
memory opts[:hwp_memory] ? (opts[:hwp_memory].to_i*1024*1024).to_s : (512*1024*1024).to_s
|
114
143
|
cpu {
|
@@ -116,15 +145,11 @@ module RHEVM
|
|
116
145
|
}
|
117
146
|
if opts[:user_data] and not opts[:user_data].empty?
|
118
147
|
if api_version?('3') and cluster_version?((opts[:realm_id] || clusters.first.id), '3')
|
148
|
+
raise "Required VDSM hook 'floppyinject' not supported by RHEV-M" unless capability?(:floppyinject)
|
119
149
|
custom_properties {
|
120
|
-
#
|
121
|
-
# FIXME: 'regexp' parameter is just a temporary workaround. This
|
122
|
-
# is a reported and verified bug and should be fixed in next
|
123
|
-
# RHEV-M release.
|
124
|
-
#
|
125
150
|
custom_property({
|
126
151
|
:name => "floppyinject",
|
127
|
-
:value => "#{RHEVM::FILEINJECT_PATH}:#{
|
152
|
+
:value => "#{RHEVM::FILEINJECT_PATH}:#{opts[:user_data]}",
|
128
153
|
:regexp => "^([^:]+):(.*)$"})
|
129
154
|
}
|
130
155
|
else
|
@@ -138,6 +163,8 @@ module RHEVM
|
|
138
163
|
:content_type => 'application/xml',
|
139
164
|
:accept => 'application/xml',
|
140
165
|
})
|
166
|
+
templates = templates(:id => template_id)
|
167
|
+
raise RHEVMBackendException::new("Requested VM not found in datacenter #{self.current_datacenter.id}") if templates.empty?
|
141
168
|
headers.merge!(auth_header)
|
142
169
|
begin
|
143
170
|
vm = RHEVM::client(@api_entrypoint)["/vms"].post(Nokogiri::XML(builder.to_xml).root.to_s, headers)
|
@@ -176,6 +203,8 @@ module RHEVM
|
|
176
203
|
:content_type => 'application/xml',
|
177
204
|
:accept => 'application/xml',
|
178
205
|
})
|
206
|
+
tmpl = template(id)
|
207
|
+
raise RHEVMBackendException::new("Requested VM not found in datacenter #{self.current_datacenter.id}") unless tmpl
|
179
208
|
headers.merge!(auth_header)
|
180
209
|
RHEVM::client(@api_entrypoint)["/templates/%s" % id].delete(headers)
|
181
210
|
return true
|
@@ -186,29 +215,20 @@ module RHEVM
|
|
186
215
|
:accept => "application/xml"
|
187
216
|
}
|
188
217
|
headers.merge!(auth_header)
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
RHEVM::Template::new(self, vm)
|
195
|
-
end
|
196
|
-
end
|
218
|
+
rhevm_templates = RHEVM::client(@api_entrypoint)["/templates"].get(headers)
|
219
|
+
Client::parse_response(rhevm_templates).xpath('/templates/template').collect do |t|
|
220
|
+
next unless current_datacenter.cluster_ids.include?((t/'cluster').first[:id])
|
221
|
+
RHEVM::Template::new(self, t)
|
222
|
+
end.compact
|
197
223
|
end
|
198
224
|
|
199
|
-
def
|
225
|
+
def template(template_id)
|
200
226
|
headers = {
|
201
|
-
:accept => "application/xml
|
227
|
+
:accept => "application/xml"
|
202
228
|
}
|
203
229
|
headers.merge!(auth_header)
|
204
|
-
|
205
|
-
|
206
|
-
[ RHEVM::Cluster::new(self, vm)]
|
207
|
-
else
|
208
|
-
Client::parse_response(RHEVM::client(@api_entrypoint)["/clusters"].get(headers)).xpath('/clusters/cluster').collect do |vm|
|
209
|
-
RHEVM::Cluster::new(self, vm) if has_datacenter?(vm)
|
210
|
-
end.compact
|
211
|
-
end
|
230
|
+
rhevm_template = RHEVM::client(@api_entrypoint)["/templates/%s" % template_id].get(headers)
|
231
|
+
RHEVM::Template::new(self, Client::parse_response(rhevm_template).root)
|
212
232
|
end
|
213
233
|
|
214
234
|
def datacenters(opts={})
|
@@ -216,16 +236,33 @@ module RHEVM
|
|
216
236
|
:accept => "application/xml"
|
217
237
|
}
|
218
238
|
headers.merge!(auth_header)
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
else
|
223
|
-
Client::parse_response(RHEVM::client(@api_entrypoint)["/datacenters"].get(headers)).xpath('/data_centers/data_center').collect do |vm|
|
224
|
-
RHEVM::DataCenter::new(self, vm)
|
225
|
-
end
|
239
|
+
rhevm_datacenters = RHEVM::client(@api_entrypoint)["/datacenters"].get(headers)
|
240
|
+
Client::parse_response(rhevm_datacenters).xpath('/data_centers/data_center').collect do |dc|
|
241
|
+
RHEVM::DataCenter::new(self, dc)
|
226
242
|
end
|
227
243
|
end
|
228
244
|
|
245
|
+
def clusters
|
246
|
+
current_datacenter.clusters
|
247
|
+
end
|
248
|
+
|
249
|
+
def cluster(cluster_id)
|
250
|
+
current_datacenter.cluster(cluster_id)
|
251
|
+
end
|
252
|
+
|
253
|
+
def current_datacenter
|
254
|
+
@current_datacenter ||= self.datacenter_id ? datacenter(self.datacenter_id) : datacenters.first
|
255
|
+
end
|
256
|
+
|
257
|
+
def datacenter(datacenter_id)
|
258
|
+
headers = {
|
259
|
+
:accept => "application/xml"
|
260
|
+
}
|
261
|
+
headers.merge!(auth_header)
|
262
|
+
rhevm_datacenter = RHEVM::client(@api_entrypoint)["/datacenters/%s" % datacenter_id].get(headers)
|
263
|
+
RHEVM::DataCenter::new(self, Client::parse_response(rhevm_datacenter).root)
|
264
|
+
end
|
265
|
+
|
229
266
|
def hosts(opts={})
|
230
267
|
headers = {
|
231
268
|
:accept => "application/xml"
|
@@ -336,11 +373,11 @@ module RHEVM
|
|
336
373
|
@storage = ((xml/'disks/disk/size').first.text rescue nil)
|
337
374
|
@macs = (xml/'nics/nic/mac').collect { |mac| mac[:address] }
|
338
375
|
@creation_time = (xml/'creation_time').text
|
339
|
-
@ip = ((xml/'guest_info/ip').first[:address] rescue nil)
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
376
|
+
@ip = ((xml/'guest_info/ips/ip').first[:address] rescue nil)
|
377
|
+
@vnc = {
|
378
|
+
:address => ((xml/'display/address').first.text rescue "127.0.0.1"),
|
379
|
+
:port => ((xml/'display/port').first.text rescue "5890")
|
380
|
+
} unless @ip
|
344
381
|
end
|
345
382
|
|
346
383
|
end
|
@@ -364,7 +401,7 @@ module RHEVM
|
|
364
401
|
end
|
365
402
|
|
366
403
|
class Cluster < BaseObject
|
367
|
-
attr_reader :description, :datacenter
|
404
|
+
attr_reader :description, :datacenter, :version
|
368
405
|
|
369
406
|
def initialize(client, xml)
|
370
407
|
super(client, xml[:id], xml[:href], (xml/'name').first.text)
|
@@ -376,7 +413,10 @@ module RHEVM
|
|
376
413
|
|
377
414
|
def parse_xml_attributes!(xml)
|
378
415
|
@description = ((xml/'description').first.text rescue nil)
|
379
|
-
@
|
416
|
+
@version =((xml/'version').first[:major].strip rescue nil)
|
417
|
+
unless (xml/'data_center').empty?
|
418
|
+
@datacenter = Link::new(@client, (xml/'data_center').first[:id], (xml/'data_center').first[:href])
|
419
|
+
end
|
380
420
|
end
|
381
421
|
|
382
422
|
end
|
@@ -390,6 +430,39 @@ module RHEVM
|
|
390
430
|
self
|
391
431
|
end
|
392
432
|
|
433
|
+
def clusters
|
434
|
+
headers = {
|
435
|
+
:accept => "application/xml; detail=datacenters"
|
436
|
+
}
|
437
|
+
headers.merge!(client.auth_header)
|
438
|
+
clusters_list = RHEVM::client(client.api_entrypoint)["/clusters"].get(headers)
|
439
|
+
cluster_arr = Client::parse_response(clusters_list).xpath('/clusters/cluster')
|
440
|
+
clusters_arr = []
|
441
|
+
cluster_arr.each do |cluster|
|
442
|
+
cluster = RHEVM::Cluster.new(self.client, cluster)
|
443
|
+
clusters_arr << cluster if cluster.datacenter && cluster.datacenter.id == client.datacenter_id
|
444
|
+
end
|
445
|
+
clusters_arr
|
446
|
+
end
|
447
|
+
|
448
|
+
def cluster(cluster_id)
|
449
|
+
headers = {
|
450
|
+
:accept => "application/xml; detail=datacenters"
|
451
|
+
}
|
452
|
+
headers.merge!(client.auth_header)
|
453
|
+
cluster_xml = RHEVM::client(client.api_entrypoint)["/clusters/%s" % cluster_id].get(headers)
|
454
|
+
cluster = RHEVM::Cluster.new(self.client, cluster_xml)
|
455
|
+
if cluster.datacenter && cluster.datacenter.id == client.datacenter_id
|
456
|
+
cluster
|
457
|
+
else
|
458
|
+
nil
|
459
|
+
end
|
460
|
+
end
|
461
|
+
|
462
|
+
def cluster_ids
|
463
|
+
@cluster_ids ||= clusters.collect { |c| c.id }
|
464
|
+
end
|
465
|
+
|
393
466
|
private
|
394
467
|
|
395
468
|
def parse_xml_attributes!(xml)
|