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
eae91fdd
authored
7 years ago
by
Czémán Arnold
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
dashboard, manager, vm: adds basic auto migration view and fake auto_migrate task
parent
4d7f1820
Pipeline
#634
passed with stage
in 0 seconds
Changes
9
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
104 additions
and
2 deletions
+104
-2
circle/circle/settings/base.py
+3
-0
circle/dashboard/forms.py
+8
-0
circle/dashboard/static/dashboard/dashboard.less
+4
-0
circle/dashboard/static/dashboard/node-list.js
+7
-0
circle/dashboard/templates/dashboard/node-list.html
+19
-0
circle/dashboard/urls.py
+3
-0
circle/dashboard/views/node.py
+33
-2
circle/manager/mancelery.py
+19
-0
circle/vm/tasks/local_periodic_tasks.py
+8
-0
No files found.
circle/circle/settings/base.py
View file @
eae91fdd
...
@@ -587,3 +587,6 @@ REQUEST_HOOK_URL = get_env_variable("REQUEST_HOOK_URL", "")
...
@@ -587,3 +587,6 @@ REQUEST_HOOK_URL = get_env_variable("REQUEST_HOOK_URL", "")
SSHKEY_EMAIL_ADD_KEY
=
False
SSHKEY_EMAIL_ADD_KEY
=
False
TWO_FACTOR_ISSUER
=
get_env_variable
(
"TWO_FACTOR_ISSUER"
,
"CIRCLE"
)
TWO_FACTOR_ISSUER
=
get_env_variable
(
"TWO_FACTOR_ISSUER"
,
"CIRCLE"
)
# Default value is every day at midnight
AUTO_MIGRATION_CRONTAB
=
get_env_variable
(
"AUTO_MIGRATION_CRONTAB"
,
"0 0 * * *"
)
This diff is collapsed.
Click to expand it.
circle/dashboard/forms.py
View file @
eae91fdd
...
@@ -1697,3 +1697,11 @@ class TwoFactorConfirmationForm(forms.Form):
...
@@ -1697,3 +1697,11 @@ class TwoFactorConfirmationForm(forms.Form):
totp
=
pyotp
.
TOTP
(
self
.
user
.
profile
.
two_factor_secret
)
totp
=
pyotp
.
TOTP
(
self
.
user
.
profile
.
two_factor_secret
)
if
not
totp
.
verify
(
self
.
cleaned_data
.
get
(
'confirmation_code'
)):
if
not
totp
.
verify
(
self
.
cleaned_data
.
get
(
'confirmation_code'
)):
raise
ValidationError
(
_
(
"Invalid confirmation code."
))
raise
ValidationError
(
_
(
"Invalid confirmation code."
))
class
AutoMigrationForm
(
forms
.
Form
):
minute
=
forms
.
CharField
()
hour
=
forms
.
CharField
()
day_of_month
=
forms
.
CharField
()
month_of_year
=
forms
.
CharField
()
day_of_week
=
forms
.
CharField
()
This diff is collapsed.
Click to expand it.
circle/dashboard/static/dashboard/dashboard.less
View file @
eae91fdd
...
@@ -1079,6 +1079,10 @@ textarea[name="new_members"] {
...
@@ -1079,6 +1079,10 @@ textarea[name="new_members"] {
max-width: 100%;
max-width: 100%;
}
}
#node-list-auto-migration-body {
padding: 20px;
}
#vm-list-table td.state,
#vm-list-table td.state,
#vm-list-table td.memory {
#vm-list-table td.memory {
white-space: nowrap;
white-space: nowrap;
...
...
This diff is collapsed.
Click to expand it.
circle/dashboard/static/dashboard/node-list.js
View file @
eae91fdd
...
@@ -3,4 +3,11 @@ $(function() {
...
@@ -3,4 +3,11 @@ $(function() {
// find disabled nodes, set danger (red) on the rows
// find disabled nodes, set danger (red) on the rows
$
(
'.node-disabled'
).
closest
(
"tr"
).
addClass
(
'danger'
);
$
(
'.node-disabled'
).
closest
(
"tr"
).
addClass
(
'danger'
);
});
});
$
(
'#reschedule-now'
).
click
(
function
()
{
$
.
get
(
$
(
this
).
attr
(
'href'
),
function
(
data
){
highlight
=
data
.
result
===
'ok'
?
'success'
:
'danger'
;
addMessage
(
data
.
message
,
highlight
);
});
return
false
;
});
});
});
This diff is collapsed.
Click to expand it.
circle/dashboard/templates/dashboard/node-list.html
View file @
eae91fdd
...
@@ -41,4 +41,23 @@
...
@@ -41,4 +41,23 @@
</div>
<!-- -col-md-12 -->
</div>
<!-- -col-md-12 -->
</div>
<!-- .row -->
</div>
<!-- .row -->
<div
class=
"row"
>
<div
class=
"col-md-12"
>
<div
class=
"panel panel-default"
>
<div
class=
"panel-heading"
>
<a
id=
"reschedule-now"
class=
"btn btn-danger pull-right"
href=
"{% url "
dashboard
.
views
.
reschedule
"
%}"
>
<i
class=
"fa fa-magic"
></i>
{% trans "Reschedule now" %}
</a>
<h3
class=
"no-margin"
><i
class=
"fa fa-truck"
></i>
{% trans "Virtual machine auto migration" %}
</h3>
</div>
<div
id=
"node-list-auto-migration-body"
>
<h1>
Crontab
</h1>
<form>
{{ auto_migration_form.as_p }}
</form>
</div>
</div>
</div>
<!-- -col-md-12 -->
</div>
<!-- .row -->
{% endblock %}
{% endblock %}
This diff is collapsed.
Click to expand it.
circle/dashboard/urls.py
View file @
eae91fdd
...
@@ -56,6 +56,7 @@ from .views import (
...
@@ -56,6 +56,7 @@ from .views import (
MessageList
,
MessageDetail
,
MessageCreate
,
MessageDelete
,
MessageList
,
MessageDetail
,
MessageCreate
,
MessageDelete
,
EnableTwoFactorView
,
DisableTwoFactorView
,
EnableTwoFactorView
,
DisableTwoFactorView
,
AclUserGroupAutocomplete
,
AclUserAutocomplete
,
AclUserGroupAutocomplete
,
AclUserAutocomplete
,
RescheduleView
,
)
)
from
.views.vm
import
vm_ops
,
vm_mass_ops
from
.views.vm
import
vm_ops
,
vm_mass_ops
from
.views.node
import
node_ops
from
.views.node
import
node_ops
...
@@ -153,6 +154,8 @@ urlpatterns = [
...
@@ -153,6 +154,8 @@ urlpatterns = [
r'(?P<time>[0-9]{1,2}[hdwy])$'
),
r'(?P<time>[0-9]{1,2}[hdwy])$'
),
NodeListGraphView
.
as_view
(),
NodeListGraphView
.
as_view
(),
name
=
'dashboard.views.node-list-graph'
),
name
=
'dashboard.views.node-list-graph'
),
url
(
r'^node/reschedule/$'
,
RescheduleView
.
as_view
(),
name
=
"dashboard.views.reschedule"
),
url
((
r'^template/(?P<pk>\d+)/graph/(?P<metric>[a-z]+)/'
url
((
r'^template/(?P<pk>\d+)/graph/(?P<metric>[a-z]+)/'
r'(?P<time>[0-9]{1,2}[hdwy])$'
),
r'(?P<time>[0-9]{1,2}[hdwy])$'
),
TemplateGraphView
.
as_view
(),
TemplateGraphView
.
as_view
(),
...
...
This diff is collapsed.
Click to expand it.
circle/dashboard/views/node.py
View file @
eae91fdd
...
@@ -25,7 +25,7 @@ from django.core.exceptions import PermissionDenied
...
@@ -25,7 +25,7 @@ from django.core.exceptions import PermissionDenied
from
django.core.urlresolvers
import
reverse_lazy
from
django.core.urlresolvers
import
reverse_lazy
from
django.db.models
import
Count
from
django.db.models
import
Count
from
django.forms.models
import
inlineformset_factory
from
django.forms.models
import
inlineformset_factory
from
django.http
import
HttpResponse
from
django.http
import
HttpResponse
,
JsonResponse
from
django.shortcuts
import
redirect
from
django.shortcuts
import
redirect
from
django.template.loader
import
render_to_string
from
django.template.loader
import
render_to_string
from
django.utils.translation
import
ugettext
as
_
from
django.utils.translation
import
ugettext
as
_
...
@@ -37,11 +37,14 @@ from django_tables2 import SingleTableView
...
@@ -37,11 +37,14 @@ from django_tables2 import SingleTableView
from
firewall.models
import
Host
from
firewall.models
import
Host
from
vm.models
import
Node
,
NodeActivity
,
Trait
from
vm.models
import
Node
,
NodeActivity
,
Trait
from
vm.tasks.vm_tasks
import
check_queue
from
vm.tasks.vm_tasks
import
check_queue
from
vm.tasks.local_periodic_tasks
import
auto_migrate
from
..forms
import
TraitForm
,
HostForm
,
NodeForm
from
..forms
import
TraitForm
,
HostForm
,
NodeForm
,
AutoMigrationForm
from
..tables
import
NodeListTable
from
..tables
import
NodeListTable
from
.util
import
AjaxOperationMixin
,
OperationView
,
GraphMixin
,
DeleteViewBase
from
.util
import
AjaxOperationMixin
,
OperationView
,
GraphMixin
,
DeleteViewBase
from
manager.mancelery
import
crontab_parser
def
get_operations
(
instance
,
user
):
def
get_operations
(
instance
,
user
):
ops
=
[]
ops
=
[]
...
@@ -190,6 +193,14 @@ class NodeList(LoginRequiredMixin, GraphMixin, SingleTableView):
...
@@ -190,6 +193,14 @@ class NodeList(LoginRequiredMixin, GraphMixin, SingleTableView):
table_class
=
NodeListTable
table_class
=
NodeListTable
table_pagination
=
False
table_pagination
=
False
def
get_crontab
(
self
):
return
crontab_parser
(
settings
.
AUTO_MIGRATION_CRONTAB
)
def
get_context_data
(
self
):
context
=
super
(
NodeList
,
self
)
.
get_context_data
()
context
[
"auto_migration_form"
]
=
AutoMigrationForm
(
self
.
get_crontab
())
return
context
def
get
(
self
,
*
args
,
**
kwargs
):
def
get
(
self
,
*
args
,
**
kwargs
):
if
not
self
.
request
.
user
.
has_perm
(
'vm.view_statistics'
):
if
not
self
.
request
.
user
.
has_perm
(
'vm.view_statistics'
):
raise
PermissionDenied
()
raise
PermissionDenied
()
...
@@ -356,3 +367,23 @@ class NodeActivityDetail(LoginRequiredMixin, SuperuserRequiredMixin,
...
@@ -356,3 +367,23 @@ class NodeActivityDetail(LoginRequiredMixin, SuperuserRequiredMixin,
)
.
order_by
(
'-started'
)
.
select_related
())
)
.
order_by
(
'-started'
)
.
select_related
())
ctx
[
'icon'
]
=
_get_activity_icon
(
self
.
object
)
ctx
[
'icon'
]
=
_get_activity_icon
(
self
.
object
)
return
ctx
return
ctx
class
RescheduleView
(
SuperuserRequiredMixin
,
View
):
def
get
(
self
,
*
args
,
**
kwargs
):
try
:
auto_migrate
.
apply_async
(
queue
=
'localhost.man.slow'
)
except
Exception
as
e
:
msg
=
str
(
e
)
result
=
'error'
else
:
result
=
'ok'
msg
=
_
(
'Reschedule has started.'
)
if
self
.
request
.
is_ajax
():
return
JsonResponse
({
'result'
:
result
,
'message'
:
msg
})
else
:
if
result
==
'ok'
:
messages
.
success
(
self
.
request
,
msg
)
else
:
messages
.
error
(
self
.
request
,
msg
)
return
redirect
(
'dashboard.views.node-list'
)
This diff is collapsed.
Click to expand it.
circle/manager/mancelery.py
View file @
eae91fdd
...
@@ -17,12 +17,26 @@
...
@@ -17,12 +17,26 @@
from
celery
import
Celery
from
celery
import
Celery
from
celery.signals
import
worker_ready
from
celery.signals
import
worker_ready
from
celery.schedules
import
crontab
from
datetime
import
timedelta
from
datetime
import
timedelta
from
kombu
import
Queue
,
Exchange
from
kombu
import
Queue
,
Exchange
from
os
import
getenv
from
os
import
getenv
HOSTNAME
=
"localhost"
HOSTNAME
=
"localhost"
QUEUE_NAME
=
HOSTNAME
+
'.man'
QUEUE_NAME
=
HOSTNAME
+
'.man'
AUTO_MIGRATION_CRONTAB
=
getenv
(
'AUTO_MIGRATION_CRONTAB'
,
'0 0 * * *'
)
def
crontab_parser
(
crontab
):
fields
=
crontab
.
split
(
' '
)
return
dict
(
minute
=
fields
[
0
],
hour
=
fields
[
1
],
day_of_month
=
fields
[
2
],
month_of_year
=
fields
[
3
],
day_of_week
=
fields
[
4
],
)
celery
=
Celery
(
'manager'
,
celery
=
Celery
(
'manager'
,
...
@@ -55,6 +69,11 @@ celery.conf.update(
...
@@ -55,6 +69,11 @@ celery.conf.update(
'schedule'
:
timedelta
(
hours
=
24
),
'schedule'
:
timedelta
(
hours
=
24
),
'options'
:
{
'queue'
:
'localhost.man'
}
'options'
:
{
'queue'
:
'localhost.man'
}
},
},
'vm.local_periodic_tasks'
:
{
'task'
:
'vm.tasks.local_periodic_tasks.auto_migrate'
,
'schedule'
:
crontab
(
**
crontab_parser
(
AUTO_MIGRATION_CRONTAB
)),
'options'
:
{
'queue'
:
'localhost.man.slow'
},
},
}
}
)
)
...
...
This diff is collapsed.
Click to expand it.
circle/vm/tasks/local_periodic_tasks.py
View file @
eae91fdd
...
@@ -76,3 +76,11 @@ def garbage_collector(timeout=15):
...
@@ -76,3 +76,11 @@ def garbage_collector(timeout=15):
i
.
notify_owners_about_expiration
()
i
.
notify_owners_about_expiration
()
else
:
else
:
logger
.
debug
(
"Instance
%
d didn't expire."
%
i
.
pk
)
logger
.
debug
(
"Instance
%
d didn't expire."
%
i
.
pk
)
@celery.task
(
ignore_result
=
True
)
def
auto_migrate
():
# Dummy implementation
import
time
logger
.
info
(
"Auto migration has started."
)
time
.
sleep
(
10
)
logger
.
info
(
"Auto migration has finished."
)
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