opennebula-oca 3.8.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,436 @@
1
+ # -------------------------------------------------------------------------- #
2
+ # Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) #
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
+
18
+ module OpenNebula
19
+
20
+ begin
21
+ require 'nokogiri'
22
+ NOKOGIRI=true
23
+ rescue LoadError
24
+ NOKOGIRI=false
25
+ end
26
+
27
+ begin
28
+ require 'rexml/formatters/pretty'
29
+ REXML_FORMATTERS=true
30
+ rescue LoadError
31
+ REXML_FORMATTERS=false
32
+ end
33
+
34
+ # The XMLElement class provides an abstraction of the underlying
35
+ # XML parser engine. It provides XML-related methods for the Pool and
36
+ # PoolElement classes
37
+ class XMLElement
38
+
39
+ # xml:: _opaque xml object_ an xml object as returned by build_xml
40
+ def initialize(xml=nil)
41
+ @xml = xml
42
+ end
43
+
44
+ # Initialize a XML document for the element
45
+ # xml:: _String_ the XML document of the object
46
+ # root_element:: _String_ Base xml element
47
+ def initialize_xml(xml, root_element)
48
+ @xml = XMLElement.build_xml(xml, root_element)
49
+
50
+ if OpenNebula.is_error?(@xml)
51
+ @xml = nil
52
+ else
53
+ if NOKOGIRI
54
+ if @xml.size == 0
55
+ @xml = nil
56
+ end
57
+ else
58
+ if @xml.name != root_element
59
+ @xml = nil
60
+ end
61
+ end
62
+ end
63
+ end
64
+
65
+ # Builds a XML document
66
+ # xml:: _String_ the XML document of the object
67
+ # root_element:: _String_ Base xml element
68
+ # [return] _XML_ object for the underlying XML engine
69
+ def self.build_xml(xml, root_element)
70
+ begin
71
+ if NOKOGIRI
72
+ doc = Nokogiri::XML(xml).xpath("/#{root_element}")
73
+ else
74
+ doc = REXML::Document.new(xml).root
75
+ end
76
+ rescue Exception => e
77
+ return OpenNebula::Error.new(e.message)
78
+ end
79
+
80
+ return doc
81
+ end
82
+ # Extract an element from the XML description of the PoolElement.
83
+ # key::_String_ The name of the element
84
+ # [return] _String_ the value of the element
85
+ # Examples:
86
+ # ['VID'] # gets VM id
87
+ # ['HISTORY/HOSTNAME'] # get the hostname from the history
88
+ def [](key)
89
+ if NOKOGIRI
90
+ element=@xml.xpath(key.to_s)
91
+
92
+ return nil if element.size == 0
93
+ else
94
+ element=@xml.elements[key.to_s]
95
+
96
+ return "" if element && !element.has_text?
97
+ end
98
+
99
+ element.text if element
100
+ end
101
+
102
+ # Delete an element from the xml
103
+ # xpath::_String_ xpath expression that selects the elemnts to be deleted
104
+ def delete_element(xpath)
105
+ if NOKOGIRI
106
+ @xml.xpath(xpath.to_s).remove
107
+ else
108
+ @xml.delete_element(xpath.to_s)
109
+ end
110
+ end
111
+
112
+ # Add a new element to the xml
113
+ # xpath::_String_ xpath xpression where the elemente will be added
114
+ # elems::_Hash_ Hash containing the pairs key-value to be included
115
+ # Examples:
116
+ # add_element('VM', 'NEW_ITEM' => 'NEW_VALUE')
117
+ # <VM><NEW_ITEM>NEW_VALUE</NEW_ITEM>...</VM>
118
+ #
119
+ # add_element('VM/TEMPLATE', 'V1' => {'X1' => 'A1', 'Y2' => 'A2'})
120
+ # <VM><TEMPLATE><V1><X1>A1</X1><Y2>A2</Y2>...</TEMPLATE></VM>
121
+ def add_element(xpath, elems)
122
+ elems.each { |key, value|
123
+ if value.instance_of?(Hash)
124
+ if NOKOGIRI
125
+ elem = Nokogiri::XML::Node.new key, @xml.document
126
+ value.each { |k2, v2|
127
+ child = Nokogiri::XML::Node.new k2, elem
128
+ child.content = v2
129
+ elem.add_child(child)
130
+ }
131
+ @xml.xpath(xpath.to_s).first.add_child(elem)
132
+ else
133
+ elem = REXML::Element.new(key)
134
+ value.each { |k2, v2|
135
+ elem.add_element(k2).text = v2
136
+ }
137
+ @xml.elements[xpath].add_element(elem)
138
+ end
139
+ else
140
+ if NOKOGIRI
141
+ elem = Nokogiri::XML::Node.new key, @xml.document
142
+ elem.content = value
143
+ @xml.xpath(xpath.to_s).first.add_child(elem)
144
+ else
145
+ @xml.elements[xpath].add_element(key).text = value
146
+ end
147
+ end
148
+ }
149
+ end
150
+
151
+ # Gets an array of text from elemenets extracted
152
+ # using the XPATH expression passed as filter
153
+ def retrieve_elements(filter)
154
+ elements_array = Array.new
155
+
156
+ if NOKOGIRI
157
+ @xml.xpath(filter.to_s).each { |pelem|
158
+ elements_array << pelem.text if pelem.text
159
+ }
160
+ else
161
+ @xml.elements.each(filter.to_s) { |pelem|
162
+ elements_array << pelem.text if pelem.text
163
+ }
164
+ end
165
+
166
+ if elements_array.size == 0
167
+ return nil
168
+ else
169
+ return elements_array
170
+ end
171
+
172
+ end
173
+
174
+ # Gets an attribute from an elemenT
175
+ # key:: _String_ xpath for the element
176
+ # name:: _String_ name of the attribute
177
+ def attr(key,name)
178
+ value = nil
179
+
180
+ if NOKOGIRI
181
+ element=@xml.xpath(key.to_s.upcase)
182
+ if element.size == 0
183
+ return nil
184
+ end
185
+
186
+ attribute = element.attr(name)
187
+
188
+ value = attribute.text if attribute != nil
189
+ else
190
+ element=@xml.elements[key.to_s.upcase]
191
+
192
+ value = element.attributes[name] if element != nil
193
+ end
194
+
195
+ return value
196
+ end
197
+
198
+ # Iterates over every Element in the XPath and calls the block with a
199
+ # a XMLElement
200
+ # block:: _Block_
201
+ def each(xpath_str,&block)
202
+ if NOKOGIRI
203
+ @xml.xpath(xpath_str).each { |pelem|
204
+ block.call XMLElement.new(pelem)
205
+ }
206
+ else
207
+ @xml.elements.each(xpath_str) { |pelem|
208
+ block.call XMLElement.new(pelem)
209
+ }
210
+ end
211
+ end
212
+
213
+ def each_xpath(xpath_str,&block)
214
+ if NOKOGIRI
215
+ @xml.xpath(xpath_str).each { |pelem|
216
+ block.call pelem.text
217
+ }
218
+ else
219
+ @xml.elements.each(xpath_str) { |pelem|
220
+ block.call pelem.text
221
+ }
222
+ end
223
+ end
224
+
225
+ def name
226
+ @xml.name
227
+ end
228
+
229
+ def text
230
+ if NOKOGIRI
231
+ @xml.content
232
+ else
233
+ @xml.text
234
+ end
235
+ end
236
+
237
+ # Returns wheter there are elements for a given XPath
238
+ # xpath_str:: _String_ XPath expression to locate the element
239
+ def has_elements?(xpath_str)
240
+ if NOKOGIRI
241
+ element = @xml.xpath(xpath_str.to_s.upcase)
242
+ return element != nil && element.children.size > 0
243
+ else
244
+ element = @xml.elements[xpath_str.to_s]
245
+ return element != nil && element.has_elements?
246
+ end
247
+ end
248
+
249
+ # Returns the <TEMPLATE> element in text form
250
+ # indent:: _Boolean_ indents the resulting string, default true
251
+ def template_str(indent=true)
252
+ template_like_str('TEMPLATE', indent)
253
+ end
254
+
255
+ # Returns the <TEMPLATE> element in XML form
256
+ def template_xml
257
+ if NOKOGIRI
258
+ @xml.xpath('TEMPLATE').to_s
259
+ else
260
+ @xml.elements['TEMPLATE'].to_s
261
+ end
262
+ end
263
+
264
+ # Returns the xml of an element
265
+ def element_xml(xpath)
266
+ if NOKOGIRI
267
+ @xml.xpath(xpath).to_s
268
+ else
269
+ @xml.elements[xpath].to_s
270
+ end
271
+ end
272
+
273
+ # Returns elements in text form
274
+ # root_element:: _String_ base element
275
+ # indent:: _Boolean_ indents the resulting string, default true
276
+ # xpath_exp:: _String_ filter elements with a XPath
277
+ def template_like_str(root_element, indent=true, xpath_exp=nil)
278
+ if NOKOGIRI
279
+ xml_template = @xml.xpath(root_element).to_s
280
+ rexml = REXML::Document.new(xml_template).root
281
+ else
282
+ rexml = @xml.elements[root_element]
283
+ end
284
+
285
+ if indent
286
+ ind_enter = "\n"
287
+ ind_tab = ' '
288
+ else
289
+ ind_enter = ''
290
+ ind_tab = ' '
291
+ end
292
+
293
+ str = rexml.elements.collect(xpath_exp) {|n|
294
+ next if n.class != REXML::Element
295
+
296
+ str_line = ""
297
+
298
+ if n.has_elements?
299
+ str_line << "#{n.name}=[#{ind_enter}" << n.collect { |n2|
300
+
301
+ next if n2.class != REXML::Element or !n2.has_text?
302
+
303
+ str = "#{ind_tab}#{n2.name}=#{attr_to_str(n2.text)}"
304
+
305
+ }.compact.join(",#{ind_enter}") << " ]"
306
+ else
307
+ next if !n.has_text?
308
+
309
+ str_line << "#{n.name}=#{attr_to_str(n.text)}"
310
+ end
311
+
312
+ str_line
313
+ }.compact.join("\n")
314
+
315
+ return str
316
+ end
317
+
318
+ #
319
+ #
320
+ #
321
+ def to_xml(pretty=false)
322
+ if NOKOGIRI && pretty
323
+ str = @xml.to_xml
324
+ elsif REXML_FORMATTERS && pretty
325
+ str = String.new
326
+
327
+ formatter = REXML::Formatters::Pretty.new
328
+ formatter.compact = true
329
+
330
+ formatter.write(@xml,str)
331
+ else
332
+ str = @xml.to_s
333
+ end
334
+
335
+ return str
336
+ end
337
+
338
+ # @return [Hash] a hash representing the resource
339
+ def to_hash
340
+ hash = {}
341
+
342
+ if NOKOGIRI
343
+ if @xml.instance_of?(Nokogiri::XML::NodeSet)
344
+ @xml.each { |c|
345
+ if c.element?
346
+ build_hash(hash, c)
347
+ end
348
+ }
349
+ else
350
+ build_hash(hash, @xml)
351
+ end
352
+ else
353
+ build_hash(hash, @xml)
354
+ end
355
+
356
+ hash
357
+ end
358
+
359
+ private
360
+
361
+ #
362
+ #
363
+ #
364
+ def build_hash(hash, element)
365
+ if NOKOGIRI
366
+ array = element.children
367
+ if array.length==1 and (array.first.text? or array.first.cdata?)
368
+ r = array.first.text
369
+ else
370
+ r = {}
371
+ array.each { |c|
372
+ if c.element?
373
+ build_hash(r, c)
374
+ end
375
+ }
376
+ end
377
+ else
378
+ r = {}
379
+ if element.has_elements?
380
+ element.each_element { |c| build_hash(r, c) }
381
+ elsif element.has_text?
382
+ r = element.text
383
+ end
384
+ end
385
+
386
+ key = element.name
387
+ if hash.has_key?(key)
388
+ if hash[key].instance_of?(Array)
389
+ hash[key] << r
390
+ else
391
+ hash[key] = [hash[key], r]
392
+ end
393
+ else
394
+ hash[key] = r
395
+ end
396
+
397
+ hash
398
+ end
399
+
400
+ #
401
+ #
402
+ #
403
+ def attr_to_str(attr)
404
+ attr.gsub!('"',"\\\"")
405
+ attr = "\"#{attr}\""
406
+
407
+ return attr
408
+ end
409
+ end
410
+
411
+ # The XMLUtilsPool module provides an abstraction of the underlying
412
+ # XML parser engine. It provides XML-related methods for the Pools
413
+ class XMLPool < XMLElement
414
+
415
+ def initialize(xml=nil)
416
+ super(xml)
417
+ end
418
+
419
+ #Executes the given block for each element of the Pool
420
+ #block:: _Block_
421
+ def each_element(block)
422
+ if NOKOGIRI
423
+ @xml.xpath(
424
+ "#{@element_name}").each {|pelem|
425
+ block.call self.factory(pelem)
426
+ }
427
+ else
428
+ @xml.elements.each(
429
+ "#{@element_name}") {|pelem|
430
+ block.call self.factory(pelem)
431
+ }
432
+ end
433
+ end
434
+ end
435
+
436
+ end
data/lib/OpenNebula.rb ADDED
@@ -0,0 +1,175 @@
1
+ # -------------------------------------------------------------------------- #
2
+ # Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) #
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
+
18
+ begin # require 'rubygems'
19
+ require 'rubygems'
20
+ rescue Exception
21
+ end
22
+
23
+ require 'xmlrpc/client'
24
+ require 'digest/sha1'
25
+ require 'rexml/document'
26
+ require 'pp'
27
+
28
+ require 'OpenNebula/XMLUtils'
29
+ require 'OpenNebula/VirtualMachine'
30
+ require 'OpenNebula/VirtualMachinePool'
31
+ require 'OpenNebula/VirtualNetwork'
32
+ require 'OpenNebula/VirtualNetworkPool'
33
+ require 'OpenNebula/Image'
34
+ require 'OpenNebula/ImagePool'
35
+ require 'OpenNebula/User'
36
+ require 'OpenNebula/UserPool'
37
+ require 'OpenNebula/Host'
38
+ require 'OpenNebula/HostPool'
39
+ require 'OpenNebula/Template'
40
+ require 'OpenNebula/TemplatePool'
41
+ require 'OpenNebula/Group'
42
+ require 'OpenNebula/GroupPool'
43
+ require 'OpenNebula/Acl'
44
+ require 'OpenNebula/AclPool'
45
+ require 'OpenNebula/Datastore'
46
+ require 'OpenNebula/DatastorePool'
47
+ require 'OpenNebula/Cluster'
48
+ require 'OpenNebula/ClusterPool'
49
+ require 'OpenNebula/Document'
50
+ require 'OpenNebula/DocumentPool'
51
+
52
+ module OpenNebula
53
+
54
+ # OpenNebula version
55
+ VERSION = '3.8.0'
56
+
57
+ # The Error Class represents a generic error in the OpenNebula
58
+ # library. It contains a readable representation of the error.
59
+ # Any function in the OpenNebula module will return an Error
60
+ # object in case of error.
61
+ class Error
62
+ ESUCCESS = 0x0000
63
+ EAUTHENTICATION = 0x0100
64
+ EAUTHORIZATION = 0x0200
65
+ ENO_EXISTS = 0x0400
66
+ EACTION = 0x0800
67
+ EXML_RPC_API = 0x1000
68
+ EINTERNAL = 0x2000
69
+ ENOTDEFINED = 0x1111
70
+
71
+ attr_reader :message, :errno
72
+
73
+ # +message+ Description of the error
74
+ # +errno+ OpenNebula code error
75
+ def initialize(message=nil, errno=0x1111)
76
+ @message = message
77
+ @errno = errno
78
+ end
79
+
80
+ def to_str()
81
+ @message
82
+ end
83
+ end
84
+
85
+ # Returns true if the object returned by a method of the OpenNebula
86
+ # library is an Error
87
+ def self.is_error?(value)
88
+ value.class==OpenNebula::Error
89
+ end
90
+
91
+
92
+ if OpenNebula::NOKOGIRI
93
+ class NokogiriStreamParser < XMLRPC::XMLParser::AbstractStreamParser
94
+ def initialize
95
+ @parser_class = NokogiriParser
96
+ end
97
+
98
+ class NokogiriParser < Nokogiri::XML::SAX::Document
99
+ include XMLRPC::XMLParser::StreamParserMixin
100
+
101
+ alias :cdata_block :character
102
+ alias :characters :character
103
+ alias :end_element :endElement
104
+ alias :start_element :startElement
105
+
106
+ def parse(str)
107
+ parser = Nokogiri::XML::SAX::Parser.new(self)
108
+ parser.parse(str)
109
+ end
110
+ end
111
+ end
112
+ end
113
+
114
+
115
+ # The client class, represents the connection with the core and handles the
116
+ # xml-rpc calls.
117
+ class Client
118
+ attr_accessor :one_auth
119
+
120
+ begin
121
+ require 'xmlparser'
122
+ XMLPARSER=true
123
+ rescue LoadError
124
+ XMLPARSER=false
125
+ end
126
+
127
+ def initialize(secret=nil, endpoint=nil)
128
+ if secret
129
+ @one_auth = secret
130
+ elsif ENV["ONE_AUTH"] and !ENV["ONE_AUTH"].empty? and File.file?(ENV["ONE_AUTH"])
131
+ @one_auth = File.read(ENV["ONE_AUTH"])
132
+ elsif File.file?(ENV["HOME"]+"/.one/one_auth")
133
+ @one_auth = File.read(ENV["HOME"]+"/.one/one_auth")
134
+ else
135
+ raise "ONE_AUTH file not present"
136
+ end
137
+
138
+ @one_auth.rstrip!
139
+
140
+ if endpoint
141
+ @one_endpoint = endpoint
142
+ elsif ENV["ONE_XMLRPC"]
143
+ @one_endpoint = ENV["ONE_XMLRPC"]
144
+ else
145
+ @one_endpoint = "http://localhost:2633/RPC2"
146
+ end
147
+
148
+ @server = XMLRPC::Client.new2(@one_endpoint)
149
+
150
+ if OpenNebula::NOKOGIRI
151
+ @server.set_parser(NokogiriStreamParser.new)
152
+ elsif XMLPARSER
153
+ @server.set_parser(XMLRPC::XMLParser::XMLStreamParser.new)
154
+ end
155
+ end
156
+
157
+ def call(action, *args)
158
+ begin
159
+ response = @server.call_async("one."+action, @one_auth, *args)
160
+
161
+ if response[0] == false
162
+ Error.new(response[1], response[2])
163
+ else
164
+ response[1] #response[1..-1]
165
+ end
166
+ rescue Exception => e
167
+ Error.new(e.message)
168
+ end
169
+ end
170
+
171
+ def get_version()
172
+ call("system.version")
173
+ end
174
+ end
175
+ end
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: opennebula-oca
3
+ version: !ruby/object:Gem::Version
4
+ version: 3.8.0.beta1
5
+ prerelease: 6
6
+ platform: ruby
7
+ authors:
8
+ - OpenNebula
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-10-30 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: nokogiri
16
+ requirement: &2152558860 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *2152558860
25
+ - !ruby/object:Gem::Dependency
26
+ name: json
27
+ requirement: &2152557640 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *2152557640
36
+ description: Libraries needed to talk to OpenNebula
37
+ email: contact@opennebula.org
38
+ executables: []
39
+ extensions: []
40
+ extra_rdoc_files: []
41
+ files:
42
+ - lib/OpenNebula.rb
43
+ - lib/OpenNebula/Acl.rb
44
+ - lib/OpenNebula/AclPool.rb
45
+ - lib/OpenNebula/Cluster.rb
46
+ - lib/OpenNebula/ClusterPool.rb
47
+ - lib/OpenNebula/Datastore.rb
48
+ - lib/OpenNebula/DatastorePool.rb
49
+ - lib/OpenNebula/Document.rb
50
+ - lib/OpenNebula/DocumentJSON.rb
51
+ - lib/OpenNebula/DocumentPool.rb
52
+ - lib/OpenNebula/DocumentPoolJSON.rb
53
+ - lib/OpenNebula/Group.rb
54
+ - lib/OpenNebula/GroupPool.rb
55
+ - lib/OpenNebula/Host.rb
56
+ - lib/OpenNebula/HostPool.rb
57
+ - lib/OpenNebula/Image.rb
58
+ - lib/OpenNebula/ImagePool.rb
59
+ - lib/OpenNebula/Pool.rb
60
+ - lib/OpenNebula/Template.rb
61
+ - lib/OpenNebula/TemplatePool.rb
62
+ - lib/OpenNebula/User.rb
63
+ - lib/OpenNebula/UserPool.rb
64
+ - lib/OpenNebula/VirtualMachine.rb
65
+ - lib/OpenNebula/VirtualMachinePool.rb
66
+ - lib/OpenNebula/VirtualNetwork.rb
67
+ - lib/OpenNebula/VirtualNetworkPool.rb
68
+ - lib/OpenNebula/XMLUtils.rb
69
+ homepage: http://opennebula.org
70
+ licenses: []
71
+ post_install_message:
72
+ rdoc_options: []
73
+ require_paths:
74
+ - lib
75
+ required_ruby_version: !ruby/object:Gem::Requirement
76
+ none: false
77
+ requirements:
78
+ - - ! '>='
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ required_rubygems_version: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ! '>'
85
+ - !ruby/object:Gem::Version
86
+ version: 1.3.1
87
+ requirements: []
88
+ rubyforge_project:
89
+ rubygems_version: 1.8.15
90
+ signing_key:
91
+ specification_version: 3
92
+ summary: OpenNebula Client API
93
+ test_files: []
94
+ has_rdoc: