Commit 4c1443f2 by cloud

dashboard, storage, vm: add snapshot limit and minor fixes

parent 895d9a95
Pipeline #626 passed with stage
in 0 seconds
......@@ -1386,6 +1386,9 @@ class UserEditForm(forms.ModelForm):
label=_('Two-factor authentication secret'),
help_text=_("Remove the secret key to disable two-factor "
"authentication for this user."), required=False)
disk_snapshot_limit = forms.IntegerField(
label=_('Snapshot limit per disk'),
min_value=0, widget=NumberInput)
def __init__(self, *args, **kwargs):
super(UserEditForm, self).__init__(*args, **kwargs)
......@@ -1393,11 +1396,13 @@ class UserEditForm(forms.ModelForm):
self.instance.profile.instance_limit)
self.fields["two_factor_secret"].initial = (
self.instance.profile.two_factor_secret)
self.fields["disk_snapshot_limit"].initial = (
self.instance.profile.disk_snapshot_limit)
class Meta:
model = User
fields = ('email', 'first_name', 'last_name', 'instance_limit',
'is_active', "two_factor_secret", )
'disk_snapshot_limit', 'is_active', "two_factor_secret", )
def save(self, commit=True):
user = super(UserEditForm, self).save()
......@@ -1405,6 +1410,8 @@ class UserEditForm(forms.ModelForm):
self.cleaned_data['instance_limit'] or None)
user.profile.two_factor_secret = (
self.cleaned_data['two_factor_secret'] or None)
user.profile.disk_snapshot_limit = (
self.cleaned_data['disk_snapshot_limit'] or None)
user.profile.save()
return user
......
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-12-11 21:24
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('dashboard', '0006_auto_20170707_1909'),
]
operations = [
migrations.AddField(
model_name='profile',
name='disk_snapshot_limit',
field=models.IntegerField(default=3, help_text='Snapshot limit per disk.', verbose_name='disk snapshot limit'),
),
]
......@@ -200,6 +200,10 @@ class Profile(Model):
verbose_name=_('disk quota'),
default=2048 * 1024 * 1024,
help_text=_('Disk quota in mebibytes.'))
disk_snapshot_limit = IntegerField(
verbose_name=_('disk snapshot limit'),
default=3,
help_text=_('Snapshot limit per disk.'))
two_factor_secret = CharField(
verbose_name=_("two factor secret key"),
max_length=32, null=True, blank=True,
......@@ -332,7 +336,7 @@ def create_profile(user):
try:
Store(user).create_user(profile.smb_password, None, profile.disk_quota)
except:
except Exception:
logger.exception("Can't create user %s", unicode(user))
return created
......
......@@ -1536,16 +1536,10 @@ textarea[name="new_members"] {
background: gray;
}
.show-snapshot-btn {
margin-top: 10px;
}
.disk-create_snapshot-btn {
margin-right: 5px;
}
.snapshot-table {
background: white;
}
#two-factor-qr {
text-align: center;
......
......@@ -248,7 +248,7 @@ class VmDetailView(GraphMixin, CheckedDetailView):
try:
messages.error(request, message)
except:
except Exception:
pass
return redirect(reverse_lazy("dashboard.views.detail",
......@@ -263,7 +263,7 @@ class VmDetailView(GraphMixin, CheckedDetailView):
self.object.tags.remove(to_remove)
message = u"Success"
except: # note this won't really happen
except Exception: # note this won't really happen
message = u"Not success"
if request.is_ajax():
......@@ -808,7 +808,8 @@ vm_ops = OrderedDict([
)),
('create_snapshot', VmDiskModifyView.factory(
op='create_snapshot', icon='camera', effect='success',
form_class=VmSnapshotDiskForm)),
form_class=VmSnapshotDiskForm,
)),
('remove_snapshot', VmCommonSnapshotDiskView.factory(
op='remove_snapshot', icon='times', effect='danger')),
('revert_snapshot', VmCommonSnapshotDiskView.factory(
......@@ -1182,7 +1183,7 @@ class VmCreate(LoginRequiredMixin, TemplateView):
else:
try:
amount = int(request.POST.get("amount", 1))
except:
except Exception:
amount = limit # TODO this should definitely use a Form
current = Instance.active.filter(owner=user).count()
logger.debug('current use: %d, limit: %d', current, limit)
......@@ -1207,7 +1208,7 @@ def get_vm_screenshot(request, pk):
instance = get_object_or_404(Instance, pk=pk)
try:
image = instance.screenshot(user=request.user).getvalue()
except:
except Exception:
# TODO handle this better
raise Http404()
......
......@@ -564,7 +564,7 @@ class Disk(TimeStampedModel):
disk.destroy()
raise humanize_exception(ugettext_noop(
"Operation aborted by user."), e)
except:
except Exception:
disk.destroy()
raise
disk.is_ready = True
......@@ -581,4 +581,4 @@ class Disk(TimeStampedModel):
@property
def is_read_only(self):
return not self.type in ('qcow2-norm', 'raw-rw', )
return self.type not in ('qcow2-norm', 'raw-rw', )
......@@ -321,6 +321,16 @@ class CreateSnapshotDiskOperation(RemoteSnapshotDiskOperation):
self.disk.did_have_snapshot = True
self.disk.save()
def _operation(self, disk, **kwargs):
user = kwargs.get('user')
snap_num = len(disk.list_snapshots())
limit = user.profile.disk_snapshot_limit
if snap_num == limit:
raise humanize_exception(ugettext_noop(
"Snapshot limit (%(limit)d) exceeded."),
PermissionDenied(), limit=limit)
super(CreateSnapshotDiskOperation, self)._operation(disk, **kwargs)
def get_activity_name(self, kwargs):
return create_readable(
ugettext_noop('Created snapshot %(snap_name)s'
......@@ -478,7 +488,7 @@ class DeployOperation(InstanceOperation):
# Deploy virtual images
try:
self.instance._deploy_disks(parent_activity=activity)
except:
except Exception:
self.instance.yield_node()
self.instance.yield_vnc_port()
raise
......@@ -495,7 +505,7 @@ class DeployOperation(InstanceOperation):
try:
self.instance.renew(parent_activity=activity)
except:
except Exception:
pass
self.instance._resume_vm(parent_activity=activity)
......@@ -580,7 +590,7 @@ class DestroyOperation(InstanceOperation):
# Delete mem. dump if exists
try:
self.instance._delete_mem_dump(parent_activity=activity)
except:
except Exception:
pass
# Clear node and VNC port association
......@@ -827,7 +837,7 @@ class SaveAsTemplateOperation(InstanceOperation):
with_shutdown=True, clone=False, task=None, **kwargs):
try:
self.instance._cleanup(parent_activity=activity, user=user)
except:
except Exception:
pass
if with_shutdown:
......@@ -891,7 +901,7 @@ class SaveAsTemplateOperation(InstanceOperation):
# create interface templates
for i in self.instance.interface_set.all():
i.save_as_template(tmpl)
except:
except Exception:
tmpl.delete()
raise
else:
......@@ -1046,7 +1056,7 @@ class WakeUpOperation(InstanceOperation):
try:
self.instance.renew(parent_activity=activity)
except:
except Exception:
pass
@register_operation
......@@ -1446,7 +1456,7 @@ class RecoverOperation(InstanceOperation):
try:
self.instance.renew(parent_activity=activity)
except:
except Exception:
pass
if self.instance.template:
......@@ -1636,7 +1646,7 @@ class AgentStartedOperation(InstanceOperation):
if not self.initialized:
try:
self.measure_boot_time()
except:
except Exception:
logger.exception('Unhandled error in measure_boot_time()')
self.instance._cleanup(parent_activity=activity)
self.instance.password_reset(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment