Distributed Cloud enhancements for Horizon

- Adding endpoints for the subcloud's platform services to the central
  keystone.  This was done so horizon can reach all subclouds
- Allowing version requests to bypass the authtoken validator in the
  dcorch proxy.  version requests do not require authentication and
  they are required by horizon to work in the SystemController region

Change-Id: I508e0168e77d1f46b8f5720fd16047177b4920c2
Partial-Bug: 1846239
Signed-off-by: Tyler Smith <tyler.smith@windriver.com>
This commit is contained in:
Tyler Smith 2019-10-18 12:18:53 -04:00
parent b020fc86c8
commit 96db1d7ee0
6 changed files with 78 additions and 29 deletions

View File

@ -152,39 +152,50 @@ class SubcloudManager(manager.Manager):
payload['systemcontroller_gateway_address'],
1)
# Create identity endpoints to this subcloud on the
# Create endpoints to this subcloud on the
# management-start-ip of the subcloud which will be allocated
# as the floating Management IP of the Subcloud if the
# Address Pool is not shared. Incase the endpoint entry
# is incorrect, or the management IP of the subcloud is changed
# Address Pool is not shared. Incase the endpoint entries
# are incorrect, or the management IP of the subcloud is changed
# in the future, it will not go managed or will show up as
# out of sync. To fix this use Openstack endpoint commands
# on the SystemController to change the subcloud endpoint
ks_service_id = None
# on the SystemController to change the subcloud endpoints.
# The non-identity endpoints are added to facilitate horizon access
# from the System Controller to the subcloud.
endpoint_config = []
endpoint_ip = payload['management_start_address']
if netaddr.IPAddress(endpoint_ip).version == 6:
endpoint_ip = '[' + endpoint_ip + ']'
for service in m_ks_client.services_list:
if service.type == dcorch_consts.ENDPOINT_TYPE_PLATFORM:
endpoint_url = "http://{}:6385/v1".format(endpoint_ip)
endpoint_config.append((service.id, endpoint_url))
if service.type == dcorch_consts.ENDPOINT_TYPE_IDENTITY:
ks_service_id = service.id
break
else:
endpoint_url = "http://{}:5000/v3".format(endpoint_ip)
endpoint_config.append((service.id, endpoint_url))
if service.type == dcorch_consts.ENDPOINT_TYPE_PATCHING:
endpoint_url = "http://{}:5491".format(endpoint_ip)
endpoint_config.append((service.id, endpoint_url))
if service.type == dcorch_consts.ENDPOINT_TYPE_FM:
endpoint_url = "http://{}:18002".format(endpoint_ip)
endpoint_config.append((service.id, endpoint_url))
if service.type == dcorch_consts.ENDPOINT_TYPE_NFV:
endpoint_url = "http://{}:4545".format(endpoint_ip)
endpoint_config.append((service.id, endpoint_url))
if len(endpoint_config) < 5:
raise exceptions.BadRequest(
resource='subcloud',
msg='No Identity service found on SystemController')
msg='Missing service in SystemController')
identity_endpoint_ip = payload['management_start_address']
if netaddr.IPAddress(identity_endpoint_ip).version == 6:
identity_endpoint_url = \
"http://[{}]:5000/v3".format(identity_endpoint_ip)
else:
identity_endpoint_url = \
"http://{}:5000/v3".format(identity_endpoint_ip)
for iface in ['internal', 'admin']:
m_ks_client.keystone_client.endpoints.create(
ks_service_id,
identity_endpoint_url,
interface=iface,
region=subcloud.name)
for endpoint in endpoint_config:
for iface in ['internal', 'admin']:
m_ks_client.keystone_client.endpoints.create(
endpoint[0],
endpoint[1],
interface=iface,
region=subcloud.name)
# Inform orchestrator that subcloud has been added
self.dcorch_rpc_client.add_subcloud(

View File

@ -130,7 +130,11 @@ class TestSubcloudManager(base.DCManagerTestCase):
mock_dcorch_rpc_client):
value = utils.create_subcloud_dict(value)
controllers = [Controller('controller-0'), Controller('controller-1')]
services = [Service('identity', '1234')]
services = [Service('identity', '1234'),
Service('faultmanagement', '1234'),
Service('patching', '1234'),
Service('platform', '1234'),
Service('nfv', '1234')]
mock_context.get_admin_context.return_value = self.ctxt
mock_db_api.subcloud_get_by_name.side_effect = \
exceptions.SubcloudNameNotFound()

