Commit d5fe25eb by Oláh István Gergely

dashboard: node functions

parent a383b8e4
......@@ -91,6 +91,10 @@ body {
min-height: 20em;
}
#node-detail-panel .panel-body {
min-height: 20em;
}
:link i:before:hover {
text-decoration: none !important;
}
......@@ -142,19 +146,20 @@ body {
height: 300px;
}
#vm-details-rename, #vm-details-rename *, #vm-details-h1-name, #vm-list-rename, #vm-list-rename * {
#vm-details-rename, #vm-details-rename *, #vm-details-h1-name, #vm-list-rename, #vm-list-rename *,
#node-details-rename, #node-details-rename *, #node-details-h1-name, #node-list-rename, #node-list-rename * {
display: inline;
}
#vm-details-rename, #vm-list-rename {
#vm-details-rename, #vm-list-rename, #node-details-rename, #node-list-rename {
display: none;
}
#vm-details-rename-name {
#vm-details-rename-name, #node-details-rename-name {
max-width: 160px;
}
#vm-list-rename-name {
#vm-list-rename-name, #node-list-rename-name {
max-width: 100px;
}
......
......@@ -15,6 +15,23 @@ $(function () {
});
return false;
});
$('.node-create').click(function(e) {
$.ajax({
type: 'GET',
url: '/dashboard/node/create/',
success: function(data) {
$('body').append(data);
nodeCreateLoaded();
addSliderMiscs();
$('#node-create-modal').modal('show');
$('#node-create-modal').on('hidden.bs.modal', function() {
$('#node-create-modal').remove();
});
}
});
return false;
});
$('[href=#index-graph-view]').click(function (e) {
var box = $(this).data('index-box');
$("#" + box + "-list-view").hide();
......@@ -65,6 +82,20 @@ $(function () {
return false;
});
/* for Node removes buttons */
$('.node-delete').click(function() {
var node_pk = $(this).data('node-pk');
var dir = window.location.pathname.indexOf('list') == -1;
addModalConfirmation(deleteNode,
{ 'url': '/dashboard/node/delete/' + node_pk + '/',
'data': [],
'node_pk': node_pk,
'redirect': dir});
return false;
});
});
function addSliderMiscs() {
......
var vlans = [];
var disks = [];
$(function() {
nodeCreateLoaded();
});
function nodeCreateLoaded() {
$('.node-create-advanced').hide();
$('.node-create-advanced-btn').click(function() {
$('.vm-create-advanced').stop().slideToggle();
if ($('.node-create-advanced-icon').hasClass('icon-caret-down')) {
$('.node-create-advanced-icon').removeClass('icon-caret-down').addClass('icon-caret-up');
} else {
$('.node-create-advanced-icon').removeClass('icon-caret-up').addClass('icon-caret-down');
}
});
$('#node-create-template-select').change(function() {
nodeCreateTemplateChange(this);
});
/* network thingies */
/* add network */
$('#node-create-network-add-button').click(function() {
var vlan_pk = $('#node-create-network-add-select :selected').val();
var managed = $('#node-create-network-add-checkbox-managed').prop('checked');
var name = $('#node-create-network-add-select :selected').text();
if ($('#node-create-network-list').children('span').length < 1) {
$('#node-create-network-list').html('');
}
$('#node-create-network-list').append(
nodeCreateNetworkLabel(vlan_pk, name, managed)
);
/* select the network from the managed/unmanaged multiple select */
if(managed) {
$('#node-create-network-add-managed option[value="' + vlan_pk + '"]').prop('selected', true);
} else {
$('#node-create-network-add-unmanaged option[value="' + vlan_pk + '"]').prop('selected', true);
}
$('option:selected', $('#node-create-network-add-select')).remove();
/* add dummy text if no more networks are available */
if($('#node-create-network-add-select option').length < 1) {
$('#node-create-network-add-button').attr('disabled', true);
$('#node-create-network-add-select').html('<option value="-1">We are out of &lt;options&gt; hehe</option>');
}
return false;
});
/* remove network */
// event for network remove button (icon, X)
$('body').on('click', '.node-create-remove-network', function() {
var vlan_pk = ($(this).parent('span').prop('id')).replace('vlan-', '')
// if it's "blue" then it's managed, kinda not cool
var managed = $(this).parent('span').hasClass('label-primary');
$(this).parent('span').fadeOut(500, function() {
/* if ther are no more vlans disabled the add button */
if($('#node-create-network-add-select option')[0].value == -1) {
$('#node-create-network-add-button').attr('disabled', false);
$('#node-create-network-add-select').html('');
}
/* remove the network label */
$(this).remove();
var vlan_name = $(this).text();
$('#node-create-network-add-select').append($('<option>', {
value: vlan_pk,
text: vlan_name
}));
/* remove the selection from the multiple select */
$('#node-create-network-add-' + (managed ? '' : 'un') + 'managed option[value="' + vlan_pk + '"]').prop('selected', false);
if ($('#node-create-network-list').children('span').length < 1) {
$('#node-create-network-list').append('Not added to any network!');
}
});
return false;
});
/* copy networks from hidden select */
$('#node-create-network-add-select').html($('#node-create-network-add-managed').html());
/* build up network list */
$('#node-create-network-add-select option').each(function() {
vlans.push({
'name': $(this).text(),
'pk': parseInt($(this).val())
});
});
/* ----- end of networks thingies ----- */
/* add disk */
$('#node-create-disk-add-button').click(function() {
var disk_pk = $('#node-create-disk-add-select :selected').val();
var name = $('#node-create-disk-add-select :selected').text();
if ($('#node-create-disk-list').children('span').length < 1) {
$('#node-create-disk-list').html('');
}
$('#node-create-disk-list').append(
nodeCreateDiskLabel(disk_pk, name)
);
/* select the disk from the multiple select */
$('#node-create-disk-add-form option[value="' + disk_pk + '"]').prop('selected', true);
$('option:selected', $('#node-create-disk-add-select')).remove();
/* add dummy text if no more disks are available */
if($('#node-create-disk-add-select option').length < 1) {
$('#node-create-disk-add-button').attr('disabled', true);
$('#node-create-disk-add-select').html('<option value="-1">We are out of &lt;options&gt; hehe</option>');
}
return false;
});
/* remove disk */
// event for disk remove button (icon, X)
$('body').on('click', '.node-create-remove-disk', function() {
var disk_pk = ($(this).parent('span').prop('id')).replace('vlan-', '')
$(this).parent('span').fadeOut(500, function() {
/* if ther are no more disks disabled the add button */
if($('#node-create-disk-add-select option')[0].value == -1) {
$('#node-create-disk-add-button').attr('disabled', false);
$('#node-create-disk-add-select').html('');
}
/* remove the disk label */
$(this).remove();
var disk_name = $(this).text();
$('#node-create-disk-add-select').append($('<option>', {
value: disk_pk,
text: disk_name
}));
/* remove the selection from the multiple select */
$('#node-create-disk-add-form option[value="' + disk_pk + '"]').prop('selected', false);
if ($('#node-create-disk-list').children('span').length < 1) {
$('#node-create-disk-list').append('No disks are added!');
}
});
return false;
});
/* copy disks from hidden select */
$('#node-create-disk-add-select').html($('#node-create-disk-add-form').html());
/* build up disk list */
$('#node-create-disk-add-select option').each(function() {
disks.push({
'name': $(this).text(),
'pk': parseInt($(this).val())
});
});
/* add button */
$('#node-create-submit').click(function() {
$.ajax({
url: '/dashboard/node/create/',
headers: {"X-CSRFToken": getCookie('csrftoken')},
type: 'POST',
data: $('form').serialize(),
success: function(data, textStatus, xhr) {
if(data.pk) {
window.location.replace('/dashboard/node/' + data.pk + '/#activity');
}
},
error: function(xhr, textStatus, error) {
if (xhr.status == 500) {
alert("uhuhuhuhuhuh");
} else {
alert("unknown error");
}
}
});
return false;
});
/* no js compatibility */
$('.no-js-hidden').show();
$('.js-hidden').hide();
}
function nodeCreateTemplateChange(new_this) {
this.value = new_this.value;
if(this.value < 0) return;
$.ajax({
url: '/dashboard/template/' + this.value,
type: 'GET',
success: function(data, textStatus, xhr) {
if(xhr.status == 200) {
// set sliders
$('#node-cpu-priority-slider').slider("setValue", data['priority']);
$('#node-cpu-count-slider').slider("setValue", data['num_cores']);
$('#node-ram-size-slider').slider("setValue", data['ram_size']);
/* slider doesn't have change event ........................ */
refreshSliders();
/* clear selections */
$('select[id^="node-create-network-add"], select[id$="managed"]').find('option').prop('selected', false);
$('#node-create-disk-add-form').find('option').prop('selected', false);
/* append vlans from InterfaceTemplates */
$('#vm-create-network-list').html('');
var added_vlans = []
for(var n = 0; n<data['network'].length; n++) {
nn = data['network'][n]
$('#node-create-network-list').append(
nodeCreateNetworkLabel(nn.vlan_pk, nn.vlan, nn.managed)
);
$('#node-create-network-add-' + (nn.managed ? '' : 'un') + 'managed option[value="' + nn.vlan_pk + '"]').prop('selected', true);
added_vlans.push(nn.vlan_pk);
}
/* remove already added vlans from dropdown or add new ones */
$('#node-create-network-add-select').html('');
for(var i=0; i < vlans.length; i++)
if(added_vlans.indexOf(vlans[i].pk) == -1)
$('#node-create-network-add-select').append($('<option>', {
value: vlans[i].pk,
text: vlans[i].name
}));
/* enalbe the network add button if there are not added vlans */
if(added_vlans.length != vlans.length) {
$('#node-create-network-add-button').attr('disabled', false);
} else {
$('#node-create-network-add-select').html('<option value="-1">We are out of &lt;options&gt; hehe</option>');
$('#node-create-network-add-button').attr('disabled', true);
}
/* append disks */
$('#node-create-disk-list').html('');
var added_disks = []
for(var d = 0; d<data['disks'].length; d++) {
dd = data['disks'][d]
$('#node-create-disk-list').append(
nodeCreateDiskLabel(dd.pk, dd.name)
);
$('#node-create-disk-add-form option[value="' + dd.pk + '"]').prop('selected', true);
added_disks.push(dd.pk);
}
/* remove already added disks from dropdown or add new ones */
$('#node-create-disk-add-select').html('');
for(var i=0; i < disks.length; i++)
if(added_disks.indexOf(disks[i].pk) == -1)
$('#node-create-disk-add-select').append($('<option>', {
value: disks[i].pk,
text: disks[i].name
}));
/* enalbe the disk add button if there are not added disks */
if(added_disks.length != disks.length) {
$('#node-create-disk-add-button').attr('disabled', false);
} else {
$('#node-create-disk-add-select').html('<option value="-1">We are out of &lt;options&gt; hehe</option>');
$('#node-create-disk-add-button').attr('disabled', true);
}
}
}
});
}
function vmCreateNetworkLabel(pk, name, managed) {
return '<span id="vlan-' + pk + '" class="label label-' + (managed ? 'primary' : 'default') + '"><i class="icon-' + (managed ? 'globe' : 'link') + '"></i> ' + name + ' <a href="#" class="hover-black node-create-remove-network"><i class="icon-remove-sign"></i></a></span> ';
}
function vmCreateDiskLabel(pk, name) {
return '<span id="vlan-' + pk + '" class="label label-primary"><i class="icon-file"></i> ' + name + ' <a href="#" class="hover-black node-create-remove-disk"><i class="icon-remove-sign"></i></a></span> ';
}
$(function() {
if($('.timeline .activity:first i:first').hasClass('icon-spin'))
checkNewActivity();
/* save resources */
$('#vm-details-resources-save').click(function() {
$('i.icon-save', this).removeClass("icon-save").addClass("icon-refresh icon-spin");
$.ajax({
type: 'POST',
url: location.href,
data: $('#vm-details-resources-form').serialize(),
success: function(data, textStatus, xhr) {
addMessage(data['message'], 'success');
$("#vm-details-resources-save i").removeClass('icon-refresh icon-spin').addClass("icon-save");
},
error: function(xhr, textStatus, error) {
$("#vm-details-resources-save i").removeClass('icon-refresh icon-spin').addClass("icon-save");
addMessage("Eww, something is wrong", 'danger');
if (xhr.status == 500) {
// alert("uhuhuhuhuhuh");
} else {
// alert("unknown error");
}
}
});
return false;
});
/* rename */
$("#vm-details-h1-name, .vm-details-rename-button").click(function() {
$("#vm-details-h1-name").hide();
$("#vm-details-rename").css('display', 'inline');
});
/* rename ajax */
$('#vm-details-rename-submit').click(function() {
var name = $('#vm-details-rename-name').val();
$.ajax({
method: 'POST',
url: location.href,
data: {'new_name': name},
headers: {"X-CSRFToken": getCookie('csrftoken')},
success: function(data, textStatus, xhr) {
$("#vm-details-h1-name").html(data['new_name']).show();
$('#vm-details-rename').hide();
// addMessage(data['message'], "success");
},
error: function(xhr, textStatus, error) {
addMessage("uhoh", "danger");
}
});
return false;
});
/* remove tag */
$('.vm-details-remove-tag').click(function() {
var to_remove = $.trim($(this).parent('div').text());
var clicked = $(this);
$.ajax({
type: 'POST',
url: location.href,
headers: {"X-CSRFToken": getCookie('csrftoken')},
data: {'to_remove': to_remove},
success: function(re) {
if(re['message'].toLowerCase() == "success") {
$(clicked).closest(".label").fadeOut(500, function() {
$(this).remove();
});
}
},
error: function() {
addMessage(re['message'], 'danger');
}
});
return false;
});
});
function checkNewActivity() {
var latest = $('.activity:first').data('activity-id');
var latest_sub = $('div[data-activity-id="' + latest + '"] .sub-timeline .sub-activity:first').data('activity-id');
var instance = location.href.split('/'); instance = instance[instance.length - 2];
$.ajax({
type: 'POST',
url: '/dashboard/vm/' + instance + '/activity/',
headers: {"X-CSRFToken": getCookie('csrftoken')},
data: {'latest': latest, 'latest_sub': latest_sub},
success: function(data) {
if(data['new_sub_activities'].length > 0) {
d = data['new_sub_activities'];
html = ""
for(var i=0; i<d.length; i++) {
html += '<div data-activity-id="' + d[i].id + '" class="sub-activity">' + d[i].name + ' - ';
if(d[i].finished != null) {
html += d[i].finished
} else {
html += '<i class="icon-refresh icon-spin" class="sub-activity-loading-icon"></i>';
}
html += '</div>';
}
$('div[data-activity-id="' + latest_sub + '"] .sub-activity .sub-activity-loading-icon').remove();
$('div[data-activity-id="' + latest + '"] .sub-timeline').prepend(html);
}
if(data['is_parent_finished']) {
var c = "icon-plus"
$('div[data-activity-id="' + latest + '"] .icon-refresh.icon-spin:first').removeClass('icon-refresh').removeClass('icon-spin').addClass(c);
}
if(data['latest_sub_finished'] != null) {
s = $('div[data-activity-id="' + latest_sub + '"]')
$('.icon-refresh.icon-spin', s).remove();
$(s).append(data['latest_sub_finished']);
}
if(data['is_parent_finished'])
return;
else
setTimeout(checkNewActivity, 1000);
},
error: function() {
}
});
}
......@@ -13,6 +13,7 @@ $(function() {
});
$('.node-list-table tbody').find('tr').mousedown(function() {
var retval = true;
if (ctrlDown) {
setRowColor($(this));
if(!$(this).hasClass('node-list-selected')) {
......@@ -20,6 +21,7 @@ $(function() {
} else {
selected.push($(this).index());
}
retval = false;
} else if(shiftDown) {
if(selected.length > 0) {
start = selected[selected.length - 1] + 1;
......@@ -36,6 +38,7 @@ $(function() {
}
}
}
retval = false;
} else {
$('.node-list-selected').removeClass('node-list-selected');
$(this).addClass('node-list-selected');
......@@ -53,10 +56,20 @@ $(function() {
} else {
$('.node-list-group-control a').attr('disabled', true);
}
return false;
return retval;
});
$(':not(#anything)').on('click', function (e) {
$('.node-list-details').each(function () {
//the 'is' for buttons that trigger popups
// //the 'has' for icons and other elements within a button that triggers a popup
if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
$(this).popover('hide');
return;
}
});
});
$('#node-list-group-migrate').click(function() {
console.log(collectIds(selected));
});
......@@ -64,12 +77,6 @@ $(function() {
$('.node-list-details').popover({
'placement': 'auto',
'html': true,
'trigger': 'hover'
});
$('.node-list-connect').popover({
'placement': 'left',
'html': true,
'trigger': 'click'
});
......@@ -80,11 +87,48 @@ $(function() {
$('tbody a').click(function(e) {
// browser doesn't jump to top when clicked the buttons
if(!$(this).hasClass('real-link')) {
if(!$(this).hasClass('real-link')) {
return false;
}
});
/* rename */
$("#node-list-rename-button, .node-details-rename-button").click(function() {
$("#node-list-column-name", $(this).closest("tr")).hide();
$("#node-list-rename", $(this).closest("tr")).css('display', 'inline');
});
/* rename ajax */
$('.node-list-rename-submit').click(function() {
var row = $(this).closest("tr")
var name = $('#node-list-rename-name', row).val();
var url = '/dashboard/node/' + row.children("td:first-child").text().replace(" ", "") + '/';
$.ajax({
method: 'POST',
url: url,
data: {'new_name': name},
headers: {"X-CSRFToken": getCookie('csrftoken')},
success: function(data, textStatus, xhr) {
$("#node-list-column-name", row).html(
$("<a/>", {
'class': "real-link",
href: "/dashboard/node/" + data['node_pk'] + "/",
text: data['new_name']
})
).show();
$('#node-list-rename', row).hide();
// addMessage(data['message'], "success");
},
error: function(xhr, textStatus, error) {
addMessage("uhoh", "danger");
}
});
return false;
});
/* group actions */
/* select all */
......@@ -103,9 +147,15 @@ $(function() {
/* mass vm delete */
$('#node-list-group-delete').click(function() {
text = "Are you sure you want to delete the selected VMs?";
random_vm_pk = $('.vm-delete').eq(0).data('vm-pk');
addModalConfirmation(text, random_vm_pk, massDeleteVm, false);
addModalConfirmation(massDeleteVm,
{
'url': '/dashboard/node/mass-delete/',
'data': {
'selected': selected,
'v': collectIds(selected)
}
}
);
return false;
});
});
......@@ -114,16 +164,15 @@ function collectIds(rows) {
var ids = [];
for(var i = 0; i < rows.length; i++) {
var div = $('td:first-child div', $('.node-list-table tbody tr').eq(rows[i]));
ids.push(div.prop('id').replace('vm-', ''));
ids.push(div.prop('id').replace('node-', ''));
}
return ids;
}
function setRowColor(row) {
if(!row.hasClass('vm-list-selected')) {
if(!row.hasClass('node-list-selected')) {
row.addClass('node-list-selected');
} else {
row.removeClass('node-list-selected');
}
}
from django_tables2 import Table, A
from django_tables2.columns import LinkColumn, TemplateColumn, Column
from django_tables2.columns import LinkColumn, TemplateColumn, Column, BooleanColumn
from vm.models import Instance, Node
from django.utils.translation import ugettext_lazy as _
......@@ -46,17 +46,99 @@ class NodeListTable(Table):
pk = Column(
verbose_name="ID",
attrs={'th': {'class': 'node-list-table-thin'}},
)
name = LinkColumn(
'dashboard.views.node-detail',
args=[A('pk')],
attrs={'a': {'class': 'real-link'}}
overcommit = Column(
verbose_name="Overcommit",
attrs={'th': {'class': 'node-list-table-thin'}},
)
host = Column(
verbose_name="Host",
)
enabled = BooleanColumn(
verbose_name="Enabled",
attrs={'th': {'class': 'node-list-table-thin'}},
)
name = TemplateColumn(
template_name="dashboard/node-list/column-name.html"
)
priority = Column(
verbose_name=_("Priority"),
attrs={'th': {'class': 'node-list-table-thin'}},
)
number_of_VMs = TemplateColumn(
template_name='dashboard/node-list/column-vm.html',
attrs={'th': {'class': 'node-list-table-admin'}},
)
admin = TemplateColumn(
template_name='dashboard/node-list/column-admin.html',
attrs={'th': {'class': 'node-list-table-admin'}},
)
details = TemplateColumn(
template_name='dashboard/node-list/column-details.html',
attrs={'th': {'class': 'node-list-table-thin'}},
)
actions = TemplateColumn(
attrs={'th': {'class': 'node-list-table-thin'}},
template_code='{% include "dashboard/node-list/column-actions.html" with btn_size="btn-xs" %}',
# actions = TemplateColumn('{% load my_filters %}{{ record.name|int_to_time }}'
# attrs={'th': {'class': 'node-list-table-thin'},'extra_tag':},
)
# time_of_suspend = TemplateColumn(
# '{{ record.time_of_suspend|timeuntil }}',
# verbose_name=_("Suspend in"))
# time_of_delete = TemplateColumn(
# '{{ record.time_of_delete|timeuntil }}',
# verbose_name=_("Delete in"))
class Meta: