Statistics
| Branch: | Tag: | Revision:

one / src / oca / ruby / opennebula / client.rb @ b7928543

History | View | Annotate | Download (7.88 KB)

1
# -------------------------------------------------------------------------- #
2
# Copyright 2002-2017, 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 'xmlrpc/client'
18
require 'bigdecimal'
19
require 'stringio'
20
require 'openssl'
21

    
22

    
23
module OpenNebula
24
    def self.pool_page_size
25
        @@pool_page_size
26
    end
27

    
28
    if OpenNebula::OX
29
        class OxStreamParser < XMLRPC::XMLParser::AbstractStreamParser
30
            def initialize
31
                @parser_class = OxParser
32
            end
33

    
34
            class OxParser < Ox::Sax
35
                include XMLRPC::XMLParser::StreamParserMixin
36

    
37
                alias :text :character
38
                alias :end_element :endElement
39
                alias :start_element :startElement
40

    
41
                def parse(str)
42

    
43
                    Ox.sax_parse(self, StringIO.new(str),
44
                        :symbolize => false,
45
                        :convert_special => true,
46
                        :skip => false)
47
                end
48
            end
49
        end
50
    elsif OpenNebula::NOKOGIRI
51
        class NokogiriStreamParser < XMLRPC::XMLParser::AbstractStreamParser
52
            def initialize
53
                @parser_class = NokogiriParser
54
            end
55

    
56
            class NokogiriParser < Nokogiri::XML::SAX::Document
57
                include XMLRPC::XMLParser::StreamParserMixin
58

    
59
                alias :cdata_block :character
60
                alias :characters :character
61
                alias :end_element :endElement
62
                alias :start_element :startElement
63

    
64
                def parse(str)
65
                    parser = Nokogiri::XML::SAX::Parser.new(self)
66
                    parser.parse(str)
67
                end
68
            end
69
        end
70
    end
71

    
72
    DEFAULT_POOL_PAGE_SIZE = 2000
73

    
74
    if size=ENV['ONE_POOL_PAGE_SIZE']
75
        if size.strip.match(/^\d+$/) && size.to_i >= 2
76
            @@pool_page_size = size.to_i
77
        else
78
            @@pool_page_size = nil
79
        end
80
    else
81
        @@pool_page_size = DEFAULT_POOL_PAGE_SIZE
82
    end
83

    
84

    
85
    # The client class, represents the connection with the core and handles the
86
    # xml-rpc calls.
87
    class Client
88
        attr_accessor :one_auth
89
        attr_reader   :one_endpoint
90

    
91
        begin
92
            require 'xmlparser'
93
            XMLPARSER=true
94
        rescue LoadError
95
            XMLPARSER=false
96
        end
97

    
98
        # Creates a new client object that will be used to call OpenNebula
99
        # functions.
100
        #
101
        # @param [String, nil] secret user credentials ("user:password") or
102
        #   nil to get the credentials from user auth file
103
        # @param [String, nil] endpoint OpenNebula server endpoint
104
        #   (http://host:2633/RPC2) or nil to get it form the environment
105
        #   variable ONE_XMLRPC or use the default endpoint
106
        # @param [Hash] options
107
        # @option params [Integer] :timeout connection timeout in seconds,
108
        #   defaults to 30
109
        # @option params [String] :http_proxy HTTP proxy string used for
110
        #  connecting to the endpoint; defaults to no proxy
111
        # @option params [Boolean] :sync Use only one http connection for
112
        #  all calls. It should not be used for multithreaded programs.
113
        #  It's the only mode that can be used with :cert_dir and
114
        #  :disable_ssl_verify
115
        # @option params [String] :cert_dir Extra directory where to import
116
        #  trusted issuer certificates. Use with :sync = true
117
        # @option params [String] :disable_ssl_verify Disable SSL certificate
118
        #  verification. Use only for testing and with :sync = true
119
        #
