opennebula 4.12.1 → 4.13.80.beta1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c6786aa76e7311b0394bf5cec4c81ff2f340e157
4
- data.tar.gz: 087e34af81a845a8c16cc45f260c2ca7bf0a1667
3
+ metadata.gz: 4c22ee052b29d751b16a22e9be737f1d4009a4ef
4
+ data.tar.gz: b882b0d31b1096e5287b47ec799f8f6b88fbcecd
5
5
  SHA512:
6
- metadata.gz: aa41eb3150b17bb655173732982e19aa079ec249ad8f53494e5376cb0c754832ebbe5bf61762119f343fe18fc7888c5cdf2839212c640c557b0951ca44af7aca
7
- data.tar.gz: 2ca43c16761cec13390635e9edd3483826515af310cd1324880fb2734f5d149862966a2c65a451359501a1ed5684097c04e65e725b51b0d4112d86da22b22681
6
+ metadata.gz: 2602b4e09ee0587d0eadd55f581209d3f5946f1bedc826a477fa2bf1b1238000df4801358ecf2042e4e769f7d9c21f01aa4da4799f81b6edca7417037ef9cecc
7
+ data.tar.gz: a89f6eabb2d2f196b2c82abf5cb7facc4a04ba7edb7b002fe1ed3bd47a90a88bf046e0386022782769d847625d81817eb25711920b764897a0868561bf2c4b47
data/NOTICE CHANGED
@@ -1,6 +1,6 @@
1
1
  OpenNebula Open Source Project
2
2
  --------------------------------------------------------------------------------
3
- Copyright 2002-2014, OpenNebula Project, OpenNebula Systems (formerly C12G Labs)
3
+ Copyright 2002-2015, OpenNebula Project, OpenNebula Systems (formerly C12G Labs)
4
4
  --------------------------------------------------------------------------------
5
5
 
6
6
  You can find more information about the project, release notes and
@@ -21,11 +21,6 @@ The following people have contributed to the development of the technology
21
21
  - Daniel Molina Aranda (dmolina@opennebula.org)
22
22
  - Hector Sanjuan Redondo (hsanjuan@opennebula.org)
23
23
 
24
- The new features for service elasticity (oneFlow) introduced in OpenNebula 4.2
25
- were funded by BlackBerry in the context of the Fund a Feature Program.
26
-
27
- OpenNebula Project also acknowledges the contributions of C12G Labs developers.
28
-
29
24
  LICENSE
30
25
 
