Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
Gutyán Gábor
/
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
e155a219
authored
Mar 19, 2018
by
Szabolcs Gelencser
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add initial template details view
parent
29ed5533
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
132 additions
and
129 deletions
+132
-129
.idea/workspace.xml
+0
-0
circle/circle/os_policies/circle_policy.json
+2
-2
circle/dashboard/forms.py
+67
-67
circle/dashboard/templates/dashboard/template-edit.html
+13
-13
circle/dashboard/urls.py
+9
-8
circle/dashboard/views/template.py
+41
-39
circle/dashboard/views/util.py
+0
-0
No files found.
.idea/workspace.xml
View file @
e155a219
This diff is collapsed.
Click to expand it.
circle/circle/os_policies/circle_policy.json
View file @
e155a219
{
"admin_or_owner"
:
"is_admin:True or (role:admin and is_admin_project:True) or project_id:%(project_id)s"
,
"default"
:
"rule:admin_or_owner"
,
"template:create"
:
""
"template:create"
:
"
rule:admin_or_owner
"
}
\ No newline at end of file
circle/dashboard/forms.py
View file @
e155a219
...
...
@@ -502,77 +502,77 @@ class NodeForm(forms.ModelForm):
class
TemplateForm
(
forms
.
ModelForm
):
networks
=
forms
.
ModelMultipleChoiceField
(
queryset
=
None
,
required
=
False
,
label
=
_
(
"Networks"
))
num_cores
=
forms
.
IntegerField
(
widget
=
forms
.
NumberInput
(
attrs
=
{
'class'
:
"form-control input-tags cpu-count-input"
,
'min'
:
1
,
'max'
:
10
,
'required'
:
""
,
}),
min_value
=
1
,
max_value
=
10
,
)
ram_size
=
forms
.
IntegerField
(
widget
=
forms
.
NumberInput
(
attrs
=
{
'class'
:
"form-control input-tags ram-input"
,
'min'
:
128
,
'max'
:
MAX_NODE_RAM
,
'step'
:
128
,
'required'
:
""
,
}),
min_value
=
128
,
max_value
=
MAX_NODE_RAM
,
)
priority
=
forms
.
ChoiceField
(
priority_choices
,
widget
=
forms
.
Select
(
attrs
=
{
'class'
:
"form-control input-tags cpu-priority-input"
,
}))
# networks = forms.ModelMultipleChoiceField(queryset=None, required=False, label=_("Networks"))
#
# num_cores = forms.IntegerField(widget=forms.NumberInput(attrs={
# 'class': "form-control input-tags cpu-count-input",
# 'min': 1,
# 'max': 10,
# 'required': "",
# }),
# min_value=1, max_value=10,
# )
#
# ram_size = forms.IntegerField(widget=forms.NumberInput(attrs={
# 'class': "form-control input-tags ram-input",
# 'min': 128,
# 'max': MAX_NODE_RAM,
# 'step': 128,
# 'required': "",
# }),
# min_value=128, max_value=MAX_NODE_RAM,
# )
#
# priority = forms.ChoiceField(priority_choices, widget=forms.Select(attrs={
# 'class': "form-control input-tags cpu-priority-input",
# }))
name
=
forms
.
TextInput
()
flavor
=
forms
.
ChoiceField
([
'a'
,
'b'
,
'c'
])
def
__init__
(
self
,
*
args
,
**
kwargs
):
self
.
user
=
kwargs
.
pop
(
"user"
,
None
)
super
(
TemplateForm
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
self
.
fields
[
'networks'
]
.
queryset
=
Vlan
.
get_objects_with_level
(
'user'
,
self
.
user
)
data
=
self
.
data
.
copy
()
data
[
'owner'
]
=
self
.
user
.
pk
self
.
data
=
data
if
self
.
instance
.
pk
:
n
=
self
.
instance
.
interface_set
.
values_list
(
"vlan"
,
flat
=
True
)
self
.
initial
[
'networks'
]
=
n
if
self
.
instance
.
pk
and
not
self
.
instance
.
has_level
(
self
.
user
,
'owner'
):
self
.
allowed_fields
=
()
else
:
self
.
allowed_fields
=
(
'name'
,
'access_method'
,
'description'
,
'system'
,
'tags'
,
'arch'
,
'lease'
,
'has_agent'
)
if
(
self
.
user
.
has_perm
(
'vm.change_template_resources'
)
or
not
self
.
instance
.
pk
):
self
.
allowed_fields
+=
tuple
(
set
(
self
.
fields
.
keys
())
-
set
([
'raw_data'
]))
if
self
.
user
.
is_superuser
:
self
.
allowed_fields
+=
(
'raw_data'
,
)
for
name
,
field
in
self
.
fields
.
items
():
if
name
not
in
self
.
allowed_fields
:
field
.
widget
.
attrs
[
'disabled'
]
=
'disabled'
if
not
self
.
instance
.
pk
and
len
(
self
.
errors
)
<
1
:
self
.
initial
[
'num_cores'
]
=
1
self
.
initial
[
'priority'
]
=
10
self
.
initial
[
'ram_size'
]
=
512
self
.
initial
[
'max_ram_size'
]
=
512
lease_queryset
=
(
Lease
.
get_objects_with_level
(
"operator"
,
self
.
user
)
.
distinct
()
|
Lease
.
objects
.
filter
(
pk
=
self
.
instance
.
lease_id
)
.
distinct
())
self
.
fields
[
"lease"
]
.
queryset
=
lease_queryset
self
.
fields
[
'raw_data'
]
.
validators
.
append
(
domain_validator
)
#
# self.fields['networks'].queryset = ()#Vlan.get_objects_with_level('user', self.user)
#
# data = self.data.copy()
# data['owner'] = self.user.pk
# self.data = data
#
# if self.instance.pk:
# n = self.instance.interface_set.values_list("vlan", flat=True)
# self.initial['networks'] = n
#
# if self.instance.pk and not self.instance.has_level(self.user, 'owner'):
# self.allowed_fields = ()
# else:
# self.allowed_fields = (
# 'name', 'access_method', 'description', 'system', 'tags',
# 'arch', 'lease', 'has_agent')
# if (self.user.has_perm('vm.change_template_resources') or
# not self.instance.pk):
# self.allowed_fields += tuple(set(self.fields.keys()) -
# set(['raw_data']))
# if self.user.is_superuser:
# self.allowed_fields += ('raw_data', )
# for name, field in self.fields.items():
# if name not in self.allowed_fields:
# field.widget.attrs['disabled'] = 'disabled'
#
# if not self.instance.pk and len(self.errors) < 1:
# self.initial['num_cores'] = 1
# self.initial['priority'] = 10
# self.initial['ram_size'] = 512
# self.initial['max_ram_size'] = 512
#
# lease_queryset = (
# Lease.get_objects_with_level("operator", self.user).distinct() |
# Lease.objects.filter(pk=self.instance.lease_id).distinct())
#
# self.fields["lease"].queryset = lease_queryset
#
# self.fields['raw_data'].validators.append(domain_validator)
def
clean_owner
(
self
):
if
self
.
instance
.
pk
is
not
None
:
...
...
circle/dashboard/templates/dashboard/template-edit.html
View file @
e155a219
...
...
@@ -39,26 +39,26 @@
<fieldset
class=
"resources-sliders"
>
<legend>
{% trans "Resource configuration" %}
</legend>
{% include "dashboard/_resources-sliders.html" with field_priority=form.priority field_num_cores=form.num_cores field_ram_size=form.ram_size %}
{{ form.max_ram_size|as_crispy_field }
}
{# {{ form.max_ram_size|as_crispy_field }}#
}
</fieldset>
<fieldset>
<legend>
{% trans "Virtual machine settings" %}
</legend>
{{ form.arch|as_crispy_field }
}
{{ form.access_method|as_crispy_field }
}
{{ form.boot_menu|as_crispy_field }
}
{{ form.raw_data|as_crispy_field }
}
{{ form.req_traits|as_crispy_field }
}
{{ form.description|as_crispy_field }
}
{{ form.system|as_crispy_field }
}
{{ form.has_agent|as_crispy_field }
}
{# {{ form.arch|as_crispy_field }}#
}
{# {{ form.access_method|as_crispy_field }}#
}
{# {{ form.boot_menu|as_crispy_field }}#
}
{# {{ form.raw_data|as_crispy_field }}#
}
{# {{ form.req_traits|as_crispy_field }}#
}
{# {{ form.description|as_crispy_field }}#
}
{# {{ form.system|as_crispy_field }}#
}
{# {{ form.has_agent|as_crispy_field }}#
}
</fieldset>
<fieldset>
<legend>
{% trans "External resources" %}
</legend>
{{ form.networks|as_crispy_field }
}
{{ form.lease|as_crispy_field }
}
{{ form.tags|as_crispy_field }
}
{# {{ form.networks|as_crispy_field }}#
}
{# {{ form.lease|as_crispy_field }}#
}
{##}
{# {{ form.tags|as_crispy_field }}#
}
</fieldset>
<input
type=
"submit"
value=
"{% trans "
Save
changes
"
%}"
class=
"btn btn-primary"
>
...
...
circle/dashboard/urls.py
View file @
e155a219
...
...
@@ -18,7 +18,8 @@
from
__future__
import
absolute_import
from
dashboard.views.autocomplete
import
AclUserGroupAutocomplete
,
AclUserAutocomplete
from
dashboard.views.template
import
TemplateList
,
TemplateChoose
,
TemplateDetail
from
dashboard.views.template
import
TemplateList
,
TemplateChoose
,
TemplateDetail
,
TemplateDelete
,
\
TransferTemplateOwnershipConfirmView
,
TransferTemplateOwnershipView
from
dashboard.views.vm
import
VmDetailView
,
VmList
,
VmCreate
,
vm_activity
,
vm_ops
,
FavouriteView
,
VmPlainImageCreate
from
django.conf.urls
import
url
...
...
@@ -52,10 +53,10 @@ urlpatterns = [
name
=
'dashboard.views.template-detail'
),
url
(
r"^template/list/$"
,
TemplateList
.
as_view
(),
name
=
"dashboard.views.template-list"
),
#
url(r"^template/delete/(?P<pk>\d+)/$", TemplateDelete.as_view(),
#
name="dashboard.views.template-delete"),
#
url(r'^template/(?P<pk>\d+)/tx/$', TransferTemplateOwnershipView.as_view(),
#
name='dashboard.views.template-transfer-ownership'),
url
(
r"^template/delete/(?P<pk>\d+)/$"
,
TemplateDelete
.
as_view
(),
name
=
"dashboard.views.template-delete"
),
url
(
r'^template/(?P<pk>\d+)/tx/$'
,
TransferTemplateOwnershipView
.
as_view
(),
name
=
'dashboard.views.template-transfer-ownership'
),
url
(
r'^vm/(?P<pk>[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})/$'
,
VmDetailView
.
as_view
(),
name
=
'dashboard.views.detail'
),
# url(r'^vm/(?P<pk>\d+)/vnctoken/$', VmDetailVncTokenView.as_view(),
...
...
@@ -88,9 +89,9 @@ urlpatterns = [
# url(r'^vm/tx/(?P<key>.*)/?$',
# TransferInstanceOwnershipConfirmView.as_view(),
# name='dashboard.views.vm-transfer-ownership-confirm'),
#
url(r'^template/tx/(?P<key>.*)/?$',
#
TransferTemplateOwnershipConfirmView.as_view(),
#
name='dashboard.views.template-transfer-ownership-confirm'),
url
(
r'^template/tx/(?P<key>.*)/?$'
,
TransferTemplateOwnershipConfirmView
.
as_view
(),
name
=
'dashboard.views.template-transfer-ownership-confirm'
),
# url(r'^node/delete/(?P<pk>\d+)/$', NodeDelete.as_view(),
# name="dashboard.views.delete-node"),
# url(r'^node/(?P<pk>\d+)/activity/$', NodeActivityView.as_view(),
...
...
circle/dashboard/views/template.py
View file @
e155a219
...
...
@@ -53,8 +53,8 @@ from .util import (
AclUpdateView
,
FilterMixin
,
# TransferOwnershipConfirmView, TransferOwnershipView,
# DeleteViewBase,
GraphMixin
)
GraphMixin
,
DeleteViewBase
,
TransferOwnershipConfirmView
,
TransferOwnershipView
)
logger
=
logging
.
getLogger
(
__name__
)
...
...
@@ -285,22 +285,21 @@ class TemplateList(LoginRequiredMixin, FilterMixin, SingleTableView):
return
qs
.
select_related
(
"lease"
,
"owner"
,
"owner__profile"
)
#
# class TemplateDelete(DeleteViewBase):
# model = InstanceTemplate
# success_message = _("Template successfully deleted.")
#
# def get_success_url(self):
# return reverse("dashboard.views.template-list")
#
# def delete_obj(self, request, *args, **kwargs):
# object = self.get_object()
# object.destroy_disks()
# object.delete()
class
TemplateDelete
(
DeleteViewBase
):
model
=
InstanceTemplate
success_message
=
_
(
"Template successfully deleted."
)
def
get_success_url
(
self
):
return
reverse
(
"dashboard.views.template-list"
)
def
delete_obj
(
self
,
request
,
*
args
,
**
kwargs
):
object
=
self
.
get_object
()
object
.
destroy_disks
()
object
.
delete
()
class
TemplateDetail
(
LoginRequiredMixin
,
GraphMixin
,
SuccessMessageMixin
,
UpdateView
):
class
TemplateDetail
(
LoginRequiredMixin
,
GraphMixin
,
SuccessMessageMixin
,
UpdateView
):
model
=
InstanceTemplate
template_name
=
"dashboard/template-edit.html"
form_class
=
TemplateForm
...
...
@@ -308,8 +307,11 @@ class TemplateDetail(LoginRequiredMixin, GraphMixin,
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
template
=
self
.
get_object
()
if
not
template
.
has_level
(
request
.
user
,
'user'
):
#TODO: multiple users
if
template
.
owner_id
!=
request
.
user
.
id
:
raise
PermissionDenied
()
if
request
.
is_ajax
():
template
=
{
'num_cores'
:
template
.
num_cores
,
...
...
@@ -334,15 +336,15 @@ class TemplateDetail(LoginRequiredMixin, GraphMixin,
return
super
(
TemplateDetail
,
self
)
.
get
(
request
,
*
args
,
**
kwargs
)
def
get_context_data
(
self
,
**
kwargs
):
obj
=
self
.
get_object
()
template
=
self
.
get_object
()
context
=
super
(
TemplateDetail
,
self
)
.
get_context_data
(
**
kwargs
)
context
[
'acl'
]
=
AclUpdateView
.
get_acl_data
(
obj
,
self
.
request
.
user
,
'dashboard.views.template-acl'
)
context
[
'disks'
]
=
obj
.
disks
.
all
()
context
[
'is_owner'
]
=
obj
.
has_level
(
self
.
request
.
user
,
'owner'
)
#
context['acl'] = AclUpdateView.get_acl_data(
# template
, self.request.user, 'dashboard.views.template-acl')
# context['disks'] = template
.disks.all()
context
[
'is_owner'
]
=
template
.
owner_id
==
self
.
request
.
user
.
id
context
[
'aclform'
]
=
AclUserOrGroupAddForm
()
context
[
'parent'
]
=
obj
.
parent
context
[
'show_graph'
]
=
obj
.
has_level
(
self
.
request
.
user
,
'operator'
)
# context['parent'] = template
.parent
# context['show_graph'] = template
.has_level(self.request.user, 'operator')
return
context
def
get_success_url
(
self
):
...
...
@@ -476,18 +478,18 @@ class LeaseDetail(LoginRequiredMixin, SuccessMessageMixin, UpdateView):
# object.delete()
#
#
#
class TransferTemplateOwnershipConfirmView(TransferOwnershipConfirmView):
#
template = "dashboard/confirm/transfer-template-ownership.html"
#
model = InstanceTemplate
#
#
#
class TransferTemplateOwnershipView(TransferOwnershipView):
#
confirm_view = TransferTemplateOwnershipConfirmView
#
model = InstanceTemplate
#
notification_msg = ugettext_noop(
#
'%(owner)s offered you to take the ownership of '
#
'his/her template called %(instance)s. '
#
'<a href="%(token)s" '
#
'class="btn btn-success btn-small">Accept</a>')
#
token_url = 'dashboard.views.template-transfer-ownership-confirm'
#
template = "dashboard/template-tx-owner.html"
class
TransferTemplateOwnershipConfirmView
(
TransferOwnershipConfirmView
):
template
=
"dashboard/confirm/transfer-template-ownership.html"
model
=
InstanceTemplate
class
TransferTemplateOwnershipView
(
TransferOwnershipView
):
confirm_view
=
TransferTemplateOwnershipConfirmView
model
=
InstanceTemplate
notification_msg
=
ugettext_noop
(
'
%(owner)
s offered you to take the ownership of '
'his/her template called
%(instance)
s. '
'<a href="
%(token)
s" '
'class="btn btn-success btn-small">Accept</a>'
)
token_url
=
'dashboard.views.template-transfer-ownership-confirm'
template
=
"dashboard/template-tx-owner.html"
circle/dashboard/views/util.py
View file @
e155a219
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