Add security service DB model and API.
Add support for managing security services information. User will be able to create description for services such as ldap, kerberos and active directory. Security service record will contain type of service (kerberos, ldap or ad), ip address of dns server, security service server hostname or ip, domain, sid (security identifier) and other auxiliary data. Partially implements bp: join-tenant-network Change-Id: I50e1f96496a40840aad97b77024a11302a1dd997
This commit is contained in:
parent
32b69b5ba4
commit
55f42ea27c
22
manila/common/constants.py
Normal file
22
manila/common/constants.py
Normal file
@ -0,0 +1,22 @@
|
||||
# Copyright 2013 Openstack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
STATUS_NEW = 'NEW'
|
||||
STATUS_CREATING = 'CREATING'
|
||||
STATUS_DELETING = 'DELETING'
|
||||
STATUS_DELETED = 'DELETED'
|
||||
STATUS_ERROR = 'ERROR'
|
||||
STATUS_ACTIVE = 'ACTIVE'
|
||||
STATUS_INACTIVE = 'INACTIVE'
|
@ -429,6 +429,37 @@ def share_snapshot_data_get_for_project(context, project_id, session=None):
|
||||
session=None)
|
||||
|
||||
|
||||
###################
|
||||
def security_service_create(context, values):
|
||||
""" Create security service DB record."""
|
||||
return IMPL.security_service_create(context, values)
|
||||
|
||||
|
||||
def security_service_delete(context, id):
|
||||
""" Delete security service DB record."""
|
||||
return IMPL.security_service_delete(context, id)
|
||||
|
||||
|
||||
def security_service_update(context, id, values):
|
||||
""" Update security service DB record."""
|
||||
return IMPL.security_service_update(context, id, values)
|
||||
|
||||
|
||||
def security_service_get(context, id):
|
||||
""" Get security service DB record."""
|
||||
return IMPL.security_service_get(context, id)
|
||||
|
||||
|
||||
def security_service_get_all(context):
|
||||
""" Get all security service DB records."""
|
||||
return IMPL.security_service_get_all(context)
|
||||
|
||||
|
||||
def security_service_get_all_by_project(context, project_id):
|
||||
""" Get all security service DB records for the given project."""
|
||||
return IMPL.security_service_get_all_by_project(context, project_id)
|
||||
|
||||
|
||||
####################
|
||||
|
||||
|
||||
|
@ -39,6 +39,7 @@ from manila.db.sqlalchemy.session import get_session
|
||||
from manila import exception
|
||||
from manila.openstack.common import log as logging
|
||||
from manila.openstack.common import timeutils
|
||||
from manila.openstack.common import uuidutils
|
||||
|
||||
|
||||
CONF = cfg.CONF
|
||||
@ -252,6 +253,7 @@ QUOTA_SYNC_FUNCTIONS = {
|
||||
'_sync_gigabytes': _sync_gigabytes,
|
||||
}
|
||||
|
||||
|
||||
###################
|
||||
|
||||
|
||||
@ -1414,3 +1416,67 @@ def _share_metadata_get_item(context, share_id, key, session=None):
|
||||
raise exception.ShareMetadataNotFound(metadata_key=key,
|
||||
share_id=share_id)
|
||||
return result
|
||||
|
||||
|
||||
@require_context
|
||||
def security_service_create(context, values):
|
||||
if not values.get('id'):
|
||||
values['id'] = uuidutils.generate_uuid()
|
||||
|
||||
security_service_ref = models.SecurityService()
|
||||
security_service_ref.update(values)
|
||||
session = get_session()
|
||||
|
||||
with session.begin():
|
||||
security_service_ref.save(session=session)
|
||||
|
||||
return security_service_ref
|
||||
|
||||
|
||||
@require_context
|
||||
def security_service_delete(context, id):
|
||||
session = get_session()
|
||||
with session.begin():
|
||||
security_service_ref = security_service_get(context,
|
||||
id,
|
||||
session=session)
|
||||
security_service_ref.delete(session=session)
|
||||
|
||||
|
||||
@require_context
|
||||
def security_service_update(context, id, values):
|
||||
session = get_session()
|
||||
with session.begin():
|
||||
security_service_ref = security_service_get(context,
|
||||
id,
|
||||
session=session)
|
||||
security_service_ref.update(values)
|
||||
security_service_ref.save(session=session)
|
||||
return security_service_ref
|
||||
|
||||
|
||||
@require_context
|
||||
def security_service_get(context, id, session=None):
|
||||
result = _security_service_get_query(context, session=session).\
|
||||
filter_by(id=id).first()
|
||||
|
||||
if result is None:
|
||||
raise exception.SecurityServiceNotFound(security_service_id=id)
|
||||
return result
|
||||
|
||||
|
||||
@require_context
|
||||
def security_service_get_all(context):
|
||||
return _security_service_get_query(context).all()
|
||||
|
||||
|
||||
@require_context
|
||||
def security_service_get_all_by_project(context, project_id):
|
||||
return _security_service_get_query(context).\
|
||||
filter_by(project_id=project_id).all()
|
||||
|
||||
|
||||
def _security_service_get_query(context, session=None):
|
||||
if session is None:
|
||||
session = get_session()
|
||||
return model_query(context, models.SecurityService, session=session)
|
||||
|
@ -0,0 +1,61 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2013 Mirantis Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from sqlalchemy import Boolean, Column, DateTime
|
||||
from sqlalchemy import MetaData, String, Table
|
||||
|
||||
from manila.openstack.common.gettextutils import _
|
||||
from manila.openstack.common import log as logging
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def upgrade(migrate_engine):
|
||||
meta = MetaData()
|
||||
meta.bind = migrate_engine
|
||||
|
||||
security_services = Table(
|
||||
'security_services', meta,
|
||||
Column('created_at', DateTime),
|
||||
Column('updated_at', DateTime),
|
||||
Column('deleted_at', DateTime),
|
||||
Column('deleted', Boolean, default=False),
|
||||
Column('id', String(length=36), primary_key=True, nullable=False),
|
||||
Column('project_id', String(length=36), nullable=False),
|
||||
Column('type', String(length=32), nullable=False),
|
||||
Column('dns_ip', String(length=64), nullable=True),
|
||||
Column('server', String(length=255), nullable=True),
|
||||
Column('domain', String(length=255), nullable=True),
|
||||
Column('sid', String(length=255), nullable=True),
|
||||
Column('name', String(length=255), nullable=True),
|
||||
Column('description', String(length=255), nullable=True),
|
||||
Column('status', String(length=16)),
|
||||
mysql_engine='InnoDB',
|
||||
mysql_charset='utf8',
|
||||
)
|
||||
|
||||
try:
|
||||
security_services.create()
|
||||
except Exception:
|
||||
LOG.exception(_("Exception while creating table"))
|
||||
raise
|
||||
|
||||
|
||||
def downgrade(migrate_engine):
|
||||
meta = MetaData()
|
||||
meta.bind = migrate_engine
|
||||
security_services = Table('security_services', meta, autoload=True)
|
||||
security_services.drop()
|
@ -27,6 +27,7 @@ from sqlalchemy.ext.declarative import declarative_base
|
||||
from sqlalchemy import ForeignKey, DateTime, Boolean, Enum
|
||||
from sqlalchemy.orm import relationship, backref, object_mapper
|
||||
|
||||
from manila.common import constants
|
||||
from manila.db.sqlalchemy.session import get_session
|
||||
|
||||
from manila import exception
|
||||
@ -320,6 +321,24 @@ class ShareSnapshot(BASE, ManilaBase):
|
||||
'ShareSnapshot.deleted == False)')
|
||||
|
||||
|
||||
class SecurityService(BASE, ManilaBase):
|
||||
"""Security service information for manila shares"""
|
||||
|
||||
__tablename__ = 'security_services'
|
||||
id = Column(String(36), primary_key=True)
|
||||
project_id = Column(String(36), nullable=False)
|
||||
type = Column(String(32), nullable=False)
|
||||
dns_ip = Column(String(64), nullable=True)
|
||||
server = Column(String(255), nullable=True)
|
||||
domain = Column(String(255), nullable=True)
|
||||
sid = Column(String(255), nullable=True)
|
||||
name = Column(String(255), nullable=True)
|
||||
description = Column(String(255), nullable=True)
|
||||
status = Column(Enum(constants.STATUS_NEW, constants.STATUS_ACTIVE,
|
||||
constants.STATUS_ERROR),
|
||||
default=constants.STATUS_NEW)
|
||||
|
||||
|
||||
def register_models():
|
||||
"""Register Models and create metadata.
|
||||
|
||||
|
@ -491,3 +491,7 @@ class InvalidShareMetadata(Invalid):
|
||||
|
||||
class InvalidShareMetadataSize(Invalid):
|
||||
message = _("Invalid metadata size")
|
||||
|
||||
|
||||
class SecurityServiceNotFound(NotFound):
|
||||
message = _("Security service %(security_service_id)s could not be found.")
|
||||
|
0
manila/tests/network/__init__.py
Normal file
0
manila/tests/network/__init__.py
Normal file
165
manila/tests/network/test_security_service_db.py
Normal file
165
manila/tests/network/test_security_service_db.py
Normal file
@ -0,0 +1,165 @@
|
||||
# Copyright 2013 OpenStack Foundation
|
||||
# All Rights Reserved
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from manila.common import constants
|
||||
from manila import context
|
||||
from manila.db import api as db_api
|
||||
from manila import exception
|
||||
from manila import test
|
||||
|
||||
|
||||
security_service_dict = {'id': 'fake id',
|
||||
'project_id': 'fake project',
|
||||
'type': 'ldap',
|
||||
'dns_ip': 'fake dns',
|
||||
'server': 'fake ldap server',
|
||||
'domain': 'fake ldap domain',
|
||||
'sid': 'fake sid',
|
||||
'name': 'whatever',
|
||||
'description': 'nevermind',
|
||||
'status': constants.STATUS_NEW}
|
||||
|
||||
|
||||
class SecurityServiceDBTest(test.TestCase):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(SecurityServiceDBTest, self).__init__(*args, **kwargs)
|
||||
|
||||
self.fake_context = context.RequestContext(user_id='fake user',
|
||||
project_id='fake project',
|
||||
is_admin=False)
|
||||
|
||||
def _check_expected_fields(self, result, expected):
|
||||
for key in expected:
|
||||
self.assertEqual(result[key], expected[key])
|
||||
|
||||
def test_create(self):
|
||||
result = db_api.security_service_create(self.fake_context,
|
||||
security_service_dict)
|
||||
|
||||
self._check_expected_fields(result, security_service_dict)
|
||||
|
||||
def test_get(self):
|
||||
db_api.security_service_create(self.fake_context,
|
||||
security_service_dict)
|
||||
|
||||
result = db_api.security_service_get(self.fake_context,
|
||||
security_service_dict['id'])
|
||||
|
||||
self._check_expected_fields(result, security_service_dict)
|
||||
|
||||
def test_get_not_found(self):
|
||||
self.assertRaises(exception.SecurityServiceNotFound,
|
||||
db_api.security_service_get,
|
||||
self.fake_context,
|
||||
'wrong id')
|
||||
|
||||
def test_delete(self):
|
||||
db_api.security_service_create(self.fake_context,
|
||||
security_service_dict)
|
||||
|
||||
db_api.security_service_delete(self.fake_context,
|
||||
security_service_dict['id'])
|
||||
|
||||
self.assertRaises(exception.SecurityServiceNotFound,
|
||||
db_api.security_service_get,
|
||||
self.fake_context,
|
||||
security_service_dict['id'])
|
||||
|
||||
def test_update(self):
|
||||
update_dict = {'dns_ip': 'new dns',
|
||||
'server': 'new ldap server',
|
||||
'domain': 'new ldap domain',
|
||||
'sid': 'new sid',
|
||||
'name': 'new whatever',
|
||||
'description': 'new nevermind',
|
||||
'status': constants.STATUS_ERROR}
|
||||
|
||||
db_api.security_service_create(self.fake_context,
|
||||
security_service_dict)
|
||||
|
||||
result = db_api.security_service_update(self.fake_context,
|
||||
security_service_dict['id'],
|
||||
update_dict)
|
||||
|
||||
self._check_expected_fields(result, update_dict)
|
||||
|
||||
def test_update_no_updates(self):
|
||||
db_api.security_service_create(self.fake_context,
|
||||
security_service_dict)
|
||||
|
||||
result = db_api.security_service_update(self.fake_context,
|
||||
security_service_dict['id'],
|
||||
{})
|
||||
|
||||
self._check_expected_fields(result, security_service_dict)
|
||||
|
||||
def test_update_not_found(self):
|
||||
self.assertRaises(exception.SecurityServiceNotFound,
|
||||
db_api.security_service_update,
|
||||
self.fake_context,
|
||||
'wrong id',
|
||||
{})
|
||||
|
||||
def test_get_all_no_records(self):
|
||||
result = db_api.security_service_get_all(self.fake_context)
|
||||
|
||||
self.assertEqual(len(result), 0)
|
||||
|
||||
def test_get_all_one_record(self):
|
||||
db_api.security_service_create(self.fake_context,
|
||||
security_service_dict)
|
||||
|
||||
result = db_api.security_service_get_all(self.fake_context)
|
||||
|
||||
self.assertEqual(len(result), 1)
|
||||
self._check_expected_fields(result[0], security_service_dict)
|
||||
|
||||
def test_get_all_two_records(self):
|
||||
dict1 = security_service_dict
|
||||
dict2 = security_service_dict.copy()
|
||||
dict2['id'] = 'fake id 2'
|
||||
db_api.security_service_create(self.fake_context,
|
||||
dict1)
|
||||
db_api.security_service_create(self.fake_context,
|
||||
dict2)
|
||||
|
||||
result = db_api.security_service_get_all(self.fake_context)
|
||||
|
||||
self.assertEqual(len(result), 2)
|
||||
|
||||
def test_get_all_by_project(self):
|
||||
dict1 = security_service_dict
|
||||
dict2 = security_service_dict.copy()
|
||||
dict2['id'] = 'fake id 2'
|
||||
dict2['project_id'] = 'fake project 2'
|
||||
db_api.security_service_create(self.fake_context,
|
||||
dict1)
|
||||
db_api.security_service_create(self.fake_context,
|
||||
dict2)
|
||||
|
||||
result1 = db_api.security_service_get_all_by_project(
|
||||
self.fake_context,
|
||||
dict1['project_id'])
|
||||
|
||||
self.assertEqual(len(result1), 1)
|
||||
self._check_expected_fields(result1[0], dict1)
|
||||
|
||||
result2 = db_api.security_service_get_all_by_project(
|
||||
self.fake_context,
|
||||
dict2['project_id'])
|
||||
|
||||
self.assertEqual(len(result2), 1)
|
||||
self._check_expected_fields(result2[0], dict2)
|
Loading…
x
Reference in New Issue
Block a user