opennebula 7.0.2 → 7.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. checksums.yaml +4 -4
  2. data/lib/cloud/CloudClient.rb +3 -3
  3. data/lib/models/role.rb +1 -1
  4. data/lib/models/service.rb +1 -1
  5. data/lib/models/vmrole.rb +1 -1
  6. data/lib/models/vrrole.rb +1 -1
  7. data/lib/models.rb +1 -1
  8. data/lib/opennebula/acl.rb +12 -14
  9. data/lib/opennebula/acl_pool.rb +1 -1
  10. data/lib/opennebula/backupjob.rb +1 -1
  11. data/lib/opennebula/backupjob_pool.rb +1 -1
  12. data/lib/opennebula/cluster.rb +1 -1
  13. data/lib/opennebula/cluster_pool.rb +3 -1
  14. data/lib/opennebula/datastore.rb +1 -1
  15. data/lib/opennebula/datastore_pool.rb +3 -1
  16. data/lib/opennebula/document.rb +2 -2
  17. data/lib/opennebula/document_json.rb +2 -1
  18. data/lib/opennebula/document_pool.rb +1 -1
  19. data/lib/opennebula/document_pool_json.rb +3 -1
  20. data/lib/opennebula/error.rb +9 -3
  21. data/lib/opennebula/flow/grammar.rb +1 -1
  22. data/lib/opennebula/flow/service_pool.rb +3 -1
  23. data/lib/opennebula/flow/service_template.rb +2 -1
  24. data/lib/opennebula/flow/service_template_ext.rb +1 -1
  25. data/lib/opennebula/flow/service_template_pool.rb +1 -1
  26. data/lib/opennebula/flow/validator.rb +1 -1
  27. data/lib/opennebula/flow.rb +1 -1
  28. data/lib/opennebula/group.rb +4 -1
  29. data/lib/opennebula/group_pool.rb +3 -1
  30. data/lib/opennebula/grpc/acl_pb.rb +21 -0
  31. data/lib/opennebula/grpc/acl_services_pb.rb +56 -0
  32. data/lib/opennebula/grpc/backupjob_pb.rb +35 -0
  33. data/lib/opennebula/grpc/backupjob_services_pb.rb +70 -0
  34. data/lib/opennebula/grpc/cluster_pb.rb +33 -0
  35. data/lib/opennebula/grpc/cluster_services_pb.rb +38 -0
  36. data/lib/opennebula/grpc/datastore_pb.rb +27 -0
  37. data/lib/opennebula/grpc/datastore_services_pb.rb +62 -0
  38. data/lib/opennebula/grpc/document_pb.rb +29 -0
  39. data/lib/opennebula/grpc/document_services_pb.rb +64 -0
  40. data/lib/opennebula/grpc/group_pb.rb +27 -0
  41. data/lib/opennebula/grpc/group_services_pb.rb +63 -0
  42. data/lib/opennebula/grpc/hook_pb.rb +28 -0
  43. data/lib/opennebula/grpc/hook_services_pb.rb +63 -0
  44. data/lib/opennebula/grpc/host_pb.rb +27 -0
  45. data/lib/opennebula/grpc/host_services_pb.rb +62 -0
  46. data/lib/opennebula/grpc/image_pb.rb +36 -0
  47. data/lib/opennebula/grpc/image_services_pb.rb +71 -0
  48. data/lib/opennebula/grpc/marketplace_pb.rb +29 -0
  49. data/lib/opennebula/grpc/marketplace_services_pb.rb +64 -0
  50. data/lib/opennebula/grpc/marketplaceapp_pb.rb +32 -0
  51. data/lib/opennebula/grpc/marketplaceapp_services_pb.rb +67 -0
  52. data/lib/opennebula/grpc/secgroup_pb.rb +28 -0
  53. data/lib/opennebula/grpc/secgroup_services_pb.rb +63 -0
  54. data/lib/opennebula/grpc/shared_pb.rb +16 -0
  55. data/lib/opennebula/grpc/system_pb.rb +22 -0
  56. data/lib/opennebula/grpc/system_services_pb.rb +57 -0
  57. data/lib/opennebula/grpc/template_pb.rb +30 -0
  58. data/lib/opennebula/grpc/template_services_pb.rb +65 -0
  59. data/lib/opennebula/grpc/user_pb.rb +32 -0
  60. data/lib/opennebula/grpc/user_services_pb.rb +68 -0
  61. data/lib/opennebula/grpc/vdc_pb.rb +34 -0
  62. data/lib/opennebula/grpc/vdc_services_pb.rb +69 -0
  63. data/lib/opennebula/grpc/vm_pb.rb +66 -0
  64. data/lib/opennebula/grpc/vm_services_pb.rb +102 -0
  65. data/lib/opennebula/grpc/vmgroup_pb.rb +31 -0
  66. data/lib/opennebula/grpc/vmgroup_services_pb.rb +66 -0
  67. data/lib/opennebula/grpc/vn_pb.rb +36 -0
  68. data/lib/opennebula/grpc/vn_services_pb.rb +71 -0
  69. data/lib/opennebula/grpc/vntemplate_pb.rb +30 -0
  70. data/lib/opennebula/grpc/vntemplate_services_pb.rb +65 -0
  71. data/lib/opennebula/grpc/vrouter_pb.rb +31 -0
  72. data/lib/opennebula/grpc/vrouter_services_pb.rb +66 -0
  73. data/lib/opennebula/grpc/zone_pb.rb +36 -0
  74. data/lib/opennebula/grpc/zone_services_pb.rb +68 -0
  75. data/lib/opennebula/hook.rb +1 -1
  76. data/lib/opennebula/hook_log.rb +1 -1
  77. data/lib/opennebula/hook_pool.rb +1 -1
  78. data/lib/opennebula/host.rb +3 -1
  79. data/lib/opennebula/host_pool.rb +3 -1
  80. data/lib/opennebula/image.rb +11 -10
  81. data/lib/opennebula/image_pool.rb +1 -1
  82. data/lib/opennebula/ldap_auth.rb +2 -2
  83. data/lib/opennebula/ldap_auth_spec.rb +1 -1
  84. data/lib/opennebula/lockable_ext.rb +13 -24
  85. data/lib/opennebula/marketplace.rb +1 -1
  86. data/lib/opennebula/marketplace_pool.rb +1 -1
  87. data/lib/opennebula/marketplaceapp.rb +1 -1
  88. data/lib/opennebula/marketplaceapp_ext.rb +4 -1
  89. data/lib/opennebula/marketplaceapp_pool.rb +1 -1
  90. data/lib/opennebula/oneflow_client.rb +1 -1
  91. data/lib/opennebula/oneform_client.rb +320 -0
  92. data/lib/opennebula/pool.rb +3 -2
  93. data/lib/opennebula/pool_element.rb +9 -9
  94. data/lib/opennebula/saml_auth.rb +2 -2
  95. data/lib/opennebula/security_group.rb +1 -1
  96. data/lib/opennebula/security_group_pool.rb +1 -1
  97. data/lib/opennebula/server_cipher_auth.rb +1 -1
  98. data/lib/opennebula/server_x509_auth.rb +1 -1
  99. data/lib/opennebula/ssh_auth.rb +1 -1
  100. data/lib/opennebula/system.rb +1 -1
  101. data/lib/opennebula/template.rb +1 -1
  102. data/lib/opennebula/template_ext.rb +1 -1
  103. data/lib/opennebula/template_pool.rb +1 -1
  104. data/lib/opennebula/user.rb +1 -1
  105. data/lib/opennebula/user_pool.rb +2 -1
  106. data/lib/opennebula/utils.rb +1 -1
  107. data/lib/opennebula/vdc.rb +1 -1
  108. data/lib/opennebula/vdc_pool.rb +1 -1
  109. data/lib/opennebula/version.rb +22 -0
  110. data/lib/opennebula/virtual_machine.rb +35 -3
  111. data/lib/opennebula/virtual_machine_ext.rb +3 -1
  112. data/lib/opennebula/virtual_machine_pool.rb +1 -1
  113. data/lib/opennebula/virtual_network.rb +1 -1
  114. data/lib/opennebula/virtual_network_pool.rb +3 -1
  115. data/lib/opennebula/virtual_router.rb +1 -1
  116. data/lib/opennebula/virtual_router_pool.rb +1 -1
  117. data/lib/opennebula/vm_group.rb +1 -1
  118. data/lib/opennebula/vm_group_pool.rb +1 -1
  119. data/lib/opennebula/vntemplate.rb +1 -1
  120. data/lib/opennebula/vntemplate_pool.rb +1 -1
  121. data/lib/opennebula/wait_ext.rb +2 -1
  122. data/lib/opennebula/x509_auth.rb +1 -1
  123. data/lib/opennebula/xml_element.rb +2 -1
  124. data/lib/opennebula/xml_pool.rb +1 -1
  125. data/lib/opennebula/xml_utils.rb +3 -3
  126. data/lib/opennebula/zone.rb +5 -4
  127. data/lib/opennebula/zone_pool.rb +1 -1
  128. data/lib/opennebula.rb +3 -14
  129. metadata +49 -3
  130. data/lib/opennebula/client.rb +0 -228
