Revision 6509e422

View differences:

src/sunstone/models/OpenNebulaJSON/VirtualMachineJSON.rb
17 17
require 'OpenNebulaJSON/JSONUtils'
18 18

  
19 19
module OpenNebulaJSON
20

  
20 21
    class VirtualMachineJSON < OpenNebula::VirtualMachine
21 22
        include JSONUtils
22 23

  
......
56 57
                when "saveas"       then self.save_as(action_hash['params'])
57 58
                when "shutdown"     then self.shutdown
58 59
                when "resubmit"     then self.resubmit
59
                when "startvnc"     then self.startvnc
60
                when "stopvnc"      then self.stopvnc
61 60
                else
62 61
                    error_msg = "#{action_hash['perform']} action not " <<
63 62
                                " available for this resource"
......
120 119

  
121 120
            super(params['disk_id'].to_i, image.id)
122 121
        end
123
        
124
        def startvnc(port)
125
            result = self.info();
126
            if OpenNebula.is_error?(result)
127
                return result
128
            end
129
            
130
            if self['LCM_STATE'] != "3"
131
                return OpenNebula::Error.new("VM is not running");
132
            end
133
            
134
            if self['TEMPLATE/GRAPHICS/TYPE'] != "vnc"
135
                return OpenNebula::Error.new("VM has no VNC configured");
136
            end
137
                      
138
            if self['TEMPLATE/GRAPHICS/PORT']
139
                vnc_port = self['TEMPLATE/GRAPHICS/PORT']
140
            else
141
                return OpenNebula::Error.new("VM has no VNC port set");
142
            end
143
            
144
            if self['TEMPLATE/GRAPHICS/PASSWD']
145
                vnc_pw = self['TEMPLATE/GRAPHICS/PASSWD']
146
            else
147
                vnc_pw = ""
148
            end
149
            
150
            host = self['HISTORY/HOSTNAME']
151
            
152
            #we are ready for the party
153
            
154
            final_port = 29876+port.to_i;
155
            
156
            # puts "Launch noVNC on #{final_port} listenting to #{host}:#{vnc_port}"
157
            # So here we launch the noVNC server listening on the final_port 
158
            # and serving as proxy for the VM host on the configured VNC port.
159
            # TODO - This path is in public...            
160
            pipe = IO.popen("#{File.dirname(__FILE__)}/../../public/vendor/noVNC/utils/launch.sh --listen #{final_port} --vnc #{host}:#{vnc_port}")
161
            
162
            return {:pipe => pipe, :port => final_port, :password => vnc_pw}
163
            
164
        end
165
        
166
        def stopvnc(pipe)
167
            #am I allowed to do something affecting this machine?
168
            result = self.info();
169
            if OpenNebula.is_error?(result)
170
                return result
171
            end
172
            pid = pipe.pid
173
            # puts "Killing noVNC with pid #{pid}"
174
            Process.kill('KILL',pid)
175
            pipe.close
176
            return
177
        end
178
        
179 122
    end
180 123
end
src/sunstone/models/SunstoneServer.rb
33 33
include OpenNebulaJSON
34 34

  
35 35
class SunstoneServer
36
    VNC_PROXY_BASE_PORT = 29876
37

  
36 38
    def initialize(username, password)
37 39
        # TBD one_client_user(name) from CloudServer
38 40
        @client = Client.new("dummy:dummy")
......
219 221
    ########################################################################
220 222

  
221 223
    def startvnc(id)
222
        rc = retrieve_resource("vm", id)
223
        if OpenNebula.is_error?(rc)
224
            return rc
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]
225 253
        end
226
        return rc.startvnc(id)
254

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

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

  
229 261
    def stopvnc(id,pipe)
230
       rc = retrieve_resource("vm", id)
231
       if OpenNebula.is_error?(rc)
232
           return rc
233
       end
234
       return rc.stopvnc(pipe)
235
       
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]
236 277
    end
237 278

  
238 279

  
src/sunstone/public/js/plugins/vms-tab.js
2044 2044
        $('#vnc_dialog').attr("vm_id",id);
2045 2045
        //Request proxy server start
2046 2046
        Sunstone.runAction("VM.startvnc",id);
2047
        return false;
2047 2048
    });
2048 2049

  
2049 2050
}
src/sunstone/sunstone-server.rb
164 164
end
165 165

  
166 166
post '/vm/:id/stopvnc' do
167
    vm = params[:id]
167
    vm_id = params[:id]
168 168
    vnc_hash = session['vnc']
169
    
170
    if !vnc_hash
171
        msg = "Ups, no VNC sessions information found. Cannot stop VNC"
172
        return [500, OpenNebula::Error.new(msg).to_json]
173
    elsif !vnc_hash[vm]
169

  
170
    if !vnc_hash || !vnc_hash[vm_id]
174 171
        msg = "It seems there is no VNC proxy running for this machine"
175
        return [500, OpenNebula::Error.new(msg).to_json]
172
        return [403, OpenNebula::Error.new(msg).to_json]
176 173
    end
177
    
178
    pipe = session['vnc'][vm]
179
    rc = @SunstoneServer.stopvnc(vm,pipe)
180
    
181
    if (OpenNebula.is_error?(rc))
182
        return [500, rc.to_json]
183
    else
184
        session['vnc'].delete(vm)
185
        return    
174

  
175
    rc = @SunstoneServer.stopvnc(vm_id, vnc_hash[vm_id])
176
    if rc[0] == 200
177
        session['vnc'].delete(vm_id)
186 178
    end
187
    
179

  
180
    rc
188 181
end
189 182

  
190 183
post '/vm/:id/startvnc' do
191
    vm = params[:id]
192
    info = @SunstoneServer.startvnc(vm)
193
    
194
    if OpenNebula.is_error?(info)
195
        return [500,info.to_json]
196
    end
197
    
198
    port = info[:port] #port to connect to
199
    pw = info[:password]
200
    pipe = info[:pipe]
201
    
184
    vm_id = params[:id]
185

  
202 186
    vnc_hash = session['vnc']
203
    
204
    if !vnc_hash 
187

  
188
    if !vnc_hash
205 189
        session['vnc']= {}
206
    elsif vnc_hash and vnc_hash[vm]
207
        return [500, OpenNebula::Error.new("There is a VNC server running for this VM").to_json]
190
    elsif vnc_hash[vm_id]
191
        msg = "There is a VNC server running for this VM"
192
        return [403, OpenNebula::Error.new(msg).to_json]
193
    end
194

  
195
    rc = @SunstoneServer.startvnc(vm_id)
196
    if rc[0] == 200
197
        info = rc[1]
198
        session['vnc'][vm_id] = info[:pipe]
199
        info.delete(:pipe)
200

  
201
        [200, info.to_json]
202
    else
203
        rc
208 204
    end
209
    
210
    session['vnc'][vm]=pipe;
211
    return {:port => port, :password => pw }.to_json
212
    
213 205
end
214 206

  
215 207
##############################################################################

Also available in: Unified diff