31
26
  OpenNebula is licensed under the Apache License, Version 2.0 (the
data/lib/opennebula.rb CHANGED
@@ -60,5 +60,5 @@ require 'opennebula/system'
60
60
  module OpenNebula
61
61
 
62
62
  # OpenNebula version
63
- VERSION = '4.12.1'
63
+ VERSION = '4.13.80'
64
64
  end
@@ -130,7 +130,7 @@ module OpenNebula
130
130
  raise "ONE_AUTH file not present"
131
131
  end
132
132
 
133
- @one_auth.rstrip!
133
+ @one_auth = @one_auth.rstrip
134
134
 
135
135
  if endpoint
136
136
  @one_endpoint = endpoint
@@ -144,6 +144,8 @@ module OpenNebula
144
144
  @one_endpoint = "http://localhost:2633/RPC2"
145
145
  end
146
146
 
147
+ @one_endpoint= @one_endpoint.rstrip
148
+
147
149
  @async = !options[:sync]
148
150
 
149
151
  timeout=nil
@@ -188,7 +188,7 @@ module OpenNebula
188
188
 
189
189
  # Returns whether or not the host with 'id' is part of this cluster
190
190
  # @param id [Integer|Array] host ID
191
- # @return [Boolean] true if found
191
+ # @return [Boolean] true if found
192
192
  def contains_host?(id)
193
193
  contains_resource?('HOSTS/ID', id)
194
194
  end
@@ -207,7 +207,7 @@ module OpenNebula
207
207
 
208
208
  # Returns whether or not the datastore with 'id' is part of this cluster
209
209
  # @param id [Integer|Array] datastore ID
210
- # @return [Boolean] true if found
210
+ # @return [Boolean] true if found
211
211
  def contains_datastore?(id)
212
212
  contains_resource?('DATASTORES/ID', id)
213
213
  end
@@ -226,7 +226,7 @@ module OpenNebula
226
226
 
227
227
  # Returns whether or not the vnet with 'id' is part of this cluster
228
228
  # @param id [Integer|Arrray] vnet ID
229
- # @return [Boolean] true if found
229
+ # @return [Boolean] true if found
230
230
  def contains_vnet?(id)
231
231
  contains_resource?('VNETS/ID', id)
232
232
  end
@@ -252,7 +252,7 @@ module OpenNebula
252
252
 
253
253
  id = [id] if id.class != Array
254
254
 
255
- id.each { |i|
255
+ id.each { |i|
256
256
  return false if !id_array.include?(i.to_s)
257
257
  }
258
258
 
@@ -44,7 +44,9 @@ module OpenNebula
44
44
  :chown => "document.chown",
45
45
  :chmod => "document.chmod",
46
46
  :clone => "document.clone",
47
- :rename => "document.rename"
47
+ :rename => "document.rename",
48
+ :lock => "document.lock",
49
+ :unlock => "document.unlock"
48
50
  }
49
51
 
50
52
  # Creates a Document Object description with just its identifier
@@ -200,6 +202,32 @@ module OpenNebula
200
202
  return call(DOCUMENT_METHODS[:rename], @pe_id, name)
201
203
  end
202
204
 
205
+ # Locks this object
206
+ #
207
+ # @param owner [String] String to identify the application requestiong
208
+ # the lock
209
+ #
210
+ # @return [Bool, OpenNebula::Error] In case of success, true if the
211
+ # lock was granted, and false if the object is already locked.
212
+ def lock(owner="")
213
+ return Error.new('ID not defined') if !@pe_id
214
+
215
+ rc = @client.call(DOCUMENT_METHODS[:lock], @pe_id, owner)
216
+
217
+ return rc
218
+ end
219
+
220
+ # Unlocks this object
221
+ #
222
+ # @param owner [String] String to identify the application requestiong
223
+ # the unlock
224
+ #
225
+ # @return [nil, OpenNebula::Error] nil in case of success, Error
226
+ # otherwise
227
+ def unlock(owner="")
228
+ return call(DOCUMENT_METHODS[:unlock], @pe_id, owner)
229
+ end
230
+
203
231
  #######################################################################
204
232
  # Helpers to get Document information
205
233
  #######################################################################
@@ -249,7 +249,7 @@ module OpenNebula
249
249
  # Returns an array with the numeric user ids
250
250
  def user_ids
251
251
  ids = self.retrieve_elements("USERS/ID")
252
-
252
+
253
253
  return [] if ids.nil?
254
254
 
255
255
  return ids.collect! {|x| x.to_i}
@@ -16,6 +16,7 @@
16
16
 
17
17
 
18
18
  require 'opennebula/pool_element'
19
+ require 'base64'
19
20
 
20
21
  module OpenNebula
21
22
  class Host < PoolElement
@@ -187,6 +188,37 @@ module OpenNebula
187
188
  return call(HOST_METHODS[:rename], @pe_id, name)
188
189
  end
189
190
 
191
+ # Imports a wild VM from the host and puts it in running state
192
+ #
193
+ # @param name [String] Name of the VM to import
194
+ #
195
+ # @return [nil, OpenNebula::Error] nil in case of success, Error
196
+ # otherwise
197
+ def import_wild(name)
198
+ vms = importable_wilds.select {|vm| vm['VM_NAME'] == name }
199
+
200
+ if vms.length == 0
201
+ return OpenNebula::Error.new("No importable wilds with name " <<
202
+ "'#{name}' found.")
203
+ elsif vms.length > 1
204
+ return OpenNebula::Error.new("More than one importable wild " <<
205
+ "with name '#{name}' found.")
206
+ end
207
+
208
+ wild = vms.first
209
+
210
+ template = Base64.decode64(wild['IMPORT_TEMPLATE'])
211
+
212
+ xml = OpenNebula::VirtualMachine.build_xml
213
+ vm = OpenNebula::VirtualMachine.new(xml, @client)
214
+
215
+ rc = vm.allocate(template)
216
+
217
+ return rc if OpenNebula.is_error?(rc)
218
+
219
+ vm.deploy(id, false)
220
+ end
221
+
190
222
  #######################################################################
191
223
  # Helpers to get Host information
192
224
  #######################################################################
@@ -206,6 +238,22 @@ module OpenNebula
206
238
  SHORT_HOST_STATES[state_str]
207
239
  end
208
240
 
241
+ # Returns the <TEMPLATE> element in text form
242
+ # indent:: _Boolean_ indents the resulting string, default true
243
+ def template_str(indent=true)
244
+ template_like_str('TEMPLATE', indent)
245
+ end
246
+
247
+ # Get wild VMs in the host
248
+ def wilds
249
+ [self.to_hash['HOST']['TEMPLATE']['VM']].flatten.compact
250
+ end
251
+
252
+ # Get importable wild VMs in the host
253
+ def importable_wilds
254
+ wilds.select {|w| Hash === w && w['IMPORT_TEMPLATE'] }
255
+ end
256
+
209
257
  private
210
258
  def set_enabled(enabled)
211
259
  return Error.new('ID not defined') if !@pe_id
@@ -45,7 +45,7 @@ module OpenNebula
45
45
  end
46
46
 
47
47
  #######################################################################
48
- # XML-RPC Methods for the Host Pool
48
+ # XML-RPC Methods for the Host Pool
49
49
  #######################################################################
50
50
 
51
51
  # Retrieves all the Hosts in the pool.
@@ -24,7 +24,6 @@ module OpenNebula
24
24
  # Constants and Class Methods
25
25
  #######################################################################
26
26
 
27
-
28
27
  IMAGE_METHODS = {
29
28
  :info => "image.info",
30
29
  :allocate => "image.allocate",
@@ -36,7 +35,10 @@ module OpenNebula
36
35
  :chmod => "image.chmod",
37
36
  :chtype => "image.chtype",
38
37
  :clone => "image.clone",
39
- :rename => "image.rename"
38
+ :rename => "image.rename",
39
+ :snapshotdelete => "image.snapshotdelete",
40
+ :snapshotrevert => "image.snapshotrevert",
41
+ :snapshotflatten=> "image.snapshotflatten"
40
42
  }
41
43
 
42
44
  IMAGE_STATES=%w{INIT READY USED DISABLED LOCKED ERROR CLONE DELETE USED_PERS}
@@ -224,6 +226,32 @@ module OpenNebula
224
226
  return call(IMAGE_METHODS[:rename], @pe_id, name)
225
227
  end
226
228
 
229
+ # Deletes Image from snapshot
230
+ #
231
+ # @param snap_id [Integer] ID of the snapshot to delete
232
+ #
233
+ # @return [nil, OpenNebula::Error] nil in case of success or Error
234
+ def snapshot_delete(snap_id)
235
+ return call(IMAGE_METHODS[:snapshotdelete], @pe_id, snap_id)
236
+ end
237
+
238
+ # Reverts Image state to a previous snapshot
239
+ #
240
+ # @param snap_id [Integer] ID of the snapshot to revert to
241
+ #
242
+ # @return [nil, OpenNebula::Error] nil in case of success or Error
243
+ def snapshot_revert(snap_id)
244
+ return call(IMAGE_METHODS[:snapshotrevert], @pe_id, snap_id)
245
+ end
246
+
247
+ # Flattens an image snapshot
248
+ #
249
+ # @param snap_id [Integer] ID of the snapshot to flatten
250
+ #
251
+ # @return [nil, OpenNebula::Error] nil in case of success or Error
252
+ def snapshot_flatten(snap_id)
253
+ return call(IMAGE_METHODS[:snapshotflatten], @pe_id, snap_id)
254
+ end
227
255
  #######################################################################
228
256
  # Helpers to get Image information
229
257
  #######################################################################
@@ -180,8 +180,6 @@ class OpenNebula::LdapAuth
180
180
  [@user['memberOf']].flatten.each do |group|
181
181
  if @mapping[group]
182
182
  groups << @mapping[group]
183
- else
184
- groups << @options[:mapping_default]
185
183
  end
186
184
  end
187
185
 
@@ -31,7 +31,6 @@ module Role
31
31
  'stop',
32
32
  'suspend',
33
33
  'resume',
34
- 'boot',
35
34
  'delete',
36
35
  'delete-recreate',
37
36
  'reboot',
@@ -23,9 +23,9 @@ require 'fileutils'
23
23
  module OpenNebula; end
24
24
 
25
25
  # Server authentication class. This method can be used by OpenNebula services
26
- # to let access authenticated users by other means. It is based on OpenSSL
26
+ # to let access authenticated users by other means. It is based on OpenSSL
27
27
  # symmetric ciphers
28
- class OpenNebula::ServerCipherAuth
28
+ class OpenNebula::ServerCipherAuth
29
29
  ###########################################################################
30
30
  #Constants with paths to relevant files and defaults
31
31
  ###########################################################################
@@ -36,7 +36,7 @@ class OpenNebula::ServerCipherAuth
36
36
 
37
37
  def initialize(srv_user, srv_passwd)
38
38
  @srv_user = srv_user
39
- @srv_passwd = srv_passwd
39
+ @srv_passwd = srv_passwd
40
40
 
41
41
  if !srv_passwd.empty?
42
42
  @key = Digest::SHA1.hexdigest(@srv_passwd)
@@ -53,7 +53,7 @@ class OpenNebula::ServerCipherAuth
53
53
 
54
54
  # Creates a ServerCipher for client usage
55
55
  def self.new_client(srv_user=nil, srv_passwd=nil)
56
- if ( srv_user == nil || srv_passwd == nil )
56
+ if ( srv_user == nil || srv_passwd == nil )
57
57
  begin
58
58
  if ENV["ONE_CIPHER_AUTH"] and !ENV["ONE_CIPHER_AUTH"].empty?
59
59
  one_auth = File.read(ENV["ONE_CIPHER_AUTH"])
@@ -64,23 +64,23 @@ class OpenNebula::ServerCipherAuth
64
64
  one_auth.rstrip!
65
65
 
66
66
  rc = one_auth.match(/(.*?):(.*)/)
67
-
67
+
68
68
  if rc.nil?
69
69
  raise "Bad format for one_auth token (<user>:<passwd>)"
70
- else
70
+ else
71
71
  srv_user = rc[1]
72
72
  srv_passwd = rc[2]
73
73
  end
74
74
  rescue => e
75
75
  raise e.message
76
76
  end
77
- end
77
+ end
78
78
 
79
79
  self.new(srv_user, srv_passwd)
80
80
  end
81
81
 
82
82
  # Generates a login token in the form:
83
- # - server_user:target_user:time_expires
83
+ # - server_user:target_user:time_expires
84
84
  # The token is then encrypted with the contents of one_auth
85
85
  def login_token(expire, target_user=nil)
86
86
  target_user ||= @srv_user
@@ -110,11 +110,11 @@ class OpenNebula::ServerCipherAuth
110
110
  def authenticate(srv_user,srv_pass, signed_text)
111
111
  begin
112
112
  @key = srv_pass
113
-
113
+
114
114
  s_user, t_user, expires = decrypt(signed_text).split(':')
115
115
 
116
116
  return "User name missmatch" if s_user != srv_user
117
-
117
+
118
118
  return "login token expired" if Time.now.to_i >= expires.to_i
119
119
 
120
120
  return true
@@ -125,20 +125,20 @@ class OpenNebula::ServerCipherAuth
125
125
 
126
126
  private
127
127
 
128
- def encrypt(data)
128
+ def encrypt(data)
129
129
  @cipher.encrypt
130
130
  @cipher.key = @key
131
-
131
+
132
132
  rc = @cipher.update(data)
133
133
  rc << @cipher.final
134
134
 
135
135
  return rc
136
136
  end
137
137
 
138
- def decrypt(data)
138
+ def decrypt(data)
139
139
  @cipher.decrypt
140
140
  @cipher.key = @key
141
-
141
+
142
142
  rc = @cipher.update(Base64::decode64(data))
143
143
  rc << @cipher.final
144
144
 
@@ -98,7 +98,7 @@ module OpenNebula
98
98
  # otherwise
99
99
  def update(new_template=nil, append=false)
100
100
  super(VDC_METHODS[:update], new_template, append ? 1 : 0)
101
- end
101
+ end
102
102
 
103
103
  # Deletes the Vdc
104
104
  # @return [nil, OpenNebula::Error] nil in case of success, Error
@@ -24,38 +24,96 @@ module OpenNebula
24
24
  #######################################################################
25
25
 
26
26
  VM_METHODS = {
27
- :info => "vm.info",
28
- :allocate => "vm.allocate",
29
- :action => "vm.action",
30
- :migrate => "vm.migrate",
31
- :deploy => "vm.deploy",
32
- :savedisk => "vm.savedisk",
33
- :chown => "vm.chown",
34
- :chmod => "vm.chmod",
35
- :monitoring => "vm.monitoring",
36
- :attach => "vm.attach",
37
- :detach => "vm.detach",
38
- :rename => "vm.rename",
39
- :update => "vm.update",
40
- :resize => "vm.resize",
27
+ :info => "vm.info",
28
+ :allocate => "vm.allocate",
29
+ :action => "vm.action",
30
+ :migrate => "vm.migrate",
31
+ :deploy => "vm.deploy",
32
+ :chown => "vm.chown",
33
+ :chmod => "vm.chmod",
34
+ :monitoring => "vm.monitoring",
35
+ :attach => "vm.attach",
36
+ :detach => "vm.detach",
37
+ :rename => "vm.rename",
38
+ :update => "vm.update",
39
+ :resize => "vm.resize",
41
40
  :snapshotcreate => "vm.snapshotcreate",
42
41
  :snapshotrevert => "vm.snapshotrevert",
43
42
  :snapshotdelete => "vm.snapshotdelete",
44
- :attachnic => "vm.attachnic",
45
- :detachnic => "vm.detachnic",
46
- :recover => "vm.recover"
43
+ :attachnic => "vm.attachnic",
44
+ :detachnic => "vm.detachnic",
45
+ :recover => "vm.recover",
46
+ :disksaveas => "vm.disksaveas",
47
+ :disksnapshotcreate => "vm.disksnapshotcreate",
48
+ :disksnapshotrevert => "vm.disksnapshotrevert",
49
+ :disksnapshotdelete => "vm.disksnapshotdelete"
47
50
  }
48
51
 
49
52
  VM_STATE=%w{INIT PENDING HOLD ACTIVE STOPPED SUSPENDED DONE FAILED
50
53
  POWEROFF UNDEPLOYED}
51
54
 
52
- LCM_STATE=%w{LCM_INIT PROLOG BOOT RUNNING MIGRATE SAVE_STOP SAVE_SUSPEND
53
- SAVE_MIGRATE PROLOG_MIGRATE PROLOG_RESUME EPILOG_STOP EPILOG
54
- SHUTDOWN CANCEL FAILURE CLEANUP_RESUBMIT UNKNOWN HOTPLUG SHUTDOWN_POWEROFF
55
- BOOT_UNKNOWN BOOT_POWEROFF BOOT_SUSPENDED BOOT_STOPPED CLEANUP_DELETE
56
- HOTPLUG_SNAPSHOT HOTPLUG_NIC HOTPLUG_SAVEAS HOTPLUG_SAVEAS_POWEROFF
57
- HOTPLUG_SAVEAS_SUSPENDED SHUTDOWN_UNDEPLOY EPILOG_UNDEPLOY
58
- PROLOG_UNDEPLOY BOOT_UNDEPLOY}
55
+ LCM_STATE=%w{
56
+ LCM_INIT
57
+ PROLOG
58
+ BOOT
59
+ RUNNING
60
+ MIGRATE
61
+ SAVE_STOP
62
+ SAVE_SUSPEND
63
+ SAVE_MIGRATE
64
+ PROLOG_MIGRATE
65
+ PROLOG_RESUME
66
+ EPILOG_STOP
67
+ EPILOG
68
+ SHUTDOWN
69
+ CANCEL
70
+ FAILURE
71
+ CLEANUP_RESUBMIT
72
+ UNKNOWN
73
+ HOTPLUG
74
+ SHUTDOWN_POWEROFF
75
+ BOOT_UNKNOWN
76
+ BOOT_POWEROFF
77
+ BOOT_SUSPENDED
78
+ BOOT_STOPPED
79
+ CLEANUP_DELETE
80
+ HOTPLUG_SNAPSHOT
81
+ HOTPLUG_NIC
82
+ HOTPLUG_SAVEAS
83
+ HOTPLUG_SAVEAS_POWEROFF
84
+ HOTPLUG_SAVEAS_SUSPENDED
85
+ SHUTDOWN_UNDEPLOY
86
+ EPILOG_UNDEPLOY
87
+ PROLOG_UNDEPLOY
88
+ BOOT_UNDEPLOY
89
+ HOTPLUG_PROLOG_POWEROFF
90
+ HOTPLUG_EPILOG_POWEROFF
91
+ BOOT_MIGRATE
92
+ BOOT_FAILURE
93
+ BOOT_MIGRATE_FAILURE
94
+ PROLOG_MIGRATE_FAILURE
95
+ PROLOG_FAILURE
96
+ EPILOG_FAILURE
97
+ EPILOG_STOP_FAILURE
98
+ EPILOG_UNDEPLOY_FAILURE
99
+ PROLOG_MIGRATE_POWEROFF
100
+ PROLOG_MIGRATE_POWEROFF_FAILURE
101
+ PROLOG_MIGRATE_SUSPEND
102
+ PROLOG_MIGRATE_SUSPEND_FAILURE
103
+ BOOT_UNDEPLOY_FAILURE
104
+ BOOT_STOPPED_FAILURE
105
+ PROLOG_RESUME_FAILURE
106
+ PROLOG_UNDEPLOY_FAILURE
107
+ DISK_SNAPSHOT_POWEROFF
108
+ DISK_SNAPSHOT_REVERT_POWEROFF
109
+ DISK_SNAPSHOT_DELETE_POWEROFF
110
+ DISK_SNAPSHOT_SUSPENDED
111
+ DISK_SNAPSHOT_REVERT_SUSPENDED
112
+ DISK_SNAPSHOT_DELETE_SUSPENDED
113
+ DISK_SNAPSHOT
114
+ DISK_SNAPSHOT_REVERT
115
+ DISK_SNAPSHOT_DELETE
116
+ }
59
117
 
60
118
  SHORT_VM_STATES={
61
119
  "INIT" => "init",
@@ -102,7 +160,34 @@ module OpenNebula
102
160
  "SHUTDOWN_UNDEPLOY" => "shut",
103
161
  "EPILOG_UNDEPLOY" => "epil",
104
162
  "PROLOG_UNDEPLOY" => "prol",
105
- "BOOT_UNDEPLOY" => "boot"
163
+ "BOOT_UNDEPLOY" => "boot",
164
+ "HOTPLUG_PROLOG_POWEROFF" => "hotp",
165
+ "HOTPLUG_EPILOG_POWEROFF" => "hotp",
166
+ "BOOT_MIGRATE" => "boot",
167
+ "BOOT_FAILURE" => "fail",
168
+ "BOOT_MIGRATE_FAILURE" => "fail",
169
+ "PROLOG_MIGRATE_FAILURE" => "fail",
170
+ "PROLOG_FAILURE" => "fail",
171
+ "EPILOG_FAILURE" => "fail",
172
+ "EPILOG_STOP_FAILURE" => "fail",
173
+ "EPILOG_UNDEPLOY_FAILURE" => "fail",
174
+ "PROLOG_MIGRATE_POWEROFF" => "migr",
175
+ "PROLOG_MIGRATE_POWEROFF_FAILURE" => "fail",
176
+ "PROLOG_MIGRATE_SUSPEND" => "migr",
177
+ "PROLOG_MIGRATE_SUSPEND_FAILURE" => "fail",
178
+ "BOOT_UNDEPLOY_FAILURE" => "fail",
179
+ "BOOT_STOPPED_FAILURE" => "fail",
180
+ "PROLOG_RESUME_FAILURE" => "fail",
181
+ "PROLOG_UNDEPLOY_FAILURE" => "fail",
182
+ "DISK_SNAPSHOT_POWEROFF" => "snap",
183
+ "DISK_SNAPSHOT_REVERT_POWEROFF" => "snap",
184
+ "DISK_SNAPSHOT_DELETE_POWEROFF" => "snap",
185
+ "DISK_SNAPSHOT_SUSPENDED" => "snap",
186
+ "DISK_SNAPSHOT_REVERT_SUSPENDED"=> "snap",
187
+ "DISK_SNAPSHOT_DELETE_SUSPENDED"=> "snap",
188
+ "DISK_SNAPSHOT" => "snap",
189
+ "DISK_SNAPSHOT_REVERT" => "snap",
190
+ "DISK_SNAPSHOT_DELETE" => "snap"
106
191
  }
107
192
 
108
193
  MIGRATE_REASON=%w{NONE ERROR USER}
@@ -116,7 +201,15 @@ module OpenNebula
116
201
  HISTORY_ACTION=%w{none migrate live-migrate shutdown shutdown-hard
117
202
  undeploy undeploy-hard hold release stop suspend resume boot delete
118
203
  delete-recreate reboot reboot-hard resched unresched poweroff
119
- poweroff-hard}
204
+ poweroff-hard disk-attach disk-detach nic-attach nic-detach
205
+ snap-create snap-delete}
206
+
207
+ EXTERNAL_IP_ATTRS = [
208
+ 'GUEST_IP',
209
+ 'AWS_IP_ADDRESS',
210
+ 'AZ_IPADDRESS',
211
+ 'SL_PRIMARYIPADDRESS'
212
+ ]
120
213
 
