opennebula 5.13.80.pre → 6.0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -14,19 +14,117 @@
14
14
  # limitations under the License. #
15
15
  #--------------------------------------------------------------------------- #
16
16
 
17
- require 'ffi-rzmq'
18
17
 
19
18
  require 'opennebula/host'
20
19
  require 'opennebula/image'
21
20
  require 'opennebula/virtual_machine'
22
21
 
22
+ module OpenNebula::WaitExtEvent
23
+ def wait_event(ctx, event, timeout)
24
+ subscriber = ctx.socket(ZMQ::SUB)
25
+
26
+ # Create subscriber
27
+ key = ''
28
+ content = ''
29
+
30
+ subscriber.setsockopt(ZMQ::RCVTIMEO, timeout * 1000)
31
+ subscriber.setsockopt(ZMQ::SUBSCRIBE, event)
32
+ subscriber.connect(@client.one_zmq)
33
+
34
+ rc = subscriber.recv_string(key)
35
+ rc = subscriber.recv_string(content) if rc != -1
36
+
37
+ return if ZMQ::Util.errno == ZMQ::EAGAIN || rc == -1
38
+
39
+ content
40
+ ensure
41
+ subscriber.setsockopt(ZMQ::UNSUBSCRIBE, event)
42
+ subscriber.close
43
+ end
44
+
45
+ def wait2(sstr1, sstr2, timeout = 60, cycles = -1)
46
+ wfun = OpenNebula::WaitExt::WAIT[self.class]
47
+
48
+ # Start with a timeout of 2 seconds, to wait until the first
49
+ # info.
50
+ #
51
+ # The timeout is increased later, to avoid multiple info calls.
52
+ c_timeout = 2
53
+ recvs = 0
54
+ in_state = false
55
+
56
+ # Subscribe with timeout seconds
57
+ #
58
+ # Subscribe string:
59
+ #
60
+ # EVENT STATE element_name/state_str//self.ID
61
+ #
62
+ # - element_name: is the element name to find in the message
63
+ # - self.ID: returns element ID to find in the message
64
+ ctx = ZMQ::Context.new(1)
65
+
66
+ until in_state || (cycles != -1 && recvs >= cycles)
67
+ content = wait_event(ctx,
68
+ wfun[:event].call(self, sstr1, sstr2),
69
+ c_timeout)
70
+
71
+ if content && !content.empty?
72
+ in_state = wfun[:in_state_e].call(sstr1, sstr2, content)
73
+
74
+ break if in_state
75
+ end
76
+
77
+ c_timeout *= 10
78
+ c_timeout = timeout if c_timeout > timeout
79
+
80
+ rco = info
81
+
82
+ return false if OpenNebula.is_error?(rco)
83
+
84
+ in_state = wfun[:in_state].call(self, sstr1, sstr2)
85
+
86
+ recvs += 1
87
+ end
88
+
89
+ in_state
90
+ end
91
+
92
+ end
93
+
94
+ module OpenNebula::WaitExtPolling
95
+ def wait2(sstr1, sstr2, timeout = 60, cycles = -1)
96
+ wfun = OpenNebula::WaitExt::WAIT[self.class]
97
+
98
+ stime = 5
99
+ recvs = 0
100
+ cycles = timeout / stime
101
+ in_state = false
102
+
103
+ loop do
104
+ rco = info
105
+
106
+ return false if OpenNebula.is_error?(rco)
107
+
108
+ in_state = wfun[:in_state].call(self, sstr1, sstr2)
109
+
110
+ recvs += 1
111
+
112
+ break if in_state || recvs >= cycles
113
+
114
+ sleep stime
115
+ end
116
+
117
+ in_state
118
+ end
119
+
120
+ end
121
+
23
122
  # Module to decorate Wait classes with the following methods:
24
123
  # - Wait
25
124
  #
26
125
  # rubocop:disable Style/ClassAndModuleChildren
27
126
  module OpenNebula::WaitExt
