Project

General

Profile

Download (38 KB) Statistics
| Branch: | Revision:
1
define([
2
"dojo/_base/connect",
3
'dojo/on',
4
'dojo/dom',
5
'dojo/dom-construct',
6
'steam2/models/Server',
7
'steam2/statusColorMap',
8
'steam2/user',
9
'stabile/grid',
10
'stabile/stores',
11
'stabile/formatters',
12
'helpers/uuid',
13
'dojox/grid/cells/_base',
14
'dojo/string',
15
'dijit/form/Button',
16
'dijit/layout/BorderContainer',
17
'dijit/form/NumberSpinner'
18

    
19
], function(connect, on, dom, domConstruct, Server, statusColorMap, user, grid, stores){
20

    
21
    var guacFormatter = function (item) {
22
        if (item.status != "shutoff" && item.status != "inactive" && item.display == "vnc") {
23
            var guac = "<button type=\"button\" title=\"console\" class=\"action_button console_icon\" " +
24
"onclick=\"steam2.models.Server.doAction(arguments[0], '" + item.uuid + "','start_html5_vnc_viewer');return false;" +
25
                //    "onclick=\"w = window.open('/guacamole/?uuid=" + item.uuid + "', '" + item.uuid + "'" +
26
                //    ",'" + "menubar=no,status=no,toolbar=no,addressbar=no,location=no,titlebar=no')" +
27
                //    "); w.focus(); return false;" +
28
                    "\"><span>console</span></button>";
29
            return guac;
30
        } else {
31
            return "";
32
        }
33
    };
34

    
35
    var servers = {
36

    
37
        grid : {},
38
        _searchQuery: "name:*",
39
        _statusQuery: "status:all",
40
        _inited: false,
41
        storeQuery: "name:*",
42
        model : function(args){
43
            return dojo.mixin({
44
                uuid: Math.uuid().toLowerCase(),
45
                name: "",
46
                user: user.username,
47
                memory: "2048",
48
                vcpu: "1",
49
                image: "",
50
                image2: "",
51
                diskbus: "virtio",
52
                cdrom: "--",
53
                boot: "hd",
54
                networkuuid1: "--",
55
                nicmodel1: "virtio",
56
                //nicmodel1: "rtl8139",
57
                networkuuid2: "--",
58
               // nicmodel2: ["rtl8139"],
59
                status: "new",
60
                mac: "",
61
                port: 0
62
            }, args || {});
63
        },
64

    
65
        // TODO: refactor should be on the model!
66
        isPowered: function(item){
67
            switch(item.status){
68
            case "shutoff":
69
            case "new":
70
            case "inactive":
71
            case "crashed":
72
            case "destroying":
73
                return false;
74
            case "starting":
75
                if(item.port && item.port){
76
                    return true;
77
                }
78
                // vnc is not ready here
79
                return false;
80
            default:
81
                return true;
82
            }
83
        },
84

    
85
        /** object name - for reflective lookup */
86
        name : "servers",
87
        store : null,
88
        sortInfo: 3,
89
        structure : [
90
            {
91
                field: '_item',
92
                name: ' ',
93
                width: '30px',
94
                steamid: 'console',
95
                formatter: guacFormatter,
96
                hidden: user.is_readonly
97
            },
98
            {
99
                field: 'name',
100
                name: 'Name',
101
                width: 'auto'
102
            },
103
            {
104
                field: 'status',
105
                name: 'Status <a href="https://www.origo.io/info/stabiledocs/web/servers/status" rel="help" target="_blank" class="irigo-tooltip">help</a>',
106
                width: '100px',
107
                formatter: function(val, rowIdx, cell) {
108
                    var t = '<span style="color:${color}">${val}</span>';
109
                    var color = statusColorMap.get(val);
110
//                    if(val != "inactive" && user.is_admin){
111
                    if(user.is_admin){
112
                        var store = this.grid.store;
113
                        var item = this.grid.getItem(rowIdx);
114
                        if (store.getValue(item, 'macname') && store.getValue(item, 'macname')!="--") {
115
                            val += " on " + store.getValue(item, 'macname');
116
                        }
117
                    }
118
                    return dojo.string.substitute(t, { color: color, val: val });
119
                }
120
            },
121
            {
122
                field: 'memory',
123
                name: 'Mem (MB)',
124
                width: '64px',
125
                cellStyles: "text-align:right;",
126
                type: dojox.grid.cells.Select,
127
                options: ["256", "512", "1024", "2048", "4096", "8192", "16384", "32768", "49152", "65536"]
128
            },
129
            {
130
                field: 'vcpu',
131
                name: 'VCPUs',
132
                width: '48px',
133
                cellStyles: "text-align:right;",
134
                // editable:true,
135
                type: dojox.grid.cells.Select,
136
                options: ["1","2","3","4","8"]
137
                },
138
            {
139
                field: 'imagename',
140
                name: 'Image',
141
                width: 'auto' },
142
            {
143
                field: 'imagetype',
144
                name: 'Type',
145
                width: '40px'
146
            },
147
            //        { field: 'diskbus', name: 'Bus', width: '40px',
148
            // editable: true,
149
            //            type: dojox.grid.cells.Select,
150
            //            options: ["ide", "scsi"]
151
            //        },
152
            {
153
                field: 'networkname1',
154
                name: 'Connection',
155
                width: '140px'
156
            },
157
            {
158
                field: 'action',
159
                name: 'Action <a href="https://www.origo.io/info/stabiledocs/web/servers/server-actions" rel="help" target="_blank" class="irigo-tooltip">help</a>',
160
                width: 'auto',
161
                formatter: function(val, rowIdx, cell) {
162
                    var item = this.grid.getItem(rowIdx);
163
                    return servers.getActionButtons(item);
164
                },
165
                hidden: user.is_readonly
166
            }
167
        ],
168

    
169
        dialogStructure : [
170
            {
171
                field:"name",
172
                name: "Name",
173
                type:"dijit.form.ValidationTextBox",
174
                //attrs: {regExp: "[\\s\\w.-]+", required:true}
175
//                attrs: {regExp: ".+", required:true, readonly: (user.is_readonly?"readonly":false)}
176
                attrs: {regExp: ".+", required:false}
177
            },
178
            {
179
                field: "status",
180
                name: "Status",
181
                type: "dijit.form.TextBox",
182
                attrs: {readonly:"readonly"}
183
            },
184
            {
185
                field: "uuid",
186
                name: "UUID",
187
                type: "dijit.form.TextBox",
188
                attrs: {readonly:"readonly"}
189
            },
190
            // hmm. dijit.form.Select doesn't do any selection on the value from the item???
191
            // Apparently the values must be of type string to do that.
192
            // It works with filtering select
193
            {
194
                field:"memory",
195
                name: "Memory",
196
                type: "dijit.form.FilteringSelect",
197
                style: "width: 55px;",
198
                attrs: { store: "stores.memory", searchAttr:"memory" }
199
            },
200
            {
201
                field:"vcpu",
202
                name: "VCPUs",
203
                type:"dijit.form.NumberSpinner",
204
                style: "width: 55px;",
205
                attrs:{ smallDelta:"1", constraints: "{min:1,max:8,places:0}"}
206
            },
207
            {
208
                field:"diskbus",
209
                name:"Bus",
210
                type: "dijit.form.Select",
211
                attrs:{ store: "stores.diskbus", searchAttr:"type" }
212
            },
213
            {
214
                field:"cdrom",
215
                name:"CD-rom",
216
                type: "dijit.form.FilteringSelect",
217
                extra: function(item){
218
                    return '<button type="button" id="mount_button" class="btn btn-xs btn-info" onclick="servers.mount()" style="font-size:80%; display:none;">Mount</button>';
219
                },
220
                attrs:{
221
                    store: "stores.cdroms", searchAttr:"name",
222
                    onChange: "if ((this.value != servers.grid.dialog.item.cdrom || this.value=='--') && servers.grid.dialog.item.status=='running') {" +
223
                            "$('#mount_button').text((this.value=='--')?'Unmount':'Mount').show(); }" +
224
                            "else {$('#mount_button').hide();};"
225
                }
226
            },
227
            {
228
                field:"boot",
229
                name:"Boot",
230
                type: "dijit.form.Select",
231
                attrs:{store: "stores.bootDevices", searchAttr:"name"}
232
            },
233
            {
234
                field: "user",
235
                name: "User",
236
                type: "dijit.form.FilteringSelect",
237
                attrs: {
238
                    store: "stores.accounts",
239
                    searchAttr: "id",
240
                    required:"true",
241
                    query: "{privileges: /(a|u)/}"
242
//                    onChange: "stores.accounts.fetch({query: {privileges:'*m*'}}); stores.accounts.close();"
243
                }
244
            },
245
            {
246
                field:"mac",
247
                name:'<span id="serverDialogNodeDialogLink">Node</span>',
248
                type: "dijit.form.FilteringSelect",
249
                restricted: true,
250
                extra: function(item){
251
                    return '<button type="button" id="move_button" class="btn btn-xs btn-info" onclick="servers.move()" style="font-size:80%; display:none;">Move</button>';
252
                },
253
                attrs:{
254
                    store: "stores.nodes", searchAttr:"name", required: false,
255
                    onChange: "if (this.value != servers.grid.dialog.item.mac && servers.grid.dialog.item.status=='running')" +
256
                            "   $('#move_button').show();" +
257
                            " else $('#move_button').hide();"
258
                }
259
            },
260
            {
261
                field: "locktonode",
262
                name:"Lock to node",
263
                type: "dijit.form.CheckBox",
264
                restricted: true,
265
                attrs:{onchange: "this.value=this.checked?'true':'false';"}
266
            },
267
            {
268
                field:"image",
269
                name:'<span id="serverDialogImageDialogLink">Image</a>',
270
                type:"dijit.form.Select",
271
                help: "servers/image",
272
                attrs: {
273
                    store: "stores.unusedImages",
274
                    searchAttr: "name",
275
                    required:true,
276
                    onChange: "suffix=this.value.substr(this.value.lastIndexOf('.')+1); " +
277
                        "stores.nodeIdentities.fetch({query: {formats:'*' +suffix+ '*'}, onComplete: servers.updateNetworkInterfaces});"
278
                }
279
            },
280
            {
281
                field:"image2",
282
                name:'<span id="serverDialogImage2DialogLink">Image2</span>',
283
                type:"dijit.form.Select",
284
                help: "servers/image-2",
285
                attrs: {store: "stores.unusedImages2", searchAttr: "name"}
286
            },
287
            {
288
                field: "networkuuid1",
289
                name:'<span id="serverDialogNetwork1DialogLink">Connection</span>',
290
                type: "dijit.form.Select",
291
                required:true,
292
                help: "servers/connection",
293
                attrs: {store:"stores.unusedNetworks", searchAttr: "name"}
294
            },
295
            {
296
                field: "networkuuid2",
297
                name: '<span id="serverDialogNetwork2DialogLink">Connection2</span>',
298
                type: "dijit.form.Select",
299
                attrs: {store:"stores.unusedNetworks2", searchAttr: "name"}
300
            },
301
            {
302
                field: "nicmodel1",
303
                name:"NIC model",
304
                type: "dijit.form.Select",
305
                help: "servers/network-interface",
306
                attrs: {store:"stores.networkInterfaces", searchAttr: "type", query: "{hypervisor: '*'}"}
307
            },
308
            {
309
                field: "autostart",
310
                name:"Auto-start",
311
                type: "dijit.form.CheckBox",
312
                restricted: true,
313
                attrs:{onchange: "this.value=this.checked?'true':'false';"}
314
            },
315
            {
316
                // HTML5 console
317
                formatter: function(item){
318
                    if(item.status == "new" || user.is_readonly){
319
                        return "";
320
                    }
321
                    if(item.status != "new" && item.status != "shutoff" && item.status != "inactive" && item.macname){
322
                       return '<td><div>Console</div></td><td><div>' + guacFormatter(item) + '</div></td>';
323
                    } else {
324
                        return "";
325
                    }
326
                }
327
            },
328
            /*
329
            {
330
                // tunnel - obsolete, disabled
331
                formatter: function(item){
332
                    if(true || item.status == "new"){
333
                        return "";
334
                    }
335

    
336
                    var server = new steam2.models.Server(item);
337

    
338
                    var start = '<button type="button" id="tunnelStartButton" onclick="return false;" title="Start" class="action_button start_icon"><span>start</span></button>',
339
                        stop    = '<button type="button" id="tunnelStopButton"    onclick="return false;" title="Stop"    class="action_button shutdown_icon"><span>stop</span></button>',
340
                        display = stores.servers.getValue(item, "display");
341

    
342
                    function getArgs(){
343
                        return {
344
                            remote_ip: item.macip,
345
                            remote_port: item.port,
346
                            host: window.location.host,
347
                            username: "irigo-" + user.get()
348
                        };
349
                    }
350

    
351
                    function addStartTunnelClickHandler(){
352
                        dojo.query('#tunnelStartButton').onclick(function(){
353
                            server._startTunnel();
354
                            return false;
355
                        });
356
                    }
357

    
358
                    function addStopTunnelClickHandler(){
359
                        dojo.query('#tunnelStopButton').onclick(function(){
360
                            server._stopTunnel();
361
                            return false;
362
                        });
363
                    }
364

    
365
                    // should be something like jquery live
366
                    dojo.connect(servers.grid, 'onDialog', function(){
367
                        addStopTunnelClickHandler();
368
                        addStartTunnelClickHandler();
369
                    });
370

    
371
                    dojo.connect(server, 'onTunnelConnect', function(){
372
                        if (dojo.byId('tunnelStatus')) dojo.byId('tunnelStatus').innerHTML = "Active ";
373
                        if (dojo.byId('tunnelButton')) dojo.byId('tunnelButton').innerHTML = stop;
374
                        if (dojo.byId('appletLabel')) dojo.byId("appletLabel").innerHTML = '<a href="' + display + '://127.0.0.1:' + server._tunnel.local_port + '">Java console</a>';
375
                        // // In dojo 1.6, the jquery.live is availble
376
                        // // change to that when available
377
                        addStopTunnelClickHandler();
378
                    });
379

    
380
                    dojo.connect(server, 'onTunnelDisconnect', function(){
381
                        if (dojo.byId('tunnelStatus')) dojo.byId('tunnelStatus').innerHTML = "Inactive ";
382
                        if (dojo.byId('tunnelButton')) dojo.byId('tunnelButton').innerHTML = start;
383
                        if (dojo.byId('appletLabel')) dojo.byId("appletLabel").innerHTML = "Java console";
384
                        if (dojo.byId('appletStatus')) dojo.byId("appletStatus").innerHTML = "Click on icon to launch";
385
                        addStartTunnelClickHandler();
386
                    });
387

    
388
                    return [
389
                        '<td>Tunnel<a href="https://www.origo.io/info/stabiledocs/web/servers/console/tunnel" rel="help" target="_blank" class="irigo-tooltip">help</a><span id="tunnelApplet" /></td>',
390
                        '<td>',
391
                        '    <span id="tunnelStatus">', server.hasTunnel() ? 'Active' : 'Inactive','&nbsp;</span>',
392
                        '    <span id="tunnelButton">', server.hasTunnel() ? stop : start, '</span>',
393
                        '    <img id="tunnel-loading-indicator" height="18px" alt="loading ..." style="display:none;vertical-align:bottom" src="/stabile/static/img/loader.gif" />',
394
                        '</td>'].join('');
395
                }
396
            },
397
            */
398
            /*
399
            {
400
                // Console applet - obsolete, disabled
401
                formatter: function(item){
402
                    if(true || item.status == "new"){
403
                        return "";
404
                    }
405
                    var server = new steam2.models.Server(item);
406

    
407
                    var handle = dojo.connect(servers.grid, 'onDialog', function(){
408
                        dojo.query('#startServerConsole').onclick(function(){
409
                            dojo.byId('tunnel-loading-indicator').style.display = 'inline';
410
                            server.startViewer();
411
                        });
412
                        dojo.disconnect(handle);
413
                    });
414

    
415
                    dojo.connect(server, 'onViewerStop', function(){
416
                        dojo.byId('tunnel-loading-indicator').style.display = 'none';
417
                    });
418

    
419
                    dojo.connect(server, 'onTunnelConnect', function(){
420
                        dojo.byId('tunnel-loading-indicator').style.display = 'none';
421
                    });
422

    
423
                    dojo.connect(server, 'onViewerStart', function(){
424
                        dojo.byId('tunnel-loading-indicator').style.display = 'none';
425
                        dojo.byId('appletStatus').innerHTML = "Started";
426
                    });
427

    
428
                    dojo.connect(server, 'onViewerStop', function(){
429
                        var elm = dojo.byId('appletStatus');
430
                        // NOTE: the dialog could be closed before the vnc window
431
                        if(elm){
432
                            elm.innerHTML = "Click on icon to launch";
433
                        }
434
                    });
435

    
436
                    return [
437
                        '<td>',
438
                        '    <div id="consoleApplet">',
439
                        '        <span id="appletLabel">Java console</span>',
440
                        '        <a href="https://www.origo.io/info/stabiledocs/web/servers/console" rel="help" target="_blank" class="irigo-tooltip">help</a>',
441
                        '    </div>',
442
                        '</td>',
443
                        '<td>',
444
                        '    <span id="appletContainer">',
445
                        '<a href="#servers" id="startServerConsole">',
446
                        '    <img src="/stabile/static/gfx/console-icon.png" height="48" width="48" style="vertical-align: middle; margin: 10px;" />',
447
                        '</a>',
448
                        '             <img id="display-loading-indicator" height="18px" alt="loading ..." style="display:none;vertical-align:bottom" src="/stabile/static/img/loader.gif" />',
449
                        '    </span>',
450
                        '        <span id="appletStatus">Click on icon to launch</span>',
451
                        '    (key mappings <a href="https://www.origo.io/info/stabiledocs/web/servers/console/key-mappings" rel="help" target="_blank" class="irigo-tooltip">help</a>)',
452
                        '</td>'].join('');
453
                }
454
            },
455
            {
456
                field: "keyboard",
457
                name: "Keyboard layout",
458
                type: "dijit.form.Select",
459
                attrs: {store:"stores.rdpKeyboardLayouts", searchAttr: "lang"}
460
            },
461
            {
462
                // Display display address
463
                formatter: function(item){
464
                    if(item.status == "new"){
465
                        return "";
466
                    }
467
                    if(user.is_admin && item.status != "new" && item.macname){
468
                        // complicated because we need to fetch the IP asynchronously
469
                        // ensure that the dialog is shown
470
                        var macname = item.macname;
471
                        var handle = dojo.connect(servers.grid, "onDialog",function(){
472
                            var durl = (item.port < 5900 ? "rdp://":"vnc://") + item.macip + ":" + item.port;
473
                            dojo.byId('ip').innerHTML = "<a href=\"" + durl + "\">" + durl + "</a>";
474
                            dojo.disconnect(handle);
475
                        });
476
                        var ret = '<td><div id="iplabel">Display</div></td><td><div id="ip"></div></td>';
477
                        return ret;
478
                    }
479
                    return '<td><div id="iplabel"></div></td><td><div id="ip"></div></td>';
480
                }
481
            }
482
            */
483
        ],
484

    
485
        updateNetworkInterfaces : function(items) {
486
            var nicmodel1 = dijit.byId("nicmodel1");
487
            nicmodel1.setStore(stores.networkInterfaces, nicmodel1.value, {query:{hypervisor: "*"+items[0].hypervisor[0]+"*"}});
488
            // var nicmodel2 = dijit.byId("nicmodel2");
489
            // nicmodel2.setStore(stores.networkInterfaces, nicmodel2.value, {query:{hypervisor: "*"+items[0].hypervisor+"*"}});
490
            var image = dijit.byId('image');
491
            var image2 = dijit.byId('image2');
492
            if (image2.value) { // Images available for selection depend on first image
493
                image2.setStore(stores.unusedImages2, image2.value, {query:{hypervisor: "*"+items[0].hypervisor[0]+"*" }});
494
            }
495
        },
496

    
497
        dialogExtras : function(item){
498
            return "";
499
        },
500

    
501
        mount: function(){
502
            var item = servers.grid.dialog.item;
503
            servers.store.setValue(item, 'action', 'mountcd');
504
            var value = dijit.byId('cdrom').get('value');
505
            servers.store.setValue(item, 'cdrom', value);
506
            servers.store.save();
507
            var res = servers.store.save();
508
        },
509

    
510
        move: function(){
511
            var item = servers.grid.dialog.item;
512
            servers.store.setValue(item, 'action', 'move');
513
            var value = dijit.byId('mac').get('value');
514
            servers.store.setValue(item, 'mac', value);
515
            servers.store.setValue(item, 'status', 'moving');
516
            servers.grid.dialog.hide();
517
            var res = servers.store.save();
518
            /* res[0].deferred.promise.then(function(e) {
519
                console.log(e.message);
520
                if (e.error) {
521
                    IRIGO.toast(e.message);
522
                    servers.grid.refresh();
523
                }
524
            }); */
525
        },
526

    
527
        getActionButtons : function(item, include_save){
528
            if (user.is_readonly) return "";
529

    
530
            var name = item.name;
531
            var type = this.name;
532

    
533
            function actionButton(args){
534
                args.name = name;
535
                args.type = type;
536
                return grid.actionButton(args);
537
            }
538
            var id = item.uuid;//store.getValue(item, 'uuid');
539
            var status = item.status;//store.getValue(item, 'status');
540
            
541
            var start = actionButton({'action':"start", 'id':id});
542
            var resume = actionButton({'action':"resume", 'id':id});
543
            var suspend = actionButton({'action':"suspend", 'id':id});
544
            var shutdown = actionButton({'action':"shutdown", title:'ACPI shutdown, <br />(Note: only works if supported by OS)', 'id':id, confirm:true});
545
            var destroy = actionButton({'action':"destroy", 'id':id, title:'pull the plug', 'confirm':true});
546
            var _delete = actionButton({'action':"delete", 'id':id, 'confirm':true});
547
            var save = include_save ? grid.saveButton(type) : "";
548
            var busy = ' <img height="18px" alt="busy" src="/stabile/static/img/loader.gif"> ';
549

    
550
            switch(status){
551
                case "running":
552
                    return suspend + shutdown + destroy + save;
553

    
554
                case "starting":
555
                case "nostate":
556
                    return busy + destroy + save;
557

    
558
                case "paused":
559
                    return resume + destroy + save;
560

    
561
                case "inactive":
562
                    return start + _delete + save;
563
                case "crashed":
564
                case "shutoff":
565
                    return start + _delete + save;
566

    
567
                case "new":
568
                    return save;
569

    
570
                case "upgrading":
571
                case "suspending":
572
                case "resuming":
573
                case "shuttingdown":
574
                    return busy + destroy;
575

    
576
                case "destroying":
577
                    return busy + destroy;
578

    
579
                case "moving":
580
                    return busy;
581

    
582
                default:
583
                    console.log("servers::getActionButtons", "unknown status: ", status);
584
                    return "";
585
            }
586
        },
587

    
588
        // update the store to include the current server image
589
        onBeforeDialog : function(item){
590
            this.item = item;
591
            stores.cdroms.close();
592
            if(item.image && item.image){
593
                stores.unusedImages.url = "/stabile/images?action=listimages&image=" +
594
                    escape(item.image);
595
                stores.unusedImages.close();
596
            }
597
            else{
598
                // update the store
599
                stores.unusedImages.url = "/stabile/images?action=listimages";
600
                stores.unusedImages.close();
601
            }
602
            if(item.image2 && item.image2){
603
                stores.unusedImages2.url = "/stabile/images?action=listimages&image1=" +
604
                    escape(item.image) + "&image=" + escape(item.image2);
605
                stores.unusedImages2.close();
606
            }
607
            else{
608
                // update the store
609
                stores.unusedImages2.url = "/stabile/images?action=listimages&image1=--";
610
                stores.unusedImages2.close();
611
            }
612
            if(item.networkuuid1 && item.networkuuid1){
613
                stores.unusedNetworks.url = "/stabile/networks?action=listnetworks&network=" +
614
                    escape(item.networkuuid1);
615
                stores.unusedNetworks.close();
616
            }
617
            else{
618
                // update the store
619
                stores.unusedNetworks.url = "/stabile/networks?action=listnetworks";
620
                stores.unusedNetworks.close();
621
            }
622
            if(item.networkuuid2 && item.networkuuid2){
623
                stores.unusedNetworks2.url = "/stabile/networks?action=listnetworks&network=" +
624
                    escape(item.networkuuid1) + "&network1=" + escape(item.networkuuid2);
625
                stores.unusedNetworks2.close();
626
            }
627
            else{
628
                // update the store
629
                stores.unusedNetworks2.url = "/stabile/networks?action=listnetworks";
630
                stores.unusedNetworks2.close();
631
            }
632
        },
633

    
634
//        onPostRender: function(){
635
//            servers.updateSums();
636
//        },
637

    
638
        canSort: function(index){
639
            if(index === 9){ // action
640
                return false;
641
            }
642
            if(index === 1){
643
                // status! Something bug in the dojo dropdown button.
644
                // it doesn't stop the event onClicks although I have specified it!
645
                // Tooltip clicks then triggers a sort, and removal of the tooltip content.
646
                // Therefore returning false.
647
                return false;
648
            }
649
            return true;
650
        },
651

    
652

    
653
        // FIXME: bad naming here
654
        onDialogButtons : function(item){
655
            // helpers
656
            var hide = function(dijitId){
657
                var elm = dijit.byId(dijitId);
658
                elm && elm.set('style', 'display:none');
659
                return elm;
660
            };
661
            var disable = function(dijitId){
662
                var elm = dijit.byId(dijitId);
663
                elm && elm.set('disabled', true);
664
                return elm;
665
            };
666
            var enable = function(dijitId){
667
                var elm = dijit.byId(dijitId);
668
                elm && elm.set('disabled', false);
669
                return elm;
670
            };
671
            var hideRow = function(domId){
672
                // tr <- td <- input
673
                dojo.query('#' + domId).parent().parent().style({display:"none"});
674
            };
675
            var showRow = function(domId){
676
                dojo.query('#' + domId).parent().parent().style({display: "table-row"});
677
            };
678

    
679
            if(servers.isPowered(item) || user.is_readonly){
680
                if (dijit.byId('dialogForm'))
681
                        dojo.forEach(dijit.byId('dialogForm').getChildren(), function(input){
682
                            if (input.id!='uuid') input.set('disabled', true);
683
                        });
684
            }
685
            else{
686
                    if (dijit.byId('dialogForm'))
687
                        dojo.forEach(dijit.byId('dialogForm').getChildren(), function(input){
688
                            input.set('disabled', false);
689
                        });
690
            }
691

    
692
            if (!user.is_readonly) {
693
                // always enable renaming
694
                enable('name');
695
                enable('boot');
696
                enable('autostart');
697
                enable('locktonode');
698
                //enable('mount_button');
699
            }
700
            if (user.is_admin) {
701
                //enable('move_button');
702
                // $('#move_button').show();
703
            }
704

    
705
            if (item.status == "new") {
706
                $('#mount_button').hide();
707
                disable('user');
708
            } else {
709
                if (item.status == "shutoff" && !user.is_readonly) {
710
                    enable('user');
711
                } else {
712
                    disable('user');
713
                }
714
            }
715

    
716
            var on_node = (new RegExp("\/mnt\/stabile\/node\/")).test(item.image)?true:false;
717
            if (item.status == "new" || on_node) {
718
                $('#move_button').hide();
719
                disable('!($image =~ /\/$user\//)');
720
            }
721
            if(item.status == "running" && !user.is_readonly){
722
                //enable('mount_button').set('style', 'display:inline');
723
                enable('cdrom');
724

    
725
                var kb = enable('keyboard');
726
                if (kb) kb.set('value', 'en-us');
727
                enable('mac');
728
                if (user.is_admin) {
729
                    // $('#move_button').show();
730
                } else {
731
                    $('#move_button').hide();
732
                }
733
            } else {
734
                $('#mount_button').hide();
735
                $('#move_button').hide();
736
            }
737

    
738
            if (servers.isPowered(item) && user.is_admin && !user.is_readonly) {
739
                showRow('consoleApplet');
740
                showRow('ip');
741
                showRow('tunnelStatus');
742
            } else {
743
                hideRow('consoleApplet');
744
                hideRow('ip');
745
                hideRow('tunnelStatus');
746
            }
747

    
748
            if (item.display == "rdp" && servers.isPowered(item) && user.is_admin && !user.is_readonly){
749
                showRow('keyboard');
750
            }
751
            else{
752
                hideRow('keyboard');
753
            }
754
        }
755
    };
756

    
757

    
758
    servers.updateFilter = function(){
759
        var query = this._searchQuery + " AND " + this._statusQuery;
760
        this.grid.store.query = query;
761
        this.grid.filter(query, /*rerender*/true);
762
    };
763

    
764
    servers.onSearchQueryChange = function(v){
765
        if(v){
766
            /*this._searchQuery = "name: '*" + v + "*'" +
767
             " OR status: '" + v + "*'" +
768
             " OR type: '" + v + "*'" +
769
             " OR internalip: '" + v + "*'" +
770
             " OR externalip: '" + v + "*'";*/
771
            this._searchQuery = "name:" +v + "*";
772
        }
773
        else{
774
            //this._searchQuery = "name: *";
775
            this._searchQuery = "name:*";
776
        }
777
        this.updateFilter();
778
    };
779

    
780
    servers.onStatusFilterChange = function(value){
781
        switch(value){
782
            case "all":
783
                //this._statusQuery = "uuid:*";
784
                this._statusQuery = "status:all";
785
                break;
786
            default:
787
                //this._statusQuery = "status:*" + value + '*';
788
                this._statusQuery = "status:" + value;
789
        }
790
        this.updateFilter();
791
    };
792

    
793
    servers.init = function() {
794
        if (servers._inited === true) return;
795
        else servers._inited = true;
796

    
797
        connect.connect(dijit.byId('servers_status_filter_select'), 'onChange', this, this.onStatusFilterChange);
798
        connect.connect(dijit.byId('servers_search_query'), 'onChange', this, this.onSearchQueryChange);
799

    
800
        servers.store = stores.servers;
801
        servers.domnode = "servers-grid";
802
        servers.grid = grid.create(servers);
803

    
804
        connect.connect(this.grid, '_onFetchComplete', this, function(rows){
805
            this.updateSums(rows);
806
            if (!user.is_readonly) $("#serversNewButton").show();
807
        });
808

    
809
        //servers.grid.query = "uuid: '*'";
810
        servers.grid.startup();
811

    
812
        // ui update
813
        dojo.subscribe("servers:update", function(task){
814
            if(dijit.byId('createServerDialog')){ return;}
815
            console.log("servers update", task);
816
            if (task.uuid) {
817
                servers.grid.refreshRow(task);
818
                home.grid.refresh();
819
            } else {
820
                servers.grid.refresh();
821
                home.grid.refresh();
822
            }
823
            var item = servers.grid.dialog.item;
824
            if(!item || item.uuid !== task.uuid){
825
                return;
826
            }
827
            if (dojo.byId('ip') && task.displayip && task.displayport) {
828
                var disp = (task.displayport<5900?"rdp://":"vnc://");
829

    
830
                // Why is the local_port arriving from the server?
831
                // var durl = disp + task.displayip + ":" + task.displayport;
832
                // changed -- Jakob
833
                var durl = disp + task.displayip + ":" + task.displayport; //tunnel.getLocalPort();
834
                dojo.byId('ip').innerHTML = "<a href=\"" + durl + "\">" + durl + "</a>";
835
                item.port = task.displayport;
836
                item.macip = task.displayip;
837
            }
838
        });
839

    
840
        connect.connect(this.grid.dialog, 'show', this, function(item){
841
            // summary: create dialog node link.
842
            var self = this;
843
            if(item.status != 'new'){
844
                if(item.image && item.image != '--'){
845
                    domConstruct.place('<a id="serverDialogImageDialogLink" nohref="#servers">Image</a>', 'serverDialogImageDialogLink', 'replace');
846
                    on(dom.byId('serverDialogImageDialogLink'), 'click', function(){
847
                        self.grid.dialog.hide();
848
                        home.showImageDialog(item.image);
849
                //        stores.imagesByPath.fetchItemByIdentity({identity: item.image , onItem: function(item) {console.log("fetching", item); stores.images.fetchItemByIdentity({identity: item.uuid, onItem: function(image){window['images'].grid.dialog.show(image);}})}});
850
                    });
851
                }
852
                if(item.image2 && item.image2 != '--'){
853
                    domConstruct.place('<a id="serverDialogImage2DialogLink" nohref="#servers">Image2</a>', 'serverDialogImage2DialogLink', 'replace');
854
                    on(dom.byId('serverDialogImage2DialogLink'), 'click', function(){
855
                        self.grid.dialog.hide();
856
                        home.showImageDialog(item.image2);
857
                //        stores.imagesByPath.fetchItemByIdentity({identity: item.image2 , onItem: function(item){stores.images.fetchItemByIdentity({identity: item.uuid, onItem: function(image){window['images'].grid.dialog.show(image);}})}});
858
                    });
859
                }
860
                if(item.networkuuid1 && item.networkuuid1 != '--'){
861
                    domConstruct.place('<a id="serverDialogNetwork1DialogLink" nohref="#servers">Connection</a>', 'serverDialogNetwork1DialogLink', 'replace');
862
                    on(dom.byId('serverDialogNetwork1DialogLink'), 'click', function(){
863
                        self.grid.dialog.hide();
864
                        networks.grid.dialog.show(stores.networks.fetchItemByIdentity({identity: item.networkuuid1 }));
865
                    });
866
                }
867
                if(item.networkuuid2 && item.networkuuid2 != '--'){
868
                    domConstruct.place('<a id="serverDialogNetwork2DialogLink" nohref="#servers">Connection2</a>', 'serverDialogNetwork2DialogLink', 'replace');
869
                    on(dom.byId('serverDialogNetwork2DialogLink'), 'click', function(){
870
                        self.grid.dialog.hide();
871
                        networks.grid.dialog.show(stores.networks.fetchItemByIdentity({identity: item.networkuuid2 }));
872
                    });
873
                }
874
                if(user.is_admin && item.mac && item.mac != '--'){
875
                    domConstruct.place('<a id="serverDialogNodeDialogLink" nohref="#servers">Node</a>', 'serverDialogNodeDialogLink', 'replace');
876
                    on(dom.byId('serverDialogNodeDialogLink'), 'click', function(){
877
                        self.grid.dialog.hide();
878
                        nodes.grid.dialog.show(stores.nodes.fetchItemByIdentity({identity: item.mac }));
879
                    });
880
                }
881
            }
882
        });
883

    
884
    };
885

    
886
    servers.updateSums = function(rows) {
887
        var totalvcpus = 0;
888
        var totalmemory = 0;
889

    
890
        if (!rows) {
891
            for(var i = 0; i < servers.grid.rowCount; i++){
892
                sumit(servers.grid.getItem(i));
893
            }
894
        } else {
895
            for(var i in rows){
896
                sumit(rows[i]);
897
            }
898
        }
899

    
900
        function sumit(item) {
901
            if (item) {
902
                if (item.status && item.status!="inactive" && item.status!="shutoff") {
903
                    totalvcpus += parseInt(item.vcpu);
904
                    totalmemory += parseInt(item.memory);
905
                }
906
            }
907
        }
908
        var vq = (user.vcpuquota==0)?'&infin;':Math.round(user.vcpuquota);
909
        var memq = (user.memoryquota==0)?'&infin;': (Math.round(10*user.memoryquota /1024)/10);
910
        document.getElementById("machines_sum").innerHTML =
911
                '<span title="Quotas: ' + vq + ' VCPUs, ' + memq + ' GB memory">' +
912
                "Total VCPUs: " + totalvcpus +
913
                "&nbsp;&nbsp;Total memory: " + (Math.round(10*totalmemory /1024)/10) +
914
                "</span>";
915
    }
916
    window.servers = servers;
917
    return servers;
918
});
919

    
920

    
(15-15/23)