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
002facdf
authored
Nov 11, 2020
by
Szeberényi Imre
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'template_instance_limit' into 'master'
Template instance limit See merge request
!418
parents
9e18bdbf
729d6f82
Pipeline
#1361
passed with stage
in 0 seconds
Changes
6
Pipelines
1
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
63 additions
and
18 deletions
+63
-18
circle/dashboard/forms.py
+10
-2
circle/dashboard/migrations/0008_profile_template_instance_limit.py
+20
-0
circle/dashboard/models.py
+1
-0
circle/dashboard/tests/test_views.py
+2
-2
circle/dashboard/views/vm.py
+27
-14
circle/vm/models/instance.py
+3
-0
No files found.
circle/dashboard/forms.py
View file @
002facdf
...
...
@@ -1336,6 +1336,9 @@ class UserEditForm(forms.ModelForm):
instance_limit
=
forms
.
IntegerField
(
label
=
_
(
'Instance limit'
),
min_value
=
0
,
widget
=
NumberInput
)
template_instance_limit
=
forms
.
IntegerField
(
label
=
_
(
'Template instance limit'
),
min_value
=
0
,
widget
=
NumberInput
)
two_factor_secret
=
forms
.
CharField
(
label
=
_
(
'Two-factor authentication secret'
),
help_text
=
_
(
"Remove the secret key to disable two-factor "
...
...
@@ -1345,18 +1348,23 @@ class UserEditForm(forms.ModelForm):
super
(
UserEditForm
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
self
.
fields
[
"instance_limit"
]
.
initial
=
(
self
.
instance
.
profile
.
instance_limit
)
self
.
fields
[
"template_instance_limit"
]
.
initial
=
(
self
.
instance
.
profile
.
template_instance_limit
)
self
.
fields
[
"two_factor_secret"
]
.
initial
=
(
self
.
instance
.
profile
.
two_factor_secret
)
class
Meta
:
model
=
User
fields
=
(
'email'
,
'first_name'
,
'last_name'
,
'instance_limit'
,
'is_active'
,
"two_factor_secret"
,)
fields
=
(
'email'
,
'first_name'
,
'last_name'
,
'instance_limit'
,
'template_instance_limit'
,
'is_active'
,
'two_factor_secret'
,)
def
save
(
self
,
commit
=
True
):
user
=
super
(
UserEditForm
,
self
)
.
save
()
user
.
profile
.
instance_limit
=
(
self
.
cleaned_data
[
'instance_limit'
]
or
None
)
user
.
profile
.
template_instance_limit
=
(
self
.
cleaned_data
[
'template_instance_limit'
]
or
None
)
user
.
profile
.
two_factor_secret
=
(
self
.
cleaned_data
[
'two_factor_secret'
]
or
None
)
user
.
profile
.
save
()
...
...
circle/dashboard/migrations/0008_profile_template_instance_limit.py
0 → 100644
View file @
002facdf
# -*- coding: utf-8 -*-
# Generated by Django 1.11.25 on 2020-11-06 13:33
from
__future__
import
unicode_literals
from
django.db
import
migrations
,
models
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'dashboard'
,
'0007_groupprofile_disk_quota'
),
]
operations
=
[
migrations
.
AddField
(
model_name
=
'profile'
,
name
=
'template_instance_limit'
,
field
=
models
.
IntegerField
(
default
=
1
),
),
]
circle/dashboard/models.py
View file @
002facdf
...
...
@@ -178,6 +178,7 @@ class Profile(Model):
unique
=
True
,
blank
=
True
,
null
=
True
,
max_length
=
64
,
help_text
=
_
(
'Unique identifier of the person, e.g. a student number.'
))
instance_limit
=
IntegerField
(
default
=
5
)
template_instance_limit
=
IntegerField
(
default
=
1
)
use_gravatar
=
BooleanField
(
verbose_name
=
_
(
"Use Gravatar"
),
default
=
True
,
help_text
=
_
(
"Whether to use email address as Gravatar profile image"
))
...
...
circle/dashboard/tests/test_views.py
View file @
002facdf
...
...
@@ -534,7 +534,7 @@ class VmDetailTest(LoginMixin, MockCeleryMixin, TestCase):
with
patch
.
object
(
DeployOperation
,
'async'
)
as
async
:
response
=
c
.
post
(
"/dashboard/vm/create/"
,
{
'name'
:
'vm'
,
'amount'
:
2
,
'amount'
:
1
,
'customized'
:
1
,
'template'
:
1
,
'cpu_priority'
:
10
,
'cpu_count'
:
1
,
'ram_size'
:
128
,
...
...
@@ -543,7 +543,7 @@ class VmDetailTest(LoginMixin, MockCeleryMixin, TestCase):
assert
async
.
called
self
.
assertEqual
(
response
.
status_code
,
302
)
self
.
assertEqual
(
instance_count
+
2
,
Instance
.
objects
.
all
()
.
count
())
self
.
assertEqual
(
instance_count
+
1
,
Instance
.
objects
.
all
()
.
count
())
def
test_unpermitted_description_update
(
self
):
c
=
Client
()
...
...
circle/dashboard/views/vm.py
View file @
002facdf
...
...
@@ -460,8 +460,7 @@ class VmMigrateView(FormOperationMixin, VmOperationView):
if
isinstance
(
inst
,
Instance
):
nodes_w_traits
=
[
n
.
pk
for
n
in
Node
.
objects
.
filter
(
enabled
=
True
)
if
n
.
online
and
has_traits
(
inst
.
req_traits
.
all
(),
n
)
if
n
.
online
and
has_traits
(
inst
.
req_traits
.
all
(),
n
)
]
ctx
[
'nodes_w_traits'
]
=
nodes_w_traits
...
...
@@ -1166,24 +1165,28 @@ class VmCreate(LoginRequiredMixin, TemplateView):
# limit chekcs
try
:
limit
=
user
.
profile
.
instance_limit
instance_limit
=
user
.
profile
.
instance_limit
template_instance_limit
=
user
.
profile
.
template_instance_limit
except
Exception
as
e
:
logger
.
debug
(
'No profile or instance limit:
%
s'
,
e
)
else
:
try
:
amount
=
int
(
request
.
POST
.
get
(
"amount"
,
1
))
except
:
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
)
if
current
+
amount
>
limit
:
messages
.
error
(
request
,
_
(
'Instance limit (
%
d) exceeded.'
)
%
limit
)
if
request
.
is_ajax
():
return
HttpResponse
(
json
.
dumps
({
'redirect'
:
'/'
}),
content_type
=
"application/json"
)
else
:
return
redirect
(
'/'
)
# TODO this should definitely use a Form
amount
=
instance_limit
instances
=
Instance
.
active
.
filter
(
owner
=
user
)
.
count
()
template_instances
=
template
.
get_user_instances
(
user
)
.
count
()
logger
.
debug
(
'current instance use:
%
d, limit:
%
d'
,
instances
,
instance_limit
)
logger
.
debug
(
'current template instance use:
%
d, limit:
%
d'
,
template_instances
,
template_instance_limit
)
if
instances
+
amount
>
instance_limit
:
return
self
.
_limit_exceeded
(
instance_limit
,
request
)
if
template_instances
+
amount
>
template_instance_limit
:
return
self
.
_limit_exceeded
(
template_instance_limit
,
request
)
create_func
=
(
self
.
__create_normal
if
request
.
POST
.
get
(
"customized"
)
is
None
else
...
...
@@ -1191,6 +1194,16 @@ class VmCreate(LoginRequiredMixin, TemplateView):
return
create_func
(
request
,
template
,
*
args
,
**
kwargs
)
def
_limit_exceeded
(
self
,
limit
,
request
):
messages
.
error
(
request
,
_
(
'Instance limit (
%
d) exceeded.'
)
%
limit
)
if
request
.
is_ajax
():
return
HttpResponse
(
json
.
dumps
({
'redirect'
:
'/'
}),
content_type
=
"application/json"
)
else
:
return
redirect
(
'/'
)
@require_GET
def
get_vm_screenshot
(
request
,
pk
):
...
...
circle/vm/models/instance.py
View file @
002facdf
...
...
@@ -200,6 +200,9 @@ class InstanceTemplate(AclBase, VirtualMachineDescModel, TimeStampedModel):
def
get_running_instances
(
self
):
return
Instance
.
active
.
filter
(
template
=
self
,
status
=
"RUNNING"
)
def
get_user_instances
(
self
,
user
):
return
Instance
.
active
.
filter
(
template
=
self
,
owner
=
user
)
@property
def
metric_prefix
(
self
):
return
'template.
%
d'
%
self
.
pk
...
...
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