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
A prog2-höz tartozó friss repo anyagok itt elérhetőek:
https://git.iit.bme.hu/
Commit
5b01216a
authored
Aug 11, 2014
by
Kálmán Viktor
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
dashboard: views + templates
parent
aef328d4
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
162 additions
and
6 deletions
+162
-6
circle/dashboard/templates/dashboard/mass-operate.html
+52
-0
circle/dashboard/templates/dashboard/vm-list.html
+7
-0
circle/dashboard/urls.py
+1
-2
circle/dashboard/views.py
+90
-0
circle/dashboard/vm/urls.py
+12
-4
No files found.
circle/dashboard/templates/dashboard/mass-operate.html
0 → 100644
View file @
5b01216a
{% load i18n %}
{% load crispy_forms_tags %}
{% block question %}
<p>
{% blocktrans with op=op.name %}
Do you want to perform the following operation:
<strong>
{{op}}
</strong>
?
{% endblocktrans %}
</p>
<p
class=
"text-info"
>
{{op.description}}
</p>
{% endblock %}
<form
method=
"POST"
action=
"{{url}}"
>
{% csrf_token %}
{% for i in instances %}
<div
class=
"panel panel-default mass-op-panel"
>
<i
class=
"fa {{ i.get_status_icon }} fa-fw"
></i>
{{ i.name }} ({{ i.pk }})
<div
style=
"float: right;"
title=
"{{ i.disabled }}"
>
<i
class=
"fa status-icon
{% if i.disabled %}fa-minus-square minus{% else %}fa-check-square check{% endif %}"
>
</i>
</div>
</div>
<input
type=
"checkbox"
name=
"vm"
value=
"{{ i.pk }}"
{%
if
not
i
.
disabled
%}
checked
{%
endif
%}
style=
"display: none;"
/>
{% endfor %}
<div
class=
"pull-right"
>
<a
class=
"btn btn-default"
href=
"{% url "
dashboard
.
views
.
vm-list
"
%}"
data-dismiss=
"modal"
>
{% trans "Cancel" %}
</a>
<button
class=
"btn btn-{{ opview.effect }}"
type=
"submit"
id=
"op-form-send"
>
{% if opview.icon %}
<i
class=
"fa fa-{{opview.icon}}"
></i>
{% endif %}{{ opview.name|capfirst }}
</button>
</div>
</form>
<style>
.mass-op-panel
{
padding
:
6px
10px
;
}
.mass-op-panel
.check
{
color
:
#449d44
;
}
.mass-op-panel
.minus
{
color
:
#d9534f
;
}
.mass-op-panel
.status-icon
{
font-size
:
1.5em
;
}
</style>
circle/dashboard/templates/dashboard/vm-list.html
View file @
5b01216a
...
...
@@ -23,6 +23,13 @@
</div>
</form>
</div>
<p>
{% for o in ops %}
<a
href=
"{{ o.get_url }}"
class=
"btn btn-xs btn-{{ o.effect }}"
title=
"{{ o.name }}"
>
<i
class=
"fa fa-{{ o.icon }}"
></i>
</a>
{% endfor %}
</p>
<div
class=
"panel-body vm-list-group-control"
>
<p>
<strong>
{% trans "Group actions" %}
</strong>
...
...
circle/dashboard/urls.py
View file @
5b01216a
...
...
@@ -49,7 +49,6 @@ from .views import (
autocomplete_light
.
autodiscover
()
urlpatterns
=
patterns
(
''
,
url
(
r'^$'
,
IndexView
.
as_view
(),
name
=
"dashboard.index"
),
url
(
r'^lease/(?P<pk>\d+)/$'
,
LeaseDetail
.
as_view
(),
...
...
@@ -74,7 +73,7 @@ urlpatterns = patterns(
url
(
r"^template/delete/(?P<pk>\d+)/$"
,
TemplateDelete
.
as_view
(),
name
=
"dashboard.views.template-delete"
),
url
(
r'^vm/
(?P<pk>\d+)/op/
'
,
include
(
'dashboard.vm.urls'
)),
url
(
r'^vm/'
,
include
(
'dashboard.vm.urls'
)),
url
(
r'^vm/(?P<pk>\d+)/remove_port/(?P<rule>\d+)/$'
,
PortDelete
.
as_view
(),
name
=
'dashboard.views.remove-port'
),
url
(
r'^vm/(?P<pk>\d+)/$'
,
VmDetailView
.
as_view
(),
...
...
circle/dashboard/views.py
View file @
5b01216a
...
...
@@ -986,6 +986,91 @@ def get_operations(instance, user):
return
ops
class
MassOperationView
(
OperationView
):
template_name
=
'dashboard/mass-operate.html'
effect
=
"info"
@classmethod
def
get_urlname
(
cls
):
return
'dashboard.vm.mass-op.
%
s'
%
cls
.
op
@classmethod
def
get_url
(
cls
):
return
reverse
(
"dashboard.vm.mass-op.
%
s"
%
cls
.
op
)
def
get_op
(
self
,
instance
=
None
):
if
instance
:
return
getattr
(
instance
,
self
.
op
)
else
:
return
Instance
.
_ops
[
self
.
op
]
def
get_context_data
(
self
,
**
kwargs
):
ctx
=
super
(
MassOperationView
,
self
)
.
get_context_data
(
**
kwargs
)
instances
=
self
.
request
.
GET
.
getlist
(
"vm"
)
instances
=
Instance
.
objects
.
filter
(
pk__in
=
instances
)
ctx
[
'instances'
]
=
self
.
_check_instances
(
instances
,
self
.
request
.
user
)
return
ctx
def
check_auth
(
self
):
pass
def
get_object
(
self
):
return
None
def
_check_instances
(
self
,
instances
,
user
):
vms
=
[]
for
i
in
instances
:
try
:
self
.
_op_checks
(
i
,
user
)
except
HumanReadableException
as
e
:
setattr
(
i
,
"disabled"
,
e
.
get_user_text
())
except
SuspiciousOperation
:
continue
except
PermissionDenied
:
setattr
(
i
,
"disabled"
,
"No permission"
)
except
Exception
:
setattr
(
i
,
"disabled"
,
"Wrong state error, probably"
)
vms
.
append
(
i
)
return
vms
def
post
(
self
,
request
,
*
args
,
**
kwargs
):
user
=
self
.
request
.
user
vms
=
request
.
POST
.
getlist
(
"vm"
)
instances
=
Instance
.
objects
.
filter
(
pk__in
=
vms
)
for
i
in
instances
:
try
:
op
=
self
.
_op_checks
(
i
,
user
)
op
.
async
(
user
=
user
)
except
HumanReadableException
as
e
:
e
.
send_message
(
request
)
except
Exception
as
e
:
pass
return
redirect
(
reverse
(
"dashboard.views.vm-list"
))
def
_op_checks
(
self
,
instance
,
user
):
objects_of_user
=
Instance
.
get_objects_with_level
(
"user"
,
user
)
if
instance
not
in
objects_of_user
:
raise
SuspiciousOperation
()
op
=
self
.
get_op
(
instance
)
op
.
check_auth
(
user
)
op
.
check_precond
()
return
op
vm_mass_ops
=
OrderedDict
([
(
'deploy'
,
MassOperationView
.
factory
(
op
=
'deploy'
,
icon
=
'play'
,
effect
=
'success'
)),
(
'wake_up'
,
MassOperationView
.
factory
(
op
=
'wake_up'
,
icon
=
'sun-o'
,
effect
=
'success'
)),
(
'sleep'
,
MassOperationView
.
factory
(
op
=
'sleep'
,
icon
=
'moon-o'
,
effect
=
'info'
)),
(
'destroy'
,
MassOperationView
.
factory
(
op
=
'destroy'
,
icon
=
'times'
,
effect
=
'danger'
)),
])
class
NodeDetailView
(
LoginRequiredMixin
,
SuperuserRequiredMixin
,
DetailView
):
template_name
=
"dashboard/node-detail.html"
model
=
Node
...
...
@@ -1557,6 +1642,11 @@ class VmList(LoginRequiredMixin, FilterMixin, ListView):
'owner'
:
"owner__username"
,
}
def
get_context_data
(
self
,
*
args
,
**
kwargs
):
context
=
super
(
VmList
,
self
)
.
get_context_data
(
*
args
,
**
kwargs
)
context
[
'ops'
]
=
[
v
for
k
,
v
in
vm_mass_ops
.
iteritems
()]
return
context
def
get
(
self
,
*
args
,
**
kwargs
):
if
self
.
request
.
is_ajax
():
favs
=
Instance
.
objects
.
filter
(
...
...
circle/dashboard/vm/urls.py
View file @
5b01216a
...
...
@@ -17,9 +17,17 @@
from
django.conf.urls
import
patterns
,
url
from
..views
import
vm_ops
from
..views
import
vm_ops
,
vm_mass_ops
urlpatterns
=
patterns
(
''
,
*
(
url
(
r'^
%
s/$'
%
op
,
v
.
as_view
(),
name
=
v
.
get_urlname
())
for
op
,
v
in
vm_ops
.
iteritems
()))
urlpatterns
=
patterns
(
''
,
*
(
url
(
r'^(?P<pk>\d+)/op/
%
s/$'
%
op
,
v
.
as_view
(),
name
=
v
.
get_urlname
())
for
op
,
v
in
vm_ops
.
iteritems
())
)
urlpatterns
+=
patterns
(
''
,
*
(
url
(
r'^mass_op/
%
s/$'
%
op
,
v
.
as_view
(),
name
=
v
.
get_urlname
())
for
op
,
v
in
vm_mass_ops
.
iteritems
())
)
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