120
        # @return [OpenNebula::Client]
121
        def initialize(secret=nil, endpoint=nil, options={})
122
            if secret
123
                @one_auth = secret
124
            elsif ENV["ONE_AUTH"] and !ENV["ONE_AUTH"].empty? and
125
                    File.file?(ENV["ONE_AUTH"])
126
                @one_auth = File.read(ENV["ONE_AUTH"])
127
            elsif ENV["HOME"] and File.file?(ENV["HOME"]+"/.one/one_auth")
128
                @one_auth = File.read(ENV["HOME"]+"/.one/one_auth")
129
            elsif File.file?("/var/lib/one/.one/one_auth")
130
                @one_auth = File.read("/var/lib/one/.one/one_auth")
131
            else
132
                raise "ONE_AUTH file not present"
133
            end
134

    
135
            @one_auth = @one_auth.rstrip
136

    
137
            if endpoint
138
                @one_endpoint = endpoint
139
            elsif ENV["ONE_XMLRPC"]
140
                @one_endpoint = ENV["ONE_XMLRPC"]
141
            elsif ENV['HOME'] and File.exists?(ENV['HOME']+"/.one/one_endpoint")
142
                @one_endpoint = File.read(ENV['HOME']+"/.one/one_endpoint")
143
            elsif File.exists?("/var/lib/one/.one/one_endpoint")
144
                @one_endpoint = File.read("/var/lib/one/.one/one_endpoint")
145
            else
146
                @one_endpoint = "http://localhost:2633/RPC2"
147
            end
148

    
149
            @one_endpoint= @one_endpoint.rstrip
150

    
151
            @async = !options[:sync]
152

    
153
            timeout=nil
154
            timeout=options[:timeout] if options[:timeout]
155

    
156
            http_proxy=nil
157
            http_proxy=options[:http_proxy] if options[:http_proxy]
158

    
159
            @server = XMLRPC::Client.new2(@one_endpoint, http_proxy, timeout)
160
            @server.http_header_extra = {'accept-encoding' => 'identity'}
161

    
162
            http = @server.instance_variable_get("@http")
163

    
164
            if options[:cert_dir] || ENV['ONE_CERT_DIR']
165
                raise "SSL options don't work in async mode" if @async
166

    
167
                cert_dir = options[:cert_dir] || ENV['ONE_CERT_DIR']
168
                cert_files = Dir["#{cert_dir}/*"]
169

    
170
                cert_store = OpenSSL::X509::Store.new
171
                cert_store.set_default_paths
172
                cert_files.each {|cert| cert_store.add_file(cert) }
173

    
174
                http.cert_store = cert_store
175
            end
176

    
177
            if options[:disable_ssl_verify] || ENV['ONE_DISABLE_SSL_VERIFY']
178
                raise "SSL options don't work in async mode" if @async
179

    
180
                http.verify_mode = OpenSSL::SSL::VERIFY_NONE
181
            end
182

    
183
            if defined?(OxStreamParser)
184
                @server.set_parser(OxStreamParser.new)
185
            elsif OpenNebula::NOKOGIRI
186
                @server.set_parser(NokogiriStreamParser.new)
187
            elsif XMLPARSER
188
                @server.set_parser(XMLRPC::XMLParser::XMLStreamParser.new)
189
            end
190
        end
191

    
192
        def call(action, *args)
193
            begin
194
                if @async
195
                    response = @server.call_async("one."+action, @one_auth, *args)
196
                else
197
                    response = @server.call("one."+action, @one_auth, *args)
198
                end
199

    
200
                if response[0] == false
201
                    Error.new(response[1], response[2])
202
                else
203
                    response[1] #response[1..-1]
204
                end
205
            rescue Exception => e
206
                Error.new(e.message, Error::EXML_RPC_CALL)
207
            end
208
        end
209

    
210
        def get_version()
211
            call("system.version")
212
        end
213
    end
214
end