knife-xapi 0.5.4 → 0.6.0
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.
- 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
|