Statistics
| Branch: | Tag: | Revision:

one / src / sunstone / models / SunstoneServer.rb @ c8df2e9a

History | View | Annotate | Download (10.4 KB)

1
# -------------------------------------------------------------------------- #
2
# Copyright 2002-2011, 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
ONE_LOCATION = ENV["ONE_LOCATION"]
18

    
19
if !ONE_LOCATION
20
    LOG_LOCATION = "/var/log/one"
21
    VAR_LOCATION = "/var/lib/one"
22
    RUBY_LIB_LOCATION = "/usr/lib/one/ruby"
23
else
24
    VAR_LOCATION = ONE_LOCATION+"/var"
25
    LOG_LOCATION = ONE_LOCATION+"/var"
26
    RUBY_LIB_LOCATION = ONE_LOCATION+"/lib/ruby"
27
end
28

    
29
$: << RUBY_LIB_LOCATION
30
$: << File.dirname(__FILE__)
31

    
32
require 'models/OpenNebulaJSON'
33
include OpenNebulaJSON
34

    
35
class SunstoneServer
36
    VNC_PROXY_BASE_PORT = 29876
37

    
38
    def initialize(username, password)
39
        # TBD one_client_user(name) from CloudServer
40
        @client = Client.new("dummy:dummy")
41
        @client.one_auth = "#{username}:#{password}"
42
    end
43

    
44
    ############################################################################
45
    #
46
    ############################################################################
47
    def self.authorize(user="", sha1_pass="")
48
        if user.empty? || sha1_pass.empty?
49
            return [401, false]
50
        end
51

    
52
        # TBD get_user_password(name) from CloudServer
53
        user_pool = UserPool.new(Client.new)
54
        rc = user_pool.info
55
        if OpenNebula.is_error?(rc)
56
            return [500, false]
57
        end
58

    
59
        user_pass = user_pool["USER[NAME=\"#{user}\"]/PASSWORD"]
60
        if user_pass == sha1_pass
61
            return [204, user_pool["USER[NAME=\"#{user}\"]/ID"]]
62
        else
63
            return [401, nil]
64
        end
65
    end
66

    
67
    ############################################################################
68
    #
69
    ############################################################################
70
    def get_pool(kind)
71
        user_flag = -2
72
        pool = case kind
73
            when "cluster" then ClusterPoolJSON.new(@client)
74
            when "host"    then HostPoolJSON.new(@client)
75
            when "image"   then ImagePoolJSON.new(@client, user_flag)
76
            when "vm"      then VirtualMachinePoolJSON.new(@client, user_flag)
77
            when "vnet"    then VirtualNetworkPoolJSON.new(@client, user_flag)
78
            when "user"    then UserPoolJSON.new(@client)
79
            else
80
                error = Error.new("Error: #{kind} resource not supported")
81
                return [404, error.to_json]
82
        end
83

    
84
        rc = pool.info
85
        if OpenNebula.is_error?(rc)
86
            return [500, rc.to_json]
87
        else
88
            return [200, pool.to_json]
89
        end
90
    end
91

    
92
    ############################################################################
93
    #
94
    ############################################################################
95
    def get_resource(kind, id)
96
        resource = retrieve_resource(kind, id)
97
        if OpenNebula.is_error?(resource)
98
            return [404, resource.to_json]
99
        else
100
            return [200, resource.to_json]
101
        end
102
    end
103

    
104
    ############################################################################
105
    #
106
    ############################################################################
107
    def create_resource(kind, template)
108
        resource = case kind
109
            when "cluster" then ClusterJSON.new(Cluster.build_xml, @client)
110
            when "host"    then HostJSON.new(Host.build_xml, @client)
111
            when "image"   then ImageJSON.new(Image.build_xml, @client)
112
            when "vm"      then VirtualMachineJSON.new(VirtualMachine.build_xml,@client)
113
            when "vnet"    then VirtualNetworkJSON.new(VirtualNetwork.build_xml, @client)
114
            when "user"    then UserJSON.new(User.build_xml, @client)
115
            else
116
                error = Error.new("Error: #{kind} resource not supported")
117
                return [404, error.to_json]
118
        end
119

    
120
        rc = resource.create(template)
121
        if OpenNebula.is_error?(rc)
122
            return [500, rc.to_json]
123
        else
124
            resource.info
125
            return [201, resource.to_json]
126
        end
127
    end
128

    
129
    ############################################################################
130
    #
131
    ############################################################################
132
    def delete_resource(kind, id)
133
        resource = retrieve_resource(kind, id)
134
        if OpenNebula.is_error?(resource)
135
            return [404, resource.to_json]
136
        end
137

    
138
        rc = resource.delete
139
        if OpenNebula.is_error?(rc)
140
            return [500, rc.to_json]
141
        else
142
            return [204, resource.to_json]
143
        end
144
    end
145

    
146
    ############################################################################
147
    #
148
    ############################################################################
149
    def perform_action(kind, id, action_json)
150
        resource = retrieve_resource(kind, id)