121
214
  # Creates a VirtualMachine description with just its identifier
122
215
  # this method should be used to create plain VirtualMachine objects.
@@ -339,13 +432,6 @@ module OpenNebula
339
432
  delete(recreate)
340
433
  end
341
434
 
342
- # Forces a re-deployment of a VM in UNKNOWN or BOOT state
343
- def boot
344
- action('boot')
345
- end
346
-
347
- alias_method :restart, :boot
348
-
349
435
  # @deprecated use {#delete} instead
350
436
  def resubmit
351
437
  action('delete-recreate')
@@ -371,12 +457,14 @@ module OpenNebula
371
457
  # @param enforce [true|false] If it is set to true, the host capacity
372
458
  # will be checked, and the deployment will fail if the host is
373
459
  # overcommited. Defaults to false
460
+ # @param ds_id [Integer] The System Datastore where to migrate the VM.
461
+ # To use the current one, set it to -1
374
462
  #
375
463
  # @return [nil, OpenNebula::Error] nil in case of success, Error
376
464
  # otherwise
377
- def migrate(host_id, live=false, enforce=false)
465
+ def migrate(host_id, live=false, enforce=false, ds_id=-1)
378
466
  call(VM_METHODS[:migrate], @pe_id, host_id.to_i, live==true,
379
- enforce)
467
+ enforce, ds_id.to_i)
380
468
  end
381
469
 
382
470
  # @deprecated use {#migrate} instead
@@ -384,40 +472,30 @@ module OpenNebula
384
472
  migrate(host_id, true, enforce)
385
473
  end
386
474
 
387
- # Set the specified vm's disk to be saved in a new image
388
- # when the VirtualMachine shutdowns
475
+ # Set the specified vm's disk to be saved as a new image
389
476
  #
390
477
  # @param disk_id [Integer] ID of the disk to be saved
391
478
  # @param image_name [String] Name for the new image where the
392
479
  # disk will be saved
393
480
  # @param image_type [String] Type of the new image. Set to empty string
394
481
  # to use the default type
395
- # @param hot [true|false] True to save the disk immediately, false will
396
- # perform the operation when the VM shuts down
397
- # @param do_template [true|false] True to clone also the VM originating
398
- # template and replace the disk with the saved image
482
+ # @param snap_id [Integer] ID of the snapshot to save, -1 to use the
483
+ # current disk image state
399
484
  #
400
485
  # @return [Integer, OpenNebula::Error] the new Image ID in case of
401
486
  # success, error otherwise
402
- def disk_snapshot(disk_id, image_name, image_type="", hot=false,
403
- do_template=false)
487
+ def disk_saveas(disk_id, image_name, image_type="", snap_id=-1)
404
488
  return Error.new('ID not defined') if !@pe_id
