Commit 7fed7d2c by Bach Dániel

Merge branch 'feature-remove-garbage'

parents 32e83265 f876f926
...@@ -198,6 +198,7 @@ PIPELINE_JS = { ...@@ -198,6 +198,7 @@ PIPELINE_JS = {
"jquery-knob/dist/jquery.knob.min.js", "jquery-knob/dist/jquery.knob.min.js",
"jquery-simple-slider/js/simple-slider.js", "jquery-simple-slider/js/simple-slider.js",
"dashboard/dashboard.js", "dashboard/dashboard.js",
"dashboard/activity.js",
"dashboard/group-details.js", "dashboard/group-details.js",
"dashboard/group-list.js", "dashboard/group-list.js",
"dashboard/js/stupidtable.min.js", # no bower file "dashboard/js/stupidtable.min.js", # no bower file
......
...@@ -282,6 +282,8 @@ def register_operation(op_cls, op_id=None, target_cls=None): ...@@ -282,6 +282,8 @@ def register_operation(op_cls, op_id=None, target_cls=None):
"in the 'target_cls' parameter to this " "in the 'target_cls' parameter to this "
"call.") "call.")
assert not hasattr(target_cls, op_id), (
"target class already has an attribute with this id")
if not issubclass(target_cls, OperatedMixin): if not issubclass(target_cls, OperatedMixin):
raise TypeError("%r is not a subclass of %r" % raise TypeError("%r is not a subclass of %r" %
(target_cls.__name__, OperatedMixin.__name__)) (target_cls.__name__, OperatedMixin.__name__))
......
...@@ -898,7 +898,7 @@ class VmDownloadDiskForm(OperationForm): ...@@ -898,7 +898,7 @@ class VmDownloadDiskForm(OperationForm):
def clean(self): def clean(self):
cleaned_data = super(VmDownloadDiskForm, self).clean() cleaned_data = super(VmDownloadDiskForm, self).clean()
if not cleaned_data['name']: if not cleaned_data['name']:
if cleaned_data['url']: if cleaned_data.get('url'):
cleaned_data['name'] = urlparse( cleaned_data['name'] = urlparse(
cleaned_data['url']).path.split('/')[-1] cleaned_data['url']).path.split('/')[-1]
if not cleaned_data['name']: if not cleaned_data['name']:
...@@ -908,6 +908,36 @@ class VmDownloadDiskForm(OperationForm): ...@@ -908,6 +908,36 @@ class VmDownloadDiskForm(OperationForm):
return cleaned_data return cleaned_data
class VmRemoveInterfaceForm(OperationForm):
def __init__(self, *args, **kwargs):
choices = kwargs.pop('choices')
self.interface = kwargs.pop('default')
super(VmRemoveInterfaceForm, self).__init__(*args, **kwargs)
self.fields.insert(0, 'interface', forms.ModelChoiceField(
queryset=choices, initial=self.interface, required=True,
empty_label=None, label=_('Interface')))
if self.interface:
self.fields['interface'].widget = HiddenInput()
@property
def helper(self):
helper = super(VmRemoveInterfaceForm, self).helper
if self.interface:
helper.layout = Layout(
AnyTag(
"div",
HTML(format_html(
_("<label>Vlan:</label> {0}"),
self.interface.vlan)),
css_class="form-group",
),
Field("interface"),
)
return helper
class VmAddInterfaceForm(OperationForm): class VmAddInterfaceForm(OperationForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
choices = kwargs.pop('choices') choices = kwargs.pop('choices')
......
/* for functions in both vm list and vm detail */
$(function() { $(function() {
var in_progress = false;
var activity_hash = 5;
var show_all = false;
var reload_vm_detail = false;
/* do we need to check for new activities */
if(decideActivityRefresh()) {
if(!in_progress) {
checkNewActivity(1);
in_progress = true;
}
}
$('a[href="#activity"]').click(function(){
$('a[href="#activity"] i').addClass('fa-spin');
if(!in_progress) {
checkNewActivity(1);
in_progress = true;
}
});
$("#activity-refresh").on("click", "#show-all-activities", function() {
$(this).find("i").addClass("fa-spinner fa-spin");
show_all = !show_all;
$('a[href="#activity"]').trigger("click");
return false;
});
/* vm operations */ /* operations */
$('#ops, #vm-details-resources-disk, #vm-details-renew-op, #vm-details-pw-reset, #vm-details-add-interface, .operation-wrapper').on('click', '.operation', function(e) { $('#ops, #vm-details-resources-disk, #vm-details-renew-op, #vm-details-pw-reset, #vm-details-add-interface, .operation-wrapper').on('click', '.operation', function(e) {
var icon = $(this).children("i").addClass('fa-spinner fa-spin'); var icon = $(this).children("i").addClass('fa-spinner fa-spin');
...@@ -23,7 +48,7 @@ $(function() { ...@@ -23,7 +48,7 @@ $(function() {
}); });
/* if the operation fails show the modal again */ /* if the operation fails show the modal again */
$("body").on("click", "#op-form-send", function() { $("body").on("click", "#confirmation-modal #op-form-send", function() {
var url = $(this).closest("form").prop("action"); var url = $(this).closest("form").prop("action");
$.ajax({ $.ajax({
...@@ -77,4 +102,91 @@ $(function() { ...@@ -77,4 +102,91 @@ $(function() {
return false; return false;
}); });
function decideActivityRefresh() {
var check = false;
/* if something is still spinning */
if($('.timeline .activity i').hasClass('fa-spin'))
check = true;
return check;
}
function checkNewActivity(runs) {
$.ajax({
type: 'GET',
url: $('a[href="#activity"]').attr('data-activity-url'),
data: {'show_all': show_all},
success: function(data) {
var new_activity_hash = (data.activities + "").hashCode();
if(new_activity_hash != activity_hash) {
$("#activity-refresh").html(data.activities);
}
activity_hash = new_activity_hash;
$("#ops").html(data.ops);
$("#disk-ops").html(data.disk_ops);
$("[title]").tooltip();
/* changing the status text */
var icon = $("#vm-details-state i");
if(data.is_new_state) {
if(!icon.hasClass("fa-spin"))
icon.prop("class", "fa fa-spinner fa-spin");
} else {
icon.prop("class", "fa " + data.icon);
}
var vm_state = $("#vm-details-state");
if (vm_state.length) {
vm_state.data("status", data['status']);
$("#vm-details-state span").html(data['human_readable_status'].toUpperCase());
}
if(data['status'] == "RUNNING") {
if(data['connect_uri']) {
$("#dashboard-vm-details-connect-button").removeClass('disabled');
}
$("[data-target=#_console]").attr("data-toggle", "pill").attr("href", "#console").parent("li").removeClass("disabled");
} else {
if(data['connect_uri']) {
$("#dashboard-vm-details-connect-button").addClass('disabled');
}
$("[data-target=#_console]").attr("data-toggle", "_pill").attr("href", "#").parent("li").addClass("disabled");
}
if(data.status == "STOPPED" || data.status == "PENDING") {
$(".change-resources-button").prop("disabled", false);
$(".change-resources-help").hide();
} else {
$(".change-resources-button").prop("disabled", true);
$(".change-resources-help").show();
}
if(runs > 0 && decideActivityRefresh()) {
setTimeout(
function() {checkNewActivity(runs + 1);},
1000 + Math.exp(runs * 0.05)
);
} else {
in_progress = false;
if(reload_vm_detail) location.reload();
}
$('a[href="#activity"] i').removeClass('fa-spin');
},
error: function() {
in_progress = false;
}
});
}
}); });
String.prototype.hashCode = function() {
var hash = 0, i, chr, len;
if (this.length == 0) return hash;
for (i = 0, len = this.length; i < len; i++) {
chr = this.charCodeAt(i);
hash = ((hash << 5) - hash) + chr;
hash |= 0; // Convert to 32bit integer
}
return hash;
};
...@@ -5,63 +5,39 @@ $(function () { ...@@ -5,63 +5,39 @@ $(function () {
var template = $(this).data("template"); var template = $(this).data("template");
$.ajax({ $.ajax({
type: 'GET', type: 'GET',
url: '/dashboard/vm/create/' + (typeof template === "undefined" ? '' : '?template=' + template), url: $(this).attr('href'),
success: function(data) { success: function(data) {
$('body').append(data); $('body').append(data);
vmCreateLoaded(); vmCreateLoaded();
addSliderMiscs(); addSliderMiscs();
$('#create-modal').modal('show'); var modal = $('#confirmation-modal');
$('#create-modal').on('hidden.bs.modal', function() { modal.modal('show');
$('#create-modal').remove(); modal.on('hidden.bs.modal', function() {
modal.remove();
}); });
} }
}); });
return false; return false;
}); });
$('.node-create').click(function(e) { $('.group-create, .node-create, .tx-tpl-ownership, .group-delete, .node-delete, .disk-remove, .template-delete, .delete-from-group').click(function(e) {
$.ajax({ $.ajax({
type: 'GET', type: 'GET',
url: '/dashboard/node/create/', url: $(this).prop('href'),
success: function(data) { success: function(data) {
$('body').append(data); $('body').append(data);
nodeCreateLoaded(); var modal = $('#confirmation-modal');
addSliderMiscs(); modal.modal('show');
$('#create-modal').modal('show'); modal.on('hidden.bs.modal', function() {
$('#create-modal').on('hidden.bs.modal', function() { modal.remove();
$('#create-modal').remove();
});
}
});
return false;
});
$('.group-create').click(function(e) {
$.ajax({
type: 'GET',
url: '/dashboard/group/create/',
success: function(data) {
$('body').append(data);
addSliderMiscs();
$('#create-modal').modal('show');
$('#create-modal').on('hidden.bs.modal', function() {
$('#create-modal').remove();
}); });
},
error: function(xhr, textStatus, error) {
if(xhr.status === 403) {
addMessage(gettext("Only the owners can delete the selected object."), "warning");
} else {
addMessage(gettext("An error occurred. (") + xhr.status + ")", 'danger')
} }
});
return false;
});
$('.tx-tpl-ownership').click(function(e) {
$.ajax({
type: 'GET',
url: $('.tx-tpl-ownership').attr('href'),
success: function(data) {
$('body').append(data);
$('#confirmation-modal').modal('show');
$('#confirmation-modal').on('hidden.bs.modal', function() {
$('#confirmation-modal').remove();
});
} }
}); });
return false; return false;
...@@ -70,12 +46,13 @@ $(function () { ...@@ -70,12 +46,13 @@ $(function () {
$('.template-choose').click(function(e) { $('.template-choose').click(function(e) {
$.ajax({ $.ajax({
type: 'GET', type: 'GET',
url: '/dashboard/template/choose/', url: $(this).prop('href'),
success: function(data) { success: function(data) {
$('body').append(data); $('body').append(data);
$('#create-modal').modal('show'); var modal = $('#confirmation-modal');
$('#create-modal').on('hidden.bs.modal', function() { modal.modal('show');
$('#create-modal').remove(); modal.on('hidden.bs.modal', function() {
modal.remove();
}); });
// check if user selected anything // check if user selected anything
$("#template-choose-next-button").click(function() { $("#template-choose-next-button").click(function() {
...@@ -101,6 +78,7 @@ $(function () { ...@@ -101,6 +78,7 @@ $(function () {
e.stopImmediatePropagation(); e.stopImmediatePropagation();
return false; return false;
}); });
$('[href=#index-list-view]').click(function (e) { $('[href=#index-list-view]').click(function (e) {
var box = $(this).data('index-box'); var box = $(this).data('index-box');
$('#' + box + '-graph-view').hide(); $('#' + box + '-graph-view').hide();
...@@ -110,9 +88,10 @@ $(function () { ...@@ -110,9 +88,10 @@ $(function () {
e.stopImmediatePropagation(); e.stopImmediatePropagation();
return false; return false;
}); });
$('body [title]:not(.title-favourite)').tooltip();
$('body .title-favourite').tooltip({'placement': 'right'}); $('body .title-favourite').tooltip({'placement': 'right'});
$('body :input[title]').tooltip({trigger: 'focus', placement: 'auto right'}); $('body :input[title]').tooltip({trigger: 'focus', placement: 'auto right'});
$('body [title]').tooltip();
$(".knob").knob(); $(".knob").knob();
$('[data-toggle="pill"]').click(function() { $('[data-toggle="pill"]').click(function() {
...@@ -167,74 +146,6 @@ $(function () { ...@@ -167,74 +146,6 @@ $(function () {
addSliderMiscs(); addSliderMiscs();
/* for VM removes buttons */
$('.vm-delete').click(function() {
var vm_pk = $(this).data('vm-pk');
var dir = window.location.pathname.indexOf('list') == -1;
addModalConfirmation(deleteObject,
{ 'url': '/dashboard/vm/delete/' + vm_pk + '/',
'data': [],
'pk': vm_pk,
'type': "vm",
'redirect': dir});
return false;
});
/* for disk remove buttons */
$('.disk-remove').click(function() {
var disk_pk = $(this).data('disk-pk');
addModalConfirmation(deleteObject,
{ 'url': '/dashboard/disk/' + disk_pk + '/remove/',
'data': [],
'pk': disk_pk,
'type': "disk",
});
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(deleteObject,
{ 'url': '/dashboard/node/delete/' + node_pk + '/',
'data': [],
'pk': node_pk,
'type': "node",
'redirect': dir});
return false;
});
/* for Node flush buttons */
$('.node-flush').click(function() {
var node_pk = $(this).data('node-pk');
var postto = $(this).attr('href');
var dir = window.location.pathname.indexOf('list') == -1;
addModalConfirmation(function(){},
{ 'url': postto,
'data': [],
'pk': node_pk,
'type': "node",
'redirect': dir});
return false;
});
/* for Group removes buttons */
$('.group-delete').click(function() {
var group_pk = $(this).data('group-pk');
var dir = window.location.pathname.indexOf('list') == -1;
addModalConfirmation(deleteObject,
{ 'url': '/dashboard/group/delete/' + group_pk + '/',
'data': [],
'type': "group",
'pk': group_pk,
'redirect': dir});
return false;
});
/* search for vms */ /* search for vms */
var my_vms = []; var my_vms = [];
$("#dashboard-vm-search-input").keyup(function(e) { $("#dashboard-vm-search-input").keyup(function(e) {
...@@ -558,62 +469,6 @@ function setDefaultSliderValues() { ...@@ -558,62 +469,6 @@ function setDefaultSliderValues() {
} }
/* deletes the VM with the pk
* if dir is true, then redirect to the dashboard landing page
* else it adds a success message */
function deleteObject(data) {
$.ajax({
type: 'POST',
data: {'redirect': data.redirect},
url: data.url,
headers: {"X-CSRFToken": getCookie('csrftoken')},
success: function(re, textStatus, xhr) {
if(!data.redirect) {
selected = [];
addMessage(re.message, 'success');
if(data.type === "disk") {
// no need to remove them from DOM
$('a[data-disk-pk="' + data.pk + '"]').parent("li").fadeOut();
$('a[data-disk-pk="' + data.pk + '"]').parent("h4").fadeOut();
}
else {
$('a[data-'+data.type+'-pk="' + data.pk + '"]').closest('tr').fadeOut(function() {
$(this).remove();
});
}
} else {
window.location.replace('/dashboard');
}
},
error: function(xhr, textStatus, error) {
addMessage('Uh oh :(', 'danger');
}
});
}
function massDeleteVm(data) {
f = function() {
selected = [];
// reset group buttons
$('.vm-list-group-control a').attr('disabled', true);
$(this).remove();
};
$.ajax({
traditional: true,
url: data.url,
headers: {"X-CSRFToken": getCookie('csrftoken')},
type: 'POST',
data: {'vms': data.data.v},
success: function(re, textStatus, xhr) {
for(var i=0; i< data.data.v.length; i++)
$('.vm-list-table tbody tr[data-vm-pk="' + data.data.v[i] + '"]').fadeOut(500, f);
addMessage(re.message, 'success');
},
error: function(xhr, textStatus, error) {
// TODO this
}
});
}
function addMessage(text, type) { function addMessage(text, type) {
...@@ -701,6 +556,7 @@ function csrfSafeMethod(method) { ...@@ -701,6 +556,7 @@ function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection // these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
} }
$.ajaxSetup({ $.ajaxSetup({
beforeSend: function(xhr, settings) { beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) { if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
......
...@@ -28,39 +28,3 @@ ...@@ -28,39 +28,3 @@
$(".group-details-help-button").click(function() { $(".group-details-help-button").click(function() {
$(".group-details-help").stop().slideToggle(); $(".group-details-help").stop().slideToggle();
}); });
/* for Node removes buttons */
$('.delete-from-group').click(function() {
var href = $(this).attr('href');
var tr = $(this).closest('tr');
var group = $(this).data('group_pk');
var member = $(this).data('member_pk');
var dir = window.location.pathname.indexOf('list') == -1;
addModalConfirmation(removeMember,
{ 'url': href,
'data': [],
'tr': tr,
'group_pk': group,
'member_pk': member,
'type': "user",
'redirect': dir});
return false;
});
function removeMember(data) {
$.ajax({
type: 'POST',
url: data.url,
headers: {"X-CSRFToken": getCookie('csrftoken')},
success: function(re, textStatus, xhr) {
data.tr.fadeOut(function() {
$(this).remove();});
},
error: function(xhr, textStatus, error) {
addMessage('Uh oh :(', 'danger');
}
});
}
$(function() { $(function() {
/* rename */ /* rename */
$("#group-list-rename-button, .group-details-rename-button").click(function() { $("#group-list-rename-button, .group-details-rename-button").click(function() {
$("#group-list-column-name", $(this).closest("tr")).hide(); $(".group-list-column-name", $(this).closest("tr")).hide();
$("#group-list-rename", $(this).closest("tr")).css('display', 'inline'); $("#group-list-rename", $(this).closest("tr")).css('display', 'inline');
$("#group-list-rename").find("input").select(); $("#group-list-rename").find("input").select();
}); });
...@@ -10,7 +10,7 @@ $(function() { ...@@ -10,7 +10,7 @@ $(function() {
$('.group-list-rename-submit').click(function() { $('.group-list-rename-submit').click(function() {
var row = $(this).closest("tr"); var row = $(this).closest("tr");
var name = $('#group-list-rename-name', row).val(); var name = $('#group-list-rename-name', row).val();
var url = '/dashboard/group/' + row.children("td:first-child").text().replace(" ", "") + '/'; var url = row.find(".group-list-column-name a").prop("href");
$.ajax({ $.ajax({
method: 'POST', method: 'POST',
url: url, url: url,
...@@ -18,7 +18,7 @@ $(function() { ...@@ -18,7 +18,7 @@ $(function() {
headers: {"X-CSRFToken": getCookie('csrftoken')}, headers: {"X-CSRFToken": getCookie('csrftoken')},
success: function(data, textStatus, xhr) { success: function(data, textStatus, xhr) {
$("#group-list-column-name", row).html( $(".group-list-column-name", row).html(
$("<a/>", { $("<a/>", {
'class': "real-link", 'class': "real-link",
href: "/dashboard/group/" + data.group_pk + "/", href: "/dashboard/group/" + data.group_pk + "/",
......
$(function() {
nodeCreateLoaded();
});
function nodeCreateLoaded() {
/* no js compatibility */
$('.no-js-hidden').show();
$('.js-hidden').hide();
}
...@@ -30,20 +30,6 @@ $(function() { ...@@ -30,20 +30,6 @@ $(function() {
$(".node-details-help").stop().slideToggle(); $(".node-details-help").stop().slideToggle();
}); });
/* for Node removes buttons */
$('.node-enable').click(function() {
var node_pk = $(this).data('node-pk');
var dir = window.location.pathname.indexOf('list') == -1;
addModalConfirmation(changeNodeStatus,
{ 'url': '/dashboard/node/status/' + node_pk + '/',
'data': [],
'pk': node_pk,
'type': "node",
'redirect': dir});
return false;
});
// remove trait // remove trait
$('.node-details-remove-trait').click(function() { $('.node-details-remove-trait').click(function() {
var to_remove = $(this).data("trait-pk"); var to_remove = $(this).data("trait-pk");
...@@ -69,22 +55,3 @@ $(function() { ...@@ -69,22 +55,3 @@ $(function() {
}); });
}); });
function changeNodeStatus(data) {
$.ajax({
type: 'POST',
url: data.url,
headers: {"X-CSRFToken": getCookie('csrftoken')},
success: function(re, textStatus, xhr) {
if(!data.redirect) {
selected = [];
addMessage(re.message, 'success');
} else {
window.location.replace('/dashboard');
}
},
error: function(xhr, textStatus, error) {
addMessage('Uh oh :(', 'danger');
}
});
}
...@@ -9,49 +9,4 @@ $(function() { ...@@ -9,49 +9,4 @@ $(function() {
$('.false').closest("tr").addClass('danger'); $('.false').closest("tr").addClass('danger');
$('.true').closest("tr").removeClass('danger'); $('.true').closest("tr").removeClass('danger');
} }
function statuschangeSuccess(tr){
var tspan=tr.children('.enabled').children();
var buttons=tr.children('.actions').children('.btn-group').children('.dropdown-menu').children('li').children('.node-enable');
buttons.each(function(index){
if ($(this).css("display")=="block"){
$(this).css("display","none");
}
else{
$(this).css("display","block");
}
});
if(tspan.hasClass("false")){
tspan.removeClass("false");
tspan.addClass("true");
tspan.text("✔");
}
else{
tspan.removeClass("true");
tspan.addClass("false");
tspan.text("✘");
}
colortable();
}
$('#table_container').on('click','.node-enable',function() {
var tr= $(this).closest("tr");
var pk =$(this).attr('data-node-pk');
var url = $(this).attr('href');
$.ajax({
method: 'POST',
url: url,
data