151
        if OpenNebula.is_error?(resource)
152
            return [404, resource.to_json]
153
        end
154

    
155
        rc = resource.perform_action(action_json)
156
        if OpenNebula.is_error?(rc)
157
            return [500, rc.to_json]
158
        else
159
            return [204, resource.to_json]
160
        end
161
    end
162

    
163
    ############################################################################
164
    #
165
    ############################################################################
166
    def get_configuration(user_id)
167
        if user_id != "0"
168
            return [401, ""]
169
        end
170

    
171
        one_config = VAR_LOCATION + "/config"
172
        config = Hash.new
173

    
174
        begin
175
            cfg = File.read(one_config)
176
        rescue Exception => e
177
            error = Error.new("Error reading config: #{e.inspect}")
178
            return [500, error.to_json]
179
        end
180

    
181
        cfg.lines do |line|
182
            m=line.match(/^([^=]+)=(.*)$/)
183

    
184
            if m
185
                name=m[1].strip.upcase
186
                value=m[2].strip
187
                config[name]=value
188
            end
189
        end
190

    
191
        return [200, config.to_json]
192
    end
193

    
194
    ############################################################################
195
    #
196
    ############################################################################
197
    def get_vm_log(id)
198
        resource = retrieve_resource("vm", id)
199
        if OpenNebula.is_error?(resource)
200
            return [404, nil]
201
        else
202
            if !ONE_LOCATION
203
                vm_log_file = LOG_LOCATION + "/#{id}.log"
204
            else
205
                vm_log_file = LOG_LOCATION + "/#{id}/vm.log"
206
            end
207

    
208
            begin
209
                log = File.read(vm_log_file)
210
            rescue Exception => e
211
                return [200, "Log for VM #{id} not available"]
212
            end
213

    
214
            return [200, log]
215
        end
216
    end
217

    
218

    
219
    ########################################################################
220
    # VNC
221
    ########################################################################
222
    def startvnc(id)
223
        resource = retrieve_resource("vm", id)
224
        if OpenNebula.is_error?(resource)
225
            return [404, resource.to_json]
226
        end
227

    
228
        if resource['LCM_STATE'] != "3"
229
            error = OpenNebula::Error.new("VM is not running")
230
            return [403, error.to_json]
231
        end
232

    
233
        if resource['TEMPLATE/GRAPHICS/TYPE'] != "vnc"
234
            error = OpenNebula::Error.new("VM has no VNC configured")
235
            return [403, error.to_json]
236
        end
237

    
238
        vnc_port = resource['TEMPLATE/GRAPHICS/PORT']
239
        host = resource['HISTORY/HOSTNAME']
240

    
241
        proxy_port = VNC_PROXY_BASE_PORT + vnc_port.to_i
242

    
243
        # puts "Launch noVNC on #{final_port} listenting to #{host}:#{vnc_port}"
244
        # So here we launch the noVNC server listening on the final_port
245
        # and serving as proxy for the VM host on the configured VNC port.
246
        # TODO - This path is in public...
247
        begin
248
            pipe = IO.popen("#{File.dirname(__FILE__)}/../lib/vendor/noVNC/utils/launch.sh --listen #{proxy_port} --vnc #{host}:#{vnc_port}")
249
        rescue Exception => e
250
            error = Error.new(e.message)
251
            return [500, error.to_json]
252
        end
253

    
254
        vnc_pw = resource['TEMPLATE/GRAPHICS/PASSWD']
255

    
256
        info = {:pipe => pipe, :port => proxy_port, :password => vnc_pw}
257
        return [200, info]
258
    end
259

    
260
    ############################################################################
261
    #
262
    ############################################################################
263
    def stopvnc(id,pipe)
264
        resource = retrieve_resource("vm", id)
265
        if OpenNebula.is_error?(resource)
266
            return [404, resource.to_json]
267
        end
268

    
269
        # puts "Killing noVNC with pid #{pid}"
270
        begin
271
            Process.kill('KILL',pipe.pid)
272
            pipe.close
273
        rescue Exception => e
274
            error = Error.new(e.message)
275
            return [500, error.to_json]
276
        end
277

    
278
        return [200, nil]
279
    end
280

    
281

    
282
    private
283

    
284
    def retrieve_resource(kind, id)
285
        resource = case kind
286
            when "cluster" then ClusterJSON.new_with_id(id, @client)
287
            when "host"    then HostJSON.new_with_id(id, @client)
288
            when "image"   then ImageJSON.new_with_id(id, @client)
289
            when "vm"      then VirtualMachineJSON.new_with_id(id, @client)
290
            when "vnet"    then VirtualNetworkJSON.new_with_id(id, @client)
291
            when "user"    then UserJSON.new_with_id(id, @client)
292
            else
293
                error = Error.new("Error: #{kind} resource not supported")
294
                return error
295
        end
296

    
297
        rc = resource.info
298
        if OpenNebula.is_error?(rc)
299
            return rc
300
        else
301
            return resource
302
        end
303
    end
304
end