405
489
 
406
- rc = @client.call(VM_METHODS[:savedisk],
490
+ rc = @client.call(VM_METHODS[:disksaveas],
407
491
  @pe_id,
408
492
  disk_id,
409
493
  image_name,
410
494
  image_type,
411
- hot,
412
- do_template)
495
+ snap_id)
413
496
  return rc
414
497
  end
415
498
 
416
- # @deprecated use {#disk_snapshot}
417
- def save_as(disk_id, image_name, image_type="", hot=false)
418
- return disk_snapshot(disk_id, image_name, image_type, hot)
419
- end
420
-
421
499
  # Resize the VM
422
500
  #
423
501
  # @param capacity_template [String] Template containing the new capacity
@@ -469,19 +547,15 @@ module OpenNebula
469
547
  # the requested xpath expressions, and an Array of 'timestamp, value'.
470
548
  #
471
549
  # @example
472
- # vm.monitoring( ['CPU', 'NET_TX', 'TEMPLATE/CUSTOM_PROBE'] )
473
- #
474
- # { "NET_TX" =>
475
- # [["1337264510", "210"],
476
- # ["1337264553", "220"],
477
- # ["1337264584", "230"]],
478
- # "TEMPLATE/CUSTOM_PROBE" =>
479
- # [],
480
- # "CPU" =>
481
- # [["1337264510", "0"],
482
- # ["1337264553", "0"],
483
- # ["1337264584", "0"]]
550
+ # vm.monitoring( ['MONITORING/CPU', 'MONITORING/NETTX'] )
551
+ #
552
+ # {
553
+ # "MONITORING/CPU"=>[["1435085098", "47"], ["1435085253", "5"],
554
+ # ["1435085410", "48"], ["1435085566", "3"], ["1435088136", "2"]],
555
+ # "MONITORING/NETTX"=>[["1435085098", "0"], ["1435085253", "50"],
556
+ # ["1435085410", "50"], ["1435085566", "50"], ["1435085723", "50"]]
484
557
  # }
558
+ #
485
559
  def monitoring(xpath_expressions)
486
560
  return super(VM_METHODS[:monitoring], 'VM',
487
561
  'LAST_POLL', xpath_expressions)
@@ -539,9 +613,42 @@ module OpenNebula
539
613
  return call(VM_METHODS[:snapshotdelete], @pe_id, snap_id)
540
614
  end
541
615
 
616
+ # Takes a new snapshot of a disk
617
+ #
618
+ # @param disk_id [Integer] Id of the disk
619
+ # @param name [String] description for the snapshot
620
+ #
621
+ # @return [Integer, OpenNebula::Error] The new snapshot ID or error
622
+ def disk_snapshot_create(disk_id, name)
623
+ return call(VM_METHODS[:disksnapshotcreate], @pe_id, disk_id, name)
624
+ end
625
+
626
+ # Reverts disk state to a previously taken snapshot
627
+ #
628
+ # @param disk_id [Integer] Id of the disk
629
+ # @param snap_id [Integer] Id of the snapshot
630
+ #
631
+ # @return [nil, OpenNebula::Error] nil in case of success, Error
632
+ # otherwise
633
+ def disk_snapshot_revert(disk_id, snap_id)
634
+ return call(VM_METHODS[:disksnapshotrevert], @pe_id, disk_id, snap_id)
635
+ end
636
+
637
+ # Deletes a disk snapshot
638
+ #
639
+ # @param disk_id [Integer] Id of the disk
640
+ # @param snap_id [Integer] Id of the snapshot
641
+ #
642
+ # @return [nil, OpenNebula::Error] nil in case of success, Error
643
+ # otherwise
644
+ def disk_snapshot_delete(disk_id, snap_id)
645
+ return call(VM_METHODS[:disksnapshotdelete], @pe_id, disk_id, snap_id)
646
+ end
647
+
542
648
  # Recovers an ACTIVE VM
