Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
Gelencsér Szabolcs
/
circlestack
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
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