Revision 96d725ac
b/ui/static/snf/js/models.js | ||
---|---|---|
330 | 330 |
var removed_from_net = this.vms.remove(model.id); |
331 | 331 |
var removed_from_vm = model.networks.remove(this.id); |
332 | 332 |
if (removed_from_net) {this.trigger("vm:disconnect", model, this); this.change()}; |
333 |
if (removed_from_vm) {vm.trigger("network:disconnect", this, model); this.change()};
|
|
333 |
if (removed_from_vm) {model.trigger("network:disconnect", this, model); this.change()};
|
|
334 | 334 |
return; |
335 | 335 |
} |
336 | 336 |
|
... | ... | |
457 | 457 |
// this will dynamicaly change if the server responds that |
458 | 458 |
// images get refreshed on different intervals |
459 | 459 |
this.stats_update_interval = synnefo.config.STATS_INTERVAL || 5000; |
460 |
this.stats_available = false; |
|
460 | 461 |
|
461 | 462 |
// initialize interval |
462 | 463 |
this.init_stats_intervals(this.stats_update_interval); |
463 | 464 |
|
464 |
// clear stats intervals on update |
|
465 |
this.bind("remove", _.bind(function(){ |
|
466 |
try { |
|
467 |
window.clearInterval(this.stats_interval); |
|
468 |
} catch (err) {}; |
|
469 |
}, this)); |
|
470 |
|
|
471 | 465 |
this.bind("change:progress", _.bind(this.update_building_progress, this)); |
472 | 466 |
this.update_building_progress(); |
473 | 467 |
|
... | ... | |
477 | 471 |
this.set({linked_to_nets:this.get("linked_to_nets") || []}); |
478 | 472 |
this.set({firewalls:this.get("firewalls") || []}); |
479 | 473 |
|
480 |
this.action_error = false;
|
|
474 |
this.bind("change:state", _.bind(function(){if (this.state() == "DESTROY") { this.handle_destroy() }}, this))
|
|
481 | 475 |
}, |
482 | 476 |
|
483 | 477 |
handle_firewall_change: function() { |
... | ... | |
555 | 549 |
|
556 | 550 |
// clear and reinitialize update interval |
557 | 551 |
init_stats_intervals: function (interval) { |
558 |
try { |
|
559 |
window.clearInterval(this.stats_interval); |
|
560 |
} catch (err){} |
|
561 |
//this.stats_interval = window.setInterval(_.bind(this.update_stats, this), interval); |
|
562 |
//this.update_stats(true); |
|
552 |
this.stats_fetcher = this.get_stats_fetcher(this.stats_update_interval); |
|
553 |
this.stats_fetcher.start(); |
|
554 |
this.update_stats(true); |
|
563 | 555 |
}, |
564 | 556 |
|
557 |
get_stats_fetcher: function(timeout) { |
|
558 |
var cb = _.bind(function(data){ |
|
559 |
this.update_stats(); |
|
560 |
}, this); |
|
561 |
var fetcher = new snf.api.updateHandler({'callback': cb, timeout:timeout}); |
|
562 |
return fetcher; |
|
563 |
}, |
|
564 |
|
|
565 | 565 |
// do the api call |
566 | 566 |
update_stats: function(force) { |
567 | 567 |
// do not update stats if flag not set |
568 | 568 |
if (!this.do_update_stats && !force) { |
569 | 569 |
return; |
570 | 570 |
} |
571 |
|
|
571 |
|
|
572 | 572 |
// make the api call, execute handle_stats_update on sucess |
573 | 573 |
// TODO: onError handler ??? |
574 | 574 |
stats_url = this.url() + "/stats"; |
575 |
this.sync("GET", this, {url: stats_url, refresh:true, success: _.bind(this.handle_stats_update, this)}); |
|
575 |
this.sync("GET", this, { |
|
576 |
handles_error:true, |
|
577 |
url: stats_url, |
|
578 |
refresh:true, |
|
579 |
success: _.bind(this.handle_stats_update, this), |
|
580 |
error: _.bind(this.handle_stats_error) |
|
581 |
}); |
|
582 |
}, |
|
583 |
|
|
584 |
get_stats_image: function(stat, type) { |
|
576 | 585 |
}, |
577 | 586 |
|
587 |
_set_stats: function(stats) { |
|
588 |
var silent = silent === undefined ? false : silent; |
|
589 |
// unavailable stats while building |
|
590 |
if (this.get("status") == "BUILD") { |
|
591 |
this.stats_available = false; |
|
592 |
} else { this.stats_available = true; } |
|
593 |
|
|
594 |
if (this.get("status") == "DESTROY") { this.stats_available = false; } |
|
595 |
|
|
596 |
this.set({stats: stats}, {silent:true}); |
|
597 |
this.trigger("stats:update", stats); |
|
598 |
}, |
|
599 |
|
|
600 |
unbind: function() { |
|
601 |
models.VM.__super__.unbind.apply(this, arguments); |
|
602 |
}, |
|
603 |
|
|
604 |
handle_stats_error: function() { |
|
605 |
stats = {}; |
|
606 |
_.each(['cpuBar', 'cpuTimeSeries', 'netBar', 'netTimeSeries'], function(k) { |
|
607 |
stats[k] = false; |
|
608 |
}); |
|
609 |
|
|
610 |
this.set({'stats': stats}); |
|
611 |
}, |
|
612 |
|
|
578 | 613 |
// this method gets executed after a successful vm stats api call |
579 | 614 |
handle_stats_update: function(data) { |
615 |
var self = this; |
|
580 | 616 |
// avoid browser caching |
617 |
|
|
581 | 618 |
if (data.stats && _.size(data.stats) > 0) { |
582 | 619 |
var ts = $.now(); |
583 | 620 |
var stats = data.stats; |
621 |
var images_loaded = 0; |
|
622 |
var images = {}; |
|
623 |
|
|
624 |
function check_images_loaded() { |
|
625 |
images_loaded++; |
|
626 |
|
|
627 |
if (images_loaded == 4) { |
|
628 |
self._set_stats(images); |
|
629 |
} |
|
630 |
} |
|
584 | 631 |
_.each(['cpuBar', 'cpuTimeSeries', 'netBar', 'netTimeSeries'], function(k) { |
632 |
|
|
585 | 633 |
stats[k] = stats[k] + "?_=" + ts; |
634 |
|
|
635 |
var stat = k.slice(0,3); |
|
636 |
var type = k.slice(3,6) == "Bar" ? "bar" : "time"; |
|
637 |
var img = $("<img />"); |
|
638 |
var val = stats[k]; |
|
639 |
|
|
640 |
// load stat image to a temporary dom element |
|
641 |
// update model stats on image load/error events |
|
642 |
img.load(function() { |
|
643 |
images[k] = val; |
|
644 |
check_images_loaded(); |
|
645 |
}); |
|
646 |
|
|
647 |
img.error(function() { |
|
648 |
images[stat + type] = false; |
|
649 |
check_images_loaded(); |
|
650 |
}); |
|
651 |
|
|
652 |
img.attr({'src': stats[k]}); |
|
586 | 653 |
}) |
587 | 654 |
data.stats = stats; |
588 | 655 |
} |
589 |
this.set({'stats': data.stats}, {silent:true}); |
|
590 |
// trigger the event |
|
591 |
this.trigger("stats:update"); |
|
592 |
|
|
656 |
|
|
593 | 657 |
// do we need to change the interval ?? |
594 | 658 |
if (data.stats.refresh * 1000 != this.stats_update_interval) { |
595 | 659 |
this.stats_update_interval = data.stats.refresh * 1000; |
596 |
this.init_stats_intervals(this.stats_update_interval); |
|
660 |
this.stats_fetcher.timeout = this.stats_update_interval; |
|
661 |
this.stats_fetcher.stop(); |
|
662 |
this.stats_fetcher.start(); |
|
597 | 663 |
} |
598 | 664 |
}, |
599 |
|
|
665 |
|
|
600 | 666 |
// helper method that sets the do_update_stats |
601 | 667 |
// in the future this method could also make an api call |
602 | 668 |
// immediaetly if needed |
603 | 669 |
enable_stats_update: function() { |
604 | 670 |
this.do_update_stats = true; |
605 | 671 |
}, |
672 |
|
|
673 |
handle_destroy: function() { |
|
674 |
this.stats_fetcher.stop(); |
|
675 |
}, |
|
606 | 676 |
|
607 | 677 |
require_reboot: function() { |
608 | 678 |
if (this.is_active()) { |
... | ... | |
1064 | 1134 |
models.VM.ACTIVE_STATES = [ |
1065 | 1135 |
'BUILD', 'REBOOT', 'ACTIVE', |
1066 | 1136 |
'BUILD_INIT', 'BUILD_COPY', 'BUILD_FINAL', |
1067 |
'SHUTDOWN', 'CONNECT', 'DISCONNECT' |
|
1137 |
'SHUTDOWN', 'CONNECT', 'DISCONNECT', 'DESTROY'
|
|
1068 | 1138 |
] |
1069 | 1139 |
|
1070 | 1140 |
models.VM.BUILDING_STATES = [ |
... | ... | |
1249 | 1319 |
vm.clear_pending_action(); |
1250 | 1320 |
}) |
1251 | 1321 |
}, |
1322 |
|
|
1323 |
reset_stats_update: function() { |
|
1324 |
this.each(function(vm) { |
|
1325 |
vm.do_update_stats = false; |
|
1326 |
}) |
|
1327 |
}, |
|
1252 | 1328 |
|
1253 | 1329 |
has_meta: function(vm_data) { |
1254 | 1330 |
return vm_data.metadata && vm_data.metadata.values |
b/ui/static/snf/js/ui/web/ui_icon_view.js | ||
---|---|---|
103 | 103 |
|
104 | 104 |
if (this.toggler.hasClass("open")) { |
105 | 105 |
this.toggler.removeClass("open"); |
106 |
this.vm.do_update_stats = false; |
|
106 | 107 |
} else { |
107 | 108 |
this.toggler.addClass("open"); |
108 |
get_server_stats(this.vm.id);
|
|
109 |
this.vm.do_update_stats = true;
|
|
109 | 110 |
} |
110 | 111 |
|
111 | 112 |
var self = this; |
... | ... | |
441 | 442 |
this.net_loading = this.el.find(".network-graph .stat-busy"); |
442 | 443 |
this.net_error = this.el.find(".network-graph .stat-error"); |
443 | 444 |
this.net_img = this.el.find(".network-graph .stat-img"); |
445 |
|
|
446 |
this.loading = this.el.find(".stat-busy"); |
|
447 |
this.error = this.el.find(".stat-error"); |
|
448 |
this.img = this.el.find(".stat-img"); |
|
444 | 449 |
|
445 | 450 |
// initial state paremeters |
446 |
this.is_building = (this.vm.get("status") == "BUILD"); |
|
447 |
this.stats_error = false; |
|
448 | 451 |
this.stats = this.vm.get("stats"); |
449 |
this.loading = false; |
|
450 | 452 |
|
451 | 453 |
// timeseries or bar images ? |
452 | 454 |
this.stats_type = options.stats_type || "bar"; |
453 |
|
|
454 |
// stats undefined so probably not loaded yet |
|
455 |
if (this.stats === undefined) { |
|
456 |
this.loading = true; |
|
457 |
} |
|
458 | 455 |
|
459 | 456 |
views.VMStatsView.__super__.initialize.apply(this, arguments); |
460 | 457 |
this.set_handlers(); |
461 | 458 |
this.update_layout(); |
459 |
|
|
460 |
this.net_loading.show(); |
|
461 |
this.net_error.hide(); |
|
462 |
this.cpu_loading.show(); |
|
463 |
this.cpu_error.hide(); |
|
464 |
|
|
465 |
this.net_img.hide(); |
|
466 |
this.cpu_img.hide(); |
|
462 | 467 |
}, |
463 | 468 |
|
464 | 469 |
|
465 | 470 |
set_handlers: function() { |
466 | 471 |
// update view state when vm stats update gets triggered |
467 | 472 |
this.vm.bind("stats:update", _.bind(function(){ |
468 |
// update building state |
|
469 |
if (this.vm.get("status") == "BUILD") { |
|
470 |
this.is_building = true; |
|
471 |
} else { |
|
472 |
this.is_building = false; |
|
473 |
} |
|
474 |
|
|
475 |
// update loading state |
|
476 |
this.stats = this.vm.get("stats"); |
|
477 |
if (this.stats == undefined) { |
|
478 |
this.loading = true |
|
479 |
} else { |
|
480 |
this.loading = false; |
|
481 |
} |
|
482 |
|
|
483 | 473 |
// update the layout |
484 | 474 |
this.update_layout(); |
485 | 475 |
}, this)); |
486 |
|
|
487 |
this.vm.bind("stats:error", _.bind(function(){ |
|
488 |
this.stats_error = true; |
|
489 |
}, this)) |
|
490 |
|
|
491 |
this.cpu_img.error(_.bind(function(){ |
|
492 |
this.stats_error = true; |
|
493 |
this.update_layout(); |
|
494 |
}, this)); |
|
495 |
|
|
496 |
this.net_img.error(_.bind(function(){ |
|
497 |
this.stats_error = true; |
|
498 |
this.update_layout(); |
|
499 |
}, this)); |
|
500 | 476 |
}, |
501 | 477 |
|
502 | 478 |
get_images: function (type) { |
... | ... | |
508 | 484 |
}, |
509 | 485 |
|
510 | 486 |
update_layout: function() { |
511 |
if (this.stats_error) { |
|
512 |
this.net_loading.hide(); |
|
513 |
this.cpu_loading.hide(); |
|
514 |
this.net_img.hide(); |
|
515 |
this.cpu_img.hide(); |
|
516 |
this.cpu_error.show(); |
|
517 |
this.net_error.show(); |
|
518 |
return; |
|
519 |
} |
|
487 |
if (!this.vm.stats_available) { |
|
488 |
this.loading.show(); |
|
489 |
this.img.hide(); |
|
490 |
this.error.hide(); |
|
491 |
} else { |
|
492 |
this.loading.hide(); |
|
493 |
this.stats = this.vm.get("stats"); |
|
494 |
var images = this.get_images(this.stats_type); |
|
520 | 495 |
|
521 |
if (this.loading) { |
|
522 |
this.net_loading.show(); |
|
523 |
this.cpu_loading.show(); |
|
524 |
this.net_img.hide(); |
|
525 |
this.cpu_img.hide(); |
|
526 |
this.cpu_error.hide(); |
|
527 |
this.net_error.hide(); |
|
528 |
return; |
|
529 |
} |
|
496 |
if (images.cpu) { |
|
497 |
this.cpu_img.attr({src:images.cpu}).show(); |
|
498 |
this.cpu_error.hide(); |
|
499 |
} else { |
|
500 |
this.cpu_img.hide(); |
|
501 |
this.cpu_error.show(); |
|
502 |
} |
|
530 | 503 |
|
531 |
this.net_loading.hide();
|
|
532 |
this.cpu_loading.hide();
|
|
533 |
this.cpu_error.hide();
|
|
534 |
this.net_error.hide();
|
|
535 |
|
|
536 |
this.net_img.attr("src", this.get_images(this.stats_type).net);
|
|
537 |
this.cpu_img.attr("src", this.get_images(this.stats_type).cpu);
|
|
538 |
this.net_img.show();
|
|
539 |
this.cpu_img.show();
|
|
504 |
if (images.net) {
|
|
505 |
this.net_img.attr({src:images.net}).show();
|
|
506 |
this.net_error.hide();
|
|
507 |
} else {
|
|
508 |
this.net_img.hide(); |
|
509 |
this.net_error.show();
|
|
510 |
}
|
|
511 |
}
|
|
512 |
$(window).trigger("resize");
|
|
540 | 513 |
} |
541 | 514 |
}); |
542 | 515 |
|
b/ui/static/snf/js/ui/web/ui_main_view.js | ||
---|---|---|
676 | 676 |
// FIXME: depricated |
677 | 677 |
$(".large-spinner").remove(); |
678 | 678 |
|
679 |
storage.vms.reset_pending_actions(); |
|
680 |
storage.vms.reset_stats_update(); |
|
681 |
|
|
679 | 682 |
// show current view |
680 | 683 |
this.show_view_pane(); |
681 | 684 |
view.show(); |
... | ... | |
706 | 709 |
// trigger view change event |
707 | 710 |
this.trigger("view:change", this.current_view.view_id); |
708 | 711 |
$(window).trigger("view:change"); |
709 |
storage.vms.reset_pending_actions(); |
|
710 | 712 |
return view; |
711 | 713 |
}, |
712 | 714 |
|
b/ui/static/snf/js/views.js | ||
---|---|---|
207 | 207 |
onClose: function () {}, |
208 | 208 |
|
209 | 209 |
show: function() { |
210 |
// close opened overlays |
|
210 | 211 |
var hidden = false; |
211 | 212 |
_.each(views._overlay_index, function(ovr){ |
212 | 213 |
if (ovr == this) { return }; |
... | ... | |
216 | 217 |
} |
217 | 218 |
}) |
218 | 219 |
|
219 |
if (hidden) { |
|
220 |
delay = 300; |
|
221 |
} else { |
|
222 |
delay = 0; |
|
223 |
} |
|
220 |
// do we need to wait for other overlays to close ??? |
|
221 |
if (hidden) { delay = 300; } else { delay = 0; } |
|
224 | 222 |
window.setTimeout(_.bind(function(){ this.overlay.load() }, this), delay) |
225 | 223 |
return this; |
226 | 224 |
}, |
Also available in: Unified diff