28
-
29
- # Wait classes and the name published in ZMQ
127
+ # Wait classes and the name published in ZMQ/STATE
30
128
  WAIT = {
31
129
  OpenNebula::Host => {
32
130
  :event => lambda {|o, s1, _s2|
@@ -78,7 +176,7 @@ module OpenNebula::WaitExt
78
176
  },
79
177
 
80
178
  :in_state => lambda {|o, s1, s2|
81
- obj_s1 = Integer(o['STATE'])
179
+ obj_s1 = Integer(o['STATE'])
82
180
  inx_s1 = OpenNebula::VirtualMachine::VM_STATE.index(s1)
83
181
 
84
182
  obj_s2 = Integer(o['LCM_STATE'])
@@ -105,93 +203,30 @@ module OpenNebula::WaitExt
105
203
  wait?(obj)
106
204
 
107
205
  class << obj
206
+ begin
207
+ require 'ffi-rzmq'
108
208
 
109
- # Wait until the element reaches some specific state
110
- # It waits until the state can be found in ZMQ event message
111
- #
112
- # @param state_str [String] State name to wait
113
- # @param timeout [Integer] Number of seconds to timeout event recv
114
- # @param cycles [Integer] Number of recv cycles. After each one
115
- # object status is checked in OpenNebula.
116
- # Use -1 (default) to wait forever.
117
- def wait(state_str, timeout = 60, cycles = -1)
118
- wait2(state_str, '', timeout, cycles)
119
- end
120
-
121
- def wait_event(ctx, event, timeout)
122
- subscriber = ctx.socket(ZMQ::SUB)
123
-
124
- # Create subscriber
125
- key = ''
126
- content = ''
127
-
128
- subscriber.setsockopt(ZMQ::RCVTIMEO, timeout * 1000)
129
- subscriber.setsockopt(ZMQ::SUBSCRIBE, event)
130
- subscriber.connect('tcp://localhost:2101')
131
-
132
- rc = subscriber.recv_string(key)
133
- rc = subscriber.recv_string(content) if rc != -1
134
-
135
- return if ZMQ::Util.errno == ZMQ::EAGAIN || rc == -1
136
-
137
- content
138
- ensure
139
- subscriber.setsockopt(ZMQ::UNSUBSCRIBE, event)
140
- subscriber.close
141
- end
142
-
143
- def wait2(sstr1, sstr2, timeout = 60, cycles = -1)
144
- wfun = WAIT[self.class]
145
-
146
- # Start with a timeout of 2 seconds, to wait until the first
147
- # info.
148
- #
149
- # The timeout is increased later, to avoid multiple info calls.
150
- c_timeout = 2
151
- recvs = 0
152
- in_state = false
153
-
154
- # Subscribe with timeout seconds
155
- #
156
- # Subscribe string:
157
- #
158
- # EVENT STATE element_name/state_str//self.ID
159
- #
160
- # - element_name: is the element name to find in the message
161
- # - self.ID: returns element ID to find in the message
162
- ctx = ZMQ::Context.new(1)
163
-
164
- until in_state || (cycles != -1 && recvs >= cycles)
165
- content = wait_event(ctx,
166
- wfun[:event].call(self, sstr1, sstr2),
167
- c_timeout)
168
-
169
- if content && !content.empty?
170
- in_state = wfun[:in_state_e].call(sstr1, sstr2, content)
171
-
172
- break if in_state
173
- end
174
-
175
- c_timeout *= 10
176
- c_timeout = timeout if c_timeout > timeout
177
-
178
- rco = info
179
-
180
- return false if OpenNebula.is_error?(rco)
181
-
182
- in_state = wfun[:in_state].call(self, sstr1, sstr2)
183
-
184
- recvs += 1
185
- end
186
-
187
- in_state
188
- end
189
-
209
+ include OpenNebula::WaitExtEvent
210
+ rescue LoadError
211
+ include OpenNebula::WaitExtPolling
212
+ end
190
213
  end
191
214
 
192
215
  super
193
216
  end
194
217
 
218
+ # Wait until the element reaches some specific state
219
+ # It waits until the state can be found in ZMQ event message
220
+ #
221
+ # @param state_str [String] State name to wait
222
+ # @param timeout [Integer] Number of seconds to timeout event recv
223
+ # @param cycles [Integer] Number of recv cycles. After each one
224
+ # object status is checked in OpenNebula.
225
+ # Use -1 (default) to wait forever.
226
+ def wait(state_str, timeout = 60, cycles = -1)
227
+ wait2(state_str, '', timeout, cycles)
228
+ end
229
+
195
230
  # Check if object has the method wait or not
196
231
  #
197
232
  # @param obj [Object or Class] Object to check class
@@ -14,6 +14,8 @@
14
14
  # limitations under the License. #
15
15
  #--------------------------------------------------------------------------- #
16
16
 
17
+ require 'shellwords'
18
+
17
19
  module OpenNebula
18
20
 
19
21
  # Generic log function
@@ -76,6 +78,7 @@ module OpenNebula
76
78
  # If a second parameter is present it is used as the error message when
77
79
  # the command fails
78
80
  def self.exec_and_log(command, message=nil, allowed_return_code=0)
81
+ command = command.shellsplit.shelljoin # escape
79
82
  output=`#{command} 2>&1 1>/dev/null`
80
83
  code=$?.exitstatus
81
84
 
@@ -36,14 +36,25 @@ end
36
36
 
37
37
  ENV['LANG'] = 'C'
38
38
 
39
+ # %%RUBYGEMS_SETUP_BEGIN%%
39
40
  if File.directory?(GEMS_LOCATION)
40
41
  real_gems_path = File.realpath(GEMS_LOCATION)
41
42
  if !defined?(Gem) || Gem.path != [real_gems_path]
42
43
  $LOAD_PATH.reject! {|l| l =~ /vendor_ruby/ }
43
- require 'rubygems'
44
- Gem.use_paths(real_gems_path)
44
+
45
+ # Suppress warnings from Rubygems
46
+ # https://github.com/OpenNebula/one/issues/5379
47
+ begin
48
+ verb = $VERBOSE
49
+ $VERBOSE = nil
50
+ require 'rubygems'
51
+ Gem.use_paths(real_gems_path)
52
+ ensure
53
+ $VERBOSE = verb
54
+ end
45
55
  end
46
56
  end
57
+ # %%RUBYGEMS_SETUP_END%%
47
58
 
48
59
  $LOAD_PATH << LIB_LOCATION + '/ruby/vendors/rbvmomi/lib'
49
60
  $LOAD_PATH << LIB_LOCATION + '/ruby'
@@ -496,9 +496,9 @@ module VCenterDriver
496
496
  end
497
497
 
498
498
  #
499
- # Create and allocate a Opennebula Object.
499
+ # Create and allocate a OpenNebula Object.
500
500
  #
501
- # @param info [String] Info passed to opennebula Core.
501
+ # @param info [String] Info passed to OpenNebula Core.
502
502
  #
503
503
  # @return [&block] the allocated object through a block.
504
504
  #
data/lib/vi_helper.rb CHANGED
@@ -231,10 +231,11 @@ module VCenterDriver
231
231
  @ref_hash[attribute][refkey]
232
232
  end
233
233
 
234
+ require 'addressable'
234
235
  def self.find_image_by(att, the_class, path, ds_id, pool = nil)
235
236
  pool = one_pool(the_class, false) if pool.nil?
236
237
  pool.find do |e|
237
- e[att] == path &&
238
+ e[att] == Addressable::URI.escape(path) &&
238
239
  e['DATASTORE_ID'] == ds_id
239
240
  end
240
241
  end
@@ -33,14 +33,27 @@ module VCenterDriver
33
33
  end
34
34
  end
35
35
 
36
- if File.directory?(GEMS_LOCATION)
37
- real_gems_path = File.realpath(GEMS_LOCATION)
38
- if !defined?(Gem) || Gem.path != [real_gems_path]
39
- $LOAD_PATH.reject! {|l| l =~ /vendor_ruby/ }
36
+ # rubocop: disable all
37
+ # %%RUBYGEMS_SETUP_BEGIN%%
38
+ if File.directory?(GEMS_LOCATION)
39
+ real_gems_path = File.realpath(GEMS_LOCATION)
40
+ if !defined?(Gem) || Gem.path != [real_gems_path]
41
+ $LOAD_PATH.reject! {|l| l =~ /vendor_ruby/ }
42
+
43
+ # Suppress warnings from Rubygems
44
+ # https://github.com/OpenNebula/one/issues/5379
45
+ begin
46
+ verb = $VERBOSE
47
+ $VERBOSE = nil
40
48
  require 'rubygems'
41
49
  Gem.use_paths(real_gems_path)
50
+ ensure
51
+ $VERBOSE = verb
42
52
  end
43
53
  end
54
+ end
55
+ # %%RUBYGEMS_SETUP_END%%
56
+ # rubocop: enable all
44
57
 
45
58
  $LOAD_PATH << RUBY_LIB_LOCATION
46
59
 
@@ -1041,7 +1054,8 @@ module VCenterDriver
1041
1054
  else
1042
1055
  if snapshots?
1043
1056
  error = 'Disk metadata not present and snapshots exist. ' \
1044
- 'OpenNebula cannot manage this VM.'
1057
+ 'Please remove imported VM with "onevm recover ' \
1058
+ '--delete-db".'
1045
1059
  raise error
1046
1060
  end
1047
1061
 
@@ -1961,7 +1975,7 @@ module VCenterDriver
1961
1975
  end
1962
1976
 
1963
1977
  card_spec = {
1964
- :key => 0,
1978
+ :key => Time.now.utc.strftime('%Y%m%d%M%S%L').to_i,
1965
1979
  :deviceInfo => {
1966
1980
  :label => 'net' + card_num.to_s,
1967
1981
  :summary => pg_name
@@ -2107,7 +2121,7 @@ module VCenterDriver
2107
2121
  end
2108
2122
 
2109
2123
  card_spec = {
2110
- :key => 0,
2124
+ :key => Time.now.utc.strftime('%Y%m%d%M%S%L').to_i,
2111
2125
  :deviceInfo => {
2112
2126
  :label => 'net' + card_num.to_s,
2113
2127
  :summary => pg_name
@@ -2401,6 +2415,15 @@ module VCenterDriver
2401
2415
 
2402
2416
  # Attach DISK to VM (hotplug)
2403
2417
  def attach_disk(disk)
2418
+ # Adding a new disk in newer vSphere versions
2419
+ # automatically cleans all system snapshots
2420
+ # https://github.com/OpenNebula/one/issues/5409
2421
+ if snapshots? or one_snapshots?
2422
+ error_message = 'Existing sytem snapshots, cannot change disks. '
2423
+ error_message << 'Please remove all snapshots and try again.'
2424
+ raise error_message
2425
+ end
2426
+
2404
2427
  spec_hash = {}
2405
2428
  device_change = []
2406
2429
 
@@ -2582,6 +2605,12 @@ module VCenterDriver
2582
2605
  def detach_disk(disk)
2583
2606
  return unless disk.exists?
2584
2607
 
2608
+ if snapshots? or one_snapshots?
2609
+ error_message = 'Existing sytem snapshots, cannot change disks. '
2610
+ error_message << 'Please remove all snapshots and try again.'
2611
+ raise error_message
2612
+ end
2613
+
2585
2614
  spec_hash = {}
2586
2615
  spec_hash[:extraConfig] = [disk.config(:delete)]
2587
2616
  spec_hash[:deviceChange] = [{
@@ -2611,15 +2640,15 @@ module VCenterDriver
2611
2640
  # - The disk is managed by OpenNebula
2612
2641
  detachable= !(one_vm['LCM_STATE'].to_i == 11 && !disk.managed?)
2613
2642
  detachable &&= disk.exists?
2614
-
2643
+
2615
2644
  return unless detachable
2616
2645
 
2617
2646
  detach_disk(disk)
2618
2647
 
2619
2648
  # Check if we want to keep the non persistent disk
2620
2649
  keep_non_persistent_disks =
2621
- VCenterDriver::CONFIG[:keep_non_persistent_disks]
2622
-
2650
+ VCenterDriver::CONFIG[:keep_non_persistent_disks]
2651
+
2623
2652
  return if keep_non_persistent_disks == true
2624
2653
 
2625
2654
  disk.destroy
@@ -2816,7 +2845,7 @@ module VCenterDriver
2816
2845
  # Convert VM to template in vCenter
2817
2846
  mark_as_template
2818
2847
 
2819
- # Edit the Opennebula template
2848
+ # Edit the OpenNebula template
2820
2849
  one_client = OpenNebula::Client.new
2821
2850
  template_id = one_item['TEMPLATE/TEMPLATE_ID']
2822
2851
  new_template = OpenNebula::Template.new_with_id(template_id,
@@ -2867,6 +2896,15 @@ module VCenterDriver
2867
2896
  self['rootSnapshot'] && !self['rootSnapshot'].empty?
2868
2897
  end
2869
2898
 
2899
+ def one_snapshots?
2900
+ begin
2901
+ !one_item['TEMPLATE/SNAPSHOT'].nil?
2902
+ rescue StandardError
2903
+ # one_item may not be retrieved if deploy_id hasn't been set
2904
+ false
2905
+ end
2906
+ end
2907
+
2870
2908
  def instantiated_as_persistent?
2871
2909
  begin
2872
2910
  !one_item['TEMPLATE/CLONING_TEMPLATE_ID'].nil?
@@ -3032,7 +3070,7 @@ module VCenterDriver
3032
3070
  # Create a snapshot for the VM
3033
3071
  def create_snapshot(snap_id, snap_name)
3034
3072
  memory_dumps = true
3035
- memory_dumps = CONFIG[:memory_dumps] if CONFIG[:memory_dumps]
3073
+ memory_dumps = CONFIG[:memory_dumps] unless CONFIG[:memory_dumps].nil?
3036
3074
 
3037
3075
  snapshot_hash = {
3038
3076
  :name => snap_id,