Statistics
| Branch: | Tag: | Revision:

root / snf-app / synnefo / ui / static / snf / js / ui / web / ui_single_view.js @ 483c9197

History | View | Annotate | Download (12.5 kB)

1
;(function(root){
2

    
3
    // root
4
    var root = root;
5
    
6
    // setup namepsaces
7
    var snf = root.synnefo = root.synnefo || {};
8
    var models = snf.models = snf.models || {}
9
    var storage = snf.storage = snf.storage || {};
10
    var ui = snf.ui = snf.ui || {};
11
    var util = snf.util = snf.util || {};
12

    
13
    var views = snf.views = snf.views || {}
14

    
15
    // shortcuts
16
    var bb = root.Backbone;
17
    var hasKey = Object.prototype.hasOwnProperty;
18

    
19
    views.SingleDetailsView = views.VMDetailsView.extend({
20
    
21
        view_id: "vm_details_single",
22
        el_sel: '.machine-details',
23
        
24
        selectors: {
25
            'cpu': '.machine-detail.cpus',
26
            'ram': '.machine-detail.ram',
27
            'disk': '.machine-detail.disk',
28
            'image_name': '.machine-detail.image-name',
29
            'image_size': '.machine-detail.image-size'
30
        }
31
    
32
    })
33

    
34
    // VMs single view
35
    views.SingleView = views.VMListView.extend({
36
        
37
        // view id (this could be used to identify 
38
        // the view object from global context
39
        view_id: 'vm_single',
40

    
41
        el: '#machinesview-single',
42
        id_tpl: 'single-vm-',
43
        link_id_tpl: 'single-vm-at-',
44

    
45
        hide_actions: false,
46

    
47
        selectors: {
48
            'vms': '.single-container',
49
            'vm': '#single-vm-',
50
            'view': '#machinesview-single',
51
            'tpl': '.single-container-template',
52
            'spinner': '.large-spinner',
53
            'vm_spinner': '#single-vm-{0} .state .spinner',
54
            'vm_wave': '#single-vm-{0} img.wave',
55
            'vm_cont_active': '#machinesview-single',
56
            'vm_cont_terminated': '#machinesview-single'
57
        },
58
        
59
        initialize: function() {
60
            this.current_vm = 0;
61
            
62
            // button selectors
63
            this.prev_button = this.$(".controls .previous");
64
            this.next_button = this.$(".controls .next");
65
            this.menu = $("#single-servers-list");
66

    
67
            views.SingleView.__super__.initialize.apply(this, arguments);
68
            this.update_current_vm();
69
        },
70

    
71
        // overload show function
72
        show: function() {
73
            views.SingleView.__super__.show.apply(this, arguments);
74
            this.log.debug("showing");
75
            this.$(".column3").show();
76
            this.show_vm_menu();
77
            this.show_current();
78
        },
79

    
80
        show_vm: function(vm) {
81
            if (!vm) { return };
82
            this.current_vm_instance = vm;
83
            this.show_vm_menu();
84
            this.show_current();
85
            this.update_layout();
86
        },
87

    
88
        // identify vm model instance id based on DOM element
89
        vm_id_for_element: function(el) {
90
            return el.attr('id').replace("single-vm-", "");
91
        },
92
        
93
        // set generic view handlers
94
        set_handlers: function() {
95
            this.prev_button.click(_.bind(function(ev){
96
                storage.vms.reset_pending_actions();
97
                ev.preventDefault();
98
                this.show_prev();
99
            }, this));
100

    
101
            this.next_button.click(_.bind(function(ev){
102
                storage.vms.reset_pending_actions();
103
                ev.preventDefault();
104
                this.show_next();
105
            }, this));
106
        },  
107

    
108
        update_current_vm: function() {
109
            try {
110
                this.current_vm_instance = storage.vms.at(this.current_vm);
111
                this.current_vm_instance.start_stats_update(true);
112
                storage.vms.stop_stats_update([this.current_vm_instance]);
113
            } catch (err) {
114
                this.log.debug("Cannot select current vm instance for: {0}".format(this.current_vm));
115
                this.current_vm_instance = undefined;
116
                this.current_vm = 0;
117
            }
118
        },
119

    
120
        show_next: function() {
121
            this.current_vm++;
122
            if (this.current_vm >= storage.vms.models.length) {
123
                this.current_vm = 0;
124
            }
125
            
126
            this.update_current_vm();
127

    
128
            // this might fail when vms get empty
129
            // catch the exception
130
            try {
131
                snf.router.vm_details_view(this.current_vm_instance.id);
132
            } catch (err) {};
133
        },
134

    
135
        show_prev: function() {
136
            this.current_vm--;
137
            if (this.current_vm < 0) {
138
                this.current_vm = storage.vms.length - 1;
139
            }
140

    
141
            this.update_current_vm();
142
            snf.router.vm_details_view(this.current_vm_instance.id);
143
        },
144

    
145
        post_remove_vm: function(vm) {
146
            // current vm removed or does not exist after an update
147
            this.show_vm_menu();
148
            if (!this.current_vm_instance || this.current_vm_instance.id == vm.id) {
149
                this.current_vm++;
150
                if (this.current_vm >= storage.vms.models.length) {
151
                    this.current_vm = 0;
152
                }
153
                this.update_current_vm();
154
                this.show_current();
155
            // this might fail when vms get empty
156
            // catch the exception
157
            } else {
158
                this.show_current();
159
            }
160
        },
161
        
162
        // stuff to do when a new vm has been created.
163
        // - create vm subviews
164
        post_add: function(vm) {
165
            this.vm(vm).removeClass("single-container-template");
166
            this.show_vm_menu();
167
            this.show_current();
168

    
169
            // rename views index
170
            this.stats_views = this.stats_views || {};
171
            this.connect_views = this.connect_views || {};
172
            this.tags_views = this.tags_views || {};
173
            this.details_views = this.details_views || {};
174
            this.action_views = this.action_views || {};
175
            this.action_error_views = this.action_error_views || {};
176

    
177
            //this.stats_views[vm.id] = new views.IconStatsView(vm, this);
178

    
179
            // same as icon view
180
            this.action_views[vm.id] = new views.VMActionsView(vm, this, this.vm(vm), this.hide_actions);
181
            this.stats_views[vm.id] = new views.VMStatsView(vm, this, {stats_type: 'series'});
182
            this.connect_views[vm.id] = new views.IconVMConnectView(vm, this);
183
            this.tags_views[vm.id] = new views.VMTagsView(vm, this, true, 20, 10, 35);
184
            this.details_views[vm.id] = new views.SingleDetailsView(vm, this);
185
            this.action_error_views[vm.id] = new views.VMActionErrorView(vm, this);
186
            
187
            if (storage.vms.models.length > 1) { this.vm(vm).hide(); };
188
        },
189

    
190
        post_update_vm: function(vm) {
191
        },
192
        
193
        // vm specific event handlers
194
        set_vm_handlers: function(vm) {
195
            var el = this.vm(vm);
196
        },
197
        
198
        // handle selected vm
199
        show_current: function() {
200
            var index = this.current_vm;
201
            var vm = storage.vms.at(index);
202

    
203
            this.$(".server-name").removeClass("column3-selected");
204
            
205
            if (vm) {
206
                this.vm(vm).show();
207
            };
208

    
209
            _.each(storage.vms.models, function(vmo){
210
                if (vm && (vm.id != vmo.id)) {
211
                    if (!hasKey.call(this._vm_els, vmo.id)) { return };
212
                    this.vm(vmo).hide();
213
                }
214
            }, this)
215

    
216
            if (!vm) {
217
                // empty list
218
                this.$(".column3").hide();
219
                return;
220
            }
221
            this.$(".column3").show();
222

    
223

    
224
            $("#" + this.link_id_tpl + this.current_vm).addClass("column3-selected");
225
            try {
226
                this.update_details(vm);
227
            } catch (err) {};
228
        },
229

    
230
        show_vm_menu: function() {
231
            this.menu.find(".server-name").remove();
232

    
233
            _.each(storage.vms.models, function(vm, index) {
234
                this.menu.append('<div class="server-name" id="'+this.link_id_tpl + index +'">' + 
235
                               util.truncate(vm.get("name"),16)+'</div>');
236
                if (this.current_vm_instance && vm.id == this.current_vm_instance.id) {
237
                    this.current_vm = index;
238
                }
239
            }, this);
240
            
241
            var self = this;
242
            this.menu.find(".server-name").click(function(ev) {
243
                ev.preventDefault();
244
                var id = $(this).attr("id").replace("single-vm-at-", "");
245
                if (self.current_vm != id) {
246
                    storage.vms.reset_pending_actions();
247
                }
248
                self.current_vm = id;
249
                self.update_current_vm();
250
                snf.router.vm_details_view(self.current_vm_instance.id);
251
            })
252
        },
253

    
254
        // generic stuff to do on each view update
255
        // called once after each vm has been updated
256
        update_layout: function() {
257
            this.update_current_vm();
258
            fix_v6_addresses();
259
        },
260

    
261
        // update vm details
262
        update_details: function(vm) {
263
            var el = this.vm(vm);
264
            if (vm != this.current_vm_instance) { return };
265

    
266
            // truncate name
267
            el.find(".machine-detail.name").text(util.truncate(vm.get("name"), 35));
268
            // set ips
269
            el.find(".machine-detail.ipv4.ipv4-text").text(vm.get_addresses().ip4 || "not set");
270
            // TODO: fix ipv6 truncates and tooltip handler
271
            el.find(".machine-detail.ipv6.ipv6-text").text(vm.get_addresses().ip6 || "not set");
272
            // set the state (i18n ??)
273
            el.find(".state-label").text(STATE_TEXTS[vm.state()]);
274
            // set state class
275
            el.find(".state").removeClass().addClass(views.SingleView.STATE_CLASSES[vm.state()].join(" "));
276
            // os icon
277
            el.find(".single-image").css({'background-image': "url(" + this.get_vm_icon_path(vm, "medium") + ")"});
278
            
279
            el.removeClass("connectable");
280
            if (vm.is_connectable()) {
281
                el.addClass("connectable");
282
            }
283

    
284
            if (vm.get('status') == 'BUILD') {
285
                // update bulding progress
286
                el.find("span.build-progress").show().text(vm.get("progress_message"));
287
            } else {
288
                // hide building progress
289
                el.find("span.build-progress").hide();
290
            }
291

    
292
            if (vm.state() == "DESTROY") {
293
                el.find("span.build-progress").show().text("Terminating...");
294
            }
295

    
296
            icon_state = vm.is_active() ? "on" : "off";
297
            set_machine_os_image(el, "single", icon_state, this.get_vm_icon_os(vm));
298
            
299
            // update subviews
300
            this.action_views[vm.id].update_layout();
301
            this.stats_views[vm.id].update_layout();
302
            this.connect_views[vm.id].update_layout();
303
            this.tags_views[vm.id].update_layout();
304
            this.details_views[vm.id].update_layout();
305
        },
306
            
307
        get_vm_icon_os: function(vm) {
308
            var os = vm.get_os();
309
            var icons = window.os_icons || views.SingleView.VM_OS_ICONS;
310
            if (icons.indexOf(os) == -1) {
311
                os = "unknown";
312
            }
313
            return os;
314
        },
315

    
316
        // TODO: move to views.utils (the method and the VM_OS_ICON vars)
317
        get_vm_icon_path: function(vm, icon_type) {
318
            var os = vm.get_os();
319
            var icons = window.os_icons || views.SingleView.VM_OS_ICONS;
320

    
321
            if (icons.indexOf(os) == -1) {
322
                os = "unknown";
323
            }
324

    
325
            return views.SingleView.VM_OS_ICON_TPLS()[icon_type].format(os);
326
        }
327
    })
328

    
329
    views.SingleView.VM_OS_ICON_TPLS = function() {
330
        return {
331
            "medium": snf.config.machines_icons_url + "large/{0}-sprite.png"
332
        }
333
    }
334

    
335
    views.SingleView.VM_OS_ICONS = window.os_icons || [];
336

    
337
    views.SingleView.STATE_CLASSES = {
338
        'UNKNOWN':          ['state', 'error-state'],
339
        'BUILD':            ['state', 'build-state'],
340
        'REBOOT':           ['state', 'rebooting-state'],
341
        'STOPPED':          ['state', 'terminated-state'],
342
        'ACTIVE':           ['state', 'running-state'],
343
        'ERROR':            ['state', 'error-state'],
344
        'DELETED':           ['state', 'destroying-state'],
345
        'DESTROY':          ['state', 'destroying-state'],
346
        'BUILD_INIT':       ['state', 'build-state'], 
347
        'BUILD_COPY':       ['state', 'build-state'],
348
        'BUILD_FINAL':      ['state', 'build-state'],
349
        'SHUTDOWN':         ['state', 'shutting-state'],
350
        'START':            ['state', 'starting-state'],
351
        'CONNECT':          ['state', 'connecting-state'],
352
        'DISCONNECT':       ['state', 'disconnecting-state']
353
    };
354

    
355
})(this);