543
649
  #
544
- # @param result [Boolean] Recover with success (true) or failure (false)
650
+ # @param result [Integer] Recover with failure (0), success (1) or
651
+ # retry (2)
545
652
  # @param result [info] Additional information needed to recover the VM
546
653
  # @return [nil, OpenNebula::Error] nil in case of success, Error
547
654
  # otherwise
@@ -595,6 +702,124 @@ module OpenNebula
595
702
  self['DEPLOY_ID']
596
703
  end
597
704
 
705
+ # Clones the VM's source Template, replacing the disks with live snapshots
706
+ # of the current disks. The VM capacity and NICs are also preserved
707
+ #
708
+ # @param name [String] Name for the new Template
709
+ #
710
+ # @return [Integer, OpenNebula::Error] the new Template ID in case of
711
+ # success, error otherwise
712
+ def save_as_template(name)
713
+ rc = info()
714
+ return rc if OpenNebula.is_error?(rc)
715
+
716
+ tid = self['TEMPLATE/TEMPLATE_ID']
717
+ if tid.nil? || tid.empty?
718
+ return Error.new('VM has no template to be saved')
719
+ end
720
+
721
+ if state_str() != "POWEROFF"
722
+ return Error.new("VM state must be POWEROFF, "<<
723
+ "current state is #{state_str()}, #{lcm_state_str()}")
724
+ end
725
+
726
+ # Clone the source template
727
+ new_tid = OpenNebula::Template.new_with_id(tid, @client).clone(name)
728
+ return new_tid if OpenNebula.is_error?(new_tid)
729
+
730
+ # Replace the original template's capacity with the actual VM values
731
+ replace = ""
732
+
733
+ cpu = self['TEMPLATE/CPU']
734
+ if !cpu.nil? && !cpu.empty?
735
+ replace << "CPU = #{cpu}\n"
736
+ end
737
+
738
+ vcpu = self['TEMPLATE/VCPU']
739
+ if !vcpu.nil? && !vcpu.empty?
740
+ replace << "VCPU = #{vcpu}\n"
741
+ end
742
+
743
+ mem = self['TEMPLATE/MEMORY']
744
+ if !mem.nil? && !mem.empty?
745
+ replace << "MEMORY = #{mem}\n"
746
+ end
747
+
748
+ self.each('TEMPLATE/DISK') do |disk|
749
+ # While the previous snapshot is still in progress, we wait
750
+ # indefinitely
751
+ rc = info()
752
+ return rc if OpenNebula.is_error?(rc)
753
+
754
+ steps = 0
755
+ while lcm_state_str() == "HOTPLUG_SAVEAS_POWEROFF"
756
+ if steps < 30
757
+ sleep 1
758
+ else
759
+ sleep 15
760
+ end
761
+
762
+ rc = info()
763
+ return rc if OpenNebula.is_error?(rc)
764
+
765
+ steps += 1
766
+ end
767
+
768
+ # If the VM is not busy with a previous disk snapshot, we wait
769
+ # but this time with a timeout
770
+ rc = wait_state("POWEROFF")
771
+ return rc if OpenNebula.is_error?(rc)
772
+
773
+ disk_id = disk["DISK_ID"]
774
+ if disk_id.nil? || disk_id.empty?
775
+ return Error.new('The DISK_ID is missing from the VM template')
776
+ end
777
+
778
+ image_id = disk["IMAGE_ID"]
779
+
780
+ if !image_id.nil? && !image_id.empty?
781
+ rc = disk_saveas(disk_id.to_i,"#{name}-disk-#{disk_id}","",-1)
782
+
783
+ return rc if OpenNebula.is_error?(rc)
784
+
785
+ replace << "DISK = [ IMAGE_ID = #{rc} ]\n"
786
+ else
787
+ # Volatile disks cannot be saved, so the definition is copied
788
+ replace << self.template_like_str(
789
+ "TEMPLATE", true, "DISK[DISK_ID=#{disk_id}]") << "\n"
790
+ end
791
+ end
792
+
793
+ self.each('TEMPLATE/NIC') do |nic|
794
+ nic_id = nic["NIC_ID"]
795
+ if nic_id.nil? || nic_id.empty?
796
+ return Error.new('The NIC_ID is missing from the VM template')
797
+ end
798
+
799
+ net_id = nic["NETWORK_ID"]
800
+
801
+ if !net_id.nil? && !net_id.empty?
802
+ replace << "NIC = [ NETWORK_ID = #{net_id} ]\n"
803
+ else
804
+ # This NIC does not use a Virtual Network
805
+ replace << self.template_like_str(
806
+ "TEMPLATE", true, "NIC[NIC_ID=#{nic_id}]") << "\n"
807
+ end
808
+ end
809
+
810
+ # Required by the Sunstone Cloud View
811
+ replace << "SAVED_TEMPLATE_ID = #{tid}\n"
812
+
813
+ new_tmpl = OpenNebula::Template.new_with_id(new_tid, @client)
814
+
815
+ rc = new_tmpl.update(replace, true)
816
+ return rc if OpenNebula.is_error?(rc)
817
+
818
+ return new_tid
819
+
820
+ # TODO: rollback in case of error
821
+ end
822
+
598
823
  private
599
824
  def action(name)
600
825
  return Error.new('ID not defined') if !@pe_id