@@ -0,0 +1,320 @@
1
+ # -------------------------------------------------------------------------- #
2
+ # Copyright 2002-2026, OpenNebula Project, OpenNebula Systems #
3
+ # #
4
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
+ # not use this file except in compliance with the License. You may obtain #
6
+ # a copy of the License at #
7
+ # #
8
+ # http://www.apache.org/licenses/LICENSE-2.0 #
9
+ # #
10
+ # Unless required by applicable law or agreed to in writing, software #
11
+ # distributed under the License is distributed on an "AS IS" BASIS, #
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
13
+ # See the License for the specific language governing permissions and #
14
+ # limitations under the License. #
15
+ #--------------------------------------------------------------------------- #
16
+
17
+ require 'uri'
18
+ require 'base64'
19
+ require 'json'
20
+
21
+ require 'opennebula/form/helpers'
22
+ require 'opennebula/form/drivers'
23
+ require 'opennebula/form/providers'
24
+ require 'opennebula/form/provisions'
25
+ require 'cloud/CloudClient'
26
+
27
+ include CloudCLI
28
+
29
+ module OneForm
30
+
31
+ # OneForm API client
32
+ class Client
33
+
34
+ DEFAULT_OPTIONS = [
35
+ ENDPOINT = {
36
+ :name => 'server',
37
+ :short => '-s url',
38
+ :large => '--server url',
39
+ :format => String,
40
+ :description => 'OneForm endpoint'
41
+ },
42
+ USERNAME={
43
+ :name => 'username',
44
+ :short => '-u name',
45
+ :large => '--username name',
46
+ :format => String,
47
+ :description => 'User name'
48
+ },
49
+ PASSWORD={
50
+ :name => 'password',
51
+ :short => '-p pass',
52
+ :large => '--password pass',
53
+ :format => String,
54
+ :description => 'User password'
55
+ },
56
+ API_VERSION={
57
+ :name => 'api_version',
58
+ :large => '--api-version version',
59
+ :format => String,
60
+ :description => 'OneForm API Version to use'
61
+ }
62
+ ]
63
+
64
+ include OneForm::Drivers
65
+ include OneForm::Providers
66
+ include OneForm::Provisions
67
+
68
+ def initialize(opts = {})
69
+ endpoint = '/.one/oneform_endpoint'
70
+ @username = opts[:username] || ENV['ONEFORM_USER']
71
+ @password = opts[:password] || ENV['ONEFORM_PASSWORD']
72
+
73
+ # By default oneform uses JSON as content type
74
+ @content_type = opts[:content_type] || 'application/json'
75
+
76
+ # Set API version
77
+ @version = opts[:api_version] || ENV['ONEFORM_VERSION'] || 'v1'
78
+
79
+ if opts[:url]
80
+ url = opts[:url]
81
+ elsif ENV['ONEFORM_URL']
82
+ url = ENV['ONEFORM_URL']
83
+ elsif Dir.home && File.exist?(Dir.home + endpoint)
84
+ url = File.read(Dir.home + endpoint).strip
85
+ elsif File.exist?('/var/lib/one/.one/oneform_endpoint')
86
+ url = File.read('/var/lib/one/.one/oneform_endpoint').strip
87
+ else
88
+ url = 'http://localhost:13013'
89
+ end
90
+
91
+ url = url.chomp('/') + "/api/#{@version}"
92
+
93
+ if @username.nil? && @password.nil?
94
+ if Dir.home && !Dir.home.empty? && ENV['ONE_AUTH'] && File.file?(ENV['ONE_AUTH'])
95
+ one_auth = File.read(ENV['ONE_AUTH'])
96
+ elsif Dir.home && File.file?(Dir.home + '/.one/one_auth')
97
+ one_auth = File.read(Dir.home + '/.one/one_auth')
98
+ elsif File.file?('/var/lib/one/.one/one_auth')
99
+ one_auth = File.read('/var/lib/one/.one/one_auth')
100
+ else
101
+ raise 'ONE_AUTH file not present'
102
+ end
103
+
104
+ one_auth = one_auth.rstrip
105
+ @username, @password = one_auth.split(':')
106
+ end
107
+
108
+ @uri = URI.parse(url)
109
+
110
+ @user_agent = "OpenNebula #{CloudClient::VERSION} " <<
111
+ "(#{opts[:user_agent]||'Ruby'})"
112
+
113
+ @host = nil
114
+ @port = nil
115
+
116
+ return unless ENV['http_proxy']
117
+
118
+ uri_proxy = URI.parse(ENV['http_proxy'])
119
+ flag = false
120
+
121
+ #  Check if we need to bypass the proxy
122
+ if ENV['no_proxy']
123
+ ENV['no_proxy'].split(',').each do |item|
124
+ item = item.strip
125
+
126
+ if (IPAddress @uri.host rescue nil).nil?
127
+ if (IPAddress(item) rescue nil).nil?
128
+ flag |= (item == @uri.host)
129
+ end
130
+ else
131
+ unless (IPAddress item rescue nil).nil?
132
+ flag |= IPAddress(item).include? IPAddress(@uri.host)
133
+ end
134
+ end
135
+ end
136
+ end
137
+
138
+ return if flag
139
+
140
+ @host = uri_proxy.host
141
+ @port = uri_proxy.port
142
+ end
143
+
144
+ private
145
+
146
+ def get(path, params = {})
147
+ uri = build_uri(path, params)
148
+ request = Net::HTTP::Proxy(@host, @port)::Get.new(uri, default_headers)
149
+ perform_request(uri, request)
150
+ end
151
+
152
+ def post(path, body = {})
153
+ uri = build_uri(path)
154
+ request = Net::HTTP::Proxy(@host, @port)::Post.new(uri, default_headers)
155
+ request.body = body.is_a?(String) ? body : body.to_json
156
+ perform_request(uri, request)
157
+ end
158
+
159
+ def put(path, body = {})
160
+ uri = build_uri(path)
161
+ request = Net::HTTP::Proxy(@host, @port)::Put.new(uri, default_headers)
162
+ request.body = body.is_a?(String) ? body : body.to_json
163
+ perform_request(uri, request)
164
+ end
165
+
166
+ def patch(path, body = {})
167
+ uri = build_uri(path)
168
+ request = Net::HTTP::Proxy(@host, @port)::Patch.new(uri, default_headers)
169
+ request.body = body.is_a?(String) ? body : body.to_json
170
+ perform_request(uri, request)
171
+ end
172
+
173
+ def delete(path, params = {})
174
+ uri = build_uri(path, params)
175
+ request = Net::HTTP::Proxy(@host, @port)::Delete.new(uri, default_headers)
176
+ perform_request(uri, request)
177
+ end
178
+
179
+ def poll_logs(path, params = {})
180
+ uri = build_uri(path, params)
181
+ request = Net::HTTP::Proxy(@host, @port)::Get.new(uri, default_headers)
182
+
183
+ raw_body = nil
184
+
185
+ Net::HTTP.start(
186
+ uri.host,
187
+ uri.port,
188
+ :use_ssl => (uri.scheme == 'https')
189
+ ) do |http|
190
+ response = http.request(request)
191
+
192
+ raise "Request failed: #{response.code} #{response.message}" \
193
+ unless response.is_a?(Net::HTTPSuccess)
194
+
195
+ raw_body = response.body
196
+ end
197
+
198
+ json =
199
+ begin
200
+ JSON.parse(raw_body)
201
+ rescue JSON::ParserError => e
202
+ raise "Invalid JSON response: #{e.message}"
203
+ end
204
+
205
+ {
206
+ :pos => json['pos'],
207
+ :meta => json['meta'],
208
+ :lines => json['lines'] || []
209
+ }
210
+ end
211
+
212
+ def follow_logs(path, params = {})
213
+ pos = params[:all] ? 0 : nil
214
+ interval = params[:interval] || 1.0
215
+
216
+ loop do
217
+ begin
218
+ response = poll_logs(path, { :pos => pos })
219
+
220
+ response[:lines].each do |entry|
221
+ level = entry['level'] || 'info'
222
+ text = entry['text'] || ''
223
+ puts "[#{level}] #{text}"
224
+ end
225
+
226
+ pos = response[:pos] || pos
227
+ sleep interval
228
+ rescue Interrupt
229
+ break
230
+ rescue StandardError => e
231
+ warn "Polling error: #{e.class}: #{e.message}"
232
+ sleep interval
233
+ end
234
+ end
235
+ end
236
+
237
+ def build_uri(path, params = {})
238
+ uri = @uri.dup
239
+ path = path.sub(%r{^/}, '')
240
+ uri.path = [@uri.path, path].join('/').gsub(%r{/{2,}}, '/')
241
+ uri.query = URI.encode_www_form(params) unless params.empty?
242
+ uri
243
+ end
244
+
245
+ def default_headers
246
+ auth = Base64.strict_encode64("#{@username}:#{@password}")
247
+ {
248
+ 'Authorization' => "Basic #{auth}",
249
+ 'Content-Type' => @content_type,
250
+ 'Accept' => @content_type,
251
+ 'User-Agent' => @user_agent
252
+ }
253
+ end
254
+
255
+ def perform_request(uri, request)
256
+ Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http|
257
+ response = http.request(request)
258
+ handle_response(response)
259
+ end
260
+ end
261
+
262
+ def handle_response(response)
263
+ json = nil
264
+
265
+ begin
266
+ body = response.body && !response.body.strip.empty? ? response.body : '{}'
267
+ json = JSON.parse(body, :symbolize_names => true)
268
+ rescue JSON::ParserError
269
+ raise "OneForm Error: #{body.inspect}"
270
+ end
271
+
272
+ case response
273
+ when Net::HTTPSuccess
274
+ if json.is_a?(Array)
275
+ json.map do |item|
276
+ item.is_a?(Hash) && item.key?(:DOCUMENT) ? item[:DOCUMENT] : item
277
+ end
278
+ elsif json.is_a?(Hash) && json.key?(:DOCUMENT)
279
+ json[:DOCUMENT]
280
+ else
281
+ json
282
+ end
283
+ else
284
+ err_code = json[:err_code] || 'UNKNOWN'
285
+ error_message = json[:message] || 'No message provided'
286
+ err_ctx = json[:context] || {}
287
+
288
+ if err_ctx && !err_ctx.empty?
289
+ context_str = format_context(err_ctx)
290
+
291
+ msg = <<~MSG
292
+ OneForm Error (#{err_code}): #{error_message}
293
+ #{context_str}
294
+ MSG
295
+ else
296
+ msg = "OneForm Error (#{err_code}): #{error_message}"
297
+ end
298
+
299
+ raise msg
300
+ end
301
+ end
302
+
303
+ def format_context(hash, indent = 0, top_level = true)
304
+ prefix = ' ' * indent
305
+
306
+ hash.map do |key, value|
307
+ line_prefix = top_level ? "#{prefix}- " : "#{prefix} "
308
+
309
+ if value.is_a?(Hash)
310
+ nested = format_context(value, indent + 2, false)
311
+ "#{line_prefix}#{key}:\n#{nested}"
312
+ else
313
+ "#{line_prefix}#{key}: #{value}"
314
+ end
315
+ end.join("\n")
316
+ end
317
+
318
+ end
319
+
320
+ end
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2025, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2026, OpenNebula Project, OpenNebula Systems #
3
3
  # #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
5
  # not use this file except in compliance with the License. You may obtain #
@@ -15,6 +15,7 @@
15
15
  #--------------------------------------------------------------------------- #
16
16
 
17
17
  require 'opennebula/xml_utils'
18
+ require 'opennebula/error'
18
19
 
19
20
  module OpenNebula
20
21
 
@@ -259,7 +260,7 @@ module OpenNebula
259
260
  end
260
261
 
261
262
  size = OpenNebula.pool_page_size if (!size || size == 0)
262
- rc = @client.call(method, @user_id, current, -size, state)
263
+ rc = @client.call(method, @user_id, current, -size, state, "")
263
264
 
264
265
  return rc if OpenNebula.is_error?(rc)
265
266
 
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2025, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2026, OpenNebula Project, OpenNebula Systems #
3
3
  # #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
5
  # not use this file except in compliance with the License. You may obtain #
@@ -39,21 +39,21 @@ module OpenNebula
39
39
  end
40
40
 
41
41
  #######################################################################
42
- # Common XML-RPC Methods for all the Pool Element Types
42
+ # Common RPC Methods for all the Pool Element Types
43
43
  #######################################################################
44
44
 
45
45
  # Common client call wrapper. Checks that @pe_id is defined, and
46
46
  # returns nil instead of the response if it is successful
47
47
  #
48
- # @param [String] xml_method xml-rpc method
48
+ # @param [String] rpc_method the name of the RPC method
49
49
  # @param [Array] args any arguments for the xml-rpc method
50
50
  #
51
51
  # @return [nil, OpenNebula::Error] nil in case of success, Error
52
52
  # otherwise
53
- def call(xml_method, *args)
53
+ def call(rpc_method, *args)
54
54
  return Error.new('ID not defined') unless @pe_id
55
55
 
56
- rc = @client.call(xml_method, *args)
56
+ rc = @client.call(rpc_method, *args)
57
57
  rc = nil unless OpenNebula.is_error?(rc)
58
58
 
59
59
  rc
@@ -86,13 +86,13 @@ module OpenNebula
86
86
  # Calls to the corresponding allocate method to create a new element
87
87
  # in the OpenNebula core
88
88
  #
89
- # @param [String] xml_method the name of the XML-RPC method
90
- # @param [Array] args any extra arguments for the xml-rpc method
89
+ # @param [String] rpc_method the name of the RPC method
90
+ # @param [Array] args any extra arguments for the RPC method
91
91
  #
92
92
  # @return [nil, OpenNebula::Error] nil in case of success, Error
93
93
  # otherwise
94
- def allocate(xml_method, *args)
95
- rc = @client.call(xml_method, *args)
94
+ def allocate(rpc_method, *args)
95
+ rc = @client.call(rpc_method, *args)
96
96
 
97
97
  if !OpenNebula.is_error?(rc)
98
98
  @pe_id = rc
@@ -1,5 +1,5 @@
1
1
  # ---------------------------------------------------------------------------- #
2
- # Copyright 2002-2024, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2026, OpenNebula Project, OpenNebula Systems #
3
3
  # #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
5
  # not use this file except in compliance with the License. You may obtain #
@@ -16,7 +16,7 @@
16
16
 
17
17
  require 'rubygems'
18
18
  require 'opennebula/xml_utils'
19
- require 'opennebula/client'
19
+ require 'opennebula/lib/client'
20
20
  require 'opennebula/group_pool'
21
21
  require 'yaml'
22
22
  require 'onelogin/ruby-saml'
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2025, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2026, OpenNebula Project, OpenNebula Systems #
3
3
  # #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
5
  # not use this file except in compliance with the License. You may obtain #
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2025, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2026, OpenNebula Project, OpenNebula Systems #
3
3
  # #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
5
  # not use this file except in compliance with the License. You may obtain #
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2025, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2026, OpenNebula Project, OpenNebula Systems #
3
3
  # #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
5
  # not use this file except in compliance with the License. You may obtain #
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2025, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2026, OpenNebula Project, OpenNebula Systems #
3
3
  # #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
5
  # not use this file except in compliance with the License. You may obtain #
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2025, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2026, OpenNebula Project, OpenNebula Systems #
3
3
  # #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
5
  # not use this file except in compliance with the License. You may obtain #
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2025, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2026, OpenNebula Project, OpenNebula Systems #
3
3
  # #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
5
  # not use this file except in compliance with the License. You may obtain #
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2025, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2026, OpenNebula Project, OpenNebula Systems #
3
3
  # #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
5
  # not use this file except in compliance with the License. You may obtain #
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2025, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2026, OpenNebula Project, OpenNebula Systems #
3
3
  # #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
5
  # not use this file except in compliance with the License. You may obtain #
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2025, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2026, OpenNebula Project, OpenNebula Systems #
3
3
  # #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
5
  # not use this file except in compliance with the License. You may obtain #
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2025, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2026, OpenNebula Project, OpenNebula Systems #
3
3
  # #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
5
  # not use this file except in compliance with the License. You may obtain #
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2025, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2026, OpenNebula Project, OpenNebula Systems #
3
3
  # #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
5
  # not use this file except in compliance with the License. You may obtain #
@@ -38,6 +38,7 @@ module OpenNebula
38
38
 
39
39
  # Factory method to create User objects
40
40
  def factory(element_xml)
41
+ require 'opennebula/user'
41
42
  OpenNebula::User.new(element_xml,@client)
42
43
  end
43
44
 
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2025, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2026, OpenNebula Project, OpenNebula Systems #
3
3
  # #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
5
  # not use this file except in compliance with the License. You may obtain #
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2025, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2026, OpenNebula Project, OpenNebula Systems #
3
3
  # #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
5
  # not use this file except in compliance with the License. You may obtain #
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2025, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2026, OpenNebula Project, OpenNebula Systems #
3
3
  # #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
5
  # not use this file except in compliance with the License. You may obtain #
@@ -0,0 +1,22 @@
1
+ # -------------------------------------------------------------------------- #
2
+ # Copyright 2002-2026, OpenNebula Project, OpenNebula Systems #
3
+ # #
4
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
+ # not use this file except in compliance with the License. You may obtain #
6
+ # a copy of the License at #
7
+ # #
8
+ # http://www.apache.org/licenses/LICENSE-2.0 #
9
+ # #
10
+ # Unless required by applicable law or agreed to in writing, software #
11
+ # distributed under the License is distributed on an "AS IS" BASIS, #
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
13
+ # See the License for the specific language governing permissions and #
14
+ # limitations under the License. #
15
+ #--------------------------------------------------------------------------- #
16
+
17
+ module OpenNebula
18
+
19
+ # OpenNebula version
20
+ VERSION = '7.2.0'
21
+
22
+ end
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2025, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2026, OpenNebula Project, OpenNebula Systems #
3
3
  # #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
5
  # not use this file except in compliance with the License. You may obtain #
@@ -64,7 +64,10 @@ module OpenNebula
64
64
  :backupcancel => 'vm.backupcancel',
65
65
  :attachpci => 'vm.attachpci',
66
66
  :detachpci => 'vm.detachpci',
67
- :restore => 'vm.restore'
67
+ :restore => 'vm.restore',
68
+ :exec => 'vm.exec',
69
+ :retryexec => 'vm.retryexec',
70
+ :cancelexec => 'vm.cancelexec'
68
71
  }
