opennebula 4.12.1 → 4.13.80.beta1

Sign up to get free protection for your applications and to get access to all the features.
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