View File

@ -1,4 +1,4 @@
# Copyright 2017 Wind River
# Copyright 2017-2019 Wind River
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -21,6 +21,7 @@ from dcorch.api.proxy.apps.controller import IdentityAPIController
from dcorch.api.proxy.apps.controller import NeutronAPIController
from dcorch.api.proxy.apps.controller import OrchAPIController
from dcorch.api.proxy.apps.controller import SysinvAPIController
from dcorch.api.proxy.apps.controller import VersionController
from dcorch.api.proxy.apps.dispatcher import APIDispatcher
from dcorch.api.proxy.apps.patch import PatchAPIController
from dcorch.api.proxy.apps.router import Router
@ -121,3 +122,13 @@ class Acceptor(Router):
for key, value in proxy_consts.IDENTITY_PATH_MAP.items():
self._add_resource(mapper, api_controller, value, key, CONF.type)
class VersionAcceptor(Router):
def __init__(self, app, conf):
self._conf = conf
mapper = routes.Mapper()
api_controller = VersionController(app, conf)
mapper.connect(proxy_consts.VERSION_ROOT, controller=api_controller,
conditions=dict(method=['GET']))
super(VersionAcceptor, self).__init__(app, conf, mapper, None)

View File

@ -1,4 +1,4 @@
# Copyright 2017 Wind River
# Copyright 2017-2019 Wind River
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -18,8 +18,10 @@ import webob.dec
import webob.exc
from dcorch.api.proxy.apps.dispatcher import APIDispatcher
from dcorch.api.proxy.apps.proxy import Proxy
from dcorch.api.proxy.common import constants as proxy_consts
from dcorch.api.proxy.common.service import Middleware
from dcorch.api.proxy.common.service import Request as ProxyRequest
from dcorch.api.proxy.common import utils as proxy_utils
from dcorch.common import consts
import dcorch.common.context as k_context
@ -689,3 +691,20 @@ class OrchAPIController(APIController):
if self.get_status_code(response) in self.OK_STATUS_CODE:
response = self._update_response(environ, request_body, response)
return response
class VersionController(Middleware):
def __init__(self, app, conf):
self._default_dispatcher = Proxy()
self._remote_host, self._remote_port = \
proxy_utils.get_remote_host_port_options(CONF)
super(VersionController, self).__init__(app)
@webob.dec.wsgify(RequestClass=ProxyRequest)
def __call__(self, req):
LOG.debug("VersionController forward the version request to remote "
"host: (%s), port: (%d)" % (self._remote_host,
self._remote_port))
proxy_utils.set_request_forward_environ(req, self._remote_host,
self._remote_port)
return self._default_dispatcher

View File

@ -1,4 +1,4 @@
# Copyright 2017 Wind River
# Copyright 2017-2019 Wind River
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -15,6 +15,8 @@
from dcorch.common import consts
VERSION_ROOT = '/{version:.*?}'
# Compute
FLAVOR_RESOURCE_TAG = 'flavors'
FLAVOR_ACCESS_RESOURCE_TAG = 'action'

View File

@ -12,7 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2017-2018 Wind River Systems, Inc.
# Copyright (c) 2017-2019 Wind River Systems, Inc.
#
# The right to copy, distribute, modify, or otherwise make use
# of this software may be licensed only pursuant to the terms
@ -135,6 +135,8 @@ ENDPOINT_TYPE_COMPUTE = "compute"
ENDPOINT_TYPE_NETWORK = "network"
ENDPOINT_TYPE_PATCHING = "patching"
ENDPOINT_TYPE_IDENTITY = "identity"
ENDPOINT_TYPE_FM = "faultmanagement"
ENDPOINT_TYPE_NFV = "nfv"
ENDPOINT_TYPES_LIST = [ENDPOINT_TYPE_PLATFORM,
ENDPOINT_TYPE_PATCHING,