69
72
 
70
73
  VM_STATE=['INIT', 'PENDING', 'HOLD', 'ACTIVE', 'STOPPED', 'SUSPENDED', 'DONE', 'FAILED',
@@ -294,7 +297,10 @@ module OpenNebula
294
297
  'sg-detach',
295
298
  'pci-attach',
296
299
  'pci-detach',
297
- 'restore'
300
+ 'restore',
301
+ 'exec',
302
+ 'exec-retry',
303
+ 'exec-cancel'
298
304
  ]
299
305
 
300
306
  # VirtualMachineDriver constants
@@ -894,6 +900,32 @@ module OpenNebula
894
900
  @client.call(VM_METHODS[:restore], @pe_id, img_id, inc_id, disk_id)
895
901
  end
896
902
 
903
+ # Execute a command in the VM
904
+ #
905
+ # @param cmd [String] Command to be executed
906
+ # @param cmd_stdin [String] Stdin data for the command
907
+ # @return [nil, OpenNebula::Error] nil in case of sucess, Error
908
+ # otherwise.
909
+ def exec(cmd, cmd_stdin)
910
+ @client.call(VM_METHODS[:exec], @pe_id, cmd, cmd_stdin)
911
+ end
912
+
913
+ # Retry the last command executed in the VM
914
+ #
915
+ # @return [nil, OpenNebula::Error] nil in case of sucess, Error
916
+ # otherwise.
917
+ def exec_retry
918
+ @client.call(VM_METHODS[:retryexec], @pe_id)
919
+ end
920
+
921
+ # Cancel the command being executed in the VM
922
+ #
923
+ # @return [nil, OpenNebula::Error] nil in case of sucess, Error
924
+ # otherwise.
925
+ def exec_cancel
926
+ @client.call(VM_METHODS[:cancelexec], @pe_id)
927
+ end
928
+
897
929
  ########################################################################
898
930
  # Helpers to get VirtualMachine information
899
931
  ########################################################################
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2025, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2026, OpenNebula Project, OpenNebula Systems #
3
3
  # #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
5
  # not use this file except in compliance with the License. You may obtain #
@@ -60,6 +60,8 @@ module OpenNebula::VirtualMachineExt
60
60
  'OPENNEBULA_MANAGED', 'PERSISTENT_SNAPSHOTS']
61
61
 
62
62
  def save_as_template(name, desc, opts = {})
63
+ require 'opennebula/template'
64
+
63
65
  opts = {
64
66
  :persistent => false,
65
67
  :poweroff => false,
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2025, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2026, OpenNebula Project, OpenNebula Systems #
3
3
  # #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
5
  # not use this file except in compliance with the License. You may obtain #
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2025, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2026, OpenNebula Project, OpenNebula Systems #
3
3
  # #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
5
  # not use this file except in compliance with the License. You may obtain #