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 +4 -4
- data/NOTICE +1 -6
- data/lib/opennebula.rb +1 -1
- data/lib/opennebula/client.rb +3 -1
- data/lib/opennebula/cluster.rb +4 -4
- data/lib/opennebula/document.rb +29 -1
- data/lib/opennebula/group.rb +1 -1
- data/lib/opennebula/host.rb +48 -0
- data/lib/opennebula/host_pool.rb +1 -1
- data/lib/opennebula/image.rb +30 -2
- data/lib/opennebula/ldap_auth.rb +0 -2
- data/lib/opennebula/oneflow_client.rb +0 -1
- data/lib/opennebula/server_cipher_auth.rb +14 -14
- data/lib/opennebula/vdc.rb +1 -1
- data/lib/opennebula/virtual_machine.rb +333 -64
- data/lib/opennebula/virtual_machine_pool.rb +16 -15
- data/lib/opennebula/xml_element.rb +2 -2
- data/lib/opennebula/zone.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4c22ee052b29d751b16a22e9be737f1d4009a4ef
|
4
|
+
data.tar.gz: b882b0d31b1096e5287b47ec799f8f6b88fbcecd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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-
|
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
data/lib/opennebula/client.rb
CHANGED
@@ -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
|
data/lib/opennebula/cluster.rb
CHANGED
@@ -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
|
|
data/lib/opennebula/document.rb
CHANGED
@@ -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
|
#######################################################################
|
data/lib/opennebula/group.rb
CHANGED
data/lib/opennebula/host.rb
CHANGED
@@ -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
|
data/lib/opennebula/host_pool.rb
CHANGED
@@ -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.
|
data/lib/opennebula/image.rb
CHANGED
@@ -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
|
#######################################################################
|
data/lib/opennebula/ldap_auth.rb
CHANGED
@@ -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
|
|
data/lib/opennebula/vdc.rb
CHANGED
@@ -24,38 +24,96 @@ module OpenNebula
|
|
24
24
|
#######################################################################
|
25
25
|
|
26
26
|
VM_METHODS = {
|
27
|
-
:info
|
28
|
-
:allocate
|
29
|
-
:action
|
30
|
-
:migrate
|
31
|
-
:deploy
|
32
|
-
:
|
33
|
-
:
|
34
|
-
:
|
35
|
-
:
|
36
|
-
:
|
37
|
-
:
|
38
|
-
:
|
39
|
-
:
|
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
|
45
|
-
:detachnic
|
46
|
-
: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{
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
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
|
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
|
396
|
-
#
|
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
|
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[:
|
490
|
+
rc = @client.call(VM_METHODS[:disksaveas],
|
407
491
|
@pe_id,
|
408
492
|
disk_id,
|
409
493
|
image_name,
|
410
494
|
image_type,
|
411
|
-
|
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', '
|
473
|
-
#
|
474
|
-
# {
|
475
|
-
#
|
476
|
-
#
|
477
|
-
#
|
478
|
-
#
|
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 [
|
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', '
|
135
|
+
# vm_pool.monitoring( ['MONITORING/CPU', 'MONITORING/NETTX'] )
|
136
136
|
#
|
137
|
-
# {"
|
138
|
-
#
|
139
|
-
#
|
140
|
-
#
|
141
|
-
#
|
142
|
-
# "
|
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
|
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
|
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)
|
data/lib/opennebula/zone.rb
CHANGED
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.
|
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-
|
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:
|
126
|
+
version: 1.3.1
|
127
127
|
requirements: []
|
128
128
|
rubyforge_project:
|
129
129
|
rubygems_version: 2.4.5
|