Project

General

Profile

Download (16.1 KB) Statistics
| Branch: | Revision:
1
define([
2
'dojo/_base/connect',
3
'dojo/on',
4
'dijit/registry',
5
'stabile/grid',
6
'stabile/stores',
7
'stabile/formatters',
8
'steam2/models/Server',
9
'stabile/ui_update',
10
// for nodes.html
11
'dojo/parser',
12
'dijit/form/Form',
13
'dijit/form/FilteringSelect',
14
'dijit/form/Button',
15
'dojo/date',
16
'dojo/date/locale'
17

    
18
],function(connect, on, registry, grid, stores, formatters, Server, ui_update, parser, Form, FilteringSelect){
19

    
20
    var sibFormatter = function (item) {
21
        var sib = "";
22
        if (item.status != "shutoff" && item.status != "asleep") {
23
            sib += "<button type=\"button\" title=\"terminal\" class=\"action_button terminal_icon\" " +
24
                    "onclick=\"w = window.open('/stabile/nodes?action=terminal&mac=" + item.mac + "', '" + item.mac + "'" +
25
                    "); w.focus(); return false;" +
26
                    "\"><span>terminal</span></button>";
27
        }
28
        if ((item.ipmiip && item.ipmiip!="--") || (item.amtip && item.amtip!="--")) {
29
            sib += " <button type=\"button\" title=\"sol\" class=\"action_button sol_icon\" " +
30
                    "onclick=\"w = window.open('/stabile/nodes?action=sol&mac=" + item.mac + "', 'SOL: " + item.mac + "'" +
31
                    "); w.focus(); return false;" +
32
                    "\"><span>SOL</span></button>";
33
        }
34
        return sib;
35
    };
36

    
37
var nodes = {
38
    _inited: false,
39

    
40
    grid: {},
41

    
42
    /** object name - for reflective lookup */
43
    name: 'nodes',
44

    
45
    store: null,
46

    
47
    sortInfo: 2,
48

    
49
    storeQuery: { mac: '*'},
50

    
51
    structure : [
52
        {
53
            field: '_item',
54
            name: ' ',
55
            width: '60px',
56
            steamid: 'terminal',
57
            formatter: sibFormatter
58
        },
59
        {
60
            field: 'name',
61
            name: 'Name',
62
            width: 'auto'
63
        },
64
        {
65
            field: 'status',
66
            name: 'Status',
67
            width: '70px',
68
            formatter: function(value, rowId){
69
                var item = this.grid.getItem(rowId);
70
                var heartbeat = item.timestamp * 1000; /*from secs to ms*/
71
                var localized = dojo.date.locale.format(new Date(heartbeat), {formatLength: 'medium'});
72
                var maintsleep = (item.maintenance && item.maintenance=='1' && value=='asleep')?' *':'';
73
                return dojo.string.substitute('<span title="Heartbeat: ${0}">${1}</span>', [localized, value + maintsleep]);
74
            }
75
        },
76
        {
77
            field: 'ip',
78
            name: "IP",
79
            width: "80px"
80
        },
81
        {
82
            field: 'identity',
83
            name: 'Identity <a href="https://www.origo.io/info/stabiledocs/web/nodes/hypervisor" rel="help" target="_blank" class="irigo-tooltip">help</a>',
84
            width: "70px"
85
        },
86
        {
87
            field:'cpucores',
88
            name:"Cores",
89
            width: "40px",
90
            cellStyles: "text-align:right;",
91
            formatter: function(val, rowIdx, cell) {
92
                var item = this.grid.getItem(rowIdx);
93
                return val*item.cpucount;
94
            }
95
        },
96
        {
97
            field: 'cpuload',
98
            name: "Load",
99
            width: "40px",
100
            cellStyles: "text-align:right;",
101
            formatter: function(val, rowIdx, cell) {
102
                var item = this.grid.getItem(rowIdx);
103
                return ((item.status=="running" || item.status=="maintenance")?val:"--");
104
            }
105
        },
106
        {
107
            field: 'vms',
108
            name: "VMs",
109
            width: "32px",
110
            cellStyles: "text-align:right;"
111
        },
112
        {
113
            field: 'storfree',
114
            name:"Free stor (MB)",
115
            formatter: formatters.kbytes2mbs,
116
            cellStyles: "text-align:right;",
117
            width: "85px"
118
        },
119
        {
120
            field: 'memfree',
121
            name:"Free mem (MB)",
122
            formatter: formatters.kbytes2mbs,
123
            cellStyles: "text-align:right;",
124
            width: "85px"
125
        },
126
        {
127
            field: 'memtotal',
128
            name: "Total mem (MB)",
129
            formatter: formatters.kbytes2mbs,
130
            cellStyles: "text-align:right;",
131
            width: "90px"
132
        },
133
        {
134
            field: 'action',
135
            name: 'Action <a href="//www.origo.io/info/stabiledocs/web/nodes/actions" rel="help" target="_blank" class="irigo-tooltip">help</a>',
136
            width: 'auto',
137
            formatter: function(val, rowIdx, cell) {
138
                var item = this.grid.getItem(rowIdx);
139
                return nodes.getActionButtons(item);
140
            }
141
        }
142
    ],
143

    
144
    dialogStructure : [
145
        { field: "name", name: "Name", type: "dijit.form.TextBox" },
146
        { field: "status", name: "Status", type: "dijit.form.TextBox" , attrs : {readonly :"readonly"} },
147
        { field: "mac", name: "Mac address", type: "dijit.form.TextBox" , attrs: {"readonly":"true"}},
148
        { field: "stortotal", name: "Total node storage (MB)", type: "dijit.form.TextBox" , attrs: {"disabled":"true"}},
149
        { field: "storfree", name: "Free node storage (MB)", type: "dijit.form.TextBox" , attrs: {"disabled":"true"}},
150
        { field: "ipmiip", name: "IPMI IP address", type: "dijit.form.TextBox" , attrs: {"readonly":"true"}},
151
        { field: "amtip", name: "AMT IP address", type: "dijit.form.TextBox" , attrs: {"readonly":"true"}},
152
        { field: "cpuname", name: "Cpu name", type: "dijit.form.TextBox",
153
            style: "width: 200px;",
154
            attrs: {"disabled":"true"} },
155
        { field: "vmvcpus", name: "Active vCPU's", type: "dijit.form.TextBox" , attrs : {readonly :"readonly"} },
156
        {
157
            formatter: function(node){
158
                if(node.status != 'shutoff' && node.vms>0 && node.vmuuids){
159
                    var doms = node.vmuuids.split(/, {0,1}/);
160
                    var domnames = node.vmnames.split(/, {0,1}/);
161
                    var domusers = node.vmusers.split(/, {0,1}/);
162
                    var serverStandIn;
163
                    var serverEditLink = "";
164
                    for (var i in doms) {
165
                        //serverStandIn = {uuid:doms[i],name:domnames[i],user:domusers[i]};
166
                        //serverEditLink += Server.getEditDialogLink(serverStandIn) + " ";
167
                        serverEditLink += '<a nohref="#nodes" title="User: ' + domusers[i] + '" onclick="servers.grid.dialog.show(stores.servers.fetchItemByIdentity({identity: \'' + doms[i]  + '\'}));">' + domnames[i] + '</a> ';
168
                    }
169
                    return '<td>Servers</td><td>' + serverEditLink + '</td>';
170
                } else {
171
                    return '<td>Servers</td><td>No running servers</td>';
172
                }
173
            }
174
        },
175
        { field: "nfsroot", name: "NFS root", type: "dijit.form.TextBox" , attrs : {readonly :"readonly"} },
176
        { field: "kernel", name: "Kernel", type: "dijit.form.TextBox" , attrs : {readonly :"readonly"} }
177
    ],
178

    
179
    canSort: function(index){
180
        if(index === 4){ // hypervisor
181
            return false;
182
        }
183
        return true;
184
    },
185

    
186
    getActionButtons : function(item, include_save){
187
        var type = this.name;
188
        var name = item.name;
189
        function actionButton(args){
190
            args.name = name;
191
            args.type = type;
192
            return grid.actionButton(args);
193
        }
194
        // var store = stores.nodes;
195

    
196
        // var id = store.getValue(item, 'mac');
197
        // var status = store.getValue(item, 'status');
198

    
199
        var id = item.mac;
200
        var status = item.status;
201
        var vms = item.vms;
202
        var amtip = item.amtip;
203
        if (!amtip || amtip === "--") amtip = item.ipmiip;
204

    
205
        var delete_button = (item.identity=='local_kvm')?'':actionButton({'action':"delete", 'id':id, 'confirm':true});
206
        var reboot_button = (item.identity=='local_kvm')?'':actionButton({'action':"reboot", 'id':id});
207
        var shutdown_button = (item.identity=='local_kvm')?'':actionButton({'action':"shutdown", 'id':id});
208
        var reset_button = actionButton({'action':"reset", 'id':id, 'confirm':true});
209
        var unjoin_button = (item.identity=='local_kvm')?'':actionButton({'action':"unjoin", 'id':id});
210
        var reload_button = actionButton({'action':"reload", 'id':id});
211
        var sleep_button = (item.identity=='local_kvm')?'':actionButton({'action':"sleep", 'id':id});
212
        var wake_button = (item.identity=='local_kvm')?'':actionButton({'action':"wake", 'id':id});
213
        var maintenance_button = actionButton({'action':"maintenance", 'id':id});
214
        var carryon_button = actionButton({'action':"carryon", 'id':id});
215
        var evacuate_button = actionButton({'action':"evacuate", 'id':id});
216
        var save = include_save ? grid.saveButton(type) : "";
217
        var buttons = "";
218

    
219
        if(status === "running"){
220
            if (vms == 0) {
221
                buttons += reboot_button;
222
                buttons += shutdown_button;
223
                buttons += unjoin_button;
224
                buttons += sleep_button;
225
            }
226
            buttons += reload_button;
227
            buttons += maintenance_button;
228
        }
229
        else if(status === "shutdown"){
230
            buttons += wake_button;
231
            buttons += delete_button;
232
            if (amtip && amtip!="--") buttons += reset_button;
233
        }
234
        else if(status === "inactive"){
235
            buttons += wake_button;
236
            buttons += delete_button;
237
            if (amtip && amtip!="--") buttons += reset_button;
238
        //    buttons += maintenance_button;
239
        }
240
        else if(status === "asleep"){
241
            buttons += wake_button;
242
        }
243
        else if(status === "maintenance"){
244
            if (vms == 0) {
245
                buttons += reboot_button;
246
                buttons += shutdown_button;
247
                buttons += unjoin_button;
248
                buttons += sleep_button;
249
                if (amtip && amtip!="--") buttons += reset_button;
250
            } else {
251
                buttons += evacuate_button;
252
            }
253
            buttons += reload_button;
254
            buttons += carryon_button;
255
        }
256
        else if(status === "reboot"){
257
            buttons += delete_button;
258
        }
259
        else if(status === "waking"){
260
            buttons += '<img height="18px" alt="waking" src="/stabile/static/img/loader.gif"></img>';
261
            buttons += delete_button;
262
            if (amtip && amtip!="--") buttons += reset_button;
263
        }
264
        else if(status === "sleeping"){
265
            buttons += '<img height="18px" alt="waking" src="/stabile/static/img/loader.gif"></img>';
266
            buttons += delete_button;
267
            if (amtip && amtip!="--") buttons += reset_button;
268
        }
269
        else if(status === "shuttingdown"){
270
            buttons += '<img height="18px" alt="waking" src="/stabile/static/img/loader.gif"></img>';
271
            buttons += delete_button;
272
            if (amtip && amtip!="--") buttons += reset_button;
273
        }
274
        else if(status === "joining" || status === "unjoining" || status === "unjoin" || status === "reload" || status === "reloading"){
275
            buttons += '<img height="18px" alt="waking" src="/stabile/static/img/loader.gif"></img>';
276
            buttons += delete_button;
277
            if (amtip && amtip!="--") buttons += reset_button;
278
        }
279
        
280
        else{
281
            console.error("unknown status", status);
282
        }
283
        buttons += save;
284
        return buttons;
285
    },
286

    
287
    onPostRender: function(){
288
        //nodes.updateSums();
289
        // FIXME: item not loaded when servers dialog is used before this...
290
        // uncommenting for now
291
        //console.log(dijit.byId('defaultidentity'));
292
        //nodes.setDefaultNodeIdentity(dijit.byId('defaultidentity').item, stores.nodeIdentities);
293
        nodes.setDefaultNodeIdentity();
294
    },
295

    
296
    onDialogButtons : function(item){
297
        var stortotal_field = dijit.byId('stortotal');
298
        var stortotal = this.store.getValue(item, 'stortotal');
299
        stortotal_field.set('value', formatters.kbytes2mbs(stortotal));
300
        var storfree_field = dijit.byId('storfree');
301
        var storfree = this.store.getValue(item, 'storfree');
302
        storfree_field.set('value', formatters.kbytes2mbs(storfree));
303
    }
304
};
305

    
306
nodes.setDefaultNodeIdentity = function(){
307
    // summary: gets the default node identity and sets the value
308
    //          of the filtering select.
309

    
310
    var nodeIdtyFilteringSelect = registry.byId('defaultidentity');
311
    // If dojo not been initialized, i.e. we are loading via jQuery
312
    if (typeof nodeIdtyFilteringSelect == 'undefined') {
313
        nodeIdtyFilteringSelect = new FilteringSelect({
314
            id: "defaultidentity",
315
            name: "defaultidentity",
316
            store: stores.nodeIdentities,
317
            searchAttr: "name"
318
        }, "defaultidentity").startup();
319
    };
320

    
321
    var nodeSleepAfterFilteringSelect = dijit.byId('sleepafter');
322
    if (typeof nodeSleepAfterFilteringSelect == 'undefined') {
323
        nodeSleepAfterFilteringSelect = new FilteringSelect({
324
            id: "sleepafter",
325
            name: "sleepafter"
326
        }, "sleepafter").startup(function(){console.log("started...");});
327
    };
328

    
329
    stores.nodeIdentities.fetch({
330
        query: {identity:'default'}, 
331
        onItem: function(defaultItem){
332
            nodeIdtyFilteringSelect.set('value', defaultItem.id);
333
            nodeIdtyFilteringSelect.set('disabled', false);
334

    
335
            nodeSleepAfterFilteringSelect.set('value', defaultItem.sleepafter);
336
            nodeSleepAfterFilteringSelect.set('disabled', false);
337
        }
338
    });
339
};
340

    
341
nodes.saveDefaultNodeIdentity = function(){
342
    var sleepafter = dijit.byId("sleepafter").value;
343
    var hypervisorId = dijit.byId('defaultidentity').get('displayedValue');
344
    dojo.xhrGet(
345
    {
346
        url: "/stabile/nodes?action=setdefaultnodeidentity&hid=" + hypervisorId + "&sleepafter=" + sleepafter,
347
        load: function(response) {
348
            // FIXME: clean up this when ready at the server side
349
            IRIGO.toaster([{
350
                message: response,
351
                type: "message",
352
                duration: 5000
353
            }
354
            ]);
355
            stores.nodeIdentities.close();
356
            nodes.setDefaultNodeIdentity();
357
        }
358
    });
359
};
360

    
361

    
362

    
363
nodes.init = function(){
364
    if (nodes._inited === true) return;
365
    else nodes._inited = true;
366

    
367
    this.setDefaultNodeIdentity();
368

    
369
    nodes.store = stores.nodes;
370
    nodes.domnode = "nodes-grid";
371
    nodes.grid = grid.create(nodes);
372
    nodes.grid.startup();
373

    
374
    function handleSelectNodesTab(e){
375
        if(e.id == 'nodes'){
376
            nodes.grid.refresh();
377
        }
378
    }
379
    dojo.subscribe('tabContainer-selectChild', null, handleSelectNodesTab);
380

    
381
    dojo.subscribe("nodes:update", function(task){
382
        if (task.uuid || task.mac) nodes.grid.refreshRow(task);
383
        else nodes.grid.refresh();
384
    });
385

    
386
    connect.connect(this.grid, '_onFetchComplete', this, function(rows){
387
        this.updateSums(rows);
388
    });
389

    
390
};
391

    
392
    nodes.updateSums = function() {
393
        dojo.xhrGet({
394
            url : "/stabile/nodes?action=stats",
395
            handleAs : "json",
396
            load : function(response, ioArgs) {
397
                /* Handle a successful callback here */
398
                //alert (100*response.cpuloadavg);
399
                var memf = 0;
400
                if (response.memtotalsum > 0) memf = 100-100*response.memfreesum / response.memtotalsum;
401
                //if (dogauge) updateGauges(memf, 100*response.cpuloadavg, 100*response.storused/(response.storused+response.storfree));
402
                var statssummary =
403
                        "Nodes: " + response.avgs.nodestotal + "&nbsp&nbsp;Cores: " + response.avgs.corestotal + "&nbsp&nbsp;Memory: " +
404
                        Math.round((response.avgs.memtotalsum - response.avgs.memfreesum)/1024) + " (" + Math.round(response.avgs.memtotalsum/1024) + ") MB"
405
                        "&nbsp;&nbsp;Load: " + Math.round(response.avgs.cpuloadavg*100)/100;
406
                var storsummary = response.stortext;
407

    
408
                document.getElementById("statsbox").innerHTML = statssummary;
409
                document.getElementById("storagestatsbox").innerHTML = storsummary;
410
                return response;
411
            },
412
            error : function(response, ioArgs) {
413
                console.log("An error occurrerd.", response, ioArgs);
414
                //return response;
415
            }
416
        });
417
    }
418

    
419
window.nodes = nodes;
420
return nodes;
421
});
422

    
423

    
424

    
425

    
(14-14/23)