@@ -604,5 +829,49 @@ module OpenNebula
604
829
 
605
830
  return rc
606
831
  end
832
+
833
+ def wait_state(state, timeout=10)
834
+ vm_state = ""
835
+ lcm_state = ""
836
+
837
+ timeout.times do
838
+ rc = info()
839
+ return rc if OpenNebula.is_error?(rc)
840
+
841
+ vm_state = state_str()
842
+ lcm_state = lcm_state_str()
843
+
844
+ if vm_state == state
845
+ return true
846
+ end
847
+
848
+ sleep 1
849
+ end
850
+
851
+ return Error.new("Timeout expired for state #{state}. "<<
852
+ "VM is in state #{vm_state}, #{lcm_state}")
853
+ end
854
+
855
+ def wait_lcm_state(state, timeout=10)
856
+ vm_state = ""
857
+ lcm_state = ""
858
+
859
+ timeout.times do
860
+ rc = info()
861
+ return rc if OpenNebula.is_error?(rc)
862
+
863
+ vm_state = state_str()
864
+ lcm_state = lcm_state_str()
865
+
866
+ if lcm_state == state
867
+ return true
868
+ end
869
+
870
+ sleep 1
871
+ end
872
+
873
+ return Error.new("Timeout expired for state #{state}. "<<
874
+ "VM is in state #{vm_state}, #{lcm_state}")
875
+ end
607
876
  end
608
877
  end
@@ -132,23 +132,24 @@ module OpenNebula
132
132
  # and an Array of 'timestamp, value'.
133
133
  #
134
134
  # @example
135
- # vm_pool.monitoring( ['CPU', 'NET_TX', 'TEMPLATE/CUSTOM_PROBE'] )
135
+ # vm_pool.monitoring( ['MONITORING/CPU', 'MONITORING/NETTX'] )
136
136
  #
137
- # {"1"=>
138
- # {"CPU"=>
139
- # [["1337608271", "0"], ["1337608301", "0"], ["1337608331", "0"]],
140
- # "NET_TX"=>
141
- # [["1337608271", "510"], ["1337608301", "510"], ["1337608331", "520"]],
142
- # "TEMPLATE/CUSTOM_PROBE"=>
143
- # []},
137
+ # {"3"=>
138
+ # {
139
+ # "MONITORING/CPU"=>[["1435085098", "47"], ["1435085253", "5"],
140
+ # ["1435085410", "48"], ["1435085566", "3"], ["1435088136", "2"]],
141
+ # "MONITORING/NETTX"=>[["1435085098", "0"], ["1435085253", "50"],
142
+ # ["1435085410", "50"], ["1435085566", "50"], ["1435085723", "50"]]
143
+ # },
144
+ # "43" =>
145
+ # {
146
+ # "MONITORING/CPU"=>[["1435085098", "47"], ["1435085253", "5"],
147
+ # ["1435085410", "48"], ["1435085566", "3"], ["1435088136", "2"]],
148
+ # "MONITORING/NETTX"=>[["1435085098", "0"], ["1435085253", "50"],
149
+ # ["1435085410", "50"], ["1435085566", "50"], ["1435085723", "50"]]
150
+ # }
151
+ # }
144
152
  #
145
- # "0"=>
146
- # {"CPU"=>
147
- # [["1337608271", "0"], ["1337608301", "0"], ["1337608331", "0"]],
148
- # "NET_TX"=>
149
- # [["1337608271", "510"], ["1337608301", "510"], ["1337608331", "520"]],
150
- # "TEMPLATE/CUSTOM_PROBE"=>
151
- # []}}
152
153
  def monitoring(xpath_expressions, filter_flag=INFO_ALL)
153
154
  return super(VM_POOL_METHODS[:monitoring],
154
155
  'VM', 'LAST_POLL', xpath_expressions, filter_flag)
@@ -139,7 +139,7 @@ module OpenNebula
139
139
  }
140
140
  end
141
141
 
142
- # Gets an array of text from elemenets extracted
142
+ # Gets an array of text from elements extracted
143
143
  # using the XPATH expression passed as filter
144
144
  def retrieve_elements(filter)
145
145
  elements_array = Array.new
@@ -162,7 +162,7 @@ module OpenNebula
162
162
 
163
163
  end
164
164
 
165
- # Gets an attribute from an elemenT
165
+ # Gets an attribute from an element
166
166
  # key:: _String_ xpath for the element
167
167
  # name:: _String_ name of the attribute
168
168
  def attr(key,name)
@@ -85,7 +85,7 @@ module OpenNebula
85
85
  # otherwise
86
86
  def update(new_template=nil, append=false)
87
87
  super(ZONE_METHODS[:update], new_template, append ? 1 : 0)
88
- end
88
+ end
89
89
 
90
90
  # Deletes the Zone
91
91
  # @return [nil, OpenNebula::Error] nil in case of success, Error
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: opennebula
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.12.1
4
+ version: 4.13.80.beta1
5
5
  platform: ruby
6
6
  authors:
7
7
  - OpenNebula
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-04-08 00:00:00.000000000 Z
11
+ date: 2015-07-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -121,9 +121,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
121
121
  version: '0'
122
122
  required_rubygems_version: !ruby/object:Gem::Requirement
123
123
  requirements:
124
- - - ">="
124
+ - - ">"
125
125
  - !ruby/object:Gem::Version
126
- version: '0'
126
+ version: 1.3.1
127
127
  requirements: []
128
128
  rubyforge_project:
129
129
  rubygems_version: 2.4.5