Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
CIRCLE
/
cloud
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
94
Merge Requests
10
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
4c1443f2
authored
7 years ago
by
cloud
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
dashboard, storage, vm: add snapshot limit and minor fixes
parent
895d9a95
Pipeline
#626
passed with stage
in 0 seconds
Changes
7
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
61 additions
and
25 deletions
+61
-25
circle/dashboard/forms.py
+8
-1
circle/dashboard/migrations/0007_profile_disk_snapshot_limit.py
+20
-0
circle/dashboard/models.py
+5
-1
circle/dashboard/static/dashboard/dashboard.less
+2
-8
circle/dashboard/views/vm.py
+6
-5
circle/storage/models.py
+2
-2
circle/vm/operations.py
+18
-8
No files found.
circle/dashboard/forms.py
View file @
4c1443f2
...
...
@@ -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
...
...
This diff is collapsed.
Click to expand it.
circle/dashboard/migrations/0007_profile_disk_snapshot_limit.py
0 → 100644
View file @
4c1443f2
# -*- 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'
),
),
]
This diff is collapsed.
Click to expand it.
circle/dashboard/models.py
View file @
4c1443f2
...
...
@@ -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
...
...
This diff is collapsed.
Click to expand it.
circle/dashboard/static/dashboard/dashboard.less
View file @
4c1443f2
...
...
@@ -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;
...
...
This diff is collapsed.
Click to expand it.
circle/dashboard/views/vm.py
View file @
4c1443f2
...
...
@@ -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
()
...
...
This diff is collapsed.
Click to expand it.
circle/storage/models.py
View file @
4c1443f2
...
...
@@ -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'
,
)
This diff is collapsed.
Click to expand it.
circle/vm/operations.py
View file @
4c1443f2
...
...
@@ -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
(
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment