knife-xapi 0.5.4 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/chef/knife/xapi_base.rb +168 -152
- data/lib/chef/knife/xapi_guest_create.rb +186 -167
- data/lib/chef/knife/xapi_guest_delete.rb +28 -30
- data/lib/chef/knife/xapi_guest_list.rb +13 -15
- data/lib/chef/knife/xapi_guest_start.rb +5 -6
- data/lib/chef/knife/xapi_guest_stop.rb +4 -7
- data/lib/chef/knife/xapi_network_list.rb +10 -13
- data/lib/chef/knife/xapi_vdi_attach.rb +33 -40
- data/lib/chef/knife/xapi_vdi_create.rb +24 -26
- data/lib/chef/knife/xapi_vdi_delete.rb +30 -33
- data/lib/chef/knife/xapi_vdi_detach.rb +36 -43
- data/lib/chef/knife/xapi_vdi_list.rb +17 -21
- data/lib/chef/knife/xapi_vlan_list.rb +6 -9
- data/lib/chef/knife/xapi_vmselect.rb +7 -9
- data/lib/knife-xapi/version.rb +1 -1
- data/lib/xenapi/xenapi.rb +2 -3
- data/lib/xenapi/xenapi/async_dispatcher.rb +2 -2
- data/lib/xenapi/xenapi/client.rb +53 -55
- data/lib/xenapi/xenapi/errors.rb +3 -3
- data/lib/xenapi/xenapi/xmlrpc_client.rb +3 -3
- metadata +19 -33
@@ -8,9 +8,9 @@
|
|
8
8
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
9
9
|
# you may not use this file except in compliance with the License.
|
10
10
|
# You may obtain a copy of the License at
|
11
|
-
#
|
11
|
+
#
|
12
12
|
# http://www.apache.org/licenses/LICENSE-2.0
|
13
|
-
#
|
13
|
+
#
|
14
14
|
# Unless required by applicable law or agreed to in writing, software
|
15
15
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
16
16
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
@@ -18,7 +18,6 @@
|
|
18
18
|
# limitations under the License.
|
19
19
|
#
|
20
20
|
|
21
|
-
|
22
21
|
require 'chef/knife/xapi_base'
|
23
22
|
|
24
23
|
class Chef
|
@@ -26,62 +25,61 @@ class Chef
|
|
26
25
|
class XapiVdiDelete < Knife
|
27
26
|
include Chef::Knife::XapiBase
|
28
27
|
|
29
|
-
banner
|
28
|
+
banner 'knife xapi vdi delete NAME_LABEL (options)'
|
30
29
|
|
31
30
|
option :uuid,
|
32
|
-
|
33
|
-
|
34
|
-
|
31
|
+
short: '-U',
|
32
|
+
long: '--uuid',
|
33
|
+
description: 'Treat the label as a UUID not a name label'
|
35
34
|
|
36
35
|
option :cleanup,
|
37
|
-
|
38
|
-
|
39
|
-
|
36
|
+
short: '-C',
|
37
|
+
long: '--cleanup',
|
38
|
+
description: 'Clean up all orphaned volumes.'
|
40
39
|
|
41
40
|
option :interactive,
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
41
|
+
short: '-I',
|
42
|
+
long: '--interactive',
|
43
|
+
description: 'Interactive clean-up of orphaned volumes'
|
46
44
|
|
47
45
|
def interactive
|
48
46
|
# Get all VDIs known to the system
|
49
|
-
vdis = get_all_vdis
|
47
|
+
vdis = get_all_vdis
|
50
48
|
first = true
|
51
49
|
|
52
50
|
for vdi_ in vdis do
|
53
51
|
vbds = get_vbds_from_vdi(vdi_)
|
54
|
-
if vbds.empty?
|
52
|
+
if vbds.empty? && xapi.VDI.get_type(vdi_).match('system')
|
55
53
|
if first
|
56
54
|
first = false
|
57
55
|
end
|
58
56
|
|
59
57
|
prinlt_vdi_info(vdi_)
|
60
|
-
destroy_vdi(vdi_) if yes_no?(
|
58
|
+
destroy_vdi(vdi_) if yes_no?('Destroy this volume? ')
|
61
59
|
end
|
62
60
|
end
|
63
61
|
end
|
64
62
|
|
65
63
|
def vdi_cleanup
|
66
64
|
orphaned_vdis = []
|
67
|
-
vdis = get_all_vdis
|
65
|
+
vdis = get_all_vdis
|
68
66
|
|
69
67
|
for vdi_ in vdis do
|
70
68
|
vbds = get_vbds_from_vdi(vdi_)
|
71
|
-
if vbds.empty?
|
69
|
+
if vbds.empty? && xapi.VDI.get_type(vdi_).match('system')
|
72
70
|
orphaned_vdis << vdi_
|
73
71
|
end
|
74
72
|
end
|
75
73
|
|
76
74
|
orphaned_vdis.each { |item| print_vdi_info(item) }
|
77
75
|
unless orphaned_vdis.empty?
|
78
|
-
if yes_no?(
|
76
|
+
if yes_no?('Destroy all these volumes? ')
|
79
77
|
orphaned_vdis.each { |item| destroy_vdi(item) }
|
80
78
|
end
|
81
79
|
end
|
82
80
|
end
|
83
81
|
|
84
|
-
def run
|
82
|
+
def run
|
85
83
|
if config[:interactive]
|
86
84
|
interactive
|
87
85
|
return
|
@@ -92,35 +90,34 @@ class Chef
|
|
92
90
|
|
93
91
|
vdi_name = @name_args[0]
|
94
92
|
if vdi_name.nil?
|
95
|
-
puts
|
96
|
-
puts
|
93
|
+
puts 'Error: No VDI Name specified...'
|
94
|
+
puts 'Usage: ' + banner
|
97
95
|
exit 1
|
98
96
|
end
|
99
97
|
|
100
|
-
vdis = []
|
98
|
+
vdis = []
|
101
99
|
if config[:uuid]
|
102
100
|
vdis << get_vdi_by_uuid(vdi_name)
|
103
101
|
else
|
104
102
|
vdis << get_vdi_by_name_label(vdi_name)
|
105
103
|
end
|
106
|
-
vdis.flatten!
|
104
|
+
vdis.flatten!
|
107
105
|
|
108
|
-
if vdis.empty?
|
109
|
-
ui.msg "VDI not found: #{h.color vdi_name, :red}"
|
106
|
+
if vdis.empty?
|
107
|
+
ui.msg "VDI not found: #{h.color vdi_name, :red}"
|
110
108
|
exit 1
|
111
109
|
elsif vdis.length > 1
|
112
|
-
ui.msg
|
110
|
+
ui.msg 'Multiple VDI matches found. Use vdi list if you are unsure'
|
113
111
|
vdi = user_select(vdis)
|
114
|
-
else
|
112
|
+
else
|
115
113
|
vdi = vdis.first
|
116
114
|
end
|
117
115
|
|
118
|
-
if vdi == :all
|
119
|
-
vdis.each {|vdi| destroy_vdi(vdi)}
|
120
|
-
else
|
116
|
+
if vdi == :all
|
117
|
+
vdis.each { |vdi| destroy_vdi(vdi) }
|
118
|
+
else
|
121
119
|
destroy_vdi(vdi)
|
122
120
|
end
|
123
|
-
|
124
121
|
end
|
125
122
|
end
|
126
123
|
end
|
@@ -18,63 +18,56 @@
|
|
18
18
|
# limitations under the License.
|
19
19
|
#
|
20
20
|
|
21
|
-
|
22
21
|
require 'chef/knife/xapi_base'
|
23
22
|
|
24
23
|
class Chef
|
25
24
|
class Knife
|
26
|
-
|
27
|
-
|
25
|
+
class XapiVdiDetach < Knife
|
26
|
+
include Chef::Knife::XapiBase
|
27
|
+
|
28
|
+
banner 'knife xapi vdi detach NAME_LABEL (options)'
|
29
|
+
|
30
|
+
option :uuid,
|
31
|
+
short: '-U',
|
32
|
+
long: '--uuid',
|
33
|
+
description: 'Treat the label as a UUID not a name label'
|
28
34
|
|
29
|
-
|
35
|
+
def run
|
36
|
+
vbd_name = @name_args[0]
|
30
37
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
def run
|
37
|
-
vbd_name = @name_args[0]
|
38
|
+
if vbd_name.nil?
|
39
|
+
ui.msg 'Error: No VDI Name specified...'
|
40
|
+
ui.msg 'Usage: ' + banner
|
41
|
+
exit 1
|
42
|
+
end
|
38
43
|
|
39
|
-
|
40
|
-
ui.msg "Error: No VDI Name specified..."
|
41
|
-
ui.msg "Usage: " +banner
|
42
|
-
exit 1
|
43
|
-
end
|
44
|
-
|
45
|
-
vdis = []
|
44
|
+
vdis = []
|
46
45
|
# detach vdi with VDI's UUID
|
47
|
-
|
46
|
+
if config[:uuid]
|
48
47
|
vdis << xapi.VDI.get_by_uuid(vbd_name)
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
48
|
+
else
|
49
|
+
# detach with VDI's Name
|
50
|
+
vdis = xapi.VDI.get_by_name_label(vbd_name)
|
51
|
+
end
|
53
52
|
|
54
53
|
if vdis.empty?
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
# Detach VDI
|
54
|
+
ui.msg "VDI not found: #{h.color vbd_name, :red}"
|
55
|
+
exit 1
|
56
|
+
# When multiple VDI matches
|
57
|
+
elsif vdis.length > 1
|
58
|
+
ui.msg 'Multiple VDI matches found use guest list if you are unsure'
|
59
|
+
vdi_ref = user_select(vdis)
|
60
|
+
else
|
61
|
+
vdi_ref = vdis.first
|
62
|
+
end
|
63
|
+
|
64
|
+
# Detach VDI
|
66
65
|
if vdi_ref == :all
|
67
|
-
vdis.each{|vdi_ref| detach_vdi(vdi_ref)}
|
66
|
+
vdis.each { |vdi_ref| detach_vdi(vdi_ref) }
|
68
67
|
else
|
69
68
|
detach_vdi(vdi_ref)
|
70
69
|
end
|
71
|
-
|
72
|
-
|
73
|
-
end
|
70
|
+
end
|
71
|
+
end
|
74
72
|
end
|
75
73
|
end
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
@@ -8,9 +8,9 @@
|
|
8
8
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
9
9
|
# you may not use this file except in compliance with the License.
|
10
10
|
# You may obtain a copy of the License at
|
11
|
-
#
|
11
|
+
#
|
12
12
|
# http://www.apache.org/licenses/LICENSE-2.0
|
13
|
-
#
|
13
|
+
#
|
14
14
|
# Unless required by applicable law or agreed to in writing, software
|
15
15
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
16
16
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
@@ -18,7 +18,6 @@
|
|
18
18
|
# limitations under the License.
|
19
19
|
#
|
20
20
|
|
21
|
-
|
22
21
|
require 'chef/knife/xapi_base'
|
23
22
|
|
24
23
|
class Chef
|
@@ -26,43 +25,40 @@ class Chef
|
|
26
25
|
class XapiVdiList < Knife
|
27
26
|
include Chef::Knife::XapiBase
|
28
27
|
|
29
|
-
banner
|
28
|
+
banner 'knife xapi vdi list'
|
30
29
|
|
31
30
|
option :vdi_name,
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
31
|
+
short: '-N',
|
32
|
+
long: '--vdi-name',
|
33
|
+
default: false,
|
34
|
+
description: 'Indicates this is a vdi name not a guest name'
|
36
35
|
|
37
|
-
|
38
|
-
def run
|
36
|
+
def run
|
39
37
|
# Get all VDIs known to the system
|
40
38
|
name = @name_args[0]
|
41
39
|
|
42
|
-
# if we were passed a guest name find its vdi's
|
40
|
+
# if we were passed a guest name find its vdi's
|
43
41
|
# otherwise do it for everything
|
44
|
-
vdis =
|
45
|
-
if name.nil?
|
42
|
+
vdis = []
|
43
|
+
if name.nil? || name.empty?
|
46
44
|
vdis = xapi.VDI.get_all
|
47
45
|
|
48
46
|
elsif config[:vdi_name]
|
49
|
-
vdis = xapi.VDI.get_by_name_label(
|
47
|
+
vdis = xapi.VDI.get_by_name_label(name)
|
50
48
|
|
51
49
|
else
|
52
|
-
ref = xapi.VM.get_by_name_label(
|
53
|
-
vm = xapi.VM.get_record(
|
50
|
+
ref = xapi.VM.get_by_name_label(name)
|
51
|
+
vm = xapi.VM.get_record(ref.first)
|
54
52
|
|
55
|
-
vm[
|
56
|
-
vdis << xapi.VBD.get_record(
|
53
|
+
vm['VBDs'].each do |vbd|
|
54
|
+
vdis << xapi.VBD.get_record(vbd)['VDI']
|
57
55
|
end
|
58
56
|
end
|
59
57
|
|
60
|
-
vdis.each do |vdi|
|
58
|
+
vdis.each do |vdi|
|
61
59
|
print_vdi_info vdi
|
62
60
|
end
|
63
|
-
|
64
61
|
end
|
65
62
|
end
|
66
63
|
end
|
67
64
|
end
|
68
|
-
|
@@ -8,9 +8,9 @@
|
|
8
8
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
9
9
|
# you may not use this file except in compliance with the License.
|
10
10
|
# You may obtain a copy of the License at
|
11
|
-
#
|
11
|
+
#
|
12
12
|
# http://www.apache.org/licenses/LICENSE-2.0
|
13
|
-
#
|
13
|
+
#
|
14
14
|
# Unless required by applicable law or agreed to in writing, software
|
15
15
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
16
16
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
@@ -18,7 +18,6 @@
|
|
18
18
|
# limitations under the License.
|
19
19
|
#
|
20
20
|
|
21
|
-
|
22
21
|
require 'chef/knife/xapi_base'
|
23
22
|
require 'pry'
|
24
23
|
class Chef
|
@@ -26,15 +25,13 @@ class Chef
|
|
26
25
|
class XapiVlanList < Knife
|
27
26
|
include Chef::Knife::XapiBase
|
28
27
|
|
29
|
-
banner
|
28
|
+
banner 'knife xapi vlan list'
|
30
29
|
|
31
|
-
def run
|
32
|
-
xapi.VLAN.get_all_records.map { |
|
33
|
-
color_kv
|
30
|
+
def run
|
31
|
+
xapi.VLAN.get_all_records.map { |_k, v| v['tag'].to_i }.uniq.sort.each do |vlan|
|
32
|
+
color_kv 'Tag: ', vlan.to_s
|
34
33
|
end
|
35
34
|
end
|
36
|
-
|
37
35
|
end
|
38
36
|
end
|
39
37
|
end
|
40
|
-
|
@@ -1,20 +1,19 @@
|
|
1
1
|
|
2
2
|
class Chef::Knife
|
3
3
|
module XapiVmSelect
|
4
|
-
|
5
4
|
def self.included(includer)
|
6
5
|
includer.class_eval do
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
option :uuid,
|
7
|
+
short: '-U',
|
8
|
+
long: '--uuid',
|
9
|
+
description: 'Treat the label as a UUID not a name label'
|
11
10
|
end
|
12
11
|
end
|
13
12
|
|
14
13
|
def select_vm(name)
|
15
14
|
if name.nil?
|
16
|
-
ui.msg
|
17
|
-
ui.msg
|
15
|
+
ui.msg 'Must Provide VM Name'
|
16
|
+
ui.msg 'Usage: ' + banner
|
18
17
|
exit 1
|
19
18
|
end
|
20
19
|
|
@@ -33,7 +32,7 @@ class Chef::Knife
|
|
33
32
|
|
34
33
|
if vms.length > 1
|
35
34
|
vm = user_select(vms)
|
36
|
-
if vm == :all
|
35
|
+
if vm == :all
|
37
36
|
return vms
|
38
37
|
end
|
39
38
|
else
|
@@ -41,6 +40,5 @@ class Chef::Knife
|
|
41
40
|
end
|
42
41
|
vm
|
43
42
|
end
|
44
|
-
|
45
43
|
end
|
46
44
|
end
|
data/lib/knife-xapi/version.rb
CHANGED
data/lib/xenapi/xenapi.rb
CHANGED
@@ -23,14 +23,14 @@ module XenApi
|
|
23
23
|
# @yieldparam [Client] client Client instance
|
24
24
|
# @return [Object] block return value
|
25
25
|
# @raise [NoHostsAvailable] No hosts could be contacted
|
26
|
-
def self.connect(uris, username, password, options={})
|
26
|
+
def self.connect(uris, username, password, options = {})
|
27
27
|
uris = uris.respond_to?(:shift) ? uris.dup : [uris]
|
28
28
|
method = options[:slave_login] ? :slave_local_login_with_password : :login_with_password
|
29
29
|
|
30
30
|
client = Client.new(uris, options[:timeout] || 10, options[:ssl_verify] || :verify_peer)
|
31
31
|
begin
|
32
32
|
args = [method, username, password]
|
33
|
-
args << options[:api_version] if options.
|
33
|
+
args << options[:api_version] if options.key?(:api_version)
|
34
34
|
client.send(*args)
|
35
35
|
|
36
36
|
if block_given?
|
@@ -44,4 +44,3 @@ module XenApi
|
|
44
44
|
end
|
45
45
|
end
|
46
46
|
end
|
47
|
-
|
@@ -29,8 +29,8 @@ module XenApi #:nodoc:
|
|
29
29
|
# @param [String,Symbol] meth Method prefix name
|
30
30
|
# @param [...] args Method arguments
|
31
31
|
# @return [Dispatcher] dispatcher instance to handle the +Async.meth+ prefix
|
32
|
-
def method_missing(meth, *
|
32
|
+
def method_missing(meth, *_args)
|
33
33
|
Dispatcher.new(@client, "Async.#{meth}", @sender)
|
34
34
|
end
|
35
|
-
end
|
35
|
+
end
|
36
36
|
end
|
data/lib/xenapi/xenapi/client.rb
CHANGED
@@ -107,10 +107,10 @@ module XenApi #:nodoc:
|
|
107
107
|
# @param [Integer] timeout Maximum number of seconds to wait for an API response
|
108
108
|
# @param [Symbol] ssl_verify SSL certificate verification mode.
|
109
109
|
# Can be one of :verify_none or :verify_peer
|
110
|
-
def initialize(uris, timeout=10, ssl_verify
|
110
|
+
def initialize(uris, timeout = 10, ssl_verify = :verify_peer)
|
111
111
|
@timeout = timeout
|
112
112
|
@ssl_verify = ssl_verify
|
113
|
-
@uris = [uris].flatten.
|
113
|
+
@uris = [uris].flatten.map do |uri|
|
114
114
|
uri = URI.parse(uri)
|
115
115
|
uri.path = '/' if uri.path == ''
|
116
116
|
uri
|
@@ -179,7 +179,7 @@ module XenApi #:nodoc:
|
|
179
179
|
# @return [String] API version
|
180
180
|
def api_version
|
181
181
|
@api_version ||= begin
|
182
|
-
pool = self.pool.get_all
|
182
|
+
pool = self.pool.get_all[0]
|
183
183
|
host = self.pool.get_master(pool)
|
184
184
|
major = self.host.get_API_version_major(host)
|
185
185
|
minor = self.host.get_API_version_minor(host)
|
@@ -228,24 +228,23 @@ module XenApi #:nodoc:
|
|
228
228
|
# object state is invalid. No API calls can be performed unless one of
|
229
229
|
# the login methods is called again.
|
230
230
|
def logout
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
_do_call("session.logout", [@session])
|
236
|
-
end
|
237
|
-
rescue
|
238
|
-
# We don't care about any error. If it works: great, if not: shit happens...
|
239
|
-
nil
|
240
|
-
ensure
|
241
|
-
@session = ""
|
242
|
-
@login_meth = nil
|
243
|
-
@login_args = []
|
244
|
-
@api_version = nil
|
231
|
+
if @login_meth.to_s.start_with? 'slave_local'
|
232
|
+
_do_call('session.local_logout', [@session])
|
233
|
+
else
|
234
|
+
_do_call('session.logout', [@session])
|
245
235
|
end
|
236
|
+
rescue
|
237
|
+
# We don't care about any error. If it works: great, if not: shit happens...
|
238
|
+
nil
|
239
|
+
ensure
|
240
|
+
@session = ''
|
241
|
+
@login_meth = nil
|
242
|
+
@login_args = []
|
243
|
+
@api_version = nil
|
246
244
|
end
|
247
245
|
|
248
|
-
|
246
|
+
protected
|
247
|
+
|
249
248
|
# @param [String,Symbol] meth API method to call
|
250
249
|
# @param [Array] args Arguments to pass to the method call
|
251
250
|
# @raise [SessionInvalid] Reauthentication failed
|
@@ -253,39 +252,38 @@ module XenApi #:nodoc:
|
|
253
252
|
# @raise [EOFError] XMLRPC::Client exception
|
254
253
|
# @raise [Errno::EPIPE] XMLRPC::Client exception
|
255
254
|
def _call(meth, *args)
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
_reconnect ? retry : raise
|
281
|
-
end
|
255
|
+
_do_call(meth, args.dup.unshift(@session))
|
256
|
+
rescue SessionInvalid
|
257
|
+
_relogin_attempts = (_relogin_attempts || 0) + 1
|
258
|
+
_relogin
|
259
|
+
retry unless _relogin_attempts > 2
|
260
|
+
_reconnect ? retry : raise
|
261
|
+
rescue Timeout::Error
|
262
|
+
_timeout_retries = (_timeout_retries || 0) + 1
|
263
|
+
@client = nil
|
264
|
+
retry unless _timeout_retries > 1
|
265
|
+
_reconnect ? retry : raise
|
266
|
+
rescue EOFError
|
267
|
+
_eof_retries = (_eof_retries || 0) + 1
|
268
|
+
@client = nil
|
269
|
+
retry unless _eof_retries > 1
|
270
|
+
_reconnect ? retry : raise
|
271
|
+
rescue Errno::EPIPE
|
272
|
+
_epipe_retries = (_epipe_retries || 0) + 1
|
273
|
+
@client = nil
|
274
|
+
retry unless _epipe_retries > 1
|
275
|
+
_reconnect ? retry : raise
|
276
|
+
rescue Errno::EHOSTUNREACH
|
277
|
+
@client = nil
|
278
|
+
_reconnect ? retry : raise
|
282
279
|
end
|
283
280
|
|
284
|
-
|
281
|
+
private
|
282
|
+
|
285
283
|
# Reauthenticate with the API
|
286
284
|
# @raise [LoginRequired] Missing authentication credentials
|
287
285
|
def _relogin
|
288
|
-
|
286
|
+
fail LoginRequired if @login_meth.nil? || @login_args.nil? || @login_args.empty?
|
289
287
|
_login(@login_meth, *@login_args)
|
290
288
|
end
|
291
289
|
|
@@ -315,7 +313,7 @@ module XenApi #:nodoc:
|
|
315
313
|
failed_uris << @uri
|
316
314
|
end
|
317
315
|
end
|
318
|
-
|
316
|
+
fail Errors::NoHostsAvailable.new('No server reachable. Giving up.')
|
319
317
|
end
|
320
318
|
|
321
319
|
# Login to the API
|
@@ -347,7 +345,7 @@ module XenApi #:nodoc:
|
|
347
345
|
#
|
348
346
|
# @return [XMLRPC::Client] XMLRPC client instance
|
349
347
|
def _client
|
350
|
-
@client ||= XMLRPCClient.new(@uri.host, @uri.path, @uri.port, nil, nil, nil, nil, @uri.scheme ==
|
348
|
+
@client ||= XMLRPCClient.new(@uri.host, @uri.path, @uri.port, nil, nil, nil, nil, @uri.scheme == 'https' ? @ssl_verify : false, @timeout)
|
351
349
|
end
|
352
350
|
|
353
351
|
# Perform XMLRPC method call.
|
@@ -361,21 +359,21 @@ module XenApi #:nodoc:
|
|
361
359
|
# @raise [ResponseMissingErrorDescriptionField] API response error missing +ErrorDescription+ field
|
362
360
|
# @raise [SessionInvalid] API session has expired
|
363
361
|
# @raise [Errors::GenericError] API method specific error
|
364
|
-
def _do_call(meth, args,
|
362
|
+
def _do_call(meth, args, _attempts = 3)
|
365
363
|
r = _client.call(meth, *args)
|
366
|
-
|
364
|
+
fail ResponseMissingStatusField unless r.key?('Status')
|
367
365
|
|
368
366
|
if r['Status'] == 'Success'
|
369
|
-
return r['Value'] if r.
|
370
|
-
|
367
|
+
return r['Value'] if r.key?('Value')
|
368
|
+
fail ResponseMissingValueField
|
371
369
|
else
|
372
|
-
|
373
|
-
|
370
|
+
fail ResponseMissingErrorDescriptionField unless r.key?('ErrorDescription')
|
371
|
+
fail SessionInvalid if r['ErrorDescription'][0] == 'SESSION_INVALID'
|
374
372
|
|
375
373
|
ed = r['ErrorDescription'].shift
|
376
374
|
ex = Errors.exception_class_from_desc(ed)
|
377
375
|
r['ErrorDescription'].unshift(ed) if ex == Errors::GenericError
|
378
|
-
|
376
|
+
fail ex, r['ErrorDescription']
|
379
377
|
end
|
380
378
|
end
|
381
379
|
end
|