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
1e44ca63
authored
May 31, 2018
by
Szabolcs Gelencser
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add initial group assignment
parent
cc8d0f7e
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
123 additions
and
49 deletions
+123
-49
circle/dashboard/views/util.py
+53
-45
circle/openstack_api/keystone.py
+1
-1
circle/vm/migrations/0017_auto_20180531_1455.py
+45
-0
circle/vm/models/instance.py
+24
-3
No files found.
circle/dashboard/views/util.py
View file @
1e44ca63
...
@@ -44,6 +44,7 @@ from django.views.decorators.debug import sensitive_post_parameters
...
@@ -44,6 +44,7 @@ from django.views.decorators.debug import sensitive_post_parameters
from
django.views.generic
import
DetailView
,
View
,
DeleteView
,
FormView
from
django.views.generic
import
DetailView
,
View
,
DeleteView
,
FormView
from
django.views.generic.detail
import
SingleObjectMixin
from
django.views.generic.detail
import
SingleObjectMixin
from
keystoneauth1.identity
import
v3
from
keystoneauth1.identity
import
v3
from
vm.models.instance
import
TemplateGroupMember
from
openstack_auth.utils
import
fix_auth_url_version
from
openstack_auth.utils
import
fix_auth_url_version
from
vm.models
import
Instance
from
vm.models
import
Instance
...
@@ -413,27 +414,9 @@ class RequestFormOperationMixin(FormOperationMixin):
...
@@ -413,27 +414,9 @@ class RequestFormOperationMixin(FormOperationMixin):
class
AclUpdateView
(
LoginRequiredMixin
,
View
,
SingleObjectMixin
):
class
AclUpdateView
(
LoginRequiredMixin
,
View
,
SingleObjectMixin
):
# def send_success_message(self, whom, old_level, new_level):
def
__get_current_users_groups
(
self
):
# if old_level and new_level:
# msg = _("Acl user/group %(w)s successfully modified.")
# elif not old_level and new_level:
# msg = _("Acl user/group %(w)s successfully added.")
# elif old_level and not new_level:
# msg = _("Acl user/group %(w)s successfully removed.")
# if msg:
# messages.success(self.request, msg % {'w': whom})
#
# def add_levels(self):
# self.request, _('User "%s" has already '
# 'access to this object.') % name)
# self.request, _('Group "%s" has already '
# 'access to this object.') % name)
# self.request, _('User or group "%s" not found.') % name)
def
__get_current_users_groups
(
self
,
request
):
from
openstack_api
import
keystone
from
openstack_api
import
keystone
groups
=
keystone
.
group_list
(
request
=
self
.
request
,
user
=
self
.
request
.
user
)
return
keystone
.
group_list
(
request
=
self
.
request
,
user
=
self
.
request
.
user
)
return
[
g
.
name
for
g
in
groups
]
def
__get_glance_admin_client
(
self
,
project_id
):
def
__get_glance_admin_client
(
self
,
project_id
):
from
keystoneauth1
import
session
from
keystoneauth1
import
session
...
@@ -449,7 +432,7 @@ class AclUpdateView(LoginRequiredMixin, View, SingleObjectMixin):
...
@@ -449,7 +432,7 @@ class AclUpdateView(LoginRequiredMixin, View, SingleObjectMixin):
return
Client
(
'2'
,
session
=
session
)
return
Client
(
'2'
,
session
=
session
)
def
__get_
all_projects
(
self
):
def
__get_
keystone_admin_client
(
self
):
from
keystoneauth1
import
session
from
keystoneauth1
import
session
from
keystoneclient.v3
import
client
from
keystoneclient.v3
import
client
...
@@ -459,9 +442,10 @@ class AclUpdateView(LoginRequiredMixin, View, SingleObjectMixin):
...
@@ -459,9 +442,10 @@ class AclUpdateView(LoginRequiredMixin, View, SingleObjectMixin):
password
=
settings
.
OPENSTACK_CIRCLE_PASSWORD
,
password
=
settings
.
OPENSTACK_CIRCLE_PASSWORD
,
)
)
sess
=
session
.
Session
(
auth
=
auth
,
verify
=
False
)
sess
=
session
.
Session
(
auth
=
auth
,
verify
=
False
)
keystone
=
client
.
Client
(
session
=
sess
,
interface
=
settings
.
OPENSTACK_INTERFACE
)
return
client
.
Client
(
session
=
sess
,
interface
=
settings
.
OPENSTACK_INTERFACE
)
return
keystone
.
projects
.
list
(
def
__get_all_projects
(
self
):
return
self
.
__get_keystone_admin_client
()
.
projects
.
list
(
domain
=
settings
.
OPENSTACK_CIRCLE_DOMAIN_ID
,
domain
=
settings
.
OPENSTACK_CIRCLE_DOMAIN_ID
,
user
=
settings
.
OPENSTACK_CIRCLE_USERID
user
=
settings
.
OPENSTACK_CIRCLE_USERID
)
)
...
@@ -478,13 +462,35 @@ class AclUpdateView(LoginRequiredMixin, View, SingleObjectMixin):
...
@@ -478,13 +462,35 @@ class AclUpdateView(LoginRequiredMixin, View, SingleObjectMixin):
glance
=
self
.
__get_glance_admin_client
(
project_id_of_user
)
glance
=
self
.
__get_glance_admin_client
(
project_id_of_user
)
glance
.
image_members
.
update
(
template
.
image_id
,
project_id_of_user
,
'accepted'
)
glance
.
image_members
.
update
(
template
.
image_id
,
project_id_of_user
,
'accepted'
)
def
__handle_group_assignment
(
self
,
request
):
def
__list_users_of_group
(
self
,
group_id
):
keystone
=
self
.
__get_keystone_admin_client
()
return
keystone
.
users
.
list
(
group
=
group_id
)
def
__get_group_by_name
(
self
,
name
):
groups
=
self
.
__get_current_users_groups
()
for
g
in
groups
:
if
g
.
name
==
name
:
return
g
return
None
def
__handle_group_assignment
(
self
):
new_group_name
=
self
.
request
.
POST
[
'name'
]
template
=
self
.
get_object
()
template
=
self
.
get_object
()
new_group
=
self
.
__get_group_by_name
(
new_group_name
)
old_groups
=
TemplateGroupMember
.
objects
.
filter
(
instancetemplate__image_id
=
template
.
image_id
)
if
new_group
.
id
in
old_groups
:
msg
=
_
(
"Already shared with group
%
s"
%
new_group_name
)
messages
.
warning
(
self
.
request
,
msg
)
else
:
template
.
groups
.
get_or_create
(
group_id
=
new_group
.
id
)
template
.
save
()
def
__handle_user_assignment
(
self
,
request
):
def
__handle_user_assignment
(
self
):
glance
=
self
.
__get_glance_admin_client
(
request
.
user
.
tenant_id
)
glance
=
self
.
__get_glance_admin_client
(
self
.
request
.
user
.
tenant_id
)
template
=
self
.
get_object
()
template
=
self
.
get_object
()
new_template_user
=
request
.
POST
[
'name'
]
new_template_user
=
self
.
request
.
POST
[
'name'
]
project_id_of_user
=
self
.
__get_project_id_by_name
(
new_template_user
)
project_id_of_user
=
self
.
__get_project_id_by_name
(
new_template_user
)
old_members_generator
=
glance
.
image_members
.
list
(
template
.
image_id
)
old_members_generator
=
glance
.
image_members
.
list
(
template
.
image_id
)
...
@@ -494,31 +500,33 @@ class AclUpdateView(LoginRequiredMixin, View, SingleObjectMixin):
...
@@ -494,31 +500,33 @@ class AclUpdateView(LoginRequiredMixin, View, SingleObjectMixin):
msg
=
_
(
"Template is already shared with
%
s"
%
new_template_user
)
msg
=
_
(
"Template is already shared with
%
s"
%
new_template_user
)
messages
.
warning
(
self
.
request
,
msg
)
messages
.
warning
(
self
.
request
,
msg
)
elif
project_id_of_user
is
not
None
:
elif
project_id_of_user
is
not
None
:
membership
=
glance
.
image_members
.
create
(
template
.
image_id
,
project_id_of_user
)
glance
.
image_members
.
create
(
template
.
image_id
,
project_id_of_user
)
self
.
__accept_membership
(
project_id_of_user
)
self
.
__accept_membership
(
project_id_of_user
)
msg
=
_
(
"Successfully shared with
%
s"
%
new_template_user
)
msg
=
_
(
"Successfully shared with
%
s"
%
new_template_user
)
messages
.
success
(
self
.
request
,
msg
)
messages
.
success
(
self
.
request
,
msg
)
else
:
else
:
msg
=
_
(
"User or group with name '
%
s' doesn't exist"
%
new_template_user
)
msg
=
_
(
"User or group with name '
%
s' doesn't exist "
"or you are not authorized to share with it"
%
new_template_user
)
messages
.
error
(
self
.
request
,
msg
)
messages
.
error
(
self
.
request
,
msg
)
def
__handle_assignments
(
self
,
request
):
def
__handle_assignments
(
self
):
current_users_groups
=
self
.
__get_current_users_groups
(
request
)
current_users_groups
=
self
.
__get_current_users_groups
()
new_template_user
=
request
.
POST
[
'name'
]
current_group_names
=
[
g
.
name
for
g
in
current_users_groups
]
new_template_user
=
self
.
request
.
POST
[
'name'
]
if
new_template_user
is
not
None
and
len
(
new_template_user
)
>
0
:
if
new_template_user
is
not
None
and
len
(
new_template_user
)
>
0
:
if
new_template_user
in
current_
users_group
s
:
if
new_template_user
in
current_
group_name
s
:
self
.
__handle_group_assignment
(
request
)
self
.
__handle_group_assignment
()
else
:
else
:
self
.
__handle_user_assignment
(
request
)
self
.
__handle_user_assignment
()
def
__get_removes
(
self
,
request
):
def
__get_removes
(
self
):
removes
=
{
removes
=
{
"u"
:
[],
"u"
:
[],
"g"
:
[],
"g"
:
[],
}
}
for
key
,
value
in
request
.
POST
.
items
():
for
key
,
value
in
self
.
request
.
POST
.
items
():
m
=
re
.
match
(
'remove-([ug])-(.+)'
,
key
)
m
=
re
.
match
(
'remove-([ug])-(.+)'
,
key
)
if
m
:
if
m
:
t
,
name
=
m
.
groups
()
t
,
name
=
m
.
groups
()
...
@@ -526,23 +534,23 @@ class AclUpdateView(LoginRequiredMixin, View, SingleObjectMixin):
...
@@ -526,23 +534,23 @@ class AclUpdateView(LoginRequiredMixin, View, SingleObjectMixin):
return
removes
return
removes
def
__remove_user
(
self
,
request
,
member_id
):
def
__remove_user
(
self
,
member_id
):
template
=
self
.
get_object
()
template
=
self
.
get_object
()
glance
=
self
.
__get_glance_admin_client
(
request
.
user
.
tenant_id
)
glance
=
self
.
__get_glance_admin_client
(
self
.
request
.
user
.
tenant_id
)
glance
.
image_members
.
delete
(
template
.
image_id
,
member_id
)
glance
.
image_members
.
delete
(
template
.
image_id
,
member_id
)
def
__handle_removes
(
self
,
request
):
def
__handle_removes
(
self
):
removes
=
self
.
__get_removes
(
request
)
removes
=
self
.
__get_removes
()
for
member_id
in
removes
[
'u'
]:
for
member_id
in
removes
[
'u'
]:
self
.
__remove_user
(
request
,
member_id
)
self
.
__remove_user
(
member_id
)
messages
.
success
(
request
,
_
(
"Successfully removed user"
))
messages
.
success
(
self
.
request
,
_
(
"Successfully removed user"
))
def
post
(
self
,
request
,
*
args
,
**
kwargs
):
def
post
(
self
,
request
,
*
args
,
**
kwargs
):
template
=
self
.
get_object
()
template
=
self
.
get_object
()
openstack_api
.
glance
.
image_update
(
request
,
template
.
image_id
,
visibility
=
"shared"
)
openstack_api
.
glance
.
image_update
(
request
,
template
.
image_id
,
visibility
=
"shared"
)
self
.
__handle_assignments
(
request
)
self
.
__handle_assignments
()
self
.
__handle_removes
(
request
)
self
.
__handle_removes
()
return
redirect
(
"
%
s#access"
%
template
.
get_absolute_url
())
return
redirect
(
"
%
s#access"
%
template
.
get_absolute_url
())
...
...
circle/openstack_api/keystone.py
View file @
1e44ca63
...
@@ -427,7 +427,7 @@ def user_list(request, project=None, domain=None, group=None, filters=None):
...
@@ -427,7 +427,7 @@ def user_list(request, project=None, domain=None, group=None, filters=None):
except
keystone_exceptions
.
NotFound
:
except
keystone_exceptions
.
NotFound
:
raise
exceptions
.
NotFound
()
raise
exceptions
.
NotFound
()
else
:
else
:
users
=
keystoneclient
(
request
,
admin
=
True
)
.
users
.
list
(
**
kwargs
)
users
=
keystoneclient
(
request
)
.
users
.
list
(
**
kwargs
)
# TODO: was admin API
return
[
VERSIONS
.
upgrade_v2_user
(
user
)
for
user
in
users
]
return
[
VERSIONS
.
upgrade_v2_user
(
user
)
for
user
in
users
]
...
...
circle/vm/migrations/0017_auto_20180531_1455.py
0 → 100644
View file @
1e44ca63
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2018-05-31 12:55
from
__future__
import
unicode_literals
from
django.db
import
migrations
,
models
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'vm'
,
'0016_auto_20180522_1515'
),
]
operations
=
[
migrations
.
CreateModel
(
name
=
'TemplateGroupMember'
,
fields
=
[
(
'id'
,
models
.
AutoField
(
auto_created
=
True
,
primary_key
=
True
,
serialize
=
False
,
verbose_name
=
'ID'
)),
(
'group_id'
,
models
.
CharField
(
max_length
=
100
,
unique
=
True
)),
],
options
=
{
'db_table'
:
'vm_template_group_member'
,
},
),
migrations
.
CreateModel
(
name
=
'TemplateUserMember'
,
fields
=
[
(
'id'
,
models
.
AutoField
(
auto_created
=
True
,
primary_key
=
True
,
serialize
=
False
,
verbose_name
=
'ID'
)),
(
'user_id'
,
models
.
CharField
(
max_length
=
100
,
unique
=
True
)),
],
options
=
{
'db_table'
:
'vm_template_user_member'
,
},
),
migrations
.
AddField
(
model_name
=
'instancetemplate'
,
name
=
'groups'
,
field
=
models
.
ManyToManyField
(
blank
=
True
,
help_text
=
'Shared with groups'
,
to
=
'vm.TemplateGroupMember'
,
verbose_name
=
'groups'
),
),
migrations
.
AddField
(
model_name
=
'instancetemplate'
,
name
=
'users'
,
field
=
models
.
ManyToManyField
(
blank
=
True
,
help_text
=
'Shared with users'
,
to
=
'vm.TemplateUserMember'
,
verbose_name
=
'users'
),
),
]
circle/vm/models/instance.py
View file @
1e44ca63
...
@@ -119,13 +119,20 @@ class VirtualMachineDescModel(BaseResourceConfigModel):
...
@@ -119,13 +119,20 @@ class VirtualMachineDescModel(BaseResourceConfigModel):
abstract
=
True
abstract
=
True
class
Template
MemberGroup
(
Model
):
class
Template
UserMember
(
Model
):
group
_id
=
CharField
(
blank
=
False
,
max_length
=
100
,
unique
=
True
)
user
_id
=
CharField
(
blank
=
False
,
max_length
=
100
,
unique
=
True
)
class
Meta
:
class
Meta
:
app_label
=
'vm'
app_label
=
'vm'
db_table
=
'vm_template_member_group'
db_table
=
'vm_template_user_member'
class
TemplateGroupMember
(
Model
):
group_id
=
CharField
(
blank
=
False
,
max_length
=
100
,
unique
=
True
)
class
Meta
:
app_label
=
'vm'
db_table
=
'vm_template_group_member'
class
InstanceTemplate
(
TimeStampedModel
):
class
InstanceTemplate
(
TimeStampedModel
):
...
@@ -147,6 +154,20 @@ class InstanceTemplate(TimeStampedModel):
...
@@ -147,6 +154,20 @@ class InstanceTemplate(TimeStampedModel):
flavor_id
=
CharField
(
blank
=
False
,
max_length
=
100
)
flavor_id
=
CharField
(
blank
=
False
,
max_length
=
100
)
owner_id
=
CharField
(
blank
=
False
,
max_length
=
100
)
owner_id
=
CharField
(
blank
=
False
,
max_length
=
100
)
users
=
ManyToManyField
(
TemplateUserMember
,
blank
=
True
,
help_text
=
_
(
"Shared with users"
),
verbose_name
=
_
(
'users'
),
)
groups
=
ManyToManyField
(
TemplateGroupMember
,
blank
=
True
,
help_text
=
_
(
"Shared with groups"
),
verbose_name
=
_
(
'groups'
),
)
class
Meta
:
class
Meta
:
app_label
=
'vm'
app_label
=
'vm'
db_table
=
'vm_instancetemplate'
db_table
=
'vm_instancetemplate'
...
...
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