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
4c29a7bb
authored
May 31, 2018
by
Szabolcs Gelencser
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement template share with users
parent
0ec3899c
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
128 additions
and
134 deletions
+128
-134
circle/dashboard/forms.py
+36
-35
circle/dashboard/templates/dashboard/_manage_access.html
+13
-27
circle/dashboard/templates/dashboard/template-edit.html
+4
-58
circle/dashboard/urls.py
+4
-3
circle/dashboard/views/autocomplete.py
+5
-6
circle/dashboard/views/template.py
+55
-3
circle/dashboard/views/util.py
+0
-0
circle/openstack_api/keystone.py
+2
-2
circle/vm/models/instance.py
+9
-0
No files found.
circle/dashboard/forms.py
View file @
4c29a7bb
...
@@ -433,11 +433,17 @@ class TemplateForm(forms.ModelForm):
...
@@ -433,11 +433,17 @@ class TemplateForm(forms.ModelForm):
# }))
# }))
name
=
forms
.
TextInput
()
name
=
forms
.
TextInput
()
flavor
=
forms
.
ChoiceField
([
'a'
,
'b'
,
'c'
])
#
flavor = forms.ChoiceField(['a','b','c'])
def
__init__
(
self
,
*
args
,
**
kwargs
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
self
.
user
=
kwargs
.
pop
(
"user"
,
None
)
self
.
user
=
kwargs
.
pop
(
"user"
,
None
)
super
(
TemplateForm
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
super
(
TemplateForm
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
self
.
allowed_fields
=
(
'name'
,
# 'lease',
)
#
#
# self.fields['networks'].queryset = ()#Vlan.get_objects_with_level('user', self.user)
# self.fields['networks'].queryset = ()#Vlan.get_objects_with_level('user', self.user)
#
#
...
@@ -487,34 +493,34 @@ class TemplateForm(forms.ModelForm):
...
@@ -487,34 +493,34 @@ class TemplateForm(forms.ModelForm):
def
clean_max_ram_size
(
self
):
def
clean_max_ram_size
(
self
):
return
self
.
cleaned_data
.
get
(
"ram_size"
,
0
)
return
self
.
cleaned_data
.
get
(
"ram_size"
,
0
)
def
_clean_fields
(
self
):
#
def _clean_fields(self):
try
:
#
try:
old
=
InstanceTemplate
.
objects
.
get
(
pk
=
self
.
instance
.
pk
)
#
old = InstanceTemplate.objects.get(pk=self.instance.pk)
except
InstanceTemplate
.
DoesNotExist
:
#
except InstanceTemplate.DoesNotExist:
old
=
None
#
old = None
for
name
,
field
in
self
.
fields
.
items
():
#
for name, field in self.fields.items():
if
name
in
self
.
allowed_fields
:
#
if name in self.allowed_fields:
value
=
field
.
widget
.
value_from_datadict
(
#
value = field.widget.value_from_datadict(
self
.
data
,
self
.
files
,
self
.
add_prefix
(
name
))
#
self.data, self.files, self.add_prefix(name))
try
:
#
try:
value
=
field
.
clean
(
value
)
#
value = field.clean(value)
self
.
cleaned_data
[
name
]
=
value
#
self.cleaned_data[name] = value
if
hasattr
(
self
,
'clean_
%
s'
%
name
):
#
if hasattr(self, 'clean_%s' % name):
value
=
getattr
(
self
,
'clean_
%
s'
%
name
)()
#
value = getattr(self, 'clean_%s' % name)()
self
.
cleaned_data
[
name
]
=
value
#
self.cleaned_data[name] = value
except
ValidationError
as
e
:
#
except ValidationError as e:
self
.
_errors
[
name
]
=
self
.
error_class
(
e
.
messages
)
#
self._errors[name] = self.error_class(e.messages)
if
name
in
self
.
cleaned_data
:
#
if name in self.cleaned_data:
del
self
.
cleaned_data
[
name
]
#
del self.cleaned_data[name]
elif
old
:
#
elif old:
if
name
==
'networks'
:
#
if name == 'networks':
self
.
cleaned_data
[
name
]
=
[
#
self.cleaned_data[name] = [
i
.
vlan
for
i
in
self
.
instance
.
interface_set
.
all
()]
#
i.vlan for i in self.instance.interface_set.all()]
else
:
#
else:
self
.
cleaned_data
[
name
]
=
getattr
(
old
,
name
)
#
self.cleaned_data[name] = getattr(old, name)
if
"req_traits"
not
in
self
.
allowed_fields
:
#
if "req_traits" not in self.allowed_fields:
self
.
cleaned_data
[
'req_traits'
]
=
self
.
instance
.
req_traits
.
all
()
#
self.cleaned_data['req_traits'] = self.instance.req_traits.all()
def
save
(
self
,
commit
=
True
):
def
save
(
self
,
commit
=
True
):
data
=
self
.
cleaned_data
data
=
self
.
cleaned_data
...
@@ -1300,12 +1306,7 @@ class UserEditForm(forms.ModelForm):
...
@@ -1300,12 +1306,7 @@ class UserEditForm(forms.ModelForm):
class
AclUserOrGroupAddForm
(
forms
.
Form
):
class
AclUserOrGroupAddForm
(
forms
.
Form
):
name
=
forms
.
CharField
(
name
=
forms
.
CharField
(
required
=
False
)
widget
=
autocomplete
.
ListSelect2
(
url
=
'autocomplete.acl.user-group'
,
attrs
=
{
'class'
:
'form-control'
,
'data-html'
:
'true'
,
'data-placeholder'
:
_
(
"Name of group or user"
)}))
class
TransferOwnershipForm
(
forms
.
Form
):
class
TransferOwnershipForm
(
forms
.
Form
):
...
...
circle/dashboard/templates/dashboard/_manage_access.html
View file @
4c29a7bb
{% load i18n %}
{% load i18n %}
<form
action=
"{{
acl.
url }}"
method=
"post"
>
{% csrf_token %}
<form
action=
"{{
manage_access_
url }}"
method=
"post"
>
{% csrf_token %}
<table
class=
"table table-striped table-with-form-fields acl-table"
id=
"{{table_id}}"
>
<table
class=
"table table-striped table-with-form-fields acl-table"
id=
"{{table_id}}"
>
<thead>
<thead>
<tr>
<tr>
<th></th>
<th></th>
<th>
{% trans "Who" %}
</th>
<th>
{% trans "Who" %}
</th>
<th>
{% trans "What" %}
</th>
<th><i
id=
"manage-access-select-all"
class=
"fa fa-times"
></i></th>
<th><i
id=
"manage-access-select-all"
class=
"fa fa-times"
></i></th>
</tr>
</tr>
</thead>
</thead>
<tbody>
<tbody>
{% for
i in acl.
users %}
{% for
member in shared_with_
users %}
<tr>
<tr>
<td>
<td>
<img
class=
"profile-avatar"
src=
"{{ i.user.profile.get_avatar_url }}"
/>
{#
<img
class=
"profile-avatar"
src=
"{{ i.user.profile.get_avatar_url }}"
/>
#}
</td>
</td>
<td>
<td>
<a
href=
"{% url "
dashboard
.
views
.
profile
"
username=
i.user.username
%}"
{#
<a
href=
"{% url "
dashboard
.
views
.
profile
"
username=
i.user.username
%}"#}
title=
"{{ i.user.username }}"
>
{#
title=
"{{ i.user.username }}"
>
#}
{% include "dashboard/_display-name.html" with user=i.user show_org=True %}
{# {% include "dashboard/_display-name.html" with user=i.user show_org=True %}#}
</a>
{#
</a>
#}
</td>
{{ member.username }}
<td>
<select
class=
"form-control"
name=
"perm-u-{{i.user.id}}"
{%
if
i
.
level
not
in
acl
.
allowed_levels
%}
disabled
{%
endif
%}
>
{% for id, name in acl.levels %}
<option
{%
if
id =
=
i
.
level
%}
selected=
"selected"
{%
endif
%}
{%
if
id
not
in
acl
.
allowed_levels
%}
disabled
{%
endif
%}
value=
"{{id}}"
>
{{name}}
</option>
{% endfor %}
</select>
</td>
</td>
<td>
<td>
<input
type=
"checkbox"
name=
"remove-u-{{
i.user.id
}}"
title=
"{% trans "
Remove
"
%}"
/>
<input
type=
"checkbox"
name=
"remove-u-{{
member.member_id
}}"
title=
"{% trans "
Remove
"
%}"
/>
</td>
</td>
</tr>
</tr>
{% endfor %}
{% endfor %}
...
@@ -57,15 +48,10 @@
...
@@ -57,15 +48,10 @@
</td>
</td>
</tr>
</tr>
{% endfor %}
{% endfor %}
<tr><td><i
class=
"fa fa-plus"
></i></td>
<tr>
<td>
{{aclform.name }}
</td>
<td><i
class=
"fa fa-plus"
></i></td>
<td><select
class=
"form-control"
name=
"level"
>
<td>
{{aclform.name }}
</td>
{% for id, name in acl.levels %}
<td></td>
{% if id in acl.allowed_levels %}
<option
value=
"{{id}}"
>
{{name}}
</option>
{% endif %}
{% endfor %}
</select></td><td></td>
</tr>
</tr>
</tbody>
</tbody>
</table>
</table>
...
...
circle/dashboard/templates/dashboard/template-edit.html
View file @
4c29a7bb
...
@@ -42,8 +42,8 @@
...
@@ -42,8 +42,8 @@
{# {{ form.max_ram_size|as_crispy_field }}#}
{# {{ form.max_ram_size|as_crispy_field }}#}
</fieldset>
</fieldset>
<fieldset>
{#
<fieldset>
#}
<legend>
{% trans "Virtual machine settings" %}
</legend>
{#
<legend>
{% trans "Virtual machine settings" %}
</legend>
#}
{# {{ form.arch|as_crispy_field }}#}
{# {{ form.arch|as_crispy_field }}#}
{# {{ form.access_method|as_crispy_field }}#}
{# {{ form.access_method|as_crispy_field }}#}
{# {{ form.boot_menu|as_crispy_field }}#}
{# {{ form.boot_menu|as_crispy_field }}#}
...
@@ -52,11 +52,11 @@
...
@@ -52,11 +52,11 @@
{# {{ form.description|as_crispy_field }}#}
{# {{ form.description|as_crispy_field }}#}
{# {{ form.system|as_crispy_field }}#}
{# {{ form.system|as_crispy_field }}#}
{# {{ form.has_agent|as_crispy_field }}#}
{# {{ form.has_agent|as_crispy_field }}#}
</fieldset>
{#
</fieldset>
#}
<fieldset>
<fieldset>
<legend>
{% trans "External resources" %}
</legend>
<legend>
{% trans "External resources" %}
</legend>
{# {{ form.networks|as_crispy_field }}#}
{# {{ form.networks|as_crispy_field }}#}
{# {{ form.lease|as_crispy_field }}#
}
{{ form.lease|as_crispy_field }
}
{##}
{##}
{# {{ form.tags|as_crispy_field }}#}
{# {{ form.tags|as_crispy_field }}#}
</fieldset>
</fieldset>
...
@@ -82,26 +82,6 @@
...
@@ -82,26 +82,6 @@
<div
class=
"panel panel-default"
>
<div
class=
"panel panel-default"
>
<div
class=
"panel-heading"
>
<div
class=
"panel-heading"
>
<h4
class=
"no-margin"
><i
class=
"fa fa-user"
></i>
{% trans "Owner" %}
</h4>
</div>
<div
class=
"panel-body"
>
{% if user == object.owner %}
{% blocktrans %}You are the current owner of this template.{% endblocktrans %}
{% else %}
{% url "dashboard.views.profile" username=object.owner.username as url %}
{% blocktrans with owner=object.owner name=object.owner.get_full_name%}
The current owner of this template is
<a
href=
"{{url}}"
>
{{name}} ({{owner}})
</a>
.
{% endblocktrans %}
{% endif %}
{% if user == object.owner or user.is_superuser %}
<a
href=
"{% url "
dashboard
.
views
.
template-transfer-ownership
"
object
.
pk
%}"
class=
"btn btn-link tx-tpl-ownership"
>
{% trans "Transfer ownership..." %}
</a>
{% endif %}
</div>
</div>
<div
class=
"panel panel-default"
>
<div
class=
"panel-heading"
>
<h4
class=
"no-margin"
><i
class=
"fa fa-group"
></i>
{% trans "Manage access" %}
</h4>
<h4
class=
"no-margin"
><i
class=
"fa fa-group"
></i>
{% trans "Manage access" %}
</h4>
</div>
</div>
<div
class=
"panel-body"
>
<div
class=
"panel-body"
>
...
@@ -111,40 +91,6 @@
...
@@ -111,40 +91,6 @@
<div
class=
"panel panel-default"
>
<div
class=
"panel panel-default"
>
<div
class=
"panel-heading"
>
<div
class=
"panel-heading"
>
<h4
class=
"no-margin"
>
<i
class=
"fa fa-question-circle"
></i>
{% trans "Access level rights" %}
</h4>
</div>
<div
class=
"panel-body"
>
<dl>
<dt>
{% trans "User" %}
</dt>
<dd>
{% blocktrans %}
User can deploy instances from this template.
{% endblocktrans %}
</dd>
<dt>
{% trans "Operator" %}
</dt>
<dd>
{% blocktrans %}
Operators are able to deploy and grant/revoke User level access to this template.
{% endblocktrans %}
</dd>
<dt>
{% trans "Owner" %}
</dt>
<dd>
{% blocktrans %}
Owners can edit attributes or delete the template.
Owners are able to grant/revoke User, Operator and Owner level access to the template.
The accountable owner (the one who created the template) can not be demoted.
The accountable ownership can be transferred to other User via the "Transfer onwership" button.
{% endblocktrans %}
</dd>
</dl>
</div>
</div>
<div
class=
"panel panel-default"
>
<div
class=
"panel-heading"
>
<h4
class=
"no-margin"
><i
class=
"fa fa-file"
></i>
{% trans "Disk list" %}
</h4>
<h4
class=
"no-margin"
><i
class=
"fa fa-file"
></i>
{% trans "Disk list" %}
</h4>
</div>
</div>
<div
class=
"panel-body"
>
<div
class=
"panel-body"
>
...
...
circle/dashboard/urls.py
View file @
4c29a7bb
...
@@ -19,7 +19,8 @@ from __future__ import absolute_import
...
@@ -19,7 +19,8 @@ from __future__ import absolute_import
from
dashboard.views.autocomplete
import
AclUserGroupAutocomplete
,
AclUserAutocomplete
from
dashboard.views.autocomplete
import
AclUserGroupAutocomplete
,
AclUserAutocomplete
from
dashboard.views.template
import
TemplateList
,
TemplateChoose
,
TemplateDetail
,
TemplateDelete
,
\
from
dashboard.views.template
import
TemplateList
,
TemplateChoose
,
TemplateDetail
,
TemplateDelete
,
\
TransferTemplateOwnershipConfirmView
,
TransferTemplateOwnershipView
,
LeaseCreate
,
LeaseDetail
,
LeaseDelete
TransferTemplateOwnershipConfirmView
,
TransferTemplateOwnershipView
,
LeaseCreate
,
LeaseDetail
,
LeaseDelete
,
\
TemplateAclUpdateView
from
dashboard.views.vm
import
VmDetailView
,
VmList
,
VmCreate
,
vm_activity
,
vm_ops
,
FavouriteView
,
VmPlainImageCreate
from
dashboard.views.vm
import
VmDetailView
,
VmList
,
VmCreate
,
vm_activity
,
vm_ops
,
FavouriteView
,
VmPlainImageCreate
from
django.conf.urls
import
url
from
django.conf.urls
import
url
...
@@ -47,8 +48,8 @@ urlpatterns = [
...
@@ -47,8 +48,8 @@ urlpatterns = [
# name="dashboard.views.template-create"),
# name="dashboard.views.template-create"),
url
(
r'^template/choose/$'
,
TemplateChoose
.
as_view
(),
url
(
r'^template/choose/$'
,
TemplateChoose
.
as_view
(),
name
=
"dashboard.views.template-choose"
),
name
=
"dashboard.views.template-choose"
),
#
url(r'template/(?P<pk>\d+)/acl/$', TemplateAclUpdateView.as_view(),
url
(
r'template/(?P<pk>\d+)/acl/$'
,
TemplateAclUpdateView
.
as_view
(),
#
name='dashboard.views.template-acl'),
name
=
'dashboard.views.template-acl'
),
url
(
r'^template/(?P<pk>\d+)/$'
,
TemplateDetail
.
as_view
(),
url
(
r'^template/(?P<pk>\d+)/$'
,
TemplateDetail
.
as_view
(),
name
=
'dashboard.views.template-detail'
),
name
=
'dashboard.views.template-detail'
),
url
(
r"^template/list/$"
,
TemplateList
.
as_view
(),
url
(
r"^template/list/$"
,
TemplateList
.
as_view
(),
...
...
circle/dashboard/views/autocomplete.py
View file @
4c29a7bb
...
@@ -89,10 +89,9 @@ class AclUserAutocomplete(autocomplete.Select2ListView):
...
@@ -89,10 +89,9 @@ class AclUserAutocomplete(autocomplete.Select2ListView):
}),
content_type
=
"application/json"
)
}),
content_type
=
"application/json"
)
class
AclUserGroupAutocomplete
(
AclUserAutocomplete
):
class
AclUserGroupAutocomplete
(
autocomplete
.
Select2ListView
):
# TODO: was AclUserAutocomplete inherited
group_search_fields
=
(
'name'
,
'groupprofile__org_id'
)
def
get_list
(
self
):
def
get_list
(
self
):
groups
=
AclUpdateView
.
get_allowed_groups
(
self
.
request
.
user
)
from
openstack_api
import
keystone
groups
=
self
.
filter
(
groups
,
self
.
group_search_fields
)
groups
=
keystone
.
group_list
(
request
=
self
.
request
,
user
=
self
.
request
.
user
)
return
super
(
AclUserGroupAutocomplete
,
self
)
.
get_list
()
+
groups
group_names
=
[
g
.
name
for
g
in
groups
]
return
super
(
AclUserGroupAutocomplete
,
self
)
.
get_list
()
+
group_names
circle/dashboard/views/template.py
View file @
4c29a7bb
...
@@ -41,6 +41,9 @@ from braces.views import (
...
@@ -41,6 +41,9 @@ from braces.views import (
)
)
from
django.views.generic.edit
import
BaseUpdateView
,
ModelFormMixin
,
FormView
from
django.views.generic.edit
import
BaseUpdateView
,
ModelFormMixin
,
FormView
from
django_tables2
import
SingleTableView
from
django_tables2
import
SingleTableView
from
keystoneauth1
import
session
from
keystoneauth1.identity
import
v3
from
openstack_auth.utils
import
fix_auth_url_version
from
vm.models
import
(
from
vm.models
import
(
InstanceTemplate
,
InterfaceTemplate
,
Instance
,
Lease
,
InstanceActivity
InstanceTemplate
,
InterfaceTemplate
,
Instance
,
Lease
,
InstanceActivity
...
@@ -289,6 +292,8 @@ class TemplateDelete(DeleteViewBase):
...
@@ -289,6 +292,8 @@ class TemplateDelete(DeleteViewBase):
object
.
delete
()
object
.
delete
()
class
TemplateDetail
(
LoginRequiredMixin
,
GraphMixin
,
SuccessMessageMixin
,
UpdateView
):
class
TemplateDetail
(
LoginRequiredMixin
,
GraphMixin
,
SuccessMessageMixin
,
UpdateView
):
model
=
InstanceTemplate
model
=
InstanceTemplate
template_name
=
"dashboard/template-edit.html"
template_name
=
"dashboard/template-edit.html"
...
@@ -325,11 +330,57 @@ class TemplateDetail(LoginRequiredMixin, GraphMixin, SuccessMessageMixin, Update
...
@@ -325,11 +330,57 @@ class TemplateDetail(LoginRequiredMixin, GraphMixin, SuccessMessageMixin, Update
else
:
else
:
return
super
(
TemplateDetail
,
self
)
.
get
(
request
,
*
args
,
**
kwargs
)
return
super
(
TemplateDetail
,
self
)
.
get
(
request
,
*
args
,
**
kwargs
)
def
__get_glance_admin_client
(
self
,
request
):
from
keystoneauth1
import
session
from
glanceclient
import
Client
auth
=
v3
.
Password
(
auth_url
=
fix_auth_url_version
(
settings
.
OPENSTACK_KEYSTONE_URL
),
user_id
=
settings
.
OPENSTACK_CIRCLE_USERID
,
password
=
settings
.
OPENSTACK_CIRCLE_PASSWORD
,
project_id
=
request
.
user
.
tenant_id
,
)
session
=
session
.
Session
(
auth
=
auth
,
verify
=
False
)
return
Client
(
'2'
,
session
=
session
)
def
__get_members_shared_with
(
self
):
template
=
self
.
get_object
()
glance
=
self
.
__get_glance_admin_client
(
self
.
request
)
members_generator
=
glance
.
image_members
.
list
(
template
.
image_id
)
return
[
m
for
m
in
members_generator
]
def
__get_project_client
(
self
,
project_id
):
from
keystoneclient.v3
import
client
auth
=
v3
.
Password
(
auth_url
=
fix_auth_url_version
(
settings
.
OPENSTACK_KEYSTONE_URL
),
user_id
=
settings
.
OPENSTACK_CIRCLE_USERID
,
password
=
settings
.
OPENSTACK_CIRCLE_PASSWORD
,
project_id
=
project_id
,
)
sess
=
session
.
Session
(
auth
=
auth
,
verify
=
False
)
return
client
.
Client
(
session
=
sess
,
interface
=
'public'
)
def
__get_username_for
(
self
,
project_id
):
client
=
self
.
__get_project_client
(
project_id
)
project
=
client
.
projects
.
get
(
project_id
)
return
project
.
name
# as username = project's name
def
__get_users_shared_with
(
self
):
members
=
self
.
__get_members_shared_with
()
for
m
in
members
:
m
[
'username'
]
=
self
.
__get_username_for
(
m
.
member_id
)
return
members
def
get_context_data
(
self
,
**
kwargs
):
def
get_context_data
(
self
,
**
kwargs
):
template
=
self
.
get_object
()
template
=
self
.
get_object
()
context
=
super
(
TemplateDetail
,
self
)
.
get_context_data
(
**
kwargs
)
context
=
super
(
TemplateDetail
,
self
)
.
get_context_data
(
**
kwargs
)
# context['acl'] = AclUpdateView.get_acl_data(
# context['acl'] = AclUpdateView.get_acl_data(
# template, self.request.user, 'dashboard.views.template-acl')
# template, self.request.user, 'dashboard.views.template-acl')
context
[
'manage_access_url'
]
=
reverse_lazy
(
'dashboard.views.template-acl'
,
kwargs
=
{
'pk'
:
template
.
id
})
context
[
'shared_with_users'
]
=
self
.
__get_users_shared_with
()
# context['disks'] = template.disks.all()
# context['disks'] = template.disks.all()
context
[
'is_owner'
]
=
template
.
owner_id
==
self
.
request
.
user
.
id
context
[
'is_owner'
]
=
template
.
owner_id
==
self
.
request
.
user
.
id
context
[
'aclform'
]
=
AclUserOrGroupAddForm
()
context
[
'aclform'
]
=
AclUserOrGroupAddForm
()
...
@@ -341,13 +392,14 @@ class TemplateDetail(LoginRequiredMixin, GraphMixin, SuccessMessageMixin, Update
...
@@ -341,13 +392,14 @@ class TemplateDetail(LoginRequiredMixin, GraphMixin, SuccessMessageMixin, Update
return
reverse_lazy
(
"dashboard.views.template-detail"
,
return
reverse_lazy
(
"dashboard.views.template-detail"
,
kwargs
=
self
.
kwargs
)
kwargs
=
self
.
kwargs
)
def
post
(
self
,
request
,
*
args
,
**
kwargs
):
def
post
(
self
,
request
):
template
=
self
.
get_object
()
template
=
self
.
get_object
()
if
not
template
.
has_level
(
request
.
user
,
'owner'
):
# TODO: multiple users
if
template
.
owner_id
!=
request
.
user
.
id
:
raise
PermissionDenied
()
raise
PermissionDenied
()
return
super
(
TemplateDetail
,
self
)
.
post
(
self
,
request
,
args
,
kwargs
)
return
super
(
TemplateDetail
,
self
)
.
post
(
self
,
request
,
args
,
kwargs
)
def
get_form_kwargs
(
self
):
def
get_form_kwargs
(
self
,
*
args
,
**
kwargs
):
kwargs
=
super
(
TemplateDetail
,
self
)
.
get_form_kwargs
()
kwargs
=
super
(
TemplateDetail
,
self
)
.
get_form_kwargs
()
kwargs
[
'user'
]
=
self
.
request
.
user
kwargs
[
'user'
]
=
self
.
request
.
user
return
kwargs
return
kwargs
...
...
circle/dashboard/views/util.py
View file @
4c29a7bb
This diff is collapsed.
Click to expand it.
circle/openstack_api/keystone.py
View file @
4c29a7bb
...
@@ -593,7 +593,7 @@ def group_delete(request, group_id):
...
@@ -593,7 +593,7 @@ def group_delete(request, group_id):
def
group_list
(
request
,
domain
=
None
,
project
=
None
,
user
=
None
,
filters
=
None
):
def
group_list
(
request
,
domain
=
None
,
project
=
None
,
user
=
None
,
filters
=
None
):
manager
=
keystoneclient
(
request
,
admin
=
True
)
.
groups
manager
=
keystoneclient
(
request
)
.
groups
# TODO: was admin API
groups
=
[]
groups
=
[]
kwargs
=
{
kwargs
=
{
"domain"
:
domain
,
"domain"
:
domain
,
...
@@ -834,7 +834,7 @@ def remove_tenant_user(request, project=None, user=None, domain=None):
...
@@ -834,7 +834,7 @@ def remove_tenant_user(request, project=None, user=None, domain=None):
def
roles_for_group
(
request
,
group
,
domain
=
None
,
project
=
None
):
def
roles_for_group
(
request
,
group
,
domain
=
None
,
project
=
None
):
manager
=
keystoneclient
(
request
,
admin
=
True
)
.
roles
manager
=
keystoneclient
(
request
)
.
roles
return
manager
.
list
(
group
=
group
,
domain
=
domain
,
project
=
project
)
return
manager
.
list
(
group
=
group
,
domain
=
domain
,
project
=
project
)
...
...
circle/vm/models/instance.py
View file @
4c29a7bb
...
@@ -119,6 +119,15 @@ class VirtualMachineDescModel(BaseResourceConfigModel):
...
@@ -119,6 +119,15 @@ class VirtualMachineDescModel(BaseResourceConfigModel):
abstract
=
True
abstract
=
True
class
TemplateMemberGroup
(
Model
):
group_id
=
CharField
(
blank
=
False
,
max_length
=
100
,
unique
=
True
)
class
Meta
:
app_label
=
'vm'
db_table
=
'vm_template_member_group'
class
InstanceTemplate
(
TimeStampedModel
):
class
InstanceTemplate
(
TimeStampedModel
):
"""Virtual machine template.
"""Virtual machine template.
"""
"""
...
...
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