Add 'default_ad_site' field to security service object
Allows to configure optional field 'default_ad_site' from version 2.76. Restrict to make sure either server or 'default_at_site' provided, but not both. APIImpact Relates-bug: #1988146 Change-Id: I8e21e9170eace134a51efed84de1ccc58eb7eaaa
This commit is contained in:
parent
d94d1ae7bd
commit
858939c190
@ -2418,6 +2418,20 @@ scheduler_hints:
|
||||
required: false
|
||||
type: object
|
||||
min_version: 2.65
|
||||
security_service_default_ad_site:
|
||||
description: |
|
||||
The security service default AD site.
|
||||
in: body
|
||||
required: true
|
||||
type: string
|
||||
min_version: 2.76
|
||||
security_service_default_ad_site_request:
|
||||
description: |
|
||||
The security service default AD site.
|
||||
in: body
|
||||
required: false
|
||||
type: string
|
||||
min_version: 2.76
|
||||
security_service_dns_ip:
|
||||
description: |
|
||||
The DNS IP address that is used inside the project network.
|
||||
|
@ -8,6 +8,7 @@
|
||||
"created_at": "2015-09-07T12:19:10.695211",
|
||||
"updated_at": null,
|
||||
"server": null,
|
||||
"default_ad_site": null,
|
||||
"dns_ip": "10.0.0.0/24",
|
||||
"user": "demo",
|
||||
"password": "supersecret",
|
||||
|
@ -8,6 +8,7 @@
|
||||
"created_at": "2015-09-07T12:19:10.000000",
|
||||
"updated_at": null,
|
||||
"server": null,
|
||||
"default_ad_site": null,
|
||||
"dns_ip": "10.0.0.0/24",
|
||||
"user": "demo",
|
||||
"password": "supersecret",
|
||||
|
@ -10,6 +10,7 @@
|
||||
"description": "Creating my first Security Service",
|
||||
"updated_at": null,
|
||||
"server": null,
|
||||
"default_ad_site": null,
|
||||
"dns_ip": "10.0.0.0/24",
|
||||
"user": "demo",
|
||||
"password": "supersecret",
|
||||
@ -27,6 +28,7 @@
|
||||
"description": "Creating my second Security Service",
|
||||
"updated_at": null,
|
||||
"server": null,
|
||||
"default_ad_site": null,
|
||||
"dns_ip": "10.0.0.0/24",
|
||||
"user": null,
|
||||
"password": null,
|
||||
|
@ -10,6 +10,7 @@
|
||||
"description": "Creating my first Security Service",
|
||||
"updated_at": null,
|
||||
"server": null,
|
||||
"default_ad_site": null,
|
||||
"dns_ip": "10.0.0.0/24",
|
||||
"user": "demo",
|
||||
"password": "supersecret",
|
||||
@ -29,6 +30,7 @@
|
||||
"description": "Creating my second Security Service",
|
||||
"updated_at": null,
|
||||
"server": null,
|
||||
"default_ad_site": null,
|
||||
"dns_ip": "10.0.0.0/24",
|
||||
"user": null,
|
||||
"password": null,
|
||||
|
@ -32,6 +32,8 @@ You can configure a security service with these options:
|
||||
|
||||
- The password for the user, if you specify a user name.
|
||||
|
||||
- A default AD site, optional (available starting with API version 2.76)
|
||||
|
||||
A security service resource can also be given a user defined name and
|
||||
description.
|
||||
|
||||
@ -125,6 +127,7 @@ Response parameters
|
||||
- domain: security_service_domain
|
||||
- ou: security_service_ou
|
||||
- server: security_service_server
|
||||
- default_ad_site: security_service_default_ad_site
|
||||
- updated_at: updated_at
|
||||
- created_at: created_at
|
||||
|
||||
@ -181,6 +184,7 @@ Response parameters
|
||||
- domain: security_service_domain
|
||||
- ou: security_service_ou
|
||||
- server: security_service_server
|
||||
- default_ad_site: security_service_default_ad_site
|
||||
- updated_at: updated_at
|
||||
- created_at: created_at
|
||||
|
||||
@ -227,6 +231,7 @@ Request
|
||||
- domain: security_service_domain_request
|
||||
- ou: security_service_ou_request
|
||||
- server: security_service_server_request
|
||||
- default_ad_site: security_service_default_ad_site_request
|
||||
|
||||
Request example
|
||||
---------------
|
||||
@ -251,6 +256,7 @@ Response parameters
|
||||
- domain: security_service_domain
|
||||
- ou: security_service_ou
|
||||
- server: security_service_server
|
||||
- default_ad_site: security_service_default_ad_site
|
||||
- updated_at: updated_at
|
||||
- created_at: created_at
|
||||
|
||||
@ -304,6 +310,7 @@ Request
|
||||
- domain: security_service_domain_request
|
||||
- ou: security_service_ou_request
|
||||
- server: security_service_server_request
|
||||
- default_ad_site: security_service_default_ad_site_request
|
||||
|
||||
Request example
|
||||
---------------
|
||||
@ -328,6 +335,7 @@ Response parameters
|
||||
- domain: security_service_domain
|
||||
- ou: security_service_ou
|
||||
- server: security_service_server
|
||||
- default_ad_site: security_service_default_ad_site
|
||||
- updated_at: updated_at
|
||||
- created_at: created_at
|
||||
|
||||
|
@ -192,6 +192,7 @@ REST_API_VERSION_HISTORY = """
|
||||
'error' state.
|
||||
* 2.75 - Added option to specify quiesce wait time in share replica
|
||||
promote API.
|
||||
* 2.76 - Added 'default_ad_site' field in security service object.
|
||||
|
||||
"""
|
||||
|
||||
@ -199,7 +200,7 @@ REST_API_VERSION_HISTORY = """
|
||||
# The default api version request is defined to be the
|
||||
# minimum version of the API supported.
|
||||
_MIN_API_VERSION = "2.0"
|
||||
_MAX_API_VERSION = "2.75"
|
||||
_MAX_API_VERSION = "2.76"
|
||||
DEFAULT_API_VERSION = _MIN_API_VERSION
|
||||
|
||||
|
||||
|
@ -410,3 +410,11 @@ ____
|
||||
2.74
|
||||
----
|
||||
Allow/deny share access rule even if share replicas are in 'error' state.
|
||||
|
||||
2.75
|
||||
----
|
||||
Added option to specify quiesce wait time in share replica promote API.
|
||||
|
||||
2.76
|
||||
----
|
||||
Added 'default_ad_site' field in security service object.
|
||||
|
@ -22,6 +22,7 @@ import webob
|
||||
from webob import exc
|
||||
|
||||
from manila.api import common
|
||||
from manila.api.openstack import api_version_request as api_version
|
||||
from manila.api.openstack import wsgi
|
||||
from manila.api.views import security_service as security_service_views
|
||||
from manila.common import constants
|
||||
@ -192,6 +193,21 @@ class SecurityServiceController(wsgi.Controller):
|
||||
"fields are available for update.") % id
|
||||
raise exc.HTTPForbidden(explanation=msg)
|
||||
|
||||
server = security_service_data.get('server')
|
||||
default_ad_site = security_service_data.get('default_ad_site')
|
||||
if default_ad_site:
|
||||
if req.api_version_request < api_version.APIVersionRequest("2.76"):
|
||||
msg = _('"default_ad_site" is only supported from API '
|
||||
'version 2.76.')
|
||||
raise webob.exc.HTTPBadRequest(explanation=msg)
|
||||
|
||||
if (security_service['type'] == 'active_directory' and server and
|
||||
default_ad_site):
|
||||
raise exception.InvalidInput(
|
||||
reason=(_("Cannot create security service because both "
|
||||
"server and 'default_ad_site' were provided. "
|
||||
"Specify either server or 'default_ad_site'.")))
|
||||
|
||||
policy.check_policy(context, RESOURCE_NAME, 'update', security_service)
|
||||
security_service = db.security_service_update(
|
||||
context, id, security_service_data)
|
||||
@ -214,6 +230,20 @@ class SecurityServiceController(wsgi.Controller):
|
||||
"service. Valid types are %(types)s") %
|
||||
{'type': security_srv_type,
|
||||
'types': ','.join(allowed_types)}))
|
||||
server = security_service_args.get('server')
|
||||
default_ad_site = security_service_args.get('default_ad_site')
|
||||
if default_ad_site:
|
||||
if req.api_version_request < api_version.APIVersionRequest("2.76"):
|
||||
msg = _('"default_ad_site" is only supported from API '
|
||||
'version 2.76.')
|
||||
raise webob.exc.HTTPBadRequest(explanation=msg)
|
||||
|
||||
if (security_srv_type == 'active_directory' and server and
|
||||
default_ad_site):
|
||||
raise exception.InvalidInput(
|
||||
reason=(_("Cannot create security service because both "
|
||||
"server and 'default_ad_site' were provided, "
|
||||
"Specify either server or 'default_ad_site'.")))
|
||||
security_service_args['project_id'] = context.project_id
|
||||
security_service = db.security_service_create(
|
||||
context, security_service_args)
|
||||
|
@ -23,6 +23,7 @@ class ViewBuilder(common.ViewBuilder):
|
||||
_collection_name = 'security_services'
|
||||
_detail_version_modifiers = [
|
||||
'add_ou_to_security_service',
|
||||
'add_default_ad_site_to_security_service',
|
||||
]
|
||||
|
||||
def summary_list(self, request, security_services):
|
||||
@ -64,6 +65,10 @@ class ViewBuilder(common.ViewBuilder):
|
||||
def add_ou_to_security_service(self, context, ss_dict, ss):
|
||||
ss_dict['ou'] = ss.get('ou')
|
||||
|
||||
@common.ViewBuilder.versioned_method("2.76")
|
||||
def add_default_ad_site_to_security_service(self, context, ss_dict, ss):
|
||||
ss_dict['default_ad_site'] = ss.get('default_ad_site')
|
||||
|
||||
def _list_view(self, func, request, security_services):
|
||||
"""Provide a view for a list of security services."""
|
||||
security_services_list = [func(request, service)['security_service']
|
||||
|
@ -0,0 +1,49 @@
|
||||
# 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.
|
||||
|
||||
"""add default_ad_site to security service
|
||||
|
||||
Revision ID: c476aeb186ec
|
||||
Revises: bb5938d74b73
|
||||
Create Date: 2022-11-30 10:59:34.866946
|
||||
|
||||
"""
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'c476aeb186ec'
|
||||
down_revision = 'bb5938d74b73'
|
||||
|
||||
from alembic import op
|
||||
from oslo_log import log
|
||||
import sqlalchemy as sa
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
ss_table_name = 'security_services'
|
||||
|
||||
|
||||
def upgrade():
|
||||
try:
|
||||
op.add_column(
|
||||
ss_table_name,
|
||||
sa.Column('default_ad_site', sa.String(255), nullable=True))
|
||||
except Exception:
|
||||
LOG.error("%s table column default_ad_site not added", ss_table_name)
|
||||
raise
|
||||
|
||||
|
||||
def downgrade():
|
||||
try:
|
||||
op.drop_column(ss_table_name, 'default_ad_site')
|
||||
except Exception:
|
||||
LOG.error("%s table column default_ad_site not dropped", ss_table_name)
|
||||
raise
|
@ -931,6 +931,7 @@ class SecurityService(BASE, ManilaBase):
|
||||
name = Column(String(255), nullable=True)
|
||||
description = Column(String(255), nullable=True)
|
||||
ou = Column(String(255), nullable=True)
|
||||
default_ad_site = Column(String(255), nullable=True)
|
||||
|
||||
|
||||
class ShareNetwork(BASE, ManilaBase):
|
||||
|
@ -3246,6 +3246,7 @@ class ShareManager(manager.SchedulerDependentManager):
|
||||
data = {
|
||||
'name': security_service['name'],
|
||||
'ou': security_service['ou'],
|
||||
'default_ad_site': security_service['default_ad_site'],
|
||||
'domain': security_service['domain'],
|
||||
'server': security_service['server'],
|
||||
'dns_ip': security_service['dns_ip'],
|
||||
@ -4205,6 +4206,7 @@ class ShareManager(manager.SchedulerDependentManager):
|
||||
'user': security_service['user'],
|
||||
'type': ss_type,
|
||||
'password': security_service['password'],
|
||||
'default_ad_site': security_service['default_ad_site'],
|
||||
}
|
||||
self.db.share_server_backend_details_set(
|
||||
context, share_server['id'],
|
||||
@ -5843,6 +5845,7 @@ class ShareManager(manager.SchedulerDependentManager):
|
||||
backend_details_data = {
|
||||
'name': new_security_service['name'],
|
||||
'ou': new_security_service['ou'],
|
||||
'default_ad_site': new_security_service['default_ad_site'],
|
||||
'domain': new_security_service['domain'],
|
||||
'server': new_security_service['server'],
|
||||
'dns_ip': new_security_service['dns_ip'],
|
||||
|
@ -140,6 +140,14 @@ class ShareApiTest(test.TestCase):
|
||||
self.assertRaises(exception.InvalidInput, self.controller.create, req,
|
||||
{"security_service": sec_service})
|
||||
|
||||
@ddt.data('2.76')
|
||||
def test_security_service_create_invalid_active_directory(self, version):
|
||||
sec_service = self.ss_active_directory.copy()
|
||||
sec_service['default_ad_site'] = 'fake_default_ad_site'
|
||||
req = fakes.HTTPRequest.blank('/security-services', version=version)
|
||||
self.assertRaises(exception.InvalidInput, self.controller.create, req,
|
||||
{"security_service": sec_service})
|
||||
|
||||
def test_create_security_service_no_body(self):
|
||||
body = {}
|
||||
req = fakes.HTTPRequest.blank('/security-services')
|
||||
|
@ -43,6 +43,8 @@ def stub_security_service(self, version, id):
|
||||
)
|
||||
if self.is_microversion_ge(version, '2.44'):
|
||||
ss_dict['ou'] = 'fake-ou'
|
||||
if self.is_microversion_ge(version, '2.76'):
|
||||
ss_dict['default_ad_site'] = 'fake-default_ad_site'
|
||||
|
||||
return ss_dict
|
||||
|
||||
@ -53,6 +55,7 @@ class SecurityServicesAPITest(test.TestCase):
|
||||
('2.0'),
|
||||
('2.43'),
|
||||
('2.44'),
|
||||
('2.76'),
|
||||
)
|
||||
def test_index(self, version):
|
||||
ss = [
|
||||
@ -85,3 +88,8 @@ class SecurityServicesAPITest(test.TestCase):
|
||||
self.assertIn('ou', ss_keys)
|
||||
else:
|
||||
self.assertNotIn('ou', ss_keys)
|
||||
|
||||
if self.is_microversion_ge(version, '2.76'):
|
||||
self.assertIn('default_ad_site', ss_keys)
|
||||
else:
|
||||
self.assertNotIn('default_ad_site', ss_keys)
|
||||
|
@ -45,6 +45,7 @@ security_service_dict = {
|
||||
'dns_ip': 'fake dns',
|
||||
'server': 'fake ldap server',
|
||||
'domain': 'fake ldap domain',
|
||||
'default_ad_site': 'fake ldap default_ad_site',
|
||||
'ou': 'fake ldap ou',
|
||||
'user': 'fake user',
|
||||
'password': 'fake password',
|
||||
@ -3232,6 +3233,7 @@ class SecurityServiceDatabaseAPITestCase(BaseDatabaseAPITestCase):
|
||||
'dns_ip': 'new dns',
|
||||
'server': 'new ldap server',
|
||||
'domain': 'new ldap domain',
|
||||
'default_ad_site': 'new ldap default_ad_site',
|
||||
'ou': 'new ldap ou',
|
||||
'user': 'new user',
|
||||
'password': 'new password',
|
||||
|
@ -3539,6 +3539,7 @@ class ShareManagerTestCase(test.TestCase):
|
||||
'user': 'fake_user' + ss_type,
|
||||
'type': ss_type,
|
||||
'password': 'fake_password' + ss_type,
|
||||
'default_ad_site': 'fake_default_ad_site' + ss_type,
|
||||
})
|
||||
sec_services = network_info['security_services']
|
||||
server_info = {'fake_server_info_key': 'fake_server_info_value'}
|
||||
@ -6491,6 +6492,7 @@ class ShareManagerTestCase(test.TestCase):
|
||||
ss_data_from_db = {
|
||||
'name': ss_from_db['name'],
|
||||
'ou': ss_from_db['ou'],
|
||||
'default_ad_site': ss_from_db['default_ad_site'],
|
||||
'domain': ss_from_db['domain'],
|
||||
'server': ss_from_db['server'],
|
||||
'dns_ip': ss_from_db['dns_ip'],
|
||||
@ -9515,8 +9517,8 @@ class ShareManagerTestCase(test.TestCase):
|
||||
fake_rules = ['fake_rules']
|
||||
network_info = {'fake': 'fake'}
|
||||
backend_details_keys = [
|
||||
'name', 'ou', 'domain', 'server', 'dns_ip', 'user', 'type',
|
||||
'password']
|
||||
'name', 'ou', 'default_ad_site', 'domain', 'server', 'dns_ip',
|
||||
'user', 'type', 'password']
|
||||
backend_details_data = {}
|
||||
[backend_details_data.update(
|
||||
{key: security_services[0][key]}) for key in backend_details_keys]
|
||||
@ -9673,8 +9675,8 @@ class ShareManagerTestCase(test.TestCase):
|
||||
new_security_service_id = security_services[1]['id']
|
||||
network_info = [{'fake': 'fake'}]
|
||||
backend_details_keys = [
|
||||
'name', 'ou', 'domain', 'server', 'dns_ip', 'user', 'type',
|
||||
'password']
|
||||
'name', 'ou', 'default_ad_site', 'domain', 'server', 'dns_ip',
|
||||
'user', 'type', 'password']
|
||||
backend_details_data = {}
|
||||
[backend_details_data.update(
|
||||
{key: security_services[0][key]}) for key in backend_details_keys]
|
||||
|
@ -0,0 +1,6 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
From API version 2.76, added 'default_ad_site' field to 'security_service'
|
||||
object. This field can not be used along-with 'server' field of the
|
||||
'security_service'.
|
Loading…
Reference in New Issue
Block a user