Revision 126a01f2
b/snf-cyclades-app/synnefo/app_settings/default/ui.py | ||
---|---|---|
117 | 117 |
UI_HANDLE_WINDOW_EXCEPTIONS = True |
118 | 118 |
|
119 | 119 |
# A list of os names that support ssh public key assignment |
120 |
UI_SUPPORT_SSH_OS_LIST = ['debian', 'fedora', 'okeanos', 'ubuntu', 'kubuntu', 'centos'] |
|
120 |
UI_SUPPORT_SSH_OS_LIST = ['debian', 'fedora', 'okeanos', 'ubuntu', 'kubuntu', |
|
121 |
'centos', 'archlinux'] |
|
121 | 122 |
|
122 | 123 |
# OS/username map to identify default user name for the specified os |
123 | 124 |
UI_OS_DEFAULT_USER_MAP = { |
... | ... | |
126 | 127 |
'windows': 'Administrator' |
127 | 128 |
} |
128 | 129 |
|
130 |
########################## |
|
131 |
# UI NETWORK VIEW SETTINGS |
|
132 |
########################## |
|
133 |
|
|
134 |
# Available network types for use to choose when creating a private network |
|
135 |
# If only one set, no select options will be displayed |
|
136 |
UI_NETWORK_AVAILABLE_NETWORK_TYPES = {'PRIVATE_FILTERED': 'mac-filtering'} |
|
137 |
|
|
138 |
# Suggested private networks to let the user choose from when creating a private |
|
139 |
# network with dhcp enabled |
|
140 |
UI_NETWORK_AVAILABLE_SUBNETS = ['10.0.0.1/24', '192.168.1.1/24'] |
|
141 |
|
|
142 |
# Whether to display already connected vm's to the network connect overlay |
|
143 |
UI_NETWORK_ALLOW_DUPLICATE_VM_NICS = False |
|
144 |
|
|
145 |
# Whether to display destroy action on private networks that contain vms. If |
|
146 |
# set to True, destroy action will only get displayed if user disconnect all |
|
147 |
# virtual machines from the network. |
|
148 |
UI_NETWORK_STRICT_DESTROY = False |
|
149 |
|
|
129 | 150 |
|
130 | 151 |
############### |
131 | 152 |
# UI EXTENSIONS |
b/snf-cyclades-app/synnefo/ui/static/snf/css/main.css | ||
---|---|---|
21 | 21 |
text-align:center; |
22 | 22 |
font-size: 16px; |
23 | 23 |
background-position: 0px 35px; |
24 |
overflow-y: scroll; |
|
24 | 25 |
} |
25 | 26 |
|
26 | 27 |
a, a:hover, a:active, a:focus, div:focus, span:focus, li:focus { |
... | ... | |
598 | 599 |
width: 140px; |
599 | 600 |
} |
600 | 601 |
|
601 |
.overlay-networks-create .form-actions { |
|
602 |
float: right; |
|
603 |
margin-top: -26px !important; |
|
602 |
.overlay-networks-create .form-action { |
|
603 |
float: left; |
|
604 |
} |
|
605 |
|
|
606 |
.overlay-networks-create .fixpos { |
|
607 |
margin-top: 3px; |
|
608 |
} |
|
609 |
|
|
610 |
.overlay-networks-create .col-fields.bordered { |
|
611 |
border-bottom: 1px solid #CCC; |
|
612 |
margin-bottom: 10px; |
|
613 |
padding-bottom: 10px; |
|
614 |
} |
|
615 |
|
|
616 |
.overlay-networks-create .col-fields { |
|
617 |
margin-bottom: 10px; |
|
618 |
} |
|
619 |
|
|
620 |
form .fields-desc { |
|
621 |
font-size: 0.8em !important; |
|
622 |
margin: 5px 0; |
|
623 |
padding-bottom: 0 !important; |
|
624 |
} |
|
625 |
|
|
626 |
.overlay-networks-create form select { |
|
627 |
padding: 1px; |
|
628 |
} |
|
629 |
|
|
630 |
.overlay-networks-create #network-create-subnet-custom { |
|
631 |
width: 125px; |
|
632 |
} |
|
633 |
|
|
634 |
.overlay-networks-create .col-fields .form-field { |
|
635 |
float: left; |
|
636 |
margin-right: 20px; |
|
637 |
} |
|
638 |
|
|
639 |
.overlay-networks-create .col-fields .right-field { |
|
640 |
float: right; |
|
641 |
width: 210px; |
|
642 |
margin-right: 0px; |
|
643 |
} |
|
644 |
|
|
645 |
.overlay-networks-create .use-dhcp { |
|
646 |
width: auto; |
|
604 | 647 |
} |
605 | 648 |
|
606 | 649 |
#wizard #start:hover, #networks-wizard .create:hover { |
... | ... | |
1095 | 1138 |
} |
1096 | 1139 |
|
1097 | 1140 |
.error-state .indicator1, .error-state .indicator2, .error-state .indicator3, .error-state .indicator4 { |
1098 |
background-color: #ff0000; |
|
1141 |
background-color: #ff0000 !important;
|
|
1099 | 1142 |
} |
1100 | 1143 |
|
1101 | 1144 |
.terminated-state .indicator1, .terminated-state .indicator2, .terminated-state .indicator3, .terminated-state .indicator4 { |
... | ... | |
2191 | 2234 |
} |
2192 | 2235 |
|
2193 | 2236 |
.network-machine h5 { |
2194 |
margin-bottom: 26px;
|
|
2237 |
margin-bottom: 20px;
|
|
2195 | 2238 |
margin-top:0px; |
2196 | 2239 |
} |
2197 | 2240 |
|
... | ... | |
2552 | 2595 |
display:none; |
2553 | 2596 |
} |
2554 | 2597 |
|
2598 |
div.network-cont.disable-destroy .actions .destroy { |
|
2599 |
display: none !important; |
|
2600 |
} |
|
2601 |
|
|
2602 |
div.network-cont.pending .actions .action-add { |
|
2603 |
display: none; |
|
2604 |
} |
|
2605 |
|
|
2606 |
div.network-cont.in-error .actions .action-add { |
|
2607 |
display: none; |
|
2608 |
} |
|
2609 |
|
|
2555 | 2610 |
div.network a.action-network-add { |
2556 | 2611 |
display: none; |
2557 | 2612 |
} |
... | ... | |
2754 | 2809 |
right:0; |
2755 | 2810 |
} |
2756 | 2811 |
|
2812 |
div.network .nic-ip { |
|
2813 |
font-size: 0.8em; |
|
2814 |
} |
|
2815 |
|
|
2757 | 2816 |
div.network div.display a { |
2758 | 2817 |
visibility: visible; |
2759 | 2818 |
} |
... | ... | |
3030 | 3089 |
h5.machine-connect { |
3031 | 3090 |
font-size: 75%; |
3032 | 3091 |
margin-bottom: 3px; |
3092 |
height: 23px; |
|
3033 | 3093 |
} |
3034 | 3094 |
|
3035 | 3095 |
.machine-connect span { |
b/snf-cyclades-app/synnefo/ui/static/snf/js/models.js | ||
---|---|---|
56 | 56 |
var baseurl = baseurl || snf.config.api_urls[this.api_type]; |
57 | 57 |
return baseurl + "/" + this.path; |
58 | 58 |
} |
59 |
|
|
60 |
var NIC_REGEX = /^nic-([0-9]+)-([0-9]+)$/ |
|
59 | 61 |
|
60 | 62 |
// i18n |
61 | 63 |
BUILDING_MESSAGES = window.BUILDING_MESSAGES || {'INIT': 'init', 'COPY': '{0}, {1}, {2}', 'FINAL': 'final'}; |
... | ... | |
337 | 339 |
|
338 | 340 |
}); |
339 | 341 |
|
340 |
//network vms list helper |
|
341 |
var NetworkVMSList = function() { |
|
342 |
this.initialize = function() { |
|
343 |
this.vms = []; |
|
344 |
this.pending = []; |
|
345 |
this.pending_for_removal = []; |
|
346 |
} |
|
347 |
|
|
348 |
this.add_pending_for_remove = function(vm_id) { |
|
349 |
if (this.pending_for_removal.indexOf(vm_id) == -1) { |
|
350 |
this.pending_for_removal.push(vm_id); |
|
351 |
} |
|
352 |
|
|
353 |
if (this.pending_for_removal.length) { |
|
354 |
this.trigger("pending:remove:add"); |
|
355 |
} |
|
356 |
}, |
|
357 |
|
|
358 |
this.add_pending = function(vm_id) { |
|
359 |
if (this.pending.indexOf(vm_id) == -1) { |
|
360 |
this.pending[this.pending.length] = vm_id; |
|
361 |
} |
|
362 |
|
|
363 |
if (this.pending.length) { |
|
364 |
this.trigger("pending:add"); |
|
365 |
} |
|
366 |
} |
|
367 |
|
|
368 |
this.check_pending = function() { |
|
369 |
var len = this.pending.length; |
|
370 |
var args = [this.pending]; |
|
371 |
this.pending = _.difference(this.pending, this.vms); |
|
372 |
if (len != this.pending.length) { |
|
373 |
if (this.pending.length == 0) { |
|
374 |
this.trigger("pending:clear"); |
|
375 |
} |
|
376 |
} |
|
377 |
|
|
378 |
var len = this.pending_for_removal.length; |
|
379 |
this.pending_for_removal = _.intersection(this.pending_for_removal, this.vms); |
|
380 |
if (this.pending_for_removal.length == 0) { |
|
381 |
this.trigger("pending:remove:clear"); |
|
382 |
} |
|
383 |
|
|
384 |
} |
|
385 |
|
|
386 |
|
|
387 |
this.add = function(vm_id) { |
|
388 |
if (this.vms.indexOf(vm_id) == -1) { |
|
389 |
this.vms[this.vms.length] = vm_id; |
|
390 |
this.trigger("network:connect", vm_id); |
|
391 |
this.check_pending(); |
|
392 |
return true; |
|
393 |
} |
|
394 |
} |
|
395 |
|
|
396 |
this.remove = function(vm_id) { |
|
397 |
if (this.vms.indexOf(vm_id) > -1) { |
|
398 |
this.vms = _.without(this.vms, vm_id); |
|
399 |
this.trigger("network:disconnect", vm_id); |
|
400 |
this.check_pending(); |
|
401 |
return true; |
|
402 |
} |
|
403 |
} |
|
404 |
|
|
405 |
this.get = function() { |
|
406 |
return this.vms; |
|
407 |
} |
|
408 |
|
|
409 |
this.list = function() { |
|
410 |
return storage.vms.filter(_.bind(function(vm){ |
|
411 |
return this.vms.indexOf(vm.id) > -1; |
|
412 |
}, this)) |
|
413 |
} |
|
414 |
|
|
415 |
this.initialize(); |
|
416 |
}; |
|
417 |
_.extend(NetworkVMSList.prototype, bb.Events); |
|
418 |
|
|
419 |
// vm networks list helper |
|
420 |
var VMNetworksList = function() { |
|
421 |
this.initialize = function() { |
|
422 |
this.networks = {}; |
|
423 |
this.network_ids = []; |
|
424 |
} |
|
425 |
|
|
426 |
this.add = function(net_id, data) { |
|
427 |
if (!this.networks[net_id]) { |
|
428 |
this.networks[net_id] = data || {}; |
|
429 |
this.network_ids[this.network_ids.length] = net_id; |
|
430 |
this.trigger("network:connect", net_id); |
|
431 |
return true; |
|
432 |
} |
|
433 |
} |
|
434 |
|
|
435 |
this.remove = function(net_id) { |
|
436 |
if (this.networks[net_id]) { |
|
437 |
delete this.networks[net_id]; |
|
438 |
this.network_ids = _.without(this.network_ids, net_id); |
|
439 |
this.trigger("network:disconnect", net_id); |
|
440 |
return true; |
|
441 |
} |
|
442 |
return false; |
|
443 |
} |
|
444 |
|
|
445 |
this.get = function() { |
|
446 |
return this.networks; |
|
447 |
} |
|
448 |
|
|
449 |
this.list = function() { |
|
450 |
return storage.networks.filter(_.bind(function(net){ |
|
451 |
return this.network_ids.indexOf(net.id) > -1; |
|
452 |
}, this)) |
|
453 |
} |
|
454 |
|
|
455 |
this.initialize(); |
|
456 |
}; |
|
457 |
_.extend(VMNetworksList.prototype, bb.Events); |
|
458 |
|
|
459 | 342 |
models.ParamsList = function(){this.initialize.apply(this, arguments)}; |
460 | 343 |
_.extend(models.ParamsList.prototype, bb.Events, { |
461 | 344 |
|
... | ... | |
559 | 442 |
models.Network = models.Model.extend({ |
560 | 443 |
path: 'networks', |
561 | 444 |
has_status: true, |
445 |
defaults: {'connecting':0}, |
|
562 | 446 |
|
563 | 447 |
initialize: function() { |
564 |
this.vms = new NetworkVMSList(); |
|
565 |
this.vms.bind("pending:add", _.bind(this.handle_pending_connections, this, "add")); |
|
566 |
this.vms.bind("pending:clear", _.bind(this.handle_pending_connections, this, "clear")); |
|
567 |
this.vms.bind("pending:remove:add", _.bind(this.handle_pending_connections, this, "add")); |
|
568 |
this.vms.bind("pending:remove:clear", _.bind(this.handle_pending_connections, this, "clear")); |
|
569 |
|
|
570 | 448 |
var ret = models.Network.__super__.initialize.apply(this, arguments); |
571 |
|
|
572 |
storage.vms.bind("change:linked_to_nets", _.bind(this.update_connections, this, "vm:change")); |
|
573 |
storage.vms.bind("add", _.bind(this.update_connections, this, "add")); |
|
574 |
storage.vms.bind("remove", _.bind(this.update_connections, this, "remove")); |
|
575 |
storage.vms.bind("reset", _.bind(this.update_connections, this, "reset")); |
|
576 |
|
|
577 |
this.bind("change:linked_to", _.bind(this.update_connections, this, "net:change")); |
|
578 |
this.update_connections(); |
|
579 |
this.update_state(); |
|
580 |
|
|
581 | 449 |
this.set({"actions": new models.ParamsList(this, "actions")}); |
582 |
|
|
450 |
this.update_state(); |
|
451 |
this.bind("change:nics", _.bind(synnefo.storage.nics.update_net_nics, synnefo.storage.nics)); |
|
452 |
this.bind("change:status", _.bind(this.update_state, this)); |
|
583 | 453 |
return ret; |
584 | 454 |
}, |
585 | 455 |
|
... | ... | |
588 | 458 |
attrs.actions = _.clone(this.get("actions").actions); |
589 | 459 |
return attrs; |
590 | 460 |
}, |
461 |
|
|
462 |
set_state: function(val) { |
|
463 |
if (val == "PENDING" && this.get("state") == "DESTORY") { |
|
464 |
return "DESTROY"; |
|
465 |
} |
|
466 |
return val; |
|
467 |
}, |
|
591 | 468 |
|
592 | 469 |
update_state: function() { |
593 |
if (this.vms.pending.length) {
|
|
470 |
if (this.get("connecting") > 0) {
|
|
594 | 471 |
this.set({state: "CONNECTING"}); |
595 | 472 |
return |
596 | 473 |
} |
597 |
|
|
598 |
if (this.vms.pending_for_removal.length) {
|
|
474 |
|
|
475 |
if (this.get_nics(function(nic){ return nic.get("removing") == 1}).length > 0) {
|
|
599 | 476 |
this.set({state: "DISCONNECTING"}); |
600 | 477 |
return |
601 | 478 |
} |
602 | 479 |
|
603 |
var firewalling = false;
|
|
604 |
_.each(this.vms.get(), _.bind(function(vm_id){
|
|
605 |
var vm = storage.vms.get(vm_id);
|
|
606 |
if (!vm) { return };
|
|
607 |
if (!_.isEmpty(vm.pending_firewalls)) { |
|
608 |
this.set({state:"FIREWALLING"});
|
|
609 |
firewalling = true;
|
|
610 |
return false;
|
|
611 |
} |
|
612 |
},this));
|
|
613 |
if (firewalling) { return };
|
|
480 |
if (this.contains_firewalling_nics() > 0) {
|
|
481 |
this.set({state: "FIREWALLING"});
|
|
482 |
return
|
|
483 |
}
|
|
484 |
|
|
485 |
if (this.get("state") == "DESTROY") {
|
|
486 |
this.set({"destroyed":1});
|
|
487 |
}
|
|
488 |
|
|
489 |
this.set({state:this.get('status')});
|
|
490 |
},
|
|
614 | 491 |
|
615 |
this.set({state:"NORMAL"}); |
|
492 |
is_public: function() { |
|
493 |
return this.id === "public"; |
|
616 | 494 |
}, |
617 | 495 |
|
618 |
handle_pending_connections: function(action) { |
|
496 |
decrease_connecting: function() { |
|
497 |
var conn = this.get("connecting"); |
|
498 |
if (!conn) { conn = 0 }; |
|
499 |
if (conn > 0) { |
|
500 |
conn--; |
|
501 |
} |
|
502 |
this.set({"connecting": conn}); |
|
619 | 503 |
this.update_state(); |
620 | 504 |
}, |
621 | 505 |
|
622 |
// handle vm/network connections |
|
623 |
update_connections: function(action, model) { |
|
624 |
|
|
625 |
// vm removed disconnect vm from network |
|
626 |
if (action == "remove") { |
|
627 |
var removed_from_net = this.vms.remove(model.id); |
|
628 |
var removed_from_vm = model.networks.remove(this.id); |
|
629 |
if (removed_from_net) {this.trigger("vm:disconnect", model, this); this.change()}; |
|
630 |
if (removed_from_vm) {model.trigger("network:disconnect", this, model); this.change()}; |
|
631 |
return; |
|
632 |
} |
|
633 |
|
|
634 |
// update links for all vms |
|
635 |
var links = this.get("linked_to"); |
|
636 |
storage.vms.each(_.bind(function(vm) { |
|
637 |
var vm_links = vm.get("linked_to") || []; |
|
638 |
if (vm_links.indexOf(this.id) > -1) { |
|
639 |
// vm has connection to current network |
|
640 |
if (links.indexOf(vm.id) > -1) { |
|
641 |
// and network has connection to vm, so try |
|
642 |
// to append it |
|
643 |
var add_to_net = this.vms.add(vm.id); |
|
644 |
var index = _.indexOf(vm_links, this.id); |
|
645 |
var add_to_vm = vm.networks.add(this.id, vm.get("linked_to_nets")[index]); |
|
646 |
|
|
647 |
// call only if connection did not existed |
|
648 |
if (add_to_net) {this.trigger("vm:connect", vm, this); this.change()}; |
|
649 |
if (add_to_vm) {vm.trigger("network:connect", this, vm); vm.change()}; |
|
650 |
} else { |
|
651 |
// no connection, try to remove it |
|
652 |
var removed_from_net = this.vms.remove(vm.id); |
|
653 |
var removed_from_vm = vm.networks.remove(this.id); |
|
654 |
if (removed_from_net) {this.trigger("vm:disconnect", vm, this); this.change()}; |
|
655 |
if (removed_from_vm) {vm.trigger("network:disconnect", this, vm); vm.change()}; |
|
656 |
} |
|
657 |
} else { |
|
658 |
// vm has no connection to current network, try to remove it |
|
659 |
var removed_from_net = this.vms.remove(vm.id); |
|
660 |
var removed_from_vm = vm.networks.remove(this.id); |
|
661 |
if (removed_from_net) {this.trigger("vm:disconnect", vm, this); this.change()}; |
|
662 |
if (removed_from_vm) {vm.trigger("network:disconnect", this, vm); vm.change()}; |
|
663 |
} |
|
664 |
},this)); |
|
506 |
increase_connecting: function() { |
|
507 |
var conn = this.get("connecting"); |
|
508 |
if (!conn) { conn = 0 }; |
|
509 |
conn++; |
|
510 |
this.set({"connecting": conn}); |
|
511 |
this.update_state(); |
|
665 | 512 |
}, |
666 | 513 |
|
667 |
is_public: function() {
|
|
668 |
return this.id == "public";
|
|
514 |
connected_to: function(vm) {
|
|
515 |
return this.get('linked_to').indexOf(""+vm.id) > -1;
|
|
669 | 516 |
}, |
670 | 517 |
|
671 |
contains_vm: function(vm) { |
|
672 |
var net_vm_exists = this.vms.get().indexOf(vm.id) > -1; |
|
673 |
var vm_net_exists = vm.is_connected_to(this); |
|
674 |
return net_vm_exists && vm_net_exists; |
|
518 |
connected_with_nic_id: function(nic_id) { |
|
519 |
return _.keys(this.get('nics')).indexOf(nic_id) > -1; |
|
675 | 520 |
}, |
676 |
|
|
521 |
|
|
522 |
get_nics: function(filter) { |
|
523 |
var nics = synnefo.storage.nics.filter(function(nic) { |
|
524 |
return nic.get('network_id') == this.id; |
|
525 |
}, this); |
|
526 |
|
|
527 |
if (filter) { |
|
528 |
return _.filter(nics, filter); |
|
529 |
} |
|
530 |
return nics; |
|
531 |
}, |
|
532 |
|
|
533 |
contains_firewalling_nics: function() { |
|
534 |
return this.get_nics(function(n){return n.get('pending_firewall')}).length |
|
535 |
}, |
|
536 |
|
|
677 | 537 |
call: function(action, params, success, error) { |
678 | 538 |
if (action == "destroy") { |
679 | 539 |
this.set({state:"DESTROY"}); |
680 |
this.get("actions").remove("destroy"); |
|
540 |
this.get("actions").remove("destroy", params);
|
|
681 | 541 |
this.remove(_.bind(function(){ |
682 | 542 |
success(); |
683 | 543 |
}, this), error); |
684 | 544 |
} |
685 | 545 |
|
686 | 546 |
if (action == "disconnect") { |
687 |
_.each(params, _.bind(function(vm_id) { |
|
688 |
var vm = snf.storage.vms.get(vm_id); |
|
689 |
this.get("actions").remove("disconnect", vm_id); |
|
690 |
if (vm) { |
|
691 |
this.remove_vm(vm, success, error); |
|
547 |
if (this.get("state") == "DESTROY") { |
|
548 |
return; |
|
549 |
} |
|
550 |
|
|
551 |
_.each(params, _.bind(function(nic_id) { |
|
552 |
var nic = snf.storage.nics.get(nic_id); |
|
553 |
this.get("actions").remove("disconnect", nic_id); |
|
554 |
if (nic) { |
|
555 |
this.remove_nic(nic, success, error); |
|
692 | 556 |
} |
693 | 557 |
}, this)); |
694 | 558 |
} |
... | ... | |
700 | 564 |
return this.api_call(this.api_path() + "/action", "create", |
701 | 565 |
payload, |
702 | 566 |
_.bind(function(){ |
703 |
this.vms.add_pending(vm.id); |
|
567 |
//this.vms.add_pending(vm.id); |
|
568 |
this.increase_connecting(); |
|
704 | 569 |
if (callback) {callback()} |
705 | 570 |
},this), error); |
706 | 571 |
}, |
707 | 572 |
|
708 |
remove_vm: function (vm, callback, error, options) {
|
|
709 |
var payload = {remove:{serverRef:"" + vm.id}};
|
|
573 |
remove_nic: function (nic, callback, error, options) {
|
|
574 |
var payload = {remove:{attachment:"" + nic.get("attachment_id")}};
|
|
710 | 575 |
payload._options = options || {}; |
711 | 576 |
return this.api_call(this.api_path() + "/action", "create", |
712 |
{remove:{serverRef:"" + vm.id}},
|
|
577 |
payload,
|
|
713 | 578 |
_.bind(function(){ |
714 |
this.vms.add_pending_for_remove(vm.id); |
|
579 |
nic.set({"removing": 1}); |
|
580 |
nic.get_network().update_state(); |
|
581 |
//this.vms.add_pending_for_remove(vm.id); |
|
715 | 582 |
if (callback) {callback()} |
716 | 583 |
},this), error); |
717 | 584 |
}, |
... | ... | |
730 | 597 |
}, |
731 | 598 |
|
732 | 599 |
get_connectable_vms: function() { |
733 |
var servers = this.vms.list(); |
|
734 | 600 |
return storage.vms.filter(function(vm){ |
735 |
return servers.indexOf(vm) == -1 && !vm.in_error_state();
|
|
601 |
return !vm.in_error_state(); |
|
736 | 602 |
}) |
737 | 603 |
}, |
738 | 604 |
|
739 | 605 |
state_message: function() { |
740 |
if (this.get("state") == "NORMAL" && this.is_public()) { |
|
741 |
return "Public network"; |
|
606 |
if (this.get("state") == "ACTIVE" && !this.is_public()) { |
|
607 |
if (this.get("cidr") && this.get("dhcp") == true) { |
|
608 |
return this.get("cidr"); |
|
609 |
} else { |
|
610 |
return "Private network"; |
|
611 |
} |
|
612 |
} |
|
613 |
if (this.get("state") == "ACTIVE" && this.is_public()) { |
|
614 |
return "Public network"; |
|
742 | 615 |
} |
743 | 616 |
|
744 | 617 |
return models.Network.STATES[this.get("state")]; |
... | ... | |
755 | 628 |
this.call(action, with_params, success, error); |
756 | 629 |
}, this)); |
757 | 630 |
}, this)); |
631 |
this.get("actions").reset(); |
|
758 | 632 |
} |
759 | 633 |
}); |
760 | 634 |
|
761 | 635 |
models.Network.STATES = { |
762 |
'NORMAL': 'Private network',
|
|
636 |
'ACTIVE': 'Private network',
|
|
763 | 637 |
'CONNECTING': 'Connecting...', |
764 | 638 |
'DISCONNECTING': 'Disconnecting...', |
765 | 639 |
'FIREWALLING': 'Firewall update...', |
766 |
'DESTROY': 'Destroying...' |
|
640 |
'DESTROY': 'Destroying...', |
|
641 |
'PENDING': 'Pending...', |
|
642 |
'ERROR': 'Error' |
|
767 | 643 |
} |
768 | 644 |
|
769 | 645 |
models.Network.STATES_TRANSITIONS = { |
770 |
'CONNECTING': ['NORMAL'], |
|
771 |
'DISCONNECTING': ['NORMAL'], |
|
772 |
'FIREWALLING': ['NORMAL'] |
|
646 |
'CONNECTING': ['ACTIVE'], |
|
647 |
'DISCONNECTING': ['ACTIVE'], |
|
648 |
'PENDING': ['ACTIVE'], |
|
649 |
'FIREWALLING': ['ACTIVE'] |
|
773 | 650 |
} |
774 | 651 |
|
775 | 652 |
// Virtualmachine model |
... | ... | |
778 | 655 |
path: 'servers', |
779 | 656 |
has_status: true, |
780 | 657 |
initialize: function(params) { |
781 |
this.networks = new VMNetworksList(); |
|
782 | 658 |
|
783 | 659 |
this.pending_firewalls = {}; |
784 | 660 |
|
... | ... | |
807 | 683 |
this.bind("change:progress", _.bind(this.update_building_progress, this)); |
808 | 684 |
this.update_building_progress(); |
809 | 685 |
|
810 |
this.bind("change:firewalls", _.bind(this.handle_firewall_change, this)); |
|
811 |
|
|
812 | 686 |
// default values |
813 |
this.set({linked_to_nets:this.get("linked_to_nets") || []}); |
|
814 |
this.set({firewalls:this.get("firewalls") || []}); |
|
815 |
|
|
816 |
this.bind("change:state", _.bind(function(){if (this.state() == "DESTROY") { this.handle_destroy() }}, this)) |
|
817 |
}, |
|
818 |
|
|
819 |
handle_firewall_change: function() { |
|
687 |
this.bind("change:state", _.bind(function(){ |
|
688 |
if (this.state() == "DESTROY") { |
|
689 |
this.handle_destroy() |
|
690 |
} |
|
691 |
}, this)); |
|
820 | 692 |
|
821 |
}, |
|
822 |
|
|
823 |
set_linked_to_nets: function(data) { |
|
824 |
this.set({"linked_to":_.map(data, function(n){ return n.id})}); |
|
825 |
return data; |
|
693 |
this.bind("change:nics", _.bind(synnefo.storage.nics.update_vm_nics, synnefo.storage.nics)); |
|
826 | 694 |
}, |
827 | 695 |
|
828 |
is_connected_to: function(net) { |
|
829 |
return _.filter(this.networks.list(), function(n){return n.id == net.id}).length > 0; |
|
830 |
}, |
|
831 |
|
|
832 | 696 |
status: function(st) { |
833 | 697 |
if (!st) { return this.get("status")} |
834 | 698 |
return this.set({status:st}); |
... | ... | |
1103 | 967 |
return models.VM.CONNECT_STATES.indexOf(this.state()) > -1; |
1104 | 968 |
}, |
1105 | 969 |
|
1106 |
set_firewalls: function(data) { |
|
1107 |
_.each(data, _.bind(function(val, key){ |
|
1108 |
if (this.pending_firewalls && this.pending_firewalls[key] && this.pending_firewalls[key] == val) { |
|
1109 |
this.require_reboot(); |
|
1110 |
this.remove_pending_firewall(key, val); |
|
1111 |
} |
|
1112 |
}, this)); |
|
1113 |
return data; |
|
1114 |
}, |
|
1115 |
|
|
1116 |
remove_pending_firewall: function(net_id, value) { |
|
1117 |
if (this.pending_firewalls[net_id] == value) { |
|
1118 |
delete this.pending_firewalls[net_id]; |
|
1119 |
storage.networks.get(net_id).update_state(); |
|
1120 |
} |
|
1121 |
}, |
|
1122 |
|
|
1123 | 970 |
remove_meta: function(key, complete, error) { |
1124 | 971 |
var url = this.api_path() + "/meta/" + key; |
1125 | 972 |
this.api_call(url, "delete", undefined, complete, error); |
... | ... | |
1139 | 986 |
this.api_call(url, "update", payload, complete, error); |
1140 | 987 |
}, |
1141 | 988 |
|
1142 |
set_firewall: function(net_id, value, callback, error, options) { |
|
1143 |
if (this.get("firewalls") && this.get("firewalls")[net_id] == value) { return } |
|
1144 |
|
|
1145 |
this.pending_firewalls[net_id] = value; |
|
1146 |
this.trigger("change", this, this); |
|
1147 |
var payload = {"firewallProfile":{"profile":value}}; |
|
1148 |
payload._options = _.extend({critical: false}, options); |
|
1149 |
|
|
1150 |
// reset firewall state on error |
|
1151 |
var error_cb = _.bind(function() { |
|
1152 |
thi |
|
1153 |
}, this); |
|
1154 |
|
|
1155 |
this.api_call(this.api_path() + "/action", "create", payload, callback, error); |
|
1156 |
storage.networks.get(net_id).update_state(); |
|
1157 |
}, |
|
1158 | 989 |
|
1159 |
firewall_pending: function(net_id) { |
|
1160 |
return this.pending_firewalls[net_id] != undefined; |
|
1161 |
}, |
|
1162 |
|
|
1163 | 990 |
// update/get the state of the machine |
1164 | 991 |
state: function() { |
1165 | 992 |
var args = slice.call(arguments); |
... | ... | |
1241 | 1068 |
get_gui: function() { |
1242 | 1069 |
return this.get_meta('GUI'); |
1243 | 1070 |
}, |
1071 |
|
|
1072 |
connected_to: function(net) { |
|
1073 |
return this.get('linked_to').indexOf(net.id) > -1; |
|
1074 |
}, |
|
1244 | 1075 |
|
1245 |
// get public ip addresses |
|
1246 |
// TODO: public network is always the 0 index ??? |
|
1247 |
get_addresses: function(net_id) { |
|
1248 |
var net_id = net_id || "public"; |
|
1249 |
|
|
1250 |
var info = this.get_network_info(net_id); |
|
1251 |
if (!info) { return {} }; |
|
1252 |
addrs = {}; |
|
1253 |
_.each(info.values, function(addr) { |
|
1254 |
addrs["ip" + addr.version] = addr.addr; |
|
1255 |
}); |
|
1256 |
return addrs |
|
1076 |
connected_with_nic_id: function(nic_id) { |
|
1077 |
return _.keys(this.get('nics')).indexOf(nic_id) > -1; |
|
1257 | 1078 |
}, |
1258 | 1079 |
|
1259 |
get_network_info: function(net_id) {
|
|
1260 |
var net_id = net_id || "public";
|
|
1261 |
|
|
1262 |
if (!this.networks.network_ids.length) { return {} };
|
|
1080 |
get_nics: function(filter) {
|
|
1081 |
ret = synnefo.storage.nics.filter(function(nic) {
|
|
1082 |
return parseInt(nic.get('vm_id')) == this.id; |
|
1083 |
}, this);
|
|
1263 | 1084 |
|
1264 |
var addresses = this.networks.get(); |
|
1265 |
try { |
|
1266 |
return _.select(addresses, function(net, key){return key == net_id })[0]; |
|
1267 |
} catch (err) { |
|
1268 |
//this.log.debug("Cannot find network {0}".format(net_id)) |
|
1085 |
if (filter) { |
|
1086 |
return _.filter(ret, filter); |
|
1269 | 1087 |
} |
1088 |
|
|
1089 |
return ret; |
|
1090 |
}, |
|
1091 |
|
|
1092 |
get_net_nics: function(net_id) { |
|
1093 |
return this.get_nics(function(n){return n.get('network_id') == net_id}); |
|
1270 | 1094 |
}, |
1271 | 1095 |
|
1272 |
firewall_profile: function(net_id) { |
|
1273 |
var net_id = net_id || "public"; |
|
1274 |
var firewalls = this.get("firewalls"); |
|
1275 |
return firewalls[net_id]; |
|
1096 |
get_public_nic: function() { |
|
1097 |
return this.get_nics(function(n){ return n.get('network_id') == 'public'})[0]; |
|
1276 | 1098 |
}, |
1277 | 1099 |
|
1278 |
has_firewall: function(net_id) { |
|
1279 |
var net_id = net_id || "public"; |
|
1280 |
return ["ENABLED","PROTECTED"].indexOf(this.firewall_profile()) > -1; |
|
1100 |
get_nic: function(net_id) { |
|
1101 |
}, |
|
1102 |
|
|
1103 |
has_firewall: function() { |
|
1104 |
var nic = this.get_public_nic(); |
|
1105 |
if (nic) { |
|
1106 |
var profile = nic.get('firewallProfile'); |
|
1107 |
return ['ENABLED', 'PROTECTED'].indexOf(profile) > -1; |
|
1108 |
} |
|
1109 |
return false; |
|
1110 |
}, |
|
1111 |
|
|
1112 |
get_firewall_profile: function() { |
|
1113 |
var nic = this.get_public_nic(); |
|
1114 |
if (nic) { |
|
1115 |
return nic.get('firewallProfile'); |
|
1116 |
} |
|
1117 |
return null; |
|
1118 |
}, |
|
1119 |
|
|
1120 |
get_addresses: function() { |
|
1121 |
var pnic = this.get_public_nic(); |
|
1122 |
if (!pnic) { return {'ip4': undefined, 'ip6': undefined }}; |
|
1123 |
return {'ip4': pnic.get('ipv4'), 'ip6': pnic.get('ipv6')}; |
|
1281 | 1124 |
}, |
1282 | 1125 |
|
1283 | 1126 |
// get actions that the user can execute |
... | ... | |
1540 | 1383 |
path: 'networks', |
1541 | 1384 |
details: true, |
1542 | 1385 |
//noUpdate: true, |
1543 |
defaults: {'linked_to':[]}, |
|
1544 |
|
|
1386 |
defaults: {'nics':[],'linked_to':[]},
|
|
1387 |
|
|
1545 | 1388 |
parse: function (resp, xhr) { |
1546 | 1389 |
// FIXME: depricated global var |
1547 | 1390 |
if (!resp) { return []}; |
... | ... | |
1550 | 1393 |
return data; |
1551 | 1394 |
}, |
1552 | 1395 |
|
1396 |
add: function() { |
|
1397 |
ret = models.Networks.__super__.add.apply(this, arguments); |
|
1398 |
// update nics after each network addition |
|
1399 |
ret.each(function(r){ |
|
1400 |
synnefo.storage.nics.update_net_nics(r); |
|
1401 |
}); |
|
1402 |
}, |
|
1403 |
|
|
1553 | 1404 |
reset_pending_actions: function() { |
1554 | 1405 |
this.each(function(net) { |
1555 | 1406 |
net.get("actions").reset(); |
1556 |
}) |
|
1407 |
});
|
|
1557 | 1408 |
}, |
1558 | 1409 |
|
1559 | 1410 |
do_all_pending_actions: function() { |
... | ... | |
1563 | 1414 |
}, |
1564 | 1415 |
|
1565 | 1416 |
parse_net_api_data: function(data) { |
1566 |
if (data.servers && data.servers.values) { |
|
1567 |
data['linked_to'] = data.servers.values; |
|
1417 |
// append nic metadata |
|
1418 |
// net.get('nics') contains a list of vm/index objects |
|
1419 |
// e.g. {'vm_id':12231, 'index':1} |
|
1420 |
// net.get('linked_to') contains a list of vms the network is |
|
1421 |
// connected to e.g. [1001, 1002] |
|
1422 |
if (data.attachments && data.attachments.values) { |
|
1423 |
data['nics'] = {}; |
|
1424 |
data['linked_to'] = []; |
|
1425 |
_.each(data.attachments.values, function(nic_id){ |
|
1426 |
|
|
1427 |
var vm_id = NIC_REGEX.exec(nic_id)[1]; |
|
1428 |
var nic_index = parseInt(NIC_REGEX.exec(nic_id)[2]); |
|
1429 |
|
|
1430 |
if (vm_id !== undefined && nic_index !== undefined) { |
|
1431 |
data['nics'][nic_id] = { |
|
1432 |
'vm_id': vm_id, |
|
1433 |
'index': nic_index, |
|
1434 |
'id': nic_id |
|
1435 |
}; |
|
1436 |
if (data['linked_to'].indexOf(vm_id) == -1) { |
|
1437 |
data['linked_to'].push(vm_id); |
|
1438 |
} |
|
1439 |
} |
|
1440 |
}); |
|
1568 | 1441 |
} |
1569 | 1442 |
return data; |
1570 | 1443 |
}, |
1571 | 1444 |
|
1572 |
create: function (name, callback) { |
|
1573 |
return this.api_call(this.path, "create", {network:{name:name}}, callback); |
|
1445 |
create: function (name, type, cidr, dhcp, callback) { |
|
1446 |
var params = { |
|
1447 |
network:{ |
|
1448 |
name:name |
|
1449 |
} |
|
1450 |
}; |
|
1451 |
|
|
1452 |
if (type) { |
|
1453 |
params.network.type = type; |
|
1454 |
} |
|
1455 |
if (cidr) { |
|
1456 |
params.network.cidr = cidr; |
|
1457 |
} |
|
1458 |
if (dhcp) { |
|
1459 |
params.network.dhcp = dhcp; |
|
1460 |
} |
|
1461 |
|
|
1462 |
if (dhcp === false) { |
|
1463 |
params.network.dhcp = false; |
|
1464 |
} |
|
1465 |
|
|
1466 |
return this.api_call(this.path, "create", params, callback); |
|
1574 | 1467 |
} |
1575 | 1468 |
}) |
1576 | 1469 |
|
... | ... | |
1588 | 1481 |
// api url |
1589 | 1482 |
update_unknown_id: function(id, callback) { |
1590 | 1483 |
var url = getUrl.call(this) + "/" + id; |
1591 |
this.api_call(this.path + "/" + id, this.read_method, {_options:{async:true, skip_api_error:true}}, undefined, |
|
1484 |
this.api_call(this.path + "/" + id, this.read_method, { |
|
1485 |
_options:{ |
|
1486 |
async:true, |
|
1487 |
skip_api_error:true} |
|
1488 |
}, undefined, |
|
1592 | 1489 |
_.bind(function() { |
1593 | 1490 |
if (!this.get(id)) { |
1594 | 1491 |
if (this.fallback_service) { |
... | ... | |
1783 | 1680 |
path: 'servers', |
1784 | 1681 |
details: true, |
1785 | 1682 |
copy_image_meta: true, |
1786 |
|
|
1683 |
|
|
1787 | 1684 |
parse: function (resp, xhr) { |
1788 | 1685 |
// FIXME: depricated after refactoring |
1789 | 1686 |
var data = resp; |
... | ... | |
1791 | 1688 |
data = _.filter(_.map(resp.servers.values, _.bind(this.parse_vm_api_data, this)), function(v){return v}); |
1792 | 1689 |
return data; |
1793 | 1690 |
}, |
1691 |
|
|
1692 |
add: function() { |
|
1693 |
ret = models.VMS.__super__.add.apply(this, arguments); |
|
1694 |
ret.each(function(r){ |
|
1695 |
synnefo.storage.nics.update_vm_nics(r); |
|
1696 |
}); |
|
1697 |
}, |
|
1794 | 1698 |
|
1795 | 1699 |
get_reboot_required: function() { |
1796 | 1700 |
return this.filter(function(vm){return vm.get("reboot_required") == true}) |
... | ... | |
1860 | 1764 |
data['OS'] = data.metadata.values.OS || "okeanos"; |
1861 | 1765 |
} |
1862 | 1766 |
|
1767 |
|
|
1768 |
// network metadata |
|
1863 | 1769 |
data['firewalls'] = {}; |
1864 |
if (data['addresses'] && data['addresses'].values) { |
|
1865 |
data['linked_to_nets'] = data['addresses'].values; |
|
1866 |
_.each(data['addresses'].values, function(f){ |
|
1867 |
if (f['firewallProfile']) { |
|
1868 |
data['firewalls'][f['id']] = f['firewallProfile'] |
|
1770 |
data['nics'] = {}; |
|
1771 |
data['linked_to'] = []; |
|
1772 |
|
|
1773 |
if (data['attachments'] && data['attachments'].values) { |
|
1774 |
var nics = data['attachments'].values; |
|
1775 |
_.each(nics, function(nic) { |
|
1776 |
var net_id = nic.network_id; |
|
1777 |
var index = parseInt(NIC_REGEX.exec(nic.id)[2]); |
|
1778 |
if (data['linked_to'].indexOf(net_id) == -1) { |
|
1779 |
data['linked_to'].push(net_id); |
|
1869 | 1780 |
} |
1870 |
}); |
|
1781 |
|
|
1782 |
data['nics'][nic.id] = nic; |
|
1783 |
}) |
|
1871 | 1784 |
} |
1872 | 1785 |
|
1873 | 1786 |
// if vm has no metadata, no metadata object |
... | ... | |
1894 | 1807 |
} |
1895 | 1808 |
|
1896 | 1809 |
}) |
1810 |
|
|
1811 |
models.NIC = models.Model.extend({ |
|
1812 |
|
|
1813 |
initialize: function() { |
|
1814 |
models.NIC.__super__.initialize.apply(this, arguments); |
|
1815 |
this.pending_for_firewall = false; |
|
1816 |
this.bind("change:firewallProfile", _.bind(this.check_firewall, this)); |
|
1817 |
this.bind("change:pending_firewall", function(nic) { |
|
1818 |
nic.get_network().update_state(); |
|
1819 |
}); |
|
1820 |
this.get_vm().bind("remove", function(){ |
|
1821 |
this.collection.remove(this); |
|
1822 |
}, this); |
|
1823 |
this.get_network().bind("remove", function(){ |
|
1824 |
try { |
|
1825 |
this.collection.remove(this); |
|
1826 |
} catch (err) {}; |
|
1827 |
}, this); |
|
1828 |
}, |
|
1829 |
|
|
1830 |
get_vm: function() { |
|
1831 |
return synnefo.storage.vms.get(parseInt(this.get('vm_id'))); |
|
1832 |
}, |
|
1833 |
|
|
1834 |
get_network: function() { |
|
1835 |
return synnefo.storage.networks.get(this.get('network_id')); |
|
1836 |
}, |
|
1837 |
|
|
1838 |
get_v6_address: function() { |
|
1839 |
return this.get("ipv6"); |
|
1840 |
}, |
|
1841 |
|
|
1842 |
get_v4_address: function() { |
|
1843 |
return this.get("ipv4"); |
|
1844 |
}, |
|
1845 |
|
|
1846 |
set_firewall: function(value, callback, error, options) { |
|
1847 |
var net_id = this.get('network_id'); |
|
1848 |
var self = this; |
|
1849 |
|
|
1850 |
// api call data |
|
1851 |
var payload = {"firewallProfile":{"profile":value}}; |
|
1852 |
payload._options = _.extend({critical: false}, options); |
|
1853 |
|
|
1854 |
this.set({'pending_firewall': value}); |
|
1855 |
this.set({'pending_firewall_sending': true}); |
|
1856 |
|
|
1857 |
var success_cb = function() { |
|
1858 |
if (callback) { |
|
1859 |
callback(); |
|
1860 |
} |
|
1861 |
self.set({'pending_firewall_sending': false}); |
|
1862 |
}; |
|
1863 |
|
|
1864 |
var error_cb = function() { |
|
1865 |
self.reset_pending_firewall(); |
|
1866 |
} |
|
1867 |
|
|
1868 |
this.get_vm().api_call(this.get_vm().api_path() + "/action", "create", payload, success_cb, error_cb); |
|
1869 |
}, |
|
1870 |
|
|
1871 |
reset_pending_firewall: function() { |
|
1872 |
this.set({'pending_firewall': false}); |
|
1873 |
}, |
|
1874 |
|
|
1875 |
check_firewall: function() { |
|
1876 |
var firewall = this.get('firewallProfile'); |
|
1877 |
var pending = this.get('pending_firewall'); |
|
1878 |
this.reset_pending_firewall(); |
|
1879 |
} |
|
1880 |
|
|
1881 |
}); |
|
1882 |
|
|
1883 |
models.NICs = models.Collection.extend({ |
|
1884 |
model: models.NIC, |
|
1885 |
|
|
1886 |
add_or_update: function(nic_id, data, vm) { |
|
1887 |
var params = _.clone(data); |
|
1888 |
params.attachment_id = params.id; |
|
1889 |
params.id = params.id + '-' + params.network_id; |
|
1890 |
params.vm_id = parseInt(NIC_REGEX.exec(nic_id)[1]); |
|
1891 |
|
|
1892 |
if (!this.get(params.id)) { |
|
1893 |
this.add(params); |
|
1894 |
var nic = this.get(params.id); |
|
1895 |
nic.get_network().decrease_connecting(); |
|
1896 |
nic.bind("remove", function() { |
|
1897 |
nic.set({"removing": 0}); |
|
1898 |
if (this.get_network()) { |
|
1899 |
// network might got removed before nic |
|
1900 |
nic.get_network().update_state(); |
|
1901 |
} |
|
1902 |
}) |
|
1903 |
} else { |
|
1904 |
this.get(params.id).set(params); |
|
1905 |
} |
|
1906 |
}, |
|
1907 |
|
|
1908 |
reset_nics: function(nics, filter_attr, filter_val) { |
|
1909 |
var nics_to_check = this.filter(function(nic) { |
|
1910 |
return nic.get(filter_attr) == filter_val; |
|
1911 |
}); |
|
1912 |
|
|
1913 |
_.each(nics_to_check, function(nic) { |
|
1914 |
if (nics.indexOf(nic.get('id')) == -1) { |
|
1915 |
this.remove(nic); |
|
1916 |
} else { |
|
1917 |
} |
|
1918 |
}, this); |
|
1919 |
}, |
|
1920 |
|
|
1921 |
update_vm_nics: function(vm) { |
|
1922 |
var nics = vm.get('nics'); |
|
1923 |
this.reset_nics(_.map(nics, function(nic, key){ |
|
1924 |
return key + "-" + nic.network_id; |
|
1925 |
}), 'vm_id', vm.id); |
|
1926 |
|
|
1927 |
_.each(nics, function(val, key) { |
|
1928 |
var net = synnefo.storage.networks.get(val.network_id); |
|
1929 |
if (net && net.connected_with_nic_id(key) && vm.connected_with_nic_id(key)) { |
|
1930 |
this.add_or_update(key, vm.get('nics')[key], vm); |
|
1931 |
} |
|
1932 |
}, this); |
|
1933 |
}, |
|
1934 |
|
|
1935 |
update_net_nics: function(net) { |
|
1936 |
var nics = net.get('nics'); |
|
1937 |
this.reset_nics(_.map(nics, function(nic, key){ |
|
1938 |
return key + "-" + net.get('id'); |
|
1939 |
}), 'network_id', net.id); |
|
1940 |
|
|
1941 |
_.each(nics, function(val, key) { |
|
1942 |
var vm = synnefo.storage.vms.get(val.vm_id); |
|
1943 |
if (vm && net.connected_with_nic_id(key) && vm.connected_with_nic_id(key)) { |
|
1944 |
this.add_or_update(key, vm.get('nics')[key], vm); |
|
1945 |
} |
|
1946 |
}, this); |
|
1947 |
} |
|
1948 |
}); |
|
1897 | 1949 |
|
1898 | 1950 |
models.PublicKey = models.Model.extend({ |
1899 | 1951 |
path: 'keys', |
... | ... | |
1967 | 2019 |
snf.storage.networks = new models.Networks(); |
1968 | 2020 |
snf.storage.vms = new models.VMS(); |
1969 | 2021 |
snf.storage.keys = new models.PublicKeys(); |
2022 |
snf.storage.nics = new models.NICs(); |
|
1970 | 2023 |
|
1971 | 2024 |
//snf.storage.vms.fetch({update:true}); |
1972 | 2025 |
//snf.storage.images.fetch({update:true}); |
b/snf-cyclades-app/synnefo/ui/static/snf/js/ui/web/ui_networks_view.js | ||
---|---|---|
109 | 109 |
} |
110 | 110 |
|
111 | 111 |
_.each(this.vms, _.bind(function(vm){ |
112 |
|
|
112 | 113 |
var html = '<li class="vm option options-object vm-{0}">' + |
113 | 114 |
'<div class="options-object-cont">' + |
114 | 115 |
'{2}' + |
... | ... | |
120 | 121 |
snf.ui.helpers.vm_icon_tag(vm, "small", {'class':'os'}), |
121 | 122 |
_.escape(vm.get_os()) |
122 | 123 |
)) |
123 |
el.data({vm:vm,vm_id:vm.id}) |
|
124 |
el.data({vm:vm, vm_id:vm.id})
|
|
124 | 125 |
this.list.append(el); |
125 | 126 |
|
126 | 127 |
vm.bind("remove", function(){ el.remove()}) |
... | ... | |
142 | 143 |
this.reset(); |
143 | 144 |
this.set_subtitle(network.escape("name")); |
144 | 145 |
this.vms = vms; |
146 |
if (!synnefo.config.network_allow_duplicate_vm_nics) { |
|
147 |
this.vms = _.filter(this.vms, function(vm) { |
|
148 |
return !vm.connected_to(this.network); |
|
149 |
}, this); |
|
150 |
} |
|
151 |
|
|
145 | 152 |
this.selected = selected; |
146 | 153 |
this.cb = callback; |
147 | 154 |
this.show(); |
... | ... | |
194 | 201 |
this.create_button = this.$("form .form-action.create"); |
195 | 202 |
this.text = this.$(".network-create-name"); |
196 | 203 |
this.form = this.$("form"); |
204 |
|
|
205 |
this.dhcp_select = this.$("#network-create-dhcp"); |
|
206 |
this.type_select = this.$("#network-create-type"); |
|
207 |
this.subnet_select = this.$("#network-create-subnet"); |
|
208 |
this.subnet_custom = this.$("#network-create-subnet-custom"); |
|
209 |
|
|
210 |
this.dhcp_form = this.$("#network-create-dhcp-fields"); |
|
211 |
|
|
212 |
this.subnet_select.find(".subnet").remove(); |
|
213 |
_.each(synnefo.config.network_suggested_subnets, function(subnet){ |
|
214 |
this.subnet_select.append($('<option value='+subnet+' class="subnet">'+subnet+'</option>')); |
|
215 |
}, this); |
|
216 |
|
|
217 |
this.type_select.find(".subnet").remove(); |
|
218 |
_.each(synnefo.config.network_available_types, function(name, value){ |
|
219 |
this.type_select.append($('<option value='+value+' class="subnet">'+name+'</option>')); |
|
220 |
}, this); |
|
221 |
|
|
222 |
this.disable_network_type = false; |
|
223 |
if (_.keys(synnefo.config.network_available_types).length <= 1) { |
|
224 |
this.disable_network_type = true; |
|
225 |
this.type_select.closest(".form-field").hide(); |
|
226 |
} |
|
227 |
|
|
228 |
this.check_dhcp_form(); |
|
197 | 229 |
this.init_handlers(); |
198 | 230 |
}, |
199 | 231 |
|
232 |
check_dhcp_form: function() { |
|
233 |
if (this.dhcp_select.is(":checked")) { |
|
234 |
this.dhcp_form.show(); |
|
235 |
} else { |
|
236 |
this.dhcp_form.hide(); |
|
237 |
} |
|
238 |
|
|
239 |
if (this.subnet_select.val() == "custom") { |
|
240 |
this.subnet_custom.show(); |
|
241 |
} else { |
|
242 |
this.subnet_custom.hide(); |
|
243 |
} |
|
244 |
}, |
|
245 |
|
|
200 | 246 |
init_handlers: function() { |
247 |
|
|
248 |
this.dhcp_select.click(_.bind(function(e){ |
|
249 |
this.check_dhcp_form(); |
|
250 |
}, this)); |
|
251 |
|
|
252 |
this.subnet_select.change(_.bind(function(e){ |
|
253 |
this.check_dhcp_form(); |
|
254 |
if (this.subnet_custom.is(":visible")) { |
|
255 |
this.subnet_custom.focus(); |
|
256 |
} |
|
257 |
}, this)); |
|
258 |
|
|
201 | 259 |
this.create_button.click(_.bind(function(e){ |
202 | 260 |
this.submit(); |
203 | 261 |
}, this)); |
... | ... | |
230 | 288 |
this.text.focus(); |
231 | 289 |
return false; |
232 | 290 |
} else { |
233 |
return true;
|
|
291 |
this.text.closest(".form-field").removeClass("error");
|
|
234 | 292 |
} |
293 |
|
|
294 |
if (this.dhcp_select.is(":checked")) { |
|
295 |
if (this.subnet_select.val() == "custom") { |
|
296 |
var sub = this.subnet_custom.val(); |
|
297 |
sub = sub.replace(/^\s+|\s+$/g,""); |
|
298 |
this.subnet_custom.val(sub); |
|
299 |
|
|
300 |
if (!synnefo.util.IP_REGEX.exec(this.subnet_custom.val())) { |
|
301 |
this.subnet_custom.closest(".form-field").prev().addClass("error"); |
|
302 |
return false; |
|
303 |
} else { |
|
304 |
this.subnet_custom.closest(".form-field").prev().removeClass("error"); |
|
305 |
} |
|
306 |
}; |
|
307 |
} |
|
308 |
|
|
309 |
return true; |
|
235 | 310 |
}, |
236 | 311 |
|
237 | 312 |
create: function() { |
238 | 313 |
this.create_button.addClass("in-progress"); |
239 |
snf.storage.networks.create(this.text.val(), _.bind(function(){ |
|
314 |
|
|
315 |
var name = this.text.val(); |
|
316 |
var dhcp = this.dhcp_select.is(":checked"); |
|
317 |
var subnet = null; |
|
318 |
var type = this.type_select.val(); |
|
319 |
|
|
320 |
if (this.disable_network_type) { type = null }; |
|
321 |
|
|
322 |
if (dhcp) { |
|
323 |
if (this.subnet_select.val() == "custom") { |
|
324 |
subnet = this.subnet_custom.val(); |
|
325 |
} else if (this.subnet_select.val() == "auto") { |
|
326 |
subnet = null; |
|
327 |
} else { |
|
328 |
subnet = this.subnet_select.val(); |
|
329 |
} |
|
330 |
|
|
331 |
} |
|
332 |
|
|
333 |
snf.storage.networks.create(name, type, subnet, dhcp, _.bind(function(){ |
|
240 | 334 |
this.hide(); |
241 | 335 |
}, this)); |
242 | 336 |
}, |
... | ... | |
247 | 341 |
this.text.val(""); |
248 | 342 |
this.text.show(); |
249 | 343 |
this.text.focus(); |
344 |
this.subnet_custom.val(""); |
|
345 |
this.subnet_select.val("auto"); |
|
346 |
this.dhcp_select.attr("checked", true); |
|
347 |
this.type_select.val(_.keys(synnefo.config.network_available_types)[0]); |
|
348 |
this.check_dhcp_form(); |
|
250 | 349 |
}, |
251 | 350 |
|
252 | 351 |
onOpen: function() { |
... | ... | |
254 | 353 |
} |
255 | 354 |
}); |
256 | 355 |
|
257 |
views.NetworkVMView = views.View.extend({
|
|
356 |
views.NetworkNICView = views.View.extend({
|
|
258 | 357 |
|
259 |
initialize: function(vm, parent, firewall_controls, el) {
|
|
358 |
initialize: function(nic, parent, firewall_controls, el) {
|
|
260 | 359 |
this.firewall_controls = firewall_controls || false; |
261 |
this.vm = vm; |
|
360 |
this.nic = nic; |
|
361 |
this.vm = nic.get_vm(); |
|
262 | 362 |
// parent view di |
263 | 363 |
this.parent = parent; |
264 | 364 |
// TODO make it better |
265 |
this.el = el || this.parent.vm(vm);
|
|
365 |
this.el = el || this.parent.get_nic_view(nic);
|
|
266 | 366 |
|
267 | 367 |
this.init_layout(); |
268 | 368 |
this.update_layout(); |
... | ... | |
279 | 379 |
|
280 | 380 |
this.firewall_view = undefined; |
281 | 381 |
if (this.firewall_controls) { |
282 |
this.firewall_view = new views.FirewallEditView(this.vm, this.parent.network, this);
|
|
382 |
this.firewall_view = new views.FirewallEditView(this.nic, this.parent.network, this);
|
|
283 | 383 |
} |
284 | 384 |
|
285 | 385 |
}, |
286 | 386 |
|
387 |
reset_all_net_actions: function(act_types) { |
|
388 |
synnefo.storage.networks.each(function(n){ |
|
389 |
var actions = n.get('actions'); |
|
390 |
_.each(act_types, function(type){ |
|
391 |
actions.remove_all(type); |
|
392 |
}) |
|
393 |
}) |
|
394 |
}, |
|
395 |
|
|
287 | 396 |
init_handlers: function() { |
288 | 397 |
if (!this.parent.network.is_public()) { |
289 | 398 |
this.disconnect.click(_.bind(function(e){ |
290 | 399 |
e.preventDefault(); |
291 |
this.parent.network.get("actions").add("disconnect", this.vm.id); |
|
400 |
this.reset_all_net_actions(['destroy','disconnect']); |
|
401 |
this.parent.network.get("actions").remove_all("disconnect"); |
|
402 |
this.parent.network.get("actions").add("disconnect", this.nic.id); |
|
292 | 403 |
this.parent.network.get("actions").remove("destroy"); |
293 | 404 |
}, this)); |
294 | 405 |
this.cancel.click(_.bind(function(e){ |
295 |
this.parent.network.get("actions").remove("disconnect", this.vm.id);
|
|
406 |
this.parent.network.get("actions").remove("disconnect", this.nic.id);
|
|
296 | 407 |
e.preventDefault() |
297 | 408 |
}, this)); |
409 |
|
|
298 | 410 |
this.confirm.click(_.bind(function(e){ |
299 | 411 |
e.preventDefault() |
300 |
this.disconnect_vm();
|
|
412 |
this.disconnect_nic();
|
|
301 | 413 |
this.confirm_el.hide(); |
302 | 414 |
this.disconnect.removeClass("selected"); |
303 | 415 |
}, this)); |
... | ... | |
309 | 421 |
}, this)); |
310 | 422 |
|
311 | 423 |
this.$(".remove-icon").click(_.bind(function(){ |
312 |
this.parent.network.get("actions").add("disconnect", this.vm.id); |
|
424 |
this.reset_all_net_actions(['destroy','disconnect']); |
|
425 |
this.parent.network.get("actions").remove_all("disconnect"); |
|
426 |
this.parent.network.get("actions").add("disconnect", this.nic.id); |
|
313 | 427 |
this.parent.network.get("actions").remove("destroy"); |
314 | 428 |
}, this)); |
315 | 429 |
|
... | ... | |
318 | 432 |
}, this)); |
319 | 433 |
|
320 | 434 |
this.parent.network.bind("change:actions", _.bind(function(model, action){ |
321 |
if (this.parent.network.get("actions").contains("disconnect", this.vm.id)) {
|
|
435 |
if (this.parent.network.get("actions").contains("disconnect", this.nic.id)) {
|
|
322 | 436 |
this.confirm_disconnect(); |
323 | 437 |
} else { |
324 | 438 |
this.cancel_disconnect(); |
... | ... | |
327 | 441 |
} |
328 | 442 |
|
329 | 443 |
var vm = this.vm; |
330 |
this.details.click(function(){ |
|
444 |
this.details.click(function(e){ |
|
445 |
e.preventDefault(); |
|
331 | 446 |
snf.ui.main.show_vm_details(vm); |
332 | 447 |
}); |
333 | 448 |
|
... | ... | |
354 | 469 |
this.$("img.logo").attr("src", ui.helpers.vm_icon_path(this.vm, "medium")); |
355 | 470 |
|
356 | 471 |
if (this.firewall_view) { |
357 |
this.$(".ipv4-text").text(this.vm.get_addresses().ip4);
|
|
358 |
this.$(".ipv6-text").text(this.vm.get_addresses().ip6);
|
|
472 |
this.$(".ipv4-text").text(this.nic.get_v4_address());
|
|
473 |
this.$(".ipv6-text").text(this.nic.get_v6_address());
|
|
359 | 474 |
} |
360 | 475 |
|
361 | 476 |
if (this.firewall_view) { |
362 | 477 |
this.firewall_view.update_layout(); |
363 | 478 |
} |
479 |
|
|
480 |
if (!this.firewall_view) { |
|
481 |
this.$(".ip4-container").hide(); |
|
482 |
this.$(".ip6-container").hide(); |
|
483 |
|
|
484 |
if (this.nic.get("ipv4")) { |
|
485 |
this.$(".ipv4-text").text(this.nic.get_v4_address()); |
|
486 |
this.$(".ip4-container").show(); |
|
487 |
this.$(".machine-connect .content").hide(); |
|
488 |
} else if (this.nic.get("ipv6")) { |
|
489 |
this.$(".ipv6-text").text(this.nic.get_v6_address()); |
|
490 |
this.$(".ip6-container").show(); |
|
491 |
this.$(".machine-connect .content").hide(); |
|
492 |
} else { |
|
493 |
this.$(".machine-connect .content").show(); |
|
494 |
} |
|
495 |
} else { |
|
496 |
} |
|
364 | 497 |
}, |
365 | 498 |
|
366 |
disconnect_vm: function() {
|
|
499 |
disconnect_nic: function() {
|
|
367 | 500 |
this.$("a.selected").removeClass("selected"); |
368 |
this.parent.network.remove_vm(this.vm);
|
|
501 |
this.parent.network.remove_nic(this.nic);
|
|
369 | 502 |
}, |
370 |
|
|
371 |
update_firewall_layout: function() { |
|
372 |
} |
|
373 |
|
|
374 |
|
|
375 | 503 |
}) |
376 | 504 |
|
377 | 505 |
views.NetworkModelRenameView = views.View.extend({ |
... | ... | |
448 | 576 |
}) |
449 | 577 |
|
450 | 578 |
views.FirewallEditView = views.View.extend({ |
451 |
initialize: function(vm, network, parent) {
|
|
579 |
initialize: function(nic, network, parent) {
|
|
452 | 580 |
this.parent = parent; |
453 |
this.vm = vm; |
|
581 |
this.vm = nic.get_vm(); |
|
582 |
this.nic = nic; |
|
454 | 583 |
this.network = network; |
455 | 584 |
this.el = this.parent.el; |
456 | 585 |
|
... | ... | |
467 | 596 |
|
468 | 597 |
this.$(".firewall-content").hide(); |
469 | 598 |
this.$(".firewall-content input[type=radio]").attr("name", "firewall-opt-for-{0}".format(this.vm.id)) |
470 |
var mode = this.vm.firewall_profile(this.network.id);
|
|
599 |
var mode = this.vm.get_firewall_profile();
|
|
471 | 600 |
this.$(".firewall-content input[value={0}]".format(mode)).attr("checked", true); |
472 | 601 |
|
473 | 602 |
this.init_handlers(); |
474 | 603 |
this.update_layout(); |
604 |
|
|
605 |
var self = this; |
|
606 |
this.nic.bind("change:pending_firewall_sending", function(nic, value) { |
|
607 |
if (value) { |
|
608 |
self.apply.addClass("in-progress"); |
|
609 |
self.progress.show(); |
|
610 |
} else { |
|
611 |
self.apply.removeClass("in-progress"); |
|
612 |
self.progress.hide(); |
|
613 |
self.toggler.click(); |
|
614 |
} |
|
615 |
}); |
|
616 |
|
|
617 |
this.nic.bind("change:firewallProfile", function(nic){ |
|
618 |
self.update_layout(); |
|
619 |
self.reset_value(); |
|
620 |
}) |
|
621 |
|
|
475 | 622 |
}, |
476 | 623 |
|
477 | 624 |
_get_selected: function() { |
... | ... | |
485 | 632 |
}, |
486 | 633 |
|
487 | 634 |
reset_value: function() { |
488 |
this.inputs.filter("[value={0}]".format(this.vm.firewall_profile(this.network.id))).attr("checked"); |
|
635 |
this.inputs.filter("[value={0}]".format( |
|
636 |
this.nic.get('firewallProfile'))).attr("checked", true); |
|
489 | 637 |
}, |
490 | 638 |
|
491 | 639 |
init_handlers: function() { |
... | ... | |
502 | 650 |
}, this)) |
503 | 651 |
|
504 | 652 |
this.apply.click(_.bind(function(){ |
505 |
this.apply.addClass("in-progress"); |
|
506 |
|
|
507 |
// make the api call |
|
508 |
this.vm.set_firewall(this.network.id, this.value(), |
|
509 |
// complete |
|
510 |
_.bind(function() { |
|
511 |
// complete callback |
|
512 |
this.apply.removeClass("in-progress"); |
|
513 |
}, this), |
|
514 |
// error |
|
515 |
_.bind(function(){ |
|
516 |
this.vm.remove_pending_firewall(this.network.id, this.value()); |
|
517 |
}, this)); |
|
518 |
this.hide_firewall(); |
|
653 |
this.nic.set_firewall(this.value()); |
|
519 | 654 |
}, this)) |
520 | 655 |
|
521 | 656 |
this.inputs.change(_.bind(function(){ |
... | ... | |
549 | 684 |
}, |
550 | 685 |
|
551 | 686 |
update_layout: function() { |
552 |
if (this.value() == this.vm.firewall_profile(this.network.id)) {
|
|
687 |
if (this.value() == this.vm.get_firewall_profile()) {
|
|
553 | 688 |
this.apply.hide(); |
554 | 689 |
} else { |
555 | 690 |
this.apply.show(); |
556 | 691 |
} |
557 | 692 |
|
558 |
profile = this.vm.firewall_profile(this.network.id);
|
|
693 |
var profile = this.vm.get_firewall_profile();
|
|
559 | 694 |
if (this.vm.has_firewall(this.network.id)) { |
560 | 695 |
this.$(".firewall-toggle .label span").text("On"); |
561 | 696 |
this.$(".firewall-toggle .label span").removeClass("firewall-off"); |
... | ... | |
567 | 702 |
} |
568 | 703 |
|
569 | 704 |
this.$("span.checkbox-legends").removeClass("current"); |
570 |
this.inputs.filter("[value={0}]".format(this.vm.firewall_profile(this.network.id))).next().addClass("current"); |
|
571 |
|
Also available in: Unified diff