Statistics
| Branch: | Tag: | Revision:

one / src / sunstone / models / SunstoneServer.rb @ 6509e422

History | View | Annotate | Download (10.2 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

    
223
    def startvnc(id)
224
        resource = retrieve_resource("vm", id)
225
        if OpenNebula.is_error?(resource)
226
            return [404, resource.to_json]
227
        end
228

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

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

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

    
242
        proxy_port = VNC_PROXY_BASE_PORT + vnc_port.to_i
243

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

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

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

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

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

    
276
        return [200, nil]
277
    end
278

    
279

    
280
    private
281

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

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